summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c185
1 files changed, 94 insertions, 91 deletions
diff --git a/src/window.c b/src/window.c
index d1441f3..5410ba6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -80,20 +80,10 @@ vwm_window_t * vwm_win_lookup(vwm_t *vwm, Window win)
}
-/* return the currently focused window (considers current context...), may return NULL */
+/* return the currently focused window, may return NULL */
vwm_window_t * vwm_win_get_focused(vwm_t *vwm)
{
- switch (vwm->focused_context) {
- case VWM_CONTEXT_SHELF:
- return vwm->focused_shelf;
-
- case VWM_CONTEXT_DESKTOP:
- return vwm->focused_desktop->focused_window;
-
- default:
- VWM_BUG("Unsupported context");
- assert(0);
- }
+ return vwm->focused_desktop->focused_window;
}
@@ -103,22 +93,15 @@ vwm_window_t * vwm_win_get_focused(vwm_t *vwm)
void vwm_win_set_focused(vwm_t *vwm, vwm_window_t *vwin)
{
/* update the border color accordingly */
- if (vwin->shelved) {
- /* set the border of the newly focused window to the shelved color */
- XSetWindowBorder(VWM_XDISPLAY(vwm), vwin->xwindow->id, vwin == vwm->console ? vwm->colors.shelved_console_border_color.pixel : vwm->colors.shelved_window_border_color.pixel);
- /* fullscreen windows in the shelf when focused, since we don't intend to overlap there */
- vwm_win_autoconf(vwm, vwin, VWM_SCREEN_REL_POINTER, VWM_WIN_AUTOCONF_FULL); /* XXX TODO: for now the shelf follows the pointer, it's simple. */
- } else {
- if (vwin->desktop->focused_window)
- /* set the border of the previously focused window on the same desktop to the unfocused color */
- XSetWindowBorder(VWM_XDISPLAY(vwm), vwin->desktop->focused_window->xwindow->id, vwm->colors.unfocused_window_border_color.pixel);
+ if (vwin->desktop->focused_window)
+ /* set the border of the previously focused window on the same desktop to the unfocused color */
+ XSetWindowBorder(VWM_XDISPLAY(vwm), vwin->desktop->focused_window->xwindow->id, vwm->colors.unfocused_window_border_color.pixel);
- /* set the border of the newly focused window to the focused color */
- XSetWindowBorder(VWM_XDISPLAY(vwm), vwin->xwindow->id, vwm->colors.focused_window_border_color.pixel);
+ /* set the border of the newly focused window to the focused color */
+ XSetWindowBorder(VWM_XDISPLAY(vwm), vwin->xwindow->id, vwm->context_colors[vwin->desktop->context->color].pixel);
- /* persist this on a per-desktop basis so it can be restored on desktop switches */
- vwin->desktop->focused_window = vwin;
- }
+ /* persist this on a per-desktop basis so it can be restored on desktop switches */
+ vwin->desktop->focused_window = vwin;
}
@@ -131,7 +114,7 @@ void vwm_win_autoconf_magic(vwm_t *vwm, vwm_window_t *vwin, const vwm_screen_t *
if (!scr)
scr = vwm_screen_find(vwm, VWM_SCREEN_REL_RECT, x, y, width, height);
- if (!vwin->shelved && scr &&
+ if (scr &&
width == scr->width &&
height == scr->height) {
VWM_TRACE_WIN(vwin->xwindow->id, "auto-allscreened window");
@@ -329,21 +312,9 @@ _retry:
VWM_TRACE("VWM_FENCE_MASKED_VIOLATE fence_mask now: 0x%lx\n", vwm->fence_mask);
}
- if (vwin->shelved) {
- if (next != vwm->focused_shelf) {
- if (vwm->focused_context == VWM_CONTEXT_SHELF) {
- vwm_win_unmap(vwm, vwm->focused_shelf);
- XFlush(VWM_XDISPLAY(vwm));
- vwm_win_map(vwm, next);
- }
- vwm->focused_shelf = next;
- vwm_win_focus(vwm, next);
- }
- } else {
- if (next != next->desktop->focused_window) {
- vwm_win_focus(vwm, next);
- XRaiseWindow(VWM_XDISPLAY(vwm), next->xwindow->id);
- }
+ if (next != next->desktop->focused_window) {
+ vwm_win_focus(vwm, next);
+ XRaiseWindow(VWM_XDISPLAY(vwm), next->xwindow->id);
}
VWM_TRACE("vwin=%p xwin=%p name=\"%s\"", next, next->xwindow, next->xwindow->name);
@@ -352,48 +323,62 @@ _retry:
}
-/* shelves a window, if the window is focused we focus the next one (if possible) */
+/* "shelves" a window, if the window is focused we focus the next one (if exists) */
+/* originally there was a special shelf context having different semantics of a fullscreen
+ * window at a time, this evolved into generic contexts containing virtual
+ * desktops, and now shelving is just the process of sending a window to the bottom/first
+ * context into a newly created desktop there, in an unattended fashion (like an unattended migrate,
+ * to an assumed bottom destination context created for this purpose at startup, and into its own
+ * desktop there).
+ */
void vwm_win_shelve(vwm_t *vwm, vwm_window_t *vwin)
{
- /* already shelved, NOOP */
- if (vwin->shelved)
+ vwm_context_t *shelf = list_entry(vwm->contexts.next, vwm_context_t, contexts);
+ vwm_desktop_t *desktop;
+
+ /* already in the first, AKA "shelf" context, NOOP */
+ if (&vwin->desktop->context->contexts == vwm->contexts.next)
return;
/* shelving focused window, focus the next window */
if (vwin == vwin->desktop->focused_window)
vwm_win_mru(vwm, vwm_win_focus_next(vwm, vwin, VWM_DIRECTION_FORWARD, VWM_FENCE_RESPECT));
+ /* vwin appears to be alone */
if (vwin == vwin->desktop->focused_window)
- /* TODO: we can probably put this into vwm_win_focus_next() and have it always handled there... */
vwin->desktop->focused_window = NULL;
- vwin->shelved = 1;
- vwm_win_mru(vwm, vwin);
+ /* TODO: ^^^ there should probably be a helper for withdrawing a window
+ * from a desktop which handles the above focus next -> lone window
+ * nonsense, and hands back an orphan window to do whatever with.
+ */
+
+ /* shelved windows always get an empty desktop in the shelf context,
+ * look for an empty one and only create a new one if there is none
+ * to use.
+ */
+ vwin->desktop = NULL;
+ list_for_each_entry(desktop, &vwm->desktops_mru, desktops_mru) {
+ if (desktop->context == shelf && !desktop->focused_window) {
+ vwin->desktop = desktop;
+ break;
+ }
+ }
- /* newly shelved windows always become the focused shelf */
- vwm->focused_shelf = vwin;
+ if (!vwin->desktop)
+ vwin->desktop = vwm_desktop_create(vwm, shelf);
+ /* always leave the newly shelved window's desktop focused */
+ vwin->desktop->context->focused_desktop = vwin->desktop;
+ vwm_win_set_focused(vwm, vwin);
+ vwm_win_mru(vwm, vwin);
vwm_win_unmap(vwm, vwin);
}
-/* helper for (idempotently) unfocusing a window, deals with context switching etc... */
+/* helper for (idempotently) unfocusing a window */
void vwm_win_unfocus(vwm_t *vwm, vwm_window_t *vwin)
{
- /* if we're the focused shelved window, cycle the focus to the next shelved window if possible, if there's no more shelf, switch to the desktop */
- /* TODO: there's probably some icky behaviors for focused windows unmapping/destroying in unfocused contexts, we probably jump contexts suddenly. */
- if (vwin == vwm->focused_shelf) {
- VWM_TRACE("unfocusing focused shelf");
- vwm_win_focus_next(vwm, vwin, VWM_DIRECTION_FORWARD, VWM_FENCE_IGNORE);
-
- if (vwin == vwm->focused_shelf) {
- VWM_TRACE("shelf empty, leaving");
- /* no other shelved windows, exit the shelf context */
- vwm_context_focus(vwm, VWM_CONTEXT_DESKTOP);
- vwm->focused_shelf = NULL;
- }
- }
-
/* if we're the focused window cycle the focus to the next window on the desktop if possible */
if (vwin->desktop->focused_window == vwin) {
VWM_TRACE("unfocusing focused window");
@@ -401,7 +386,7 @@ void vwm_win_unfocus(vwm_t *vwm, vwm_window_t *vwin)
}
if (vwin->desktop->focused_window == vwin) {
- VWM_TRACE("desktop empty");
+ VWM_TRACE("unfocused last window on desktop");
vwin->desktop->focused_window = NULL;
}
}
@@ -468,26 +453,23 @@ static void vwm_win_assimilate(vwm_t *vwm, vwm_window_t *vwin)
/* TODO: this is a good place to hook in a window placement algo */
/* on client-requested mapping we place the window */
- if (!vwin->shelved) {
- /* we place the window on the screen containing the the pointer only if that screen is empty,
- * otherwise we place windows on the screen containing the currently focused window */
- scr = vwm_screen_find(vwm, VWM_SCREEN_REL_POINTER);
- if (vwm_screen_is_empty(vwm, scr, vwin->xwindow)) {
- /* focus the new window if it isn't already focused when it's going to an empty screen */
- VWM_TRACE("window \"%s\" is alone on screen \"%i\", focusing", vwin->xwindow->name, scr->screen_number);
- vwm_win_focus(vwm, vwin);
- } else {
- scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, vwm->focused_desktop->focused_window->xwindow);
- }
-
- changes.x = scr->x_org;
- changes.y = scr->y_org;
- } else if (vwm->focused_context == VWM_CONTEXT_SHELF) {
- scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, vwm->focused_shelf->xwindow);
- changes.x = scr->x_org;
- changes.y = scr->y_org;
+ /* we place the window on the screen containing the the pointer only if that screen is empty,
+ * otherwise we place windows on the screen containing the currently focused window */
+ scr = vwm_screen_find(vwm, VWM_SCREEN_REL_POINTER);
+ if (vwm_screen_is_empty(vwm, scr, vwin->xwindow)) {
+ /* focus the new window if it isn't already focused when it's going to an empty screen */
+ VWM_TRACE("window \"%s\" is alone on screen \"%i\", focusing", vwin->xwindow->name, scr->screen_number);
+ vwm_win_focus(vwm, vwin);
+ } else {
+ /* FIXME TODO: there's some situation where we get here but focused_desktop->focused_window == NULL,
+ * which shouldn't be possible; for there to be a non-empty screen, the focused_desktop must have a focused_window.
+ */
+ scr = vwm_screen_find(vwm, VWM_SCREEN_REL_XWIN, vwm->focused_desktop->focused_window->xwindow);
}
+ changes.x = scr->x_org;
+ changes.y = scr->y_org;
+
/* XXX TODO: does this belong here? */
XGetWMNormalHints(VWM_XDISPLAY(vwm), xwin->id, vwin->hints, &vwin->hints_supplied);
XGetWindowAttributes(VWM_XDISPLAY(vwm), xwin->id, &attrs);
@@ -541,7 +523,6 @@ vwm_window_t * vwm_win_manage_xwin(vwm_t *vwm, vwm_xwindow_t *xwin)
vwin->desktop = vwm->focused_desktop;
vwin->autoconfigured = VWM_WIN_AUTOCONF_NONE;
- vwin->shelved = (vwm->focused_context == VWM_CONTEXT_SHELF); /* if we're in the shelf when the window is created, the window is shelved */
vwin->client = xwin->attrs; /* remember whatever the current attributes are */
VWM_TRACE("hints: flags=%lx x=%i y=%i w=%i h=%i minw=%i minh=%i maxw=%i maxh=%i winc=%i hinc=%i basew=%i baseh=%i grav=%x",
@@ -572,9 +553,9 @@ vwm_window_t * vwm_win_manage_xwin(vwm_t *vwm, vwm_xwindow_t *xwin)
/* always raise newly managed windows so we know about them. */
XRaiseWindow(VWM_XDISPLAY(vwm), xwin->id);
- /* if the desktop has no focused window yet, automatically focus the newly managed one, provided we're on the desktop context */
- if (!vwm->focused_desktop->focused_window && vwm->focused_context == VWM_CONTEXT_DESKTOP) {
- VWM_TRACE("Mapped new window \"%s\" is alone on desktop, focusing", xwin->name);
+ /* if the desktop has no focused window yet, automatically focus the newly managed one */
+ if (!vwm->focused_desktop->focused_window) {
+ VWM_TRACE("Mapped new window \"%s\" is alone on desktop \"%s\", focusing", xwin->name, vwm->focused_desktop->name);
vwm_win_focus(vwm, vwin);
}
@@ -595,12 +576,34 @@ _fail:
void vwm_win_migrate(vwm_t *vwm, vwm_window_t *vwin, vwm_desktop_t *desktop)
{
vwm_win_unfocus(vwm, vwin); /* go through the motions of unfocusing the window if it is focused */
- vwin->shelved = 0; /* ensure not shelved */
- vwin->desktop = desktop; /* assign the new desktop */
+ vwin->desktop = desktop; /* assign the new desktop */
vwm_desktop_focus(vwm, desktop); /* currently we always focus the new desktop in a migrate */
vwm_win_focus(vwm, vwin); /* focus the window so borders get updated */
vwm_win_mru(vwm, vwin); /* TODO: is this right? shouldn't the Mod1 release be what's responsible for this? I migrate so infrequently it probably doesn't matter */
- XRaiseWindow(VWM_XDISPLAY(vwm), vwin->xwindow->id); /* ensure the window is raised */
+ XRaiseWindow(VWM_XDISPLAY(vwm), vwin->xwindow->id); /* ensure the window is @ top of stack */
+}
+
+
+/* "send" a window to another desktop, no desktop/context switching occurs. */
+void vwm_win_send(vwm_t *vwm, vwm_window_t *vwin, vwm_desktop_t *desktop)
+{
+ if (desktop == vwin->desktop)
+ return;
+
+ vwm_win_unfocus(vwm, vwin);
+ vwm_win_unmap(vwm, vwin);
+ vwin->desktop = desktop;
+
+ /* XXX: only focus the destination desktop when not the focused context, as
+ * it creates an awkward disconnect for the focused context's focused desktop
+ * to become updated to something else while looking at it without actually
+ * realizing that focus change like a migrate does.
+ */
+ if (vwm->focused_desktop->context != desktop->context)
+ desktop->context->focused_desktop = desktop;
+
+ vwm_win_set_focused(vwm, vwin);
+ XRaiseWindow(VWM_XDISPLAY(vwm), vwin->xwindow->id); /* ensure the window is @ top of stack */
}
© All Rights Reserved