A tiling window manager
at master 333 lines 7.1 kB view raw
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