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