1 /*
2  * Copyright (c) 2002,2003 Sasha Vasko <sasha@aftercode.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  */
19 
20 /**********************************************************************
21  *
22  * Add a new window, put the titlbar and other stuff around
23  * the window
24  *
25  **********************************************************************/
26 #define LOCAL_DEBUG
27 
28 #include "../../configure.h"
29 
30 #include "asinternals.h"
31 #include "../../libAfterStep/wmprops.h"
32 
33 /* icon geometry relative to the root window :                      */
get_icon_root_geometry(ASWindow * asw,ASRectangle * geom)34 Bool get_icon_root_geometry (ASWindow * asw, ASRectangle * geom)
35 {
36 	ASCanvas *canvas = NULL;
37 	if (AS_ASSERT (asw) || AS_ASSERT (geom))
38 		return False;
39 
40 	geom->height = 0;
41 	if (asw->icon_canvas) {
42 		canvas = asw->icon_canvas;
43 		if (asw->icon_title_canvas && asw->icon_title_canvas != canvas)
44 			geom->height = asw->icon_title_canvas->height;
45 	} else if (asw->icon_title_canvas)
46 		canvas = asw->icon_title_canvas;
47 
48 	if (canvas) {
49 		geom->x = canvas->root_x;
50 		geom->y = canvas->root_y;
51 		geom->width = canvas->width + canvas->bw * 2;
52 		geom->height += canvas->height + canvas->bw * 2;
53 		return True;
54 	}
55 	return False;
56 }
57 
check_canvas_offscreen(ASCanvas * pc)58 Bool check_canvas_offscreen (ASCanvas * pc)
59 {
60 	if (!pc)
61 		return True;
62 	return (pc->root_x >= Scr.MyDisplayWidth
63 					|| pc->root_y >= Scr.MyDisplayHeight
64 					|| pc->root_x + (int)pc->width < 0
65 					|| pc->root_y + (int)pc->height < 0);
66 }
67 
68 
check_window_offscreen(ASWindow * asw)69 Bool check_window_offscreen (ASWindow * asw)
70 {
71 	if (!ASWIN_GET_FLAGS (asw, AS_Sticky) &&
72 			ASWIN_DESK (asw) != Scr.CurrentDesk)
73 		return True;
74 
75 	return check_canvas_offscreen (asw->client_canvas);
76 }
77 
check_frame_offscreen(ASWindow * asw)78 Bool check_frame_offscreen (ASWindow * asw)
79 {
80 	if (!ASWIN_GET_FLAGS (asw, AS_Sticky) &&
81 			ASWIN_DESK (asw) != Scr.CurrentDesk)
82 		return True;
83 
84 	return check_canvas_offscreen (asw->frame_canvas);
85 }
86 
check_frame_side_offscreen(ASWindow * asw,int side)87 Bool check_frame_side_offscreen (ASWindow * asw, int side)
88 {
89 	if (!ASWIN_GET_FLAGS (asw, AS_Sticky) &&
90 			ASWIN_DESK (asw) != Scr.CurrentDesk)
91 		return True;
92 
93 	return check_canvas_offscreen (asw->frame_sides[side]);
94 }
95 
96 
97 
98 
99 /* this gets called when Root background changes : */
update_window_transparency(ASWindow * asw,Bool force)100 void update_window_transparency (ASWindow * asw, Bool force)
101 {
102 	ASOrientation *od = get_orientation_data (asw);
103 	int i;
104 	ASCanvas *changed_canvases[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
105 
106 	if (!ASWIN_GET_FLAGS (asw, AS_Iconic)) {
107 		ASCanvas *fc;
108 		for (i = 0; i < FRAME_PARTS; ++i)
109 			if (asw->frame_bars[i]) {
110 				fc = asw->frame_sides[od->tbar2canvas_xref[i]];
111 				if (!check_canvas_offscreen (fc)) {
112 					update_astbar_transparency (asw->frame_bars[i], fc, force);
113 					if (DoesBarNeedsRendering (asw->frame_bars[i])) {
114 						changed_canvases[od->tbar2canvas_xref[i]] = fc;
115 						render_astbar (asw->frame_bars[i], fc);
116 					}
117 				}
118 			}
119 
120 		if (asw->tbar) {
121 			fc = asw->frame_sides[od->tbar_side];
122 			if (!check_canvas_offscreen (fc)) {
123 				update_astbar_transparency (asw->tbar, fc, force);
124 				if (DoesBarNeedsRendering (asw->tbar)) {
125 					changed_canvases[od->tbar_side] = fc;
126 					render_astbar (asw->tbar, fc);
127 				}
128 			}
129 		}
130 	} else {
131 		if (asw->icon_button) {
132 			update_astbar_transparency (asw->icon_button, asw->icon_canvas,
133 																	force);
134 			if (DoesBarNeedsRendering (asw->icon_button)) {
135 				changed_canvases[4] = asw->icon_canvas;
136 				render_astbar (asw->icon_button, asw->icon_canvas);
137 			}
138 		}
139 		if (asw->icon_title) {
140 			update_astbar_transparency (asw->icon_title,
141 																	asw->icon_title_canvas ? asw->
142 																	icon_title_canvas : asw->icon_canvas,
143 																	force);
144 			if (DoesBarNeedsRendering (asw->icon_title)) {
145 				if (asw->icon_title_canvas != NULL
146 						&& asw->icon_title_canvas != asw->icon_canvas)
147 					changed_canvases[5] = asw->icon_title_canvas;
148 				else
149 					changed_canvases[4] = asw->icon_canvas;
150 				render_astbar (asw->icon_title,
151 											 asw->icon_title_canvas ? asw->
152 											 icon_title_canvas : asw->icon_canvas);
153 			}
154 		}
155 	}
156 	for (i = 0; i < 6; ++i)
157 		if (changed_canvases[i]) {
158 			invalidate_canvas_save (changed_canvases[i]);
159 			update_canvas_display (changed_canvases[i]);
160 		}
161 
162 }
163 
164 #define GetNormalBarHeight(h,b,od)  \
165 	do{if((b)!=NULL){ *((od)->in_width)=(b)->width; *((od)->in_height)=(b)->height;(h) = *((od)->out_height);} \
166 	   else (h) = 0; \
167 	  }while(0)
168 
169 
make_corner_addon(ASOrientation * od,ASTBarData * longbar,ASTBarData * corner1,ASTBarData * corner2)170 static unsigned int make_corner_addon (ASOrientation * od,
171 																			 ASTBarData * longbar,
172 																			 ASTBarData * corner1,
173 																			 ASTBarData * corner2)
174 {
175 	unsigned int longbar_height = 0, c1_height = 0, c2_height = 0;
176 	GetNormalBarHeight (longbar_height, longbar, od);
177 	GetNormalBarHeight (c1_height, corner1, od);
178 	GetNormalBarHeight (c2_height, corner2, od);
179 	LOCAL_DEBUG_OUT ("longbar_height = %d, c1_height = %d, c2_height = %d",
180 									 longbar_height, c1_height, c2_height);
181 	if (c1_height >= c2_height)
182 		return (c1_height > longbar_height) ? c1_height - longbar_height : 0;
183 	else
184 		return (c2_height > longbar_height) ? c2_height - longbar_height : 0;
185 }
186 
187 static void
resize_canvases(ASWindow * asw,ASOrientation * od,unsigned int normal_width,unsigned int normal_height,unsigned int * frame_sizes)188 resize_canvases (ASWindow * asw, ASOrientation * od,
189 								 unsigned int normal_width, unsigned int normal_height,
190 								 unsigned int *frame_sizes)
191 {
192 	unsigned short tbar_size = frame_sizes[od->tbar_side];
193 	unsigned short sbar_size = frame_sizes[od->sbar_side];
194 	unsigned short tbar_addon, sbar_addon;
195 
196 	/* we need to determine if corners are bigger then frame bars on sbar and tbar : */
197 	tbar_addon =
198 			make_corner_addon (od, asw->frame_bars[od->tbar_side],
199 												 asw->frame_bars[od->tbar_mirror_corners[0]],
200 												 asw->frame_bars[od->tbar_mirror_corners[1]]);
201 	sbar_addon =
202 			make_corner_addon (od, asw->frame_bars[od->sbar_side],
203 												 asw->frame_bars[od->sbar_mirror_corners[0]],
204 												 asw->frame_bars[od->sbar_mirror_corners[1]]);
205 	tbar_size += tbar_addon;
206 	sbar_size += sbar_addon;
207 	LOCAL_DEBUG_OUT
208 			("tbar_size = %d, addon = %d, sbar_size = %d, addon = %d, frame_sizes = {%d,%d}",
209 			 tbar_size, tbar_addon, sbar_size, sbar_addon,
210 			 frame_sizes[od->tbar_side], frame_sizes[od->sbar_side]);
211 	*(od->in_width) = normal_width;
212 	*(od->in_height) = tbar_size;
213 	if (asw->frame_sides[od->tbar_side])
214 		moveresize_canvas (asw->frame_sides[od->tbar_side], 0, 0,
215 											 *(od->out_width), *(od->out_height));
216 
217 	*(od->in_x) = 0;
218 	*(od->in_y) = normal_height - sbar_size;
219 	*(od->in_height) = sbar_size;
220 	if (asw->frame_sides[od->sbar_side])
221 		moveresize_canvas (asw->frame_sides[od->sbar_side], *(od->out_x),
222 											 *(od->out_y), *(od->out_width), *(od->out_height));
223 
224 	/* for left and right sides - somewhat twisted logic - we mirror sides over lt2rb diagonal in case of
225 	 * vertical title orientation. That allows us to apply simple x/y switching instead of complex
226 	 * calculations. Note that we only do that for placement purposes. Contexts and images are still taken
227 	 * from MyFrame parts as if it was rotated counterclockwise instead of mirrored.
228 	 */
229 	*(od->in_x) = 0;
230 	*(od->in_y) = tbar_size;
231 	*(od->in_width) = frame_sizes[od->left_mirror_side];
232 	*(od->in_height) = normal_height - (tbar_size + sbar_size);
233 	if (asw->frame_sides[od->left_mirror_side])
234 		moveresize_canvas (asw->frame_sides[od->left_mirror_side],
235 											 *(od->out_x), *(od->out_y), *(od->out_width),
236 											 *(od->out_height));
237 
238 	*(od->in_x) = normal_width - frame_sizes[od->right_mirror_side];
239 	*(od->in_width) = frame_sizes[od->right_mirror_side];
240 	if (asw->frame_sides[od->right_mirror_side])
241 		moveresize_canvas (asw->frame_sides[od->right_mirror_side],
242 											 *(od->out_x), *(od->out_y), *(od->out_width),
243 											 *(od->out_height));
244 }
245 
246 #if 0
247 static unsigned short frame_side_height (ASCanvas * c1, ASCanvas * c2)
248 {
249 	unsigned short h = 0;
250 	if (c1)
251 		h += c1->height;
252 	if (c2)
253 		h += c2->height;
254 	return h;
255 }
256 
257 static unsigned short frame_side_width (ASCanvas * c1, ASCanvas * c2)
258 {
259 	unsigned short w = 0;
260 	if (c1)
261 		w += c1->width;
262 	if (c2)
263 		w += c2->width;
264 	return w;
265 }
266 
267 static unsigned short
268 frame_corner_height (ASTBarData * c1, ASTBarData * c2)
269 {
270 	unsigned short h = 0;
271 	if (c1)
272 		h += c1->height;
273 	if (c2)
274 		h += c2->height;
275 	return h;
276 }
277 
278 static unsigned short frame_corner_width (ASTBarData * c1, ASTBarData * c2)
279 {
280 	unsigned short w = 0;
281 	if (c1)
282 		w += c1->width;
283 	if (c2)
284 		w += c2->width;
285 	return w;
286 }
287 #endif
288 
make_shade_animation_step(ASWindow * asw,ASOrientation * od)289 static int make_shade_animation_step (ASWindow * asw, ASOrientation * od)
290 {
291 	int step_size = 0;
292 	if (asw->tbar) {
293 		int steps = asw->shading_steps;
294 
295 		if (steps > 0) {
296 			int from_size, to_size;
297 			*(od->in_width) = asw->frame_canvas->width;
298 			*(od->in_height) = asw->frame_canvas->height;
299 			from_size = *(od->out_height);
300 			if (ASWIN_GET_FLAGS (asw, AS_Shaded)) {
301 				*(od->in_width) = asw->tbar->width;
302 				*(od->in_height) = asw->tbar->height;
303 			} else {
304 				*(od->in_width) = asw->status->width;
305 				*(od->in_height) = asw->status->height;
306 			}
307 			to_size = *(od->out_height);
308 
309 			if (from_size != to_size) {
310 				int step_delta = (from_size - to_size) / steps;
311 				if (step_delta == 0)
312 					step_delta = (from_size > to_size) ? 1 : -1;
313 				LOCAL_DEBUG_OUT ("@@ANIM to(%d)->from(%d)->delta(%d)->step(%d)",
314 												 to_size, from_size, step_delta, steps);
315 
316 				step_size = from_size - step_delta;
317 				--(asw->shading_steps);
318 			}
319 		} else if (!ASWIN_GET_FLAGS (asw, AS_Shaded)) {
320 			/* when we shade the window - focus gets set to frame window -
321 			   we need to revert it back to the client : */
322 			if (Scr.Windows->focused == asw) {
323 				focus_window (asw, asw->w);
324 				autoraise_window (asw);
325 			}
326 			if (!ASWIN_GET_FLAGS (asw, AS_Dead))
327 				XRaiseWindow (dpy, asw->w);
328 			return 0;
329 		} else {
330 			*(od->in_width) = asw->tbar->width;
331 			*(od->in_height) = asw->tbar->height;
332 			return *(od->out_height);
333 		}
334 	}
335 	return step_size;
336 }
337 
338 inline static Bool
move_resize_frame_bar(ASTBarData * tbar,ASCanvas * canvas,int normal_x,int normal_y,unsigned int normal_width,unsigned int normal_height,Bool force_render)339 move_resize_frame_bar (ASTBarData * tbar, ASCanvas * canvas, int normal_x,
340 											 int normal_y, unsigned int normal_width,
341 											 unsigned int normal_height, Bool force_render)
342 {
343 	if (set_astbar_size (tbar, normal_width, normal_height))
344 		force_render = True;
345 	if (move_astbar (tbar, canvas, normal_x, normal_y))
346 		force_render = True;
347 	if (force_render)
348 		render_astbar (tbar, canvas);
349 	return force_render;
350 }
351 
352 inline static Bool
move_resize_corner(ASTBarData * bar,ASCanvas * canvas,ASOrientation * od,int normal_y,unsigned int normal_width,unsigned int normal_height,Bool left,Bool force_render)353 move_resize_corner (ASTBarData * bar, ASCanvas * canvas,
354 										ASOrientation * od, int normal_y,
355 										unsigned int normal_width, unsigned int normal_height,
356 										Bool left, Bool force_render)
357 {
358 	unsigned int w = bar->width;
359 	unsigned int h = bar->height;
360 
361 	*(od->in_y) = normal_y;
362 
363 	if (od == &VertOrientation)
364 		w = normal_height - normal_y;
365 	else
366 		h = normal_height - normal_y;
367 	LOCAL_DEBUG_OUT
368 			(" w = %d, h = %d, bar->width = %d, bar->height = %d, n_w = %d, n_h = %d, n_y = %d",
369 			 w, h, bar->width, bar->height, normal_width, normal_height,
370 			 normal_y);
371 	*(od->in_width) = w;
372 	*(od->in_height) = h;
373 	*(od->in_x) = left ? 0 : (normal_width - (*(od->out_width)));
374 	return move_resize_frame_bar (bar, canvas, *(od->out_x), *(od->out_y), w,
375 																h, force_render);
376 }
377 
378 inline static Bool
move_resize_longbar(ASTBarData * bar,ASCanvas * canvas,ASOrientation * od,int normal_offset,unsigned int normal_length,unsigned int corner_size1,unsigned int corner_size2,Bool vertical,Bool force_render)379 move_resize_longbar (ASTBarData * bar, ASCanvas * canvas,
380 										 ASOrientation * od, int normal_offset,
381 										 unsigned int normal_length, unsigned int corner_size1,
382 										 unsigned int corner_size2, Bool vertical,
383 										 Bool force_render)
384 {
385 	unsigned int w = bar->width;
386 	unsigned int h = bar->height;
387 	int bar_size;
388 
389 	LOCAL_DEBUG_OUT
390 			("normal_offset = %d, normal_length = %d, corner_sizes = %d,%d, vert = %d, force = %d",
391 			 normal_offset, normal_length, corner_size1, corner_size2, vertical,
392 			 force_render);
393 	/* swapping bar height in case of vertical orientation of the etire window: */
394 	*(od->in_width) = w;
395 	*(od->in_height) = h;
396 
397 	if (vertical) {								/*vertical bar - west or east */
398 		bar_size = *(od->out_width);
399 		*(od->in_width) = bar_size;
400 		*(od->in_height) = normal_length;
401 		*(od->in_x) = normal_offset;
402 		*(od->in_y) = corner_size1;
403 	} else {
404 		bar_size = *(od->out_height);
405 		*(od->in_height) = bar_size;
406 		if (corner_size1 + corner_size2 > normal_length)
407 			*(od->in_width) = 1;
408 		else
409 			*(od->in_width) = normal_length - (corner_size1 + corner_size2);
410 		*(od->in_x) = corner_size1;
411 		*(od->in_y) = normal_offset;
412 	}
413 
414 	return move_resize_frame_bar (bar, canvas, *(od->out_x), *(od->out_y),
415 																*(od->out_width), *(od->out_height),
416 																force_render);
417 }
418 
419 static unsigned int
condense_tbar(ASTBarData * tbar,unsigned int max_size,unsigned int * off1,unsigned int * off2,Bool vert,ASFlagType align)420 condense_tbar (ASTBarData * tbar, unsigned int max_size,
421 							 unsigned int *off1, unsigned int *off2, Bool vert,
422 							 ASFlagType align)
423 {
424 	unsigned int condensed = max_size;
425 	*off1 = 0;
426 	*off2 = 0;
427 
428 #ifdef SHAPE
429 	if (get_flags (align, ALIGN_LEFT | ALIGN_RIGHT)) {
430 		if (vert) {
431 			condensed = calculate_astbar_height (tbar);
432 			if (condensed < max_size) {
433 				if (get_flags (align, ALIGN_LEFT)) {
434 					*off1 = max_size - condensed;
435 					if (get_flags (align, ALIGN_RIGHT)) {
436 						*off1 /= 2;
437 						*off2 = *off1;
438 					}
439 				} else
440 					*off2 = max_size - condensed;
441 			} else
442 				condensed = max_size;
443 		} else {
444 			condensed = calculate_astbar_width (tbar);
445 			if (condensed < max_size) {
446 				if (get_flags (align, ALIGN_RIGHT)) {
447 					*off1 = max_size - condensed;
448 					if (get_flags (align, ALIGN_LEFT)) {
449 						*off1 /= 2;
450 						*off2 = *off1;
451 					}
452 				} else
453 					*off2 = max_size - condensed;
454 			} else
455 				condensed = max_size;
456 		}
457 	}
458 #endif
459 	return condensed;
460 }
461 
462 
463 static Bool
move_resize_frame_bars(ASWindow * asw,int side,ASOrientation * od,unsigned int normal_width,unsigned int normal_height,Bool force_render)464 move_resize_frame_bars (ASWindow * asw, int side, ASOrientation * od,
465 												unsigned int normal_width,
466 												unsigned int normal_height, Bool force_render)
467 {
468 	int corner_size1 = 0, corner_size2 = 0;
469 	Bool rendered = False;
470 	int tbar_size = 0;
471 	ASCanvas *canvas = asw->frame_sides[side];
472 	ASTBarData *title = NULL, *corner1 = NULL, *longbar = NULL, *corner2 =
473 			NULL;
474 	Bool vertical = False;
475 
476 	LOCAL_DEBUG_CALLER_OUT ("%p,%d, %ux%u, %s", asw, side, normal_width,
477 													normal_height,
478 													force_render ? "force" : "don't force");
479 	longbar = asw->frame_bars[side];
480 	if (side == od->tbar_side) {
481 		title = asw->tbar;
482 		corner1 = asw->frame_bars[od->tbar_mirror_corners[0]];
483 		corner2 = asw->frame_bars[od->tbar_mirror_corners[1]];
484 	} else if (side == od->sbar_side) {
485 		corner1 = asw->frame_bars[od->sbar_mirror_corners[0]];
486 		corner2 = asw->frame_bars[od->sbar_mirror_corners[1]];
487 	} else
488 		vertical = True;
489 
490 	if (title) {
491 		unsigned int tbar_offset1, tbar_offset2, tbar_width;
492 
493 		tbar_width =
494 				condense_tbar (title, normal_width, &tbar_offset1, &tbar_offset2,
495 											 ASWIN_HFLAGS (asw, AS_VerticalTitle),
496 											 asw->frame_data->condense_titlebar);
497 		if (tbar_offset1 > 0 || tbar_offset2 > 0 || tbar_width != normal_width)
498 			set_flags (canvas->state, CANVAS_FORCE_MASK);
499 
500 		/* title always considered a "horizontal bar" */
501 		if (move_resize_longbar
502 				(title, canvas, od, 0, normal_width, tbar_offset1, tbar_offset2,
503 				 False, force_render))
504 			rendered = True;
505 		tbar_size = *(od->in_height);
506 	}
507 	/* mirror_corner 0 */
508 	if (corner1) {
509 		if (move_resize_corner
510 				(corner1, canvas, od, tbar_size, normal_width, normal_height, True,
511 				 force_render))
512 			rendered = True;
513 		corner_size1 = *(od->out_width);
514 	}
515 	/* mirror_corner 1 */
516 	if (corner2) {
517 		if (move_resize_corner
518 				(corner2, canvas, od, tbar_size, normal_width, normal_height,
519 				 False, force_render))
520 			rendered = True;
521 		corner_size2 = *(od->out_width);
522 	}
523 	/* side */
524 	if (longbar) {
525 		if (side != od->tbar_side && (corner_size1 > 0 || corner_size2 > 0)) {	/* we are in the sbar */
526 			*(od->in_width) = longbar->width;
527 			*(od->in_height) = longbar->height;
528 			tbar_size = normal_height - (int)(*(od->out_height));
529 			if (tbar_size < 0)
530 				tbar_size = 0;
531 		}
532 		if (move_resize_longbar (longbar, canvas, od,
533 														 tbar_size,
534 														 vertical ? normal_height : normal_width,
535 														 corner_size1, corner_size2, vertical,
536 														 force_render))
537 			rendered = True;
538 	}
539 
540 	return rendered;
541 }
542 
543 static ASFlagType
resize_frame_subwindows(ASWindow * asw,ASOrientation * od,unsigned int frame_win_width,unsigned int frame_win_height)544 resize_frame_subwindows (ASWindow * asw, ASOrientation * od,
545 												 unsigned int frame_win_width,
546 												 unsigned int frame_win_height)
547 {
548 	register unsigned int *frame_size = &(asw->status->frame_size[0]);
549 	unsigned int normal_width, normal_height;
550 	ASFlagType client_changes = 0;
551 
552 	if (od == NULL)
553 		od = get_orientation_data (asw);
554 
555 	*(od->in_width) = asw->frame_canvas->width;
556 	*(od->in_height) = asw->frame_canvas->height;
557 	normal_width = *(od->out_width);
558 	normal_height = *(od->out_height);
559 
560 	resize_canvases (asw, od, normal_width, normal_height, frame_size);
561 	if (!ASWIN_GET_FLAGS (asw, AS_Shaded))	/* leave shaded client alone ! */
562 		client_changes = moveresize_canvas (asw->client_canvas,
563 																				frame_size[FR_W], frame_size[FR_N],
564 																				(int)frame_win_width -
565 																				(int)(frame_size[FR_W] +
566 																							frame_size[FR_E]),
567 																				(int)frame_win_height -
568 																				(int)(frame_size[FR_N] +
569 																							frame_size[FR_S]));
570 	return client_changes;
571 }
572 
573 
574 
apply_window_status_size(register ASWindow * asw,ASOrientation * od)575 Bool apply_window_status_size (register ASWindow * asw, ASOrientation * od)
576 {
577 	Bool moved = False;
578 	Bool resized = False;
579 	ASFlagType client_changes = 0;
580 	/* note that icons are handled by iconbox */
581 	if (!ASWIN_GET_FLAGS (asw, AS_Iconic)) {
582 		int step_size = make_shade_animation_step (asw, od);
583 		int new_width = asw->status->width;
584 		int new_height = asw->status->height;
585 		LOCAL_DEBUG_OUT
586 				("**CONFG Client(%lx(%s))->status(%ux%u%+d%+d,%s,%s(%d>-%d))",
587 				 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname",
588 				 asw->status->width, asw->status->height, asw->status->x,
589 				 asw->status->y, ASWIN_HFLAGS (asw,
590 																			 AS_VerticalTitle) ? "Vert" : "Horz",
591 				 step_size > 0 ? "Shaded" : "Unshaded", asw->shading_steps,
592 				 step_size);
593 
594 		if (step_size > 0) {
595 			if (ASWIN_HFLAGS (asw, AS_VerticalTitle)) {
596 				new_width = step_size;
597 			} else {
598 				new_height = step_size;
599 			}
600 		}
601 		resized = (asw->frame_canvas->width != new_width ||
602 							 asw->frame_canvas->height != new_height);
603 		moved = (asw->frame_canvas->root_x != asw->status->x ||
604 						 asw->frame_canvas->root_y != asw->status->y);
605 
606 		moveresize_canvas (asw->frame_canvas, asw->status->x, asw->status->y,
607 											 new_width, new_height);
608 		/* when we resize the client - our frame should already be positioned correctly ! */
609 		if (step_size <= 0)
610 			client_changes =
611 					resize_frame_subwindows (asw, od, new_width, new_height);
612 #if 0
613 		fprintf (stderr, "client_changes = %X, moved = %d. Called from :\n",
614 						 client_changes, moved);
615 		print_simple_backtrace ();
616 #endif
617 		if (moved && client_changes == 0)
618 			send_canvas_configure_notify (asw->frame_canvas, asw->client_canvas);
619 	}
620 	return moved || resized || client_changes != 0;
621 }
622 
623 static void
on_frame_bars_moved(ASWindow * asw,unsigned int side,ASOrientation * od)624 on_frame_bars_moved (ASWindow * asw, unsigned int side, ASOrientation * od)
625 {
626 	ASCanvas *canvas = asw->frame_sides[side];
627 
628 	update_astbar_transparency (asw->frame_bars[side], canvas, False);
629 	if (side == od->tbar_side) {
630 		update_astbar_transparency (asw->tbar, canvas, False);
631 		update_astbar_transparency (asw->
632 																frame_bars[od->tbar_mirror_corners[0]],
633 																canvas, False);
634 		update_astbar_transparency (asw->
635 																frame_bars[od->tbar_mirror_corners[1]],
636 																canvas, False);
637 	} else if (side == od->sbar_side) {
638 		update_astbar_transparency (asw->
639 																frame_bars[od->sbar_mirror_corners[0]],
640 																canvas, False);
641 		update_astbar_transparency (asw->
642 																frame_bars[od->sbar_mirror_corners[1]],
643 																canvas, False);
644 	}
645 }
646 
update_window_frame_moved(ASWindow * asw,ASOrientation * od)647 void update_window_frame_moved (ASWindow * asw, ASOrientation * od)
648 {
649 	int i;
650 
651 	if (ASWIN_GET_FLAGS (asw, AS_Dead | AS_MoveresizeInProgress))
652 		return;
653 
654 	handle_canvas_config (asw->client_canvas);
655 
656 	if (!check_window_offscreen (asw))
657 		if (asw->internal && asw->internal->on_moveresize)
658 			asw->internal->on_moveresize (asw->internal, None);
659 
660 	if (!check_frame_offscreen (asw))
661 		for (i = 0; i < FRAME_SIDES; ++i)
662 			if (asw->frame_sides[i]) {
663 				handle_canvas_config (asw->frame_sides[i]);
664 				if (!check_frame_side_offscreen (asw, i)) {	/* canvas has been resized - resize tbars!!! */
665 					on_frame_bars_moved (asw, i, od);
666 				}
667 			}
668 }
669 
update_window_frame_pos(ASWindow * asw)670 void update_window_frame_pos (ASWindow * asw)
671 {
672 	if (ASWIN_GET_FLAGS (asw, AS_Dead | AS_MoveresizeInProgress))
673 		return;
674 
675 	handle_canvas_config (asw->client_canvas);
676 
677 /*
678 	if (!check_window_offscreen( asw ))
679 		if( asw->internal && asw->internal->on_moveresize )
680 			asw->internal->on_moveresize( asw->internal, None );
681 */
682 
683 	if (!check_frame_offscreen (asw)) {
684 		int i;
685 		ASFlagType changes = 0;
686 		for (i = 0; i < FRAME_SIDES; ++i)
687 			if (asw->frame_sides[i])
688 				changes |= handle_canvas_config (asw->frame_sides[i]);
689 
690 		if (changes != 0)
691 			update_window_transparency (asw, False);
692 	}
693 }
694 
695 
SendConfigureNotify(ASWindow * asw)696 void SendConfigureNotify (ASWindow * asw)
697 {
698 	XEvent client_event;
699 
700 	if (ASWIN_GET_FLAGS (asw, AS_Dead | AS_MoveresizeInProgress))
701 		return;
702 
703 	client_event.type = ConfigureNotify;
704 	client_event.xconfigure.display = dpy;
705 	client_event.xconfigure.event = asw->w;
706 	client_event.xconfigure.window = asw->w;
707 
708 	client_event.xconfigure.x = asw->client_canvas->root_x;
709 	client_event.xconfigure.y = asw->client_canvas->root_y;
710 	client_event.xconfigure.width = asw->client_canvas->width;
711 	client_event.xconfigure.height = asw->client_canvas->height;
712 
713 	client_event.xconfigure.border_width = asw->status->border_width;
714 	/* Real ConfigureNotify events say we're above title window, so ... */
715 	/* what if we don't have a title ????? */
716 	client_event.xconfigure.above =
717 			asw->frame_sides[FR_N] ? asw->frame_sides[FR_N]->w : asw->frame;
718 	client_event.xconfigure.override_redirect = False;
719 	XSendEvent (dpy, asw->w, False, StructureNotifyMask, &client_event);
720 }
721 
722 static Bool
check_frame_side_config(ASWindow * asw,Window w,ASOrientation * od)723 check_frame_side_config (ASWindow * asw, Window w, ASOrientation * od)
724 {
725 	Bool found = False;
726 	int i;
727 	unsigned int normal_width, normal_height;
728 
729 	for (i = 0; i < FRAME_SIDES; ++i)
730 		if (asw->frame_sides[i] && asw->frame_sides[i]->w == w) {	/* canvas has beer resized - resize tbars!!! */
731 			Bool changes = handle_canvas_config (asw->frame_sides[i]);
732 
733 			/* we must resize using current window size instead of event's size */
734 			*(od->in_width) = asw->frame_sides[i]->width;
735 			*(od->in_height) = asw->frame_sides[i]->height;
736 			normal_width = *(od->out_width);
737 			normal_height = *(od->out_height);
738 
739 			/* don't redraw window decoration while in the middle of animation : */
740 			if (asw->shading_steps <= 0) {
741 				if (move_resize_frame_bars (asw, i, od, normal_width, normal_height, changes) || changes) {	/* now we need to show them on screen !!!! */
742 					update_canvas_display (asw->frame_sides[i]);
743 					if (ASWIN_GET_FLAGS (asw, AS_Shaped | AS_ShapedDecor))
744 						SetShape (asw, 0);
745 					else if (get_flags
746 									 (asw->internal_flags, ASWF_PendingShapeRemoval))
747 						ClearShape (asw);
748 				}
749 			}
750 			found = True;
751 			break;
752 		}
753 	return found;
754 }
755 
756 static void
move_shading_frame(ASWindow * asw,ASOrientation * od,int step_size)757 move_shading_frame (ASWindow * asw, ASOrientation * od, int step_size)
758 {
759 	if (asw->frame_sides[od->sbar_side]) {
760 		XRaiseWindow (dpy, asw->frame_sides[od->sbar_side]->w);
761 		if (ASWIN_HFLAGS (asw, AS_VerticalTitle))
762 			move_canvas (asw->frame_sides[od->sbar_side],
763 									 step_size - asw->frame_sides[od->sbar_side]->width, 0);
764 		else
765 			move_canvas (asw->frame_sides[od->sbar_side], 0,
766 									 step_size - asw->frame_sides[od->sbar_side]->height);
767 	}
768 	if (asw->frame_sides[od->tbar_side])
769 		XRaiseWindow (dpy, asw->frame_sides[od->tbar_side]->w);
770 }
771 
772 
773 /* this gets called when StructureNotify/SubstractureNotify arrives : */
on_window_moveresize(ASWindow * asw,Window w)774 void on_window_moveresize (ASWindow * asw, Window w)
775 {
776 	int i;
777 	ASOrientation *od;
778 	unsigned int normal_width, normal_height;
779 	Bool update_shape = False;
780 
781 	LOCAL_DEBUG_CALLER_OUT ("(%p,%lx,asw->w=%lx)", asw, w, asw->w);
782 	if (AS_ASSERT (asw))
783 		return;
784 
785 	od = get_orientation_data (asw);
786 
787 	if (w == asw->w) {						/* simply update client's size and position */
788 		ASFlagType changes;
789 		if (ASWIN_GET_FLAGS (asw, AS_Dead))
790 			return;
791 		changes = handle_canvas_config (asw->client_canvas);
792 		if (asw->internal && asw->internal->on_moveresize)
793 			asw->internal->on_moveresize (asw->internal, w);
794 
795 		update_shape = (changes != 0);
796 		if (XPending (dpy) > 0) {
797 			XEvent tmp;
798 			XNextEvent (dpy, &tmp);
799 			if (tmp.type == ConfigureNotify
800 					&& tmp.xconfigure.window == asw->frame)
801 				w = asw->frame;
802 			else
803 				XPutBackEvent (dpy, &tmp);
804 		}
805 
806 	}
807 
808 	if (w == asw->frame) {				/* resize canvases here : */
809 		int changes = handle_canvas_config (asw->frame_canvas);
810 		LOCAL_DEBUG_OUT ("changes=0x%X", changes);
811 		/* we must resize using current window size instead of event's size */
812 		*(od->in_width) = asw->frame_canvas->width;
813 		*(od->in_height) = asw->frame_canvas->height;
814 		normal_width = *(od->out_width);
815 		normal_height = *(od->out_height);
816 
817 		if (get_flags (changes, CANVAS_RESIZED)) {
818 			register unsigned int *frame_size = &(asw->status->frame_size[0]);
819 			int step_size = make_shade_animation_step (asw, od);
820 			LOCAL_DEBUG_OUT ("step_size = %d", step_size);
821 			if (step_size <= 0) {			/* don't moveresize client window while shading !!!! */
822 				resize_frame_subwindows (asw, od, asw->frame_canvas->width,
823 																 asw->frame_canvas->height);
824 			} else {
825 				if (normal_height != step_size) {
826 					*(od->in_width) = normal_width;
827 					*(od->in_height) = step_size;
828 
829 					if (normal_height < step_size) {
830 						/* we get smoother animation if we move decoration ahead of actually
831 						 * resizing frame window : */
832 						move_shading_frame (asw, od, step_size);
833 						ASSync (False);
834 						sleep_a_millisec (10);
835 						/*LOCAL_DEBUG_OUT( "**SHADE Client(%lx(%s))->(%d>-%d)", asw->w, ASWIN_NAME(asw)?ASWIN_NAME(asw):"noname", asw->shading_steps, step_size ); */
836 						resize_canvas (asw->frame_canvas, *(od->out_width),
837 													 *(od->out_height));
838 						ASSync (False);
839 					} else {
840 						sleep_a_millisec (10);
841 						resize_canvas (asw->frame_canvas, *(od->out_width),
842 													 *(od->out_height));
843 						ASSync (False);
844 						move_shading_frame (asw, od, step_size);
845 						ASSync (False);
846 					}
847 				} else {								/* probably just the change of the look - titlebar may need to be resized */
848 					resize_canvases (asw, od, normal_width, normal_height,
849 													 frame_size);
850 					move_canvas (asw->client_canvas, frame_size[FR_W],
851 											 frame_size[FR_N]);
852 				}
853 
854 			}
855 			if (asw->shading_steps == 0) {
856 				for (i = 0; i < FRAME_SIDES; ++i)
857 					if (asw->frame_sides[i])
858 						check_frame_side_config (asw, asw->frame_sides[i]->w, od);
859 			}
860 			update_shape = True;
861 		} else if (get_flags (changes, CANVAS_MOVED)) {
862 			LOCAL_DEBUG_OUT ("window is moved but not resized %s", "");
863 			update_window_frame_moved (asw, od);
864 			/* also sent synthetic ConfigureNotify : */
865 			SendConfigureNotify (asw);
866 		}
867 
868 		if (changes != 0) {
869 			LOCAL_DEBUG_OUT ("resized = %X, shaped = %lX",
870 											 get_flags (changes, CANVAS_RESIZED),
871 											 ASWIN_GET_FLAGS (asw, AS_ShapedDecor | AS_Shaped));
872 
873 			if (!check_frame_offscreen (asw))
874 				update_window_transparency (asw, False);
875 
876 			if (!ASWIN_GET_FLAGS (asw, AS_Dead | AS_MoveresizeInProgress))
877 				broadcast_config (M_CONFIGURE_WINDOW, asw);
878 		}
879 	} else if (asw->icon_canvas && w == asw->icon_canvas->w) {
880 		ASFlagType changes = handle_canvas_config (asw->icon_canvas);
881 		LOCAL_DEBUG_OUT ("icon resized to %dx%d%+d%+d",
882 										 asw->icon_canvas->width, asw->icon_canvas->height,
883 										 asw->icon_canvas->root_x, asw->icon_canvas->root_y);
884 		if (get_flags (changes, CANVAS_RESIZED)) {
885 			unsigned short title_size = 0;
886 			if (asw->icon_title
887 					&& (asw->icon_title_canvas == asw->icon_canvas
888 							|| asw->icon_title_canvas == NULL)) {
889 				title_size = calculate_astbar_height (asw->icon_title);
890 				move_astbar (asw->icon_title, asw->icon_canvas, 0,
891 										 asw->icon_canvas->height - title_size);
892 				set_astbar_size (asw->icon_title, asw->icon_canvas->width,
893 												 title_size);
894 				if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
895 					render_astbar (asw->icon_title, asw->icon_canvas);
896 				}
897 				LOCAL_DEBUG_OUT ("title_size = %d", title_size);
898 			}
899 			set_astbar_size (asw->icon_button, asw->icon_canvas->width,
900 											 asw->icon_canvas->height - title_size);
901 			if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
902 				render_astbar (asw->icon_button, asw->icon_canvas);
903 				update_canvas_display (asw->icon_canvas);
904 			}
905 		}
906 		if (ASWIN_GET_FLAGS (asw, AS_Iconic))
907 			broadcast_config (M_CONFIGURE_WINDOW, asw);
908 	} else if (asw->icon_title_canvas && w == asw->icon_title_canvas->w) {
909 		if (handle_canvas_config (asw->icon_title_canvas) && asw->icon_title) {
910 			LOCAL_DEBUG_OUT ("icon_title resized to %dx%d%+d%+d",
911 											 asw->icon_title_canvas->width,
912 											 asw->icon_title_canvas->height,
913 											 asw->icon_title_canvas->root_x,
914 											 asw->icon_title_canvas->root_y);
915 			set_astbar_size (asw->icon_title, asw->icon_title_canvas->width,
916 											 asw->icon_title->height);
917 			if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
918 				render_astbar (asw->icon_title, asw->icon_title_canvas);
919 				update_canvas_display (asw->icon_title_canvas);
920 			}
921 		}
922 		if (ASWIN_GET_FLAGS (asw, AS_Iconic))
923 			broadcast_config (M_CONFIGURE_WINDOW, asw);
924 	} else if (asw->shading_steps == 0) {	/* one of the frame canvases : */
925 		if (!check_frame_side_config (asw, w, od))
926 			if (asw->internal && asw->internal->on_moveresize)
927 				asw->internal->on_moveresize (asw->internal, w);
928 	}
929 
930 	if (update_shape) {
931 		if (ASWIN_GET_FLAGS (asw, AS_ShapedDecor | AS_Shaped))
932 			SetShape (asw, 0);
933 		else if (get_flags (asw->internal_flags, ASWF_PendingShapeRemoval))
934 			ClearShape (asw);
935 	}
936 
937 	ASSync (False);
938 }
939 
940 int update_window_tbar_size (ASWindow * asw);
941 
942 
on_window_title_changed(ASWindow * asw,Bool update_display)943 void on_window_title_changed (ASWindow * asw, Bool update_display)
944 {
945 	if (AS_ASSERT (asw))
946 		return;
947 	if (is_output_level_under_threshold (OUTPUT_LEVEL_HINTS))
948 		print_clean_hints (NULL, NULL, asw->hints);
949 	if (asw->tbar) {
950 		ASCanvas *canvas =
951 				ASWIN_HFLAGS (asw,
952 											AS_VerticalTitle) ? asw->frame_sides[FR_W] : asw->
953 				frame_sides[FR_N];
954 		if (change_astbar_first_label
955 				(asw->tbar, ASWIN_NAME (asw), ASWIN_NAME_ENCODING (asw)))
956 			if (canvas && update_display) {
957 				invalidate_canvas_save (canvas);
958 
959 				if (canvas->shape) {
960 					XRectangle rect;
961 					rect.x = asw->tbar->win_x;
962 					rect.y = asw->tbar->win_y;
963 					rect.width = asw->tbar->width;
964 					rect.height = asw->tbar->height;
965 					subtract_shape_rectangle (canvas->shape, &rect, 1, 0, 0,
966 																		canvas->width, canvas->height);
967 				}
968 				update_window_tbar_size (asw);
969 				render_astbar (asw->tbar, canvas);
970 				update_canvas_display (canvas);
971 				//if( ASWIN_GET_FLAGS( asw, AS_ShapedDecor ) )
972 				SetShape (asw, 0);
973 			}
974 	}
975 	LOCAL_DEBUG_OUT ("icon_title = %p, icon_name = \"%s\"", asw->icon_title,
976 									 ASWIN_ICON_NAME (asw) ? ASWIN_ICON_NAME (asw) :
977 									 "(null)");
978 	if (asw->icon_title) {
979 		if (change_astbar_first_label
980 				(asw->icon_title, ASWIN_ICON_NAME (asw),
981 				 ASWIN_ICON_NAME_ENC (asw)))
982 			if (ASWIN_GET_FLAGS (asw, AS_Iconic))
983 				on_icon_changed (asw);
984 	}
985 }
986 
987 Bool collect_aswindow_hints (ASWindow * asw, ASRawHints * raw_hints);
988 
on_window_hints_changed(ASWindow * asw)989 void on_window_hints_changed (ASWindow * asw)
990 {
991 	static ASRawHints raw_hints;
992 	ASHints *hints = NULL, *old_hints = NULL;
993 	Bool tie_changed = False;
994 	ASStatusHints scratch_status;	/* all we need from it is AS_Urgent state change */
995 	Bool status_changed = False;
996 
997 
998 	if (AS_ASSERT (asw))
999 		return;
1000 	if (ASWIN_GET_FLAGS (asw, AS_Dead))
1001 		return;
1002 	if (!collect_aswindow_hints (asw, &raw_hints))
1003 		return;
1004 
1005 	memset (&scratch_status, 0x00, sizeof (scratch_status));
1006 
1007 	hints =
1008 			merge_hints (&raw_hints, Database, &scratch_status,
1009 									 Scr.Look.supported_hints, HINT_ANY, NULL, asw->w);
1010 
1011 	destroy_raw_hints (&raw_hints, True);
1012 	if (hints) {
1013 		show_debug (__FILE__, __FUNCTION__, __LINE__,
1014 								"Window management hints collected and merged for window %X",
1015 								asw->w);
1016 		if (is_output_level_under_threshold (OUTPUT_LEVEL_HINTS))
1017 			print_clean_hints (NULL, NULL, hints);
1018 	} else {
1019 		show_warning ("Failed to merge window management hints for window %X",
1020 									asw->w);
1021 		return;
1022 	}
1023 
1024 	old_hints = asw->hints;
1025 	tie_changed = ((old_hints->transient_for != hints->transient_for) ||
1026 								 (old_hints->group_lead != hints->group_lead));
1027 
1028 	if (tie_changed)
1029 		untie_aswindow (asw);
1030 
1031 	asw->hints = hints;
1032 
1033 	if (tie_changed)
1034 		tie_aswindow (asw);
1035 
1036 	SelectDecor (asw);
1037 
1038 	LOCAL_DEBUG_OUT
1039 			("redecorating window %p(\"%s\") to update to new hints...", asw,
1040 			 hints->names[0] ? hints->names[0] : "none");
1041 	/* we do not want to do a complete refresh of decorations -
1042 	 * we want to do only what is neccessary: */
1043 
1044 	if (get_flags (scratch_status.flags, AS_Urgent)) {
1045 		if (!get_flags (asw->status->flags, AS_Urgent)) {
1046 			set_flags (asw->status->flags, AS_Urgent);
1047 			status_changed = True;
1048 		}
1049 	} else if (get_flags (asw->status->flags, AS_Urgent)) {
1050 		ASFlagType extwm_state = 0;
1051 
1052 		if (!get_extwm_state_flags (asw->w, &extwm_state))
1053 			extwm_state = 0;					/* just in case */
1054 		if (!get_flags (extwm_state, EXTWM_StateDemandsAttention)) {
1055 			clear_flags (asw->status->flags, AS_Urgent);
1056 			status_changed = True;
1057 		}
1058 	}
1059 	if (hints2decorations (asw, old_hints))
1060 		status_changed = True;
1061 
1062 	if (status_changed)
1063 		on_window_status_changed (asw, True);
1064 
1065 	if (mystrcmp (old_hints->res_name, hints->res_name) != 0 ||
1066 			mystrcmp (old_hints->res_class, hints->res_class) != 0)
1067 		broadcast_res_names (asw);
1068 	if (mystrcmp (old_hints->names[0], hints->names[0]) != 0) {
1069 		broadcast_window_name (asw);
1070 		set_flags (asw->internal_flags, ASWF_NameChanged);
1071 	}
1072 	if (mystrcmp (old_hints->icon_name, hints->icon_name) != 0)
1073 		broadcast_icon_name (asw);
1074 
1075 	destroy_hints (old_hints, False);
1076 }
1077 
on_window_opacity_changed(ASWindow * asw)1078 void on_window_opacity_changed (ASWindow * asw)
1079 {
1080 	CARD32 new_opacity = NET_WM_WINDOW_OPACITY_OPAQUE;
1081 	Bool set = False;
1082 	ASDatabaseRecord db_rec;
1083 
1084 	if (AS_ASSERT (asw))
1085 		return;
1086 	if (ASWIN_GET_FLAGS (asw, AS_Dead))
1087 		return;
1088 	set =
1089 			read_32bit_property (asw->w, _XA_NET_WM_WINDOW_OPACITY,
1090 													 &new_opacity);
1091 	if (set && new_opacity == asw->hints->window_opacity
1092 			&& ASWIN_HFLAGS (asw, AS_WindowOpacity))
1093 		return;
1094 
1095 	if (fill_asdb_record (Database, asw->hints->names, &db_rec, False)) {
1096 		if (get_flags (db_rec.set_data_flags, STYLE_WINDOW_OPACITY)) {
1097 			new_opacity =
1098 					set_hints_window_opacity_percent (NULL, db_rec.window_opacity);
1099 			set = True;
1100 		}
1101 	}
1102 
1103 	if (!set)
1104 		XDeleteProperty (dpy, asw->frame, _XA_NET_WM_WINDOW_OPACITY);
1105 	else if (new_opacity != asw->hints->window_opacity
1106 					 || !ASWIN_HFLAGS (asw, AS_WindowOpacity)) {
1107 		set_flags (asw->hints->flags, AS_WindowOpacity);
1108 		asw->hints->window_opacity = new_opacity;
1109 		set_32bit_property (asw->frame, _XA_NET_WM_WINDOW_OPACITY, XA_CARDINAL,
1110 												asw->hints->window_opacity);
1111 	}
1112 }
1113 
update_window_tbar_size(ASWindow * asw)1114 int update_window_tbar_size (ASWindow * asw)
1115 {
1116 	int tbar_size = 0;
1117 	if (asw->tbar) {
1118 		unsigned int tbar_width = 0;
1119 		unsigned int tbar_height = 0;
1120 		int x_offset = 0, y_offset = 0;
1121 		LOCAL_DEBUG_OUT ("IsVertical = %lX",
1122 										 ASWIN_HFLAGS (asw, AS_VerticalTitle));
1123 
1124 		if (ASWIN_HFLAGS (asw, AS_VerticalTitle)) {
1125 			tbar_size = calculate_astbar_width (asw->tbar);
1126 			tbar_width = tbar_size;
1127 			tbar_height = asw->frame_canvas->height;
1128 #ifdef SHAPE
1129 			if (get_flags
1130 					(asw->frame_data->condense_titlebar, ALIGN_LEFT | ALIGN_RIGHT)) {
1131 				int condensed = calculate_astbar_height (asw->tbar);
1132 				if (condensed < tbar_height) {
1133 					if (get_flags (asw->frame_data->condense_titlebar, ALIGN_LEFT)) {
1134 						y_offset = tbar_height - condensed;
1135 						if (get_flags
1136 								(asw->frame_data->condense_titlebar, ALIGN_RIGHT))
1137 							y_offset /= 2;
1138 					}
1139 					tbar_height = condensed;
1140 				}
1141 			}
1142 #endif
1143 		} else {
1144 			tbar_size = calculate_astbar_height (asw->tbar);
1145 			tbar_width = asw->frame_canvas->width;
1146 			tbar_height = tbar_size;
1147 #ifdef SHAPE
1148 			if (get_flags
1149 					(asw->frame_data->condense_titlebar, ALIGN_LEFT | ALIGN_RIGHT)) {
1150 				int condensed = calculate_astbar_width (asw->tbar);
1151 				if (condensed < tbar_width) {
1152 					if (get_flags (asw->frame_data->condense_titlebar, ALIGN_RIGHT)) {
1153 						x_offset = tbar_width - condensed;
1154 						if (get_flags (asw->frame_data->condense_titlebar, ALIGN_LEFT))
1155 							x_offset /= 2;
1156 					}
1157 					tbar_width = condensed;
1158 				}
1159 			}
1160 #endif
1161 		}
1162 		/* we need that to set up tbar size : */
1163 		set_astbar_size (asw->tbar, tbar_width, tbar_height);
1164 		/* does not matter if we use frame canvas, since part's
1165 		 * canvas resizes at frame canvas origin anyway */
1166 		move_astbar (asw->tbar, asw->frame_canvas, x_offset, y_offset);
1167 
1168 	}
1169 	return tbar_size;
1170 }
1171 
1172 
on_window_status_changed(ASWindow * asw,Bool reconfigured)1173 void on_window_status_changed (ASWindow * asw, Bool reconfigured)
1174 {
1175 	char *unfocus_mystyle = NULL;
1176 	char *frame_unfocus_mystyle = NULL;
1177 	int i;
1178 	Bool changed = False;
1179 	ASOrientation *od = get_orientation_data (asw);
1180 
1181 	if (AS_ASSERT (asw))
1182 		return;
1183 
1184 /*	get_extwm_state_flags (asw->w, &i); */
1185 
1186 	LOCAL_DEBUG_CALLER_OUT ("(%p,%s Reconfigured)", asw,
1187 													reconfigured ? "" : "Not");
1188 	LOCAL_DEBUG_OUT ("status geometry = %dx%d%+d%+d", asw->status->width,
1189 									 asw->status->height, asw->status->x, asw->status->y);
1190 	if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1191 		unfocus_mystyle = ASWIN_GET_FLAGS (asw, AS_Sticky) ?
1192 				AS_ICON_TITLE_STICKY_MYSTYLE : AS_ICON_TITLE_UNFOCUS_MYSTYLE;
1193 		if (asw->icon_title)
1194 			changed =
1195 					set_astbar_style (asw->icon_title, BAR_STATE_UNFOCUSED,
1196 														unfocus_mystyle);
1197 		if (changed || reconfigured)	/* now we need to update icon title size */
1198 			on_icon_changed (asw);
1199 	} else {
1200 		Bool decor_shaped = False;
1201 		MyFrame *frame_data = asw->frame_data;
1202 		int back_type;
1203 		ASFlagType *frame_bevel, title_bevel;
1204 		int title_cm, title_hue = -1, title_sat = -1;
1205 
1206 		if (ASWIN_GET_FLAGS (asw, AS_Sticky)) {
1207 			back_type = BACK_STICKY;
1208 			frame_bevel = &(frame_data->part_sbevel[0]);
1209 			title_bevel = frame_data->title_sbevel;
1210 			title_cm = frame_data->title_scm;
1211 			if (get_flags (frame_data->set_title_attr, MYFRAME_TitleSHueSet))
1212 				title_hue = frame_data->title_shue;
1213 			if (get_flags (frame_data->set_title_attr, MYFRAME_TitleSSatSet))
1214 				title_sat = frame_data->title_ssat;
1215 		} else {
1216 			back_type = BACK_UNFOCUSED;
1217 			frame_bevel = &(frame_data->part_ubevel[0]);
1218 			title_bevel = frame_data->title_ubevel;
1219 			title_cm = frame_data->title_ucm;
1220 			if (get_flags (frame_data->set_title_attr, MYFRAME_TitleUHueSet))
1221 				title_hue = frame_data->title_uhue;
1222 			if (get_flags (frame_data->set_title_attr, MYFRAME_TitleUSatSet))
1223 				title_sat = frame_data->title_usat;
1224 		}
1225 
1226 		unfocus_mystyle = asw->hints->mystyle_names[back_type];
1227 		if (frame_data->title_style_names[back_type])
1228 			unfocus_mystyle = frame_data->title_style_names[back_type];
1229 		if (unfocus_mystyle == NULL)
1230 			unfocus_mystyle = Scr.Look.MSWindow[back_type]->name;
1231 		if (unfocus_mystyle == NULL)
1232 			unfocus_mystyle = Scr.Look.MSWindow[BACK_UNFOCUSED]->name;
1233 
1234 		frame_unfocus_mystyle =
1235 				(frame_data->frame_style_names[back_type] ==
1236 				 NULL) ? unfocus_mystyle : frame_data->
1237 				frame_style_names[back_type];
1238 
1239 		for (i = 0; i < FRAME_PARTS; ++i) {
1240 			unsigned int real_part = od->frame_rotation[i];
1241 			if (asw->frame_bars[real_part]) {
1242 				if (set_astbar_style
1243 						(asw->frame_bars[real_part], BAR_STATE_UNFOCUSED,
1244 						 frame_unfocus_mystyle))
1245 					changed = True;
1246 				if (set_astbar_hilite
1247 						(asw->frame_bars[real_part], BAR_STATE_UNFOCUSED,
1248 						 frame_bevel[i]))
1249 					changed = True;
1250 				if (is_astbar_shaped (asw->frame_bars[real_part], -1))
1251 					decor_shaped = True;
1252 			}
1253 		}
1254 		if (asw->tbar) {
1255 			if (set_astbar_style
1256 					(asw->tbar, BAR_STATE_UNFOCUSED, unfocus_mystyle))
1257 				changed = True;
1258 			if (set_astbar_hilite (asw->tbar, BAR_STATE_UNFOCUSED, title_bevel))
1259 				changed = True;
1260 			if (set_astbar_composition_method
1261 					(asw->tbar, BAR_STATE_UNFOCUSED, title_cm))
1262 				changed = True;
1263 			if (set_astbar_huesat
1264 					(asw->tbar, BAR_STATE_UNFOCUSED, title_hue, title_sat))
1265 				changed = True;
1266 			if (get_flags
1267 					(asw->frame_data->condense_titlebar, ALIGN_LEFT | ALIGN_RIGHT)
1268 					|| is_astbar_shaped (asw->tbar, -1)) {
1269 				decor_shaped = True;
1270 			}
1271 		}
1272 		if (decor_shaped)
1273 			ASWIN_SET_FLAGS (asw, AS_ShapedDecor);
1274 		else
1275 			ASWIN_CLEAR_FLAGS (asw, AS_ShapedDecor);
1276 
1277 		LOCAL_DEBUG_OUT ("status geometry = %dx%d%+d%+d", asw->status->width,
1278 										 asw->status->height, asw->status->x, asw->status->y);
1279 		if (changed || reconfigured) {	/* now we need to update frame sizes in status */
1280 			unsigned int *frame_size = &(asw->status->frame_size[0]);
1281 			unsigned short tbar_size = 0;
1282 /*			int bw = 0 ;
1283 			if( asw->hints && get_flags(asw->hints->flags, AS_Border))
1284 				bw = asw->hints->border_width ; */
1285 			tbar_size = update_window_tbar_size (asw);
1286 			for (i = 0; i < FRAME_SIDES; ++i) {
1287 				if (asw->frame_bars[i])
1288 					frame_size[i] = IsSideVertical (i) ? asw->frame_bars[i]->width :
1289 							asw->frame_bars[i]->height;
1290 				else
1291 					frame_size[i] = 0;
1292 				//frame_size[i] += bw ;
1293 			}
1294 			if (tbar_size > 0) {
1295 				for (i = FRAME_SIDES; i < FRAME_PARTS; ++i) {
1296 					if (get_flags
1297 							(asw->internal_flags,
1298 							 ASWF_FirstCornerFollowsTbarSize << (i - FRAME_SIDES))) {
1299 						unsigned int real_part = od->frame_rotation[i];
1300 						if (asw->frame_bars[real_part]) {
1301 							if (ASWIN_HFLAGS (asw, AS_VerticalTitle))
1302 								set_astbar_size (asw->frame_bars[real_part],
1303 																 asw->frame_bars[real_part]->width,
1304 																 tbar_size);
1305 							else
1306 								set_astbar_size (asw->frame_bars[real_part], tbar_size,
1307 																 asw->frame_bars[real_part]->height);
1308 						}
1309 					}
1310 				}
1311 			}
1312 
1313 			frame_size[od->tbar_side] += tbar_size;
1314 			LOCAL_DEBUG_OUT
1315 					("status geometry = %dx%d%+d%+d frame_size = %d,%d,%d,%d",
1316 					 asw->status->width, asw->status->height, asw->status->x,
1317 					 asw->status->y, frame_size[0], frame_size[1], frame_size[2],
1318 					 frame_size[3]);
1319 			anchor2status (asw->status, asw->hints, &(asw->anchor));
1320 			LOCAL_DEBUG_OUT ("status geometry = %dx%d%+d%+d", asw->status->width,
1321 											 asw->status->height, asw->status->x,
1322 											 asw->status->y);
1323 		}
1324 	}
1325 
1326 	/* now we need to move/resize our frame window */
1327 	if (!apply_window_status_size (asw, od))
1328 		changed = True;
1329 	if (changed)
1330 		broadcast_config (M_STATUS_CHANGE, asw);	/* must enforce status change propagation */
1331 	if (!ASWIN_GET_FLAGS (asw, AS_Dead))
1332 		set_client_state (asw->w, asw->status);
1333 }
1334 
on_window_anchor_changed(ASWindow * asw)1335 void on_window_anchor_changed (ASWindow * asw)
1336 {
1337 	if (asw) {
1338 		ASOrientation *od = get_orientation_data (asw);
1339 		anchor2status (asw->status, asw->hints, &(asw->anchor));
1340 		LOCAL_DEBUG_OUT ("status geometry = %dx%d%+d%+d", asw->status->width,
1341 										 asw->status->height, asw->status->x, asw->status->y);
1342 
1343 		/* now we need to move/resize our frame window */
1344 		if (!apply_window_status_size (asw, od))
1345 			broadcast_config (M_CONFIGURE_WINDOW, asw);	/* must enforce status change propagation */
1346 		if (!ASWIN_GET_FLAGS (asw, AS_Dead))
1347 			set_client_state (asw->w, asw->status);
1348 	}
1349 }
1350 
1351 void
validate_window_anchor(ASWindow * asw,XRectangle * new_anchor,Bool initial_placement)1352 validate_window_anchor (ASWindow * asw, XRectangle * new_anchor,
1353 												Bool initial_placement)
1354 {
1355 	if (asw) {
1356 		ASStatusHints status = *(asw->status);
1357 		anchor2status (&status, asw->hints, new_anchor);
1358 		LOCAL_DEBUG_OUT ("status geometry = %dx%d%+d%+d", status.width,
1359 										 status.height, status.x, status.y);
1360 
1361 		if (ASWIN_HFLAGS (asw, AS_AvoidCover | AS_ShortLived) != AS_AvoidCover) {
1362 			obey_avoid_cover (asw, &status, new_anchor,
1363 												initial_placement ? AS_LayerHighest :
1364 												ASWIN_LAYER (asw));
1365 		}
1366 	}
1367 }
1368 
on_window_hilite_changed(ASWindow * asw,Bool focused)1369 void on_window_hilite_changed (ASWindow * asw, Bool focused)
1370 {
1371 	ASOrientation *od = get_orientation_data (asw);
1372 	int i;
1373 
1374 	LOCAL_DEBUG_CALLER_OUT ("(%p,%s focused)", asw, focused ? "" : "not");
1375 	if (AS_ASSERT (asw))
1376 		return;
1377 
1378 	for (i = FRAME_SIDES; --i >= 0;) {
1379 		ASCanvas *update_canvas = asw->frame_sides[i];
1380 		int k;
1381 		if (swap_save_canvas (update_canvas)) {
1382 			LOCAL_DEBUG_OUT ("canvas save swapped for side %d", i);
1383 			update_canvas = NULL;
1384 		}
1385 		if (i == od->tbar_side)
1386 			set_astbar_focused (asw->tbar, update_canvas, focused);
1387 
1388 		for (k = 0; k < FRAME_PARTS; ++k)
1389 			if (od->tbar2canvas_xref[k] == i)
1390 				set_astbar_focused (asw->frame_bars[k], update_canvas, focused);
1391 	}
1392 	/* now posting all the changes on display : */
1393 	for (i = FRAME_SIDES; --i >= 0;)
1394 		if (is_canvas_dirty (asw->frame_sides[i]))
1395 			update_canvas_display (asw->frame_sides[i]);
1396 	if (asw->internal && asw->internal->on_hilite_changed)
1397 		asw->internal->on_hilite_changed (asw->internal, NULL, focused);
1398 	if (ASWIN_GET_FLAGS (asw, AS_ShapedDecor))
1399 		SetShape (asw, 0);
1400 	if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1401 		set_astbar_focused (asw->icon_button, asw->icon_canvas, focused);
1402 		set_astbar_focused (asw->icon_title, asw->icon_title_canvas, focused);
1403 		if (is_canvas_dirty (asw->icon_canvas))
1404 			update_canvas_display (asw->icon_canvas);
1405 		if (is_canvas_dirty (asw->icon_title_canvas))
1406 			update_canvas_display (asw->icon_title_canvas);
1407 	}
1408 }
1409 
on_window_pressure_changed(ASWindow * asw,int pressed_context)1410 void on_window_pressure_changed (ASWindow * asw, int pressed_context)
1411 {
1412 	ASOrientation *od = get_orientation_data (asw);
1413 	LOCAL_DEBUG_CALLER_OUT ("(%p,%s)", asw, context2text (pressed_context));
1414 
1415 	if (AS_ASSERT (asw) || asw->status == NULL)
1416 		return;
1417 
1418 	if (!ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1419 		register int i = FRAME_PARTS;
1420 		/* Titlebar */
1421 		set_astbar_btn_pressed (asw->tbar, pressed_context);	/* must go before next call to properly redraw :  */
1422 		set_astbar_pressed (asw->tbar, asw->frame_sides[od->tbar_side],
1423 												pressed_context & C_TITLE);
1424 		/* frame decor : */
1425 		for (i = FRAME_PARTS; --i >= 0;)
1426 			set_astbar_pressed (asw->frame_bars[i],
1427 													asw->frame_sides[od->tbar2canvas_xref[i]],
1428 													pressed_context & (C_FrameN << i));
1429 		/* now posting all the changes on display : */
1430 		for (i = FRAME_SIDES; --i >= 0;)
1431 			if (is_canvas_dirty (asw->frame_sides[i])) {
1432 				update_canvas_display (asw->frame_sides[i]);
1433 			}
1434 		if (asw->internal && asw->internal->on_pressure_changed)
1435 			asw->internal->on_pressure_changed (asw->internal,
1436 																					pressed_context & C_CLIENT);
1437 	} else {											/* Iconic !!! */
1438 
1439 		set_astbar_pressed (asw->icon_button, asw->icon_canvas,
1440 												pressed_context & C_IconButton);
1441 		set_astbar_pressed (asw->icon_title, asw->icon_title_canvas,
1442 												pressed_context & C_IconTitle);
1443 		if (is_canvas_dirty (asw->icon_canvas))
1444 			update_canvas_display (asw->icon_canvas);
1445 		if (is_canvas_dirty (asw->icon_title_canvas))
1446 			update_canvas_display (asw->icon_title_canvas);
1447 	}
1448 }
1449 
1450 /********************************************************************/
1451 /* end of ASWindow frame decorations management                     */
1452 
save_aswindow_anchor(ASWindow * asw,Bool hor,Bool vert)1453 void save_aswindow_anchor (ASWindow * asw, Bool hor, Bool vert)
1454 {
1455 	if (hor && asw->saved_anchor.width == 0
1456 			&& asw->status->width < Scr.MyDisplayWidth) {
1457 		asw->saved_anchor.x = asw->anchor.x;
1458 		asw->saved_anchor.width = asw->anchor.width;
1459 	}
1460 	if (vert && asw->saved_anchor.height == 0
1461 			&& asw->status->height < Scr.MyDisplayHeight) {
1462 		asw->saved_anchor.y = asw->anchor.y;
1463 		asw->saved_anchor.height = asw->anchor.height;
1464 	}
1465 }
1466 
1467 void
moveresize_aswindow_wm(ASWindow * asw,int x,int y,unsigned int width,unsigned int height,Bool save_anchor)1468 moveresize_aswindow_wm (ASWindow * asw, int x, int y, unsigned int width,
1469 												unsigned int height, Bool save_anchor)
1470 {
1471 	LOCAL_DEBUG_CALLER_OUT ("asw(%p)->geom(%dx%d%+d%+d)->save_anchor(%d)",
1472 													asw, width, height, x, y, save_anchor);
1473 	if (!AS_ASSERT (asw)) {
1474 		ASStatusHints scratch_status = *(asw->status);
1475 		scratch_status.x = x;
1476 		scratch_status.y = y;
1477 		if (width > 0)
1478 			scratch_status.width = width;
1479 		if (height > 0)
1480 			scratch_status.height = height;
1481 
1482 		if (ASWIN_GET_FLAGS (asw, AS_Shaded)) {	/* tricky tricky */
1483 			if (ASWIN_HFLAGS (asw, AS_VerticalTitle))
1484 				scratch_status.width = asw->status->width;
1485 			else
1486 				scratch_status.height = asw->status->height;
1487 		}
1488 		if (save_anchor)
1489 			save_aswindow_anchor (asw, True, True);
1490 		/* need to apply two-way conversion in order to make sure that size restrains are applied : */
1491 		status2anchor (&(asw->anchor), asw->hints, &scratch_status,
1492 									 Scr.VxMax + Scr.MyDisplayWidth,
1493 									 Scr.VyMax + Scr.MyDisplayHeight);
1494 		anchor2status (asw->status, asw->hints, &(asw->anchor));
1495 
1496 		/* now lets actually resize the window : */
1497 		apply_window_status_size (asw, get_orientation_data (asw));
1498 	}
1499 }
1500 
init_aswindow_status(ASWindow * t,ASStatusHints * status)1501 Bool init_aswindow_status (ASWindow * t, ASStatusHints * status)
1502 {
1503 	Bool pending_placement = False;
1504 
1505 	if (t->status == NULL) {
1506 		t->status = safecalloc (1, sizeof (ASStatusHints));
1507 		*(t->status) = *status;
1508 	}
1509 	if (get_flags (status->flags, AS_StartDesktop)
1510 			&& status->desktop != Scr.CurrentDesk) {
1511 		t->status->desktop = status->desktop;
1512 		if (get_flags (AfterStepState, ASS_NormalOperation))
1513 			ChangeDesks (status->desktop);
1514 	} else
1515 		t->status->desktop = Scr.CurrentDesk;
1516 
1517 	if (get_flags (status->flags, AS_StartViewportX)
1518 			&& get_flags (AfterStepState, ASS_NormalOperation)) {
1519 		t->status->viewport_x = MIN (status->viewport_x, Scr.VxMax);
1520 		t->status->x %= Scr.MyDisplayWidth;
1521 		if (!get_flags (t->status->flags, AS_Sticky))
1522 			t->status->x += t->status->viewport_x;
1523 	} else if (!get_flags (t->status->flags, AS_Sticky)) {
1524 		if (t->status->x < 0)
1525 			t->status->viewport_x = 0;
1526 		else
1527 			t->status->viewport_x =
1528 					(t->status->x / Scr.MyDisplayWidth) * Scr.MyDisplayWidth;
1529 		if (!get_flags (AfterStepState, ASS_NormalOperation))
1530 			set_flags (status->flags, AS_StartViewportX);
1531 	} else
1532 		t->status->x %= Scr.MyDisplayWidth;
1533 
1534 	if (get_flags (status->flags, AS_StartViewportY)
1535 			&& get_flags (AfterStepState, ASS_NormalOperation)) {
1536 		t->status->viewport_y = MIN (status->viewport_y, Scr.VyMax);
1537 		t->status->y %= Scr.MyDisplayWidth;
1538 		if (!get_flags (t->status->flags, AS_Sticky))
1539 			t->status->y += t->status->viewport_y;
1540 	} else if (!get_flags (t->status->flags, AS_Sticky)) {
1541 		if (t->status->y < 0)
1542 			t->status->viewport_y = 0;
1543 		else
1544 			t->status->viewport_y =
1545 					(t->status->y / Scr.MyDisplayHeight) * Scr.MyDisplayHeight;
1546 		if (!get_flags (AfterStepState, ASS_NormalOperation))
1547 			set_flags (status->flags, AS_StartViewportY);
1548 	} else
1549 		t->status->y %= Scr.MyDisplayHeight;
1550 
1551 	if (t->status->viewport_x != Scr.Vx || t->status->viewport_y != Scr.Vy) {
1552 		int new_vx =
1553 				get_flags (status->flags,
1554 									 AS_StartViewportX) ? t->status->viewport_x : Scr.Vx;
1555 		int new_vy =
1556 				get_flags (status->flags,
1557 									 AS_StartViewportY) ? t->status->viewport_y : Scr.Vy;
1558 		MoveViewport (new_vx, new_vy, False);
1559 		t->status->viewport_x = Scr.Vx;
1560 		t->status->viewport_y = Scr.Vy;
1561 	}
1562 	if (!get_flags (t->status->flags, AS_Sticky)) {
1563 		Bool absolute_origin = (!ASWIN_HFLAGS (t, AS_UseCurrentViewport));
1564 
1565 		if (absolute_origin && get_flags (t->hints->flags, AS_Transient) && get_flags (t->status->flags, AS_StartPositionUser)) {	/* most likely stupid KDE or GNOME app that is abusing USPosition
1566 																																																															   for no good reason - place it on current viewport */
1567 			absolute_origin = (t->status->x >= Scr.MyDisplayWidth ||
1568 												 t->status->y >= Scr.MyDisplayHeight);
1569 		}
1570 		if (absolute_origin) {
1571 			t->status->x -= t->status->viewport_x;
1572 			t->status->y -= t->status->viewport_y;
1573 		}
1574 	}
1575 	LOCAL_DEBUG_OUT ("status->pos = %+d%+d, Scr.Vpos = %+d%+d", t->status->x,
1576 									 t->status->y, Scr.Vx, Scr.Vy);
1577 
1578 	/* TODO: AS_Iconic */
1579 	if (!ASWIN_GET_FLAGS (t, AS_StartLayer))
1580 		ASWIN_LAYER (t) = AS_LayerNormal;
1581 	else if (ASWIN_LAYER (t) < AS_LayerLowest)
1582 		ASWIN_LAYER (t) = AS_LayerLowest;
1583 	else if (ASWIN_LAYER (t) > AS_LayerHighest)
1584 		ASWIN_LAYER (t) = AS_LayerHighest;
1585 
1586 	if (get_flags (t->status->flags, AS_Fullscreen)) {
1587 		t->status->width = Scr.MyDisplayWidth;
1588 		t->status->height = Scr.MyDisplayHeight;
1589 		t->status->x = 0;
1590 		t->status->y = 0;
1591 	} else {
1592 		if (get_flags (t->hints->flags, AS_MinSize)) {
1593 			int width = t->status->width;
1594 			int height = t->status->height;
1595 			if ((!get_flags (t->status->flags, AS_StartSizeUser)
1596 					 && width < t->hints->min_width) || width == 1)
1597 				width = min (t->hints->min_width, Scr.VxMax + Scr.MyDisplayWidth);
1598 			if ((!get_flags (t->status->flags, AS_StartSizeUser)
1599 					 && height < t->hints->min_height) || height == 1)
1600 				height =
1601 						min (t->hints->min_height, Scr.VyMax + Scr.MyDisplayHeight);
1602 			if (width != t->status->width || height != t->status->height) {
1603 				int dx = 0, dy = 0;
1604 				if (t->hints->gravity == EastGravity ||
1605 						t->hints->gravity == SouthEastGravity ||
1606 						t->hints->gravity == NorthEastGravity ||
1607 						t->hints->gravity == CenterGravity)
1608 					dx = (int)(t->status->width) - width;
1609 				if (t->hints->gravity == SouthGravity ||
1610 						t->hints->gravity == SouthEastGravity ||
1611 						t->hints->gravity == SouthWestGravity ||
1612 						t->hints->gravity == CenterGravity)
1613 					dy = (int)(t->status->height) - height;
1614 				if (t->hints->gravity == EastGravity
1615 						|| t->hints->gravity == CenterGravity)
1616 					dx = dx / 2;
1617 				if (t->hints->gravity == SouthGravity
1618 						|| t->hints->gravity == CenterGravity)
1619 					dy = dy / 2;
1620 				t->status->x += dx;
1621 				t->status->y += dy;
1622 				t->status->width = width;
1623 				t->status->height = height;
1624 				XResizeWindow (dpy, t->w, width, height);
1625 			}
1626 		}
1627 		if (!get_flags (AfterStepState, ASS_NormalOperation)) {
1628 			int min_x, min_y, max_x, max_y;
1629 			int margin = Scr.MyDisplayWidth >> 5;
1630 			if (!ASWIN_GET_FLAGS (t, AS_Sticky)) {
1631 				min_x = -Scr.Vx;
1632 				max_x = Scr.VxMax + Scr.MyDisplayWidth;
1633 				min_y = -Scr.Vy;
1634 				max_y = Scr.VyMax + Scr.MyDisplayHeight;
1635 			} else {
1636 				min_x = 0;
1637 				max_x = Scr.MyDisplayWidth;
1638 				min_y = 0;
1639 				max_y = Scr.MyDisplayHeight;
1640 			}
1641 			/* we have to make sure that window is visible !!!! */
1642 			LOCAL_DEBUG_OUT ("x_range(%d,%d), y_range(%d,%d), margin = %d",
1643 											 min_x, max_x, min_y, max_y, margin);
1644 			if ((int)t->status->x + (int)t->status->width < min_x + margin)
1645 				t->status->x = min_x + margin - (int)t->status->width;
1646 			else if ((int)t->status->x > max_x - margin)
1647 				t->status->x = max_x - margin;
1648 			if ((int)t->status->y + (int)t->status->height < min_y + margin)
1649 				t->status->y = min_y + margin - (int)t->status->height;
1650 			else if ((int)t->status->y > max_y - margin)
1651 				t->status->y = max_y - margin;
1652 
1653 			LOCAL_DEBUG_OUT ("status->pos = %+d%+d, Scr.Vpos = %+d%+d",
1654 											 t->status->x, t->status->y, Scr.Vx, Scr.Vy);
1655 
1656 			set_flags (t->status->flags, AS_Position);
1657 
1658 		} else if (get_flags (Scr.Feel.flags, NoPPosition)) {
1659 
1660 			if (!get_flags (t->hints->flags, AS_Transient) &&
1661 					!get_flags (t->status->flags, AS_StartPositionUser))
1662 				clear_flags (t->status->flags, AS_Position);
1663 		}
1664 		if (get_flags (status->flags, AS_MaximizedX | AS_MaximizedY))
1665 			pending_placement = True;
1666 		else if (!get_flags (t->status->flags, AS_Position)) {
1667 			if (!get_flags (t->status->flags, AS_StartsIconic)) {
1668 				int x = -1, y = -1;
1669 				pending_placement = True;
1670 				ASQueryPointerRootXY (&x, &y);
1671 				if (get_flags (t->hints->flags, AS_Transient | AS_ShortLived)) {
1672 					x -= (int)t->status->width / 2;
1673 					y -= (int)t->status->height / 2;
1674 					set_flags (t->status->flags, AS_Position);
1675 					pending_placement = False;
1676 				}
1677 
1678 				if (x + (int)t->status->width > (int)Scr.MyDisplayWidth)
1679 					x = (int)Scr.MyDisplayWidth - (int)t->status->width;
1680 				if (x < 0)
1681 					x = 0;
1682 
1683 				if (y + (int)t->status->height > (int)Scr.MyDisplayHeight)
1684 					y = Scr.MyDisplayHeight - (int)t->status->height;
1685 				if (y < 0)
1686 					y = 0;
1687 
1688 				t->status->x = x;
1689 				t->status->y = y;
1690 
1691 				LOCAL_DEBUG_OUT ("status->pos = %+d%+d, Scr.Vpos = %+d%+d",
1692 												 t->status->x, t->status->y, Scr.Vx, Scr.Vy);
1693 			}
1694 		}
1695 	}
1696 
1697 	if (is_output_level_under_threshold (OUTPUT_LEVEL_HINTS))
1698 		print_status_hints (NULL, NULL, t->status);
1699 
1700 	/* by now we have a valid position for the window: */
1701 	set_flags (t->status->flags, AS_Position);
1702 
1703 	status2anchor (&(t->anchor), t->hints, t->status,
1704 								 Scr.VxMax + Scr.MyDisplayWidth,
1705 								 Scr.VyMax + Scr.MyDisplayHeight);
1706 	LOCAL_DEBUG_OUT
1707 			("status->geom=%dx%d%+d%+d,status->viewport=%+d%+d,anchor=%dx%d%+d%+d",
1708 			 t->status->width, t->status->height, t->status->x, t->status->y,
1709 			 t->status->viewport_x, t->status->viewport_y, t->anchor.width,
1710 			 t->anchor.height, t->anchor.x, t->anchor.y);
1711 
1712 	if (!pending_placement) {
1713 		validate_window_anchor (t, &(t->anchor), True);
1714 		anchor2status (t->status, t->hints, &(t->anchor));
1715 	}
1716 
1717 	return pending_placement;
1718 }
1719 
1720 /***************************************************************************************/
1721 /* iconify/deiconify code :                                                            */
1722 /***************************************************************************************/
complete_wm_state_transition(ASWindow * asw,int state)1723 void complete_wm_state_transition (ASWindow * asw, int state)
1724 {
1725 	asw->wm_state_transition = ASWT_StableState;
1726 	if (state == NormalState) {
1727 		LOCAL_DEBUG_OUT
1728 				("mapping frame subwindows for client %lX, frame canvas = %p",
1729 				 asw->w, asw->frame_canvas);
1730 		XMapSubwindows (dpy, asw->frame);
1731 		map_canvas_window (asw->frame_canvas, False);
1732 		restack_desktop_cover ();
1733 	} else if (state == IconicState) {
1734 		unmap_canvas_window (asw->frame_canvas);
1735 	}
1736 	if (!ASWIN_GET_FLAGS (asw, AS_Dead))
1737 		set_multi32bit_property (asw->w, _XA_WM_STATE, _XA_WM_STATE, 2, state,
1738 														 (state ==
1739 															IconicState) ? asw->status->
1740 														 icon_window : None);
1741 }
1742 
1743 Bool
set_window_wm_state(ASWindow * asw,Bool iconify,Bool force_unmapped)1744 set_window_wm_state (ASWindow * asw, Bool iconify, Bool force_unmapped)
1745 {
1746 	XWindowAttributes attr;
1747 
1748 	LOCAL_DEBUG_CALLER_OUT ("client = %p, iconify = %d", asw, iconify);
1749 
1750 	if (AS_ASSERT (asw))
1751 		return False;
1752 
1753 	if (iconify) {
1754 		asw->DeIconifyDesk = ASWIN_DESK (asw);
1755 		if (asw->wm_state_transition == ASWT_StableState) {
1756 			if (get_flags (asw->status->flags, AS_Iconic))
1757 				return False;
1758 
1759 			asw->wm_state_transition = ASWT_Normal2Iconic;
1760 			set_flags (asw->status->flags, AS_Iconic);
1761 			if (get_flags (Scr.Feel.flags, StickyIcons)
1762 					|| ASWIN_DESK (asw) == Scr.CurrentDesk)
1763 				quietly_reparent_aswindow (asw, Scr.Root, True);
1764 			else
1765 				quietly_reparent_aswindow (asw, Scr.ServiceWin, True);
1766 		}
1767 
1768 		asw->status->icon_window =
1769 				asw->icon_canvas ? asw->icon_canvas->w : None;
1770 
1771 		if (asw->icon_canvas)
1772 			asw->status->icon_window = asw->icon_canvas->w;
1773 		else if (asw->icon_title_canvas)
1774 			asw->status->icon_window = asw->icon_title_canvas->w;
1775 
1776 		if (get_flags (Scr.Feel.flags, ClickToFocus)
1777 				|| get_flags (Scr.Feel.flags, SloppyFocus)) {
1778 			if (asw == Scr.Windows->focused)
1779 				focus_prev_aswindow (asw);
1780 		}
1781 
1782 		LOCAL_DEBUG_OUT ("unmaping client window 0x%lX",
1783 										 (unsigned long)asw->w);
1784 		if (!ASWIN_GET_FLAGS (asw, AS_Dead)) {
1785 			if (!XGetWindowAttributes (dpy, asw->w, &attr))
1786 				ASWIN_SET_FLAGS (asw, AS_Dead);
1787 			else {
1788 				if (attr.map_state != IsUnmapped)
1789 					XUnmapWindow (dpy, asw->w);
1790 				else {
1791 					ASWIN_CLEAR_FLAGS (asw, AS_Mapped);
1792 					complete_wm_state_transition (asw, IconicState);
1793 				}
1794 			}
1795 			ASSync (False);
1796 		}
1797 
1798 		LOCAL_DEBUG_OUT ("hilited == %p", Scr.Windows->hilited);
1799 		if (Scr.Windows->hilited == asw)
1800 			hide_hilite ();
1801 
1802 		/* finally mapping the icon windows : */
1803 		add_iconbox_icon (asw);
1804 		restack_window (asw, None, Below);
1805 		map_canvas_window (asw->icon_canvas, True);
1806 		if (asw->icon_canvas != asw->icon_title_canvas)
1807 			map_canvas_window (asw->icon_title_canvas, True);
1808 		on_window_status_changed (asw, True);
1809 		LOCAL_DEBUG_OUT ("updating status to iconic for client %p(\"%s\")",
1810 										 asw, ASWIN_NAME (asw));
1811 	} else {											/* Performing transition IconicState->NormalState  */
1812 		if (asw->wm_state_transition == ASWT_StableState) {
1813 			if (!get_flags (asw->status->flags, AS_Iconic))
1814 				return False;
1815 			asw->wm_state_transition = ASWT_Iconic2Normal;
1816 			clear_flags (asw->status->flags, AS_Iconic);
1817 			remove_iconbox_icon (asw);
1818 			unmap_canvas_window (asw->icon_canvas);
1819 			if (asw->icon_canvas != asw->icon_title_canvas)
1820 				unmap_canvas_window (asw->icon_title_canvas);
1821 
1822 			change_aswindow_desktop (asw,
1823 															 get_flags (Scr.Feel.flags,
1824 																					StubbornIcons) ? asw->
1825 															 DeIconifyDesk : Scr.CurrentDesk, True);
1826 		}
1827 
1828 		asw->status->icon_window = None;
1829 
1830 		if (!ASWIN_GET_FLAGS (asw, AS_Dead) && !force_unmapped) {
1831 			if (!XGetWindowAttributes (dpy, asw->w, &attr))
1832 				ASWIN_SET_FLAGS (asw, AS_Dead);
1833 		}
1834 		if (!ASWIN_GET_FLAGS (asw, AS_Dead)) {
1835 			{
1836 				/* TODO: make sure that the window is on this screen */
1837 				if (attr.map_state == IsUnmapped || force_unmapped)
1838 					XMapRaised (dpy, asw->w);
1839 				else {
1840 					complete_wm_state_transition (asw, NormalState);
1841 					ASWIN_SET_FLAGS (asw, AS_Mapped);
1842 					if (get_flags (Scr.Feel.flags, ClickToFocus))
1843 						activate_aswindow (asw, True, False);
1844 				}
1845 			}
1846 		}
1847 		on_window_status_changed (asw, False);
1848 	}
1849 
1850 	if (!get_flags (asw->wm_state_transition, ASWT_FROM_WITHDRAWN))
1851 		broadcast_config (M_CONFIGURE_WINDOW, asw);
1852 
1853 	return True;
1854 }
1855 
bring_aswindow_on_vscreen(ASWindow * asw)1856 Bool bring_aswindow_on_vscreen (ASWindow * asw)
1857 {
1858 	int min_x, min_y, max_x, max_y;
1859 	int margin_x = Scr.MyDisplayWidth >> 5, margin_y =
1860 			Scr.MyDisplayHeight >> 5;
1861 
1862 	if (asw == NULL)
1863 		return False;
1864 
1865 	if (!ASWIN_GET_FLAGS (asw, AS_Sticky)) {
1866 		min_x = -Scr.Vx;
1867 		max_x = Scr.VxMax + Scr.MyDisplayWidth - Scr.Vx;
1868 		min_y = -Scr.Vy;
1869 		max_y = Scr.VyMax + Scr.MyDisplayHeight - Scr.Vy;
1870 	} else {
1871 		min_x = 0;
1872 		max_x = Scr.MyDisplayWidth;
1873 		min_y = 0;
1874 		max_y = Scr.MyDisplayHeight;
1875 	}
1876 	if (!ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1877 		int new_x = asw->status->x;
1878 		int new_y = asw->status->y;
1879 		int w = asw->status->width;
1880 		int h = asw->status->height;
1881 
1882 		if (margin_x > w >> 2) {
1883 			margin_x = w >> 2;
1884 			if (margin_x == 0)
1885 				margin_x = 1;
1886 		}
1887 		if (margin_y > h >> 2) {
1888 			margin_y = h >> 2;
1889 			if (margin_y == 0)
1890 				margin_y = 1;
1891 		}
1892 
1893 		if (new_x + w < min_x + margin_x)
1894 			new_x = min_x + margin_x - w;
1895 		else if (new_x > max_x - margin_x)
1896 			new_x = max_x - margin_x;
1897 
1898 		if (new_y + h < min_y + margin_y)
1899 			new_y = min_y + margin_y - h;
1900 		else if (new_y > max_y - margin_y)
1901 			new_y = max_y - margin_y;
1902 		LOCAL_DEBUG_OUT
1903 				("min_pos = (%+d%+d), max_pos = (%+d%+d), new_pos = (%+d%+d)",
1904 				 min_x, min_y, max_x, max_y, new_x, new_y);
1905 		if (new_x != asw->status->x || new_y != asw->status->y)
1906 			moveresize_aswindow_wm (asw, new_x, new_y, asw->status->width,
1907 															asw->status->height, False);
1908 	}
1909 	return True;
1910 }
1911 
1912 
make_aswindow_visible(ASWindow * asw,Bool deiconify)1913 Bool make_aswindow_visible (ASWindow * asw, Bool deiconify)
1914 {
1915 	if (asw == NULL || !get_flags (AfterStepState, ASS_NormalOperation))
1916 		return False;
1917 
1918 	if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1919 		if (deiconify) {
1920 			set_window_wm_state (asw, False, False);
1921 		}
1922 	}
1923 
1924 	if (ASWIN_DESK (asw) != Scr.CurrentDesk) {
1925 		ChangeDesks (ASWIN_DESK (asw));
1926 	}
1927 
1928 	bring_aswindow_on_vscreen (asw);
1929 
1930 #ifndef NO_VIRTUAL
1931 	if (!ASWIN_GET_FLAGS (asw, AS_Sticky)) {
1932 		int dx, dy;
1933 		int cx = Scr.MyDisplayWidth / 2;
1934 		int cy = Scr.MyDisplayHeight / 2;
1935 
1936 		if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1937 			if (asw->icon_canvas) {
1938 				cx = asw->icon_canvas->root_x + asw->icon_canvas->width / 2;
1939 				cy = asw->icon_canvas->root_y + asw->icon_canvas->height / 2;
1940 			}
1941 		} else if (asw->frame_canvas) {
1942 			cx = asw->frame_canvas->root_x + asw->frame_canvas->width / 2;
1943 			cy = asw->frame_canvas->root_y + asw->frame_canvas->height / 2;
1944 		}
1945 
1946 		/* Put center of window on the visible screen */
1947 		if (get_flags (Scr.Feel.flags, CenterOnCirculate)) {
1948 			dx = cx - Scr.MyDisplayWidth / 2 + Scr.Vx;
1949 			dy = cy - Scr.MyDisplayHeight / 2 + Scr.Vy;
1950 		} else {
1951 			dx = (cx + Scr.Vx) / Scr.MyDisplayWidth * Scr.MyDisplayWidth;
1952 			dy = (cy + Scr.Vy) / Scr.MyDisplayHeight * Scr.MyDisplayHeight;
1953 		}
1954 		MoveViewport (dx, dy, True);
1955 	}
1956 #endif
1957 
1958 	RaiseObscuredWindow (asw);
1959 	if (!get_flags (Scr.Feel.flags, ClickToFocus)) {
1960 		int x, y;
1961 		/* need to to center on window */
1962 		if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1963 			if (asw->icon_title_canvas
1964 					&& asw->icon_canvas != asw->icon_title_canvas)
1965 				on_window_moveresize (asw, asw->icon_title_canvas->w);
1966 			if (asw->icon_canvas) {
1967 				on_window_moveresize (asw, asw->icon_canvas->w);
1968 				x = asw->icon_canvas->root_x;
1969 				y = asw->icon_canvas->root_y;
1970 			} else if (asw->icon_title_canvas) {
1971 				x = asw->icon_title_canvas->root_x;
1972 				y = asw->icon_title_canvas->root_y;
1973 			} else
1974 				return False;
1975 		} else {
1976 			on_window_moveresize (asw, asw->frame);
1977 			x = asw->client_canvas->root_x;
1978 			y = asw->client_canvas->root_y;
1979 		}
1980 		LOCAL_DEBUG_OUT ("Warping pointer to : %+d%+d", x + Scr.Feel.Xzap,
1981 										 y + Scr.Feel.Yzap);
1982 		XWarpPointer (dpy, None, Scr.Root, 0, 0, 0, 0, x + Scr.Feel.Xzap,
1983 									y + Scr.Feel.Yzap);
1984 	}
1985 	return True;
1986 }
1987 
change_aswindow_layer(ASWindow * asw,int layer)1988 void change_aswindow_layer (ASWindow * asw, int layer)
1989 {
1990 	if (AS_ASSERT (asw))
1991 		return;
1992 	if (asw->transient_owner == NULL && ASWIN_LAYER (asw) != layer) {
1993 		remove_aswindow_from_layer (asw, ASWIN_LAYER (asw));
1994 		LOCAL_DEBUG_OUT ("changing window's layer to %d", layer);
1995 		ASWIN_LAYER (asw) = layer;
1996 		add_aswindow_to_layer (asw, layer);
1997 		restack_window_list (ASWIN_DESK (asw));
1998 		ASWIN_SET_FLAGS (asw, AS_Layer);
1999 		set_client_state (asw->w, asw->status);
2000 	}
2001 }
2002 
2003 static void
do_change_aswindow_desktop(ASWindow * asw,int new_desk,Bool force)2004 do_change_aswindow_desktop (ASWindow * asw, int new_desk, Bool force)
2005 {
2006 	int old_desk = ASWIN_DESK (asw);
2007 
2008 	if (!force && ASWIN_DESK (asw) == new_desk)
2009 		return;
2010 
2011 	ASWIN_DESK (asw) = new_desk;
2012 
2013 	if (!ASWIN_GET_FLAGS (asw, AS_Dead)) {
2014 		set_client_desktop (asw->w, as_desk2ext_desk_safe(new_desk));
2015 
2016 		/* desktop changing : */
2017 		if (new_desk == Scr.CurrentDesk) {
2018 			quietly_reparent_aswindow (asw, Scr.Root, True);
2019 		} else if (old_desk == Scr.CurrentDesk)
2020 			quietly_reparent_aswindow (asw, Scr.ServiceWin, True);
2021 		broadcast_config (M_CONFIGURE_WINDOW, asw);
2022 	}
2023 }
2024 
2025 static void
change_aswindow_desktop_nontransient(ASWindow * asw,int new_desk,Bool force)2026 change_aswindow_desktop_nontransient (ASWindow * asw, int new_desk,
2027 																			Bool force)
2028 {
2029 	ASWindow **sublist;
2030 	int i;
2031 
2032 	if (ASWIN_GET_FLAGS (asw, AS_Sticky))
2033 		new_desk = Scr.CurrentDesk;
2034 
2035 	do_change_aswindow_desktop (asw, new_desk, force);
2036 	if (asw->transients) {
2037 		sublist = PVECTOR_HEAD (ASWindow *, asw->transients);
2038 		for (i = 0; i < PVECTOR_USED (asw->transients); ++i)
2039 			do_change_aswindow_desktop (sublist[i], new_desk, force);
2040 	}
2041 }
2042 
2043 #if 0														/* TODO do we really need that ??? */
2044 
2045 struct ChangeGroupDesktopAuxData {
2046 	Window group_lead;
2047 	ASWindow *initiator;
2048 	int new_desk;
2049 	Bool force;
2050 
2051 };
2052 
2053 static Bool
2054 change_aswindow_desktop_for_group_func (void *data, void *aux_data)
2055 {
2056 	ASWindow *asw = (ASWindow *) data;
2057 	struct ChangeGroupDesktopAuxData *ad =
2058 			(struct ChangeGroupDesktopAuxData *)aux_data;
2059 	LOCAL_DEBUG_OUT
2060 			("asw = %p(w = %lX), initiator = %p, to = %p, asw->gl = %lX, gl = %lX",
2061 			 asw, asw->w, ad->initiator, asw->transient_owner,
2062 			 asw->hints->group_lead, ad->group_lead);
2063 	if (asw && asw != ad->initiator && asw->transient_owner == NULL
2064 			&& asw->hints->group_lead == ad->group_lead)
2065 		change_aswindow_desktop_nontransient (asw, ad->new_desk, ad->force);
2066 	return True;
2067 }
2068 #endif
2069 
change_aswindow_desktop(ASWindow * asw,int new_desk,Bool force)2070 void change_aswindow_desktop (ASWindow * asw, int new_desk, Bool force)
2071 {
2072 	ASWindow **sublist;
2073 	int i;
2074 
2075 	if (AS_ASSERT (asw))
2076 		return;
2077 	if (asw->transient_owner)
2078 		asw = asw->transient_owner;
2079 
2080 	change_aswindow_desktop_nontransient (asw, new_desk, force);
2081 
2082 #if 0														/* TODO do we really need that ??? */
2083 	LOCAL_DEBUG_OUT ("group_members = %p; group_lead = %lX",
2084 									 asw->group_members, asw->hints->group_lead);
2085 	if (asw->group_members) {
2086 		sublist = PVECTOR_HEAD (ASWindow *, asw->group_members);
2087 		for (i = 0; i < PVECTOR_USED (asw->group_members); ++i)
2088 			if (sublist[i]->transient_owner == NULL)
2089 				do_change_aswindow_desktop (sublist[i], new_desk, force);
2090 	} else if (asw->hints->group_lead != None) {	/* sometimes group lead may be unmapped untracked window */
2091 		struct ChangeGroupDesktopAuxData ad;
2092 		ad.group_lead = asw->hints->group_lead;
2093 		ad.initiator = asw;
2094 		ad.new_desk = new_desk;
2095 		ad.force = force;
2096 		iterate_asbidirlist (Scr.Windows->clients,
2097 												 change_aswindow_desktop_for_group_func, &ad, NULL,
2098 												 False);
2099 	}
2100 #endif
2101 }
2102 
restore_anchor_x(ASWindow * asw)2103 static Bool restore_anchor_x (ASWindow * asw)
2104 {
2105 	if (asw->saved_anchor.width > 0) {
2106 		asw->anchor.x = asw->saved_anchor.x;
2107 		asw->anchor.width = asw->saved_anchor.width;
2108 		asw->saved_anchor.width = 0;	/* invalidating saved anchor */
2109 		return True;
2110 	}
2111 	return False;
2112 }
2113 
restore_anchor_y(ASWindow * asw)2114 static Bool restore_anchor_y (ASWindow * asw)
2115 {
2116 	if (asw->saved_anchor.height > 0) {
2117 		asw->anchor.y = asw->saved_anchor.y;
2118 		asw->anchor.height = asw->saved_anchor.height;
2119 		asw->saved_anchor.height = 0;	/* invalidating saved anchor */
2120 		return True;
2121 	}
2122 	return False;
2123 }
2124 
toggle_aswindow_status(ASWindow * asw,ASFlagType flags)2125 void toggle_aswindow_status (ASWindow * asw, ASFlagType flags)
2126 {
2127 	ASFlagType on_flags, off_flags;
2128 	Bool need_placement = False;
2129 	Bool reconfigured = False;
2130 
2131 	if (AS_ASSERT (asw))
2132 		return;
2133 
2134 	if (flags == 0)
2135 		return;
2136 
2137 	if (get_flags (flags, AS_Fullscreen))
2138 		clear_flags (flags, AS_MaximizedX | AS_MaximizedY);
2139 
2140 	on_flags = (~(asw->status->flags)) & flags;
2141 	off_flags = (asw->status->flags) & (~flags);
2142 	asw->status->flags = on_flags | off_flags;
2143 	LOCAL_DEBUG_OUT ("flags = %lx, on_flags = %lx, off_flags = %lx", flags,
2144 									 on_flags, off_flags);
2145 	if (get_flags (flags, AS_Shaded)) {
2146 		if (get_flags (asw->status->flags, AS_Shaded)) {
2147 			ASOrientation *od = get_orientation_data (asw);
2148 			if (asw->frame_sides[od->tbar_side]) {
2149 				Window ww[2];
2150 				ww[0] = asw->w;
2151 				ww[1] = asw->frame_sides[od->tbar_side]->w;
2152 				XRestackWindows (dpy, &(ww[0]), 2);
2153 			}
2154 		}
2155 		asw->shading_steps = Scr.Feel.ShadeAnimationSteps;
2156 	}
2157 	if (get_flags (flags, AS_Sticky)) {	/* anchor of sticky window is always in real coordinates, while
2158 																			 * for non-sticky its in virtual coordinates
2159 																			 */
2160 		if (ASWIN_GET_FLAGS (asw, AS_Sticky)) {
2161 			asw->anchor.x -= asw->status->viewport_x;
2162 			asw->anchor.y -= asw->status->viewport_y;
2163 		} else {
2164 			asw->anchor.x += asw->status->viewport_x;
2165 			asw->anchor.y += asw->status->viewport_y;
2166 		}
2167 	}
2168 
2169 	if (get_flags (flags, AS_Fullscreen)) {
2170 		if (!ASWIN_GET_FLAGS (asw, AS_Fullscreen)) {	/* fullscreen->normal */
2171 			if (!ASWIN_GET_FLAGS (asw, AS_MaximizedX))
2172 				if (!restore_anchor_x (asw)) {
2173 					asw->anchor.width = Scr.MyDisplayWidth / 3;
2174 					asw->anchor.x = (Scr.MyDisplayWidth - asw->anchor.width) / 2;
2175 				}
2176 
2177 			if (!ASWIN_GET_FLAGS (asw, AS_MaximizedY))
2178 				if (!restore_anchor_y (asw)) {
2179 					asw->anchor.height = Scr.MyDisplayHeight / 3;
2180 					asw->anchor.y = (Scr.MyDisplayHeight - asw->anchor.height) / 2;
2181 				}
2182 
2183 			reconfigured = True;
2184 			if (ASWIN_GET_FLAGS (asw, AS_MaximizedY | AS_MaximizedX))
2185 				need_placement = True;
2186 		} else {										/* normal->fullscreen */
2187 			ASStatusHints scratch_status = *(asw->status);
2188 			scratch_status.x = 0;
2189 			scratch_status.y = 0;
2190 			scratch_status.width = Scr.MyDisplayWidth;
2191 			scratch_status.height = Scr.MyDisplayHeight;
2192 
2193 			save_aswindow_anchor (asw, True, True);
2194 			status2anchor (&(asw->anchor), asw->hints, &scratch_status,
2195 										 Scr.VxMax + Scr.MyDisplayWidth,
2196 										 Scr.VyMax + Scr.MyDisplayHeight);
2197 			reconfigured = True;
2198 		}
2199 	}
2200 	if (get_flags (flags, AS_MaximizedX)) {
2201 		if (!ASWIN_GET_FLAGS (asw, AS_MaximizedX)) {
2202 			if (restore_anchor_x (asw))
2203 				reconfigured = True;
2204 		} else if (!ASWIN_GET_FLAGS (asw, AS_Fullscreen))
2205 			need_placement = True;
2206 	}
2207 	if (get_flags (flags, AS_MaximizedY)) {
2208 		if (!ASWIN_GET_FLAGS (asw, AS_MaximizedY)) {
2209 			if (restore_anchor_y (asw))
2210 				reconfigured = True;
2211 		} else if (!ASWIN_GET_FLAGS (asw, AS_Fullscreen))
2212 			need_placement = True;
2213 	}
2214 
2215 	if (get_flags (flags, AS_Focused))
2216 		activate_aswindow (asw, False, True);
2217 
2218 	if (need_placement)
2219 		place_aswindow (asw);
2220 
2221 	on_window_status_changed (asw, reconfigured);
2222 	if (get_flags (flags, AS_Sticky))
2223 		update_window_transparency (asw, False);
2224 	LOCAL_DEBUG_OUT ("Window is %sticky",
2225 									 ASWIN_GET_FLAGS (asw, AS_Sticky) ? "S" : "NotS");
2226 }
2227 
activate_aswindow(ASWindow * asw,Bool force,Bool deiconify)2228 Bool activate_aswindow (ASWindow * asw, Bool force, Bool deiconify)
2229 {
2230 	Bool res = False;
2231 	LOCAL_DEBUG_CALLER_OUT ("%p, %d, %d", asw, force, deiconify);
2232 	LOCAL_DEBUG_OUT ("current focused is %p, active is %p",
2233 									 Scr.Windows->focused, Scr.Windows->active);
2234 	if (asw == NULL || asw->status == NULL || ASWIN_GET_FLAGS (asw, AS_Dead))
2235 		return False;
2236 
2237 	if (force) {
2238 		GrabEm (ASDefaultScr, Scr.Feel.cursors[ASCUR_Select]);	/* to prevent Enter Notify events to
2239 																														   be sent to us while shifting windows around */
2240 		if ((res = make_aswindow_visible (asw, deiconify))) {
2241 			LOCAL_DEBUG_OUT ("CHANGE Scr.Windows->active from %p to %p",
2242 											 Scr.Windows->active, asw);
2243 			Scr.Windows->active = asw;	/* must do that prior to UngrabEm, so that window gets focused */
2244 		}
2245 		UngrabEm ();
2246 	} else {
2247 		if (ASWIN_GET_FLAGS (asw, AS_Iconic)) {
2248 			LOCAL_DEBUG_OUT ("Window is iconic - pending implementation%s", "");
2249 			if (deiconify)
2250 				set_window_wm_state (asw, False, False);
2251 			else
2252 				return False;
2253 		}
2254 		if (ASWIN_DESK (asw) != Scr.CurrentDesk) {
2255 			LOCAL_DEBUG_OUT ("Window is on inactive desk - can't focus%s", "");
2256 			return False;
2257 		}
2258 		if (asw->status->x + asw->status->width < 0
2259 				|| asw->status->x >= Scr.MyDisplayWidth
2260 				|| asw->status->y + asw->status->height < 0
2261 				|| asw->status->y >= Scr.MyDisplayHeight) {
2262 			LOCAL_DEBUG_OUT ("Window is out of the screen - can't focus%s", "");
2263 			return False;							/* we are out of screen - can't focus */
2264 		}
2265 		LOCAL_DEBUG_OUT ("CHANGE Scr.Windows->active from %p to %p",
2266 										 Scr.Windows->active, asw);
2267 		Scr.Windows->active = asw;	/* must do that prior to UngrabEm, so that window gets focused */
2268 		res = focus_active_window ();
2269 	}
2270 	return res;
2271 }
2272 
2273 
hilite_aswindow(ASWindow * asw)2274 void hilite_aswindow (ASWindow * asw)
2275 {
2276 	if (Scr.Windows->hilited != asw) {
2277 		if (Scr.Windows->hilited)
2278 			on_window_hilite_changed (Scr.Windows->hilited, False);
2279 		if (asw)
2280 			on_window_hilite_changed (asw, True);
2281 
2282 		if (Scr.Windows->hilited)
2283 			broadcast_focus_change (Scr.Windows->hilited, False);
2284 		if (asw)
2285 			broadcast_focus_change (asw, True);
2286 
2287 		Scr.Windows->hilited = asw;
2288 		set_active_window_prop (Scr.wmprops, asw ? asw->w : None);
2289 	}
2290 }
2291 
hide_hilite()2292 void hide_hilite ()
2293 {
2294 	if (Scr.Windows->hilited != NULL) {
2295 		on_window_hilite_changed (Scr.Windows->hilited, False);
2296 		broadcast_focus_change (Scr.Windows->hilited, False);
2297 		Scr.Windows->hilited = NULL;
2298 	}
2299 }
2300 
press_aswindow(ASWindow * asw,int context)2301 void press_aswindow (ASWindow * asw, int context)
2302 {
2303 	if (context == C_NO_CONTEXT) {
2304 		if (Scr.Windows->pressed == asw)
2305 			Scr.Windows->pressed = NULL;
2306 	} else if (Scr.Windows->pressed != asw) {
2307 		/* TODO :may need to do something to avoid recursion here */
2308 		if (Scr.Windows->pressed != NULL)
2309 			on_window_pressure_changed (Scr.Windows->pressed, C_NO_CONTEXT);
2310 		Scr.Windows->pressed = asw;
2311 	}
2312 
2313 	if (asw)
2314 		on_window_pressure_changed (asw, context);
2315 }
2316 
release_pressure()2317 void release_pressure ()
2318 {
2319 	if (Scr.Windows->pressed != NULL) {
2320 		on_window_pressure_changed (Scr.Windows->pressed, C_NO_CONTEXT);
2321 		Scr.Windows->pressed = NULL;
2322 	}
2323 }
2324 
2325 /**********************************************************************/
2326 /* The End                                                            */
2327 /**********************************************************************/
2328