Changes for omnipresent icons in clip (menu entries redone).
[wmaker-crm.git] / WINGs / wwindow.c
blob56d67b1dbee92799eef3e81b77915c4d621a694c
2 #include <X11/Xmd.h>
4 #include "WINGsP.h"
6 #include <X11/Xatom.h>
9 typedef struct W_Window {
10 W_Class widgetClass;
11 W_View *view;
13 struct W_Window *nextPtr; /* next in the window list */
15 struct W_Window *owner;
17 char *title;
19 WMPixmap *miniImage; /* miniwindow */
20 char *miniTitle;
22 char *wname;
24 WMSize resizeIncrement;
25 WMSize baseSize;
26 WMSize minSize;
27 WMSize maxSize;
29 WMPoint upos;
30 WMSize usize;
32 WMAction *closeAction;
33 void *closeData;
35 int level;
37 struct {
38 unsigned style:4;
39 unsigned configured:1;
40 unsigned documentEdited:1;
42 unsigned upos_set:1;
43 } flags;
44 } _Window;
48 typedef struct {
49 CARD32 flags;
50 CARD32 window_style;
51 CARD32 window_level;
52 CARD32 reserved;
53 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
54 Pixmap close_pixmap; /* pixmap for close button */
55 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
56 Pixmap close_mask; /* close pixmap mask */
57 CARD32 extra_flags;
58 } GNUstepWMAttributes;
60 #define GSWindowStyleAttr (1<<0)
61 #define GSWindowLevelAttr (1<<1)
62 #define GSMiniaturizePixmapAttr (1<<3)
63 #define GSClosePixmapAttr (1<<4)
64 #define GSMiniaturizeMaskAttr (1<<5)
65 #define GSCloseMaskAttr (1<<6)
66 #define GSExtraFlagsAttr (1<<7)
68 /* extra flags */
69 #define GSDocumentEditedFlag (1<<0)
70 #define GSNoApplicationIconFlag (1<<5)
72 #define WMFHideOtherApplications 10
73 #define WMFHideApplication 12
77 static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned*, unsigned*);
79 struct W_ViewDelegate _WindowViewDelegate = {
80 NULL,
81 NULL,
82 NULL,
83 NULL,
84 willResizeWindow
88 #define DEFAULT_WIDTH 400
89 #define DEFAULT_HEIGHT 180
90 #define DEFAULT_TITLE ""
93 static void destroyWindow(_Window *win);
95 static void handleEvents();
97 static void realizeWindow();
99 static void
100 realizeObserver(void *self, WMNotification *not)
102 realizeWindow(self);
106 WMWindow*
107 WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
109 WMWindow *win;
111 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
112 win->owner = owner;
114 return win;
119 WMWindow*
120 WMCreatePanelForWindow(WMWindow *owner, char *name)
122 return WMCreatePanelWithStyleForWindow(owner, name,
123 WMTitledWindowMask
124 |WMClosableWindowMask
125 |WMResizableWindowMask);
129 void
130 WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
132 win->owner = newOwner;
134 if (win->view->flags.realized && newOwner) {
135 XSetTransientForHint(win->view->screen->display, win->view->window,
136 newOwner->view->window);
142 WMWindow*
143 WMCreateWindow(WMScreen *screen, char *name)
145 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
146 |WMClosableWindowMask
147 |WMMiniaturizableWindowMask
148 |WMResizableWindowMask);
153 WMWindow*
154 WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
156 _Window *win;
158 win = wmalloc(sizeof(_Window));
159 memset(win, 0, sizeof(_Window));
161 win->widgetClass = WC_Window;
163 win->view = W_CreateTopView(screen);
164 if (!win->view) {
165 free(win);
166 return NULL;
168 win->view->self = win;
170 win->view->delegate = &_WindowViewDelegate;
172 win->wname = wstrdup(name);
174 /* add to the window list of the screen (application) */
175 win->nextPtr = screen->windowList;
176 screen->windowList = win;
178 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
179 |ClientMessageMask|FocusChangeMask,
180 handleEvents, win);
182 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
184 WMAddNotificationObserver(realizeObserver, win,
185 WMViewRealizedNotification, win->view);
187 win->flags.style = style;
189 win->level = WMNormalWindowLevel;
191 /* kluge. Find a better solution */
192 W_SetFocusOfTopLevel(win->view, win->view);
194 return win;
198 void
199 WMSetWindowTitle(WMWindow *win, char *title)
201 XTextProperty property;
202 int result;
204 if (win->title!=NULL)
205 free(win->title);
206 if (title!=NULL)
207 win->title = wstrdup(title);
208 else
209 win->title = NULL;
211 if (win->view->flags.realized) {
212 result = XmbTextListToTextProperty (win->view->screen->display,
213 &title, 1, XStdICCTextStyle,
214 &property);
215 if (result == XNoMemory || result == XLocaleNotSupported) {
216 wwarning("window title conversion error... using STRING encoding");
217 XStoreName(win->view->screen->display, win->view->window, title);
218 } else {
219 XSetWMName(win->view->screen->display, win->view->window, &property);
220 if (property.value)
221 XFree(property.value);
229 void
230 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
232 Atom *atoms = NULL;
233 Atom *newAtoms;
234 int count;
235 WMScreen *scr = win->view->screen;
237 if (win->view->flags.realized) {
238 if (action && !win->closeAction) {
239 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
240 &count)) {
241 count = 0;
243 newAtoms = wmalloc((count+1)*sizeof(Atom));
244 if (count > 0)
245 memcpy(newAtoms, atoms, count*sizeof(Atom));
246 newAtoms[count++] = scr->deleteWindowAtom;
247 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
248 if (atoms)
249 XFree(atoms);
250 free(newAtoms);
251 } else if (!action && win->closeAction) {
252 int i, ncount;
254 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
255 &count) && count>0) {
256 newAtoms = wmalloc((count-1)*sizeof(Atom));
257 ncount = 0;
258 for (i=0; i < count; i++) {
259 if (atoms[i]!=scr->deleteWindowAtom) {
260 newAtoms[i] = atoms[i];
261 ncount++;
264 XSetWMProtocols(scr->display, win->view->window, newAtoms,
265 ncount);
266 if (atoms)
267 XFree(atoms);
268 free(newAtoms);
272 win->closeAction = action;
273 win->closeData = clientData;
278 static void
279 willResizeWindow(W_ViewDelegate *self, WMView *view,
280 unsigned *width, unsigned *height)
282 WMWindow *win = (WMWindow*)view->self;
284 if (win->minSize.width > 0 && win->minSize.height > 0) {
285 if (*width < win->minSize.width)
286 *width = win->minSize.width;
287 if (*height < win->minSize.height)
288 *height = win->minSize.height;
291 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
292 if (*width > win->maxSize.width)
293 *width = win->maxSize.width;
294 if (*height > win->maxSize.height)
295 *height = win->maxSize.height;
300 static void
301 setSizeHints(WMWindow *win)
303 XSizeHints *hints;
305 hints = XAllocSizeHints();
306 if (!hints) {
307 wwarning("could not allocate memory for window size hints");
308 return;
311 hints->flags = 0;
313 if (win->flags.upos_set) {
314 hints->flags |= USPosition;
315 hints->x = win->upos.x;
316 hints->y = win->upos.y;
318 if (win->usize.width>0 && win->usize.height>0) {
319 hints->flags |= USSize;
320 hints->width = win->usize.width;
321 hints->height = win->usize.height;
323 if (win->minSize.width>0 && win->minSize.height>0) {
324 hints->flags |= PMinSize;
325 hints->min_width = win->minSize.width;
326 hints->min_height = win->minSize.height;
328 if (win->maxSize.width>0 && win->maxSize.height>0) {
329 hints->flags |= PMaxSize;
330 hints->max_width = win->maxSize.width;
331 hints->max_height = win->maxSize.height;
333 if (win->baseSize.width>0 && win->baseSize.height>0) {
334 hints->flags |= PBaseSize;
335 hints->base_width = win->baseSize.width;
336 hints->base_height = win->baseSize.height;
338 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
339 hints->flags |= PResizeInc;
340 hints->width_inc = win->resizeIncrement.width;
341 hints->height_inc = win->resizeIncrement.height;
344 if (hints->flags) {
345 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
347 XFree(hints);
352 static void
353 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
355 unsigned long data[9];
357 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
358 data[0] = attr->flags;
359 data[1] = attr->window_style;
360 data[2] = attr->window_level;
361 data[3] = 0; /* reserved */
362 /* The X protocol says XIDs are 32bit */
363 data[4] = attr->miniaturize_pixmap;
364 data[5] = attr->close_pixmap;
365 data[6] = attr->miniaturize_mask;
366 data[7] = attr->close_mask;
367 data[8] = attr->extra_flags;
368 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
369 32, PropModeReplace, (unsigned char *)data, 9);
373 static void
374 setWindowMakerHints(WMWindow *win)
376 GNUstepWMAttributes attribs;
377 WMScreen *scr = WMWidgetScreen(win);
379 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
380 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
381 attribs.window_style = win->flags.style;
382 attribs.window_level = win->level;
383 if (win->flags.documentEdited)
384 attribs.extra_flags = GSDocumentEditedFlag;
385 else
386 attribs.extra_flags = 0;
388 writeGNUstepWMAttr(scr, win->view->window, &attribs);
392 static void
393 realizeWindow(WMWindow *win)
395 XWMHints *hints;
396 XClassHint *classHint;
397 WMScreen *scr = win->view->screen;
398 Atom atoms[4];
399 int count;
401 classHint = XAllocClassHint();
402 classHint->res_name = win->wname;
403 classHint->res_class = WMGetApplicationName();
404 XSetClassHint(scr->display, win->view->window, classHint);
405 XFree(classHint);
407 hints = XAllocWMHints();
408 hints->flags = 0;
409 if (!scr->aflags.simpleApplication) {
410 hints->flags |= WindowGroupHint;
411 hints->window_group = scr->groupLeader;
413 if (win->miniImage) {
414 hints->flags |= IconPixmapHint;
415 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
416 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
417 if (hints->icon_mask != None) {
418 hints->flags |= IconMaskHint;
421 if (hints->flags != 0)
422 XSetWMHints(scr->display, win->view->window, hints);
423 XFree(hints);
425 count = 0;
426 if (win->closeAction) {
427 atoms[count++] = scr->deleteWindowAtom;
430 if (count>0)
431 XSetWMProtocols(scr->display, win->view->window, atoms, count);
433 if (win->title || win->miniTitle)
434 XmbSetWMProperties(scr->display, win->view->window, win->title,
435 win->miniTitle, NULL, 0, NULL, NULL, NULL);
437 setWindowMakerHints(win);
439 setSizeHints(win);
441 if (win->owner) {
442 XSetTransientForHint(scr->display, win->view->window,
443 win->owner->view->window);
449 void
450 WMSetWindowUPosition(WMWindow *win, int x, int y)
452 win->flags.upos_set = 1;
453 win->upos.x = x;
454 win->upos.y = y;
455 if (win->view->flags.realized)
456 setSizeHints(win);
461 void
462 WMSetWindowUSize(WMWindow *win, unsigned width, unsigned height)
464 win->usize.width = width;
465 win->usize.height = height;
466 if (win->view->flags.realized)
467 setSizeHints(win);
471 void
472 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
474 win->minSize.width = width;
475 win->minSize.height = height;
476 if (win->view->flags.realized)
477 setSizeHints(win);
482 void
483 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
485 win->maxSize.width = width;
486 win->maxSize.height = height;
487 if (win->view->flags.realized)
488 setSizeHints(win);
492 void
493 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
495 /* TODO: validate sizes */
496 win->baseSize.width = width;
497 win->baseSize.height = height;
498 if (win->view->flags.realized)
499 setSizeHints(win);
503 void
504 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
506 win->resizeIncrement.width = wIncr;
507 win->resizeIncrement.height = hIncr;
508 if (win->view->flags.realized)
509 setSizeHints(win);
513 void
514 WMSetWindowLevel(WMWindow *win, int level)
516 win->level = level;
517 if (win->view->flags.realized)
518 setWindowMakerHints(win);
522 void
523 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
525 if (win->flags.documentEdited != flag) {
526 win->flags.documentEdited = flag;
527 if (win->view->flags.realized)
528 setWindowMakerHints(win);
533 void
534 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
536 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
537 if (win->miniImage)
538 WMReleasePixmap(win->miniImage);
540 if (pixmap)
541 win->miniImage = WMRetainPixmap(pixmap);
542 else
543 win->miniImage = NULL;
545 if (win->view->flags.realized) {
546 XWMHints *hints;
548 hints = XGetWMHints(win->view->screen->display, win->view->window);
549 if (!hints) {
550 hints = XAllocWMHints();
551 if (!hints) {
552 wwarning("could not allocate memory for WM hints");
553 return;
555 hints->flags = 0;
557 if (pixmap) {
558 hints->flags |= IconPixmapHint;
559 hints->icon_pixmap = WMGetPixmapXID(pixmap);
560 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
561 if (hints->icon_mask != None) {
562 hints->flags |= IconMaskHint;
565 XSetWMHints(win->view->screen->display, win->view->window, hints);
566 XFree(hints);
572 void
573 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
575 XTextProperty property;
576 int result;
578 if ((win->miniTitle && !title) || (!win->miniTitle && title)
579 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
580 if (win->miniTitle)
581 free(win->miniTitle);
583 if (title)
584 win->miniTitle = wstrdup(title);
585 else
586 win->miniTitle = NULL;
588 if (win->view->flags.realized) {
589 result = XmbTextListToTextProperty (win->view->screen->display,
590 &title, 1, XStdICCTextStyle,
591 &property);
592 if (result == XNoMemory || result == XLocaleNotSupported) {
593 wwarning("icon title conversion error..using STRING encoding");
594 XSetIconName(win->view->screen->display, win->view->window,
595 title);
596 } else {
597 XSetWMIconName(win->view->screen->display, win->view->window,
598 &property);
599 if (property.value)
600 XFree(property.value);
607 void
608 WMCloseWindow(WMWindow *win)
610 WMUnmapWidget(win);
611 /* withdraw the window */
612 if (win->view->flags.realized)
613 XWithdrawWindow(win->view->screen->display, win->view->window,
614 win->view->screen->screen);
618 static void
619 handleEvents(XEvent *event, void *clientData)
621 _Window *win = (_Window*)clientData;
622 W_View *view = win->view;
625 switch (event->type) {
626 case ClientMessage:
627 if (event->xclient.message_type == win->view->screen->protocolsAtom
628 && event->xclient.format == 32
629 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
631 if (win->closeAction) {
632 (*win->closeAction)(win, win->closeData);
635 break;
637 case UnmapNotify:
638 WMUnmapWidget(win);
639 break;
641 case DestroyNotify:
642 destroyWindow(win);
643 break;
645 case ConfigureNotify:
646 if (event->xconfigure.width != view->size.width
647 || event->xconfigure.height != view->size.height) {
649 view->size.width = event->xconfigure.width;
650 view->size.height = event->xconfigure.height;
652 if (view->flags.notifySizeChanged) {
653 WMPostNotificationName(WMViewSizeDidChangeNotification,
654 view, NULL);
657 if (event->xconfigure.x != view->pos.x
658 || event->xconfigure.y != view->pos.y) {
660 if (event->xconfigure.send_event) {
661 view->pos.x = event->xconfigure.x;
662 view->pos.y = event->xconfigure.y;
663 } else {
664 Window foo;
666 XTranslateCoordinates(view->screen->display,
667 view->window, view->screen->rootWin,
668 event->xconfigure.x, event->xconfigure.y,
669 &view->pos.x, &view->pos.y, &foo);
672 break;
679 static void
680 destroyWindow(_Window *win)
682 WMScreen *scr = win->view->screen;
684 WMRemoveNotificationObserver(win);
686 if (scr->windowList == win) {
687 scr->windowList = scr->windowList->nextPtr;
688 } else {
689 WMWindow *ptr;
690 ptr = scr->windowList;
692 while (ptr->nextPtr) {
693 if (ptr->nextPtr==win) {
694 ptr->nextPtr = ptr->nextPtr->nextPtr;
695 break;
697 ptr = ptr->nextPtr;
701 if (win->title) {
702 free(win->title);
705 if (win->miniTitle) {
706 free(win->miniTitle);
709 if (win->miniImage) {
710 WMReleasePixmap(win->miniImage);
713 if (win->wname)
714 free(win->wname);
716 free(win);