From 7c9bd4ba525fc8bf25a7c8caf06cc6d6e7eaddf5 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 15 Jun 2024 18:58:02 -0700 Subject: screen: support xwin next/prev screen_rels This is an attempt to minimally support autoconfing windows to different screens on multihead setups. --- src/key.c | 34 ++++++++++++++++++++++------------ src/screen.c | 18 ++++++++++++++++++ src/screen.h | 10 ++++++---- src/window.c | 2 ++ src/window.h | 1 + 5 files changed, 49 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/key.c b/src/key.c index 51ea947..4b1a34a 100644 --- a/src/key.c +++ b/src/key.c @@ -196,21 +196,31 @@ void vwm_key_pressed(vwm_t *vwm, Window win, XKeyPressedEvent *keypress) case XK_backslash: do_grab = 1; + /* Backslash is all about screen boundaries within the current desktop. + * Screens are funky since they're basically just subrects within the X "screen" + * that spans all the displays in multihead setups (xinerama). + */ + if (vwin) { - if (keypress->state & ShiftMask) { - /* TODO: migrate window to another screen within this desktop, - * like VWM_FENCE_MASKED_VIOLATE would focus the next window on - * the next screen, but instead of focusing the next window on - * the next display, move the focused one to that next desktop. - * - * since screens are handled within vwm_win_focus_next() via - * the fence abstraction, but fences aren't exposed outside of - * their, it's non-trivial to implement here. I may want to - * break that out into a more public interface to make things - * more composable at the screen level. + if (send_it) { + /* "send" the focused window to the next screen */ + VWM_TRACE("send window to screen not implemented yet"); + /* TODO: this is identical to "migrate" below, but needs to focus + * the next window within the origin screen if there is one. + * It's unclear to me what should happen when you "send" the only + * window in the current scren to another screen - should it just + * turn into a migrate effectively? I don't think there's a situation + * currently where no window is focused in the curent desktop, it's + * one of those things that's prevented from happening, until there's + * no windows left in the desktop. The screens are just subregions + * of the current desktop which map to displays. */ - VWM_TRACE("migrate window to screen not implemented yet"); + } else if (keypress->state & ShiftMask) { + /* "migrate" the focused window to the next screen */ + vwm_win_autoconf(vwm, vwin, VWM_SCREEN_REL_XWIN_NEXT, vwin->autoconfigured, vwin->autoconfigured_param); + /* TODO reverse via VWM_SCREEN_REL_XWIN_PREV */ } else { + /* focus the MRU window on the next screen */ vwm_win_focus_next(vwm, vwin, direction, VWM_FENCE_MASKED_VIOLATE); } } diff --git a/src/screen.c b/src/screen.c index 0563202..ed8af7b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -97,6 +97,8 @@ const vwm_screen_t * vwm_screen_find(vwm_t *vwm, vwm_screen_rel_t rel, ...) break; } + case VWM_SCREEN_REL_XWIN_NEXT: + case VWM_SCREEN_REL_XWIN_PREV: case VWM_SCREEN_REL_XWIN: { va_list ap; vwm_xwindow_t *xwin; @@ -113,6 +115,22 @@ const vwm_screen_t * vwm_screen_find(vwm_t *vwm, vwm_screen_rel_t rel, ...) best_pct = this_pct; } } + + if (rel != VWM_SCREEN_REL_XWIN) { + unsigned idx = best - vwm->xinerama_screens; + + /* find the neighboring screen according to rel, note this isn't + * a spatial neighbor trying to consider RandR screen layout - it's + * simply next/prev in the list of screens in the order they appear + * there. + */ + if (rel == VWM_SCREEN_REL_XWIN_NEXT) + idx += 1; + else if (rel == VWM_SCREEN_REL_XWIN_PREV) + idx += vwm->xinerama_screens_cnt - 1; + + best = &vwm->xinerama_screens[idx % vwm->xinerama_screens_cnt]; + } break; } diff --git a/src/screen.h b/src/screen.h index ad8ddce..9c7c882 100644 --- a/src/screen.h +++ b/src/screen.h @@ -9,10 +9,12 @@ typedef struct _vwm_xwindow_t vwm_xwindow_t; typedef XineramaScreenInfo vwm_screen_t; /* conveniently reuse the xinerama type for describing screens */ typedef enum _vwm_screen_rel_t { - VWM_SCREEN_REL_RECT, /* return the screen the supplied rectangle x,y,w,h most resides in */ - VWM_SCREEN_REL_XWIN, /* return the screen the supplied window most resides in */ - VWM_SCREEN_REL_POINTER, /* return the screen the pointer resides in */ - VWM_SCREEN_REL_TOTAL, /* return the bounding rectangle of all screens as one */ + VWM_SCREEN_REL_RECT, /* return the screen the supplied rectangle x,y,w,h most resides in */ + VWM_SCREEN_REL_XWIN, /* return the screen the supplied window most resides in */ + VWM_SCREEN_REL_XWIN_NEXT, /* return the next screen from the one the supplied window most resides in */ + VWM_SCREEN_REL_XWIN_PREV, /* return the prev screen from the one the supplied window most resides in */ + VWM_SCREEN_REL_POINTER, /* return the screen the pointer resides in */ + VWM_SCREEN_REL_TOTAL, /* return the bounding rectangle of all screens as one */ } vwm_screen_rel_t; const vwm_screen_t * vwm_screen_find(vwm_t *vwm, vwm_screen_rel_t rel, ...); diff --git a/src/window.c b/src/window.c index b850ec9..9cf9b0a 100644 --- a/src/window.c +++ b/src/window.c @@ -162,6 +162,7 @@ void vwm_win_autoconf(vwm_t *vwm, vwm_window_t *vwin, vwm_screen_rel_t rel, vwm_ changes.y = scr->y_org + scr->height / 2; break; } + vwin->autoconfigured_param = corner; break; } @@ -196,6 +197,7 @@ void vwm_win_autoconf(vwm_t *vwm, vwm_window_t *vwin, vwm_screen_rel_t rel, vwm_ changes.y = scr->y_org; break; } + vwin->autoconfigured_param = side; break; } diff --git a/src/window.h b/src/window.h index 74f30ab..cafabb8 100644 --- a/src/window.h +++ b/src/window.h @@ -33,6 +33,7 @@ typedef struct _vwm_window_t { long hints_supplied; /* bitfield reflecting the hints the client supplied */ unsigned int autoconfigured:3; /* autoconfigured window states (none/quarter/half/full/all) */ + unsigned int autoconfigured_param:2; unsigned int mapping:1; /* is the window being mapped? (by vwm) */ unsigned int unmapping:1; /* is the window being unmapped? (by vwm) */ } vwm_window_t; -- cgit v1.2.3