Compare commits

...

4 Commits

Author SHA1 Message Date
9e2fc32395 Keybindings: uniquify the name for non-builtin keybindings
Multiple settings objects could have the same key, so that alone
is not enough to identify the binding. Add also the pointer value
of the GSettings object.

https://bugzilla.gnome.org/show_bug.cgi?id=613543
2012-11-10 17:06:29 +01:00
53a17185a0 Allow a keybinding handler to ignore a keybinding
Previous commit moved policy for keybindings when grabbed down to
the handler, but did not replay the event if it is was not handled.
This commit adds the missing bit.

https://bugzilla.gnome.org/show_bug.cgi?id=613543
2012-11-10 17:06:29 +01:00
fa679976e3 Handle some keybindings even when a compositor grab is active
Do not ignore all key events automatically when a compositor grab
is active, and introduce a flag for masking which keybindings should
be active.
This does not mean that automatically all keybindings are active
when the compositor is modal, it merely moves the policy down to
the handler.

https://bugzilla.gnome.org/show_bug.cgi?id=613543
2012-11-10 17:06:29 +01:00
f505c59a9f Keybindings: add a mechanism to grab a specific key combination
Instead of requiring a GSettings object, allow to hardcode a specific
combination for a keybinding. This will be used by the Shell to
replace the media keys plugin in gnome-settings-daemon.

https://bugzilla.gnome.org/show_bug.cgi?id=613543
2012-11-10 17:06:29 +01:00
6 changed files with 323 additions and 129 deletions

View File

