6 #include "render/theme.h"
8 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
9 EnterWindowMask | LeaveWindowMask)
10 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
18 XSetWindowAttributes attrib
;
20 STRUT_SET(dock_strut
, 0, 0, 0, 0);
22 dock
= g_new0(struct Dock
, 1);
23 dock
->obwin
.type
= Window_Dock
;
27 attrib
.event_mask
= DOCK_EVENT_MASK
;
28 attrib
.override_redirect
= True
;
29 dock
->frame
= XCreateWindow(ob_display
, ob_root
, 0, 0, 1, 1, 0,
30 render_depth
, InputOutput
, render_visual
,
31 CWOverrideRedirect
| CWEventMask
,
33 dock
->a_frame
= appearance_copy(theme_a_unfocused_title
);
34 XSetWindowBorder(ob_display
, dock
->frame
, theme_b_color
->pixel
);
35 XSetWindowBorderWidth(ob_display
, dock
->frame
, theme_bwidth
);
37 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
38 stacking_add(DOCK_AS_WINDOW(dock
));
39 stacking_raise(DOCK_AS_WINDOW(dock
));
44 XDestroyWindow(ob_display
, dock
->frame
);
45 appearance_free(dock
->a_frame
);
46 g_hash_table_remove(window_map
, &dock
->frame
);
47 stacking_remove(dock
);
50 void dock_add(Window win
, XWMHints
*wmhints
)
53 XWindowAttributes attrib
;
55 app
= g_new0(DockApp
, 1);
56 app
->obwin
.type
= Window_DockApp
;
58 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
59 wmhints
->icon_window
: win
;
61 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
62 app
->w
= attrib
.width
;
63 app
->h
= attrib
.height
;
68 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
71 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
73 This is the same case as in frame.c for client windows. When Openbox is
74 starting, the window is already mapped so we see unmap events occur for
75 it. There are 2 unmap events generated that we see, one with the 'event'
76 member set the root window, and one set to the client, but both get
77 handled and need to be ignored.
79 if (ob_state
== State_Starting
)
80 app
->ignore_unmaps
+= 2;
82 if (app
->win
!= app
->icon_win
) {
83 /* have to map it so that it can be re-managed on a restart */
84 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
85 XMapWindow(ob_display
, app
->win
);
87 XMapWindow(ob_display
, app
->icon_win
);
88 XSync(ob_display
, False
);
90 /* specify that if we exit, the window should not be destroyed and should
91 be reparented back to root automatically */
92 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
93 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
95 grab_button_full(2, 0, app
->icon_win
,
96 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
97 GrabModeAsync
, ob_cursors
.move
);
99 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
101 g_message("Managed Dock App: 0x%lx", app
->icon_win
);
104 void dock_remove_all()
106 while (dock
->dock_apps
)
107 dock_remove(dock
->dock_apps
->data
, TRUE
);
110 void dock_remove(DockApp
*app
, gboolean reparent
)
112 ungrab_button(2, 0, app
->icon_win
);
113 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
114 /* remove the window from our save set */
115 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
116 XSync(ob_display
, False
);
118 g_hash_table_remove(window_map
, &app
->icon_win
);
121 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
123 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
126 g_message("Unmanaged Dock App: 0x%lx", app
->icon_win
);
131 void dock_configure()
137 dock
->w
= dock
->h
= spot
= 0;
139 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
140 struct DockApp
*app
= it
->data
;
141 if (config_dock_horz
) {
145 dock
->h
= MAX(dock
->h
, app
->h
);
150 dock
->w
= MAX(dock
->w
, app
->w
);
155 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
158 /* used for calculating offsets */
159 dock
->w
+= theme_bwidth
* 2;
160 dock
->h
+= theme_bwidth
* 2;
162 /* calculate position */
163 switch (config_dock_pos
) {
164 case DockPos_Floating
:
165 dock
->x
= config_dock_x
;
166 dock
->y
= config_dock_y
;
167 gravity
= NorthWestGravity
;
169 case DockPos_TopLeft
:
172 gravity
= NorthWestGravity
;
175 dock
->x
= screen_physical_size
.width
/ 2;
177 gravity
= NorthGravity
;
179 case DockPos_TopRight
:
180 dock
->x
= screen_physical_size
.width
;
182 gravity
= NorthEastGravity
;
186 dock
->y
= screen_physical_size
.height
/ 2;
187 gravity
= WestGravity
;
190 dock
->x
= screen_physical_size
.width
;
191 dock
->y
= screen_physical_size
.height
/ 2;
192 gravity
= EastGravity
;
194 case DockPos_BottomLeft
:
196 dock
->y
= screen_physical_size
.height
;
197 gravity
= SouthWestGravity
;
200 dock
->x
= screen_physical_size
.width
/ 2;
201 dock
->y
= screen_physical_size
.height
;
202 gravity
= SouthGravity
;
204 case DockPos_BottomRight
:
205 dock
->x
= screen_physical_size
.width
;
206 dock
->y
= screen_physical_size
.height
;
207 gravity
= SouthEastGravity
;
215 dock
->x
-= dock
->w
/ 2;
217 case NorthEastGravity
:
219 case SouthEastGravity
:
227 dock
->y
-= dock
->h
/ 2;
229 case SouthWestGravity
:
231 case SouthEastGravity
:
236 if (config_dock_hide
&& dock
->hidden
) {
237 switch (config_dock_pos
) {
238 case DockPos_Floating
:
240 case DockPos_TopLeft
:
241 if (config_dock_horz
)
242 dock
->y
-= dock
->h
- theme_bwidth
;
244 dock
->x
-= dock
->w
- theme_bwidth
;
247 dock
->y
-= dock
->h
- theme_bwidth
;
249 case DockPos_TopRight
:
250 if (config_dock_horz
)
251 dock
->y
-= dock
->h
- theme_bwidth
;
253 dock
->x
+= dock
->w
- theme_bwidth
;
256 dock
->x
-= dock
->w
- theme_bwidth
;
259 dock
->x
+= dock
->w
- theme_bwidth
;
261 case DockPos_BottomLeft
:
262 if (config_dock_horz
)
263 dock
->y
+= dock
->h
- theme_bwidth
;
265 dock
->x
-= dock
->w
- theme_bwidth
;
268 dock
->y
+= dock
->h
- theme_bwidth
;
270 case DockPos_BottomRight
:
271 if (config_dock_horz
)
272 dock
->y
+= dock
->h
- theme_bwidth
;
274 dock
->x
+= dock
->w
- theme_bwidth
;
280 switch (config_dock_pos
) {
281 case DockPos_Floating
:
282 STRUT_SET(dock_strut
, 0, 0, 0, 0);
284 case DockPos_TopLeft
:
285 if (config_dock_horz
)
286 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
288 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
291 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
293 case DockPos_TopRight
:
294 if (config_dock_horz
)
295 STRUT_SET(dock_strut
, 0, dock
->h
, 0, 0);
297 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
300 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
303 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
305 case DockPos_BottomLeft
:
306 if (config_dock_horz
)
307 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
309 STRUT_SET(dock_strut
, dock
->w
, 0, 0, 0);
312 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
314 case DockPos_BottomRight
:
315 if (config_dock_horz
)
316 STRUT_SET(dock_strut
, 0, 0, 0, dock
->h
);
318 STRUT_SET(dock_strut
, 0, 0, dock
->w
, 0);
322 /* not used for actually sizing shit */
323 dock
->w
-= theme_bwidth
* 2;
324 dock
->h
-= theme_bwidth
* 2;
326 if (dock
->w
> 0 && dock
->h
> 0) {
327 RECT_SET(dock
->a_frame
->area
, 0, 0, dock
->w
, dock
->h
);
328 XMoveResizeWindow(ob_display
, dock
->frame
,
329 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
331 paint(dock
->frame
, dock
->a_frame
);
332 XMapWindow(ob_display
, dock
->frame
);
334 XUnmapWindow(ob_display
, dock
->frame
);
336 /* but they are useful outside of this function! */
337 dock
->w
+= theme_bwidth
* 2;
338 dock
->h
+= theme_bwidth
* 2;
340 screen_update_struts();
343 void dock_app_configure(DockApp
*app
, int w
, int h
)
350 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
352 DockApp
*over
= NULL
;
360 /* are we on top of the dock? */
361 if (!(x
>= dock
->x
&&
363 x
< dock
->x
+ dock
->w
&&
364 y
< dock
->y
+ dock
->h
))
370 /* which dock app are we on top of? */
371 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
373 if (config_dock_horz
) {
374 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
377 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
381 if (!it
|| app
== over
) return;
386 if (config_dock_horz
)
387 after
= (x
> over
->w
/ 2);
389 after
= (y
> over
->h
/ 2);
391 /* remove before doing the it->next! */
392 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
394 if (after
) it
= it
->next
;
396 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
400 static void hide_timeout(void *n
)
403 timer_stop(dock
->hide_timer
);
404 dock
->hide_timer
= NULL
;
411 void dock_hide(gboolean hide
)
413 if (dock
->hidden
== hide
|| !config_dock_hide
)
417 dock
->hidden
= FALSE
;
420 /* if was hiding, stop it */
421 if (dock
->hide_timer
) {
422 timer_stop(dock
->hide_timer
);
423 dock
->hide_timer
= NULL
;
426 g_assert(!dock
->hide_timer
);
427 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
428 (TimeoutHandler
)hide_timeout
,