コード例 #1
0
ファイル: xwindow.py プロジェクト: jesuisbenjamin/Qontrol
class Window(object):

    """
        Abstract object representing the X Window of an application
        obtained with the window ID.
    """

    def __init__(self, windowID):

        self._display = Display()
        self._root = self._display.screen().root
        self._window = self._display.create_resource_object('window', windowID)


    def reserve_space(self, left=0, right=0, top=0, bottom=0):

        """ Reserves screen-space for toplevel window. """

        LEFT    = left
        RIGHT   = right
        TOP     = top
        BOTTOM  = bottom

        self._window.change_property(self._display.intern_atom('_NET_WM_STRUT'),
                                    self._display.intern_atom('CARDINAL'),
                                    32, [LEFT, RIGHT, TOP, BOTTOM])
        self._display.sync()


    def set_wm_state_skip_taskbar(self):

        """ Change state of the window. """

        self._window.set_wm_state(Display().intern_atom('_NET_WM_STATE_SKIP_TASKBAR'))
コード例 #2
0
ファイル: _window_x11.py プロジェクト: MeeperMogle/HTTPi
def getWindows():
    """Return dict: {'window title' : window id} for all visible windows"""

    titles = {}

    display = Display()
    root = display.screen().root
    win_list = root.get_full_property(NET_CLIENT_LIST, X.AnyPropertyType).value
    for win_id in win_list:
        window = display.create_resource_object('window', win_id)
        class_list = window.get_wm_class()
        """
        get_wm_name() method unable to handle utf-8 characters, thats why
        below window title gets from property and decoding instead of using 
        one short Window method that provided by python xlib
        """
        try:
            win_name = window.get_full_property(NET_WM_NAME,
                                                X.AnyPropertyType).value
        except:
            pass
        if win_name:
            try:
                win_name = win_name.decode("utf-8")
            except:
                pass
            titles[win_name] = win_id
        else:
            titles[class_list[1]] = win_id

    return titles
コード例 #3
0
ファイル: pointerMonitor.py プロジェクト: JKAbrams/mintmenu
class PointerMonitor(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)
        self.display = Display()
        self.root = self.display.screen().root
        self.windows = []

    # Receives GDK windows
    def addWindowToMonitor(self, window):
        gdk.gdk_x11_drawable_get_xid.argtypes = [c_void_p]
        xWindow = self.display.create_resource_object("window", gdk.gdk_x11_drawable_get_xid(hash(window)))
        self.windows.append(xWindow)

    def grabPointer(self):
        self.root.grab_button(X.AnyButton, X.AnyModifier, True, X.ButtonPressMask, X.GrabModeSync, X.GrabModeAsync, 0, 0)
        self.display.flush()

    def ungrabPointer(self):
        self.root.ungrab_button(X.AnyButton, X.AnyModifier)
        self.display.flush()

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        self.running = True
        while self.running:
            event = self.display.next_event()
            try:
                if event.type == X.ButtonPress:
                    # Check if pointer is inside monitored windows
                    for w in self.windows:
                        p = w.query_pointer()
                        g = w.get_geometry()
                        if p.win_x >= 0 and p.win_y >= 0 and p.win_x <= g.width and p.win_y <= g.height:
                            break
                    else:
                        # Is outside, so activate
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.ReplayPointer, event.time)
                else:
                    self.display.allow_events(X.ReplayPointer, X.CurrentTime)
            except Exception as e:
                print "Unexpected error: " + str(e)

    def stop(self):
        self.running = False
        self.root.ungrab_button(X.AnyButton, X.AnyModifier)
        self.display.close()
コード例 #4
0
 def run(self, window, screen):
     opacity = max(0.0, min(1.0, self.arg))
     xdisplay = XDisplay()
     xwindow = xdisplay.create_resource_object("window", window.get_xid())
     atom = xdisplay.intern_atom("_NET_WM_WINDOW_OPACITY")
     data = struct.pack("L", int(4294967295 * opacity))
     xwindow.change_property(atom, Xatom.CARDINAL, 32, data)
     xdisplay.sync()
コード例 #5
0
ファイル: pointerMonitor.py プロジェクト: sam0hack/mintmenu
class PointerMonitor(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }
       
    def __init__(self):
        GObject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)
        self.display = Display()
        self.root = self.display.screen().root
        self.windows = []
        
    # Receives GDK windows
    def addWindowToMonitor(self, window):
        xWindow = self.display.create_resource_object("window", gdk.gdk_x11_drawable_get_xid(hash(window)))
        self.windows.append(xWindow)
            
    def grabPointer(self):
        self.root.grab_button(X.AnyButton, X.AnyModifier, True, X.ButtonPressMask, X.GrabModeSync, X.GrabModeAsync, 0, 0)
        self.display.flush()
        
    def ungrabPointer(self):
        self.root.ungrab_button(X.AnyButton, X.AnyModifier)
        self.display.flush()

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)
                    
    def run(self):
        self.running = True
        while self.running:
            event = self.display.next_event()
            try:
                if event.type == X.ButtonPress:
                    # Check if pointer is inside monitored windows
                    for w in self.windows:
                        p = w.query_pointer()
                        g = w.get_geometry()
                        if p.win_x >= 0 and p.win_y >= 0 and p.win_x <= g.width and p.win_y <= g.height:
                            break
                    else:
                        # Is outside, so activate
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.ReplayPointer, event.time)
                else:        
                    self.display.allow_events(X.ReplayPointer, X.CurrentTime)
            except Exception as e:
                print "Unexpected error: " + str(e)

    def stop(self):
        self.running = False
        self.root.ungrab_button(X.AnyButton, X.AnyModifier)
        self.display.close()
コード例 #6
0
ファイル: mouse.py プロジェクト: lxing/kinect_mouse
class Window(object):
    def __init__(self):
        self.display = Display()
        self.root = self.display.screen().root
        self.title = 'Pointer active'

    def active_window(self):
        window_id = self.root.get_full_property(self.display.intern_atom('_NET_ACTIVE_WINDOW'), X.AnyPropertyType).value[0]
        window = self.display.create_resource_object('window', window_id)
        return window

    def find_window(self, title):
        window_ids = self.root.get_full_property(self.display.intern_atom('_NET_CLIENT_LIST'), X.AnyPropertyType).value
        for window_id in window_ids:
            window = self.display.create_resource_object('window', window_id)
            if title == window.get_wm_name():
                return window
        return None

    def resize(self, window, dim):
        window.configure(width = dim[0], height = dim[1])
        self.display.sync()

    def move(self, window, pos):
        window.configure(x = pos[0], y = pos[1])
        self.display.sync()

    def destroy(self, window):
        window.destroy()
        self.display.sync()

    def shape(self, window):
        geo = window.get_geometry()
        return (geo.width, geo.height)

    def position(self, window):
        p = window.query_pointer()
        return (p.root_x - p.win_x, p.root_y - p.win_y - 28) # The 28 seems to be the taskbar

    def rename(self, window):
        print 'renaming', window.get_wm_name()
        window.set_wm_icon_name('poo')
        window.set_wm_name('poo')
        self.display.sync()
コード例 #7
0
ファイル: bar_panel.py プロジェクト: giobyte8/LearningPySide2
class BarWindow:
    def __init__(self, window_id):
        self._display = Display()
        self._window = self._display.create_resource_object('window', window_id)

    def reserve_space(self, left=0, right=0, top=0, bottom=0):
        self._window.change_property(
            self._display.intern_atom('_NET_WM_STRUT'),
            self._display.intern_atom('CARDINAL'),
            32,
            [left, right, top, bottom])
        self._display.sync()
コード例 #8
0
class XlibHelper:
    """Utility class for some X11-specific logic"""
    def __init__(self):
        self.display = Display()
        self.use_xres = self._try_init_xres()

    def _try_init_xres(self) -> bool:
        if XRes is None or self.display.query_extension(XRes.extname) is None:
            LOG.warning(
                "X-Resource extension is not supported. "
                "Process identification for X11 applications will be less reliable."
            )
            return False
        ver = self.display.res_query_version()
        LOG.info(
            "X-Resource version %d.%d",
            ver.server_major,
            ver.server_minor,
        )
        return (ver.server_major, ver.server_minor) >= (1, 2)

    def get_net_wm_pid(self, wid: int) -> int:
        """Get PID from _NET_WM_PID property of X11 window"""
        window = self.display.create_resource_object("window", wid)
        net_wm_pid = self.display.get_atom("_NET_WM_PID")
        pid = window.get_full_property(net_wm_pid, X.AnyPropertyType)

        if pid is None:
            raise Exception("Failed to get PID from _NET_WM_PID")
        return int(pid.value.tolist()[0])

    def get_xres_client_id(self, wid: int) -> int:
        """Get PID from X server via X-Resource extension"""
        res = self.display.res_query_client_ids([{
            "client":
            wid,
            "mask":
            XRes.LocalClientPIDMask
        }])
        for cid in res.ids:
            if cid.spec.client > 0 and cid.spec.mask == XRes.LocalClientPIDMask:
                for value in cid.value:
                    return value
        raise Exception("Failed to get PID via X-Resource extension")

    def get_window_pid(self, wid: int) -> Optional[int]:
        """Get PID of X11 window"""
        if self.use_xres:
            return self.get_xres_client_id(wid)

        return self.get_net_wm_pid(wid)
コード例 #9
0
ファイル: kivyXwm.py プロジェクト: jegger/PBController
def repositionize(title=str, x=int, y=int, width=int, height=int):
    HEIGHT = height
    WIDTH = width
    y=1080-y-height
    display = Display()
    root = display.screen().root
    windowIDs = root.get_full_property(display.intern_atom('_NET_CLIENT_LIST'),X.AnyPropertyType).value
    for windowID in windowIDs:
        window = display.create_resource_object('window', windowID)
        titles = window.get_wm_name()
        pid = window.get_full_property(display.intern_atom('_NET_WM_PID'), X.AnyPropertyType)
        if title in titles:
            window.configure(x = x, y = y, width=WIDTH, height=HEIGHT)
            display.sync()
コード例 #10
0
ファイル: test.py プロジェクト: dolfandringa/kivy_playground
 def set_wm_class(self):
     """
     Set the X11 WM_CLASS. This is used to link the window to the X11
     application (menu entry from the .desktop file). Gnome-shell won't
     display the application icon correctly in the dash with the default
     value of `python3, python3`.
     """
     display = Display()
     root = display.screen().root
     windowIDs = root.get_full_property(
         display.intern_atom('_NET_CLIENT_LIST'), X.AnyPropertyType).value
     for windowID in windowIDs:
         window = display.create_resource_object('window', windowID)
         title = window.get_wm_name()
         if title == self.title:
             window.set_wm_class("MyKivyTestApp", "python3")
             display.sync()
コード例 #11
0
ファイル: kivyXvm.py プロジェクト: RahulRavindren/TreeFinder
def resize(title=str, height=int, width=int):
    TITLE = title
    HEIGHT = height
    WIDTH = width

    display = Display()
    root = display.screen().root
    windowIDs = root.get_full_property(display.intern_atom('_NET_CLIENT_LIST'),
        X.AnyPropertyType).value
    for windowID in windowIDs:
        window = display.create_resource_object('window', windowID)
        title = window.get_wm_name()
        pid = window.get_full_property(display.intern_atom('_NET_WM_PID'),
        X.AnyPropertyType)
        if TITLE in title:
            window.configure(width = WIDTH, height = HEIGHT)
            display.sync()
コード例 #12
0
def resize(title=str, height=int, width=int):
    TITLE = title
    HEIGHT = height
    WIDTH = width

    display = Display()
    root = display.screen().root
    windowIDs = root.get_full_property(display.intern_atom('_NET_CLIENT_LIST'),
                                       X.AnyPropertyType).value
    for windowID in windowIDs:
        window = display.create_resource_object('window', windowID)
        title = window.get_wm_name()
        pid = window.get_full_property(display.intern_atom('_NET_WM_PID'),
                                       X.AnyPropertyType)
        if TITLE in title:
            window.configure(width=WIDTH, height=HEIGHT)
            display.sync()
コード例 #13
0
ファイル: ucom-eli.py プロジェクト: wdbm/ucom-eli
class Window(object):
    def __init__(self, window_ID):
        self._display = Display()
        self._window = self._display.create_resource_object(
            'window', window_ID)

    def reserve_space(self, left=0, right=0, top=0, bottom=0):
        LEFT = int(left)
        RIGHT = int(right)
        TOP = int(top)
        BOTTOM = int(bottom)
        print([LEFT, RIGHT, TOP, BOTTOM])
        self._window.change_property(
            self._display.intern_atom('_NET_WM_STRUT'),
            self._display.intern_atom('CARDINAL'), 32,
            [LEFT, RIGHT, TOP, BOTTOM])
        self._display.sync()
