Exemple #1
0
def send_event(client_id, keystate, shiftstate, keycode):
    display = Xlib.display.Display()
    Xlib_root_window = display.screen().root
    window = display.create_resource_object('window', client_id)
    if keystate == 2:
        XEVENT = Xlib.protocol.event.KeyPress
    elif keystate == 3:
        XEVENT = Xlib.protocol.event.KeyRelease
    else:
        raise

    event = XEVENT(time=int(time.time()),
                   root=Xlib_root_window,
                   window=window,
                   same_screen=0,
                   child=Xlib.X.NONE,
                   root_x=0,
                   root_y=0,
                   event_x=0,
                   event_y=0,
                   state=shiftstate,
                   detail=keycode)
    display.sync()
    p = window.send_event(event, propagate=False)
    display.sync()
    display.close()
    return True
Exemple #2
0
def close_x():
    '''
    Closes the connection to X, but flushes it first
    '''
    global display
    display.flush()
    display.close()
Exemple #3
0
def close_x():
    '''
    Closes the connection to X, but flushes it first
    '''
    global display
    display.flush()
    display.close()
Exemple #4
0
def main() -> None:
    for cmd in CMDS:
        assert shutil.which(cmd) is not None, "'%s' not found in PATH." % cmd
    signal.signal(signal.SIGCHLD, signal.SIG_IGN)
    display: Xlib.display.Display = Xlib.display.Display()
    window_manager: WindowManager = WindowManager(display)
    while window_manager.is_running():
        window_manager.on_event(display.next_event())
    display.close()
def remap_keys(remap):
  """ Remap keycode -> keysym for function keys

  The keycode -> keysym mapping is so that the keycode generated
  when the F1 key is pressed sends the F25 keysym. But to do that you
  need to know the keycodes for F1-10, for Linux on x86 the keycode for
  F1 is 67 but for other platforms it could be different. So the code
  looks up the keycode mapped to F1 keysym if that is non zero (i.e. F1
  is mapped) I map that keycode to F1 or F25 as required, if F1 is not
  mapped I lookup the keycode for F25 and if that is non zero I map
  that keycode to F1 or F25 as required. If F1 and F25 are not mapped
  to any keycode I use 67 as the keycode for the F1 key. The code
  assumes that the keycodes for F1-10 are sequential which may not be
  true for all platforms. A more robust solution may be found by
  accessing the keyboard layout somehow but I haven't had time to look
  yet.
  """
  
  display = Xlib.display.Display()
  
  # only keycodes 8 to 255 are defined
  first_keycode = 8
  keymaps_orig = display.get_keyboard_mapping(first_keycode, 255 - first_keycode)
  keymaps = list(keymaps_orig)

  if remap == True: 
    keysym = 65494
  else:
    keysym = 65470

  keycode_F1 = display.keysym_to_keycode(65470)
  keycode_F25 = display.keysym_to_keycode(65494)
  
  # set first_fkeycode to a sensible default incase F1 and F25 are not mapped
  first_fkeycode = 67
  
  if keycode_F1 > 0:
    first_fkeycode = keycode_F1
  elif keycode_F25 > 0:
    first_fkeycode = keycode_F25
    
  for i in range(0, 10):

    keymaps[(i + first_fkeycode - first_keycode)][0] = keysym + i
    keymaps[(i + first_fkeycode - first_keycode)][2] = keysym + i
    keymaps[(i + first_fkeycode - first_keycode)][4] = keysym + i
    
  display.change_keyboard_mapping(first_keycode, keymaps, onerror = None)
  display.sync()
  display.close()
