Esempio n. 1
0
def loop(dpy: Display, actions: dict):
    try:
        while True:
            evt = dpy.next_event()
            process(dpy, actions, evt)
    finally:
        dpy.close()
Esempio n. 2
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()
Esempio n. 3
0
class XTestSendContext(object):

    """
    This class manages a connection to the X-Server and allows to send key events.
    """

    def __init__(self):
        # open a connection to the x server
        self.display = Display()

        # get the root window of the default screen
        self.root = self.display.screen().root

    def send_key_event(self, key_code, key_down):
        """
        Sends a key event to the focused window using python-xlibs fake_input method.

        :param key_code: Integer code of the key event that should be sent
        :param key_down: True = key press event, False = key release event
        """
        # select the right event type depending on key_down
        event_type = X.KeyPress if key_down else X.KeyRelease

        # fake keyboard event
        fake_input(self.display, event_type, key_code)

        # sync connection to ensure that the input is actually sent to the x server
        self.display.sync()

    def close(self):
        """
        Closes the connection to the x server
        """
        self.display.close()
Esempio n. 4
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()
Esempio n. 5
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()
Esempio n. 6
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()
Esempio n. 7
0
 def stop(self):
     if self.record_thread.is_alive():
         conn = Display()
         conn.record_disable_context(self.context)
         conn.close()
         print('display stopped recording')
         self.record_thread.join()
     print('recording thread ended')
Esempio n. 8
0
 def stop(self):
     # hack for unreleased context
     # https://github.com/SavinaRoja/PyUserInput/issues/48
     from Xlib.display import Display
     display = Display()
     display.record_disable_context(self.ctx)
     display.close()
     return super().stop()
Esempio n. 9
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()
Esempio n. 10
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()
Esempio n. 11
0
def Xdisplay():
    disp = None
    try:
        disp = Display()
        yield disp
    except:
        if disp is not None:
            disp.close()
        raise
Esempio n. 12
0
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()
Esempio n. 13
0
 def get_min_resolution(DISPLAY=None):
     if DISPLAY is None:
         DISPLAY = getenv('DISPLAY', ':0')
     display = Display(DISPLAY)
     try:
         n_screens = display.screen_count()
         heights = set()
         for idx in range(n_screens):
             screen = display.screen(idx)
             heights.add(screen['height_in_pixels'])
         return min(heights)
     finally:
         display.close()
Esempio n. 14
0
class Record:
    def __init__(self):

        self.record_thread = threading.Thread(
            target=self._record, name='x keyboard listener thread')
        self.recording_connection = Display()
        self.recording_connection.set_error_handler(
            self._record_display_error_handler)

        if not self.recording_connection.has_extension("RECORD"):
            raise Exception("RECORD extension not found")

        r = self.recording_connection.record_get_version(0, 0)
        print("RECORD extension version %d.%d" %
              (r.major_version, r.minor_version))
        self.context = self.recording_connection.record_create_context(
            0, [record.AllClients], CONTEXT_FILTER)

    def start(self):
        self.recording_connection.sync()
        self.record_thread.start()

    def stop(self):
        if self.record_thread.is_alive():
            conn = Display()
            conn.record_disable_context(self.context)
            conn.close()
            print('display stopped recording')
            self.record_thread.join()
        print('recording thread ended')

    #
    # xlib plugs
    #
    def _record(self):
        self.recording_connection.record_enable_context(
            self.context, self.handler)
        self.recording_connection.record_free_context(self.context)
        self.recording_connection.close()

    def _record_display_error_handler(self, exception, *args):
        print('Error at record display: {}'.format(exception), file=sys.stderr)

    def handler(self, reply):
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(
                data, self.recording_connection.display, None, None)

            if event.type == X.KeyPress:
                format_key_event(event)
Esempio n. 15
0
def main(argv):
    display = Display()

    thread = EventThread(display)
    thread.start()
    time.sleep(1)

    screen = display.screen()

    # The get_property call should not deadlock, despite the blocking next_event
    # call in the thread.
    atom = display.intern_atom('_XROOTPMAP_ID', True)
    response = screen.root.get_property(atom, Xatom.PIXMAP, 0, 1)
    print('get_property response: %r' % response)

    display.close()
Esempio n. 16
0
def initMouseAndGetSquare():
    """ init gtk window and grab mouse """
    w = gtk.gdk.get_default_root_window()
    """change cursor"""
    cursor = gtk.gdk.Cursor(gtk.gdk.CROSSHAIR)
    gtk.gdk.pointer_grab(w, 
                         False,
                         0,
                         None,
                         cursor, 
                         0)
    """ first grab all mouse events """
    display = Display(':0')
    root = display.screen().root
    root.grab_pointer(True, X.ButtonPressMask | X.ButtonReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)
    mouse_handle = listenToMouse()
    mouse_handle.run()
    display.close()
    """release mouse"""
    gtk.gdk.pointer_ungrab()
    del display
    return w
Esempio n. 17
0
class XInputSendContext(object):

    """
    This class manages a connection to the X-Server and allows to send key events.
    """

    def __init__(self):
        # open a connection to the x server
        self.display = Display()

        # get the root window of the default screen
        self.root = self.display.screen().root

    def send_key_event(self, key_code, key_down):
        """
        Sends a key event to the focused window using python-xlibs send_input method.

        :param key_code: Integer code of the key event that should be sent
        :param key_down: True = key press event, False = key release event
        """
        # get the window that has the input focus
        focus_window = self.display.get_input_focus().focus

        # select the right event class depending on key_down
        event_class = KeyPress if key_down else KeyRelease

        # create event
        event = event_class(time=X.CurrentTime, root=self.root, window=focus_window,
                            same_screen=0, child=0, root_x=0, root_y=0, event_x=0, event_y=0,
                            state=0, detail=key_code)

        # send event to the window that has the input focus
        focus_window.send_event(event)

    def close(self):
        """
        Closes the connection to the x server
        """
        self.display.close()
