2 * NanoWM - Window Manager for Nano-X
4 * Copyright (C) 2000 Greg Haerr <greg@censoft.com>
5 * Copyright (C) 2000 Alex Holden <alex@linuxhacker.org>
9 #define MWINCLUDECOLORS
12 /* Uncomment this if you want debugging output from this file */
17 /* default window style for GR_WM_PROPS_APPWINDOW*/
18 #define DEFAULT_WINDOW_STYLE (GR_WM_PROPS_APPFRAME | GR_WM_PROPS_CAPTION |\
21 static GR_COORD lastx = FIRST_WINDOW_LOCATION;
22 static GR_COORD lasty = FIRST_WINDOW_LOCATION;
25 * A new client window has been mapped, so we need to reparent and decorate it.
26 * Returns -1 on failure or 0 on success.
28 int new_client_window(GR_WINDOW_ID wid)
33 GR_COORD x, y, width, height, xoffset, yoffset;
35 GR_WM_PROPERTIES props;
37 /* get client window information*/
38 GrGetWindowInfo(wid, &winfo);
41 /* if not redecorating or not child of root window, return*/
42 if (winfo.parent != GR_ROOT_WINDOW_ID ||
43 (style & GR_WM_PROPS_NODECORATE))
46 /* deal with replacing borders with window decorations*/
47 if (winfo.bordersize) {
49 * For complex reasons, it's easier to unmap,
50 * remove the borders, and then map again,
51 * rather than try to recalculate the window
52 * position in the server w/o borders. By
53 * the time we get this event, the window has
54 * already been painted with borders...
55 * This currently causes a screen flicker as
56 * the window is painted twice. The workaround
57 * is to create the window without borders in
62 /* remove client borders, if any*/
63 props.flags = style | GR_WM_FLAGS_BORDERSIZE;
65 GrSetWMProperties(wid, &props);
67 /* remap the window without borders, call this routine again*/
72 /* if default decoration style asked for, set real draw bits*/
73 if ((style & GR_WM_PROPS_APPMASK) == GR_WM_PROPS_APPWINDOW) {
76 style = (style & ~GR_WM_PROPS_APPMASK)|DEFAULT_WINDOW_STYLE;
77 pr.flags = GR_WM_FLAGS_PROPS;
79 GrSetWMProperties(wid, &pr);
82 /* determine container widths and client child window offsets*/
83 if (style & GR_WM_PROPS_APPFRAME) {
84 width = winfo.width + CXFRAME;
85 height = winfo.height + CYFRAME;
88 } else if (style & GR_WM_PROPS_BORDER) {
89 width = winfo.width + 2;
90 height = winfo.height + 2;
95 height = winfo.height;
99 if (style & GR_WM_PROPS_CAPTION) {
101 yoffset += CYCAPTION;
102 if (style & GR_WM_PROPS_APPFRAME) {
103 /* extra line under caption with appframe*/
109 /* determine x,y window location*/
110 if (style & GR_WM_PROPS_NOAUTOMOVE) {
114 /* We could proably use a more intelligent algorithm here */
115 x = lastx + WINDOW_STEP;
116 if((x + width) > si.cols)
117 x = FIRST_WINDOW_LOCATION;
119 y = lasty + WINDOW_STEP;
120 if((y + height) > si.rows)
121 y = FIRST_WINDOW_LOCATION;
125 /* create container window*/
126 pid = GrNewWindow(GR_ROOT_WINDOW_ID, x, y, width, height,
129 window.pid = GR_ROOT_WINDOW_ID;
130 window.type = WINDOW_TYPE_CONTAINER;
131 window.sizing = GR_FALSE;
134 window.clientid = wid;
137 /* don't erase background of container window*/
138 props.flags = GR_WM_FLAGS_PROPS;
139 props.props = style | GR_WM_PROPS_NOBACKGROUND;
140 GrSetWMProperties(pid, &props);
142 Dprintf("New client window %d container %d\n", wid, pid);
144 GrSelectEvents(pid, GR_EVENT_MASK_CHLD_UPDATE
145 | GR_EVENT_MASK_BUTTON_UP | GR_EVENT_MASK_BUTTON_DOWN
146 | GR_EVENT_MASK_MOUSE_POSITION | GR_EVENT_MASK_EXPOSURE);
148 /* reparent client to container window*/
149 /* must map before reparent (nano-x bug)*/
151 GrReparentWindow(wid, pid, xoffset, yoffset);
153 GrSetFocus(wid); /* force fixed focus*/
155 /* add client window*/
158 window.type = WINDOW_TYPE_CLIENT;
159 window.sizing = GR_FALSE;
166 /* add system utility button*/
167 nid = GrNewWindow(pid, 0, 0, TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT, 0,
171 window.type = WINDOW_TYPE_UTILITYBUTTON;
172 window.active = GR_FALSE;
176 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
177 | GR_EVENT_MASK_EXPOSURE
178 | GR_EVENT_MASK_MOUSE_EXIT);
180 GrBitmap(nid, buttonsgc, 0, 0, TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT,
181 utilitybutton_notpressed);
183 nid = GrNewWindow(pid, TITLE_BAR_HEIGHT + 1, 1, width - (4 *
184 TITLE_BAR_HEIGHT) - 3, TITLE_BAR_HEIGHT - 3, 1, LTGRAY,
188 window.type = WINDOW_TYPE_TOPBAR;
189 window.active = GR_FALSE;
194 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
195 | GR_EVENT_MASK_EXPOSURE
196 | GR_EVENT_MASK_MOUSE_POSITION);
199 nid = GrNewWindow(pid, width - (3 * TITLE_BAR_HEIGHT), 0,
200 TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT, 0, LTGRAY, BLACK);
203 window.type = WINDOW_TYPE_ICONISEBUTTON;
204 window.active = GR_FALSE;
208 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
209 | GR_EVENT_MASK_EXPOSURE
210 | GR_EVENT_MASK_MOUSE_EXIT);
212 GrBitmap(nid, buttonsgc, 0, 0, TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT,
213 iconisebutton_notpressed);
215 nid = GrNewWindow(pid, width - (2 * TITLE_BAR_HEIGHT), 0,
216 TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT, 0, LTGRAY, BLACK);
219 window.type = WINDOW_TYPE_MAXIMISEBUTTON;
220 window.active = GR_FALSE;
224 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
225 | GR_EVENT_MASK_EXPOSURE
226 | GR_EVENT_MASK_MOUSE_EXIT);
228 GrBitmap(nid, buttonsgc, 0, 0, TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT,
229 maximisebutton_notpressed);
231 nid = GrNewWindow(pid, width - TITLE_BAR_HEIGHT, 0,
232 TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT, 0, LTGRAY, BLACK);
235 window.type = WINDOW_TYPE_CLOSEBUTTON;
236 window.active = GR_FALSE;
240 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
241 | GR_EVENT_MASK_EXPOSURE
242 | GR_EVENT_MASK_MOUSE_EXIT);
244 GrBitmap(nid, buttonsgc, 0, 0, TITLE_BAR_HEIGHT, TITLE_BAR_HEIGHT,
245 closebutton_notpressed);
247 nid = GrNewWindow(pid, 1, TITLE_BAR_HEIGHT + 1, BORDER_WIDTHS - 2,
248 height - TITLE_BAR_HEIGHT - BORDER_WIDTHS - 1,
252 window.type = WINDOW_TYPE_LEFTBAR;
253 window.active = GR_FALSE;
258 GrSetCursor(nid, horizontal_resize_columns, horizontal_resize_rows,
259 horizontal_resize_hotx, horizontal_resize_hoty,
260 BLACK, WHITE, horizontal_resize_fg,
261 horizontal_resize_bg);
263 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
264 | GR_EVENT_MASK_MOUSE_POSITION);
268 nid = GrNewWindow(pid, 1, height - BORDER_WIDTHS + 1, BORDER_WIDTHS - 2,
269 BORDER_WIDTHS - 2, 1, LTGRAY, BLACK);
272 window.type = WINDOW_TYPE_LEFTRESIZE;
273 window.active = GR_FALSE;
279 GrSetCursor(nid, lefthand_resize_columns, lefthand_resize_rows,
280 lefthand_resize_hotx, lefthand_resize_hoty,
281 BLACK, WHITE, lefthand_resize_fg, lefthand_resize_bg);
283 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
284 | GR_EVENT_MASK_MOUSE_POSITION);
288 nid = GrNewWindow(pid, BORDER_WIDTHS, height - BORDER_WIDTHS + 1,
289 width - (2 * BORDER_WIDTHS), BORDER_WIDTHS - 2, 1,
293 window.type = WINDOW_TYPE_BOTTOMBAR;
294 window.active = GR_FALSE;
298 GrSetCursor(nid, vertical_resize_columns, vertical_resize_rows,
299 vertical_resize_hotx, vertical_resize_hoty,
300 BLACK, WHITE, vertical_resize_fg, vertical_resize_bg);
302 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
303 | GR_EVENT_MASK_MOUSE_POSITION);
307 nid = GrNewWindow(pid, width - BORDER_WIDTHS + 1,
308 height - BORDER_WIDTHS + 1, BORDER_WIDTHS - 2,
309 BORDER_WIDTHS - 2, 1, LTGRAY, BLACK);
312 window.type = WINDOW_TYPE_RIGHTRESIZE;
313 window.active = GR_FALSE;
318 GrSetCursor(nid, righthand_resize_columns, righthand_resize_rows,
319 righthand_resize_hotx, righthand_resize_hoty,
320 BLACK, WHITE, righthand_resize_fg, righthand_resize_bg);
322 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
323 | GR_EVENT_MASK_MOUSE_POSITION);
327 nid = GrNewWindow(pid, width - BORDER_WIDTHS + 1, TITLE_BAR_HEIGHT + 1,
328 BORDER_WIDTHS - 2, height - TITLE_BAR_HEIGHT - BORDER_WIDTHS -1,
332 window.type = WINDOW_TYPE_RIGHTBAR;
333 window.active = GR_FALSE;
338 GrSetCursor(nid, horizontal_resize_columns, horizontal_resize_rows,
339 horizontal_resize_hotx, horizontal_resize_hoty,
340 BLACK, WHITE, horizontal_resize_fg,
341 horizontal_resize_bg);
343 GrSelectEvents(nid, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP
344 | GR_EVENT_MASK_MOUSE_POSITION);
351 * We've just received an event notifying us that a client window has been
352 * unmapped, so we need to destroy all of the decorations.
354 void client_window_destroy(win *window)
359 Dprintf("Client window %d has been destroyed\n", window->wid);
361 if(!(pwin = find_window(window->pid))) {
362 fprintf(stderr, "Couldn't find parent of destroyed window "
363 "%d\n", window->wid);
367 /* Do it this way around so we don't handle events after destroying */
369 remove_window_and_children(pwin);
371 Dprintf("Destroying container %d\n", pid);
372 GrDestroyWindow(pid);