コード例 #14
0
	def xstuff(self):
		screen = self.window.get_screen()
		s = Gdk.Screen.get_default()
		disp = screen.get_display()
		width = s.get_width()
		height = s.get_height()
		bar_size = 40
		x,y = 0,0
		self.window.move(x,y)
		self.window.resize(width,bar_size)
		self.window.show_all()

		display = Display()
		topw = display.create_resource_object('window',
                                       self.window.get_toplevel().get_window().get_xid())
		topw.change_property(display.intern_atom('_NET_WM_STRUT'),
                       display.intern_atom('CARDINAL'), 32,
                       [0, 0, bar_size, 0 ],
                       X.PropModeReplace)

		topw.change_property(display.intern_atom('_NET_WM_STRUT_PARTIAL'),
		display.intern_atom('CARDINAL'), 32,
		[0, 0, bar_size, 0, 0, 0, 0, 0, x, x+width-1, 0, 0],
		X.PropModeReplace)
コード例 #15
0
ファイル: gui.py プロジェクト: ammubhave/secure-workstation
#    print(str(event))
#area.connect("motion_notify_event", mouse_move_callback);
#window.add(area)
#area.show()

label = Gtk.Label('<span size="38000" color="red">gmail.com</span>')
label.set_use_markup(True)
window.add(label)

window.connect("delete-event", Gtk.main_quit)
window.show_all()

# Reserve space on the top
display = Display()
topw = display.create_resource_object(
    'window',
    window.get_toplevel().get_window().get_xid())
topw.change_property(display.intern_atom('_NET_WM_STRUT'),
                     display.intern_atom('CARDINAL'), 32, [0, 0, 100, 0],
                     X.PropModeReplace)
topw.change_property(display.intern_atom('_NET_WM_STRUCT_PARTIAL'),
                     display.intern_atom('CARDINAL'), 32,
                     [0, 0, 100, 0, 0, 0, 0, 0, width - 1, 0, 0],
                     X.PropModeReplace)

from threading import Thread


class KeyboardReaderThread(Thread):
    def run(self):
        from evdev import InputDevice, categorize, ecodes
コード例 #16
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)

        gdk.gdk_keymap_get_default.restype = c_void_p
        self.keymap = capi.get_widget (gdk.gdk_keymap_get_default())
        self.display = Display()
        self.screen = self.display.screen()
        self.window = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask)
        self.map_modifiers()
        self.raw_keyval = None
        self.keytext = ""

    def is_hotkey(self, key, modifier):
        keymatch = False
        modmatch = False
        modifier = modifier & ~Gdk.ModifierType.SUPER_MASK
        modint = int(modifier)
        if self.get_keycode(key) == self.keycode:
            keymatch = True
        for ignored_mask in self.ignored_masks:
            if self.modifiers | ignored_mask == modint | ignored_mask:
                modmatch = True
                break
        return keymatch and modmatch

    def map_modifiers(self):
        gdk_modifiers =(Gdk.ModifierType.CONTROL_MASK, Gdk.ModifierType.SHIFT_MASK, Gdk.ModifierType.MOD1_MASK,
                         Gdk.ModifierType.MOD2_MASK, Gdk.ModifierType.MOD3_MASK, Gdk.ModifierType.MOD4_MASK, Gdk.ModifierType.MOD5_MASK,
                         Gdk.ModifierType.SUPER_MASK, Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(0, modifier) or "Mod4" in Gtk.accelerator_name(0, modifier):
                self.known_modifiers_mask |= modifier

    def get_keycode(self, keyval):
        count = c_int()
        array = (KeymapKey * 10)()
        keys = cast(array, POINTER(KeymapKey))
        gdk.gdk_keymap_get_entries_for_keyval.argtypes = [c_void_p, c_uint, c_void_p, c_void_p]
        gdk.gdk_keymap_get_entries_for_keyval(hash(self.keymap), keyval, byref(keys), byref(count))
        return keys[0].keycode

    def grab(self, key):
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        self.keycode = self.get_keycode(keyval)
        self.modifiers = int(modifiers)

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode, mod, True, X.GrabModeAsync, X.GrabModeSync, onerror=catch)
        self.display.flush()
        # sync has been blocking. Don't know why.
        #self.display.sync()
        if catch.get_error():
            return False
        return True

    def ungrab(self):
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)
            
    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""
    
    def set_focus_window(self, window = None):
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            gdk.gdk_x11_drawable_get_xid.argtypes = [c_void_p]
            self.window = self.display.create_resource_object("window", gdk.gdk_x11_drawable_get_xid(hash(window)))
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in xrange(mask+1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            try:
                self.current_event_time = event.time
                if event.detail == self.keycode and event.type == X.KeyPress and not wait_for_release:
                    modifiers = event.state & self.known_modifiers_mask
                    if modifiers == self.modifiers:
                        wait_for_release = True
                        self.display.allow_events(X.AsyncKeyboard, event.time)
                    else:
                        self.display.allow_events(X.ReplayKeyboard, event.time)
                elif event.detail == self.keycode and wait_for_release:
                    if event.type == X.KeyRelease:
                        wait_for_release = False
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.AsyncKeyboard, event.time)
                else:
                    self.display.allow_events(X.ReplayKeyboard, event.time)
            except AttributeError:
                continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
コード例 #17
0
class XWindowFocusTracker:
    def __init__(self):
        self._callbacks: MutableSequence[Callback] = []
        self._disp = Display()
        self._current_window_id: Optional[XWindowId] = None
        self.NET_ACTIVE_WINDOW = self._disp.intern_atom('_NET_ACTIVE_WINDOW')
        self.NET_WM_NAME = self._disp.intern_atom('_NET_WM_NAME')
        self._screen_locked = False
        self._lock = threading.Lock()

    def register(self, callback: Callback) -> None:
        with self._lock:
            self._callbacks.append(callback)

    def run(self) -> None:
        screen_lock_tracker = ScreenLockTracker(self)
        screen_lock_tracker_thread = threading.Thread(
            target=screen_lock_tracker.run, daemon=True)
        screen_lock_tracker_thread.start()

        root = self._disp.screen().root
        root.change_attributes(event_mask=X.PropertyChangeMask)

        while True:
            self._handle_xevent(self._disp.next_event())

    def set_screen_locked(self, locked: bool) -> None:
        logging.info(f'XWindowFocusTracker.set_screen_locked(locked={locked})')
        with self._lock:
            self._screen_locked = locked
            if locked:
                window_id = -1
                window_name = 'locked'
            else:
                window_id = self._current_window_id
                window_name = self._get_window_name(window_id)
            for callback in self._callbacks:
                callback(window_id, window_name)

    def _handle_xevent(self, event: Event) -> None:
        """Handler for X events which ignores anything but focus/title change"""
        if event.type != X.PropertyNotify:
            return

        if event.atom != self.NET_ACTIVE_WINDOW:
            return

        window_id = event.window.get_full_property(self.NET_ACTIVE_WINDOW,
                                                   X.AnyPropertyType).value[0]

        with self._lock:
            if self._current_window_id == window_id:
                return
            self._current_window_id = window_id

            window_name = self._get_window_name(window_id)

            for callback in self._callbacks:
                callback(window_id, window_name)

    def _get_window_name(self, window_id: XWindowId) -> str:
        window_obj = self._disp.create_resource_object('window', window_id)
        try:
            window_name_property = window_obj.get_full_property(
                self.NET_WM_NAME, 0)
        except Xlib.error.BadWindow:
            return ''
        else:
            return window_name_property.value.decode('utf-8')
