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
;
107 handleEvents(XEvent
*event
, void *data
)
109 W_View
*view
= (W_View
*)data
;
111 if (event
->type
== ConfigureNotify
) {
113 if (event
->xconfigure
.width
!= view
->size
.width
114 || event
->xconfigure
.height
!= view
->size
.height
) {
116 if (view
->flags
.notifySizeChanged
) {
117 view
->size
.width
= event
->xconfigure
.width
;
118 view
->size
.height
= event
->xconfigure
.height
;
119 WMPostNotificationName(WMViewSizeDidChangeNotification
,
128 createView(W_Screen
*screen
, W_View
*parent
)
133 ViewContext
= XUniqueContext();
135 view
= wmalloc(sizeof(W_View
));
136 memset(view
, 0, sizeof(W_View
));
140 view
->screen
= screen
;
143 /* attributes are not valid for root window */
144 view
->attribFlags
= CWEventMask
|CWBitGravity
;
145 view
->attribs
= defAtts
;
147 view
->attribFlags
|= CWBackPixel
|CWColormap
;
148 view
->attribs
.background_pixel
= W_PIXEL(screen
->gray
);
149 view
->attribs
.colormap
= screen
->colormap
;
151 adoptChildView(parent
, view
);
160 W_CreateView(W_View
*parent
)
162 return createView(parent
->screen
, parent
);
167 W_CreateRootView(W_Screen
*screen
)
171 view
= createView(screen
, NULL
);
173 view
->window
= screen
->rootWin
;
175 view
->flags
.realized
= 1;
176 view
->flags
.mapped
= 1;
177 view
->flags
.root
= 1;
180 WidthOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
182 HeightOfScreen(ScreenOfDisplay(screen
->display
, screen
->screen
));
189 W_CreateTopView(W_Screen
*screen
)
193 view
= createView(screen
, screen
->rootView
);
197 view
->flags
.topLevel
= 1;
198 view
->attribs
.event_mask
|= StructureNotifyMask
;
200 /* catch changes in the toplevel window (resize from user etc.) */
201 WMCreateEventHandler(view
, StructureNotifyMask
, handleEvents
, view
);
209 W_RealizeView(W_View
*view
)
212 Display
*dpy
= view
->screen
->display
;
215 assert(view
->size
.width
> 0);
216 assert(view
->size
.height
> 0);
219 if (view
->parent
&& !view
->parent
->flags
.realized
) {
220 wwarning("trying to realize widget of unrealized parent");
224 if (!view
->flags
.realized
) {
225 parentWID
= view
->parent
->window
;
226 view
->window
= XCreateWindow(dpy
, parentWID
, view
->pos
.x
, view
->pos
.y
,
227 view
->size
.width
, view
->size
.height
, 0,
228 view
->screen
->depth
, InputOutput
,
229 view
->screen
->visual
, view
->attribFlags
,
232 XSaveContext(dpy
, view
->window
, ViewContext
, (XPointer
)view
);
234 view
->flags
.realized
= 1;
236 if (view
->flags
.mapWhenRealized
) {
238 view
->flags
.mapWhenRealized
= 0;
241 WMPostNotificationName(WMViewRealizedNotification
, view
, NULL
);
244 /* realize children */
245 ptr
= view
->childrenList
;
249 ptr
= ptr
->nextSister
;
256 W_CheckInternalMessage(W_Screen
*scr
, XClientMessageEvent
*cev
, int event
)
258 if (cev
->message_type
== scr
->internalMessage
259 && cev
->format
== 32 && cev
->data
.l
[1] == event
)
267 W_ReparentView(W_View
*view
, W_View
*newParent
)
270 Display
*dpy
= view
->screen
->display
;
272 assert(!view
->flags
.topLevel
);
274 wasMapped
= view
->flags
.mapped
;
279 adoptChildView(newParent
, view
);
281 if (view
->flags
.realized
) {
282 if (newParent
->flags
.realized
) {
283 XReparentWindow(dpy
, view
->window
, newParent
->window
, 0, 0);
285 wwarning("trying to reparent realized view to unrealized parent");
300 W_MapView(W_View
*view
)
302 if (!view
->flags
.mapped
) {
303 if (view
->flags
.realized
) {
304 XMapRaised(view
->screen
->display
, view
->window
);
305 XFlush(view
->screen
->display
);
306 view
->flags
.mapped
= 1;
308 view
->flags
.mapWhenRealized
= 1;
316 * maps all children of the current view that where already realized.
319 W_MapSubviews(W_View
*view
)
321 XMapSubwindows(view
->screen
->display
, view
->window
);
322 XFlush(view
->screen
->display
);
324 view
= view
->childrenList
;
326 view
->flags
.mapped
= 1;
327 view
->flags
.mapWhenRealized
= 0;
328 view
= view
->nextSister
;
335 W_UnmapSubviews(W_View
*view
)
337 XUnmapSubwindows(view
->screen
->display
, view
->window
);
338 XFlush(view
->screen
->display
);
340 view
= view
->childrenList
;
342 view
->flags
.mapped
= 0;
343 view
->flags
.mapWhenRealized
= 0;
344 view
= view
->nextSister
;
351 W_UnmapView(W_View
*view
)
353 view
->flags
.mapWhenRealized
= 0;
354 if (!view
->flags
.mapped
)
357 XUnmapWindow(view
->screen
->display
, view
->window
);
358 XFlush(view
->screen
->display
);
360 view
->flags
.mapped
= 0;
365 W_TopLevelOfView(W_View
*view
)
369 for (toplevel
=view
; !toplevel
->flags
.topLevel
; toplevel
=toplevel
->parent
);
376 destroyView(W_View
*view
)
380 if (view
->flags
.alreadyDead
)
382 view
->flags
.alreadyDead
= 1;
384 /* Do not leave focus in a inexisting control */
385 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view
))==view
)
386 W_SetFocusOfTopLevel(W_TopLevelOfView(view
), NULL
);
388 if (view
->flags
.topLevel
) {
389 W_FocusInfo
*info
= view
->screen
->focusInfo
;
390 /* remove focus information associated to this toplevel */
393 if (info
->toplevel
==view
) {
394 view
->screen
->focusInfo
= info
->next
;
398 if (info
->next
->toplevel
== view
)
403 W_FocusInfo
*next
= info
->next
->next
;
407 /* else the toplevel did not have any focused subview */
412 /* destroy children recursively */
413 while (view
->childrenList
!=NULL
) {
414 ptr
= view
->childrenList
;
415 ptr
->flags
.parentDying
= 1;
419 if (ptr
== view
->childrenList
) {
420 view
->childrenList
= ptr
->nextSister
;
425 W_CallDestroyHandlers(view
);
427 if (view
->flags
.realized
) {
428 XDeleteContext(view
->screen
->display
, view
->window
, ViewContext
);
430 /* if parent is being destroyed, it will die naturaly */
431 if (!view
->flags
.parentDying
|| view
->flags
.topLevel
)
432 XDestroyWindow(view
->screen
->display
, view
->window
);
435 /* remove self from parent's children list */
438 W_CleanUpEvents(view
);
440 if (view
->dragSourceProcs
)
441 free(view
->dragSourceProcs
);
443 if (view
->dragDestinationProcs
)
444 free(view
->dragDestinationProcs
);
452 W_DestroyView(W_View
*view
)
460 W_MoveView(W_View
*view
, int x
, int y
)
462 assert(view
->flags
.root
==0);
464 if (view
->pos
.x
== x
&& view
->pos
.y
== y
)
467 if (view
->flags
.realized
) {
468 XMoveWindow(view
->screen
->display
, view
->window
, x
, y
);
476 W_ResizeView(W_View
*view
, unsigned int width
, unsigned int height
)
483 if (view
->size
.width
== width
&& view
->size
.height
== height
)
486 shrinked
= width
< view
->size
.width
|| height
< view
->size
.height
;
488 if (view
->flags
.realized
) {
489 XResizeWindow(view
->screen
->display
, view
->window
, width
, height
);
491 view
->size
.width
= width
;
492 view
->size
.height
= height
;
494 if (view
->flags
.notifySizeChanged
)
495 WMPostNotificationName(WMViewSizeDidChangeNotification
, view
, NULL
);
500 W_RedisplayView(W_View
*view
)
504 if (!view
->flags
.mapped
)
508 ev
.display
= view
->screen
->display
;
509 ev
.window
= view
->window
;
512 WMHandleEvent((XEvent
*)&ev
);
517 W_SetViewBackgroundColor(W_View
*view
, WMColor
*color
)
519 view
->attribFlags
|= CWBackPixel
;
520 view
->attribs
.background_pixel
= color
->color
.pixel
;
521 if (view
->flags
.realized
) {
522 XSetWindowBackground(view
->screen
->display
, view
->window
,
524 XClearWindow(view
->screen
->display
, view
->window
);
531 W_FocusedViewOfToplevel(W_View
*view
)
533 WMScreen
*scr
= view
->screen
;
536 for (info
= scr
->focusInfo
; info
!=NULL
; info
= info
->next
)
537 if (view
== info
->toplevel
)
543 return info
->focused
;
548 W_SetFocusOfTopLevel(W_View
*toplevel
, W_View
*view
)
550 WMScreen
*scr
= toplevel
->screen
;
554 for (info
= scr
->focusInfo
; info
!=NULL
; info
= info
->next
)
555 if (toplevel
== info
->toplevel
)
559 info
= wmalloc(sizeof(W_FocusInfo
));
560 info
->toplevel
= toplevel
;
561 info
->focused
= view
;
562 info
->next
= scr
->focusInfo
;
563 scr
->focusInfo
= info
;
565 event
.xfocus
.mode
= NotifyNormal
;
566 event
.xfocus
.detail
= NotifyDetailNone
;
568 /* simulate FocusOut event */
569 event
.xfocus
.type
= FocusOut
;
570 W_DispatchMessage(info
->focused
, &event
);
572 info
->focused
= view
;
575 /* simulate FocusIn event */
576 event
.xfocus
.type
= FocusIn
;
577 W_DispatchMessage(view
, &event
);
583 W_BroadcastMessage(W_View
*targetParent
, XEvent
*event
)
587 target
= targetParent
->childrenList
;
588 while (target
!=NULL
) {
589 W_DispatchMessage(target
, event
);
591 target
= target
->nextSister
;
597 W_DispatchMessage(W_View
*target
, XEvent
*event
)
599 if (target
->window
==None
)
601 event
->xclient
.window
= target
->window
;
602 event
->xclient
.display
= target
->screen
->display
;
604 WMHandleEvent(event
);
606 XSendEvent(target->screen->display, target->window, False,
607 SubstructureNotifyMask, event);
614 W_RetainView(WMView
*view
)
623 W_ReleaseView(WMView
*view
)
626 if (view
->refCount
< 1) {
633 WMWidgetOfView(WMView
*view
)
640 WMGetViewSize(WMView
*view
)
646 WMGetViewPosition(WMView
*view
)
653 WMSetViewNotifySizeChanges(WMView
*view
, Bool flag
)
655 view
->flags
.notifySizeChanged
= flag
;
659 WMViewXID(WMView
*view
)