9 #include "render/theme.h"
11 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
12 EnterWindowMask | LeaveWindowMask)
13 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
17 StrutPartial dock_strut
;
19 void dock_startup(gboolean reconfig
)
21 XSetWindowAttributes attrib
;
28 STRUT_PARTIAL_SET(dock_strut
, 0, 0, 0, 0,
29 0, 0, 0, 0, 0, 0, 0, 0);
31 dock
= g_new0(ObDock
, 1);
32 dock
->obwin
.type
= Window_Dock
;
36 attrib
.event_mask
= DOCK_EVENT_MASK
;
37 attrib
.override_redirect
= True
;
38 dock
->frame
= XCreateWindow(ob_display
, RootWindow(ob_display
, ob_screen
),
40 RrDepth(ob_rr_inst
), InputOutput
,
42 CWOverrideRedirect
| CWEventMask
,
44 dock
->a_frame
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
45 XSetWindowBorder(ob_display
, dock
->frame
,
46 RrColorPixel(ob_rr_theme
->b_color
));
47 XSetWindowBorderWidth(ob_display
, dock
->frame
, ob_rr_theme
->bwidth
);
49 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
50 stacking_add(DOCK_AS_WINDOW(dock
));
51 stacking_raise(DOCK_AS_WINDOW(dock
));
54 void dock_shutdown(gboolean reconfig
)
58 XDestroyWindow(ob_display
, dock
->frame
);
59 RrAppearanceFree(dock
->a_frame
);
60 g_hash_table_remove(window_map
, &dock
->frame
);
61 stacking_remove(dock
);
64 void dock_add(Window win
, XWMHints
*wmhints
)
67 XWindowAttributes attrib
;
70 app
= g_new0(ObDockApp
, 1);
71 app
->obwin
.type
= Window_DockApp
;
73 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
74 wmhints
->icon_window
: win
;
76 if (PROP_GETSS(app
->win
, wm_class
, locale
, &data
)) {
78 app
->name
= g_strdup(data
[0]);
80 app
->class = g_strdup(data
[1]);
85 if (app
->name
== NULL
) app
->name
= g_strdup("");
86 if (app
->class == NULL
) app
->class = g_strdup("");
88 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
89 app
->w
= attrib
.width
;
90 app
->h
= attrib
.height
;
95 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
98 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
100 This is the same case as in frame.c for client windows. When Openbox is
101 starting, the window is already mapped so we see unmap events occur for
102 it. There are 2 unmap events generated that we see, one with the 'event'
103 member set the root window, and one set to the client, but both get
104 handled and need to be ignored.
106 if (ob_state() == OB_STATE_STARTING
)
107 app
->ignore_unmaps
+= 2;
109 if (app
->win
!= app
->icon_win
) {
110 /* have to map it so that it can be re-managed on a restart */
111 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
112 XMapWindow(ob_display
, app
->win
);
114 XMapWindow(ob_display
, app
->icon_win
);
115 XSync(ob_display
, False
);
117 /* specify that if we exit, the window should not be destroyed and should
118 be reparented back to root automatically */
119 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
120 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
122 grab_button_full(2, 0, app
->icon_win
,
123 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
124 GrabModeAsync
, OB_CURSOR_MOVE
);
126 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
128 ob_debug("Managed Dock App: 0x%lx (%s)\n", app
->icon_win
, app
->class);
131 void dock_remove_all()
133 while (dock
->dock_apps
)
134 dock_remove(dock
->dock_apps
->data
, TRUE
);
137 void dock_remove(ObDockApp
*app
, gboolean reparent
)
139 ungrab_button(2, 0, app
->icon_win
);
140 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
141 /* remove the window from our save set */
142 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
143 XSync(ob_display
, False
);
145 g_hash_table_remove(window_map
, &app
->icon_win
);
148 XReparentWindow(ob_display
, app
->icon_win
,
149 RootWindow(ob_display
, ob_screen
), app
->x
, app
->y
);
151 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
154 ob_debug("Unmanaged Dock App: 0x%lx (%s)\n", app
->icon_win
, app
->class);
161 void dock_configure()
170 RrMinsize(dock
->a_frame
, &minw
, &minh
);
172 dock
->w
= dock
->h
= 0;
175 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
176 ObDockApp
*app
= it
->data
;
177 switch (config_dock_orient
) {
178 case OB_ORIENTATION_HORZ
:
180 dock
->h
= MAX(dock
->h
, app
->h
);
182 case OB_ORIENTATION_VERT
:
183 dock
->w
= MAX(dock
->w
, app
->w
);
189 spot
= (config_dock_orient
== OB_ORIENTATION_HORZ
? minw
: minh
) / 2;
191 /* position the apps */
192 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
193 ObDockApp
*app
= it
->data
;
194 switch (config_dock_orient
) {
195 case OB_ORIENTATION_HORZ
:
197 app
->y
= (dock
->h
- app
->h
) / 2;
200 case OB_ORIENTATION_VERT
:
201 app
->x
= (dock
->w
- app
->w
) / 2;
207 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
210 /* used for calculating offsets */
211 dock
->w
+= ob_rr_theme
->bwidth
* 2;
212 dock
->h
+= ob_rr_theme
->bwidth
* 2;
214 a
= screen_physical_area();
216 /* calculate position */
217 if (config_dock_floating
) {
218 dock
->x
= config_dock_x
;
219 dock
->y
= config_dock_y
;
220 gravity
= NorthWestGravity
;
222 switch (config_dock_pos
) {
223 case OB_DIRECTION_NORTHWEST
:
226 gravity
= NorthWestGravity
;
228 case OB_DIRECTION_NORTH
:
229 dock
->x
= a
->width
/ 2;
231 gravity
= NorthGravity
;
233 case OB_DIRECTION_NORTHEAST
:
236 gravity
= NorthEastGravity
;
238 case OB_DIRECTION_WEST
:
240 dock
->y
= a
->height
/ 2;
241 gravity
= WestGravity
;
243 case OB_DIRECTION_EAST
:
245 dock
->y
= a
->height
/ 2;
246 gravity
= EastGravity
;
248 case OB_DIRECTION_SOUTHWEST
:
251 gravity
= SouthWestGravity
;
253 case OB_DIRECTION_SOUTH
:
254 dock
->x
= a
->width
/ 2;
256 gravity
= SouthGravity
;
258 case OB_DIRECTION_SOUTHEAST
:
261 gravity
= SouthEastGravity
;
270 dock
->x
-= dock
->w
/ 2;
272 case NorthEastGravity
:
274 case SouthEastGravity
:
282 dock
->y
-= dock
->h
/ 2;
284 case SouthWestGravity
:
286 case SouthEastGravity
:
291 if (config_dock_hide
&& dock
->hidden
) {
292 if (!config_dock_floating
) {
293 switch (config_dock_pos
) {
294 case OB_DIRECTION_NORTHWEST
:
295 switch (config_dock_orient
) {
296 case OB_ORIENTATION_HORZ
:
297 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
299 case OB_ORIENTATION_VERT
:
300 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
304 case OB_DIRECTION_NORTH
:
305 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
307 case OB_DIRECTION_NORTHEAST
:
308 switch (config_dock_orient
) {
309 case OB_ORIENTATION_HORZ
:
310 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
312 case OB_ORIENTATION_VERT
:
313 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
317 case OB_DIRECTION_WEST
:
318 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
320 case OB_DIRECTION_EAST
:
321 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
323 case OB_DIRECTION_SOUTHWEST
:
324 switch (config_dock_orient
) {
325 case OB_ORIENTATION_HORZ
:
326 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
328 case OB_ORIENTATION_VERT
:
329 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
332 case OB_DIRECTION_SOUTH
:
333 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
335 case OB_DIRECTION_SOUTHEAST
:
336 switch (config_dock_orient
) {
337 case OB_ORIENTATION_HORZ
:
338 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
340 case OB_ORIENTATION_VERT
:
341 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
349 if (!config_dock_floating
&& config_dock_hide
) {
350 strw
= ob_rr_theme
->bwidth
;
351 strh
= ob_rr_theme
->bwidth
;
358 if (config_dock_floating
) {
359 STRUT_PARTIAL_SET(dock_strut
, 0, 0, 0, 0,
360 0, 0, 0, 0, 0, 0, 0, 0);
362 switch (config_dock_pos
) {
363 case OB_DIRECTION_NORTHWEST
:
364 switch (config_dock_orient
) {
365 case OB_ORIENTATION_HORZ
:
366 STRUT_PARTIAL_SET(dock_strut
, 0, strh
, 0, 0,
367 0, 0, dock
->x
, dock
->x
+ dock
->w
- 1,
370 case OB_ORIENTATION_VERT
:
371 STRUT_PARTIAL_SET(dock_strut
, strw
, 0, 0, 0,
372 dock
->y
, dock
->y
+ dock
->h
- 1,
377 case OB_DIRECTION_NORTH
:
378 STRUT_PARTIAL_SET(dock_strut
, 0, strh
, 0, 0,
379 dock
->x
, dock
->x
+ dock
->w
- 1,
382 case OB_DIRECTION_NORTHEAST
:
383 switch (config_dock_orient
) {
384 case OB_ORIENTATION_HORZ
:
385 STRUT_PARTIAL_SET(dock_strut
, 0, strh
, 0, 0,
386 0, 0, dock
->x
, dock
->x
+ dock
->w
-1,
389 case OB_ORIENTATION_VERT
:
390 STRUT_PARTIAL_SET(dock_strut
, 0, 0, strw
, 0,
392 dock
->y
, dock
->y
+ dock
->h
- 1, 0, 0);
396 case OB_DIRECTION_WEST
:
397 STRUT_PARTIAL_SET(dock_strut
, strw
, 0, 0, 0,
398 dock
->y
, dock
->y
+ dock
->h
- 1,
401 case OB_DIRECTION_EAST
:
402 STRUT_PARTIAL_SET(dock_strut
, 0, 0, strw
, 0,
404 dock
->y
, dock
->y
+ dock
->h
- 1, 0, 0);
406 case OB_DIRECTION_SOUTHWEST
:
407 switch (config_dock_orient
) {
408 case OB_ORIENTATION_HORZ
:
409 STRUT_PARTIAL_SET(dock_strut
, 0, 0, 0, strh
,
411 dock
->x
, dock
->x
+ dock
->w
- 1);
413 case OB_ORIENTATION_VERT
:
414 STRUT_PARTIAL_SET(dock_strut
, strw
, 0, 0, 0,
415 dock
->y
, dock
->y
+ dock
->h
- 1,
420 case OB_DIRECTION_SOUTH
:
421 STRUT_PARTIAL_SET(dock_strut
, 0, 0, 0, strh
,
423 dock
->x
, dock
->x
+ dock
->w
- 1);
425 case OB_DIRECTION_SOUTHEAST
:
426 switch (config_dock_orient
) {
427 case OB_ORIENTATION_HORZ
:
428 STRUT_PARTIAL_SET(dock_strut
, 0, 0, 0, strh
,
430 dock
->x
, dock
->x
+ dock
->w
- 1);
432 case OB_ORIENTATION_VERT
:
433 STRUT_PARTIAL_SET(dock_strut
, 0, 0, strw
, 0,
435 dock
->y
, dock
->y
+ dock
->h
- 1, 0, 0);
445 /* not used for actually sizing shit */
446 dock
->w
-= ob_rr_theme
->bwidth
* 2;
447 dock
->h
-= ob_rr_theme
->bwidth
* 2;
449 if (dock
->w
> 0 && dock
->h
> 0) {
450 XMoveResizeWindow(ob_display
, dock
->frame
,
451 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
453 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
454 XMapWindow(ob_display
, dock
->frame
);
456 XUnmapWindow(ob_display
, dock
->frame
);
458 /* but they are useful outside of this function! */
459 dock
->w
+= ob_rr_theme
->bwidth
* 2;
460 dock
->h
+= ob_rr_theme
->bwidth
* 2;
462 screen_update_areas();
465 void dock_app_configure(ObDockApp
*app
, gint w
, gint h
)
472 void dock_app_drag(ObDockApp
*app
, XMotionEvent
*e
)
474 ObDockApp
*over
= NULL
;
483 /* are we on top of the dock? */
484 if (!(x
>= dock
->x
&&
486 x
< dock
->x
+ dock
->w
&&
487 y
< dock
->y
+ dock
->h
))
493 /* which dock app are we on top of? */
495 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
497 switch (config_dock_orient
) {
498 case OB_ORIENTATION_HORZ
:
499 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
502 case OB_ORIENTATION_VERT
:
503 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
507 /* dont go to it->next! */
510 if (!it
|| app
== over
) return;
515 switch (config_dock_orient
) {
516 case OB_ORIENTATION_HORZ
:
517 after
= (x
> over
->w
/ 2);
519 case OB_ORIENTATION_VERT
:
520 after
= (y
> over
->h
/ 2);
524 /* remove before doing the it->next! */
525 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
527 if (after
) it
= it
->next
;
529 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
533 static gboolean
hide_timeout(gpointer data
)
539 return FALSE
; /* don't repeat */
542 void dock_hide(gboolean hide
)
544 if (dock
->hidden
== hide
|| !config_dock_hide
)
548 dock
->hidden
= FALSE
;
551 /* if was hiding, stop it */
552 ob_main_loop_timeout_remove(ob_main_loop
, hide_timeout
);
554 ob_main_loop_timeout_add(ob_main_loop
, config_dock_hide_timeout
* 1000,
555 hide_timeout
, NULL
, NULL
);