コード例 #18
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__(self)
        threading.Thread.__init__(self)
        self.setDaemon(True)

        self.keymap = Gdk.Keymap().get_default()
        self.display = Display()
        self.screen = self.display.screen()
        self.window = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask
                                                        | X.Mod5Mask)
        self.map_modifiers()
        self.raw_keyval = None
        self.keytext = ""

    def map_modifiers(self):
        gdk_modifiers = (Gdk.ModifierType.CONTROL_MASK,
                         Gdk.ModifierType.SHIFT_MASK,
                         Gdk.ModifierType.MOD1_MASK,
                         Gdk.ModifierType.MOD2_MASK,
                         Gdk.ModifierType.MOD3_MASK,
                         Gdk.ModifierType.MOD4_MASK,
                         Gdk.ModifierType.MOD5_MASK,
                         Gdk.ModifierType.SUPER_MASK,
                         Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(
                    0, modifier) or "Mod4" in Gtk.accelerator_name(
                        0, modifier):
                self.known_modifiers_mask |= modifier

    def grab(self, key):
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        try:
            self.keycode = self.keymap.get_entries_for_keyval(
                keyval).keys[0].keycode
        except AttributeError:
            # In older Gtk3 the get_entries_for_keyval() returns an unnamed tuple...
            self.keycode = self.keymap.get_entries_for_keyval(
                keyval)[1][0].keycode
        self.modifiers = int(modifiers)

        # Request to receive key press/release reports from other windows that may not be using modifiers
        catch = error.CatchError(error.BadWindow)
        if self.modifiers:
            self.window.change_attributes(onerror=catch,
                                          event_mask=X.KeyPressMask
                                          | X.KeyReleaseMask)
        else:
            self.window.change_attributes(onerror=catch,
                                          event_mask=X.NoEventMask)
        if catch.get_error():
            return False

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode,
                                          mod,
                                          True,
                                          X.GrabModeAsync,
                                          X.GrabModeAsync,
                                          onerror=catch)
        self.display.flush()
        # sync has been blocking. Don't know why.
        #self.display.sync()
        if catch.get_error():
            return False
        return True

    def ungrab(self):
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)

    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""

    def set_focus_window(self, window=None):
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            self.window = self.display.create_resource_object(
                "window", window.get_xid())
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in xrange(mask + 1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()

            if self.modifiers:
                # Use simpler logic when using traditional combined keybindings
                modifiers = event.state & self.known_modifiers_mask
                if event.type == X.KeyPress and event.detail == self.keycode and modifiers == self.modifiers:
                    GLib.idle_add(self.idle)

            else:
                try:
                    if event.type == X.KeyPress and event.detail == self.keycode and not wait_for_release:
                        modifiers = event.state & self.known_modifiers_mask
                        if modifiers == self.modifiers:
                            wait_for_release = True
                    elif event.type == X.KeyRelease and event.detail == self.keycode and wait_for_release:
                        GLib.idle_add(self.idle)
                        wait_for_release = False
                    else:
                        self.display.ungrab_keyboard(X.CurrentTime)
                        # Send the event up in case another window is listening to it
                        self.display.send_event(
                            event.window, event,
                            X.KeyPressMask | X.KeyReleaseMask, True)
                        wait_for_release = False
                except AttributeError:
                    continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
コード例 #19
0
def getBox(winID):
    dpy = Display()
    data = dpy.create_resource_object('window', winID).get_geometry()
    boxWin = (data.x, data.y, data.x + data.width, data.y + data.height)
    return boxWin
コード例 #20
0
 def run(self, window, screen):
     xid = window.get_xid()
     xdisplay = XDisplay()
     xwindow = xdisplay.create_resource_object("window", xid)
     xwindow.configure(x=self.arg[0], y=self.arg[1])
     xdisplay.sync()
コード例 #21
0
def getBox(winID):
    dpy = Display()
    data = dpy.create_resource_object('window', winID).get_geometry()
    boxWin = (data.x, data.y, data.x + data.width, data.y + data.height)
    return boxWin
コード例 #22
0
class ActiveWindowManager():
    # Based on code by Stephan Sokolow
    # Source: https://gist.github.com/ssokolow/e7c9aae63fb7973e4d64cff969a78ae8
    # Modified by hezral to add _get_window_class_name function

    """python-xlib example which reacts to changing the active window/title.

    Requires:
    - Python
    - python-xlib

    Tested with Python 2.x because my Kubuntu 14.04 doesn't come with python-xlib
    for Python 3.x.

    Design:
    -------

    Any modern window manager that isn't horrendously broken maintains an X11
    property on the root window named _NET_ACTIVE_WINDOW.

    Any modern application toolkit presents the window title via a property
    named _NET_WM_NAME.

    This listens for changes to both of them and then hides duplicate events
    so it only reacts to title changes once.

    Known Bugs:
    -----------

    - Under some circumstances, I observed that the first window creation and last
    window deletion on on an empty desktop (ie. not even a taskbar/panel) would
    go ignored when using this test setup:

        Xephyr :3 &
        DISPLAY=:3 openbox &
        DISPLAY=:3 python3 x11_watch_active_window.py

        # ...and then launch one or more of these in other terminals
        DISPLAY=:3 leafpad
    """

    stop_thread = False
    id_thread = None
    callback = None

    def __init__(self, gtk_application=None):
        super().__init__()

        self.app = gtk_application

        # Connect to the X server and get the root window
        self.disp = Display()
        self.root = self.disp.screen().root

        # Prepare the property names we use so they can be fed into X11 APIs
        self.NET_ACTIVE_WINDOW = self.disp.intern_atom('_NET_ACTIVE_WINDOW')
        self.NET_WM_NAME = self.disp.intern_atom('_NET_WM_NAME')  # UTF-8
        self.WM_NAME = self.disp.intern_atom('WM_NAME')           # Legacy encoding
        self.WM_CLASS = self.disp.intern_atom('WM_CLASS')

        self.last_seen = {'xid': None, 'title': None}  # type: Dict[str, Any]

    def _run(self, callback):

        self.callback = callback
        self.stop_thread = False

        def init_manager():
            # Listen for _NET_ACTIVE_WINDOW changes
            self.root.change_attributes(event_mask=X.PropertyChangeMask)

            # Prime last_seen with whatever window was active when we started this
            self.get_window_name(self.get_active_window()[0])
            self.handle_change(self.last_seen)

            while True:  # next_event() sleeps until we get an event
                self.handle_xevent(self.disp.next_event())
                if self.stop_thread:
                    print(datetime.now(), "active_window_manager stopped")
                    break

        self.thread = threading.Thread(target=init_manager)
        self.thread.daemon = True
        self.thread.start()
        print(datetime.now(), "active_window_manager started")

    def _stop(self):
        self.stop_thread = True

    @contextmanager
    def window_obj(self, win_id: Optional[int]) -> Window:
        """Simplify dealing with BadWindow (make it either valid or None)"""
        window_obj = None
        if win_id:
            try:
                window_obj = self.disp.create_resource_object('window', win_id)
            except XError:
                pass
        yield window_obj

    def get_active_window(self) -> Tuple[Optional[int], bool]:
        """Return a (window_obj, focus_has_changed) tuple for the active window."""
        response = self.root.get_full_property(self.NET_ACTIVE_WINDOW, X.AnyPropertyType)
        if not response:
            return None, False
        win_id = response.value[0]

        focus_changed = (win_id != self.last_seen['xid'])
        if focus_changed:
            with self.window_obj(self.last_seen['xid']) as old_win:
                if old_win:
                    old_win.change_attributes(event_mask=X.NoEventMask)

            self.last_seen['xid'] = win_id
            with self.window_obj(win_id) as new_win:
                if new_win:
                    new_win.change_attributes(event_mask=X.PropertyChangeMask)

        return win_id, focus_changed

    def _get_window_name_inner(self, win_obj: Window) -> str:
        """Simplify dealing with _NET_WM_NAME (UTF-8) vs. WM_NAME (legacy)"""
        for atom in (self.NET_WM_NAME, self.WM_NAME):
            try:
                window_name = win_obj.get_full_property(atom, 0)
            except UnicodeDecodeError:  # Apparently a Debian distro package bug
                title = "<could not decode characters>"
            else:
                if window_name:
                    win_name = window_name.value  # type: Union[str, bytes]
                    if isinstance(win_name, bytes):
                        # Apparently COMPOUND_TEXT is so arcane that this is how
                        # tools like xprop deal with receiving it these days
                        win_name = win_name.decode('latin1', 'replace')
                    return win_name
                else:
                    title = "<unnamed window>"

        return "{} (XID: {})".format(title, win_obj.id)

    def _get_window_class_name(self, win_obj: Window) -> str:
        """SReturn window class name"""
        try:
            window_name = win_obj.get_full_property(self.WM_CLASS, 0)
        except UnicodeDecodeError:  # Apparently a Debian distro package bug
            title = "<could not decode characters>"
        else:
            if window_name:
                win_class_name = window_name.value  # type: Union[str, bytes]
                if isinstance(win_class_name, bytes):
                    # Apparently COMPOUND_TEXT is so arcane that this is how
                    # tools like xprop deal with receiving it these days
                    win_class_name = win_class_name.replace(b'\x00',b' ').decode("utf-8").lower()
                return win_class_name
            else:
                title = "<undefined wm_class_name>"

        return "{} (XID: {})".format(title, win_obj.id)

    def get_window_name(self, win_id: Optional[int]) -> Tuple[Optional[str], bool]:
        """
        Look up the window class name for a given X11 window ID
        retrofitted to provide window class name instead of window title
        """
        if not win_id:
            self.last_seen['title'] = None
            return self.last_seen['title'], True

        title_changed = False
        with self.window_obj(win_id) as wobj:
            if wobj:
                try:
                    win_title = self._get_window_class_name(wobj)
                except XError:
                    pass
                else:
                    title_changed = (win_title != self.last_seen['title'])
                    self.last_seen['title'] = win_title

        return self.last_seen['title'], title_changed

    def handle_xevent(self, event: Event):
        """Handler for X events which ignores anything but focus/title change"""
        if event.type != X.PropertyNotify:
            return

        changed = False
        if event.atom == self.NET_ACTIVE_WINDOW:
            if self.get_active_window()[1]:
                self.get_window_name(self.last_seen['xid'])  # Rely on the side-effects
                changed = True
        elif event.atom in (self.NET_WM_NAME, self.WM_NAME):
            changed = changed or self.get_window_name(self.last_seen['xid'])[1]

        if changed:
            self.handle_change(self.last_seen)

    def handle_change(self, new_state: dict):
        """Replace this with whatever you want to actually do"""
        GLib.idle_add(self.callback, new_state['title'])
コード例 #23
0
win_class = sys.argv[1]
fps = int(sys.argv[2])
width = int(sys.argv[3])
height = int(sys.argv[4])
name = len(sys.argv) >= 6 and sys.argv[5] or "A Stream"
streamer_name = len(sys.argv) >= 7 and sys.argv[6] or "Anonymous"

url = "https://sevii.dev/api/streamer" # "http://localhost/api/streamer"
dis = Display()
root = dis.screen().root
win = None

# ------------------------------ #

if win_class[0] == "0":
	win = dis.create_resource_object("window", int(win_class, 16))
else:
	for w in root.query_tree().children:
		wclass = w.get_wm_class()
		
		if wclass != None and wclass[1].lower() == win_class:
			try:
				dis.create_resource_object("window", w.id + 2).get_image(0, 0, 1, 1, X.ZPixmap, 0xffffffff)
			except:
				pass
			else:
				win = dis.create_resource_object("window", w.id + 2)
				
				break

if not win:
コード例 #24
0
ファイル: bar.py プロジェクト: tpb1908/notifbar
    def __init__(self,
                 notification: int,
                 summary: str,
                 body: str,
                 application: str,
                 icon_path: Optional[str] = None,
                 timeout: Optional[int] = -1,
                 actions: Optional[List[List]] = None,
                 dismiss: bool = False):
        # Set up empty window and add style
        Gtk.Window.__init__(self)

        # No need to provide a mainloop, as we are only sending

        # Version information
        print("Gtk %d.%d.%d" %
              (Gtk.get_major_version(), Gtk.get_minor_version(),
               Gtk.get_micro_version()))
        self.notification = notification
        self.body = body
        self.summary = summary
        self.application = application
        self.icon_path = icon_path
        self.timeout = timeout
        self.actions = actions
        self.dismiss = dismiss

        self.set_name("bar")
        self.set_type_hint(Gdk.WindowTypeHint.DOCK)
        self.set_decorated(False)
        self.connect("delete-event", Gtk.main_quit)

        # style_provider = Gtk.CssProvider()
        # style_provider.from_data(stylesheet)
        # Gtk.StyleContext.add_provider_for_screen(
        #     Gdk.Screen.get_default(),
        #     style_provider,
        #     Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        # Layout container
        self.hbox = Gtk.Box(spacing=5)
        self.hbox.set_homogeneous(False)

        message_str = "<big>{}</big>".format(self.application)

        if icon_path is not None:
            if self._try_init_icon():
                message_str = ""  # Application displayed with icon

        self.message = Gtk.Label()

        if self.body is None:
            message_str += "<b>{}</b>".format(self.summary)
        else:
            message_str += "<b>{}</b>\n{}".format(self.summary, self.body)
        self.message.set_markup(message_str)
        self.hbox.pack_start(self.message, False, True, 0)

        self._init_action_buttons()
        button = Gtk.Button.new_with_mnemonic("_OK")
        button.connect("clicked", self.done)
        self.hbox.pack_end(button, False, False, 0)

        self.add(self.hbox)

        # the screen contains all monitors
        screen = self.get_screen()
        width = screen.width()  # width = Gdk.Screen.width()
        print("width: %d" % width)

        # (c) collect data about each monitor
        monitors = []
        nmons = screen.get_display().get_n_monitors()
        print("there are %d monitors" % nmons)
        for m in range(nmons):
            mg = screen.get_monitor_geometry(m)
            print("monitor %d: %d x %d" % (m, mg.width, mg.height))
            monitors.append(mg)

        # current monitor
        curmon = screen.get_monitor_at_window(screen.get_active_window())
        x = monitors[curmon].x
        y = monitors[curmon].y
        width = monitors[curmon].width
        height = monitors[curmon].height
        print("monitor %d: %d x %d (current, offset %d)" %
              (curmon, width, height, x))
        print("bar: start=%d end=%d" % (x, x + width - 1))

        # display bar along the top of the current monitor
        self.move(x, y)
        self.resize(width, bar_size)

        # it must be shown before changing properties
        self.show_all()
        print(f"Window shown. Size {self.get_size()}")
        print(f"Window shown. Size {self.get_size()}")
        # (d) reserve space (a "strut") for the bar so it does not become obscured
        #     when other windows are maximized, etc
        # http://stackoverflow.com/questions/33719686  property_change not in gtk3.0
        # https://sourceforge.net/p/python-xlib/mailman/message/27574603
        display = Display()
        topw = display.create_resource_object(
            'window',
            self.get_toplevel().get_window().get_xid())

        # http://python-xlib.sourceforge.net/doc/html/python-xlib_21.html#SEC20
        topw.change_property(display.intern_atom('_NET_WM_STRUT'),
                             display.intern_atom('CARDINAL'), 32,
                             [0, 0, bar_size, 0], X.PropModeReplace)
        topw.change_property(
            display.intern_atom('_NET_WM_STRUT_PARTIAL'),
            display.intern_atom('CARDINAL'), 32,
            [0, 0, bar_size, 0, 0, 0, 0, 0, x, x + width - 1, 0, 0],
            X.PropModeReplace)

        # we set _NET_WM_STRUT, the older mechanism as well as _NET_WM_STRUT_PARTIAL
        # but window managers ignore the former if they support the latter.
        #
        # the numbers in the array are as follows:
        #
        # 0, 0, bar_size, 0 are the number of pixels to reserve along each edge of the
        # screen given in the order left, right, top, bottom. Here the size of the bar
        # is reserved at the top of the screen and the other edges are left alone.
        #
        # _NET_WM_STRUT_PARTIAL also supplies a further four pairs, each being a
        # start and end position for the strut (they don't need to occupy the entire
        # edge).
        #
        # In the example, we set the top start to the current monitor's x co-ordinate
        # and the top-end to the same value plus that monitor's width, deducting one.
        # because the co-ordinate system starts at zero rather than 1. The net result
        # is that space is reserved only on the current monitor.
        #
        # co-ordinates are specified relative to the screen (i.e. all monitors together).
        #

        # main event loop
        # Gtk.main()
        # Control-C termination broken in GTK3 http://stackoverflow.com/a/33834721
        # https://bugzilla.gnome.org/show_bug.cgi?id=622084
        from gi.repository import GLib

        self.invoker = ActionInvoker()

        print(f"Timeout {self.timeout}")
        self.timer = Event()
        if self.timeout > 0:
            seconds = timeout / 1000

            def sleep_then_quit():
                self.timer.wait(seconds)
                self.quit()

            Thread(target=sleep_then_quit).start()

        print("Running main loop")

        Gtk.main()
コード例 #25
0
ファイル: knox.py プロジェクト: josebadoe/keybender
class KnoX:
    Geometry = namedtuple("Geometry", "x y width height")
    FrameExtents = namedtuple("FrameExtents", "left right top bottom")

    def __init__(self):
        #self.display = Display(os.environ.get("DISPLAY", ":0.0"))
        self.display = Display()
        print("Connected to X DISPLAY %r" % self.display.get_display_name())
        self.display.set_error_handler(self.knox_error_handler)
        self.screen = self.display.screen()
        self.root = self.screen.root
        self.atoms = dict()
        self.atom_names = dict()
        self.keysyms = Keysyms()
        self.modifiers = Modifiers(self)
        self._supported_properties = None
        self._acceptable_error_sequence = 0
        self._acceptable_errors = dict()
        self._silenced_errors = set()

    def fileno(self):
        """This function is here to make select work with this object"""
        return self.display.fileno()

    @contextmanager
    def silenced_error(self, error):
        silencer = self.silence_error(error)
        try:
            yield silencer
        finally:
            self.remove_silencer(silencer)

    def silence_error(self, error):
        k = self._acceptable_error_sequence
        self._acceptable_errors[k] = error
        self._acceptable_error_sequence += 1
        self._silenced_errors = set(self._acceptable_errors.values())
        return k

    def remove_silencer(self, key):
        if key in self._acceptable_errors:
            del self._acceptable_errors[key]
            self._silenced_errors = set(self._acceptable_errors.values())

    def knox_error_handler(self, err, *args):
        if type(err) not in self._silenced_errors:
            print("X protocol error: %s" % err)
            traceback.print_stack()

    # def wait_for_event(self, timeout_seconds):
    #     """ Wait up to `timeout_seconds` seconds for an event to be queued.
    #     Return True, if a xevent is available.
    #     Return False, if the timeout was reached.
    #     from https://gist.github.com/fphammerle/d81ca3ff0a169f062a9f28e57b18f04d"""
    #     rlist = select.select(
    #         [self.display], # rlist
    #         [], # wlist
    #         [], # xlist
    #         timeout_seconds, # timeout [seconds]
    #     )[0]
    #     return len(rlist) > 0

    def next_event(self, wait=True):
        if (wait or self.display.pending_events()):
            return self.display.next_event()
        else:
            return None

    # def next_event(self, event_loop):
    #     event_loop.register_reader(self.display,

    def atom(self, name, only_if_exists=False):
        if isinstance(name, int):
            a = name
        elif name not in self.atoms:
            a = self.display.get_atom(name, only_if_exists=only_if_exists)
            self.atoms[name] = a
        else:
            a = self.atoms[name]
        return a

    def atom_name(self, atom):
        if atom in self.atom_names:
            return self.atom_names[atom]
        name = self.display.get_atom_name(atom)
        if name:
            self.atom_names[atom] = name
            if name not in self.atoms:
                self.atoms[name] = atom
            return name

    def get_prop(self, window, name):
        prop_name = self.atom(name, only_if_exists=True)
        if not prop_name:
            return None
        if isinstance(window, int):
            window = self.get_window(window)
        p = window.get_full_property(prop_name, X.AnyPropertyType)
        if p:
            return p.value

    def get_text_prop(self, window, name):
        prop_name = self.atom(name, only_if_exists=True)
        if not prop_name:
            return None
        s = window.get_full_text_property(prop_name, Xatom.STRING)
        if not s:
            t = self.atom("UTF8_STRING", only_if_exists=True)
            if t:
                s = window.get_full_text_property(prop_name, t)
        return s

    def onerror(self, *args, **kwargs):
        print("ERROR: something bad happened about %r and %r" % (args, kwargs))
        raise Exception("Error is bad...")

    def set_prop(self, window, name, type_name, value):
        if isinstance(window, int):
            window = self.get_window(window)
        if isinstance(type_name, int):
            prop_type_name = type_name
            #type_name = self.atom_name(prop_type_name)
        else:
            prop_type_name = self.atom(type_name, only_if_exists=False)

        prop_name = self.atom(name, only_if_exists=False)

        if value is None:
            window.delete_property(prop_name)
        else:
            window.change_property(prop_name,
                                   prop_type_name,
                                   32,
                                   value,
                                   mode=X.PropModeReplace,
                                   onerror=self.onerror)

    def send_prop_change_event(
        self,
        property_name,
        data,
        target=None,
        window=None,
    ):
        if target is None:
            target = self.root
        if window is None:
            window = target
        ev = protocol.event.ClientMessage(window=window,
                                          client_type=self.atom(property_name),
                                          data=data)
        target.send_event(ev,
                          event_mask=X.SubstructureNotifyMask
                          | X.SubstructureRedirectMask,
                          propagate=False,
                          onerror=self.onerror)

    def current_desktop(self, desktop=None, wait=True):
        prop_name = "_NET_CURRENT_DESKTOP"
        if desktop is None:
            pv = self.get_prop(self.root, prop_name)
            if pv:
                return pv[0]
        else:
            v = array('I', [desktop])
            #self.set_prop(self.root, prop_name, Xatom.CARDINAL, v)
            self.send_prop_change_event(
                prop_name, (32, [desktop, X.CurrentTime, 0, 0, 0]))
            self.flush()
            w = Waiter(wait)
            while w.wait():
                print("DESKTOPCHECK", hex(desktop))
                if self.current_desktop() == desktop:
                    print("DESKTOP OK")
                    break

    def get_wm_pid(self, window):
        pid_prop = self.get_prop(window, "_NET_WM_PID")
        if pid_prop:
            return pid_prop[0]
        return None

    def get_wm_name(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        # window.get_wm_name gets only STRING property and returns nothing
        # if it's UTF8_STRING
        return self.get_text_prop(window, Xatom.WM_NAME)

    def active_window(self, window=None, wait=3, id_only=False):
        prop_name = "_NET_ACTIVE_WINDOW"
        if window is None:
            pv = self.get_prop(self.root, prop_name)
            if pv and pv[0]:
                window = self.get_window(pv[0])
                if window and window.get_wm_name() != 'Desktop':
                    if id_only:
                        return window.id
                    else:
                        return window
        else:
            if isinstance(window, int):
                window = self.get_window(window)
            desktop = self.get_desktop_for_window(window)
            self.current_desktop(desktop)
            #v = array('I', [ window.id, 0 ])
            #self.set_prop(self.root, prop_name, Xatom.WINDOW, v)
            # data[0]: source indication
            #   1: when the request comes from an application
            #   2: from a pager
            #   0: no spec.
            self.send_prop_change_event(prop_name,
                                        (32, [2, X.CurrentTime, 0, 0, 0]),
                                        window=window)
            self.flush()
            #self.raise_window(window)
            # it won't become active until it's focused
            focused = self.set_focused_window(window, wait=1)
            w = Waiter(wait)
            while w.wait():
                a = self.active_window()
                self.flush()
                if not focused:
                    focused = self.set_focused_window(window, wait=1)
                    self.flush()
                if a and a.id == window.id:
                    print("Activated %r!" % window.id)
                    return True
                self.send_prop_change_event(prop_name,
                                            (32, [2, X.CurrentTime, 0, 0, 0]),
                                            window=window)
                self.flush()
            print("Can't activate %d" % window.id)
            return False

    def get_focused_window(self, toplevel=True):
        f = self.display.get_input_focus()
        #f = protocol.request.GetInputFocus(display=self.display.display)
        if f.focus in [X.NONE, X.PointerRoot]:
            return None
        if toplevel:
            w = self.get_client_window(f.focus)
            if w is not None:
                return w.id
        return f.focus.id

    def raise_window(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        elif window is None:
            return
        window.raise_window()

    def focus_error(self, *args, **kwargs):
        print("Cannot set_input_focus: %r %r" % (args, kwargs))

    def set_focused_window(self, window, wait=3):
        if window is None:
            self.display.set_input_focus(X.NONE,
                                         X.RevertToParent,
                                         X.CurrentTime,
                                         onerror=self.focus_error)
            return True
        elif not wait:
            self.display.set_input_focus(window, X.RevertToParent,
                                         X.CurrentTime)
            return True
        else:
            with self.silenced_error(error.BadMatch):
                if isinstance(window, int):
                    window = self.get_window(window)
                self.display.set_input_focus(window, X.RevertToParent,
                                             X.CurrentTime)
                self.flush()
                w = Waiter(wait)
                while w.wait():
                    if w.timeout:
                        if w.progressed:
                            print("WAITING %.3f seconds more for focus on %r" %
                                  (w.remaining, window.id))
                        else:
                            print(
                                "READY TO WAIT %.3f seconds for focus on %r" %
                                (w.remaining, window.id))
                    focused_win_id = self.get_focused_window()
                    if focused_win_id == window.id:
                        print("FOCUSED %r" % window.id)
                        return True
                    # many times it's needed to repeat the command, esp. when mouse is
                    # not inside the target window
                    self.display.set_input_focus(window, X.RevertToParent,
                                                 X.CurrentTime)
                    self.flush()
                    #self.display.set_input_focus(window, X.RevertToParent, X.CurrentTime)
                    #self.display.flush()
            return False

    def get_desktop_for_window(self, window):
        pv = self.get_prop(window, "_NET_WM_DESKTOP")
        if pv:
            return pv[0]

    def set_desktop_for_window(self, window, desktop):
        if desktop is None:
            return
        name = self.atom("_NET_WM_DESKTOP", only_if_exists=True)
        if name in self.supported_properties:
            pv = self.set_prop(window, name, Xatom.CARDINAL,
                               array('I', [desktop]))

    def save_state(self):
        state = {
            "Current Desktop": self.current_desktop(),
            "Active Window": self.active_window(id_only=True),
            "Focused Window": self.get_focused_window()
        }
        return state

    def restore_state(self, state):
        a = self.supported_properties
        self.current_desktop(state["Current Desktop"])
        self.flush()
        try:
            self.set_focused_window(state["Focused Window"])
        except error.BadWindow:
            print("Sorry, the old focused window went away...")
        # self.active_window(state["Active Window"])

    def keysym_to_string(self, keysym, friendly=False, very_friendly=False):
        if keysym not in self.keysyms.keysyms:
            return chr(keysym)
        if very_friendly:
            return self.keysyms.friendly_name(keysym, simplest=True)
        if friendly:
            return self.keysyms.friendly_name(keysym, simplest=False)
        else:
            return self.keysyms[keysym]

    def keycode_to_keysym(self, keycode, idx=None):
        if idx is None:
            syms = set()
            for i in range(4):
                keysym = self.display.keycode_to_keysym(keycode, i)
                if keysym:
                    syms.add(keysym)
            return syms
        else:
            return self.display.keycode_to_keysym(event.detail, i)

    def keysym_to_keycode(self, keysym):
        return self.display.keysym_to_keycode(keysym)

    def string_to_keysym(self, s):
        k = self.keysyms[s]
        if not k:
            k = self.keysyms["XK_" + s]
        if k:
            return k
        k = XK.string_to_keysym(s)
        return k
        # allow simpler names, like AudioRaiseVolume?
        # if s.startswith("XF86_"):
        #     s = "XF86" + s[5:]
        #     return XK.string_to_keysym(s)

    def error_handler(self, fn, *args, **kwargs):
        return functools.partial(fn, *args, **kwargs)

    def toggle_frame(self, window, frame=None, wait=1):
        """Set window frame. Value should be True or False for on and off, or None for toggle."""
        # flags - set bit for every iteresting value
        # 0 functions   => integer bits
        # 1 decorations => integer bits
        # 2 input_mode  => enum string or integer
        # 3 status      => integer bits
        #
        # functions:
        # bit    actions offered
        # ---    ---------------
        #  1     all functions
        #  2     resize window
        #  4     move window
        #  8     minimize, to iconify
        # 16     maximize, to full-screen (with a frame still)
        # 32     close window
        #
        # decorations:
        # bit       decorations displayed
        # ---       ---------------------
        #  1        all decorations
        #  2        border around the window
        #  4        resizeh, handles to resize by dragging
        #  8        title bar, showing WM_NAME
        # 16        menu, drop-down menu of the "functions" above
        # 32        minimize button, to iconify
        # 64        maximize button, to full-screen
        #
        # input mode:
        #   string                   integer
        # "modeless"                    0    not modal (the default)
        # "primary_application_modal"   1    modal to its "transient for"
        # "system_modal"                2    modal to the whole display
        # "full_application_modal"      3    modal to the current client
        #
        # status:
        #
        # bit
        #  1    tearoff menu window

        name = self.atom("_MOTIF_WM_HINTS", only_if_exists=True)
        # If does not exist, probably not supported, though should check
        # root for _NET_SUPPORTED list return assert prop != 0 pv =
        pv = self.get_prop(window, name)
        fe = self.get_frame_extents(window)
        if pv and len(pv) == 5:
            hints = array(pv.typecode, pv)
            if frame is None:
                hints[2] = 0 if hints[2] else 1
            elif frame:
                hints[2] = 1
            else:
                hints[2] = 0
        else:
            # reasonable default
            hints = array('I', [2, 0, 0, 0, 0])

        self.set_prop(window, name, name, hints)

        w = Waiter(wait)
        while w.wait():
            pv = self.get_prop(window, name)
            if pv and array(pv.typecode, pv) == hints:
                new_fe = self.get_frame_extents(window)
                # make sure frame extents changed
                # this seems to take a while once the hints change
                if new_fe != fe:
                    break

    def set_opacity(self, window, value):
        """value is a number between 0 and 1"""
        v = int(((1 << 32) - 1) * value)
        self.set_prop(window, "_NET_WM_WINDOW_OPACITY", Xatom.CARDINAL,
                      array('I', [v]))

    def get_opacity(self, window):
        pv = self.get_prop(window, "_NET_WM_WINDOW_OPACITY")
        if pv:
            value = int(pv[0] / ((1 << 32) - 1))
            return value
        return 1

    @property
    def supported_properties(self):
        if self._supported_properties is None:
            self._supported_properties = self.get_prop(self.root,
                                                       "_NET_SUPPORTED") or []
        return self._supported_properties

    def get_window(self, win_id):
        if isinstance(win_id, int):
            return self.display.create_resource_object('window', win_id)
        else:
            return win_id

    def get_client_window(self, window):
        win_id = window.id
        for tlw in self.toplevel_windows():
            for (_, parent, _) in self.window_tree(
                    tlw, filter=lambda w, parent, level: w.id == win_id):
                return tlw
        return None

    def toplevel_windows(self, id_only=False):
        name = self.atom("_NET_CLIENT_LIST", only_if_exists=True)
        if name in self.supported_properties:
            lst = self.get_prop(self.root, name)
            if id_only:
                return lst
            else:
                return list(map(lambda win_id: self.get_window(win_id), lst))
        else:
            print("BELGENGOC")
            if id_only:
                return list(
                    map(lambda w: w.id,
                        self.root.query_tree().children))
            else:
                return list(self.root.query_tree().children)

    def window_tree(self, parent=None, level=1, filter=None):
        if parent is None:
            parent = self.root
            if filter is None or filter(parent, None, 0):
                yield (parent, None, 0)
        for w in parent.query_tree().children:
            if filter is None or filter(w, parent, level):
                yield (w, parent, level)
                yield from self.window_tree(parent=w,
                                            level=level + 1,
                                            filter=filter)

    def close_window(self, window):
        self.send_prop_change_event("_NET_CLOSE_WINDOW", (32, [0, 0, 0, 0, 0]),
                                    window=self.get_window(window))

    # https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html
    # window  = the respective client window
    # message_type = _NET_WM_STATE
    # format = 32
    # data.l[0] = the action, as listed below
    # data.l[1] = first property to alter
    # data.l[2] = second property to alter
    # data.l[3] = source indication
    #  other data.l[] elements = 0
    # This message allows two prop
    #
    _NET_WM_STATE_REMOVE = 0  # remove/unset property
    _NET_WM_STATE_ADD = 1  #add/set property
    _NET_WM_STATE_TOGGLE = 2  # toggle property

    def set_wm_states(self, window, names, action=None):
        if action is None:
            action = self._NET_WM_STATE_TOGGLE
        elif action is True:
            action = self._NET_WM_STATE_ADD
        elif action is False:
            action = self._NET_WM_STATE_REMOVE
        window = self.get_window(window)
        values = list()
        for name in names:
            value = self.atom("_NET_WM_STATE_%s" % name.upper())
            values.append(value)
        data = [action, *values]
        while len(data) < 5:
            data.append(0)
        self.send_prop_change_event("_NET_WM_STATE", (32, data),
                                    window=self.get_window(window))

    def set_wm_state(self, window, name, action=None):
        if action is None:
            action = self._NET_WM_STATE_TOGGLE
        elif action is True:
            action = self._NET_WM_STATE_ADD
        elif action is False:
            action = self._NET_WM_STATE_REMOVE
        window = self.get_window(window)
        value = self.atom("_NET_WM_STATE_%s" % name.upper())
        self.send_prop_change_event("_NET_WM_STATE",
                                    (32, [action, value, 0, 0, 0]),
                                    window=self.get_window(window))

    def below_window(self, window, action=None):
        self.set_wm_state(window, name="below", action=action)

    def fullscreen_window(self, window, action=None):
        self.set_wm_state(window, name="fullscreen", action=action)

    def above_window(self, window, action=None):
        self.set_wm_state(window, name="above", action=action)

    def sticky_window(self, window, action=None):
        self.set_wm_state(window, name="sticky", action=action)

    def skip_pager(self, window, action=None):
        self.set_wm_state(window, name="skip_pager", action=action)

    def skip_taskbar(self, window, action=None):
        self.set_wm_state(window, name="skip_taskbar", action=action)

    def maximize_window(self,
                        window,
                        horizontal=True,
                        vertical=True,
                        action=None):
        if horizontal:
            self.set_wm_state(window, name="maximized_horz", action=action)
        if vertical:
            self.set_wm_state(window, name="maximized_vert", action=action)

    def minimize_window(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        self.send_prop_change_event("WM_CHANGE_STATE",
                                    (32, [Xutil.IconicState, 0, 0, 0, 0]),
                                    window=self.get_window(window))

    def get_attributes(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        return window.get_attributes()

    def get_window_type(self, window):
        e = self.get_prop(window, "_NET_WM_WINDOW_TYPE")
        if e is None:
            return None
        type_details = set()
        prefix = "_NET_WM_WINDOW_TYPE_"
        for t in e:
            if not t:
                continue
            s = self.atom_name(t)
            if s.startswith(prefix):
                s = s[len(prefix):]
            type_details.add(s)
        return type_details

    def get_frame_extents(self, window):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        e = self.get_prop(window, "_NET_FRAME_EXTENTS")
        if e:
            return self.FrameExtents(*e)
        else:
            return self.FrameExtents(0, 0, 0, 0)

    def get_geometry(self, window):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        return window.get_geometry()

    def set_geometry(self, window, **data):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        if any(map(lambda v: v < 0, data.values())):
            gw = self.get_geometry(window)
            f = self.get_frame_extents(window)
            wa = self.usable_workarea()

            if 'x' in data and data['x'] < 0:
                data['x'] = wa.width - gw.width - (f.left +
                                                   f.right) + data['x'] + 1
            else:
                data['x'] += wa.x
            if 'y' in data and data['y'] < 0:
                data['y'] = wa.height - gw.height - (f.top +
                                                     f.bottom) + data['y'] + 1
            else:
                data['y'] += wa.y
        window.configure(**data)

    def usable_workarea(self):
        a = self.get_prop(self.root, "_NET_WORKAREA")
        if a:
            p = self.current_desktop() * 4
            #return (x, y, width, height)
            return self.Geometry(*a[p:p + 4])
        else:
            r = self.get_geometry(self.root)
            return self.Geometry(0, 0, r.width, r.height)

    def send_key(self, window, keysym, modifiers):
        if isinstance(window, int):
            window = self.get_window(window)
        keycode = self.display.keysym_to_keycode(keysym)
        event = protocol.event.KeyPress(time=X.CurrentTime,
                                        root=self.root,
                                        window=window,
                                        child=X.NONE,
                                        same_screen=True,
                                        root_x=0,
                                        root_y=0,
                                        event_x=0,
                                        event_y=0,
                                        state=modifiers.bitmap,
                                        detail=keycode)
        window.send_event(event, propagate=False)
        event = protocol.event.KeyRelease(
            time=X.CurrentTime,
            root=self.root,
            window=window,
            child=X.NONE,
            same_screen=True,  # same screen as the root window
            root_x=0,
            root_y=0,
            event_x=0,
            event_y=0,
            state=modifiers.bitmap,
            detail=keycode)
        window.send_event(event, propagate=False)

    def show_desktop(self, action=None):
        prop_name = self.atom("_NET_SHOWING_DESKTOP")
        if action is True:
            self.send_prop_change_event(prop_name,
                                        (32, [1, X.CurrentTime, 0, 0, 0]))
        elif action is False:
            self.send_prop_change_event(prop_name,
                                        (32, [0, X.CurrentTime, 0, 0, 0]))
        else:
            pv = self.get_prop(self.root, prop_name)
            new_val = 0 if pv and pv[0] else 1
            self.send_prop_change_event(
                prop_name, (32, [new_val, X.CurrentTime, 0, 0, 0]))

    def flush(self):
        # send all pending events
        self.display.flush()

    def sync(self):
        # flush and make sure everything is handled and processed or rejected by the server
        self.display.sync()

    @property
    def display_count(self):
        res = randr.get_screen_resources(self.root)
        n = 0
        for i in res.outputs:
            o = randr.get_output_info(self.root, i, config_timestamp=0)
            if o.modes:
                # has modes, empty if there's no monitor connected here
                n += 1
        return n
コード例 #26
0
class WindowManager(AbstractWindowManager):
    def __init__(self):
        super(WindowManager, self).__init__()
        self.disp = Display()
        self.root = self.disp.screen().root
        self._listen_for_window_property_changes()

        self.NET_ACTIVE_WINDOW = self.disp.intern_atom('_NET_ACTIVE_WINDOW')

        self._active_window = None
        self._update_active_window()

    def run(self):
        self.notify_all()
        while True:  # next_event() sleeps until we get an event
            self._handle_xevent(self.disp.next_event())

    def get_active_program_name(self):
        try:
            return self._active_window.get_wm_class()[1]
        except:
            logger.exception("_xorg.WindowManager.get_active_program_name failed")
            return 'FAILED'

    def _handle_xevent(self, event):
        if event.type != Xlib.X.PropertyNotify:
            return

        if event.atom == self.NET_ACTIVE_WINDOW:
            if self._update_active_window():
                self.notify_all()

    def _update_active_window(self):
        active_win_id = self.root.get_full_property(self.NET_ACTIVE_WINDOW,
                                                    Xlib.X.AnyPropertyType).value[0]
        if self._has_focus_changed(active_win_id):
            new_win = self._window_obj(active_win_id)
            if new_win:
                if self._active_window:
                    self._active_window.change_attributes(event_mask=Xlib.X.NoEventMask)

                self._active_window = new_win
                self._active_window.change_attributes(event_mask=Xlib.X.PropertyChangeMask)
                return True
        return False

    def _listen_for_window_property_changes(self):
        self.root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)

    def _window_obj(self, xid):
        window_obj = None
        if xid:
            try:
                window_obj = self.disp.create_resource_object('window', xid)
            except Xlib.error.XError:
                pass
        return window_obj

    def _has_focus_changed(self, active_win_xid):
        if self._active_window:
            return active_win_xid != self._active_window.id
        return True
コード例 #27
0
ファイル: mwsd.py プロジェクト: TheWorldOfCode/MWS
class mwsd:
    def __init__(self, args):

        self.verbose = args.verbose
        self.ip = "localhost"
        self.port = args.port
        self.ignore = args.ignore

        self.disp = Display()
        self.screen = self.disp.screen()
        self.root = self.screen.root

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.setup_socket()

        self.ids = []
        self.windows = []

        self.status = False
        self.running = True

        self.lock = threading.Lock()

# Communication to daemon

    def setup_socket(self):
        #        self.socket.setblocking(False)
        self.socket.bind((self.ip, self.port))
        self.socket.listen(1)

        # Running the server in a other thread
        self.running = True
        self.thread = threading.Thread(target=self.server_listen)
        self.thread.daemon = True
        self.thread.start()

    def server_listen(self):
        while self.running is True:

            connection, client_address = self.socket.accept()

            try:
                msg = ""
                while True:
                    data = connection.recv(16)

                    if data:
                        msg += data.decode()
                    else:
                        break

                if msg != "":
                    msg_list = msg.split()

                    if self.verbose is True:
                        print(msg)

                    if msg_list[0] == "add":
                        for id in msg_list[1:]:
                            self.add(int(id))
                        connection.sendall("done".encode())
                    elif msg_list[0] == "rm":
                        for id in msg_list[1:]:
                            self.rm(int(id))
                        connection.sendall("done".encode())
                    elif msg_list[0] == "clear":
                        self.clear()
                    elif msg_list[0] == "active":
                        self.active()
                    elif msg_list[0] == "deactive":
                        self.deactive()
                    elif msg_list[0] == "toggle":
                        if self.status is True:
                            self.active()
                        else:
                            self.deactive()
                    elif msg_list[0] == "stop":
                        self.terminate()
                    else:
                        print("Unknown command")
                        connection.sendall("UnknownCommand".encode())

            finally:
                connection.close()

# Actions

    def add(self, id: int):
        self.lock.acquire(blocking=True)
        self.ids.append(id)
        self.windows.append(self.disp.create_resource_object('window', id))
        self.grab(self.windows[-1])
        self.lock.release()

    def rm(self, id: int):
        self.lock.acquire(blocking=True)

        index = self.ids.index(id)
        self.ids.remove(id)
        self.windows.remove(self.windows[index])

        self.lock.release()

    def clear(self):
        self.lock.acquire(blocking=True)

        self.windows.clear()
        self.ids.clear()

        self.lock.release()

    def active(self):
        self.status = True

    def deactive(self):
        self.status = False

    def terminate(self):
        self.running = False

# Daemon main function

    def listen(self):
        while self.running:
            # X11
            if len(self.windows) != 0 and len(self.ids) != 0:
                evt = self.disp.next_event()
                if evt.type in [X.KeyPress]:
                    keycode = evt.detail
                    if self.verbose is True:
                        print("Keycode:", keycode)

                    self.disp.allow_events(X.ReplayKeyboard, X.CurrentTime)
                    if self.status is True:
                        for window in self.windows:
                            self.press(window, keycode, evt.state)
                    else:
                        index = self.ids.index(evt.window.id)
                        self.press(self.windows[index], keycode, evt.state)

                if evt.type == X.DestroyNotify:
                    try:
                        self.rm(evt.window.id)
                    except ValueError:
                        pass

# X11

    def event(self, name, window, detail, state):
        return name(time=X.CurrentTime,
                    root=self.root,
                    window=window,
                    same_screen=0,
                    child=Xlib.X.NONE,
                    root_x=0,
                    root_y=0,
                    event_x=0,
                    event_y=0,
                    state=state,
                    detail=detail)

    def press(self, window, keycode, mask=X.NONE):
        window.send_event(self.event(event.KeyPress, window, keycode, mask),
                          propagate=True)
        window.send_event(self.event(event.KeyRelease, window, keycode, mask),
                          propagate=True)
        self.disp.flush()
        self.disp.sync()

    def grab(self, window):
        window.grab_key(X.AnyKey, X.AnyModifier, True, X.GrabModeAsync,
                        X.GrabModeAsync)

        # Ungrab window manager shortcuts (Super + ...)
        for key in self.ignore:
            window.ungrab_key(key, X.AnyModifier, True)

        window.change_attributes(event_mask=X.KeyReleaseMask | X.KeyPressMask
                                 | X.StructureNotifyMask)

    def ungrab(self, window):
        window.ungrab_key(X.AnyKey, X.AnyModifier, True)


# Cleanup

    def cleanup(self):
        self.running = False
コード例 #28
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        try:
            GObject.GObject.__init__(self)
            threading.Thread.__init__(self)
            self.setDaemon(True)

            self.keymap = Gdk.Keymap().get_default()
            self.display = Display()
            self.screen = self.display.screen()
            self.window = self.screen.root
            self.showscreen = Wnck.Screen.get_default()
            self.ignored_masks = self.get_mask_combinations(X.LockMask
                                                            | X.Mod2Mask
                                                            | X.Mod5Mask)
            self.map_modifiers()
            self.raw_keyval = None
            self.keytext = ""
        except Exception as cause:
            print(("init keybinding error: \n", str(cause)))
            self.display = None
            return None

    def is_hotkey(self, key, modifier):
        keymatch = False
        modmatch = False
        modifier = modifier & ~Gdk.ModifierType.SUPER_MASK
        modint = int(modifier)
        if self.get_keycode(key) == self.keycode or self.get_keycode(
                key) == 134:
            keymatch = True
        for ignored_mask in self.ignored_masks:
            if self.modifiers | ignored_mask == modint | ignored_mask:
                modmatch = True
                break
        return keymatch and modmatch

    def map_modifiers(self):
        gdk_modifiers = (Gdk.ModifierType.CONTROL_MASK,
                         Gdk.ModifierType.SHIFT_MASK,
                         Gdk.ModifierType.MOD1_MASK,
                         Gdk.ModifierType.MOD2_MASK,
                         Gdk.ModifierType.MOD3_MASK,
                         Gdk.ModifierType.MOD4_MASK,
                         Gdk.ModifierType.MOD5_MASK,
                         Gdk.ModifierType.SUPER_MASK,
                         Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(
                    0, modifier) or "Mod4" in Gtk.accelerator_name(
                        0, modifier):
                self.known_modifiers_mask |= modifier

    def get_keycode(self, keyval):
        return self.keymap.get_entries_for_keyval(keyval).keys[0].keycode

    def grab(self, key):
        if self.display == None:
            return False
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        self.keycode = self.get_keycode(keyval)
        self.modifiers = int(modifiers)

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode,
                                          mod,
                                          True,
                                          X.GrabModeAsync,
                                          X.GrabModeSync,
                                          onerror=catch)
            result = self.window.grab_key(134,
                                          mod,
                                          True,
                                          X.GrabModeAsync,
                                          X.GrabModeSync,
                                          onerror=catch)
        self.display.flush()
        # sync has been blocking. Don't know why.
        #self.display.sync()
        if catch.get_error():
            return False
        return True

    def ungrab(self):
        if self.display == None:
            return
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)
            self.window.ungrab_key(134, X.AnyModifier, self.window)

    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""

    def set_focus_window(self, window=None):
        if self.display == None:
            return
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            self.window = self.display.create_resource_object(
                "window", window.get_xid())
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in range(mask + 1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        if self.display == None:
            return
        self.running = True
        wait_for_release = False
        showdesktop = True
        while self.running:
            event = self.display.next_event()
            try:
                self.current_event_time = event.time
                if (event.detail == self.keycode and event.type == X.KeyPress
                        and not wait_for_release) or (
                            event.detail == 134 and event.type == X.KeyPress
                            and not wait_for_release):
                    modifiers = event.state & self.known_modifiers_mask
                    if modifiers == self.modifiers:
                        wait_for_release = True
                        self.display.allow_events(X.SyncKeyboard, event.time)
                    else:
                        self.display.allow_events(X.ReplayKeyboard, event.time)
                elif (event.detail == self.keycode
                      and wait_for_release) or (event.detail == 134
                                                and wait_for_release):
                    if event.type == X.KeyRelease:
                        wait_for_release = False
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.SyncKeyboard, event.time)
                elif event.detail == 40 and event.type == X.KeyPress:  #super+d
                    self.display.allow_events(X.SyncKeyboard, event.time)
                elif event.detail == 40 and event.type == X.KeyRelease:  #super+d
                    if showdesktop:
                        self.showscreen.toggle_showing_desktop(True)
                        showdesktop = False
                    else:
                        self.showscreen.toggle_showing_desktop(False)
                        showdesktop = True
                    self.display.allow_events(X.ReplayKeyboard, event.time)
                elif event.detail == 33 and event.type == X.KeyPress:  #super+p
                    self.display.allow_events(X.SyncKeyboard, event.time)
                elif event.detail == 33 and event.type == X.KeyRelease:  #super+p
                    self.display.allow_events(X.ReplayKeyboard, event.time)
                elif event.detail == 26 and event.type == X.KeyPress:  #super+e
                    self.display.allow_events(X.SyncKeyboard, event.time)
                elif event.detail == 26 and event.type == X.KeyRelease:  #super+e
                    os.system("peony &")
                    self.display.allow_events(X.ReplayKeyboard, event.time)
                else:
                    self.display.allow_events(X.ReplayKeyboard, event.time)
            except AttributeError:
                continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
コード例 #29
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__(self)
        threading.Thread.__init__(self)
        self.setDaemon(True)

        self.keymap = capi.get_widget(gdk.gdk_keymap_get_default())
        self.display = Display()
        self.screen = self.display.screen()
        self.window = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask
                                                        | X.Mod5Mask)
        self.map_modifiers()
        self.raw_keyval = None
        self.keytext = ""

    def is_hotkey(self, key, modifier):
        keymatch = False
        modmatch = False
        modifier = modifier & ~Gdk.ModifierType.SUPER_MASK
        modint = int(modifier)
        if self.get_keycode(key) == self.keycode:
            keymatch = True
        for ignored_mask in self.ignored_masks:
            if self.modifiers | ignored_mask == modint | ignored_mask:
                modmatch = True
                break
        return keymatch and modmatch

    def map_modifiers(self):
        gdk_modifiers = (Gdk.ModifierType.CONTROL_MASK,
                         Gdk.ModifierType.SHIFT_MASK,
                         Gdk.ModifierType.MOD1_MASK,
                         Gdk.ModifierType.MOD2_MASK,
                         Gdk.ModifierType.MOD3_MASK,
                         Gdk.ModifierType.MOD4_MASK,
                         Gdk.ModifierType.MOD5_MASK,
                         Gdk.ModifierType.SUPER_MASK,
                         Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(
                    0, modifier) or "Mod4" in Gtk.accelerator_name(
                        0, modifier):
                self.known_modifiers_mask |= modifier

    def get_keycode(self, keyval):
        count = c_int()
        array = (KeymapKey * 10)()
        keys = cast(array, POINTER(KeymapKey))
        gdk.gdk_keymap_get_entries_for_keyval(hash(self.keymap), keyval,
                                              byref(keys), byref(count))
        return keys[0].keycode

    def grab(self, key):
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        self.keycode = self.get_keycode(keyval)
        self.modifiers = int(modifiers)

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode,
                                          mod,
                                          True,
                                          X.GrabModeAsync,
                                          X.GrabModeSync,
                                          onerror=catch)
        self.display.flush()
        # sync has been blocking. Don't know why.
        #self.display.sync()
        if catch.get_error():
            return False
        return True

    def ungrab(self):
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)

    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""

    def set_focus_window(self, window=None):
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            self.window = self.display.create_resource_object(
                "window", gdk.gdk_x11_drawable_get_xid(hash(window)))
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in xrange(mask + 1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            try:
                self.current_event_time = event.time
                if event.detail == self.keycode and event.type == X.KeyPress and not wait_for_release:
                    modifiers = event.state & self.known_modifiers_mask
                    if modifiers == self.modifiers:
                        wait_for_release = True
                        self.display.allow_events(X.AsyncKeyboard, event.time)
                    else:
                        self.display.allow_events(X.ReplayKeyboard, event.time)
                elif event.detail == self.keycode and wait_for_release:
                    if event.type == X.KeyRelease:
                        wait_for_release = False
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.AsyncKeyboard, event.time)
                else:
                    self.display.allow_events(X.ReplayKeyboard, event.time)
            except AttributeError:
                continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
コード例 #30
0
ファイル: keybinding.py プロジェクト: monsta/mintmenu
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)

        self.keymap = Gdk.Keymap().get_default()
        self.display = Display()
        self.screen = self.display.screen()
        self.window = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask)
        self.map_modifiers()
        self.raw_keyval = None
        self.keytext = ""

    def map_modifiers(self):
        gdk_modifiers =(Gdk.ModifierType.CONTROL_MASK, Gdk.ModifierType.SHIFT_MASK, Gdk.ModifierType.MOD1_MASK,
                        Gdk.ModifierType.MOD2_MASK, Gdk.ModifierType.MOD3_MASK, Gdk.ModifierType.MOD4_MASK, Gdk.ModifierType.MOD5_MASK,
                        Gdk.ModifierType.SUPER_MASK, Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(0, modifier) or "Mod4" in Gtk.accelerator_name(0, modifier):
                self.known_modifiers_mask |= modifier

    def grab(self, key):
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        try:
            self.keycode = self.keymap.get_entries_for_keyval(keyval).keys[0].keycode
        except:
            # In Betsy, the get_entries_for_keyval() returns an unamed tuple...
            self.keycode = self.keymap.get_entries_for_keyval(keyval)[1][0].keycode
        self.modifiers = int(modifiers)

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode, mod, True, X.GrabModeAsync, X.GrabModeAsync, onerror=catch)
        self.display.flush()
        # sync has been blocking. Don't know why.
        #self.display.sync()
        if catch.get_error():
            return False
        return True

    def ungrab(self):
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)

    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""

    def set_focus_window(self, window = None):
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            self.window = self.display.create_resource_object("window", window.get_xid())
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in xrange(mask+1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            try:
                self.current_event_time = event.time
                if event.detail == self.keycode and event.type == X.KeyPress and not wait_for_release:
                    modifiers = event.state & self.known_modifiers_mask
                    if modifiers == self.modifiers:
                        wait_for_release = True
                        self.display.allow_events(X.AsyncKeyboard, event.time)
                    else:
                        self.display.allow_events(X.ReplayKeyboard, event.time)
                elif event.detail == self.keycode and wait_for_release:
                    if event.type == X.KeyRelease:
                        wait_for_release = False
                        GLib.idle_add(self.idle)
                    self.display.allow_events(X.AsyncKeyboard, event.time)
                else:
                    self.display.send_event(self.window, event, X.KeyPressMask | X.KeyReleaseMask, True)
                    self.display.allow_events(X.ReplayKeyboard, event.time)
                    wait_for_release = False
            except AttributeError:
                continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
コード例 #31
0
ファイル: _window_x11.py プロジェクト: MeeperMogle/HTTPi
class Window(object):
    def __init__(self, win_id):
        self.dpy = Display()
        self.screen = self.dpy.screen()
        self.root = self.screen.root
        self._hwnd = self.dpy.create_resource_object('window', win_id)

    def set_position(self, x, y, width, height):
        """Set window top-left corner position and size"""
        self._hwnd.configure(x=x, y=y, width=width, height=height)
        self.dpy.sync()

    def move(self, x, y):
        """Move window top-left corner to position"""
        self._hwnd.configure(x=x, y=y)
        self.dpy.sync()

    def resize(self, width, height):
        """Change window size"""
        self._hwnd.configure(width=width, height=height)
        self.dpy.sync()

    def maximize(self):
        win_send_event(self.root, self._hwnd, NET_WM_STATE, [
            NET_WM_STATE_TOGGLE, NET_WM_STATE_MAXIMIZED_HORZ,
            NET_WM_STATE_MAXIMIZED_VERT
        ])
        self.dpy.sync()

    def set_foreground(self):
        self._hwnd.set_input_focus(X.RevertToParent, X.CurrentTime)
        win_send_event(self.root, self._hwnd, NET_WM_STATE,
                       [NET_WM_STATE_ADD, NET_WM_STATE_ABOVE])
        self.dpy.sync()

    def minimize(self):
        win_send_event(self.root, self._hwnd, WM_CHANGE_STATE,
                       [Xutil.IconicState])
        self.dpy.sync()

    def restore(self):
        self._hwnd.map()
        self.dpy.sync()

    def close(self):
        win_send_event(self.root, self._hwnd, NET_CLOSE_WINDOW, [])
        self.dpy.sync()

    def get_position(self):
        # get_geometry() in KDE5 always returns zero x and y
        coords = self._hwnd.translate_coords(self.root, 0, 0)
        # translate_coords always returns inverted coordinates
        if coords.x < 0:
            x = abs(coords.x)
        else:
            x = coords.x * -1
        if coords.y < 0:
            y = abs(coords.y)
        else:
            y = coords.y * -1

        return x, y
コード例 #32
0
ファイル: server.py プロジェクト: enzbang/prenestr
class Prenestr(object):

    def __init__(self):
        self.ratio = 0.5
        self.wborder = 10
        self.hborder = 30
        self.disp = Display()
        self.root = self.disp.screen().root

        # we tell the X server we want to catch keyPress event
        self.root.change_attributes(event_mask=X.KeyPressMask)

        self.grab_key(K_L)
        self.grab_key(K_H)
        self.grab_key(K_L, X.Mod4Mask | X.ShiftMask)
        self.grab_key(K_H, X.Mod4Mask | X.ShiftMask)
        self.grab_key(K_T)
        self.grab_key(K_ENTER)
        while True:
            event = self.root.display.next_event()
            if event.type == X.KeyPress:
                self.keypress(event)

    def get_active(self):
        id = self.root.get_full_property(
            self.disp.intern_atom("_NET_ACTIVE_WINDOW"), 0).value[0]
        obj = self.disp.create_resource_object('window', id)
        return (id, obj)

    def _send_event(self, win, ctype, data, mask=None):
        data = (data + ([0] * (5 - len(data))))[:5]
        ev = protocol.event.ClientMessage(window=win,
                                          client_type=ctype, data=(32, (data)))
        self.root.send_event(ev, event_mask=X.SubstructureRedirectMask)

    def workarea(self):
        v = self.root.get_full_property(
            self.disp.intern_atom("_NET_WORKAREA"), 0).value
        return v[0], v[1], v[2], v[3]

    def move(self, win, to='left', y_pos=0, y_nbwin=1):
        id, obj = win
        rx, ry, rw, rh = self.workarea()

        if to == 'left':
            x = rx
            y = ry
            w = rw * self.ratio - self.wborder
            h = rh
        elif to == 'right':
            x = rx + rw * self.ratio + self.wborder
            y = ry + y_pos * (rh / y_nbwin)
            w = rw * (1 - self.ratio) - self.wborder
            h = rh / y_nbwin
            if y_nbwin > 1:
                h = h - self.hborder

        # Reset state
        self._send_event(id,
                self.disp.intern_atom("_NET_WM_STATE"),
                [0, self.disp.intern_atom("_NET_WM_STATE_MAXIMIZED_VERT"),
                    self.disp.intern_atom("_NET_WM_STATE_MAXIMIZED_HORZ")])
        obj.configure(x=x, y=y, width=w, height=h, stack_mode=X.Above)
        self._send_event(id,
                self.disp.intern_atom("_NET_ACTIVE_WINDOW"), [])
        self.disp.flush()

    def grab_key(self, key, mask=X.Mod4Mask, ungrab=False):
        self.root.grab_key(key, mask, 1, X.GrabModeAsync, X.GrabModeAsync)
        if ungrab:
            self.ungrab_list.append(key)

    def ungrab_key(self, key, mask=X.Mod4Mask):
        self.root.ungrab_key(key, mask, 1)

    def tile(self, master='position'):
        current_window = self.get_active()
        win_list = self.root.get_full_property(
            self.disp.intern_atom("_NET_CLIENT_LIST"),
            Xatom.WINDOW).value
        current_desktop = self.root.get_full_property(
            self.disp.intern_atom("_NET_CURRENT_DESKTOP"), 0).value[0]
        desk_list = []
        for win_id in win_list:
            obj = self.disp.create_resource_object('window', win_id)
            windesk = obj.get_full_property(
                self.disp.intern_atom("_NET_WM_DESKTOP"), 0).value[0]
            if windesk == current_desktop:
                # This window is on the current desktop

                # Skip if transient
                transient = obj.get_wm_transient_for()
                if transient and transient != self.root:
                    continue

                # Skip if hidden
                state = obj.get_full_property(
                    self.disp.intern_atom("_NET_WM_STATE"), Xatom.ATOM)
                dock = obj.get_full_property(
                    self.disp.intern_atom("_NET_WM_WINDOW_TYPE"), Xatom.ATOM)

                if (state and self.disp.intern_atom("_NET_WM_STATE_HIDDEN") in state.value
                    or self.disp.intern_atom("_NET_WM_STATE_SKIP_TASKBAR") in state.value
                    or self.disp.intern_atom("_NET_WM_STATE_SKIP_PAGER") in state.value):
                    # hidden
                    continue
                if (dock and self.disp.intern_atom("_NET_WM_WINDOW_TYPE_DOCK") in dock.value
                    and self.disp.intern_atom("_NET_WM_WINDOW_TYPE_TOOLBAR") in dock.value
                    and self.disp.intern_atom("_NET_WM_WINDOW_TYPE_MENU") in dock.value
                    and self.disp.intern_atom("_NET_ACTIVE_WINDOW_TYPE_SPLASH") in dock.value
                    and self.disp.intern_atom("_NET_ACTIVE_WINDOW_TYPE_DIALOG") in dock.value):
                    # hidden
                    continue

                desk_list.append((win_id, obj))

        if not desk_list:
            return

        def get_geom(window):
            wg = window.get_geometry()
            tl = window.translate_coords(self.root, wg.x, wg.y)
            return (-tl.x, -tl.y, wg.width, wg.height)

        geom = [(w, get_geom(w[1])) for w in desk_list]

        if master == 'position':
            left = min(geom, key=lambda l: l[1][0])[0]
        else:
            left = current_window

        self.move(left, to="left")
        others = [w for w in geom if w[0][0] != left[0]]
        others.sort(key=lambda l: l[1][1])

        for pos, win in enumerate(others):
            self.move(win[0], to="right", y_pos=pos, y_nbwin=len(others))


        # Reactivate window
        self._send_event(current_window[0],
                         self.disp.intern_atom("_NET_ACTIVE_WINDOW"), [])

        return

    def keypress(self, event):

        if event.detail == K_H:
            if event.state & X.ShiftMask:
                self.ratio -= 0.1
                if self.ratio < 0:
                    self.ratio = 0
                self.tile()
            else:
                self.move(self.get_active())
        elif event.detail == K_L:
            if event.state & X.ShiftMask:
                self.ratio += 0.1
                if self.ratio > 1:
                    self.ratio = 1
                self.tile()
            else:
                self.move(self.get_active(), to='right')
        elif event.detail == K_T:
            self.tile()
        elif event.detail == K_ENTER:
            self.tile(master='active')
コード例 #33
0
ファイル: overlay.py プロジェクト: trigg/Discover
    def __init__(self, discover, piggyback=None):
        Gtk.Window.__init__(self, type=self.detect_type())
        self.discover = discover
        screen = self.get_screen()
        self.compositing = False
        self.text_font = None
        self.text_size = None
        self.pos_x = None
        self.pos_y = None
        self.width = None
        self.height = None
        self.needsredraw = True
        self.hidden = False
        self.enabled = False

        self.set_size_request(50, 50)
        self.connect('draw', self.overlay_draw)
        # Set RGBA
        screen = self.get_screen()
        visual = screen.get_rgba_visual()
        if not self.get_display().supports_input_shapes():
            log.info("Input shapes not available. Quitting")
            sys.exit(1)
        if visual:
            # Set the visual even if we can't use it right now
            self.set_visual(visual)
        if screen.is_composited():
            self.compositing = True

        self.set_app_paintable(True)
        self.set_untouchable()
        self.set_skip_pager_hint(True)
        self.set_skip_taskbar_hint(True)
        self.set_keep_above(True)
        self.set_decorated(True)
        self.set_accept_focus(False)
        self.set_wayland_state()
        if not piggyback:
            self.show_all()
            if discover.steamos:
                display = Display()
                atom = display.intern_atom("GAMESCOPE_EXTERNAL_OVERLAY")
                opaq = display.intern_atom("_NET_WM_WINDOW_OPACITY")

                topw = display.create_resource_object(
                    "window",
                    self.get_toplevel().get_window().get_xid())

                topw.change_property(atom, Xatom.CARDINAL, 32, [1],
                                     X.PropModeReplace)
                # Keep for reference, but appears to be unnecessary
                # topw.change_property(opaq,
                #                     Xatom.CARDINAL,16,
                #                     [0xffff], X.PropModeReplace)

                log.info("Setting STEAM_EXTERNAL_OVERLAY")
                display.sync()
        self.monitor = 0
        self.align_right = True
        self.align_vert = 1
        self.floating = False
        self.force_xshape = False
        self.context = None
        self.autohide = False
        self.piggyback = None
        self.piggyback_parent = None
        if piggyback:
            self.set_piggyback(piggyback)
コード例 #34
0
class Manager():
    def __init__(self, inkscape_id):
        self.id = inkscape_id
        self.disp = Display()
        self.screen = self.disp.screen()
        self.root = self.screen.root

        self.inkscape = self.disp.create_resource_object('window', inkscape_id)
        self.mode = normal_mode

    def event(self, name, detail, state):
        return name(time=X.CurrentTime,
                    root=self.root,
                    window=self.inkscape,
                    same_screen=0,
                    child=Xlib.X.NONE,
                    root_x=0,
                    root_y=0,
                    event_x=0,
                    event_y=0,
                    state=state,
                    detail=detail)

    def string_to_keycode(self, key):
        keysym = XK.string_to_keysym(key)
        keycode = self.disp.keysym_to_keycode(keysym)
        return keycode

    def press(self, key, mask=X.NONE):
        keycode = self.string_to_keycode(key)
        self.inkscape.send_event(self.event(event.KeyPress, keycode, mask),
                                 propagate=True)
        self.inkscape.send_event(self.event(event.KeyRelease, keycode, mask),
                                 propagate=True)
        self.disp.flush()
        self.disp.sync()

    def grab(self):
        self.inkscape.grab_key(X.AnyKey, X.AnyModifier, True, X.GrabModeAsync,
                               X.GrabModeAsync)

        # Ungrab window manager shortcuts (Super + ...)
        self.inkscape.ungrab_key(self.string_to_keycode('Super'),
                                 X.AnyModifier, True)
        self.inkscape.ungrab_key(self.string_to_keycode('Alt_L'),
                                 X.AnyModifier, True)
        self.inkscape.ungrab_key(self.string_to_keycode('Shift_R'),
                                 X.AnyModifier, True)
        self.inkscape.change_attributes(event_mask=X.KeyReleaseMask
                                        | X.KeyPressMask
                                        | X.StructureNotifyMask)

    def ungrab(self):
        self.inkscape.ungrab_key(X.AnyKey, X.AnyModifier, True)

    def listen(self):
        self.grab()
        while True:
            evt = self.disp.next_event()
            if evt.type in [X.KeyPress, X.KeyRelease]:
                keycode = evt.detail
                keysym = self.disp.keycode_to_keysym(keycode, 0)
                char = XK.keysym_to_string(keysym)
                self.disp.allow_events(X.ReplayKeyboard, X.CurrentTime)

                self.mode(self, evt, char)

            if evt.type == X.DestroyNotify:
                if evt.window.id == self.id:
                    self.ungrab()
                    return
コード例 #35
0
class Environment():
    def __init__(self):
        self.display = Display()
        self.screen = self.display.screen()
        self.root = self.screen.root
        self.region = Region(x=0,
                             y=0,
                             width=self.screen.width_in_pixels,
                             height=self.screen.height_in_pixels)
        self.desktops = []
        self.windows = self.get_window_set()
        self.window_desktop_map = {}
        self.hidden_windows = set()
        self.visible_windows = set()

        for i in range(self.number_of_desktops()):
            LOGGER.debug("\n\n\nCreating Desktop %d" % (i))
            d = Desktop(i, self)
            self.desktops.append(d)
            #d.print_windows()
            d.arrange()

        self.update_desktop_map()
        self.setup_listeners()

        #self.print_hierarchy(self.root, " - ")

    def setup_listeners(self):
        self.root.change_attributes(event_mask=X.SubstructureNotifyMask
                                    | X.PropertyChangeMask)

        anchor = self.root.create_window(0, 0, 1, 1, 1, self.screen.root_depth)

        anchor.xrandr_select_input(randr.RRScreenChangeNotifyMask
                                   | randr.RRCrtcChangeNotifyMask
                                   | randr.RROutputChangeNotifyMask
                                   | randr.RROutputPropertyNotifyMask)

    def update_all_the_things(self):
        self.display = Display()
        self.screen = self.display.screen()
        self.root = self.screen.root
        self.region = Region(x=0,
                             y=0,
                             width=self.screen.width_in_pixels,
                             height=self.screen.height_in_pixels - 32)

        LOGGER.debug("NEW REGION: %s" % (self.region))

        for d in self.desktops:
            d.resize()

        self.setup_listeners()

    def print_hierarchy(self, window, indent):
        children = window.query_tree().children
        for w in children:
            LOGGER.debug(indent, window.get_wm_class())
            self.print_hierarchy(w, indent + '-')

    def interesting_properties(self):
        #_NET_WM_DESKTOP
        # root: _NET_CURRENT_DESKTOP
        LOGGER.debug("Current desktop")
        LOGGER.debug(
            self.root.get_full_property(
                self.display.intern_atom('_NET_CURRENT_DESKTOP'),
                Xatom.CARDINAL).value[0])

    def current_desktop(self):
        return self.root.get_full_property(
            self.display.intern_atom('_NET_CURRENT_DESKTOP'),
            Xatom.CARDINAL).value[0]

    def number_of_desktops(self):
        return self.root.get_full_property(
            self.display.intern_atom('_NET_NUMBER_OF_DESKTOPS'),
            Xatom.CARDINAL).value[0]

    def update_window_states(self):
        window_ids = self.get_window_set(include_hidden=True)
        for window_id in window_ids:
            if self.is_window_hidden(window_id):
                self.hidden_windows.add(window_id)
            else:
                self.visible_windows.add(window_id)

    def update_desktop_map(self):
        self.window_desktop_map = {}
        for d in self.desktops:
            for window_id in d.get_window_set(include_hidden=True):
                self.window_desktop_map[window_id] = d

    def get_window_desktop(self, window):
        if type(window) is long:
            w = self.display.create_resource_object('window', window)
        else:
            w = window

        try:
            value = w.get_full_property(
                self.display.intern_atom('_NET_WM_DESKTOP'),
                Xatom.CARDINAL).value[0]
            if value > self.number_of_desktops():
                return None
            else:
                return value

        except AttributeError:
            return None
        except Xlib.error.BadWindow:
            return None

    def get_window_states(self, window_id):
        w = self.display.create_resource_object('window', window_id)
        #return w.get_full_property(self.display.intern_atom('_NET_WM_STATE'), Xatom.ATOM).value
        try:
            states = w.get_full_property(
                self.display.get_atom('_NET_WM_STATE'), Xatom.WINDOW)
        except Xlib.error.BadWindow:
            LOGGER.warn("Bad window fetching states...")
            states = None

        if states == None:
            return []
        else:
            res = w.get_full_property(self.display.get_atom('_NET_WM_STATE'),
                                      0).value.tolist()
            return res

    def is_window_hidden(self, window_id):
        hidden_state_atom = self.display.get_atom("_NET_WM_STATE_HIDDEN")
        states = self.get_window_states(window_id)
        return hidden_state_atom in states

    def is_window_visible(self, window_id):
        return not self.is_window_hidden(window_id)

    def listen_for_events(self):
        LOGGER.debug("Listening for change events!")
        while True:
            ev = self.display.next_event()
            self.handle_event(ev)

    def handle_event(self, event):
        old_hidden = set(self.hidden_windows)
        old_visible = set(self.visible_windows)
        self.update_window_states()
        changed_ids = set()
        changed_ids.update(old_hidden.symmetric_difference(
            self.hidden_windows))
        changed_ids.update(
            old_visible.symmetric_difference(self.visible_windows))

        if len(changed_ids) > 0:
            LOGGER.debug("Changed IDs: %s" % (changed_ids))

        needs_update = False

        wm_active_window = self.display.get_atom('_NET_ACTIVE_WINDOW')
        wm_move_window = self.display.get_atom('_NET_MOVERESIZE_WINDOW')
        wm_hidden_window = self.display.get_atom('_NET_WM_STATE_HIDDEN')
        wm_state = self.display.get_atom('_NET_WM_STATE')

        try:
            window_props = event.window.get_full_property(event.atom, 0)
            window_id = int(window_props.value.tolist()[0])
            LOGGER.debug("Window ID: %s" % (window_id))
        except AttributeError:
            pass
            #LOGGER.debug("Not a window-level event")

        for window_id in changed_ids:
            desktop = self.window_desktop_map.get(window_id, None)
            LOGGER.debug("Window changed: %s on desktop: %s" %
                         (window_id, desktop))
            if desktop is not None:
                desktop.arrange()
                needs_update = True

        if event.type == X.PropertyNotify:
            LOGGER.debug("Property changed...")
            if event.atom == wm_active_window:
                LOGGER.debug("Property changed on an active window....")

        elif event.type == X.CreateNotify or event.type == X.DestroyNotify:
            needs_update = True
            window_set = self.get_window_set()

            if event.type == X.CreateNotify:
                LOGGER.debug("Handling creation!")
                new_windows = window_set.difference(self.windows)
                for window in new_windows:
                    window_resource = self.display.create_resource_object(
                        'window', window)
                    window_desktop = self.get_window_desktop(window_resource)
                    if window_desktop is not None:
                        self.desktops[window_desktop].layout.add_window(
                            window_resource)

            if event.type == X.DestroyNotify:
                LOGGER.debug("Handling destruction!")
                missing_windows = self.windows.difference(window_set)
                for window in missing_windows:
                    window_resource = self.display.create_resource_object(
                        'window', window)
                    # TODO: optimize lookup by keeping old map?
                    for desktop in self.desktops:
                        LOGGER.debug("Trying to remove from desktop %s" %
                                     (desktop))
                        desktop.layout.remove_window(window_resource)

            self.windows = window_set

            for desktop in self.desktops:
                desktop.layout.redraw()

        elif event.__class__.__name__ == randr.ScreenChangeNotify.__name__:
            LOGGER.debug('Screen change')
            self.update_all_the_things()

        else:
            #LOGGER.debug("Unhandled event: %d" % (event.type))
            pass

        if needs_update:
            self.update_desktop_map()

    def get_window_set(self, include_hidden=False, desktop_number=None):
        windows = set([
            x for x in self.root.get_full_property(
                self.display.intern_atom('_NET_CLIENT_LIST'),
                Xatom.WINDOW).value
        ])

        if desktop_number is not None:
            #LOGGER.debug("Filtering windows not on: %d" % (desktop_number))
            windows = filter(
                lambda w: self.get_window_desktop(w) == desktop_number,
                windows)

        if include_hidden is False:
            #LOGGER.debug("Filtering hidden windows...")
            windows = filter(lambda w: self.is_window_visible(w) == True,
                             windows)

        return set(windows)
コード例 #36
0
def handleQuery(query):
    if not query.isTriggered:
        return []

    try:
        items = []

        # Prepare query string
        input = query.string
        needles = cgi.escape(input.lower()).strip().split(' ')

        # Create display handle
        display = Display()

        # Intern a few atoms we will use later
        NET_CLIENT_LIST = display.intern_atom('_NET_CLIENT_LIST')
        NET_WM_WINDOW_TYPE = display.intern_atom('_NET_WM_WINDOW_TYPE')
        NET_WM_WINDOW_TYPE_NORMAL = display.intern_atom(
            '_NET_WM_WINDOW_TYPE_NORMAL')
        NET_WM_NAME = display.intern_atom('_NET_WM_NAME')

        # Get the IDs of all windows on the display
        root = display.screen().root
        win_list = root.get_full_property(NET_CLIENT_LIST,
                                          X.AnyPropertyType).value

        for id in win_list:
            # If the user already typed something new, the query is cancelled
            # and we should just stop wasting resources
            if not query.isValid:
                return []

            # Get the window associated with that ID
            win = display.create_resource_object('window', id)

            # Check if the window type is "normal window"
            win_type = win.get_full_property(NET_WM_WINDOW_TYPE,
                                             X.AnyPropertyType).value[0]
            if win_type == NET_WM_WINDOW_TYPE_NORMAL:
                # Obtain the name of the window. Windows without the `_NET_WM_NAME`
                # property will be ignored
                name = win.get_full_property(NET_WM_NAME, X.AnyPropertyType)
                if not name:
                    continue

                name = name.value.decode('utf-8')

                # Apply filter to the name
                lowercase_name = name.lower()
                is_ok = True
                for needle in needles:
                    if needle not in lowercase_name:
                        is_ok = False
                        break

                if not is_ok:
                    continue

                for needle in needles:
                    start = lowercase_name.find(needle)
                    end = start + len(needle)
                    name = name[:start] + "<b>" + name[
                        start:end] + "</b>" + name[end:]
                    lowercase_name = name.lower()

                # Add the item
                def activate_win(id):
                    call(['xdotool', 'windowactivate', str(id)])

                # Generate icon
                icon_path = gen_icon(display, id, win)

                item = Item(id=__prettyname__, completion=query.rawString)
                item.text = name  #cgi.escape(str(type(name)))
                item.subtext = "Switch to"
                item.icon = icon_path
                item.addAction(
                    FuncAction("Switch to", lambda id=id: activate_win(id)))
                items.append(item)

        return items

    # We never know what could go wrong...
    except Exception as e:
        item = Item(id=__prettyname__, completion=query.rawString)
        item.text = e.__class__.__name__
        item.subtext = str(e)
        return item
コード例 #37
0
ファイル: xutil.py プロジェクト: Stefantb/ueberzug
def get_pid_by_window_id(display: Xdisplay.Display, window_id: int):
    window = display.create_resource_object('window', window_id)
    prop = window.get_full_property(display.intern_atom('_NET_WM_PID'),
                                    Xlib.X.AnyPropertyType)
    return (prop.value[0] if prop else None)
コード例 #38
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

    def __init__(self):
        GObject.GObject.__init__(self)
        threading.Thread.__init__(self)
        self.setDaemon(True)

        self.keymap = Gdk.Keymap().get_default()
        self.display = Display()
        self.screen = self.display.screen()
        self.window = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask
                                                        | X.Mod5Mask)
        self.map_modifiers()
        self.raw_keyval = None
        self.keytext = ""

    def map_modifiers(self):
        gdk_modifiers = (Gdk.ModifierType.CONTROL_MASK,
                         Gdk.ModifierType.SHIFT_MASK,
                         Gdk.ModifierType.MOD1_MASK,
                         Gdk.ModifierType.MOD2_MASK,
                         Gdk.ModifierType.MOD3_MASK,
                         Gdk.ModifierType.MOD4_MASK,
                         Gdk.ModifierType.MOD5_MASK,
                         Gdk.ModifierType.SUPER_MASK,
                         Gdk.ModifierType.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            if "Mod" not in Gtk.accelerator_name(
                    0, modifier) or "Mod4" in Gtk.accelerator_name(
                        0, modifier):
                self.known_modifiers_mask |= modifier

    def grab(self, key):
        accelerator = key
        accelerator = accelerator.replace("<Super>", "<Mod4>")
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False

        self.keytext = key
        try:
            self.keycode = self.keymap.get_entries_for_keyval(
                keyval).keys[0].keycode
        except AttributeError:
            # In older Gtk3 the get_entries_for_keyval() returns an unnamed tuple...
            self.keycode = self.keymap.get_entries_for_keyval(
                keyval)[1][0].keycode
        self.modifiers = int(modifiers)

        # Request to receive key press/release reports from other windows that may not be using modifiers
        catch = error.CatchError(error.BadWindow)
        if self.modifiers:
            self.window.change_attributes(onerror=catch,
                                          event_mask=X.KeyPressMask
                                          | X.KeyReleaseMask)
        else:
            self.window.change_attributes(onerror=catch,
                                          event_mask=X.NoEventMask)
        if catch.get_error():
            return False

        catch = error.CatchError(error.BadAccess)
        for ignored_mask in self.ignored_masks:
            mod = modifiers | ignored_mask
            result = self.window.grab_key(self.keycode,
                                          mod,
                                          True,
                                          X.GrabModeAsync,
                                          X.GrabModeAsync,
                                          onerror=catch)
        self.display.flush()
        if catch.get_error():
            return False

        catch = error.CatchError(error.BadCursor)
        if not self.modifiers:
            # We grab Super+click so that we can forward it to the window manager and allow Super+click bindings (window move, resize, etc.)
            self.window.grab_button(X.AnyButton, X.Mod4Mask, True,
                                    X.ButtonPressMask, X.GrabModeSync,
                                    X.GrabModeAsync, X.NONE, X.NONE)
        self.display.flush()
        if catch.get_error():
            return False

        return True

    def ungrab(self):
        if self.keycode:
            self.window.ungrab_key(self.keycode, X.AnyModifier, self.window)

    def rebind(self, key):
        self.ungrab()
        if key != "":
            self.grab(key)
        else:
            self.keytext = ""

    def set_focus_window(self, window=None):
        self.ungrab()
        if window is None:
            self.window = self.screen.root
        else:
            self.window = self.display.create_resource_object(
                "window", window.get_xid())
        self.grab(self.keytext)

    def get_mask_combinations(self, mask):
        return [x for x in range(mask + 1) if not (x & ~mask)]

    def idle(self):
        self.emit("activate")
        return False

    def activate(self):
        GLib.idle_add(self.run)

    # Get which window manager we're currently using (Marco, Compiz, Metacity, etc...)
    def get_wm(self):
        name = ''
        wm_check = self.display.get_atom('_NET_SUPPORTING_WM_CHECK')
        win_id = self.window.get_full_property(wm_check, X.AnyPropertyType)
        if win_id:
            w = self.display.create_resource_object("window", win_id.value[0])
            wm_name = self.display.get_atom('_NET_WM_NAME')
            prop = w.get_full_property(wm_name, X.AnyPropertyType)
            if prop:
                name = prop.value
        return name.lower()

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()

            if self.modifiers:
                # Use simpler logic when using traditional combined keybindings
                modifiers = event.state & self.known_modifiers_mask
                if event.type == X.KeyPress and event.detail == self.keycode and modifiers == self.modifiers:
                    GLib.idle_add(self.idle)

            else:
                try:
                    # KeyPress
                    if event.type == X.KeyPress and event.detail == self.keycode and not wait_for_release:
                        modifiers = event.state & self.known_modifiers_mask
                        if modifiers == self.modifiers:
                            wait_for_release = True

                    # KeyRelease
                    elif event.type == X.KeyRelease and event.detail == self.keycode and wait_for_release:
                        GLib.idle_add(self.idle)
                        wait_for_release = False

                    # Modifiers are often used with mouse events - don't let the system swallow those
                    elif event.type == X.ButtonPress:
                        self.display.allow_events(X.ReplayPointer,
                                                  X.CurrentTime)
                        # Compiz would rather not have the event sent to it and just read it from the replayed queue
                        wm = self.get_wm()
                        if wm != "compiz":
                            self.display.ungrab_keyboard(X.CurrentTime)
                            self.display.ungrab_pointer(X.CurrentTime)
                            query_pointer = self.window.query_pointer()
                            self.display.send_event(query_pointer.child, event,
                                                    X.ButtonPressMask, True)
                        wait_for_release = False

                    # If the user presses another key in between the KeyPress and the KeyRelease, they
                    # meant to use a different shortcut
                    else:
                        self.display.ungrab_keyboard(X.CurrentTime)
                        # Send the event up in case another window is listening to it
                        self.display.send_event(
                            event.window, event,
                            X.KeyPressMask | X.KeyReleaseMask, True)
                        wait_for_release = False
                except AttributeError:
                    continue

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()