You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

3689 lines
117 KiB

  1. /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2. /* Muffin Keybindings */
  3. /*
  4. * Copyright (C) 2001 Havoc Pennington
  5. * Copyright (C) 2002 Red Hat Inc.
  6. * Copyright (C) 2003 Rob Adams
  7. * Copyright (C) 2004-2006 Elijah Newren
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA
  22. * 02110-1335, USA.
  23. */
  24. /**
  25. * SECTION:keybindings
  26. * @title: MetaKeybinding
  27. * @short_description: Key bindings
  28. */
  29. #ifndef _GNU_SOURCE
  30. #define _GNU_SOURCE
  31. #endif
  32. #define _SVID_SOURCE /* for putenv() */
  33. #include <config.h>
  34. #include "keybindings-private.h"
  35. #include "workspace-private.h"
  36. #include <meta/errors.h>
  37. #include "edge-resistance.h"
  38. #include "ui.h"
  39. #include "frame.h"
  40. #include "place.h"
  41. #include <meta/prefs.h>
  42. #include <meta/util.h>
  43. #include <X11/keysym.h>
  44. #include <string.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #ifdef HAVE_XKB
  48. #include <X11/XKBlib.h>
  49. #endif
  50. #define SCHEMA_MUFFIN_KEYBINDINGS "org.cinnamon.desktop.keybindings.wm"
  51. #define SCHEMA_MUFFIN "org.cinnamon.muffin"
  52. static gboolean all_bindings_disabled = FALSE;
  53. static gboolean modifier_only_is_down = FALSE;
  54. static gboolean add_builtin_keybinding (MetaDisplay *display,
  55. const char *name,
  56. const char *schema,
  57. MetaKeyBindingFlags flags,
  58. MetaKeyBindingAction action,
  59. MetaKeyHandlerFunc handler,
  60. int handler_arg);
  61. static void invoke_handler_by_name (MetaDisplay *display,
  62. MetaScreen *screen,
  63. const char *handler_name,
  64. MetaWindow *window,
  65. XEvent *event);
  66. enum {
  67. META_MOVE_TO_XCHANGE_FLAG = 8, // 1000
  68. META_MOVE_TO_YCHANGE_FLAG = 4, // 0100
  69. META_MOVE_TO_RIGHT_FLAG = 2, // 0010
  70. META_MOVE_TO_BOTTOM_FLAG = 1 // 0001
  71. };
  72. // Using flags above
  73. enum {
  74. META_MOVE_TO_SE = 15, // 1111
  75. META_MOVE_TO_NE = 14, // 1110
  76. META_MOVE_TO_SW = 13, // 1101
  77. META_MOVE_TO_NW = 12, // 1100
  78. META_MOVE_TO_E = 10, // 1010
  79. META_MOVE_TO_W = 8, // 1000
  80. META_MOVE_TO_S = 5, // 0101
  81. META_MOVE_TO_N = 4 // 0100
  82. };
  83. static void
  84. meta_key_binding_free (MetaKeyBinding *binding)
  85. {
  86. g_slice_free (MetaKeyBinding, binding);
  87. }
  88. static MetaKeyBinding *
  89. meta_key_binding_copy (MetaKeyBinding *binding)
  90. {
  91. return g_slice_dup (MetaKeyBinding, binding);
  92. }
  93. GType
  94. meta_key_binding_get_type (void)
  95. {
  96. static GType type_id = 0;
  97. if (G_UNLIKELY (type_id == 0))
  98. type_id = g_boxed_type_register_static (g_intern_static_string ("MetaKeyBinding"),
  99. (GBoxedCopyFunc)meta_key_binding_copy,
  100. (GBoxedFreeFunc)meta_key_binding_free);
  101. return type_id;
  102. }
  103. const char *
  104. meta_key_binding_get_name (MetaKeyBinding *binding)
  105. {
  106. return binding->name;
  107. }
  108. MetaVirtualModifier
  109. meta_key_binding_get_modifiers (MetaKeyBinding *binding)
  110. {
  111. return binding->modifiers;
  112. }
  113. guint
  114. meta_key_binding_get_mask (MetaKeyBinding *binding)
  115. {
  116. return binding->mask;
  117. }
  118. /* These can't be bound to anything, but they are used to handle
  119. * various other events. TODO: Possibly we should include them as event
  120. * handler functions and have some kind of flag to say they're unbindable.
  121. */
  122. static gboolean process_mouse_move_resize_grab (MetaDisplay *display,
  123. MetaScreen *screen,
  124. MetaWindow *window,
  125. XEvent *event,
  126. KeySym keysym);
  127. static gboolean process_keyboard_move_grab (MetaDisplay *display,
  128. MetaScreen *screen,
  129. MetaWindow *window,
  130. XEvent *event,
  131. KeySym keysym);
  132. static gboolean process_keyboard_resize_grab (MetaDisplay *display,
  133. MetaScreen *screen,
  134. MetaWindow *window,
  135. XEvent *event,
  136. KeySym keysym);
  137. static void regrab_key_bindings (MetaDisplay *display);
  138. static GHashTable *key_handlers;
  139. #define HANDLER(name) g_hash_table_lookup (key_handlers, (name))
  140. static void
  141. key_handler_free (MetaKeyHandler *handler)
  142. {
  143. g_free (handler->name);
  144. if (handler->user_data_free_func && handler->user_data)
  145. handler->user_data_free_func (handler->user_data);
  146. g_free (handler);
  147. }
  148. static void
  149. reload_keymap (MetaDisplay *display)
  150. {
  151. if (display->keymap)
  152. meta_XFree (display->keymap);
  153. /* This is expensive to compute, so we'll lazily load if and when we first
  154. * need it */
  155. display->above_tab_keycode = 0;
  156. display->keymap = XGetKeyboardMapping (display->xdisplay,
  157. display->min_keycode,
  158. display->max_keycode -
  159. display->min_keycode + 1,
  160. &display->keysyms_per_keycode);
  161. }
  162. static void
  163. reload_modmap (MetaDisplay *display)
  164. {
  165. XModifierKeymap *modmap;
  166. int map_size;
  167. int i;
  168. if (display->modmap)
  169. XFreeModifiermap (display->modmap);
  170. modmap = XGetModifierMapping (display->xdisplay);
  171. display->modmap = modmap;
  172. display->ignored_modifier_mask = 0;
  173. /* Multiple bits may get set in each of these */
  174. display->num_lock_mask = 0;
  175. display->scroll_lock_mask = 0;
  176. display->meta_mask = 0;
  177. display->hyper_mask = 0;
  178. display->super_mask = 0;
  179. /* there are 8 modifiers, and the first 3 are shift, shift lock,
  180. * and control
  181. */
  182. map_size = 8 * modmap->max_keypermod;
  183. i = 3 * modmap->max_keypermod;
  184. while (i < map_size)
  185. {
  186. /* get the key code at this point in the map,
  187. * see if its keysym is one we're interested in
  188. */
  189. int keycode = modmap->modifiermap[i];
  190. if (keycode >= display->min_keycode &&
  191. keycode <= display->max_keycode)
  192. {
  193. int j = 0;
  194. KeySym *syms = display->keymap +
  195. (keycode - display->min_keycode) * display->keysyms_per_keycode;
  196. while (j < display->keysyms_per_keycode)
  197. {
  198. if (syms[j] != 0)
  199. {
  200. const char *str;
  201. str = XKeysymToString (syms[j]);
  202. meta_topic (META_DEBUG_KEYBINDINGS,
  203. "Keysym %s bound to modifier 0x%x\n",
  204. str ? str : "none",
  205. (1 << ( i / modmap->max_keypermod)));
  206. }
  207. if (syms[j] == XK_Num_Lock)
  208. {
  209. /* Mod1Mask is 1 << 3 for example, i.e. the
  210. * fourth modifier, i / keyspermod is the modifier
  211. * index
  212. */
  213. display->num_lock_mask |= (1 << ( i / modmap->max_keypermod));
  214. }
  215. else if (syms[j] == XK_Scroll_Lock)
  216. {
  217. display->scroll_lock_mask |= (1 << ( i / modmap->max_keypermod));
  218. }
  219. else if (syms[j] == XK_Super_L ||
  220. syms[j] == XK_Super_R)
  221. {
  222. display->super_mask |= (1 << ( i / modmap->max_keypermod));
  223. }
  224. else if (syms[j] == XK_Hyper_L ||
  225. syms[j] == XK_Hyper_R)
  226. {
  227. display->hyper_mask |= (1 << ( i / modmap->max_keypermod));
  228. }
  229. else if (syms[j] == XK_Meta_L ||
  230. syms[j] == XK_Meta_R)
  231. {
  232. display->meta_mask |= (1 << ( i / modmap->max_keypermod));
  233. }
  234. ++j;
  235. }
  236. }
  237. ++i;
  238. }
  239. display->ignored_modifier_mask = (display->num_lock_mask |
  240. display->scroll_lock_mask |
  241. LockMask);
  242. meta_topic (META_DEBUG_KEYBINDINGS,
  243. "Ignoring modmask 0x%x num lock 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x\n",
  244. display->ignored_modifier_mask,
  245. display->num_lock_mask,
  246. display->scroll_lock_mask,
  247. display->hyper_mask,
  248. display->super_mask,
  249. display->meta_mask);
  250. }
  251. static guint
  252. keysym_to_keycode (MetaDisplay *display,
  253. guint keysym)
  254. {
  255. if (keysym == META_KEY_ABOVE_TAB)
  256. return meta_display_get_above_tab_keycode (display);
  257. else
  258. return XKeysymToKeycode (display->xdisplay, keysym);
  259. }
  260. static void
  261. reload_keycodes (MetaDisplay *display)
  262. {
  263. meta_topic (META_DEBUG_KEYBINDINGS,
  264. "Reloading keycodes for binding tables\n");
  265. if (display->key_bindings)
  266. {
  267. int i;
  268. i = 0;
  269. while (i < display->n_key_bindings)
  270. {
  271. if (display->key_bindings[i].keysym != 0)
  272. {
  273. display->key_bindings[i].keycode =
  274. keysym_to_keycode (display, display->key_bindings[i].keysym);
  275. }
  276. ++i;
  277. }
  278. }
  279. }
  280. static void
  281. reload_modifiers (MetaDisplay *display)
  282. {
  283. meta_topic (META_DEBUG_KEYBINDINGS,
  284. "Reloading keycodes for binding tables\n");
  285. if (display->key_bindings)
  286. {
  287. int i;
  288. i = 0;
  289. while (i < display->n_key_bindings)
  290. {
  291. meta_display_devirtualize_modifiers (display,
  292. display->key_bindings[i].modifiers,
  293. &display->key_bindings[i].mask);
  294. meta_topic (META_DEBUG_KEYBINDINGS,
  295. " Devirtualized mods 0x%x -> 0x%x (%s)\n",
  296. display->key_bindings[i].modifiers,
  297. display->key_bindings[i].mask,
  298. display->key_bindings[i].name);
  299. ++i;
  300. }
  301. }
  302. }
  303. static int
  304. count_bindings (GList *prefs)
  305. {
  306. GList *p;
  307. int count;
  308. count = 0;
  309. p = prefs;
  310. while (p)
  311. {
  312. MetaKeyPref *pref = (MetaKeyPref*)p->data;
  313. GSList *tmp = pref->bindings;
  314. while (tmp)
  315. {
  316. MetaKeyCombo *combo = tmp->data;
  317. if (combo && (combo->keysym != None || combo->keycode != 0))
  318. {
  319. count += 1;
  320. if (pref->add_shift &&
  321. (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
  322. count += 1;
  323. }
  324. tmp = tmp->next;
  325. }
  326. p = p->next;
  327. }
  328. return count;
  329. }
  330. static void
  331. rebuild_binding_table (MetaDisplay *display,
  332. MetaKeyBinding **bindings_p,
  333. int *n_bindings_p,
  334. GList *prefs)
  335. {
  336. GList *p;
  337. int n_bindings;
  338. int i;
  339. n_bindings = count_bindings (prefs);
  340. g_free (*bindings_p);
  341. *bindings_p = g_new0 (MetaKeyBinding, n_bindings);
  342. i = 0;
  343. p = prefs;
  344. while (p)
  345. {
  346. MetaKeyPref *pref = (MetaKeyPref*)p->data;
  347. GSList *tmp = pref->bindings;
  348. while (tmp)
  349. {
  350. MetaKeyCombo *combo = tmp->data;
  351. if (combo && (combo->keysym != None || combo->keycode != 0))
  352. {
  353. MetaKeyHandler *handler = HANDLER (pref->name);
  354. (*bindings_p)[i].name = pref->name;
  355. (*bindings_p)[i].handler = handler;
  356. (*bindings_p)[i].keysym = combo->keysym;
  357. (*bindings_p)[i].keycode = combo->keycode;
  358. (*bindings_p)[i].modifiers = combo->modifiers;
  359. (*bindings_p)[i].mask = 0;
  360. ++i;
  361. if (pref->add_shift &&
  362. (combo->modifiers & META_VIRTUAL_SHIFT_MASK) == 0)
  363. {
  364. meta_topic (META_DEBUG_KEYBINDINGS,
  365. "Binding %s also needs Shift grabbed\n",
  366. pref->name);
  367. (*bindings_p)[i].name = pref->name;
  368. (*bindings_p)[i].handler = handler;
  369. (*bindings_p)[i].keysym = combo->keysym;
  370. (*bindings_p)[i].keycode = combo->keycode;
  371. (*bindings_p)[i].modifiers = combo->modifiers |
  372. META_VIRTUAL_SHIFT_MASK;
  373. (*bindings_p)[i].mask = 0;
  374. ++i;
  375. }
  376. }
  377. tmp = tmp->next;
  378. }
  379. p = p->next;
  380. }
  381. g_assert (i == n_bindings);
  382. *n_bindings_p = i;
  383. meta_topic (META_DEBUG_KEYBINDINGS,
  384. " %d bindings in table\n",
  385. *n_bindings_p);
  386. }
  387. static void
  388. rebuild_key_binding_table (MetaDisplay *display)
  389. {
  390. GList *prefs;
  391. meta_topic (META_DEBUG_KEYBINDINGS,
  392. "Rebuilding key binding table from preferences\n");
  393. prefs = meta_prefs_get_keybindings ();
  394. rebuild_binding_table (display,
  395. &display->key_bindings,
  396. &display->n_key_bindings,
  397. prefs);
  398. g_list_free (prefs);
  399. }
  400. static void
  401. regrab_key_bindings (MetaDisplay *display)
  402. {
  403. GSList *tmp;
  404. GSList *windows;
  405. meta_error_trap_push (display); /* for efficiency push outer trap */
  406. tmp = display->screens;
  407. while (tmp != NULL)
  408. {
  409. MetaScreen *screen = tmp->data;
  410. meta_screen_ungrab_keys (screen);
  411. meta_screen_grab_keys (screen);
  412. tmp = tmp->next;
  413. }
  414. windows = meta_display_list_windows (display, META_LIST_DEFAULT);
  415. tmp = windows;
  416. while (tmp != NULL)
  417. {
  418. MetaWindow *w = tmp->data;
  419. meta_window_ungrab_keys (w);
  420. meta_window_grab_keys (w);
  421. tmp = tmp->next;
  422. }
  423. meta_error_trap_pop (display);
  424. g_slist_free (windows);
  425. }
  426. static MetaKeyBinding *
  427. display_get_keybinding (MetaDisplay *display,
  428. unsigned int keysym,
  429. unsigned int keycode,
  430. unsigned long mask)
  431. {
  432. int i;
  433. i = display->n_key_bindings - 1;
  434. while (i >= 0)
  435. {
  436. if (display->key_bindings[i].keysym == keysym &&
  437. display->key_bindings[i].keycode == keycode &&
  438. display->key_bindings[i].mask == mask)
  439. {
  440. return &display->key_bindings[i];
  441. }
  442. --i;
  443. }
  444. return NULL;
  445. }
  446. static gboolean
  447. add_keybinding_internal (MetaDisplay *display,
  448. const char *name,
  449. const char *schema,
  450. MetaKeyBindingFlags flags,
  451. MetaKeyBindingAction action,
  452. MetaKeyHandlerFunc func,
  453. int data,
  454. gpointer user_data,
  455. GDestroyNotify free_data)
  456. {
  457. MetaKeyHandler *handler;
  458. if (!meta_prefs_add_keybinding (name, schema, action, flags))
  459. return FALSE;
  460. handler = g_new0 (MetaKeyHandler, 1);
  461. handler->name = g_strdup (name);
  462. handler->func = func;
  463. handler->default_func = func;
  464. handler->data = data;
  465. handler->flags = flags;
  466. handler->action = action;
  467. handler->user_data = user_data;
  468. handler->user_data_free_func = free_data;
  469. g_hash_table_insert (key_handlers, g_strdup (name), handler);
  470. return TRUE;
  471. }
  472. static gboolean
  473. add_builtin_keybinding (MetaDisplay *display,
  474. const char *name,
  475. const char *schema,
  476. MetaKeyBindingFlags flags,
  477. MetaKeyBindingAction action,
  478. MetaKeyHandlerFunc handler,
  479. int handler_arg)
  480. {
  481. return add_keybinding_internal (display, name, schema,
  482. flags | META_KEY_BINDING_BUILTIN,
  483. action, handler, handler_arg, NULL, NULL);
  484. }
  485. /**
  486. * meta_display_add_keybinding:
  487. * @display: a #MetaDisplay
  488. * @name: the binding's name
  489. * @schema: the #GSettings schema where @name is stored
  490. * @flags: flags to specify binding details
  491. * @handler: function to run when the keybinding is invoked
  492. * @user_data: the data to pass to @handler
  493. * @free_data: function to free @user_data
  494. *
  495. * Add a keybinding at runtime. The key @name in @schema needs to be of type
  496. * %G_VARIANT_TYPE_STRING_ARRAY, with each string describing a keybinding in
  497. * the form of "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1". The parser
  498. * is fairly liberal and allows lower or upper case, and also abbreviations
  499. * such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;". If the key is set to the empty
  500. * list or a list with a single element of either "" or "disabled", the
  501. * keybinding is disabled. If %META_KEY_BINDING_REVERSES is specified in
  502. * @flags, the binding may be reversed by holding down the "shift" key;
  503. * therefore, "&lt;Shift&gt;"
  504. * cannot be one of the keys used. @handler is expected to check for the
  505. * "shift" modifier in this case and reverse its action.
  506. *
  507. * Use meta_display_remove_keybinding() to remove the binding.
  508. *
  509. * Returns: %TRUE if the keybinding was added successfully,
  510. * otherwise %FALSE
  511. */
  512. gboolean
  513. meta_display_add_keybinding (MetaDisplay *display,
  514. const char *name,
  515. const char *schema,
  516. MetaKeyBindingFlags flags,
  517. MetaKeyHandlerFunc handler,
  518. gpointer user_data,
  519. GDestroyNotify free_data)
  520. {
  521. return add_keybinding_internal (display, name, schema, flags,
  522. META_KEYBINDING_ACTION_NONE,
  523. handler, 0, user_data, free_data);
  524. }
  525. /**
  526. * meta_display_remove_keybinding:
  527. * @display: the #MetaDisplay
  528. * @name: name of the keybinding to remove
  529. *
  530. * Remove keybinding @name; the function will fail if @name is not a known
  531. * keybinding or has not been added with meta_display_add_keybinding().
  532. *
  533. * Returns: %TRUE if the binding has been removed sucessfully,
  534. * otherwise %FALSE
  535. */
  536. gboolean
  537. meta_display_remove_keybinding (MetaDisplay *display,
  538. const char *name)
  539. {
  540. if (!meta_prefs_remove_keybinding (name))
  541. return FALSE;
  542. g_hash_table_remove (key_handlers, name);
  543. return TRUE;
  544. }
  545. static gboolean
  546. add_custom_keybinding_internal (MetaDisplay *display,
  547. const char *name,
  548. const char **bindings,
  549. MetaKeyBindingFlags flags,
  550. MetaKeyBindingAction action,
  551. MetaKeyHandlerFunc func,
  552. int data,
  553. gpointer user_data,
  554. GDestroyNotify free_data)
  555. {
  556. MetaKeyHandler *handler;
  557. if (!meta_prefs_add_custom_keybinding (name, bindings, action, flags))
  558. return FALSE;
  559. handler = g_new0 (MetaKeyHandler, 1);
  560. handler->name = g_strdup (name);
  561. handler->func = func;
  562. handler->default_func = func;
  563. handler->data = data;
  564. handler->flags = flags;
  565. handler->action = action;
  566. handler->user_data = user_data;
  567. handler->user_data_free_func = free_data;
  568. g_hash_table_insert (key_handlers, g_strdup (name), handler);
  569. return TRUE;
  570. }
  571. /**
  572. * meta_display_add_custom_keybinding:
  573. * @display: a #MetaDisplay
  574. * @name: the binding's unique name
  575. * @bindings: (allow-none) (array zero-terminated=1): array of parseable keystrokes
  576. * @callback: function to run when the keybinding is invoked
  577. * @user_data: the data to pass to @handler
  578. * @free_data: function to free @user_data
  579. *
  580. *
  581. * Use meta_display_remove_custom_keybinding() to remove the binding.
  582. *
  583. * Returns: %TRUE if the keybinding was added successfully,
  584. * otherwise %FALSE
  585. */
  586. gboolean
  587. meta_display_add_custom_keybinding (MetaDisplay *display,
  588. const char *name,
  589. const char **bindings,
  590. MetaKeyHandlerFunc callback,
  591. gpointer user_data,
  592. GDestroyNotify free_data)
  593. {
  594. return add_custom_keybinding_internal (display, name, bindings,
  595. META_KEY_BINDING_PER_WINDOW,
  596. META_KEYBINDING_ACTION_CUSTOM,
  597. (MetaKeyHandlerFunc)callback, 0, user_data, free_data);
  598. }
  599. /**
  600. * meta_display_remove_custom_keybinding:
  601. * @display: the #MetaDisplay
  602. * @name: name of the keybinding to remove
  603. *
  604. * Remove keybinding @name; the function will fail if @name is not a known
  605. * keybinding or has not been added with meta_display_add_custom_keybinding().
  606. *
  607. * Returns: %TRUE if the binding has been removed sucessfully,
  608. * otherwise %FALSE
  609. */
  610. gboolean
  611. meta_display_remove_custom_keybinding (MetaDisplay *display,
  612. const char *name)
  613. {
  614. if (!meta_prefs_remove_custom_keybinding (name))
  615. return FALSE;
  616. g_hash_table_remove (key_handlers, name);
  617. return TRUE;
  618. }
  619. /**
  620. * meta_display_get_keybinding_action:
  621. * @display: A #MetaDisplay
  622. * @keycode: Raw keycode
  623. * @mask: Event mask
  624. *
  625. * Get the #MetaKeyBindingAction bound to %keycode. Only builtin
  626. * keybindings have an associated #MetaKeyBindingAction, for
  627. * bindings added dynamically with meta_display_add_keybinding()
  628. * the function will always return %META_KEYBINDING_ACTION_NONE.
  629. *
  630. * Returns: The action that should be taken for the given key, or
  631. * %META_KEYBINDING_ACTION_NONE.
  632. */
  633. MetaKeyBindingAction
  634. meta_display_get_keybinding_action (MetaDisplay *display,
  635. unsigned int keycode,
  636. unsigned long mask)
  637. {
  638. MetaKeyBinding *binding;
  639. KeySym keysym;
  640. keysym = XkbKeycodeToKeysym (display->xdisplay, keycode, 0, 0);
  641. mask = mask & 0xff & ~display->ignored_modifier_mask;
  642. binding = display_get_keybinding (display, keysym, keycode, mask);
  643. if (!binding && keycode == meta_display_get_above_tab_keycode (display))
  644. binding = display_get_keybinding (display, META_KEY_ABOVE_TAB, keycode, mask);
  645. if (binding)
  646. return meta_prefs_get_keybinding_action (binding->name);
  647. else
  648. return META_KEYBINDING_ACTION_NONE;
  649. }
  650. void
  651. meta_display_keybinding_action_invoke_by_code (MetaDisplay *display,
  652. unsigned int keycode,
  653. unsigned long mask)
  654. {
  655. MetaKeyBinding *binding;
  656. KeySym keysym;
  657. keysym = XkbKeycodeToKeysym (display->xdisplay, keycode, 0, 0);
  658. mask = mask & 0xff & ~display->ignored_modifier_mask;
  659. binding = display_get_keybinding (display, keysym, keycode, mask);
  660. if (!binding && keycode == meta_display_get_above_tab_keycode (display))
  661. binding = display_get_keybinding (display, META_KEY_ABOVE_TAB, keycode, mask);
  662. if (binding)
  663. invoke_handler_by_name (display, NULL, binding->name, NULL, NULL);
  664. }
  665. LOCAL_SYMBOL void
  666. meta_display_process_mapping_event (MetaDisplay *display,
  667. XEvent *event)
  668. {
  669. gboolean keymap_changed = FALSE;
  670. gboolean modmap_changed = FALSE;
  671. #ifdef HAVE_XKB
  672. if (event->type == display->xkb_base_event_type)
  673. {
  674. meta_topic (META_DEBUG_KEYBINDINGS,
  675. "XKB mapping changed, will redo keybindings\n");
  676. keymap_changed = TRUE;
  677. modmap_changed = TRUE;
  678. }
  679. else
  680. #endif
  681. if (event->xmapping.request == MappingModifier)
  682. {
  683. meta_topic (META_DEBUG_KEYBINDINGS,
  684. "Received MappingModifier event, will reload modmap and redo keybindings\n");
  685. modmap_changed = TRUE;
  686. }
  687. else if (event->xmapping.request == MappingKeyboard)
  688. {
  689. meta_topic (META_DEBUG_KEYBINDINGS,
  690. "Received MappingKeyboard event, will reload keycodes and redo keybindings\n");
  691. keymap_changed = TRUE;
  692. }
  693. /* Now to do the work itself */
  694. if (keymap_changed || modmap_changed)
  695. {
  696. if (keymap_changed)
  697. reload_keymap (display);
  698. /* Deciphering the modmap depends on the loaded keysyms to find out
  699. * what modifiers is Super and so forth, so we need to reload it
  700. * even when only the keymap changes */
  701. reload_modmap (display);
  702. if (keymap_changed)
  703. reload_keycodes (display);
  704. reload_modifiers (display);
  705. regrab_key_bindings (display);
  706. }
  707. }
  708. static gboolean
  709. rebuild_keybindings_at_idle (MetaDisplay *display)
  710. {
  711. display->rebuild_keybinding_idle_id = 0;
  712. rebuild_key_binding_table (display);
  713. reload_keycodes (display);
  714. reload_modifiers (display);
  715. regrab_key_bindings (display);
  716. return FALSE;
  717. }
  718. static void
  719. queue_rebuild_keybindings (MetaDisplay *display)
  720. {
  721. if (display->rebuild_keybinding_idle_id > 0)
  722. {
  723. g_source_remove (display->rebuild_keybinding_idle_id);
  724. display->rebuild_keybinding_idle_id = 0;
  725. }
  726. display->rebuild_keybinding_idle_id = g_idle_add_full (G_PRIORITY_LOW,
  727. (GSourceFunc) rebuild_keybindings_at_idle,
  728. display, NULL);
  729. }
  730. static void
  731. bindings_changed_callback (MetaPreference pref,
  732. void *data)
  733. {
  734. MetaDisplay *display;
  735. display = data;
  736. switch (pref)
  737. {
  738. case META_PREF_KEYBINDINGS:
  739. queue_rebuild_keybindings (display);
  740. break;
  741. default:
  742. break;
  743. }
  744. }
  745. /**
  746. * meta_display_rebuild_keybindings:
  747. * @display: the #MetaDisplay
  748. *
  749. * Rebuild all keybindings (typically done after adding, removing, or changing
  750. * one or more keybindings)
  751. *
  752. */
  753. void
  754. meta_display_rebuild_keybindings (MetaDisplay *display)
  755. {
  756. queue_rebuild_keybindings (display);
  757. }
  758. LOCAL_SYMBOL void
  759. meta_display_shutdown_keys (MetaDisplay *display)
  760. {
  761. /* Note that display->xdisplay is invalid in this function */
  762. meta_prefs_remove_listener (bindings_changed_callback, display);
  763. if (display->keymap)
  764. meta_XFree (display->keymap);
  765. if (display->modmap)
  766. XFreeModifiermap (display->modmap);
  767. g_free (display->key_bindings);
  768. }
  769. static const char*
  770. keysym_name (int keysym)
  771. {
  772. const char *name;
  773. name = XKeysymToString (keysym);
  774. if (name == NULL)
  775. name = "(unknown)";
  776. return name;
  777. }
  778. /* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
  779. static void
  780. meta_change_keygrab (MetaDisplay *display,
  781. Window xwindow,
  782. gboolean grab,
  783. int keysym,
  784. unsigned int keycode,
  785. int modmask)
  786. {
  787. unsigned int ignored_mask;
  788. /* Grab keycode/modmask, together with
  789. * all combinations of ignored modifiers.
  790. * X provides no better way to do this.
  791. */
  792. meta_topic (META_DEBUG_KEYBINDINGS,
  793. "%s keybinding %s keycode %d mask 0x%x on 0x%lx\n",
  794. grab ? "Grabbing" : "Ungrabbing",
  795. keysym_name (keysym), keycode,
  796. modmask, xwindow);
  797. /* efficiency, avoid so many XSync() */
  798. meta_error_trap_push (display);
  799. ignored_mask = 0;
  800. while (ignored_mask <= display->ignored_modifier_mask)
  801. {
  802. if (ignored_mask & ~(display->ignored_modifier_mask))
  803. {
  804. /* Not a combination of ignored modifiers
  805. * (it contains some non-ignored modifiers)
  806. */
  807. ++ignored_mask;
  808. continue;
  809. }
  810. if (meta_is_debugging ())
  811. meta_error_trap_push_with_return (display);
  812. if (grab)
  813. XGrabKey (display->xdisplay, keycode,
  814. modmask | ignored_mask,
  815. xwindow,
  816. True,
  817. GrabModeAsync, GrabModeSync);
  818. else
  819. XUngrabKey (display->xdisplay, keycode,
  820. modmask | ignored_mask,
  821. xwindow);
  822. if (meta_is_debugging ())
  823. {
  824. int result;
  825. result = meta_error_trap_pop_with_return (display);
  826. if (grab && result != Success)
  827. {
  828. if (result == BadAccess)
  829. meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask);
  830. else
  831. meta_topic (META_DEBUG_KEYBINDINGS,
  832. "Failed to grab key %s with modifiers %x\n",
  833. keysym_name (keysym), modmask | ignored_mask);
  834. }
  835. }
  836. ++ignored_mask;
  837. }
  838. meta_error_trap_pop (display);
  839. }
  840. static void
  841. meta_grab_key (MetaDisplay *display,
  842. Window xwindow,
  843. int keysym,
  844. unsigned int keycode,
  845. int modmask)
  846. {
  847. meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask);
  848. }
  849. static void
  850. grab_keys (MetaKeyBinding *bindings,
  851. int n_bindings,
  852. MetaDisplay *display,
  853. Window xwindow,
  854. gboolean binding_per_window)
  855. {
  856. int i;
  857. g_assert (n_bindings == 0 || bindings != NULL);
  858. meta_error_trap_push (display);
  859. i = 0;
  860. while (i < n_bindings)
  861. {
  862. if (!!binding_per_window ==
  863. !!(bindings[i].handler->flags & META_KEY_BINDING_PER_WINDOW) &&
  864. bindings[i].keycode != 0)
  865. {
  866. meta_grab_key (display, xwindow,
  867. bindings[i].keysym,
  868. bindings[i].keycode,
  869. bindings[i].mask);
  870. }
  871. ++i;
  872. }
  873. meta_error_trap_pop (display);
  874. }
  875. static void
  876. ungrab_all_keys (MetaDisplay *display,
  877. Window xwindow)
  878. {
  879. if (meta_is_debugging ())
  880. meta_error_trap_push_with_return (display);
  881. else
  882. meta_error_trap_push (display);
  883. XUngrabKey (display->xdisplay, AnyKey, AnyModifier,
  884. xwindow);
  885. if (meta_is_debugging ())
  886. {
  887. int result;
  888. result = meta_error_trap_pop_with_return (display);
  889. if (result != Success)
  890. meta_topic (META_DEBUG_KEYBINDINGS,
  891. "Ungrabbing all keys on 0x%lx failed\n", xwindow);
  892. }
  893. else
  894. meta_error_trap_pop (display);
  895. }
  896. LOCAL_SYMBOL void
  897. meta_screen_grab_keys (MetaScreen *screen)
  898. {
  899. if (screen->all_keys_grabbed)
  900. return;
  901. if (screen->keys_grabbed)
  902. return;
  903. grab_keys (screen->display->key_bindings,
  904. screen->display->n_key_bindings,
  905. screen->display, screen->xroot,
  906. FALSE);
  907. screen->keys_grabbed = TRUE;
  908. }
  909. LOCAL_SYMBOL void
  910. meta_screen_ungrab_keys (MetaScreen *screen)
  911. {
  912. if (screen->keys_grabbed)
  913. {
  914. ungrab_all_keys (screen->display, screen->xroot);
  915. screen->keys_grabbed = FALSE;
  916. }
  917. }
  918. LOCAL_SYMBOL void
  919. meta_window_grab_keys (MetaWindow *window)
  920. {
  921. if (window->all_keys_grabbed)
  922. return;
  923. if (window->type == META_WINDOW_DOCK
  924. || window->override_redirect)
  925. {
  926. if (window->keys_grabbed)
  927. ungrab_all_keys (window->display, window->xwindow);
  928. window->keys_grabbed = FALSE;
  929. return;
  930. }
  931. if (window->keys_grabbed)
  932. {
  933. if (window->frame && !window->grab_on_frame)
  934. ungrab_all_keys (window->display, window->xwindow);
  935. else if (window->frame == NULL &&
  936. window->grab_on_frame)
  937. ; /* continue to regrab on client window */
  938. else
  939. return; /* already all good */
  940. }
  941. grab_keys (window->display->key_bindings,
  942. window->display->n_key_bindings,
  943. window->display,
  944. window->frame ? window->frame->xwindow : window->xwindow,
  945. TRUE);
  946. window->keys_grabbed = TRUE;
  947. window->grab_on_frame = window->frame != NULL;
  948. }
  949. LOCAL_SYMBOL void
  950. meta_window_ungrab_keys (MetaWindow *window)
  951. {
  952. if (window->keys_grabbed)
  953. {
  954. if (window->grab_on_frame &&
  955. window->frame != NULL)
  956. ungrab_all_keys (window->display,
  957. window->frame->xwindow);
  958. else if (!window->grab_on_frame)
  959. ungrab_all_keys (window->display,
  960. window->xwindow);
  961. window->keys_grabbed = FALSE;
  962. }
  963. }
  964. #ifdef WITH_VERBOSE_MODE
  965. static const char*
  966. grab_status_to_string (int status)
  967. {
  968. switch (status)
  969. {
  970. case AlreadyGrabbed:
  971. return "AlreadyGrabbed";
  972. case GrabSuccess:
  973. return "GrabSuccess";
  974. case GrabNotViewable:
  975. return "GrabNotViewable";
  976. case GrabFrozen:
  977. return "GrabFrozen";
  978. case GrabInvalidTime:
  979. return "GrabInvalidTime";
  980. default:
  981. return "(unknown)";
  982. }
  983. }
  984. #endif /* WITH_VERBOSE_MODE */
  985. static gboolean
  986. grab_keyboard (MetaDisplay *display,
  987. Window xwindow,
  988. guint32 timestamp)
  989. {
  990. int result;
  991. int grab_status;
  992. /* Grab the keyboard, so we get key releases and all key
  993. * presses
  994. */
  995. meta_error_trap_push_with_return (display);
  996. grab_status = XGrabKeyboard (display->xdisplay,
  997. xwindow, True,
  998. GrabModeAsync, GrabModeAsync,
  999. timestamp);
  1000. if (grab_status != GrabSuccess)
  1001. {
  1002. meta_error_trap_pop_with_return (display);
  1003. meta_topic (META_DEBUG_KEYBINDINGS,
  1004. "XGrabKeyboard() returned failure status %s time %u\n",
  1005. grab_status_to_string (grab_status),
  1006. timestamp);
  1007. return FALSE;
  1008. }
  1009. else
  1010. {
  1011. result = meta_error_trap_pop_with_return (display);
  1012. if (result != Success)
  1013. {
  1014. meta_topic (META_DEBUG_KEYBINDINGS,
  1015. "XGrabKeyboard() resulted in an error\n");
  1016. return FALSE;
  1017. }
  1018. }
  1019. meta_topic (META_DEBUG_KEYBINDINGS, "Grabbed all keys\n");
  1020. return TRUE;
  1021. }
  1022. static void
  1023. ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
  1024. {
  1025. meta_error_trap_push (display);
  1026. meta_topic (META_DEBUG_KEYBINDINGS,
  1027. "Ungrabbing keyboard with timestamp %u\n",
  1028. timestamp);
  1029. XUngrabKeyboard (display->xdisplay, timestamp);
  1030. meta_error_trap_pop (display);
  1031. }
  1032. gboolean
  1033. meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp)
  1034. {
  1035. gboolean retval;
  1036. if (screen->all_keys_grabbed)
  1037. return FALSE;
  1038. if (screen->keys_grabbed)
  1039. meta_screen_ungrab_keys (screen);
  1040. meta_topic (META_DEBUG_KEYBINDINGS,
  1041. "Grabbing all keys on RootWindow\n");
  1042. retval = grab_keyboard (screen->display, screen->xroot, timestamp);
  1043. if (retval)
  1044. {
  1045. screen->all_keys_grabbed = TRUE;
  1046. g_object_notify (G_OBJECT (screen), "keyboard-grabbed");
  1047. }
  1048. else
  1049. meta_screen_grab_keys (screen);
  1050. return retval;
  1051. }
  1052. void
  1053. meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp)
  1054. {
  1055. if (screen->all_keys_grabbed)
  1056. {
  1057. ungrab_keyboard (screen->display, timestamp);
  1058. screen->all_keys_grabbed = FALSE;
  1059. screen->keys_grabbed = FALSE;
  1060. /* Re-establish our standard bindings */
  1061. meta_screen_grab_keys (screen);
  1062. g_object_notify (G_OBJECT (screen), "keyboard-grabbed");
  1063. }
  1064. }
  1065. LOCAL_SYMBOL gboolean
  1066. meta_window_grab_all_keys (MetaWindow *window,
  1067. guint32 timestamp)
  1068. {
  1069. Window grabwindow;
  1070. gboolean retval;
  1071. if (window->all_keys_grabbed)
  1072. return FALSE;
  1073. if (window->keys_grabbed)
  1074. meta_window_ungrab_keys (window);
  1075. /* Make sure the window is focused, otherwise the grab
  1076. * won't do a lot of good.
  1077. */
  1078. meta_topic (META_DEBUG_FOCUS,
  1079. "Focusing %s because we're grabbing all its keys\n",
  1080. window->desc);
  1081. meta_window_focus (window, timestamp);
  1082. grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
  1083. meta_topic (META_DEBUG_KEYBINDINGS,
  1084. "Grabbing all keys on window %s\n", window->desc);
  1085. retval = grab_keyboard (window->display, grabwindow, timestamp);
  1086. if (retval)
  1087. {
  1088. window->keys_grabbed = FALSE;
  1089. window->all_keys_grabbed = TRUE;
  1090. window->grab_on_frame = window->frame != NULL;
  1091. }
  1092. return retval;
  1093. }
  1094. LOCAL_SYMBOL void
  1095. meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
  1096. {
  1097. if (window->all_keys_grabbed)
  1098. {
  1099. ungrab_keyboard (window->display, timestamp);
  1100. window->grab_on_frame = FALSE;
  1101. window->all_keys_grabbed = FALSE;
  1102. window->keys_grabbed = FALSE;
  1103. /* Re-establish our standard bindings */
  1104. meta_window_grab_keys (window);
  1105. }
  1106. }
  1107. LOCAL_SYMBOL gboolean
  1108. meta_window_resize_or_move_allowed (MetaWindow *window,
  1109. MetaDirection dir)
  1110. {
  1111. if (!META_WINDOW_MAXIMIZED (window) && !META_WINDOW_TILED_OR_SNAPPED (window))
  1112. return TRUE;
  1113. switch (dir)
  1114. {
  1115. case META_DIRECTION_LEFT:
  1116. if (window->tile_mode == META_TILE_RIGHT ||
  1117. window->tile_mode == META_TILE_URC ||
  1118. window->tile_mode == META_TILE_LRC)
  1119. return TRUE;
  1120. break;
  1121. case META_DIRECTION_RIGHT:
  1122. if (window->tile_mode == META_TILE_LEFT ||
  1123. window->tile_mode == META_TILE_ULC ||
  1124. window->tile_mode == META_TILE_LLC)
  1125. return TRUE;
  1126. break;
  1127. case META_DIRECTION_UP:
  1128. if (window->tile_mode == META_TILE_BOTTOM ||
  1129. window->tile_mode == META_TILE_LLC ||
  1130. window->tile_mode == META_TILE_LRC)
  1131. return TRUE;
  1132. break;
  1133. case META_DIRECTION_DOWN:
  1134. if (window->tile_mode == META_TILE_TOP ||
  1135. window->tile_mode == META_TILE_ULC ||
  1136. window->tile_mode == META_TILE_URC)
  1137. return TRUE;
  1138. break;
  1139. default:
  1140. return FALSE;
  1141. }
  1142. return FALSE;
  1143. }
  1144. static gboolean
  1145. is_modifier (MetaDisplay *display,
  1146. unsigned int keycode)
  1147. {
  1148. int i;
  1149. int map_size;
  1150. gboolean retval = FALSE;
  1151. g_assert (display->modmap);
  1152. map_size = 8 * display->modmap->max_keypermod;
  1153. i = 0;
  1154. while (i < map_size)
  1155. {
  1156. if (keycode == display->modmap->modifiermap[i])
  1157. {
  1158. retval = TRUE;
  1159. break;
  1160. }
  1161. ++i;
  1162. }
  1163. return retval;
  1164. }
  1165. /* Indexes:
  1166. * shift = 0
  1167. * lock = 1
  1168. * control = 2
  1169. * mod1 = 3
  1170. * mod2 = 4
  1171. * mod3 = 5
  1172. * mod4 = 6
  1173. * mod5 = 7
  1174. */
  1175. static void
  1176. invoke_handler (MetaDisplay *display,
  1177. MetaScreen *screen,
  1178. MetaKeyHandler *handler,
  1179. MetaWindow *window,
  1180. XEvent *event,
  1181. MetaKeyBinding *binding)
  1182. {
  1183. if (handler->func)
  1184. (* handler->func) (display, screen,
  1185. handler->flags & META_KEY_BINDING_PER_WINDOW ?
  1186. window : NULL,
  1187. event,
  1188. binding,
  1189. handler->user_data);
  1190. else
  1191. (* handler->default_func) (display, screen,
  1192. handler->flags & META_KEY_BINDING_PER_WINDOW ?
  1193. window: NULL,
  1194. event,
  1195. binding,
  1196. NULL);
  1197. }
  1198. static void
  1199. invoke_handler_by_name (MetaDisplay *display,
  1200. MetaScreen *screen,
  1201. const char *handler_name,
  1202. MetaWindow *window,
  1203. XEvent *event)
  1204. {
  1205. MetaKeyHandler *handler;
  1206. handler = HANDLER (handler_name);
  1207. if (handler)
  1208. invoke_handler (display, screen, handler, window, event, NULL);
  1209. }
  1210. static gboolean
  1211. modifier_only_keysym (KeySym keysym)
  1212. {
  1213. return keysym == XK_Super_L ||
  1214. keysym == XK_Super_R ||
  1215. keysym == XK_Control_L ||
  1216. keysym == XK_Control_R ||
  1217. keysym == XK_Alt_L ||
  1218. keysym == XK_Alt_R ||
  1219. keysym == XK_Shift_L ||
  1220. keysym == XK_Shift_R;
  1221. }
  1222. static void
  1223. strip_self_mod (KeySym keysym, unsigned long *mask)
  1224. {
  1225. unsigned long mod = 0;
  1226. switch (keysym)
  1227. {
  1228. case XK_Super_L:
  1229. case XK_Super_R:
  1230. mod = GDK_MOD4_MASK;
  1231. break;
  1232. case XK_Control_L:
  1233. case XK_Control_R:
  1234. mod = GDK_CONTROL_MASK;
  1235. break;
  1236. case XK_Alt_L:
  1237. case XK_Alt_R:
  1238. mod = GDK_MOD1_MASK;
  1239. break;
  1240. case XK_Shift_L:
  1241. case XK_Shift_R:
  1242. mod = GDK_SHIFT_MASK;
  1243. break;
  1244. default:
  1245. mod = 0;
  1246. break;
  1247. }
  1248. *mask = *mask & ~mod;
  1249. }
  1250. static gboolean
  1251. is_modifier_only_kb (MetaDisplay *display, XEvent *event, KeySym keysym)
  1252. {
  1253. unsigned long mask;
  1254. mask = (event->xkey.state & 0xff & ~(display->ignored_modifier_mask));
  1255. strip_self_mod (keysym, &mask);
  1256. return mask == 0 && modifier_only_keysym (keysym);
  1257. }
  1258. /* now called from only one place, may be worth merging */
  1259. static gboolean
  1260. process_event (MetaKeyBinding *bindings,
  1261. int n_bindings,
  1262. MetaDisplay *display,
  1263. MetaScreen *screen,
  1264. MetaWindow *window,
  1265. XEvent *event,
  1266. KeySym keysym,
  1267. gboolean on_window,
  1268. gboolean allow_release)
  1269. {
  1270. int i;
  1271. unsigned long mask;
  1272. /* we used to have release-based bindings but no longer. */
  1273. if (event->type == KeyRelease && !allow_release)
  1274. return FALSE;
  1275. mask = event->xkey.state & 0xff & ~(display->ignored_modifier_mask);
  1276. if (allow_release)
  1277. {
  1278. strip_self_mod (keysym, &mask);
  1279. }
  1280. /*
  1281. * TODO: This would be better done with a hash table;
  1282. * it doesn't suit to use O(n) for such a common operation.
  1283. */
  1284. for (i=0; i<n_bindings; i++)
  1285. {
  1286. MetaKeyHandler *handler = bindings[i].handler;
  1287. /* Custom keybindings are from Cinnamon, and never need a window */
  1288. if (!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW && handler->action < META_KEYBINDING_ACTION_CUSTOM)
  1289. continue;
  1290. if ((event->type != KeyPress && !allow_release) ||
  1291. bindings[i].keycode != event->xkey.keycode ||
  1292. mask != bindings[i].mask)
  1293. continue;
  1294. /*
  1295. * window must be non-NULL for on_window to be true,
  1296. * and so also window must be non-NULL if we get here and
  1297. * this is a META_KEY_BINDING_PER_WINDOW binding.
  1298. */
  1299. meta_topic (META_DEBUG_KEYBINDINGS,
  1300. "Binding keycode 0x%x mask 0x%x matches event 0x%x state 0x%x\n",
  1301. bindings[i].keycode, bindings[i].mask,
  1302. event->xkey.keycode, event->xkey.state);
  1303. if (handler == NULL)
  1304. meta_bug ("Binding %s has no handler\n", bindings[i].name);
  1305. else
  1306. meta_topic (META_DEBUG_KEYBINDINGS,
  1307. "Running handler for %s\n",
  1308. bindings[i].name);
  1309. /* Global keybindings count as a let-the-terminal-lose-focus
  1310. * due to new window mapping until the user starts
  1311. * interacting with the terminal again.
  1312. */
  1313. display->allow_terminal_deactivation = TRUE;
  1314. invoke_handler (display, screen, handler, window, event, &bindings[i]);
  1315. return TRUE;
  1316. }
  1317. meta_topic (META_DEBUG_KEYBINDINGS,
  1318. "No handler found for this event in this binding table\n");
  1319. return FALSE;
  1320. }
  1321. static gboolean
  1322. process_modifier_key (MetaDisplay *display,
  1323. MetaScreen *screen,
  1324. MetaWindow *window,
  1325. XEvent *event,
  1326. KeySym keysym,
  1327. gboolean have_window,
  1328. gboolean *allow_key_up)
  1329. {
  1330. if (event->xkey.type == KeyPress)
  1331. {
  1332. /* check if we're just Pressing a captured modifier at this time */
  1333. if (is_modifier_only_kb (display, event, keysym))
  1334. {
  1335. /* remember this state, because we'll need to know it for subsequent events */
  1336. modifier_only_is_down = TRUE;
  1337. /* We keep the keyboard frozen - this allows us to use ReplayKeyboard
  1338. * on the next event if it's not the release of this modifier key */
  1339. XAllowEvents (display->xdisplay, SyncKeyboard, event->xkey.time);
  1340. return TRUE;
  1341. }
  1342. else
  1343. {
  1344. /* If it's a press, with a mod+key combination, we try our own keybindings
  1345. * first, then pass it to the current window if we don't have anything for it.
  1346. * Also, negate modifier_only_is_down. At this point we won't want a modifier
  1347. * release to trigger a binding, since when it happens now, it will only be the
  1348. * user releasing the keys after a combination binding has been used
  1349. */
  1350. modifier_only_is_down = FALSE;
  1351. /* Try our keybindings */
  1352. if (process_event (display->key_bindings,
  1353. display->n_key_bindings,
  1354. display, screen, window, event, keysym,
  1355. have_window, FALSE))
  1356. {
  1357. /* we had a binding, we're done */
  1358. XAllowEvents (display->xdisplay, AsyncKeyboard, event->xkey.time);
  1359. return TRUE;
  1360. }
  1361. else
  1362. {
  1363. /* if we have nothing, let focused window handle it */
  1364. XAllowEvents (display->xdisplay, ReplayKeyboard, event->xkey.time);
  1365. return FALSE;
  1366. }
  1367. }
  1368. }
  1369. else
  1370. {
  1371. /* We only care about key releases for modifier-only bindings -
  1372. * and only when that release directly follows a press. When this happens,
  1373. * negate modifier_only_is_down, and allow the binding handler to accept
  1374. * a key release.
  1375. */
  1376. if (is_modifier_only_kb (display, event, keysym))
  1377. {
  1378. if (modifier_only_is_down)
  1379. *allow_key_up = TRUE;
  1380. modifier_only_is_down = FALSE;
  1381. }
  1382. }
  1383. return FALSE;
  1384. }
  1385. /* Handle a key event. May be called recursively: some key events cause
  1386. * grabs to be ended and then need to be processed again in their own
  1387. * right. This cannot cause infinite recursion because we never call
  1388. * ourselves when there wasn't a grab, and we always clear the grab
  1389. * first; the invariant is enforced using an assertion. See #112560.
  1390. *
  1391. * The return value is whether we handled the key event.
  1392. *
  1393. * FIXME: We need to prove there are no race conditions here.
  1394. * FIXME: Does it correctly handle alt-Tab being followed by another
  1395. * grabbing keypress without letting go of alt?
  1396. * FIXME: An iterative solution would probably be simpler to understand
  1397. * (and help us solve the other fixmes).
  1398. */
  1399. LOCAL_SYMBOL gboolean
  1400. meta_display_process_key_event (MetaDisplay *display,
  1401. MetaWindow *window,
  1402. XEvent *event)
  1403. {
  1404. KeySym keysym;
  1405. gboolean keep_grab;
  1406. gboolean all_keys_grabbed;
  1407. gboolean handled;
  1408. gboolean allow_key_up = FALSE;
  1409. const char *str;
  1410. MetaScreen *screen;
  1411. if (all_bindings_disabled)
  1412. {
  1413. /* In this mode, we try to pretend we don't have grabs, so we
  1414. * immediately replay events and drop the grab. (This still
  1415. * messes up global passive grabs from other clients.) The
  1416. * FALSE return here is a little suspect, but we don't really
  1417. * know if we'll see the event again or not, and it's pretty
  1418. * poorly defined how this mode is supposed to interact with
  1419. * plugins.
  1420. */
  1421. XAllowEvents (display->xdisplay, ReplayKeyboard, event->xkey.time);
  1422. return FALSE;
  1423. }
  1424. /* if key event was on root window, we have a shortcut */
  1425. screen = meta_display_screen_for_root (display, event->xkey.window);
  1426. /* else round-trip to server */
  1427. if (screen == NULL)
  1428. screen = meta_display_screen_for_xwindow (display,
  1429. event->xany.window);
  1430. if (screen == NULL)
  1431. return FALSE; /* event window is destroyed */
  1432. /* ignore key events on popup menus and such. */
  1433. if (meta_ui_window_is_widget (screen->ui, event->xany.window))
  1434. return FALSE;
  1435. /* window may be NULL */
  1436. keysym = XkbKeycodeToKeysym (display->xdisplay, event->xkey.keycode, 0, 0);
  1437. str = XKeysymToString (keysym);
  1438. /* was topic */
  1439. meta_topic (META_DEBUG_KEYBINDINGS,
  1440. "Processing key %s event, keysym: %s state: 0x%x window: %s\n",
  1441. event->type == KeyPress ? "press" : "release",
  1442. str ? str : "none", event->xkey.state,
  1443. window ? window->desc : "(no window)");
  1444. all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed;
  1445. if (!all_keys_grabbed)
  1446. {
  1447. handled = process_modifier_key (display, screen, window, event, keysym, (!all_keys_grabbed && window), &allow_key_up);
  1448. if (handled)
  1449. return TRUE;
  1450. }
  1451. XAllowEvents (display->xdisplay, AsyncKeyboard, event->xkey.time);
  1452. keep_grab = TRUE;
  1453. if (all_keys_grabbed)
  1454. {
  1455. if (display->grab_op == META_GRAB_OP_NONE)
  1456. return TRUE;
  1457. /* If we get here we have a global grab, because
  1458. * we're in some special keyboard mode such as window move
  1459. * mode.
  1460. */
  1461. if (window ? (window == display->grab_window) :
  1462. (screen == display->grab_screen))
  1463. {
  1464. switch (display->grab_op)
  1465. {
  1466. case META_GRAB_OP_MOVING:
  1467. case META_GRAB_OP_RESIZING_SE:
  1468. case META_GRAB_OP_RESIZING_S:
  1469. case META_GRAB_OP_RESIZING_SW:
  1470. case META_GRAB_OP_RESIZING_N:
  1471. case META_GRAB_OP_RESIZING_NE:
  1472. case META_GRAB_OP_RESIZING_NW:
  1473. case META_GRAB_OP_RESIZING_W:
  1474. case META_GRAB_OP_RESIZING_E:
  1475. meta_topic (META_DEBUG_KEYBINDINGS,
  1476. "Processing event for mouse-only move/resize\n");
  1477. g_assert (window != NULL);
  1478. keep_grab = process_mouse_move_resize_grab (display, screen,
  1479. window, event, keysym);
  1480. break;
  1481. case META_GRAB_OP_KEYBOARD_MOVING:
  1482. meta_topic (META_DEBUG_KEYBINDINGS,
  1483. "Processing event for keyboard move\n");
  1484. g_assert (window != NULL);
  1485. keep_grab = process_keyboard_move_grab (display, screen,
  1486. window, event, keysym);
  1487. break;
  1488. case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
  1489. case META_GRAB_OP_KEYBOARD_RESIZING_S:
  1490. case META_GRAB_OP_KEYBOARD_RESIZING_N:
  1491. case META_GRAB_OP_KEYBOARD_RESIZING_W:
  1492. case META_GRAB_OP_KEYBOARD_RESIZING_E:
  1493. case META_GRAB_OP_KEYBOARD_RESIZING_SE:
  1494. case META_GRAB_OP_KEYBOARD_RESIZING_NE:
  1495. case META_GRAB_OP_KEYBOARD_RESIZING_SW:
  1496. case META_GRAB_OP_KEYBOARD_RESIZING_NW:
  1497. meta_topic (META_DEBUG_KEYBINDINGS,
  1498. "Processing event for keyboard resize\n");
  1499. g_assert (window != NULL);
  1500. keep_grab = process_keyboard_resize_grab (display, screen,
  1501. window, event, keysym);
  1502. break;
  1503. default:
  1504. break;
  1505. }
  1506. }
  1507. if (!keep_grab)
  1508. {
  1509. meta_topic (META_DEBUG_KEYBINDINGS,
  1510. "Ending grab op %u on key event sym %s\n",
  1511. display->grab_op, XKeysymToString (keysym));
  1512. meta_display_end_grab_op (display, event->xkey.time);
  1513. }
  1514. return TRUE;
  1515. }
  1516. /* Do the normal keybindings */
  1517. return process_event (display->key_bindings,
  1518. display->n_key_bindings,
  1519. display, screen, window, event, keysym,
  1520. !all_keys_grabbed && window, allow_key_up);
  1521. }
  1522. static gboolean
  1523. process_mouse_move_resize_grab (MetaDisplay *display,
  1524. MetaScreen *screen,
  1525. MetaWindow *window,
  1526. XEvent *event,
  1527. KeySym keysym)
  1528. {
  1529. /* don't care about releases, but eat them, don't end grab */
  1530. if (event->type == KeyRelease)
  1531. return TRUE;
  1532. if (keysym == XK_Escape)
  1533. {
  1534. /* Hide the tiling preview if necessary */
  1535. meta_screen_tile_preview_hide (screen);
  1536. meta_screen_tile_hud_hide (screen);
  1537. /* Restore the original tile mode */
  1538. window->tile_mode = display->grab_tile_mode;
  1539. window->tile_monitor_number = display->grab_tile_monitor_number;
  1540. /* End move or resize and restore to original state. If the
  1541. * window was a maximized window that had been "shaken loose" we
  1542. * need to remaximize it. In normal cases, we need to do a
  1543. * moveresize now to get the position back to the original.
  1544. */
  1545. if (window->shaken_loose)
  1546. meta_window_maximize (window,
  1547. META_MAXIMIZE_HORIZONTAL |
  1548. META_MAXIMIZE_VERTICAL);
  1549. else if (window->tile_mode != META_TILE_NONE) {
  1550. window->custom_snap_size = FALSE;
  1551. meta_window_real_tile (window, FALSE);
  1552. } else
  1553. meta_window_move_resize (display->grab_window,
  1554. TRUE,
  1555. display->grab_initial_window_pos.x,
  1556. display->grab_initial_window_pos.y,
  1557. display->grab_initial_window_pos.width,
  1558. display->grab_initial_window_pos.height);
  1559. /* End grab */
  1560. return FALSE;
  1561. }
  1562. return TRUE;
  1563. }
  1564. static gboolean
  1565. process_keyboard_move_grab (MetaDisplay *display,
  1566. MetaScreen *screen,
  1567. MetaWindow *window,
  1568. XEvent *event,
  1569. KeySym keysym)
  1570. {
  1571. gboolean handled;
  1572. int x, y;
  1573. int incr;
  1574. gboolean smart_snap;
  1575. handled = FALSE;
  1576. /* don't care about releases, but eat them, don't end grab */
  1577. if (event->type == KeyRelease)
  1578. return TRUE;
  1579. /* don't end grab on modifier key presses */
  1580. if (is_modifier (display, event->xkey.keycode))
  1581. return TRUE;
  1582. meta_window_get_position (window, &x, &y);
  1583. smart_snap = (event->xkey.state & ShiftMask) != 0;
  1584. #define SMALL_INCREMENT 1
  1585. #define NORMAL_INCREMENT 10
  1586. if (smart_snap)
  1587. incr = 1;
  1588. else if (event->xkey.state & ControlMask)
  1589. incr = SMALL_INCREMENT;
  1590. else
  1591. incr = NORMAL_INCREMENT;
  1592. if (keysym == XK_Escape)
  1593. {
  1594. /* End move and restore to original state. If the window was a
  1595. * maximized window that had been "shaken loose" we need to
  1596. * remaximize it. In normal cases, we need to do a moveresize
  1597. * now to get the position back to the original.
  1598. */
  1599. if (window->shaken_loose)
  1600. {
  1601. meta_window_maximize (window,
  1602. META_MAXIMIZE_HORIZONTAL |
  1603. META_MAXIMIZE_VERTICAL);
  1604. }
  1605. else if (window->tile_mode != META_TILE_NONE)
  1606. {
  1607. window->custom_snap_size = FALSE;
  1608. meta_window_real_tile (window, FALSE);
  1609. }
  1610. else
  1611. {
  1612. meta_window_move_resize (display->grab_window,
  1613. TRUE,
  1614. display->grab_initial_window_pos.x,
  1615. display->grab_initial_window_pos.y,
  1616. display->grab_initial_window_pos.width,
  1617. display->grab_initial_window_pos.height);
  1618. }
  1619. }
  1620. /* When moving by increments, we still snap to edges if the move
  1621. * to the edge is smaller than the increment. This is because
  1622. * Shift + arrow to snap is sort of a hidden feature. This way
  1623. * people using just arrows shouldn't get too frustrated.
  1624. */
  1625. switch (keysym)
  1626. {
  1627. case XK_KP_Home:
  1628. case XK_KP_Prior:
  1629. case XK_Up:
  1630. case XK_KP_Up:
  1631. y -= incr;
  1632. handled = TRUE;
  1633. break;
  1634. case XK_KP_End:
  1635. case XK_KP_Next:
  1636. case XK_Down:
  1637. case XK_KP_Down:
  1638. y += incr;
  1639. handled = TRUE;
  1640. break;
  1641. }
  1642. switch (keysym)
  1643. {
  1644. case XK_KP_Home:
  1645. case XK_KP_End:
  1646. case XK_Left:
  1647. case XK_KP_Left:
  1648. x -= incr;
  1649. handled = TRUE;
  1650. break;
  1651. case XK_KP_Prior:
  1652. case XK_KP_Next:
  1653. case XK_Right:
  1654. case XK_KP_Right:
  1655. x += incr;
  1656. handled = TRUE;
  1657. break;
  1658. }
  1659. if (handled)
  1660. {
  1661. MetaRectangle old_rect;
  1662. meta_topic (META_DEBUG_KEYBINDINGS,
  1663. "Computed new window location %d,%d due to keypress\n",
  1664. x, y);
  1665. meta_window_tile (window, META_TILE_NONE, FALSE);
  1666. meta_window_get_client_root_coords (window, &old_rect);
  1667. meta_window_edge_resistance_for_move (window,
  1668. old_rect.x,
  1669. old_rect.y,
  1670. &x,
  1671. &y,
  1672. NULL,
  1673. smart_snap,
  1674. TRUE);
  1675. meta_window_move (window, TRUE, x, y);
  1676. meta_window_update_keyboard_move (window);
  1677. }
  1678. return handled;
  1679. }
  1680. static gboolean
  1681. process_keyboard_resize_grab_op_change (MetaDisplay *display,
  1682. MetaScreen *screen,
  1683. MetaWindow *window,
  1684. XEvent *event,
  1685. KeySym keysym)
  1686. {
  1687. gboolean handled;
  1688. handled = FALSE;
  1689. switch (display->grab_op)
  1690. {
  1691. case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
  1692. switch (keysym)
  1693. {
  1694. case XK_Up:
  1695. case XK_KP_Up:
  1696. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) {
  1697. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
  1698. }
  1699. handled = TRUE;
  1700. break;
  1701. case XK_Down:
  1702. case XK_KP_Down:
  1703. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) {
  1704. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
  1705. }
  1706. handled = TRUE;
  1707. break;
  1708. case XK_Left:
  1709. case XK_KP_Left:
  1710. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) {
  1711. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
  1712. }
  1713. handled = TRUE;
  1714. break;
  1715. case XK_Right:
  1716. case XK_KP_Right:
  1717. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) {
  1718. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
  1719. }
  1720. handled = TRUE;
  1721. break;
  1722. }
  1723. break;
  1724. case META_GRAB_OP_KEYBOARD_RESIZING_S:
  1725. switch (keysym)
  1726. {
  1727. case XK_Left:
  1728. case XK_KP_Left:
  1729. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) {
  1730. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
  1731. }
  1732. handled = TRUE;
  1733. break;
  1734. case XK_Right:
  1735. case XK_KP_Right:
  1736. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) {
  1737. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
  1738. }
  1739. handled = TRUE;
  1740. break;
  1741. }
  1742. break;
  1743. case META_GRAB_OP_KEYBOARD_RESIZING_N:
  1744. switch (keysym)
  1745. {
  1746. case XK_Left:
  1747. case XK_KP_Left:
  1748. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) {
  1749. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
  1750. }
  1751. handled = TRUE;
  1752. break;
  1753. case XK_Right:
  1754. case XK_KP_Right:
  1755. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) {
  1756. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
  1757. }
  1758. handled = TRUE;
  1759. break;
  1760. }
  1761. break;
  1762. case META_GRAB_OP_KEYBOARD_RESIZING_W:
  1763. switch (keysym)
  1764. {
  1765. case XK_Up:
  1766. case XK_KP_Up:
  1767. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) {
  1768. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
  1769. }
  1770. handled = TRUE;
  1771. break;
  1772. case XK_Down:
  1773. case XK_KP_Down:
  1774. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) {
  1775. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
  1776. }
  1777. handled = TRUE;
  1778. break;
  1779. }
  1780. break;
  1781. case META_GRAB_OP_KEYBOARD_RESIZING_E:
  1782. switch (keysym)
  1783. {
  1784. case XK_Up:
  1785. case XK_KP_Up:
  1786. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) {
  1787. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
  1788. }
  1789. handled = TRUE;
  1790. break;
  1791. case XK_Down:
  1792. case XK_KP_Down:
  1793. if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) {
  1794. display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
  1795. }
  1796. handled = TRUE;
  1797. break;
  1798. }
  1799. break;
  1800. case META_GRAB_OP_KEYBOARD_RESIZING_SE:
  1801. case META_GRAB_OP_KEYBOARD_RESIZING_NE:
  1802. case META_GRAB_OP_KEYBOARD_RESIZING_SW:
  1803. case META_GRAB_OP_KEYBOARD_RESIZING_NW:
  1804. break;
  1805. default:
  1806. g_assert_not_reached ();
  1807. break;
  1808. }
  1809. if (handled)
  1810. {
  1811. meta_window_update_keyboard_resize (window, TRUE);
  1812. return TRUE;
  1813. }
  1814. return FALSE;
  1815. }
  1816. static gboolean
  1817. process_keyboard_resize_grab (MetaDisplay *display,
  1818. MetaScreen *screen,
  1819. MetaWindow *window,
  1820. XEvent *event,
  1821. KeySym keysym)
  1822. {
  1823. gboolean handled;
  1824. int height_inc;
  1825. int width_inc;
  1826. int width, height;
  1827. gboolean smart_snap;
  1828. int gravity;
  1829. handled = FALSE;
  1830. /* don't care about releases, but eat them, don't end grab */
  1831. if (event->type == KeyRelease)
  1832. return TRUE;
  1833. /* don't end grab on modifier key presses */
  1834. if (is_modifier (display, event->xkey.keycode))
  1835. return TRUE;
  1836. if (keysym == XK_Escape)
  1837. {
  1838. /* End resize and restore to original state. */
  1839. meta_window_move_resize (display->grab_window,
  1840. TRUE,
  1841. display->grab_initial_window_pos.x,
  1842. display->grab_initial_window_pos.y,
  1843. display->grab_initial_window_pos.width,
  1844. display->grab_initial_window_pos.height);
  1845. return FALSE;
  1846. }
  1847. if (process_keyboard_resize_grab_op_change (display, screen, window,
  1848. event, keysym))
  1849. return TRUE;
  1850. width = window->rect.width;
  1851. height = window->rect.height;
  1852. if (window->tile_mode != META_TILE_NONE)
  1853. gravity = meta_resize_gravity_from_tile_mode (window->tile_mode);
  1854. else
  1855. gravity = meta_resize_gravity_from_grab_op (display->grab_op);
  1856. smart_snap = (event->xkey.state & ShiftMask) != 0;
  1857. #define SMALL_INCREMENT 1
  1858. #define NORMAL_INCREMENT 10
  1859. if (smart_snap)
  1860. {
  1861. height_inc = 1;
  1862. width_inc = 1;
  1863. }
  1864. else if (event->xkey.state & ControlMask)
  1865. {
  1866. width_inc = SMALL_INCREMENT;
  1867. height_inc = SMALL_INCREMENT;
  1868. }
  1869. else
  1870. {
  1871. width_inc = NORMAL_INCREMENT;
  1872. height_inc = NORMAL_INCREMENT;
  1873. }
  1874. /* If this is a resize increment window, make the amount we resize
  1875. * the window by match that amount (well, unless snap resizing...)
  1876. */
  1877. if (window->size_hints.width_inc > 1)
  1878. width_inc = window->size_hints.width_inc;
  1879. if (window->size_hints.height_inc > 1)
  1880. height_inc = window->size_hints.height_inc;
  1881. switch (keysym)
  1882. {
  1883. case XK_Up:
  1884. case XK_KP_Up:
  1885. switch (gravity)
  1886. {
  1887. case NorthGravity:
  1888. case NorthWestGravity:
  1889. case NorthEastGravity:
  1890. /* Move bottom edge up */
  1891. height -= height_inc;
  1892. break;
  1893. case SouthGravity:
  1894. case SouthWestGravity:
  1895. case SouthEastGravity:
  1896. /* Move top edge up */
  1897. height += height_inc;
  1898. break;
  1899. case EastGravity:
  1900. case WestGravity:
  1901. case CenterGravity:
  1902. g_assert_not_reached ();
  1903. break;
  1904. }
  1905. handled = TRUE;
  1906. break;
  1907. case XK_Down:
  1908. case XK_KP_Down:
  1909. switch (gravity)
  1910. {
  1911. case NorthGravity:
  1912. case NorthWestGravity:
  1913. case NorthEastGravity:
  1914. /* Move bottom edge down */
  1915. height += height_inc;
  1916. break;
  1917. case SouthGravity:
  1918. case SouthWestGravity:
  1919. case SouthEastGravity:
  1920. /* Move top edge down */
  1921. height -= height_inc;
  1922. break;
  1923. case EastGravity:
  1924. case WestGravity:
  1925. case CenterGravity:
  1926. g_assert_not_reached ();
  1927. break;
  1928. }
  1929. handled = TRUE;
  1930. break;
  1931. case XK_Left:
  1932. case XK_KP_Left:
  1933. switch (gravity)
  1934. {
  1935. case EastGravity:
  1936. case SouthEastGravity:
  1937. case NorthEastGravity:
  1938. /* Move left edge left */
  1939. width += width_inc;
  1940. break;
  1941. case WestGravity:
  1942. case SouthWestGravity:
  1943. case NorthWestGravity:
  1944. /* Move right edge left */
  1945. width -= width_inc;
  1946. break;
  1947. case NorthGravity:
  1948. case SouthGravity:
  1949. case CenterGravity:
  1950. g_assert_not_reached ();
  1951. break;
  1952. }
  1953. handled = TRUE;
  1954. break;
  1955. case XK_Right:
  1956. case XK_KP_Right:
  1957. switch (gravity)
  1958. {
  1959. case EastGravity:
  1960. case SouthEastGravity:
  1961. case NorthEastGravity:
  1962. /* Move left edge right */
  1963. width -= width_inc;
  1964. break;
  1965. case WestGravity:
  1966. case SouthWestGravity:
  1967. case NorthWestGravity:
  1968. /* Move right edge right */
  1969. width += width_inc;
  1970. break;
  1971. case NorthGravity:
  1972. case SouthGravity:
  1973. case CenterGravity:
  1974. g_assert_not_reached ();
  1975. break;
  1976. }
  1977. handled = TRUE;
  1978. break;
  1979. default:
  1980. break;
  1981. }
  1982. /* fixup hack (just paranoia, not sure it's required) */
  1983. if (height < 1)
  1984. height = 1;
  1985. if (width < 1)
  1986. width = 1;
  1987. if (handled)
  1988. {
  1989. MetaRectangle old_rect;
  1990. meta_topic (META_DEBUG_KEYBINDINGS,
  1991. "Computed new window size due to keypress: "
  1992. "%dx%d, gravity %s\n",
  1993. width, height, meta_gravity_to_string (gravity));
  1994. old_rect = window->rect; /* Don't actually care about x,y */
  1995. /* Do any edge resistance/snapping */
  1996. meta_window_edge_resistance_for_resize (window,
  1997. old_rect.width,
  1998. old_rect.height,
  1999. &width,
  2000. &height,
  2001. gravity,
  2002. NULL,
  2003. smart_snap,
  2004. TRUE);
  2005. /* We don't need to update unless the specified width and height
  2006. * are actually different from what we had before.
  2007. */
  2008. if (window->rect.width != width || window->rect.height != height)
  2009. meta_window_resize_with_gravity (window,
  2010. TRUE,
  2011. width,
  2012. height,
  2013. gravity);
  2014. meta_window_update_keyboard_resize (window, FALSE);
  2015. }
  2016. return handled;
  2017. }
  2018. static void
  2019. handle_switch_to_workspace (MetaDisplay *display,
  2020. MetaScreen *screen,
  2021. MetaWindow *event_window,
  2022. XEvent *event,
  2023. MetaKeyBinding *binding,
  2024. gpointer dummy)
  2025. {
  2026. gint which = binding->handler->data;
  2027. MetaWorkspace *workspace;
  2028. workspace = meta_screen_get_workspace_by_index (screen, which);
  2029. if (workspace)
  2030. meta_workspace_activate (workspace, event->xkey.time);
  2031. }
  2032. static void
  2033. handle_maximize_vertically (MetaDisplay *display,
  2034. MetaScreen *screen,
  2035. MetaWindow *window,
  2036. XEvent *event,
  2037. MetaKeyBinding *binding,
  2038. gpointer dummy)
  2039. {
  2040. if (window->has_resize_func)
  2041. {
  2042. if (window->maximized_vertically)
  2043. meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
  2044. else
  2045. meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
  2046. }
  2047. }
  2048. static void
  2049. handle_maximize_horizontally (MetaDisplay *display,
  2050. MetaScreen *screen,
  2051. MetaWindow *window,
  2052. XEvent *event,
  2053. MetaKeyBinding *binding,
  2054. gpointer dummy)
  2055. {
  2056. if (window->has_resize_func)
  2057. {
  2058. if (window->maximized_horizontally)
  2059. meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
  2060. else
  2061. meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
  2062. }
  2063. }
  2064. static void
  2065. handle_opacity (MetaDisplay *display,
  2066. MetaScreen *screen,
  2067. MetaWindow *window,
  2068. XEvent *event,
  2069. MetaKeyBinding *binding,
  2070. gpointer dummy)
  2071. {
  2072. MetaKeyBindingAction action = meta_prefs_get_keybinding_action (binding->name);
  2073. meta_window_adjust_opacity (window, action == META_KEYBINDING_ACTION_INCREASE_OPACITY);
  2074. }
  2075. static void
  2076. handle_move_to (MetaDisplay *display,
  2077. MetaScreen *screen,
  2078. MetaWindow *window,
  2079. XEvent *event,
  2080. MetaKeyBinding *binding,
  2081. gpointer dummy)
  2082. {
  2083. guint direction = binding->handler->data;
  2084. MetaRectangle work_area, outer;
  2085. int monitor, new_x, new_y;
  2086. monitor = meta_screen_get_current_monitor (window->screen);
  2087. meta_window_get_work_area_for_monitor (window, monitor, &work_area);
  2088. meta_window_get_outer_rect (window, &outer);
  2089. if (direction & META_MOVE_TO_XCHANGE_FLAG) {
  2090. new_x = work_area.x + (direction & META_MOVE_TO_RIGHT_FLAG ?
  2091. work_area.width - outer.width :
  2092. 0);
  2093. } else {
  2094. new_x = outer.x;
  2095. }
  2096. if (direction & META_MOVE_TO_YCHANGE_FLAG) {
  2097. new_y = work_area.y + (direction & META_MOVE_TO_BOTTOM_FLAG ?
  2098. work_area.height - outer.height :
  2099. 0);
  2100. } else {
  2101. new_y = outer.y;
  2102. }
  2103. meta_window_move_frame (window,
  2104. TRUE,
  2105. new_x,
  2106. new_y);
  2107. }
  2108. static void
  2109. handle_move_to_center (MetaDisplay *display,
  2110. MetaScreen *screen,
  2111. MetaWindow *window,
  2112. XEvent *event,
  2113. MetaKeyBinding *binding,
  2114. gpointer dummy)
  2115. {
  2116. MetaFrameBorders borders;
  2117. const MetaMonitorInfo *monitor;
  2118. int window_width, window_height;
  2119. int center_x, center_y;
  2120. monitor = meta_screen_get_current_monitor_info (window->screen);
  2121. meta_frame_calc_borders (window->frame, &borders);
  2122. window_width = (window->frame ? window->frame->rect.width : window->rect.width);
  2123. window_height = (window->frame ? window->frame->rect.height : window->rect.height);
  2124. center_x = monitor->rect.x + monitor->rect.width / 2;
  2125. center_y = monitor->rect.y + monitor->rect.height / 2;
  2126. meta_window_move_resize (window,
  2127. TRUE,
  2128. center_x + borders.visible.left - window_width / 2,
  2129. center_y + borders.visible.top - window_height / 2,
  2130. window->rect.width,
  2131. window->rect.height);
  2132. }
  2133. static void
  2134. handle_show_desktop (MetaDisplay *display,
  2135. MetaScreen *screen,
  2136. MetaWindow *window,
  2137. XEvent *event,
  2138. MetaKeyBinding *binding,
  2139. gpointer dummy)
  2140. {
  2141. meta_screen_toggle_desktop (screen, event->xkey.time);
  2142. }
  2143. static void
  2144. handle_toggle_recording (MetaDisplay *display,
  2145. MetaScreen *screen,
  2146. MetaWindow *window,
  2147. XEvent *event,
  2148. MetaKeyBinding *binding,
  2149. gpointer dummy)
  2150. {
  2151. g_signal_emit_by_name (screen, "toggle-recording");
  2152. }
  2153. static void
  2154. handle_activate_window_menu (MetaDisplay *display,
  2155. MetaScreen *screen,
  2156. MetaWindow *event_window,
  2157. XEvent *event,
  2158. MetaKeyBinding *binding,
  2159. gpointer dummy)
  2160. {
  2161. if (display->focus_window)
  2162. {
  2163. int x, y;
  2164. meta_window_get_position (display->focus_window,
  2165. &x, &y);
  2166. if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
  2167. x += display->focus_window->rect.width;
  2168. meta_window_show_menu (display->focus_window,
  2169. x, y,
  2170. 0,
  2171. event->xkey.time);
  2172. }
  2173. }
  2174. static void
  2175. handle_toggle_fullscreen (MetaDisplay *display,
  2176. MetaScreen *screen,
  2177. MetaWindow *window,
  2178. XEvent *event,
  2179. MetaKeyBinding *binding,
  2180. gpointer dummy)
  2181. {
  2182. if (window->fullscreen)
  2183. meta_window_unmake_fullscreen (window);
  2184. else if (window->has_fullscreen_func)
  2185. meta_window_make_fullscreen (window);
  2186. }
  2187. static void
  2188. handle_toggle_above (MetaDisplay *display,
  2189. MetaScreen *screen,
  2190. MetaWindow *window,
  2191. XEvent *event,
  2192. MetaKeyBinding *binding,
  2193. gpointer dummy)
  2194. {
  2195. if (window->wm_state_above)
  2196. meta_window_unmake_above (window);
  2197. else
  2198. meta_window_make_above (window);
  2199. }
  2200. static MetaTileMode
  2201. get_new_tile_mode (MetaTileMode direction,
  2202. MetaTileMode current)
  2203. {
  2204. MetaTileMode ret = META_TILE_NONE;
  2205. switch (current) {
  2206. case META_TILE_NONE:
  2207. ret = direction;
  2208. break;
  2209. case META_TILE_MAXIMIZE:
  2210. if (direction == META_TILE_LEFT)
  2211. ret = META_TILE_LEFT;
  2212. else if (direction == META_TILE_RIGHT)
  2213. ret = META_TILE_RIGHT;
  2214. else if (direction == META_TILE_TOP)
  2215. ret = direction;
  2216. else if (direction == META_TILE_BOTTOM)
  2217. ret = META_TILE_TOP;
  2218. else
  2219. ret = META_TILE_NONE;
  2220. break;
  2221. case META_TILE_LEFT:
  2222. if (direction == META_TILE_LEFT)
  2223. ret = META_TILE_LEFT;
  2224. else if (direction == META_TILE_RIGHT)
  2225. ret = META_TILE_NONE;
  2226. else if (direction == META_TILE_TOP)
  2227. ret = META_TILE_ULC;
  2228. else
  2229. ret = META_TILE_LLC;
  2230. break;
  2231. case META_TILE_RIGHT:
  2232. if (direction == META_TILE_LEFT)
  2233. ret = META_TILE_NONE;
  2234. else if (direction == META_TILE_RIGHT)
  2235. ret = META_TILE_RIGHT;
  2236. else if (direction == META_TILE_TOP)
  2237. ret = META_TILE_URC;
  2238. else
  2239. ret = META_TILE_LRC;
  2240. break;
  2241. case META_TILE_TOP:
  2242. if (direction == META_TILE_LEFT)
  2243. ret = META_TILE_ULC;
  2244. else if (direction == META_TILE_RIGHT)
  2245. ret = META_TILE_URC;
  2246. else if (direction == META_TILE_TOP)
  2247. ret = META_TILE_MAXIMIZE;
  2248. else
  2249. ret = META_TILE_NONE;
  2250. break;
  2251. case META_TILE_BOTTOM:
  2252. if (direction == META_TILE_LEFT)
  2253. ret = META_TILE_LLC;
  2254. else if (direction == META_TILE_RIGHT)
  2255. ret = META_TILE_LRC;
  2256. else if (direction == META_TILE_TOP)
  2257. ret = META_TILE_NONE;
  2258. else
  2259. ret = META_TILE_BOTTOM;
  2260. break;
  2261. case META_TILE_ULC:
  2262. if (direction == META_TILE_LEFT)
  2263. ret = META_TILE_ULC;
  2264. else if (direction == META_TILE_RIGHT)
  2265. ret = META_TILE_TOP;
  2266. else if (direction == META_TILE_TOP)
  2267. ret = META_TILE_ULC;
  2268. else
  2269. ret = META_TILE_LEFT;
  2270. break;
  2271. case META_TILE_LLC:
  2272. if (direction == META_TILE_LEFT)
  2273. ret = META_TILE_LLC;
  2274. else if (direction == META_TILE_RIGHT)
  2275. ret = META_TILE_BOTTOM;
  2276. else if (direction == META_TILE_TOP)
  2277. ret = META_TILE_LEFT;
  2278. else
  2279. ret = META_TILE_LLC;
  2280. break;
  2281. case META_TILE_URC:
  2282. if (direction == META_TILE_LEFT)
  2283. ret = META_TILE_TOP;
  2284. else if (direction == META_TILE_RIGHT)
  2285. ret = META_TILE_URC;
  2286. else if (direction == META_TILE_TOP)
  2287. ret = META_TILE_URC;
  2288. else
  2289. ret = META_TILE_RIGHT;
  2290. break;
  2291. case META_TILE_LRC:
  2292. if (direction == META_TILE_LEFT)
  2293. ret = META_TILE_BOTTOM;
  2294. else if (direction == META_TILE_RIGHT)
  2295. ret = META_TILE_LRC;
  2296. else if (direction == META_TILE_TOP)
  2297. ret = META_TILE_RIGHT;
  2298. else
  2299. ret = META_TILE_LRC;
  2300. break;
  2301. default:
  2302. ret = current;
  2303. break;
  2304. }
  2305. return ret;
  2306. }
  2307. static void
  2308. handle_tile_action (MetaDisplay *display,
  2309. MetaScreen *screen,
  2310. MetaWindow *window,
  2311. XEvent *event,
  2312. MetaKeyBinding *binding,
  2313. gpointer dummy)
  2314. {
  2315. MetaTileMode mode = binding->handler->data;
  2316. MetaKeyBindingAction action = meta_prefs_get_keybinding_action (binding->name);
  2317. gboolean snap = action == META_KEYBINDING_ACTION_PUSH_SNAP_LEFT ||
  2318. action == META_KEYBINDING_ACTION_PUSH_SNAP_RIGHT ||
  2319. action == META_KEYBINDING_ACTION_PUSH_SNAP_UP ||
  2320. action == META_KEYBINDING_ACTION_PUSH_SNAP_DOWN;
  2321. MetaTileMode new_mode = get_new_tile_mode (mode, META_WINDOW_MAXIMIZED (window) ?
  2322. META_TILE_MAXIMIZE : window->tile_mode);
  2323. if (new_mode == window->tile_mode)
  2324. return;
  2325. if (new_mode == META_TILE_MAXIMIZE)
  2326. {
  2327. meta_window_maximize (window,
  2328. META_MAXIMIZE_HORIZONTAL |
  2329. META_MAXIMIZE_VERTICAL);
  2330. }
  2331. else
  2332. {
  2333. meta_window_tile (window, new_mode, snap);
  2334. }
  2335. }
  2336. static void
  2337. handle_toggle_maximized (MetaDisplay *display,
  2338. MetaScreen *screen,
  2339. MetaWindow *window,
  2340. XEvent *event,
  2341. MetaKeyBinding *binding,
  2342. gpointer dummy)
  2343. {
  2344. if (META_WINDOW_MAXIMIZED (window))
  2345. meta_window_unmaximize (window,
  2346. META_MAXIMIZE_HORIZONTAL |
  2347. META_MAXIMIZE_VERTICAL);
  2348. else if (window->has_maximize_func)
  2349. meta_window_maximize (window,
  2350. META_MAXIMIZE_HORIZONTAL |
  2351. META_MAXIMIZE_VERTICAL);
  2352. }
  2353. static void
  2354. handle_maximize (MetaDisplay *display,
  2355. MetaScreen *screen,
  2356. MetaWindow *window,
  2357. XEvent *event,
  2358. MetaKeyBinding *binding,
  2359. gpointer dummy)
  2360. {
  2361. if (window->has_maximize_func)
  2362. meta_window_maximize (window,
  2363. META_MAXIMIZE_HORIZONTAL |
  2364. META_MAXIMIZE_VERTICAL);
  2365. }
  2366. static void
  2367. handle_unmaximize (MetaDisplay *display,
  2368. MetaScreen *screen,
  2369. MetaWindow *window,
  2370. XEvent *event,
  2371. MetaKeyBinding *binding,
  2372. gpointer dummy)
  2373. {
  2374. if (window->maximized_vertically || window->maximized_horizontally)
  2375. meta_window_unmaximize (window,
  2376. META_MAXIMIZE_HORIZONTAL |
  2377. META_MAXIMIZE_VERTICAL);
  2378. }
  2379. static void
  2380. handle_toggle_shaded (MetaDisplay *display,
  2381. MetaScreen *screen,
  2382. MetaWindow *window,
  2383. XEvent *event,
  2384. MetaKeyBinding *binding,
  2385. gpointer dummy)
  2386. {
  2387. if (window->shaded)
  2388. meta_window_unshade (window, event->xkey.time);
  2389. else if (window->has_shade_func)
  2390. meta_window_shade (window, event->xkey.time);
  2391. }
  2392. static void
  2393. handle_close (MetaDisplay *display,
  2394. MetaScreen *screen,
  2395. MetaWindow *window,
  2396. XEvent *event,
  2397. MetaKeyBinding *binding,
  2398. gpointer dummy)
  2399. {
  2400. if (window->has_close_func)
  2401. meta_window_delete (window, event->xkey.time);
  2402. }
  2403. static void
  2404. handle_minimize (MetaDisplay *display,
  2405. MetaScreen *screen,
  2406. MetaWindow *window,
  2407. XEvent *event,
  2408. MetaKeyBinding *binding,
  2409. gpointer dummy)
  2410. {
  2411. if (window->has_minimize_func)
  2412. meta_window_minimize (window);
  2413. }
  2414. static void
  2415. handle_begin_move (MetaDisplay *display,
  2416. MetaScreen *screen,
  2417. MetaWindow *window,
  2418. XEvent *event,
  2419. MetaKeyBinding *binding,
  2420. gpointer dummy)
  2421. {
  2422. if (window->has_move_func)
  2423. {
  2424. meta_window_begin_grab_op (window,
  2425. META_GRAB_OP_KEYBOARD_MOVING,
  2426. FALSE,
  2427. event->xkey.time);
  2428. }
  2429. }
  2430. static void
  2431. handle_begin_resize (MetaDisplay *display,
  2432. MetaScreen *screen,
  2433. MetaWindow *window,
  2434. XEvent *event,
  2435. MetaKeyBinding *binding,
  2436. gpointer dummy)
  2437. {
  2438. if (window->has_resize_func)
  2439. {
  2440. if (window->tile_mode != META_TILE_NONE)
  2441. {
  2442. window->resize_tile_mode = window->tile_mode;
  2443. window->resizing_tile_type = window->tile_type;
  2444. }
  2445. meta_window_begin_grab_op (window,
  2446. META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
  2447. FALSE,
  2448. event->xkey.time);
  2449. }
  2450. }
  2451. static void
  2452. handle_toggle_on_all_workspaces (MetaDisplay *display,
  2453. MetaScreen *screen,
  2454. MetaWindow *window,
  2455. XEvent *event,
  2456. MetaKeyBinding *binding,
  2457. gpointer dummy)
  2458. {
  2459. if (window->on_all_workspaces_requested)
  2460. meta_window_unstick (window);
  2461. else
  2462. meta_window_stick (window);
  2463. }
  2464. static void
  2465. handle_move_to_workspace (MetaDisplay *display,
  2466. MetaScreen *screen,
  2467. MetaWindow *window,
  2468. XEvent *event,
  2469. MetaKeyBinding *binding,
  2470. gpointer dummy)
  2471. {
  2472. gint which = binding->handler->data;
  2473. gboolean flip = (which < 0);
  2474. gboolean new = (which == META_MOTION_NOT_EXIST_YET);
  2475. MetaWorkspace *workspace;
  2476. /* If which is zero or positive, it's a workspace number, and the window
  2477. * should move to the workspace with that number.
  2478. *
  2479. * However, if it's negative, it's a direction with respect to the current
  2480. * position; it's expressed as a member of the MetaMotionDirection enum,
  2481. * all of whose members are negative. Such a change is called a flip.
  2482. */
  2483. if (window->always_sticky)
  2484. return;
  2485. workspace = NULL;
  2486. if (!new) {
  2487. if (flip)
  2488. {
  2489. workspace = meta_workspace_get_neighbor (screen->active_workspace,
  2490. which);
  2491. }
  2492. else
  2493. {
  2494. workspace = meta_screen_get_workspace_by_index (screen, which);
  2495. }
  2496. }
  2497. if (workspace)
  2498. {
  2499. /* Activate second, so the window is never unmapped */
  2500. meta_window_change_workspace (window, workspace);
  2501. if (flip)
  2502. {
  2503. meta_topic (META_DEBUG_FOCUS,
  2504. "Resetting mouse_mode to FALSE due to "
  2505. "handle_move_to_workspace() call with flip set.\n");
  2506. workspace->screen->display->mouse_mode = FALSE;
  2507. meta_workspace_activate_with_focus (workspace,
  2508. window,
  2509. event->xkey.time);
  2510. }
  2511. }
  2512. else if (new)
  2513. {
  2514. workspace = meta_screen_append_new_workspace (window->screen, FALSE, event->xkey.time);
  2515. GSettings *cinnamon = g_settings_new ("org.cinnamon");
  2516. g_settings_set_int (cinnamon, "number-workspaces", g_list_length (screen->workspaces));
  2517. g_object_unref (cinnamon);
  2518. meta_window_change_workspace (window, workspace);
  2519. }
  2520. }
  2521. static void
  2522. handle_move_to_monitor (MetaDisplay *display,
  2523. MetaScreen *screen,
  2524. MetaWindow *window,
  2525. XEvent *event,
  2526. MetaKeyBinding *binding,
  2527. gpointer dummy)
  2528. {
  2529. gint which = binding->handler->data;
  2530. const MetaMonitorInfo *current, *new;
  2531. current = meta_screen_get_monitor_for_window (screen, window);
  2532. new = meta_screen_get_monitor_neighbor (screen, current->number, which);
  2533. if (new == NULL)
  2534. return;
  2535. meta_window_move_to_monitor (window, new->number);
  2536. }
  2537. static void
  2538. handle_raise_or_lower (MetaDisplay *display,
  2539. MetaScreen *screen,
  2540. MetaWindow *window,
  2541. XEvent *event,
  2542. MetaKeyBinding *binding,
  2543. gpointer dummy)
  2544. {
  2545. /* Get window at pointer */
  2546. MetaWindow *above = NULL;
  2547. /* Check if top */
  2548. if (meta_stack_get_top (window->screen->stack) == window)
  2549. {
  2550. meta_window_lower (window);
  2551. return;
  2552. }
  2553. /* else check if windows in same layer are intersecting it */
  2554. above = meta_stack_get_above (window->screen->stack, window, TRUE);
  2555. while (above)
  2556. {
  2557. MetaRectangle tmp, win_rect, above_rect;
  2558. if (above->mapped)
  2559. {
  2560. meta_window_get_outer_rect (window, &win_rect);
  2561. meta_window_get_outer_rect (above, &above_rect);
  2562. /* Check if obscured */
  2563. if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
  2564. {
  2565. meta_window_raise (window);
  2566. return;
  2567. }
  2568. }
  2569. above = meta_stack_get_above (window->screen->stack, above, TRUE);
  2570. }
  2571. /* window is not obscured */
  2572. meta_window_lower (window);
  2573. }
  2574. static void
  2575. handle_raise (MetaDisplay *display,
  2576. MetaScreen *screen,
  2577. MetaWindow *window,
  2578. XEvent *event,
  2579. MetaKeyBinding *binding,
  2580. gpointer dummy)
  2581. {
  2582. meta_window_raise (window);
  2583. }
  2584. static void
  2585. handle_lower (MetaDisplay *display,
  2586. MetaScreen *screen,
  2587. MetaWindow *window,
  2588. XEvent *event,
  2589. MetaKeyBinding *binding,
  2590. gpointer dummy)
  2591. {
  2592. meta_window_lower (window);
  2593. }
  2594. static void
  2595. handle_set_spew_mark (MetaDisplay *display,
  2596. MetaScreen *screen,
  2597. MetaWindow *window,
  2598. XEvent *event,
  2599. MetaKeyBinding *binding,
  2600. gpointer dummy)
  2601. {
  2602. meta_verbose ("-- MARK MARK MARK MARK --\n");
  2603. }
  2604. LOCAL_SYMBOL void
  2605. meta_set_keybindings_disabled (gboolean setting)
  2606. {
  2607. all_bindings_disabled = setting;
  2608. meta_topic (META_DEBUG_KEYBINDINGS,
  2609. "Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
  2610. }
  2611. gboolean
  2612. meta_keybindings_set_custom_handler (const gchar *name,
  2613. MetaKeyHandlerFunc handler,
  2614. gpointer user_data,
  2615. GDestroyNotify free_data)
  2616. {
  2617. MetaKeyHandler *key_handler = HANDLER (name);
  2618. if (!key_handler)
  2619. return FALSE;
  2620. if (key_handler->user_data_free_func && key_handler->user_data)
  2621. key_handler->user_data_free_func (key_handler->user_data);
  2622. key_handler->func = handler;
  2623. key_handler->user_data = user_data;
  2624. key_handler->user_data_free_func = free_data;
  2625. return TRUE;
  2626. }
  2627. static void
  2628. init_builtin_key_bindings (MetaDisplay *display)
  2629. {
  2630. #define REVERSES_AND_REVERSED (META_KEY_BINDING_REVERSES | \
  2631. META_KEY_BINDING_IS_REVERSED)
  2632. add_builtin_keybinding (display,
  2633. "switch-to-workspace-1",
  2634. SCHEMA_MUFFIN_KEYBINDINGS,
  2635. META_KEY_BINDING_NONE,
  2636. META_KEYBINDING_ACTION_WORKSPACE_1,
  2637. handle_switch_to_workspace, 0);
  2638. add_builtin_keybinding (display,
  2639. "switch-to-workspace-2",
  2640. SCHEMA_MUFFIN_KEYBINDINGS,
  2641. META_KEY_BINDING_NONE,
  2642. META_KEYBINDING_ACTION_WORKSPACE_2,
  2643. handle_switch_to_workspace, 1);
  2644. add_builtin_keybinding (display,
  2645. "switch-to-workspace-3",
  2646. SCHEMA_MUFFIN_KEYBINDINGS,
  2647. META_KEY_BINDING_NONE,
  2648. META_KEYBINDING_ACTION_WORKSPACE_3,
  2649. handle_switch_to_workspace, 2);
  2650. add_builtin_keybinding (display,
  2651. "switch-to-workspace-4",
  2652. SCHEMA_MUFFIN_KEYBINDINGS,
  2653. META_KEY_BINDING_NONE,
  2654. META_KEYBINDING_ACTION_WORKSPACE_4,
  2655. handle_switch_to_workspace, 3);
  2656. add_builtin_keybinding (display,
  2657. "switch-to-workspace-5",
  2658. SCHEMA_MUFFIN_KEYBINDINGS,
  2659. META_KEY_BINDING_NONE,
  2660. META_KEYBINDING_ACTION_WORKSPACE_5,
  2661. handle_switch_to_workspace, 4);
  2662. add_builtin_keybinding (display,
  2663. "switch-to-workspace-6",
  2664. SCHEMA_MUFFIN_KEYBINDINGS,
  2665. META_KEY_BINDING_NONE,
  2666. META_KEYBINDING_ACTION_WORKSPACE_6,
  2667. handle_switch_to_workspace, 5);
  2668. add_builtin_keybinding (display,
  2669. "switch-to-workspace-7",
  2670. SCHEMA_MUFFIN_KEYBINDINGS,
  2671. META_KEY_BINDING_NONE,
  2672. META_KEYBINDING_ACTION_WORKSPACE_7,
  2673. handle_switch_to_workspace, 6);
  2674. add_builtin_keybinding (display,
  2675. "switch-to-workspace-8",
  2676. SCHEMA_MUFFIN_KEYBINDINGS,
  2677. META_KEY_BINDING_NONE,
  2678. META_KEYBINDING_ACTION_WORKSPACE_8,
  2679. handle_switch_to_workspace, 7);
  2680. add_builtin_keybinding (display,
  2681. "switch-to-workspace-9",
  2682. SCHEMA_MUFFIN_KEYBINDINGS,
  2683. META_KEY_BINDING_NONE,
  2684. META_KEYBINDING_ACTION_WORKSPACE_9,
  2685. handle_switch_to_workspace, 8);
  2686. add_builtin_keybinding (display,
  2687. "switch-to-workspace-10",
  2688. SCHEMA_MUFFIN_KEYBINDINGS,
  2689. META_KEY_BINDING_NONE,
  2690. META_KEYBINDING_ACTION_WORKSPACE_10,
  2691. handle_switch_to_workspace, 9);
  2692. add_builtin_keybinding (display,
  2693. "switch-to-workspace-11",
  2694. SCHEMA_MUFFIN_KEYBINDINGS,
  2695. META_KEY_BINDING_NONE,
  2696. META_KEYBINDING_ACTION_WORKSPACE_11,
  2697. handle_switch_to_workspace, 10);
  2698. add_builtin_keybinding (display,
  2699. "switch-to-workspace-12",
  2700. SCHEMA_MUFFIN_KEYBINDINGS,
  2701. META_KEY_BINDING_NONE,
  2702. META_KEYBINDING_ACTION_WORKSPACE_12,
  2703. handle_switch_to_workspace, 11);
  2704. // Handled by Cinnamon, hence handler is NULL
  2705. add_builtin_keybinding (display,
  2706. "switch-to-workspace-left",
  2707. SCHEMA_MUFFIN_KEYBINDINGS,
  2708. META_KEY_BINDING_NONE,
  2709. META_KEYBINDING_ACTION_WORKSPACE_LEFT,
  2710. NULL, META_MOTION_LEFT);
  2711. add_builtin_keybinding (display,
  2712. "switch-to-workspace-right",
  2713. SCHEMA_MUFFIN_KEYBINDINGS,
  2714. META_KEY_BINDING_NONE,
  2715. META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
  2716. NULL, META_MOTION_RIGHT);
  2717. add_builtin_keybinding (display,
  2718. "switch-to-workspace-up",
  2719. SCHEMA_MUFFIN_KEYBINDINGS,
  2720. META_KEY_BINDING_NONE,
  2721. META_KEYBINDING_ACTION_WORKSPACE_UP,
  2722. NULL, META_MOTION_UP);
  2723. add_builtin_keybinding (display,
  2724. "switch-to-workspace-down",
  2725. SCHEMA_MUFFIN_KEYBINDINGS,
  2726. META_KEY_BINDING_NONE,
  2727. META_KEYBINDING_ACTION_WORKSPACE_DOWN,
  2728. NULL, META_MOTION_DOWN);
  2729. /* The ones which have inverses. These can't be bound to any keystroke
  2730. * containing Shift because Shift will invert their "backward" state.
  2731. *
  2732. * TODO: "NORMAL" and "DOCKS" should be renamed to the same name as their
  2733. * action, for obviousness.
  2734. *
  2735. * TODO: handle_switch and handle_cycle should probably really be the
  2736. * same function checking a bit in the parameter for difference.
  2737. */
  2738. add_builtin_keybinding (display,
  2739. "switch-group",
  2740. SCHEMA_MUFFIN_KEYBINDINGS,
  2741. META_KEY_BINDING_REVERSES,
  2742. META_KEYBINDING_ACTION_SWITCH_GROUP,
  2743. NULL, META_TAB_LIST_GROUP);
  2744. add_builtin_keybinding (display,
  2745. "switch-group-backward",
  2746. SCHEMA_MUFFIN_KEYBINDINGS,
  2747. REVERSES_AND_REVERSED,
  2748. META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD,
  2749. NULL, META_TAB_LIST_GROUP);
  2750. add_builtin_keybinding (display,
  2751. "switch-windows",
  2752. SCHEMA_MUFFIN_KEYBINDINGS,
  2753. META_KEY_BINDING_REVERSES,
  2754. META_KEYBINDING_ACTION_SWITCH_WINDOWS,
  2755. NULL, META_TAB_LIST_NORMAL);
  2756. add_builtin_keybinding (display,
  2757. "switch-windows-backward",
  2758. SCHEMA_MUFFIN_KEYBINDINGS,
  2759. REVERSES_AND_REVERSED,
  2760. META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD,
  2761. NULL, META_TAB_LIST_NORMAL);
  2762. add_builtin_keybinding (display,
  2763. "switch-panels",
  2764. SCHEMA_MUFFIN_KEYBINDINGS,
  2765. META_KEY_BINDING_REVERSES,
  2766. META_KEYBINDING_ACTION_SWITCH_PANELS,
  2767. NULL, META_TAB_LIST_DOCKS);
  2768. add_builtin_keybinding (display,
  2769. "switch-panels-backward",
  2770. SCHEMA_MUFFIN_KEYBINDINGS,
  2771. REVERSES_AND_REVERSED,
  2772. META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD,
  2773. NULL, META_TAB_LIST_DOCKS);
  2774. add_builtin_keybinding (display,
  2775. "show-desktop",
  2776. SCHEMA_MUFFIN_KEYBINDINGS,
  2777. META_KEY_BINDING_NONE,
  2778. META_KEYBINDING_ACTION_SHOW_DESKTOP,
  2779. handle_show_desktop, 0);
  2780. add_builtin_keybinding (display,
  2781. "panel-run-dialog",
  2782. SCHEMA_MUFFIN_KEYBINDINGS,
  2783. META_KEY_BINDING_NONE,
  2784. META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
  2785. NULL, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG);
  2786. add_builtin_keybinding (display,
  2787. "toggle-recording",
  2788. SCHEMA_MUFFIN_KEYBINDINGS,
  2789. META_KEY_BINDING_NONE,
  2790. META_KEYBINDING_ACTION_TOGGLE_RECORDING,
  2791. handle_toggle_recording, 0);
  2792. add_builtin_keybinding (display,
  2793. "set-spew-mark",
  2794. SCHEMA_MUFFIN_KEYBINDINGS,
  2795. META_KEY_BINDING_NONE,
  2796. META_KEYBINDING_ACTION_SET_SPEW_MARK,
  2797. handle_set_spew_mark, 0);
  2798. #undef REVERSES_AND_REVERSED
  2799. /************************ PER WINDOW BINDINGS ************************/
  2800. /* These take a window as an extra parameter; they have no effect
  2801. * if no window is active.
  2802. */
  2803. add_builtin_keybinding (display,
  2804. "activate-window-menu",
  2805. SCHEMA_MUFFIN_KEYBINDINGS,
  2806. META_KEY_BINDING_PER_WINDOW,
  2807. META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU,
  2808. handle_activate_window_menu, 0);
  2809. add_builtin_keybinding (display,
  2810. "toggle-fullscreen",
  2811. SCHEMA_MUFFIN_KEYBINDINGS,
  2812. META_KEY_BINDING_PER_WINDOW,
  2813. META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN,
  2814. handle_toggle_fullscreen, 0);
  2815. add_builtin_keybinding (display,
  2816. "toggle-maximized",
  2817. SCHEMA_MUFFIN_KEYBINDINGS,
  2818. META_KEY_BINDING_PER_WINDOW,
  2819. META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED,
  2820. handle_toggle_maximized, 0);
  2821. add_builtin_keybinding (display,
  2822. "push-tile-left",
  2823. SCHEMA_MUFFIN_KEYBINDINGS,
  2824. META_KEY_BINDING_PER_WINDOW,
  2825. META_KEYBINDING_ACTION_PUSH_TILE_LEFT,
  2826. handle_tile_action, META_TILE_LEFT);
  2827. add_builtin_keybinding (display,
  2828. "push-tile-right",
  2829. SCHEMA_MUFFIN_KEYBINDINGS,
  2830. META_KEY_BINDING_PER_WINDOW,
  2831. META_KEYBINDING_ACTION_PUSH_TILE_RIGHT,
  2832. handle_tile_action, META_TILE_RIGHT);
  2833. add_builtin_keybinding (display,
  2834. "push-tile-up",
  2835. SCHEMA_MUFFIN_KEYBINDINGS,
  2836. META_KEY_BINDING_PER_WINDOW,
  2837. META_KEYBINDING_ACTION_PUSH_TILE_UP,
  2838. handle_tile_action, META_TILE_TOP);
  2839. add_builtin_keybinding (display,
  2840. "push-tile-down",
  2841. SCHEMA_MUFFIN_KEYBINDINGS,
  2842. META_KEY_BINDING_PER_WINDOW,
  2843. META_KEYBINDING_ACTION_PUSH_TILE_DOWN,
  2844. handle_tile_action, META_TILE_BOTTOM);
  2845. add_builtin_keybinding (display,
  2846. "push-snap-left",
  2847. SCHEMA_MUFFIN_KEYBINDINGS,
  2848. META_KEY_BINDING_PER_WINDOW,
  2849. META_KEYBINDING_ACTION_PUSH_SNAP_LEFT,
  2850. handle_tile_action, META_TILE_LEFT);
  2851. add_builtin_keybinding (display,
  2852. "push-snap-right",
  2853. SCHEMA_MUFFIN_KEYBINDINGS,
  2854. META_KEY_BINDING_PER_WINDOW,
  2855. META_KEYBINDING_ACTION_PUSH_SNAP_RIGHT,
  2856. handle_tile_action, META_TILE_RIGHT);
  2857. add_builtin_keybinding (display,
  2858. "push-snap-up",
  2859. SCHEMA_MUFFIN_KEYBINDINGS,
  2860. META_KEY_BINDING_PER_WINDOW,
  2861. META_KEYBINDING_ACTION_PUSH_SNAP_UP,
  2862. handle_tile_action, META_TILE_TOP);
  2863. add_builtin_keybinding (display,
  2864. "push-snap-down",
  2865. SCHEMA_MUFFIN_KEYBINDINGS,
  2866. META_KEY_BINDING_PER_WINDOW,
  2867. META_KEYBINDING_ACTION_PUSH_SNAP_DOWN,
  2868. handle_tile_action, META_TILE_BOTTOM);
  2869. add_builtin_keybinding (display,
  2870. "toggle-above",
  2871. SCHEMA_MUFFIN_KEYBINDINGS,
  2872. META_KEY_BINDING_PER_WINDOW,
  2873. META_KEYBINDING_ACTION_TOGGLE_ABOVE,
  2874. handle_toggle_above, 0);
  2875. add_builtin_keybinding (display,
  2876. "maximize",
  2877. SCHEMA_MUFFIN_KEYBINDINGS,
  2878. META_KEY_BINDING_PER_WINDOW,
  2879. META_KEYBINDING_ACTION_MAXIMIZE,
  2880. handle_maximize, 0);
  2881. add_builtin_keybinding (display,
  2882. "unmaximize",
  2883. SCHEMA_MUFFIN_KEYBINDINGS,
  2884. META_KEY_BINDING_PER_WINDOW,
  2885. META_KEYBINDING_ACTION_UNMAXIMIZE,
  2886. handle_unmaximize, 0);
  2887. add_builtin_keybinding (display,
  2888. "toggle-shaded",
  2889. SCHEMA_MUFFIN_KEYBINDINGS,
  2890. META_KEY_BINDING_PER_WINDOW,
  2891. META_KEYBINDING_ACTION_TOGGLE_SHADED,
  2892. handle_toggle_shaded, 0);
  2893. add_builtin_keybinding (display,
  2894. "minimize",
  2895. SCHEMA_MUFFIN_KEYBINDINGS,
  2896. META_KEY_BINDING_PER_WINDOW,
  2897. META_KEYBINDING_ACTION_MINIMIZE,
  2898. handle_minimize, 0);
  2899. add_builtin_keybinding (display,
  2900. "close",
  2901. SCHEMA_MUFFIN_KEYBINDINGS,
  2902. META_KEY_BINDING_PER_WINDOW,
  2903. META_KEYBINDING_ACTION_CLOSE,
  2904. handle_close, 0);
  2905. add_builtin_keybinding (display,
  2906. "begin-move",
  2907. SCHEMA_MUFFIN_KEYBINDINGS,
  2908. META_KEY_BINDING_PER_WINDOW,
  2909. META_KEYBINDING_ACTION_BEGIN_MOVE,
  2910. handle_begin_move, 0);
  2911. add_builtin_keybinding (display,
  2912. "begin-resize",
  2913. SCHEMA_MUFFIN_KEYBINDINGS,
  2914. META_KEY_BINDING_PER_WINDOW,
  2915. META_KEYBINDING_ACTION_BEGIN_RESIZE,
  2916. handle_begin_resize, 0);
  2917. add_builtin_keybinding (display,
  2918. "toggle-on-all-workspaces",
  2919. SCHEMA_MUFFIN_KEYBINDINGS,
  2920. META_KEY_BINDING_PER_WINDOW,
  2921. META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES,
  2922. handle_toggle_on_all_workspaces, 0);
  2923. add_builtin_keybinding (display,
  2924. "move-to-workspace-1",
  2925. SCHEMA_MUFFIN_KEYBINDINGS,
  2926. META_KEY_BINDING_PER_WINDOW,
  2927. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1,
  2928. handle_move_to_workspace, 0);
  2929. add_builtin_keybinding (display,
  2930. "move-to-workspace-2",
  2931. SCHEMA_MUFFIN_KEYBINDINGS,
  2932. META_KEY_BINDING_PER_WINDOW,
  2933. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2,
  2934. handle_move_to_workspace, 1);
  2935. add_builtin_keybinding (display,
  2936. "move-to-workspace-3",
  2937. SCHEMA_MUFFIN_KEYBINDINGS,
  2938. META_KEY_BINDING_PER_WINDOW,
  2939. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3,
  2940. handle_move_to_workspace, 2);
  2941. add_builtin_keybinding (display,
  2942. "move-to-workspace-4",
  2943. SCHEMA_MUFFIN_KEYBINDINGS,
  2944. META_KEY_BINDING_PER_WINDOW,
  2945. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4,
  2946. handle_move_to_workspace, 3);
  2947. add_builtin_keybinding (display,
  2948. "move-to-workspace-5",
  2949. SCHEMA_MUFFIN_KEYBINDINGS,
  2950. META_KEY_BINDING_PER_WINDOW,
  2951. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5,
  2952. handle_move_to_workspace, 4);
  2953. add_builtin_keybinding (display,
  2954. "move-to-workspace-6",
  2955. SCHEMA_MUFFIN_KEYBINDINGS,
  2956. META_KEY_BINDING_PER_WINDOW,
  2957. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6,
  2958. handle_move_to_workspace, 5);
  2959. add_builtin_keybinding (display,
  2960. "move-to-workspace-7",
  2961. SCHEMA_MUFFIN_KEYBINDINGS,
  2962. META_KEY_BINDING_PER_WINDOW,
  2963. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7,
  2964. handle_move_to_workspace, 6);
  2965. add_builtin_keybinding (display,
  2966. "move-to-workspace-8",
  2967. SCHEMA_MUFFIN_KEYBINDINGS,
  2968. META_KEY_BINDING_PER_WINDOW,
  2969. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8,
  2970. handle_move_to_workspace, 7);
  2971. add_builtin_keybinding (display,
  2972. "move-to-workspace-9",
  2973. SCHEMA_MUFFIN_KEYBINDINGS,
  2974. META_KEY_BINDING_PER_WINDOW,
  2975. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9,
  2976. handle_move_to_workspace, 8);
  2977. add_builtin_keybinding (display,
  2978. "move-to-workspace-10",
  2979. SCHEMA_MUFFIN_KEYBINDINGS,
  2980. META_KEY_BINDING_PER_WINDOW,
  2981. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10,
  2982. handle_move_to_workspace, 9);
  2983. add_builtin_keybinding (display,
  2984. "move-to-workspace-11",
  2985. SCHEMA_MUFFIN_KEYBINDINGS,
  2986. META_KEY_BINDING_PER_WINDOW,
  2987. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11,
  2988. handle_move_to_workspace, 10);
  2989. add_builtin_keybinding (display,
  2990. "move-to-workspace-12",
  2991. SCHEMA_MUFFIN_KEYBINDINGS,
  2992. META_KEY_BINDING_PER_WINDOW,
  2993. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12,
  2994. handle_move_to_workspace, 11);
  2995. add_builtin_keybinding (display,
  2996. "move-to-workspace-left",
  2997. SCHEMA_MUFFIN_KEYBINDINGS,
  2998. META_KEY_BINDING_PER_WINDOW,
  2999. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT,
  3000. NULL, META_MOTION_LEFT);
  3001. add_builtin_keybinding (display,
  3002. "move-to-workspace-right",
  3003. SCHEMA_MUFFIN_KEYBINDINGS,
  3004. META_KEY_BINDING_PER_WINDOW,
  3005. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT,
  3006. NULL, META_MOTION_RIGHT);
  3007. add_builtin_keybinding (display,
  3008. "move-to-workspace-up",
  3009. SCHEMA_MUFFIN_KEYBINDINGS,
  3010. META_KEY_BINDING_PER_WINDOW,
  3011. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP,
  3012. handle_move_to_workspace, META_MOTION_UP);
  3013. add_builtin_keybinding (display,
  3014. "move-to-workspace-down",
  3015. SCHEMA_MUFFIN_KEYBINDINGS,
  3016. META_KEY_BINDING_PER_WINDOW,
  3017. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN,
  3018. handle_move_to_workspace, META_MOTION_DOWN);
  3019. add_builtin_keybinding (display,
  3020. "move-to-workspace-new",
  3021. SCHEMA_MUFFIN_KEYBINDINGS,
  3022. META_KEY_BINDING_PER_WINDOW,
  3023. META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_NEW,
  3024. handle_move_to_workspace, META_MOTION_NOT_EXIST_YET);
  3025. add_builtin_keybinding (display,
  3026. "move-to-monitor-left",
  3027. SCHEMA_MUFFIN_KEYBINDINGS,
  3028. META_KEY_BINDING_PER_WINDOW,
  3029. META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT,
  3030. handle_move_to_monitor, META_SCREEN_LEFT);
  3031. add_builtin_keybinding (display,
  3032. "move-to-monitor-right",
  3033. SCHEMA_MUFFIN_KEYBINDINGS,
  3034. META_KEY_BINDING_PER_WINDOW,
  3035. META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT,
  3036. handle_move_to_monitor, META_SCREEN_RIGHT);
  3037. add_builtin_keybinding (display,
  3038. "move-to-monitor-down",
  3039. SCHEMA_MUFFIN_KEYBINDINGS,
  3040. META_KEY_BINDING_PER_WINDOW,
  3041. META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN,
  3042. handle_move_to_monitor, META_SCREEN_DOWN);
  3043. add_builtin_keybinding (display,
  3044. "move-to-monitor-up",
  3045. SCHEMA_MUFFIN_KEYBINDINGS,
  3046. META_KEY_BINDING_PER_WINDOW,
  3047. META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP,
  3048. handle_move_to_monitor, META_SCREEN_UP);
  3049. add_builtin_keybinding (display,
  3050. "raise-or-lower",
  3051. SCHEMA_MUFFIN_KEYBINDINGS,
  3052. META_KEY_BINDING_PER_WINDOW,
  3053. META_KEYBINDING_ACTION_RAISE_OR_LOWER,
  3054. handle_raise_or_lower, 0);
  3055. add_builtin_keybinding (display,
  3056. "raise",
  3057. SCHEMA_MUFFIN_KEYBINDINGS,
  3058. META_KEY_BINDING_PER_WINDOW,
  3059. META_KEYBINDING_ACTION_RAISE,
  3060. handle_raise, 0);
  3061. add_builtin_keybinding (display,
  3062. "lower",
  3063. SCHEMA_MUFFIN_KEYBINDINGS,
  3064. META_KEY_BINDING_PER_WINDOW,
  3065. META_KEYBINDING_ACTION_LOWER,
  3066. handle_lower, 0);
  3067. add_builtin_keybinding (display,
  3068. "maximize-vertically",
  3069. SCHEMA_MUFFIN_KEYBINDINGS,
  3070. META_KEY_BINDING_PER_WINDOW,
  3071. META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY,
  3072. handle_maximize_vertically, 0);
  3073. add_builtin_keybinding (display,
  3074. "maximize-horizontally",
  3075. SCHEMA_MUFFIN_KEYBINDINGS,
  3076. META_KEY_BINDING_PER_WINDOW,
  3077. META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
  3078. handle_maximize_horizontally, 0);
  3079. add_builtin_keybinding (display,
  3080. "move-to-corner-nw",
  3081. SCHEMA_MUFFIN_KEYBINDINGS,
  3082. META_KEY_BINDING_PER_WINDOW,
  3083. META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW,
  3084. handle_move_to, META_MOVE_TO_NW);
  3085. add_builtin_keybinding (display,
  3086. "move-to-corner-ne",
  3087. SCHEMA_MUFFIN_KEYBINDINGS,
  3088. META_KEY_BINDING_PER_WINDOW,
  3089. META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE,
  3090. handle_move_to, META_MOVE_TO_NE);
  3091. add_builtin_keybinding (display,
  3092. "move-to-corner-sw",
  3093. SCHEMA_MUFFIN_KEYBINDINGS,
  3094. META_KEY_BINDING_PER_WINDOW,
  3095. META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW,
  3096. handle_move_to, META_MOVE_TO_SW);
  3097. add_builtin_keybinding (display,
  3098. "move-to-corner-se",
  3099. SCHEMA_MUFFIN_KEYBINDINGS,
  3100. META_KEY_BINDING_PER_WINDOW,
  3101. META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE,
  3102. handle_move_to, META_MOVE_TO_SE);
  3103. add_builtin_keybinding (display,
  3104. "move-to-side-n",
  3105. SCHEMA_MUFFIN_KEYBINDINGS,
  3106. META_KEY_BINDING_PER_WINDOW,
  3107. META_KEYBINDING_ACTION_MOVE_TO_SIDE_N,
  3108. handle_move_to, META_MOVE_TO_N);
  3109. add_builtin_keybinding (display,
  3110. "move-to-side-s",
  3111. SCHEMA_MUFFIN_KEYBINDINGS,
  3112. META_KEY_BINDING_PER_WINDOW,
  3113. META_KEYBINDING_ACTION_MOVE_TO_SIDE_S,
  3114. handle_move_to, META_MOVE_TO_S);
  3115. add_builtin_keybinding (display,
  3116. "move-to-side-e",
  3117. SCHEMA_MUFFIN_KEYBINDINGS,
  3118. META_KEY_BINDING_PER_WINDOW,
  3119. META_KEYBINDING_ACTION_MOVE_TO_SIDE_E,
  3120. handle_move_to, META_MOVE_TO_E);
  3121. add_builtin_keybinding (display,
  3122. "move-to-side-w",
  3123. SCHEMA_MUFFIN_KEYBINDINGS,
  3124. META_KEY_BINDING_PER_WINDOW,
  3125. META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
  3126. handle_move_to, META_MOVE_TO_W);
  3127. add_builtin_keybinding (display,
  3128. "move-to-center",
  3129. SCHEMA_MUFFIN_KEYBINDINGS,
  3130. META_KEY_BINDING_PER_WINDOW,
  3131. META_KEYBINDING_ACTION_MOVE_TO_CENTER,
  3132. handle_move_to_center, 0);
  3133. add_builtin_keybinding (display,
  3134. "increase-opacity",
  3135. SCHEMA_MUFFIN_KEYBINDINGS,
  3136. META_KEY_BINDING_PER_WINDOW,
  3137. META_KEYBINDING_ACTION_INCREASE_OPACITY,
  3138. handle_opacity, 0);
  3139. add_builtin_keybinding (display,
  3140. "decrease-opacity",
  3141. SCHEMA_MUFFIN_KEYBINDINGS,
  3142. META_KEY_BINDING_PER_WINDOW,
  3143. META_KEYBINDING_ACTION_DECREASE_OPACITY,
  3144. handle_opacity, 0);
  3145. }
  3146. LOCAL_SYMBOL void
  3147. meta_display_init_keys (MetaDisplay *display)
  3148. {
  3149. /* Keybindings */
  3150. display->keymap = NULL;
  3151. display->keysyms_per_keycode = 0;
  3152. display->modmap = NULL;
  3153. display->min_keycode = 0;
  3154. display->max_keycode = 0;
  3155. display->ignored_modifier_mask = 0;
  3156. display->num_lock_mask = 0;
  3157. display->scroll_lock_mask = 0;
  3158. display->hyper_mask = 0;
  3159. display->super_mask = 0;
  3160. display->meta_mask = 0;
  3161. display->key_bindings = NULL;
  3162. display->n_key_bindings = 0;
  3163. XDisplayKeycodes (display->xdisplay,
  3164. &display->min_keycode,
  3165. &display->max_keycode);
  3166. meta_topic (META_DEBUG_KEYBINDINGS,
  3167. "Display has keycode range %d to %d\n",
  3168. display->min_keycode,
  3169. display->max_keycode);
  3170. reload_keymap (display);
  3171. reload_modmap (display);
  3172. key_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
  3173. (GDestroyNotify) key_handler_free);
  3174. init_builtin_key_bindings (display);
  3175. rebuild_key_binding_table (display);
  3176. reload_keycodes (display);
  3177. reload_modifiers (display);
  3178. /* Keys are actually grabbed in meta_screen_grab_keys() */
  3179. meta_prefs_add_listener (bindings_changed_callback, display);
  3180. #ifdef HAVE_XKB
  3181. /* meta_display_init_keys() should have already called XkbQueryExtension() */
  3182. if (display->xkb_base_event_type != -1)
  3183. XkbSelectEvents (display->xdisplay, XkbUseCoreKbd,
  3184. XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
  3185. XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
  3186. #endif
  3187. }