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(theme_a_unfocused_title
);
36 XSetWindowBorder(ob_display
, dock
->frame
, theme_b_color
->pixel
);
37 XSetWindowBorderWidth(ob_display
, dock
->frame
, 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()
154 dock
->w
= dock
->h
= spot
= 0;
157 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
158 struct DockApp
*app
= it
->data
;
159 if (config_dock_horz
) {
161 dock
->h
= MAX(dock
->h
, app
->h
);
163 dock
->w
= MAX(dock
->w
, app
->w
);
168 /* position the apps */
169 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
170 struct DockApp
*app
= it
->data
;
171 if (config_dock_horz
) {
173 app
->y
= (dock
->h
- app
->h
) / 2;
176 app
->x
= (dock
->w
- app
->w
) / 2;
181 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
184 /* used for calculating offsets */
185 dock
->w
+= theme_bwidth
* 2;
186 dock
->h
+= theme_bwidth
* 2;
188 /* calculate position */
189 switch (config_dock_pos
) {
190 case DockPos_Floating
:
191 dock
->x
= config_dock_x
;
192 dock
->y
= config_dock_y
;
193 gravity
= NorthWestGravity
;
195 case DockPos_TopLeft
:
198 gravity
= NorthWestGravity
;
201 dock
->x
= screen_physical_size
.width
/ 2;
203 gravity
= NorthGravity
;
205 case DockPos_TopRight
:
206 dock
->x
= screen_physical_size
.width
;
208 gravity
= NorthEastGravity
;
212 dock
->y
= screen_physical_size
.height
/ 2;
213 gravity
= WestGravity
;
216 dock
->x
= screen_physical_size
.width
;
217 dock
->y
= screen_physical_size
.height
/ 2;
218 gravity
= EastGravity
;
220 case DockPos_BottomLeft
:
222 dock
->y
= screen_physical_size
.height
;
223 gravity
= SouthWestGravity
;
226 dock
->x
= screen_physical_size
.width
/ 2;
227 dock
->y
= screen_physical_size
.height
;
228 gravity
= SouthGravity
;
230 case DockPos_BottomRight
:
231 dock
->x
= screen_physical_size
.width
;
232 dock
->y
= screen_physical_size
.height
;
233 gravity
= SouthEastGravity
;
241 dock
->x
-= dock
->w
/ 2;
243 case NorthEastGravity
:
245 case SouthEastGravity
:
253 dock
->y
-= dock
->h
/ 2;
255 case SouthWestGravity
:
257 case SouthEastGravity
:
262 if (config_dock_hide
&& dock
->hidden
) {
263 switch (config_dock_pos
) {
264 case DockPos_Floating
:
266 case DockPos_TopLeft
:
267 if (config_dock_horz
)
268 dock
->y
-= dock
->h
- theme_bwidth
;
270 dock
->x
-= dock
->w
- theme_bwidth
;
273 dock
->y
-= dock
->h
- theme_bwidth
;
275 case DockPos_TopRight
:
276 if (config_dock_horz
)
277 dock
->y
-= dock
->h
- theme_bwidth
;
279 dock
->x
+= dock
->w
- theme_bwidth
;
282 dock
->x
-= dock
->w
- theme_bwidth
;
285 dock
->x
+= dock
->w
- theme_bwidth
;
287 case DockPos_BottomLeft
:
288 if (config_dock_horz
)
289 dock
->y
+= dock
->h
- theme_bwidth
;
291 dock
->x
-= dock
->w
- theme_bwidth
;
294 dock
->y
+= dock
->h
- theme_bwidth
;
296 case DockPos_BottomRight
:
297 if (config_dock_horz
)
298 dock
->y
+= dock
->h
- theme_bwidth
;
300 dock
->x
+= dock
->w
- theme_bwidth
;
306 switch (config_dock_pos
) {
307 case DockPos_Floating
:
308 STRUT_SET(dock_strut
, 0, 0, 0, 0);
310 case DockPos_TopLeft
:
311 if (config_dock_horz
)
312 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
314 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
317 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
319 case DockPos_TopRight
:
320 if (config_dock_horz
)
321 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
323 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
326 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
329 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
331 case DockPos_BottomLeft
:
332 if (config_dock_horz
)
333 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
335 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
338 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
340 case DockPos_BottomRight
:
341 if (config_dock_horz
)
342 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
344 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
348 /* not used for actually sizing shit */
349 dock
->w
-= theme_bwidth
* 2;
350 dock
->h
-= theme_bwidth
* 2;
352 if (dock
->w
> 0 && dock
->h
> 0) {
353 XMoveResizeWindow(ob_display
, dock
->frame
,
354 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
356 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
357 XMapWindow(ob_display
, dock
->frame
);
359 XUnmapWindow(ob_display
, dock
->frame
);
361 /* but they are useful outside of this function! */
362 dock
->w
+= theme_bwidth
* 2;
363 dock
->h
+= theme_bwidth
* 2;
365 screen_update_struts();
368 void dock_app_configure(DockApp
*app
, int w
, int h
)
375 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
377 DockApp
*over
= NULL
;
385 /* are we on top of the dock? */
386 if (!(x
>= dock
->x
&&
388 x
< dock
->x
+ dock
->w
&&
389 y
< dock
->y
+ dock
->h
))
395 /* which dock app are we on top of? */
396 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
398 if (config_dock_horz
) {
399 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
402 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
406 if (!it
|| app
== over
) return;
411 if (config_dock_horz
)
412 after
= (x
> over
->w
/ 2);
414 after
= (y
> over
->h
/ 2);
416 /* remove before doing the it->next! */
417 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
419 if (after
) it
= it
->next
;
421 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
425 static void hide_timeout(void *n
)
428 timer_stop(dock
->hide_timer
);
429 dock
->hide_timer
= NULL
;
436 void dock_hide(gboolean hide
)
438 if (dock
->hidden
== hide
|| !config_dock_hide
)
442 dock
->hidden
= FALSE
;
445 /* if was hiding, stop it */
446 if (dock
->hide_timer
) {
447 timer_stop(dock
->hide_timer
);
448 dock
->hide_timer
= NULL
;
451 g_assert(!dock
->hide_timer
);
452 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
453 (TimeoutHandler
)hide_timeout
,