5 #include <X11/Xresource.h>
9 /* the notifications about views */
11 char *WMViewSizeDidChangeNotification
= "WMViewSizeDidChangeNotification";
12 char *WMViewFocusDidChangeNotification
= "WMViewFocusDidChangeNotification";
13 char *WMViewRealizedNotification
= "WMViewRealizedNotification";
17 KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
18 EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
19 VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|\
20 SubstructureNotifyMask|SubstructureRedirectMask
23 static XSetWindowAttributes defAtts
= {
24 None
, /* background_pixmap */
25 0, /* background_pixel */
26 CopyFromParent
, /* border_pixmap */
28 ForgetGravity
, /* bit_gravity */
29 ForgetGravity
, /* win_gravity */
30 NotUseful
, /* backing_store */
31 (unsigned) ~0, /* backing_planes */
32 0, /* backing_pixel */
33 False
, /* save_under */
34 EVENT_MASK
, /* event_mask */
35 0, /* do_not_propagate_mask */
36 False
, /* override_redirect */
43 static XContext ViewContext
=0; /* context for views */
49 W_GetViewForXWindow(Display
*display
, Window window
)
53 if (XFindContext(display
, window
, ViewContext
, (XPointer
*)&view
)==0) {
62 unparentView(W_View
*view
)
64 /* remove from parent's children list */
65 if (view
->parent
!=NULL
) {
68 ptr
= view
->parent
->childrenList
;
70 view
->parent
->childrenList
= view
->nextSister
;
73 if (ptr
->nextSister
== view
) {
74 ptr
->nextSister
= view
->nextSister
;
77 ptr
= ptr
->nextSister
;
86 adoptChildView(W_View
*view
, W_View
*child
)
88 child
->nextSister
= NULL
;
90 /* add to end of children list of parent */
91 if (view
->childrenList
== NULL
) {
92 view
->childrenList
= child
;
96 ptr
= view
->childrenList
;
97 while (ptr
->nextSister
!=NULL
)
98 ptr
= ptr
->nextSister
;
99 ptr
->nextSister
= child
;
101 child
->parent
= view
;
106 createView(W_Screen
*screen
, W_View
*parent
)
111 ViewContext
= XUniqueContext();
113 view
= wmalloc(sizeof(W_View
));
114 memset(view
, 0, sizeof(W_View
));
116 view
->screen
= screen
;
119 /* attributes are not valid for root window */
120 view
->attribFlags
= CWEventMask
|CWBitGravity
;
121 view
->attribs
= defAtts
;
123 view
->attribFlags
|= CWBackPixel
|CWColormap
|CWBorderPixel
;
124 view
->attribs
.background_pixel
= W_PIXEL(screen
->gray
);
125 view
->attribs
.border_pixel
= W_PIXEL(screen
->black
);
126 view
->attribs
.colormap
= screen
->colormap
;
128 view
->backColor
= WMRetainColor(screen
->gray
);
130 adoptChildView(parent
, view
);
135 view
->eventHandlers
= WMCreateArrayWithDestructor(4, wfree
);
143 W_CreateView(W_View
*parent
)
145 return createView(parent
->screen
, parent
);
150 W_CreateRootView(W_Screen
*screen
)
154 view
= createView(screen
, NULL
);
156 view
->window
= screen
->rootWin
;
158 view
->flags
.realized
= 1;
159 view
->flags
.mapped
= 1;
160 view
->flags
.root
= 1;
163 WidthOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
165 HeightOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
172 W_CreateTopView(W_Screen
*screen
)
176 view
= createView(screen
, screen
->rootView
);
180 view
->flags
.topLevel
= 1;
181 view
->attribs
.event_mask
|= StructureNotifyMask
;
188 W_CreateUnmanagedTopView(W_Screen
*screen
)
192 view
= createView(screen
, screen
->rootView
);
196 view
->flags
.topLevel
= 1;
197 view
->attribs
.event_mask
|= StructureNotifyMask
;
199 view
->attribFlags
|= CWOverrideRedirect
;
200 view
->attribs
.override_redirect
= True
;
207 W_RealizeView(W_View
*view
)
210 Display
*dpy
= view
->screen
->display
;
213 assert(view
->size
.width
> 0);
214 assert(view
->size
.height
> 0);
217 if (view
->parent
&& !view
->parent
->flags
.realized
) {
218 wwarning("trying to realize widget of unrealized parent");
222 if (!view
->flags
.realized
) {
223 parentWID
= view
->parent
->window
;
224 view
->window
= XCreateWindow(dpy
, parentWID
, view
->pos
.x
, view
->pos
.y
,
225 view
->size
.width
, view
->size
.height
, 0,
226 view
->screen
->depth
, InputOutput
,
227 view
->screen
->visual
, view
->attribFlags
,
230 XSaveContext(dpy
, view
->window
, ViewContext
, (XPointer
)view
);
232 view
->flags
.realized
= 1;
234 if (view
->flags
.mapWhenRealized
) {
236 view
->flags
.mapWhenRealized
= 0;
239 WMPostNotificationName(WMViewRealizedNotification
, view
, NULL
);
242 /* realize children */
243 ptr
= view
->childrenList
;
247 ptr
= ptr
->nextSister
;
253 W_ReparentView(W_View
*view
, W_View
*newParent
, int x
, int y
)
255 Display
*dpy
= view
->screen
->display
;
257 assert(!view
->flags
.topLevel
);
260 adoptChildView(newParent
, view
);
262 if (view
->flags
.realized
) {
263 if (newParent
->flags
.realized
) {
264 XReparentWindow(dpy
, view
->window
, newParent
->window
, x
, y
);
266 wwarning("trying to reparent realized view to unrealized parent");
277 W_RaiseView(W_View
*view
)
279 if (W_VIEW_REALIZED(view
))
280 XRaiseWindow(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
));
286 W_LowerView(W_View
*view
)
288 if (W_VIEW_REALIZED(view
))
289 XLowerWindow(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
));
295 W_MapView(W_View
*view
)
297 if (!view
->flags
.mapped
) {
298 if (view
->flags
.realized
) {
299 XMapRaised(view
->screen
->display
, view
->window
);
300 XFlush(view
->screen
->display
);
301 view
->flags
.mapped
= 1;
303 view
->flags
.mapWhenRealized
= 1;
311 * maps all children of the current view that where already realized.
314 W_MapSubviews(W_View
*view
)
316 XMapSubwindows(view
->screen
->display
, view
->window
);
317 XFlush(view
->screen
->display
);
319 view
= view
->childrenList
;
321 view
->flags
.mapped
= 1;
322 view
->flags
.mapWhenRealized
= 0;
323 view
= view
->nextSister
;
330 W_UnmapSubviews(W_View
*view
)
332 XUnmapSubwindows(view
->screen
->display
, view
->window
);
333 XFlush(view
->screen
->display
);
335 view
= view
->childrenList
;
337 view
->flags
.mapped
= 0;
338 view
->flags
.mapWhenRealized
= 0;
339 view
= view
->nextSister
;
346 W_UnmapView(W_View
*view
)
348 view
->flags
.mapWhenRealized
= 0;
349 if (!view
->flags
.mapped
)
352 XUnmapWindow(view
->screen
->display
, view
->window
);
353 XFlush(view
->screen
->display
);
355 view
->flags
.mapped
= 0;
360 W_TopLevelOfView(W_View
*view
)
365 toplevel
&& !toplevel
->flags
.topLevel
;
366 toplevel
=toplevel
->parent
);
373 destroyView(W_View
*view
)
377 if (view
->flags
.alreadyDead
)
379 view
->flags
.alreadyDead
= 1;
381 /* delete the balloon text for the view, if there's any */
382 WMSetBalloonTextForView(NULL
, view
);
384 if (view
->nextFocusChain
)
385 view
->nextFocusChain
->prevFocusChain
= view
->prevFocusChain
;
386 if (view
->prevFocusChain
)
387 view
->prevFocusChain
->nextFocusChain
= view
->nextFocusChain
;
389 /* Do not leave focus in a inexisting control */
390 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view
))==view
)
391 W_SetFocusOfTopLevel(W_TopLevelOfView(view
), NULL
);
393 if (view
->flags
.topLevel
) {
394 W_FocusInfo
*info
= view
->screen
->focusInfo
;
395 /* remove focus information associated to this toplevel */
398 if (info
->toplevel
==view
) {
399 view
->screen
->focusInfo
= info
->next
;
403 if (info
->next
->toplevel
== view
)
408 W_FocusInfo
*next
= info
->next
->next
;
412 /* else the toplevel did not have any focused subview */
417 /* destroy children recursively */
418 while (view
->childrenList
!=NULL
) {
419 ptr
= view
->childrenList
;
420 ptr
->flags
.parentDying
= 1;
424 if (ptr
== view
->childrenList
) {
425 view
->childrenList
= ptr
->nextSister
;
430 W_CallDestroyHandlers(view
);
432 if (view
->flags
.realized
) {
433 XDeleteContext(view
->screen
->display
,
434 view
->window
, ViewContext
);
436 /* if parent is being destroyed, it will die naturaly */
437 if (!view
->flags
.parentDying
|| view
->flags
.topLevel
)
438 XDestroyWindow(view
->screen
->display
, view
->window
);
441 /* remove self from parent's children list */
444 /* the array has a wfree() destructor that will be called automatically */
445 WMFreeArray(view
->eventHandlers
);
446 view
->eventHandlers
= NULL
;
448 WMRemoveNotificationObserver(view
);
450 W_FreeViewXdndPart(view
);
458 W_DestroyView(W_View
*view
)
462 if (view
->refCount
< 1) {
470 W_MoveView(W_View
*view
, int x
, int y
)
472 assert(view
->flags
.root
==0);
474 if (view
->delegate
&& view
->delegate
->willMove
) {
475 (*view
->delegate
->willMove
)(view
->delegate
, view
, &x
, &y
);
478 if (view
->pos
.x
== x
&& view
->pos
.y
== y
)
481 if (view
->flags
.realized
) {
482 XMoveWindow(view
->screen
->display
, view
->window
, x
, y
);
487 if (view
->delegate
&& view
->delegate
->didMove
) {
488 (*view
->delegate
->didMove
)(view
->delegate
, view
);
494 W_ResizeView(W_View
*view
, unsigned int width
, unsigned int height
)
498 if (view
->delegate
&& view
->delegate
->willResize
) {
499 (*view
->delegate
->willResize
)(view
->delegate
, view
, &width
, &height
);
505 if (view
->size
.width
== width
&& view
->size
.height
== height
)
508 /*shrinked = width < view->size.width || height < view->size.height;*/
510 if (view
->flags
.realized
) {
511 XResizeWindow(view
->screen
->display
, view
->window
, width
, height
);
513 view
->size
.width
= width
;
514 view
->size
.height
= height
;
516 if (view
->delegate
&& view
->delegate
->didResize
) {
517 (*view
->delegate
->didResize
)(view
->delegate
, view
);
520 /* // TODO. replace in WINGs code, with the didResize delegate */
521 if (view
->flags
.notifySizeChanged
)
522 WMPostNotificationName(WMViewSizeDidChangeNotification
, view
, NULL
);
527 W_RedisplayView(W_View
*view
)
531 if (!view
->flags
.mapped
)
534 ev
.xexpose
.type
= Expose
;
535 ev
.xexpose
.display
= view
->screen
->display
;
536 ev
.xexpose
.window
= view
->window
;
537 ev
.xexpose
.count
= 0;
539 ev
.xexpose
.serial
= 0;
546 W_SetViewBackgroundColor(W_View
*view
, WMColor
*color
)
549 WMReleaseColor(view
->backColor
);
550 view
->backColor
= WMRetainColor(color
);
552 view
->attribFlags
|= CWBackPixel
;
553 view
->attribs
.background_pixel
= W_PIXEL(color
);
554 if (view
->flags
.realized
) {
555 XSetWindowBackground(view
->screen
->display
, view
->window
,
557 XClearWindow(view
->screen
->display
, view
->window
);
563 W_SetViewCursor(W_View
*view
, Cursor cursor
)
565 view
->cursor
= cursor
;
566 if (W_VIEW_REALIZED(view
)) {
567 XDefineCursor(W_VIEW_DISPLAY(view
), W_VIEW_DRAWABLE(view
), cursor
);
569 view
->attribFlags
|= CWCursor
;
570 view
->attribs
.cursor
= cursor
;
576 W_FocusedViewOfToplevel(W_View
*view
)
578 WMScreen
*scr
= view
->screen
;
581 for (info
= scr
->focusInfo
; info
!=NULL
; info
= info
->next
)
582 if (view
== info
->toplevel
)
588 return info
->focused
;
593 W_SetFocusOfTopLevel(W_View
*toplevel
, W_View
*view
)
595 WMScreen
*scr
= toplevel
->screen
;
599 for (info
= scr
->focusInfo
; info
!=NULL
; info
= info
->next
)
600 if (toplevel
== info
->toplevel
)
604 info
= wmalloc(sizeof(W_FocusInfo
));
605 info
->toplevel
= toplevel
;
606 info
->focused
= view
;
607 info
->next
= scr
->focusInfo
;
608 scr
->focusInfo
= info
;
610 event
.xfocus
.mode
= NotifyNormal
;
611 event
.xfocus
.detail
= NotifyDetailNone
;
613 /* simulate FocusOut event */
614 event
.xfocus
.type
= FocusOut
;
615 W_DispatchMessage(info
->focused
, &event
);
617 info
->focused
= view
;
620 /* simulate FocusIn event */
621 event
.xfocus
.type
= FocusIn
;
622 W_DispatchMessage(view
, &event
);
628 W_BroadcastMessage(W_View
*targetParent
, XEvent
*event
)
632 target
= targetParent
->childrenList
;
633 while (target
!=NULL
) {
634 W_DispatchMessage(target
, event
);
636 target
= target
->nextSister
;
642 W_DispatchMessage(W_View
*target
, XEvent
*event
)
644 if (target
->window
==None
)
646 event
->xclient
.window
= target
->window
;
647 event
->xclient
.display
= target
->screen
->display
;
649 WMHandleEvent(event
);
651 XSendEvent(target->screen->display, target->window, False,
652 SubstructureNotifyMask, event);
659 W_RetainView(WMView
*view
)
668 W_ReleaseView(WMView
*view
)
672 if (view
->refCount
< 1) {
679 WMWidgetOfView(WMView
*view
)
686 WMGetViewSize(WMView
*view
)
692 WMGetViewPosition(WMView
*view
)
699 WMSetViewNotifySizeChanges(WMView
*view
, Bool flag
)
701 view
->flags
.notifySizeChanged
= ((flag
==0) ? 0 : 1);
706 WMViewXID(WMView
*view
)
713 WMGetViewScreenPosition(WMView
*view
)
715 WMScreen
*scr
= W_VIEW_SCREEN(view
);
717 int x
, y
, topX
, topY
, bar
;
721 while (topView
->parent
&& topView
->parent
!=scr
->rootView
)
722 topView
= topView
->parent
;
724 if (!XGetGeometry(scr
->display
, W_VIEW_DRAWABLE(topView
), &foo
, &topX
,
725 &topY
, &bar
, &bar
, &bar
, &bar
)) {
729 XTranslateCoordinates(scr
->display
, W_VIEW_DRAWABLE(view
),
730 scr
->rootWin
, 0, 0, &x
, &y
, &foo
);
732 return wmkpoint(x
-topX
, y
-topY
);
737 resizedParent(void *self
, WMNotification
*notif
)
739 WMSize size
= WMGetViewSize((WMView
*)WMGetNotificationObject(notif
));
740 WMView
*view
= (WMView
*)self
;
742 W_MoveView(view
, view
->leftOffs
, view
->topOffs
);
743 W_ResizeView(view
, size
.width
- (view
->leftOffs
+ view
->rightOffs
),
744 size
.height
- (view
->topOffs
+ view
->bottomOffs
));
749 WMSetViewExpandsToParent(WMView
*view
, int leftOffs
, int topOffs
,
750 int rightOffs
, int bottomOffs
)
752 WMSize size
= view
->parent
->size
;
754 view
->topOffs
= topOffs
;
755 view
->bottomOffs
= bottomOffs
;
756 view
->leftOffs
= leftOffs
;
757 view
->rightOffs
= rightOffs
;
759 WMAddNotificationObserver(resizedParent
, view
,
760 WMViewSizeDidChangeNotification
,
762 WMSetViewNotifySizeChanges(view
->parent
, True
);
764 W_MoveView(view
, leftOffs
, topOffs
);
765 W_ResizeView(view
, size
.width
- (leftOffs
+ rightOffs
),
766 size
.height
- (topOffs
+ bottomOffs
));