Esempio n. 18
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.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()
Esempio n. 19
0
class WM(object):
    def __init__(self):
        self.display = Display()
        self.root_win = self.display.screen().root
        self.go_on = True  # var to keep looping events (or not)
        self.notifs_on = False
        self.poweroff_time = 0
        clear_log()  # clear the log file once
        # kobo touch screen dimension: 600x800px (minus the dock)
        self.full_width = 600
        self.full_height = 740
        self.keyboard_height = 0
        self.keyboard_on = False
        self.active_window = None  # may be transient
        self.top_win_list = []  # list of the top window to cycle in
        self.top_win_pos = -1  # postition in the top win list, -1 means you have to start over
        self.transient_of = {
        }  # key: win, val: set of windows transient for win
        # windows of wm-related apps
        self.wm_keyboard, self.wm_launcher, self.wm_dock, self.wm_notifs = None, None, None, None
        # codes for the keys to catch
        self.f1_codes = set(
            code for code, index in self.display.keysym_to_keycodes(XK.XK_F1))
        self.f2_codes = set(
            code for code, index in self.display.keysym_to_keycodes(XK.XK_F2))
        self.f3_codes = set(
            code for code, index in self.display.keysym_to_keycodes(XK.XK_F3))
        self.f4_codes = set(
            code for code, index in self.display.keysym_to_keycodes(XK.XK_F4))
        self.f9_codes = set(
            code for code, index in self.display.keysym_to_keycodes(XK.XK_F9))
        XK.load_keysym_group('xf86')
        self.poweroff_codes = set(
            code for code, index in self.display.keysym_to_keycodes(
                XK.XK_XF86_PowerOff))
        self.poweroff_codes.update(
            set(code
                for code, index in self.display.keysym_to_keycodes(XK.XK_F12)))
        self.launch1_codes = set(
            code for code, index in self.display.keysym_to_keycodes(
                XK.XK_XF86_Launch1))
        self.launch1_codes.update(
            set(code
                for code, index in self.display.keysym_to_keycodes(XK.XK_F11)))
        # error catcher
        error_catcher = CatchError(BadAccess)
        self.root_win.change_attributes(
            event_mask=X.SubstructureRedirectMask,
            onerror=error_catcher,
            background_pixel=self.display.screen().white_pixel)
        self.display.sync()
        error = error_catcher.get_error()
        if error:
            sys.exit(1)
        # grab root window key events
        self.grab_root_key(self.poweroff_codes, X.NONE)
        self.grab_root_key(self.launch1_codes, X.NONE)
        self.grab_root_key(self.f1_codes, X.NONE)
        self.grab_root_key(self.f2_codes, X.NONE)
        self.grab_root_key(self.f3_codes, X.NONE)
        self.grab_root_key(self.f4_codes, X.NONE)
        self.grab_root_key(self.f9_codes, X.NONE)
        # handlers
        self.display.set_error_handler(self.x_error_handler)
        self.event_dispatch_table = {
            X.MapRequest: self.handle_map_request,
            X.ConfigureRequest: self.handle_configure_request,
            X.MappingNotify: self.handle_mapping_notify,
            X.UnmapNotify: self.handle_unmapping_notify,
            X.KeyPress: self.handle_key_press,
            X.KeyRelease: self.handle_key_release
        }

    def grab_root_key(self, codes, modifier):
        for code in codes:
            self.root_win.grab_key(code, modifier, 1, X.GrabModeAsync,
                                   X.GrabModeAsync)

    # top level window utility functions

    def win_show(self):
        window = self.top_win_list[self.top_win_pos]  # assumes it exists
        # map the window
        window.map()
        # map transient window if any
        if window in self.transient_of:
            win = None
            for win in self.transient_of[window]:
                win.map()
            # use last transient as active window
            if win:
                self.active_window = win
            else:
                self.active_window = window
        else:
            # set the window as the active one
            self.active_window = window

    def win_hide(self):
        window = self.top_win_list[self.top_win_pos]  # assumes it exists
        # unmap the window
        window.unmap()
        # un map transient window if any
        if window in self.transient_of:
            for win in self.transient_of[window]:
                win.unmap()
        # unset active window
        self.active_window = None

    def win_remove(self):
        window = self.top_win_list.pop(self.top_win_pos)  # assumes it exists
        # remove entry in transient dict if any
        if window in self.transient_of:
            del self.transient_of[window]
        window.destroy()
        self.active_window = None

    # event handling functions

    def x_error_handler(self, err, request):
        log('X protocol error: {0}'.format(err))

    def loop(self):
        # Load every wm app before starting the actual loop
        try:
            self.load_wmapps()
        except KeyboardInterrupt:
            raise
        # Loop until go_on, Ctrl+C or exceptions > MAX_EXCEPTION times.
        errors = 0
        while self.go_on:
            try:
                self.handle_event()
            except KeyboardInterrupt:
                raise
            except:
                errors += 1
                if errors > MAX_EXCEPTIONS:
                    sys.exit(1)
        close_log()
        self.display.close()

    def load_wmapps(self):
        # launch the other apps:
        python_path = find_full_path('python')
        keyboard_path = find_full_path('matchbox-keyboard')
        if not keyboard_path or not python_path:
            raise KeyboardInterrupt
        system([python_path, kobowm_path + '/launcher.py'])
        system([python_path, kobowm_path + '/dock.py'])
        system([python_path, kobowm_path + '/notifzmq.py'])
        system([keyboard_path])
        # catch the events until every wm app has a window
        while not all((self.wm_notifs, self.wm_keyboard, self.wm_launcher,
                       self.wm_dock)):
            try:
                event = self.display.next_event()
            except ConnectionClosedError:
                log('Display connection closed by server')
                raise KeyboardInterrupt
            # ignore events that are not map requests
            if event.type == X.MapRequest:
                event.window.map()
                if str(event.window.get_wm_name()) == 'Keyboard':
                    self.wm_keyboard = event.window
                    self.keyboard_height = event.window.get_geometry().height
                    event.window.configure(x=0,
                                           y=self.full_height -
                                           self.keyboard_height,
                                           width=self.full_width)
                    # catch the keyboard events to later redirect them to the active window
                    event.window.change_attributes(event_mask=X.KeyPressMask
                                                   | X.KeyReleaseMask)
                    event.window.unmap()
                elif str(event.window.get_wm_name()) == 'kobowm-dock':
                    self.wm_dock = event.window
                    event.window.configure(x=0,
                                           y=self.full_height,
                                           width=self.full_width,
                                           height=60)
                    event.window.unmap()
                elif str(event.window.get_wm_name()) == 'kobowm-launcher':
                    self.wm_launcher = event.window
                    event.window.configure(x=0,
                                           y=0,
                                           height=self.full_height,
                                           width=self.full_width)
                    event.window.unmap()
                elif str(event.window.get_wm_name()) == 'kobowm-notifications':
                    self.wm_notifs = event.window
                    event.window.configure(x=380, y=20, height=100, width=200)
                    event.window.unmap()
                else:
                    # there is an unexpexted window: stop
                    raise KeyboardInterrupt
        # finally map again the dock
        self.wm_dock.map()

    def handle_event(self):
        try:
            event = self.display.next_event()
        except ConnectionClosedError:
            log('Display connection closed by server')
            raise KeyboardInterrupt
        if event.type in self.event_dispatch_table:
            self.event_dispatch_table[event.type](event)
        else:
            log('unhandled event: {event}'.format(event=event))

    def handle_configure_request(self, event):
        window = event.window
        args = {'border_width': 1}
        if event.value_mask & X.CWX:
            args['x'] = event.x
        if event.value_mask & X.CWY:
            args['y'] = event.y
        if event.value_mask & X.CWWidth:
            args['width'] = event.width
        if event.value_mask & X.CWHeight:
            args['height'] = event.height
        if event.value_mask & X.CWSibling:
            args['sibling'] = event.above
        if event.value_mask & X.CWStackMode:
            args['stack_mode'] = event.stack_mode
        window.configure(**args)

    def handle_map_request(self, event):
        event.window.map()
        # handle transient windows
        transient_for = event.window.get_wm_transient_for()
        if transient_for:
            self.active_window = event.window
            if transient_for not in self.transient_of:
                self.transient_of[transient_for] = []
            self.transient_of[transient_for].append(event.window)
        else:
            if self.active_window:
                self.active_window.unmap()
            self.active_window = event.window
            self.top_win_list.append(event.window)
            self.top_win_pos = len(self.top_win_list) - 1
        # use all the available screen
        self.active_window.configure(x=-1,
                                     y=-1,
                                     width=self.full_width,
                                     height=self.full_height)
        # hide the keyboard if it was open
        if self.keyboard_on:
            self.wm_keyboard.unmap()
            self.keyboard_on = False

    def handle_mapping_notify(self, event):
        # necessary by documentation
        self.display.refresh_keyboard_mapping(event)

    def handle_unmapping_notify(self, event):
        # used to handle windows that get unmapped not by this wm directly
        transient_for = event.window.get_wm_transient_for()
        if transient_for:
            self.transient_of[transient_for].remove(event.window)
            if self.active_window == event.window:
                self.active_window = transient_for
        elif event.window in self.top_win_list:
            self.top_win_list.remove(event.window)
            if self.active_window == event.window:
                self.active_window = None
                self.top_win_pos = -1

    def handle_key_press(self, event):
        if event.window == self.wm_keyboard:
            return  # do nothing: will be sent to the active window on release
        if event.detail in self.poweroff_codes:
            self.go_on = False
        elif event.detail in self.launch1_codes:
            self.action_apps()
        elif event.detail in self.f1_codes:
            self.action_tasks()
        elif event.detail in self.f2_codes:
            self.action_keyboard()
        elif event.detail in self.f3_codes:
            system(XTERM_COMMAND)
        elif event.detail in self.f4_codes:
            self.action_close()
        elif event.detail in self.f9_codes:
            self.action_notifs()

    def handle_key_release(self, event):
        if event.window == self.wm_keyboard:
            # focus on the active window and emulate key press/release
            self.display.sync()
            self.display.set_input_focus(self.active_window, X.RevertToParent,
                                         X.CurrentTime)
            fake_input(self.display, X.KeyPress, event.detail)
            fake_input(self.display, X.KeyRelease, event.detail)
            self.display.sync()

    # action performer functions

    def action_apps(self):
        if not self.active_window:
            self.active_window = self.wm_launcher
            self.active_window.map()
        elif self.active_window == self.wm_launcher:
            self.active_window.unmap()
            self.active_window = None
        else:
            # hide the active window (and the stack if it's transient)
            self.win_hide()
            # start over with the cycling
            self.top_win_pos = -1
            self.active_window = self.wm_launcher
            self.active_window.map()

    def action_tasks(self):
        if not self.top_win_list:
            return
        if self.top_win_pos != -1 and self.top_win_pos < len(
                self.top_win_list):
            self.win_hide()
        self.top_win_pos += 1
        if self.top_win_pos >= len(self.top_win_list):
            self.top_win_pos = 0
        self.win_show()

    def action_keyboard(self):
        if self.keyboard_on:
            self.wm_keyboard.unmap()
            self.active_window.configure(height=self.full_height)
            self.keyboard_on = False
        elif self.active_window and self.active_window != self.wm_launcher:
            self.wm_keyboard.map()
            self.active_window.configure(height=self.full_height -
                                         self.keyboard_height)
            self.wm_keyboard.configure(stack_mode=X.Above)
            self.keyboard_on = True

    def action_close(self):
        if not self.active_window:
            return  # nothing to close here
        if self.active_window in self.top_win_list:
            self.win_remove()
        else:
            # it's a transient window
            transient_for = self.active_window.get_wm_transient_for()
            self.transient_of[transient_for].remove(self.active_window)
            self.active_window.destroy()
            self.active_window = transient_for
        # close the keyboard if open
        if self.keyboard_on:
            self.wm_keyboard.unmap()
            self.keyboard_on = False

    def action_notifs(self):
        if self.notifs_on:
            self.wm_notifs.unmap()
            log('Notification window hidden')
        else:
            self.wm_notifs.configure(stack_mode=X.Above)
            self.wm_notifs.map()
            log('Notification window visible')
        self.notifs_on = not self.notifs_on
