Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 583 lines (493 sloc) 16.09 kb
fd81641 @nsf Fix translate coordinates.
nsf authored
1 #include <math.h>
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
2 #include "settings.h"
507f15b @nsf Add 'pager' widget.
nsf authored
3 #include "builtin-widgets.h"
4
92c6026 @nsf Fix formatting.
nsf authored
5 static int create_widget_private(struct widget *w, struct config_format_entry *e,
507f15b @nsf Add 'pager' widget.
nsf authored
6 struct config_format_tree *tree);
7 static void destroy_widget_private(struct widget *w);
8 static void draw(struct widget *w);
9 static void button_click(struct widget *w, XButtonEvent *e);
10 static void prop_change(struct widget *w, XPropertyEvent *e);
11 static void client_msg(struct widget *w, XClientMessageEvent *e);
12
13 static void dnd_drop(struct widget *w, struct drag_info *di);
14
15 static void configure(struct widget *w, XConfigureEvent *e);
16 static void mouse_motion(struct widget *w, XMotionEvent *e);
17 static void mouse_leave(struct widget *w);
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
18 static void reconfigure(struct widget *w);
507f15b @nsf Add 'pager' widget.
nsf authored
19
20 struct widget_interface pager_interface = {
92c6026 @nsf Fix formatting.
nsf authored
21 .theme_name = "pager",
22 .size_type = WIDGET_SIZE_CONSTANT,
23 .create_widget_private = create_widget_private,
507f15b @nsf Add 'pager' widget.
nsf authored
24 .destroy_widget_private = destroy_widget_private,
92c6026 @nsf Fix formatting.
nsf authored
25 .draw = draw,
26 .button_click = button_click,
27 .prop_change = prop_change,
28 .dnd_drop = dnd_drop,
507f15b @nsf Add 'pager' widget.
nsf authored
29 .client_msg = client_msg,
30 .configure = configure,
31 .mouse_motion = mouse_motion,
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
32 .mouse_leave = mouse_leave,
33 .reconfigure = reconfigure
507f15b @nsf Add 'pager' widget.
nsf authored
34 };
35
36 /**************************************************************************
37 Pager theme
38 **************************************************************************/
39
40 #define COLOR_WHITE (unsigned char[]){255,255,255}
41 #define COLOR_BLACK (unsigned char[]){0,0,0}
42
43 static int parse_pager_state(struct pager_state *ps, const char *name,
44 struct config_format_entry *e,
45 struct config_format_tree *tree,
46 int required)
47 {
48 struct config_format_entry *ee = find_config_format_entry(e, name);
49 if (!ee) {
50 if (required)
51 required_entry_not_found(e, name);
52 ps->exists = 0;
53 return -1;
54 }
55
56 parse_color(ps->border, "border", ee, COLOR_WHITE);
57 parse_color(ps->fill, "fill", ee, COLOR_BLACK);
58 parse_color(ps->inactive_window_border, "inactive_window_border", ee, COLOR_WHITE);
59 parse_color(ps->inactive_window_fill, "inactive_window_fill", ee, COLOR_BLACK);
60 parse_color(ps->active_window_border, "active_window_border", ee, COLOR_WHITE);
61 parse_color(ps->active_window_fill, "active_window_fill", ee, COLOR_BLACK);
62
63 parse_text_info_named(&ps->font, "font", ee, 0);
64
65 ps->exists = 1;
66 return 0;
67 }
68
69 static void free_pager_state(struct pager_state *ps)
70 {
71 if (ps->exists)
72 free_text_info(&ps->font);
73 }
74
75 static int parse_pager_theme(struct pager_theme *pt,
76 struct config_format_entry *e,
77 struct config_format_tree *tree)
78 {
79 if (parse_pager_state(&pt->states[BUTTON_STATE_IDLE], "idle", e, tree, 1))
80 goto parse_pager_state_error_idle;
81
82 if (parse_pager_state(&pt->states[BUTTON_STATE_PRESSED], "pressed", e, tree, 1))
83 goto parse_pager_state_error_pressed;
84
85 pt->height = parse_int("height", e, 999);
86 pt->desktop_spacing = parse_int("desktop_spacing", e, 1);
92c6026 @nsf Fix formatting.
nsf authored
87 parse_pager_state(&pt->states[BUTTON_STATE_IDLE_HIGHLIGHT],
507f15b @nsf Add 'pager' widget.
nsf authored
88 "idle_highlight", e, tree, 0);
92c6026 @nsf Fix formatting.
nsf authored
89 parse_pager_state(&pt->states[BUTTON_STATE_PRESSED_HIGHLIGHT],
507f15b @nsf Add 'pager' widget.
nsf authored
90 "pressed_highlight", e, tree, 0);
91
92 return 0;
93
94 parse_pager_state_error_pressed:
95 free_pager_state(&pt->states[BUTTON_STATE_IDLE]);
96 parse_pager_state_error_idle:
97 return -1;
98 }
99
100 static void free_pager_theme(struct pager_theme *pt)
101 {
102 unsigned int i;
103 for (i = 0; i < 4; ++i)
104 free_pager_state(&pt->states[i]);
105 }
106
107 /**************************************************************************
108 Tasks management
109 **************************************************************************/
110
111 static gboolean task_remove_dead(Window *win, struct pager_task *t, void *notused)
112 {
113 if (t->alive) {
114 t->alive = 0;
115 return 0;
116 }
117 xfree(t);
118 return 1;
119 }
120
121 static gboolean task_remove_all(Window *win, struct pager_task *t, void *notused)
122 {
123 xfree(t);
124 return 1;
125 }
126
127 static void get_window_position(struct x_connection *c, struct pager_task *t, Window win)
128 {
129 XWindowAttributes winattrs;
130 XGetWindowAttributes(c->dpy, win, &winattrs);
131 t->w = winattrs.width;
132 t->h = winattrs.height;
fd81641 @nsf Fix translate coordinates.
nsf authored
133 x_translate_coordinates(c, 0, 0, &t->x, &t->y, win);
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
134
135 long *extents = x_get_prop_data(c, win, c->atoms[XATOM_NET_FRAME_EXTENTS],
136 XA_CARDINAL, 0);
137 if (extents) {
138 t->x -= extents[0]; t->w += extents[0] + extents[1];
139 t->y -= extents[2]; t->h += extents[2] + extents[3];
140 XFree(extents);
141 }
507f15b @nsf Add 'pager' widget.
nsf authored
142 }
143
144 static void select_window_input(struct x_connection *c, Window win)
145 {
146 XWindowAttributes winattrs;
147 XGetWindowAttributes(c->dpy, win, &winattrs);
148 long mask = winattrs.your_event_mask | PropertyChangeMask | StructureNotifyMask;
149 XSelectInput(c->dpy, win, mask);
150 }
151
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
152 static int update_tasks(struct widget *w)
507f15b @nsf Add 'pager' widget.
nsf authored
153 {
154 struct x_connection *c = &w->panel->connection;
155 struct pager_widget *pw = (struct pager_widget*)w->private;
156 if (pw->windows)
157 XFree(pw->windows);
158
159 pw->windows = x_get_prop_data(c, c->root, c->atoms[XATOM_NET_CLIENT_LIST_STACKING],
160 XA_WINDOW, &pw->windows_n);
161 if (!pw->windows_n)
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
162 return 0;
507f15b @nsf Add 'pager' widget.
nsf authored
163
164 int needs_expose = 0;
165 size_t i;
166 struct pager_task *t;
167 for (i = 0; i < pw->windows_n; ++i) {
168 Window win = pw->windows[i];
169 t = g_hash_table_lookup(pw->tasks, &win);
170 if (t) {
171 t->alive = 1;
172 if (t->stackpos != i) {
173 t->stackpos = i;
174 needs_expose = 1;
175 }
176 } else {
177 t = xmallocz(sizeof(struct pager_task));
178 select_window_input(c, win);
179 get_window_position(c, t, win);
180 t->win = win;
181 t->alive = 1;
182 t->desktop = x_get_window_desktop(c, win);
21c1f61 @nsf Change window visibility function naming slightly.
nsf authored
183 t->visible = x_is_window_visible_on_screen(c, win);
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
184 t->visible_on_panel = x_is_window_visible_on_panel(c, win);
507f15b @nsf Add 'pager' widget.
nsf authored
185 t->stackpos = i;
186
187 g_hash_table_insert(pw->tasks, &t->win, t);
188 needs_expose = 1;
189 }
190 }
191
192 g_hash_table_foreach_remove(pw->tasks, (GHRFunc)task_remove_dead, 0);
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
193 return needs_expose;
507f15b @nsf Add 'pager' widget.
nsf authored
194 }
195
196 static void clear_tasks(struct pager_widget *pw)
197 {
198 g_hash_table_foreach_remove(pw->tasks, (GHRFunc)task_remove_all, 0);
199 g_hash_table_destroy(pw->tasks);
200 if (pw->windows)
201 XFree(pw->windows);
202 }
203
204 /**************************************************************************
205 Desktops management
206 **************************************************************************/
207
208 static void free_desktops(struct pager_widget *pw)
209 {
210 CLEAR_ARRAY(pw->desktops);
211 }
212
213 static void update_active(struct pager_widget *pw, struct x_connection *c)
214 {
215 pw->active_win = x_get_prop_window(c, c->root, c->atoms[XATOM_NET_ACTIVE_WINDOW]);
216 }
217
218 static void update_active_desktop(struct pager_widget *pw, struct x_connection *c)
219 {
220 pw->active = x_get_prop_int(c, c->root,
221 c->atoms[XATOM_NET_CURRENT_DESKTOP]);
222 }
223
224 static void switch_desktop(int desktop, struct x_connection *c)
225 {
226 int desktops = x_get_prop_int(c, c->root,
227 c->atoms[XATOM_NET_NUMBER_OF_DESKTOPS]);
228 if (desktop >= desktops)
229 return;
230
231 x_send_netwm_message(c, c->root, c->atoms[XATOM_NET_CURRENT_DESKTOP],
232 desktop, 0, 0, 0, 0);
233 }
234
235 static void update_desktops(struct pager_widget *pw, struct x_connection *c)
236 {
237 free_desktops(pw);
238 update_active_desktop(pw, c);
239 int desktops_n = x_get_prop_int(c, c->root,
240 c->atoms[XATOM_NET_NUMBER_OF_DESKTOPS]);
241 size_t i;
242 for (i = 0; i < desktops_n; ++i) {
243 struct pager_desktop d = {0, 0, 0, 0};
244 ARRAY_APPEND(pw->desktops, d);
245 }
246 }
247
248 static void resize_desktops(struct widget *w)
249 {
250 struct x_connection *c = &w->panel->connection;
251 struct pager_widget *pw = (struct pager_widget*)w->private;
252 if (pw->theme.height > w->panel->height)
253 pw->theme.height = w->panel->height - 2;
254
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
255 const struct x_monitor *xmon = &c->monitors[w->panel->monitor];
256 struct rect mon = {xmon->x, xmon->y, xmon->width, xmon->height};
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
257 if (!pw->current_monitor_only) {
d07dce0 @nsf Fix monitor non-constness bug in pager.
nsf authored
258 mon.x = mon.y = 0;
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
259 mon.w = c->screen_width;
260 mon.h = c->screen_height;
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
261 }
262
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
263 int workareas_n = 0;
264 long *workareas = x_get_prop_data(c, c->root, c->atoms[XATOM_NET_WORKAREA],
265 XA_CARDINAL, &workareas_n);
266
267 int width = 0;
507f15b @nsf Add 'pager' widget.
nsf authored
268 size_t i;
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
269 for (i = 0; i < pw->desktops_n; ++i) {
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
270 struct pager_desktop *pd = &pw->desktops[i];
271 struct rect workarea = {
272 workareas[4*i+0], workareas[4*i+1],
273 workareas[4*i+2], workareas[4*i+3]
274 };
275 rect_intersection(&pd->workarea, &workarea, &mon);
276 pd->div = pd->workarea.h / (pw->theme.height - 2);
277 pd->w = (mon.w / pd->div) + 2;
278 width += pd->w;
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
279 }
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
280 XFree(workareas);
507f15b @nsf Add 'pager' widget.
nsf authored
281
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
282 w->width = width + (pw->desktops_n - 1) * pw->theme.desktop_spacing;
507f15b @nsf Add 'pager' widget.
nsf authored
283 }
284
285 static int get_desktop_at(struct widget *w, int x)
286 {
287 struct pager_widget *pw = (struct pager_widget*)w->private;
288
289 size_t i;
290 for (i = 0; i < pw->desktops_n; ++i) {
291 struct pager_desktop *d = &pw->desktops[i];
292 if (x < (d->x + d->w) && x > d->x)
293 return (int)i;
294 }
295 return -1;
296 }
297
298 /**************************************************************************
299 Pager interface
300 **************************************************************************/
301
302 static int create_widget_private(struct widget *w, struct config_format_entry *e,
303 struct config_format_tree *tree)
304 {
305 struct pager_widget *pw = xmallocz(sizeof(struct pager_widget));
306 if (parse_pager_theme(&pw->theme, e, tree)) {
307 xfree(pw);
308 XWARNING("Failed to parse pager theme");
309 return -1;
310 }
311
312 INIT_ARRAY(pw->desktops, 16);
313 w->private = pw;
314
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
315 pw->current_monitor_only = parse_bool("pager_current_monitor_only", &g_settings.root);
316
507f15b @nsf Add 'pager' widget.
nsf authored
317 struct x_connection *c = &w->panel->connection;
318 update_desktops(pw, c);
319 update_active(pw, c);
320 resize_desktops(w);
321 pw->highlighted = -1;
322 pw->tasks = g_hash_table_new(g_int_hash, g_int_equal);
323 update_tasks(w);
324
325 return 0;
326 }
327
328 static void destroy_widget_private(struct widget *w)
329 {
330 struct pager_widget *pw = (struct pager_widget*)w->private;
331 free_pager_theme(&pw->theme);
332 free_desktops(pw);
333 FREE_ARRAY(pw->desktops);
334 clear_tasks(pw);
335 xfree(pw);
336 }
337
338 static void draw(struct widget *w)
339 {
340 struct pager_widget *pw = (struct pager_widget*)w->private;
341 cairo_t *cr = w->panel->cr;
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
342 PangoLayout *layout = w->panel->layout;
507f15b @nsf Add 'pager' widget.
nsf authored
343 size_t i;
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
344 struct rect r;
345 r.x = w->x;
346 r.y = (w->panel->height - pw->theme.height) / 2;
347 r.h = pw->theme.height;
507f15b @nsf Add 'pager' widget.
nsf authored
348
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
349 struct rect activerect;
350 struct pager_state *activeps = &pw->theme.states[0];
351
507f15b @nsf Add 'pager' widget.
nsf authored
352 for (i = 0; i < pw->desktops_n; ++i) {
0b528f1 @nsf Use pointer instead of an array member. Minor stuff..
nsf authored
353 struct pager_desktop *pd = &pw->desktops[i];
507f15b @nsf Add 'pager' widget.
nsf authored
354 int state = (i == pw->active) << 1;
355 int state_hl = ((i == pw->active) << 1) | (i == pw->highlighted);
356 struct pager_state *ps;
357
358 if (pw->theme.states[state_hl].exists)
359 ps = &pw->theme.states[state_hl];
360 else
361 ps = &pw->theme.states[state];
92c6026 @nsf Fix formatting.
nsf authored
362
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
363 pd->x = r.x;
364 r.w = pd->w;
365 fill_rectangle(cr, ps->fill, &r);
507f15b @nsf Add 'pager' widget.
nsf authored
366
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
367 if (pw->active == i) {
368 activerect = r;
369 activeps = ps;
370 }
371
5fda82e @nsf More precise cut and also react on _NET_WM_WORKAREA changes.
nsf authored
372 r.x++; r.y++; r.w -= 2; r.h -= 2;
373
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
374 size_t visible_tasks_count = 0;
507f15b @nsf Add 'pager' widget.
nsf authored
375 size_t j;
376 for (j = 0; j < pw->windows_n; ++j) {
377 Window win = pw->windows[j];
378 struct pager_task *t = g_hash_table_lookup(pw->tasks, &win);
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
379 if (t && t->visible_on_panel && (t->desktop == i || t->desktop == -1))
380 visible_tasks_count++;
507f15b @nsf Add 'pager' widget.
nsf authored
381 if (t && t->visible && (t->desktop == i || t->desktop == -1)) {
382 unsigned char *window_fill;
383 unsigned char *window_border;
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
384 struct rect intersection;
385 struct rect winr;
5fda82e @nsf More precise cut and also react on _NET_WM_WORKAREA changes.
nsf authored
386 winr.x = r.x + (t->x - pd->workarea.x) / pd->div;
387 winr.y = r.y + (t->y - pd->workarea.y) / pd->div;
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
388 winr.w = t->w / pd->div;
389 winr.h = t->h / pd->div;
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
390 if (!rect_intersection(&intersection, &winr, &r))
391 continue;
392
507f15b @nsf Add 'pager' widget.
nsf authored
393 if (win == pw->active_win) {
394 window_fill = ps->active_window_fill;
395 window_border = ps->active_window_border;
396 } else {
397 window_fill = ps->inactive_window_fill;
398 window_border = ps->inactive_window_border;
399 }
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
400 fill_rectangle(cr, window_fill, &intersection);
401 draw_rectangle_outline(cr, window_border, &intersection);
507f15b @nsf Add 'pager' widget.
nsf authored
402 }
403 }
404
5fda82e @nsf More precise cut and also react on _NET_WM_WORKAREA changes.
nsf authored
405 r.x--; r.y--; r.w += 2; r.h += 2;
406
b5a7493 @nsf Fix bug with drawing windows on pager out of desktop.
nsf authored
407 draw_rectangle_outline(cr, ps->border, &r);
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
408 if (ps->font.pfd && visible_tasks_count) {
409 /* draw number */
410 char buf[10];
411 snprintf(buf, sizeof(buf), "%u", visible_tasks_count);
412 draw_text(cr, layout, &ps->font, buf, r.x, r.y, r.w, r.h, 0);
413 }
21c1f61 @nsf Change window visibility function naming slightly.
nsf authored
414 r.x += r.w + pw->theme.desktop_spacing;
507f15b @nsf Add 'pager' widget.
nsf authored
415 }
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
416 draw_rectangle_outline(cr, activeps->border, &activerect);
507f15b @nsf Add 'pager' widget.
nsf authored
417 }
418
419 static void button_click(struct widget *w, XButtonEvent *e)
420 {
421 struct pager_widget *pw = (struct pager_widget*)w->private;
422 int di = get_desktop_at(w, e->x);
423 if (di == -1)
424 return;
92c6026 @nsf Fix formatting.
nsf authored
425
507f15b @nsf Add 'pager' widget.
nsf authored
426 struct x_connection *c = &w->panel->connection;
427
929a6eb @nsf Add cusomizable mouse actions.
nsf authored
428 int mbutton_use = check_mbutton_condition(w->panel, e->button, MBUTTON_USE);
429
430 if (mbutton_use && e->type == ButtonRelease && pw->active != di)
507f15b @nsf Add 'pager' widget.
nsf authored
431 switch_desktop(di, c);
432 }
433
434 static void prop_change(struct widget *w, XPropertyEvent *e)
435 {
436 struct pager_widget *pw = (struct pager_widget*)w->private;
437 struct x_connection *c = &w->panel->connection;
438
439 if (e->window == c->root) {
5fda82e @nsf More precise cut and also react on _NET_WM_WORKAREA changes.
nsf authored
440 if (e->atom == c->atoms[XATOM_NET_NUMBER_OF_DESKTOPS]) {
507f15b @nsf Add 'pager' widget.
nsf authored
441 update_desktops(pw, c);
442 resize_desktops(w);
443 recalculate_widgets_sizes(w->panel);
444 return;
445 }
92c6026 @nsf Fix formatting.
nsf authored
446
5fda82e @nsf More precise cut and also react on _NET_WM_WORKAREA changes.
nsf authored
447 if (e->atom == c->atoms[XATOM_NET_WORKAREA]) {
448 resize_desktops(w);
449 recalculate_widgets_sizes(w->panel);
450 return;
451 }
452
507f15b @nsf Add 'pager' widget.
nsf authored
453 if (e->atom == c->atoms[XATOM_NET_ACTIVE_WINDOW]) {
454 update_active(pw, c);
455 w->needs_expose = 1;
456 return;
457 }
458
459 if (e->atom == c->atoms[XATOM_NET_CURRENT_DESKTOP]) {
460 update_active_desktop(pw, c);
461 w->needs_expose = 1;
462 return;
463 }
464
465 if (e->atom == c->atoms[XATOM_NET_CLIENT_LIST_STACKING]) {
956ac7d @nsf Never clear the needs_expose flag.
nsf authored
466 int needs = update_tasks(w);
467 if (!w->needs_expose)
468 w->needs_expose = needs;
507f15b @nsf Add 'pager' widget.
nsf authored
469 return;
470 }
471 }
472
473 struct pager_task *t = g_hash_table_lookup(pw->tasks, &e->window);
474 if (!t)
475 return;
476
477 if (e->atom == c->atoms[XATOM_NET_WM_DESKTOP]) {
478 t->desktop = x_get_window_desktop(c, t->win);
479 w->needs_expose = 1;
480 return;
481 }
92c6026 @nsf Fix formatting.
nsf authored
482
507f15b @nsf Add 'pager' widget.
nsf authored
483 if (e->atom == c->atoms[XATOM_NET_WM_STATE]) {
21c1f61 @nsf Change window visibility function naming slightly.
nsf authored
484 t->visible = x_is_window_visible_on_screen(c, t->win);
82db749 @nsf Add "visible on panel" number drawing in pager.
nsf authored
485 t->visible_on_panel = x_is_window_visible_on_panel(c, t->win);
507f15b @nsf Add 'pager' widget.
nsf authored
486 w->needs_expose = 1;
487 return;
488 }
621c349 @nsf Use more wise scheme for placing windows in pager.
nsf authored
489
490 if (e->atom == c->atoms[XATOM_NET_FRAME_EXTENTS]) {
491 get_window_position(c, t, e->window);
492 w->needs_expose = 1;
493 return;
494 }
507f15b @nsf Add 'pager' widget.
nsf authored
495 }
496
497 static void client_msg(struct widget *w, XClientMessageEvent *e)
498 {
499 struct panel *p = w->panel;
500 struct x_connection *c = &p->connection;
501 struct pager_widget *pw = (struct pager_widget*)w->private;
502
503 if (e->message_type == c->atoms[XATOM_XDND_POSITION]) {
504 int x = (e->data.l[2] >> 16) & 0xFFFF;
505
506 /* if it's not ours, skip.. */
507 if ((x < (p->x + w->x)) || (x > (p->x + w->x + w->width)))
508 return;
509
510 int di = get_desktop_at(w, x - p->x);
511 if (di != -1 && di != pw->active)
512 switch_desktop(di, c);
513
92c6026 @nsf Fix formatting.
nsf authored
514 x_send_dnd_message(c, e->data.l[0],
507f15b @nsf Add 'pager' widget.
nsf authored
515 c->atoms[XATOM_XDND_STATUS],
516 p->win,
517 2, /* bits: 0 1 */
92c6026 @nsf Fix formatting.
nsf authored
518 0, 0,
507f15b @nsf Add 'pager' widget.
nsf authored
519 None);
520 }
521 }
522
523 static void dnd_drop(struct widget *w, struct drag_info *di)
524 {
525 if (di->taken_on->interface != &taskbar_interface)
526 return;
527
528 struct taskbar_widget *tw = di->taken_on->private;
529 if (tw->taken == None)
530 return;
531
532 int desktop = get_desktop_at(w, di->dropped_x);
533 if (desktop == -1)
534 return;
535
536 struct x_connection *c = &w->panel->connection;
92c6026 @nsf Fix formatting.
nsf authored
537 x_send_netwm_message(c, tw->taken,
507f15b @nsf Add 'pager' widget.
nsf authored
538 c->atoms[XATOM_NET_WM_DESKTOP],
539 (long)desktop, 2, 0, 0, 0);
540 }
541
542 static void configure(struct widget *w, XConfigureEvent *e)
543 {
544 struct x_connection *c = &w->panel->connection;
545 struct pager_widget *pw = (struct pager_widget*)w->private;
546 struct pager_task *t = g_hash_table_lookup(pw->tasks, &e->window);
547 if (!t)
548 return;
549
550 get_window_position(c, t, e->window);
551 w->needs_expose = 1;
552 }
553
554 static void mouse_motion(struct widget *w, XMotionEvent *e)
555 {
556 struct pager_widget *pw = (struct pager_widget*)w->private;
557 int i = get_desktop_at(w, e->x);
558 if (i != pw->highlighted) {
559 pw->highlighted = i;
560 w->needs_expose = 1;
561 }
562 }
563
564 static void mouse_leave(struct widget *w)
565 {
566 struct pager_widget *pw = (struct pager_widget*)w->private;
567 if (pw->highlighted != -1) {
568 pw->highlighted = -1;
569 w->needs_expose = 1;
570 }
571 }
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
572
573 static void reconfigure(struct widget *w)
574 {
575 struct pager_widget *pw = (struct pager_widget*)w->private;
d07dce0 @nsf Fix monitor non-constness bug in pager.
nsf authored
576 int current_monitor_only = parse_bool("pager_current_monitor_only", &g_settings.root);
577 if (current_monitor_only != pw->current_monitor_only) {
578 pw->current_monitor_only = current_monitor_only;
579 resize_desktops(w);
580 recalculate_widgets_sizes(w->panel);
581 }
ebb4f66 @nsf Add 'pager_current_monitor_only' boolean option.
nsf authored
582 }
Something went wrong with that request. Please try again.