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
, RootWindow(ob_display
, ob_screen
),
32 RrDepth(ob_rr_inst
), InputOutput
,
34 CWOverrideRedirect
| CWEventMask
,
36 dock
->a_frame
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
37 XSetWindowBorder(ob_display
, dock
->frame
,
38 RrColorPixel(ob_rr_theme
->b_color
));
39 XSetWindowBorderWidth(ob_display
, dock
->frame
, ob_rr_theme
->bwidth
);
41 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
42 stacking_add(DOCK_AS_WINDOW(dock
));
43 stacking_raise(DOCK_AS_WINDOW(dock
));
48 XDestroyWindow(ob_display
, dock
->frame
);
49 RrAppearanceFree(dock
->a_frame
);
50 g_hash_table_remove(window_map
, &dock
->frame
);
51 stacking_remove(dock
);
54 void dock_add(Window win
, XWMHints
*wmhints
)
57 XWindowAttributes attrib
;
60 app
= g_new0(ObDockApp
, 1);
61 app
->obwin
.type
= Window_DockApp
;
63 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
64 wmhints
->icon_window
: win
;
66 if (PROP_GETSS(app
->win
, wm_class
, locale
, &data
)) {
68 app
->name
= g_strdup(data
[0]);
70 app
->class = g_strdup(data
[1]);
75 if (app
->name
== NULL
) app
->name
= g_strdup("");
76 if (app
->class == NULL
) app
->class = g_strdup("");
78 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
79 app
->w
= attrib
.width
;
80 app
->h
= attrib
.height
;
85 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
88 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
90 This is the same case as in frame.c for client windows. When Openbox is
91 starting, the window is already mapped so we see unmap events occur for
92 it. There are 2 unmap events generated that we see, one with the 'event'
93 member set the root window, and one set to the client, but both get
94 handled and need to be ignored.
96 if (ob_state() == OB_STATE_STARTING
)
97 app
->ignore_unmaps
+= 2;
99 if (app
->win
!= app
->icon_win
) {
100 /* have to map it so that it can be re-managed on a restart */
101 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
102 XMapWindow(ob_display
, app
->win
);
104 XMapWindow(ob_display
, app
->icon_win
);
105 XSync(ob_display
, False
);
107 /* specify that if we exit, the window should not be destroyed and should
108 be reparented back to root automatically */
109 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
110 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
112 grab_button_full(2, 0, app
->icon_win
,
113 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
114 GrabModeAsync
, OB_CURSOR_MOVE
);
116 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
118 g_message("Managed Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
121 void dock_remove_all()
123 while (dock
->dock_apps
)
124 dock_remove(dock
->dock_apps
->data
, TRUE
);
127 void dock_remove(ObDockApp
*app
, gboolean reparent
)
129 ungrab_button(2, 0, app
->icon_win
);
130 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
131 /* remove the window from our save set */
132 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
133 XSync(ob_display
, False
);
135 g_hash_table_remove(window_map
, &app
->icon_win
);
138 XReparentWindow(ob_display
, app
->icon_win
,
139 RootWindow(ob_display
, ob_screen
), app
->x
, app
->y
);
141 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
144 g_message("Unmanaged Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
151 void dock_configure()
160 RrMinsize(dock
->a_frame
, &minw
, &minh
);
162 dock
->w
= dock
->h
= 0;
165 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
166 ObDockApp
*app
= it
->data
;
167 switch (config_dock_orient
) {
168 case OB_ORIENTATION_HORZ
:
170 dock
->h
= MAX(dock
->h
, app
->h
);
172 case OB_ORIENTATION_VERT
:
173 dock
->w
= MAX(dock
->w
, app
->w
);
179 spot
= (config_dock_orient
== OB_ORIENTATION_HORZ
? minw
: minh
) / 2;
181 /* position the apps */
182 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
183 ObDockApp
*app
= it
->data
;
184 switch (config_dock_orient
) {
185 case OB_ORIENTATION_HORZ
:
187 app
->y
= (dock
->h
- app
->h
) / 2;
190 case OB_ORIENTATION_VERT
:
191 app
->x
= (dock
->w
- app
->w
) / 2;
197 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
200 /* used for calculating offsets */
201 dock
->w
+= ob_rr_theme
->bwidth
* 2;
202 dock
->h
+= ob_rr_theme
->bwidth
* 2;
204 a
= screen_physical_area();
206 /* calculate position */
207 if (config_dock_floating
) {
208 dock
->x
= config_dock_x
;
209 dock
->y
= config_dock_y
;
210 gravity
= NorthWestGravity
;
212 switch (config_dock_pos
) {
213 case OB_DIRECTION_NORTHWEST
:
216 gravity
= NorthWestGravity
;
218 case OB_DIRECTION_NORTH
:
219 dock
->x
= a
->width
/ 2;
221 gravity
= NorthGravity
;
223 case OB_DIRECTION_NORTHEAST
:
226 gravity
= NorthEastGravity
;
228 case OB_DIRECTION_WEST
:
230 dock
->y
= a
->height
/ 2;
231 gravity
= WestGravity
;
233 case OB_DIRECTION_EAST
:
235 dock
->y
= a
->height
/ 2;
236 gravity
= EastGravity
;
238 case OB_DIRECTION_SOUTHWEST
:
241 gravity
= SouthWestGravity
;
243 case OB_DIRECTION_SOUTH
:
244 dock
->x
= a
->width
/ 2;
246 gravity
= SouthGravity
;
248 case OB_DIRECTION_SOUTHEAST
:
251 gravity
= SouthEastGravity
;
260 dock
->x
-= dock
->w
/ 2;
262 case NorthEastGravity
:
264 case SouthEastGravity
:
272 dock
->y
-= dock
->h
/ 2;
274 case SouthWestGravity
:
276 case SouthEastGravity
:
281 if (config_dock_hide
&& dock
->hidden
) {
282 if (!config_dock_floating
) {
283 switch (config_dock_pos
) {
284 case OB_DIRECTION_NORTHWEST
:
285 switch (config_dock_orient
) {
286 case OB_ORIENTATION_HORZ
:
287 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
289 case OB_ORIENTATION_VERT
:
290 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
294 case OB_DIRECTION_NORTH
:
295 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
297 case OB_DIRECTION_NORTHEAST
:
298 switch (config_dock_orient
) {
299 case OB_ORIENTATION_HORZ
:
300 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
302 case OB_ORIENTATION_VERT
:
303 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
307 case OB_DIRECTION_WEST
:
308 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
310 case OB_DIRECTION_EAST
:
311 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
313 case OB_DIRECTION_SOUTHWEST
:
314 switch (config_dock_orient
) {
315 case OB_ORIENTATION_HORZ
:
316 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
318 case OB_ORIENTATION_VERT
:
319 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
322 case OB_DIRECTION_SOUTH
:
323 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
325 case OB_DIRECTION_SOUTHEAST
:
326 switch (config_dock_orient
) {
327 case OB_ORIENTATION_HORZ
:
328 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
330 case OB_ORIENTATION_VERT
:
331 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
339 if (!config_dock_floating
&& config_dock_hide
) {
340 strw
= strh
= ob_rr_theme
->bwidth
;
347 if (config_dock_floating
) {
348 STRUT_SET(dock_strut
, 0, 0, 0, 0);
350 switch (config_dock_pos
) {
351 case OB_DIRECTION_NORTHWEST
:
352 switch (config_dock_orient
) {
353 case OB_ORIENTATION_HORZ
:
354 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
356 case OB_ORIENTATION_VERT
:
357 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
361 case OB_DIRECTION_NORTH
:
362 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
364 case OB_DIRECTION_NORTHEAST
:
365 switch (config_dock_orient
) {
366 case OB_ORIENTATION_HORZ
:
367 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
369 case OB_ORIENTATION_VERT
:
370 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
374 case OB_DIRECTION_WEST
:
375 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
377 case OB_DIRECTION_EAST
:
378 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
380 case OB_DIRECTION_SOUTHWEST
:
381 switch (config_dock_orient
) {
382 case OB_ORIENTATION_HORZ
:
383 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
385 case OB_ORIENTATION_VERT
:
386 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
390 case OB_DIRECTION_SOUTH
:
391 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
393 case OB_DIRECTION_SOUTHEAST
:
394 switch (config_dock_orient
) {
395 case OB_ORIENTATION_HORZ
:
396 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
398 case OB_ORIENTATION_VERT
:
399 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
409 /* not used for actually sizing shit */
410 dock
->w
-= ob_rr_theme
->bwidth
* 2;
411 dock
->h
-= ob_rr_theme
->bwidth
* 2;
413 if (dock
->w
> 0 && dock
->h
> 0) {
414 XMoveResizeWindow(ob_display
, dock
->frame
,
415 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
417 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
418 XMapWindow(ob_display
, dock
->frame
);
420 XUnmapWindow(ob_display
, dock
->frame
);
422 /* but they are useful outside of this function! */
423 dock
->w
+= ob_rr_theme
->bwidth
* 2;
424 dock
->h
+= ob_rr_theme
->bwidth
* 2;
426 screen_update_areas();
429 void dock_app_configure(ObDockApp
*app
, gint w
, gint h
)
436 void dock_app_drag(ObDockApp
*app
, XMotionEvent
*e
)
438 ObDockApp
*over
= NULL
;
447 /* are we on top of the dock? */
448 if (!(x
>= dock
->x
&&
450 x
< dock
->x
+ dock
->w
&&
451 y
< dock
->y
+ dock
->h
))
457 /* which dock app are we on top of? */
459 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
461 switch (config_dock_orient
) {
462 case OB_ORIENTATION_HORZ
:
463 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
466 case OB_ORIENTATION_VERT
:
467 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
471 /* dont go to it->next! */
474 if (!it
|| app
== over
) return;
479 switch (config_dock_orient
) {
480 case OB_ORIENTATION_HORZ
:
481 after
= (x
> over
->w
/ 2);
483 case OB_ORIENTATION_VERT
:
484 after
= (y
> over
->h
/ 2);
488 /* remove before doing the it->next! */
489 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
491 if (after
) it
= it
->next
;
493 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
497 static void hide_timeout(void *n
)
500 timer_stop(dock
->hide_timer
);
501 dock
->hide_timer
= NULL
;
508 void dock_hide(gboolean hide
)
510 if (dock
->hidden
== hide
|| !config_dock_hide
)
514 dock
->hidden
= FALSE
;
517 /* if was hiding, stop it */
518 if (dock
->hide_timer
) {
519 timer_stop(dock
->hide_timer
);
520 dock
->hide_timer
= NULL
;
523 g_assert(!dock
->hide_timer
);
524 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
525 (ObTimeoutHandler
)hide_timeout
,