Esempio n. 20
0
        'get_memory_bus_width': display.nvcontrol_get_memory_bus_width(gpu),
        'get_total_dedicated_gpu_memory': display.nvcontrol_get_total_dedicated_gpu_memory(gpu),
        'get_used_dedicated_gpu_memory': display.nvcontrol_get_used_dedicated_gpu_memory(gpu),
        'get_curr_pcie_link_width': display.nvcontrol_get_curr_pcie_link_width(gpu),
        'get_max_pcie_link_width': display.nvcontrol_get_max_pcie_link_width(gpu),
        'get_curr_pcie_link_generation': display.nvcontrol_get_curr_pcie_link_generation(gpu),
        'get_encoder_utilization': display.nvcontrol_get_encoder_utilization(gpu),
        'get_decoder_utilization': display.nvcontrol_get_decoder_utilization(gpu),
        'get_current_performance_level': display.nvcontrol_get_current_performance_level(gpu),
        'get_gpu_nvclock_offset': display.nvcontrol_get_gpu_nvclock_offset(gpu, perf_level),
        'get_mem_transfer_rate_offset': display.nvcontrol_get_mem_transfer_rate_offset(gpu, perf_level),
        'get_cooler_manual_control_enabled': display.nvcontrol_get_cooler_manual_control_enabled(gpu),
        'get_fan_duty': display.nvcontrol_get_fan_duty(fan),
        'get_fan_rpm': display.nvcontrol_get_fan_rpm(fan),
        'get_coolers_used_by_gpu': display.nvcontrol_get_coolers_used_by_gpu(gpu),
        'get_max_displays': display.nvcontrol_get_max_displays(gpu),
        'get_name': display.nvcontrol_get_name(gpu),
        'get_driver_version': display.nvcontrol_get_driver_version(gpu),
        'get_vbios_version': display.nvcontrol_get_vbios_version(gpu),
        'get_gpu_uuid': display.nvcontrol_get_gpu_uuid(gpu),
        'get_utilization_rates': display.nvcontrol_get_utilization_rates(gpu),
        'get_performance_modes': display.nvcontrol_get_performance_modes(gpu),
        'get_gpu_nvclock_offset_range': display.nvcontrol_get_gpu_nvclock_offset_range(gpu, perf_level),
        'get_mem_transfer_rate_offset_range': display.nvcontrol_get_mem_transfer_rate_offset_range(gpu, perf_level),
        'get_clock_info': display.nvcontrol_get_clock_info(gpu)
    }

    pprint(dic)

    display.close()
