# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
"""
Notes:
# https://stackoverflow.com/questions/51070465/is-it-possible-to-get-the-directory-of-a-specific-nautilus-window-in-a-script?noredirect=1#comment95427874_51070465
sudo apt install python-nautilus
mkdir -p ~/.local/share/nautilus-python/extensions
"""
try:
import ubelt as ub
except Exception:
ub = None
import time
import re
import pipes
import logging
from vimtk import cplat
logger = logging.getLogger(__name__)
[docs]
def is_directory_open(dpath):
# FIXME
import ubelt as ub # pip install me! https://github.com/Erotemic/ubelt
import platform
from os.path import basename
import re
computer_name = platform.node()
dname = basename(dpath)
if not ub.find_exe('wmctrl'):
raise Exception('wmctrl must be installed')
for line in ub.cmd('wmctrl -lxp')['out'].splitlines():
parts = re.split(' +', line)
if len(parts) > 3 and parts[3] == 'nautilus.Nautilus':
if parts[4] == computer_name:
# FIXME: Might be a False positive!
line_dname = ' '.join(parts[5:])
if line_dname == dname:
return True
# Always correctly returns False
return False
[docs]
def wmctrl_list():
lines = ub.cmd('wmctrl -lxp')['out']
windows = {}
for line in lines.split('\n'):
if line:
parts = re.split(' +', line)
hexid, deskid, pid, wm_class, client = parts[0:5]
title = ' '.join(parts[5:])
wm_id = int(hexid, 16)
windows[wm_id] = {
'hexid': hexid,
'wm_id': wm_id,
'deskid': deskid,
'pid': int(pid),
'wm_class': wm_class,
'client': client,
'title': title,
}
return windows
[docs]
def windows_in_order():
"""
CommandLine:
python -m vimtk.xctrl windows_in_order
References:
https://stackoverflow.com/questions/15638885/linux-how-to-get-a-list-of-all-visible-windows
Example:
>>> # xdoctest: +REQUIRES(env:DISPLAY)
>>> from vimtk.xctrl import *
>>> result = list(windows_in_order())
>>> for win in result:
... if win.visible():
... print(win)
Ignore:
# Why is this slow somtimes?
import subprocess
subprocess.call(['xprop', '-root'])
proc = subprocess.Popen(['xprop', '-root'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1, text=True)
out, err = proc.communicate()
proc = subprocess.Popen('xprop -root', shell=True, stdout=subprocess.PIPE, bufsize=1)
info = ub.cmd('xprop -root | grep "^_NET_CLIENT_LIST_STACKING"', shell=True)
info = ub.cmd('xprop -root _NET_CLIENT_LIST_STACKING', shell=True)
info = ub.cmd('xprop -root _NET_CLIENT_LIST_STACKING')
# I don't understand why this can be fast sometimes and slow others
import subprocess
import timerit
import itertools as it
import ubelt as ub
options = {
'bufsize': [-1, 0],
'shell': [True, False],
'stdout': [subprocess.PIPE, None],
'stderr': [subprocess.PIPE, None],
'stdin': [subprocess.PIPE, None],
'universal_newlines': [True, False],
# 'cwd': [None, '.']
# 'env': [None, {}]
}
ti = timerit.Timerit(3, bestof=1, verbose=3)
for vals in it.product(*options.values()):
opt = ub.dzip(options.keys(), vals)
command = ['xprop', '-root', '_NET_CLIENT_LIST_STACKING']
name = ub.urepr(opt, explicit=True, nobr=1, nl=0, itemsep='')
if opt['shell']:
command = ' '.join(command)
for timer in ti.reset(name):
with timer:
proc = subprocess.Popen(command, **opt)
out, err = proc.communicate()
assert proc.returncode == 0
# print(out)
for timer in ti.reset('ubelt'):
with timer:
print(ub.cmd('xprop -root _NET_CLIENT_LIST_STACKING')['out'])
print(ub.urepr(ub.sorted_vals(ti.measures['mean']), nl=1, precision=6))
proc = subprocess.Popen('xprop -root', shell=True, stdout=subprocess.PIPE, bufsize=0)
out, err = proc.communicate()
info = ub.cmd('xprop -root', verbose=3, shell=True)
ub.cmd('wmctrl -lxp')['out']
os.system('wmctrl -lxp')
"""
# info = XCtrl.cmd('xprop -root')
info = XCtrl.cmd('xprop -root _NET_CLIENT_LIST_STACKING')
lines = [line for line in info['out'].split('\n')
if line.startswith('_NET_CLIENT_LIST_STACKING')]
assert len(lines) == 1, str(lines)
winid_order_str = lines[0]
winid_order = winid_order_str.split('#')[1].strip().split(', ')[::-1]
winid_order = [int(h, 16) for h in winid_order]
windows = wmctrl_list()
for wm_id in winid_order:
info = windows[wm_id]
yield XWindow(wm_id, info)
[docs]
def find_windows(proc=None, title=None, visible=True):
"""
CommandLine:
python -m vimtk.xctrl find_windows
Example:
>>> # xdoctest: +REQUIRES(env:DISPLAY)
>>> from vimtk.xctrl import * # NOQA
>>> for win in find_windows('gvim'):
>>> print(ub.urepr(win.info()))
>>> for win in find_windows('terminator'):
>>> print(ub.urepr(win.info()))
"""
import re
for win in windows_in_order():
flag = True
if proc:
try:
proc_name = win.process_name()
flag &= bool(re.match(proc, proc_name))
except Exception:
flag = False
if title:
try:
win_title = win.title()
flag &= bool(re.match(title, win_title))
except Exception:
flag = False
if visible:
try:
flag &= win.visible()
except Exception:
flag = False
if flag:
yield win
[docs]
class XWindow(object):
"""
TODO: make API consistent with the win32 version
"""
def __init__(self, wm_id, info=None, sleeptime=0.01):
self.wm_id = wm_id
self.cache = info
self.sleeptime = 0.01
[docs]
@classmethod
def find(XWindow, pattern, method='mru'):
wm_id = XCtrl.find_window_id(pattern, method=method)
self = XWindow(wm_id)
return self
[docs]
@classmethod
def findall(XWindow, pattern):
wm_ids = XCtrl.findall_window_ids(pattern)
result = [XWindow(wm_id) for wm_id in wm_ids]
return result
[docs]
@classmethod
def current(XWindow):
r"""
CommandLine:
VIMTK_TEST=1 xdoctest -m vimtk.xctrl XWindow.current
Example:
>>> # xdoctest: +REQUIRES(env:VIMTK_TEST)
>>> from vimtk.xctrl import * # NOQA
>>> self = XWindow.current()
>>> print('self: XWindow = {}'.format(ub.urepr(self, nl=1)))
>>> print('info = ' + ub.urepr(self.wininfo()))
"""
wm_id = int(ub.cmd('xdotool getwindowfocus')['out'].strip())
win = XWindow(wm_id)
return win
[docs]
def _wmquery(self, key):
if self.cache:
return self.cache[key]
windows = wmctrl_list()
info = windows[self.wm_id]
self.cache = info
return info['title']
@property
def hexid(self):
return hex(self.wm_id)
[docs]
def title(self):
self._wmquery('title')
[docs]
def visible(self):
""" Basically true for wmctrl (afaik) """
return True
def __nice__(self):
try:
fname = self.process_name()
except Exception:
fname = '<error: unable to get process name>'
return str(self.wm_id) + ' ' + fname + ' ' + repr(self.title())
[docs]
def wm_class(self):
return self._wmquery('wm_class')
[docs]
def process(self):
import psutil
pid = self._wmquery('pid')
proc = psutil.Process(pid)
return proc
[docs]
def size(self):
# Get the current size
info = self.wininfo()
w, h = int(info['Width']), int(info['Height'])
dsize = (w, h)
return dsize
[docs]
def resize(self, width, height):
"""
CommandLine:
VIMTK_TEST=1 xdoctest -m vimtk.xctrl XWindow.resize
Example:
>>> # xdoctest: +REQUIRES(env:VIMTK_TEST)
>>> from vimtk.xctrl import * # NOQA
>>> self = XWindow.current()
>>> w, h = self.size()
>>> self.resize(w + 10, h + 10)
"""
command = f'xdotool windowsize {self.wm_id} {width} {height}'
ub.cmd(command, verbose=3)
[docs]
def wininfo(self):
"""
"""
cmdinfo = ub.cmd('xwininfo -id {}'.format(self.wm_id))
if cmdinfo['ret'] != 0:
print('info = {}'.format(ub.urepr(cmdinfo, nl=1)))
raise Exception(cmdinfo['ret'])
out = cmdinfo['out']
info = {}
curr_key = None
val_accum = []
# Parse key/val lines
def accept(info, curr_key, val_accum):
if curr_key is not None:
info[curr_key] = (' '.join(val_accum)).strip()
val_accum.clear()
for line in out.split('\n'):
if ':' in line:
accept(info, curr_key, val_accum)
key, val = line.split(':', 1)
val_accum.append(val)
curr_key = key.strip()
else:
val_accum.append(line)
accept(info, curr_key, val_accum)
return info
[docs]
def process_name(self):
proc = self.process()
return proc.name()
[docs]
def focus(self, sleeptime=None):
ub.cmd('wmctrl -ia {}'.format(self.hexid))
time.sleep(sleeptime if sleeptime is not None else self.sleeptime)
[docs]
def info(self):
info = self.cache.copy()
info['proc_name'] = self.process_name()
return info
[docs]
def move(self, bbox):
"""
CommandLine:
# List windows
wmctrl -l
# List desktops
wmctrl -d
# Window info
xwininfo -id 60817412
python -m vimtk.xctrl XWindow.move joncrall 0+1920,680,400,600,400
python -m vimtk.xctrl XWindow.move joncrall [0,0,1000,1000]
python -m vimtk.xctrl XWindow.move GVIM special2
python -m vimtk.xctrl XWindow.move joncrall special2
python -m vimtk.xctrl XWindow.move x-terminal-emulator.X-terminal-emulator [0,0,1000,1000]
CommandLine:
python -m vimtk.xctrl XWindow.move
CommandLine:
python -m vimtk.xctrl XCtrl.move_window
Example:
>>> # xdoctest: +SKIP
>>> XCtrl.move_window('joncrall', '[0,0,1000,1000]')
Ignore:
# >>> orig_window = []
# >>> X = xctrl.XCtrl
win_key = 'x-terminal-emulator.X-terminal-emulator'
win_id = X.findall_window_ids(key)[0]
python -m xctrl XCtrl.findall_window_ids gvim
"""
monitor_infos = {
i + 1: cplat.get_resolution_info(i)
for i in range(2)
}
# TODO: cut out borders
# TODO: fix screeninfo monitor offsets
# TODO: dynamic num screens
def rel_to_abs_bbox(m, x, y, w, h):
""" monitor_num, relative x, y, w, h """
minfo = monitor_infos[m]
# print('minfo(%d) = %s' % (m, ub.urepr(minfo),))
mx, my = minfo['off_x'], minfo['off_y']
mw, mh = minfo['pixels_w'], minfo['pixels_h']
# Transform to the absolution position
abs_x = (x * mw) + mx
abs_y = (y * mh) + my
abs_w = (w * mw)
abs_h = (h * mh)
abs_bbox = [abs_x, abs_y, abs_w, abs_h]
abs_bbox = ','.join(map(str, map(int, abs_bbox)))
return abs_bbox
if self.title().startswith('joncrall') and bbox == 'special2':
# Specify the relative position
abs_bbox = rel_to_abs_bbox(m=2,
x=0.0, y=0.7,
w=1.0, h=0.3)
elif self.title().startswith('GVIM') and bbox == 'special2':
# Specify the relative position
abs_bbox = rel_to_abs_bbox(m=2,
x=0.0, y=0.0,
w=1.0, h=0.7)
else:
abs_bbox = ','.join(map(str, eval(bbox)))
print('MOVING: win_key = %r' % (self.title(),))
print('TO: abs_bbox = %r' % (abs_bbox,))
# abs_bbox.replace('[', '').replace(']', '')
# get = lambda cmd: XCtrl.cmd(' '.join(["/bin/bash", "-c", cmd]))['out'] # NOQA
win_id = XCtrl.find_window_id(self.title(), error='raise')
print('MOVING: win_id = %r' % (win_id,))
fmtdict = locals()
cmd_list = [
("wmctrl -ir {win_id} -b remove,maximized_horz".format(**fmtdict)),
("wmctrl -ir {win_id} -b remove,maximized_vert".format(**fmtdict)),
("wmctrl -ir {win_id} -e 0,{abs_bbox}".format(**fmtdict)),
]
print('\n'.join(cmd_list))
for cmd in cmd_list:
XCtrl.cmd(cmd)
[docs]
def _wmctrl_terminal_patterns():
"""
wmctrl patterns associated with common terminals
"""
terminal_pattern = r'|'.join([
'terminal',
re.escape('terminator.Terminator'), # gtk3 terminator
re.escape('x-terminal-emulator.X-terminal-emulator'), # gtk2 terminator
# other common terminal applications
'tilix',
'konsole',
'rxvt',
'terminology',
'xterm',
'tilda',
'Yakuake',
'kitty.kitty',
])
return terminal_pattern
[docs]
class XCtrl(object):
r"""
xdotool key ctrl+shift+i
References:
http://superuser.com/questions/382616/detecting-currently-active-window
http://askubuntu.com/questions/455762/xbindkeys-wont-work-properly
Ignore:
xdotool keyup --window 0 7 type --clearmodifiers ---window 0 '%paste'
# List current windows:
wmctrl -l
# Get current window
xdotool getwindowfocus getwindowname
#====
# Get last opened window
#====
win_title=x-terminal-emulator.X-terminal-emulator
key_ = 'x-terminal-emulator.X-terminal-emulator'
# Get all windows in current workspace
workspace_number=`wmctrl -d | grep '\*' | cut -d' ' -f 1`
win_list=`wmctrl -lx | grep $win_title | grep " $workspace_number " | awk '{print $1}'`
# Get stacking order of windows in current workspace
win_order=$(xprop -root|grep "^_NET_CLIENT_LIST_STACKING" | tr "," " ")
echo $win_order
CommandLine:
python -m vimtk.xctrl XCtrl:0
Example:
>>> # xdoctest: +SKIP
>>> # Script
>>> orig_window = []
>>> copy_text_to_clipboard(lorium_ipsum())
>>> doscript = [
>>> ('focus', 'x-terminal-emulator.X-terminal-emulator'),
>>> ('type', '%paste'),
>>> ('key', 'KP_Enter'),
>>> # ('focus', 'GVIM')
>>> ]
>>> XCtrl.do(*doscript, sleeptime=.01)
Ignore:
>>> # xdoctest: +SKIP
>>> copy_text_to_clipboard(text)
>>> if '\n' in text or len(text) > 20:
>>> text = '\'%paste\''
>>> else:
>>> import pipes
>>> text = pipes.quote(text.lstrip(' '))
>>> ('focus', 'GVIM'),
>>> #
>>> doscript = [
>>> ('focus', 'x-terminal-emulator.X-terminal-emulator'),
>>> ('type', text),
>>> ('key', 'KP_Enter'),
>>> ]
>>> XCtrl.do(*doscript, sleeptime=.01)
"""
# @staticmethod
# def send_raw_key_input(keys):
# print('send key input: %r' % (keys,))
# args = ['xdotool', 'type', keys]
# XCtrl.cmd(*args, quiet=True, silence=True)
[docs]
@classmethod
def cmd(XCtrl, command):
logging.debug('[cmd] {}'.format(command))
info = ub.cmd(command)
if info['ret'] != 0:
logging.warn('Something went wrong {}'.format(ub.urepr(info)))
return info
[docs]
@classmethod
def findall_window_ids(XCtrl, pattern=None):
"""
Returns:
List[int]: wmctl ids for the matching windows
CommandLine:
python -m vimtk.xctrl XCtrl.findall_window_ids --pat=gvim --noskip
python -m vimtk.xctrl XCtrl.findall_window_ids --pat=gvim
python -m vimtk.xctrl XCtrl.findall_window_ids --pat=joncrall
Example:
>>> # xdoctest: +REQUIRES(--noskip)
>>> from vimtk.xctrl import * # NOQA
>>> pattern = ub.argval('--pat')
>>> winid_list = XCtrl.findall_window_ids(pattern)
>>> print('winid_list = {!r}'.format(winid_list))
Ignore:
wmctrl -l
xprop -id
wmctrl -l | awk '{print $1}' | xprop -id
0x00a00007 | grep "WM_CLASS(STRING)"
"""
# List all windows and their identifiers
info = XCtrl.cmd('wmctrl -lx')
lines = info['out'].split('\n')
if pattern is not None:
# Find windows with identifiers matching the pattern
lines = [line for line in lines if re.search(pattern, line)]
# Get the hex-id portion of the output
winid_list = [line.split()[0] for line in lines]
winid_list = [int(h, 16) for h in winid_list if h]
return winid_list
[docs]
@classmethod
def sort_window_ids(XCtrl, winid_list, order='mru'):
"""
Orders window ids by most recently used
"""
def isect(list1, list2):
set2 = set(list2)
return [item for item in list1 if item in set2]
winid_order = XCtrl.sorted_window_ids(order)
sorted_win_ids = isect(winid_order, winid_list)
return sorted_win_ids
[docs]
@staticmethod
def killold(pattern, num=4):
"""
Leaves no more than `num` instances of a program alive. Ordering is
determined by most recent usage.
CommandLine:
python -m vimtk.xctrl XCtrl.killold gvim 2
Example:
>>> # xdoctest: +SKIP
>>> XCtrl = xctrl.XCtrl
>>> pattern = 'gvim'
>>> num = 2
"""
import psutil
num = int(num)
winid_list = XCtrl.findall_window_ids(pattern)
winid_list = XCtrl.sort_window_ids(winid_list, 'mru')[num:]
info = XCtrl.cmd('wmctrl -lxp')
lines = info['out'].split('\n')
lines = [' '.join(list(ub.take(line.split(), [0, 2])))
for line in lines]
output_lines = lines
# output_lines = XCtrl.cmd(
# """wmctrl -lxp | awk '{print $1 " " $3}'""",
# **cmdkw)['out'].strip().split('\n')
output_fields = [line.split(' ') for line in output_lines]
output_fields = [(int(wid, 16), int(pid)) for wid, pid in output_fields]
pid_list = [pid for wid, pid in output_fields if wid in winid_list]
for pid in pid_list:
proc = psutil.Process(pid=pid)
proc.kill()
[docs]
@staticmethod
def sorted_window_ids(order='mru'):
"""
Returns window ids orderd by criteria
default is mru (most recently used)
CommandLine:
xprop -root | grep "^_NET_CLIENT_LIST_STACKING" | tr "," " "
python -m vimtk.xctrl XCtrl.sorted_window_ids
CommandLine:
python -m vimtk.xctrl XCtrl.sorted_window_ids
Example:
>>> # xdoctest: +SKIP
>>> winid_order = XCtrl.sorted_window_ids()
>>> print('winid_order = {!r}'.format(winid_order))
"""
info = XCtrl.cmd('xprop -root')
lines = [line for line in info['out'].split('\n')
if line.startswith('_NET_CLIENT_LIST_STACKING')]
assert len(lines) == 1, str(lines)
winid_order_str = lines[0]
winid_order = winid_order_str.split('#')[1].strip().split(', ')[::-1]
winid_order = [int(h, 16) for h in winid_order]
if order == 'lru':
winid_order = winid_order[::-1]
elif order == 'mru':
winid_order = winid_order
else:
raise NotImplementedError(order)
return winid_order
[docs]
@staticmethod
def find_window_id(pattern, method='mru', error='raise'):
"""
xprop -id 0x00a00007 | grep "WM_CLASS(STRING)"
"""
logging.debug('Find window id pattern={}, method={}'.format(pattern, method))
winid_candidates = XCtrl.findall_window_ids(pattern)
if len(winid_candidates) == 0:
if error == 'raise':
available_windows = XCtrl.cmd('wmctrl -lx')['out']
msg = 'No window matches pattern=%r' % (pattern,)
msg += '\navailable windows are:\n%s' % (available_windows,)
logger.error(msg)
raise Exception(msg)
win_id = None
elif len(winid_candidates) == 1:
win_id = winid_candidates[0]
else:
# print('Multiple (%d) windows matches pattern=%r' % (
# len(winid_list), pattern,))
# Find most recently used window with the focus name.
win_id = XCtrl.sort_window_ids(winid_candidates, method)[0]
return win_id
[docs]
@staticmethod
def current_gvim_edit(op='e', fpath=''):
r"""
CommandLine:
python -m vimtk.xctrl XCtrl.current_gvim_edit sp ~/.bashrc
"""
fpath = ub.shrinkuser(ub.truepath(fpath))
# print('fpath = %r' % (fpath,))
cplat.copy_text_to_clipboard(fpath)
doscript = [
('focus', 'gvim'),
('key', 'Escape'),
('type2', ';' + op + ' ' + fpath),
# ('type2', ';' + op + ' '),
# ('key', 'ctrl+v'),
('key', 'KP_Enter'),
]
XCtrl.do(*doscript, verbose=0, sleeptime=.001)
[docs]
@staticmethod
def copy_gvim_to_terminal_script(text, return_to_win="1", verbose=0, sleeptime=.02):
"""
vimtk.xctrl.XCtrl.copy_gvim_to_terminal_script('print("hi")', verbose=1)
python -m vimtk.xctrl XCtrl.copy_gvim_to_terminal_script "echo hi" 1 1
If this doesn't work make sure pyperclip is installed and set to xsel
print('foobar')
echo hi
"""
# Prepare to send text to xdotool
cplat.copy_text_to_clipboard(text)
if verbose:
print('text = %r' % (text,))
print(cplat.get_clipboard())
terminal_pattern = r'\|'.join([
'terminal',
re.escape('terminator.Terminator'), # gtk3 terminator
re.escape('x-terminal-emulator.X-terminal-emulator'), # gtk2 terminator
])
# Build xdtool script
doscript = [
('remember_window_id', 'ACTIVE_WIN'),
# ('focus', 'x-terminal-emulator.X-terminal-emulator'),
('focus', terminal_pattern),
('key', 'ctrl+shift+v'),
('key', 'KP_Enter'),
]
if '\n' in text:
# Press enter twice for multiline texts
doscript += [
('key', 'KP_Enter'),
]
if return_to_win == "1":
doscript += [
('focus_id', '$ACTIVE_WIN'),
]
# execute script
# verbose = 1
XCtrl.do(*doscript, sleeptime=sleeptime, verbose=verbose)
[docs]
@staticmethod
def do(*cmd_list, **kwargs):
"""
DEPRICATE THIS
"""
verbose = kwargs.get('verbose', False)
if verbose:
print = logger.info
else:
print = logger.debug
print('Executing x do: %s' % (ub.urepr(cmd_list),))
# http://askubuntu.com/questions/455762/xbindkeys-wont-work-properly
# Make things work even if other keys are pressed
defaultsleep = 0.0
sleeptime = kwargs.get('sleeptime', defaultsleep)
time.sleep(.05)
XCtrl.cmd('xset r off')
memory = {}
for count, item in enumerate(cmd_list):
# print('item = %r' % (item,))
sleeptime = kwargs.get('sleeptime', defaultsleep)
assert isinstance(item, tuple)
assert len(item) >= 2
xcmd, key_ = item[0:2]
if len(item) >= 3:
if isinstance(item[2], str) and item[2].endswith('?'):
sleeptime = float(item[2][:-1])
print('special command sleep')
print('sleeptime = %r' % (sleeptime,))
else:
sleeptime = float(item[2])
args = []
print('# Step %d' % (count,))
print('xcmd = {!r}'.format(xcmd))
if xcmd == 'focus':
key_ = str(key_)
if key_.startswith('$'):
key_ = memory[key_[1:]]
pattern = key_
win_id = XCtrl.find_window_id(pattern, method='mru')
if win_id is None:
args = ['wmctrl', '-xa', pattern]
else:
args = ['wmctrl', '-ia', hex(win_id)]
elif xcmd == 'focus_id':
key_ = str(key_)
if key_.startswith('$'):
key_ = memory[key_[1:]]
args = ['wmctrl', '-ia', hex(key_)]
elif xcmd == 'remember_window_id':
memory[key_] = XCtrl.current_window_id()
continue
elif xcmd == 'remember_window_name':
memory[key_] = XCtrl.current_window_name()
continue
elif xcmd == 'type':
args = [
'xdotool',
'keyup', '--window', '0', '7',
'type', '--clearmodifiers',
'--window', '0', str(key_)
]
elif xcmd == 'type2':
args = [
'xdotool', 'type', pipes.quote(str(key_))
]
elif xcmd == 'xset-r-on':
args = ['xset', 'r', 'on']
elif xcmd == 'xset-r-off':
args = ['xset', 'r', 'off']
else:
args = ['xdotool', str(xcmd), str(key_)]
print('args = {!r}'.format(args))
XCtrl.cmd(args)
if sleeptime > 0:
time.sleep(sleeptime)
XCtrl.cmd('xset r on')
[docs]
@staticmethod
def current_window_id():
logging.debug('Get current window id')
info = XCtrl.cmd('xdotool getwindowfocus')
value = int(info['out'].strip())
logging.debug('... current window id = {}'.format(value))
return value
[docs]
@staticmethod
def current_window_name():
logging.debug('Get current window name')
info = XCtrl.cmd('xdotool getwindowfocus getwindowname')
value = pipes.quote(info['out'].strip())
logging.debug('... current window name = {}'.format(value))
return value
[docs]
@staticmethod
def focus_window(winhandle, path=None, name=None, sleeptime=.01):
"""
sudo apt-get install xautomation
apt-get install autokey-gtk
wmctrl -xa gnome-terminal.Gnome-terminal
wmctrl -xl
"""
print('focus: ' + winhandle)
args = ['wmctrl', '-xa', winhandle]
XCtrl.cmd(*args, verbose=False)
time.sleep(sleeptime)
[docs]
@classmethod
def send_keys(XCtrl, key, sleeptime=0.1):
args = ['xdotool', 'key', str(key)]
XCtrl.cmd(args)
time.sleep(sleeptime)
# @classmethod
# def focus(XCtrl, pattern=None, win_id=None, sleeptime=.01):
# """
# sudo apt-get install xautomation
# apt-get install autokey-gtk
# wmctrl -xa gnome-terminal.Gnome-terminal
# wmctrl -xl
# """
# if pattern is not None:
# assert win_id is None
# if win_id is None:
# assert pattern is not None
# win_id = XCtrl.find_window_id(pattern, method='mru')
# if win_id is None:
# args = ['wmctrl', '-xa', pattern]
# else:
# args = ['wmctrl', '-ia', hex(win_id)]
# XCtrl.cmd(*args, verbose=False)
# time.sleep(sleeptime)
if __name__ == '__main__':
r"""
CommandLine:
export PYTHONPATH=$PYTHONPATH:$HOME/code/vimtk
python -m vimtk.xctrl
"""
import xdoctest
xdoctest.doctest_module(__file__)