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