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
== 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(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()
157 RrMinsize(dock
->a_frame
, &minw
, &minh
);
159 dock
->w
= dock
->h
= 0;
162 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
163 struct DockApp
*app
= it
->data
;
164 if (config_dock_horz
) {
166 dock
->h
= MAX(dock
->h
, app
->h
);
168 dock
->w
= MAX(dock
->w
, app
->w
);
173 spot
= (config_dock_horz
? minw
: minh
) / 2;
175 /* position the apps */
176 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
177 struct DockApp
*app
= it
->data
;
178 if (config_dock_horz
) {
180 app
->y
= (dock
->h
- app
->h
) / 2;
183 app
->x
= (dock
->w
- app
->w
) / 2;
188 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
191 /* used for calculating offsets */
192 dock
->w
+= ob_rr_theme
->bwidth
* 2;
193 dock
->h
+= ob_rr_theme
->bwidth
* 2;
195 a
= screen_physical_area();
197 /* calculate position */
198 switch (config_dock_pos
) {
199 case DockPos_Floating
:
200 dock
->x
= config_dock_x
;
201 dock
->y
= config_dock_y
;
202 gravity
= NorthWestGravity
;
204 case DockPos_TopLeft
:
207 gravity
= NorthWestGravity
;
210 dock
->x
= a
->width
/ 2;
212 gravity
= NorthGravity
;
214 case DockPos_TopRight
:
217 gravity
= NorthEastGravity
;
221 dock
->y
= a
->height
/ 2;
222 gravity
= WestGravity
;
226 dock
->y
= a
->height
/ 2;
227 gravity
= EastGravity
;
229 case DockPos_BottomLeft
:
232 gravity
= SouthWestGravity
;
235 dock
->x
= a
->width
/ 2;
237 gravity
= SouthGravity
;
239 case DockPos_BottomRight
:
242 gravity
= SouthEastGravity
;
250 dock
->x
-= dock
->w
/ 2;
252 case NorthEastGravity
:
254 case SouthEastGravity
:
262 dock
->y
-= dock
->h
/ 2;
264 case SouthWestGravity
:
266 case SouthEastGravity
:
271 if (config_dock_hide
&& dock
->hidden
) {
272 switch (config_dock_pos
) {
273 case DockPos_Floating
:
275 case DockPos_TopLeft
:
276 if (config_dock_horz
)
277 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
279 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
282 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
284 case DockPos_TopRight
:
285 if (config_dock_horz
)
286 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
288 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
291 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
294 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
296 case DockPos_BottomLeft
:
297 if (config_dock_horz
)
298 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
300 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
303 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
305 case DockPos_BottomRight
:
306 if (config_dock_horz
)
307 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
309 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
314 if (config_dock_pos
!= DockPos_Floating
&& config_dock_hide
) {
315 strw
= strh
= ob_rr_theme
->bwidth
;
322 switch (config_dock_pos
) {
323 case DockPos_Floating
:
324 STRUT_SET(dock_strut
, 0, 0, 0, 0);
326 case DockPos_TopLeft
:
327 if (config_dock_horz
)
328 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
330 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
333 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
335 case DockPos_TopRight
:
336 if (config_dock_horz
)
337 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
339 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
342 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
345 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
347 case DockPos_BottomLeft
:
348 if (config_dock_horz
)
349 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
351 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
354 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
356 case DockPos_BottomRight
:
357 if (config_dock_horz
)
358 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
360 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
367 /* not used for actually sizing shit */
368 dock
->w
-= ob_rr_theme
->bwidth
* 2;
369 dock
->h
-= ob_rr_theme
->bwidth
* 2;
371 if (dock
->w
> 0 && dock
->h
> 0) {
372 XMoveResizeWindow(ob_display
, dock
->frame
,
373 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
375 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
376 XMapWindow(ob_display
, dock
->frame
);
378 XUnmapWindow(ob_display
, dock
->frame
);
380 /* but they are useful outside of this function! */
381 dock
->w
+= ob_rr_theme
->bwidth
* 2;
382 dock
->h
+= ob_rr_theme
->bwidth
* 2;
384 screen_update_areas();
387 void dock_app_configure(DockApp
*app
, int w
, int h
)
394 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
396 DockApp
*over
= NULL
;
404 /* are we on top of the dock? */
405 if (!(x
>= dock
->x
&&
407 x
< dock
->x
+ dock
->w
&&
408 y
< dock
->y
+ dock
->h
))
414 /* which dock app are we on top of? */
415 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
417 if (config_dock_horz
) {
418 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
421 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
425 if (!it
|| app
== over
) return;
430 if (config_dock_horz
)
431 after
= (x
> over
->w
/ 2);
433 after
= (y
> over
->h
/ 2);
435 /* remove before doing the it->next! */
436 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
438 if (after
) it
= it
->next
;
440 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
444 static void hide_timeout(void *n
)
447 timer_stop(dock
->hide_timer
);
448 dock
->hide_timer
= NULL
;
455 void dock_hide(gboolean hide
)
457 if (dock
->hidden
== hide
|| !config_dock_hide
)
461 dock
->hidden
= FALSE
;
464 /* if was hiding, stop it */
465 if (dock
->hide_timer
) {
466 timer_stop(dock
->hide_timer
);
467 dock
->hide_timer
= NULL
;
470 g_assert(!dock
->hide_timer
);
471 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
472 (TimeoutHandler
)hide_timeout
,