Again, don't be rude on people.
[wmaker-crm.git] / WINGs / wwindow.c
blob12d6cb45c928305e96f4ef4af55d141c5e4a398d
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 wfree(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 wfree(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 wfree(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 wfree(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 |= PPosition;
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 |= PSize;
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 WMSetWindowInitialPosition(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);
457 WMMoveWidget(win, x, y);
462 void
463 WMSetWindowInitialSize(WMWindow *win, unsigned width, unsigned height)
465 win->usize.width = width;
466 win->usize.height = height;
467 if (win->view->flags.realized)
468 setSizeHints(win);
469 WMResizeWidget(win, width, height);
473 void
474 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
476 win->minSize.width = width;
477 win->minSize.height = height;
478 if (win->view->flags.realized)
479 setSizeHints(win);
484 void
485 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
487 win->maxSize.width = width;
488 win->maxSize.height = height;
489 if (win->view->flags.realized)
490 setSizeHints(win);
494 void
495 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
497 /* TODO: validate sizes */
498 win->baseSize.width = width;
499 win->baseSize.height = height;
500 if (win->view->flags.realized)
501 setSizeHints(win);
505 void
506 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
508 win->resizeIncrement.width = wIncr;
509 win->resizeIncrement.height = hIncr;
510 if (win->view->flags.realized)
511 setSizeHints(win);
515 void
516 WMSetWindowLevel(WMWindow *win, int level)
518 win->level = level;
519 if (win->view->flags.realized)
520 setWindowMakerHints(win);
524 void
525 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
527 if (win->flags.documentEdited != flag) {
528 win->flags.documentEdited = flag;
529 if (win->view->flags.realized)
530 setWindowMakerHints(win);
535 void
536 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
538 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
539 if (win->miniImage)
540 WMReleasePixmap(win->miniImage);
542 if (pixmap)
543 win->miniImage = WMRetainPixmap(pixmap);
544 else
545 win->miniImage = NULL;
547 if (win->view->flags.realized) {
548 XWMHints *hints;
550 hints = XGetWMHints(win->view->screen->display, win->view->window);
551 if (!hints) {
552 hints = XAllocWMHints();
553 if (!hints) {
554 wwarning("could not allocate memory for WM hints");
555 return;
557 hints->flags = 0;
559 if (pixmap) {
560 hints->flags |= IconPixmapHint;
561 hints->icon_pixmap = WMGetPixmapXID(pixmap);
562 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
563 if (hints->icon_mask != None) {
564 hints->flags |= IconMaskHint;
567 XSetWMHints(win->view->screen->display, win->view->window, hints);
568 XFree(hints);
574 void
575 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
577 XTextProperty property;
578 int result;
580 if ((win->miniTitle && !title) || (!win->miniTitle && title)
581 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
582 if (win->miniTitle)
583 wfree(win->miniTitle);
585 if (title)
586 win->miniTitle = wstrdup(title);
587 else
588 win->miniTitle = NULL;
590 if (win->view->flags.realized) {
591 result = XmbTextListToTextProperty (win->view->screen->display,
592 &title, 1, XStdICCTextStyle,
593 &property);
594 if (result == XNoMemory || result == XLocaleNotSupported) {
595 wwarning("icon title conversion error..using STRING encoding");
596 XSetIconName(win->view->screen->display, win->view->window,
597 title);
598 } else {
599 XSetWMIconName(win->view->screen->display, win->view->window,
600 &property);
601 if (property.value)
602 XFree(property.value);
609 void
610 WMCloseWindow(WMWindow *win)
612 WMUnmapWidget(win);
613 /* withdraw the window */
614 if (win->view->flags.realized)
615 XWithdrawWindow(win->view->screen->display, win->view->window,
616 win->view->screen->screen);
620 static void
621 handleEvents(XEvent *event, void *clientData)
623 _Window *win = (_Window*)clientData;
624 W_View *view = win->view;
627 switch (event->type) {
628 case ClientMessage:
629 if (event->xclient.message_type == win->view->screen->protocolsAtom
630 && event->xclient.format == 32
631 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
633 if (win->closeAction) {
634 (*win->closeAction)(win, win->closeData);
637 break;
639 case UnmapNotify:
640 WMUnmapWidget(win);
641 break;
643 case DestroyNotify:
644 destroyWindow(win);
645 break;
647 case ConfigureNotify:
648 if (event->xconfigure.width != view->size.width
649 || event->xconfigure.height != view->size.height) {
651 view->size.width = event->xconfigure.width;
652 view->size.height = event->xconfigure.height;
654 if (view->flags.notifySizeChanged) {
655 WMPostNotificationName(WMViewSizeDidChangeNotification,
656 view, NULL);
659 if (event->xconfigure.x != view->pos.x
660 || event->xconfigure.y != view->pos.y) {
662 if (event->xconfigure.send_event) {
663 view->pos.x = event->xconfigure.x;
664 view->pos.y = event->xconfigure.y;
665 } else {
666 Window foo;
668 XTranslateCoordinates(view->screen->display,
669 view->window, view->screen->rootWin,
670 event->xconfigure.x, event->xconfigure.y,
671 &view->pos.x, &view->pos.y, &foo);
674 break;
681 static void
682 destroyWindow(_Window *win)
684 WMScreen *scr = win->view->screen;
686 WMRemoveNotificationObserver(win);
688 if (scr->windowList == win) {
689 scr->windowList = scr->windowList->nextPtr;
690 } else {
691 WMWindow *ptr;
692 ptr = scr->windowList;
694 if (ptr) {
695 while (ptr->nextPtr) {
696 if (ptr->nextPtr==win) {
697 ptr->nextPtr = ptr->nextPtr->nextPtr;
698 break;
700 ptr = ptr->nextPtr;
705 if (win->title) {
706 wfree(win->title);
709 if (win->miniTitle) {
710 wfree(win->miniTitle);
713 if (win->miniImage) {
714 WMReleasePixmap(win->miniImage);
717 if (win->wname)
718 wfree(win->wname);
720 wfree(win);