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.
 
 
 
 

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