Exemple #6
0
def remap_keys(remap):
   """ Remap keycode -> keysym for function keys
   
   The keycode -> keysym mapping is so that the keycode generated
   when the F1 key is pressed sends the F25 keysym. But to do that you
   need to know the keycodes for F1-10, for Linux on x86 the keycode for
   F1 is 67 but for other platforms it could be different. So the code
   looks up the keycode mapped to F1 keysym if that is non zero (i.e. F1
   is mapped) I map that keycode to F1 or F25 as required, if F1 is not
   mapped I lookup the keycode for F25 and if that is non zero I map
   that keycode to F1 or F25 as required. If F1 and F25 are not mapped
   to any keycode I use 67 as the keycode for the F1 key. The code
   assumes that the keycodes for F1-10 are sequential which may not be
   true for all platforms. A more robust solution may be found by
   accessing the keyboard layout somehow but I haven't had time to look
   yet.
   """
   
   display = Xlib.display.Display()
  
   # only keycodes 8 to 255 are defined
   first_keycode = 8
   keymaps_orig = display.get_keyboard_mapping(first_keycode, 255 - first_keycode)
   keymaps = list(keymaps_orig)
   
   if remap == True: 
      keysym = 65494
   else:
      keysym = 65470
   
   keycode_F1 = display.keysym_to_keycode(65470)
   keycode_F25 = display.keysym_to_keycode(65494)
  
   # set first_fkeycode to a sensible default incase F1 and F25 are not mapped
   first_fkeycode = 67
  
   if keycode_F1 > 0:
      first_fkeycode = keycode_F1
   elif keycode_F25 > 0:
      first_fkeycode = keycode_F25
   
   for i in range(0, int(number_of_suggestions)):

      keymaps[(i + first_fkeycode - first_keycode)][0] = keysym + i
      keymaps[(i + first_fkeycode - first_keycode)][2] = keysym + i
      keymaps[(i + first_fkeycode - first_keycode)][4] = keysym + i
   
   display.change_keyboard_mapping(first_keycode, keymaps, onerror = None)
   display.sync()
   display.close()
Exemple #7
0
def setup(ui_model):
    keymap_mgr = ui_model.get_keymap_manager()

    scancode_rows = _get_scancode_rows()

    # Scancodes
    scancode_locs = {}
    for row, codes in enumerate(scancode_rows):
        for index, code in enumerate(codes):
            scancode_locs[code] = (row, index)
    keymap_mgr.set_scancode_locations(scancode_locs)

    if _has_xlib:
        display = Xlib.display.Display()

        key_names = {}
        for row, codes in enumerate(scancode_rows):
            for index, code in enumerate(codes):
                keysym = display.keycode_to_keysym(code, 0)
                if keysym != Xlib.X.NoSymbol:
                    name = display.lookup_string(keysym)
                    if name:
                        key_names[(row, index)] = name.upper()

        display.close()

        keymap_mgr.set_key_names(key_names)

    # TODO: set key ID locations for systems that need them

    # Actions
    key_actions = {
        (0, 0): KeyboardAction(KeyboardAction.REST),
        (2, 9): KeyboardAction(KeyboardAction.OCTAVE_DOWN),
        (2, 10): KeyboardAction(KeyboardAction.OCTAVE_UP),
        (3, 7): KeyboardAction(KeyboardAction.PLAY),
        (3, 8): KeyboardAction(KeyboardAction.SILENCE),
    }
    tw_sizes = keymap_mgr.get_typewriter_row_sizes()
    tw_offsets = keymap_mgr.get_typewriter_row_offsets()
    for row, (size, offset) in enumerate(zip(tw_sizes, tw_offsets)):
        for index in range(size):
            loc = (row, index + offset)
            assert loc not in key_actions
            key_actions[loc] = KeyboardNoteAction(row, index)
    keymap_mgr.set_key_actions(key_actions)
