6 #include "render/theme.h"
8 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
9 EnterWindowMask | LeaveWindowMask)
10 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
18 XSetWindowAttributes attrib;
21 STRUT_SET(dock_strut, 0, 0, 0, 0);
23 dock = g_new0(struct Dock, 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 render_depth, InputOutput, render_visual,
32 CWOverrideRedirect | CWEventMask,
34 dock->a_frame = appearance_copy(theme_a_unfocused_title);
35 XSetWindowBorder(ob_display, dock->frame, theme_b_color->pixel);
36 XSetWindowBorderWidth(ob_display, dock->frame, theme_bwidth);
38 g_hash_table_insert(window_map, &dock->frame, dock);
39 stacking_add(DOCK_AS_WINDOW(&dock[i]));
40 stacking_raise(DOCK_AS_WINDOW(&dock[i]));
45 XDestroyWindow(ob_display, dock->frame);
46 appearance_free(dock->a_frame);
47 g_hash_table_remove(window_map, &dock->frame);
48 stacking_remove(dock);
51 void dock_add(Window win, XWMHints *wmhints)
54 XWindowAttributes attrib;
56 app = g_new0(DockApp, 1);
57 app->obwin.type = Window_DockApp;
59 app->icon_win = (wmhints->flags & IconWindowHint) ?
60 wmhints->icon_window : win;
62 if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
63 app->w = attrib.width;
64 app->h = attrib.height;
69 dock->dock_apps = g_list_append(dock->dock_apps, app);
72 XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
74 This is the same case as in frame.c for client windows. When Openbox is
75 starting, the window is already mapped so we see unmap events occur for
76 it. There are 2 unmap events generated that we see, one with the 'event'
77 member set the root window, and one set to the client, but both get
78 handled and need to be ignored.
80 if (ob_state == State_Starting)
81 app->ignore_unmaps += 2;
83 if (app->win != app->icon_win) {
84 /* have to map it so that it can be re-managed on a restart */
85 XMoveWindow(ob_display, app->win, -1000, -1000);
86 XMapWindow(ob_display, app->win);
88 XMapWindow(ob_display, app->icon_win);
89 XSync(ob_display, False);
91 /* specify that if we exit, the window should not be destroyed and should
92 be reparented back to root automatically */
93 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
94 XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
96 grab_button_full(2, 0, app->icon_win,
97 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
98 GrabModeAsync, ob_cursors.move);
100 g_hash_table_insert(window_map, &app->icon_win, app);
102 g_message("Managed Dock App: 0x%lx", app->icon_win);
105 void dock_remove_all()
107 while (dock->dock_apps)
108 dock_remove(dock->dock_apps->data, TRUE);
111 void dock_remove(DockApp *app, gboolean reparent)
113 ungrab_button(2, 0, app->icon_win);
114 XSelectInput(ob_display, app->icon_win, NoEventMask);
115 /* remove the window from our save set */
116 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
117 XSync(ob_display, False);
119 g_hash_table_remove(window_map, &app->icon_win);
122 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
124 dock->dock_apps = g_list_remove(dock->dock_apps, app);
127 g_message("Unmanaged Dock App: 0x%lx", app->icon_win);
132 void dock_configure()
138 dock->w = dock->h = spot = 0;
140 for (it = dock->dock_apps; it; it = it->next) {
141 struct DockApp *app = it->data;
142 if (config_dock_horz) {
146 dock->h = MAX(dock->h, app->h);
151 dock->w = MAX(dock->w, app->w);
156 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
159 /* used for calculating offsets */
160 dock->w += theme_bwidth * 2;
161 dock->h += theme_bwidth * 2;
163 /* calculate position */
164 switch (config_dock_pos) {
165 case DockPos_Floating:
166 dock->x = config_dock_x;
167 dock->y = config_dock_y;
168 gravity = NorthWestGravity;
170 case DockPos_TopLeft:
173 gravity = NorthWestGravity;
176 dock->x = screen_physical_size.width / 2;
178 gravity = NorthGravity;
180 case DockPos_TopRight:
181 dock->x = screen_physical_size.width;
183 gravity = NorthEastGravity;
187 dock->y = screen_physical_size.height / 2;
188 gravity = WestGravity;
191 dock->x = screen_physical_size.width;
192 dock->y = screen_physical_size.height / 2;
193 gravity = EastGravity;
195 case DockPos_BottomLeft:
197 dock->y = screen_physical_size.height;
198 gravity = SouthWestGravity;
201 dock->x = screen_physical_size.width / 2;
202 dock->y = screen_physical_size.height;
203 gravity = SouthGravity;
205 case DockPos_BottomRight:
206 dock->x = screen_physical_size.width;
207 dock->y = screen_physical_size.height;
208 gravity = SouthEastGravity;
216 dock->x -= dock->w / 2;
218 case NorthEastGravity:
220 case SouthEastGravity:
228 dock->y -= dock->h / 2;
230 case SouthWestGravity:
232 case SouthEastGravity:
237 if (config_dock_hide && dock->hidden) {
238 switch (config_dock_pos) {
239 case DockPos_Floating:
241 case DockPos_TopLeft:
242 if (config_dock_horz)
243 dock->y -= dock->h - theme_bwidth;
245 dock->x -= dock->w - theme_bwidth;
248 dock->y -= dock->h - theme_bwidth;
250 case DockPos_TopRight:
251 if (config_dock_horz)
252 dock->y -= dock->h - theme_bwidth;
254 dock->x += dock->w - theme_bwidth;
257 dock->x -= dock->w - theme_bwidth;
260 dock->x += dock->w - theme_bwidth;
262 case DockPos_BottomLeft:
263 if (config_dock_horz)
264 dock->y += dock->h - theme_bwidth;
266 dock->x -= dock->w - theme_bwidth;
269 dock->y += dock->h - theme_bwidth;
271 case DockPos_BottomRight:
272 if (config_dock_horz)
273 dock->y += dock->h - theme_bwidth;
275 dock->x += dock->w - theme_bwidth;
281 switch (config_dock_pos) {
282 case DockPos_Floating:
283 STRUT_SET(dock_strut, 0, 0, 0, 0);
285 case DockPos_TopLeft:
286 if (config_dock_horz)
287 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
289 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
292 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
294 case DockPos_TopRight:
295 if (config_dock_horz)
296 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
298 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
301 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
304 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
306 case DockPos_BottomLeft:
307 if (config_dock_horz)
308 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
310 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
313 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
315 case DockPos_BottomRight:
316 if (config_dock_horz)
317 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
319 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
323 /* not used for actually sizing shit */
324 dock->w -= theme_bwidth * 2;
325 dock->h -= theme_bwidth * 2;
327 if (dock->w > 0 && dock->h > 0) {
328 RECT_SET(dock->a_frame->area, 0, 0, dock->w, dock->h);
329 XMoveResizeWindow(ob_display, dock->frame,
330 dock->x, dock->y, dock->w, dock->h);
332 paint(dock->frame, dock->a_frame);
333 XMapWindow(ob_display, dock->frame);
335 XUnmapWindow(ob_display, dock->frame);
337 /* but they are useful outside of this function! */
338 dock->w += theme_bwidth * 2;
339 dock->h += theme_bwidth * 2;
341 screen_update_struts();
344 void dock_app_configure(DockApp *app, int w, int h)
351 void dock_app_drag(DockApp *app, XMotionEvent *e)
353 DockApp *over = NULL;
361 /* are we on top of the dock? */
362 if (!(x >= dock->x &&
364 x < dock->x + dock->w &&
365 y < dock->y + dock->h))
371 /* which dock app are we on top of? */
372 for (it = dock->dock_apps; it; it = it->next) {
374 if (config_dock_horz) {
375 if (x >= over->x && x < over->x + over->w)
378 if (y >= over->y && y < over->y + over->h)
382 if (!it || app == over) return;
387 if (config_dock_horz)
388 after = (x > over->w / 2);
390 after = (y > over->h / 2);
392 /* remove before doing the it->next! */
393 dock->dock_apps = g_list_remove(dock->dock_apps, app);
395 if (after) it = it->next;
397 dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app);
401 static void hide_timeout(void *n)
404 timer_stop(dock->hide_timer);
405 dock->hide_timer = NULL;
412 void dock_hide(gboolean hide)
414 if (dock->hidden == hide || !config_dock_hide)
418 dock->hidden = FALSE;
421 /* if was hiding, stop it */
422 if (dock->hide_timer) {
423 timer_stop(dock->hide_timer);
424 dock->hide_timer = NULL;
427 g_assert(!dock->hide_timer);
428 dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
429 (TimeoutHandler)hide_timeout,