Reorganize the window menu according to discussion on #110904. The

2003-12-20  Rob Adams  <readams@readams.net>

	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.
This commit is contained in:
Rob Adams 2003-12-21 06:31:40 +00:00 committed by Rob Adams
parent 95b0ee480e
commit 690100f1ad
5 changed files with 182 additions and 58 deletions

View File

@ -1,3 +1,31 @@
2003-12-20 Rob Adams <readams@readams.net>
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 <lumina@silverpen.de> 2003-12-20 Arafat Medini <lumina@silverpen.de>
* configure.in: Added Arabic locale "ar" to ALL_LINGUAS * configure.in: Added Arabic locale "ar" to ALL_LINGUAS

View File

@ -58,7 +58,13 @@ typedef enum
META_MENU_OP_STICK = 1 << 7, META_MENU_OP_STICK = 1 << 7,
META_MENU_OP_WORKSPACES = 1 << 8, META_MENU_OP_WORKSPACES = 1 << 8,
META_MENU_OP_MOVE = 1 << 9, 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; } MetaMenuOp;
typedef struct _MetaWindowMenu MetaWindowMenu; typedef struct _MetaWindowMenu MetaWindowMenu;

View File

@ -586,17 +586,17 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
name = META_KEYBINDING_MAXIMIZE; name = META_KEYBINDING_MAXIMIZE;
break; break;
case META_MENU_OP_UNSHADE: case META_MENU_OP_UNSHADE:
name = META_KEYBINDING_TOGGLE_SHADE;
break;
case META_MENU_OP_SHADE: case META_MENU_OP_SHADE:
name = META_KEYBINDING_TOGGLE_SHADE; name = META_KEYBINDING_TOGGLE_SHADE;
break; break;
case META_MENU_OP_UNSTICK: case META_MENU_OP_UNSTICK:
name = META_KEYBINDING_TOGGLE_STICKY;
break;
case META_MENU_OP_STICK: case META_MENU_OP_STICK:
name = META_KEYBINDING_TOGGLE_STICKY; name = META_KEYBINDING_TOGGLE_STICKY;
break; break;
case META_MENU_OP_ABOVE:
case META_MENU_OP_UNABOVE:
name = META_KEYBINDING_TOGGLE_ABOVE;
break;
case META_MENU_OP_WORKSPACES: case META_MENU_OP_WORKSPACES:
switch (workspace) switch (workspace)
{ {
@ -644,6 +644,18 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
case META_MENU_OP_RESIZE: case META_MENU_OP_RESIZE:
name = META_KEYBINDING_BEGIN_RESIZE; name = META_KEYBINDING_BEGIN_RESIZE;
break; 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) if (name)

View File

@ -36,6 +36,7 @@ struct _MenuItem
{ {
MetaMenuOp op; MetaMenuOp op;
const char *stock_id; const char *stock_id;
const gboolean checked;
const char *label; const char *label;
}; };
@ -49,18 +50,24 @@ struct _MenuData
static void activate_cb (GtkWidget *menuitem, gpointer data); static void activate_cb (GtkWidget *menuitem, gpointer data);
static MenuItem menuitems[] = { static MenuItem menuitems[] = {
{ META_MENU_OP_MINIMIZE, METACITY_STOCK_MINIMIZE, N_("Mi_nimize") }, { META_MENU_OP_MINIMIZE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") },
{ META_MENU_OP_MAXIMIZE, METACITY_STOCK_MAXIMIZE, N_("Ma_ximize") }, { META_MENU_OP_MAXIMIZE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") },
{ META_MENU_OP_UNMAXIMIZE, NULL, N_("Unma_ximize") }, { META_MENU_OP_UNMAXIMIZE, NULL, FALSE, N_("Unma_ximize") },
{ META_MENU_OP_SHADE, NULL, N_("Roll _Up") }, { META_MENU_OP_SHADE, NULL, FALSE, N_("Roll _Up") },
{ META_MENU_OP_UNSHADE, NULL, N_("_Unroll") }, { META_MENU_OP_UNSHADE, NULL, FALSE, N_("_Unroll") },
{ META_MENU_OP_MOVE, NULL, N_("_Move") }, { META_MENU_OP_ABOVE, NULL, FALSE, N_("On _Top") },
{ META_MENU_OP_RESIZE, NULL, N_("_Resize") }, { META_MENU_OP_UNABOVE, NULL, TRUE, N_("On _Top") },
{ 0, NULL, NULL }, /* separator */ { META_MENU_OP_MOVE, NULL, FALSE, N_("_Move") },
{ META_MENU_OP_DELETE, METACITY_STOCK_DELETE, N_("_Close") }, { META_MENU_OP_RESIZE, NULL, FALSE, N_("_Resize") },
{ 0, NULL, NULL }, /* separator */ { 0, NULL, FALSE, NULL }, /* separator */
{ META_MENU_OP_STICK, NULL, N_("Put on _All Workspaces") }, { META_MENU_OP_DELETE, METACITY_STOCK_DELETE, FALSE, N_("_Close") },
{ META_MENU_OP_UNSTICK, NULL, N_("Only on _This Workspace") } { 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 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 * Above name is a pointer into the Workspace struct. Here we make
* a copy copy so we can have our wicked way with it. * a copy copy so we can have our wicked way with it.
*/ */
new_name = g_strdup_printf (_("Workspace %s%d"), if (number == 10)
number < 10 ? "_" : "", new_name = g_strdup_printf (_("Workspace 1_0"));
number); else
new_name = g_strdup_printf (_("Workspace %s%d"),
number < 10 ? "_" : "",
number);
return new_name; return new_name;
} }
else else
{ {
/* /*
* Otherwise this is just a normal name to which we cannot really * Otherwise this is just a normal name. Escape any _ characters so that
* add accelerators. Escape any _ characters so that the user's * the user's workspace names do not get mangled. If the number is less
* workspace names do not get mangled. * than 10 we provide an accelerator.
*/ */
char *new_name; char *new_name;
const char *source; const char *source;
char *dest; 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 * Now iterate down the strings, adding '_' to escape as we go
@ -190,6 +201,16 @@ get_workspace_name_with_accel (Display *display,
*dest++ = *source++; *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; return new_name;
} }
} }
@ -197,13 +218,20 @@ get_workspace_name_with_accel (Display *display,
static GtkWidget* static GtkWidget*
menu_item_new (const char *label, menu_item_new (const char *label,
gboolean with_image, gboolean with_image,
gboolean with_check,
unsigned int key, unsigned int key,
MetaVirtualModifier mods) MetaVirtualModifier mods)
{ {
GtkWidget *menu_item; GtkWidget *menu_item;
GtkWidget *accel_label; 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 (); menu_item = gtk_image_menu_item_new ();
else else
menu_item = gtk_menu_item_new (); 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, meta_core_get_menu_accelerator (menuitems[i].op, -1,
&key, &mods); &key, &mods);
if (image) 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), gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),
image); image);
gtk_widget_show (image); gtk_widget_show (image);
} }
else 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) if (insensitive & menuitems[i].op)
@ -321,6 +350,8 @@ meta_window_menu_new (MetaFrames *frames,
Display *display; Display *display;
Window xroot; Window xroot;
GdkScreen *screen; GdkScreen *screen;
GtkWidget *submenu;
GtkWidget *submenuitem;
meta_verbose ("Creating %d-workspace menu current space %d\n", meta_verbose ("Creating %d-workspace menu current space %d\n",
n_workspaces, active_workspace); n_workspaces, active_workspace);
@ -329,11 +360,18 @@ meta_window_menu_new (MetaFrames *frames,
screen = gdk_drawable_get_screen (GTK_WIDGET (frames)->window); screen = gdk_drawable_get_screen (GTK_WIDGET (frames)->window);
xroot = GDK_DRAWABLE_XID (gdk_screen_get_root_window (screen)); 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; i = 0;
while (i < n_workspaces) while (i < n_workspaces)
{ {
char *label, *name; char *label;
MenuData *md; MenuData *md;
unsigned int key; unsigned int key;
MetaVirtualModifier mods; MetaVirtualModifier mods;
@ -342,14 +380,9 @@ meta_window_menu_new (MetaFrames *frames,
i + 1, i + 1,
&key, &mods); &key, &mods);
name = get_workspace_name_with_accel (display, xroot, i); label = get_workspace_name_with_accel (display, xroot, i);
if (ops & META_MENU_OP_UNSTICK) mi = menu_item_new (label, FALSE, FALSE, key, mods);
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);
g_free (name);
g_free (label); g_free (label);
if (!(ops & META_MENU_OP_UNSTICK) && if (!(ops & META_MENU_OP_UNSTICK) &&
@ -374,7 +407,7 @@ meta_window_menu_new (MetaFrames *frames,
md, md,
g_free, FALSE, FALSE); g_free, FALSE, FALSE);
gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), gtk_menu_shell_append (GTK_MENU_SHELL (submenu),
mi); mi);
gtk_widget_show (mi); gtk_widget_show (mi);

View File

@ -5518,9 +5518,11 @@ menu_callback (MetaWindowMenu *menu,
{ {
MetaDisplay *display; MetaDisplay *display;
MetaWindow *window; MetaWindow *window;
MetaWorkspace *workspace;
display = meta_display_for_x_display (xdisplay); display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, client_xwindow); window = meta_display_lookup_x_window (display, client_xwindow);
workspace = NULL;
if (window != NULL) /* window can be NULL */ if (window != NULL) /* window can be NULL */
{ {
@ -5553,26 +5555,29 @@ menu_callback (MetaWindowMenu *menu,
meta_window_shade (window); meta_window_shade (window);
break; 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: case META_MENU_OP_WORKSPACES:
{ workspace = meta_screen_get_workspace_by_index (window->screen,
MetaWorkspace *workspace; workspace_index);
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);
}
break; break;
case META_MENU_OP_STICK: case META_MENU_OP_STICK:
@ -5583,6 +5588,14 @@ menu_callback (MetaWindowMenu *menu,
meta_window_unstick (window); meta_window_unstick (window);
break; 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: case META_MENU_OP_MOVE:
meta_window_begin_grab_op (window, meta_window_begin_grab_op (window,
META_GRAB_OP_KEYBOARD_MOVING, META_GRAB_OP_KEYBOARD_MOVING,
@ -5603,6 +5616,16 @@ menu_callback (MetaWindowMenu *menu,
meta_warning (G_STRLOC": Unknown window op\n"); meta_warning (G_STRLOC": Unknown window op\n");
break; break;
} }
if (workspace)
{
meta_window_change_workspace (window,
workspace);
#if 0
meta_workspace_activate (workspace);
meta_window_raise (window);
#endif
}
} }
else else
{ {
@ -5628,6 +5651,7 @@ meta_window_show_menu (MetaWindow *window,
MetaMenuOp ops; MetaMenuOp ops;
MetaMenuOp insensitive; MetaMenuOp insensitive;
MetaWindowMenu *menu; MetaWindowMenu *menu;
MetaWorkspaceLayout layout;
if (window->display->window_menu) if (window->display->window_menu)
{ {
@ -5640,22 +5664,43 @@ meta_window_show_menu (MetaWindow *window,
insensitive = 0; insensitive = 0;
ops |= (META_MENU_OP_DELETE | META_MENU_OP_WORKSPACES | META_MENU_OP_MINIMIZE | META_MENU_OP_MOVE | META_MENU_OP_RESIZE); 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) if (window->maximized)
ops |= META_MENU_OP_UNMAXIMIZE; ops |= META_MENU_OP_UNMAXIMIZE;
else else
ops |= META_MENU_OP_MAXIMIZE; ops |= META_MENU_OP_MAXIMIZE;
#if 0
if (window->shaded) if (window->shaded)
ops |= META_MENU_OP_UNSHADE; ops |= META_MENU_OP_UNSHADE;
else else
ops |= META_MENU_OP_SHADE; ops |= META_MENU_OP_SHADE;
#endif
if (window->on_all_workspaces) if (window->on_all_workspaces)
ops |= META_MENU_OP_UNSTICK; ops |= META_MENU_OP_UNSTICK;
else else
ops |= META_MENU_OP_STICK; 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) if (!window->has_maximize_func)
insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE; insensitive |= META_MENU_OP_UNMAXIMIZE | META_MENU_OP_MAXIMIZE;