- added WMGetLabelText()
[wmaker-crm.git] / WINGs / wview.c
blob60af77c5819749205086e1cd643e2d0f16ba20c5
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->screen = screen;
118 if (parent!=NULL) {
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);
133 view->eventHandlers = WMCreateBag(4);
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;
185 W_View*
186 W_CreateUnmanagedTopView(W_Screen *screen)
188 W_View *view;
190 view = createView(screen, screen->rootView);
191 if (!view)
192 return NULL;
194 view->flags.topLevel = 1;
195 view->attribs.event_mask |= StructureNotifyMask;
197 view->attribFlags |= CWOverrideRedirect;
198 view->attribs.override_redirect = True;
200 return view;
204 void
205 W_RealizeView(W_View *view)
207 Window parentWID;
208 Display *dpy = view->screen->display;
209 W_View *ptr;
211 assert(view->size.width > 0);
212 assert(view->size.height > 0);
215 if (view->parent && !view->parent->flags.realized) {
216 wwarning("trying to realize widget of unrealized parent");
217 return;
220 if (!view->flags.realized) {
221 parentWID = view->parent->window;
222 view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
223 view->size.width, view->size.height, 0,
224 view->screen->depth, InputOutput,
225 view->screen->visual, view->attribFlags,
226 &view->attribs);
228 XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
230 view->flags.realized = 1;
232 if (view->flags.mapWhenRealized) {
233 W_MapView(view);
234 view->flags.mapWhenRealized = 0;
237 WMPostNotificationName(WMViewRealizedNotification, view, NULL);
240 /* realize children */
241 ptr = view->childrenList;
242 while (ptr!=NULL) {
243 W_RealizeView(ptr);
245 ptr = ptr->nextSister;
250 void
251 W_ReparentView(W_View *view, W_View *newParent, int x, int y)
253 Display *dpy = view->screen->display;
255 assert(!view->flags.topLevel);
257 unparentView(view);
258 adoptChildView(newParent, view);
260 if (view->flags.realized) {
261 if (newParent->flags.realized) {
262 XReparentWindow(dpy, view->window, newParent->window, x, y);
263 } else {
264 wwarning("trying to reparent realized view to unrealized parent");
265 return;
269 view->pos.x = x;
270 view->pos.y = y;
274 void
275 W_RaiseView(W_View *view)
277 if (W_VIEW_REALIZED(view))
278 XRaiseWindow(W_VIEW_DISPLAY(view), W_VIEW_DRAWABLE(view));
283 void
284 W_LowerView(W_View *view)
286 if (W_VIEW_REALIZED(view))
287 XLowerWindow(W_VIEW_DISPLAY(view), W_VIEW_DRAWABLE(view));
292 void
293 W_MapView(W_View *view)
295 if (!view->flags.mapped) {
296 if (view->flags.realized) {
297 XMapRaised(view->screen->display, view->window);
298 XFlush(view->screen->display);
299 view->flags.mapped = 1;
300 } else {
301 view->flags.mapWhenRealized = 1;
308 * W_MapSubviews-
309 * maps all children of the current view that where already realized.
311 void
312 W_MapSubviews(W_View *view)
314 XMapSubwindows(view->screen->display, view->window);
315 XFlush(view->screen->display);
317 view = view->childrenList;
318 while (view) {
319 view->flags.mapped = 1;
320 view->flags.mapWhenRealized = 0;
321 view = view->nextSister;
327 void
328 W_UnmapSubviews(W_View *view)
330 XUnmapSubwindows(view->screen->display, view->window);
331 XFlush(view->screen->display);
333 view = view->childrenList;
334 while (view) {
335 view->flags.mapped = 0;
336 view->flags.mapWhenRealized = 0;
337 view = view->nextSister;
343 void
344 W_UnmapView(W_View *view)
346 view->flags.mapWhenRealized = 0;
347 if (!view->flags.mapped)
348 return;
350 XUnmapWindow(view->screen->display, view->window);
351 XFlush(view->screen->display);
353 view->flags.mapped = 0;
357 W_View*
358 W_TopLevelOfView(W_View *view)
360 W_View *toplevel;
362 for (toplevel=view;
363 toplevel && !toplevel->flags.topLevel;
364 toplevel=toplevel->parent);
366 return toplevel;
370 static void
371 destroyView(W_View *view)
373 W_View *ptr;
375 if (view->flags.alreadyDead)
376 return;
377 view->flags.alreadyDead = 1;
379 /* delete the balloon text for the view, if there's any */
380 WMSetBalloonTextForView(NULL, view);
382 if (view->nextFocusChain)
383 view->nextFocusChain->prevFocusChain = view->prevFocusChain;
384 if (view->prevFocusChain)
385 view->prevFocusChain->nextFocusChain = view->nextFocusChain;
387 /* Do not leave focus in a inexisting control */
388 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
389 W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
391 if (view->flags.topLevel) {
392 W_FocusInfo *info = view->screen->focusInfo;
393 /* remove focus information associated to this toplevel */
395 if (info) {
396 if (info->toplevel==view) {
397 view->screen->focusInfo = info->next;
398 wfree(info);
399 } else {
400 while (info->next) {
401 if (info->next->toplevel == view)
402 break;
403 info = info->next;
405 if (info->next) {
406 W_FocusInfo *next = info->next->next;
407 wfree(info->next);
408 info->next = next;
410 /* else the toplevel did not have any focused subview */
415 /* destroy children recursively */
416 while (view->childrenList!=NULL) {
417 ptr = view->childrenList;
418 ptr->flags.parentDying = 1;
420 W_DestroyView(ptr);
422 if (ptr == view->childrenList) {
423 view->childrenList = ptr->nextSister;
424 ptr->parent = NULL;
428 W_CallDestroyHandlers(view);
430 if (view->flags.realized) {
431 XDeleteContext(view->screen->display,
432 view->window, ViewContext);
434 /* if parent is being destroyed, it will die naturaly */
435 if (!view->flags.parentDying || view->flags.topLevel)
436 XDestroyWindow(view->screen->display, view->window);
439 /* remove self from parent's children list */
440 unparentView(view);
442 W_CleanUpEvents(view);
444 WMFreeBag(view->eventHandlers);
445 view->eventHandlers = NULL;
447 WMUnregisterViewDraggedTypes(view);
449 #if 0
450 if (view->dragSourceProcs)
451 wfree(view->dragSourceProcs);
453 if (view->dragDestinationProcs)
454 wfree(view->dragDestinationProcs);
456 if (scr->dragInfo.destView == view) {
457 scr->dragInfo.destView = NULL;
459 #endif
460 wfree(view);
465 void
466 W_DestroyView(W_View *view)
468 if (view->refCount == 0)
469 destroyView(view);
474 void
475 W_MoveView(W_View *view, int x, int y)
477 assert(view->flags.root==0);
479 if (view->delegate && view->delegate->willMove) {
480 (*view->delegate->willMove)(view->delegate, view, &x, &y);
483 if (view->pos.x == x && view->pos.y == y)
484 return;
486 if (view->flags.realized) {
487 XMoveWindow(view->screen->display, view->window, x, y);
489 view->pos.x = x;
490 view->pos.y = y;
492 if (view->delegate && view->delegate->didMove) {
493 (*view->delegate->didMove)(view->delegate, view);
498 void
499 W_ResizeView(W_View *view, unsigned int width, unsigned int height)
501 int shrinked;
503 if (view->delegate && view->delegate->willResize) {
504 (*view->delegate->willResize)(view->delegate, view, &width, &height);
507 assert(width > 0);
508 assert(height > 0);
510 if (view->size.width == width && view->size.height == height)
511 return;
513 shrinked = width < view->size.width || height < view->size.height;
515 if (view->flags.realized) {
516 XResizeWindow(view->screen->display, view->window, width, height);
518 view->size.width = width;
519 view->size.height = height;
521 if (view->delegate && view->delegate->didResize) {
522 (*view->delegate->didResize)(view->delegate, view);
525 if (view->flags.notifySizeChanged)
526 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
530 void
531 W_RedisplayView(W_View *view)
533 XEvent ev;
535 if (!view->flags.mapped)
536 return;
538 ev.xexpose.type = Expose;
539 ev.xexpose.display = view->screen->display;
540 ev.xexpose.window = view->window;
541 ev.xexpose.count = 0;
543 WMHandleEvent(&ev);
547 void
548 W_SetViewBackgroundColor(W_View *view, WMColor *color)
550 if (view->backColor)
551 WMReleaseColor(view->backColor);
552 view->backColor = WMRetainColor(color);
554 view->attribFlags |= CWBackPixel;
555 view->attribs.background_pixel = color->color.pixel;
556 if (view->flags.realized) {
557 XSetWindowBackground(view->screen->display, view->window,
558 color->color.pixel);
559 XClearWindow(view->screen->display, view->window);
565 W_View*
566 W_FocusedViewOfToplevel(W_View *view)
568 WMScreen *scr = view->screen;
569 W_FocusInfo *info;
571 for (info = scr->focusInfo; info!=NULL; info = info->next)
572 if (view == info->toplevel)
573 break;
575 if (!info)
576 return NULL;
578 return info->focused;
582 void
583 W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
585 WMScreen *scr = toplevel->screen;
586 XEvent event;
587 W_FocusInfo *info;
589 for (info = scr->focusInfo; info!=NULL; info = info->next)
590 if (toplevel == info->toplevel)
591 break;
593 if (!info) {
594 info = wmalloc(sizeof(W_FocusInfo));
595 info->toplevel = toplevel;
596 info->focused = view;
597 info->next = scr->focusInfo;
598 scr->focusInfo = info;
599 } else {
600 event.xfocus.mode = NotifyNormal;
601 event.xfocus.detail = NotifyDetailNone;
602 if (info->focused) {
603 /* simulate FocusOut event */
604 event.xfocus.type = FocusOut;
605 W_DispatchMessage(info->focused, &event);
607 info->focused = view;
609 if (view) {
610 /* simulate FocusIn event */
611 event.xfocus.type = FocusIn;
612 W_DispatchMessage(view, &event);
617 void
618 W_BroadcastMessage(W_View *targetParent, XEvent *event)
620 W_View *target;
622 target = targetParent->childrenList;
623 while (target!=NULL) {
624 W_DispatchMessage(target, event);
626 target = target->nextSister;
631 void
632 W_DispatchMessage(W_View *target, XEvent *event)
634 if (target->window==None)
635 return;
636 event->xclient.window = target->window;
637 event->xclient.display = target->screen->display;
639 WMHandleEvent(event);
641 XSendEvent(target->screen->display, target->window, False,
642 SubstructureNotifyMask, event);
648 WMView*
649 W_RetainView(WMView *view)
651 view->refCount++;
653 return view;
658 void
659 W_ReleaseView(WMView *view)
661 view->refCount--;
663 if (view->refCount < 0) {
664 destroyView(view);
669 WMWidget*
670 WMWidgetOfView(WMView *view)
672 return view->self;
676 WMSize
677 WMGetViewSize(WMView *view)
679 return view->size;
682 WMPoint
683 WMGetViewPosition(WMView *view)
685 return view->pos;
689 void
690 WMSetViewNotifySizeChanges(WMView *view, Bool flag)
692 view->flags.notifySizeChanged = flag;
695 Window
696 WMViewXID(WMView *view)
698 return view->window;
702 WMPoint
703 WMGetViewScreenPosition(WMView *view)
705 WMScreen *scr = W_VIEW_SCREEN(view);
706 Window foo;
707 int x, y;
709 XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(view),
710 scr->rootWin, 0, 0, &x, &y, &foo);
712 return wmkpoint(x, y);