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
,
37 RrColorPixel(ob_rr_theme
->b_color
));
38 XSetWindowBorderWidth(ob_display
, dock
->frame
, ob_rr_theme
->bwidth
);
40 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
41 stacking_add(DOCK_AS_WINDOW(dock
));
42 stacking_raise(DOCK_AS_WINDOW(dock
));
47 XDestroyWindow(ob_display
, dock
->frame
);
48 RrAppearanceFree(dock
->a_frame
);
49 g_hash_table_remove(window_map
, &dock
->frame
);
50 stacking_remove(dock
);
53 void dock_add(Window win
, XWMHints
*wmhints
)
56 XWindowAttributes attrib
;
59 app
= g_new0(ObDockApp
, 1);
60 app
->obwin
.type
= Window_DockApp
;
62 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
63 wmhints
->icon_window
: win
;
65 if (PROP_GETSS(app
->win
, wm_class
, locale
, &data
)) {
67 app
->name
= g_strdup(data
[0]);
69 app
->class = g_strdup(data
[1]);
74 if (app
->name
== NULL
) app
->name
= g_strdup("");
75 if (app
->class == NULL
) app
->class = g_strdup("");
77 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
78 app
->w
= attrib
.width
;
79 app
->h
= attrib
.height
;
84 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
87 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
89 This is the same case as in frame.c for client windows. When Openbox is
90 starting, the window is already mapped so we see unmap events occur for
91 it. There are 2 unmap events generated that we see, one with the 'event'
92 member set the root window, and one set to the client, but both get
93 handled and need to be ignored.
95 if (ob_state
== OB_STATE_STARTING
)
96 app
->ignore_unmaps
+= 2;
98 if (app
->win
!= app
->icon_win
) {
99 /* have to map it so that it can be re-managed on a restart */
100 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
101 XMapWindow(ob_display
, app
->win
);
103 XMapWindow(ob_display
, app
->icon_win
);
104 XSync(ob_display
, False
);
106 /* specify that if we exit, the window should not be destroyed and should
107 be reparented back to root automatically */
108 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
109 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
111 grab_button_full(2, 0, app
->icon_win
,
112 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
113 GrabModeAsync
, OB_CURSOR_MOVE
);
115 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
117 g_message("Managed Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
120 void dock_remove_all()
122 while (dock
->dock_apps
)
123 dock_remove(dock
->dock_apps
->data
, TRUE
);
126 void dock_remove(ObDockApp
*app
, gboolean reparent
)
128 ungrab_button(2, 0, app
->icon_win
);
129 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
130 /* remove the window from our save set */
131 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
132 XSync(ob_display
, False
);
134 g_hash_table_remove(window_map
, &app
->icon_win
);
137 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
139 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
142 g_message("Unmanaged Dock App: 0x%lx (%s)", app
->icon_win
, app
->class);
149 void dock_configure()
158 RrMinsize(dock
->a_frame
, &minw
, &minh
);
160 dock
->w
= dock
->h
= 0;
163 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
164 ObDockApp
*app
= it
->data
;
165 switch (config_dock_orient
) {
166 case OB_ORIENTATION_HORZ
:
168 dock
->h
= MAX(dock
->h
, app
->h
);
170 case OB_ORIENTATION_VERT
:
171 dock
->w
= MAX(dock
->w
, app
->w
);
177 spot
= (config_dock_orient
== OB_ORIENTATION_HORZ
? minw
: minh
) / 2;
179 /* position the apps */
180 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
181 ObDockApp
*app
= it
->data
;
182 switch (config_dock_orient
) {
183 case OB_ORIENTATION_HORZ
:
185 app
->y
= (dock
->h
- app
->h
) / 2;
188 case OB_ORIENTATION_VERT
:
189 app
->x
= (dock
->w
- app
->w
) / 2;
195 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
198 /* used for calculating offsets */
199 dock
->w
+= ob_rr_theme
->bwidth
* 2;
200 dock
->h
+= ob_rr_theme
->bwidth
* 2;
202 a
= screen_physical_area();
204 /* calculate position */
205 if (config_dock_floating
) {
206 dock
->x
= config_dock_x
;
207 dock
->y
= config_dock_y
;
208 gravity
= NorthWestGravity
;
210 switch (config_dock_pos
) {
211 case OB_DIRECTION_NORTHWEST
:
214 gravity
= NorthWestGravity
;
216 case OB_DIRECTION_NORTH
:
217 dock
->x
= a
->width
/ 2;
219 gravity
= NorthGravity
;
221 case OB_DIRECTION_NORTHEAST
:
224 gravity
= NorthEastGravity
;
226 case OB_DIRECTION_WEST
:
228 dock
->y
= a
->height
/ 2;
229 gravity
= WestGravity
;
231 case OB_DIRECTION_EAST
:
233 dock
->y
= a
->height
/ 2;
234 gravity
= EastGravity
;
236 case OB_DIRECTION_SOUTHWEST
:
239 gravity
= SouthWestGravity
;
241 case OB_DIRECTION_SOUTH
:
242 dock
->x
= a
->width
/ 2;
244 gravity
= SouthGravity
;
246 case OB_DIRECTION_SOUTHEAST
:
249 gravity
= SouthEastGravity
;
258 dock
->x
-= dock
->w
/ 2;
260 case NorthEastGravity
:
262 case SouthEastGravity
:
270 dock
->y
-= dock
->h
/ 2;
272 case SouthWestGravity
:
274 case SouthEastGravity
:
279 if (config_dock_hide
&& dock
->hidden
) {
280 if (!config_dock_floating
) {
281 switch (config_dock_pos
) {
282 case OB_DIRECTION_NORTHWEST
:
283 switch (config_dock_orient
) {
284 case OB_ORIENTATION_HORZ
:
285 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
287 case OB_ORIENTATION_VERT
:
288 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
292 case OB_DIRECTION_NORTH
:
293 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
295 case OB_DIRECTION_NORTHEAST
:
296 switch (config_dock_orient
) {
297 case OB_ORIENTATION_HORZ
:
298 dock
->y
-= dock
->h
- ob_rr_theme
->bwidth
;
300 case OB_ORIENTATION_VERT
:
301 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
305 case OB_DIRECTION_WEST
:
306 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
308 case OB_DIRECTION_EAST
:
309 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
311 case OB_DIRECTION_SOUTHWEST
:
312 switch (config_dock_orient
) {
313 case OB_ORIENTATION_HORZ
:
314 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
316 case OB_ORIENTATION_VERT
:
317 dock
->x
-= dock
->w
- ob_rr_theme
->bwidth
;
320 case OB_DIRECTION_SOUTH
:
321 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
323 case OB_DIRECTION_SOUTHEAST
:
324 switch (config_dock_orient
) {
325 case OB_ORIENTATION_HORZ
:
326 dock
->y
+= dock
->h
- ob_rr_theme
->bwidth
;
328 case OB_ORIENTATION_VERT
:
329 dock
->x
+= dock
->w
- ob_rr_theme
->bwidth
;
337 if (!config_dock_floating
&& config_dock_hide
) {
338 strw
= strh
= ob_rr_theme
->bwidth
;
345 if (config_dock_floating
) {
346 STRUT_SET(dock_strut
, 0, 0, 0, 0);
348 switch (config_dock_pos
) {
349 case OB_DIRECTION_NORTHWEST
:
350 switch (config_dock_orient
) {
351 case OB_ORIENTATION_HORZ
:
352 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
354 case OB_ORIENTATION_VERT
:
355 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
359 case OB_DIRECTION_NORTH
:
360 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
362 case OB_DIRECTION_NORTHEAST
:
363 switch (config_dock_orient
) {
364 case OB_ORIENTATION_HORZ
:
365 STRUT_SET(dock_strut
, 0, strh
, 0, 0);
367 case OB_ORIENTATION_VERT
:
368 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
372 case OB_DIRECTION_WEST
:
373 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
375 case OB_DIRECTION_EAST
:
376 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
378 case OB_DIRECTION_SOUTHWEST
:
379 switch (config_dock_orient
) {
380 case OB_ORIENTATION_HORZ
:
381 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
383 case OB_ORIENTATION_VERT
:
384 STRUT_SET(dock_strut
, strw
, 0, 0, 0);
388 case OB_DIRECTION_SOUTH
:
389 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
391 case OB_DIRECTION_SOUTHEAST
:
392 switch (config_dock_orient
) {
393 case OB_ORIENTATION_HORZ
:
394 STRUT_SET(dock_strut
, 0, 0, 0, strh
);
396 case OB_ORIENTATION_VERT
:
397 STRUT_SET(dock_strut
, 0, 0, strw
, 0);
407 /* not used for actually sizing shit */
408 dock
->w
-= ob_rr_theme
->bwidth
* 2;
409 dock
->h
-= ob_rr_theme
->bwidth
* 2;
411 if (dock
->w
> 0 && dock
->h
> 0) {
412 XMoveResizeWindow(ob_display
, dock
->frame
,
413 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
415 RrPaint(dock
->a_frame
, dock
->frame
, dock
->w
, dock
->h
);
416 XMapWindow(ob_display
, dock
->frame
);
418 XUnmapWindow(ob_display
, dock
->frame
);
420 /* but they are useful outside of this function! */
421 dock
->w
+= ob_rr_theme
->bwidth
* 2;
422 dock
->h
+= ob_rr_theme
->bwidth
* 2;
424 screen_update_areas();
427 void dock_app_configure(ObDockApp
*app
, gint w
, gint h
)
434 void dock_app_drag(ObDockApp
*app
, XMotionEvent
*e
)
436 ObDockApp
*over
= NULL
;
445 /* are we on top of the dock? */
446 if (!(x
>= dock
->x
&&
448 x
< dock
->x
+ dock
->w
&&
449 y
< dock
->y
+ dock
->h
))
455 /* which dock app are we on top of? */
457 for (it
= dock
->dock_apps
; it
&& !stop
; it
= it
->next
) {
459 switch (config_dock_orient
) {
460 case OB_ORIENTATION_HORZ
:
461 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
464 case OB_ORIENTATION_VERT
:
465 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
470 if (!it
|| app
== over
) return;
475 switch (config_dock_orient
) {
476 case OB_ORIENTATION_HORZ
:
477 after
= (x
> over
->w
/ 2);
479 case OB_ORIENTATION_VERT
:
480 after
= (y
> over
->h
/ 2);
484 /* remove before doing the it->next! */
485 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
487 if (after
) it
= it
->next
;
489 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
493 static void hide_timeout(void *n
)
496 timer_stop(dock
->hide_timer
);
497 dock
->hide_timer
= NULL
;
504 void dock_hide(gboolean hide
)
506 if (dock
->hidden
== hide
|| !config_dock_hide
)
510 dock
->hidden
= FALSE
;
513 /* if was hiding, stop it */
514 if (dock
->hide_timer
) {
515 timer_stop(dock
->hide_timer
);
516 dock
->hide_timer
= NULL
;
519 g_assert(!dock
->hide_timer
);
520 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
521 (ObTimeoutHandler
)hide_timeout
,