7 #include "render2/render.h"
8 #include "render2/theme.h"
10 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
11 EnterWindowMask | LeaveWindowMask)
12 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
20 XSetWindowAttributes attrib;
22 STRUT_SET(dock_strut, 0, 0, 0, 0);
24 dock = g_new0(struct Dock, 1);
25 dock->obwin.type = Window_Dock;
29 attrib.event_mask = DOCK_EVENT_MASK;
30 attrib.override_redirect = True;
31 dock->frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
32 RrInstanceDepth(ob_render_inst),
34 RrInstanceVisual(ob_render_inst),
35 CWOverrideRedirect | CWEventMask,
37 dock->s_frame = RrSurfaceNew(ob_render_inst, 0, dock->frame, 0);
38 RrSurfaceCopy(dock->s_frame, ob_theme->title);
40 g_hash_table_insert(window_map, &dock->frame, dock);
41 stacking_add(DOCK_AS_WINDOW(dock));
42 stacking_raise(DOCK_AS_WINDOW(dock));
47 RrSurfaceFree(dock->s_frame);
48 XDestroyWindow(ob_display, dock->frame);
49 g_hash_table_remove(window_map, &dock->frame);
50 stacking_remove(dock);
53 void dock_add(Window win, XWMHints *wmhints)
56 XWindowAttributes attrib;
59 app = g_new0(DockApp, 1);
60 app->obwin.type = Window_DockApp;
62 app->icon_win = (wmhints->flags & IconWindowHint) ?
63 wmhints->icon_window : win;
65 if (PROP_GETSS(app->win, wm_class, locale, &data)) {
67 app->name = g_strdup(data[0]);
69 app->class = g_strdup(data[1]);
74 if (app->name == NULL) app->name = g_strdup("");
75 if (app->class == NULL) app->class = g_strdup("");
77 if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
78 app->w = attrib.width;
79 app->h = attrib.height;
84 dock->dock_apps = g_list_append(dock->dock_apps, app);
87 XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
89 This is the same case as in frame.c for client windows. When Openbox is
90 starting, the window is already mapped so we see unmap events occur for
91 it. There are 2 unmap events generated that we see, one with the 'event'
92 member set the root window, and one set to the client, but both get
93 handled and need to be ignored.
95 if (ob_state == State_Starting)
96 app->ignore_unmaps += 2;
98 if (app->win != app->icon_win) {
99 /* have to map it so that it can be re-managed on a restart */
100 XMoveWindow(ob_display, app->win, -1000, -1000);
101 XMapWindow(ob_display, app->win);
103 XMapWindow(ob_display, app->icon_win);
104 XSync(ob_display, False);
106 /* specify that if we exit, the window should not be destroyed and should
107 be reparented back to root automatically */
108 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
109 XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK);
111 grab_button_full(2, 0, app->icon_win,
112 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
113 GrabModeAsync, ob_cursors.move);
115 g_hash_table_insert(window_map, &app->icon_win, app);
117 g_message("Managed Dock App: 0x%lx (%s)", app->icon_win, app->class);
120 void dock_remove_all()
122 while (dock->dock_apps)
123 dock_remove(dock->dock_apps->data, TRUE);
126 void dock_remove(DockApp *app, gboolean reparent)
128 ungrab_button(2, 0, app->icon_win);
129 XSelectInput(ob_display, app->icon_win, NoEventMask);
130 /* remove the window from our save set */
131 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
132 XSync(ob_display, False);
134 g_hash_table_remove(window_map, &app->icon_win);
137 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
139 dock->dock_apps = g_list_remove(dock->dock_apps, app);
142 g_message("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
149 void dock_configure()
155 dock->w = dock->h = spot = 0;
158 for (it = dock->dock_apps; it; it = it->next) {
159 struct DockApp *app = it->data;
160 if (config_dock_horz) {
162 dock->h = MAX(dock->h, app->h);
164 dock->w = MAX(dock->w, app->w);
169 /* position the apps */
170 for (it = dock->dock_apps; it; it = it->next) {
171 struct DockApp *app = it->data;
172 if (config_dock_horz) {
174 app->y = (dock->h - app->h) / 2;
177 app->x = (dock->w - app->w) / 2;
182 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
185 dock->w += ob_theme->bwidth * 2;
186 dock->h += ob_theme->bwidth * 2;
188 /* calculate position */
189 switch (config_dock_pos) {
190 case DockPos_Floating:
191 dock->x = config_dock_x;
192 dock->y = config_dock_y;
193 gravity = NorthWestGravity;
195 case DockPos_TopLeft:
198 gravity = NorthWestGravity;
201 dock->x = screen_physical_size.width / 2;
203 gravity = NorthGravity;
205 case DockPos_TopRight:
206 dock->x = screen_physical_size.width;
208 gravity = NorthEastGravity;
212 dock->y = screen_physical_size.height / 2;
213 gravity = WestGravity;
216 dock->x = screen_physical_size.width;
217 dock->y = screen_physical_size.height / 2;
218 gravity = EastGravity;
220 case DockPos_BottomLeft:
222 dock->y = screen_physical_size.height;
223 gravity = SouthWestGravity;
226 dock->x = screen_physical_size.width / 2;
227 dock->y = screen_physical_size.height;
228 gravity = SouthGravity;
230 case DockPos_BottomRight:
231 dock->x = screen_physical_size.width;
232 dock->y = screen_physical_size.height;
233 gravity = SouthEastGravity;
241 dock->x -= dock->w / 2;
243 case NorthEastGravity:
245 case SouthEastGravity:
253 dock->y -= dock->h / 2;
255 case SouthWestGravity:
257 case SouthEastGravity:
262 if (config_dock_hide && dock->hidden) {
263 switch (config_dock_pos) {
264 case DockPos_Floating:
266 case DockPos_TopLeft:
267 if (config_dock_horz)
268 dock->y -= dock->h - ob_theme->bwidth;
270 dock->x -= dock->w - ob_theme->bwidth;
273 dock->y -= dock->h - ob_theme->bwidth;
275 case DockPos_TopRight:
276 if (config_dock_horz)
277 dock->y -= dock->h - ob_theme->bwidth;
279 dock->x += dock->w - ob_theme->bwidth;
282 dock->x -= dock->w - ob_theme->bwidth;
285 dock->x += dock->w - ob_theme->bwidth;
287 case DockPos_BottomLeft:
288 if (config_dock_horz)
289 dock->y += dock->h - ob_theme->bwidth;
291 dock->x -= dock->w - ob_theme->bwidth;
294 dock->y += dock->h - ob_theme->bwidth;
296 case DockPos_BottomRight:
297 if (config_dock_horz)
298 dock->y += dock->h - ob_theme->bwidth;
300 dock->x += dock->w - ob_theme->bwidth;
306 switch (config_dock_pos) {
307 case DockPos_Floating:
308 STRUT_SET(dock_strut, 0, 0, 0, 0);
310 case DockPos_TopLeft:
311 if (config_dock_horz)
312 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
314 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
317 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
319 case DockPos_TopRight:
320 if (config_dock_horz)
321 STRUT_SET(dock_strut, 0, dock->h, 0, 0);
323 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
326 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
329 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
331 case DockPos_BottomLeft:
332 if (config_dock_horz)
333 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
335 STRUT_SET(dock_strut, dock->w, 0, 0, 0);
338 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
340 case DockPos_BottomRight:
341 if (config_dock_horz)
342 STRUT_SET(dock_strut, 0, 0, 0, dock->h);
344 STRUT_SET(dock_strut, 0, 0, dock->w, 0);
348 if (dock->w > 0 && dock->h > 0) {
349 RrSurfaceSetArea(dock->s_frame, dock->x, dock->y, dock->w, dock->h);
350 RrSurfaceShow(dock->s_frame);
352 RrSurfaceHide(dock->s_frame);
354 dock->w += ob_theme->bwidth * 2;
355 dock->h += ob_theme->bwidth * 2;
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,