xpra icon
Bug tracker and wiki

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


Ticket #139: pointer-grab-v2.patch

File pointer-grab-v2.patch, 11.0 KB (added by Antoine Martin, 7 years ago)

better patch, should prevent client grab lockups

  • xpra/client/gtk2/client.py

     
    235235        capabilities = GTKXpraClient.make_hello(self)
    236236        if xor_str is not None:
    237237            capabilities["encoding.supports_delta"] = [x for x in ("png", "rgb24", "rgb32") if x in self.get_core_encodings()]
     238        capabilities["pointer.grabs"] = True
    238239        return capabilities
    239240
     241    def init_packet_handlers(self):
     242        GTKXpraClient.init_packet_handlers(self)
     243        self._ui_packet_handlers["grab-window"] = self._process_grab_window
     244        self._ui_packet_handlers["ungrab-window"] = self._process_ungrab_window
     245
     246
    240247    def process_ui_capabilities(self, capabilities):
    241248        GTKXpraClient.process_ui_capabilities(self, capabilities)
    242249        if self.server_randr:
     
    358365                gdkwin.set_cursor(cursor)
    359366
    360367
     368    def _process_grab_window(self, packet):
     369        wid = packet[1]
     370        window = self._id_to_window.get(wid)
     371        if window:
     372            log("grabbing %s", window)
     373            mask = gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK  | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.ENTER_NOTIFY_MASK | gtk.gdk.LEAVE_NOTIFY_MASK
     374            gtk.gdk.pointer_grab(window.gdk_window(), owner_events=True, event_mask=mask)
     375
     376    def _process_ungrab_window(self, packet):
     377        wid = packet[1]
     378        window = self._id_to_window.get(wid)
     379        log("ungrabbing %s", window)
     380        gtk.gdk.pointer_ungrab()
     381
     382
    361383    def init_opengl(self, enable_opengl):
    362384        #enable_opengl can be True, False or None (auto-detect)
    363385        self.client_supports_opengl = False
  • xpra/server/server_base.py

     
    919919            for k,v in size_constraints.items():
    920920                info["size-constraints.%s" % k] = v
    921921        info.update({
     922             "has-grab"             : window.get_property("has-grab"),
    922923             "override-redirect"    : window.is_OR(),
    923924             "tray"                 : window.is_tray(),
    924925             "size"                 : window.get_dimensions(),
  • xpra/server/source.py

     
    259259        self.send_notifications = False
    260260        self.send_windows = True
    261261        self.window_raise = False
     262        self.pointer_grabs = False
    262263        self.randr_notify = False
    263264        self.named_cursors = False
    264265        self.clipboard_enabled = False
     
    468469        self.lz4 = c.boolget("lz4", False)
    469470        self.send_windows = c.boolget("windows", True)
    470471        self.window_raise = c.boolget("window.raise")
     472        self.pointer_grabs = c.boolget("pointer.grabs")
    471473        self.server_window_resize = c.boolget("server-window-resize")
    472474        self.send_cursors = self.send_windows and c.boolget("cursors")
    473475        self.send_bell = c.boolget("bell")
     
    10971099            return
    10981100        self.send(*packet)
    10991101
     1102
     1103    def grab_window(self, wid):
     1104        if self.pointer_grabs:
     1105            self.send("grab-window", wid)
     1106
     1107    def ungrab_window(self, wid):
     1108        if self.pointer_grabs:
     1109            self.send("ungrab-window", wid)
     1110
     1111
    11001112    def send_cursor(self, cursor_data, sizes):
    11011113        if not self.send_cursors or self.suspended:
    11021114            return
  • xpra/x11/gtk_x11/composite.py

     
    2929    XShmEnabled = True
    3030
    3131    __gsignals__ = {
    32         "contents-changed": one_arg_signal,
     32        "contents-changed"      : one_arg_signal,
    3333
    34         "xpra-damage-event": one_arg_signal,
    35         "xpra-unmap-event": one_arg_signal,
    36         "xpra-configure-event": one_arg_signal,
    37         "xpra-reparent-event": one_arg_signal,
     34        "xpra-damage-event"     : one_arg_signal,
     35        "xpra-unmap-event"      : one_arg_signal,
     36        "xpra-configure-event"  : one_arg_signal,
     37        "xpra-reparent-event"   : one_arg_signal,
     38
     39        #FIXME: we want to see these events to be able to manage grabs
     40        #but we only actually get them here because
     41        #the method "do_get_property_contents_handle" selects
     42        #all parent windows recursively and adds this instance
     43        #as an event receiver for all of them...
     44        #if the pixmap is invalidated, we may stop listening for events
     45        #which could lock up the client if we get a "grab" but not the "ungrab"...
     46        #so callers MUST also watch for unmap/configure/reparent events
     47        #and force ungrab if those events are received.
     48        "xpra-focus-in-event"   : one_arg_signal,
     49        "xpra-focus-out-event"  : one_arg_signal,
    3850        }
    3951
    4052    __gproperties__ = {
  • xpra/x11/gtk_x11/window.py

     
    5757MAX_ASPECT = 2**15-1
    5858USE_XSHM = os.environ.get("XPRA_XSHM", "1")=="1"
    5959
     60GRAB_CONSTANTS = {
     61                  constants["NotifyNormal"] : "NotifyNormal",
     62                  constants["NotifyGrab"]   : "NotifyGrab",
     63                  constants["NotifyUngrab"] : "NotifyUngrab"}
    6064
     65
    6166# Todo:
    6267#   client focus hints
    6368#   _NET_WM_SYNC_REQUEST
     
    228233                       "Does the window use transparency", "",
    229234                       False,
    230235                       gobject.PARAM_READABLE),
     236        "has-grab": (gobject.TYPE_BOOLEAN,
     237                       "Does the window own a grab", "",
     238                       False,
     239                       gobject.PARAM_READABLE),
    231240        "fullscreen": (gobject.TYPE_BOOLEAN,
    232241                       "Fullscreen-ness of window", "",
    233242                       False,
     
    260269        }
    261270    __gsignals__ = {
    262271        "client-contents-changed": one_arg_signal,
    263         "raised": one_arg_signal,
    264         "unmanaged": one_arg_signal,
     272        "raised"                : one_arg_signal,
     273        "unmanaged"             : one_arg_signal,
    265274
     275        "grab"                  : one_arg_signal,
     276        "ungrab"                : one_arg_signal,
     277
    266278# this signal must be defined in the subclasses to be seen by the event stuff:
    267279#        "xpra-configure-event": one_arg_signal,
    268280        }
     
    337349    def setup(self):
    338350        h = self._composite.connect("contents-changed", self._forward_contents_changed)
    339351        self._damage_forward_handle = h
     352        self._composite.connect("xpra-focus-in-event", self.focus_in_event)
     353        self._composite.connect("xpra-focus-out-event", self.focus_out_event)
     354        #we also need to watch out for these events to clear the grab
     355        #since these events cause the composite helper to stop listening for grabs!
     356        self._composite.connect("xpra-unmap-event", self.composite_unmap_event)
     357        self._composite.connect("xpra-configure-event", self.composite_configure_event)
     358        self._composite.connect("xpra-reparent-event", self.composite_reparent_event)
    340359
    341360    def prop_get(self, key, ptype, ignore_errors=False, raise_xerrors=False):
    342361        # Utility wrapper for prop_get on the client_window
     
    573592            log("do_xpra_client_message_event(%s)", event)
    574593        self._last_wm_state_serial = event.serial
    575594
     595    #bits to do with grabs:
     596    def focus_in_event(self, ch, event):
     597        log("focus_in_event(%s) mode=%s", event, GRAB_CONSTANTS.get(event.mode))
     598        self._focus_event(event)
    576599
     600    def focus_out_event(self, ch, event):
     601        log("focus_out_event(%s) mode=%s", event, GRAB_CONSTANTS.get(event.mode))
     602        self._focus_event(event)
     603   
     604    def _focus_event(self, event):
     605        if event.mode==constants["NotifyGrab"]:
     606            log("emitting grab on %s", self)
     607            self._internal_set_property("has-grab", True)
     608            self.emit("grab", event)
     609        if event.mode==constants["NotifyUngrab"]:
     610            log("emitting ungrab on %s", self)
     611            self._internal_set_property("has-grab", False)
     612            self.emit("ungrab", event)
    577613
     614    def composite_unmap_event(self, ch, event):
     615        self.force_ungrab(event)
     616
     617    def composite_configure_event(self, ch, event):
     618        self.force_ungrab(event)
     619
     620    def composite_reparent_event(self, ch, event):
     621        self.force_ungrab(event)
     622
     623    def force_ungrab(self, event):
     624        if self.get_property("has-grab"):
     625            self._internal_set_property("has-grab", False)
     626            self.emit("ungrab", event)
     627
     628
    578629gobject.type_register(BaseWindowModel)
    579630
    580631
     
    651702        BaseWindowModel._read_initial_properties(self)
    652703        self._internal_set_property("tray", True)
    653704
    654     def composite_configure_event(self, composite_window, event):
    655         BaseWindowModel.composite_configure_event(self, composite_window, event)
    656         log("SystemTrayWindowModel.composite_configure_event(%s, %s) client window geometry=%s", composite_window, event, self.client_window.get_geometry())
    657 
    658705    def move_resize(self, x, y, width, height):
    659706        #Used by clients to tell us where the tray is located on screen
    660707        log("SystemTrayWindowModel.move_resize(%s, %s, %s, %s)", x, y, width, height)
  • xpra/x11/server.py

     
    188188    def make_hello(self):
    189189        capabilities = X11ServerBase.make_hello(self)
    190190        capabilities["window.raise"] = True
     191        capabilities["pointer.grabs"] = True
    191192        return capabilities
    192193
    193194
     
    320321        window.managed_connect("client-contents-changed", self._contents_changed)
    321322        window.managed_connect("unmanaged", self._lost_window)
    322323        window.managed_connect("raised", self._raised_window)
     324        window.managed_connect("grab", self._window_grab)
     325        window.managed_connect("ungrab", self._window_ungrab)
    323326        return wid
    324327
    325328    _window_export_properties = ("title", "size-hints", "fullscreen", "maximized")
     
    523526        if window.is_OR() or self._desktop_manager.visible(window):
    524527            self._damage(window, event.x, event.y, event.width, event.height)
    525528
     529
     530    def _window_grab(self, window, event):
     531        log("window_grab(%s, %s)", window, event)
     532        wid = self._window_to_id[window]
     533        for ss in self._server_sources.values():
     534            ss.grab_window(wid)
     535
     536    def _window_ungrab(self, window, event):
     537        log("window_ungrab(%s, %s)", window, event)
     538        wid = self._window_to_id[window]
     539        for ss in self._server_sources.values():
     540            ss.ungrab_window(wid)
     541
     542
    526543    def _raised_window(self, window, event):
    527544        wid = self._window_to_id[window]
    528545        for ss in self._server_sources.values():