mirror of
https://github.com/gryf/moveto.git
synced 2025-12-18 20:10:25 +01:00
Added py3 support
This commit is contained in:
150
moveto.py
150
moveto.py
@@ -3,7 +3,7 @@
|
|||||||
Position/place windows in WindowMaker.
|
Position/place windows in WindowMaker.
|
||||||
Script calculates size of the target windows depending on current screen size.
|
Script calculates size of the target windows depending on current screen size.
|
||||||
|
|
||||||
Required python 2.7
|
Required python 3.9
|
||||||
|
|
||||||
Dependencies:
|
Dependencies:
|
||||||
- docopt
|
- docopt
|
||||||
@@ -125,16 +125,16 @@ Date: 2015-12-13 Added simple detection of certain windows, which doesn't
|
|||||||
Date: 2016-01-15 Moved corrections of the position of the QT apps after the
|
Date: 2016-01-15 Moved corrections of the position of the QT apps after the
|
||||||
columns gets calculated
|
columns gets calculated
|
||||||
Date: 2017-01-13 Removed pygtk dependency, don't rely on display names
|
Date: 2017-01-13 Removed pygtk dependency, don't rely on display names
|
||||||
Version: 1.7
|
Date: 2021-09-10 removed docopt, added support for py3
|
||||||
"""
|
"""
|
||||||
from subprocess import Popen, PIPE, call, check_output
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import subprocess
|
||||||
|
|
||||||
from docopt import docopt
|
|
||||||
|
|
||||||
|
__version__ = 1.8
|
||||||
|
|
||||||
# TODO: Make it configurable (lots of options starting from ini file)
|
# TODO: Make it configurable (lots of options starting from ini file)
|
||||||
|
|
||||||
@@ -142,12 +142,12 @@ from docopt import docopt
|
|||||||
def get_magic_number():
|
def get_magic_number():
|
||||||
"""Get the numbers for window shift and position"""
|
"""Get the numbers for window shift and position"""
|
||||||
|
|
||||||
out = Popen(['xdotool', 'getactivewindow'],
|
res = subprocess.run(['xdotool', 'getactivewindow'], encoding='utf-8',
|
||||||
stdout=PIPE).communicate()[0]
|
capture_output=True)
|
||||||
out = out.strip()
|
out = res.stdout.strip()
|
||||||
out = Popen(['xwininfo', '-id', out],
|
res = subprocess.run(['xwininfo', '-id', out], encoding='utf-8',
|
||||||
stdout=PIPE).communicate()[0]
|
capture_output=True)
|
||||||
out.strip()
|
out = res.stdout.strip()
|
||||||
for line in out.split("\n"):
|
for line in out.split("\n"):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line.startswith("Relative upper-left Y"):
|
if line.startswith("Relative upper-left Y"):
|
||||||
@@ -156,15 +156,16 @@ def get_magic_number():
|
|||||||
|
|
||||||
return magic * 2 + 1, magic + 8
|
return magic * 2 + 1, magic + 8
|
||||||
|
|
||||||
|
|
||||||
MAGIC_NO, DECORATIONS_HEIGHT = get_magic_number()
|
MAGIC_NO, DECORATIONS_HEIGHT = get_magic_number()
|
||||||
|
|
||||||
|
|
||||||
def get_window_name():
|
def get_window_name():
|
||||||
"""Return the current active window name"""
|
"""Return the current active window name"""
|
||||||
|
|
||||||
name = Popen(["xdotool", "getactivewindow", "getwindowname"],
|
res = subprocess.run(["xdotool", "getactivewindow", "getwindowname"],
|
||||||
stdout=PIPE).communicate()[0]
|
encoding='utf-8', capture_output=True)
|
||||||
name = name.strip()
|
name = res.stdout.strip()
|
||||||
logging.debug('window name: %s', name)
|
logging.debug('window name: %s', name)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ def get_monitors():
|
|||||||
dimensions (as a tuple position x, y and dimension x and y)
|
dimensions (as a tuple position x, y and dimension x and y)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
connected = re.compile('^(?P<display_name>.+)\sconnected\s'
|
connected = re.compile('^(?P<display_name>[a-zA-Z0-9-]+)\s[a-zA-Z\s]+\s'
|
||||||
'(?P<x>\d+)x'
|
'(?P<x>\d+)x'
|
||||||
'(?P<y>\d+)\+'
|
'(?P<y>\d+)\+'
|
||||||
'(?P<sx>\d+)\+'
|
'(?P<sx>\d+)\+'
|
||||||
@@ -185,10 +186,12 @@ def get_monitors():
|
|||||||
|
|
||||||
monitors = {}
|
monitors = {}
|
||||||
|
|
||||||
randr = Popen(['xrandr'], stdout=PIPE)
|
res = subprocess.run(['xrandr'], encoding='utf-8', capture_output=True)
|
||||||
out = check_output('grep connected'.split(), stdin=randr.stdout)
|
|
||||||
|
for line in res.stdout.split('\n'):
|
||||||
|
if 'disconnected' in line or 'connected' not in line:
|
||||||
|
continue
|
||||||
|
|
||||||
for line in out.split('\n'):
|
|
||||||
res = connected.match(line)
|
res = connected.match(line)
|
||||||
if not res:
|
if not res:
|
||||||
continue
|
continue
|
||||||
@@ -383,10 +386,11 @@ class WMWindow(object):
|
|||||||
arranged vertically. Note, that clip may or may not influence the
|
arranged vertically. Note, that clip may or may not influence the
|
||||||
process, since it might be placed freely, and contains more dockapps
|
process, since it might be placed freely, and contains more dockapps
|
||||||
or appicons than dock itself."""
|
or appicons than dock itself."""
|
||||||
res = Popen("xwininfo -tree -root -children".split(),
|
|
||||||
stdout=PIPE).communicate()[0]
|
res = subprocess.run("xwininfo -tree -root -children".split(),
|
||||||
|
encoding='utf-8', capture_output=True)
|
||||||
result = {}
|
result = {}
|
||||||
for item in res.split("\n"):
|
for item in res.stdout.split("\n"):
|
||||||
if "64x64" not in item:
|
if "64x64" not in item:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -423,9 +427,10 @@ class WMWindow(object):
|
|||||||
"""
|
"""
|
||||||
self.x = self.y = self.pos_x = self.pos_y = None
|
self.x = self.y = self.pos_x = self.pos_y = None
|
||||||
|
|
||||||
out = Popen(["xdotool", "getactivewindow", "getwindowgeometry"],
|
res = subprocess.run(["xdotool", "getactivewindow",
|
||||||
stdout=PIPE).communicate()[0]
|
"getwindowgeometry"],
|
||||||
out = out.strip().split("\n")
|
encoding='utf-8', capture_output=True)
|
||||||
|
out = res.stdout.strip().split("\n")
|
||||||
|
|
||||||
if len(out) != 3:
|
if len(out) != 3:
|
||||||
logging.warning('Cannot get window size and position for %s',
|
logging.warning('Cannot get window size and position for %s',
|
||||||
@@ -554,12 +559,12 @@ class WMWindow(object):
|
|||||||
return coord_map[which]
|
return coord_map[which]
|
||||||
|
|
||||||
|
|
||||||
def cycle(monitors, right=False, main_screen=None):
|
def cycle(monitors, args):
|
||||||
"""Cycle through the window states"""
|
"""Cycle through the window states"""
|
||||||
wmwin = WMWindow(monitors, main_screen)
|
wmwin = WMWindow(monitors, args.monitor_name)
|
||||||
current_state = wmwin.guess_dimensions()
|
current_state = wmwin.guess_dimensions()
|
||||||
|
|
||||||
direction = "right" if right else "left"
|
direction = "right" if args.right else "left"
|
||||||
logging.debug('direction: %s, current_state %s', direction, current_state)
|
logging.debug('direction: %s, current_state %s', direction, current_state)
|
||||||
|
|
||||||
if direction == "left":
|
if direction == "left":
|
||||||
@@ -594,74 +599,85 @@ def cycle(monitors, right=False, main_screen=None):
|
|||||||
'mousemove', str(coords['pos_x'] + coords['size_x'] / 2),
|
'mousemove', str(coords['pos_x'] + coords['size_x'] / 2),
|
||||||
str(coords['pos_y'] + coords['size_y'] / 2)]
|
str(coords['pos_y'] + coords['size_y'] / 2)]
|
||||||
|
|
||||||
call(cmd)
|
subprocess.run(cmd)
|
||||||
|
|
||||||
|
|
||||||
def show_monitors(monitors):
|
def show_monitors(monitors, args):
|
||||||
"""Print out available monitors"""
|
"""Print out available monitors"""
|
||||||
print "Available monitors:"
|
print("Available monitors:")
|
||||||
for name, data in monitors.items():
|
for name, data in monitors.items():
|
||||||
mon = data.copy()
|
mon = data.copy()
|
||||||
mon.update({'name': name})
|
mon.update({'name': name})
|
||||||
logging.debug('%(name)s at %(sx)sx%(sy)s with dimensions '
|
print('%(name)s at %(sx)sx%(sy)s with dimensions %(x)sx%(y)s' % mon)
|
||||||
'%(x)sx%(y)s', mon)
|
|
||||||
|
|
||||||
|
|
||||||
def move_mouse(monitors, name):
|
def move_mouse(monitors, args):
|
||||||
"""Move the mosue pointer to the left upper corner oft the specified by
|
"""Move the mosue pointer to the left upper corner oft the specified by
|
||||||
the name screen"""
|
the name screen"""
|
||||||
mon = monitors.get(name)
|
mon = monitors.get(args.monitor_name)
|
||||||
|
|
||||||
# if not mon:
|
# if not mon:
|
||||||
# logging.warning('No such monitor: %s', name)
|
# logging.warning('No such monitor: %s', name)
|
||||||
# return
|
# return
|
||||||
|
|
||||||
posx = mon['sx'] + 15
|
posx = int(mon['sx']) + 15
|
||||||
posy = mon['sy'] + 50
|
posy = int(mon['sy']) + 50
|
||||||
cmd = ['xdotool', 'mousemove', str(posx), str(posy)]
|
cmd = ['xdotool', 'mousemove', str(posx), str(posy)]
|
||||||
call(cmd)
|
subprocess.run(cmd)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""get the arguments, run the app"""
|
"""get the arguments, run the app"""
|
||||||
arguments = """Move windows around mimicking Windows7 flag+arrows behaviour
|
parser = argparse.ArgumentParser(description="Move windows around "
|
||||||
|
"mimicking Windows7 flag+arrows "
|
||||||
|
"behaviour")
|
||||||
|
parser.add_argument('-v', '--version', help='Show version',
|
||||||
|
action='store_true')
|
||||||
|
|
||||||
Usage:
|
subparsers = parser.add_subparsers(help='supported commands')
|
||||||
%(prog)s move (left|right) [-r|-l] [-m NAME] [-d]
|
|
||||||
%(prog)s mousemove -m NAME [-d]
|
|
||||||
%(prog)s showmonitors [-d]
|
|
||||||
%(prog)s (-h | --help)
|
|
||||||
%(prog)s --version
|
|
||||||
|
|
||||||
Options:
|
move = subparsers.add_parser('move', help='Move window')
|
||||||
-m NAME --monitor-name=NAME Name of the monitor to be treated as the main
|
group = move.add_mutually_exclusive_group()
|
||||||
one (so the one containing dock)
|
group.add_argument('--left', action='store_true')
|
||||||
-r --dock-right Dock is on the right edge of the rightmost
|
group.add_argument('--right', action='store_true')
|
||||||
screen
|
group = move.add_mutually_exclusive_group()
|
||||||
-l --dock-left Dock is on the left edge of the leftmost screen
|
group.add_argument('-r', '--dock-right', action='store_true',
|
||||||
-h --help Show this screen.
|
help='Dock is on the right edge of the rightmost '
|
||||||
-v --version Show version.
|
'screen')
|
||||||
-d --debug Show debug messages.
|
group.add_argument('-l', '--dock-left', action='store_true',
|
||||||
|
help='Dock is on the left edge of the leftmost screen')
|
||||||
|
move.add_argument('-m', '--monitor-name', help='Name of the monitor to be '
|
||||||
|
'treated as the main one (so the one containing dock)')
|
||||||
|
move.add_argument('-d', '--debug', action='store_true',
|
||||||
|
help='Show debug messages')
|
||||||
|
move.set_defaults(func=cycle)
|
||||||
|
|
||||||
""" % {'prog': sys.argv[0]}
|
mousemove = subparsers.add_parser('mousemove', help='Move mouse pointer')
|
||||||
opts = docopt(arguments, version=1.7)
|
mousemove.add_argument('-m', '--monitor-name', help='Name of the monitor '
|
||||||
level = logging.DEBUG if opts['--debug'] else logging.WARNING
|
'to move mouse pointer to', required=True)
|
||||||
|
mousemove.add_argument('-d', '--debug', action='store_true',
|
||||||
|
help='Show debug messages')
|
||||||
|
mousemove.set_defaults(func=move_mouse)
|
||||||
|
|
||||||
|
showmonitors = subparsers.add_parser('showmonitors')
|
||||||
|
showmonitors.add_argument('-d', '--debug', action='store_true',
|
||||||
|
help='Show debug messages')
|
||||||
|
showmonitors.set_defaults(func=show_monitors)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.version:
|
||||||
|
print(__version__)
|
||||||
|
return
|
||||||
|
|
||||||
|
level = logging.DEBUG if args.debug else logging.WARNING
|
||||||
logging.basicConfig(filename=os.path.expanduser('~/moveto.log'),
|
logging.basicConfig(filename=os.path.expanduser('~/moveto.log'),
|
||||||
format='%(funcName)s:%(lineno)d %(message)s',
|
format='%(funcName)s:%(lineno)d %(message)s',
|
||||||
level=level)
|
level=level)
|
||||||
|
|
||||||
monitors = get_monitors()
|
monitors = get_monitors()
|
||||||
|
|
||||||
if opts['showmonitors']:
|
args.func(monitors, args)
|
||||||
show_monitors(monitors)
|
|
||||||
return
|
|
||||||
|
|
||||||
if opts['mousemove']:
|
|
||||||
move_mouse(monitors, opts['--monitor-name'])
|
|
||||||
return
|
|
||||||
|
|
||||||
if opts['move']:
|
|
||||||
cycle(monitors, bool(opts['right']),
|
|
||||||
main_screen=opts['--monitor-name'])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user