7 #include "render/theme.h"
9 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
10 EnterWindowMask | LeaveWindowMask)
11 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
19 XSetWindowAttributes attrib
;
21 STRUT_SET(dock_strut
, 0, 0, 0, 0);
23 dock
= g_new0(ObDock
, 1);
24 dock
->obwin
.type
= Window_Dock
;
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 RrDepth(ob_rr_inst
), InputOutput
,
33 CWOverrideRedirect
| CWEventMask
,
35 dock
->a_frame
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
36 XSetWindowBorder(ob_display
, dock
->frame
, ob_rr_theme
->b_color
->pixel
);
37 XSetWindowBorderWidth(ob_display
, dock
->frame
, ob_rr_theme
->bwidth
);
39 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
40 stacking_add(DOCK_AS_WINDOW(dock
));
41 stacking_raise(DOCK_AS_WINDOW(dock
));
46 XDestroyWindow(ob_display
, dock
->frame
);
47 RrAppearanceFree(dock
->a_frame
);
48 g_hash_table_remove(window_map
, &dock
->frame
);
49 stacking_remove(dock
);
52 void dock_add(Window win
, XWMHints
*wmhints
)
55 XWindowAttributes attrib
;
58 app
= g_new0(ObDockApp
, 1);
59 app
->obwin
.type
= Window_DockApp
;
61 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
62 wmhints
->icon_window
: win
;
64 if (PROP_GETSS(app
->win
, wm_class
, locale
, &data
)) {
66 app
->name
= g_strdup(data
[0]);
68 app
->class = g_strdup(data
[1]);
73 if (app
->name
== NULL
) app
->name
= g_strdup("");
74 if (app
->class == NULL
) app
->class = g_strdup("");
76 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
77 app
->w
= attrib
.width
;
78 app
->h
= attrib
.height
;
83 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
86 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
88 This is the same case as in frame.c for client windows. When Openbox is
89 starting, the window is already mapped so we see unmap events occur for
90 it. There are 2 unmap events generated that we see, one with the 'event'
91 member set the root window, and one set to the client, but both get
92 handled and need to be ignored.
94 if (ob_state
== OB_STATE_STARTING
)
95 app
->ignore_unmaps
+= 2;
97 if (app
->win
!= app
->icon_win
) {
98 /* have to map it so that it can be re-managed on a restart */
99 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
100 XMapWindow(ob_display
, app
->win
);
102 XMapWindow(ob_display
, app
->icon_win
);
103 XSync(ob_display
, False
);
105 /* specify that if we exit, the window should not be destroyed and should
106 be reparented back to root automatically */
107 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
108 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
110 grab_button_full(2, 0, app
->icon_win
,
111 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
112 GrabModeAsync
, OB_CURSOR_MOVE
);
114 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
116 g_message("Managed Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
119 void dock_remove_all()
121 while (dock
->dock_apps
)
122 dock_remove(dock
->dock_apps
->data
, TRUE
);
125 void dock_remove(ObDockApp
*app
, gboolean reparent
)
127 ungrab_button(2, 0, app
->icon_win
);
128 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
129 /* remove the window from our save set */
130 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
131 XSync(ob_display
, False
);
133 g_hash_table_remove(window_map
, &app
->icon_win
);
136 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
138 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
141 g_message("Unmanaged Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
148 void dock_configure()
157 RrMinsize(dock
->a_frame
, &minw
, &minh
);
159 dock
->w
= dock
->h
= 0;
162 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
163 ObDockApp
*app
= it
->data
;
164 switch (config_dock_orient
) {
165 case OB_ORIENTATION_HORZ
:
167 dock
->h
= MAX(dock
->h
, app
->h
);
169 case OB_ORIENTATION_VERT
:
170 dock
->w
= MAX(dock
->w
, app
->w
);
176 spot
= (config_dock_orient
== OB_ORIENTATION_HORZ
? minw
: minh
) / 2;
178 /* position the apps */
179 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
180 ObDockApp
*app
= it
->data
;
181 switch (config_dock_orient
) {
182 case OB_ORIENTATION_HORZ
:
184 app
->y
= (dock
->h
- app
->h
) / 2;
187 case OB_ORIENTATION_VERT
:
188 app
->x
= (dock
->w
- app
->w
) / 2;
194 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
197 /* used for calculating offsets */
198 dock
->w
+= ob_rr_theme
->bwidth
* 2;
199 dock
->h
+= ob_rr_theme
->bwidth
* 2;
201 a
= screen_physical_area();
203 /* calculate position */
204 if (config_dock_floating
) {
205 dock
->x
= config_dock_x
;
206 dock
->y
= config_dock_y
;
207 gravity
= NorthWestGravity
;
209 switch (config_dock_pos
) {
210 case OB_DIRECTION_NORTHWEST
:
213 gravity
= NorthWestGravity
;
215 case OB_DIRECTION_NORTH
:
216 dock
->x
= a
->width
/ 2;
218 gravity
= NorthGravity
;
220 case OB_DIRECTION_NORTHEAST
:
223 gravity
= NorthEastGravity
;
225 case OB_DIRECTION_WEST
:
227 dock
->y
= a
->height
/ 2;
228 gravity
= WestGravity
;
230 case OB_DIRECTION_EAST
:
232 dock
->y
= a
->height
/ 2;
233 gravity
= EastGravity
;
235 case OB_DIRECTION_SOUTHWEST
:
238 gravity
= SouthWestGravity
;
240 case OB_DIRECTION_SOUTH
:
241 dock
->x
= a
->width
/ 2;
243 gravity
= SouthGravity
;
245 case OB_DIRECTION_SOUTHEAST
:
248 gravity
= SouthEastGravity
;
257 dock
->x
-= dock
->w
/ 2;
259 case NorthEastGravity
:
261 case SouthEastGravity
:
269 dock
->y
-= dock
->h
/ 2;
271 case SouthWestGravity
:
273 case SouthEastGravity
:
278 if (config_dock_hide
&& dock
->hidden
) {
279 if (!config_dock_floating
) {
280 switch (config_dock_pos
) {
281 case OB_DIRECTION_NORTHWEST
:
282 switch (config_dock_orient
) {
283 case OB_ORIENTATION_HORZ
:
284 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
286 case OB_ORIENTATION_VERT
:
287 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
291 case OB_DIRECTION_NORTH
:
292 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
294 case OB_DIRECTION_NORTHEAST
:
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_WEST
:
305 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
307 case OB_DIRECTION_EAST
:
308 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
310 case OB_DIRECTION_SOUTHWEST
:
311 switch (config_dock_orient
) {
312 case OB_ORIENTATION_HORZ
:
313 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
315 case OB_ORIENTATION_VERT
:
316 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
319 case OB_DIRECTION_SOUTH
:
320 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
322 case OB_DIRECTION_SOUTHEAST
:
323 switch (config_dock_orient
) {
324 case OB_ORIENTATION_HORZ
:
325 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
327 case OB_ORIENTATION_VERT
:
328 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
336 if (!config_dock_floating
&& config_dock_hide
) {
337 strw
= strh
= ob_rr_theme
->bwidth
;
344 if (config_dock_floating
) {
345 STRUT_SET(dock_strut
, 0, 0, 0, 0);
347 switch (config_dock_pos
) {
348 case OB_DIRECTION_NORTHWEST
:
349 switch (config_dock_orient
) {
350 case OB_ORIENTATION_HORZ
:
351 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
353 case OB_ORIENTATION_VERT
:
354 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
358 case OB_DIRECTION_NORTH
:
359 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
361 case OB_DIRECTION_NORTHEAST
:
362 switch (config_dock_orient
) {
363 case OB_ORIENTATION_HORZ
:
364 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
366 case OB_ORIENTATION_VERT
:
367 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
371 case OB_DIRECTION_WEST
:
372 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
374 case OB_DIRECTION_EAST
:
375 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
377 case OB_DIRECTION_SOUTHWEST
:
378 switch (config_dock_orient
) {
379 case OB_ORIENTATION_HORZ
:
380 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
382 case OB_ORIENTATION_VERT
:
383 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
387 case OB_DIRECTION_SOUTH
:
388 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
390 case OB_DIRECTION_SOUTHEAST
:
391 switch (config_dock_orient
) {
392 case OB_ORIENTATION_HORZ
:
393 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
395 case OB_ORIENTATION_VERT
:
396 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
406 /* not used for actually sizing shit */
407 dock
->w
-= ob_rr_theme
->bwidth
* 2;
408 dock
->h
-= ob_rr_theme
->bwidth
* 2;
410 if (dock
->w
> 0 && dock
->h
> 0) {
411 XMoveResizeWindow(ob_display
, dock
->frame
,
412 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
414 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
415 XMapWindow(ob_display
, dock
->frame
);
417 XUnmapWindow(ob_display
, dock
->frame
);
419 /* but they are useful outside of this function! */
420 dock
->w
+= ob_rr_theme
->bwidth
* 2;
421 dock
->h
+= ob_rr_theme
->bwidth
* 2;
423 screen_update_areas();
426 void dock_app_configure(ObDockApp
*app
, gint w
, gint h
)
433 void dock_app_drag(ObDockApp
*app
, XMotionEvent
*e
)
435 ObDockApp
*over
= NULL
;
444 /* are we on top of the dock? */
445 if (!(x
>= dock
->x
&&
447 x
< dock
->x
+ dock
->w
&&
448 y
< dock
->y
+ dock
->h
))
454 /* which dock app are we on top of? */
456 for (it
= dock
->dock_apps
; it
&& !stop
; it
= it
->next
) {
458 switch (config_dock_orient
) {
459 case OB_ORIENTATION_HORZ
:
460 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
463 case OB_ORIENTATION_VERT
:
464 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
469 if (!it
|| app
== over
) return;
474 switch (config_dock_orient
) {
475 case OB_ORIENTATION_HORZ
:
476 after
= (x
> over
->w
/ 2);
478 case OB_ORIENTATION_VERT
:
479 after
= (y
> over
->h
/ 2);
483 /* remove before doing the it->next! */
484 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
486 if (after
) it
= it
->next
;
488 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
492 static void hide_timeout(void *n
)
495 timer_stop(dock
->hide_timer
);
496 dock
->hide_timer
= NULL
;
503 void dock_hide(gboolean hide
)
505 if (dock
->hidden
== hide
|| !config_dock_hide
)
509 dock
->hidden
= FALSE
;
512 /* if was hiding, stop it */
513 if (dock
->hide_timer
) {
514 timer_stop(dock
->hide_timer
);
515 dock
->hide_timer
= NULL
;
518 g_assert(!dock
->hide_timer
);
519 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
520 (TimeoutHandler
)hide_timeout
,