removed listbag added tree bag
[wmaker-crm.git] / WINGs / wview.c
blob15ad177aaed99e6dc884b98bb678f8b66d9f19f3
3 #include "WINGsP.h"
5 #include <X11/Xresource.h>
9 /* the notifications about views */
11 char *WMViewSizeDidChangeNotification = "WMViewSizeDidChangeNotification";
12 char *WMViewFocusDidChangeNotification = "WMViewFocusDidChangeNotification";
13 char *WMViewRealizedNotification = "WMViewRealizedNotification";
16 #define EVENT_MASK \
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 */
27 0, /* border_pixel */
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 */
37 None, /* colormap */
38 None /* cursor */
43 static XContext ViewContext=0; /* context for views */
48 W_View*
49 W_GetViewForXWindow(Display *display, Window window)
51 W_View *view;
53 if (XFindContext(display, window, ViewContext, (XPointer*)&view)==0) {
54 return view;
56 return NULL;
61 static void
62 unparentView(W_View *view)
64 /* remove from parent's children list */
65 if (view->parent!=NULL) {
66 W_View *ptr;
68 ptr = view->parent->childrenList;
69 if (ptr == view) {
70 view->parent->childrenList = view->nextSister;
71 } else {
72 while (ptr!=NULL) {
73 if (ptr->nextSister == view) {
74 ptr->nextSister = view->nextSister;
75 break;
77 ptr = ptr->nextSister;
81 view->parent = NULL;
85 static void
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;
93 } else {
94 W_View *ptr;
96 ptr = view->childrenList;
97 while (ptr->nextSister!=NULL)
98 ptr = ptr->nextSister;
99 ptr->nextSister = child;
101 child->parent = view;
105 static W_View*
106 createView(W_Screen *screen, W_View *parent)
108 W_View *view;
110 if (ViewContext==0)
111 ViewContext = XUniqueContext();
113 view = wmalloc(sizeof(W_View));
114 memset(view, 0, sizeof(W_View));
116 view->refCount = 1;
118 view->screen = screen;
120 if (parent!=NULL) {
121 /* attributes are not valid for root window */
122 view->attribFlags = CWEventMask|CWBitGravity;
123 view->attribs = defAtts;
125 view->attribFlags |= CWBackPixel|CWColormap|CWBorderPixel;
126 view->attribs.background_pixel = W_PIXEL(screen->gray);
127 view->attribs.border_pixel = W_PIXEL(screen->black);
128 view->attribs.colormap = screen->colormap;
130 view->backColor = WMRetainColor(screen->gray);
132 adoptChildView(parent, view);
135 return view;
140 W_View*
141 W_CreateView(W_View *parent)
143 return createView(parent->screen, parent);
147 W_View*
148 W_CreateRootView(W_Screen *screen)
150 W_View *view;
152 view = createView(screen, NULL);
154 view->window = screen->rootWin;
156 view->flags.realized = 1;
157 view->flags.mapped = 1;
158 view->flags.root = 1;
160 view->size.width =
161 WidthOfScreen(ScreenOfDisplay(screen->display, screen->screen));
162 view->size.height =
163 HeightOfScreen(ScreenOfDisplay(screen->display, screen->screen));
165 return view;
169 W_View*
170 W_CreateTopView(W_Screen *screen)
172 W_View *view;
174 view = createView(screen, screen->rootView);
175 if (!view)
176 return NULL;
178 view->flags.topLevel = 1;
179 view->attribs.event_mask |= StructureNotifyMask;
181 return view;
186 void
187 W_RealizeView(W_View *view)
189 Window parentWID;
190 Display *dpy = view->screen->display;
191 W_View *ptr;
193 assert(view->size.width > 0);
194 assert(view->size.height > 0);
197 if (view->parent && !view->parent->flags.realized) {
198 wwarning("trying to realize widget of unrealized parent");
199 return;
202 if (!view->flags.realized) {
203 parentWID = view->parent->window;
204 view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
205 view->size.width, view->size.height, 0,
206 view->screen->depth, InputOutput,
207 view->screen->visual, view->attribFlags,
208 &view->attribs);
210 XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
212 view->flags.realized = 1;
214 if (view->flags.mapWhenRealized) {
215 W_MapView(view);
216 view->flags.mapWhenRealized = 0;
219 WMPostNotificationName(WMViewRealizedNotification, view, NULL);
222 /* realize children */
223 ptr = view->childrenList;
224 while (ptr!=NULL) {
225 W_RealizeView(ptr);
227 ptr = ptr->nextSister;
232 void
233 W_ReparentView(W_View *view, W_View *newParent, int x, int y)
235 Display *dpy = view->screen->display;
237 assert(!view->flags.topLevel);
239 unparentView(view);
240 adoptChildView(newParent, view);
242 if (view->flags.realized) {
243 if (newParent->flags.realized) {
244 XReparentWindow(dpy, view->window, newParent->window, x, y);
245 } else {
246 wwarning("trying to reparent realized view to unrealized parent");
247 return;
251 view->pos.x = x;
252 view->pos.y = y;
257 void
258 W_MapView(W_View *view)
260 if (!view->flags.mapped) {
261 if (view->flags.realized) {
262 XMapRaised(view->screen->display, view->window);
263 XFlush(view->screen->display);
264 view->flags.mapped = 1;
265 } else {
266 view->flags.mapWhenRealized = 1;
273 * W_MapSubviews-
274 * maps all children of the current view that where already realized.
276 void
277 W_MapSubviews(W_View *view)
279 XMapSubwindows(view->screen->display, view->window);
280 XFlush(view->screen->display);
282 view = view->childrenList;
283 while (view) {
284 view->flags.mapped = 1;
285 view->flags.mapWhenRealized = 0;
286 view = view->nextSister;
292 void
293 W_UnmapSubviews(W_View *view)
295 XUnmapSubwindows(view->screen->display, view->window);
296 XFlush(view->screen->display);
298 view = view->childrenList;
299 while (view) {
300 view->flags.mapped = 0;
301 view->flags.mapWhenRealized = 0;
302 view = view->nextSister;
308 void
309 W_UnmapView(W_View *view)
311 view->flags.mapWhenRealized = 0;
312 if (!view->flags.mapped)
313 return;
315 XUnmapWindow(view->screen->display, view->window);
316 XFlush(view->screen->display);
318 view->flags.mapped = 0;
322 W_View*
323 W_TopLevelOfView(W_View *view)
325 W_View *toplevel;
327 for (toplevel=view; !toplevel->flags.topLevel; toplevel=toplevel->parent);
329 return toplevel;
333 static void
334 destroyView(W_View *view)
336 W_View *ptr;
338 if (view->flags.alreadyDead)
339 return;
340 view->flags.alreadyDead = 1;
342 /* delete the balloon text for the view, if there's any */
343 WMSetBalloonTextForView(NULL, view);
345 if (view->nextFocusChain)
346 view->nextFocusChain->prevFocusChain = view->prevFocusChain;
347 if (view->prevFocusChain)
348 view->prevFocusChain->nextFocusChain = view->nextFocusChain;
350 /* Do not leave focus in a inexisting control */
351 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
352 W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
354 if (view->flags.topLevel) {
355 W_FocusInfo *info = view->screen->focusInfo;
356 /* remove focus information associated to this toplevel */
358 if (info) {
359 if (info->toplevel==view) {
360 view->screen->focusInfo = info->next;
361 wfree(info);
362 } else {
363 while (info->next) {
364 if (info->next->toplevel == view)
365 break;
366 info = info->next;
368 if (info->next) {
369 W_FocusInfo *next = info->next->next;
370 wfree(info->next);
371 info->next = next;
373 /* else the toplevel did not have any focused subview */
378 /* destroy children recursively */
379 while (view->childrenList!=NULL) {
380 ptr = view->childrenList;
381 ptr->flags.parentDying = 1;
383 W_DestroyView(ptr);
385 if (ptr == view->childrenList) {
386 view->childrenList = ptr->nextSister;
387 ptr->parent = NULL;
391 W_CallDestroyHandlers(view);
393 if (view->flags.realized) {
394 XDeleteContext(view->screen->display, view->window, ViewContext);
396 /* if parent is being destroyed, it will die naturaly */
397 if (!view->flags.parentDying || view->flags.topLevel)
398 XDestroyWindow(view->screen->display, view->window);
401 /* remove self from parent's children list */
402 unparentView(view);
404 W_CleanUpEvents(view);
406 // WMUnregisterViewDraggedTypes(view);
408 #if 0
409 if (view->dragSourceProcs)
410 wfree(view->dragSourceProcs);
412 if (view->dragDestinationProcs)
413 wfree(view->dragDestinationProcs);
414 #endif
415 wfree(view);
420 void
421 W_DestroyView(W_View *view)
423 W_ReleaseView(view);
428 void
429 W_MoveView(W_View *view, int x, int y)
431 assert(view->flags.root==0);
433 if (view->delegate && view->delegate->willMove) {
434 (*view->delegate->willMove)(view->delegate, view, &x, &y);
437 if (view->pos.x == x && view->pos.y == y)
438 return;
440 if (view->flags.realized) {
441 XMoveWindow(view->screen->display, view->window, x, y);
443 view->pos.x = x;
444 view->pos.y = y;
446 if (view->delegate && view->delegate->didMove) {
447 (*view->delegate->didMove)(view->delegate, view);
452 void
453 W_ResizeView(W_View *view, unsigned int width, unsigned int height)
455 int shrinked;
457 if (view->delegate && view->delegate->willResize) {
458 (*view->delegate->willResize)(view->delegate, view, &width, &height);
461 assert(width > 0);
462 assert(height > 0);
464 if (view->size.width == width && view->size.height == height)
465 return;
467 shrinked = width < view->size.width || height < view->size.height;
469 if (view->flags.realized) {
470 XResizeWindow(view->screen->display, view->window, width, height);
472 view->size.width = width;
473 view->size.height = height;
475 if (view->delegate && view->delegate->didResize) {
476 (*view->delegate->didResize)(view->delegate, view);
479 if (view->flags.notifySizeChanged)
480 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
484 void
485 W_RedisplayView(W_View *view)
487 XEvent ev;
489 if (!view->flags.mapped)
490 return;
492 ev.xexpose.type = Expose;
493 ev.xexpose.display = view->screen->display;
494 ev.xexpose.window = view->window;
495 ev.xexpose.count = 0;
497 WMHandleEvent(&ev);
501 void
502 W_SetViewBackgroundColor(W_View *view, WMColor *color)
504 if (view->backColor)
505 WMReleaseColor(view->backColor);
506 view->backColor = WMRetainColor(color);
508 view->attribFlags |= CWBackPixel;
509 view->attribs.background_pixel = color->color.pixel;
510 if (view->flags.realized) {
511 XSetWindowBackground(view->screen->display, view->window,
512 color->color.pixel);
513 XClearWindow(view->screen->display, view->window);
519 W_View*
520 W_FocusedViewOfToplevel(W_View *view)
522 WMScreen *scr = view->screen;
523 W_FocusInfo *info;
525 for (info = scr->focusInfo; info!=NULL; info = info->next)
526 if (view == info->toplevel)
527 break;
529 if (!info)
530 return NULL;
532 return info->focused;
536 void
537 W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
539 WMScreen *scr = toplevel->screen;
540 XEvent event;
541 W_FocusInfo *info;
543 for (info = scr->focusInfo; info!=NULL; info = info->next)
544 if (toplevel == info->toplevel)
545 break;
547 if (!info) {
548 info = wmalloc(sizeof(W_FocusInfo));
549 info->toplevel = toplevel;
550 info->focused = view;
551 info->next = scr->focusInfo;
552 scr->focusInfo = info;
553 } else {
554 event.xfocus.mode = NotifyNormal;
555 event.xfocus.detail = NotifyDetailNone;
556 if (info->focused) {
557 /* simulate FocusOut event */
558 event.xfocus.type = FocusOut;
559 W_DispatchMessage(info->focused, &event);
561 info->focused = view;
563 if (view) {
564 /* simulate FocusIn event */
565 event.xfocus.type = FocusIn;
566 W_DispatchMessage(view, &event);
571 void
572 W_BroadcastMessage(W_View *targetParent, XEvent *event)
574 W_View *target;
576 target = targetParent->childrenList;
577 while (target!=NULL) {
578 W_DispatchMessage(target, event);
580 target = target->nextSister;
585 void
586 W_DispatchMessage(W_View *target, XEvent *event)
588 if (target->window==None)
589 return;
590 event->xclient.window = target->window;
591 event->xclient.display = target->screen->display;
593 WMHandleEvent(event);
595 XSendEvent(target->screen->display, target->window, False,
596 SubstructureNotifyMask, event);
602 WMView*
603 W_RetainView(WMView *view)
605 view->refCount++;
606 return view;
611 void
612 W_ReleaseView(WMView *view)
614 view->refCount--;
615 if (view->refCount < 1) {
616 destroyView(view);
621 WMWidget*
622 WMWidgetOfView(WMView *view)
624 return view->self;
628 WMSize
629 WMGetViewSize(WMView *view)
631 return view->size;
634 WMPoint
635 WMGetViewPosition(WMView *view)
637 return view->pos;
641 void
642 WMSetViewNotifySizeChanges(WMView *view, Bool flag)
644 view->flags.notifySizeChanged = flag;
647 Window
648 WMViewXID(WMView *view)
650 return view->window;
654 WMPoint
655 WMGetViewScreenPosition(WMView *view)
657 WMScreen *scr = W_VIEW_SCREEN(view);
658 Window foo;
659 int x, y;
661 XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(view),
662 scr->rootWin, 0, 0, &x, &y, &foo);
664 return wmkpoint(x, y);