mirror of
https://github.com/gryf/moveto.git
synced 2025-12-18 20:10:25 +01:00
Removed pygtk dependency, generalize a way for detecting and name monitors
This commit is contained in:
81
moveto.py
81
moveto.py
@@ -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)
|
||||||
@@ -171,19 +170,31 @@ def get_window_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:
|
||||||
@@ -313,6 +329,25 @@ class Screen(object):
|
|||||||
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"""
|
||||||
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user