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()
155 RrMinsize(dock
->a_frame
, &minw
, &minh
);
157 dock
->w
= dock
->h
= 0;
160 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
161 struct DockApp
*app
= it
->data
;
162 if (config_dock_horz
) {
164 dock
->h
= MAX(dock
->h
, app
->h
);
166 dock
->w
= MAX(dock
->w
, app
->w
);
171 spot
= (config_dock_horz
? minw
: minh
) / 2;
173 /* position the apps */
174 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
175 struct DockApp
*app
= it
->data
;
176 if (config_dock_horz
) {
178 app
->y
= (dock
->h
- app
->h
) / 2;
181 app
->x
= (dock
->w
- app
->w
) / 2;
186 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
189 /* used for calculating offsets */
190 dock
->w
+= ob_rr_theme
->bwidth
* 2;
191 dock
->h
+= ob_rr_theme
->bwidth
* 2;
193 /* calculate position */
194 switch (config_dock_pos
) {
195 case DockPos_Floating
:
196 dock
->x
= config_dock_x
;
197 dock
->y
= config_dock_y
;
198 gravity
= NorthWestGravity
;
200 case DockPos_TopLeft
:
203 gravity
= NorthWestGravity
;
206 dock
->x
= screen_physical_size
.width
/ 2;
208 gravity
= NorthGravity
;
210 case DockPos_TopRight
:
211 dock
->x
= screen_physical_size
.width
;
213 gravity
= NorthEastGravity
;
217 dock
->y
= screen_physical_size
.height
/ 2;
218 gravity
= WestGravity
;
221 dock
->x
= screen_physical_size
.width
;
222 dock
->y
= screen_physical_size
.height
/ 2;
223 gravity
= EastGravity
;
225 case DockPos_BottomLeft
:
227 dock
->y
= screen_physical_size
.height
;
228 gravity
= SouthWestGravity
;
231 dock
->x
= screen_physical_size
.width
/ 2;
232 dock
->y
= screen_physical_size
.height
;
233 gravity
= SouthGravity
;
235 case DockPos_BottomRight
:
236 dock
->x
= screen_physical_size
.width
;
237 dock
->y
= screen_physical_size
.height
;
238 gravity
= SouthEastGravity
;
246 dock
->x
-= dock
->w
/ 2;
248 case NorthEastGravity
:
250 case SouthEastGravity
:
258 dock
->y
-= dock
->h
/ 2;
260 case SouthWestGravity
:
262 case SouthEastGravity
:
267 if (config_dock_hide
&& dock
->hidden
) {
268 switch (config_dock_pos
) {
269 case DockPos_Floating
:
271 case DockPos_TopLeft
:
272 if (config_dock_horz
)
273 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
275 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
278 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
280 case DockPos_TopRight
:
281 if (config_dock_horz
)
282 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
284 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
287 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
290 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
292 case DockPos_BottomLeft
:
293 if (config_dock_horz
)
294 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
296 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
299 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
301 case DockPos_BottomRight
:
302 if (config_dock_horz
)
303 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
305 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
311 switch (config_dock_pos
) {
312 case DockPos_Floating
:
313 STRUT_SET(dock_strut
, 0, 0, 0, 0);
315 case DockPos_TopLeft
:
316 if (config_dock_horz
)
317 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
319 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
322 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
324 case DockPos_TopRight
:
325 if (config_dock_horz
)
326 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
328 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
331 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
334 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
336 case DockPos_BottomLeft
:
337 if (config_dock_horz
)
338 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
340 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
343 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
345 case DockPos_BottomRight
:
346 if (config_dock_horz
)
347 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
349 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
356 /* not used for actually sizing shit */
357 dock
->w
-= ob_rr_theme
->bwidth
* 2;
358 dock
->h
-= ob_rr_theme
->bwidth
* 2;
360 if (dock
->w
> 0 && dock
->h
> 0) {
361 XMoveResizeWindow(ob_display
, dock
->frame
,
362 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
364 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
365 XMapWindow(ob_display
, dock
->frame
);
367 XUnmapWindow(ob_display
, dock
->frame
);
369 /* but they are useful outside of this function! */
370 dock
->w
+= ob_rr_theme
->bwidth
* 2;
371 dock
->h
+= ob_rr_theme
->bwidth
* 2;
373 screen_update_struts();
376 void dock_app_configure(DockApp
*app
, int w
, int h
)
383 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
385 DockApp
*over
= NULL
;
393 /* are we on top of the dock? */
394 if (!(x
>= dock
->x
&&
396 x
< dock
->x
+ dock
->w
&&
397 y
< dock
->y
+ dock
->h
))
403 /* which dock app are we on top of? */
404 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
406 if (config_dock_horz
) {
407 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
410 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
414 if (!it
|| app
== over
) return;
419 if (config_dock_horz
)
420 after
= (x
> over
->w
/ 2);
422 after
= (y
> over
->h
/ 2);
424 /* remove before doing the it->next! */
425 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
427 if (after
) it
= it
->next
;
429 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
433 static void hide_timeout(void *n
)
436 timer_stop(dock
->hide_timer
);
437 dock
->hide_timer
= NULL
;
444 void dock_hide(gboolean hide
)
446 if (dock
->hidden
== hide
|| !config_dock_hide
)
450 dock
->hidden
= FALSE
;
453 /* if was hiding, stop it */
454 if (dock
->hide_timer
) {
455 timer_stop(dock
->hide_timer
);
456 dock
->hide_timer
= NULL
;
459 g_assert(!dock
->hide_timer
);
460 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
461 (TimeoutHandler
)hide_timeout
,