1#!/usr/local/bin/python3.8 2 3import gi 4gi.require_version('CDesktopEnums', '3.0') 5from gi.repository import Gtk, GObject, Gdk, Gio, CinnamonDesktop 6from gi.repository.CDesktopEnums import MediaKeyType as MK 7 8import status 9import singletons 10from util import settings 11 12ALLOWED_ACTIONS = [MK.MUTE, 13 MK.VOLUME_UP, 14 MK.VOLUME_UP_QUIET, 15 MK.VOLUME_DOWN, 16 MK.VOLUME_DOWN_QUIET, 17 MK.MIC_MUTE, 18 MK.EJECT, 19 MK.PLAY, 20 MK.PAUSE, 21 MK.STOP, 22 MK.PREVIOUS, 23 MK.NEXT, 24 MK.REWIND, 25 MK.FORWARD, 26 MK.REPEAT, 27 MK.RANDOM, 28 MK.TOUCHPAD, 29 MK.TOUCHPAD_ON, 30 MK.TOUCHPAD_OFF, 31 MK.SHUTDOWN, 32 MK.SUSPEND, 33 MK.HIBERNATE, 34 MK.SCREEN_BRIGHTNESS_UP, 35 MK.SCREEN_BRIGHTNESS_DOWN, 36 MK.ROTATE_VIDEO, 37 MK.KEYBOARD_BRIGHTNESS_UP, 38 MK.KEYBOARD_BRIGHTNESS_DOWN, 39 MK.KEYBOARD_BRIGHTNESS_TOGGLE] 40 41class ShortcutAction(GObject.GObject): 42 """ 43 A class representing a group of keybindings for a specific 44 media key action. 45 """ 46 def __init__(self, action, bindings): 47 super(ShortcutAction, self).__init__() 48 49 self.action = action 50 self.bindings = bindings 51 52 self.parsed = [] 53 54 for binding in self.bindings: 55 key, codes, mods = Gtk.accelerator_parse_with_keycode(binding) 56 57 self.parsed.append((key, codes, mods)) 58 59 def activate(self, key, keycode, mods): 60 for binding in self.parsed: 61 if (key == binding[0] or keycode in binding[1]) and mods == binding[2]: 62 return self.action 63 64 return -1 65 66class KeyBindings(GObject.GObject): 67 """ 68 Receives keystrokes from the EventHandler - it checks for media key 69 activation, as well as special keys like Escape or Tab, and performs the 70 appropriate actions. 71 """ 72 def __init__(self, manager): 73 super(KeyBindings, self).__init__() 74 75 self.manager = manager 76 77 self.client = singletons.KeybindingHandlerClient 78 79 self.keymap = Gdk.Keymap.get_default() 80 81 self.media_key_settings = Gio.Settings(schema_id="org.cinnamon.desktop.keybindings.media-keys") 82 self.shortcut_actions = [] 83 84 self.load_bindings() 85 86 def load_bindings(self): 87 self.shortcut_actions = [] 88 89 for action_id in ALLOWED_ACTIONS: 90 bindings = self.media_key_settings.get_strv(CinnamonDesktop.desktop_get_media_key_string(action_id)) 91 92 action = ShortcutAction(action_id, bindings) 93 94 self.shortcut_actions.append(action) 95 96 def maybe_handle_event(self, event): 97 if event.type != Gdk.EventType.KEY_PRESS: 98 return False 99 100 filtered_state = Gdk.ModifierType(event.state & ~(Gdk.ModifierType.MOD2_MASK | Gdk.ModifierType.LOCK_MASK)) 101 102 if filtered_state == 0 and event.keyval == Gdk.KEY_Escape: 103 if status.Awake: 104 self.manager.cancel_unlock_widget() 105 return True 106 107 if event.keyval == Gdk.KEY_Menu: 108 return True 109 110 if status.Awake: 111 if (event.keyval in (Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab)): 112 if event.keyval == Gdk.KEY_ISO_Left_Tab: 113 self.manager.propagate_tab_event(True) 114 else: 115 self.manager.propagate_tab_event(False) 116 return True 117 elif event.keyval == Gdk.KEY_space and isinstance(self.manager.get_focused_widget(), Gtk.Button): 118 self.manager.propagate_activation() 119 return True 120 121 if settings.get_allow_shortcuts(): 122 for entry in self.shortcut_actions: 123 res = entry.activate(event.keyval, event.hardware_keycode, filtered_state) 124 125 if res == -1: 126 continue 127 else: 128 self.client.handle_keybinding(res) 129 return True 130 131 return False 132