4 #include <cairo-xlib.h>
6 #include <X11/Xresource.h>
8 /* the notifications about views */
10 char *WMViewSizeDidChangeNotification
= "WMViewSizeDidChangeNotification";
11 char *WMViewFocusDidChangeNotification
= "WMViewFocusDidChangeNotification";
12 char *WMViewRealizedNotification
= "WMViewRealizedNotification";
15 KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
16 EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
17 VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|\
18 SubstructureNotifyMask|SubstructureRedirectMask
20 static XSetWindowAttributes defAtts
= {
21 None
, /* background_pixmap */
22 0, /* background_pixel */
23 CopyFromParent
, /* border_pixmap */
25 ForgetGravity
, /* bit_gravity */
26 ForgetGravity
, /* win_gravity */
27 NotUseful
, /* backing_store */
28 (unsigned)~0, /* backing_planes */
29 0, /* backing_pixel */
30 False
, /* save_under */
31 EVENT_MASK
, /* event_mask */
32 0, /* do_not_propagate_mask */
33 False
, /* override_redirect */
38 static XContext ViewContext
= 0; /* context for views */
40 W_View
*W_GetViewForXWindow(Display
* display
, Window window
)
44 if (XFindContext(display
, window
, ViewContext
, (XPointer
*) & view
) == 0) {
50 static void unparentView(W_View
* view
)
52 /* remove from parent's children list */
53 if (view
->parent
!= NULL
) {
56 ptr
= view
->parent
->childrenList
;
58 view
->parent
->childrenList
= view
->nextSister
;
61 if (ptr
->nextSister
== view
) {
62 ptr
->nextSister
= view
->nextSister
;
65 ptr
= ptr
->nextSister
;
72 static void adoptChildView(W_View
* view
, W_View
* child
)
74 child
->nextSister
= NULL
;
76 /* add to end of children list of parent */
77 if (view
->childrenList
== NULL
) {
78 view
->childrenList
= child
;
82 ptr
= view
->childrenList
;
83 while (ptr
->nextSister
!= NULL
)
84 ptr
= ptr
->nextSister
;
85 ptr
->nextSister
= child
;
90 static W_View
*createView(W_Screen
* screen
, W_View
* parent
)
95 ViewContext
= XUniqueContext();
97 view
= wmalloc(sizeof(W_View
));
98 memset(view
, 0, sizeof(W_View
));
100 view
->screen
= screen
;
102 view
->backColor
= WMGrayColorSpec();
106 xcolor
.red
= view
->backColor
.red
<< 8;
107 xcolor
.green
= view
->backColor
.green
<< 8;
108 xcolor
.blue
= view
->backColor
.blue
<< 8;
109 xcolor
.flags
= DoRed
| DoGreen
| DoBlue
;
110 XAllocColor(screen
->display
,screen
->colormap
,&xcolor
);
112 /* attributes are not valid for root window */
113 view
->attribFlags
= CWEventMask
|CWBitGravity
;
114 view
->attribs
= defAtts
;
116 view
->attribFlags
|= CWBackPixel
|CWColormap
|CWBorderPixel
;
117 view
->attribs
.background_pixel
= xcolor
.pixel
;
118 view
->attribs
.border_pixel
= 0;
119 view
->attribs
.colormap
= screen
->colormap
;
121 adoptChildView(parent
, view
);
128 view
->eventHandlers
= WMCreateArrayWithDestructor(4, wfree
);
133 W_View
*W_CreateView(W_View
* parent
)
135 return createView(parent
->screen
, parent
);
138 W_View
*W_CreateRootView(W_Screen
* screen
)
142 view
= createView(screen
, NULL
);
144 view
->window
= screen
->rootWin
;
146 view
->flags
.realized
= 1;
147 view
->flags
.mapped
= 1;
148 view
->flags
.root
= 1;
150 view
->size
.width
= WidthOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
151 view
->size
.height
= HeightOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
156 W_View
*W_CreateTopView(W_Screen
* screen
)
160 view
= createView(screen
, screen
->rootView
);
164 view
->flags
.topLevel
= 1;
165 view
->attribs
.event_mask
|= StructureNotifyMask
;
170 W_View
*W_CreateUnmanagedTopView(W_Screen
* screen
)
174 view
= createView(screen
, screen
->rootView
);
178 view
->flags
.topLevel
= 1;
179 view
->attribs
.event_mask
|= StructureNotifyMask
;
181 view
->attribFlags
|= CWOverrideRedirect
;
182 view
->attribs
.override_redirect
= True
;
187 void W_RealizeView(W_View
* view
)
190 Display
*dpy
= view
->screen
->display
;
193 assert(view
->size
.width
> 0);
194 assert(view
->size
.height
> 0);
196 if (view
->parent
&& !view
->parent
->flags
.realized
) {
197 wwarning("trying to realize widget of unrealized parent");
201 if (!view
->flags
.realized
) {
202 parentWID
= view
->parent
->window
;
203 view
->window
= XCreateWindow(dpy
, parentWID
, view
->pos
.x
, view
->pos
.y
,
204 view
->size
.width
, view
->size
.height
, 0,
205 view
->screen
->depth
, InputOutput
,
206 view
->screen
->visual
, view
->attribFlags
, &view
->attribs
);
208 XSaveContext(dpy
, view
->window
, ViewContext
, (XPointer
) view
);
210 view
->flags
.realized
= 1;
212 if (view
->flags
.mapWhenRealized
) {
214 view
->flags
.mapWhenRealized
= 0;
217 WMPostNotificationName(WMViewRealizedNotification
, view
, NULL
);
220 /* realize children */
221 ptr
= view
->childrenList
;
222 while (ptr
!= NULL
) {
225 ptr
= ptr
->nextSister
;
229 void W_ReparentView(W_View
* view
, W_View
* newParent
, int x
, int y
)
231 Display
*dpy
= view
->screen
->display
;
233 assert(!view
->flags
.topLevel
);
236 adoptChildView(newParent
, view
);
237 if (view
->flags
.realized
) {
238 if (newParent
->flags
.realized
) {
239 XReparentWindow(dpy
, view
->window
, newParent
->window
, x
, y
);
241 wwarning("trying to reparent realized view to unrealized parent");
250 void W_RaiseView(W_View
* view
)
252 if (W_VIEW_REALIZED(view
))
253 XRaiseWindow(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
));
256 void W_LowerView(W_View
* view
)
258 if (W_VIEW_REALIZED(view
))
259 XLowerWindow(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
));
262 void W_MapView(W_View
* view
)
264 if (!view
->flags
.mapped
) {
265 if (view
->flags
.realized
) {
266 XMapRaised(view
->screen
->display
, view
->window
);
267 XFlush(view
->screen
->display
);
268 view
->flags
.mapped
= 1;
270 view
->flags
.mapWhenRealized
= 1;
277 * maps all children of the current view that where already realized.
279 void W_MapSubviews(W_View
* view
)
281 XMapSubwindows(view
->screen
->display
, view
->window
);
282 XFlush(view
->screen
->display
);
284 view
= view
->childrenList
;
286 view
->flags
.mapped
= 1;
287 view
->flags
.mapWhenRealized
= 0;
288 view
= view
->nextSister
;
292 void W_UnmapSubviews(W_View
* view
)
294 XUnmapSubwindows(view
->screen
->display
, view
->window
);
295 XFlush(view
->screen
->display
);
297 view
= view
->childrenList
;
299 view
->flags
.mapped
= 0;
300 view
->flags
.mapWhenRealized
= 0;
301 view
= view
->nextSister
;
305 void W_UnmapView(W_View
* view
)
307 view
->flags
.mapWhenRealized
= 0;
308 if (!view
->flags
.mapped
)
311 XUnmapWindow(view
->screen
->display
, view
->window
);
312 XFlush(view
->screen
->display
);
314 view
->flags
.mapped
= 0;
317 W_View
*W_TopLevelOfView(W_View
* view
)
321 for (toplevel
= view
; toplevel
&& !toplevel
->flags
.topLevel
; toplevel
= toplevel
->parent
) ;
326 static void destroyView(W_View
* view
)
330 if (view
->flags
.alreadyDead
)
332 view
->flags
.alreadyDead
= 1;
334 /* delete the balloon text for the view, if there's any */
335 WMSetBalloonTextForView(NULL
, view
);
337 if (view
->nextFocusChain
)
338 view
->nextFocusChain
->prevFocusChain
= view
->prevFocusChain
;
339 if (view
->prevFocusChain
)
340 view
->prevFocusChain
->nextFocusChain
= view
->nextFocusChain
;
342 /* Do not leave focus in a inexisting control */
343 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view
)) == view
)
344 W_SetFocusOfTopLevel(W_TopLevelOfView(view
), NULL
);
346 if (view
->flags
.topLevel
) {
347 W_FocusInfo
*info
= view
->screen
->focusInfo
;
348 /* remove focus information associated to this toplevel */
351 if (info
->toplevel
== view
) {
352 view
->screen
->focusInfo
= info
->next
;
356 if (info
->next
->toplevel
== view
)
361 W_FocusInfo
*next
= info
->next
->next
;
365 /* else the toplevel did not have any focused subview */
370 /* destroy children recursively */
371 while (view
->childrenList
!= NULL
) {
372 ptr
= view
->childrenList
;
373 ptr
->flags
.parentDying
= 1;
377 if (ptr
== view
->childrenList
) {
378 view
->childrenList
= ptr
->nextSister
;
384 W_CallDestroyHandlers(view
);
386 if (view
->flags
.realized
) {
387 XDeleteContext(view
->screen
->display
, view
->window
, ViewContext
);
389 /* if parent is being destroyed, it will die naturaly */
390 if (!view
->flags
.parentDying
|| view
->flags
.topLevel
)
391 XDestroyWindow(view
->screen
->display
, view
->window
);
394 /* remove self from parent's children list */
397 /* the array has a wfree() destructor that will be called automatically */
398 WMFreeArray(view
->eventHandlers
);
399 view
->eventHandlers
= NULL
;
401 WMRemoveNotificationObserver(view
);
403 W_FreeViewXdndPart(view
);
408 cairo_t
* W_CreateCairoForView(W_View
*view
)
410 cairo_surface_t
*surface
;
413 surface
= cairo_xlib_surface_create(W_VIEW_DISPLAY(view
),
414 W_VIEW_DRAWABLE(view
),
415 W_VIEW_SCREEN(view
)->visual
,
417 W_VIEW_HEIGHT(view
));
418 cairo
= cairo_create(surface
);
419 cairo_surface_destroy(surface
);
420 cairo_translate(cairo
, 0.5, 0.5);
421 cairo_set_line_width(cairo
, 1.0);
426 void W_DestroyView(W_View
* view
)
430 if (view
->refCount
< 1) {
435 void W_MoveView(W_View
* view
, int x
, int y
)
437 assert(view
->flags
.root
== 0);
439 if (view
->delegate
&& view
->delegate
->willMove
) {
440 (*view
->delegate
->willMove
) (view
->delegate
, view
, &x
, &y
);
443 if (view
->pos
.x
== x
&& view
->pos
.y
== y
)
446 if (view
->flags
.realized
) {
447 XMoveWindow(view
->screen
->display
, view
->window
, x
, y
);
452 if (view
->delegate
&& view
->delegate
->didMove
) {
453 (*view
->delegate
->didMove
) (view
->delegate
, view
);
457 void W_ResizeView(W_View
* view
, unsigned int width
, unsigned int height
)
461 if (view
->delegate
&& view
->delegate
->willResize
) {
462 (*view
->delegate
->willResize
) (view
->delegate
, view
, &width
, &height
);
468 if (view
->size
.width
== width
&& view
->size
.height
== height
)
471 /*shrinked = width < view->size.width || height < view->size.height; */
473 if (view
->flags
.realized
) {
474 XResizeWindow(view
->screen
->display
, view
->window
, width
, height
);
476 view
->size
.width
= width
;
477 view
->size
.height
= height
;
479 if (view
->delegate
&& view
->delegate
->didResize
) {
480 (*view
->delegate
->didResize
) (view
->delegate
, view
);
483 /* // TODO. replace in WINGs code, with the didResize delegate */
484 if (view
->flags
.notifySizeChanged
)
485 WMPostNotificationName(WMViewSizeDidChangeNotification
, view
, NULL
);
488 void W_RedisplayView(W_View
* view
)
492 if (!view
->flags
.mapped
)
495 ev
.xexpose
.type
= Expose
;
496 ev
.xexpose
.display
= view
->screen
->display
;
497 ev
.xexpose
.window
= view
->window
;
498 ev
.xexpose
.count
= 0;
500 ev
.xexpose
.serial
= 0;
505 void W_SetViewBackgroundColor(W_View
*view
, WMColorSpec
*color
)
507 // XColor xcolor= WMCreateColorWithSpec(view->screen, color);
509 // view->backColor = *color;
511 // view->attribFlags |= CWBackPixel;
512 // view->attribs.background_pixel = W_PIXEL(xcolor);
513 // if (view->flags.realized) {
514 // XSetWindowBackground(view->screen->display, view->window,
516 // XClearWindow(view->screen->display, view->window);
518 // WMReleaseColor(xcolor);
521 void W_SetViewCursor(W_View
* view
, Cursor cursor
)
523 view
->cursor
= cursor
;
524 if (W_VIEW_REALIZED(view
)) {
525 XDefineCursor(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
), cursor
);
527 view
->attribFlags
|= CWCursor
;
528 view
->attribs
.cursor
= cursor
;
532 W_View
*W_FocusedViewOfToplevel(W_View
* view
)
534 WMScreen
*scr
= view
->screen
;
537 for (info
= scr
->focusInfo
; info
!= NULL
; info
= info
->next
)
538 if (view
== info
->toplevel
)
544 return info
->focused
;
547 void W_SetFocusOfTopLevel(W_View
* toplevel
, W_View
* view
)
549 WMScreen
*scr
= toplevel
->screen
;
553 for (info
= scr
->focusInfo
; info
!= NULL
; info
= info
->next
)
554 if (toplevel
== info
->toplevel
)
558 info
= wmalloc(sizeof(W_FocusInfo
));
559 info
->toplevel
= toplevel
;
560 info
->focused
= view
;
561 info
->next
= scr
->focusInfo
;
562 scr
->focusInfo
= info
;
564 event
.xfocus
.mode
= NotifyNormal
;
565 event
.xfocus
.detail
= NotifyDetailNone
;
567 /* simulate FocusOut event */
568 event
.xfocus
.type
= FocusOut
;
569 W_DispatchMessage(info
->focused
, &event
);
571 info
->focused
= view
;
574 /* simulate FocusIn event */
575 event
.xfocus
.type
= FocusIn
;
576 W_DispatchMessage(view
, &event
);
580 void W_BroadcastMessage(W_View
* targetParent
, XEvent
* event
)
584 target
= targetParent
->childrenList
;
585 while (target
!= NULL
) {
586 W_DispatchMessage(target
, event
);
588 target
= target
->nextSister
;
592 void W_DispatchMessage(W_View
* target
, XEvent
* event
)
594 if (target
->window
== None
)
596 event
->xclient
.window
= target
->window
;
597 event
->xclient
.display
= target
->screen
->display
;
599 WMHandleEvent(event
);
601 XSendEvent(target->screen->display, target->window, False,
602 SubstructureNotifyMask, event);
606 WMView
*W_RetainView(WMView
* view
)
613 void W_ReleaseView(WMView
* view
)
617 if (view
->refCount
< 1) {
622 WMWidget
*WMWidgetOfView(WMView
* view
)
627 WMSize
WMGetViewSize(WMView
* view
)
632 WMPoint
WMGetViewPosition(WMView
* view
)
637 void WMSetViewNotifySizeChanges(WMView
* view
, Bool flag
)
639 view
->flags
.notifySizeChanged
= ((flag
== 0) ? 0 : 1);
642 Window
WMViewXID(WMView
* view
)
647 WMPoint
WMGetViewScreenPosition(WMView
* view
)
649 WMScreen
*scr
= W_VIEW_SCREEN(view
);
651 int x
, y
, topX
, topY
;
656 while (topView
->parent
&& topView
->parent
!= scr
->rootView
)
657 topView
= topView
->parent
;
659 if (!XGetGeometry(scr
->display
, W_VIEW_DRAWABLE(topView
), &foo
, &topX
, &topY
, &bar
, &bar
, &bar
, &bar
)) {
663 XTranslateCoordinates(scr
->display
, W_VIEW_DRAWABLE(view
), scr
->rootWin
, 0, 0, &x
, &y
, &foo
);
665 return wmkpoint(x
- topX
, y
- topY
);
668 static void resizedParent(void *self
, WMNotification
* notif
)
670 WMSize size
= WMGetViewSize((WMView
*) WMGetNotificationObject(notif
));
671 WMView
*view
= (WMView
*) self
;
673 W_MoveView(view
, view
->leftOffs
, view
->topOffs
);
674 W_ResizeView(view
, size
.width
- (view
->leftOffs
+ view
->rightOffs
),
675 size
.height
- (view
->topOffs
+ view
->bottomOffs
));
678 void WMSetViewExpandsToParent(WMView
* view
, int leftOffs
, int topOffs
, int rightOffs
, int bottomOffs
)
680 WMSize size
= view
->parent
->size
;
682 view
->topOffs
= topOffs
;
683 view
->bottomOffs
= bottomOffs
;
684 view
->leftOffs
= leftOffs
;
685 view
->rightOffs
= rightOffs
;
687 WMAddNotificationObserver(resizedParent
, view
, WMViewSizeDidChangeNotification
, view
->parent
);
688 WMSetViewNotifySizeChanges(view
->parent
, True
);
690 W_MoveView(view
, leftOffs
, topOffs
);
691 W_ResizeView(view
, size
.width
- (leftOffs
+ rightOffs
), size
.height
- (topOffs
+ bottomOffs
));