From c558b8530b426efa185257c455f696c789313694 Mon Sep 17 00:00:00 2001 From: John Ralls Date: Sun, 1 Jul 2018 14:46:55 -0700 Subject: [PATCH] Correct binary test logic for primary mask. state & get_primary_mask(another) tested (state & (primary | other)), which will be true if state matches *either* primary *or* other, but what is wanted in a not-negated test is state matching all bits of (primary | other). match_primary_mask does that. On the other hand there are also cases of "not state & (primary | other)". no_match_primary_mask handles that, returning true if state matches none of the bits in (primary | other). Fixes #10646. --- gramps/gui/clipboard.py | 8 ++++---- gramps/gui/editors/displaytabs/buttontab.py | 4 ++-- gramps/gui/editors/displaytabs/surnametab.py | 9 ++++----- gramps/gui/filters/_searchbar.py | 4 ++-- gramps/gui/filters/sidebar/_sidebarfilter.py | 4 ++-- gramps/gui/utils.py | 19 +++++++++++++++---- gramps/gui/views/navigationview.py | 4 ++-- gramps/gui/widgets/grampletpane.py | 7 +++---- gramps/gui/widgets/interactivesearchbox.py | 4 ++-- gramps/gui/widgets/multitreeview.py | 6 +++--- gramps/gui/widgets/styledtexteditor.py | 9 ++++----- 11 files changed, 43 insertions(+), 35 deletions(-) diff --git a/gramps/gui/clipboard.py b/gramps/gui/clipboard.py index a063bd3f6..28b706a3c 100644 --- a/gramps/gui/clipboard.py +++ b/gramps/gui/clipboard.py @@ -57,7 +57,7 @@ from .managedwindow import ManagedWindow from .glade import Glade from .ddtargets import DdTargets from .makefilter import make_filter -from .utils import is_right_click, get_primary_mask +from .utils import is_right_click, no_match_primary_mask from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.sgettext @@ -1572,9 +1572,9 @@ class MultiTreeView(Gtk.TreeView): # otherwise: if (target and event.type == Gdk.EventType.BUTTON_PRESS and - self.get_selection().path_is_selected(target[0]) and not - (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK))): + self.get_selection().path_is_selected(target[0]) and + no_match_primary_mask(event.get_state(), + Gdk.ModifierType.SHIFT_MASK)): # disable selection self.get_selection().set_select_function( lambda *ignore: False, None) diff --git a/gramps/gui/editors/displaytabs/buttontab.py b/gramps/gui/editors/displaytabs/buttontab.py index c8fd12b04..f590915e2 100644 --- a/gramps/gui/editors/displaytabs/buttontab.py +++ b/gramps/gui/editors/displaytabs/buttontab.py @@ -43,7 +43,7 @@ _ = glocale.translation.gettext from ...widgets import SimpleButton from .grampstab import GrampsTab from gramps.gen.errors import WindowActiveError -from ...utils import get_primary_mask +from ...utils import match_primary_mask _KP_ENTER = Gdk.keyval_from_name("KP_Enter") _RETURN = Gdk.keyval_from_name("Return") @@ -220,7 +220,7 @@ class ButtonTab(GrampsTab): return self.add_button_clicked(obj) elif event.keyval in (_OPEN,) and self.share_btn and \ - (event.get_state() & get_primary_mask()): + match_primary_mask(event.get_state()): self.share_button_clicked(obj) elif event.keyval in (_LEFT,) and \ (event.get_state() & Gdk.ModifierType.MOD1_MASK): diff --git a/gramps/gui/editors/displaytabs/surnametab.py b/gramps/gui/editors/displaytabs/surnametab.py index c3e19a474..1d4b079a9 100644 --- a/gramps/gui/editors/displaytabs/surnametab.py +++ b/gramps/gui/editors/displaytabs/surnametab.py @@ -48,7 +48,7 @@ from .surnamemodel import SurnameModel from .embeddedlist import EmbeddedList, TEXT_EDIT_COL from ...ddtargets import DdTargets from gramps.gen.lib import Surname, NameOriginType -from ...utils import get_primary_mask +from ...utils import match_primary_mask, no_match_primary_mask #------------------------------------------------------------------------- # @@ -345,11 +345,10 @@ class SurnameTab(EmbeddedList): """ if not EmbeddedList.key_pressed(self, obj, event): if event.type == Gdk.EventType.KEY_PRESS and event.keyval in (_TAB,): - if not (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK)): + if no_match_primary_mask(event.get_state(), + Gdk.ModifierType.SHIFT_MASK): return self.next_cell() - elif (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK)): + elif match_primary_mask(event.get_state(), Gdk.ModifierType.SHIFT_MASK): return self.prev_cell() else: return diff --git a/gramps/gui/filters/_searchbar.py b/gramps/gui/filters/_searchbar.py index f8aa9a722..ee407b475 100644 --- a/gramps/gui/filters/_searchbar.py +++ b/gramps/gui/filters/_searchbar.py @@ -32,7 +32,7 @@ from gi.repository import Gdk from gi.repository import Gtk from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.translation.gettext -from ..utils import get_primary_mask +from ..utils import no_match_primary_mask _RETURN = Gdk.keyval_from_name("Return") _KP_ENTER = Gdk.keyval_from_name("KP_Enter") @@ -139,7 +139,7 @@ class SearchBar: self.clear_button.set_sensitive(True) def key_press(self, obj, event): - if not (event.get_state() & get_primary_mask()): + if no_match_primary_mask(event.get_state()): if event.keyval in (_RETURN, _KP_ENTER): self.filter_button.set_sensitive(False) self.clear_button.set_sensitive(True) diff --git a/gramps/gui/filters/sidebar/_sidebarfilter.py b/gramps/gui/filters/sidebar/_sidebarfilter.py index b87f06c8f..ae44944a8 100644 --- a/gramps/gui/filters/sidebar/_sidebarfilter.py +++ b/gramps/gui/filters/sidebar/_sidebarfilter.py @@ -29,7 +29,7 @@ from gi.repository import Pango from ... import widgets from ...dbguielement import DbGUIElement from gramps.gen.config import config -from ...utils import get_primary_mask +from ...utils import no_match_primary_mask _RETURN = Gdk.keyval_from_name("Return") _KP_ENTER = Gdk.keyval_from_name("KP_Enter") @@ -130,7 +130,7 @@ class SidebarFilter(DbGUIElement): widget.set_tooltip_text(tooltip) def key_press(self, obj, event): - if not (event.get_state() & get_primary_mask()): + if no_match_primary_mask(event.get_state()): if event.keyval in (_RETURN, _KP_ENTER): self.clicked(obj) return False diff --git a/gramps/gui/utils.py b/gramps/gui/utils.py index 4a504a096..469cffa71 100644 --- a/gramps/gui/utils.py +++ b/gramps/gui/utils.py @@ -714,11 +714,22 @@ def text_to_clipboard(text): Gdk.SELECTION_CLIPBOARD) clipboard.set_text(text, -1) -def get_primary_mask(addl_mask=0): +def match_primary_mask(test_mask, addl_mask=0): """ - Obtain the IntentPrimary mask for the platform bitwise-ored with a - passed-in additional mask. + Return True if test_mask fully matches all bits of + GdkModifierIntent.PRIMARY_ACCELERATOR and addl_mask, False + otherwise. """ keymap = Gdk.Keymap.get_default() primary = keymap.get_modifier_mask(Gdk.ModifierIntent.PRIMARY_ACCELERATOR) - return primary | addl_mask + return ((test_mask & (primary | addl_mask)) == (primary | addl_mask)) + +def no_match_primary_mask(test_mask, addl_mask=0): + """ + Return False if test_mask matches any bit of + GdkModifierIntent.PRIMARY_ACCELERATOR or addl_mask, True + otherwise. + """ + keymap = Gdk.Keymap.get_default() + primary = keymap.get_modifier_mask(Gdk.ModifierIntent.PRIMARY_ACCELERATOR) + return (test_mask & (primary | addl_mask)) == 0 diff --git a/gramps/gui/views/navigationview.py b/gramps/gui/views/navigationview.py index ed96673b8..df4fd3e3b 100644 --- a/gramps/gui/views/navigationview.py +++ b/gramps/gui/views/navigationview.py @@ -52,7 +52,7 @@ from .pageview import PageView from ..actiongroup import ActionGroup from gramps.gen.utils.db import navigation_label from gramps.gen.constfunc import mod_key -from ..utils import get_primary_mask +from ..utils import match_primary_mask DISABLED = -1 MRU_SIZE = 10 @@ -481,7 +481,7 @@ class NavigationView(PageView): if self.active: if event.type == Gdk.EventType.KEY_PRESS: if (event.keyval == Gdk.KEY_c and - (event.get_state() & get_primary_mask())): + match_primary_mask(event.get_state())): self.call_copy() return True return super(NavigationView, self).key_press_handler(widget, event) diff --git a/gramps/gui/widgets/grampletpane.py b/gramps/gui/widgets/grampletpane.py index 65b7fb43f..bc09d987f 100644 --- a/gramps/gui/widgets/grampletpane.py +++ b/gramps/gui/widgets/grampletpane.py @@ -48,7 +48,7 @@ from gramps.gen.errors import WindowActiveError from gramps.gen.const import URL_MANUAL_PAGE, VERSION_DIR, COLON from ..editors import EditPerson, EditFamily from ..managedwindow import ManagedWindow -from ..utils import is_right_click, get_primary_mask, get_link_color +from ..utils import is_right_click, match_primary_mask, get_link_color from .menuitem import add_menuitem from ..plug import make_gui_option from ..plug.quick import run_quick_report_by_name @@ -400,12 +400,11 @@ class GuiGramplet: """ if ((Gdk.keyval_name(event.keyval) == 'Z') and - (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK))): + match_primary_mask(event.get_state(), Gdk.ModifierType.SHIFT_MASK)): self.redo() return True elif ((Gdk.keyval_name(event.keyval) == 'z') and - (event.get_state() & get_primary_mask())): + match_primary_mask(event.get_state())): self.undo() return True diff --git a/gramps/gui/widgets/interactivesearchbox.py b/gramps/gui/widgets/interactivesearchbox.py index 65ada415e..a3e3ab0d5 100644 --- a/gramps/gui/widgets/interactivesearchbox.py +++ b/gramps/gui/widgets/interactivesearchbox.py @@ -43,7 +43,7 @@ from gi.repository import Gtk, Gdk, GLib # Gramps modules # #------------------------------------------------------------------------- -from ..utils import get_primary_mask +from ..utils import match_primary_mask #------------------------------------------------------------------------- # # InteractiveSearchBox class @@ -106,7 +106,7 @@ class InteractiveSearchBox: self._search_entry.disconnect(popup_menu_id) # Intercept CTRL+F keybinding because Gtk do not allow to _replace_ it. - if ((event.state & get_primary_mask()) + if (match_primary_mask(event.state) and event.keyval in [Gdk.KEY_f, Gdk.KEY_F]): self.__imcontext_changed = True # self.real_start_interactive_search(event.get_device(), True) diff --git a/gramps/gui/widgets/multitreeview.py b/gramps/gui/widgets/multitreeview.py index 13e423802..52eccdec5 100644 --- a/gramps/gui/widgets/multitreeview.py +++ b/gramps/gui/widgets/multitreeview.py @@ -24,7 +24,7 @@ An override to allow easy multiselections. from gi.repository import Gdk from gi.repository import Gtk -from ..utils import get_primary_mask +from ..utils import no_match_primary_mask #------------------------------------------------------------------------- # @@ -66,8 +66,8 @@ class MultiTreeView(Gtk.TreeView): target = self.get_path_at_pos(int(event.x), int(event.y)) if (target and event.type == Gdk.EventType.BUTTON_PRESS - and not (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK)) + and no_match_primary_mask(event.get_state(), + Gdk.ModifierType.SHIFT_MASK) and self.get_selection().path_is_selected(target[0])): # disable selection self.get_selection().set_select_function(lambda *ignore: False, None) diff --git a/gramps/gui/widgets/styledtexteditor.py b/gramps/gui/widgets/styledtexteditor.py index 602d0f556..4b8460659 100644 --- a/gramps/gui/widgets/styledtexteditor.py +++ b/gramps/gui/widgets/styledtexteditor.py @@ -60,7 +60,7 @@ from .toolcomboentry import ToolComboEntry from .springseparator import SpringSeparatorAction from ..spell import Spell from ..display import display_url -from ..utils import SystemFonts, get_primary_mask, get_link_color +from ..utils import SystemFonts, match_primary_mask, get_link_color from gramps.gen.config import config from gramps.gen.constfunc import has_display, mac from ..actiongroup import ActionGroup @@ -243,12 +243,11 @@ class StyledTextEditor(Gtk.TextView): """ if ((Gdk.keyval_name(event.keyval) == 'Z') and - (event.get_state() & - get_primary_mask(Gdk.ModifierType.SHIFT_MASK))): + match_primary_mask(event.get_state(), Gdk.ModifierType.SHIFT_MASK)): self.redo() return True elif ((Gdk.keyval_name(event.keyval) == 'z') and - (event.get_state() & get_primary_mask())): + match_primary_mask(event.get_state())): self.undo() return True else: @@ -342,7 +341,7 @@ class StyledTextEditor(Gtk.TextView): self.selclick=False if ((event.type == Gdk.EventType.BUTTON_PRESS) and (event.button == 1) and (self.url_match) and - ((event.get_state() & get_primary_mask()) or + (match_primary_mask(event.get_state()) or not self.get_editable())): flavor = self.url_match[MATCH_FLAVOR]