From f7b59a027060697d2a1b1c9a319f19823a140041 Mon Sep 17 00:00:00 2001 From: Lukas Rysavy Date: Wed, 27 May 2020 08:46:30 +0200 Subject: [PATCH 1/5] fixed multi screen x offset for dual monitor mode --- snaptile.py | 8 ++++++-- window.py | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/snaptile.py b/snaptile.py index e74586b..1545f1a 100755 --- a/snaptile.py +++ b/snaptile.py @@ -97,7 +97,7 @@ def global_inital_states(): get_posmap(keymap, displ) ) -global disp, root, lastkey_state, posmap; +global disp, root, lastkey_state, posmap, isDualMonitor; def run(): @@ -105,6 +105,9 @@ def run(): opts, args = getopt.getopt(sys.argv[1:], "hdWk:") keyboardLayout = autodetectKeyboard() + + global isDualMonitor + isDualMonitor = False for opt in opts: @@ -175,7 +178,8 @@ def checkevt(_, __, handle=None): def handleevt(startkey, endkey): position( posmap[startkey], - posmap[endkey] + posmap[endkey], + isDualMonitor, ) if __name__ == '__main__': diff --git a/window.py b/window.py index a53faed..c959af6 100644 --- a/window.py +++ b/window.py @@ -1,6 +1,6 @@ from gi.repository import Gdk -def position(startpos, endpos): +def position(startpos, endpos, dualMonitor): window, screen = active_window() window.unmaximize() window.set_shadow_width(0, 0, 0, 0) @@ -19,7 +19,10 @@ def position(startpos, endpos): ) - multiscreen_offset = get_multi_screen_offset(screen, window) + if dualMonitor: + multiscreen_offset = 0 + else: + multiscreen_offset = get_multi_screen_offset(screen, window) window.move_resize( pos[1] * w + multiscreen_offset, From 9c1bd6c6577fae7d665e0da84b49aee03adde7e0 Mon Sep 17 00:00:00 2001 From: Lukas Rysavy Date: Wed, 24 Jun 2020 18:28:05 +0200 Subject: [PATCH 2/5] fixed multi screen offset handling for misaligned screens --- window.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/window.py b/window.py index c959af6..8eb7a8a 100644 --- a/window.py +++ b/window.py @@ -5,6 +5,7 @@ def position(startpos, endpos, dualMonitor): window.unmaximize() window.set_shadow_width(0, 0, 0, 0) workarea = screen.get_monitor_workarea(screen.get_monitor_at_window(window)) + display = Gdk.Display.get_default() offx, offy = offsets(window) w, h = (workarea.width / 4, workarea.height / 3) @@ -24,11 +25,19 @@ def position(startpos, endpos, dualMonitor): else: multiscreen_offset = get_multi_screen_offset(screen, window) + if dualMonitor: + screen_y_offset = [ + monitor_y_offset(display, min(startpos, endpos, key=lambda x: x[0]*10 + x[1])[1]), + monitor_y_offset(display, max(startpos, endpos, key=lambda x: x[0]*10 + x[1])[1]), + ] + else: + screen_y_offset = [0, 0] + window.move_resize( pos[1] * w + multiscreen_offset, - pos[0] * h, + pos[0] * h + screen_y_offset[0], w * dims[1] - (offx * 2), - h * dims[0]- (offx + offy) + h * dims[0]- (offx + offy) + screen_y_offset[1] - screen_y_offset[0] ) def active_window(): @@ -61,3 +70,11 @@ def no_window(screen, window): ) or window.get_type_hint().value_name == 'GDK_WINDOW_TYPE_HINT_DESKTOP' ) + + +def monitor_y_offset(display, x): + left_monitor = display.get_monitor_at_point(0, 0) + right_monitor = display.get_monitor(1) \ + if left_monitor == display.get_monitor(0) \ + else display.get_monitor(0) + return [left_monitor, right_monitor][x // 4].get_workarea().y From 1da7b25cd076628b91745d1b718a863c18161528 Mon Sep 17 00:00:00 2001 From: Lukas Rysavy Date: Wed, 24 Jun 2020 18:28:32 +0200 Subject: [PATCH 3/5] fixed crash on shortcut without window focus --- window.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/window.py b/window.py index 8eb7a8a..ecd5ae9 100644 --- a/window.py +++ b/window.py @@ -2,6 +2,8 @@ def position(startpos, endpos, dualMonitor): window, screen = active_window() + if window is None: + return window.unmaximize() window.set_shadow_width(0, 0, 0, 0) workarea = screen.get_monitor_workarea(screen.get_monitor_at_window(window)) @@ -45,7 +47,7 @@ def active_window(): window = screen.get_active_window() if no_window(screen, window): - return None + return None, None return (window, screen) From bbb952e9d4b23626597daa9102f759f97d2912c7 Mon Sep 17 00:00:00 2001 From: Lukas Rysavy Date: Mon, 29 Jun 2020 11:10:57 +0200 Subject: [PATCH 4/5] reworked geometry calculation to be able to handle differently sized monitors --- window.py | 77 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/window.py b/window.py index ecd5ae9..aeaf4d1 100644 --- a/window.py +++ b/window.py @@ -6,42 +6,54 @@ def position(startpos, endpos, dualMonitor): return window.unmaximize() window.set_shadow_width(0, 0, 0, 0) - workarea = screen.get_monitor_workarea(screen.get_monitor_at_window(window)) + display = Gdk.Display.get_default() + if dualMonitor: + monitor = get_target_monitor(display, startpos[1]) + workarea = monitor.get_workarea() + end_monitor = get_target_monitor(display, endpos[1]) + end_workarea = end_monitor.get_workarea() + else: + monitor = screen.get_monitor_at_window(window) + workarea = screen.get_monitor_workarea(monitor) + # same screen -> same workarea on both corners + end_workarea = workarea - offx, offy = offsets(window) w, h = (workarea.width / 4, workarea.height / 3) - - pos = ( - min(startpos[0], endpos[0]), - min(startpos[1], endpos[1]) + end_w, end_h = (end_workarea.width / 4, end_workarea.height / 3) + + # each contain top left and bottom right position of the respective cell + first_corner = ( + (startpos[1] % 4) * w + workarea.x, + startpos[0] * h + workarea.y, + (startpos[1] % 4 + 1) * w + workarea.x, + (startpos[0] + 1) * h + workarea.y, ) - dims = ( - max(abs(endpos[0] - startpos[0]) + 1, 1), - max(abs(endpos[1] - startpos[1]) + 1, 1) + second_corner = ( + (endpos[1] % 4) * end_w + end_workarea.x, + endpos[0] * end_h + end_workarea.y, + (endpos[1] % 4 + 1) * end_w + end_workarea.x, + (endpos[0] + 1) * end_h + end_workarea.y, ) + top_left, bottom_right = ( + # use top left corner of cells (0 & 1) + (min(first_corner[0], second_corner[0]), min(first_corner[1], second_corner[1])), + # use bottom right corner of cells (2 & 3) + (max(first_corner[2], second_corner[2]), max(first_corner[3], second_corner[3])), + ) - if dualMonitor: - multiscreen_offset = 0 - else: - multiscreen_offset = get_multi_screen_offset(screen, window) - - if dualMonitor: - screen_y_offset = [ - monitor_y_offset(display, min(startpos, endpos, key=lambda x: x[0]*10 + x[1])[1]), - monitor_y_offset(display, max(startpos, endpos, key=lambda x: x[0]*10 + x[1])[1]), - ] - else: - screen_y_offset = [0, 0] + dims = ( + bottom_right[0] - top_left[0], + bottom_right[1] - top_left[1], + ) window.move_resize( - pos[1] * w + multiscreen_offset, - pos[0] * h + screen_y_offset[0], - w * dims[1] - (offx * 2), - h * dims[0]- (offx + offy) + screen_y_offset[1] - screen_y_offset[0] + *top_left, + *dims, ) + def active_window(): screen = Gdk.Screen.get_default() window = screen.get_active_window() @@ -51,16 +63,6 @@ def active_window(): return (window, screen) -def get_multi_screen_offset(screen,window): - monitor = screen.get_monitor_at_window(window) - monitor_geometry = screen.get_monitor_geometry(monitor) - return monitor_geometry.x - -def offsets(window): - origin = window.get_origin() - root = window.get_root_origin() - return (origin.x - root.x, origin.y - root.y) - def no_window(screen, window): return ( @@ -74,9 +76,10 @@ def no_window(screen, window): ) -def monitor_y_offset(display, x): +def get_target_monitor(display, x): + # NOTE: only works for up to 2 monitors!! left_monitor = display.get_monitor_at_point(0, 0) right_monitor = display.get_monitor(1) \ if left_monitor == display.get_monitor(0) \ else display.get_monitor(0) - return [left_monitor, right_monitor][x // 4].get_workarea().y + return [left_monitor, right_monitor][x // 4] From 190b92bdb954946c3e55f0d9dde0a64defd54d40 Mon Sep 17 00:00:00 2001 From: Lukas Rysavy Date: Wed, 1 Jul 2020 11:15:10 +0200 Subject: [PATCH 5/5] allow termination via kill --- snaptile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/snaptile.py b/snaptile.py index 1545f1a..4278195 100755 --- a/snaptile.py +++ b/snaptile.py @@ -144,6 +144,7 @@ def run(): GObject.io_add_watch(root.display, GObject.IO_IN, checkevt) print('Snaptile running. Press CTRL+C to quit.') signal.signal(signal.SIGINT, signal.SIG_DFL) + signal.signal(signal.SIGTERM, signal.SIG_DFL) Gtk.main() def checkevt(_, __, handle=None):