Esempio n. 21
0
class TrayerWatch(EventInput):
    def __init__(self, args=None):
        command = ['trayer']
        self.default_args = {
            'edge': 'top',
            'align': 'right',
            'widthtype': 'request',
            'expand': 'true',
            'SetDockType': 'true',
            'transparent': 'true',
            'alpha': '0',
            'height': '16',
            'margin': '0',
            'tint': '0x29b2e',
        }
        if args is not None:
            self.default_args.update(args)
        for key, val in self.default_args.items():
            command += ["--%s" % (key), str(val)]

        super(TrayerWatch, self).__init__(command)
        self.proc.stdin.close()
        self.proc.stdout.close()

        # search for running trayer window
        self.display = Display()
        root = self.display.screen().root
        self.trayer = self.find_tray_window(root)
        assert self.trayer is not None, 'Panel not found!'

        # activate ConfigureNotify-Events for self.trayer
        self.trayer.change_attributes(event_mask=X.StructureNotifyMask)

    def find_tray_window(self, root, tray_name='trayer'):
        children = root.query_tree().children
        for window in children:
            if window.get_wm_class() and window.get_wm_class()[1] == tray_name:
                return window
            res = self.find_tray_window(window, tray_name)
            if res:
                return res
        return None

    def watch_trayer_non_blocking(self):
        while self.display.pending_events() > 0:
            event = self.display.next_event()
            if event.type != X.ConfigureNotify:
                continue
            if event.window != self.trayer:
                continue

    def get_width(self):
        self.width = self.trayer.get_geometry().width
        return self.width + int(self.default_args['margin'])

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

    def fileno(self):
        return self.display.fileno()

    def process(self):
        self.watch_trayer_non_blocking()
Esempio n. 22
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
Esempio n. 23
0
class XwmSession(object):
    def __init__(self, winman=None, keybinder=None):

        self.winman = winman
        self.kb_map = keybinder
        self.current_event = None

        self.display = Display()
        self.root = self.display.screen().root
        self.width = self.root.get_geometry().width
        self.height = self.root.get_geometry().height
        self.root.change_attributes(event_mask=X.SubstructureRedirectMask)

        self.startup_ops = [self._init_keybinds]
        self.loop_ops = [self._handle_events]

    def startup(self, method):
        logger.info(f"Adding method ({method}) to startup operations")
        self.startup_ops.append(method)
        return method

    def onloop(self, method):
        logger.info(f"Adding method ({method}) to session loop operations")
        self.loop_ops.append(method)
        return method

    def run(self):
        try:
            logger.info("Running startup operations")
            for func in self.startup_ops:
                func()
            logger.info("Running session loops")
            while True:
                time.sleep(REFRESH_RATE)
                for func in self.loop_ops:
                    func()
        except KeyboardInterrupt:
            logger.info("Keyboard interrupt receieved, closing the display")
            self.close_display()
        except Exception:
            logger.exception("Unkown exception has occured")
            self.close_display()

    def _handle_events(self):
        # handle events
        # Why are these events blacklisted?
        ignored_events = [3, 33, 34, 23]
        if self.display.pending_events() == 0:
            return

        self.current_event = self.display.next_event()
        logger.info(f"Handling event {self.current_event}")

        if self.current_event.type == X.MapRequest:
            self._handle_map()

        elif self.current_event.type == X.KeyPress:
            self._handle_key_press()

        elif self.current_event.type in ignored_events:
            pass

        else:
            pass

    def _handle_map(self):
        logger.info("Handling map event")
        window = self.current_event.window
        self.winman.spawn(window, window.get_wm_name(), active=True)
        window.map()

    def _init_keybinds(self):
        logger.info("Initializing keybindings")
        self.keybinds = {}
        mod = X.Mod1Mask
        for key, v in self.kb_map.items():
            # Modifier is hardcoded in instead being taken from KeyBinder
            code = self.display.keysym_to_keycode(str_to_keysym[key])
            self.root.grab_key(code, mod, 1, X.GrabModeAsync, X.GrabModeAsync)
            self.keybinds[code] = self.kb_map[key]

    def _handle_key_press(self):
        logger.info("Handling key press event")
        try:
            self.keybinds[self.current_event.detail]()
        except KeyError as e:
            logger.exception(e)
            logger.error("unable to process key press")
        except Exception as e:
            logger.exception(e)
            logger.error("something when wrong with keyfunc")

    def close_display(self):
        logger.info("Closing display")
        self.display.close()
