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 render_depth
, InputOutput
, render_visual
,
32 CWOverrideRedirect
| CWEventMask
,
34 dock
->a_frame
= appearance_copy(theme_a_unfocused_title
);
35 XSetWindowBorder(ob_display
, dock
->frame
, theme_b_color
->pixel
);
36 XSetWindowBorderWidth(ob_display
, dock
->frame
, theme_bwidth
);
38 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
39 stacking_add(DOCK_AS_WINDOW(dock
));
40 stacking_raise(DOCK_AS_WINDOW(dock
));
45 XDestroyWindow(ob_display
, dock
->frame
);
46 appearance_free(dock
->a_frame
);
47 g_hash_table_remove(window_map
, &dock
->frame
);
48 stacking_remove(dock
);
51 void dock_add(Window win
, XWMHints
*wmhints
)
54 XWindowAttributes attrib
;
57 app
= g_new0(DockApp
, 1);
58 app
->obwin
.type
= Window_DockApp
;
60 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
61 wmhints
->icon_window
: win
;
63 if (PROP_GETSS(app
->win
, wm_class
, locale
, &data
)) {
65 app
->name
= g_strdup(data
[0]);
67 app
->class = g_strdup(data
[1]);
72 if (app
->name
== NULL
) app
->name
= g_strdup("");
73 if (app
->class == NULL
) app
->class = g_strdup("");
75 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
76 app
->w
= attrib
.width
;
77 app
->h
= attrib
.height
;
82 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
85 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
87 This is the same case as in frame.c for client windows. When Openbox is
88 starting, the window is already mapped so we see unmap events occur for
89 it. There are 2 unmap events generated that we see, one with the 'event'
90 member set the root window, and one set to the client, but both get
91 handled and need to be ignored.
93 if (ob_state
== State_Starting
)
94 app
->ignore_unmaps
+= 2;
96 if (app
->win
!= app
->icon_win
) {
97 /* have to map it so that it can be re-managed on a restart */
98 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
99 XMapWindow(ob_display
, app
->win
);
101 XMapWindow(ob_display
, app
->icon_win
);
102 XSync(ob_display
, False
);
104 /* specify that if we exit, the window should not be destroyed and should
105 be reparented back to root automatically */
106 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
107 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
109 grab_button_full(2, 0, app
->icon_win
,
110 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
111 GrabModeAsync
, ob_cursors
.move
);
113 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
115 g_message("Managed Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
118 void dock_remove_all()
120 while (dock
->dock_apps
)
121 dock_remove(dock
->dock_apps
->data
, TRUE
);
124 void dock_remove(DockApp
*app
, gboolean reparent
)
126 ungrab_button(2, 0, app
->icon_win
);
127 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
128 /* remove the window from our save set */
129 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
130 XSync(ob_display
, False
);
132 g_hash_table_remove(window_map
, &app
->icon_win
);
135 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
137 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
140 g_message("Unmanaged Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
147 void dock_configure()
153 dock
->w
= dock
->h
= spot
= 0;
155 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
156 struct DockApp
*app
= it
->data
;
157 if (config_dock_horz
) {
161 dock
->h
= MAX(dock
->h
, app
->h
);
166 dock
->w
= MAX(dock
->w
, app
->w
);
171 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
174 /* used for calculating offsets */
175 dock
->w
+= theme_bwidth
* 2;
176 dock
->h
+= theme_bwidth
* 2;
178 /* calculate position */
179 switch (config_dock_pos
) {
180 case DockPos_Floating
:
181 dock
->x
= config_dock_x
;
182 dock
->y
= config_dock_y
;
183 gravity
= NorthWestGravity
;
185 case DockPos_TopLeft
:
188 gravity
= NorthWestGravity
;
191 dock
->x
= screen_physical_size
.width
/ 2;
193 gravity
= NorthGravity
;
195 case DockPos_TopRight
:
196 dock
->x
= screen_physical_size
.width
;
198 gravity
= NorthEastGravity
;
202 dock
->y
= screen_physical_size
.height
/ 2;
203 gravity
= WestGravity
;
206 dock
->x
= screen_physical_size
.width
;
207 dock
->y
= screen_physical_size
.height
/ 2;
208 gravity
= EastGravity
;
210 case DockPos_BottomLeft
:
212 dock
->y
= screen_physical_size
.height
;
213 gravity
= SouthWestGravity
;
216 dock
->x
= screen_physical_size
.width
/ 2;
217 dock
->y
= screen_physical_size
.height
;
218 gravity
= SouthGravity
;
220 case DockPos_BottomRight
:
221 dock
->x
= screen_physical_size
.width
;
222 dock
->y
= screen_physical_size
.height
;
223 gravity
= SouthEastGravity
;
231 dock
->x
-= dock
->w
/ 2;
233 case NorthEastGravity
:
235 case SouthEastGravity
:
243 dock
->y
-= dock
->h
/ 2;
245 case SouthWestGravity
:
247 case SouthEastGravity
:
252 if (config_dock_hide
&& dock
->hidden
) {
253 switch (config_dock_pos
) {
254 case DockPos_Floating
:
256 case DockPos_TopLeft
:
257 if (config_dock_horz
)
258 dock
->y
-= dock
->h
- theme_bwidth
;
260 dock
->x
-= dock
->w
- theme_bwidth
;
263 dock
->y
-= dock
->h
- theme_bwidth
;
265 case DockPos_TopRight
:
266 if (config_dock_horz
)
267 dock
->y
-= dock
->h
- theme_bwidth
;
269 dock
->x
+= dock
->w
- theme_bwidth
;
272 dock
->x
-= dock
->w
- theme_bwidth
;
275 dock
->x
+= dock
->w
- theme_bwidth
;
277 case DockPos_BottomLeft
:
278 if (config_dock_horz
)
279 dock
->y
+= dock
->h
- theme_bwidth
;
281 dock
->x
-= dock
->w
- theme_bwidth
;
284 dock
->y
+= dock
->h
- theme_bwidth
;
286 case DockPos_BottomRight
:
287 if (config_dock_horz
)
288 dock
->y
+= dock
->h
- theme_bwidth
;
290 dock
->x
+= dock
->w
- theme_bwidth
;
296 switch (config_dock_pos
) {
297 case DockPos_Floating
:
298 STRUT_SET(dock_strut
, 0, 0, 0, 0);
300 case DockPos_TopLeft
:
301 if (config_dock_horz
)
302 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
304 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
307 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
309 case DockPos_TopRight
:
310 if (config_dock_horz
)
311 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
313 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
316 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
319 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
321 case DockPos_BottomLeft
:
322 if (config_dock_horz
)
323 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
325 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
328 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
330 case DockPos_BottomRight
:
331 if (config_dock_horz
)
332 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
334 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
338 /* not used for actually sizing shit */
339 dock
->w
-= theme_bwidth
* 2;
340 dock
->h
-= theme_bwidth
* 2;
342 if (dock
->w
> 0 && dock
->h
> 0) {
343 RECT_SET(dock
->a_frame
->area
, 0, 0, dock
->w
, dock
->h
);
344 XMoveResizeWindow(ob_display
, dock
->frame
,
345 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
347 paint(dock
->frame
, dock
->a_frame
);
348 XMapWindow(ob_display
, dock
->frame
);
350 XUnmapWindow(ob_display
, dock
->frame
);
352 /* but they are useful outside of this function! */
353 dock
->w
+= theme_bwidth
* 2;
354 dock
->h
+= theme_bwidth
* 2;
356 screen_update_struts();
359 void dock_app_configure(DockApp
*app
, int w
, int h
)
366 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
368 DockApp
*over
= NULL
;
376 /* are we on top of the dock? */
377 if (!(x
>= dock
->x
&&
379 x
< dock
->x
+ dock
->w
&&
380 y
< dock
->y
+ dock
->h
))
386 /* which dock app are we on top of? */
387 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
389 if (config_dock_horz
) {
390 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
393 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
397 if (!it
|| app
== over
) return;
402 if (config_dock_horz
)
403 after
= (x
> over
->w
/ 2);
405 after
= (y
> over
->h
/ 2);
407 /* remove before doing the it->next! */
408 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
410 if (after
) it
= it
->next
;
412 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
416 static void hide_timeout(void *n
)
419 timer_stop(dock
->hide_timer
);
420 dock
->hide_timer
= NULL
;
427 void dock_hide(gboolean hide
)
429 if (dock
->hidden
== hide
|| !config_dock_hide
)
433 dock
->hidden
= FALSE
;
436 /* if was hiding, stop it */
437 if (dock
->hide_timer
) {
438 timer_stop(dock
->hide_timer
);
439 dock
->hide_timer
= NULL
;
442 g_assert(!dock
->hide_timer
);
443 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
444 (TimeoutHandler
)hide_timeout
,