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);
53 app
->obwin
.type
= Window_DockApp
;
55 app
->icon_win
= (wmhints
->flags
& IconWindowHint
) ?
56 wmhints
->icon_window
: win
;
58 if (XGetWindowAttributes(ob_display
, app
->icon_win
, &attrib
)) {
59 app
->w
= attrib
.width
;
60 app
->h
= attrib
.height
;
65 dock
->dock_apps
= g_list_append(dock
->dock_apps
, app
);
68 XReparentWindow(ob_display
, app
->icon_win
, dock
->frame
, app
->x
, app
->y
);
70 This is the same case as in frame.c for client windows. When Openbox is
71 starting, the window is already mapped so we see unmap events occur for
72 it. There are 2 unmap events generated that we see, one with the 'event'
73 member set the root window, and one set to the client, but both get
74 handled and need to be ignored.
76 if (ob_state
== State_Starting
)
77 app
->ignore_unmaps
+= 2;
79 if (app
->win
!= app
->icon_win
) {
80 /* have to map it so that it can be re-managed on a restart */
81 XMoveWindow(ob_display
, app
->win
, -1000, -1000);
82 XMapWindow(ob_display
, app
->win
);
84 XMapWindow(ob_display
, app
->icon_win
);
85 XSync(ob_display
, False
);
87 /* specify that if we exit, the window should not be destroyed and should
88 be reparented back to root automatically */
89 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeInsert
);
90 XSelectInput(ob_display
, app
->icon_win
, DOCKAPP_EVENT_MASK
);
92 grab_button_full(2, 0, app
->icon_win
,
93 ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
,
94 GrabModeAsync
, ob_cursors
.move
);
96 g_hash_table_insert(window_map
, &app
->icon_win
, app
);
98 g_message("Managed Dock App: 0x%lx", app
->icon_win
);
101 void dock_remove_all()
103 while (dock
->dock_apps
)
104 dock_remove(dock
->dock_apps
->data
, TRUE
);
107 void dock_remove(DockApp
*app
, gboolean reparent
)
109 ungrab_button(2, 0, app
->icon_win
);
110 XSelectInput(ob_display
, app
->icon_win
, NoEventMask
);
111 /* remove the window from our save set */
112 XChangeSaveSet(ob_display
, app
->icon_win
, SetModeDelete
);
113 XSync(ob_display
, False
);
115 g_hash_table_remove(window_map
, &app
->icon_win
);
118 XReparentWindow(ob_display
, app
->icon_win
, ob_root
, app
->x
, app
->y
);
120 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
123 g_message("Unmanaged Dock App: 0x%lx", app
->icon_win
);
128 void dock_configure()
134 dock
->w
= dock
->h
= spot
= 0;
136 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
137 struct DockApp
*app
= it
->data
;
138 if (config_dock_horz
) {
142 dock
->h
= MAX(dock
->h
, app
->h
);
147 dock
->w
= MAX(dock
->w
, app
->w
);
152 XMoveWindow(ob_display
, app
->icon_win
, app
->x
, app
->y
);
155 /* used for calculating offsets */
156 dock
->w
+= theme_bwidth
* 2;
157 dock
->h
+= theme_bwidth
* 2;
159 /* calculate position */
160 switch (config_dock_pos
) {
161 case DockPos_Floating
:
162 dock
->x
= config_dock_x
;
163 dock
->y
= config_dock_y
;
164 gravity
= NorthWestGravity
;
166 case DockPos_TopLeft
:
169 gravity
= NorthWestGravity
;
172 dock
->x
= screen_physical_size
.width
/ 2;
174 gravity
= NorthGravity
;
176 case DockPos_TopRight
:
177 dock
->x
= screen_physical_size
.width
;
179 gravity
= NorthEastGravity
;
183 dock
->y
= screen_physical_size
.height
/ 2;
184 gravity
= WestGravity
;
187 dock
->x
= screen_physical_size
.width
;
188 dock
->y
= screen_physical_size
.height
/ 2;
189 gravity
= EastGravity
;
191 case DockPos_BottomLeft
:
193 dock
->y
= screen_physical_size
.height
;
194 gravity
= SouthWestGravity
;
197 dock
->x
= screen_physical_size
.width
/ 2;
198 dock
->y
= screen_physical_size
.height
;
199 gravity
= SouthGravity
;
201 case DockPos_BottomRight
:
202 dock
->x
= screen_physical_size
.width
;
203 dock
->y
= screen_physical_size
.height
;
204 gravity
= SouthEastGravity
;
212 dock
->x
-= dock
->w
/ 2;
214 case NorthEastGravity
:
216 case SouthEastGravity
:
224 dock
->y
-= dock
->h
/ 2;
226 case SouthWestGravity
:
228 case SouthEastGravity
:
233 if (config_dock_hide
&& dock
->hidden
) {
234 switch (config_dock_pos
) {
235 case DockPos_Floating
:
237 case DockPos_TopLeft
:
238 if (config_dock_horz
)
239 dock
->y
-= dock
->h
- theme_bwidth
;
241 dock
->x
-= dock
->w
- theme_bwidth
;
244 dock
->y
-= dock
->h
- theme_bwidth
;
246 case DockPos_TopRight
:
247 if (config_dock_horz
)
248 dock
->y
-= dock
->h
- theme_bwidth
;
250 dock
->x
+= dock
->w
- theme_bwidth
;
253 dock
->x
-= dock
->w
- theme_bwidth
;
256 dock
->x
+= dock
->w
- theme_bwidth
;
258 case DockPos_BottomLeft
:
259 if (config_dock_horz
)
260 dock
->y
+= dock
->h
- theme_bwidth
;
262 dock
->x
-= dock
->w
- theme_bwidth
;
265 dock
->y
+= dock
->h
- theme_bwidth
;
267 case DockPos_BottomRight
:
268 if (config_dock_horz
)
269 dock
->y
+= dock
->h
- theme_bwidth
;
271 dock
->x
+= dock
->w
- theme_bwidth
;
276 /* not used for actually sizing shit */
277 dock
->w
-= theme_bwidth
* 2;
278 dock
->h
-= theme_bwidth
* 2;
280 if (dock
->w
> 0 && dock
->h
> 0) {
281 RECT_SET(dock
->a_frame
->area
, 0, 0, dock
->w
, dock
->h
);
282 XMoveResizeWindow(ob_display
, dock
->frame
,
283 dock
->x
, dock
->y
, dock
->w
, dock
->h
);
285 paint(dock
->frame
, dock
->a_frame
);
286 XMapWindow(ob_display
, dock
->frame
);
288 XUnmapWindow(ob_display
, dock
->frame
);
290 /* but they are useful outside of this function! */
291 dock
->w
+= theme_bwidth
* 2;
292 dock
->h
+= theme_bwidth
* 2;
295 void dock_app_configure(DockApp
*app
, int w
, int h
)
302 void dock_app_drag(DockApp
*app
, XMotionEvent
*e
)
304 DockApp
*over
= NULL
;
312 /* are we on top of the dock? */
313 if (!(x
>= dock
->x
&&
315 x
< dock
->x
+ dock
->w
&&
316 y
< dock
->y
+ dock
->h
))
322 /* which dock app are we on top of? */
323 for (it
= dock
->dock_apps
; it
; it
= it
->next
) {
325 if (config_dock_horz
) {
326 if (x
>= over
->x
&& x
< over
->x
+ over
->w
)
329 if (y
>= over
->y
&& y
< over
->y
+ over
->h
)
333 if (!it
|| app
== over
) return;
338 if (config_dock_horz
)
339 after
= (x
> over
->w
/ 2);
341 after
= (y
> over
->h
/ 2);
343 /* remove before doing the it->next! */
344 dock
->dock_apps
= g_list_remove(dock
->dock_apps
, app
);
346 if (after
) it
= it
->next
;
348 dock
->dock_apps
= g_list_insert_before(dock
->dock_apps
, it
, app
);
352 static void hide_timeout(void *n
)
355 timer_stop(dock
->hide_timer
);
356 dock
->hide_timer
= NULL
;
363 void dock_hide(gboolean hide
)
365 if (dock
->hidden
== hide
|| !config_dock_hide
)
369 dock
->hidden
= FALSE
;
372 /* if was hiding, stop it */
373 if (dock
->hide_timer
) {
374 timer_stop(dock
->hide_timer
);
375 dock
->hide_timer
= NULL
;
378 g_assert(!dock
->hide_timer
);
379 dock
->hide_timer
= timer_start(config_dock_hide_timeout
* 1000,
380 (TimeoutHandler
)hide_timeout
,