]> Dogcows Code - chaz/openbox/blob - openbox/dock.c
remove debug print
[chaz/openbox] / openbox / dock.c
1 #include "dock.h"
2 #include "screen.h"
3 #include "prop.h"
4 #include "config.h"
5 #include "grab.h"
6 #include "openbox.h"
7 #include "render/theme.h"
8
9 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
10 EnterWindowMask | LeaveWindowMask)
11 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
12
13 static Dock *dock;
14
15 Strut dock_strut;
16
17 void dock_startup()
18 {
19 XSetWindowAttributes attrib;
20
21 STRUT_SET(dock_strut, 0, 0, 0, 0);
22
23 dock = g_new0(struct Dock, 1);
24 dock->obwin.type = Window_Dock;
25
26 dock->hidden = TRUE;
27
28 attrib.event_mask = DOCK_EVENT_MASK;
29 attrib.override_redirect = True;
30 dock->frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
31 render_depth, InputOutput, render_visual,
32 CWOverrideRedirect | CWEventMask,
33 &attrib);
34 dock->a_frame = appearance_copy(theme_a_unfocused_title);
35 XSetWindowBorder(ob_display, dock->frame, theme_b_color->pixel);
36 XSetWindowBorderWidth(ob_display, dock->frame, theme_bwidth);
37
38 g_hash_table_insert(window_map, &dock->frame, dock);
39 stacking_add(DOCK_AS_WINDOW(dock));
40 stacking_raise(DOCK_AS_WINDOW(dock));
41 }
42
43 void dock_shutdown()
44 {
45 XDestroyWindow(ob_display, dock->frame);
46 appearance_free(dock->a_frame);
47 g_hash_table_remove(window_map, &dock->frame);
48 stacking_remove(dock);
49 }
50
51 void dock_add(Window win, XWMHints *wmhints)
52 {
53 DockApp *app;
54 XWindowAttributes attrib;
55 char **data;
56
57 app = g_new0(DockApp, 1);
58 app->obwin.type = Window_DockApp;
59 app->win = win;
60 app->icon_win = (wmhints->flags & IconWindowHint) ?
61 wmhints->icon_window : win;
62
63 if (PROP_GETSS(app->win, wm_class, locale, &data)) {
64 if (data[0]) {
65 app->name = g_strdup(data[0]);
66 if (data[1])
67 app->class = g_strdup(data[1]);
68 }
69 g_strfreev(data);
70 }
71
72 if (app->name == NULL) app->name = g_strdup("");
73 if (app->class == NULL) app->class = g_strdup("");
74
75 if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
76 app->w = attrib.width;
77 app->h = attrib.height;
78 } else {
79 app->w = app->h = 64;
80 }
81
82 dock->dock_apps = g_list_append(dock->dock_apps, app);
83 dock_configure();
84
85 XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
86 /*
87 This is the same case as in frame.c for client windows. When Openbox is
88 starting, the window is already mapped so we see unmap events occur for
89 it. There are 2 unmap events generated that we see, one with the 'event'
90 member set the root window, and one set to the client, but both get
91 handled and need to be ignored.
92 */
93 if (ob_state == State_Starting)
94 app->ignore_unmaps += 2;
95
96 if (app->win != app->icon_win) {
97 /* have to map it so that it can be re-managed on a restart */
98 XMoveWindow(ob_display, app->win, -1000, -1000);
99 XMapWindow(ob_display, app->win);
100 }
101 XMapWindow(ob_display, app->icon_win);
102 XSync(ob_display, False);
103
104 /* specify that if we exit, the window should not be destroyed and should
105 be reparented back to root automatically */
106 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
107 XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
108
109 grab_button_full(2, 0, app->icon_win,
110 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
111 GrabModeAsync, ob_cursors.move);
112
113 g_hash_table_insert(window_map, &app->icon_win, app);
114
115 g_message("Managed Dock App: 0x%lx (%s)", app->icon_win, app->class);
116 }
117
118 void dock_remove_all()
119 {
120 while (dock->dock_apps)
121 dock_remove(dock->dock_apps->data, TRUE);
122 }
123
124 void dock_remove(DockApp *app, gboolean reparent)
125 {
126 ungrab_button(2, 0, app->icon_win);
127 XSelectInput(ob_display, app->icon_win, NoEventMask);
128 /* remove the window from our save set */
129 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
130 XSync(ob_display, False);
131
132 g_hash_table_remove(window_map, &app->icon_win);
133
134 if (reparent)
135 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
136
137 dock->dock_apps = g_list_remove(dock->dock_apps, app);
138 dock_configure();
139
140 g_message("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
141
142 g_free(app->name);
143 g_free(app->class);
144 g_free(app);
145 }
146
147 void dock_configure()
148 {
149 GList *it;
150 int spot;
151 int gravity;
152
153 dock->w = dock->h = spot = 0;
154
155 /* get the size */
156 for (it = dock->dock_apps; it; it = it->next) {
157 struct DockApp *app = it->data;
158 if (config_dock_horz) {
159 dock->w += app->w;
160 dock->h = MAX(dock->h, app->h);
161 } else {
162 dock->w = MAX(dock->w, app->w);
163 dock->h += app->h;
164 }
165 }
166
167 /* position the apps */
168 for (it = dock->dock_apps; it; it = it->next) {
169 struct DockApp *app = it->data;
170 if (config_dock_horz) {
171 app->x = spot;
172 app->y = (dock->h - app->h) / 2;
173 spot += app->w;
174 } else {
175 app->x = (dock->w - app->w) / 2;
176 app->y = spot;
177 spot += app->h;
178 }
179
180 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
181 }
182
183 /* used for calculating offsets */
184 dock->w += theme_bwidth * 2;
185 dock->h += theme_bwidth * 2;
186
187 /* calculate position */
188 switch (config_dock_pos) {
189 case DockPos_Floating:
190 dock->x = config_dock_x;
191 dock->y = config_dock_y;
192 gravity = NorthWestGravity;
193 break;
194 case DockPos_TopLeft:
195 dock->x = 0;
196 dock->y = 0;
197 gravity = NorthWestGravity;
198 break;
199 case DockPos_Top:
200 dock->x = screen_physical_size.width / 2;
201 dock->y = 0;
202 gravity = NorthGravity;
203 break;
204 case DockPos_TopRight:
205 dock->x = screen_physical_size.width;
206 dock->y = 0;
207 gravity = NorthEastGravity;
208 break;
209 case DockPos_Left:
210 dock->x = 0;
211 dock->y = screen_physical_size.height / 2;
212 gravity = WestGravity;
213 break;
214 case DockPos_Right:
215 dock->x = screen_physical_size.width;
216 dock->y = screen_physical_size.height / 2;
217 gravity = EastGravity;
218 break;
219 case DockPos_BottomLeft:
220 dock->x = 0;
221 dock->y = screen_physical_size.height;
222 gravity = SouthWestGravity;
223 break;
224 case DockPos_Bottom:
225 dock->x = screen_physical_size.width / 2;
226 dock->y = screen_physical_size.height;
227 gravity = SouthGravity;
228 break;
229 case DockPos_BottomRight:
230 dock->x = screen_physical_size.width;
231 dock->y = screen_physical_size.height;
232 gravity = SouthEastGravity;
233 break;
234 }
235
236 switch(gravity) {
237 case NorthGravity:
238 case CenterGravity:
239 case SouthGravity:
240 dock->x -= dock->w / 2;
241 break;
242 case NorthEastGravity:
243 case EastGravity:
244 case SouthEastGravity:
245 dock->x -= dock->w;
246 break;
247 }
248 switch(gravity) {
249 case WestGravity:
250 case CenterGravity:
251 case EastGravity:
252 dock->y -= dock->h / 2;
253 break;
254 case SouthWestGravity:
255 case SouthGravity:
256 case SouthEastGravity:
257 dock->y -= dock->h;
258 break;
259 }
260
261 if (config_dock_hide && dock->hidden) {
262 switch (config_dock_pos) {
263 case DockPos_Floating:
264 break;
265 case DockPos_TopLeft:
266 if (config_dock_horz)
267 dock->y -= dock->h - theme_bwidth;
268 else
269 dock->x -= dock->w - theme_bwidth;
270 break;
271 case DockPos_Top:
272 dock->y -= dock->h - theme_bwidth;
273 break;
274 case DockPos_TopRight:
275 if (config_dock_horz)
276 dock->y -= dock->h - theme_bwidth;
277 else
278 dock->x += dock->w - theme_bwidth;
279 break;
280 case DockPos_Left:
281 dock->x -= dock->w - theme_bwidth;
282 break;
283 case DockPos_Right:
284 dock->x += dock->w - theme_bwidth;
285 break;
286 case DockPos_BottomLeft:
287 if (config_dock_horz)
288 dock->y += dock->h - theme_bwidth;
289 else
290 dock->x -= dock->w - theme_bwidth;
291 break;
292 case DockPos_Bottom:
293 dock->y += dock->h - theme_bwidth;
294 break;
295 case DockPos_BottomRight:
296 if (config_dock_horz)
297 dock->y += dock->h - theme_bwidth;
298 else
299 dock->x += dock->w - theme_bwidth;
300 break;
301 }
302 }
303
304 /* set the strut */
305 switch (config_dock_pos) {
306 case DockPos_Floating:
307 STRUT_SET(dock_strut, 0, 0, 0, 0);
308 break;
309 case DockPos_TopLeft:
310 if (config_dock_horz)
311 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
312 else
313 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
314 break;
315 case DockPos_Top:
316 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
317 break;
318 case DockPos_TopRight:
319 if (config_dock_horz)
320 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
321 else
322 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
323 break;
324 case DockPos_Left:
325 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
326 break;
327 case DockPos_Right:
328 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
329 break;
330 case DockPos_BottomLeft:
331 if (config_dock_horz)
332 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
333 else
334 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
335 break;
336 case DockPos_Bottom:
337 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
338 break;
339 case DockPos_BottomRight:
340 if (config_dock_horz)
341 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
342 else
343 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
344 break;
345 }
346
347 /* not used for actually sizing shit */
348 dock->w -= theme_bwidth * 2;
349 dock->h -= theme_bwidth * 2;
350
351 if (dock->w > 0 && dock->h > 0) {
352 RECT_SET(dock->a_frame->area, 0, 0, dock->w, dock->h);
353 XMoveResizeWindow(ob_display, dock->frame,
354 dock->x, dock->y, dock->w, dock->h);
355
356 paint(dock->frame, dock->a_frame);
357 XMapWindow(ob_display, dock->frame);
358 } else
359 XUnmapWindow(ob_display, dock->frame);
360
361 /* but they are useful outside of this function! */
362 dock->w += theme_bwidth * 2;
363 dock->h += theme_bwidth * 2;
364
365 screen_update_struts();
366 }
367
368 void dock_app_configure(DockApp *app, int w, int h)
369 {
370 app->w = w;
371 app->h = h;
372 dock_configure();
373 }
374
375 void dock_app_drag(DockApp *app, XMotionEvent *e)
376 {
377 DockApp *over = NULL;
378 GList *it;
379 int x, y;
380 gboolean after;
381
382 x = e->x_root;
383 y = e->y_root;
384
385 /* are we on top of the dock? */
386 if (!(x >= dock->x &&
387 y >= dock->y &&
388 x < dock->x + dock->w &&
389 y < dock->y + dock->h))
390 return;
391
392 x -= dock->x;
393 y -= dock->y;
394
395 /* which dock app are we on top of? */
396 for (it = dock->dock_apps; it; it = it->next) {
397 over = it->data;
398 if (config_dock_horz) {
399 if (x >= over->x && x < over->x + over->w)
400 break;
401 } else {
402 if (y >= over->y && y < over->y + over->h)
403 break;
404 }
405 }
406 if (!it || app == over) return;
407
408 x -= over->x;
409 y -= over->y;
410
411 if (config_dock_horz)
412 after = (x > over->w / 2);
413 else
414 after = (y > over->h / 2);
415
416 /* remove before doing the it->next! */
417 dock->dock_apps = g_list_remove(dock->dock_apps, app);
418
419 if (after) it = it->next;
420
421 dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app);
422 dock_configure();
423 }
424
425 static void hide_timeout(void *n)
426 {
427 /* dont repeat */
428 timer_stop(dock->hide_timer);
429 dock->hide_timer = NULL;
430
431 /* hide */
432 dock->hidden = TRUE;
433 dock_configure();
434 }
435
436 void dock_hide(gboolean hide)
437 {
438 if (dock->hidden == hide || !config_dock_hide)
439 return;
440 if (!hide) {
441 /* show */
442 dock->hidden = FALSE;
443 dock_configure();
444
445 /* if was hiding, stop it */
446 if (dock->hide_timer) {
447 timer_stop(dock->hide_timer);
448 dock->hide_timer = NULL;
449 }
450 } else {
451 g_assert(!dock->hide_timer);
452 dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
453 (TimeoutHandler)hide_timeout,
454 NULL);
455 }
456 }
This page took 0.059485 seconds and 4 git commands to generate.