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