1 /*
2 * Copyright (C) 1998 Eric Tremblay <deltax@pragma.net>
3 * Copyright (c) 1998 Michal Vitecek <fuf@fuf.sh.cvut.cz>
4 * Copyright (c) 1998 Doug Alcorn <alcornd@earthlink.net>
5 * Copyright (c) 2002,1998 Sasha Vasko <sasha at aftercode.net>
6 * Copyright (c) 1997 ric@giccs.georgetown.edu
7 * Copyright (C) 1998 Makoto Kato <m_kato@ga2.so-net.ne.jp>
8 * Copyright (c) 1997 Guylhem Aznar <guylhem@oeil.qc.ca>
9 * Copyright (C) 1996 Rainer M. Canavan (canavan@Zeus.cs.bonn.edu)
10 * Copyright (C) 1996 Dan Weeks
11 * Copyright (C) 1994 Rob Nation
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 */
28
29 /*#define DO_CLOCKING */
30 #define LOCAL_DEBUG
31 #define EVENT_TRACE
32
33 #include "../../configure.h"
34 #include "../../libAfterStep/asapp.h"
35 #include <signal.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #ifdef HAVE_SYS_WAIT_H
39 #include <sys/wait.h>
40 #endif
41 #if TIME_WITH_SYS_TIME
42 # include <sys/time.h>
43 # include <time.h>
44 #else
45 # if HAVE_SYS_TIME_H
46 # include <sys/time.h>
47 # else
48 # include <time.h>
49 # endif
50 #endif
51 #define IN_MODULE
52 #define MODULE_X_INTERFACE
53
54 #include "../../libAfterStep/afterstep.h"
55 #include "../../libAfterStep/screen.h"
56 #include "../../libAfterStep/module.h"
57 #include "../../libAfterStep/parser.h"
58 #include "../../libAfterStep/mystyle.h"
59 #include "../../libAfterStep/mystyle_property.h"
60 #include "../../libAfterStep/balloon.h"
61 #include "../../libAfterStep/aswindata.h"
62 #include "../../libAfterStep/decor.h"
63 #include "../../libAfterStep/event.h"
64 #include "../../libAfterStep/wmprops.h"
65 #include "../../libAfterStep/moveresize.h"
66 #include "../../libAfterStep/shape.h"
67
68 #include "../../libAfterConf/afterconf.h"
69
70 /* pager flags - shared between PagerDEsk and PagerState */
71 #define ASP_DeskShaded (0x01<<0)
72 #define ASP_UseRootBackground (0x01<<1)
73 #define ASP_Shaped (0x01<<2)
74 #define ASP_ShapeDirty (0x01<<3)
75 #define ASP_ReceivingWindowList (0x01<<4)
76
77
78 typedef struct ASPagerDesk {
79
80 ASFlagType flags;
81 INT32 desk; /* absolute value - no need to add start_desk */
82 ASCanvas *desk_canvas;
83 ASTBarData *title;
84 ASTBarData *background;
85 Window *separator_bars; /* (rows-1)*(columns-1) */
86 XRectangle *separator_bar_rects;
87 unsigned int separator_bars_num;
88 unsigned int title_width, title_height;
89
90 ASWindowData **clients;
91 unsigned int clients_num;
92
93 ASImage *back;
94 } ASPagerDesk;
95
96 typedef struct ASPagerState {
97 ASFlagType flags;
98
99 ASCanvas *main_canvas;
100 ASCanvas *icon_canvas;
101
102 ASPagerDesk *desks;
103 INT32 start_desk, desks_num;
104
105 int page_rows, page_columns;
106 /* x and y size of desktop */
107 int desk_width, desk_height; /* adjusted for the size of title */
108 /* area of the main window used up by labels, borders and other garbadge : */
109 int wasted_width, wasted_height;
110 /* x and y size of virtual screen size inside desktop mini-window */
111 int vscreen_width, vscreen_height;
112 int aspect_x, aspect_y;
113
114 int wait_as_response;
115
116 ASCanvas *pressed_canvas;
117 ASTBarData *pressed_bar;
118 int pressed_context;
119 ASPagerDesk *pressed_desk;
120 int pressed_button;
121
122 ASPagerDesk *focused_desk;
123 ASPagerDesk *resize_desk; /* desk on which we are currently resizing the window */
124
125 Window selection_bars[4];
126 XRectangle selection_bar_rects[4];
127
128 ASTBarProps *tbar_props;
129
130 #define C_ShadeButton C_TButton0
131
132 MyButton shade_button;
133 } ASPagerState;
134
135 ASPagerState PagerState;
136 #define DEFAULT_BORDER_COLOR 0xFF808080
137
138 #define PAGE_MOVE_THRESHOLD 15 /* precent */
139
140 #define CLIENT_EVENT_MASK StructureNotifyMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|EnterWindowMask|LeaveWindowMask
141
142 /* Storing window list as hash table hashed by client window ID : */
143 ASHashTable *PagerClients = NULL;
144
145 PagerConfig *Config = NULL;
146 int Rows_override = 0;
147 int Columns_override = 0;
148
149 CommandLineOpts Pager_cmdl_options[3] = {
150 {NULL, "rows", "Overrides module's layout rows", NULL, handler_set_int,
151 &Rows_override, 0, CMO_HasArgs},
152 {NULL, "cols", "Overrides module's layout cols", NULL, handler_set_int,
153 &Columns_override, 0, CMO_HasArgs},
154 {NULL, NULL, NULL, NULL, NULL, NULL, 0}
155 };
156
157
pager_usage(void)158 void pager_usage (void)
159 {
160 printf (OPTION_USAGE_FORMAT " [--rows rows] [--cols cols] n m\n",
161 MyName);
162 print_command_line_opt ("standard_options are ",
163 as_standard_cmdl_options, ASS_Restarting);
164 print_command_line_opt ("additional options are ", Pager_cmdl_options,
165 0);
166 printf
167 ("The last two numbers n and m define a range of desktops to be displayed.\n");
168 exit (0);
169 }
170
171 void HandleEvents ();
172 void process_message (send_data_type type, send_data_type * body);
173 void DispatchEvent (ASEvent * Event);
174 void rearrange_pager_window ();
175 Window make_pager_window ();
176 void GetOptions (const char *filename);
177 void GetBaseOptions (const char *filename);
178 void CheckConfigSanity ();
179 void redecorate_pager_desks ();
180 void rearrange_pager_desks (Bool dont_resize_main);
181 void on_pager_window_moveresize (void *client, Window w, int x, int y,
182 unsigned int width, unsigned int height);
183 void on_pager_pressure_changed (ASEvent * event);
184 void release_pressure ();
185 void on_desk_moveresize (ASPagerDesk * d);
186 void on_scroll_viewport (ASEvent * event);
187 void place_separation_bars (ASPagerDesk * d);
188 void DeadPipe (int);
189 void request_background_image (ASPagerDesk * d);
190
191
192 /***********************************************************************
193 * main - start of module
194 ***********************************************************************/
main(int argc,char ** argv)195 int main (int argc, char **argv)
196 {
197 int i;
198 INT32 desk1 = 0, desk2 = 0;
199 int desk_cnt = 0;
200
201 /* Save our program name - for error messages */
202 set_DeadPipe_handler (DeadPipe);
203 InitMyApp (CLASS_PAGER, argc, argv, NULL, pager_usage, ASS_Restarting);
204 LinkAfterStepConfig ();
205
206 memset (&PagerState, 0x00, sizeof (PagerState));
207 PagerState.page_rows = PagerState.page_columns = 1;
208
209 for (i = 1; i < argc; ++i) {
210 LOCAL_DEBUG_OUT ("argv[%d] = \"%s\", original argv[%d] = \"%s\"", i,
211 argv[i], i, MyArgs.saved_argv[i]);
212 if (argv[i] != NULL) {
213 if (isdigit (argv[i][0])) {
214 ++desk_cnt;
215 if (desk_cnt == 1)
216 desk1 = atoi (argv[i]);
217 else if (desk_cnt == 2)
218 desk2 = atoi (argv[i]);
219 else
220 break;
221 } else if (strcmp (argv[i], "--rows") == 0 && i + 1 < argc
222 && argv[i + 1] != NULL) {
223 Rows_override = atoi (argv[++i]);
224 } else if (strcmp (argv[i], "--cols") == 0 && i + 1 < argc
225 && argv[i + 1] != NULL) {
226 Columns_override = atoi (argv[++i]);
227 }
228 }
229 }
230 LOCAL_DEBUG_OUT
231 ("desk1 = %ld, desk2 = %ld, desks = %ld, start_desk = %ld", desk1,
232 desk2, PagerState.desks_num, PagerState.start_desk);
233 if (desk2 < desk1) {
234 PagerState.desks_num = (desk1 - desk2) + 1;
235 PagerState.start_desk = desk2;
236 } else {
237 PagerState.desks_num = (desk2 - desk1) + 1;
238 PagerState.start_desk = desk1;
239 }
240
241 PagerState.desks =
242 safecalloc (PagerState.desks_num, sizeof (ASPagerDesk));
243 for (i = 0; i < PagerState.desks_num; ++i)
244 PagerState.desks[i].desk = PagerState.start_desk + i;
245
246 ConnectX (ASDefaultScr, EnterWindowMask);
247 if (ConnectAfterStep (M_ADD_WINDOW |
248 M_CONFIGURE_WINDOW |
249 M_STATUS_CHANGE |
250 M_DESTROY_WINDOW |
251 M_FOCUS_CHANGE |
252 M_NEW_DESKVIEWPORT |
253 M_NEW_BACKGROUND |
254 M_WINDOW_NAME |
255 M_ICON_NAME |
256 M_END_WINDOWLIST | M_STACKING_ORDER, 0) < 0)
257 exit (1); /* no AfterStep */
258
259 Config = CreatePagerConfig (PagerState.desks_num);
260
261 LOCAL_DEBUG_OUT ("parsing Options for \"%s\"", MyName);
262 LoadBaseConfig (GetBaseOptions);
263 LoadColorScheme ();
264 LoadConfig ("pager", GetOptions);
265
266 CheckConfigSanity ();
267
268 /* Create a list of all windows */
269 /* Request a list of all windows,
270 * wait for ConfigureWindow packets */
271 SendInfo ("Send_WindowList", 0);
272 set_flags (PagerState.flags, ASP_ReceivingWindowList);
273
274 PagerState.main_canvas = create_ascanvas (make_pager_window ());
275 redecorate_pager_desks ();
276 rearrange_pager_desks (False);
277
278 LOCAL_DEBUG_OUT ("starting The Loop ...%s", "");
279 HandleEvents ();
280
281 return 0;
282 }
283
HandleEvents()284 void HandleEvents ()
285 {
286 ASEvent event;
287 Bool has_x_events = False;
288 while (True) {
289 LOCAL_DEBUG_OUT ("wait_as_resp = %d", PagerState.wait_as_response);
290
291 while (PagerState.wait_as_response > 0) {
292 ASMessage *msg = CheckASMessage (WAIT_AS_RESPONSE_TIMEOUT);
293 if (msg) {
294 process_message (msg->header[1], msg->body);
295 DestroyASMessage (msg);
296 }
297 --PagerState.wait_as_response;
298 }
299 while ((has_x_events = XPending (dpy))) {
300 if (ASNextEvent (&(event.x), True)) {
301 event.client = NULL;
302 setup_asevent_from_xevent (&event);
303 DispatchEvent (&event);
304 }
305 }
306 module_wait_pipes_input (process_message);
307 }
308 }
309
DeadPipe(int nonsense)310 void DeadPipe (int nonsense)
311 {
312 static int already_dead = False;
313 int i;
314
315 if (already_dead)
316 return;
317 already_dead = True;
318
319 window_data_cleanup ();
320 destroy_ashash (&PagerClients);
321 for (i = 0; i < PagerState.desks_num; ++i) {
322 ASPagerDesk *d = &PagerState.desks[i];
323 destroy_astbar (&(d->title));
324 destroy_astbar (&(d->background));
325 destroy_ascanvas (&(d->desk_canvas));
326 if (d->separator_bars) {
327 int p;
328 for (p = 0; p < d->separator_bars_num; ++p)
329 if (d->separator_bars[p])
330 XDestroyWindow (dpy, d->separator_bars[p]);
331 free (d->separator_bars);
332 free (d->separator_bar_rects);
333 }
334 if (d->clients)
335 free (d->clients);
336 if (d->back)
337 safe_asimage_destroy (d->back);
338 }
339 destroy_ascanvas (&PagerState.main_canvas);
340 destroy_ascanvas (&PagerState.icon_canvas);
341
342 for (i = 0; i < 4; ++i) {
343 if (PagerState.selection_bars[i])
344 XDestroyWindow (dpy, PagerState.selection_bars[i]);
345 }
346
347 if (Config)
348 DestroyPagerConfig (Config);
349 destroy_astbar_props (&(PagerState.tbar_props));
350 free_button_resources (&PagerState.shade_button);
351
352 if (Config->MSDeskBack)
353 free (Config->MSDeskBack);
354 free (PagerState.desks);
355
356 FreeMyAppResources ();
357 #ifdef DEBUG_ALLOCS
358 print_unfreed_mem ();
359 #endif /* DEBUG_ALLOCS */
360
361 XFlush (dpy);
362 XCloseDisplay (dpy);
363 exit (0);
364 }
365
366
retrieve_pager_astbar_props()367 void retrieve_pager_astbar_props ()
368 {
369 destroy_astbar_props (&(PagerState.tbar_props));
370
371 PagerState.tbar_props = get_astbar_props (Scr.wmprops);
372
373 free_button_resources (&PagerState.shade_button);
374 PagerState.shade_button.context = C_NO_CONTEXT;
375 if (get_flags (Config->set_flags, PAGER_SET_SHADE_BUTTON)) {
376 if (Config->shade_button[0])
377 if (load_button
378 (&PagerState.shade_button, Config->shade_button,
379 Scr.image_manager))
380 PagerState.shade_button.context = C_ShadeButton;
381 } else
382 button_from_astbar_props (PagerState.tbar_props,
383 &PagerState.shade_button, C_ShadeButton,
384 _AS_BUTTON_SHADE, _AS_BUTTON_SHADE_PRESSED);
385 }
386
387
388 /*****************************************************************************
389 * This routine is responsible for reading and parsing the config file
390 ****************************************************************************/
391
CheckConfigSanity()392 void CheckConfigSanity ()
393 {
394 int i;
395 char buf[256];
396
397 if (Config == NULL)
398 Config = CreatePagerConfig (PagerState.desks_num);
399
400 if (Rows_override > 0)
401 Config->rows = Rows_override;
402 if (Columns_override > 0)
403 Config->columns = Columns_override;
404 LOCAL_DEBUG_OUT
405 ("columns = %d, rows = %d, desks = %ld, start_desk = %ld",
406 Config->columns, Config->rows, PagerState.desks_num,
407 PagerState.start_desk);
408 if (Config->rows > PagerState.desks_num)
409 Config->rows = PagerState.desks_num;
410 if (Config->rows == 0)
411 Config->rows = 1;
412
413 if (Config->columns == 0 ||
414 Config->rows * Config->columns != PagerState.desks_num)
415 Config->columns = PagerState.desks_num / Config->rows;
416
417 if (Config->rows * Config->columns < PagerState.desks_num)
418 ++(Config->columns);
419
420 LOCAL_DEBUG_OUT
421 ("columns = %d, rows = %d, desks = %ld, start_desk = %ld",
422 Config->columns, Config->rows, PagerState.desks_num,
423 PagerState.start_desk);
424
425 if (MyArgs.geometry.flags != 0)
426 Config->geometry = MyArgs.geometry;
427
428 LOCAL_DEBUG_OUT ("geometry = %dx%d%+d%+d", Config->geometry.width,
429 Config->geometry.height, Config->geometry.x,
430 Config->geometry.y);
431
432 if (get_flags (Config->geometry.flags, XNegative))
433 Config->gravity =
434 get_flags (Config->geometry.flags,
435 YNegative) ? SouthEastGravity : NorthEastGravity;
436 else if (get_flags (Config->geometry.flags, YNegative))
437 Config->gravity = SouthWestGravity;
438
439 if (MyArgs.gravity != ForgetGravity)
440 Config->gravity = MyArgs.gravity;
441
442 if (Config->geometry.width <= Config->columns)
443 clear_flags (Config->geometry.flags, WidthValue);
444 if (!get_flags (Config->geometry.flags, WidthValue))
445 Config->geometry.width =
446 (PagerState.vscreen_width * Config->columns) / Scr.VScale;
447
448 PagerState.desk_width = Config->geometry.width / Config->columns;
449 Config->geometry.width = PagerState.desk_width * Config->columns;
450
451 if (Config->geometry.height <= Config->rows)
452 clear_flags (Config->geometry.flags, HeightValue);
453 if (!get_flags (Config->geometry.flags, HeightValue)
454 || Config->geometry.height <= Config->rows)
455 Config->geometry.height =
456 (PagerState.vscreen_height * Config->rows) / Scr.VScale;
457
458 PagerState.desk_height = Config->geometry.height / Config->rows;
459 Config->geometry.height = PagerState.desk_height * Config->rows;
460
461 PagerState.wasted_width = PagerState.wasted_height = 0;
462
463 if (!get_flags (Config->geometry.flags, XValue)) {
464 Config->geometry.x = 0;
465 } else {
466 int real_x = Config->geometry.x;
467 if (get_flags (Config->geometry.flags, XNegative)) {
468 Config->gravity = NorthEastGravity;
469 real_x += (int)Scr.MyDisplayWidth;
470 }
471 if (real_x + (int)Config->geometry.width < 0)
472 Config->geometry.x = get_flags (Config->geometry.flags, XNegative) ?
473 (int)Config->geometry.width - (int)Scr.MyDisplayWidth : 0;
474 else if (real_x > (int)Scr.MyDisplayWidth)
475 Config->geometry.x = get_flags (Config->geometry.flags, XNegative) ?
476 0 : (int)Scr.MyDisplayWidth - (int)Config->geometry.width;
477 }
478 if (!get_flags (Config->geometry.flags, YValue)) {
479 Config->geometry.y = 0;
480 } else {
481 int real_y = Config->geometry.y;
482 if (get_flags (Config->geometry.flags, YNegative)) {
483 Config->gravity =
484 (Config->gravity ==
485 NorthEastGravity) ? SouthEastGravity : SouthWestGravity;
486 real_y += (int)Scr.MyDisplayHeight;
487 }
488 if (real_y + (int)Config->geometry.height < 0)
489 Config->geometry.y = get_flags (Config->geometry.flags, YNegative) ?
490 (int)Config->geometry.height - (int)Scr.MyDisplayHeight : 0;
491 else if (real_y > (int)Scr.MyDisplayHeight)
492 Config->geometry.y = get_flags (Config->geometry.flags, YNegative) ?
493 0 : (int)Scr.MyDisplayHeight - (int)Config->geometry.height;
494 }
495
496
497 if (get_flags (Config->set_flags, PAGER_SET_ICON_GEOMETRY)) {
498 if (!get_flags (Config->icon_geometry.flags, WidthValue)
499 || Config->icon_geometry.width <= 0)
500 Config->icon_geometry.width = 54;
501 if (!get_flags (Config->icon_geometry.flags, HeightValue)
502 || Config->icon_geometry.height <= 0)
503 Config->icon_geometry.height = 54;
504 } else {
505 Config->icon_geometry.width = 54;
506 Config->icon_geometry.height = 54;
507 }
508
509 parse_argb_color (Config->border_color, &(Config->border_color_argb));
510 parse_argb_color (Config->selection_color,
511 &(Config->selection_color_argb));
512 parse_argb_color (Config->grid_color, &(Config->grid_color_argb));
513
514
515 if (!get_flags (Config->set_flags, PAGER_SET_ACTIVE_BEVEL))
516 Config->active_desk_bevel = DEFAULT_TBAR_HILITE;
517 if (!get_flags (Config->set_flags, PAGER_SET_INACTIVE_BEVEL))
518 Config->inactive_desk_bevel = DEFAULT_TBAR_HILITE;
519
520 if (PagerState.tbar_props == NULL)
521 retrieve_pager_astbar_props ();
522
523 LOCAL_DEBUG_OUT ("active_bevel = %lX, inactive_bevel = %lX",
524 Config->active_desk_bevel, Config->inactive_desk_bevel);
525 mystyle_get_property (Scr.wmprops);
526
527 for (i = 0; i < BACK_STYLES; ++i) {
528 static char *window_style_names[BACK_STYLES] = { "*%sFWindowStyle",
529 "*%sUWindowStyle",
530 "*%sSWindowStyle", NULL
531 };
532 static char *default_window_style_name[BACK_STYLES] =
533 { "focused_window_style",
534 "unfocused_window_style",
535 "sticky_window_style", NULL
536 };
537 if (window_style_names[i]) {
538 sprintf (&(buf[0]), window_style_names[i], MyName);
539 if ((Scr.Look.MSWindow[i] = mystyle_find (buf)) == NULL
540 && i != BACK_URGENT)
541 Scr.Look.MSWindow[i] =
542 mystyle_find_or_default (default_window_style_name[i]);
543 }
544 }
545
546 if (Config->small_font_name) {
547 MyFont small_font = { NULL, NULL };
548 if (load_font (Config->small_font_name, &small_font)) {
549 mystyle_merge_font (Scr.Look.MSWindow[0], &small_font, True);
550 for (i = 1; i < BACK_STYLES; ++i)
551 if (Scr.Look.MSWindow[i])
552 mystyle_merge_font (Scr.Look.MSWindow[i], &small_font, True);
553 }
554 unload_font (&small_font);
555 }
556
557 for (i = 0; i < DESK_STYLES; ++i) {
558 static char *desk_style_names[DESK_STYLES] =
559 { "*%sActiveDesk", "*%sInActiveDesk" };
560
561 sprintf (buf, desk_style_names[i], MyName);
562 Config->MSDeskTitle[i] = mystyle_find_or_default (buf);
563 LOCAL_DEBUG_OUT ("desk_style %d: \"%s\" ->%p(\"%s\")->colors(%lX,%lX)",
564 i, buf, Config->MSDeskTitle[i],
565 Config->MSDeskTitle[i]->name,
566 Config->MSDeskTitle[i]->colors.fore,
567 Config->MSDeskTitle[i]->colors.back);
568 }
569
570 if (Config->MSDeskBack == NULL)
571 Config->MSDeskBack =
572 safecalloc (PagerState.desks_num, sizeof (MyStyle *));
573 for (i = 0; i < PagerState.desks_num; ++i) {
574 Config->MSDeskBack[i] = NULL;
575 if (Config->styles && Config->styles[i] != NULL)
576 Config->MSDeskBack[i] = mystyle_find (Config->styles[i]);
577
578 if (Config->MSDeskBack[i] == NULL) {
579 sprintf (buf, "*%sDesk%d", MyName, i + (int)PagerState.start_desk);
580 Config->MSDeskBack[i] = mystyle_find_or_default (buf);
581 }
582 }
583 /* shade button : */
584 Scr.Feel.EdgeResistanceMove = 5;
585 Scr.Feel.EdgeAttractionScreen = 5;
586 Scr.Feel.EdgeAttractionWindow = 10;
587 Scr.Feel.OpaqueMove = 100;
588 Scr.Feel.OpaqueResize = 100;
589 Scr.Feel.no_snaping_mod = ShiftMask;
590
591 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
592 Print_balloonConfig (Config->balloon_conf);
593 #endif
594 balloon_config2look (&(Scr.Look), NULL, Config->balloon_conf,
595 "*PagerBalloon");
596 set_balloon_look (Scr.Look.balloon_look);
597
598 LOCAL_DEBUG_OUT ("geometry = %dx%d%+d%+d", Config->geometry.width,
599 Config->geometry.height, Config->geometry.x,
600 Config->geometry.y);
601
602 }
603
GetOptions(const char * filename)604 void GetOptions (const char *filename)
605 {
606 PagerConfig *config =
607 ParsePagerOptions (filename, MyName, PagerState.start_desk,
608 PagerState.start_desk + PagerState.desks_num);
609 int i;
610 START_TIME (option_time);
611
612 /* WritePagerOptions( filename, MyName, Pager.desk1, Pager.desk2, config, WF_DISCARD_UNKNOWN|WF_DISCARD_COMMENTS );
613 */
614
615 /* Need to merge new config with what we have already : */
616 /* now lets check the config sanity : */
617 /* mixing set and default flags : */
618 Config->flags =
619 (config->flags & config->set_flags) | (Config->
620 flags & (~config->set_flags));
621 Config->set_flags |= config->set_flags;
622
623 if (get_flags (config->set_flags, PAGER_SET_ROWS))
624 Config->rows = config->rows;
625
626 if (get_flags (config->set_flags, PAGER_SET_COLUMNS))
627 Config->columns = config->columns;
628
629 Config->gravity = NorthWestGravity;
630 if (get_flags (config->set_flags, PAGER_SET_GEOMETRY))
631 merge_geometry (&(config->geometry), &(Config->geometry));
632
633 if (get_flags (config->set_flags, PAGER_SET_ICON_GEOMETRY))
634 merge_geometry (&(config->icon_geometry), &(Config->icon_geometry));
635
636 if (config->labels) {
637 if (Config->labels == NULL)
638 Config->labels = safecalloc (PagerState.desks_num, sizeof (char *));
639 for (i = 0; i < PagerState.desks_num; ++i)
640 if (config->labels[i])
641 set_string (&(Config->labels[i]), mystrdup (config->labels[i]));
642 }
643 if (config->styles) {
644 if (Config->styles == NULL)
645 Config->styles = safecalloc (PagerState.desks_num, sizeof (char *));
646 for (i = 0; i < PagerState.desks_num; ++i)
647 if (config->styles[i])
648 set_string (&(Config->styles[i]), mystrdup (config->styles[i]));
649 }
650 if (get_flags (config->set_flags, PAGER_SET_ALIGN))
651 Config->align = config->align;
652
653 if (get_flags (config->set_flags, PAGER_SET_SMALL_FONT))
654 set_string (&(Config->small_font_name),
655 mystrdup (config->small_font_name));
656
657 if (get_flags (config->set_flags, PAGER_SET_BORDER_WIDTH))
658 Config->border_width = config->border_width;
659
660 if (get_flags (config->set_flags, PAGER_SET_SELECTION_COLOR))
661 set_string (&(Config->selection_color),
662 mystrdup (config->selection_color));
663
664 if (get_flags (config->set_flags, PAGER_SET_GRID_COLOR))
665 set_string (&(Config->grid_color), mystrdup (config->grid_color));
666
667
668 if (get_flags (config->set_flags, PAGER_SET_BORDER_COLOR))
669 set_string (&(Config->border_color), mystrdup (config->border_color));
670
671 if (config->shade_button[0])
672 set_string (&(Config->shade_button[0]),
673 mystrdup (config->shade_button[0]));
674
675 if (config->shade_button[1])
676 set_string (&(Config->shade_button[1]),
677 mystrdup (config->shade_button[1]));
678
679 if (get_flags (config->set_flags, PAGER_SET_ACTIVE_BEVEL)) {
680 Config->active_desk_bevel = config->active_desk_bevel;
681 set_flags (Config->set_flags, PAGER_SET_ACTIVE_BEVEL);
682 }
683 if (get_flags (config->set_flags, PAGER_SET_INACTIVE_BEVEL)) {
684 Config->inactive_desk_bevel = config->inactive_desk_bevel;
685 set_flags (Config->set_flags, PAGER_SET_INACTIVE_BEVEL);
686 }
687
688 if (Config->balloon_conf)
689 Destroy_balloonConfig (Config->balloon_conf);
690 Config->balloon_conf = config->balloon_conf;
691 config->balloon_conf = NULL;
692
693 if (config->style_defs)
694 ProcessMyStyleDefinitions (&(config->style_defs));
695
696 DestroyPagerConfig (config);
697 SHOW_TIME ("Config parsing", option_time);
698 }
699
700 /*****************************************************************************
701 *
702 * This routine is responsible for reading and parsing the base file
703 *
704 ****************************************************************************/
GetBaseOptions(const char * filename)705 void GetBaseOptions (const char *filename)
706 {
707
708 START_TIME (started);
709
710 ReloadASEnvironment (NULL, NULL, NULL, False, True);
711
712 if (Environment->desk_pages_h > 0)
713 PagerState.page_columns = Environment->desk_pages_h;
714 if (Environment->desk_pages_v > 0)
715 PagerState.page_rows = Environment->desk_pages_v;
716
717 Scr.Vx = 0;
718 Scr.Vy = 0;
719 PagerState.vscreen_width = Scr.VxMax + Scr.MyDisplayWidth;
720 PagerState.vscreen_height = Scr.VyMax + Scr.MyDisplayHeight;
721
722 SHOW_TIME ("BaseConfigParsingTime", started);
723 LOCAL_DEBUG_OUT ("desk_size(%dx%d),vscreen_size(%dx%d),vscale(%d)",
724 PagerState.desk_width, PagerState.desk_height,
725 PagerState.vscreen_width, PagerState.vscreen_height,
726 Scr.VScale);
727 }
728
729 /********************************************************************/
730 /* showing our main window : */
731 /********************************************************************/
make_pager_window()732 Window make_pager_window ()
733 {
734 Window w;
735 XSizeHints shints;
736 ExtendedWMHints extwm_hints;
737 int x, y;
738 int width = Config->geometry.width;
739 int height = Config->geometry.height;
740 XSetWindowAttributes attr;
741 LOCAL_DEBUG_OUT ("configured geometry is %dx%d%+d%+d", width, height,
742 Config->geometry.x, Config->geometry.y);
743 switch (Config->gravity) {
744 case NorthEastGravity:
745 x = Scr.MyDisplayWidth - width + Config->geometry.x;
746 y = Config->geometry.y;
747 break;
748 case SouthEastGravity:
749 x = Scr.MyDisplayWidth - width + Config->geometry.x;
750 y = Scr.MyDisplayHeight - height + Config->geometry.y;
751 break;
752 case SouthWestGravity:
753 x = Config->geometry.x;
754 y = Scr.MyDisplayHeight - height + Config->geometry.y;
755 break;
756 case NorthWestGravity:
757 default:
758 x = Config->geometry.x;
759 y = Config->geometry.y;
760 break;
761 }
762 attr.event_mask =
763 StructureNotifyMask | ButtonPressMask | ButtonReleaseMask |
764 PointerMotionMask;
765 w = create_visual_window (Scr.asv, Scr.Root, x, y, width, height, 0,
766 InputOutput, CWEventMask, &attr);
767 set_client_names (w, MyName, MyName, AS_MODULE_CLASS, CLASS_PAGER);
768
769 Scr.RootClipArea.x = x;
770 Scr.RootClipArea.y = y;
771 Scr.RootClipArea.width = width;
772 Scr.RootClipArea.height = height;
773
774 shints.flags = USSize | PMinSize | PResizeInc | PWinGravity;
775 if (get_flags (Config->set_flags, PAGER_SET_GEOMETRY)
776 || get_flags (MyArgs.geometry.flags, XValue | YValue))
777 shints.flags |= USPosition;
778 else
779 shints.flags |= PPosition;
780
781 shints.min_width = Config->columns + Config->border_width;
782 shints.min_height = Config->rows + Config->border_width;
783 shints.width_inc = 1;
784 shints.height_inc = 1;
785 shints.win_gravity = Config->gravity;
786
787 extwm_hints.pid = getpid ();
788 extwm_hints.flags = EXTWM_PID | EXTWM_StateSet | EXTWM_TypeSet;
789 extwm_hints.type_flags = EXTWM_TypeMenu | EXTWM_TypeASModule;
790 extwm_hints.state_flags = EXTWM_StateSkipTaskbar | EXTWM_StateSkipPager;
791
792 set_client_hints (w, NULL, &shints, AS_DoesWmDeleteWindow, &extwm_hints);
793 set_client_cmd (w);
794
795 /* showing window to let user see that we are doing something */
796 XMapRaised (dpy, w);
797 LOCAL_DEBUG_OUT ("mapping main window at %ux%u%+d%+d", width, height, x,
798 y);
799 /* final cleanup */
800 XFlush (dpy);
801 sleep (1); /* we have to give AS a chance to spot us */
802 /* we will need to wait for PropertyNotify event indicating transition
803 into Withdrawn state, so selecting event mask: */
804 XSelectInput (dpy, w, PropertyChangeMask | StructureNotifyMask);
805 return w;
806 }
807
update_main_canvas_config()808 int update_main_canvas_config ()
809 {
810 int changes = handle_canvas_config (PagerState.main_canvas);
811 if (changes != 0)
812 set_root_clip_area (PagerState.main_canvas);
813 return changes;
814 }
815
place_desk_title(ASPagerDesk * d)816 static void place_desk_title (ASPagerDesk * d)
817 {
818 if (d->title) {
819 int x = 0, y = 0;
820 int width = d->title_width, height = d->title_height;
821 if (get_flags (Config->flags, VERTICAL_LABEL)) {
822 if (get_flags (Config->flags, LABEL_BELOW_DESK)
823 && !get_flags (d->flags, ASP_DeskShaded))
824 x = PagerState.desk_width - width - Config->border_width;
825 height = PagerState.desk_height - Config->border_width;
826 } else {
827 if (get_flags (Config->flags, LABEL_BELOW_DESK)
828 && !get_flags (d->flags, ASP_DeskShaded))
829 y = PagerState.desk_height - height - Config->border_width;
830 width = PagerState.desk_width - Config->border_width;
831 }
832 move_astbar (d->title, d->desk_canvas, x, y);
833 set_astbar_size (d->title, width, height);
834 }
835 }
836
place_desk_background(ASPagerDesk * d)837 static void place_desk_background (ASPagerDesk * d)
838 {
839 int x = 0, y = 0;
840 int width = PagerState.desk_width;
841 int height = PagerState.desk_height;
842 if (get_flags (Config->flags, USE_LABEL)) {
843 width -= Config->border_width;
844 height -= Config->border_width;
845
846 if (get_flags (Config->flags, VERTICAL_LABEL))
847 width -= d->title_width;
848 else
849 height -= d->title_height;
850
851
852 if (!get_flags (Config->flags, LABEL_BELOW_DESK)
853 || get_flags (d->flags, ASP_DeskShaded)) {
854 if (get_flags (Config->flags, VERTICAL_LABEL))
855 x = d->title_width;
856 else
857 y = d->title_height;
858 }
859 }
860 move_astbar (d->background, d->desk_canvas, x, y);
861 set_astbar_size (d->background, width, height);
862 }
863
render_desk(ASPagerDesk * d,Bool force)864 static Bool render_desk (ASPagerDesk * d, Bool force)
865 {
866 if (is_canvas_needs_redraw (d->desk_canvas))
867 force = True;
868
869 if (d->title)
870 if (force || DoesBarNeedsRendering (d->title))
871 render_astbar (d->title, d->desk_canvas);
872 if (force || DoesBarNeedsRendering (d->background))
873 render_astbar (d->background, d->desk_canvas);
874
875 if (d->desk_canvas->shape == NULL && get_flags (d->flags, ASP_Shaped)) {
876 clear_flags (d->flags, ASP_Shaped);
877 set_flags (d->flags, ASP_ShapeDirty);
878 } else if (d->desk_canvas->shape != NULL) {
879 set_flags (d->flags, ASP_Shaped);
880 set_flags (d->flags, ASP_ShapeDirty);
881 }
882
883 if (is_canvas_dirty (d->desk_canvas)) {
884 update_canvas_display (d->desk_canvas);
885 // update_pager_shape();
886 return True;
887 }
888 return False;
889 }
890
891 #if 0
892 static void update_desk_shape (ASPagerDesk * d)
893 {
894 int i;
895
896 if (d == NULL)
897 return;
898
899 update_canvas_display_mask (d->desk_canvas, True);
900
901 LOCAL_DEBUG_CALLER_OUT ("desk %p flags = 0x%lX", d, d->flags);
902 if (get_flags (Config->flags, SHOW_SELECTION)
903 && d->desk == Scr.CurrentDesk) {
904 XShapeCombineRectangles (dpy, d->desk_canvas->w, ShapeBounding, 0, 0,
905 &(PagerState.selection_bar_rects[0]), 4,
906 ShapeUnion, Unsorted);
907 LOCAL_DEBUG_OUT ("added selection_bar_rects to shape%s", "");
908 }
909 if (get_flags (Config->flags, PAGE_SEPARATOR)) {
910 XShapeCombineRectangles (dpy, d->desk_canvas->w, ShapeBounding,
911 0, 0, &(d->separator_bar_rects[0]),
912 d->separator_bars_num, ShapeUnion, Unsorted);
913 LOCAL_DEBUG_OUT ("added %d separator_bar_rects to shape",
914 d->separator_bars_num);
915 #if 0
916 i = d->separator_bars_num;
917 while (--i >= 0) {
918 LOCAL_DEBUG_OUT ("\t %dx%d%+d%+d", d->separator_bar_rects[i].width,
919 d->separator_bar_rects[i].height,
920 d->separator_bar_rects[i].x,
921 d->separator_bar_rects[i].y);
922 }
923 #endif
924 }
925
926 if (d->clients_num > 0) {
927 register ASWindowData **clients = d->clients;
928 i = d->clients_num;
929 LOCAL_DEBUG_OUT ("clients_num %d", d->clients_num);
930 while (--i >= 0) {
931 LOCAL_DEBUG_OUT ("client %d data %p", i, clients[i]);
932 if (clients[i]) {
933 LOCAL_DEBUG_OUT ("combining client \"%s\"", clients[i]->icon_name);
934 combine_canvas_shape (d->desk_canvas, clients[i]->canvas, False,
935 True);
936 }
937 }
938 }
939 clear_flags (d->flags, ASP_ShapeDirty);
940 }
941 #endif
942
update_pager_shape()943 void update_pager_shape ()
944 {
945 #ifdef SHAPE
946 int i;
947 Bool shape_cleared = False;
948 XRectangle border[4];
949
950 if (get_flags (PagerState.flags, ASP_ReceivingWindowList))
951 return;
952
953 LOCAL_DEBUG_CALLER_OUT ("pager flags = 0x%lX", PagerState.flags);
954
955 if (get_flags (PagerState.flags, ASP_ShapeDirty)) {
956 shape_cleared = True;
957 clear_flags (PagerState.flags, ASP_ShapeDirty);
958 }
959
960 if (PagerState.main_canvas->shape)
961 flush_vector (PagerState.main_canvas->shape);
962 else
963 PagerState.main_canvas->shape = create_shape ();
964
965 for (i = 0; i < PagerState.desks_num; ++i) {
966 ASPagerDesk *d = &(PagerState.desks[i]);
967 int x, y;
968 unsigned int d_width, d_height, bw;
969
970 #ifdef STRICT_GEOMETRY
971 get_current_canvas_geometry (d->desk_canvas, &x, &y, &d_width,
972 &d_height, &bw);
973 #else
974 x = d->desk_canvas->root_x - PagerState.main_canvas->root_x;
975 y = d->desk_canvas->root_y - PagerState.main_canvas->root_y;
976 d_width = d->desk_canvas->width;
977 d_height = d->desk_canvas->height;
978 bw = Config->border_width;
979 #endif
980
981 LOCAL_DEBUG_OUT ("desk geometry = %dx%d%+d%+d, bw = %d", d_width,
982 d_height, x, y, bw);
983 combine_canvas_shape_at_geom (PagerState.main_canvas, d->desk_canvas,
984 x, y, d_width, d_height, bw);
985
986 if (Config->MSDeskBack[i]->texture_type == TEXTURE_SHAPED_PIXMAP ||
987 Config->MSDeskBack[i]->texture_type ==
988 TEXTURE_SHAPED_SCALED_PIXMAP) {
989 if (get_flags (Config->flags, SHOW_SELECTION)
990 && d->desk == Scr.CurrentDesk)
991 add_shape_rectangles (PagerState.main_canvas->shape,
992 &(PagerState.selection_bar_rects[0]), 4, x,
993 y, PagerState.main_canvas->width,
994 PagerState.main_canvas->height);
995
996 if (get_flags (Config->flags, PAGE_SEPARATOR))
997 add_shape_rectangles (PagerState.main_canvas->shape,
998 &(d->separator_bar_rects[0]),
999 d->separator_bars_num, x, y,
1000 PagerState.main_canvas->width,
1001 PagerState.main_canvas->height);
1002
1003 if (d->clients_num > 0) {
1004 register ASWindowData **clients = d->clients;
1005 int k = d->clients_num;
1006 LOCAL_DEBUG_OUT ("desk %d clients_num %d", i, d->clients_num);
1007 while (--k >= 0) {
1008 LOCAL_DEBUG_OUT ("client %d data %p", i, clients[k]);
1009 if (clients[k] && clients[k]->canvas) {
1010 int client_x, client_y;
1011 unsigned int client_width, client_height, client_bw;
1012 get_current_canvas_geometry (clients[k]->canvas, &client_x,
1013 &client_y, &client_width,
1014 &client_height, &client_bw);
1015
1016 LOCAL_DEBUG_OUT ("combining client \"%s\"",
1017 clients[k]->icon_name);
1018 combine_canvas_shape_at_geom (PagerState.main_canvas,
1019 clients[k]->canvas, client_x + x,
1020 client_y + y, client_width,
1021 client_height, client_bw);
1022 }
1023 }
1024 }
1025 }
1026 clear_flags (d->flags, ASP_ShapeDirty);
1027 }
1028
1029 border[0].x = 0;
1030 border[0].y = PagerState.main_canvas->height - Config->border_width;
1031 border[0].width = PagerState.main_canvas->width;
1032 border[0].height = Config->border_width;
1033 border[1].x = PagerState.main_canvas->width - Config->border_width;
1034 border[1].y = 0;
1035 border[1].width = Config->border_width;
1036 border[1].height = PagerState.main_canvas->height;
1037 #if 1
1038 border[2].x = 0;
1039 border[2].y = 0;
1040 border[2].width = PagerState.main_canvas->width;
1041 border[2].height = Config->border_width;
1042 border[3].x = 0;
1043 border[3].y = 0;
1044 border[3].width = Config->border_width;
1045 border[3].height = PagerState.main_canvas->height;
1046 #endif
1047
1048 add_shape_rectangles (PagerState.main_canvas->shape, &(border[0]), 4, 0,
1049 0, PagerState.main_canvas->width,
1050 PagerState.main_canvas->height);
1051
1052 update_canvas_display_mask (PagerState.main_canvas, True);
1053
1054 #endif
1055 }
1056
1057
calculate_desk_width(ASPagerDesk * d)1058 inline unsigned int calculate_desk_width (ASPagerDesk * d)
1059 {
1060 unsigned int width = PagerState.desk_width;
1061
1062 if (get_flags (Config->flags, VERTICAL_LABEL) && d->title_width > 0) {
1063 if (get_flags (d->flags, ASP_DeskShaded))
1064 width = d->title_width + Config->border_width;
1065 }
1066 return width;
1067 }
1068
calculate_desk_height(ASPagerDesk * d)1069 unsigned int calculate_desk_height (ASPagerDesk * d)
1070 {
1071 unsigned int height = PagerState.desk_height;
1072
1073 if (!get_flags (Config->flags, VERTICAL_LABEL) && d->title_height > 0) {
1074 if (get_flags (d->flags, ASP_DeskShaded))
1075 height = d->title_height + Config->border_width;
1076 }
1077 return height;
1078 }
1079
place_desk(ASPagerDesk * d,int x,int y,unsigned int width,unsigned int height)1080 void place_desk (ASPagerDesk * d, int x, int y, unsigned int width,
1081 unsigned int height)
1082 {
1083 int win_x = 0, win_y = 0;
1084 unsigned int bw;
1085 get_canvas_position (d->desk_canvas, NULL, &win_x, &win_y, &bw);
1086 LOCAL_DEBUG_OUT
1087 ("desk window %lX, curr_geom = %dx%d%+d%+d, bw = %d, new_geom = %dx%d%+d%+d",
1088 d->desk_canvas->w, d->desk_canvas->width, d->desk_canvas->height,
1089 win_x, win_y, bw, width, height, x, y);
1090 if (d->desk_canvas->width == width && d->desk_canvas->height == height
1091 && win_x == x && win_y == y) {
1092 on_desk_moveresize (d);
1093 } else
1094 moveresize_canvas (d->desk_canvas, x, y, width, height);
1095 }
1096
get_pager_desk(INT32 desk)1097 inline ASPagerDesk *get_pager_desk (INT32 desk)
1098 {
1099 if (IsValidDesk (desk)) {
1100 register INT32 pager_desk = desk - PagerState.start_desk;
1101 if (pager_desk >= 0 && pager_desk < PagerState.desks_num)
1102 return &(PagerState.desks[pager_desk]);
1103 }
1104 return NULL;
1105 }
1106
restack_desk_windows(ASPagerDesk * d)1107 void restack_desk_windows (ASPagerDesk * d)
1108 {
1109 Window *list, *curr;
1110 int win_count = 0;
1111 int i, k;
1112 if (d == NULL)
1113 return;
1114
1115 win_count = d->clients_num;
1116 if (get_flags (Config->flags, SHOW_SELECTION)
1117 && d->desk == Scr.CurrentDesk)
1118 win_count += 4;
1119 if (get_flags (Config->flags, PAGE_SEPARATOR))
1120 win_count += d->separator_bars_num;
1121
1122 if (win_count <= 1)
1123 return;
1124
1125 curr = list = safecalloc (win_count, sizeof (Window));
1126 k = 0;
1127
1128 if (get_flags (Config->flags, SHOW_SELECTION)
1129 && d->desk == Scr.CurrentDesk)
1130 for (i = 0; i < 4; ++i) {
1131 if (PagerState.selection_bars[i]) {
1132 curr[k] = PagerState.selection_bars[i];
1133 ++k;
1134 }
1135 }
1136
1137 if (get_flags (Config->flags, PAGE_SEPARATOR)) {
1138 register Window *sbars = d->separator_bars;
1139 i = d->separator_bars_num;
1140 while (--i >= 0) {
1141 if (sbars[i]) {
1142 curr[k] = sbars[i];
1143 ++k;
1144 }
1145 }
1146 }
1147
1148 if (d->clients_num > 0) {
1149 register ASWindowData **clients = d->clients;
1150 i = -1;
1151 while (++i < d->clients_num) {
1152 if (clients[i] && clients[i]->desk == d->desk &&
1153 clients[i]->canvas && clients[i]->canvas->w) {
1154 LOCAL_DEBUG_OUT
1155 ("k = %d, w = %lX, client = %lX, wd = %p, name = \"%s\"", k,
1156 clients[i]->canvas->w, clients[i]->client, clients[i],
1157 clients[i]->window_name ? clients[i]->window_name : "(null)");
1158 curr[k++] = clients[i]->canvas->w;
1159 }
1160 }
1161 }
1162
1163 XRaiseWindow (dpy, list[0]);
1164 XRestackWindows (dpy, list, k);
1165 free (list);
1166 }
1167
place_separation_bars(ASPagerDesk * d)1168 void place_separation_bars (ASPagerDesk * d)
1169 {
1170 register Window *wa = d ? d->separator_bars : NULL;
1171 register XRectangle *wrecta = d ? d->separator_bar_rects : NULL;
1172 if (wa) {
1173 register int p = PagerState.page_columns - 1;
1174 int pos_inc =
1175 (Scr.MyDisplayWidth * d->background->width) /
1176 PagerState.vscreen_width;
1177 /* d->background->width/PagerState.page_columns ; */
1178 int pos = d->background->win_x + p * pos_inc;
1179 int size = d->background->height;
1180 int pos2 = d->background->win_y;
1181 /* vertical bars : */
1182 while (--p >= 0) {
1183 wrecta[p].x = pos;
1184 wrecta[p].y = pos2;
1185 wrecta[p].width = 1;
1186 wrecta[p].height = size;
1187 XMoveResizeWindow (dpy, wa[p], pos, pos2, 1, size);
1188 pos -= pos_inc;
1189 }
1190 /* horizontal bars */
1191 wa += PagerState.page_columns - 1;
1192 wrecta += PagerState.page_columns - 1;
1193 p = PagerState.page_rows - 1;
1194 pos_inc =
1195 (Scr.MyDisplayHeight * d->background->height) /
1196 PagerState.vscreen_height;
1197 /* Scr.MyDisplayHeight/PagerState.vscale_v; */
1198 /* d->background->height/PagerState.page_rows ; */
1199 pos = d->background->win_y + p * pos_inc;
1200 pos2 = d->background->win_x;
1201 size = d->background->width;
1202 while (--p >= 0) {
1203 wrecta[p].x = pos2;
1204 wrecta[p].y = pos;
1205 wrecta[p].width = size;
1206 wrecta[p].height = 1;
1207 XMoveResizeWindow (dpy, wa[p], pos2, pos, size, 1);
1208 pos -= pos_inc;
1209 }
1210 }
1211 }
1212
place_selection()1213 void place_selection ()
1214 {
1215 LOCAL_DEBUG_CALLER_OUT ("Scr.CurrentDesk(%d)->start_desk(%ld)",
1216 Scr.CurrentDesk, PagerState.start_desk);
1217 if (get_flags (Config->flags, SHOW_SELECTION)) {
1218 ASPagerDesk *sel_desk = get_pager_desk (Scr.CurrentDesk);
1219
1220 if (sel_desk != NULL && sel_desk->background && sel_desk->desk_canvas) {
1221 int sel_x = sel_desk->background->win_x;
1222 int sel_y = sel_desk->background->win_y;
1223 int page_width = /*Scr.MyDisplayWidth/PagerState.vscale_h ; */
1224 (Scr.MyDisplayWidth * sel_desk->background->width) /
1225 PagerState.vscreen_width;
1226 int page_height = /* Scr.MyDisplayHeight/PagerState.vscale_v ; */
1227 (Scr.MyDisplayHeight * sel_desk->background->height) /
1228 PagerState.vscreen_height;
1229 int i = 4;
1230
1231 sel_x += (Scr.Vx * page_width) / Scr.MyDisplayWidth;
1232 sel_y += (Scr.Vy * page_height) / Scr.MyDisplayHeight;
1233 LOCAL_DEBUG_OUT ("sel_pos(%+d%+d)->page_size(%dx%d)->desk(%ld)",
1234 sel_x, sel_y, page_width, page_height,
1235 sel_desk->desk);
1236 while (--i >= 0)
1237 XReparentWindow (dpy, PagerState.selection_bars[i],
1238 sel_desk->desk_canvas->w, -10, -10);
1239
1240 PagerState.selection_bar_rects[0].x = sel_x - 1;
1241 PagerState.selection_bar_rects[0].y = sel_y - 1;
1242 PagerState.selection_bar_rects[0].width = page_width + 2;
1243 PagerState.selection_bar_rects[0].height = 1;
1244
1245 PagerState.selection_bar_rects[1].x = sel_x - 1;
1246 PagerState.selection_bar_rects[1].y = sel_y - 1;
1247 PagerState.selection_bar_rects[1].width = 1;
1248 PagerState.selection_bar_rects[1].height = page_height + 2;
1249
1250 PagerState.selection_bar_rects[2].x = sel_x - 1;
1251 PagerState.selection_bar_rects[2].y = sel_y + page_height + 1;
1252 PagerState.selection_bar_rects[2].width = page_width + 2;
1253 PagerState.selection_bar_rects[2].height = 1;
1254
1255 PagerState.selection_bar_rects[3].x = sel_x + page_width + 1;
1256 PagerState.selection_bar_rects[3].y = sel_y - 1;
1257 PagerState.selection_bar_rects[3].width = 1;
1258 PagerState.selection_bar_rects[3].height = page_height + 2;
1259
1260 if (!get_flags (sel_desk->flags, ASP_DeskShaded)) {
1261 i = 4;
1262 while (--i >= 0)
1263 XMoveResizeWindow (dpy, PagerState.selection_bars[i],
1264 PagerState.selection_bar_rects[i].x,
1265 PagerState.selection_bar_rects[i].y,
1266 PagerState.selection_bar_rects[i].width,
1267 PagerState.selection_bar_rects[i].height);
1268 }
1269 XMapSubwindows (dpy, sel_desk->desk_canvas->w);
1270 ASSync (False);
1271 restack_desk_windows (sel_desk);
1272 set_flags (sel_desk->flags, ASP_ShapeDirty);
1273 }
1274 }
1275 }
1276
redecorate_pager_desks()1277 void redecorate_pager_desks ()
1278 {
1279 /* need to create enough desktop canvases */
1280 int i;
1281 char buf[256];
1282 XSetWindowAttributes attr;
1283 int wasted_x = Config->border_width * (Config->columns);
1284 int wasted_y = Config->border_width * (Config->rows);
1285 int max_title_width = 0;
1286 int max_title_height = 0;
1287
1288 for (i = 0; i < PagerState.desks_num; ++i) {
1289 ASPagerDesk *d = &(PagerState.desks[i]);
1290 int p;
1291 Bool just_created_background = False;
1292
1293 ARGB2PIXEL (Scr.asv, Config->border_color_argb, &(attr.border_pixel));
1294 if (d->desk_canvas == NULL) {
1295 Window w;
1296 attr.event_mask =
1297 StructureNotifyMask | ButtonReleaseMask | ButtonPressMask |
1298 ButtonMotionMask;
1299
1300 w = create_visual_window (Scr.asv, PagerState.main_canvas->w, 0, 0,
1301 PagerState.desk_width,
1302 PagerState.desk_height,
1303 Config->border_width, InputOutput,
1304 CWEventMask | CWBorderPixel, &attr);
1305 d->desk_canvas = create_ascanvas (w);
1306 LOCAL_DEBUG_OUT
1307 ("+CREAT canvas(%p)->desk(%ld)->geom(%dx%d%+d%+d)->parent(%lx)",
1308 d->desk_canvas, PagerState.start_desk + i,
1309 PagerState.desk_width, PagerState.desk_height, 0, 0,
1310 PagerState.main_canvas->w);
1311 handle_canvas_config (d->desk_canvas);
1312 } else {
1313 XSetWindowBorder (dpy, d->desk_canvas->w, attr.border_pixel);
1314 }
1315 /* create & moveresize label bar : */
1316 if (get_flags (Config->flags, USE_LABEL)) {
1317 int align = Config->align;
1318 ASFlagType ibevel = Config->inactive_desk_bevel;
1319 ASFlagType abevel = Config->active_desk_bevel;
1320 int h_spacing = Config->h_spacing;
1321 int v_spacing = Config->v_spacing;
1322 int flip =
1323 get_flags (Config->flags, VERTICAL_LABEL) ? FLIP_VERTICAL : 0;
1324 Bool just_created = False;
1325
1326 if (!get_flags (Config->set_flags, PAGER_SET_ALIGN))
1327 align = PagerState.tbar_props->align;
1328 if (!get_flags (Config->set_flags, PAGER_SET_ACTIVE_BEVEL))
1329 abevel = PagerState.tbar_props->bevel;
1330 if (!get_flags (Config->set_flags, PAGER_SET_INACTIVE_BEVEL))
1331 ibevel = PagerState.tbar_props->bevel;
1332 h_spacing = PagerState.tbar_props->title_h_spacing;
1333 v_spacing = PagerState.tbar_props->title_v_spacing;
1334
1335 if (d->title == NULL) {
1336 d->title = create_astbar ();
1337 d->title->context = C_TITLE;
1338 just_created = True;
1339 } else /* delete label if it was previously created : */
1340 delete_astbar_tile (d->title, -1);
1341
1342 set_astbar_hilite (d->title, BAR_STATE_UNFOCUSED, ibevel);
1343 set_astbar_hilite (d->title, BAR_STATE_FOCUSED, abevel);
1344
1345 set_astbar_style_ptr (d->title, -1,
1346 Config->MSDeskTitle[DESK_ACTIVE]);
1347 set_astbar_style_ptr (d->title, BAR_STATE_UNFOCUSED,
1348 Config->MSDeskTitle[DESK_INACTIVE]);
1349
1350 if (Config->labels && Config->labels[i])
1351 add_astbar_label (d->title, 0, flip ? 1 : 0, flip, align,
1352 h_spacing, v_spacing, Config->labels[i],
1353 AS_Text_ASCII);
1354 else {
1355 sprintf (buf, "Desk %d", (int)PagerState.start_desk + i);
1356 add_astbar_label (d->title, 0, flip ? 1 : 0, flip, align,
1357 h_spacing, v_spacing, buf, AS_Text_ASCII);
1358 }
1359 if (PagerState.shade_button.context != C_NO_CONTEXT) {
1360 MyButton *list[1];
1361 list[0] = &(PagerState.shade_button);
1362 add_astbar_btnblock (d->title, flip ? 0 : 1, 0, flip, NO_ALIGN,
1363 &list[0], 0xFFFFFFFF, 1,
1364 PagerState.tbar_props->buttons_h_border,
1365 PagerState.tbar_props->buttons_v_border,
1366 PagerState.tbar_props->buttons_spacing, 0);
1367 }
1368 if (get_flags (Config->flags, VERTICAL_LABEL)) {
1369 int size = calculate_astbar_width (d->title);
1370 if (size > max_title_width)
1371 max_title_width = size;
1372 d->title_height =
1373 PagerState.desk_height - Config->border_width * 2;
1374 /*we do it below using max_title_width : wasted_x += d->title_width ; */
1375 } else {
1376 int size = calculate_astbar_height (d->title);
1377 LOCAL_DEBUG_OUT ("size = %d, max_title_height = %d", size,
1378 max_title_height);
1379 d->title_width = PagerState.desk_width - Config->border_width * 2;
1380 if (size > max_title_height)
1381 max_title_height = size;
1382 /*we do it below using max_title_height : wasted_y += d->title_height ; */
1383 }
1384 } else {
1385 if (d->title)
1386 destroy_astbar (&(d->title));
1387 d->title_width = d->title_height = 0;
1388 }
1389
1390 /* create & moveresize desktop background bar : */
1391 if (d->background == NULL) {
1392 d->background = create_astbar ();
1393 just_created_background = True;
1394 }
1395
1396 set_astbar_style_ptr (d->background, -1, Config->MSDeskBack[i]);
1397 set_astbar_style_ptr (d->background, BAR_STATE_UNFOCUSED,
1398 Config->MSDeskBack[i]);
1399 if (Config->styles[i] == NULL)
1400 set_flags (d->flags, ASP_UseRootBackground);
1401
1402 if (just_created_background)
1403 place_desk_background (d);
1404 if (get_flags (d->flags, ASP_UseRootBackground))
1405 request_background_image (d);
1406
1407 if (d->separator_bars) {
1408 for (p = 0; p < d->separator_bars_num; ++p)
1409 if (d->separator_bars[p])
1410 XDestroyWindow (dpy, d->separator_bars[p]);
1411 free (d->separator_bars);
1412 free (d->separator_bar_rects);
1413 d->separator_bars_num = 0;
1414 d->separator_bars = NULL;
1415 d->separator_bar_rects = NULL;
1416 }
1417 if (get_flags (Config->flags, PAGE_SEPARATOR)) {
1418 d->separator_bars_num =
1419 PagerState.page_columns - 1 + PagerState.page_rows - 1;
1420 d->separator_bars =
1421 safecalloc (d->separator_bars_num, sizeof (Window));
1422 d->separator_bar_rects =
1423 safecalloc (d->separator_bars_num, sizeof (XRectangle));
1424 ARGB2PIXEL (Scr.asv, Config->grid_color_argb,
1425 &(attr.background_pixel));
1426 for (p = 0; p < d->separator_bars_num; ++p) {
1427 d->separator_bars[p] =
1428 create_visual_window (Scr.asv, d->desk_canvas->w, 0, 0, 1, 1,
1429 0, InputOutput, CWBackPixel, &attr);
1430 d->separator_bar_rects[p].width =
1431 d->separator_bar_rects[p].height = 1;
1432 }
1433 XMapSubwindows (dpy, d->desk_canvas->w);
1434 place_separation_bars (d);
1435 }
1436 }
1437
1438 if (get_flags (Config->flags, USE_LABEL)) {
1439 for (i = 0; i < PagerState.desks_num; ++i) { /* create & moveresize label bar : */
1440 ASPagerDesk *d = &(PagerState.desks[i]);
1441
1442 if (get_flags (Config->flags, VERTICAL_LABEL))
1443 d->title_width = max_title_width;
1444 else
1445 d->title_height = max_title_height;
1446 place_desk_title (d);
1447 }
1448
1449 if (get_flags (Config->flags, VERTICAL_LABEL)) {
1450 wasted_x += max_title_width * Config->columns;
1451 LOCAL_DEBUG_OUT ("title_width = %d", max_title_width);
1452 } else {
1453 wasted_y += max_title_height * Config->rows;
1454 LOCAL_DEBUG_OUT ("title_height = %d", max_title_height);
1455 }
1456 }
1457
1458 /* if wasted space changed and configured geometry does not specify size -
1459 * adjust desk_width/height accordingly :
1460 */
1461 if (!get_flags (Config->geometry.flags, WidthValue)) {
1462 int delta = (wasted_x - PagerState.wasted_width) / Config->columns;
1463 LOCAL_DEBUG_OUT
1464 ("wasted_x = %d, (old was = %d) - adjusting desk_width by %d",
1465 wasted_x, PagerState.wasted_width, delta);
1466 if (delta != 0) {
1467 PagerState.desk_width += delta;
1468 PagerState.wasted_width += delta * Config->columns;
1469 }
1470 }
1471 if (!get_flags (Config->geometry.flags, HeightValue)) {
1472 int delta = (wasted_y - PagerState.wasted_height) / Config->rows;
1473 LOCAL_DEBUG_OUT
1474 (" :RESIZING: wasted_y = %d, (old was = %d) - adjusting desk_height(%d) by %d",
1475 wasted_y, PagerState.wasted_height, PagerState.desk_height,
1476 delta);
1477 if (delta != 0) {
1478 PagerState.desk_height += delta;
1479 PagerState.wasted_height += delta * Config->rows;
1480 }
1481 }
1482
1483 /* selection bars : */
1484 ARGB2PIXEL (Scr.asv, Config->selection_color_argb,
1485 &(attr.background_pixel));
1486 if (get_flags (Config->flags, SHOW_SELECTION)) {
1487 for (i = 0; i < 4; i++)
1488 if (PagerState.selection_bars[i] == None) {
1489 PagerState.selection_bars[i] =
1490 create_visual_window (Scr.asv, PagerState.main_canvas->w, 0, 0,
1491 1, 1, 0, InputOutput, CWBackPixel,
1492 &attr);
1493 } else {
1494 XSetWindowBackground (dpy, PagerState.selection_bars[i],
1495 attr.background_pixel);
1496 XClearWindow (dpy, PagerState.selection_bars[i]);
1497 }
1498 } else
1499 for (i = 0; i < 4; i++)
1500 if (PagerState.selection_bars[i] != None) {
1501 XDestroyWindow (dpy, PagerState.selection_bars[i]);
1502 PagerState.selection_bars[i] = None;
1503 }
1504 XMapSubwindows (dpy, PagerState.main_canvas->w);
1505 }
1506
rearrange_pager_desks(Bool dont_resize_main)1507 void rearrange_pager_desks (Bool dont_resize_main)
1508 {
1509 /* need to create enough desktop canvases */
1510 int i;
1511 int col = 0;
1512 int x = 0, y = 0, row_height = 0;
1513 /* Pass 1: first we must resize or main window !!! */
1514 update_main_canvas_config ();
1515 if (!dont_resize_main) {
1516 int all_width = 0, all_height = 0;
1517 for (i = 0; i < PagerState.desks_num; ++i) {
1518 ASPagerDesk *d = &(PagerState.desks[i]);
1519 int width, height;
1520
1521 width = calculate_desk_width (d);
1522 height = calculate_desk_height (d);
1523
1524 if (height > row_height)
1525 row_height = height;
1526
1527 if (++col >= Config->columns) {
1528 if (all_width < x + width)
1529 all_width = x + width;
1530 y += row_height;
1531
1532 row_height = 0;
1533 x = 0;
1534 col = 0;
1535 } else
1536 x += width;
1537 LOCAL_DEBUG_OUT
1538 (" :RESIZING: desk = %d, size = %dx%d, all_size = %+d%+d, +x+y = %+d%+d, row_height = %d",
1539 i, width, height, all_width, all_height, x, y, row_height);
1540
1541 }
1542 if (all_width < x)
1543 all_width = x;
1544 if (all_height < y + row_height)
1545 all_height = y + row_height;
1546 all_width += Config->border_width;
1547 all_height += Config->border_width;
1548 LOCAL_DEBUG_OUT
1549 (" :RESIZING: resizing_main : all_size = %dx%d current size = %dx%d",
1550 all_width, all_height, PagerState.main_canvas->width,
1551 PagerState.main_canvas->height);
1552 if (PagerState.main_canvas->width != all_width
1553 || PagerState.main_canvas->height != all_height) {
1554 resize_canvas (PagerState.main_canvas, all_width, all_height);
1555 return;
1556 }
1557 }
1558 /* Pass 2: now we can resize the rest of the windows : */
1559 col = 0;
1560 x = y = 0;
1561 row_height = 0;
1562 for (i = 0; i < PagerState.desks_num; ++i) {
1563 ASPagerDesk *d = &(PagerState.desks[i]);
1564 int width, height;
1565
1566 width = calculate_desk_width (d);
1567 height = calculate_desk_height (d);
1568
1569 place_desk (d, x, y, width - Config->border_width,
1570 height - Config->border_width);
1571
1572 if (height > row_height)
1573 row_height = height;
1574
1575 if (++col >= Config->columns) {
1576 y += row_height;
1577 row_height = 0;
1578 x = 0;
1579 col = 0;
1580 } else
1581 x += width;
1582 }
1583 ASSync (False);
1584 }
1585
calculate_pager_desk_width()1586 unsigned int calculate_pager_desk_width ()
1587 {
1588 int main_width = PagerState.main_canvas->width - Config->border_width;
1589 if (!get_flags (Config->flags, VERTICAL_LABEL))
1590 return main_width / Config->columns;
1591 else {
1592 unsigned int unshaded_col_count = 0;
1593 unsigned int shaded_width = 0;
1594 int col = 0;
1595 /* we have to calculate the number of not-shaded columns,
1596 * and then devide size of the main canvas by this number : */
1597 for (col = 0; col < Config->columns; ++col) {
1598 unsigned int col_shaded_width = 0;
1599 int i;
1600
1601 for (i = col; i < PagerState.desks_num; i += Config->columns) {
1602 ASPagerDesk *d = &(PagerState.desks[i]);
1603
1604 if (!get_flags (d->flags, ASP_DeskShaded)) {
1605 ++unshaded_col_count;
1606 col_shaded_width = 0;
1607 break;
1608 } else {
1609 int dw = calculate_desk_width (d);
1610 if (col_shaded_width < dw)
1611 col_shaded_width = dw;
1612 }
1613 }
1614 shaded_width += col_shaded_width;
1615 }
1616
1617 LOCAL_DEBUG_OUT ("unshaded_col_count = %d", unshaded_col_count);
1618 if (unshaded_col_count == 0)
1619 return PagerState.desk_width;
1620 return (main_width - shaded_width) / unshaded_col_count;
1621 }
1622 }
1623
calculate_pager_desk_height()1624 unsigned int calculate_pager_desk_height ()
1625 {
1626 int main_height = PagerState.main_canvas->height - Config->border_width;
1627 if (get_flags (Config->flags, VERTICAL_LABEL))
1628 return main_height / Config->rows;
1629 else {
1630 unsigned int unshaded_row_count = 0;
1631 unsigned int shaded_height = 0;
1632 int row;
1633 /* we have to calculate the number of not-shaded columns,
1634 * and then devide size of the main canvas by this number : */
1635 for (row = 0; row < Config->rows; ++row) {
1636 unsigned int row_shaded_height = 0;
1637 int i, max_i = (row + 1) * Config->columns;
1638
1639 if (max_i > PagerState.desks_num)
1640 max_i = PagerState.desks_num;
1641
1642 for (i = row * Config->columns; i < max_i; ++i) {
1643 ASPagerDesk *d = &(PagerState.desks[i]);
1644 if (!get_flags (d->flags, ASP_DeskShaded)) {
1645 ++unshaded_row_count;
1646 row_shaded_height = 0;
1647 break;
1648 } else {
1649 int dh = calculate_desk_height (d);
1650 if (row_shaded_height < dh)
1651 row_shaded_height = dh;
1652 }
1653 }
1654 shaded_height += row_shaded_height;
1655 }
1656 LOCAL_DEBUG_OUT
1657 ("unshaded_row_count = %d, shaded_height = %d, main_height = %d",
1658 unshaded_row_count, shaded_height, main_height);
1659 if (unshaded_row_count == 0)
1660 return PagerState.desk_height;
1661 return (main_height - shaded_height) / unshaded_row_count;
1662 }
1663 }
1664
1665
1666 /*************************************************************************
1667 * shading/unshading
1668 *************************************************************************/
shade_desk_column(ASPagerDesk * d,Bool shade)1669 void shade_desk_column (ASPagerDesk * d, Bool shade)
1670 {
1671 int i;
1672 for (i = (d->desk - PagerState.start_desk) % Config->columns;
1673 i < PagerState.desks_num; i += Config->columns) {
1674 if (shade)
1675 set_flags (PagerState.desks[i].flags, ASP_DeskShaded);
1676 else
1677 clear_flags (PagerState.desks[i].flags, ASP_DeskShaded);
1678 }
1679 rearrange_pager_desks (False);
1680 }
1681
shade_desk_row(ASPagerDesk * d,Bool shade)1682 void shade_desk_row (ASPagerDesk * d, Bool shade)
1683 {
1684 int col_start =
1685 ((d->desk -
1686 PagerState.start_desk) / Config->columns) * Config->columns;
1687 int i;
1688 for (i = col_start; i < col_start + Config->columns; ++i) {
1689 if (shade)
1690 set_flags (PagerState.desks[i].flags, ASP_DeskShaded);
1691 else
1692 clear_flags (PagerState.desks[i].flags, ASP_DeskShaded);
1693 }
1694 LOCAL_DEBUG_OUT ("Shading - rcol_start = %d", col_start);
1695 rearrange_pager_desks (False);
1696 }
1697
1698 /*************************************************************************
1699 *
1700 *************************************************************************/
set_client_name(ASWindowData * wd,Bool redraw)1701 void set_client_name (ASWindowData * wd, Bool redraw)
1702 {
1703 if (wd->bar) {
1704 LOCAL_DEBUG_OUT ("name_enc = %ld, name = \"%s\"",
1705 wd->window_name_encoding,
1706 wd->window_name ? wd->window_name : "(null)");
1707 change_astbar_first_label (wd->bar, wd->window_name,
1708 wd->window_name_encoding);
1709 set_astbar_balloon (wd->bar, 0, wd->window_name,
1710 wd->window_name_encoding);
1711 }
1712 if (redraw && wd->canvas)
1713 render_astbar (wd->bar, wd->canvas);
1714 }
1715
1716 void
place_client(ASPagerDesk * d,ASWindowData * wd,Bool force_redraw,Bool dont_update_shape)1717 place_client (ASPagerDesk * d, ASWindowData * wd, Bool force_redraw,
1718 Bool dont_update_shape)
1719 {
1720 int x = 0, y = 0, width = 1, height = 1;
1721 int curr_x, curr_y;
1722 int desk_width = d->background->width;
1723 int desk_height = d->background->height;
1724
1725 if (desk_width == 0 || desk_height == 0)
1726 return;
1727 if (wd) {
1728 int client_x = wd->frame_rect.x;
1729 int client_y = wd->frame_rect.y;
1730 int client_width = wd->frame_rect.width;
1731 int client_height = wd->frame_rect.height;
1732 if (get_flags (wd->state_flags, AS_Iconic)) {
1733 client_x = wd->icon_rect.x + Scr.Vx;
1734 client_y = wd->icon_rect.y + Scr.Vy;
1735 client_width = wd->icon_rect.width;
1736 client_height = wd->icon_rect.height;
1737 } else {
1738 if (get_flags (wd->state_flags, AS_Sticky)) {
1739 client_x += Scr.Vx;
1740 client_y += Scr.Vy;
1741 }
1742 if (get_flags (wd->state_flags, AS_Shaded)) {
1743 if (get_flags (wd->flags, AS_VerticalTitle))
1744 client_width = (PagerState.vscreen_width * 2) / desk_width;
1745 else
1746 client_height = (PagerState.vscreen_height * 2) / desk_height;
1747 }
1748 }
1749 LOCAL_DEBUG_OUT ("+PLACE->client(%lX)->frame_geom(%dx%d%+d%+d)",
1750 wd->client, client_width, client_height, client_x,
1751 client_y);
1752 x = (client_x * desk_width) / PagerState.vscreen_width;
1753 y = (client_y * desk_height) / PagerState.vscreen_height;
1754 width = (client_width * desk_width) / PagerState.vscreen_width;
1755 height = (client_height * desk_height) / PagerState.vscreen_height;
1756 if (x < 0) {
1757 width += x;
1758 x = 0;
1759 }
1760 if (y < 0) {
1761 height += y;
1762 y = 0;
1763 }
1764 if (width <= 0)
1765 width = 1;
1766 if (height <= 0)
1767 height = 1;
1768
1769 LOCAL_DEBUG_OUT
1770 ("@@@@ ### $$$ Client \"%s\" background position is %+d%+d, client's = %+d%+d",
1771 wd->window_name ? wd->window_name : "(null)",
1772 d->background->win_x, d->background->win_y, x, y);
1773 x += (int)d->background->win_x;
1774 y += (int)d->background->win_y;
1775 if (wd->canvas) {
1776 ASCanvas *canvas = wd->canvas;
1777 unsigned int bw = 0;
1778 get_canvas_position (canvas, NULL, &curr_x, &curr_y, &bw);
1779 LOCAL_DEBUG_OUT ("current canvas at = %+d%+d", curr_x, curr_y);
1780 if (curr_x == x && curr_y == y && width == canvas->width
1781 && height == canvas->height) {
1782 if (force_redraw) {
1783 render_astbar (wd->bar, canvas);
1784 update_canvas_display (canvas);
1785 }
1786 } else
1787 moveresize_canvas (canvas, x - bw, y - bw, width, height);
1788
1789 LOCAL_DEBUG_OUT ("+PLACE->canvas(%p)->geom(%dx%d%+d%+d)", wd->canvas,
1790 width, height, x, y);
1791 }
1792 }
1793 }
1794
set_client_look(ASWindowData * wd,Bool redraw)1795 void set_client_look (ASWindowData * wd, Bool redraw)
1796 {
1797 LOCAL_DEBUG_CALLER_OUT ("%p, %p", wd, wd->bar);
1798
1799 if (wd->bar) {
1800 int state = get_flags (wd->state_flags, AS_Sticky) ?
1801 BACK_STICKY : BACK_UNFOCUSED;
1802 set_astbar_style_ptr (wd->bar, -1, Scr.Look.MSWindow[state]);
1803 set_astbar_style_ptr (wd->bar, BAR_STATE_FOCUSED,
1804 Scr.Look.MSWindow[BACK_FOCUSED]);
1805 } else
1806 show_warning ("NULL tbar for window data found. client = %lX",
1807 wd->client);
1808
1809 if (redraw && wd->canvas)
1810 render_astbar (wd->bar, wd->canvas);
1811 }
1812
on_client_moveresize(ASWindowData * wd)1813 void on_client_moveresize (ASWindowData * wd)
1814 {
1815 if (handle_canvas_config (wd->canvas) != 0) {
1816 ASPagerDesk *d = get_pager_desk (wd->desk);
1817 set_astbar_size (wd->bar, wd->canvas->width, wd->canvas->height);
1818 render_astbar (wd->bar, wd->canvas);
1819 update_canvas_display (wd->canvas);
1820 if (d)
1821 set_flags (d->flags, ASP_ShapeDirty);
1822 }
1823 }
1824
register_client(ASWindowData * wd)1825 Bool register_client (ASWindowData * wd)
1826 {
1827 if (PagerClients == NULL)
1828 PagerClients = create_ashash (0, NULL, NULL, NULL);
1829
1830 return (add_hash_item (PagerClients, AS_HASHABLE (wd->canvas->w), wd) ==
1831 ASH_Success);
1832 }
1833
fetch_client(Window w)1834 ASWindowData *fetch_client (Window w)
1835 {
1836 ASHashData hdata = { 0 };
1837 if (PagerClients)
1838 if (get_hash_item (PagerClients, AS_HASHABLE (w), &hdata.vptr) !=
1839 ASH_Success)
1840 hdata.vptr = NULL;
1841 return hdata.vptr;
1842 }
1843
unregister_client(Window w)1844 void unregister_client (Window w)
1845 {
1846 if (PagerClients)
1847 remove_hash_item (PagerClients, AS_HASHABLE (w), NULL, False);
1848 }
1849
forget_desk_client(int desk,ASWindowData * wd)1850 void forget_desk_client (int desk, ASWindowData * wd)
1851 {
1852 ASPagerDesk *d = get_pager_desk (desk);
1853 LOCAL_DEBUG_CALLER_OUT ("%d(%p),%p", desk, d, wd);
1854 if (d && wd && d->clients) {
1855 register int i = d->clients_num;
1856 while (--i >= 0)
1857 if (d->clients[i] == wd) {
1858 register int k = i, last_k = d->clients_num;
1859 LOCAL_DEBUG_OUT ("client found at %d", i);
1860 while (++k < last_k)
1861 d->clients[k - 1] = d->clients[k];
1862 d->clients[k - 1] = NULL;
1863 --(d->clients_num);
1864 }
1865 if (i >= 0)
1866 set_flags (d->flags, ASP_ShapeDirty);
1867 }
1868 }
1869
add_desk_client(ASPagerDesk * d,ASWindowData * wd)1870 void add_desk_client (ASPagerDesk * d, ASWindowData * wd)
1871 {
1872 LOCAL_DEBUG_OUT ("%p, %p, index %d", d, wd, d ? d->clients_num : -1);
1873 if (d && wd) {
1874 int i = d->clients_num;
1875 while (--i >= 0)
1876 if (d->clients[i] == wd)
1877 return; /* already belongs to that desk */
1878 d->clients =
1879 realloc (d->clients,
1880 (d->clients_num + 1) * sizeof (ASWindowData *));
1881 d->clients[d->clients_num] = wd;
1882 ++(d->clients_num);
1883 set_flags (d->flags, ASP_ShapeDirty);
1884 }
1885 }
1886
add_client(ASWindowData * wd)1887 void add_client (ASWindowData * wd)
1888 {
1889 ASPagerDesk *d = get_pager_desk (wd->desk);
1890 Window w;
1891 XSetWindowAttributes attr;
1892
1893 if (d == NULL)
1894 return;
1895
1896 attr.event_mask = CLIENT_EVENT_MASK;
1897 /* create window, canvas and tbar : */
1898 w = create_visual_window (Scr.asv, d->desk_canvas->w, -1, -1, 1, 1, 0,
1899 InputOutput, CWEventMask, &attr);
1900 if (w == None)
1901 return;
1902
1903 wd->canvas = create_ascanvas (w);
1904 wd->bar = create_astbar ();
1905
1906 add_desk_client (d, wd);
1907 register_client (wd);
1908
1909 set_astbar_hilite (wd->bar, BAR_STATE_UNFOCUSED,
1910 NORMAL_HILITE | NO_HILITE_OUTLINE);
1911 set_astbar_hilite (wd->bar, BAR_STATE_FOCUSED,
1912 NORMAL_HILITE | NO_HILITE_OUTLINE);
1913 add_astbar_label (wd->bar, 0, 0, 0, NO_ALIGN, 0, 0, NULL, AS_Text_ASCII);
1914 move_astbar (wd->bar, wd->canvas, 0, 0);
1915 if (wd->focused)
1916 set_astbar_focused (wd->bar, NULL, True);
1917
1918 set_client_name (wd, False);
1919 set_client_look (wd, False);
1920 place_client (d, wd, True, False);
1921 map_canvas_window (wd->canvas, True);
1922 LOCAL_DEBUG_OUT ("+CREAT->canvas(%p)->bar(%p)->client_win(%lX)",
1923 wd->canvas, wd->bar, wd->client);
1924 }
1925
refresh_client(INT32 old_desk,ASWindowData * wd)1926 void refresh_client (INT32 old_desk, ASWindowData * wd)
1927 {
1928 ASPagerDesk *d = get_pager_desk (wd->desk);
1929 LOCAL_DEBUG_OUT
1930 ("client(%lX)->name(%s)->icon_name(%s)->desk(%ld)->old_desk(%ld)",
1931 wd->client, wd->window_name ? wd->window_name : "(null)",
1932 wd->icon_name, wd->desk, old_desk);
1933 if (old_desk != wd->desk) {
1934 forget_desk_client (old_desk, wd);
1935 if (d != NULL) {
1936 add_desk_client (d, wd);
1937 LOCAL_DEBUG_OUT ("reparenting client to desk %ld", d->desk);
1938 quietly_reparent_canvas (wd->canvas, d->desk_canvas->w,
1939 CLIENT_EVENT_MASK, False, None);
1940 }
1941 }
1942 set_client_name (wd, False);
1943 LOCAL_DEBUG_OUT ("client \"%s\" focused = %d",
1944 wd->window_name ? wd->window_name : "(null)",
1945 wd->focused);
1946 set_astbar_focused (wd->bar, NULL, wd->focused);
1947 set_client_look (wd, True);
1948 LOCAL_DEBUG_OUT ("placing client%s", "");
1949 if (d != NULL)
1950 place_client (d, wd, False, False);
1951 LOCAL_DEBUG_OUT ("all done%s", "");
1952 }
1953
1954
1955 void
change_desk_stacking(int desk,unsigned int clients_num,Window * clients)1956 change_desk_stacking (int desk, unsigned int clients_num, Window * clients)
1957 {
1958 ASPagerDesk *d = get_pager_desk (desk);
1959 int i, real_clients_count = 0;
1960 if (d == NULL)
1961 return;
1962
1963 if (d->clients_num < clients_num) {
1964 d->clients =
1965 realloc (d->clients, clients_num * sizeof (ASWindowData *));
1966 memset (d->clients, 0x00, clients_num * sizeof (ASWindowData *));
1967 d->clients_num = clients_num;
1968 }
1969 for (i = 0; i < clients_num; ++i) {
1970 ASWindowData *wd = fetch_window_by_id (clients[i]);
1971 if (wd != NULL) { /* window is in stacking order, but wew were not notifyed about it yet */
1972 int k = real_clients_count;
1973 while (--k >= 0)
1974 if (d->clients[k] == wd)
1975 break; /* already belongs to that desk */
1976 if (k < 0) {
1977 d->clients[i] = wd;
1978 ++real_clients_count;
1979 LOCAL_DEBUG_OUT ("id(%lX)->wd(%p)", clients[i], d->clients[i]);
1980 }
1981 }
1982 }
1983 d->clients_num = real_clients_count;
1984 set_flags (d->flags, ASP_ShapeDirty);
1985 restack_desk_windows (d);
1986 }
1987
set_desktop_pixmap(int desk,Pixmap pmap)1988 void set_desktop_pixmap (int desk, Pixmap pmap)
1989 {
1990 ASPagerDesk *d = get_pager_desk (desk);
1991 unsigned int width, height;
1992
1993 if (!get_drawable_size (pmap, &width, &height))
1994 pmap = None;
1995 LOCAL_DEBUG_OUT ("desk(%d)->d(%p)->pmap(%lX)->size(%dx%d)", desk, d,
1996 pmap, width, height);
1997 if (pmap == None)
1998 return;
1999 if (d == NULL) {
2000 XFreePixmap (dpy, pmap);
2001 return;
2002 }
2003
2004 if (get_flags (d->flags, ASP_UseRootBackground)) {
2005 ASImage *im =
2006 pixmap2asimage (Scr.asv, pmap, 0, 0, width, height, 0xFFFFFFFF,
2007 False, 100);
2008
2009 XFreePixmap (dpy, pmap);
2010 if (d->back)
2011 destroy_asimage (&(d->back));
2012 d->back = im;
2013 delete_astbar_tile (d->background, 0);
2014 add_astbar_icon (d->background, 0, 0, 0, NO_ALIGN, d->back);
2015 render_astbar (d->background, d->desk_canvas);
2016 update_canvas_display (d->desk_canvas);
2017 }
2018 }
2019
move_sticky_clients()2020 void move_sticky_clients ()
2021 {
2022 int desk = PagerState.desks_num;
2023 ASPagerDesk *current_desk = get_pager_desk (Scr.CurrentDesk);
2024
2025 while (--desk >= 0) {
2026 ASPagerDesk *d = &(PagerState.desks[desk]);
2027 if (d->clients && d->clients_num > 0) {
2028 register int i = d->clients_num;
2029 register ASWindowData **clients = d->clients;
2030 while (--i >= 0)
2031 if (clients[i] && get_flags (clients[i]->state_flags, AS_Sticky)) {
2032 if (clients[i]->desk != Scr.CurrentDesk && current_desk) { /* in order to make an illusion of smooth desktop
2033 * switching - we'll reparent window ahead of time */
2034 LOCAL_DEBUG_OUT ("reparenting client to desk %ld", d->desk);
2035 quietly_reparent_canvas (clients[i]->canvas,
2036 current_desk->desk_canvas->w,
2037 CLIENT_EVENT_MASK, False, None);
2038 }
2039 place_client (d, clients[i], True, True);
2040 }
2041 set_flags (d->flags, ASP_ShapeDirty);
2042 }
2043 }
2044 }
2045
2046
switch_deskviewport(int new_desk,int new_vx,int new_vy)2047 void switch_deskviewport (int new_desk, int new_vx, int new_vy)
2048 {
2049 Bool view_changed = (new_vx != Scr.Vx || new_vy != Scr.Vy);
2050 Bool desk_changed = (new_desk != Scr.CurrentDesk);
2051
2052 Scr.Vx = new_vx;
2053 Scr.Vy = new_vy;
2054 Scr.CurrentDesk = new_desk;
2055
2056 if (desk_changed && IsValidDesk (new_desk)) {
2057 ASPagerDesk *new_d = get_pager_desk (new_desk);
2058
2059 if (PagerState.focused_desk != new_d) {
2060 if (PagerState.focused_desk) {
2061 set_astbar_focused (PagerState.focused_desk->title,
2062 PagerState.focused_desk->desk_canvas, False);
2063 set_astbar_focused (PagerState.focused_desk->background,
2064 PagerState.focused_desk->desk_canvas, False);
2065 if (is_canvas_dirty (PagerState.focused_desk->desk_canvas))
2066 update_canvas_display (PagerState.focused_desk->desk_canvas);
2067 PagerState.focused_desk = NULL;
2068 }
2069 if (new_d) {
2070 set_astbar_focused (new_d->title, new_d->desk_canvas, True);
2071 set_astbar_focused (new_d->background, new_d->desk_canvas, True);
2072 if (is_canvas_dirty (new_d->desk_canvas))
2073 update_canvas_display (new_d->desk_canvas);
2074 PagerState.focused_desk = new_d;
2075 }
2076 }
2077 }
2078
2079 if (view_changed || desk_changed) {
2080 move_sticky_clients ();
2081 place_selection ();
2082 if (new_desk < PagerState.start_desk
2083 || new_desk >= PagerState.start_desk + PagerState.desks_num) {
2084 int i = 4;
2085 while (--i >= 0)
2086 XUnmapWindow (dpy, PagerState.selection_bars[i]);
2087
2088 }
2089 }
2090 }
2091
2092 static char as_comm_buf[256];
2093
move_client_to_desk(ASWindowData * wd,int desk)2094 void move_client_to_desk (ASWindowData * wd, int desk)
2095 {
2096 sprintf (as_comm_buf, "WindowsDesk %d", desk);
2097 SendInfo (as_comm_buf, wd->client);
2098 }
2099
translate_client_pos_main(int x,int y,unsigned int width,unsigned int height,int desk,int * ret_x,int * ret_y)2100 ASPagerDesk *translate_client_pos_main (int x, int y, unsigned int width,
2101 unsigned int height, int desk,
2102 int *ret_x, int *ret_y)
2103 {
2104 ASPagerDesk *d = NULL;
2105 if (x + width >= PagerState.main_canvas->root_x
2106 && y + height >= PagerState.main_canvas->root_y
2107 && x < PagerState.main_canvas->width + PagerState.main_canvas->root_x
2108 && y <
2109 PagerState.main_canvas->height + PagerState.main_canvas->root_y) {
2110 int i = PagerState.desks_num;
2111 if ((d = get_pager_desk (desk)) != NULL) {
2112 if (d->desk_canvas->root_x + d->desk_canvas->bw > x + width ||
2113 d->desk_canvas->root_x + d->desk_canvas->bw +
2114 d->desk_canvas->width <= x
2115 || d->desk_canvas->root_y + d->desk_canvas->bw > y + height
2116 || d->desk_canvas->root_y + d->desk_canvas->bw +
2117 d->desk_canvas->height <= y) {
2118 d = NULL;
2119 }
2120 }
2121
2122 while (--i >= 0 && d == NULL) {
2123 d = &(PagerState.desks[i]);
2124 LOCAL_DEBUG_OUT
2125 ("checking desk %d: pos(%+d%+d)->desk_geom(%dx%d%+d%+d)", i, x,
2126 y, d->desk_canvas->width, d->desk_canvas->height,
2127 d->desk_canvas->root_x, d->desk_canvas->root_y);
2128 if (d->desk_canvas->root_x + d->desk_canvas->bw > x + width
2129 || d->desk_canvas->root_x + d->desk_canvas->bw +
2130 d->desk_canvas->width <= x
2131 || d->desk_canvas->root_y + d->desk_canvas->bw > y + height
2132 || d->desk_canvas->root_y + d->desk_canvas->bw +
2133 d->desk_canvas->height <= y) {
2134 d = NULL;
2135 }
2136 }
2137 }
2138
2139 if (d) {
2140 x -= d->background->root_x;
2141 y -= d->background->root_y;
2142 LOCAL_DEBUG_OUT
2143 ("desk(%ld) pager_vpos(%+d%+d) vscreen_size(%dx%d) desk_size(%dx%d) ",
2144 d->desk, x, y, PagerState.vscreen_width,
2145 PagerState.vscreen_height, d->background->width,
2146 d->background->height);
2147 if (d->background->width > 0)
2148 x = (x * PagerState.vscreen_width) / d->background->width;
2149 if (d->background->height > 0)
2150 y = (y * PagerState.vscreen_height) / d->background->height;
2151 *ret_x = x;
2152 *ret_y = y;
2153 } else {
2154 *ret_x = x;
2155 *ret_y = y;
2156 }
2157 return d;
2158 }
2159
2160 void
translate_client_size(unsigned int width,unsigned int height,unsigned int * ret_width,unsigned int * ret_height)2161 translate_client_size (unsigned int width, unsigned int height,
2162 unsigned int *ret_width, unsigned int *ret_height)
2163 {
2164 if (PagerState.resize_desk) {
2165 ASPagerDesk *d = PagerState.resize_desk;
2166 if (d->background->width > 0) {
2167 width = (width * PagerState.vscreen_width) / d->background->width;
2168 }
2169 if (d->background->height > 0) {
2170 height =
2171 (height * PagerState.vscreen_height) / d->background->height;
2172 }
2173 *ret_width = width;
2174 *ret_height = height;
2175 }
2176 }
2177
2178 typedef struct ASPagerMoveResizeReq {
2179 FunctionCode func;
2180 send_signed_data_type func_val[2];
2181 Window client;
2182 Bool pending;
2183 } ASPagerMoveResizeReq;
2184
2185 ASPagerMoveResizeReq PagerMoveResizeReq = { 0, {0, 0}, None, False };
2186
exec_moveresize_req(void * data)2187 void exec_moveresize_req (void *data)
2188 {
2189 ASPagerMoveResizeReq *req = (ASPagerMoveResizeReq *) data;
2190 if (req && req->pending) {
2191 send_signed_data_type unit_val[2] = { 1, 1 };
2192 SendNumCommand (req->func, NULL, &(req->func_val[0]), &(unit_val[0]),
2193 req->client);
2194 req->pending = False;
2195 }
2196 }
2197
2198 void
schedule_moveresize_req(FunctionCode func,send_signed_data_type val1,send_signed_data_type val2,Window client,Bool immidiate)2199 schedule_moveresize_req (FunctionCode func, send_signed_data_type val1,
2200 send_signed_data_type val2, Window client,
2201 Bool immidiate)
2202 {
2203 if (PagerMoveResizeReq.pending) {
2204 if (PagerMoveResizeReq.client != client
2205 || PagerMoveResizeReq.func != func) {
2206 timer_remove_by_data (&PagerMoveResizeReq);
2207 exec_moveresize_req (&PagerMoveResizeReq);
2208 } else if (immidiate) {
2209 timer_remove_by_data (&PagerMoveResizeReq);
2210 PagerMoveResizeReq.pending = False;
2211 }
2212 }
2213 PagerMoveResizeReq.func = func;
2214 PagerMoveResizeReq.func_val[0] = val1;
2215 PagerMoveResizeReq.func_val[1] = val2;
2216 PagerMoveResizeReq.client = client;
2217 if (immidiate)
2218 exec_moveresize_req (&PagerMoveResizeReq);
2219 else if (!PagerMoveResizeReq.pending) {
2220 PagerMoveResizeReq.pending = True;
2221 timer_new (40, exec_moveresize_req, &PagerMoveResizeReq);
2222 }
2223 }
2224
apply_client_move(struct ASMoveResizeData * data)2225 void apply_client_move (struct ASMoveResizeData *data)
2226 {
2227 ASWindowData *wd = fetch_client (AS_WIDGET_WINDOW (data->mr));
2228 int real_x = 0, real_y = 0;
2229 ASPagerDesk *d =
2230 translate_client_pos_main (PagerState.main_canvas->root_x +
2231 data->curr.x,
2232 PagerState.main_canvas->root_y +
2233 data->curr.y,
2234 data->curr.width, data->curr.height,
2235 wd->desk, &real_x, &real_y);
2236 if (d && d->desk != wd->desk) {
2237 move_client_to_desk (wd, d->desk);
2238 set_moveresize_aspect (data, PagerState.vscreen_width,
2239 d->background->width, PagerState.vscreen_height,
2240 d->background->height, d->background->root_x,
2241 d->background->root_y);
2242 }
2243 LOCAL_DEBUG_OUT ("d(%p)->curr(%+d%+d)->real(%+d%+d)", d, data->curr.x,
2244 data->curr.y, real_x, real_y);
2245 schedule_moveresize_req (F_MOVE, real_x, real_y, wd->client, False);
2246 }
2247
complete_client_move(struct ASMoveResizeData * data,Bool cancelled)2248 void complete_client_move (struct ASMoveResizeData *data, Bool cancelled)
2249 {
2250 ASWindowData *wd = fetch_client (AS_WIDGET_WINDOW (data->mr));
2251 int real_x = 0, real_y = 0;
2252 ASPagerDesk *d = NULL;
2253 MRRectangle *rect = &(data->curr);
2254
2255 if (cancelled)
2256 rect = &(data->start);
2257
2258 d = translate_client_pos_main (rect->x + PagerState.main_canvas->root_x,
2259 rect->y + PagerState.main_canvas->root_y,
2260 rect->width,
2261 rect->height, wd->desk, &real_x, &real_y);
2262
2263 if (d && d->desk != wd->desk) {
2264 move_client_to_desk (wd, d->desk);
2265 set_moveresize_aspect (data, PagerState.vscreen_width,
2266 d->background->width, PagerState.vscreen_height,
2267 d->background->height, d->background->root_x,
2268 d->background->root_y);
2269 }
2270 LOCAL_DEBUG_OUT ("d(%p)->start(%+d%+d)->curr(%+d%+d)->real(%+d%+d)", d,
2271 data->start.x, data->start.y, data->curr.x,
2272 data->curr.y, real_x, real_y);
2273 schedule_moveresize_req (F_MOVE, real_x, real_y, wd->client, True);
2274 Scr.moveresize_in_progress = NULL;
2275 }
2276
apply_client_resize(struct ASMoveResizeData * data)2277 void apply_client_resize (struct ASMoveResizeData *data)
2278 {
2279 ASWindowData *wd = fetch_client (AS_WIDGET_WINDOW (data->mr));
2280 unsigned int real_width = 1, real_height = 1;
2281 LOCAL_DEBUG_OUT ("desk(%p)->size(%dx%d)", PagerState.resize_desk,
2282 data->curr.width, data->curr.height);
2283 translate_client_size (data->curr.width, data->curr.height, &real_width,
2284 &real_height);
2285 schedule_moveresize_req (F_RESIZE, real_width, real_height, wd->client,
2286 False);
2287 }
2288
complete_client_resize(struct ASMoveResizeData * data,Bool cancelled)2289 void complete_client_resize (struct ASMoveResizeData *data, Bool cancelled)
2290 {
2291 ASWindowData *wd = fetch_client (AS_WIDGET_WINDOW (data->mr));
2292 unsigned int real_width = 1, real_height = 1;
2293
2294 if (cancelled) {
2295 LOCAL_DEBUG_OUT ("%dx%d%+d%+d", data->start.x, data->start.y,
2296 data->start.width, data->start.height);
2297 translate_client_size (data->start.width, data->start.height,
2298 &real_width, &real_height);
2299 } else {
2300 LOCAL_DEBUG_OUT ("%dx%d%+d%+d", data->curr.x, data->curr.y,
2301 data->curr.width, data->curr.height);
2302 translate_client_size (data->curr.width, data->curr.height,
2303 &real_width, &real_height);
2304 }
2305 schedule_moveresize_req (F_RESIZE, real_width, real_height, wd->client,
2306 True);
2307 PagerState.resize_desk = NULL;
2308 Scr.moveresize_in_progress = NULL;
2309 }
2310
make_pager_grid()2311 ASGrid *make_pager_grid ()
2312 {
2313 ASGrid *grid;
2314 int resist = Scr.Feel.EdgeResistanceMove;
2315 int attract = Scr.Feel.EdgeAttractionScreen;
2316 int i;
2317
2318 grid = safecalloc (1, sizeof (ASGrid));
2319
2320 for (i = 0; i < PagerState.desks_num; ++i) {
2321 ASPagerDesk *d = &(PagerState.desks[i]);
2322 int k = d->clients_num;
2323 ASWindowData *wd;
2324 ASTBarData *bb = d->background;
2325
2326 add_gridline (grid, bb->root_y, bb->root_x, bb->root_x + bb->width,
2327 resist, attract, ASGL_Absolute);
2328 add_gridline (grid, bb->root_y + bb->height, bb->root_x,
2329 bb->root_x + bb->width, resist, attract, ASGL_Absolute);
2330 add_gridline (grid, bb->root_x, bb->root_y, bb->root_y + bb->height,
2331 resist, attract, ASGL_Absolute | ASGL_Vertical);
2332 add_gridline (grid, bb->root_x + bb->width, bb->root_y,
2333 bb->root_y + bb->height, resist, attract,
2334 ASGL_Absolute | ASGL_Vertical);
2335
2336 if (!get_flags (d->flags, ASP_DeskShaded)) { /* add all the grid separation windows : */
2337 register int p = PagerState.page_columns - 1;
2338 int pos_inc = bb->width / PagerState.page_columns;
2339 int pos = bb->root_x + p * pos_inc;
2340 int size = bb->height;
2341 int pos2 = bb->root_y;
2342 /* vertical bars : */
2343 while (--p >= 0) {
2344 add_gridline (grid, pos, pos2, pos2 + size, resist, attract,
2345 ASGL_Absolute | ASGL_Vertical);
2346 pos -= pos_inc;
2347 }
2348 /* horizontal bars */
2349 p = PagerState.page_rows - 1;
2350 pos_inc = bb->height / PagerState.page_rows;
2351 pos = bb->root_y + p * pos_inc;
2352 pos2 = bb->root_x;
2353 size = bb->width;
2354 while (--p >= 0) {
2355 add_gridline (grid, pos, pos2, pos2 + size, resist, attract,
2356 ASGL_Absolute);
2357 pos -= pos_inc;
2358 }
2359 }
2360 while (--k >= 0)
2361 if ((wd = PagerState.desks[i].clients[k]) != NULL) {
2362 int outer_gravity = Scr.Feel.EdgeAttractionWindow;
2363 int inner_gravity = Scr.Feel.EdgeAttractionWindow;
2364 if (get_flags (wd->flags, AS_AvoidCover))
2365 inner_gravity = -1;
2366
2367 if (inner_gravity != 0)
2368 add_canvas_grid (grid, wd->canvas, outer_gravity, inner_gravity,
2369 ASGL_Absolute);
2370 }
2371 }
2372 /* add all the window edges for this desktop : */
2373 /* iterate_asbidirlist( Scr.Windows->clients, get_aswindow_grid_iter_func, (void*)&grid_data, NULL, False ); */
2374
2375 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
2376 print_asgrid (grid);
2377 #endif
2378
2379 return grid;
2380 }
2381
2382
2383 void
start_moveresize_client(ASWindowData * wd,Bool move,ASEvent * event)2384 start_moveresize_client (ASWindowData * wd, Bool move, ASEvent * event)
2385 {
2386 ASMoveResizeData *mvrdata = NULL;
2387 ASPagerDesk *d = get_pager_desk (wd->desk);
2388 MyStyle *pager_focused_style = Scr.Look.MSWindow[BACK_FOCUSED];
2389
2390 release_pressure ();
2391 if (Scr.moveresize_in_progress)
2392 return;
2393
2394
2395 if (move) {
2396 Scr.Look.MSWindow[BACK_FOCUSED] =
2397 mystyle_find_or_default ("focused_window_style");
2398 mvrdata =
2399 move_widget_interactively (PagerState.main_canvas, wd->canvas,
2400 event, apply_client_move,
2401 complete_client_move);
2402 } else if (d != NULL) {
2403 if (get_flags (wd->state_flags, AS_Shaded)) {
2404 XBell (dpy, Scr.screen);
2405 return;
2406 }
2407
2408 Scr.Look.MSWindow[BACK_FOCUSED] =
2409 mystyle_find_or_default ("focused_window_style");
2410 PagerState.resize_desk = d;
2411 mvrdata = resize_widget_interactively (d->desk_canvas,
2412 wd->canvas,
2413 event,
2414 apply_client_resize,
2415 complete_client_resize, FR_SE);
2416 }
2417 Scr.Look.MSWindow[BACK_FOCUSED] = pager_focused_style;
2418
2419 LOCAL_DEBUG_OUT ("mvrdata(%p)", mvrdata);
2420 if (mvrdata) {
2421 if (d)
2422 set_moveresize_aspect (mvrdata, PagerState.vscreen_width,
2423 d->background->width,
2424 PagerState.vscreen_height,
2425 d->background->height, d->background->root_x,
2426 d->background->root_y);
2427
2428 mvrdata->grid = make_pager_grid ();
2429 Scr.moveresize_in_progress = mvrdata;
2430 }
2431 }
2432
2433 /*************************************************************************
2434 * individuaL Desk manipulation
2435 *************************************************************************/
2436 /****************************************************************************/
2437 /* PROCESSING OF AFTERSTEP MESSAGES : */
2438 /****************************************************************************/
process_message(send_data_type type,send_data_type * body)2439 void process_message (send_data_type type, send_data_type * body)
2440 {
2441 LOCAL_DEBUG_OUT ("received message %lX, wait_as_resp = %d", type,
2442 PagerState.wait_as_response);
2443 --PagerState.wait_as_response;
2444 if ((type & WINDOW_PACKET_MASK) != 0) {
2445 struct ASWindowData *wd = fetch_window_by_id (body[0]);
2446 WindowPacketResult res;
2447 /* saving relevant client info since handle_window_packet could destroy the actuall structure */
2448 Window saved_w = None;
2449 INT32 saved_desk = wd ? wd->desk : INVALID_DESK;
2450 INT32 new_desk = saved_desk;
2451 struct ASWindowData *saved_wd = wd;
2452
2453 if (wd && wd->canvas)
2454 saved_w = wd->canvas->w;
2455
2456 /* show_activity( "message %lX window %X data %p", type, body[0], wd ); */
2457 res = handle_window_packet (type, body, &wd);
2458 if (res == WP_DataCreated && get_flags (wd->flags, AS_HitPager))
2459 add_client (wd);
2460 else if (res == WP_DataChanged && get_flags (wd->flags, AS_HitPager)) {
2461 refresh_client (saved_desk, wd);
2462 new_desk = wd->desk;
2463 } else if (res == WP_DataDeleted) {
2464 int i = PagerState.desks_num;
2465 LOCAL_DEBUG_OUT ("client deleted (%p)->window(%lX)->desk(%ld)",
2466 saved_wd, saved_w, (long)saved_desk);
2467 /* we really want to make sure that no desk is referencing this client : */
2468 while (--i >= 0)
2469 forget_desk_client (i, saved_wd);
2470 unregister_client (saved_w);
2471 }
2472 if (!get_flags (PagerState.flags, ASP_ReceivingWindowList)) {
2473 Bool need_shape_update = False;
2474 if (IsValidDesk (saved_desk)) {
2475 register INT32 pager_desk = saved_desk - PagerState.start_desk;
2476 if (pager_desk >= 0 && pager_desk < PagerState.desks_num)
2477 if (Config->MSDeskBack[pager_desk]->texture_type ==
2478 TEXTURE_SHAPED_PIXMAP
2479 || Config->MSDeskBack[pager_desk]->texture_type ==
2480 TEXTURE_SHAPED_SCALED_PIXMAP)
2481 need_shape_update = True;
2482 }
2483 if (need_shape_update && saved_desk != new_desk
2484 && IsValidDesk (new_desk)) {
2485 register INT32 pager_desk = new_desk - PagerState.start_desk;
2486 if (pager_desk >= 0 && pager_desk < PagerState.desks_num)
2487 if (Config->MSDeskBack[pager_desk]->texture_type ==
2488 TEXTURE_SHAPED_PIXMAP
2489 || Config->MSDeskBack[pager_desk]->texture_type ==
2490 TEXTURE_SHAPED_SCALED_PIXMAP)
2491 need_shape_update = True;
2492 }
2493 if (need_shape_update)
2494 update_pager_shape ();
2495 }
2496 } else {
2497 switch (type) {
2498 case M_TOGGLE_PAGING:
2499 break;
2500 case M_NEW_DESKVIEWPORT:
2501 {
2502 LOCAL_DEBUG_OUT ("M_NEW_DESKVIEWPORT(desk = %ld,Vx=%ld,Vy=%ld)",
2503 body[2], body[0], body[1]);
2504 switch_deskviewport (body[2], body[0], body[1]);
2505 update_pager_shape ();
2506 }
2507 break;
2508 case M_STACKING_ORDER:
2509 {
2510 LOCAL_DEBUG_OUT ("M_STACKING_ORDER(desk=%ld, clients_num=%ld)",
2511 body[0], body[1]);
2512 change_desk_stacking (body[0], body[1], (Window *) & (body[2]));
2513 }
2514 break;
2515 case M_END_WINDOWLIST:
2516 clear_flags (PagerState.flags, ASP_ReceivingWindowList);
2517 update_pager_shape ();
2518 break;
2519 default:
2520 return;
2521 }
2522 }
2523
2524 }
2525
2526 /*************************************************************************
2527 * Event handling :
2528 *************************************************************************/
DispatchEvent(ASEvent * event)2529 void DispatchEvent (ASEvent * event)
2530 {
2531 static Bool root_pointer_moved = True;
2532 SHOW_EVENT_TRACE (event);
2533
2534 LOCAL_DEBUG_OUT ("mvrdata(%p)->main_canvas(%p)->widget(%p)",
2535 Scr.moveresize_in_progress, PagerState.main_canvas,
2536 event->widget);
2537 if (Scr.moveresize_in_progress) {
2538 event->widget =
2539 PagerState.resize_desk ? PagerState.resize_desk->
2540 desk_canvas : PagerState.main_canvas;
2541 if (check_moveresize_event (event))
2542 return;
2543 }
2544
2545 if ((event->eclass & ASE_POINTER_EVENTS) != 0
2546 && is_balloon_click (&(event->x))) {
2547 withdraw_balloon (NULL);
2548 return;
2549 }
2550
2551 event->client = NULL;
2552 event->widget = PagerState.main_canvas;
2553
2554 if (event->w != PagerState.main_canvas->w) {
2555 ASWindowData *wd = fetch_client (event->w);
2556
2557 if (wd) {
2558 if (event->x.type == ButtonPress
2559 && event->x.xbutton.button != Button2) {
2560 event->w = get_pager_desk (wd->desk)->desk_canvas->w;
2561 } else {
2562 event->client = (void *)wd;
2563 event->widget = ((ASWindowData *) (event->client))->canvas;
2564 if ((event->eclass & ASE_POINTER_EVENTS) != 0) {
2565 on_astbar_pointer_action (((ASWindowData *) (event->client))->
2566 bar, 0, (event->x.type == LeaveNotify),
2567 root_pointer_moved);
2568 root_pointer_moved = False;
2569 }
2570 }
2571 }
2572 }
2573
2574 switch (event->x.type) {
2575 case ConfigureNotify:
2576 if (event->client != NULL)
2577 on_client_moveresize ((ASWindowData *) event->client);
2578 else {
2579 on_pager_window_moveresize (event->client, event->w,
2580 event->x.xconfigure.x,
2581 event->x.xconfigure.y,
2582 event->x.xconfigure.width,
2583 event->x.xconfigure.height);
2584 }
2585 break;
2586 case KeyPress:
2587 if (event->client != NULL) {
2588 ASWindowData *wd = (ASWindowData *) (event->client);
2589 event->x.xkey.window = wd->client;
2590 XSendEvent (dpy, wd->client, False, KeyPressMask, &(event->x));
2591 }
2592 return;
2593 case KeyRelease:
2594 if (event->client != NULL) {
2595 ASWindowData *wd = (ASWindowData *) (event->client);
2596 event->x.xkey.window = wd->client;
2597 XSendEvent (dpy, wd->client, False, KeyReleaseMask, &(event->x));
2598 }
2599 return;
2600 case ButtonPress:
2601 on_pager_pressure_changed (event);
2602 return;
2603 case ButtonRelease:
2604 LOCAL_DEBUG_OUT ("state(0x%X)->state&ButtonAnyMask(0x%X)",
2605 event->x.xbutton.state,
2606 event->x.xbutton.state & ButtonAnyMask);
2607 if ((event->x.xbutton.state & ButtonAnyMask) ==
2608 (Button1Mask << (event->x.xbutton.button - Button1)))
2609 release_pressure ();
2610 return;
2611 case EnterNotify:
2612 if (event->x.xcrossing.window == Scr.Root)
2613 withdraw_active_balloon ();
2614 return;
2615 case MotionNotify:
2616 root_pointer_moved = True;
2617 if ((event->x.xbutton.state & Button3Mask)) {
2618 XEvent d;
2619 sleep_a_millisec (10);
2620 ASSync (False);
2621 while (ASCheckTypedEvent (MotionNotify, &d)) {
2622 event->x = d;
2623 setup_asevent_from_xevent (event);
2624 }
2625 on_scroll_viewport (event);
2626 sleep_a_millisec (100);
2627 }
2628 return;
2629 case ClientMessage:
2630 LOCAL_DEBUG_OUT
2631 ("ClientMessage(\"%s\",format = %d, data=(%8.8lX,%8.8lX,%8.8lX,%8.8lX,%8.8lX)",
2632 XGetAtomName (dpy, event->x.xclient.message_type),
2633 event->x.xclient.format, event->x.xclient.data.l[0],
2634 event->x.xclient.data.l[1], event->x.xclient.data.l[2],
2635 event->x.xclient.data.l[3], event->x.xclient.data.l[4]);
2636 if (event->x.xclient.format == 32
2637 && event->x.xclient.data.l[0] == _XA_WM_DELETE_WINDOW) {
2638 DeadPipe (0);
2639 } else if (event->x.xclient.format == 32 &&
2640 event->x.xclient.message_type == _AS_BACKGROUND
2641 && event->x.xclient.data.l[1] != None) {
2642 set_desktop_pixmap (event->x.xclient.data.l[0] -
2643 PagerState.start_desk,
2644 event->x.xclient.data.l[1]);
2645 }
2646
2647 return;
2648 case PropertyNotify:
2649 if (event->x.xproperty.atom == _XA_NET_WM_STATE) {
2650 LOCAL_DEBUG_OUT ("_XA_NET_WM_STATE updated!%s", "");
2651 return;
2652 }
2653 handle_wmprop_event (Scr.wmprops, &(event->x));
2654 if (event->x.xproperty.atom == _AS_BACKGROUND) {
2655 register int i = PagerState.desks_num;
2656 LOCAL_DEBUG_OUT ("root background updated!%s", "");
2657 safe_asimage_destroy (Scr.RootImage);
2658 Scr.RootImage = NULL;
2659 while (--i >= 0) {
2660 update_astbar_transparency (PagerState.desks[i].title,
2661 PagerState.desks[i].desk_canvas, True);
2662 update_astbar_transparency (PagerState.desks[i].background,
2663 PagerState.desks[i].desk_canvas, True);
2664 render_desk (&(PagerState.desks[i]), False);
2665 }
2666 } else if (event->x.xproperty.atom == _AS_STYLE) {
2667 int i = PagerState.desks_num;
2668 LOCAL_DEBUG_OUT ("AS Styles updated!%s", "");
2669 mystyle_list_destroy_all (&(Scr.Look.styles_list));
2670 LoadColorScheme ();
2671 CheckConfigSanity ();
2672 /* now we need to update everything */
2673 while (--i >= 0) {
2674 register int k = PagerState.desks[i].clients_num;
2675 register ASWindowData **clients = PagerState.desks[i].clients;
2676 LOCAL_DEBUG_OUT ("i = %d, clients_num = %d ", i, k);
2677 while (--k >= 0) {
2678 LOCAL_DEBUG_OUT ("k = %d", k);
2679 if (clients[k])
2680 set_client_look (clients[k], False);
2681 else
2682 show_warning ("client %d of the desk %d is NULL", k, i);
2683 }
2684 }
2685 redecorate_pager_desks ();
2686 rearrange_pager_desks (False);
2687 } else if (event->x.xproperty.atom == _AS_TBAR_PROPS) {
2688 retrieve_pager_astbar_props ();
2689 redecorate_pager_desks ();
2690 rearrange_pager_desks (False);
2691 }
2692 return;
2693 default:
2694 #ifdef XSHMIMAGE
2695 LOCAL_DEBUG_OUT
2696 ("XSHMIMAGE> EVENT : completion_type = %d, event->type = %d ",
2697 Scr.ShmCompletionEventType, event->x.type);
2698 if (event->x.type == Scr.ShmCompletionEventType)
2699 handle_ShmCompletion (event);
2700 #endif /* SHAPE */
2701 return;
2702 }
2703 update_pager_shape ();
2704 }
2705
request_background_image(ASPagerDesk * d)2706 void request_background_image (ASPagerDesk * d)
2707 {
2708 if (d->back == NULL ||
2709 (d->back->width != d->background->width ||
2710 d->back->height != d->background->height)) {
2711 XEvent e;
2712 e.xclient.type = ClientMessage;
2713 e.xclient.message_type = _AS_BACKGROUND;
2714 e.xclient.format = 16;
2715 e.xclient.window = PagerState.main_canvas->w;
2716 e.xclient.data.s[0] = d->desk;
2717 e.xclient.data.s[1] = 0;
2718 e.xclient.data.s[2] = 0;
2719 e.xclient.data.s[3] = d->background->width;
2720 e.xclient.data.s[4] = d->background->height;
2721 e.xclient.data.s[5] = 0x01;
2722 e.xclient.data.s[6] = 0;
2723 e.xclient.data.s[7] = 0;
2724 e.xclient.data.s[8] = 0;
2725 LOCAL_DEBUG_OUT ("size(%dx%d)", e.xclient.data.s[3],
2726 e.xclient.data.s[4]);
2727 XSendEvent (dpy, Scr.Root, False, PropertyChangeMask, &e);
2728 ASSync (False);
2729 }
2730 }
2731
on_desk_moveresize(ASPagerDesk * d)2732 void on_desk_moveresize (ASPagerDesk * d)
2733 {
2734 ASFlagType changes = handle_canvas_config (d->desk_canvas);
2735
2736 if (get_flags (changes, CANVAS_RESIZED)) {
2737 place_desk_title (d);
2738 place_desk_background (d);
2739 /* place all the grid separation windows : */
2740 place_separation_bars (d);
2741
2742 /* rearrange all the client windows : */
2743 if (d->clients && d->clients_num > 0) {
2744 register int i;
2745 i = d->clients_num;
2746 while (--i >= 0)
2747 place_client (d, d->clients[i], False, True);
2748 }
2749 if (d->desk == Scr.CurrentDesk)
2750 place_selection ();
2751 if (get_flags (d->flags, ASP_UseRootBackground))
2752 request_background_image (d);
2753 }
2754 update_astbar_transparency (d->title, d->desk_canvas, False);
2755 update_astbar_transparency (d->background, d->desk_canvas, False);
2756
2757 render_desk (d, (changes != 0));
2758 }
2759
on_pager_window_moveresize(void * client,Window w,int x,int y,unsigned int width,unsigned int height)2760 void on_pager_window_moveresize (void *client, Window w, int x, int y,
2761 unsigned int width, unsigned int height)
2762 {
2763 if (client == NULL) { /* then its one of our canvases !!! */
2764 int i;
2765
2766 if (w == PagerState.main_canvas->w) { /* need to rescale everything? maybe: */
2767 int new_desk_width;
2768 int new_desk_height = 0;
2769 int changes;
2770
2771 changes = update_main_canvas_config ();
2772 if (changes & CANVAS_RESIZED) {
2773 set_flags (PagerState.flags, ASP_ShapeDirty);
2774
2775 new_desk_width = calculate_pager_desk_width ();
2776 new_desk_height = calculate_pager_desk_height ();
2777
2778 if (new_desk_width <= 0)
2779 new_desk_width = 1;
2780 if (new_desk_height <= 0)
2781 new_desk_height = 1;
2782 LOCAL_DEBUG_OUT
2783 (" :RESIZING: old_desk_size(%dx%d) new_desk_size(%dx%d)",
2784 PagerState.desk_width, PagerState.desk_height, new_desk_width,
2785 new_desk_height);
2786 if (new_desk_width != PagerState.desk_width
2787 || new_desk_height != PagerState.desk_height) {
2788 PagerState.desk_width = new_desk_width;
2789 PagerState.desk_height = new_desk_height;
2790 }
2791
2792 rearrange_pager_desks (True);
2793 } else if (changes != 0) {
2794 for (i = 0; i < PagerState.desks_num; ++i)
2795 on_desk_moveresize (&(PagerState.desks[i]));
2796 }
2797 } else { /* then its one of our desk subwindows : */
2798
2799 for (i = 0; i < PagerState.desks_num; ++i) {
2800 if (PagerState.desks[i].desk_canvas->w == w) {
2801 on_desk_moveresize (&(PagerState.desks[i]));
2802 break;
2803 }
2804 }
2805 }
2806 }
2807 }
2808
on_desk_pressure_changed(ASPagerDesk * d,ASEvent * event)2809 void on_desk_pressure_changed (ASPagerDesk * d, ASEvent * event)
2810 {
2811 int root_x = event->x.xbutton.x_root;
2812 int root_y = event->x.xbutton.y_root;
2813 /* int state = event->x.xbutton.state ; */
2814 int context = check_astbar_point (d->title, root_x, root_y);
2815 LOCAL_DEBUG_OUT ("root_pos(%+d%+d)->title_root_pos(%+d%+d)->context(%s)",
2816 root_x, root_y, d->title ? d->title->root_x : 0,
2817 d->title ? d->title->root_y : 0,
2818 context2text (context));
2819 if (context != C_NO_CONTEXT && d->title) {
2820 set_astbar_btn_pressed (d->title, context); /* must go before next call to properly redraw : */
2821 set_astbar_pressed (d->title, d->desk_canvas, context & C_TITLE);
2822 PagerState.pressed_bar = d->title;
2823 PagerState.pressed_context = context;
2824 } else {
2825 set_astbar_pressed (d->background, d->desk_canvas, context & C_TITLE);
2826 PagerState.pressed_bar = d->background;
2827 PagerState.pressed_context = C_ROOT;
2828 }
2829 PagerState.pressed_canvas = d->desk_canvas;
2830 PagerState.pressed_desk = d;
2831 PagerState.pressed_button = event->x.xbutton.button;
2832
2833 LOCAL_DEBUG_OUT ("canvas(%p)->bar(%p)->context(%X)",
2834 PagerState.pressed_canvas, PagerState.pressed_bar,
2835 context);
2836
2837 if (is_canvas_dirty (d->desk_canvas))
2838 update_canvas_display (d->desk_canvas);
2839 }
2840
2841
on_pager_pressure_changed(ASEvent * event)2842 void on_pager_pressure_changed (ASEvent * event)
2843 {
2844 if (event->client == NULL) {
2845 if (event->w == PagerState.main_canvas->w) {
2846
2847
2848 } else {
2849 int i;
2850 for (i = 0; i < PagerState.desks_num; ++i)
2851 if (PagerState.desks[i].desk_canvas->w == event->w) {
2852 on_desk_pressure_changed (&(PagerState.desks[i]), event);
2853 break;
2854 }
2855 }
2856 } else
2857 start_moveresize_client ((ASWindowData *) (event->client),
2858 (event->x.xbutton.state & ControlMask) == 0,
2859 event);
2860 }
2861
on_scroll_viewport(ASEvent * event)2862 void on_scroll_viewport (ASEvent * event)
2863 {
2864 ASPagerDesk *d = PagerState.pressed_desk;
2865 if (d) {
2866 char command[64];
2867 int px = 0, py = 0;
2868 ASQueryPointerRootXY (&px, &py);
2869 px -= d->desk_canvas->root_x + d->desk_canvas->bw;
2870 py -= d->desk_canvas->root_y + d->desk_canvas->bw;
2871 if (px > 0 && px < d->desk_canvas->width &&
2872 py > 0 && py < d->desk_canvas->height) {
2873 px -= d->background->win_x;
2874 py -= d->background->win_y;
2875 if (px >= 0 && py >= 0 &&
2876 px < d->background->width && py < d->background->height) {
2877 int sx = (px * PagerState.vscreen_width) / d->background->width;
2878 int sy = (py * PagerState.vscreen_height) / d->background->height;
2879
2880 sprintf (command, "GotoDeskViewport %d%+d%+d\n", (int)d->desk, sx,
2881 sy);
2882 SendInfo (command, 0);
2883 ++PagerState.wait_as_response;
2884 }
2885 }
2886 }
2887 }
2888
release_pressure()2889 void release_pressure ()
2890 {
2891 if (PagerState.pressed_canvas && PagerState.pressed_bar) {
2892 LOCAL_DEBUG_OUT ("canvas(%p)->bar(%p)->context(%s)",
2893 PagerState.pressed_canvas, PagerState.pressed_bar,
2894 context2text (PagerState.pressed_context));
2895 LOCAL_DEBUG_OUT ("main_geometry(%dx%d%+d%+d)",
2896 PagerState.main_canvas->width,
2897 PagerState.main_canvas->height,
2898 PagerState.main_canvas->root_x,
2899 PagerState.main_canvas->root_y);
2900 if (PagerState.pressed_desk) {
2901 ASPagerDesk *d = PagerState.pressed_desk;
2902 if (PagerState.pressed_context == C_TButton0) {
2903 if (get_flags (Config->flags, VERTICAL_LABEL))
2904 shade_desk_column (d, !get_flags (d->flags, ASP_DeskShaded));
2905 else
2906 shade_desk_row (d, !get_flags (d->flags, ASP_DeskShaded));
2907 } else { /* need to switch desktops here ! */
2908
2909 char command[64];
2910 int px = 0, py = 0;
2911 ASQueryPointerRootXY (&px, &py);
2912 LOCAL_DEBUG_OUT ("pointer root pos(%+d%+d)", px, py);
2913 px -= d->desk_canvas->root_x + d->desk_canvas->bw;
2914 py -= d->desk_canvas->root_y + d->desk_canvas->bw;
2915 if (px > 0 && px < d->desk_canvas->width &&
2916 py > 0 && py < d->desk_canvas->height) {
2917 int new_desk, new_vx = -1, new_vy = -1;
2918 new_desk = d->desk;
2919 px -= d->background->win_x;
2920 py -= d->background->win_y;
2921 if (px >= 0 && py >= 0 &&
2922 px < d->background->width && py < d->background->height) {
2923 if (PagerState.pressed_button == Button3) {
2924 new_vx =
2925 (px * PagerState.vscreen_width) / d->background->width;
2926 new_vy =
2927 (py * PagerState.vscreen_height) / d->background->height;
2928 } else { /* calculate destination page : */
2929 new_vx =
2930 (px * PagerState.page_columns) / d->background->width;
2931 new_vy = (py * PagerState.page_rows) / d->background->height;
2932 new_vx *= Scr.MyDisplayWidth;
2933 new_vy *= Scr.MyDisplayHeight;
2934 }
2935 }
2936 if (new_vx >= 0 && new_vy >= 0)
2937 sprintf (command, "GotoDeskViewport %d%+d%+d\n", new_desk,
2938 new_vx, new_vy);
2939 else
2940 sprintf (command, "Desk 0 %d\n", new_desk);
2941 SendInfo (command, 0);
2942 ++PagerState.wait_as_response;
2943 }
2944 }
2945 }
2946 set_astbar_btn_pressed (PagerState.pressed_bar, 0); /* must go before next call to properly redraw : */
2947 set_astbar_pressed (PagerState.pressed_bar, PagerState.pressed_canvas,
2948 False);
2949 if (is_canvas_dirty (PagerState.pressed_canvas))
2950 update_canvas_display (PagerState.pressed_canvas);
2951 }
2952 PagerState.pressed_canvas = NULL;
2953 PagerState.pressed_bar = NULL;
2954 PagerState.pressed_desk = NULL;
2955 PagerState.pressed_context = C_NO_CONTEXT;
2956 }
2957
2958 /*****************************************************************************
2959 * Grab the pointer and keyboard
2960 ****************************************************************************/
2961 static ScreenInfo *grabbed_screen = NULL;
2962
GrabEm(ScreenInfo * scr,Cursor cursor)2963 Bool GrabEm (ScreenInfo * scr, Cursor cursor)
2964 {
2965 int i = 0;
2966 unsigned int mask;
2967 int res;
2968
2969 XSync (dpy, 0);
2970 /* move the keyboard focus prior to grabbing the pointer to
2971 * eliminate the enterNotify and exitNotify events that go
2972 * to the windows */
2973 grabbed_screen = scr;
2974
2975 mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
2976 PointerMotionMask | EnterWindowMask | LeaveWindowMask;
2977 while ((res =
2978 XGrabPointer (dpy, PagerState.main_canvas->w, True, mask,
2979 GrabModeAsync, GrabModeAsync, scr->Root, cursor,
2980 CurrentTime)) != GrabSuccess) {
2981 if (i++ >= 1000) {
2982 #define MAX_GRAB_ERROR 4
2983 static char *_as_grab_error_code[MAX_GRAB_ERROR + 1 + 1] = {
2984 "Grab Success",
2985 "pointer is actively grabbed by some other client",
2986 "the specified time is earlier than the last-pointer-grab time or later than the current X server time",
2987 "window is not viewable or lies completely outside the boundaries of the root window",
2988 "pointer is frozen by an active grab of another client",
2989 "I'm totally messed up - restart me please"
2990 };
2991 char *error_text = _as_grab_error_code[MAX_GRAB_ERROR + 1];
2992 if (res <= MAX_GRAB_ERROR)
2993 error_text = _as_grab_error_code[res];
2994
2995 show_warning
2996 ("Failed to grab pointer for requested interactive operation.(X server says:\"%s\")",
2997 error_text);
2998 return False;
2999 }
3000 /* If you go too fast, other windows may not get a change to release
3001 * any grab that they have. */
3002 sleep_a_millisec (100);
3003 XSync (dpy, 0);
3004 }
3005 return True;
3006 }
3007
3008 /*****************************************************************************
3009 * UnGrab the pointer and keyboard
3010 ****************************************************************************/
UngrabEm()3011 void UngrabEm ()
3012 {
3013 if (grabbed_screen) { /* check if we grabbed everything */
3014 XSync (dpy, 0);
3015 XUngrabPointer (dpy, CurrentTime);
3016 XSync (dpy, 0);
3017 grabbed_screen = NULL;
3018 }
3019 }
3020