]> Dogcows Code - chaz/openbox/blob - openbox/dock.c
dockapps are ObWindows now.
[chaz/openbox] / openbox / dock.c
1 #include "dock.h"
2 #include "screen.h"
3 #include "config.h"
4 #include "grab.h"
5 #include "openbox.h"
6 #include "render/theme.h"
7
8 #define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
9 EnterWindowMask | LeaveWindowMask)
10 #define DOCKAPP_EVENT_MASK (StructureNotifyMask)
11
12 static Dock *dock;
13
14 void dock_startup()
15 {
16 XSetWindowAttributes attrib;
17 int i;
18
19 dock = g_new0(struct Dock, 1);
20 dock->obwin.type = Window_Dock;
21
22 dock->hidden = TRUE;
23
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,
29 &attrib);
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);
33
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]));
37 }
38
39 void dock_shutdown()
40 {
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);
45 }
46
47 void dock_add(Window win, XWMHints *wmhints)
48 {
49 DockApp *app;
50 XWindowAttributes attrib;
51
52 app = g_new0(DockApp, 1);
53 app->obwin.type = Window_DockApp;
54 app->win = win;
55 app->icon_win = (wmhints->flags & IconWindowHint) ?
56 wmhints->icon_window : win;
57
58 if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
59 app->w = attrib.width;
60 app->h = attrib.height;
61 } else {
62 app->w = app->h = 64;
63 }
64
65 dock->dock_apps = g_list_append(dock->dock_apps, app);
66 dock_configure();
67
68 XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y);
69 /*
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.
75 */
76 if (ob_state == State_Starting)
77 app->ignore_unmaps += 2;
78
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);
83 }
84 XMapWindow(ob_display, app->icon_win);
85 XSync(ob_display, False);
86
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);
91
92 grab_button_full(2, 0, app->icon_win,
93 ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
94 GrabModeAsync, ob_cursors.move);
95
96 g_hash_table_insert(window_map, &app->icon_win, app);
97
98 g_message("Managed Dock App: 0x%lx", app->icon_win);
99 }
100
101 void dock_remove_all()
102 {
103 while (dock->dock_apps)
104 dock_remove(dock->dock_apps->data, TRUE);
105 }
106
107 void dock_remove(DockApp *app, gboolean reparent)
108 {
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);
114
115 g_hash_table_remove(window_map, &app->icon_win);
116
117 if (reparent)
118 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
119
120 dock->dock_apps = g_list_remove(dock->dock_apps, app);
121 dock_configure();
122
123 g_message("Unmanaged Dock App: 0x%lx", app->icon_win);
124
125 g_free(app);
126 }
127
128 void dock_configure()
129 {
130 GList *it;
131 int spot;
132 int gravity;
133
134 dock->w = dock->h = spot = 0;
135
136 for (it = dock->dock_apps; it; it = it->next) {
137 struct DockApp *app = it->data;
138 if (config_dock_horz) {
139 app->x = spot;
140 app->y = 0;
141 dock->w += app->w;
142 dock->h = MAX(dock->h, app->h);
143 spot += app->w;
144 } else {
145 app->x = 0;
146 app->y = spot;
147 dock->w = MAX(dock->w, app->w);
148 dock->h += app->h;
149 spot += app->h;
150 }
151
152 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
153 }
154
155 /* used for calculating offsets */
156 dock->w += theme_bwidth * 2;
157 dock->h += theme_bwidth * 2;
158
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;
165 break;
166 case DockPos_TopLeft:
167 dock->x = 0;
168 dock->y = 0;
169 gravity = NorthWestGravity;
170 break;
171 case DockPos_Top:
172 dock->x = screen_physical_size.width / 2;
173 dock->y = 0;
174 gravity = NorthGravity;
175 break;
176 case DockPos_TopRight:
177 dock->x = screen_physical_size.width;
178 dock->y = 0;
179 gravity = NorthEastGravity;
180 break;
181 case DockPos_Left:
182 dock->x = 0;
183 dock->y = screen_physical_size.height / 2;
184 gravity = WestGravity;
185 break;
186 case DockPos_Right:
187 dock->x = screen_physical_size.width;
188 dock->y = screen_physical_size.height / 2;
189 gravity = EastGravity;
190 break;
191 case DockPos_BottomLeft:
192 dock->x = 0;
193 dock->y = screen_physical_size.height;
194 gravity = SouthWestGravity;
195 break;
196 case DockPos_Bottom:
197 dock->x = screen_physical_size.width / 2;
198 dock->y = screen_physical_size.height;
199 gravity = SouthGravity;
200 break;
201 case DockPos_BottomRight:
202 dock->x = screen_physical_size.width;
203 dock->y = screen_physical_size.height;
204 gravity = SouthEastGravity;
205 break;
206 }
207
208 switch(gravity) {
209 case NorthGravity:
210 case CenterGravity:
211 case SouthGravity:
212 dock->x -= dock->w / 2;
213 break;
214 case NorthEastGravity:
215 case EastGravity:
216 case SouthEastGravity:
217 dock->x -= dock->w;
218 break;
219 }
220 switch(gravity) {
221 case WestGravity:
222 case CenterGravity:
223 case EastGravity:
224 dock->y -= dock->h / 2;
225 break;
226 case SouthWestGravity:
227 case SouthGravity:
228 case SouthEastGravity:
229 dock->y -= dock->h;
230 break;
231 }
232
233 if (config_dock_hide && dock->hidden) {
234 switch (config_dock_pos) {
235 case DockPos_Floating:
236 break;
237 case DockPos_TopLeft:
238 if (config_dock_horz)
239 dock->y -= dock->h - theme_bwidth;
240 else
241 dock->x -= dock->w - theme_bwidth;
242 break;
243 case DockPos_Top:
244 dock->y -= dock->h - theme_bwidth;
245 break;
246 case DockPos_TopRight:
247 if (config_dock_horz)
248 dock->y -= dock->h - theme_bwidth;
249 else
250 dock->x += dock->w - theme_bwidth;
251 break;
252 case DockPos_Left:
253 dock->x -= dock->w - theme_bwidth;
254 break;
255 case DockPos_Right:
256 dock->x += dock->w - theme_bwidth;
257 break;
258 case DockPos_BottomLeft:
259 if (config_dock_horz)
260 dock->y += dock->h - theme_bwidth;
261 else
262 dock->x -= dock->w - theme_bwidth;
263 break;
264 case DockPos_Bottom:
265 dock->y += dock->h - theme_bwidth;
266 break;
267 case DockPos_BottomRight:
268 if (config_dock_horz)
269 dock->y += dock->h - theme_bwidth;
270 else
271 dock->x += dock->w - theme_bwidth;
272 break;
273 }
274 }
275
276 /* not used for actually sizing shit */
277 dock->w -= theme_bwidth * 2;
278 dock->h -= theme_bwidth * 2;
279
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);
284
285 paint(dock->frame, dock->a_frame);
286 XMapWindow(ob_display, dock->frame);
287 } else
288 XUnmapWindow(ob_display, dock->frame);
289
290 /* but they are useful outside of this function! */
291 dock->w += theme_bwidth * 2;
292 dock->h += theme_bwidth * 2;
293 }
294
295 void dock_app_configure(DockApp *app, int w, int h)
296 {
297 app->w = w;
298 app->h = h;
299 dock_configure();
300 }
301
302 void dock_app_drag(DockApp *app, XMotionEvent *e)
303 {
304 DockApp *over = NULL;
305 GList *it;
306 int x, y;
307 gboolean after;
308
309 x = e->x_root;
310 y = e->y_root;
311
312 /* are we on top of the dock? */
313 if (!(x >= dock->x &&
314 y >= dock->y &&
315 x < dock->x + dock->w &&
316 y < dock->y + dock->h))
317 return;
318
319 x -= dock->x;
320 y -= dock->y;
321
322 /* which dock app are we on top of? */
323 for (it = dock->dock_apps; it; it = it->next) {
324 over = it->data;
325 if (config_dock_horz) {
326 if (x >= over->x && x < over->x + over->w)
327 break;
328 } else {
329 if (y >= over->y && y < over->y + over->h)
330 break;
331 }
332 }
333 if (!it || app == over) return;
334
335 x -= over->x;
336 y -= over->y;
337
338 if (config_dock_horz)
339 after = (x > over->w / 2);
340 else
341 after = (y > over->h / 2);
342
343 /* remove before doing the it->next! */
344 dock->dock_apps = g_list_remove(dock->dock_apps, app);
345
346 if (after) it = it->next;
347
348 dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app);
349 dock_configure();
350 }
351
352 static void hide_timeout(void *n)
353 {
354 /* dont repeat */
355 timer_stop(dock->hide_timer);
356 dock->hide_timer = NULL;
357
358 /* hide */
359 dock->hidden = TRUE;
360 dock_configure();
361 }
362
363 void dock_hide(gboolean hide)
364 {
365 if (dock->hidden == hide || !config_dock_hide)
366 return;
367 if (!hide) {
368 /* show */
369 dock->hidden = FALSE;
370 dock_configure();
371
372 /* if was hiding, stop it */
373 if (dock->hide_timer) {
374 timer_stop(dock->hide_timer);
375 dock->hide_timer = NULL;
376 }
377 } else {
378 g_assert(!dock->hide_timer);
379 dock->hide_timer = timer_start(config_dock_hide_timeout * 1000,
380 (TimeoutHandler)hide_timeout,
381 NULL);
382 }
383 }
This page took 0.055162 seconds and 4 git commands to generate.