xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #567: modifiers-ignore-v3.patch

File modifiers-ignore-v3.patch, 22.5 KB (added by Antoine Martin, 7 years ago)

updated patch against latest code

  • xpra/client/client_window_base.py

     
    308308        #see UIXpraClient.dbus_call
    309309        return self._client.dbus_call(self._id, *args, **kwargs)
    310310
     311
     312    def send_mouse_packet(self, *packet):
     313        if self._client.mouse_modignore:
     314            #add list of "modifiers to ignore" to packet:
     315            packet = list(packet) + [self._client.get_modifiers_ignore(keyboard_event=False)]
     316            mouselog("mouse packet, added modignore: %s", packet[-1])
     317        self._client.send_positional(packet)
     318
    311319    def do_motion_notify_event(self, event):
    312320        if self._client.readonly:
    313321            return
    314322        pointer, modifiers, buttons = self._pointer_modifiers(event)
    315323        mouselog("do_motion_notify_event(%s) wid=%s, pointer=%s, modifiers=%s, buttons=%s", event, self._id, pointer, modifiers, buttons)
    316         self._client.send_mouse_position(["pointer-position", self._id,
    317                                           pointer, modifiers, buttons])
     324        self.send_mouse_packet("pointer-position", self._id, pointer, modifiers, buttons)
    318325
    319326    def _button_action(self, button, event, depressed):
    320327        if self._client.readonly:
     
    322329        pointer, modifiers, buttons = self._pointer_modifiers(event)
    323330        mouselog("_button_action(%s, %s, %s) wid=%s, pointer=%s, modifiers=%s, buttons=%s", button, event, depressed, self._id, pointer, modifiers, buttons)
    324331        def send_button(pressed):
    325             self._client.send_positional(["button-action", self._id,
    326                                           button, pressed,
    327                                           pointer, modifiers, buttons])
     332            self.send_mouse_packet("button-action", self._id, button, pressed,
     333                                          pointer, modifiers, buttons)
    328334        pressed_state = self.button_state.get(button, False)
    329335        if pressed_state is False and depressed is False:
    330336            mouselog("button action: simulating a missing mouse-down event for window %s before sending the mouse-up event", self._id)
  • xpra/client/ui_client_base.py

     
    159159        self.opengl_props = {}
    160160        self.toggle_cursors_bell_notify = False
    161161        self.toggle_keyboard_sync = False
     162        self.mouse_modignore = False
    162163        self.force_ungrab = False
    163164        self.window_unmap = False
    164165        self.window_refresh_config = False
     
    702703            return []
    703704        return self.keyboard_helper.mask_to_names(mask)
    704705
     706    def get_modifiers_ignore(self, *args, **kwargs):
     707        if self.keyboard_helper and self.keyboard_helper.keyboard:
     708            return self.keyboard_helper.keyboard.get_modifiers_ignore(*args, **kwargs)
     709        return []
    705710
     711
    706712    def set_default_window_icon(self, window_icon):
    707713        if not window_icon:
    708714            window_icon = self.get_icon_filename("xpra.png")
     
    715721
    716722    def send_focus(self, wid):
    717723        focuslog("send_focus(%s)", wid)
    718         self.send("focus", wid, self.get_current_modifiers())
     724        packet = ["focus", wid, self.get_current_modifiers()]
     725        if self.mouse_modignore:
     726            #add list of "modifiers to ignore" to packet:
     727            packet.append(self.get_modifiers_ignore(keyboard_event=False))
     728        self.send(*packet)
    719729
    720730    def update_focus(self, wid, gotit):
    721731        focuslog("update_focus(%s, %s) focused=%s, grabbed=%s", wid, gotit, self._focused, self._window_with_grab)
     
    11861196        self.server_platform = c.strget("platform")
    11871197        self.toggle_cursors_bell_notify = c.boolget("toggle_cursors_bell_notify")
    11881198        self.toggle_keyboard_sync = c.boolget("toggle_keyboard_sync")
     1199        self.mouse_modignore = c.boolget("mouse_modignore")
    11891200
    11901201        self.server_display = c.strget("display")
    11911202        self.server_max_desktop_size = c.intpair("max_desktop_size")
  • xpra/client/window_backing_base.py

     
    461461
    462462    def draw_region(self, x, y, width, height, coding, img_data, rowstride, options, callbacks):
    463463        """ dispatches the paint to one of the paint_XXXX methods """
    464         log("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks)
     464        log.info("draw_region(%s, %s, %s, %s, %s, %s bytes, %s, %s, %s)", x, y, width, height, coding, len(img_data), rowstride, options, callbacks)
    465465        img_data = self.img_data_tobytes(img_data)
    466466        coding = bytestostr(coding)
    467467        if coding == "mmap":
  • xpra/platform/darwin/keyboard.py

     
    55# later version. See the file COPYING for details.
    66
    77
    8 import gtk.gdk
     8from xpra.gtk_common.gtk_util import META_MASK
    99from xpra.platform.keyboard_base import KeyboardBase, log
    1010from xpra.platform.darwin.osx_menu import getOSXMenuHelper
    1111
     
    4747                self.key_translations[orig_keysym] = new_def
    4848        log("set_modifier_mappings(..) swap keys translations=%s", self.key_translations)
    4949
     50    def get_modifiers_ignore(self, *args, **kwargs):
     51        #override here so we can tell the server to ignore
     52        #a missing "control" modifier when swap keys is on:
     53        #(that's because META_MASK is not set when Meta is pressed...)
     54        #but it is set from the keyboard events (go figure)
     55        if self.swap_keys and not kwargs.get("keyboard_event", False):
     56            return ["control"]
     57        return []
     58
    5059    def find_translation(self, orig_keysym):
    5160        new_def = None
    5261        #ie: keysyms : ["Meta_L", "Alt_L"]
     
    7685    def mask_to_names(self, mask):
    7786        names = KeyboardBase.mask_to_names(self, mask)
    7887        if self.swap_keys and self.meta_modifier is not None and self.control_modifier is not None:
    79             meta_on = bool(mask & gtk.gdk.META_MASK)
     88            meta_on = bool(mask & META_MASK)
    8089            meta_set = self.meta_modifier in names
    8190            control_set = self.control_modifier in names
    8291            log("mask_to_names names=%s, meta_on=%s, meta_set=%s, control_set=%s", names, meta_on, meta_set, control_set)
  • xpra/platform/darwin/shadow_server.py

     
    8181    def makeRootWindowModel(self):
    8282        return  OSXRootWindowModel(self.root)
    8383
    84     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     84    def _process_mouse_common(self, proto, wid, pointer, modifiers, modignore):
    8585        CG.CGWarpMouseCursorPosition(pointer)
    8686
    8787    def get_keycode(self, ss, client_keycode, keyname, modifiers):
  • xpra/platform/keyboard_base.py

     
    5050        """
    5151        return  {}, [], ["lock"]
    5252
     53    def get_modifiers_ignore(self, *args, **kwargs):
     54        return []
     55
    5356    def get_keymap_spec(self):
    5457        return "", ""
    5558
  • xpra/platform/win32/keyboard_config.py

     
    3333        log("get_keycode%s=%s", (client_keycode, keyname, modifiers), keycode)
    3434        return keycode
    3535
    36     def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None):
    37         log("make_keymask_match%s", (modifier_list, ignored_modifier_keycode, ignored_modifier_keynames))
     36    def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None, ignored_modifiers=None):
     37        log("make_keymask_match%s", (modifier_list, ignored_modifier_keycode, ignored_modifier_keynames, ignored_modifiers))
    3838        mods = self.get_modifiers_state()
    3939        log("modifiers_state=%s", mods)
    4040        log("GetKeyboardState=%s", [int(x!=0) for x in win32api.GetKeyboardState()])
  • xpra/platform/win32/shadow_server.py

     
    3737    def makeRootWindowModel(self):
    3838        return GTKRootWindowModel(self.root)
    3939
    40     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     40    def _process_mouse_common(self, proto, wid, pointer, modifiers, modignore):
    4141        #adjust pointer position for offset in client:
    4242        x, y = pointer
    4343        wx, wy = self.mapped_at[:2]
     
    6464
    6565    def _process_button_action(self, proto, packet):
    6666        wid, button, pressed, pointer, modifiers = packet[1:6]
    67         self._process_mouse_common(proto, wid, pointer, modifiers)
     67        modignore = []
     68        if len(packet)>=7:
     69            modignore = packet[6]
     70        self._process_mouse_common(proto, wid, pointer, modifiers, modignore)
    6871        self._server_sources.get(proto).user_event()
    6972        event = BUTTON_EVENTS.get((button, pressed))
    7073        if event is None:
  • xpra/server/gtk_server_base.py

     
    126126        display = gtk.gdk.display_get_default()
    127127        display.warp_pointer(display.get_default_screen(), x, y)
    128128
    129     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     129    def _process_mouse_common(self, *args):
    130130        pass
    131131
    132132    def _process_button_action(self, proto, packet):
  • xpra/server/keyboard_config_base.py

     
    4040    def set_default_keymap(self):
    4141        pass
    4242
    43     def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None):
     43    def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None, ignored_modifiers=None):
    4444        pass
    4545
    4646    def get_keycode(self, client_keycode, keyname, modifiers):
  • xpra/server/server_base.py

     
    10551055        pass
    10561056
    10571057
    1058     def _focus(self, server_source, wid, modifiers):
    1059         focuslog("_focus(%s,%s)", wid, modifiers)
     1058    def _focus(self, server_source, wid, modifiers, modignore=None):
     1059        focuslog("_focus(%s, %s, %s)", wid, modifiers, modignore)
    10601060
    10611061    def get_focus(self):
    10621062        #can be overriden by subclasses that do manage focus
     
    13141314    def _process_focus(self, proto, packet):
    13151315        wid = packet[1]
    13161316        focuslog("process_focus: wid=%s", wid)
     1317        modifiers, modignore = None, None
    13171318        if len(packet)>=3:
    13181319            modifiers = packet[2]
    1319         else:
    1320             modifiers = None
     1320        if len(packet)>=4:
     1321            modignore = packet[3]
    13211322        ss = self._server_sources.get(proto)
    13221323        if ss:
    1323             self._focus(ss, wid, modifiers)
     1324            self._focus(ss, wid, modifiers, modignore)
    13241325
    13251326    def _process_layout(self, proto, packet):
    13261327        layout, variant = packet[1:3]
     
    13421343        ss.make_keymask_match(modifiers)
    13431344
    13441345    def _process_key_action(self, proto, packet):
    1345         wid, keyname, pressed, modifiers, keyval, _, client_keycode = packet[1:8]
    13461346        ss = self._server_sources.get(proto)
    13471347        if ss is None:
    13481348            return
     1349        wid, keyname, pressed, modifiers, keyval, _, client_keycode = packet[1:8]
     1350        modignore = None
     1351        if len(packet)>=9:
     1352            modignore = packet[8]
    13491353        keycode = self.get_keycode(ss, client_keycode, keyname, modifiers)
    13501354        log("process_key_action(%s) server keycode=%s", packet, keycode)
    13511355        #currently unused: (group, is_modifier) = packet[8:10]
    13521356        self._focus(ss, wid, None)
    1353         ss.make_keymask_match(modifiers, keycode, ignored_modifier_keynames=[keyname])
     1357        ss.make_keymask_match(modifiers, keycode, ignored_modifier_keynames=[keyname], ignored_modifiers=modignore)
    13541358        #negative keycodes are used for key events without a real keypress/unpress
    13551359        #for example, used by win32 to send Caps_Lock/Num_Lock changes
    13561360        if keycode>0:
     
    13821386            del self.keys_timedout[keycode]
    13831387        def press():
    13841388            keylog("handle keycode pressing %s: key %s", keycode, name)
    1385             if self.keyboard_sync:
    1386                 self.keys_pressed[keycode] = name
     1389            self.keys_pressed[keycode] = name
    13871390            self.fake_key(keycode, True)
    13881391        def unpress():
    13891392            keylog("handle keycode unpressing %s: key %s", keycode, name)
    1390             if self.keyboard_sync:
     1393            if keycode in self.keys_pressed:
    13911394                del self.keys_pressed[keycode]
    13921395            self.fake_key(keycode, False)
    13931396        if pressed:
    13941397            if keycode not in self.keys_pressed:
    13951398                press()
    1396                 if not self.keyboard_sync:
     1399                if not self.keyboard_sync and not self.keyboard_config.is_modifier(keycode):
    13971400                    #keyboard is not synced: client manages repeat so unpress
    1398                     #it immediately
     1401                    #it immediately unless this is a modifier key
     1402                    #(as modifiers are synced via many packets: key, focus and mouse events)
    13991403                    unpress()
    14001404            else:
    14011405                keylog("handle keycode %s: key %s was already pressed, ignoring", keycode, name)
     
    14271431            self.keys_repeat_timers[keycode] = self.timeout_add(delay_ms, _key_repeat_timeout, now)
    14281432
    14291433    def _process_key_repeat(self, proto, packet):
    1430         wid, keyname, keyval, client_keycode, modifiers = packet[1:6]
    14311434        ss = self._server_sources.get(proto)
    14321435        if ss is None:
    14331436            return
     1437        wid, keyname, keyval, client_keycode, modifiers = packet[1:6]
     1438        modignore = None
     1439        if len(packet)>=9:
     1440            modignore = packet[8]
    14341441        keycode = ss.get_keycode(client_keycode, keyname, modifiers)
    14351442        #key repeat uses modifiers from a pointer event, so ignore mod_pointermissing:
    1436         ss.make_keymask_match(modifiers)
     1443        ss.make_keymask_match(modifiers, ignored_modifiers=modignore)
    14371444        if not self.keyboard_sync:
    14381445            #this check should be redundant: clients should not send key-repeat without
    14391446            #having keyboard_sync enabled
     
    14561463    def _move_pointer(self, wid, pos):
    14571464        raise NotImplementedError()
    14581465
    1459     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     1466    def _process_mouse_common(self, proto, wid, pointer, modifiers, modignore):
    14601467        pass
    14611468
    14621469    def _process_button_action(self, proto, packet):
     
    14641471
    14651472    def _process_pointer_position(self, proto, packet):
    14661473        wid, pointer, modifiers = packet[1:4]
    1467         self._process_mouse_common(proto, wid, pointer, modifiers)
     1474        modignore = []
     1475        if len(packet)>=5:
     1476            modignore = packet[4]
     1477        self._process_mouse_common(proto, wid, pointer, modifiers, modignore)
    14681478
    14691479
    14701480    def _process_damage_sequence(self, proto, packet):
  • xpra/server/source.py

     
    866866            self.keyboard_config.compute_modifier_keynames()
    867867        keylog("keys_changed() updated keyboard config=%s", self.keyboard_config)
    868868
    869     def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None):
     869    def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None, ignored_modifiers=None):
    870870        if self.keyboard_config and self.keyboard_config.enabled:
    871             self.keyboard_config.make_keymask_match(modifier_list, ignored_modifier_keycode, ignored_modifier_keynames)
     871            self.keyboard_config.make_keymask_match(modifier_list, ignored_modifier_keycode, ignored_modifier_keynames, ignored_modifiers)
    872872
    873873    def set_default_keymap(self):
    874874        keylog("set_default_keymap() keyboard_config=%s", self.keyboard_config)
  • xpra/x11/server.py

     
    530530
    531531
    532532
    533     def _focus(self, server_source, wid, modifiers):
     533    def _focus(self, server_source, wid, modifiers, modignore=None):
    534534        focuslog("focus wid=%s has_focus=%s", wid, self._has_focus)
    535535        if self._has_focus==wid:
    536536            #nothing to do!
     
    568568        gobject.idle_add(give_focus)
    569569        if server_source and modifiers is not None:
    570570            focuslog("focus: will set modified mask to %s", modifiers)
    571             server_source.make_keymask_match(modifiers)
     571            server_source.make_keymask_match(modifiers, ignored_modifiers=modignore)
    572572        self._has_focus = wid
    573573
    574574    def get_focus(self):
  • xpra/x11/server_keyboard_config.py

     
    275275        log("set_default_keymap: modifier_map=%s", self.modifier_map)
    276276
    277277
     278    def is_modifier(self, keycode):
     279        for mod, keys in self.keycodes_for_modifier_keynames.items():
     280            if keycode in keys:
     281                log("is_modifier(%s) found modifier: %s", keycode, mod)
     282                return True
     283        log("is_modifier(%s) not found", keycode)
     284        return False
     285
    278286    def get_keycode(self, client_keycode, keyname, modifiers):
    279287        if not self.enabled:
    280288            log("ignoring keycode since keyboard is turned off")
     
    298306        _, _, current_mask = gtk.gdk.get_default_root_window().get_pointer()
    299307        return mask_to_names(current_mask, self.modifier_map)
    300308
    301     def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None):
     309    def make_keymask_match(self, modifier_list, ignored_modifier_keycode=None, ignored_modifier_keynames=None, ignored_modifiers=None):
    302310        """
    303311            Given a list of modifiers that should be set, try to press the right keys
    304312            to make the server's modifier list match it.
     
    335343
    336344        current = set(self.get_current_mask())
    337345        wanted = set(modifier_list)
     346        if ignored_modifiers:
     347            current -= set(ignored_modifiers)
     348            wanted -= set(ignored_modifiers)
    338349        if current==wanted:
    339350            return
    340         log("make_keymask_match(%s) current mask: %s, wanted: %s, ignoring=%s/%s, keys_pressed=%s", modifier_list, current, wanted, ignored_modifier_keycode, ignored_modifier_keynames, self.keys_pressed)
     351        log("make_keymask_match(%s) current mask: %s, wanted: %s, ignoring=%s/%s/%s, keys_pressed=%s", modifier_list, current, wanted, ignored_modifier_keycode, ignored_modifier_keynames, ignored_modifiers, self.keys_pressed)
    341352
    342353        def change_mask(modifiers, press, info):
    343354            for modifier in modifiers:
  • xpra/x11/shadow_x11_server.py

     
    2323    def makeRootWindowModel(self):
    2424        return GTKRootWindowModel(self.root)
    2525
    26     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     26    def _process_mouse_common(self, proto, wid, pointer, modifiers, modignore):
    2727        #adjust pointer position for offset in client:
    2828        x, y = pointer
    2929        wx, wy = self.mapped_at[:2]
    3030        pointer = x-wx, y-wy
    31         X11ServerBase._process_mouse_common(self, proto, wid, pointer, modifiers)
     31        X11ServerBase._process_mouse_common(self, proto, wid, pointer, modifiers, modignore)
    3232
    3333    def make_hello(self):
    3434        capabilities = X11ServerBase.make_hello(self)
  • xpra/x11/x11_server_base.py

     
    145145
    146146    def make_hello(self):
    147147        capabilities = GTKServerBase.make_hello(self)
    148         capabilities["resize_screen"] = self.randr
    149         capabilities["force_ungrab"] = True
     148        capabilities.update({
     149                     "resize_screen"    : self.randr,
     150                     "force_ungrab"     : True,
     151                     "mouse_modignore"  : True})
    150152        return capabilities
    151153
    152154    def do_get_info(self, proto, server_sources, window_ids):
     
    467469        display = gtk.gdk.display_get_default()
    468470        display.warp_pointer(display.get_default_screen(), x, y)
    469471
    470     def _process_mouse_common(self, proto, wid, pointer, modifiers):
     472    def _process_mouse_common(self, proto, wid, pointer, modifiers, modignore):
    471473        ss = self._server_sources.get(proto)
    472474        if ss is None:
    473475            return
     
    475477        if pos==pointer:
    476478            return
    477479        trap.swallow_synced(self._move_pointer, wid, pointer)
    478         ss.make_keymask_match(modifiers)
     480        ss.make_keymask_match(modifiers, ignored_modifiers=modignore)
    479481
    480482    def _process_button_action(self, proto, packet):
    481483        ss = self._server_sources.get(proto)
     
    482484        if ss is None:
    483485            return
    484486        wid, button, pressed, pointer, modifiers = packet[1:6]
    485         self._process_mouse_common(proto, wid, pointer, modifiers)
     487        modignore = []
     488        if len(packet)>=7:
     489            modignore = packet[6]
     490        self._process_mouse_common(proto, wid, pointer, modifiers, modignore)
    486491        ss.user_event()
    487492        try:
    488493            trap.call_synced(X11Keyboard.xtest_fake_button, button, pressed)