Add save and restore position and sizes of windows for floating/tiled

Author Mitja Felicijan <mitja.felicijan@gmail.com> 2026-04-15 16:46:09 +0200
Committer Mitja Felicijan <mitja.felicijan@gmail.com> 2026-04-15 16:46:09 +0200
Commit b94d7cea0d3a05b3e05664fe697431b618a43328 (patch)
-rw-r--r-- glitch.h 3
-rw-r--r-- manager.c 64
2 files changed, 65 insertions, 2 deletions
diff --git a/glitch.h b/glitch.h
...
50
	Window window;
50
	Window window;
51
	struct Client *next;
51
	struct Client *next;
52
	struct Client *prev;
52
	struct Client *prev;
  
53
	int saved_x, saved_y;
  
54
	unsigned int saved_w, saved_h;
  
55
	int has_saved_state;
53
} Client;
56
} Client;
54
  
57
  
55
typedef struct {
58
typedef struct {
...
diff --git a/manager.c b/manager.c
...
130
	new_c->window = w;
130
	new_c->window = w;
131
	new_c->next = wm.clients;
131
	new_c->next = wm.clients;
132
	new_c->prev = NULL;
132
	new_c->prev = NULL;
  
133
	new_c->saved_x = 0;
  
134
	new_c->saved_y = 0;
  
135
	new_c->saved_w = 0;
  
136
	new_c->saved_h = 0;
  
137
	new_c->has_saved_state = 0;
133
  
138
  
134
	if (wm.clients) {
139
	if (wm.clients) {
135
		wm.clients->prev = new_c;
140
		wm.clients->prev = new_c;
...
1678
  
1683
  
1679
void toggle_layout(const Arg *arg) {
1684
void toggle_layout(const Arg *arg) {
1680
	(void)arg;
1685
	(void)arg;
1681
	wm.layout_modes[wm.current_desktop] = (wm.layout_modes[wm.current_desktop] == LAYOUT_TILING) ? LAYOUT_FLOATING : LAYOUT_TILING;
1686
	LayoutMode current_mode = wm.layout_modes[wm.current_desktop];
1682
	if (wm.layout_modes[wm.current_desktop] == LAYOUT_TILING) {
1687
  
  
1688
	if (current_mode == LAYOUT_FLOATING) {
  
1689
		// Moving to TILING, save floating positions
  
1690
		for (Client *c = wm.clients; c; c = c->next) {
  
1691
			if (!window_exists(c->window)) continue;
  
1692
  
  
1693
			unsigned long desktop;
  
1694
			Atom actual_type;
  
1695
			int actual_format;
  
1696
			unsigned long nitems, bytes_after;
  
1697
			unsigned char *prop = NULL;
  
1698
  
  
1699
			int status = XGetWindowProperty(wm.dpy, c->window, _NET_WM_DESKTOP, 0, 1, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
  
1700
			if (status == Success && prop && nitems > 0) {
  
1701
				desktop = *(unsigned long *)prop;
  
1702
				XFree(prop);
  
1703
				if (desktop == wm.current_desktop && !is_sticky(c->window) && !is_always_on_top(c->window) && !has_wm_state(c->window, _NET_WM_STATE_FULLSCREEN)) {
  
1704
					XWindowAttributes attr;
  
1705
					if (XGetWindowAttributes(wm.dpy, c->window, &attr)) {
  
1706
						c->saved_x = attr.x;
  
1707
						c->saved_y = attr.y;
  
1708
						c->saved_w = attr.width;
  
1709
						c->saved_h = attr.height;
  
1710
						c->has_saved_state = 1;
  
1711
					}
  
1712
				}
  
1713
			} else if (prop) {
  
1714
				XFree(prop);
  
1715
			}
  
1716
		}
  
1717
		wm.layout_modes[wm.current_desktop] = LAYOUT_TILING;
1683
		apply_tiling_layout();
1718
		apply_tiling_layout();
  
1719
	} else {
  
1720
		// Moving to FLOATING, restore positions
  
1721
		wm.layout_modes[wm.current_desktop] = LAYOUT_FLOATING;
  
1722
		for (Client *c = wm.clients; c; c = c->next) {
  
1723
			if (!window_exists(c->window)) continue;
  
1724
			if (c->has_saved_state) {
  
1725
				unsigned long desktop;
  
1726
				Atom actual_type;
  
1727
				int actual_format;
  
1728
				unsigned long nitems, bytes_after;
  
1729
				unsigned char *prop = NULL;
  
1730
  
  
1731
				int status = XGetWindowProperty(wm.dpy, c->window, _NET_WM_DESKTOP, 0, 1, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop);
  
1732
				if (status == Success && prop && nitems > 0) {
  
1733
					desktop = *(unsigned long *)prop;
  
1734
					XFree(prop);
  
1735
					if (desktop == wm.current_desktop) {
  
1736
						XMoveResizeWindow(wm.dpy, c->window, c->saved_x, c->saved_y, c->saved_w, c->saved_h);
  
1737
						c->has_saved_state = 0;
  
1738
					}
  
1739
				} else if (prop) {
  
1740
					XFree(prop);
  
1741
				}
  
1742
			}
  
1743
		}
1684
	}
1744
	}
1685
	redraw_widgets();
1745
	redraw_widgets();
1686
	log_message(stdout, LOG_DEBUG, "Toggled layout for desktop %d to %s", wm.current_desktop, wm.layout_modes[wm.current_desktop] == LAYOUT_TILING ? "TILING" : "FLOATING");
1746
	log_message(stdout, LOG_DEBUG, "Toggled layout for desktop %d to %s", wm.current_desktop, wm.layout_modes[wm.current_desktop] == LAYOUT_TILING ? "TILING" : "FLOATING");
...