1
0
mirror of https://github.com/gryf/moveto.git synced 2025-12-18 03:50:25 +01:00

Removed pygtk dependency, generalize a way for detecting and name monitors

This commit is contained in:
2017-01-13 18:53:18 +01:00
parent 874ecbabb7
commit b318abe5ba

View File

@@ -6,7 +6,6 @@ Script calculates size of the target windows depending on current screen size.
Required python 2.7 Required python 2.7
Dependencies: Dependencies:
- pygtk
- docopt - docopt
- wmctrl - wmctrl
- xdotool - xdotool
@@ -125,16 +124,16 @@ Date: 2015-12-13 Added simple detection of certain windows, which doesn't
behave nicely - mostly QT apps behave nicely - mostly QT apps
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
Version: 1.6 Date: 2017-01-13 Removed pygtk dependency, don't rely on display names
Version: 1.7
""" """
from subprocess import Popen, PIPE, call from subprocess import Popen, PIPE, call, check_output
import logging import logging
import os import os
import re import re
import sys import sys
from docopt import docopt from docopt import docopt
from gtk import gdk
# TODO: Make it configurable (lots of options starting from ini file) # TODO: Make it configurable (lots of options starting from ini file)
@@ -164,26 +163,38 @@ def get_window_name():
"""Return the current active window name""" """Return the current active window name"""
name = Popen(["xdotool", "getactivewindow", "getwindowname"], name = Popen(["xdotool", "getactivewindow", "getwindowname"],
stdout=PIPE).communicate()[0] stdout=PIPE).communicate()[0]
name = name.strip() name = name.strip()
logging.debug('window name: %s', name) logging.debug('window name: %s', name)
return name return name
def get_monitors(): def get_monitors():
"""Get monitors information: """
Get monitors information:
name name
index 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'
'(?P<x>\d+)x'
'(?P<y>\d+)\+'
'(?P<sx>\d+)\+'
'(?P<sy>\d+)\s'
'\(.*\)\s\d+mm\sx\s\d+mm$')
monitors = {} monitors = {}
gdk_screen = gdk.screen_get_default()
for out_num in range(gdk_screen.get_n_monitors()): randr = Popen(['xrandr'], stdout=PIPE)
monitor = {"index": out_num} out = check_output('grep connected'.split(), stdin=randr.stdout)
(monitor["sx"], monitor["sy"],
monitor["x"], monitor["y"]) = gdk_screen.get_monitor_geometry(out_num) for line in out.split('\n'):
monitors[gdk_screen.get_monitor_plug_name(out_num)] = monitor res = connected.match(line)
if not res:
continue
res = res.groupdict()
name = res.pop('display_name')
monitors[name] = res
return monitors return monitors
@@ -225,6 +236,10 @@ class Screens(object):
return None return None
def __str__(self):
"""str"""
return "<Screens: %s>" % " ".join([str(s) for s in self.screens])
class Conf(object): class Conf(object):
"""Config namespace""" """Config namespace"""
@@ -234,7 +249,8 @@ class Conf(object):
def __init__(self): def __init__(self):
"""read actual wmaker config and set appropriate config options""" """read actual wmaker config and set appropriate config options"""
with open(os.path.expanduser("~/GNUstep/Defaults/WindowMaker")) as fobj: path = os.path.expanduser("~/GNUstep/Defaults/WindowMaker")
with open(path) as fobj:
for line in fobj: for line in fobj:
if "NoWindowOverIcons" in line and "YES" in line: if "NoWindowOverIcons" in line and "YES" in line:
self.cover_miniwindows = False self.cover_miniwindows = False
@@ -284,7 +300,7 @@ class Screen(object):
conf = Conf() conf = Conf()
if sx % 2 != 0: if sx % 2 != 0:
# it is rare, but hell, shit happens # it should't have a place, but hell, shit happens
sx = sx - 1 sx = sx - 1
if self.main and not conf.cover_dock: if self.main and not conf.cover_dock:
@@ -307,12 +323,31 @@ class Screen(object):
self.maximized['size_x'] = sx self.maximized['size_x'] = sx
self.maximized['size_y'] = self.right_half['size_y'] = \ self.maximized['size_y'] = self.right_half['size_y'] = \
self.left_half['size_y'] = sy - DECORATIONS_HEIGHT self.left_half['size_y'] = sy - DECORATIONS_HEIGHT
logging.debug('left half: %s', self.left_half) logging.debug('left half: %s', self.left_half)
logging.debug('right half: %s', self.right_half) logging.debug('right half: %s', self.right_half)
logging.debug('maximized: %s', self.maximized) logging.debug('maximized: %s', self.maximized)
def __str__(self):
return ("[Screen <%dx%d+%d+%d>, left: <%dx%d+%d+%d>, right: "
"<%dx%d+%d+%d>, max: <%dx%d+%d+%d>]" %
(self.x, self.y, self.x_shift, self.y_shift,
self.left_half['size_x'],
self.left_half['size_y'],
self.left_half['pos_x'],
self.left_half['pos_y'],
self.right_half['size_x'],
self.right_half['size_y'],
self.right_half['pos_x'],
self.right_half['pos_y'],
self.maximized['size_x'],
self.maximized['size_y'],
self.maximized['pos_x'],
self.maximized['pos_y']))
class WMWindow(object): class WMWindow(object):
""" """
Window object. Hold all of the information about current window and Window object. Hold all of the information about current window and
@@ -321,7 +356,8 @@ class WMWindow(object):
position_re = re.compile("^\s+Position:\s(\d+),(\d+)\s.*$") position_re = re.compile("^\s+Position:\s(\d+),(\d+)\s.*$")
geometry_re = re.compile(".*Geometry:\s(\d+)x(\d+).*") geometry_re = re.compile(".*Geometry:\s(\d+)x(\d+).*")
misbehaving_windows = ["Oracle VM VirtualBox", "LibreOffice"] misbehaving_windows = ["Oracle VM VirtualBox", "LibreOffice",
'cool-retro-term']
def __init__(self, monitors, main_screen): def __init__(self, monitors, main_screen):
""" """
@@ -373,7 +409,6 @@ class WMWindow(object):
winner = int(winner) winner = int(winner)
logging.debug("predicted x position of the dock: %d", winner) logging.debug("predicted x position of the dock: %d", winner)
import ripdb; ripdb.set_trace()
for screen in self.screens.screens: for screen in self.screens.screens:
logging.debug("screen: %s", str(screen)) logging.debug("screen: %s", str(screen))
if winner in range(screen.x_shift, screen.x + screen.x_shift + 1): if winner in range(screen.x_shift, screen.x + screen.x_shift + 1):
@@ -468,6 +503,7 @@ class WMWindow(object):
for screen in self.screens.screens: for screen in self.screens.screens:
screen.calculate_columns() screen.calculate_columns()
logging.info('discovered screens: %s', self.screens)
def get_data(self): def get_data(self):
"""Return current window coordinates and size""" """Return current window coordinates and size"""
@@ -553,10 +589,10 @@ def cycle(monitors, right=False, main_screen=None):
str(coords['pos_y'] + coords['size_y'] / 2)] str(coords['pos_y'] + coords['size_y'] / 2)]
else: else:
cmd = ['xdotool', 'getactivewindow', cmd = ['xdotool', 'getactivewindow',
'windowmove', str(coords['pos_x']), str(coords['pos_y']), 'windowmove', str(coords['pos_x']), str(coords['pos_y']),
'windowsize', str(coords['size_x']), str(coords['size_y']), 'windowsize', str(coords['size_x']), str(coords['size_y']),
'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) call(cmd)
@@ -567,7 +603,8 @@ def show_monitors(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 %(x)sx%(y)s', mon) logging.debug('%(name)s at %(sx)sx%(sy)s with dimensions '
'%(x)sx%(y)s', mon)
def move_mouse(monitors, name): def move_mouse(monitors, name):
@@ -575,9 +612,9 @@ def move_mouse(monitors, name):
the name screen""" the name screen"""
mon = monitors.get(name) mon = monitors.get(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 = mon['sx'] + 15
posy = mon['sy'] + 50 posy = mon['sy'] + 50
@@ -607,7 +644,7 @@ Options:
-d --debug Show debug messages. -d --debug Show debug messages.
""" % {'prog': sys.argv[0]} """ % {'prog': sys.argv[0]}
opts = docopt(arguments, version=1.6) opts = docopt(arguments, version=1.7)
level = logging.DEBUG if opts['--debug'] else logging.WARNING level = logging.DEBUG if opts['--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',