Update for 0.52.0. This is a test version, which brings the Appearance
[wmaker-crm.git] / WINGs / wview.c
blob51f58436861cd14abadc5f876881b5aa0238e7c9
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 void
106 handleEvents(XEvent *event, void *data)
108 W_View *view = (W_View*)data;
110 if (event->type == ConfigureNotify) {
112 if (event->xconfigure.width != view->size.width
113 || event->xconfigure.height != view->size.height) {
115 view->size.width = event->xconfigure.width;
116 view->size.height = event->xconfigure.height;
118 if (view->flags.notifySizeChanged) {
119 WMPostNotificationName(WMViewSizeDidChangeNotification,
120 view, NULL);
123 if (event->xconfigure.x != view->pos.x
124 || event->xconfigure.y != view->pos.y) {
126 if (event->xconfigure.send_event) {
127 view->pos.x = event->xconfigure.x;
128 view->pos.y = event->xconfigure.y;
129 } else {
130 Window foo;
132 XTranslateCoordinates(view->screen->display,
133 view->window, view->screen->rootWin,
134 event->xconfigure.x, event->xconfigure.y,
135 &view->pos.x, &view->pos.y, &foo);
142 static W_View*
143 createView(W_Screen *screen, W_View *parent)
145 W_View *view;
147 if (ViewContext==0)
148 ViewContext = XUniqueContext();
150 view = wmalloc(sizeof(W_View));
151 memset(view, 0, sizeof(W_View));
153 view->refCount = 1;
155 view->screen = screen;
157 if (parent!=NULL) {
158 /* attributes are not valid for root window */
159 view->attribFlags = CWEventMask|CWBitGravity;
160 view->attribs = defAtts;
162 view->attribFlags |= CWBackPixel|CWColormap|CWBorderPixel;
163 view->attribs.background_pixel = W_PIXEL(screen->gray);
164 view->attribs.border_pixel = W_PIXEL(screen->black);
165 view->attribs.colormap = screen->colormap;
167 adoptChildView(parent, view);
170 return view;
175 W_View*
176 W_CreateView(W_View *parent)
178 return createView(parent->screen, parent);
182 W_View*
183 W_CreateRootView(W_Screen *screen)
185 W_View *view;
187 view = createView(screen, NULL);
189 view->window = screen->rootWin;
191 view->flags.realized = 1;
192 view->flags.mapped = 1;
193 view->flags.root = 1;
195 view->size.width =
196 WidthOfScreen(ScreenOfDisplay(screen->display, screen->screen));
197 view->size.height =
198 HeightOfScreen(ScreenOfDisplay(screen->display, screen->screen));
200 return view;
204 W_View*
205 W_CreateTopView(W_Screen *screen)
207 W_View *view;
209 view = createView(screen, screen->rootView);
210 if (!view)
211 return NULL;
213 view->flags.topLevel = 1;
214 view->attribs.event_mask |= StructureNotifyMask;
216 /* catch changes in the toplevel window (resize from user etc.) */
217 WMCreateEventHandler(view, StructureNotifyMask, handleEvents, view);
219 return view;
224 void
225 W_RealizeView(W_View *view)
227 Window parentWID;
228 Display *dpy = view->screen->display;
229 W_View *ptr;
231 assert(view->size.width > 0);
232 assert(view->size.height > 0);
235 if (view->parent && !view->parent->flags.realized) {
236 wwarning("trying to realize widget of unrealized parent");
237 return;
240 if (!view->flags.realized) {
241 parentWID = view->parent->window;
242 view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
243 view->size.width, view->size.height, 0,
244 view->screen->depth, InputOutput,
245 view->screen->visual, view->attribFlags,
246 &view->attribs);
248 XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
250 view->flags.realized = 1;
252 if (view->flags.mapWhenRealized) {
253 W_MapView(view);
254 view->flags.mapWhenRealized = 0;
257 WMPostNotificationName(WMViewRealizedNotification, view, NULL);
260 /* realize children */
261 ptr = view->childrenList;
262 while (ptr!=NULL) {
263 W_RealizeView(ptr);
265 ptr = ptr->nextSister;
271 Bool
272 W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event)
274 if (cev->message_type == scr->internalMessage
275 && cev->format == 32 && cev->data.l[1] == event)
276 return True;
277 else
278 return False;
282 void
283 W_ReparentView(W_View *view, W_View *newParent, int x, int y)
285 Display *dpy = view->screen->display;
287 assert(!view->flags.topLevel);
289 unparentView(view);
290 adoptChildView(newParent, view);
292 if (view->flags.realized) {
293 if (newParent->flags.realized) {
294 XReparentWindow(dpy, view->window, newParent->window, x, y);
295 } else {
296 wwarning("trying to reparent realized view to unrealized parent");
297 return;
301 view->pos.x = x;
302 view->pos.y = y;
307 void
308 W_MapView(W_View *view)
310 if (!view->flags.mapped) {
311 if (view->flags.realized) {
312 XMapRaised(view->screen->display, view->window);
313 XFlush(view->screen->display);
314 view->flags.mapped = 1;
315 } else {
316 view->flags.mapWhenRealized = 1;
323 * W_MapSubviews-
324 * maps all children of the current view that where already realized.
326 void
327 W_MapSubviews(W_View *view)
329 XMapSubwindows(view->screen->display, view->window);
330 XFlush(view->screen->display);
332 view = view->childrenList;
333 while (view) {
334 view->flags.mapped = 1;
335 view->flags.mapWhenRealized = 0;
336 view = view->nextSister;
342 void
343 W_UnmapSubviews(W_View *view)
345 XUnmapSubwindows(view->screen->display, view->window);
346 XFlush(view->screen->display);
348 view = view->childrenList;
349 while (view) {
350 view->flags.mapped = 0;
351 view->flags.mapWhenRealized = 0;
352 view = view->nextSister;
358 void
359 W_UnmapView(W_View *view)
361 view->flags.mapWhenRealized = 0;
362 if (!view->flags.mapped)
363 return;
365 XUnmapWindow(view->screen->display, view->window);
366 XFlush(view->screen->display);
368 view->flags.mapped = 0;
372 W_View*
373 W_TopLevelOfView(W_View *view)
375 W_View *toplevel;
377 for (toplevel=view; !toplevel->flags.topLevel; toplevel=toplevel->parent);
379 return toplevel;
383 static void
384 destroyView(W_View *view)
386 W_View *ptr;
388 if (view->flags.alreadyDead)
389 return;
390 view->flags.alreadyDead = 1;
392 if (view->nextFocusChain)
393 view->nextFocusChain->prevFocusChain = view->prevFocusChain;
394 if (view->prevFocusChain)
395 view->prevFocusChain->nextFocusChain = view->nextFocusChain;
397 /* Do not leave focus in a inexisting control */
398 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
399 W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
401 if (view->flags.topLevel) {
402 W_FocusInfo *info = view->screen->focusInfo;
403 /* remove focus information associated to this toplevel */
405 if (info) {
406 if (info->toplevel==view) {
407 view->screen->focusInfo = info->next;
408 free(info);
409 } else {
410 while (info->next) {
411 if (info->next->toplevel == view)
412 break;
413 info = info->next;
415 if (info->next) {
416 W_FocusInfo *next = info->next->next;
417 free(info->next);
418 info->next = next;
420 /* else the toplevel did not have any focused subview */
425 /* destroy children recursively */
426 while (view->childrenList!=NULL) {
427 ptr = view->childrenList;
428 ptr->flags.parentDying = 1;
430 W_DestroyView(ptr);
432 if (ptr == view->childrenList) {
433 view->childrenList = ptr->nextSister;
434 ptr->parent = NULL;
438 W_CallDestroyHandlers(view);
440 if (view->flags.realized) {
441 XDeleteContext(view->screen->display, view->window, ViewContext);
443 /* if parent is being destroyed, it will die naturaly */
444 if (!view->flags.parentDying || view->flags.topLevel)
445 XDestroyWindow(view->screen->display, view->window);
448 /* remove self from parent's children list */
449 unparentView(view);
451 W_CleanUpEvents(view);
452 #if 0
453 if (view->dragSourceProcs)
454 free(view->dragSourceProcs);
456 if (view->dragDestinationProcs)
457 free(view->dragDestinationProcs);
458 #endif
459 free(view);
464 void
465 W_DestroyView(W_View *view)
467 W_ReleaseView(view);
472 void
473 W_MoveView(W_View *view, int x, int y)
475 assert(view->flags.root==0);
477 if (view->pos.x == x && view->pos.y == y)
478 return;
480 if (view->flags.realized) {
481 XMoveWindow(view->screen->display, view->window, x, y);
483 view->pos.x = x;
484 view->pos.y = y;
488 void
489 W_ResizeView(W_View *view, unsigned int width, unsigned int height)
491 int shrinked;
493 assert(width > 0);
494 assert(height > 0);
496 if (view->size.width == width && view->size.height == height)
497 return;
499 shrinked = width < view->size.width || height < view->size.height;
501 if (view->flags.realized) {
502 XResizeWindow(view->screen->display, view->window, width, height);
504 view->size.width = width;
505 view->size.height = height;
507 if (view->flags.notifySizeChanged)
508 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
512 void
513 W_RedisplayView(W_View *view)
515 XEvent ev;
517 if (!view->flags.mapped)
518 return;
520 ev.xexpose.type = Expose;
521 ev.xexpose.display = view->screen->display;
522 ev.xexpose.window = view->window;
523 ev.xexpose.count = 0;
525 WMHandleEvent(&ev);
529 void
530 W_SetViewBackgroundColor(W_View *view, WMColor *color)
532 view->attribFlags |= CWBackPixel;
533 view->attribs.background_pixel = color->color.pixel;
534 if (view->flags.realized) {
535 XSetWindowBackground(view->screen->display, view->window,
536 color->color.pixel);
537 XClearWindow(view->screen->display, view->window);
543 W_View*
544 W_FocusedViewOfToplevel(W_View *view)
546 WMScreen *scr = view->screen;
547 W_FocusInfo *info;
549 for (info = scr->focusInfo; info!=NULL; info = info->next)
550 if (view == info->toplevel)
551 break;
553 if (!info)
554 return NULL;
556 return info->focused;
560 void
561 W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
563 WMScreen *scr = toplevel->screen;
564 XEvent event;
565 W_FocusInfo *info;
567 for (info = scr->focusInfo; info!=NULL; info = info->next)
568 if (toplevel == info->toplevel)
569 break;
571 if (!info) {
572 info = wmalloc(sizeof(W_FocusInfo));
573 info->toplevel = toplevel;
574 info->focused = view;
575 info->next = scr->focusInfo;
576 scr->focusInfo = info;
577 } else {
578 event.xfocus.mode = NotifyNormal;
579 event.xfocus.detail = NotifyDetailNone;
580 if (info->focused) {
581 /* simulate FocusOut event */
582 event.xfocus.type = FocusOut;
583 W_DispatchMessage(info->focused, &event);
585 info->focused = view;
587 if (view) {
588 /* simulate FocusIn event */
589 event.xfocus.type = FocusIn;
590 W_DispatchMessage(view, &event);
595 void
596 W_BroadcastMessage(W_View *targetParent, XEvent *event)
598 W_View *target;
600 target = targetParent->childrenList;
601 while (target!=NULL) {
602 W_DispatchMessage(target, event);
604 target = target->nextSister;
609 void
610 W_DispatchMessage(W_View *target, XEvent *event)
612 if (target->window==None)
613 return;
614 event->xclient.window = target->window;
615 event->xclient.display = target->screen->display;
617 WMHandleEvent(event);
619 XSendEvent(target->screen->display, target->window, False,
620 SubstructureNotifyMask, event);
626 WMView*
627 W_RetainView(WMView *view)
629 view->refCount++;
630 return view;
635 void
636 W_ReleaseView(WMView *view)
638 view->refCount--;
639 if (view->refCount < 1) {
640 destroyView(view);
645 WMWidget*
646 WMWidgetOfView(WMView *view)
648 return view->self;
652 WMSize
653 WMGetViewSize(WMView *view)
655 return view->size;
658 WMPoint
659 WMGetViewPosition(WMView *view)
661 return view->pos;
665 void
666 WMSetViewNotifySizeChanges(WMView *view, Bool flag)
668 view->flags.notifySizeChanged = flag;
671 Window
672 WMViewXID(WMView *view)
674 return view->window;