6 #include "render/theme.h"
8 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
9 EnterWindowMask | LeaveWindowMask)
10 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
16 XSetWindowAttributes attrib
;
19 dock
= g_new0(struct Dock
, 1);
20 dock
->obwin
.type
= Window_Dock
;
24 attrib
.event_mask
= DOCK_EVENT_MASK
;
25 attrib
.override_redirect
= True
;
26 dock
->frame
= XCreateWindow(ob_display
, ob_root
, 0, 0, 1, 1, 0,
27 render_depth
, InputOutput
, render_visual
,
28 CWOverrideRedirect
| CWEventMask
,
30 dock
->a_frame
= appearance_copy(theme_a_unfocused_title
);
31 XSetWindowBorder(ob_display
, dock
->frame
, theme_b_color
->pixel
);
32 XSetWindowBorderWidth(ob_display
, dock
->frame
, theme_bwidth
);
34 g_hash_table_insert(window_map
, &dock
->frame
, dock
);
35 stacking_add(DOCK_AS_WINDOW(&dock
[i
]));
36 stacking_raise(DOCK_AS_WINDOW(&dock
[i
]));
41 XDestroyWindow(ob_display
, dock
->frame
);
42 appearance_free(dock
->a_frame
);
43 g_hash_table_remove(window_map
, &dock
->frame
);
44 stacking_remove(dock
);
47 void dock_add(Window win
, XWMHints
*wmhints
)
50 XWindowAttributes attrib
;
52 app
= g_new0(DockApp
, 1);
54 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
55 wmhints
->icon_window
: win
;
57 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
58 app
->w
= attrib
.width
;
59 app
->h
= attrib
.height
;
64 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
67 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
69 This is the same case as in frame.c for client windows. When Openbox is
70 starting, the window is already mapped so we see unmap events occur for
71 it. There are 2 unmap events generated that we see, one with the 'event'
72 member set the root window, and one set to the client, but both get
73 handled and need to be ignored.
75 if (ob_state
== State_Starting
)
76 app
->ignore_unmaps
+= 2;
78 if (app
->win
!= app
->icon_win
) {
79 /* have to map it so that it can be re-managed on a restart */
80 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
81 XMapWindow(ob_display
, app
->win
);
83 XMapWindow(ob_display
, app
->icon_win
);
84 XSync(ob_display
, False
);
86 /* specify that if we exit, the window should not be destroyed and should
87 be reparented back to root automatically */
88 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
89 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
91 grab_button_full(2, 0, app
->icon_win
,
92 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
93 GrabModeAsync
, ob_cursors
.move
);
95 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
97 g_message("Managed Dock App: 0x%lx", app
->icon_win
);
100 void dock_remove_all()
102 while (dock
->dock_apps
)
103 dock_remove(dock
->dock_apps
->data
, TRUE
);
106 void dock_remove(DockApp
*app
, gboolean reparent
)
108 ungrab_button(2, 0, app
->icon_win
);
109 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
110 /* remove the window from our save set */
111 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
112 XSync(ob_display
, False
);
114 g_hash_table_remove(window_map
, &app
->icon_win
);
117 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
119 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
122 g_message("Unmanaged Dock App: 0x%lx", app
->icon_win
);
127 void dock_configure()
133 dock
->w
= dock
->h
= spot
= 0;
135 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
136 struct DockApp
*app
= it
->data
;
137 if (config_dock_horz
) {
141 dock
->h
= MAX(dock
->h
, app
->h
);
146 dock
->w
= MAX(dock
->w
, app
->w
);
151 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
154 /* used for calculating offsets */
155 dock
->w
+= theme_bwidth
* 2;
156 dock
->h
+= theme_bwidth
* 2;
158 /* calculate position */
159 switch (config_dock_pos
) {
160 case DockPos_Floating
:
161 dock
->x
= config_dock_x
;
162 dock
->y
= config_dock_y
;
163 gravity
= NorthWestGravity
;
165 case DockPos_TopLeft
:
168 gravity
= NorthWestGravity
;
171 dock
->x
= screen_physical_size
.width
/ 2;
173 gravity
= NorthGravity
;
175 case DockPos_TopRight
:
176 dock
->x
= screen_physical_size
.width
;
178 gravity
= NorthEastGravity
;
182 dock
->y
= screen_physical_size
.height
/ 2;
183 gravity
= WestGravity
;
186 dock
->x
= screen_physical_size
.width
;
187 dock
->y
= screen_physical_size
.height
/ 2;
188 gravity
= EastGravity
;
190 case DockPos_BottomLeft
:
192 dock
->y
= screen_physical_size
.height
;
193 gravity
= SouthWestGravity
;
196 dock
->x
= screen_physical_size
.width
/ 2;
197 dock
->y
= screen_physical_size
.height
;
198 gravity
= SouthGravity
;
200 case DockPos_BottomRight
:
201 dock
->x
= screen_physical_size
.width
;
202 dock
->y
= screen_physical_size
.height
;
203 gravity
= SouthEastGravity
;
211 dock
->x
-= dock
->w
/ 2;
213 case NorthEastGravity
:
215 case SouthEastGravity
:
223 dock
->y
-= dock
->h
/ 2;
225 case SouthWestGravity
:
227 case SouthEastGravity
:
232 if (config_dock_hide
&& dock
->hidden
) {
233 switch (config_dock_pos
) {
234 case DockPos_Floating
:
236 case DockPos_TopLeft
:
237 if (config_dock_horz
)
238 dock
->y
-= dock
->h
- theme_bwidth
;
240 dock
->x
-= dock
->w
- theme_bwidth
;
243 dock
->y
-= dock
->h
- theme_bwidth
;
245 case DockPos_TopRight
:
246 if (config_dock_horz
)
247 dock
->y
-= dock
->h
- theme_bwidth
;
249 dock
->x
+= dock
->w
- theme_bwidth
;
252 dock
->x
-= dock
->w
- theme_bwidth
;
255 dock
->x
+= dock
->w
- theme_bwidth
;
257 case DockPos_BottomLeft
:
258 if (config_dock_horz
)
259 dock
->y
+= dock
->h
- theme_bwidth
;
261 dock
->x
-= dock
->w
- theme_bwidth
;
264 dock
->y
+= dock
->h
- theme_bwidth
;
266 case DockPos_BottomRight
:
267 if (config_dock_horz
)
268 dock
->y
+= dock
->h
- theme_bwidth
;
270 dock
->x
+= dock
->w
- theme_bwidth
;
275 /* not used for actually sizing shit */
276 dock
->w
-= theme_bwidth
* 2;
277 dock
->h
-= theme_bwidth
* 2;
279 if (dock
->w
> 0 && dock
->h
> 0) {
280 RECT_SET(dock
->a_frame
->area
, 0, 0, dock
->w
, dock
->h
);
281 XMoveResizeWindow(ob_display
, dock
->frame
,
282 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
284 paint(dock
->frame
, dock
->a_frame
);
285 XMapWindow(ob_display
, dock
->frame
);
287 XUnmapWindow(ob_display
, dock
->frame
);
289 /* but they are useful outside of this function! */
290 dock
->w
+= theme_bwidth
* 2;
291 dock
->h
+= theme_bwidth
* 2;
294 void dock_app_configure(DockApp
*app
, int w
, int h
)
301 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
303 DockApp
*over
= NULL
;
311 /* are we on top of the dock? */
312 if (!(x
>= dock
->x
&&
314 x
< dock
->x
+ dock
->w
&&
315 y
< dock
->y
+ dock
->h
))
321 /* which dock app are we on top of? */
322 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
324 if (config_dock_horz
) {
325 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
328 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
332 if (!it
|| app
== over
) return;
337 if (config_dock_horz
)
338 after
= (x
> over
->w
/ 2);
340 after
= (y
> over
->h
/ 2);
342 /* remove before doing the it->next! */
343 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
345 if (after
) it
= it
->next
;
347 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
351 static void hide_timeout(void *n
)
354 timer_stop(dock
->hide_timer
);
355 dock
->hide_timer
= NULL
;
362 void dock_hide(gboolean hide
)
364 if (dock
->hidden
== hide
|| !config_dock_hide
)
368 dock
->hidden
= FALSE
;
371 /* if was hiding, stop it */
372 if (dock
->hide_timer
) {
373 timer_stop(dock
->hide_timer
);
374 dock
->hide_timer
= NULL
;
377 g_assert(!dock
->hide_timer
);
378 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
379 (TimeoutHandler
)hide_timeout
,