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(ObDock
, 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(ObDockApp
, 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
== OB_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_CURSOR_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(ObDockApp
*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()
157 RrMinsize(dock
->a_frame
, &minw
, &minh
);
159 dock
->w
= dock
->h
= 0;
162 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
163 ObDockApp
*app
= it
->data
;
164 if (config_dock_horz
) {
166 dock
->h
= MAX(dock
->h
, app
->h
);
168 dock
->w
= MAX(dock
->w
, app
->w
);
173 spot
= (config_dock_horz
? minw
: minh
) / 2;
175 /* position the apps */
176 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
177 ObDockApp
*app
= it
->data
;
178 if (config_dock_horz
) {
180 app
->y
= (dock
->h
- app
->h
) / 2;
183 app
->x
= (dock
->w
- app
->w
) / 2;
188 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
191 /* used for calculating offsets */
192 dock
->w
+= ob_rr_theme
->bwidth
* 2;
193 dock
->h
+= ob_rr_theme
->bwidth
* 2;
195 a
= screen_physical_area();
197 /* calculate position */
198 if (config_dock_floating
) {
199 dock
->x
= config_dock_x
;
200 dock
->y
= config_dock_y
;
201 gravity
= NorthWestGravity
;
203 switch (config_dock_pos
) {
204 case OB_DIRECTION_NORTHWEST
:
207 gravity
= NorthWestGravity
;
209 case OB_DIRECTION_NORTH
:
210 dock
->x
= a
->width
/ 2;
212 gravity
= NorthGravity
;
214 case OB_DIRECTION_NORTHEAST
:
217 gravity
= NorthEastGravity
;
219 case OB_DIRECTION_WEST
:
221 dock
->y
= a
->height
/ 2;
222 gravity
= WestGravity
;
224 case OB_DIRECTION_EAST
:
226 dock
->y
= a
->height
/ 2;
227 gravity
= EastGravity
;
229 case OB_DIRECTION_SOUTHWEST
:
232 gravity
= SouthWestGravity
;
234 case OB_DIRECTION_SOUTH
:
235 dock
->x
= a
->width
/ 2;
237 gravity
= SouthGravity
;
239 case OB_DIRECTION_SOUTHEAST
:
242 gravity
= SouthEastGravity
;
251 dock
->x
-= dock
->w
/ 2;
253 case NorthEastGravity
:
255 case SouthEastGravity
:
263 dock
->y
-= dock
->h
/ 2;
265 case SouthWestGravity
:
267 case SouthEastGravity
:
272 if (config_dock_hide
&& dock
->hidden
) {
273 if (!config_dock_floating
) {
274 switch (config_dock_pos
) {
275 case OB_DIRECTION_NORTHWEST
:
276 if (config_dock_horz
)
277 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
279 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
281 case OB_DIRECTION_NORTH
:
282 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
284 case OB_DIRECTION_NORTHEAST
:
285 if (config_dock_horz
)
286 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
288 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
290 case OB_DIRECTION_WEST
:
291 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
293 case OB_DIRECTION_EAST
:
294 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
296 case OB_DIRECTION_SOUTHWEST
:
297 if (config_dock_horz
)
298 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
300 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
302 case OB_DIRECTION_SOUTH
:
303 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
305 case OB_DIRECTION_SOUTHEAST
:
306 if (config_dock_horz
)
307 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
309 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
315 if (!config_dock_floating
&& config_dock_hide
) {
316 strw
= strh
= ob_rr_theme
->bwidth
;
323 if (config_dock_floating
) {
324 STRUT_SET(dock_strut
, 0, 0, 0, 0);
326 switch (config_dock_pos
) {
327 case OB_DIRECTION_NORTHWEST
:
328 if (config_dock_horz
)
329 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
331 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
333 case OB_DIRECTION_NORTH
:
334 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
336 case OB_DIRECTION_NORTHEAST
:
337 if (config_dock_horz
)
338 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
340 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
342 case OB_DIRECTION_WEST
:
343 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
345 case OB_DIRECTION_EAST
:
346 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
348 case OB_DIRECTION_SOUTHWEST
:
349 if (config_dock_horz
)
350 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
352 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
354 case OB_DIRECTION_SOUTH
:
355 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
357 case OB_DIRECTION_SOUTHEAST
:
358 if (config_dock_horz
)
359 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
361 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
369 /* not used for actually sizing shit */
370 dock
->w
-= ob_rr_theme
->bwidth
* 2;
371 dock
->h
-= ob_rr_theme
->bwidth
* 2;
373 if (dock
->w
> 0 && dock
->h
> 0) {
374 XMoveResizeWindow(ob_display
, dock
->frame
,
375 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
377 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
378 XMapWindow(ob_display
, dock
->frame
);
380 XUnmapWindow(ob_display
, dock
->frame
);
382 /* but they are useful outside of this function! */
383 dock
->w
+= ob_rr_theme
->bwidth
* 2;
384 dock
->h
+= ob_rr_theme
->bwidth
* 2;
386 screen_update_areas();
389 void dock_app_configure(ObDockApp
*app
, gint w
, gint h
)
396 void dock_app_drag(ObDockApp
*app
, XMotionEvent
*e
)
398 ObDockApp
*over
= NULL
;
406 /* are we on top of the dock? */
407 if (!(x
>= dock
->x
&&
409 x
< dock
->x
+ dock
->w
&&
410 y
< dock
->y
+ dock
->h
))
416 /* which dock app are we on top of? */
417 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
419 if (config_dock_horz
) {
420 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
423 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
427 if (!it
|| app
== over
) return;
432 if (config_dock_horz
)
433 after
= (x
> over
->w
/ 2);
435 after
= (y
> over
->h
/ 2);
437 /* remove before doing the it->next! */
438 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
440 if (after
) it
= it
->next
;
442 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
446 static void hide_timeout(void *n
)
449 timer_stop(dock
->hide_timer
);
450 dock
->hide_timer
= NULL
;
457 void dock_hide(gboolean hide
)
459 if (dock
->hidden
== hide
|| !config_dock_hide
)
463 dock
->hidden
= FALSE
;
466 /* if was hiding, stop it */
467 if (dock
->hide_timer
) {
468 timer_stop(dock
->hide_timer
);
469 dock
->hide_timer
= NULL
;
472 g_assert(!dock
->hide_timer
);
473 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
474 (TimeoutHandler
)hide_timeout
,