1 /***********************************************************/
2 /*                                                         */
3 /*  System dependent widget management (unix, x11)         */
4 /*                                                         */
5 /***********************************************************/
6 
7 #include "unix/guts.h"
8 #include "Window.h"
9 #include "Application.h"
10 
11 #define SORT(a,b)       { int swp; if ((a) > (b)) { swp=(a); (a)=(b); (b)=swp; }}
12 #define REVERT(a)	( XX-> size. y - (a) - 1)
13 
14 Bool
apc_widget_map_points(Handle self,Bool toScreen,int n,Point * p)15 apc_widget_map_points( Handle self, Bool toScreen, int n, Point *p)
16 {
17 	Point d = {0,0};
18 
19 	while ( self && (self != application)) {
20 		DEFXX;
21 		Point origin;
22 		if ( XX-> parentHandle) {
23 			XWindow dummy;
24 			XTranslateCoordinates( DISP, XX-> client, guts. root, 0, XX-> size.y-1, &origin.x, &origin.y, &dummy);
25 			origin. y = guts. displaySize. y - origin. y;
26 			self = application;
27 		} else {
28 			origin = XX-> origin;
29 			self = XX-> flags. clip_owner ? PWidget(self)-> owner : application;
30 		}
31 		d. x += origin. x;
32 		d. y += origin. y;
33 	}
34 
35 	if ( !toScreen) {
36 		d. x = -d. x;
37 		d. y = -d. y;
38 	}
39 
40 	while (n--) {
41 		p[n]. x += d. x;
42 		p[n]. y += d. y;
43 	}
44 	return true;
45 }
46 
47 ApiHandle
apc_widget_get_parent_handle(Handle self)48 apc_widget_get_parent_handle( Handle self)
49 {
50 	return X(self)-> parentHandle;
51 }
52 
53 Handle
apc_widget_get_z_order(Handle self,int zOrderId)54 apc_widget_get_z_order( Handle self, int zOrderId)
55 {
56 	DEFXX;
57 	XWindow root, parent, *children;
58 	unsigned int count;
59 	int i, inc;
60 	Handle ret = NULL_HANDLE;
61 
62 	if ( !( PComponent(self)-> owner))
63 		return self;
64 
65 	switch ( zOrderId) {
66 	case zoFirst:
67 		i = 1;
68 		inc = -1;
69 		break;
70 	case zoLast:
71 		i  = 1;
72 		inc = 1;
73 		break;
74 	case zoNext:
75 		i = 0;
76 		inc = -1;
77 		break;
78 	case zoPrev:
79 		i = 0;
80 		inc = 1;
81 		break;
82 	default:
83 		return NULL_HANDLE;
84 	}
85 
86 	if ( XQueryTree( DISP, X(PComponent(self)-> owner)-> client,
87 		&root, &parent, &children, &count) == 0)
88 			return NULL_HANDLE;
89 
90 	if ( count == 0) goto EXIT;
91 
92 	if ( i == 0) {
93 		int found = -1;
94 		for ( i = 0; i < count; i++) {
95 			if ( children[ i] == XX-> client) {
96 				found = i;
97 				break;
98 			}
99 		}
100 		if ( found < 0) { /* if !clipOwner */
101 			ret = self;
102 			goto EXIT;
103 		}
104 		i = found + inc;
105 		if ( i < 0 || i >= count) goto EXIT; /* last in line */
106 	} else
107 		i = ( zOrderId == zoFirst) ? count - 1 : 0;
108 
109 	while ( 1) {
110 		Handle who = ( Handle) hash_fetch( guts. windows, (void*)&(children[i]), sizeof(X_WINDOW));
111 		if ( who) {
112 			ret = who;
113 			break;
114 		}
115 		i += inc;
116 		if ( i < 0 || i >= count) break;
117 	}
118 
119 EXIT:
120 	if ( children) XFree( children);
121 	return ret;
122 }
123 
124 void
process_transparents(Handle self)125 process_transparents( Handle self)
126 {
127 	int i;
128 	Point sz = X(self)-> size;
129 	for ( i = 0; i < PWidget(self)-> widgets. count; i++) {
130 		Handle x = PWidget(self)-> widgets. items[ i];
131 		if ( X(x)-> flags. transparent &&
132 			X(x)-> flags. want_visible &&
133 			!X(x)-> flags. falsely_hidden) {
134 			Point pos = X(x)-> origin;
135 			if ( pos. x >= sz.x || pos.y >= sz.y ||
136 				pos. x + X(x)-> size.x <= 0 ||
137 				pos. y + X(x)-> size.y <= 0) continue;
138 			apc_widget_invalidate_rect( x, NULL);
139 		}
140 	}
141 }
142 
143 int
prima_flush_events(Display * disp,XEvent * ev,Handle self)144 prima_flush_events( Display * disp, XEvent * ev, Handle self)
145 {
146 	XWindow win;
147 	/* leave only configuration unrelated commands on the queue */
148 	switch ( ev-> type) {
149 	case SelectionRequest:
150 	case SelectionClear:
151 	case MappingNotify:
152 	case SelectionNotify:
153 	case ClientMessage:
154 	case MapNotify:
155 	case UnmapNotify:
156 	case KeymapNotify:
157 	case KeyPress:
158 	case KeyRelease:
159 	case PropertyNotify:
160 	case ColormapNotify:
161 	case DestroyNotify:
162 		return false;
163 	}
164 
165 	switch ( ev-> type) {
166 	case ConfigureNotify:
167 	case -ConfigureNotify:
168 		win = ev-> xconfigure. window;
169 		break;
170 	case ReparentNotify:
171 		win = ev-> xreparent. window;
172 		break;
173 	default:
174 		win = ev-> xany. window;
175 	}
176 
177 	return win == X(self)-> client || win == X_WINDOW;
178 }
179 
180 void
prima_get_view_ex(Handle self,PViewProfile p)181 prima_get_view_ex( Handle self, PViewProfile p)
182 {
183 	DEFXX;
184 	if ( !p) return;
185 	if ( XX-> type. window) {
186 		p-> pos       = apc_window_get_client_pos( self);
187 		p-> size      = apc_window_get_client_size( self);
188 		XFetchName( DISP, X_WINDOW, &p-> title);
189 	} else {
190 		p-> pos       = apc_widget_get_pos( self);
191 		p-> size      = apc_widget_get_size( self);
192 		p-> title     = NULL;
193 	}
194 	p-> capture   = apc_widget_is_captured( self);
195 	p-> focused   = apc_widget_is_focused( self);
196 	p-> visible   = apc_widget_is_visible( self);
197 
198 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
199 	p-> shape_count = 0;
200 	if ( XX-> shape_extent. x != 0 && XX-> shape_extent. y != 0)
201 		p-> shape_rects = XShapeGetRectangles( DISP, X_WINDOW, ShapeBounding, &p-> shape_count, &p->shape_ordering);
202 #endif
203 }
204 
205 void
prima_set_view_ex(Handle self,PViewProfile p)206 prima_set_view_ex( Handle self, PViewProfile p)
207 {
208 	DEFXX;
209 
210 	if ( p-> visible ) XMapWindow( DISP, X_WINDOW);
211 	XX-> origin. x--; /* force it */
212 	if ( XX-> type. window ) {
213 		apc_window_set_client_rect( self, p-> pos.x, p-> pos.y, p-> size.x, p->size.y);
214 		apc_window_set_caption( self, p->title, XX->flags. title_utf8);
215 		XFree(p->title);
216 	} else {
217 		apc_widget_set_rect( self, p-> pos.x, p-> pos.y, p-> size.x, p->size.y);
218 	}
219 
220 	if ( p-> focused) apc_widget_set_focused( self);
221 	if ( p-> capture) apc_widget_set_capture( self, 1, NULL_HANDLE);
222 
223 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
224 	if ( p-> shape_count > 0 ) {
225 		XShapeCombineRectangles( DISP, X_WINDOW, ShapeBounding, 0, 0, p-> shape_rects, p->shape_count, ShapeSet, p->shape_ordering);
226 		if ( X_WINDOW != XX-> client)
227 			XShapeCombineRectangles( DISP, XX->client, ShapeBounding, 0, 0, p-> shape_rects, p->shape_count, ShapeSet, p->shape_ordering);
228 		XFree( p-> shape_rects );
229 	}
230 #endif
231 }
232 
233 void
prima_notify_sys_handle(Handle self)234 prima_notify_sys_handle( Handle self )
235 {
236 	Event ev = {cmSysHandle};
237 	ev. gen. source = self;
238 	apc_message( self, &ev, false);
239 }
240 
241 Bool
apc_widget_create(Handle self,Handle owner,Bool sync_paint,Bool clip_owner,Bool transparent,ApiHandle parentHandle,Bool layered)242 apc_widget_create( Handle self, Handle owner, Bool sync_paint,
243 						Bool clip_owner, Bool transparent, ApiHandle parentHandle, Bool layered)
244 {
245 	DEFXX;
246 	ViewProfile vprf;
247 	Bool reparent, recreate, layered_requested;
248 	Handle real_owner, old_parent;
249 	XWindow parent, old = X_WINDOW;
250 	XSetWindowAttributes attrs;
251 	unsigned long valuemask;
252 
253 	if ( !guts. argb_visual. visual || guts. argb_visual. visualid == guts. visual. visualid)
254 		layered = false;
255 
256 	layered_requested = layered;
257 	layered = ( clip_owner && owner != application ) ? X(owner)->flags. layered : layered_requested;
258 
259 	XX-> visual   = layered ? &guts. argb_visual : &guts. visual;
260 	XX-> colormap = layered ? guts. argbColormap : guts. defaultColormap;
261 
262 	reparent = ( old != NULL_HANDLE) && (
263 		( clip_owner != XX-> flags. clip_owner) ||
264 		( parentHandle != XX-> parent)
265 	);
266 	recreate = ( old != NULL_HANDLE) && (
267 		( layered != XX-> flags. layered )
268 	);
269 	if ( recreate ) {
270 		int i, count;
271 		Handle * list;
272 		XEvent dummy_ev;
273 
274 		list  = PWidget(self)-> widgets. items;
275 		count = PWidget(self)-> widgets. count;
276 		CWidget(self)-> end_paint_info( self);
277 		CWidget(self)-> end_paint( self);
278 		prima_release_gc( XX);
279 		for( i = 0; i < count; i++)
280 			prima_get_view_ex( list[ i], ( ViewProfile*)( X( list[ i])-> recreateData = malloc( sizeof( ViewProfile))));
281 
282 		reparent = false;
283 		if ( XX-> recreateData) {
284 			memcpy( &vprf, XX-> recreateData, sizeof( vprf));
285 			free( XX-> recreateData);
286 			XX-> recreateData = NULL;
287 		} else
288 			prima_get_view_ex( self, &vprf);
289 		if ( guts. currentMenu && PComponent( guts. currentMenu)-> owner == self) prima_end_menu();
290 		CWidget( self)-> end_paint_info( self);
291 		CWidget( self)-> end_paint( self);
292 		if ( XX-> flags. paint_pending) {
293 			TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
294 			XX-> flags. paint_pending = false;
295 		}
296 		/* flush configure events */
297 		XSync( DISP, false);
298 		while ( XCheckIfEvent( DISP, &dummy_ev, (XIfEventProcType)prima_flush_events, (XPointer)self));
299 		hash_delete( guts.windows, (void*)&old, sizeof(old), false);
300 		XCHECKPOINT;
301 	}
302 
303 	old_parent = ( old != NULL_HANDLE ) ? XX->parent : NULL_HANDLE;
304 
305 	XX-> flags. transparent = !!transparent;
306 	XX-> type.drawable = true;
307 	XX-> type.widget = true;
308 	if ( !clip_owner || ( owner == application)) {
309 		parent = guts. root;
310 		real_owner = application;
311 	} else {
312 		parent = X( owner)-> client;
313 		real_owner = owner;
314 	}
315 
316 	if ( parentHandle)
317 		parent = parentHandle;
318 	XX-> parentHandle = parentHandle;
319 	XX-> real_parent = XX-> parent = parent;
320 	XX-> above = NULL_HANDLE;
321 	XX-> owner = real_owner;
322 
323 	XX-> flags. clip_owner = !!clip_owner;
324 	XX-> flags. sync_paint = !!sync_paint;
325 	XX-> flags. layered    = !!layered;
326 	XX-> flags. layered_requested = !!layered_requested;
327 
328 	attrs. event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask
329 		| ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask
330 		| ButtonMotionMask | KeymapStateMask | ExposureMask | VisibilityChangeMask
331 		| StructureNotifyMask | FocusChangeMask | PropertyChangeMask | ColormapChangeMask
332 		| OwnerGrabButtonMask;
333 	attrs. override_redirect = true;
334 	attrs. do_not_propagate_mask = attrs. event_mask;
335 	attrs. win_gravity = ( clip_owner && ( owner != application))
336 		? SouthWestGravity : NorthWestGravity;
337 	attrs. colormap = XX->colormap;
338 
339 	if ( reparent) {
340 		Point pos = PWidget(self)-> pos;
341 		XEvent dummy_ev;
342 
343 		if ( old_parent == parent ) return true;
344 
345 		if ( guts. currentMenu && PComponent( guts. currentMenu)-> owner == self) prima_end_menu();
346 		CWidget( self)-> end_paint_info( self);
347 		CWidget( self)-> end_paint( self);
348 		if ( XX-> flags. paint_pending) {
349 			TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
350 			XX-> flags. paint_pending = false;
351 		}
352 		/* flush configure events */
353 		XSync( DISP, false);
354 		while ( XCheckIfEvent( DISP, &dummy_ev, (XIfEventProcType)prima_flush_events, (XPointer)self));
355 
356 		XChangeWindowAttributes( DISP, X_WINDOW, CWWinGravity, &attrs);
357 		XReparentWindow( DISP, X_WINDOW, parent, pos. x,
358 			X(real_owner)-> size.y - pos. y - X(self)-> size. y);
359 
360 		XX-> ackOrigin = pos;
361 		XX-> ackSize   = XX-> size;
362 		XX-> flags. mapped = XX-> flags. want_visible;
363 		process_transparents( self);
364 		return true;
365 	}
366 
367 	valuemask =
368 		0
369 		/* | CWBackPixmap */
370 		/* | CWBackPixel */
371 		/* | CWBorderPixmap */
372 		/* | CWBorderPixel */
373 		/* | CWBitGravity */
374 		| CWWinGravity
375 		/* | CWBackingStore */
376 		/* | CWBackingPlanes */
377 		/* | CWBackingPixel */
378 		| CWOverrideRedirect
379 		/* | CWSaveUnder */
380 		| CWEventMask
381 		/* | CWDontPropagate */
382 		| CWColormap
383 		/* | CWCursor */
384 	;
385 
386 	if ( layered ) {
387 		valuemask |= CWBackPixel | CWBorderPixel;
388 		attrs. background_pixel = 0;
389 		attrs. border_pixel = 0;
390 	}
391 
392 	XX-> client = X_WINDOW = XCreateWindow( DISP, parent,
393 		0, 0, 1, 1, 0, XX-> visual-> depth,
394 		InputOutput, XX-> visual-> visual,
395 		valuemask, &attrs
396 	);
397 	XCHECKPOINT;
398 	if (!X_WINDOW) {
399 		warn("error creating window");
400 		return false;
401 	}
402 
403 	if (recreate) {
404 		int i, count;
405 		Handle * list;
406 		Point pos = PWidget(self)-> pos;
407 		list  = PWidget(self)-> widgets. items;
408 		count = PWidget(self)-> widgets. count;
409 		prima_set_view_ex( self, &vprf);
410 		XX-> gdrawable = XX-> udrawable = X_WINDOW;
411 		XX-> ackOrigin = pos;
412 		XX-> ackSize   = XX-> size;
413 		XX-> flags. mapped = XX-> flags. want_visible;
414 		hash_store( guts.windows, &X_WINDOW, sizeof(X_WINDOW), (void*)self);
415 		for ( i = 0; i < count; i++) ((( PComponent) list[ i])-> self)-> recreate( list[ i]);
416 		XDestroyWindow( DISP, old);
417 		prima_notify_sys_handle( self );
418 		return true;
419 	}
420 
421 	XX-> size. x = XX-> size. y =
422 	XX-> ackOrigin. x = XX-> ackOrigin. y =
423 	XX-> ackSize. x = XX-> ackSize. y = 0;
424 
425 	hash_store( guts.windows, &X_WINDOW, sizeof(X_WINDOW), (void*)self);
426 
427 	XX-> gdrawable = XX-> udrawable = X_WINDOW;
428 
429 	XX-> flags. position_determined = 1;
430 
431 	apc_component_fullname_changed_notify( self);
432 
433 	prima_send_create_event( X_WINDOW);
434 
435 	return true;
436 }
437 
438 Bool
apc_widget_begin_paint(Handle self,Bool inside_on_paint)439 apc_widget_begin_paint( Handle self, Bool inside_on_paint)
440 {
441 	DEFXX;
442 	Bool useRPDraw = false;
443 
444 	if ( guts. appLock > 0) return false;
445 
446 	if ( XX-> size.x <= 0 || XX-> size.y <= 0) return false;
447 
448 	if ( XX-> flags. transparent && inside_on_paint) {
449 		if ( XX-> flags. want_visible && !XX-> flags. falsely_hidden) {
450 			if ( XX-> parent == guts. root) {
451 				XEvent ev;
452 				if ( XX-> flags. transparent_busy) return false;
453 				XX-> flags. transparent_busy = 1;
454 				XUnmapWindow( DISP, X_WINDOW);
455 				XSync( DISP, false);
456 				while ( XCheckMaskEvent( DISP, ExposureMask, &ev))
457 					prima_handle_event( &ev, NULL);
458 				XMapWindow( DISP, X_WINDOW);
459 				XSync( DISP, false);
460 				while ( XCheckMaskEvent( DISP, ExposureMask, &ev))
461 					prima_handle_event( &ev, NULL);
462 				if ( XX-> flags. paint_pending) {
463 					TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
464 					XX-> flags. paint_pending = false;
465 				}
466 				XX-> flags. transparent_busy = 0;
467 			} else
468 				useRPDraw = true;
469 		}
470 	}
471 	XCHECKPOINT;
472 	if ( guts. dynamicColors && inside_on_paint) prima_palette_free( self, false);
473 	prima_no_cursor( self);
474 	prima_prepare_drawable_for_painting( self, inside_on_paint);
475 	CREATE_ARGB_PICTURE(XX->gdrawable, XF_LAYERED(XX) ? 32 : 0, XX->argb_picture);
476 	if ( useRPDraw) {
477 		Handle owner = PWidget(self)->owner;
478 		Point po = apc_widget_get_pos( self);
479 		Point sz = apc_widget_get_size( self);
480 		Point so = CWidget(owner)-> get_size( owner);
481 		XDrawable dc;
482 		Region region;
483 		XRectangle xr = {0,0,0,0};
484 		xr. width = sz.x;
485 		xr. height = sz.y;
486 
487 		CWidget(owner)-> begin_paint( owner);
488 		dc = X(owner)-> gdrawable;
489 		X(owner)-> gdrawable = XX-> gdrawable;
490 		X(owner)-> btransform. x = -po. x;
491 		X(owner)-> btransform. y = so. y - sz. y - po. y;
492 		if ( X(owner)-> paint_region) {
493 			XDestroyRegion( X(owner)-> paint_region);
494 			X(owner)-> paint_region = NULL;
495 		}
496 		region = XCreateRegion();
497 		XUnionRectWithRegion( &xr, region, region);
498 		if ( XX-> paint_region)
499 			XIntersectRegion( XX-> paint_region, region, region);
500 		X(owner)-> paint_region = XCreateRegion();
501 		XUnionRegion( X(owner)-> paint_region, region, X(owner)-> paint_region);
502 		XOffsetRegion( X(owner)-> paint_region, -X(owner)-> btransform.x, X(owner)-> btransform.y);
503 		XSetRegion( DISP, X(owner)-> gc, region);
504 		X(owner)-> current_region = region;
505 		X(owner)-> flags. kill_current_region = 1;
506 		CWidget( owner)-> notify( owner, "sH", "Paint", owner);
507 		X(owner)-> gdrawable = dc;
508 		CWidget( owner)-> end_paint( owner);
509 	}
510 
511 	XX-> flags. force_flush = !inside_on_paint;
512 
513 	return true;
514 }
515 
516 Bool
apc_widget_begin_paint_info(Handle self)517 apc_widget_begin_paint_info( Handle self)
518 {
519 	prima_no_cursor( self);
520 	prima_prepare_drawable_for_painting( self, false);
521 	return true;
522 }
523 
524 Bool
apc_widget_destroy(Handle self)525 apc_widget_destroy( Handle self)
526 {
527 	DEFXX;
528 	ConfigureEventPair *n1, *n2;
529 
530 	if ( guts.xdndr_last_target == self )
531 		guts.xdndr_last_target = NULL_HANDLE;
532 
533 	if ( XX-> recreateData) free( XX-> recreateData);
534 
535 	n1 = TAILQ_FIRST( &XX-> configure_pairs);
536 	while (n1 != NULL) {
537 		n2 = TAILQ_NEXT(n1, link);
538 		free(n1);
539 		n1 = n2;
540 	}
541 
542 	if ( XX-> user_pointer.cursor != None) {
543 		XFreeCursor( DISP, XX-> user_pointer.cursor);
544 		XX-> user_pointer.cursor = None;
545 	}
546 	if ( XX-> user_pointer.xor != None) {
547 		XFreePixmap( DISP, XX-> user_pointer.xor);
548 		XX-> user_pointer.xor = None;
549 	}
550 	if ( XX-> user_pointer.and != None) {
551 		XFreePixmap( DISP, XX-> user_pointer.and);
552 		XX-> user_pointer.and = None;
553 	}
554 #ifdef HAVE_X11_XCURSOR_XCURSOR_H
555 	if ( XX-> user_pointer.xcursor != NULL) {
556 		XcursorImageDestroy(XX-> user_pointer.xcursor);
557 		XX-> user_pointer.xcursor = NULL;
558 	}
559 #endif
560 	if ( guts. currentMenu && PComponent( guts. currentMenu)-> owner == self)
561 		prima_end_menu();
562 	if ( guts. focused == self)
563 		guts. focused = NULL_HANDLE;
564 	XX-> flags.modal = false;
565 	if ( XX-> flags. paint_pending) {
566 		TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
567 		XX-> flags. paint_pending = false;
568 	}
569 	if ( XX-> invalid_region) {
570 		XDestroyRegion( XX-> invalid_region);
571 		XX-> invalid_region = NULL;
572 	}
573 
574 	if ( XX-> flags. dnd_aware )
575 		apc_dnd_set_aware( self, false );
576 	if ( guts. xdndr_widget == self )
577 		guts. xdndr_widget = NULL_HANDLE;
578 	if ( guts. xdndr_receiver == self )
579 		guts. xdndr_receiver = NULL_HANDLE;
580 
581 	if ( X_WINDOW) {
582 		if ( guts. grab_redirect == XX-> client || guts. grab_redirect == X_WINDOW)
583 			guts. grab_redirect = NULL_HANDLE;
584 		if ( guts. grab_widget == self || XX-> flags. grab) {
585 			XUngrabPointer( DISP, CurrentTime);
586 			guts. grab_widget = NULL_HANDLE;
587 		}
588 		XCHECKPOINT;
589 		if ( XX-> client != X_WINDOW) {
590 			XDestroyWindow( DISP, XX-> client);
591 			hash_delete( guts.windows, (void*)&XX-> client, sizeof(X_WINDOW), false);
592 		}
593 		XX-> client = NULL_HANDLE;
594 		XDestroyWindow( DISP, X_WINDOW);
595 		XCHECKPOINT;
596 		hash_delete( guts.windows, (void*)&X_WINDOW, sizeof(X_WINDOW), false);
597 		X_WINDOW = NULL_HANDLE;
598 	}
599 	XFlush( DISP);
600 	return true;
601 }
602 
603 PFont
apc_widget_default_font(PFont f)604 apc_widget_default_font( PFont f)
605 {
606 	memcpy( f, &guts. default_widget_font, sizeof( Font));
607 	return f;
608 }
609 
610 Bool
apc_widget_end_paint(Handle self)611 apc_widget_end_paint( Handle self)
612 {
613 	DEFXX;
614 	XX-> flags. force_flush = 0;
615 
616 	/* make the unintended layered window opaque */
617 	if ( !XX-> flags. layered_requested && XF_LAYERED(XX) && XX-> gc) {
618 		XGCValues gcv;
619 		Point sz;
620 		gcv. foreground = 0xFFFFFFFF;
621 		gcv. function   = GXcopy;
622 		gcv. fill_style = FillSolid;
623 		gcv. plane_mask = guts. argb_bits. alpha_mask;
624 		XChangeGC( DISP, XX->gc, GCPlaneMask|GCForeground|GCFunction|GCFillStyle, &gcv);
625 		sz = apc_widget_get_size( self);
626 		XFillRectangle( DISP, XX-> gdrawable, XX-> gc, 0, 0, sz.x, sz.y);
627 		gcv. plane_mask = 0xFFFFFFFF;
628 		XChangeGC( DISP, XX->gc, GCPlaneMask, &gcv);
629 	}
630 
631 	DELETE_ARGB_PICTURE(XX->argb_picture);
632 	prima_cleanup_drawable_after_painting( self);
633 	prima_update_cursor( self);
634 	return true;
635 }
636 
637 Bool
apc_widget_end_paint_info(Handle self)638 apc_widget_end_paint_info( Handle self)
639 {
640 	prima_cleanup_drawable_after_painting( self);
641 	prima_update_cursor( self);
642 	return true;
643 }
644 
645 Bool
apc_widget_get_clip_by_children(Handle self)646 apc_widget_get_clip_by_children( Handle self)
647 {
648 	return X(self)->flags. clip_by_children;
649 }
650 
651 Bool
apc_widget_get_clip_owner(Handle self)652 apc_widget_get_clip_owner( Handle self)
653 {
654 	return X(self)-> flags. clip_owner;
655 }
656 
657 Color
apc_widget_get_color(Handle self,int index)658 apc_widget_get_color( Handle self, int index)
659 {
660 	return X(self)-> colors[ index];
661 }
662 
663 Bool
apc_widget_get_first_click(Handle self)664 apc_widget_get_first_click( Handle self)
665 {
666 	return X(self)-> flags. first_click ? true : false;
667 }
668 
669 Handle
apc_widget_get_focused(void)670 apc_widget_get_focused( void)
671 {
672 	return guts. focused;
673 }
674 
675 ApiHandle
apc_widget_get_handle(Handle self)676 apc_widget_get_handle( Handle self)
677 {
678 	return X_WINDOW;
679 }
680 
681 Rect
apc_widget_get_invalid_rect(Handle self)682 apc_widget_get_invalid_rect( Handle self)
683 {
684 	DEFXX;
685 	Rect ret;
686 	XRectangle r;
687 	if ( !XX-> invalid_region) {
688 		Rect r = {0,0,0,0};
689 		return r;
690 	}
691 	XClipBox( XX-> invalid_region, &r);
692 	ret. left = r.x;
693 	ret. bottom = XX-> size.y - r.height - r.y;
694 	ret. right = r.x + r.width;
695 	ret. top =  XX-> size.y - r.y;
696 	return ret;
697 }
698 
699 Bool
apc_widget_get_layered_request(Handle self)700 apc_widget_get_layered_request( Handle self)
701 {
702 	return X(self)-> flags. layered_requested;
703 }
704 
705 Bool
apc_widget_surface_is_layered(Handle self)706 apc_widget_surface_is_layered( Handle self)
707 {
708 	return X(self)-> flags. layered;
709 }
710 
711 Point
apc_widget_get_pos(Handle self)712 apc_widget_get_pos( Handle self)
713 {
714 	DEFXX;
715 	XWindow r;
716 	Point ret;
717 	int x, y;
718 	unsigned int w, h, d, b;
719 
720 	if ( XX-> type. window) {
721 		Rect rc;
722 		Point p = apc_window_get_client_pos( self);
723 		prima_get_frame_info( self, &rc);
724 		p. x -= rc. left;
725 		p. y -= rc. bottom;
726 		return p;
727 	}
728 
729 	if ( XX-> parentHandle == NULL_HANDLE)
730 		return XX-> origin;
731 
732 	XGetGeometry( DISP, X_WINDOW, &r, &x, &y, &w, &h, &b, &d);
733 	XTranslateCoordinates( DISP, XX-> parentHandle, guts. root, x, y, &x, &y, &r);
734 	ret. x = x;
735 	ret. y = DisplayHeight( DISP, SCREEN) - y - w;
736 	return ret;
737 }
738 
739 Bool
apc_widget_get_shape(Handle self,Handle mask)740 apc_widget_get_shape( Handle self, Handle mask)
741 {
742 #ifndef HAVE_X11_EXTENSIONS_SHAPE_H
743 	return false;
744 #else
745 	DEFXX;
746 	XRectangle *r, *rc;
747 	int i, count, ordering, aperture;
748 	Region rgn;
749 
750 	if ( !guts. shape_extension) return false;
751 
752 	if ( !mask)
753 		return XX-> shape_extent. x != 0 && XX-> shape_extent. y != 0;
754 
755 	if ( XX-> shape_extent. x == 0 || XX-> shape_extent. y == 0)
756 		return false;
757 
758 	r = rc = XShapeGetRectangles( DISP, X_WINDOW, ShapeBounding, &count, &ordering);
759 
760 	rgn = GET_REGION(mask)-> region;
761 	for ( i = aperture = 0; i < count; i++, r++) {
762 		int h = r-> y + r-> height;
763 		if ( aperture < h ) aperture = h;
764 		XUnionRectWithRegion( r, rgn, rgn);
765 	}
766 	GET_REGION(mask)-> aperture = aperture;
767 	XFree( rc);
768 	return true;
769 #endif
770 }
771 
772 Point
apc_widget_get_size(Handle self)773 apc_widget_get_size( Handle self)
774 {
775 	DEFXX;
776 	if ( XX-> type. window) {
777 		Rect rc;
778 		Point p = apc_window_get_client_size( self);
779 		prima_get_frame_info( self, &rc);
780 		p. x += rc. left + rc. right;
781 		p. y += rc. bottom + rc. top;
782 		return p;
783 	}
784 
785 	return XX-> size;
786 }
787 
788 Bool
apc_widget_get_sync_paint(Handle self)789 apc_widget_get_sync_paint( Handle self)
790 {
791 	return X(self)-> flags. sync_paint;
792 }
793 
794 Bool
apc_widget_get_transparent(Handle self)795 apc_widget_get_transparent( Handle self)
796 {
797 	return X(self)-> flags. transparent;
798 }
799 
800 Bool
apc_widget_is_captured(Handle self)801 apc_widget_is_captured( Handle self)
802 {
803 	return X(self)-> flags. grab ? true : false;
804 }
805 
806 Bool
apc_widget_is_enabled(Handle self)807 apc_widget_is_enabled( Handle self)
808 {
809 	return XF_ENABLED(X(self)) ? true : false;
810 }
811 
812 Bool
apc_widget_is_exposed(Handle self)813 apc_widget_is_exposed( Handle self)
814 {
815 	return X(self)-> flags. exposed ? true : false;
816 }
817 
818 Bool
apc_widget_is_focused(Handle self)819 apc_widget_is_focused( Handle self)
820 {
821 	return guts. focused == self;
822 }
823 
824 Bool
apc_widget_is_responsive(Handle self)825 apc_widget_is_responsive( Handle self)
826 {
827 	Bool ena = true;
828 	while ( ena && self != application) {
829 		ena  = XF_ENABLED(X(self)) ? true : false;
830 		self = PWidget(self)-> owner;
831 	}
832 	return ena;
833 }
834 
835 Bool
apc_widget_is_showing(Handle self)836 apc_widget_is_showing( Handle self)
837 {
838 	XWindowAttributes attrs;
839 	DEFXX;
840 
841 	if ( XX
842 		&& XGetWindowAttributes( DISP, XX->udrawable, &attrs)
843 		&& attrs. map_state == IsViewable)
844 		return true;
845 	else
846 		return false;
847 }
848 
849 Bool
apc_widget_is_visible(Handle self)850 apc_widget_is_visible( Handle self)
851 {
852 	return X(self)-> flags. want_visible ? true : false;
853 }
854 
855 Bool
apc_widget_invalidate_rect(Handle self,Rect * rect)856 apc_widget_invalidate_rect( Handle self, Rect *rect)
857 {
858 	XRectangle r;
859 	DEFXX;
860 
861 	if ( rect) {
862 		SORT( rect-> left,   rect-> right);
863 		SORT( rect-> bottom, rect-> top);
864 		r. x = rect-> left;
865 		r. width = rect-> right - rect-> left;
866 		r. y = XX-> size. y - rect-> top;
867 		r. height = rect-> top - rect-> bottom;
868 	} else {
869 		r. x = 0;
870 		r. width = XX-> size. x;
871 		r. y = 0;
872 		r. height = XX-> size. y;
873 	}
874 
875 	if ( !XX-> invalid_region) {
876 		XX-> invalid_region = XCreateRegion();
877 		if ( !XX-> flags. paint_pending) {
878 			TAILQ_INSERT_TAIL( &guts.paintq, XX, paintq_link);
879 			XX-> flags. paint_pending = true;
880 		}
881 	}
882 
883 	XUnionRectWithRegion( &r, XX-> invalid_region, XX-> invalid_region);
884 	if ( XX-> flags. sync_paint) {
885 		apc_widget_update( self);
886 	}
887 	process_transparents( self);
888 	return true;
889 }
890 
891 static Bool
scroll(Handle owner,Handle self,Point * delta)892 scroll( Handle owner, Handle self, Point * delta)
893 {
894 	DEFXX;
895 	if ( XX-> flags. clip_owner)
896 		apc_widget_set_pos( self, XX-> origin. x + delta-> x, XX-> origin. y + delta-> y);
897 	return 0;
898 }
899 
900 int
apc_widget_scroll(Handle self,int horiz,int vert,Rect * confine,Rect * clip,Bool withChildren)901 apc_widget_scroll( Handle self, int horiz, int vert,
902 	Rect *confine, Rect *clip, Bool withChildren)
903 {
904 	DEFXX;
905 	int src_x, src_y, w, h, dst_x, dst_y, iw, ih;
906 	XRectangle r;
907 	Region invalid, reg;
908 
909 	prima_no_cursor( self);
910 	prima_get_gc( XX);
911 	XX-> gcv. clip_mask = None;
912 	XChangeGC( DISP, XX-> gc, VIRGIN_GC_MASK, &XX-> gcv);
913 	XCHECKPOINT;
914 
915 	if ( confine) {
916 		SORT( confine-> left,   confine-> right);
917 		SORT( confine-> bottom, confine-> top);
918 		src_x = confine-> left;
919 		src_y = XX-> size. y - confine-> top;
920 		w = confine-> right - src_x;
921 		h = confine-> top - confine-> bottom;
922 	} else {
923 		src_x = 0;
924 		src_y = 0;
925 		w = XX-> size. x;
926 		h = XX-> size. y;
927 	}
928 
929 	dst_x = src_x + horiz;
930 	dst_y = src_y - vert;
931 	iw = w;
932 	ih = h;
933 
934 	if (clip) {
935 		XRectangle cpa;
936 
937 		SORT( clip-> left,   clip-> right);
938 		SORT( clip-> bottom, clip-> top);
939 
940 		r. x = clip-> left;
941 		r. y = REVERT( clip-> top) + 1;
942 		r. width = clip-> right - clip-> left;
943 		r. height = clip-> top - clip-> bottom;
944 		reg = XCreateRegion();
945 		XUnionRectWithRegion( &r, reg, reg);
946 		XSetRegion( DISP, XX-> gc, reg);
947 		XCHECKPOINT;
948 		XDestroyRegion( reg);
949 		cpa. x = src_x;
950 		cpa. y = src_y;
951 		cpa. width = w;
952 		cpa. height = h;
953 		prima_rect_intersect( &cpa, &r);
954 		dst_x += -src_x + cpa. x;
955 		dst_y += -src_y + cpa. y;
956 		src_x = cpa. x;
957 		src_y = cpa. y;
958 		w = cpa. width;
959 		h = cpa. height;
960 	}
961 
962 	if ( src_x < XX-> size. x && src_x + w >= 0 && dst_x < XX-> size. x && dst_x + w >= 0 &&
963 		src_y < XX-> size. y && src_x + h >= 0 && dst_y < XX-> size. y && dst_y + h >= 0) {
964 		XGCValues gcv;
965 		gcv. graphics_exposures = true;
966 		XChangeGC( DISP, XX-> gc, GCGraphicsExposures, &gcv);
967 		XCopyArea( DISP, XX-> udrawable, XX-> udrawable, XX-> gc,
968 		      src_x, src_y, w, h, dst_x, dst_y);
969 		gcv. graphics_exposures = false;
970 		XChangeGC( DISP, XX-> gc, GCGraphicsExposures, &gcv);
971 	}
972 	prima_release_gc( XX);
973 	XCHECKPOINT;
974 	XFlush( DISP);
975 
976 	r. x = src_x;
977 	r. y = src_y;
978 	r. width = w;
979 	r. height = h;
980 	invalid = XCreateRegion();
981 	if ( src_x < XX-> size. x && src_x + w >= 0 &&
982 		src_y < XX-> size. y && src_y + h >= 0)
983 		XUnionRectWithRegion( &r, invalid, invalid);
984 	if ( clip &&
985 		dst_x < XX-> size. x && dst_x + iw >= 0 &&
986 		dst_y < XX-> size. y && dst_y + ih >= 0) {
987 		XRectangle cpa;
988 		cpa. x = dst_x;
989 		cpa. y = dst_y;
990 		cpa. width = w;
991 		cpa. height = h;
992 		XUnionRectWithRegion( &cpa, invalid, invalid);
993 	}
994 
995 	if ( XX-> invalid_region) {
996 		reg = XCreateRegion();
997 		XUnionRegion( XX-> invalid_region, reg, reg);
998 		XIntersectRegion( reg, invalid, reg);
999 		XSubtractRegion( XX-> invalid_region, reg, XX-> invalid_region);
1000 		XOffsetRegion( reg, horiz, -vert);
1001 		XUnionRegion( XX-> invalid_region, reg, XX-> invalid_region);
1002 		XDestroyRegion( reg);
1003 	} else
1004 		XX-> invalid_region = XCreateRegion();
1005 
1006 	if ( dst_x < XX-> size. x && dst_x + w >= 0 &&
1007 		dst_y < XX-> size. y && dst_y + h >= 0) {
1008 		r. x = dst_x;
1009 		r. y = dst_y;
1010 		reg = XCreateRegion();
1011 		XUnionRectWithRegion( &r, reg, reg);
1012 		XSubtractRegion( invalid, reg, invalid);
1013 		XDestroyRegion( reg);
1014 	}
1015 	XUnionRegion( XX-> invalid_region, invalid, XX-> invalid_region);
1016 	XDestroyRegion( invalid);
1017 	if ( !XX-> flags. paint_pending) {
1018 		TAILQ_INSERT_TAIL( &guts.paintq, XX, paintq_link);
1019 		XX-> flags. paint_pending = true;
1020 	}
1021 
1022 	if ( withChildren) {
1023 		Point delta;
1024 		delta. x = horiz;
1025 		delta. y = vert;
1026 		CWidget(self)-> first_that( self, (void*)scroll, &delta);
1027 	}
1028 
1029 	process_transparents( self);
1030 
1031 	return scrExpose;
1032 }
1033 
1034 Bool
apc_widget_set_capture(Handle self,Bool capture,Handle confineTo)1035 apc_widget_set_capture( Handle self, Bool capture, Handle confineTo)
1036 {
1037 	int r;
1038 	XWindow confine_to = None;
1039 	DEFXX;
1040 
1041 	if ( capture) {
1042 		XWindow z = XX-> client;
1043 		Time t = guts. last_time;
1044 		Cursor cursor = prima_get_cursor(self);
1045 		if ( confineTo && PWidget(confineTo)-> handle)
1046 			confine_to = PWidget(confineTo)-> handle;
1047 AGAIN:
1048 		r = XGrabPointer( DISP, z, false, 0
1049 			| ButtonPressMask
1050 			| ButtonReleaseMask
1051 			| PointerMotionMask
1052 			| ButtonMotionMask, GrabModeAsync, GrabModeAsync,
1053 			confine_to, cursor, t
1054 		);
1055 		XCHECKPOINT;
1056 		if ( r != GrabSuccess) {
1057 			XWindow root = guts. root, rx;
1058 			if (( r == GrabNotViewable) && ( root != z)) {
1059 				XTranslateCoordinates( DISP, z, guts. root, 0, 0,
1060 					&guts. grab_translate_mouse.x, &guts. grab_translate_mouse.y, &rx);
1061 				guts. grab_redirect = z;
1062 				guts. grab_widget = self;
1063 				z = root;
1064 				goto AGAIN;
1065 			}
1066 			if ( r == GrabInvalidTime) {
1067 				t = CurrentTime;
1068 				goto AGAIN;
1069 			}
1070 			guts. grab_redirect = NULL_HANDLE;
1071 			return false;
1072 		} else {
1073 			XX-> flags. grab   = true;
1074 			guts. grab_widget  = self;
1075 			guts. grab_confine = confineTo;
1076 		}
1077 	} else if ( XX-> flags. grab) {
1078 		guts. grab_redirect = NULL_HANDLE;
1079 		XUngrabPointer( DISP, CurrentTime);
1080 		XCHECKPOINT;
1081 		XX-> flags. grab = false;
1082 		guts. grab_widget = NULL_HANDLE;
1083 	}
1084 	XFlush( DISP);
1085 	return true;
1086 }
1087 
1088 Bool
apc_widget_set_clip_by_children(Handle self,Bool clip_by_children)1089 apc_widget_set_clip_by_children( Handle self, Bool clip_by_children)
1090 {
1091 	DEFXX;
1092 	XX->flags. clip_by_children = clip_by_children;
1093 	if ( XF_IN_PAINT(XX) ) {
1094 		XX-> gcv. subwindow_mode = (XX->flags.clip_by_children ? ClipByChildren : IncludeInferiors);
1095 		XChangeGC( DISP, XX-> gc, GCSubwindowMode, &XX-> gcv);
1096 	}
1097 	return true;
1098 }
1099 
1100 Bool
apc_widget_set_color(Handle self,Color color,int i)1101 apc_widget_set_color( Handle self, Color color, int i)
1102 {
1103 	Event e = {cmColorChanged};
1104 
1105 	X(self)-> colors[ i] = color;
1106 	if ( i == ciFore)
1107 		apc_gp_set_color( self, color);
1108 	else if ( i == ciBack)
1109 		apc_gp_set_back_color( self, color);
1110 
1111 	bzero( &e, sizeof(e));
1112 	e. gen. source = self;
1113 	e. gen. i      = i;
1114 	apc_message( self, &e, false);
1115 
1116 	return true;
1117 }
1118 
1119 Bool
apc_widget_set_enabled(Handle self,Bool enable)1120 apc_widget_set_enabled( Handle self, Bool enable)
1121 {
1122 	DEFXX;
1123 
1124 	if ( enable == XF_ENABLED(XX)) return true;
1125 	XF_ENABLED(XX) = enable;
1126 	prima_simple_message(self, enable ? cmEnable : cmDisable, false);
1127 	return true;
1128 }
1129 
1130 Bool
apc_widget_set_first_click(Handle self,Bool firstClick)1131 apc_widget_set_first_click( Handle self, Bool firstClick)
1132 {
1133 	X(self)-> flags. first_click = firstClick ? 1 : 0;
1134 	return true;
1135 }
1136 
1137 static int
flush_refocus(Display * disp,XEvent * ev,void * dummy)1138 flush_refocus( Display * disp, XEvent * ev, void * dummy)
1139 {
1140 	return ev-> type == ClientMessage &&
1141 			ev-> xclient. message_type == WM_PROTOCOLS &&
1142 		(Atom) ev-> xclient. data. l[0] == WM_TAKE_FOCUS;
1143 }
1144 
1145 Bool
apc_widget_set_focused(Handle self)1146 apc_widget_set_focused( Handle self)
1147 {
1148 	int rev;
1149 	XWindow focus = None, xfoc;
1150 	XEvent ev;
1151 	if ( guts. message_boxes) return false;
1152 	if ( self && ( self != CApplication( application)-> map_focus( application, self)))
1153 		return false;
1154 	if ( self) {
1155 		if (XT_IS_WINDOW(X(self))) return true; /* already done in activate() */
1156 		focus = X_WINDOW;
1157 	}
1158 	XGetInputFocus( DISP, &xfoc, &rev);
1159 	if ( xfoc == focus) return true;
1160 
1161 	{ /* code for no-wm environment */
1162 		Handle who = ( Handle) hash_fetch( guts.windows, (void*)&xfoc, sizeof(xfoc)), x = self;
1163 		while ( who && XT_IS_WINDOW(X(who))) who = PComponent( who)-> owner;
1164 		while ( x && !XT_IS_WINDOW(X(x)) && X(x)->flags.clip_owner) x = PComponent( x)-> owner;
1165 		if ( x && x != application && x != who && XT_IS_WINDOW(X(x)))
1166 			XSetInputFocus( DISP, PComponent(x)-> handle, RevertToNone, guts. currentFocusTime);
1167 	}
1168 
1169 	XSetInputFocus( DISP, focus, RevertToParent, guts. currentFocusTime);
1170 	XCHECKPOINT;
1171 
1172 	XSync( DISP, false);
1173 	while ( XCheckMaskEvent( DISP, FocusChangeMask|ExposureMask, &ev))
1174 		prima_handle_event( &ev, NULL);
1175 	while ( XCheckIfEvent( DISP, &ev, (XIfEventProcType)flush_refocus, (XPointer)0));
1176 	return true;
1177 }
1178 
1179 Bool
apc_widget_set_font(Handle self,PFont font)1180 apc_widget_set_font( Handle self, PFont font)
1181 {
1182 	apc_gp_set_font( self, font);
1183 	prima_simple_message( self, cmFontChanged, false);
1184 	return true;
1185 }
1186 
1187 Bool
apc_widget_set_palette(Handle self)1188 apc_widget_set_palette( Handle self)
1189 {
1190 	return prima_palette_replace( self, false);
1191 }
1192 
1193 Bool
apc_widget_set_pos(Handle self,int x,int y)1194 apc_widget_set_pos( Handle self, int x, int y)
1195 {
1196 	DEFXX;
1197 	Event e;
1198 	if ( XX-> type. window) {
1199 		Rect rc;
1200 		prima_get_frame_info( self, &rc);
1201 		return apc_window_set_client_pos( self, x + rc. left, y + rc. bottom);
1202 	}
1203 
1204 	if ( XX-> parentHandle == NULL_HANDLE && x == XX-> origin.x && y == XX-> origin. y)
1205 		return true;
1206 	if ( XX-> client == guts. grab_redirect) {
1207 		XWindow rx;
1208 		XTranslateCoordinates( DISP, XX-> client, guts. root, 0, 0,
1209 			&guts. grab_translate_mouse.x, &guts. grab_translate_mouse.y, &rx);
1210 	}
1211 	bzero( &e, sizeof( e));
1212 	e. cmd = cmMove;
1213 	e. gen. source = self;
1214 	XX-> origin. x = e. gen. P. x = x;
1215 	XX-> origin. y = e. gen. P. y = y;
1216 	y = X(XX-> owner)-> size. y - XX-> size.y - y;
1217 	if ( XX-> parentHandle) {
1218 		XWindow cld;
1219 		XTranslateCoordinates( DISP, PWidget(XX-> owner)-> handle, XX-> parentHandle, x, y, &x, &y, &cld);
1220 	}
1221 	XMoveWindow( DISP, X_WINDOW, x, y);
1222 	XCHECKPOINT;
1223 	apc_message( self, &e, false);
1224 	if ( PObject( self)-> stage == csDead) return false;
1225 	if ( XX-> flags. transparent)
1226 		apc_widget_invalidate_rect( self, NULL);
1227 	return true;
1228 }
1229 
1230 Bool
apc_widget_set_shape(Handle self,Handle mask)1231 apc_widget_set_shape( Handle self, Handle mask)
1232 {
1233 #ifndef HAVE_X11_EXTENSIONS_SHAPE_H
1234 	return false;
1235 #else
1236 	DEFXX;
1237 	XRectangle xr;
1238 
1239 	if ( !guts. shape_extension) return false;
1240 
1241 	if ( !mask) {
1242 		if ( XX-> shape_extent. x == 0 || XX-> shape_extent. y == 0) return true;
1243 		XShapeCombineMask( DISP, X_WINDOW, ShapeBounding, 0, 0, None, ShapeSet);
1244 		if ( X_WINDOW != XX-> client)
1245 			XShapeCombineMask( DISP, XX-> client, ShapeBounding, 0, 0, None, ShapeSet);
1246 		XX-> shape_extent. x = XX-> shape_extent. y = 0;
1247 		return true;
1248 	}
1249 
1250 	XShapeCombineRegion( DISP, X_WINDOW, ShapeBounding, 0, XX->size.y - GET_REGION(mask)->aperture + XX->menuHeight, GET_REGION(mask)->region, ShapeSet);
1251 	if ( XX-> menuHeight > 0 ) {
1252 	/*
1253 		XXX This static shape approach doesn't work when menuHeight is dynamically changed.
1254 			Need to implement something more elaborated.
1255 	*/
1256 		xr. x = 0;
1257 		xr. y = 0;
1258 		xr. width  = XX->size.x;
1259 		xr. height = XX->menuHeight;
1260 		XShapeCombineRectangles( DISP, X_WINDOW, ShapeBounding, 0, 0, &xr, 1, ShapeUnion, 0);
1261 	}
1262 	XClipBox( GET_REGION(mask)->region, &xr);
1263 	XX-> shape_extent. x = xr. x + xr. width;
1264 	XX-> shape_extent. y = GET_REGION(mask)->aperture;
1265 	XX-> shape_offset. x = 0;
1266 	XX-> shape_offset. y = XX-> menuHeight;
1267 	return true;
1268 #endif
1269 }
1270 
1271 /* Used instead of XUnmapWindow sometimes because when a focused
1272 	widget gets hidden, the X server's revert_to is sometimes
1273 	weirdly set to RevertToPointerRoot ( mwm is the guilty one ) */
1274 static void
apc_XUnmapWindow(Handle self)1275 apc_XUnmapWindow( Handle self)
1276 {
1277 	Handle z = guts. focused;
1278 	while ( z) {
1279 		if ( z == self) {
1280 			if (PComponent(self)-> owner) {
1281 				z = PComponent(self)-> owner;
1282 				while ( z && !X(z)-> type. window) z = PComponent(z)-> owner;
1283 				if ( z && z != application)
1284 					XSetInputFocus( DISP, PComponent(z)-> handle, RevertToNone, guts. currentFocusTime);
1285 			}
1286 			break;
1287 		}
1288 		z = PComponent(z)-> owner;
1289 	}
1290 	XUnmapWindow( DISP, X_WINDOW);
1291 }
1292 
1293 void
prima_send_cmSize(Handle self,Point oldSize)1294 prima_send_cmSize( Handle self, Point oldSize)
1295 {
1296 	DEFXX;
1297 	Event e;
1298 
1299 	bzero( &e, sizeof(e));
1300 	e. gen. source = self;
1301 	e. cmd = cmSize;
1302 	e. gen. R. left = oldSize. x;
1303 	e. gen. R. bottom = oldSize. y;
1304 	e. gen. P. x = e. gen. R. right = XX-> size. x;
1305 	e. gen. P. y = e. gen. R. top = XX-> size. y;
1306 	{
1307 		int i, y = XX-> size. y, count = PWidget( self)-> widgets. count;
1308 		for ( i = 0; i < count; i++) {
1309 			PWidget child = PWidget( PWidget( self)-> widgets. items[i]);
1310 			if ((( PWidget(child)-> growMode & gmDontCare) == 0) &&
1311 				( !X(child)-> flags. clip_owner || ( child-> owner == application))) {
1312 				XMoveWindow( DISP, child-> handle, X(child)-> origin.x, y - X(child)-> size.y - X(child)-> origin. y);
1313 			}
1314 		}
1315 	}
1316 	apc_message( self, &e, false);
1317 }
1318 
1319 Bool
apc_widget_set_size(Handle self,int width,int height)1320 apc_widget_set_size( Handle self, int width, int height)
1321 {
1322 	DEFXX;
1323 	Point sz = XX-> size;
1324 	PWidget widg = PWidget( self);
1325 	int x, y;
1326 
1327 	if ( XX-> type. window) {
1328 		Rect rc;
1329 		prima_get_frame_info( self, &rc);
1330 		return apc_window_set_client_size( self, width - rc. left - rc. right, height - rc. bottom - rc. top);
1331 	}
1332 
1333 	widg-> virtualSize. x = width;
1334 	widg-> virtualSize. y = height;
1335 
1336 	width = ( width >= widg-> sizeMin. x)
1337 			? (( width <= widg-> sizeMax. x)
1338 				? width
1339 				: widg-> sizeMax. x)
1340 			: widg-> sizeMin. x;
1341 
1342 	height = ( height >= widg-> sizeMin. y)
1343 			? (( height <= widg-> sizeMax. y)
1344 				? height
1345 				: widg-> sizeMax. y)
1346 			: widg-> sizeMin. y;
1347 
1348 	if ( XX-> parentHandle == NULL_HANDLE && XX-> size. x == width && XX-> size. y == height)
1349 		return true;
1350 
1351 	XX-> size. x = width;
1352 	XX-> size. y = height;
1353 
1354 	x = XX-> origin. x;
1355 	y = X(XX-> owner)-> size. y - XX-> size.y - XX-> origin. y;
1356 	if ( XX-> parentHandle) {
1357 		XWindow cld;
1358 		XTranslateCoordinates( DISP, PWidget(XX-> owner)-> handle, XX-> parentHandle, x, y, &x, &y, &cld);
1359 	}
1360 	if ( width != 0 && height != 0) {
1361 		if ( XX-> client != X_WINDOW)
1362 			XMoveResizeWindow( DISP, XX-> client, 0, XX-> menuHeight, width, height);
1363 		XMoveResizeWindow( DISP, X_WINDOW, x, y, width, height);
1364 		if ( XX-> flags. falsely_hidden) {
1365 			if ( XX-> flags. want_visible) XMapWindow( DISP, X_WINDOW);
1366 			XX-> flags. falsely_hidden = 0;
1367 		}
1368 	} else {
1369 		if ( XX-> flags. want_visible) apc_XUnmapWindow( self);
1370 		if ( XX-> client != X_WINDOW)
1371 			XMoveResizeWindow( DISP, XX-> client, 0, XX-> menuHeight, ( width == 0) ? 1 : width, ( height == 0) ? 1 : height);
1372 		XMoveResizeWindow( DISP, X_WINDOW, x, y, ( width == 0) ? 1 : width, ( height == 0) ? 1 : height);
1373 		XX-> flags. falsely_hidden = 1;
1374 	}
1375 	prima_send_cmSize( self, sz);
1376 	if ( PObject( self)-> stage == csDead) return false;
1377 	return true;
1378 }
1379 
1380 Bool
apc_widget_set_rect(Handle self,int x,int y,int width,int height)1381 apc_widget_set_rect( Handle self, int x, int y, int width, int height)
1382 {
1383 	DEFXX;
1384 	Point sz = XX-> size;
1385 	PWidget widg = PWidget( self);
1386 	Event e;
1387 
1388 	if ( XX-> type. window) {
1389 		Rect rc;
1390 		prima_get_frame_info( self, &rc);
1391 		return apc_window_set_client_rect( self, x + rc. left, y + rc. bottom,
1392 			width - rc. left - rc. right, height - rc. bottom - rc. top);
1393 	}
1394 
1395 	widg-> virtualSize. x = width;
1396 	widg-> virtualSize. y = height;
1397 
1398 	width = ( width >= widg-> sizeMin. x)
1399 			? (( width <= widg-> sizeMax. x)
1400 				? width
1401 				: widg-> sizeMax. x)
1402 			: widg-> sizeMin. x;
1403 
1404 	height = ( height >= widg-> sizeMin. y)
1405 			? (( height <= widg-> sizeMax. y)
1406 				? height
1407 				: widg-> sizeMax. y)
1408 			: widg-> sizeMin. y;
1409 
1410 	if ( XX-> parentHandle == NULL_HANDLE &&
1411 		XX-> size. x == width && XX-> size. y == height &&
1412 		x == XX-> origin.x && y == XX-> origin. y)
1413 		return true;
1414 
1415 	if ( XX-> client == guts. grab_redirect) {
1416 		XWindow rx;
1417 		XTranslateCoordinates( DISP, XX-> client, guts. root, 0, 0,
1418 			&guts. grab_translate_mouse.x, &guts. grab_translate_mouse.y, &rx);
1419 	}
1420 
1421 	XX-> size. x = width;
1422 	XX-> size. y = height;
1423 
1424 	bzero( &e, sizeof( e));
1425 	e. cmd = cmMove;
1426 	e. gen. source = self;
1427 	XX-> origin. x = e. gen. P. x = x;
1428 	XX-> origin. y = e. gen. P. y = y;
1429 	y = X(XX-> owner)-> size. y - height - XX-> origin. y;
1430 	if ( XX-> parentHandle) {
1431 		XWindow cld;
1432 		XTranslateCoordinates( DISP, PWidget(XX-> owner)-> handle, XX-> parentHandle, x, y, &x, &y, &cld);
1433 	}
1434 	if ( width != 0 && height != 0) {
1435 		if ( XX-> client != X_WINDOW)
1436 			XMoveResizeWindow( DISP, XX-> client, 0, XX-> menuHeight, width, height);
1437 		XMoveResizeWindow( DISP, X_WINDOW, x, y, width, height);
1438 		if ( XX-> flags. falsely_hidden) {
1439 			if ( XX-> flags. want_visible) XMapWindow( DISP, X_WINDOW);
1440 			XX-> flags. falsely_hidden = 0;
1441 		}
1442 	} else {
1443 		if ( XX-> flags. want_visible) apc_XUnmapWindow( self);
1444 		if ( XX-> client != X_WINDOW)
1445 			XMoveResizeWindow( DISP, XX-> client, 0, XX-> menuHeight, ( width == 0) ? 1 : width, ( height == 0) ? 1 : height);
1446 		XMoveResizeWindow( DISP, X_WINDOW, x, y, ( width == 0) ? 1 : width, ( height == 0) ? 1 : height);
1447 		XX-> flags. falsely_hidden = 1;
1448 	}
1449 	apc_message( self, &e, false);
1450 	if ( PObject( self)-> stage == csDead) return false;
1451 	prima_send_cmSize( self, sz);
1452 	if ( PObject( self)-> stage == csDead) return false;
1453 	if ( XX-> flags. transparent)
1454 		apc_widget_invalidate_rect( self, NULL);
1455 	return true;
1456 }
1457 
1458 Bool
apc_widget_set_size_bounds(Handle self,Point min,Point max)1459 apc_widget_set_size_bounds( Handle self, Point min, Point max)
1460 {
1461 	DEFXX;
1462 	if ( XX-> type. window) {
1463 		XSizeHints hints;
1464 		bzero( &hints, sizeof( hints));
1465 		apc_SetWMNormalHints( self, &hints);
1466 	}
1467 	return true;
1468 }
1469 
1470 Bool
apc_widget_set_visible(Handle self,Bool show)1471 apc_widget_set_visible( Handle self, Bool show)
1472 {
1473 	DEFXX;
1474 	int oldShow;
1475 	if ( XX-> type. window)
1476 		return apc_window_set_visible( self, show);
1477 
1478 	oldShow = XX-> flags. want_visible ? 1 : 0;
1479 	XX-> flags. want_visible = show;
1480 	if ( !XX-> flags. falsely_hidden) {
1481 		if ( show)
1482 			XMapWindow( DISP, X_WINDOW);
1483 		else
1484 			apc_XUnmapWindow( self);
1485 		XCHECKPOINT;
1486 	}
1487 	if ( oldShow != ( show ? 1 : 0))
1488 		prima_simple_message(self, show ? cmShow : cmHide, false);
1489 	return true;
1490 }
1491 
1492 Bool
apc_widget_set_z_order(Handle self,Handle behind,Bool top)1493 apc_widget_set_z_order( Handle self, Handle behind, Bool top)
1494 {
1495 	XWindow windoze[2];
1496 
1497 	/* top does not matter if behind is non-NULL */
1498 	if (behind) {
1499 		windoze[0] = PComponent(behind)->handle;
1500 		windoze[1] = X_WINDOW;
1501 		XRestackWindows( DISP, windoze, 2);
1502 		XCHECKPOINT;
1503 	} else if (top) {
1504 		XRaiseWindow( DISP, X_WINDOW);
1505 		XCHECKPOINT;
1506 	} else {
1507 		XLowerWindow( DISP, X_WINDOW);
1508 		XCHECKPOINT;
1509 	}
1510 
1511 	if ( X(self)-> type. window)
1512 		prima_wm_sync( self, ConfigureNotify);
1513 	else
1514 		prima_simple_message( self, cmZOrderChanged, false);
1515 	return true;
1516 }
1517 
1518 Bool
apc_widget_update(Handle self)1519 apc_widget_update( Handle self)
1520 {
1521 	DEFXX;
1522 
1523 	if ( XX-> invalid_region) {
1524 		if ( XX-> flags. paint_pending) {
1525 			TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
1526 			XX-> flags. paint_pending = false;
1527 		}
1528 		prima_simple_message( self, cmPaint, false);
1529 		XSync(DISP, false);
1530 	}
1531 	return true;
1532 }
1533 
1534 Bool
apc_widget_validate_rect(Handle self,Rect rect)1535 apc_widget_validate_rect( Handle self, Rect rect)
1536 {
1537 	XRectangle r;
1538 	DEFXX;
1539 	Region rgn;
1540 
1541 	SORT( rect. left,   rect. right);
1542 	SORT( rect. bottom, rect. top);
1543 
1544 
1545 	r. x = rect. left;
1546 	r. width = rect. right - rect. left;
1547 	r. y = XX-> size. y - rect. top;
1548 	r. height = rect. top - rect. bottom;
1549 
1550 	if ( !XX-> invalid_region)
1551 		return true;
1552 
1553 	if ( !( rgn = XCreateRegion()))
1554 		return false;
1555 
1556 	XUnionRectWithRegion( &r, rgn, rgn);
1557 	XSubtractRegion( XX-> invalid_region, rgn, XX-> invalid_region);
1558 	XDestroyRegion( rgn);
1559 
1560 	if ( XEmptyRegion( XX-> invalid_region)) {
1561 		if ( XX-> flags. paint_pending) {
1562 			TAILQ_REMOVE( &guts.paintq, XX, paintq_link);
1563 			XX-> flags. paint_pending = false;
1564 		}
1565 		XDestroyRegion( XX-> invalid_region);
1566 		XX-> invalid_region = NULL;
1567 	}
1568 	return true;
1569 }
1570 
1571