GNOME mouseclickproxy thing fix
[wmaker-crm.git] / WINGs / wview.c
bloba5964e1e83e81e9eb90a993368ce97b365bf55d3
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 adoptChildView(parent, view);
133 return view;
138 W_View*
139 W_CreateView(W_View *parent)
141 return createView(parent->screen, parent);
145 W_View*
146 W_CreateRootView(W_Screen *screen)
148 W_View *view;
150 view = createView(screen, NULL);
152 view->window = screen->rootWin;
154 view->flags.realized = 1;
155 view->flags.mapped = 1;
156 view->flags.root = 1;
158 view->size.width =
159 WidthOfScreen(ScreenOfDisplay(screen->display, screen->screen));
160 view->size.height =
161 HeightOfScreen(ScreenOfDisplay(screen->display, screen->screen));
163 return view;
167 W_View*
168 W_CreateTopView(W_Screen *screen)
170 W_View *view;
172 view = createView(screen, screen->rootView);
173 if (!view)
174 return NULL;
176 view->flags.topLevel = 1;
177 view->attribs.event_mask |= StructureNotifyMask;
179 return view;
184 void
185 W_RealizeView(W_View *view)
187 Window parentWID;
188 Display *dpy = view->screen->display;
189 W_View *ptr;
191 assert(view->size.width > 0);
192 assert(view->size.height > 0);
195 if (view->parent && !view->parent->flags.realized) {
196 wwarning("trying to realize widget of unrealized parent");
197 return;
200 if (!view->flags.realized) {
201 parentWID = view->parent->window;
202 view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
203 view->size.width, view->size.height, 0,
204 view->screen->depth, InputOutput,
205 view->screen->visual, view->attribFlags,
206 &view->attribs);
208 XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
210 view->flags.realized = 1;
212 if (view->flags.mapWhenRealized) {
213 W_MapView(view);
214 view->flags.mapWhenRealized = 0;
217 WMPostNotificationName(WMViewRealizedNotification, view, NULL);
220 /* realize children */
221 ptr = view->childrenList;
222 while (ptr!=NULL) {
223 W_RealizeView(ptr);
225 ptr = ptr->nextSister;
231 Bool
232 W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event)
234 if (cev->message_type == scr->internalMessage
235 && cev->format == 32 && cev->data.l[1] == event)
236 return True;
237 else
238 return False;
242 void
243 W_ReparentView(W_View *view, W_View *newParent, int x, int y)
245 Display *dpy = view->screen->display;
247 assert(!view->flags.topLevel);
249 unparentView(view);
250 adoptChildView(newParent, view);
252 if (view->flags.realized) {
253 if (newParent->flags.realized) {
254 XReparentWindow(dpy, view->window, newParent->window, x, y);
255 } else {
256 wwarning("trying to reparent realized view to unrealized parent");
257 return;
261 view->pos.x = x;
262 view->pos.y = y;
267 void
268 W_MapView(W_View *view)
270 if (!view->flags.mapped) {
271 if (view->flags.realized) {
272 XMapRaised(view->screen->display, view->window);
273 XFlush(view->screen->display);
274 view->flags.mapped = 1;
275 } else {
276 view->flags.mapWhenRealized = 1;
283 * W_MapSubviews-
284 * maps all children of the current view that where already realized.
286 void
287 W_MapSubviews(W_View *view)
289 XMapSubwindows(view->screen->display, view->window);
290 XFlush(view->screen->display);
292 view = view->childrenList;
293 while (view) {
294 view->flags.mapped = 1;
295 view->flags.mapWhenRealized = 0;
296 view = view->nextSister;
302 void
303 W_UnmapSubviews(W_View *view)
305 XUnmapSubwindows(view->screen->display, view->window);
306 XFlush(view->screen->display);
308 view = view->childrenList;
309 while (view) {
310 view->flags.mapped = 0;
311 view->flags.mapWhenRealized = 0;
312 view = view->nextSister;
318 void
319 W_UnmapView(W_View *view)
321 view->flags.mapWhenRealized = 0;
322 if (!view->flags.mapped)
323 return;
325 XUnmapWindow(view->screen->display, view->window);
326 XFlush(view->screen->display);
328 view->flags.mapped = 0;
332 W_View*
333 W_TopLevelOfView(W_View *view)
335 W_View *toplevel;
337 for (toplevel=view; !toplevel->flags.topLevel; toplevel=toplevel->parent);
339 return toplevel;
343 static void
344 destroyView(W_View *view)
346 W_View *ptr;
348 if (view->flags.alreadyDead)
349 return;
350 view->flags.alreadyDead = 1;
352 /* delete the balloon text for the view, if there's any */
353 WMSetBalloonTextForView(NULL, view);
355 if (view->nextFocusChain)
356 view->nextFocusChain->prevFocusChain = view->prevFocusChain;
357 if (view->prevFocusChain)
358 view->prevFocusChain->nextFocusChain = view->nextFocusChain;
360 /* Do not leave focus in a inexisting control */
361 if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
362 W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
364 if (view->flags.topLevel) {
365 W_FocusInfo *info = view->screen->focusInfo;
366 /* remove focus information associated to this toplevel */
368 if (info) {
369 if (info->toplevel==view) {
370 view->screen->focusInfo = info->next;
371 free(info);
372 } else {
373 while (info->next) {
374 if (info->next->toplevel == view)
375 break;
376 info = info->next;
378 if (info->next) {
379 W_FocusInfo *next = info->next->next;
380 free(info->next);
381 info->next = next;
383 /* else the toplevel did not have any focused subview */
388 /* destroy children recursively */
389 while (view->childrenList!=NULL) {
390 ptr = view->childrenList;
391 ptr->flags.parentDying = 1;
393 W_DestroyView(ptr);
395 if (ptr == view->childrenList) {
396 view->childrenList = ptr->nextSister;
397 ptr->parent = NULL;
401 W_CallDestroyHandlers(view);
403 if (view->flags.realized) {
404 XDeleteContext(view->screen->display, view->window, ViewContext);
406 /* if parent is being destroyed, it will die naturaly */
407 if (!view->flags.parentDying || view->flags.topLevel)
408 XDestroyWindow(view->screen->display, view->window);
411 /* remove self from parent's children list */
412 unparentView(view);
414 W_CleanUpEvents(view);
415 #if 0
416 if (view->dragSourceProcs)
417 free(view->dragSourceProcs);
419 if (view->dragDestinationProcs)
420 free(view->dragDestinationProcs);
421 #endif
422 free(view);
427 void
428 W_DestroyView(W_View *view)
430 W_ReleaseView(view);
435 void
436 W_MoveView(W_View *view, int x, int y)
438 assert(view->flags.root==0);
440 if (view->pos.x == x && view->pos.y == y)
441 return;
443 if (view->flags.realized) {
444 XMoveWindow(view->screen->display, view->window, x, y);
446 view->pos.x = x;
447 view->pos.y = y;
451 void
452 W_ResizeView(W_View *view, unsigned int width, unsigned int height)
454 int shrinked;
456 assert(width > 0);
457 assert(height > 0);
459 if (view->size.width == width && view->size.height == height)
460 return;
462 shrinked = width < view->size.width || height < view->size.height;
464 if (view->flags.realized) {
465 XResizeWindow(view->screen->display, view->window, width, height);
467 view->size.width = width;
468 view->size.height = height;
470 if (view->flags.notifySizeChanged)
471 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
475 void
476 W_RedisplayView(W_View *view)
478 XEvent ev;
480 if (!view->flags.mapped)
481 return;
483 ev.xexpose.type = Expose;
484 ev.xexpose.display = view->screen->display;
485 ev.xexpose.window = view->window;
486 ev.xexpose.count = 0;
488 WMHandleEvent(&ev);
492 void
493 W_SetViewBackgroundColor(W_View *view, WMColor *color)
495 view->attribFlags |= CWBackPixel;
496 view->attribs.background_pixel = color->color.pixel;
497 if (view->flags.realized) {
498 XSetWindowBackground(view->screen->display, view->window,
499 color->color.pixel);
500 XClearWindow(view->screen->display, view->window);
506 W_View*
507 W_FocusedViewOfToplevel(W_View *view)
509 WMScreen *scr = view->screen;
510 W_FocusInfo *info;
512 for (info = scr->focusInfo; info!=NULL; info = info->next)
513 if (view == info->toplevel)
514 break;
516 if (!info)
517 return NULL;
519 return info->focused;
523 void
524 W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
526 WMScreen *scr = toplevel->screen;
527 XEvent event;
528 W_FocusInfo *info;
530 for (info = scr->focusInfo; info!=NULL; info = info->next)
531 if (toplevel == info->toplevel)
532 break;
534 if (!info) {
535 info = wmalloc(sizeof(W_FocusInfo));
536 info->toplevel = toplevel;
537 info->focused = view;
538 info->next = scr->focusInfo;
539 scr->focusInfo = info;
540 } else {
541 event.xfocus.mode = NotifyNormal;
542 event.xfocus.detail = NotifyDetailNone;
543 if (info->focused) {
544 /* simulate FocusOut event */
545 event.xfocus.type = FocusOut;
546 W_DispatchMessage(info->focused, &event);
548 info->focused = view;
550 if (view) {
551 /* simulate FocusIn event */
552 event.xfocus.type = FocusIn;
553 W_DispatchMessage(view, &event);
558 void
559 W_BroadcastMessage(W_View *targetParent, XEvent *event)
561 W_View *target;
563 target = targetParent->childrenList;
564 while (target!=NULL) {
565 W_DispatchMessage(target, event);
567 target = target->nextSister;
572 void
573 W_DispatchMessage(W_View *target, XEvent *event)
575 if (target->window==None)
576 return;
577 event->xclient.window = target->window;
578 event->xclient.display = target->screen->display;
580 WMHandleEvent(event);
582 XSendEvent(target->screen->display, target->window, False,
583 SubstructureNotifyMask, event);
589 WMView*
590 W_RetainView(WMView *view)
592 view->refCount++;
593 return view;
598 void
599 W_ReleaseView(WMView *view)
601 view->refCount--;
602 if (view->refCount < 1) {
603 destroyView(view);
608 WMWidget*
609 WMWidgetOfView(WMView *view)
611 return view->self;
615 WMSize
616 WMGetViewSize(WMView *view)
618 return view->size;
621 WMPoint
622 WMGetViewPosition(WMView *view)
624 return view->pos;
628 void
629 WMSetViewNotifySizeChanges(WMView *view, Bool flag)
631 view->flags.notifySizeChanged = flag;
634 Window
635 WMViewXID(WMView *view)
637 return view->window;