Esempio n. 24
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()
Esempio n. 25
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
Esempio n. 26
0
class TrayerWatch(EventInput):
    def __init__(self, cmd, args):
        command = [cmd]
        self.default_args = {
            'edge': 'top',
            'align': 'right',
            #widthtype': 'request',
            'width': '4',
            'expand': 'false',
            'SetDockType': 'true',
            #'SetPartialStrut': 'true',
            'transparent': 'true',
            'alpha': '0',
            'height': '20',
            'margin': '0',
            'tint': '0x00000',
        }
        if args is not None:
            self.default_args.update(args)
        for key, val in self.default_args.items():
            command += ["--%s" % (key), str(val)]

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

        # get root window's current event mask and replace it in order to wait
        # passively for the trayer window
        old_mask = root.get_attributes().your_event_mask
        root.change_attributes(event_mask=X.SubstructureNotifyMask)
        self.display.sync()

        super(TrayerWatch, self).__init__(command)
        self.proc.stdin.close()
        self.proc.stdout.close()

        # wait passively for trayer to create its window
        while True:
            event = self.display.next_event()
            self.trayer = self.find_tray_window(root, cmd)
            if self.trayer is not None:
                break

        # revert root window event_mask to remove unnecessary wakeups
        root.change_attributes(event_mask=old_mask)

        # activate ConfigureNotify-Events for self.trayer
        self.trayer.change_attributes(event_mask=X.StructureNotifyMask)

    def find_tray_window(self, root, tray_name):
        children = root.query_tree().children
        for window in children:
            if window.get_wm_class() and window.get_wm_class()[1] == tray_name:
                return window
            res = self.find_tray_window(window, tray_name)
            if res:
                return res
        return None

    def watch_trayer_non_blocking(self):
        while self.display.pending_events() > 0:
            event = self.display.next_event()
            if event.type != X.ConfigureNotify:
                continue
            if event.window != self.trayer:
                continue

    def get_width(self):
        self.width = self.trayer.get_geometry().width

        return self.width + int(self.default_args['margin'])

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

    def fileno(self):
        return self.display.fileno()

    def process(self):
        self.watch_trayer_non_blocking()
Esempio n. 27
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

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

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

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

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

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

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

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

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

        return True

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

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

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

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

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

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

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

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

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

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

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

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

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

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
Esempio n. 28
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()
Esempio n. 29
0
class KeyboardListener:
    def __init__(self, callback=None, on_error=None):
        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.record_thread = threading.Thread(
            target=self._record, name='x keyboard listener thread')
        self.well_thread = threading.Thread(target=self._drop_key,
                                            daemon=True,
                                            name='hotkey well thread')

        self.recording_connection = Display()
        self.well_connection = Display()
        self.recording_connection.set_error_handler(
            self._record_display_error_handler)
        self.well_connection.set_error_handler(
            self._local_display_error_handler)

        if not self.recording_connection.has_extension("RECORD"):
            raise Exception("RECORD extension not found")

        r = self.recording_connection.record_get_version(0, 0)
        print("RECORD extension version %d.%d" %
              (r.major_version, r.minor_version))
        self.context = self.recording_connection.record_create_context(
            0, [record.AllClients], CONTEXT_FILTER)

        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 = self.well_connection.screen().root
        self.root.change_attributes(event_mask=X.KeyPressMask
                                    | X.KeyReleaseMask)
        self.modifiers_count = self.modified_count = 0
        self.code_map = {}
        self.composed_code_map = {}
        self.composed_mapping_first_code = None
        self.multiplier = ''

    #
    # API
    #
    def bind(self, key):
        if self.stopped:
            return
        if len(key.accelerators) == 1:
            self._bind_single_accelerator(key)
        elif len(key.accelerators) == 2:
            self._bind_composed_accelerator(key)
        self.well_connection.sync()
        if self.stopped:
            print('Unable to bind: {}'.format(', '.join(key.accelerators)),
                  file=sys.stderr)

    def start(self):
        self.well_connection.sync()
        self.recording_connection.sync()
        if self.stopped:
            return
        self.well_thread.start()
        self.record_thread.start()

    def stop(self):
        self.stopped = True
        if self.record_thread.is_alive():
            self.well_connection.record_disable_context(self.context)
            self.well_connection.close()
            print('display stopped recording')
            self.record_thread.join()
        print('recording thread ended')

    #
    # Thread targets
    #
    def _drop_key(self):
        while not self.stopped:
            self.well_connection.next_event()

    def _record(self):
        self.recording_connection.record_enable_context(
            self.context, self.handler)
        self.recording_connection.record_free_context(self.context)
        self.recording_connection.close()

    def _record_display_error_handler(self, exception, *args):
        print('Error at record display: {}'.format(exception), file=sys.stderr)
        if not self.stopped:
            self.stopped = True
            self.on_error()

    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)

    def _bind_single_accelerator(self, key):
        gdk_keyval, code, mask = parse_accelerator(key.accelerators[0])

        self._grab_keys(code, mask)

        if code not in self.code_map:
            self.code_map[code] = {}

        self.code_map[code][mask] = key

    def _bind_composed_accelerator(self, key):
        gdk_keyval, code, mask = parse_accelerator(key.accelerators[0])
        second_gdk_keyval, second_code, second_mask = parse_accelerator(
            key.accelerators[1])

        self._grab_keys(code, mask)

        if code not in self.composed_code_map:
            self.composed_code_map[code] = {}
        if mask not in self.composed_code_map[code]:
            self.composed_code_map[code][mask] = {}
        if second_code not in self.composed_code_map[code][mask]:
            self.composed_code_map[code][mask][second_code] = {}

        if second_mask in self.composed_code_map[code][mask][second_code]:
            raise Exception('key ({}) already mapped'.format(', '.join(
                key.accelerators)))

        self.composed_code_map[code][mask][second_code][second_mask] = key

    #
    # Event handling
    #
    def handler(self, reply):
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(
                data, self.recording_connection.display, None, None)

            if event.detail in self.mod_keys_set:
                self.modifiers_count += 1 if event.type == X.KeyPress else -1
                self.modified_count = 0
                continue

            if self.modifiers_count:
                self.modified_count += 1 if event.type == X.KeyPress else -1

            if event.type == X.KeyPress:
                self.handle_keypress(event)

    def handle_keypress(self, event):
        _wasmapped, keyval, egroup, level, consumed = Gdk.Keymap.get_default(
        ).translate_keyboard_state(event.detail, Gdk.ModifierType(event.state),
                                   0)

        code = event.detail
        event.keyval = keyval  # TODO: explain
        mask = normalize_state(event.state)

        if self.composed_mapping_first_code and self.composed_mapping_first_code != (
                code, mask):

            key_name = Gdk.keyval_name(event.keyval)
            if not mask and key_name and key_name.isdigit():
                self.multiplier = self.multiplier + key_name
                return

            second_code_map = self.composed_code_map[
                self.composed_mapping_first_code[0]][
                    self.composed_mapping_first_code[1]]
            if code in second_code_map and mask in second_code_map[code]:
                multiplier_int = int(self.multiplier) if self.multiplier else 1
                self.callback(second_code_map[code][mask],
                              event,
                              multiplier=multiplier_int)

            self.composed_mapping_first_code = None

        elif self.modified_count == 1:

            if code in self.code_map and mask in self.code_map[code]:
                self.callback(self.code_map[code][mask], event)

            if code in self.composed_code_map and mask in self.composed_code_map[
                    code]:
                self.composed_mapping_first_code = (code, mask)

        self.multiplier = ''
