A tiling window manager
1/*
2 * functions that manipulate the frame structure.
3 * Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA.
18 */
19
20#include "sdorfehs.h"
21
22#include <string.h>
23#include <err.h>
24
25int
26frame_left(rp_frame *frame)
27{
28 return frame->x;
29}
30
31int
32frame_left_screen_edge(rp_frame *frame)
33{
34 return (frame_left(frame) <= screen_left(frame->vscreen->screen) +
35 defaults.padding_left);
36}
37
38int
39frame_top(rp_frame *frame)
40{
41 return frame->y;
42}
43
44int
45frame_top_screen_edge(rp_frame *frame)
46{
47 return (frame_top(frame) <= (screen_top(frame->vscreen->screen) +
48 defaults.padding_top));
49}
50
51int
52frame_right(rp_frame *frame)
53{
54 return frame->x + frame->width;
55}
56
57int
58frame_right_screen_edge(rp_frame *frame)
59{
60 return (frame_right(frame) >= screen_right(frame->vscreen->screen) -
61 defaults.padding_right);
62}
63
64int
65frame_bottom(rp_frame *frame)
66{
67 return frame->y + frame->height;
68}
69
70int
71frame_bottom_screen_edge(rp_frame *frame)
72{
73 return (frame_bottom(frame) >= screen_bottom(frame->vscreen->screen) -
74 defaults.padding_bottom);
75}
76
77int
78frame_width(rp_frame *frame)
79{
80 return frame->width;
81}
82
83int
84frame_height(rp_frame *frame)
85{
86 return frame->height;
87}
88
89void
90frame_resize_left(rp_frame *frame, int amount)
91{
92 frame->x -= amount;
93 frame->width += amount;
94}
95
96void
97frame_resize_right(rp_frame *frame, int amount)
98{
99 frame->width += amount;
100}
101
102void
103frame_resize_up(rp_frame *frame, int amount)
104{
105 frame->y -= amount;
106 frame->height += amount;
107}
108
109void
110frame_resize_down(rp_frame *frame, int amount)
111{
112 frame->height += amount;
113}
114
115void
116mark_edge_frames(void)
117{
118 rp_screen *s;
119 rp_vscreen *v;
120 rp_frame *f;
121
122 list_for_each_entry(s, &rp_screens, node) {
123 list_for_each_entry(v, &s->vscreens, node) {
124 list_for_each_entry(f, &v->frames, node) {
125 f->edges = 0;
126
127 if (frame_top_screen_edge(f))
128 f->edges |= EDGE_TOP;
129 if (frame_left_screen_edge(f))
130 f->edges |= EDGE_LEFT;
131 if (frame_right_screen_edge(f))
132 f->edges |= EDGE_RIGHT;
133 if (frame_bottom_screen_edge(f))
134 f->edges |= EDGE_BOTTOM;
135 }
136 }
137 }
138}
139
140static void
141init_frame(rp_frame *f)
142{
143 f->number = 0;
144 f->x = 0;
145 f->y = 0;
146 f->width = 0;
147 f->height = 0;
148 f->win_number = 0;
149 f->last_access = 0;
150 f->dedicated = 0;
151 f->restore_win_number = EMPTY;
152}
153
154rp_frame *
155frame_new(rp_vscreen *v)
156{
157 rp_frame *f;
158
159 f = xmalloc(sizeof(rp_frame));
160 init_frame(f);
161 f->vscreen = v;
162 f->number = numset_request(v->frames_numset);
163
164 return f;
165}
166
167void
168frame_free(rp_vscreen *v, rp_frame *f)
169{
170 numset_release(v->frames_numset, f->number);
171 free(f);
172}
173
174rp_frame *
175frame_copy(rp_frame *frame)
176{
177 rp_frame *copy;
178
179 copy = xmalloc(sizeof(rp_frame));
180
181 copy->vscreen = frame->vscreen;
182 copy->number = frame->number;
183 copy->x = frame->x;
184 copy->y = frame->y;
185 copy->width = frame->width;
186 copy->height = frame->height;
187 copy->win_number = frame->win_number;
188 copy->last_access = frame->last_access;
189
190 return copy;
191}
192
193char *
194frame_dump(rp_frame *frame, rp_vscreen *vscreen)
195{
196 rp_window *win;
197 char *tmp;
198 struct sbuf *s;
199
200 /* rather than use win_number, use the X11 window ID. */
201 win = find_window_number(frame->win_number);
202
203 s = sbuf_new(0);
204 sbuf_printf(s, "(frame :number %d :x %d :y %d :width %d :height %d "
205 ":screenw %d :screenh %d :window %ld :last-access %d :dedicated %d)",
206 frame->number,
207 frame->x,
208 frame->y,
209 frame->width,
210 frame->height,
211 vscreen->screen->width,
212 vscreen->screen->height,
213 win ? win->w : 0,
214 frame->last_access,
215 frame->dedicated);
216
217 /* Extract the string and return it, and don't forget to free s. */
218 tmp = sbuf_get(s);
219 free(s);
220 return tmp;
221}
222
223/* Used only by frame_read */
224#define read_slot(x) do { tmp = strtok_ws (NULL); x = strtol(tmp,NULL,10); } while(0)
225
226rp_frame *
227frame_read(char *str, rp_vscreen *vscreen)
228{
229 Window w = 0L;
230 rp_window *win;
231 rp_frame *f;
232 char *tmp, *d;
233 int s_width = -1;
234 int s_height = -1;
235
236 /* Create a blank frame. */
237 f = xmalloc(sizeof(rp_frame));
238 init_frame(f);
239 f->vscreen = vscreen;
240
241 PRINT_DEBUG(("parsing '%s'\n", str));
242
243 d = xstrdup(str);
244 tmp = strtok_ws(d);
245
246 /* Verify it starts with '(frame ' */
247 if (tmp == NULL || strcmp(tmp, "(frame")) {
248 PRINT_DEBUG(("Doesn't start with '(frame '\n"));
249 free(d);
250 free(f);
251 return NULL;
252 }
253 /* NOTE: there is no check to make sure each field was filled in. */
254 tmp = strtok_ws(NULL);
255 while (tmp) {
256 if (!strcmp(tmp, ":number"))
257 read_slot(f->number);
258 else if (!strcmp(tmp, ":x"))
259 read_slot(f->x);
260 else if (!strcmp(tmp, ":y"))
261 read_slot(f->y);
262 else if (!strcmp(tmp, ":width"))
263 read_slot(f->width);
264 else if (!strcmp(tmp, ":height"))
265 read_slot(f->height);
266 else if (!strcmp(tmp, ":screenw"))
267 read_slot(s_width);
268 else if (!strcmp(tmp, ":screenh"))
269 read_slot(s_height);
270 else if (!strcmp(tmp, ":window"))
271 read_slot(w);
272 else if (!strcmp(tmp, ":last-access"))
273 read_slot(f->last_access);
274 else if (!strcmp(tmp, ":dedicated")) {
275 /* f->dedicated is unsigned, so read into local variable. */
276 long dedicated;
277
278 read_slot(dedicated);
279 if (dedicated <= 0)
280 f->dedicated = 0;
281 else
282 f->dedicated = 1;
283 } else if (!strcmp(tmp, ")"))
284 break;
285 else
286 warn("unknown slot reading frame: %s", tmp);
287
288 /* Read the next token. */
289 tmp = strtok_ws(NULL);
290 }
291 if (tmp)
292 warnx("frame has trailing garbage: %s", tmp);
293 free(d);
294
295 /* adjust x, y, width and height to a possible screen size change */
296 if (s_width > 0) {
297 f->x = (f->x * vscreen->screen->width) / s_width;
298 f->width = (f->width * vscreen->screen->width) / s_width;
299 }
300 if (s_height > 0) {
301 f->y = (f->y * vscreen->screen->height) / s_height;
302 f->height = (f->height * vscreen->screen->height) / s_height;
303 }
304 /*
305 * Perform some integrity checks on what we got and fix any problems.
306 */
307 if (f->number <= 0)
308 f->number = 0;
309 if (f->x <= 0)
310 f->x = 0;
311 if (f->y <= 0)
312 f->y = 0;
313 if (f->width <= (defaults.window_border_width * 2) + (defaults.gap * 2))
314 f->width = (defaults.window_border_width * 2) +
315 (defaults.gap * 2) + 1;
316 if (f->height <= (defaults.window_border_width * 2) +
317 (defaults.gap * 2))
318 f->height = (defaults.window_border_width * 2) +
319 (defaults.gap * 2) + 1;
320 if (f->last_access < 0)
321 f->last_access = 0;
322
323 /* Find the window with the X11 window ID. */
324 win = find_window_in_list(w, &rp_mapped_window);
325 if (win)
326 f->win_number = win->number;
327 else
328 f->win_number = EMPTY;
329
330 return f;
331}
332
333#undef read_slot