@ -1961,9 +1961,6 @@ event_callback (XEvent *event,
{
case KeyPress:
case KeyRelease:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
/* For key events, it's important to enforce single-handling, or
* we can get into a confused state. So if a keybinding is
* handled (because it's one of our hot-keys, or because we are

View File

@ -75,6 +75,8 @@ void meta_display_process_mapping_event (MetaDisplay *display,
gboolean meta_prefs_add_keybinding (const char *name,
GSettings *settings,
const char *setting_key,
const char *hardcoded_key,
MetaKeyBindingAction action,
MetaKeyBindingFlags flags);

View File

@ -99,12 +99,12 @@ meta_key_binding_get_mask (MetaKeyBinding *binding)
* handler functions and have some kind of flag to say they're unbindable.
*/
static void handle_workspace_switch (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy);
static gboolean handle_workspace_switch (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy);
static gboolean process_mouse_move_resize_grab (MetaDisplay *display,
MetaScreen *screen,
@ -539,6 +539,8 @@ static gboolean
add_keybinding_internal (MetaDisplay *display,
const char *name,
GSettings *settings,
const char *setting_key,
const char *hardcoded_key,
MetaKeyBindingFlags flags,
MetaKeyBindingAction action,
MetaKeyHandlerFunc func,
@ -548,7 +550,7 @@ add_keybinding_internal (MetaDisplay *display,
{
MetaKeyHandler *handler;
if (!meta_prefs_add_keybinding (name, settings, action, flags))
if (!meta_prefs_add_keybinding (name, settings, setting_key, hardcoded_key, action, flags))
return FALSE;
handler = g_new0 (MetaKeyHandler, 1);
@ -567,16 +569,20 @@ add_keybinding_internal (MetaDisplay *display,
static gboolean
add_builtin_keybinding (MetaDisplay *display,
const char *name,
const char *key,
GSettings *settings,
MetaKeyBindingFlags flags,
MetaKeyBindingAction action,
MetaKeyHandlerFunc handler,
int handler_arg)
{
return add_keybinding_internal (display, name, settings,
char *name = g_strdup_printf ("internal-keybinding-%s", key);
return add_keybinding_internal (display, name, settings, key, NULL,
flags | META_KEY_BINDING_BUILTIN,
action, handler, handler_arg, NULL, NULL);
g_free (name);
}
/**
@ -608,22 +614,74 @@ add_builtin_keybinding (MetaDisplay *display,
*/
gboolean
meta_display_add_keybinding (MetaDisplay *display,
const char *name,
const char *key,
GSettings *settings,
MetaKeyBindingFlags flags,
MetaKeyHandlerFunc handler,
gpointer user_data,
GDestroyNotify free_data)
{
return add_keybinding_internal (display, name, settings, flags,
META_KEYBINDING_ACTION_NONE,
char *name = g_strdup_printf("custom-keybinding-%p-%s", settings, key);
return add_keybinding_internal (display, name, settings, key, NULL,
flags, META_KEYBINDING_ACTION_NONE,
handler, 0, user_data, free_data);
g_free (name);
}
/**
* meta_display_add_grabbed_key:
* @display: a #MetaDisplay
* @name: the binding's name
* @keyval: the key combination that should trigger this keybinding
* @flags: flags to specify binding details
* @handler: function to run when the keybinding is invoked
* @user_data: the data to pass to @handler
* @free_data: function to free @user_data
*
* This function is similar to meta_display_add_keybinding(), except
* that the keybinding is hardcoded to @keyval, which should be a GTK
* key string combination.
*/
gboolean
meta_display_add_grabbed_key (MetaDisplay *display,
const char *name,
const char *keyval,
MetaKeyBindingFlags flags,
MetaKeyHandlerFunc handler,
gpointer user_data,
GDestroyNotify free_data)
{
return add_keybinding_internal (display, name, NULL, NULL, keyval,
flags, META_KEYBINDING_ACTION_NONE,
handler, 0, user_data, free_data);
}
/**
* meta_display_remove_grabbed_key:
* @display: the #MetaDisplay
* @name: the name that was passed to meta_display_add_grabbed_key()
*
* Undoes the effect of meta_display_add_grabbed_key()
*/
gboolean
meta_display_remove_grabbed_key (MetaDisplay *display,
const char *name)
{
if (!meta_prefs_remove_keybinding (name))
return FALSE;
g_hash_table_remove (key_handlers, name);
return TRUE;
}
/**
* meta_display_remove_keybinding:
* @display: the #MetaDisplay
* @name: name of the keybinding to remove
* @settings: (allow-none): the #GSettings object on which the keybinding is registered
*
* Remove keybinding @name; the function will fail if @name is not a known
* keybinding or has not been added with meta_display_add_keybinding().
@ -633,14 +691,28 @@ meta_display_add_keybinding (MetaDisplay *display,
*/
gboolean
meta_display_remove_keybinding (MetaDisplay *display,
const char *name)
const char *key,
GSettings *settings)
{
gboolean retval;
char *name;
if (settings)
name = g_strdup_printf ("custom-keybinding-%p-%s", settings, key);
else
name = g_strdup (key);
retval = FALSE;
if (!meta_prefs_remove_keybinding (name))
return FALSE;
goto out;
g_hash_table_remove (key_handlers, name);
return TRUE;
retval = TRUE;
out:
g_free (name);
return retval;
}
/**
@ -1344,7 +1416,7 @@ primary_modifier_still_pressed (MetaDisplay *display,
return TRUE;
}
static void
static gboolean
invoke_handler (MetaDisplay *display,
MetaScreen *screen,
MetaKeyHandler *handler,
@ -1354,22 +1426,22 @@ invoke_handler (MetaDisplay *display,
{
if (handler->func)
(* handler->func) (display, screen,
handler->flags & META_KEY_BINDING_PER_WINDOW ?
window : NULL,
event,
binding,
handler->user_data);
return (* handler->func) (display, screen,
handler->flags & META_KEY_BINDING_PER_WINDOW ?
window : NULL,
event,
binding,
handler->user_data);
else
(* handler->default_func) (display, screen,
handler->flags & META_KEY_BINDING_PER_WINDOW ?
window: NULL,
event,
binding,
NULL);
return (* handler->default_func) (display, screen,
handler->flags & META_KEY_BINDING_PER_WINDOW ?
window: NULL,
event,
binding,
NULL);
}
static void
static gboolean
invoke_handler_by_name (MetaDisplay *display,
MetaScreen *screen,
const char *handler_name,
@ -1380,7 +1452,8 @@ invoke_handler_by_name (MetaDisplay *display,
handler = HANDLER (handler_name);
if (handler)
invoke_handler (display, screen, handler, window, event, NULL);
return invoke_handler (display, screen, handler, window, event, NULL);
return FALSE;
}
/* now called from only one place, may be worth merging */
@ -1415,6 +1488,10 @@ process_event (MetaKeyBinding *bindings,
bindings[i].mask))
continue;
if (display->grab_op != META_GRAB_OP_NONE &&
(handler->flags & META_KEY_BINDING_HANDLE_WHEN_GRABBED) == 0)
continue;
/*
* window must be non-NULL for on_window to be true,
* and so also window must be non-NULL if we get here and
@ -1439,9 +1516,7 @@ process_event (MetaKeyBinding *bindings,
*/
display->allow_terminal_deactivation = TRUE;
invoke_handler (display, screen, handler, window, event, &bindings[i]);
return TRUE;
return invoke_handler (display, screen, handler, window, event, &bindings[i]);
}
meta_topic (META_DEBUG_KEYBINDINGS,
@ -1664,6 +1739,11 @@ meta_display_process_key_event (MetaDisplay *display,
"Processing event for keyboard workspace switching\n");
keep_grab = process_workspace_switch_grab (display, screen, event, keysym);
break;
case META_GRAB_OP_COMPOSITOR:
/* Compositor grabs don't go through meta_display_begin_grab_op(),
so all_keys_grabbed is always false for them */
g_assert_not_reached ();
default:
break;
@ -2550,7 +2630,7 @@ process_tab_grab (MetaDisplay *display,
return key_used;
}
static void
static gboolean
handle_switch_to_workspace (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
@ -2575,7 +2655,7 @@ handle_switch_to_workspace (MetaDisplay *display,
*/
handle_workspace_switch (display, screen, event_window, event, binding,
dummy);
return;
return TRUE;
}
workspace = meta_screen_get_workspace_by_index (screen, which);
@ -2588,10 +2668,12 @@ handle_switch_to_workspace (MetaDisplay *display,
{
/* We could offer to create it I suppose */
}
return TRUE;
}
static void
static gboolean
handle_maximize_vertically (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2606,9 +2688,11 @@ handle_maximize_vertically (MetaDisplay *display,
else
meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
}
return TRUE;
}
static void
static gboolean
handle_maximize_horizontally (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2623,6 +2707,8 @@ handle_maximize_horizontally (MetaDisplay *display,
else
meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
}
return TRUE;
}
/* Move a window to a corner; to_bottom/to_right are FALSE for the
@ -2672,7 +2758,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
new_y);
}
static void
static gboolean
handle_move_to_corner_nw (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2681,9 +2767,10 @@ handle_move_to_corner_nw (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, FALSE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_corner_ne (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2692,9 +2779,10 @@ handle_move_to_corner_ne (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, FALSE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_corner_sw (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2703,9 +2791,10 @@ handle_move_to_corner_sw (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, FALSE, TRUE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_corner_se (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2714,9 +2803,10 @@ handle_move_to_corner_se (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, TRUE, TRUE, TRUE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_side_n (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2725,9 +2815,10 @@ handle_move_to_side_n (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, FALSE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_side_s (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2736,9 +2827,10 @@ handle_move_to_side_s (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, FALSE, TRUE, FALSE, TRUE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_side_e (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2747,9 +2839,10 @@ handle_move_to_side_e (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, TRUE, FALSE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_side_w (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2758,9 +2851,10 @@ handle_move_to_side_w (MetaDisplay *display,
gpointer dummy)
{
handle_move_to_corner_backend (display, screen, window, TRUE, FALSE, FALSE, FALSE, dummy);
return TRUE;
}
static void
static gboolean
handle_move_to_center (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2786,6 +2880,8 @@ handle_move_to_center (MetaDisplay *display,
work_area.y + (work_area.height+frame_height-outer.height)/2,
window->rect.width,
window->rect.height);
return FALSE;
}
static gboolean
@ -2902,7 +2998,7 @@ process_workspace_switch_grab (MetaDisplay *display,
return FALSE;
}
static void
static gboolean
handle_show_desktop (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2919,9 +3015,11 @@ handle_show_desktop (MetaDisplay *display,
}
else
meta_screen_show_desktop (screen, event->xkey.time);
return TRUE;
}
static void
static gboolean
handle_panel (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -2944,7 +3042,7 @@ handle_panel (MetaDisplay *display,
action_atom = display->atom__GNOME_PANEL_ACTION_RUN_DIALOG;
break;
default:
return;
return FALSE;
}
ev.type = ClientMessage;
@ -2971,9 +3069,11 @@ handle_panel (MetaDisplay *display,
(XEvent*) &ev);
meta_error_trap_pop (display);
return TRUE;
}
static void
static gboolean
handle_activate_window_menu (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
@ -2996,6 +3096,8 @@ handle_activate_window_menu (MetaDisplay *display,
0,
event->xkey.time);
}
return TRUE;
}
static MetaGrabOp
@ -3142,7 +3244,7 @@ do_choose_window (MetaDisplay *display,
}
}
static void
static gboolean
handle_switch (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
@ -3154,9 +3256,10 @@ handle_switch (MetaDisplay *display,
do_choose_window (display, screen, event_window, event, binding,
backwards, TRUE);
return TRUE;
}
static void
static gboolean
handle_cycle (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
@ -3168,9 +3271,10 @@ handle_cycle (MetaDisplay *display,
do_choose_window (display, screen, event_window, event, binding,
backwards, FALSE);
return TRUE;
}
static void
static gboolean
handle_tab_popup_select (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3179,9 +3283,10 @@ handle_tab_popup_select (MetaDisplay *display,
gpointer dummy)
{
/* Stub for custom handlers; no default implementation */
return FALSE;
}
static void
static gboolean
handle_tab_popup_cancel (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3190,9 +3295,10 @@ handle_tab_popup_cancel (MetaDisplay *display,
gpointer dummy)
{
/* Stub for custom handlers; no default implementation */
return FALSE;
}
static void
static gboolean
handle_toggle_fullscreen (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3204,9 +3310,11 @@ handle_toggle_fullscreen (MetaDisplay *display,
meta_window_unmake_fullscreen (window);
else if (window->has_fullscreen_func)
meta_window_make_fullscreen (window);
return TRUE;
}
static void
static gboolean
handle_toggle_above (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3218,9 +3326,11 @@ handle_toggle_above (MetaDisplay *display,
meta_window_unmake_above (window);
else
meta_window_make_above (window);
return TRUE;
}
static void
static gboolean
handle_toggle_tiled (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3258,9 +3368,11 @@ handle_toggle_tiled (MetaDisplay *display,
window->maximized_horizontally = FALSE;
meta_window_tile (window);
}
return TRUE;
}
static void
static gboolean
handle_toggle_maximized (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3276,9 +3388,11 @@ handle_toggle_maximized (MetaDisplay *display,
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
return TRUE;
}
static void
static gboolean
handle_maximize (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3290,9 +3404,11 @@ handle_maximize (MetaDisplay *display,
meta_window_maximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
return TRUE;
}
static void
static gboolean
handle_unmaximize (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3304,9 +3420,11 @@ handle_unmaximize (MetaDisplay *display,
meta_window_unmaximize (window,
META_MAXIMIZE_HORIZONTAL |
META_MAXIMIZE_VERTICAL);
return TRUE;
}
static void
static gboolean
handle_toggle_shaded (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3318,9 +3436,11 @@ handle_toggle_shaded (MetaDisplay *display,
meta_window_unshade (window, event->xkey.time);
else if (window->has_shade_func)
meta_window_shade (window, event->xkey.time);
return TRUE;
}
static void
static gboolean
handle_close (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3330,9 +3450,11 @@ handle_close (MetaDisplay *display,
{
if (window->has_close_func)
meta_window_delete (window, event->xkey.time);
return TRUE;
}
static void
static gboolean
handle_minimize (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3342,9 +3464,11 @@ handle_minimize (MetaDisplay *display,
{
if (window->has_minimize_func)
meta_window_minimize (window);
return TRUE;
}
static void
static gboolean
handle_begin_move (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3359,9 +3483,11 @@ handle_begin_move (MetaDisplay *display,
FALSE,
event->xkey.time);
}
return TRUE;
}
static void
static gboolean
handle_begin_resize (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3376,9 +3502,11 @@ handle_begin_resize (MetaDisplay *display,
FALSE,
event->xkey.time);
}
return TRUE;
}
static void
static gboolean
handle_toggle_on_all_workspaces (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3390,13 +3518,15 @@ handle_toggle_on_all_workspaces (MetaDisplay *display,
meta_window_unstick (window);
else
meta_window_stick (window);
return TRUE;
}
static void
static gboolean
handle_move_to_workspace (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
@ -3413,11 +3543,11 @@ handle_move_to_workspace (MetaDisplay *display,
*/
if (window->always_sticky)
return;
return FALSE;
workspace = NULL;
if (flip)
{
{
workspace = meta_workspace_get_neighbor (screen->active_workspace,
which);
}
@ -3425,7 +3555,7 @@ handle_move_to_workspace (MetaDisplay *display,
{
workspace = meta_screen_get_workspace_by_index (screen, which);
}
if (workspace)
{
/* Activate second, so the window is never unmapped */
@ -3444,10 +3574,12 @@ handle_move_to_workspace (MetaDisplay *display,
else
{
/* We could offer to create it I suppose */
}
}
return TRUE;
}
static void
static gboolean
handle_raise_or_lower (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3463,7 +3595,7 @@ handle_raise_or_lower (MetaDisplay *display,
if (meta_stack_get_top (window->screen->stack) == window)
{
meta_window_lower (window);
return;
return TRUE;
}
/* else check if windows in same layer are intersecting it */
@ -3483,7 +3615,7 @@ handle_raise_or_lower (MetaDisplay *display,
if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
{
meta_window_raise (window);
return;
return TRUE;
}
}
@ -3492,9 +3624,10 @@ handle_raise_or_lower (MetaDisplay *display,
/* window is not obscured */
meta_window_lower (window);
return TRUE;
}
static void
static gboolean
handle_raise (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3503,9 +3636,11 @@ handle_raise (MetaDisplay *display,
gpointer dummy)
{
meta_window_raise (window);
return TRUE;
}
static void
static gboolean
handle_lower (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3514,9 +3649,11 @@ handle_lower (MetaDisplay *display,
gpointer dummy)
{
meta_window_lower (window);
return TRUE;
}
static void
static gboolean
handle_workspace_switch (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
@ -3547,7 +3684,7 @@ handle_workspace_switch (MetaDisplay *display,
grab_mask,
event->xkey.time,
0, 0))
return;
return FALSE;
next = meta_workspace_get_neighbor (screen->active_workspace, motion);
g_assert (next);
@ -3570,17 +3707,21 @@ handle_workspace_switch (MetaDisplay *display,
if (grabbed_before_release && !meta_prefs_get_no_tab_popup ())
meta_screen_workspace_popup_create (screen, next);
return TRUE;
}
static void
static gboolean
handle_set_spew_mark (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
meta_verbose ("-- MARK MARK MARK MARK --\n");
return TRUE;
}
void
@ -3726,28 +3867,28 @@ init_builtin_key_bindings (MetaDisplay *display)
add_builtin_keybinding (display,
"switch-to-workspace-left",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_WORKSPACE_LEFT,
handle_switch_to_workspace, META_MOTION_LEFT);
add_builtin_keybinding (display,
"switch-to-workspace-right",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
handle_switch_to_workspace, META_MOTION_RIGHT);
add_builtin_keybinding (display,
"switch-to-workspace-up",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_WORKSPACE_UP,
handle_switch_to_workspace, META_MOTION_UP);
add_builtin_keybinding (display,
"switch-to-workspace-down",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_WORKSPACE_DOWN,
handle_switch_to_workspace, META_MOTION_DOWN);
@ -3793,14 +3934,14 @@ init_builtin_key_bindings (MetaDisplay *display)
add_builtin_keybinding (display,
"switch-panels",
common_keybindings,
META_KEY_BINDING_REVERSES,
META_KEY_BINDING_REVERSES | META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_SWITCH_PANELS,
handle_switch, META_TAB_LIST_DOCKS);
add_builtin_keybinding (display,
"switch-panels-backward",
common_keybindings,
REVERSES_AND_REVERSED,
REVERSES_AND_REVERSED | META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD,
handle_switch, META_TAB_LIST_DOCKS);
@ -3878,14 +4019,14 @@ init_builtin_key_bindings (MetaDisplay *display)
add_builtin_keybinding (display,
"panel-main-menu",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
handle_panel, META_KEYBINDING_ACTION_PANEL_MAIN_MENU);
add_builtin_keybinding (display,
"panel-run-dialog",
common_keybindings,
META_KEY_BINDING_NONE,
META_KEY_BINDING_HANDLE_WHEN_GRABBED,
META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
handle_panel, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG);

View File

@ -110,13 +110,12 @@ static gboolean workspaces_only_on_primary = FALSE;
static gboolean no_tab_popup = FALSE;
static GHashTable *key_bindings;
static void handle_preference_update_enum (GSettings *settings,
gchar *key);
static gboolean update_binding (MetaKeyPref *binding,
gchar **strokes);
static gboolean update_key_binding (const char *key,
gchar **strokes);
static gboolean update_workspace_names (void);
static void settings_changed (GSettings *settings,
@ -1052,13 +1051,30 @@ bindings_changed (GSettings *settings,
gchar *key,
gpointer data)
{
gchar *static_strokes[2];
gchar **strokes;
strokes = g_settings_get_strv (settings, key);
MetaKeyPref *pref;
if (update_key_binding (key, strokes))
queue_changed (META_PREF_KEYBINDINGS);
pref = g_hash_table_lookup (key_bindings, key);
if (!pref)
return;
g_strfreev (strokes);
if (pref->is_single)
{
static_strokes[0] = g_settings_get_string (settings, key);
static_strokes[1] = NULL;
strokes = static_strokes;
}
else
strokes = g_settings_get_strv (settings, key);
update_binding (pref, strokes);
queue_changed (META_PREF_KEYBINDINGS);
if (strokes != static_strokes)
g_strfreev(strokes);
else
g_free(static_strokes[0]);
}
/**
@ -1693,7 +1709,10 @@ meta_key_pref_free (MetaKeyPref *pref)
update_binding (pref, NULL);
g_free (pref->name);
g_object_unref (pref->settings);
if (pref->settings)
g_object_unref (pref->settings);
g_free (pref->setting_key);
g_free (pref->hardcoded_key);
g_free (pref);
}
@ -1785,18 +1804,6 @@ update_binding (MetaKeyPref *binding,
return changed;
}
static gboolean
update_key_binding (const char *key,
gchar **strokes)
{
MetaKeyPref *pref = g_hash_table_lookup (key_bindings, key);
if (pref)
return update_binding (pref, strokes);
else
return FALSE;
}
static gboolean
update_workspace_names (void)
{
@ -1929,11 +1936,14 @@ meta_prefs_get_visual_bell_type (void)
gboolean
meta_prefs_add_keybinding (const char *name,
GSettings *settings,
const char *setting_key,
const char *hardcoded_key,
MetaKeyBindingAction action,
MetaKeyBindingFlags flags)
{
MetaKeyPref *pref;
char **strokes;
char *static_strokes[2];
guint id;
if (g_hash_table_lookup (key_bindings, name))
@ -1944,19 +1954,45 @@ meta_prefs_add_keybinding (const char *name,
pref = g_new0 (MetaKeyPref, 1);
pref->name = g_strdup (name);
pref->settings = g_object_ref (settings);
pref->settings = settings ? g_object_ref (settings) : NULL;
pref->setting_key = g_strdup (setting_key);
pref->hardcoded_key = g_strdup (hardcoded_key);
pref->action = action;
pref->bindings = NULL;
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
pref->is_single = (flags & META_KEY_BINDING_IS_SINGLE) != 0;
if (settings)
{
if (pref->is_single)
{
static_strokes[0] = g_settings_get_string (settings, setting_key);
static_strokes[1] = NULL;
strokes = static_strokes;
}
else
strokes = g_settings_get_strv (settings, setting_key);
}
else
{
static_strokes[0] = (char*)hardcoded_key;
static_strokes[1] = NULL;
strokes = static_strokes;
}
strokes = g_settings_get_strv (settings, name);
update_binding (pref, strokes);
g_strfreev (strokes);
g_hash_table_insert (key_bindings, g_strdup (name), pref);
if (strokes != static_strokes)
g_strfreev (strokes);
else if (static_strokes[0] != hardcoded_key)
g_free (static_strokes[0]);
if (!settings)
return TRUE;
if (pref->builtin)
{
if (g_object_get_data (G_OBJECT (settings), "changed-signal") == NULL)
@ -1968,7 +2004,7 @@ meta_prefs_add_keybinding (const char *name,
}
else
{
char *changed_signal = g_strdup_printf ("changed::%s", name);
char *changed_signal = g_strdup_printf ("changed::%s", setting_key);
id = g_signal_connect (settings, changed_signal,
G_CALLBACK (bindings_changed), NULL);
g_free (changed_signal);

View File

@ -134,8 +134,18 @@ gboolean meta_display_add_keybinding (MetaDisplay *display,
MetaKeyHandlerFunc handler,
gpointer user_data,
GDestroyNotify free_data);
gboolean meta_display_remove_keybinding (MetaDisplay *display,
gboolean meta_display_add_grabbed_key (MetaDisplay *display,
const char *name,
const char *keyval,
MetaKeyBindingFlags flags,
MetaKeyHandlerFunc handler,
gpointer user_data,
GDestroyNotify free_data);
gboolean meta_display_remove_grabbed_key(MetaDisplay *display,
const char *name);
gboolean meta_display_remove_keybinding (MetaDisplay *display,
const char *name,
GSettings *settings);
MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display,
unsigned int keycode,

View File

@ -234,7 +234,9 @@ typedef enum
META_KEY_BINDING_PER_WINDOW = 1 << 0,
META_KEY_BINDING_BUILTIN = 1 << 1,
META_KEY_BINDING_REVERSES = 1 << 2,
META_KEY_BINDING_IS_REVERSED = 1 << 3
META_KEY_BINDING_IS_REVERSED = 1 << 3,
META_KEY_BINDING_IS_SINGLE = 1 << 4,
META_KEY_BINDING_HANDLE_WHEN_GRABBED = 1 << 5,
} MetaKeyBindingFlags;
typedef struct
@ -249,12 +251,12 @@ typedef struct
* @event: (type gpointer):
*
*/
typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer user_data);
typedef gboolean (* MetaKeyHandlerFunc) (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer user_data);
typedef struct _MetaKeyHandler MetaKeyHandler;
@ -262,6 +264,8 @@ typedef struct
{
char *name;
GSettings *settings;
char *setting_key;
char *hardcoded_key;
MetaKeyBindingAction action;
@ -280,6 +284,10 @@ typedef struct
/** for keybindings not added with meta_display_add_keybinding() */
gboolean builtin:1;
/** for keybindings that are stored as a single value, not
as a list */
gboolean is_single:1;
} MetaKeyPref;
GType meta_key_binding_get_type (void);