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;
156 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
157 struct DockApp
*app
= it
->data
;
158 if (config_dock_horz
) {
160 dock
->h
= MAX(dock
->h
, app
->h
);
162 dock
->w
= MAX(dock
->w
, app
->w
);
167 /* position the apps */
168 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
169 struct DockApp
*app
= it
->data
;
170 if (config_dock_horz
) {
172 app
->y
= (dock
->h
- app
->h
) / 2;
175 app
->x
= (dock
->w
- app
->w
) / 2;
180 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
183 /* used for calculating offsets */
184 dock
->w
+= theme_bwidth
* 2;
185 dock
->h
+= theme_bwidth
* 2;
187 /* calculate position */
188 switch (config_dock_pos
) {
189 case DockPos_Floating
:
190 dock
->x
= config_dock_x
;
191 dock
->y
= config_dock_y
;
192 gravity
= NorthWestGravity
;
194 case DockPos_TopLeft
:
197 gravity
= NorthWestGravity
;
200 dock
->x
= screen_physical_size
.width
/ 2;
202 gravity
= NorthGravity
;
204 case DockPos_TopRight
:
205 dock
->x
= screen_physical_size
.width
;
207 gravity
= NorthEastGravity
;
211 dock
->y
= screen_physical_size
.height
/ 2;
212 gravity
= WestGravity
;
215 dock
->x
= screen_physical_size
.width
;
216 dock
->y
= screen_physical_size
.height
/ 2;
217 gravity
= EastGravity
;
219 case DockPos_BottomLeft
:
221 dock
->y
= screen_physical_size
.height
;
222 gravity
= SouthWestGravity
;
225 dock
->x
= screen_physical_size
.width
/ 2;
226 dock
->y
= screen_physical_size
.height
;
227 gravity
= SouthGravity
;
229 case DockPos_BottomRight
:
230 dock
->x
= screen_physical_size
.width
;
231 dock
->y
= screen_physical_size
.height
;
232 gravity
= SouthEastGravity
;
240 dock
->x
-= dock
->w
/ 2;
242 case NorthEastGravity
:
244 case SouthEastGravity
:
252 dock
->y
-= dock
->h
/ 2;
254 case SouthWestGravity
:
256 case SouthEastGravity
:
261 if (config_dock_hide
&& dock
->hidden
) {
262 switch (config_dock_pos
) {
263 case DockPos_Floating
:
265 case DockPos_TopLeft
:
266 if (config_dock_horz
)
267 dock
->y
-= dock
->h
- theme_bwidth
;
269 dock
->x
-= dock
->w
- theme_bwidth
;
272 dock
->y
-= dock
->h
- theme_bwidth
;
274 case DockPos_TopRight
:
275 if (config_dock_horz
)
276 dock
->y
-= dock
->h
- theme_bwidth
;
278 dock
->x
+= dock
->w
- theme_bwidth
;
281 dock
->x
-= dock
->w
- theme_bwidth
;
284 dock
->x
+= dock
->w
- theme_bwidth
;
286 case DockPos_BottomLeft
:
287 if (config_dock_horz
)
288 dock
->y
+= dock
->h
- theme_bwidth
;
290 dock
->x
-= dock
->w
- theme_bwidth
;
293 dock
->y
+= dock
->h
- theme_bwidth
;
295 case DockPos_BottomRight
:
296 if (config_dock_horz
)
297 dock
->y
+= dock
->h
- theme_bwidth
;
299 dock
->x
+= dock
->w
- theme_bwidth
;
305 switch (config_dock_pos
) {
306 case DockPos_Floating
:
307 STRUT_SET(dock_strut
, 0, 0, 0, 0);
309 case DockPos_TopLeft
:
310 if (config_dock_horz
)
311 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
313 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
316 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
318 case DockPos_TopRight
:
319 if (config_dock_horz
)
320 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
322 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
325 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
328 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
330 case DockPos_BottomLeft
:
331 if (config_dock_horz
)
332 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
334 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
337 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
339 case DockPos_BottomRight
:
340 if (config_dock_horz
)
341 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
343 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
347 /* not used for actually sizing shit */
348 dock
->w
-= theme_bwidth
* 2;
349 dock
->h
-= theme_bwidth
* 2;
351 if (dock
->w
> 0 && dock
->h
> 0) {
352 XMoveResizeWindow(ob_display
, dock
->frame
,
353 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
355 paint(dock
->frame
, dock
->a_frame
, dock
->w
, dock
->h
);
356 XMapWindow(ob_display
, dock
->frame
);
358 XUnmapWindow(ob_display
, dock
->frame
);
360 /* but they are useful outside of this function! */
361 dock
->w
+= theme_bwidth
* 2;
362 dock
->h
+= theme_bwidth
* 2;
364 screen_update_struts();
367 void dock_app_configure(DockApp
*app
, int w
, int h
)
374 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
376 DockApp
*over
= NULL
;
384 /* are we on top of the dock? */
385 if (!(x
>= dock
->x
&&
387 x
< dock
->x
+ dock
->w
&&
388 y
< dock
->y
+ dock
->h
))
394 /* which dock app are we on top of? */
395 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
397 if (config_dock_horz
) {
398 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
401 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
405 if (!it
|| app
== over
) return;
410 if (config_dock_horz
)
411 after
= (x
> over
->w
/ 2);
413 after
= (y
> over
->h
/ 2);
415 /* remove before doing the it->next! */
416 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
418 if (after
) it
= it
->next
;
420 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
424 static void hide_timeout(void *n
)
427 timer_stop(dock
->hide_timer
);
428 dock
->hide_timer
= NULL
;
435 void dock_hide(gboolean hide
)
437 if (dock
->hidden
== hide
|| !config_dock_hide
)
441 dock
->hidden
= FALSE
;
444 /* if was hiding, stop it */
445 if (dock
->hide_timer
) {
446 timer_stop(dock
->hide_timer
);
447 dock
->hide_timer
= NULL
;
450 g_assert(!dock
->hide_timer
);
451 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
452 (TimeoutHandler
)hide_timeout
,