Exemple #8
0
def setup(ui_model):
    keymap_mgr = ui_model.get_keymap_manager()

    scancode_rows = _get_scancode_rows()

    # Scancodes
    scancode_locs = {}
    for row, codes in enumerate(scancode_rows):
        for index, code in enumerate(codes):
            scancode_locs[code] = (row, index)
    keymap_mgr.set_scancode_locations(scancode_locs)

    if _has_xlib:
        display = Xlib.display.Display()

        key_names = {}
        for row, codes in enumerate(scancode_rows):
            for index, code in enumerate(codes):
                keysym = display.keycode_to_keysym(code, 0)
                if keysym != Xlib.X.NoSymbol:
                    name = display.lookup_string(keysym)
                    if name:
                        key_names[(row, index)] = name.upper()

        display.close()

        keymap_mgr.set_key_names(key_names)

    # TODO: set key ID locations for systems that need them

    # Actions
    key_actions = {
        (0, 0):     KeyboardAction(KeyboardAction.REST),
        (2, 9):     KeyboardAction(KeyboardAction.OCTAVE_DOWN),
        (2, 10):    KeyboardAction(KeyboardAction.OCTAVE_UP),
        (3, 7):     KeyboardAction(KeyboardAction.PLAY),
        (3, 8):     KeyboardAction(KeyboardAction.SILENCE),
    }
    tw_sizes = keymap_mgr.get_typewriter_row_sizes()
    tw_offsets = keymap_mgr.get_typewriter_row_offsets()
    for row, (size, offset) in enumerate(zip(tw_sizes, tw_offsets)):
        for index in range(size):
            loc = (row, index + offset)
            assert loc not in key_actions
            key_actions[loc] = KeyboardNoteAction(row, index)
    keymap_mgr.set_key_actions(key_actions)
Exemple #9
0
def current_app(x):
    """ Metric function for MIDAS that returns the
        app currently in focus
    """
    try:
        display = Xlib.display.Display()
        window = display.get_input_focus().focus
        wmclass = window.get_wm_class()

        if wmclass is None:
            window = window.query_tree().parent
            wmclass = window.get_wm_class()

        display.close()
        del display

        if wmclass:
            return(wmclass[1])
        else:
            return('UNKNOWN')
    except:
        return('ERROR!')
Exemple #10
0
def current_app(x):
    """ Metric function for MIDAS that returns the
        app currently in focus
    """
    try:
        display = Xlib.display.Display()
        window = display.get_input_focus().focus
        wmclass = window.get_wm_class()

        if wmclass is None:
            window = window.query_tree().parent
            wmclass = window.get_wm_class()

        display.close()
        del display

        if wmclass:
            return (wmclass[1])
        else:
            return ('UNKNOWN')
    except:
        return ('ERROR!')
Exemple #11
0
import sys
import threading
import types

import PIL
import Xlib.display
import Xlib.threaded
import Xlib.XK

from six.moves import queue

from . import _base

# Create a display to verify that we have an X connection
display = Xlib.display.Display()
display.close()
del display


class XError(Exception):
    """An error that is thrown at the end of a code block managed by a
    :func:`display_manager` if an *X* error occurred.
    """
    pass


