From 690100f1ad494022dbecb0730e63f9a250d032f4 Mon Sep 17 00:00:00 2001 From: Rob Adams Date: Sun, 21 Dec 2003 06:31:40 +0000 Subject: [PATCH] Reorganize the window menu according to discussion on #110904. The 2003-12-20 Rob Adams Reorganize the window menu according to discussion on #110904. The workspace name mnemonic chunk of the patch is thanks to Jonathan Blandford. * src/common.h: add MENU_OP_ABOVE, MENU_OP_UNABOVE, MENU_UP_MOVE_TO_* menu ops. * src/core.c (meta_core_get_menu_accelerator): add accelerator for the new menu ops. * src/menu.c: add checked attribute in _MenuItem struct to display a checkmark next to a menu item. Add the new menu items to menuitems. (get_workspace_name_with_accel): Add mnemonics even to renamed workspaces. (menu_item_new): provide support for the checked attribute (meta_window_menu_new): construct new submenu for workspace switching. * src/window.c (menu_callback): implement support for the new menu ops. (meta_window_show_menu): don't use the OP_*SHAPE operations, and compute which of the OP_MOVE_TO_* ops should be used for the current workspace and workspace layout. Add the OP_*ABOVE operations. --- ChangeLog | 28 ++++++++++++++ src/common.h | 8 +++- src/core.c | 20 ++++++++-- src/menu.c | 101 ++++++++++++++++++++++++++++++++++----------------- src/window.c | 83 ++++++++++++++++++++++++++++++++---------- 5 files changed, 182 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 67b462156..9f35ef9f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2003-12-20 Rob Adams + + Reorganize the window menu according to discussion on #110904. + The workspace name mnemonic chunk of the patch is thanks to + Jonathan Blandford. + + * src/common.h: add MENU_OP_ABOVE, MENU_OP_UNABOVE, MENU_UP_MOVE_TO_* + menu ops. + + * src/core.c (meta_core_get_menu_accelerator): add accelerator for + the new menu ops. + + * src/menu.c: add checked attribute in _MenuItem struct to display + a checkmark next to a menu item. Add the new menu items to + menuitems. + (get_workspace_name_with_accel): Add mnemonics even to renamed + workspaces. + (menu_item_new): provide support for the checked attribute + (meta_window_menu_new): construct new submenu for workspace + switching. + + * src/window.c (menu_callback): implement support for the new menu + ops. + (meta_window_show_menu): don't use the OP_*SHAPE operations, and + compute which of the OP_MOVE_TO_* ops should be used for the + current workspace and workspace layout. Add the OP_*ABOVE + operations. + 2003-12-20 Arafat Medini * configure.in: Added Arabic locale "ar" to ALL_LINGUAS diff --git a/src/common.h b/src/common.h index 440b56cc6..4268ee5ec 100644 --- a/src/common.h +++ b/src/common.h @@ -58,7 +58,13 @@ typedef enum META_MENU_OP_STICK = 1 << 7, META_MENU_OP_WORKSPACES = 1 << 8, META_MENU_OP_MOVE = 1 << 9, - META_MENU_OP_RESIZE = 1 << 10 + META_MENU_OP_RESIZE = 1 << 10, + META_MENU_OP_ABOVE = 1 << 11, + META_MENU_OP_UNABOVE = 1 << 12, + META_MENU_OP_MOVE_LEFT = 1 << 13, + META_MENU_OP_MOVE_RIGHT = 1 << 14, + META_MENU_OP_MOVE_UP = 1 << 15, + META_MENU_OP_MOVE_DOWN = 1 << 16 } MetaMenuOp; typedef struct _MetaWindowMenu MetaWindowMenu; diff --git a/src/core.c b/src/core.c index 422ef3c2c..5eb897926 100644 --- a/src/core.c +++ b/src/core.c @@ -586,17 +586,17 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op, name = META_KEYBINDING_MAXIMIZE; break; case META_MENU_OP_UNSHADE: - name = META_KEYBINDING_TOGGLE_SHADE; - break; case META_MENU_OP_SHADE: name = META_KEYBINDING_TOGGLE_SHADE; break; case META_MENU_OP_UNSTICK: - name = META_KEYBINDING_TOGGLE_STICKY; - break; case META_MENU_OP_STICK: name = META_KEYBINDING_TOGGLE_STICKY; break; + case META_MENU_OP_ABOVE: + case META_MENU_OP_UNABOVE: + name = META_KEYBINDING_TOGGLE_ABOVE; + break; case META_MENU_OP_WORKSPACES: switch (workspace) { @@ -644,6 +644,18 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op, case META_MENU_OP_RESIZE: name = META_KEYBINDING_BEGIN_RESIZE; break; + case META_MENU_OP_MOVE_LEFT: + name = META_KEYBINDING_MOVE_WORKSPACE_LEFT; + break; + case META_MENU_OP_MOVE_RIGHT: + name = META_KEYBINDING_MOVE_WORKSPACE_RIGHT; + break; + case META_MENU_OP_MOVE_UP: + name = META_KEYBINDING_MOVE_WORKSPACE_UP; + break; + case META_MENU_OP_MOVE_DOWN: + name = META_KEYBINDING_MOVE_WORKSPACE_DOWN; + break; } if (name) diff --git a/src/menu.c b/src/menu.c index 4ffc5e76e..958bbe2e9 100644 --- a/src/menu.c +++ b/src/menu.c @@ -36,6 +36,7 @@ struct _MenuItem { MetaMenuOp op; const char *stock_id; + const gboolean checked; const char *label; }; @@ -49,18 +50,24 @@ struct _MenuData static void activate_cb (GtkWidget *menuitem, gpointer data); static MenuItem menuitems[] = { - { META_MENU_OP_MINIMIZE, METACITY_STOCK_MINIMIZE, N_("Mi_nimize") }, - { META_MENU_OP_MAXIMIZE, METACITY_STOCK_MAXIMIZE, N_("Ma_ximize") }, - { META_MENU_OP_UNMAXIMIZE, NULL, N_("Unma_ximize") }, - { META_MENU_OP_SHADE, NULL, N_("Roll _Up") }, - { META_MENU_OP_UNSHADE, NULL, N_("_Unroll") }, - { META_MENU_OP_MOVE, NULL, N_("_Move") }, - { META_MENU_OP_RESIZE, NULL, N_("_Resize") }, - { 0, NULL, NULL }, /* separator */ - { META_MENU_OP_DELETE, METACITY_STOCK_DELETE, N_("_Close") }, - { 0, NULL, NULL }, /* separator */ - { META_MENU_OP_STICK, NULL, N_("Put on _All Workspaces") }, - { META_MENU_OP_UNSTICK, NULL, N_("Only on _This Workspace") } + { META_MENU_OP_MINIMIZE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") }, + { META_MENU_OP_MAXIMIZE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") }, + { META_MENU_OP_UNMAXIMIZE, NULL, FALSE, N_("Unma_ximize") }, + { META_MENU_OP_SHADE, NULL, FALSE, N_("Roll _Up") }, + { META_MENU_OP_UNSHADE, NULL, FALSE, N_("_Unroll") }, + { META_MENU_OP_ABOVE, NULL, FALSE, N_("On _Top") }, + { META_MENU_OP_UNABOVE, NULL, TRUE, N_("On _Top") }, + { META_MENU_OP_MOVE, NULL, FALSE, N_("_Move") }, + { META_MENU_OP_RESIZE, NULL, FALSE, N_("_Resize") }, + { 0, NULL, FALSE, NULL }, /* separator */ + { META_MENU_OP_DELETE, METACITY_STOCK_DELETE, FALSE, N_("_Close") }, + { 0, NULL, FALSE, NULL }, /* separator */ + { META_MENU_OP_STICK, NULL, FALSE, N_("Put on _All Workspaces") }, + { META_MENU_OP_UNSTICK, NULL, FALSE, N_("Only on _This Workspace") }, + { META_MENU_OP_MOVE_LEFT, NULL, FALSE, N_("Move to Workspace _Left") }, + { META_MENU_OP_MOVE_RIGHT, NULL, FALSE, N_("Move to Workspace R_ight") }, + { META_MENU_OP_MOVE_UP, NULL, FALSE, N_("Move to Workspace _Up") }, + { META_MENU_OP_MOVE_DOWN, NULL, FALSE, N_("Move to Workspace _Down") } }; static void @@ -157,26 +164,30 @@ get_workspace_name_with_accel (Display *display, * Above name is a pointer into the Workspace struct. Here we make * a copy copy so we can have our wicked way with it. */ - new_name = g_strdup_printf (_("Workspace %s%d"), - number < 10 ? "_" : "", - number); + if (number == 10) + new_name = g_strdup_printf (_("Workspace 1_0")); + else + new_name = g_strdup_printf (_("Workspace %s%d"), + number < 10 ? "_" : "", + number); return new_name; } else { /* - * Otherwise this is just a normal name to which we cannot really - * add accelerators. Escape any _ characters so that the user's - * workspace names do not get mangled. + * Otherwise this is just a normal name. Escape any _ characters so that + * the user's workspace names do not get mangled. If the number is less + * than 10 we provide an accelerator. */ char *new_name; const char *source; char *dest; /* - * Assume the worst case, that every character is a _ + * Assume the worst case, that every character is a _. We also + * provide memory for " (_#)" */ - new_name = g_malloc0 (strlen (name) * 2 + 1); + new_name = g_malloc0 (strlen (name) * 2 + 6 + 1); /* * Now iterate down the strings, adding '_' to escape as we go @@ -190,6 +201,16 @@ get_workspace_name_with_accel (Display *display, *dest++ = *source++; } + /* People don't start at workstation 0, but workstation 1 */ + if (index < 9) + { + g_snprintf (dest, 6, " (_%d)", index + 1); + } + else if (index == 9) + { + g_snprintf (dest, 6, " (_0)"); + } + return new_name; } } @@ -197,13 +218,20 @@ get_workspace_name_with_accel (Display *display, static GtkWidget* menu_item_new (const char *label, gboolean with_image, + gboolean with_check, unsigned int key, MetaVirtualModifier mods) { GtkWidget *menu_item; GtkWidget *accel_label; - if (with_image) + if (with_check) + { + menu_item = gtk_check_menu_item_new (); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), + TRUE); + } + else if (with_image) menu_item = gtk_image_menu_item_new (); else menu_item = gtk_menu_item_new (); @@ -277,17 +305,18 @@ meta_window_menu_new (MetaFrames *frames, meta_core_get_menu_accelerator (menuitems[i].op, -1, &key, &mods); - + if (image) { - mi = menu_item_new (_(menuitems[i].label), TRUE, key, mods); + mi = menu_item_new (_(menuitems[i].label), TRUE, FALSE, key, mods); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image); gtk_widget_show (image); } else { - mi = menu_item_new (_(menuitems[i].label), FALSE, key, mods); + mi = menu_item_new (_(menuitems[i].label), FALSE, + menuitems[i].checked, key, mods); } if (insensitive & menuitems[i].op) @@ -321,6 +350,8 @@ meta_window_menu_new (MetaFrames *frames, Display *display; Window xroot; GdkScreen *screen; + GtkWidget *submenu; + GtkWidget *submenuitem; meta_verbose ("Creating %d-workspace menu current space %d\n", n_workspaces, active_workspace); @@ -329,11 +360,18 @@ meta_window_menu_new (MetaFrames *frames, screen = gdk_drawable_get_screen (GTK_WIDGET (frames)->window); xroot = GDK_DRAWABLE_XID (gdk_screen_get_root_window (screen)); - + + submenu = gtk_menu_new (); + submenuitem = menu_item_new (N_("Move to Another _Workspace"), FALSE, FALSE, 0, 0); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (submenuitem), submenu); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), + submenuitem); + gtk_widget_show (submenuitem); + i = 0; while (i < n_workspaces) { - char *label, *name; + char *label; MenuData *md; unsigned int key; MetaVirtualModifier mods; @@ -342,14 +380,9 @@ meta_window_menu_new (MetaFrames *frames, i + 1, &key, &mods); - name = get_workspace_name_with_accel (display, xroot, i); - if (ops & META_MENU_OP_UNSTICK) - label = g_strdup_printf (_("Only on %s"), name); - else - label = g_strdup_printf(_("Move to %s"), name); - mi = menu_item_new (label, FALSE, key, mods); + label = get_workspace_name_with_accel (display, xroot, i); + mi = menu_item_new (label, FALSE, FALSE, key, mods); - g_free (name); g_free (label); if (!(ops & META_MENU_OP_UNSTICK) && @@ -374,7 +407,7 @@ meta_window_menu_new (MetaFrames *frames, md, g_free, FALSE, FALSE); - gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), mi); gtk_widget_show (mi); diff --git a/src/window.c b/src/window.c index 384d790a1..65002124c 100644 --- a/src/window.c +++ b/src/window.c @@ -5518,9 +5518,11 @@ menu_callback (MetaWindowMenu *menu, { MetaDisplay *display; MetaWindow *window; + MetaWorkspace *workspace; display = meta_display_for_x_display (xdisplay); window = meta_display_lookup_x_window (display, client_xwindow); + workspace = NULL; if (window != NULL) /* window can be NULL */ { @@ -5553,26 +5555,29 @@ menu_callback (MetaWindowMenu *menu, meta_window_shade (window); break; + case META_MENU_OP_MOVE_LEFT: + workspace = meta_workspace_get_neighbor (window->screen->active_workspace, + META_MOTION_LEFT); + break; + + case META_MENU_OP_MOVE_RIGHT: + workspace = meta_workspace_get_neighbor (window->screen->active_workspace, + META_MOTION_RIGHT); + break; + + case META_MENU_OP_MOVE_UP: + workspace = meta_workspace_get_neighbor (window->screen->active_workspace, + META_MOTION_UP); + break; + + case META_MENU_OP_MOVE_DOWN: + workspace = meta_workspace_get_neighbor (window->screen->active_workspace, + META_MOTION_DOWN); + break; + case META_MENU_OP_WORKSPACES: - { - MetaWorkspace *workspace; - - workspace = - meta_screen_get_workspace_by_index (window->screen, - workspace_index); - - if (workspace) - { - meta_window_change_workspace (window, - workspace); -#if 0 - meta_workspace_activate (workspace); - meta_window_raise (window); -#endif - } - else - meta_warning ("Workspace %d doesn't exist\n", workspace_index); - } + workspace = meta_screen_get_workspace_by_index (window->screen, + workspace_index); break; case META_MENU_OP_STICK: @@ -5583,6 +5588,14 @@ menu_callback (MetaWindowMenu *menu, meta_window_unstick (window); break; + case META_MENU_OP_ABOVE: + meta_window_make_above (window); + break; + + case META_MENU_OP_UNABOVE: + meta_window_unmake_above (window); + break; + case META_MENU_OP_MOVE: meta_window_begin_grab_op (window, META_GRAB_OP_KEYBOARD_MOVING, @@ -5603,6 +5616,16 @@ menu_callback (MetaWindowMenu *menu, meta_warning (G_STRLOC": Unknown window op\n"); break; } + + if (workspace) + { + meta_window_change_workspace (window, + workspace); +#if 0 + meta_workspace_activate (workspace); + meta_window_raise (window); +#endif + } } else { @@ -5628,6 +5651,7 @@ meta_window_show_menu (MetaWindow *window, MetaMenuOp ops; MetaMenuOp insensitive; MetaWindowMenu *menu; + MetaWorkspaceLayout layout; if (window->display->window_menu) { @@ -5640,22 +5664,43 @@ meta_window_show_menu (MetaWindow *window, insensitive = 0; ops |= (META_MENU_OP_DELETE | META_MENU_OP_WORKSPACES | META_MENU_OP_MINIMIZE | META_MENU_OP_MOVE | META_MENU_OP_RESIZE); + + meta_screen_calc_workspace_layout (window->screen, + meta_screen_get_n_workspaces (window->screen), + meta_workspace_index ( window->screen->active_workspace), + &layout); + + if (layout.current_col > 0) + ops |= META_MENU_OP_MOVE_LEFT; + if (layout.current_col < layout.cols - 1) + ops |= META_MENU_OP_MOVE_RIGHT; + if (layout.current_row > 0) + ops |= META_MENU_OP_MOVE_UP; + if (layout.current_row < layout.rows - 1) + ops |= META_MENU_OP_MOVE_DOWN; if (window->maximized) ops |= META_MENU_OP_UNMAXIMIZE; else ops |= META_MENU_OP_MAXIMIZE; +#if 0 if (window->shaded) ops |= META_MENU_OP_UNSHADE; else ops |= META_MENU_OP_SHADE; +#endif if (window->on_all_workspaces) ops |= META_MENU_OP_UNSTICK; else ops |= META_MENU_OP_STICK; + if (window->wm_state_above) + ops |= META_MENU_OP_UNABOVE; + else + ops |= META_MENU_OP_ABOVE; + if (!window->has_maximize_func) insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE;