1
0
mirror of https://github.com/gryf/moveto.git synced 2025-12-17 11:30:21 +01:00

Use gdk to dedect screen layout

This commit is contained in:
2015-01-05 13:33:08 +01:00
parent b5a2e1a431
commit 20684f77db

View File

@@ -6,7 +6,7 @@ Script calculates size of the target windows depending on current screen size.
Required python 2.7
Dependencies:
- xrandr
- pygtk
- wmctrl
- xdotool
- xwininfo
@@ -47,17 +47,20 @@ possible moves of the depicted window would be:
- move to screen 1 to the left half
- move to screen 1 to the right half
TODO: Make it more flexible with different window configurations
Author: Roman 'gryf' Dobosz <gryf73@gmail.com>
Date: 2013-01-06
Version: 1.1
Date: 2014-03-31 (used pygtk instead of xrandr, which is faster)
Version: 1.2
"""
import os
import sys
import re
from subprocess import Popen, PIPE, call
import json
CACHE_FILENAME = "~/.cache/res_pos_win.cache"
from gtk import gdk
DOCK_ON_RIGHT = True
COVER_MINIWINDOWS = False
COVER_DOCK = False
@@ -72,25 +75,12 @@ class Screens(object):
"""Class container for a Screen objects and whole area coordinates"""
self.screens = []
self.coords = ()
self.dimension = None
def append(self, screen):
"""Add screen"""
self.screens.append(screen)
def dump(self):
"""Dump object as dictionary - suitable for serialziation"""
return {"coords": self.coords,
"screens": [scr.dump() for scr in self.screens]}
def load(self, data):
"""Recreate object state from provided dictionary"""
self.screens = []
self.coords = tuple(data["coords"])
for scr in data['screens']:
screen = Screen()
screen.load(scr)
self.screens.append(screen)
def guess_dimensions(self, window):
"""
Check wheter current window is in one of three states: maximized,
@@ -111,6 +101,7 @@ class Screens(object):
return None
class Screen(object):
"""
Holds separate display information. It can be separate X screen or just a
@@ -150,7 +141,6 @@ class Screen(object):
# it is rare, but hell, shit happens
sx = sx - 1
if self.main and not COVER_DOCK:
# dock on the right side + 2px for border
self.x = sx = sx - (64 + 2)
@@ -169,31 +159,6 @@ class Screen(object):
self.maximized['size_y'] = self.right_half['size_y'] = \
self.left_half['size_y'] = sy - DECOTATORS_HEIGHT
def dump(self):
"""
Return current Screen object state as dictionary suitable for
serialization
"""
return {"main": self.main,
"x": self.x,
"y": self.y,
"x_shift": self.x_shift,
"y_shift": self.y_shift,
"left_half": self.left_half,
"right_half": self.right_half,
"maximized": self.maximized}
def load(self, data):
"""Restore Screen state from provided dictionary"""
self.x = data['x']
self.y = data['y']
self.x_shift = data['x_shift']
self.y_shift = data['y_shift']
self.left_half = data['left_half']
self.right_half = data['right_half']
self.maximized = data['maximized']
self.main = data['main']
class WMWindow(object):
"""
@@ -201,7 +166,7 @@ class WMWindow(object):
surrounded environment (screens and such).
"""
screen_re = re.compile("[^,]*,\scurrent\s(\d+)\sx\s(\d+),.*")
screen_re = re.compile("[^,].*,\scurrent\s(\d+)\sx\s(\d+),.*")
device_re = re.compile(".*\sconnected\s(\d+)x(\d+)\+(\d+)\+(\d+)")
display_re = re.compile("^.*,\scurrent\s(\d+)\sx\s(\d+),\s.*$")
position_re = re.compile("^\s+Position:\s(\d+),(\d+)\s.*$")
@@ -220,22 +185,9 @@ class WMWindow(object):
self.current_screen = 0
self.state = None
self._load_screens()
self._discover_screens()
self._get_props()
def _load_screens(self):
"""
Load screen form cache file or create them from scratch if cache
doesn't exists
"""
fname = os.path.expanduser(CACHE_FILENAME)
if not os.path.exists(fname):
self._discover_screens()
else:
with open(fname) as fp_:
self.screens = Screens()
self.screens.load(json.load(fp_))
def _get_props(self):
"""
Update current window dimensions and position
@@ -281,45 +233,20 @@ class WMWindow(object):
def _discover_screens(self):
"""Create list of available screens. Assuming, that first screen
reported is main screen."""
out = Popen(['xrandr'], stdout=PIPE).communicate()[0]
self.screens = Screens()
for line in out.split("\n"):
if self.device_re.match(line):
x, y, sx, sy = self.device_re.match(line).groups()
screen = Screen(x, y, sx, sy)
if not self.screens.screens:
screen.main = True
screen.calculate_columns()
self.screens.append(screen)
match = self.display_re.match(line)
if match:
self.display_size = match.groups()
# get the screen dimension - it may be composed by several outputs
self.display_size = (gdk.screen_width(), gdk.screen_height())
fname = os.path.expanduser(CACHE_FILENAME)
# sort screens depending on the position (only horizontal order is
# supported)
screens = {}
for screen in self.screens.screens:
screens[screen.x_shift] = screen
self.screens.screens = [screens[key] for key in
sorted(screens.keys())]
if not os.path.exists(fname):
try:
os.makedirs(os.path.dirname(fname))
except OSError:
pass
try:
with open(fname, "w") as fp:
json.dump(self.screens.dump(), fp)
except (OSError, IOError) as msg:
print "Error in creating cache file:\n", msg
gdk_screen = gdk.screen_get_default()
for out_num in range(gdk_screen.get_n_monitors()):
sx, sy, x, y = gdk_screen.get_monitor_geometry(out_num)
screen = Screen(x, y, sx, sy)
if not self.screens.screens:
screen.main = True
screen.calculate_columns()
self.screens.append(screen)
def get_data(self):
"""Return current window coordinates and size"""
@@ -350,30 +277,27 @@ class WMWindow(object):
self.current_screen = idx
return True
def full(self):
"""Maximize window"""
# def left(self, screen_direction=None):
# """Maximize to left half"""
def left(self, screen_direction=None):
"""Maximize to left half"""
# coords = self.screens.screens[self.current_screen].left_half
# cmd = ['xdotool', "getactivewindow",
# "windowmove", str(coords['pos_x']), str(coords['pos_y']),
# "windowsize", str(coords['size_x']), str(coords['size_y'])]
# call(cmd)
coords = self.screens.screens[self.current_screen].left_half
cmd = ['xdotool', "getactivewindow",
"windowmove", str(coords['pos_x']), str(coords['pos_y']),
"windowsize", str(coords['size_x']), str(coords['size_y'])]
call(cmd)
# def right(self, screen_direction=None):
# """Maximize to right half"""
# cmd = ['xdotool', "getactivewindow"]
# if screen_direction:
# if not self.move_to_screen(screen_direction):
# return
def right(self, screen_direction=None):
"""Maximize to right half"""
cmd = ['xdotool', "getactivewindow"]
if screen_direction:
if not self.move_to_screen(screen_direction):
return
if screen_direction:
move = self.move_to_screen(screen_direction)
if not move:
return
cmd.extend(move)
# if screen_direction:
# move = self.move_to_screen(screen_direction)
# if not move:
# return
# cmd.extend(move)
def get_coords(self, which):
"""Return screen coordinates"""
@@ -422,6 +346,7 @@ def usage():
if __name__ == "__main__":
if len(sys.argv) < 2:
usage()
sys.exit(1)
if sys.argv[1] == "cycle_left":
cycle("left")
@@ -429,4 +354,4 @@ if __name__ == "__main__":
cycle("right")
else:
usage()
sys.exit(1)