def send_button_click(widget, button, primary=False, shift=False, recursive=False): """See send_key_click_event""" state = Gdk.ModifierType(0) if primary: state |= get_primary_accel_mod() if shift: state |= Gdk.ModifierType.SHIFT_MASK assert isinstance(widget, Gtk.Widget) handled = _send_button_click_event(widget, button=button, state=state) if recursive: if isinstance(widget, Gtk.Container): for child in widget.get_children(): handled += send_button_click(child, button, primary, shift, recursive) return handled
def button_press_displayname(button, mods, shorten=False): """Converts a button number & modifier mask to a localized unicode string. """ button = int(button) mods = int(mods) if button <= 0: return None mods = Gdk.ModifierType(mods) modif_label = Gtk.accelerator_get_label(0, mods) modif_label = unicode(modif_label) separator = "" if modif_label: separator = u"+" mouse_button_label = _("Button") if shorten: # TRANSLATORS: abbreviated "Button <number>" for forms like "Alt+Btn1" mouse_button_label = _("Btn") return "{modifiers}{plus}{btn}{button_number}".format( modifiers=modif_label, plus=separator, btn=mouse_button_label, button_number=button, )
def maybe_handle_event(self, event): if event.type != Gdk.EventType.KEY_PRESS: return False filtered_state = Gdk.ModifierType( event.state & ~(Gdk.ModifierType.MOD2_MASK | Gdk.ModifierType.LOCK_MASK)) if filtered_state == 0 and event.keyval == Gdk.KEY_Escape: if status.Awake: self.manager.cancel_unlock_widget() return True if status.Awake: if (event.keyval in (Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab)): if event.keyval == Gdk.KEY_ISO_Left_Tab: self.manager.propagate_tab_event(True) else: self.manager.propagate_tab_event(False) return True elif event.keyval == Gdk.KEY_space and isinstance( self.manager.get_focused_widget(), Gtk.Button): self.manager.propagate_activation() return True if settings.get_allow_shortcuts(): for entry in self.shortcut_actions: res = entry.activate(event.keyval, event.hardware_keycode, filtered_state) if res == -1: continue else: self.client.handle_keybinding(res) return True return False
def on_got_key(self, widget, key, mods, cell_data): cell, path = cell_data new = Gtk.accelerator_name(key, Gdk.ModifierType(mods)) if new in ('BackSpace', 'Delete', 'Escape', ''): self.on_clean_clicked(cell, path) return True for mod in KeyModifier: if "%s_L" % mod in new: new = new.replace ("%s_L" % mod, "<%s>" % mod) if "%s_R" % mod in new: new = new.replace ("%s_R" % mod, "<%s>" % mod) widget.destroy() client = GConf.Client.get_default() column = cell.get_data("id") iter = self.model.get_iter_from_string(cell.get_data("path_string")) id = self.model.get_value(iter, self.COLUMN_ID) client.set_string("/apps/metacity/global_keybindings/run_command_%d" % id, new) self.model.set_value(iter, self.COLUMN_KEY, new)
def button_press_parse(name): """Converts button press names to a button number & modifier mask. Analogous to `Gtk.accelerator_parse()`. This function parses the strings created by `button_press_name()`, and returns a 2-tuple containing the button number and modifier mask corresponding to `name`. If the parse fails, both values will be 0 (zero). """ if name is None: return (0, 0) name = str(name) try: mods_s, button_s = name.split("Button", 1) if button_s == '': button = 0 else: button = int(button_s) except ValueError: button = 0 mods = Gdk.ModifierType(0) else: keyval_ignored, mods = Gtk.accelerator_parse(mods_s) return button, mods
def _onComboChanged(self, model, path, iter): ''' Callback for row changes. Copies the changed key combos over to gsettings. @param model: The model that emitted the signal. Should be this class instance. @type model: L{gtk.TreeModel} @param path: The path of the row that has changed. @type path: tuple @param iter: The iter of the row that has changed. @type iter: L{gtk.TreeIter} ''' if not model[iter][COL_COMPONENT] or not model[iter][COL_DESC]: return gspath = self._getComboGSettingsPath(model[iter][COL_COMPONENT], model[iter][COL_DESC]) gsettings = GSettings.new_with_path(HOTKEYS_GSCHEMA, gspath) combo_name = gtk.accelerator_name( model[iter][COL_KEYPRESS], gdk.ModifierType(model[iter][COL_MOD])) key = gsettings.get_string('hotkey-combo') if key != combo_name and key != '/': gsettings.set_string('hotkey-combo', combo_name)
def _edit_dialog_key_press_cb(self, dialog, event, editable): if event.type != Gdk.EventType.KEY_PRESS: return False if event.is_modifier: return False if self._USE_NORMAL_DIALOG_KEYS: if event.keyval == Gdk.KEY_Return: dialog.response(Gtk.ResponseType.OK) return True elif event.keyval == Gdk.KEY_Escape: dialog.response(Gtk.ResponseType.CANCEL) return True elif event.keyval == Gdk.KEY_BackSpace: dialog.response(Gtk.ResponseType.REJECT) return True # Stolen from GTK 2.24's gtk/gtkmenu.c (gtk_menu_key_press()) # Figure out what modifiers went into determining the key symbol keymap = Gdk.Keymap.get_default() bound, keyval, effective_group, level, consumed_modifiers = ( keymap.translate_keyboard_state( event.hardware_keycode, event.state, event.group, )) keyval = Gdk.keyval_to_lower(keyval) mods = Gdk.ModifierType(event.state & Gtk.accelerator_get_default_mod_mask() & ~consumed_modifiers) # If lowercasing affects the keysym, then we need to include # SHIFT in the modifiers. We re-upper case when we match against # the keyval, but display and save in caseless form. if keyval != event.keyval: mods |= Gdk.ModifierType.SHIFT_MASK accel_label = Gtk.accelerator_get_label(keyval, mods) # So we get (<Shift>j, Shift+J) but just (plus, +). As I # understand it. # This is rejecting some legit key combinations such as the # arrowkeys, so I had to remove it... # if not Gtk.accelerator_valid(keyval, mods) # return True clash_accel_path = None clash_action_label = None for path, kv, m, changed in self._get_accel_map_entries(): if (kv, m) == (keyval, mods): clash_accel_path = path clash_action_label = _udecode( self._action_labels.get( clash_accel_path, _(u"Unknown Action"), )) break if clash_accel_path == dialog.accel_path: # no change self._edit_dialog_set_standard_hint(dialog) label = str(accel_label) dialog.accel_label_widget.set_text(label) elif clash_accel_path: markup_tmpl = _(u"<b>{accel} is already in use for '{action}'. " u"The existing assignment will be replaced.</b>") markup = markup_tmpl.format( accel=lib.xml.escape(accel_label), action=lib.xml.escape(clash_action_label), ) self._edit_dialog_set_hint(dialog, markup) label = u"%s (replace)" % (accel_label, ) dialog.accel_label_widget.set_text(str(label)) else: self._edit_dialog_set_standard_hint(dialog) label = u"%s (changed)" % (accel_label, ) dialog.accel_label_widget.set_text(label) dialog.result_mods = mods dialog.result_keyval = keyval return True
def checkKeyboardEventData(self, keyboardEvent): """Processes the given keyboard event. Here is used to: * Fill event_string using the key.id * Set the is_text properly Arguments: - keyboardEvent: an instance of input_event.KeyboardEvent """ # On the AtkKeyEventStruct documentation you can find this # description: # guint keyval; # A guint representing a keysym value corresponding to those # used by GDK # # There are no Clutter way to get a gdk-like keyvalname. # Anyway, cally will fill event_string with the final # representation of a text char. # # In the same way, Clutter provides the keyval without the # modifiers, and GDK yes. We will try to apply it, at least # to compute keyval_name # # More information: # http://library.gnome.org/devel/atk/stable/AtkUtil.html # http://bugzilla.o-hand.com/show_bug.cgi?id=2072 # apply the modifiers to keyboardEvent.id # keyval = keyboardEvent.id try: keymap = Gdk.Keymap.get_default() if keymap: success, entries = keymap.get_entries_for_keyval(keyval) group = entries[0].group modifiers = Gdk.ModifierType(keyboardEvent.modifiers) success, keyval, egroup, level, consumed = \ keymap.translate_keyboard_state (keyboardEvent.hw_code, modifiers, group) except: msg = 'ERROR: Exception computing keyval with modifiers' debug.println(debug.LEVEL_INFO, msg, True) msg = 'CLUTTER: Checked keyboard event data: ' \ 'prev keyval=%d; post keyval=%d' % (keyboardEvent.id, keyval) debug.println(debug.LEVEL_INFO, msg, True) keyboardEvent.id = keyval # if cally doesn't provide a event_string we get that using # Gdk. I know that it will probably called again computing # keyval_name but to simplify code, and not start to add # guess-code here I will maintain that in this way # if (keyboardEvent.event_string == ""): msg = 'CLUTTER: Keyboard Event event_string is empty. Computing.' debug.println(debug.LEVEL_INFO, msg, True) try: keyboardEvent.event_string = Gdk.keyval_name(keyboardEvent.id) msg = 'CLUTTER: New event string: %s' % keyboardEvent.event_string debug.println(debug.LEVEL_INFO, msg, True) except: msg = 'ERROR: Exception obtaining keyval_name for id: %d' \ % keyboardEvent.id debug.println(debug.LEVEL_INFO, msg, True) # at-spi uses event_string to compute is_text, so if it is # NULL we should compute again with the proper # event_string # keyboardEvent.is_text = _computeIsText(keyboardEvent.event_string) return default.Script.checkKeyboardEventData(self, keyboardEvent)
def on_key_release(self, widget, event): self.ungrab() self.teaching = False event = self.press_event display = widget.get_display() keyval = 0 group = event.group accel_mods = event.state # HACK: we don't want to use SysRq as a keybinding (but we do # want Alt+Print), so we avoid translation from Alt+Print to SysRq if event.keyval == Gdk.KEY_Sys_Req and \ ((accel_mods & Gdk.ModifierType.MOD1_MASK) != 0): keyval = Gdk.KEY_Print consumed_modifiers = 0 else: keymap = Gdk.Keymap.get_for_display(display) group_mask_disabled = False shift_group_mask = 0 shift_group_mask = keymap.get_modifier_mask( Gdk.ModifierIntent.SHIFT_GROUP) retval, keyval, effective_group, level, consumed_modifiers = \ keymap.translate_keyboard_state(event.hardware_keycode, accel_mods, group) if group_mask_disabled: effective_group = 1 if consumed_modifiers: consumed_modifiers &= ~shift_group_mask accel_key = Gdk.keyval_to_lower(keyval) if accel_key == Gdk.KEY_ISO_Left_Tab: accel_key = Gdk.KEY_Tab accel_mods &= Gtk.accelerator_get_default_mod_mask() if accel_mods == 0: if accel_key == Gdk.KEY_Escape: self.update_label() self.teaching = False self.path = None self.press_event = None return True elif accel_key == Gdk.KEY_BackSpace: self.teaching = False self.press_event = None self.set_value(None) self.emit("accel-cleared", self.path) self.path = None return True accel_string = Gtk.accelerator_name_with_keycode( None, accel_key, event.hardware_keycode, Gdk.ModifierType(accel_mods)) accel_label = Gtk.accelerator_get_label_with_keycode( None, accel_key, event.hardware_keycode, Gdk.ModifierType(accel_mods)) # print("Storing %s as %s" % (accel_label, accel_string)) if (accel_mods == 0 or accel_mods == Gdk.ModifierType.SHIFT_MASK ) and event.hardware_keycode != 0: if ((keyval >= Gdk.KEY_a and keyval <= Gdk.KEY_z) or (keyval >= Gdk.KEY_A and keyval <= Gdk.KEY_Z) or (keyval >= Gdk.KEY_0 and keyval <= Gdk.KEY_9) or (keyval >= Gdk.KEY_kana_fullstop and keyval <= Gdk.KEY_semivoicedsound) or (keyval >= Gdk.KEY_Arabic_comma and keyval <= Gdk.KEY_Arabic_sukun) or (keyval >= Gdk.KEY_Serbian_dje and keyval <= Gdk.KEY_Cyrillic_HARDSIGN) or (keyval >= Gdk.KEY_Greek_ALPHAaccent and keyval <= Gdk.KEY_Greek_omega) or (keyval >= Gdk.KEY_hebrew_doublelowline and keyval <= Gdk.KEY_hebrew_taf) or (keyval >= Gdk.KEY_Thai_kokai and keyval <= Gdk.KEY_Thai_lekkao) or (keyval >= Gdk.KEY_Hangul and keyval <= Gdk.KEY_Hangul_Special) or (keyval >= Gdk.KEY_Hangul_Kiyeog and keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) or keyval in FORBIDDEN_KEYVALS): dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, None) dialog.set_default_size(400, 200) msg = _( "\nThis key combination, \'<b>%s</b>\' cannot be used because it would become impossible to type using this key.\n\n" ) msg += _( "Please try again with a modifier key such as Control, Alt or Super (Windows key) at the same time.\n" ) dialog.set_markup(msg % (accel_label)) dialog.show_all() response = dialog.run() dialog.destroy() return True self.press_event = None self.set_value(accel_string) self.emit("accel-edited", self.path, accel_string, accel_label) self.path = None return True
@pytest.mark.parametrize( "accel_params,expected", [ # 1) 'edit_tab_title' Ctrl+Alt+A ( ("9", 97, CONTROL_ALT_MOD, 38), False, ), # 2) 'edit_terminal_title' Ctrl+Alt+A ( ("10", 97, CONTROL_ALT_MOD, 38), True, ), # 3) 'edit_window_title' F11 ( ("11", 65480, Gdk.ModifierType(0), 95), True, ), # 4) 'zoom_in' Shift+Ctrl+Z ( ("70", 122, CONTROL_SHIFT_MOD, 52), True, ), # 5) 'close_terminal' Ctrl+Alt+{ ( ("3", 123, CONTROL_ALT_SHIFT_MOD, 34), False, ), # 6) 'zoom_in' Shift+Ctrl+B ( ("70", 98, CONTROL_SHIFT_MOD, 56),
def click_in_tree(view, path=None, column=0, button=1, events=pygps.single_click_events, process_events=True, control=False, alt=False, shift=False, modifier=None, through_gps=True): """Simulate a click in the TreeView on the given path and column. This event is sent asynchronously, and you should check its result in an idle callback, or call process_all_events() immediately after the call to click_in_tree. If path is none, the event is sent to the first selected row. modifier is a Gdk.ModifierType, overriding control, alt or shift. If you are using the third button to display a contextual menu, see also activate_contextual() To send a double-click, emit an event with type=Gdk._2BUTTON_PRESS """ if not view.get_realized(): GPS.Logger("TESTSUITE").log("click_in_tree: view is not realized") return if (os.name == 'nt' and button == 3 and events == pygps.single_click_events): # ??? work around # On Windows sending a BUTTON_PRESS followed by a # BUTTON_RELEASE event when opening a contextual menu does # not work. The BUTTON_RELEASE close the contextual menu. # For now we remove this event. events = events[:1] if not path: path = view.get_selection().get_selected_rows()[1][0] rect = view.get_cell_area(path, view.get_column(column)) x = float(rect.x + rect.width / 2) y = float(rect.y + rect.height / 2) if modifier is not None: state = modifier else: state = Gdk.ModifierType(0) if control: if sys.platform == 'darwin': # on Mac, we need to also pass the Command key state |= Gdk.ModifierType.MOD2_MASK else: state |= Gdk.ModifierType.CONTROL_MASK if shift: state |= Gdk.ModifierType.SHIFT_MASK if alt: state |= Gdk.ModifierType.MOD1_MASK # TreeView doesn't handle single click well without # getting "enter-notify-event" first if through_gps: GPS.send_crossing_event(type=Gdk.EventType.ENTER_NOTIFY, window=view.get_bin_window(), x=int(x), y=int(y), state=0) else: event = Gdk.EventCrossing() event.type = Gdk.EventType.ENTER_NOTIFY event.window = view.get_bin_window() event.device = pygps.default_event_device() event.x = x event.y = y event.state = 0 event.put() for t in events: if through_gps: GPS.send_button_event(button=button, x=int(x), y=int(y), window=view.get_bin_window(), state=state, type=t) else: # event = Gdk.Event.new(t) event = Gdk.EventButton() event.type = t event.window = view.get_bin_window() event.device = pygps.default_event_device() event.button = button event.x = x event.y = y event.state = state event.put() if process_events: pygps.process_all_events()
def on_key_release(self, widget, event): """On key release callback. Parameters ---------- widget : Gtk.CellEditable The ``Gtk.CellEditable`` for the widget. event : Gdk.EventKey The ``Gdk.EventKey`` which triggered this signal. Returns ------- bool Whether to propagate the event or not. """ if self.press_event is not None: self.ungrab() self.teaching = False event = self.press_event or event display = widget.get_display() keyval = 0 group = event.group accel_mods = event.state # HACK: we don't want to use SysRq as a keybinding (but we do # want Alt+Print), so we avoid translation from Alt+Print to SysRq if event.keyval == Gdk.KEY_Sys_Req and \ ((accel_mods & Gdk.ModifierType.MOD1_MASK) != 0): keyval = Gdk.KEY_Print consumed_modifiers = 0 else: keymap = Gdk.Keymap.get_for_display(display) shift_group_mask = 0 shift_group_mask = keymap.get_modifier_mask(Gdk.ModifierIntent.SHIFT_GROUP) retval, keyval, effective_group, level, consumed_modifiers = \ keymap.translate_keyboard_state(event.hardware_keycode, accel_mods, group) if consumed_modifiers: consumed_modifiers &= ~shift_group_mask accel_key = Gdk.keyval_to_lower(keyval) if accel_key == Gdk.KEY_ISO_Left_Tab: accel_key = Gdk.KEY_Tab accel_mods &= Gtk.accelerator_get_default_mod_mask() if accel_mods == 0: if accel_key == Gdk.KEY_Escape: self.update_label() self.teaching = False self.path = None self.press_event = None return Gdk.EVENT_STOP elif accel_key == Gdk.KEY_BackSpace: self.teaching = False self.press_event = None self.set_value(None) self.emit("accel-cleared", self.path) self.path = None return Gdk.EVENT_STOP elif accel_key == Gdk.KEY_Return or accel_key == Gdk.KEY_KP_Enter or accel_key == Gdk.KEY_space: return Gdk.EVENT_STOP accel_string = Gtk.accelerator_name_with_keycode( None, accel_key, event.hardware_keycode, Gdk.ModifierType(accel_mods)) accel_label = Gtk.accelerator_get_label_with_keycode( None, accel_key, event.hardware_keycode, Gdk.ModifierType(accel_mods)) # print("accel_mods: %d, keyval: %d, Storing %s as %s" % (accel_mods, keyval, accel_label, accel_string)) if (accel_mods == 0 or accel_mods == Gdk.ModifierType.SHIFT_MASK) and event.hardware_keycode != 0: if ((keyval >= Gdk.KEY_a and keyval <= Gdk.KEY_z) or (keyval >= Gdk.KEY_A and keyval <= Gdk.KEY_Z) or (keyval >= Gdk.KEY_0 and keyval <= Gdk.KEY_9) or (keyval >= Gdk.KEY_kana_fullstop and keyval <= Gdk.KEY_semivoicedsound) or (keyval >= Gdk.KEY_Arabic_comma and keyval <= Gdk.KEY_Arabic_sukun) or (keyval >= Gdk.KEY_Serbian_dje and keyval <= Gdk.KEY_Cyrillic_HARDSIGN) or (keyval >= Gdk.KEY_Greek_ALPHAaccent and keyval <= Gdk.KEY_Greek_omega) or (keyval >= Gdk.KEY_hebrew_doublelowline and keyval <= Gdk.KEY_hebrew_taf) or (keyval >= Gdk.KEY_Thai_kokai and keyval <= Gdk.KEY_Thai_lekkao) or (keyval >= Gdk.KEY_Hangul and keyval <= Gdk.KEY_Hangul_Special) or (keyval >= Gdk.KEY_Hangul_Kiyeog and keyval <= Gdk.KEY_Hangul_J_YeorinHieuh) or keyval in FORBIDDEN_KEYVALS): msg = _( "\nThis key combination, \'<b>%s</b>\' cannot be used because it would become impossible to type using this key.\n\n") msg += _("Please try again with a modifier key such as Control, Alt or Super (Windows key) at the same time.\n") display_message_dialog(self.a_widget, "", msg, "error") return Gdk.EVENT_STOP self.press_event = None self.set_value(accel_string) self.emit("accel-edited", self.path, accel_string, accel_label) self.path = None return Gdk.EVENT_STOP