/usr/share/pyshared/wimpiggy/selection.py is in python-wimpiggy 0.0.7.36+dfsg-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | # This file is part of Parti.
# Copyright (C) 2008, 2009 Nathaniel Smith <njs@pobox.com>
# Parti is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.
# According to ICCCM 2.8/4.3, a window manager for screen N is a client which
# acquires the selection WM_S<N>. If another client already has this
# selection, we can either abort or steal it. Once we have it, if someone
# else steals it, then we should exit.
import gobject
import gtk
from struct import pack, unpack
from wimpiggy.util import no_arg_signal, one_arg_signal
from wimpiggy.error import XError
from wimpiggy.lowlevel import (
get_xatom, #@UnresolvedImport
get_pywindow, #@UnresolvedImport
sendClientMessage, #@UnresolvedImport
myGetSelectionOwner, const, #@UnresolvedImport
add_event_receiver, #@UnresolvedImport
remove_event_receiver #@UnresolvedImport
)
from wimpiggy.error import trap
from wimpiggy.log import Logger
log = Logger()
class AlreadyOwned(Exception):
pass
class ManagerSelection(gobject.GObject):
__gsignals__ = {
"selection-lost": no_arg_signal,
"wimpiggy-destroy-event": one_arg_signal,
}
def __init__(self, display, selection):
gobject.GObject.__init__(self)
self.atom = selection
self.clipboard = gtk.Clipboard(display, selection)
self._xwindow = None
def _owner(self):
return myGetSelectionOwner(self.clipboard, self.atom)
def owned(self):
"Returns True if someone owns the given selection."
return self._owner() != const["XNone"]
# If the selection is already owned, then raise AlreadyOwned rather
# than stealing it.
IF_UNOWNED = "if_unowned"
# If the selection is already owned, then steal it, and then block until
# the previous owner has signaled that they are done cleaning up.
FORCE = "force"
# If the selection is already owned, then steal it and return immediately.
# Created for the use of tests.
FORCE_AND_RETURN = "force_and_return"
def acquire(self, when):
old_owner = self._owner()
if when is self.IF_UNOWNED and old_owner != const["XNone"]:
raise AlreadyOwned
self.clipboard.set_with_data([("VERSION", 0, 0)],
self._get,
self._clear,
None)
# Having acquired the selection, we have to announce our existence
# (ICCCM 2.8, still). The details here probably don't matter too
# much; I've never heard of an app that cares about these messages,
# and metacity actually gets the format wrong in several ways (no
# MANAGER or owner_window atoms). But might as well get it as right
# as possible.
# To announce our existence, we need:
# -- the timestamp we arrived at
# -- the manager selection atom
# -- the window that registered the selection
# Of course, because Gtk is doing so much magic for us, we have to do
# some weird tricks to get at these.
# Ask ourselves when we acquired the selection:
ts_data = self.clipboard.wait_for_contents("TIMESTAMP").data
ts_num = unpack("@i", ts_data[:4])[0]
# Calculate the X atom for this selection:
selection_xatom = get_xatom(self.atom)
# Ask X what window we used:
self._xwindow = myGetSelectionOwner(self.clipboard, self.atom)
root = self.clipboard.get_display().get_default_screen().get_root_window()
sendClientMessage(root, False, const["StructureNotifyMask"],
"MANAGER",
ts_num, selection_xatom, self._xwindow, 0, 0)
if old_owner != const["XNone"] and when is self.FORCE:
# Block in a recursive mainloop until the previous owner has
# cleared out.
def getwin():
window = get_pywindow(self.clipboard, old_owner)
window.set_events(window.get_events() | gtk.gdk.STRUCTURE_MASK)
return window
try:
window = trap.call(getwin)
log("got window")
except XError:
log("Previous owner is already gone, not blocking")
else:
log("Waiting for previous owner to exit...")
add_event_receiver(window, self)
gtk.main()
log("...they did.")
def do_wimpiggy_destroy_event(self, event):
remove_event_receiver(event.window, self)
gtk.main_quit()
def _get(self, clipboard, outdata, which, userdata):
# We are compliant with ICCCM version 2.0 (see section 4.3)
outdata.set("INTEGER", 32, pack("@ii", 2, 0))
def _clear(self, clipboard, userdata):
self._xwindow = None
self.emit("selection-lost")
def window(self):
if self._xwindow is None:
return None
return get_pywindow(self.clipboard, self._xwindow)
gobject.type_register(ManagerSelection)
|