Esempio n. 30
0
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 ()
Esempio n. 31
0
class App():
    def __init__(self, options):
        self.options = options
        self.reload_app = True
        self.xroot = None
        self.dpy = None
        self.menus, self.config = load_menus(self.options)
        self.create_menus()
        self.running = False

    def init_x_root(self):
        if self.dpy is None:
            self.dpy = Display()
        if self.xroot is None:
            self.xroot = self.dpy.screen().root

    def create_menus(self):
        self.keycode_to_char = {}
        self.menu_hot_keys = {}
        self.root = tk.Tk()
        self.menu_font = self.config['font']
        self.init_x_root()
        self.root.bind("<Key>", self.on_key)
        self.buttons = []
        for menu_name, fa_menu in self.menus.items():
            self.add_menu(menu_name, fa_menu)
        self.root.config()

    def reload_menus(self):
        self.reload_app = True
        self.withdraw()
        self.xroot.destroy()
        self.dpy.close()
        self.menu_hot_keys = None
        self.root = None
        self.menu_font = None
        self.buttons = None
        self.xroot = None
        self.dpy = None
        gc.collect()
        self.menus, self.config = load_menus(self.options)
        self.create_menus()

    def key_spec_to_keycode_modifier_mask(self, key_spec):
        modifiers, key = parse_modifier_mask(key_spec)
        keysym = XK.string_to_keysym(key)
        keycode = self.dpy.keysym_to_keycode(keysym)
        if keycode not in self.keycode_to_char.keys():
            self.keycode_to_char[keycode] = key
        modifier_mask = reduce(lambda x, y: x | y, modifiers, 0)
        return key, keycode, modifier_mask

    def add_menu(self, menu_name, fa_menu):
        max_width = max((len(item.item_name) for item in fa_menu.menu_content))
        menu_frame = tk.Frame(self.root, borderwidth=2,
                              relief=tk.RAISED)
        menu_frame.pack_propagate(True)
        menu_label = tk.Label(menu_frame, text=menu_name,
                              font=self.menu_font, anchor="w",
                              justify=tk.LEFT)
        menu_label.pack(fill="y")
        for menu_item in fa_menu.menu_content:
            jb = Button(menu_frame, menu_item, self.root, self,
                          font=self.menu_font, borderwidth=2,
                          relief=tk.RAISED, width=max_width)
            if menu_item.hot_key is not None:
                fa_menu.hot_keys[menu_item.hot_key] = jb.on_key
            jb.pack(fill="y")
            menu_item.button = jb
            fa_menu.menu_frame = menu_frame
            fa_menu.menu_buttons.append(jb)
        if fa_menu.menu_hot_key is not None:
            if self.menu_hot_keys.get(fa_menu.menu_hot_key) is None:
                hot_key, hot_key_states = self.bind_key(fa_menu.menu_hot_key)
                for state in hot_key_states:
                    key_state_str = key_state(hot_key, state)
                    self.menu_hot_keys[key_state_str] = fa_menu.menu_name
        fa_menu.select_button()

    def on_key(self, event):
        run = self.hot_keys.get(event.char)
        if run is None:
            if event.keysym == "Up":
                self.menus[self.menu_name].prev_button()
            elif event.keysym == "Down":
                self.menus[self.menu_name].next_button()
            elif event.keysym == "Return" or event.keysym == "space":
                run = self.menus[self.menu_name].button().on_key
            elif event.keysym == "Escape":
                self.withdraw()
        if run is not None:
            if run(event):
                self.withdraw()

    def withdraw(self):
        self.menus[self.menu_name].menu_frame.pack_forget()
        self.root.withdraw()
        self.root.quit()

    def switch_to_menu(self, menu_name):
        old_menu = self.menus[self.menu_name]
        old_menu.menu_frame.pack_forget()
        self.root.withdraw()
        new_menu = self.menus[menu_name]
        self.show_menu(new_menu)

    def show_menu(self, menu):
        self.menu_name = menu.menu_name
        if self.running:
            menu.menu_frame.pack()
            self.hot_keys = menu.hot_keys
            self.root.update()
            self.root.deiconify()
        else:
            self.running = True
            menu.menu_frame.pack()
            self.hot_keys = menu.hot_keys

    def do_loop(self):
        while not self.reload_app:
            ev = self.xroot.display.next_event()
            if ev.type == X.KeyPress:
                key = self.keycode_to_char.get(ev.detail)
                state = ev.state
                key_state_str = key_state(key, state)
                menu_name = self.menu_hot_keys.get(key_state_str)
                if menu_name is not None:
                    menu = self.menus[menu_name]
                    self.show_menu(menu)
                    self.root.mainloop()

    def run(self):
        self.reload_app = False
        self.do_loop()

    def bind_key(self, key_spec):
        self.xroot.change_attributes(event_mask=X.KeyPressMask)
        key, keycode, modifier_mask = self.key_spec_to_keycode_modifier_mask(key_spec)
        states = []
        for ignored in powerset(IGNORED_MODIFIERS):
            modmask = reduce(lambda x, y: x | y, ignored, 0)
            modmask |= modifier_mask
            states.append(modmask)
            self.xroot.grab_key(keycode, modmask, 1,
                                  X.GrabModeAsync, X.GrabModeAsync)
        return key, states
