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 RECT_SET(dock
->a_frame
->area
, 0, 0, dock
->w
, dock
->h
);
353 XMoveResizeWindow(ob_display
, dock
->frame
,
354 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
356 paint(dock
->frame
, dock
->a_frame
);
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
,