9 static int theme_bwidth = 3;
11 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
12 EnterWindowMask | LeaveWindowMask)
13 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
21 XSetWindowAttributes attrib;
23 STRUT_SET(dock_strut, 0, 0, 0, 0);
25 dock = g_new0(struct Dock, 1);
26 dock->obwin.type = Window_Dock;
30 attrib.event_mask = DOCK_EVENT_MASK;
31 attrib.override_redirect = True;
32 dock->frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
33 RrInstanceDepth(ob_render_inst), InputOutput,
34 RrInstanceVisual(ob_render_inst),
35 CWOverrideRedirect | CWEventMask,
37 dock->s_frame = RrSurfaceNew(ob_render_inst, RR_SURFACE_PLANAR,
39 /* XXX COPY THE APPEARANCE FROM THE THEME !#&*(# LIKE THIS SORTA...
40 dock->a_frame = appearance_copy(theme_a_unfocused_title);
43 g_hash_table_insert(window_map, &dock->frame, dock);
44 stacking_add(DOCK_AS_WINDOW(dock));
45 stacking_raise(DOCK_AS_WINDOW(dock));
50 RrSurfaceFree(dock->s_frame);
51 XDestroyWindow(ob_display, dock->frame);
52 g_hash_table_remove(window_map, &dock->frame);
53 stacking_remove(dock);
56 void dock_add(Window win, XWMHints *wmhints)
59 XWindowAttributes attrib;
62 app = g_new0(DockApp, 1);
63 app->obwin.type = Window_DockApp;
65 app->icon_win = (wmhints->flags & IconWindowHint) ?
66 wmhints->icon_window : win;
68 if (PROP_GETSS(app->win, wm_class, locale, &data)) {
70 app->name = g_strdup(data[0]);
72 app->class = g_strdup(data[1]);
77 if (app->name == NULL) app->name = g_strdup("");
78 if (app->class == NULL) app->class = g_strdup("");
80 if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
81 app->w = attrib.width;
82 app->h = attrib.height;
87 dock->dock_apps = g_list_append(dock->dock_apps, app);
90 XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
92 This is the same case as in frame.c for client windows. When Openbox is
93 starting, the window is already mapped so we see unmap events occur for
94 it. There are 2 unmap events generated that we see, one with the 'event'
95 member set the root window, and one set to the client, but both get
96 handled and need to be ignored.
98 if (ob_state == State_Starting)
99 app->ignore_unmaps += 2;
101 if (app->win != app->icon_win) {
102 /* have to map it so that it can be re-managed on a restart */
103 XMoveWindow(ob_display, app->win, -1000, -1000);
104 XMapWindow(ob_display, app->win);
106 XMapWindow(ob_display, app->icon_win);
107 XSync(ob_display, False);
109 /* specify that if we exit, the window should not be destroyed and should
110 be reparented back to root automatically */
111 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
112 XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
114 grab_button_full(2, 0, app->icon_win,
115 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
116 GrabModeAsync, ob_cursors.move);
118 g_hash_table_insert(window_map, &app->icon_win, app);
120 g_message("Managed Dock App: 0x%lx (%s)", app->icon_win, app->class);
123 void dock_remove_all()
125 while (dock->dock_apps)
126 dock_remove(dock->dock_apps->data, TRUE);
129 void dock_remove(DockApp *app, gboolean reparent)
131 ungrab_button(2, 0, app->icon_win);
132 XSelectInput(ob_display, app->icon_win, NoEventMask);
133 /* remove the window from our save set */
134 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
135 XSync(ob_display, False);
137 g_hash_table_remove(window_map, &app->icon_win);
140 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
142 dock->dock_apps = g_list_remove(dock->dock_apps, app);
145 g_message("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
152 void dock_configure()
158 dock->w = dock->h = spot = 0;
161 for (it = dock->dock_apps; it; it = it->next) {
162 struct DockApp *app = it->data;
163 if (config_dock_horz) {
165 dock->h = MAX(dock->h, app->h);
167 dock->w = MAX(dock->w, app->w);
172 dock->w += theme_bwidth * 2;
173 dock->h += theme_bwidth * 2;
175 /* position the apps */
176 for (it = dock->dock_apps; it; it = it->next) {
177 struct DockApp *app = it->data;
178 if (config_dock_horz) {
180 app->y = (dock->h - app->h) / 2;
183 app->x = (dock->w - app->w) / 2;
188 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
191 /* calculate position */
192 switch (config_dock_pos) {
193 case DockPos_Floating:
194 dock->x = config_dock_x;
195 dock->y = config_dock_y;
196 gravity = NorthWestGravity;
198 case DockPos_TopLeft:
201 gravity = NorthWestGravity;
204 dock->x = screen_physical_size.width / 2;
206 gravity = NorthGravity;
208 case DockPos_TopRight:
209 dock->x = screen_physical_size.width;
211 gravity = NorthEastGravity;
215 dock->y = screen_physical_size.height / 2;
216 gravity = WestGravity;
219 dock->x = screen_physical_size.width;
220 dock->y = screen_physical_size.height / 2;
221 gravity = EastGravity;
223 case DockPos_BottomLeft:
225 dock->y = screen_physical_size.height;
226 gravity = SouthWestGravity;
229 dock->x = screen_physical_size.width / 2;
230 dock->y = screen_physical_size.height;
231 gravity = SouthGravity;
233 case DockPos_BottomRight:
234 dock->x = screen_physical_size.width;
235 dock->y = screen_physical_size.height;
236 gravity = SouthEastGravity;
244 dock->x -= dock->w / 2;
246 case NorthEastGravity:
248 case SouthEastGravity:
256 dock->y -= dock->h / 2;
258 case SouthWestGravity:
260 case SouthEastGravity:
265 if (config_dock_hide && dock->hidden) {
266 switch (config_dock_pos) {
267 case DockPos_Floating:
269 case DockPos_TopLeft:
270 if (config_dock_horz)
271 dock->y -= dock->h - theme_bwidth;
273 dock->x -= dock->w - theme_bwidth;
276 dock->y -= dock->h - theme_bwidth;
278 case DockPos_TopRight:
279 if (config_dock_horz)
280 dock->y -= dock->h - theme_bwidth;
282 dock->x += dock->w - theme_bwidth;
285 dock->x -= dock->w - theme_bwidth;
288 dock->x += dock->w - theme_bwidth;
290 case DockPos_BottomLeft:
291 if (config_dock_horz)
292 dock->y += dock->h - theme_bwidth;
294 dock->x -= dock->w - theme_bwidth;
297 dock->y += dock->h - theme_bwidth;
299 case DockPos_BottomRight:
300 if (config_dock_horz)
301 dock->y += dock->h - theme_bwidth;
303 dock->x += dock->w - theme_bwidth;
309 switch (config_dock_pos) {
310 case DockPos_Floating:
311 STRUT_SET(dock_strut, 0, 0, 0, 0);
313 case DockPos_TopLeft:
314 if (config_dock_horz)
315 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
317 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
320 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
322 case DockPos_TopRight:
323 if (config_dock_horz)
324 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
326 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
329 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
332 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
334 case DockPos_BottomLeft:
335 if (config_dock_horz)
336 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
338 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
341 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
343 case DockPos_BottomRight:
344 if (config_dock_horz)
345 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
347 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
351 if (dock->w > 0 && dock->h > 0) {
352 RrSurfaceSetArea(dock->s_frame, dock->x, dock->y, dock->w, dock->h);
353 RrSurfaceShow(dock->s_frame);
355 RrSurfaceHide(dock->s_frame);
357 screen_update_struts();
360 void dock_app_configure(DockApp *app, int w, int h)
367 void dock_app_drag(DockApp *app, XMotionEvent *e)
369 DockApp *over = NULL;
377 /* are we on top of the dock? */
378 if (!(x >= dock->x &&
380 x < dock->x + dock->w &&
381 y < dock->y + dock->h))
387 /* which dock app are we on top of? */
388 for (it = dock->dock_apps; it; it = it->next) {
390 if (config_dock_horz) {
391 if (x >= over->x && x < over->x + over->w)
394 if (y >= over->y && y < over->y + over->h)
398 if (!it || app == over) return;
403 if (config_dock_horz)
404 after = (x > over->w / 2);
406 after = (y > over->h / 2);
408 /* remove before doing the it->next! */
409 dock->dock_apps = g_list_remove(dock->dock_apps, app);
411 if (after) it = it->next;
413 dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app);
417 static void hide_timeout(void *n)
420 timer_stop(dock->hide_timer);
421 dock->hide_timer = NULL;
428 void dock_hide(gboolean hide)
430 if (dock->hidden == hide || !config_dock_hide)
434 dock->hidden = FALSE;
437 /* if was hiding, stop it */
438 if (dock->hide_timer) {
439 timer_stop(dock->hide_timer);
440 dock->hide_timer = NULL;
443 g_assert(!dock->hide_timer);
444 dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
445 (TimeoutHandler)hide_timeout,