Esempio n. 32
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def stop(self):
        self.running = False
        self.ungrab()
        self.display.close()
Esempio n. 33
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()
Esempio n. 34
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.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()
Esempio n. 35
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
Esempio n. 36
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()
Esempio n. 37
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()
Esempio n. 38
0
class GlobalKeyBinding(GObject.GObject, threading.Thread):
    __gsignals__ = {
        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
        }

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

        self.keymap = 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()
Esempio n. 39
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()
Esempio n. 40
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()
Esempio n. 41
0
class wm(object):
    """Initialise WM variables and open display"""
    def __init__(self):
        self.windowList = []  # List of opened windows
        self.display = Display()  # Initialise display
        self.colormap = self.display.screen().default_colormap  # Initialise colourmap
        self.currentMode = None
        self.activeWindow = None
        self.rootWindow = self.display.screen().root  # Get root window
        self.displayWidth = self.rootWindow.get_geometry().width  # Get width of display
        self.displayHeight = self.rootWindow.get_geometry().height  # Get height of display
        self.rootWindow.change_attributes(event_mask = X.SubstructureRedirectMask)  # Redirect events from root window
        self.configureKeys()  # Configure key bindings

    def mainLoop(self):
        self.updateFocus()
        self.updateBorders()
        self.handleEvents()
        log(3, "Mode:"+str(self.currentMode))

    """Destroy an active window"""
    def destroyWindow(self, event):
        try:
            self.activeWindow.destroy()
            self.windowList.remove(self.activeWindow)
            self.activeWindow = None
        except:
            log(2, "No focused window!")
 
    def updateFocus(self):
        window = self.display.screen().root.query_pointer().child
        if window != 0:
            self.activeWindow = window

    def updateBorders(self):
        for window in self.windowList:
            #gc = self.rootWindow.create_gc()
            #window.fill_rectangle(gc, 0, window.get_geometry().y-5, window.get_geometry().width, 5)
            #window.draw_text(gc, window.get_geometry().width/2, 5, "Hello, World!", "ff0011")
            if window != self.activeWindow:
                borderColour = preferences.theme.border.inactiveColour
            else:
                borderColour = preferences.theme.border.activeColour
            borderColour = self.colormap.alloc_named_color(borderColour).pixel #borderColour).pixel
            window.configure(border_width = preferences.theme.border.borderWidth)
            window.change_attributes(None,border_pixel=borderColour)
            self.display.sync()

    """Handle WM events"""
    def handleEvents(self):
        ignoredEvents = [3, 33, 34, 23]  # Blacklisted events
        if self.display.pending_events() > 0:
            event = self.display.next_event()  # Get next event from display 
        else:
            return
        if event.type == X.MapRequest: self.handleMap(event)  # Send mapping events to the mapping handler
        elif event.type == X.KeyPress: self.handleKeyPress(event)  # Send keypress event to the keypress handler
        elif event.type in ignoredEvents: log(3, "Ignoring event: "+str(event.type))  # Ignore event if it is a blacklisted event
        else:  # Otherwise, if the event is not a currently handled event
            log(1, "Unhandled event: "+str(event.type))  # Warn of an unhandled event

    """Handle a mapping request"""
    def handleMap(self, event):
        self.windowList.append(event.window)  # Add the window identifier to a list of open windows
        log(3, str(self.windowList))  # Show list of windows (DEBUG)
        self.activeWindow = event.window  # Set the active window to the mapped window
        self.activeWindowName = event.window.get_wm_name()  # Set the active window name to the window title
        event.window.map()  # Map the window

    """Receive a KeyPressed event when a certain key is pressed"""
    def grabKey(self, codes, modifier):
        for code in codes:  # For each code
            self.rootWindow.grab_key(code, modifier, 1, X.GrabModeAsync, X.GrabModeAsync)  # Receive events when the key is pressed

    """Bind keys"""
    def configureKeys(self):
        self.left = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_Left))  # Assign a list of possible keycodes to the variable
        self.right = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_Right))
        self.up = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_Up))
        self.down = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_Down))
        self.close = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_X))
        self.t = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_T))
        self.e = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_E))
        self.x = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_X))
        self.r = set(code for code, index in self.display.keysym_to_keycodes(XK.XK_X))
        self.grabbedKeys = [self.left, self.right, self.up, self.down, self.close, self.t, self.e, self.x, self.r]
        for key in self.grabbedKeys:  # For each key to grab,
            self.grabKey(key, X.Mod1Mask)  # Grab the key with the modifer of Alt

    #def resizeWindow(window, direction):
    #    windowW = window.get_geometry().width
    #    windowH = window.get_geometry().height
    #    if direction == 0: window.configure(width=windowW-1)
    #    elif direction == 1: window.configure(width=windowW+1)
    #    elif direction == 2: window.configure(height=windowH-1)
    #    elif direction == 3: window.configure(height=windowH+1)


    """Change the position of an active window"""
    def moveWindow(self, direction):
        try:
            if direction == "left":
                windowX = self.activeWindow.get_geometry().x  # Get the current position of the active window
                self.activeWindow.configure(x=windowX-5)  # Decrease the X position to move it left
            elif direction == "right":
                windowX = self.activeWindow.get_geometry().x
                self.activeWindow.configure(x=windowX+5)
            elif direction == "up":
                windowY = self.activeWindow.get_geometry().y
                self.activeWindow.configure(y=windowY-5)    
            elif direction == "down":
                windowY = self.activeWindow.get_geometry().y
                self.activeWindow.configure(y=windowY+5)
            else:
                log(1, "Invalid movement direction!")  
        except AttributeError:
                log(1, "No focused window!")

    """Handle key presses"""
    def handleKeyPress(self, event): 
      #  if self.currentMode == "resize":                                                             # If resize mode is enabled:
            #if event.detail in self.left: self.resizeWindow(event.window, 0)                        # Alt+Left Arrow: resize window (x-1)
           # elif event.detail in self.right: self.moveWindow(event.window, 1)                       # Alt+Right Arrow: resize window (x+1)
          #  elif event.detail in self.up: self.moveWindow(event.window, 2)                          # Alt+Up Arrow: resize window (y-1)
         #   elif event.detail in self.down: self.moveWindow(event.window, 3)                        # Alt+Down Arrow: resize window (y+1)
     #   else:                                                                                       # Otherwise,
        if event.detail in self.left: self.moveWindow("left")                                   # Alt+Left Arrow: move a window left
        elif event.detail in self.right: self.moveWindow("right")                               # Alt+Right Arrow: move a window right
        elif event.detail in self.up: self.moveWindow("up")                                     # Alt+Up Arrow: move a window up
        elif event.detail in self.down: self.moveWindow("down")                                 # Alt+Down Arrow: move a window down
        elif event.detail in self.t: self.runProcess(preferences.applicationDefaults.terminal)      # Alt+T: Launch a terminal
        elif event.detail in self.e: self.runProcess(preferences.applicationDefaults.launcher)      # Alt+E: Launch a program launcher
        elif event.detail in self.x: self.destroyWindow(event)                                      # ALT+X: Close a window
        elif event.detail in self.r: self.currentMode = "resize"                                    # ALT+R: Enable resize mode
        else:
            log(1, "Unhandled key event!")

    """Close connection to display server"""
    def closeDisplay(self):
        log(0, "Exiting...")
        self.display.close()

    """Run an application/process"""
    def runProcess(self, applicationInfo):
        try:
            name = applicationInfo["name"]  # Get application name
            command = applicationInfo["command"]  # Get aplication command 
        except:
            raise ValueError
        try:
            log(0, "Running: "+name)
            subprocess.Popen(command)  # Run the command and disown the child process
        except BaseException as error:
            log(2, "Failed to launch process: "+processCommand+"!")
            log(3, str(error))
