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(struct Dock
, 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(DockApp
, 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
== 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_cursors
.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(DockApp
*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()
156 RrMinsize(dock
->a_frame
, &minw
, &minh
);
158 dock
->w
= dock
->h
= 0;
161 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
162 struct DockApp
*app
= it
->data
;
163 if (config_dock_horz
) {
165 dock
->h
= MAX(dock
->h
, app
->h
);
167 dock
->w
= MAX(dock
->w
, app
->w
);
172 spot
= (config_dock_horz
? minw
: minh
) / 2;
174 /* position the apps */
175 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
176 struct DockApp
*app
= it
->data
;
177 if (config_dock_horz
) {
179 app
->y
= (dock
->h
- app
->h
) / 2;
182 app
->x
= (dock
->w
- app
->w
) / 2;
187 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
190 /* used for calculating offsets */
191 dock
->w
+= ob_rr_theme
->bwidth
* 2;
192 dock
->h
+= ob_rr_theme
->bwidth
* 2;
194 a
= screen_physical_area();
196 /* calculate position */
197 switch (config_dock_pos
) {
198 case DockPos_Floating
:
199 dock
->x
= config_dock_x
;
200 dock
->y
= config_dock_y
;
201 gravity
= NorthWestGravity
;
203 case DockPos_TopLeft
:
206 gravity
= NorthWestGravity
;
209 dock
->x
= a
->width
/ 2;
211 gravity
= NorthGravity
;
213 case DockPos_TopRight
:
216 gravity
= NorthEastGravity
;
220 dock
->y
= a
->height
/ 2;
221 gravity
= WestGravity
;
225 dock
->y
= a
->height
/ 2;
226 gravity
= EastGravity
;
228 case DockPos_BottomLeft
:
231 gravity
= SouthWestGravity
;
234 dock
->x
= a
->width
/ 2;
236 gravity
= SouthGravity
;
238 case DockPos_BottomRight
:
241 gravity
= SouthEastGravity
;
249 dock
->x
-= dock
->w
/ 2;
251 case NorthEastGravity
:
253 case SouthEastGravity
:
261 dock
->y
-= dock
->h
/ 2;
263 case SouthWestGravity
:
265 case SouthEastGravity
:
270 if (config_dock_hide
&& dock
->hidden
) {
271 switch (config_dock_pos
) {
272 case DockPos_Floating
:
274 case DockPos_TopLeft
:
275 if (config_dock_horz
)
276 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
278 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
281 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
283 case DockPos_TopRight
:
284 if (config_dock_horz
)
285 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
287 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
290 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
293 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
295 case DockPos_BottomLeft
:
296 if (config_dock_horz
)
297 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
299 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
302 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
304 case DockPos_BottomRight
:
305 if (config_dock_horz
)
306 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
308 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
314 switch (config_dock_pos
) {
315 case DockPos_Floating
:
316 STRUT_SET(dock_strut
, 0, 0, 0, 0);
318 case DockPos_TopLeft
:
319 if (config_dock_horz
)
320 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
322 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
325 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
327 case DockPos_TopRight
:
328 if (config_dock_horz
)
329 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
331 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
334 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
337 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
339 case DockPos_BottomLeft
:
340 if (config_dock_horz
)
341 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
343 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
346 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
348 case DockPos_BottomRight
:
349 if (config_dock_horz
)
350 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
352 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
359 /* not used for actually sizing shit */
360 dock
->w
-= ob_rr_theme
->bwidth
* 2;
361 dock
->h
-= ob_rr_theme
->bwidth
* 2;
363 if (dock
->w
> 0 && dock
->h
> 0) {
364 XMoveResizeWindow(ob_display
, dock
->frame
,
365 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
367 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
368 XMapWindow(ob_display
, dock
->frame
);
370 XUnmapWindow(ob_display
, dock
->frame
);
372 /* but they are useful outside of this function! */
373 dock
->w
+= ob_rr_theme
->bwidth
* 2;
374 dock
->h
+= ob_rr_theme
->bwidth
* 2;
376 screen_update_areas();
379 void dock_app_configure(DockApp
*app
, int w
, int h
)
386 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
388 DockApp
*over
= NULL
;
396 /* are we on top of the dock? */
397 if (!(x
>= dock
->x
&&
399 x
< dock
->x
+ dock
->w
&&
400 y
< dock
->y
+ dock
->h
))
406 /* which dock app are we on top of? */
407 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
409 if (config_dock_horz
) {
410 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
413 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
417 if (!it
|| app
== over
) return;
422 if (config_dock_horz
)
423 after
= (x
> over
->w
/ 2);
425 after
= (y
> over
->h
/ 2);
427 /* remove before doing the it->next! */
428 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
430 if (after
) it
= it
->next
;
432 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
436 static void hide_timeout(void *n
)
439 timer_stop(dock
->hide_timer
);
440 dock
->hide_timer
= NULL
;
447 void dock_hide(gboolean hide
)
449 if (dock
->hidden
== hide
|| !config_dock_hide
)
453 dock
->hidden
= FALSE
;
456 /* if was hiding, stop it */
457 if (dock
->hide_timer
) {
458 timer_stop(dock
->hide_timer
);
459 dock
->hide_timer
= NULL
;
462 g_assert(!dock
->hide_timer
);
463 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
464 (TimeoutHandler
)hide_timeout
,