@contextlib.contextmanager
def display_manager(display):
    """Traps *X* errors and raises an :class:`XError` at the end if any
    error occurred.
Exemple #12
0
def _check():
    display = Xlib.display.Display()
    display.close()
Exemple #13
0
def _check_and_initialize():
    display = Xlib.display.Display()
    display.close()

    for group in Xlib.keysymdef.__all__:
        Xlib.XK.load_keysym_group(group)
Exemple #14
0
def sendViaClipboard(blobs, record = None, txtselections = defSelections, ui=ui_null()):
  """
  Send a list of blobs via the clipboard (using X selections, cut buffers are
  not yet supported) in sequence. Typically the PRIMARY and/or SECONDARY
  selections are used for middle click and shift+insert pasting, while the
  CLIPBOARD selection is often used by Ctrl+V pasting.

  Raises an XFailConnection exception if connecting to the X DISPLAY failed.
  """
  global Xlib, X, Xatom, Xerror
  if Xlib is None:
    ui.status('Initialising python-Xlib, stand by...')
    ui.mainloop.draw_screen()
    try:
      from Xlib import X, Xatom, error as Xerror
      import Xlib.display
    except ImportError:
      ui.status('Error importing python-Xlib, X clipboard integration unavailable')
      return

  # Can't do this in the function definition - it seems that a .remove()
  # affects the default. That would be expected if it were assigned as a
  # reference to the default list, but even happens when the [:] syntax is
  # used to copy the list. I guess that must be an unexpected side effect of
  # the function definition only excuting once when the file is loaded?
  txtselections = txtselections[:]
  selections = txtselections[:]

  def findClientWindow(window, ui):
    """ walk up the tree looking for a client window """

    def get_wm_client_leader(window):
        d = window.get_full_property(Xatom.WM_CLIENT_LEADER, Xatom.WINDOW)
        if d is None or d.format != 32 or len(d.value) < 1:
          return None
        else:
          cls = window.display.get_resource_class('window', type(window))
          return cls(window.display, d.value[0])

    host = window.get_wm_client_machine()
    while True:
      comm = window.get_full_property(Xatom.WM_COMMAND, Xatom.STRING)
      name = window.get_wm_name()
      # Nokia N900 uses _NET_WM_NAME instead of WM_NAME:
      netname = window.get_full_property(Xatom._NET_WM_NAME, Xatom.UTF8_STRING)
      leadercomm = None

      # Only one top-level window for a given client has WM_COMMAND. Find the
      # leader top-level window (if we are looking at a top-level window) and
      # check it's WM_COMMAND property.
      #
      # I don't see a requirement in the ICCCM that the client leader
      # necessarily be the window with the WM_COMMAND property, it may end up
      # being necessary to iterate all the windows with the same
      # WM_CLIENT_LEADER to find the one window that has the WM_COMMAND.
      leader = get_wm_client_leader(window)
      if leader is not None and leader != window:
        leadercomm = leader.get_full_property(Xatom.WM_COMMAND, Xatom.STRING)

      requestor = name or netname or comm or leadercomm
      if hasattr(requestor, 'value'):
        requestor = requestor.value
      if requestor:
        break
      resp = window.query_tree()
      root = resp.root; parent = resp.parent
      if parent == root:
        return ('<unknown>', host)
      window = parent
    return (requestor, host)

  def handleSelectionRequest(e, field, record, ui):
    global _prev_requestor
    if ((e.time != X.CurrentTime and e.time < timestamp) or # Timestamp out of bounds
        (e.selection not in selections) or # Requesting a different selection
        (e.owner.id != win.id)): # We aren't the owner
      return _refuseSelectionRequest(e)
    if (e.target in (Xatom.STRING, Xatom.TEXT)):
      (requestor, host) = findClientWindow(e.requestor, ui)
      if requestor.lower() in blacklist or any([ pattern.match(requestor) for pattern in blacklist_re ]):
        if requestor != _prev_requestor:
          ui.status("Ignoring request from %s@%s"%(requestor, host), append=True)
          _prev_requestor = requestor
        return _refuseSelectionRequest(e)
      ui.status("Sent %s for '%s' via %s to %s@%s"%(field.upper(), record, display.get_atom_name(e.selection), requestor, host), append=True)
      oldmask = e.requestor.get_attributes().your_event_mask
      e.requestor.change_attributes(event_mask = oldmask | X.PropertyChangeMask)
      _sendSelection(blob, Xatom.STRING, 8, e, ui)
      return True
    elif (e.target == Xatom.TIMESTAMP):
      _sendSelection([timestamp], Xatom.TIMESTAMP, 32, e, ui)
    elif (e.target == Xatom.TARGETS):
      _sendSelection([Xatom.TARGETS, Xatom.TIMESTAMP, Xatom.TEXT, Xatom.STRING], Xatom.ATOM, 32, e, ui)
    else:
      return _refuseSelectionRequest(e)
    return False

  # Opening the display prints 'Xlib.protocol.request.QueryExtension' to
  # stdout, so temporarily redirect it:
  ui.status('Connecting to display, stand by...')
  ui.mainloop.draw_screen()
  import sys, StringIO
  saved_stdout = sys.stdout
  sys.stdout = StringIO.StringIO()
  try:
    display = Xlib.display.Display()
  except Xerror.DisplayError:
    raise XFailConnection()
  finally:
    sys.stdout = saved_stdout
  screen = display.screen()
  win = screen.root.create_window(0,0,1,1,0,0)

  Xatom.TEXT = display.intern_atom('TEXT', True)
  Xatom.TARGETS = display.intern_atom('TARGETS', True)
  Xatom.TIMESTAMP = display.intern_atom('TIMESTAMP', True)
  Xatom.WM_CLIENT_LEADER = display.intern_atom('WM_CLIENT_LEADER', True)
  Xatom._NET_WM_NAME = display.intern_atom('_NET_WM_NAME', True)
  Xatom.UTF8_STRING = display.intern_atom('UTF8_STRING', True)

  ui_fds = ui.mainloop.screen.get_input_descriptors()
  if ui_fds is None: ui_fds = []
  select_fds = set([display] + ui_fds)
  try:
    old = ui_tty.set_cbreak() # Set unbuffered IO (if not already)
    ui.status('')
    for (field, blob) in blobs:
      ui.status("Ready to send %s for '%s' via %s... (enter skips, escape cancels)"%(field.upper(),record,str(txtselections)), append=True)
      ui.mainloop.draw_screen()
      awaitingCompletion = []
      timestamp = _ownSelections(display, win, selections)

      timeout = None
      skip = False
      while 1:
        if skip and awaitingCompletion == []: break
        while True:
          try:
            (readable, ign, ign) = select.select(select_fds, [], [], timeout)
          except select.error as e:
            if e.args[0] == 4: continue # Interrupted system call
            raise
          break

        if not readable and awaitingCompletion == []:
          break

        for fd in readable:
          if fd == sys.stdin.fileno():
            char = sys.stdin.read(1)
            if char == '\n':
              skip = True
            elif char == '\x1b':
              return
          elif fd in ui_fds:
            # This is a hack to redraw the screen - we really should
            # restructure all this so as not to block instead:
            ui.mainloop.event_loop._loop()

          if fd == display:
            while display.pending_events():
              e = display.next_event()
              if e.type == X.SelectionRequest:
                if handleSelectionRequest(e, field, record, ui):
                  # Don't break immediately, transfer will not have finished.
                  # Wait until the property has been deleted by the requestor
                  awaitingCompletion.append((e.requestor, e.property))
              elif e.type == X.PropertyNotify:
                if (e.window, e.atom) in awaitingCompletion \
                    and e.state == 1: # Deleted
                  awaitingCompletion.remove((e.window, e.atom))
                  # Some programs, such as firefox (when pasting with
                  # shift+insert), don't expect the selection to change suddenly
                  # and behave badly if it does, so wait a moment before ending:
                  timeout = 0.01
              elif e.type == X.SelectionClear:
                if e.time == X.CurrentTime or e.time >= timestamp:
                  # If we lost CLIPBOARD (explicit copy) or no longer control any selection, abort:
                  name = display.get_atom_name(e.atom)
                  selections.remove(e.atom)
                  txtselections.remove(name)
                  if name == 'CLIPBOARD' or not selections:
                    # If transfer is in progress it should be allowed to complete:
                    if awaitingCompletion == []: return
                    timeout = 0.01
                  else:
                    ui.status("Lost control of %s, still ready to send %s via %s..."%(name, field.upper() ,str(txtselections)), append=True)
                    ui.mainloop.draw_screen()
            ui.mainloop.draw_screen()
  finally:
    ui_tty.restore_cbreak(old)
    win.destroy()
    display.close() # I may have introduced a bug while adding the urwid loop
                    # stuff here - the clipboard selection remained grabbed
                    # after destroying the window. This worked around it since
                    # I can't see what is wrong.
    ui.status('Clipboard Cleared', append=True)
Exemple #15
0
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import contextlib
import itertools
import Xlib.display
import Xlib.threaded
import Xlib.XK

from . import AbstractListener
from .xorg_keysyms import *


# Create a display to verify that we have an X connection
display = Xlib.display.Display()
display.close()
del display


class X11Error(Exception):
    """An error that is thrown at the end of a code block managed by a
    :func:`display_manager` if an *X11* error occurred.
    """
    pass


@contextlib.contextmanager
def display_manager(display):
    """Traps *X* errors and raises an :class:``X11Error`` at the end if any
    error occurred.