Esempio n. 42
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()
Esempio n. 43
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)
Esempio n. 44
0
class WindowWatch(EventInput):
    """
    Run an external command that creates a window and then
    watch that window's size.
    """
    def __init__(self, command, is_right_window, kill_old_instance=False):
        """
        - command is a tokinzed command to invoke the process
        - is_right_window is a callback such that
            is_right_window(window) returns 'window' if it is a the window to watch
            and None otherwise.
        - if kill_old_instance is set, then all clients matching
          is_right_window() are killed before 'command' is invoked.
        """

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

        # get root window's current event mask and replace it in order to wait
        # passively for the trayer window
        old_mask = root.get_attributes().your_event_mask
        root.change_attributes(event_mask=X.SubstructureNotifyMask)
        self.display.sync()

        if kill_old_instance:
            while True:
                old_tray = self.find_tray_window(root, is_right_window)
                if old_tray is None:
                    # no old instance
                    break
                # force shutdown:
                old_tray.kill_client()
                # wait for an event, i.e. any kind of updater from X
                self.display.next_event()

        # start the process:
        super(WindowWatch, self).__init__(command)
        self.proc.stdin.close()
        self.proc.stdout.close()

        # wait passively for trayer to create its window
        while self.proc.poll() is None:
            event = self.display.next_event()
            self.trayer = self.find_tray_window(root, is_right_window)
            if self.trayer is not None:
                break

        if self.proc.poll() is not None:
            print("command »{}« exited unexpectedly.".format(
                ' '.join(command)),
                  file=sys.stderr)
            return

        # revert root window event_mask to remove unnecessary wakeups
        root.change_attributes(event_mask=old_mask)

        # activate ConfigureNotify-Events for self.trayer
        self.trayer.change_attributes(event_mask=X.StructureNotifyMask)

    def find_tray_window(self, root, is_right_window):
        children = root.query_tree().children
        for window in children:
            try:
                found = is_right_window(window)
                if found is not None:
                    return found
                res = self.find_tray_window(window, is_right_window)
                if res:
                    return res
            except Xlib.error.BadWindow as e:
                # if a window disappeared while inspecting it,
                # just skip it.
                pass
        return None

    def watch_trayer_non_blocking(self):
        while self.display.pending_events() > 0:
            event = self.display.next_event()
            if event.type != X.ConfigureNotify:
                continue
            if event.window != self.trayer:
                continue

    def get_width(self):
        try:
            self.width = self.trayer.get_geometry().width
        except Xlib.error.BadWindow:
            self.width = 0
        except Xlib.error.BadDrawable:
            self.width = 0
        return self.width

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

    def fileno(self):
        return self.display.fileno()

    def process(self):
        self.watch_trayer_non_blocking()
Esempio n. 45
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()
Esempio n. 46
0
signal.alarm(10)

while True:
    print("event...")
    event = display.next_event()
    print(event.type, event.detail, event.time)
    if event.type == X.KeyPress and event.detail == 10:
        print("pressed")
        if not counter % 2:
            swallow_keystroke(event)
        else:
            passthru_keystroke(event)
    elif event.type == X.KeyRelease and event.detail == 10:
        print("released")
        if not counter % 2:
            swallow_keystroke(event)
        else:
            passthru_keystroke(event)
        counter += 1

    if event.type == X.KeyPress and event.detail == 15:
        swallow_keystroke(event)

    if event.type == X.KeyRelease and event.detail == 15:
        print("exit")
        break
root.ungrab_key(10, 0)
root.ungrab_key(15, 0)
display.close()