Example #1
0
 def do_selection_request_event(self, event):
     log("do_selection_request_event(%s)", event)
     self._selection_request_events += 1
     if not self._enabled or not self._can_receive:
         gtk.Invisible.do_selection_request_event(self, event)
         return
     # Black magic: the superclass default handler for this signal
     # implements all the hards parts of selection handling, occasionally
     # calling back to the do_selection_get handler (below) to actually get
     # the data to be sent.  However, it only does this for targets that
     # have been registered ahead of time; other targets fall through to a
     # default implementation that cannot be overridden.  So, we swoop in
     # ahead of time and add whatever target was requested to the list of
     # targets we want to handle!
     #
     # Special cases (magic targets defined by ICCCM):
     #   TIMESTAMP: the remote side has a different timeline than us, so
     #     sending TIMESTAMPS across the wire doesn't make any sense. We
     #     ignore TIMESTAMP requests, and let them fall through to GTK+'s
     #     default handler.
     #   TARGET: GTK+ has default handling for this, but we don't want to
     #     use it. Fortunately, if we tell GTK+ that we can handle TARGET
     #     requests, then it will pass them on to us rather than fall
     #     through to the default handler.
     #   MULTIPLE: Ugh. To handle this properly, we need to go out
     #     ourselves and fetch the magic property off the requesting window
     #     (with proper error trapping and all), and interpret its
     #     contents. Probably doable (FIXME), just a pain.
     #
     # Another special case is that if an app requests the contents of a
     # clipboard that it currently owns, then GTK+ will short-circuit the
     # normal logic and request the contents directly (i.e. it calls
     # gtk_selection_invoke_handler) -- without giving us a chance to
     # assert that we can handle the requested sort of target. Fortunately,
     # Xpra never needs to request the clipboard when it owns it, so that's
     # okay.
     assert str(event.selection) == self._selection, "selection does not match: expected %s but got %s" % (event.selection, self._selection)
     target = str(event.target)
     if target == "TIMESTAMP":
         pass
     elif target == "MULTIPLE":
         if not self.prop_get:
             log("MULTIPLE for property '%s' not handled due to missing xpra.x11.gtk_x11 bindings", event.property)
             gtk.Invisible.do_selection_request_event(self, event)
             return
         atoms = self.prop_get(event.window, event.property, ["multiple-conversion"])
         log("MULTIPLE clipboard atoms: %r", atoms)
         if atoms:
             targets = atoms[::2]
             for t in targets:
                 selection_add_target(self, self._selection, t, 0)
     else:
         log("target for %s: %r", self._selection, target)
         selection_add_target(self, self._selection, target, 0)
     log("do_selection_request_event(%s) target=%s, selection=%s", event, target, self._selection)
     gtk.Invisible.do_selection_request_event(self, event)
Example #2
0
 def got_token(self,
               targets,
               target_data,
               claim=True,
               synchronous_client=False):
     # We got the anti-token.
     self.cancel_emit_token()
     if not self._enabled:
         return
     self._got_token_events += 1
     log(
         "got token, selection=%s, targets=%s, target data=%s, claim=%s, can-receive=%s",
         self._selection, targets, target_data, claim, self._can_receive)
     if self._greedy_client or CLIPBOARD_GREEDY:
         self._block_owner_change = True
         #re-enable the flag via idle_add so events like do_owner_changed
         #get a chance to run first.
         glib.idle_add(self.remove_block)
     if (CLIPBOARD_GREEDY or synchronous_client) and self._can_receive:
         if targets:
             for target in targets:
                 selection_add_target(self, self._selection, target, 0)
             selection_owner_set(self, self._selection)
         if target_data:
             for text_target in TEXT_TARGETS:
                 if text_target in target_data:
                     text_data = target_data.get(text_target)
                     log("clipboard %s set to '%s'", self._selection,
                         repr_ellipsized(text_data))
                     set_clipboard_data(self._clipboard, text_data,
                                        text_target)
     if not claim:
         log("token packet without claim, not setting the token flag")
         #the other end is just telling us to send the token again next time something changes,
         #not that they want to own the clipboard selection
         return
     self._have_token = True
     if self._can_receive:
         if not self._block_owner_change:
             #if we don't claim the selection (can-receive=False),
             #we will have to send the token back on owner-change!
             self._block_owner_change = True
             glib.idle_add(self.remove_block)
         self.claim()