updated upzzle, removed SetWindowInitialSize added SetWindowAspectRatio
[wmaker-crm.git] / WINGs / wwindow.c
blob40e30243399b2d6d5de867abd783b685e541f107
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;
28 WMPoint minAspect;
29 WMPoint maxAspect;
31 WMPoint upos;
33 WMAction *closeAction;
34 void *closeData;
36 int level;
38 struct {
39 unsigned style:4;
40 unsigned configured:1;
41 unsigned documentEdited:1;
43 unsigned setUPos:1;
44 unsigned setAspect:1;
45 } flags;
46 } _Window;
50 typedef struct {
51 CARD32 flags;
52 CARD32 window_style;
53 CARD32 window_level;
54 CARD32 reserved;
55 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
56 Pixmap close_pixmap; /* pixmap for close button */
57 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
58 Pixmap close_mask; /* close pixmap mask */
59 CARD32 extra_flags;
60 } GNUstepWMAttributes;
62 #define GSWindowStyleAttr (1<<0)
63 #define GSWindowLevelAttr (1<<1)
64 #define GSMiniaturizePixmapAttr (1<<3)
65 #define GSClosePixmapAttr (1<<4)
66 #define GSMiniaturizeMaskAttr (1<<5)
67 #define GSCloseMaskAttr (1<<6)
68 #define GSExtraFlagsAttr (1<<7)
70 /* extra flags */
71 #define GSDocumentEditedFlag (1<<0)
72 #define GSNoApplicationIconFlag (1<<5)
74 #define WMFHideOtherApplications 10
75 #define WMFHideApplication 12
79 static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned*, unsigned*);
81 struct W_ViewDelegate _WindowViewDelegate = {
82 NULL,
83 NULL,
84 NULL,
85 NULL,
86 willResizeWindow
90 #define DEFAULT_WIDTH 400
91 #define DEFAULT_HEIGHT 180
92 #define DEFAULT_TITLE ""
95 static void destroyWindow(_Window *win);
97 static void handleEvents();
99 static void realizeWindow();
101 static void
102 realizeObserver(void *self, WMNotification *not)
104 realizeWindow(self);
108 WMWindow*
109 WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
111 WMWindow *win;
113 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
114 win->owner = owner;
116 return win;
121 WMWindow*
122 WMCreatePanelForWindow(WMWindow *owner, char *name)
124 return WMCreatePanelWithStyleForWindow(owner, name,
125 WMTitledWindowMask
126 |WMClosableWindowMask
127 |WMResizableWindowMask);
131 void
132 WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
134 win->owner = newOwner;
136 if (win->view->flags.realized && newOwner) {
137 XSetTransientForHint(win->view->screen->display, win->view->window,
138 newOwner->view->window);
144 WMWindow*
145 WMCreateWindow(WMScreen *screen, char *name)
147 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
148 |WMClosableWindowMask
149 |WMMiniaturizableWindowMask
150 |WMResizableWindowMask);
155 WMWindow*
156 WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
158 _Window *win;
160 win = wmalloc(sizeof(_Window));
161 memset(win, 0, sizeof(_Window));
163 win->widgetClass = WC_Window;
165 win->view = W_CreateTopView(screen);
166 if (!win->view) {
167 wfree(win);
168 return NULL;
170 win->view->self = win;
172 win->view->delegate = &_WindowViewDelegate;
174 win->wname = wstrdup(name);
176 /* add to the window list of the screen (application) */
177 win->nextPtr = screen->windowList;
178 screen->windowList = win;
180 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
181 |ClientMessageMask|FocusChangeMask,
182 handleEvents, win);
184 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
186 WMAddNotificationObserver(realizeObserver, win,
187 WMViewRealizedNotification, win->view);
189 win->flags.style = style;
191 win->level = WMNormalWindowLevel;
193 /* kluge. Find a better solution */
194 W_SetFocusOfTopLevel(win->view, win->view);
196 return win;
200 void
201 WMSetWindowTitle(WMWindow *win, char *title)
203 XTextProperty property;
204 int result;
206 if (win->title!=NULL)
207 wfree(win->title);
208 if (title!=NULL)
209 win->title = wstrdup(title);
210 else
211 win->title = NULL;
213 if (win->view->flags.realized) {
214 result = XmbTextListToTextProperty (win->view->screen->display,
215 &title, 1, XStdICCTextStyle,
216 &property);
217 if (result == XNoMemory || result == XLocaleNotSupported) {
218 wwarning("window title conversion error... using STRING encoding");
219 XStoreName(win->view->screen->display, win->view->window, title);
220 } else {
221 XSetWMName(win->view->screen->display, win->view->window, &property);
222 if (property.value)
223 XFree(property.value);
231 void
232 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
234 Atom *atoms = NULL;
235 Atom *newAtoms;
236 int count;
237 WMScreen *scr = win->view->screen;
239 if (win->view->flags.realized) {
240 if (action && !win->closeAction) {
241 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
242 &count)) {
243 count = 0;
245 newAtoms = wmalloc((count+1)*sizeof(Atom));
246 if (count > 0)
247 memcpy(newAtoms, atoms, count*sizeof(Atom));
248 newAtoms[count++] = scr->deleteWindowAtom;
249 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
250 if (atoms)
251 XFree(atoms);
252 wfree(newAtoms);
253 } else if (!action && win->closeAction) {
254 int i, ncount;
256 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
257 &count) && count>0) {
258 newAtoms = wmalloc((count-1)*sizeof(Atom));
259 ncount = 0;
260 for (i=0; i < count; i++) {
261 if (atoms[i]!=scr->deleteWindowAtom) {
262 newAtoms[i] = atoms[i];
263 ncount++;
266 XSetWMProtocols(scr->display, win->view->window, newAtoms,
267 ncount);
268 if (atoms)
269 XFree(atoms);
270 wfree(newAtoms);
274 win->closeAction = action;
275 win->closeData = clientData;
280 static void
281 willResizeWindow(W_ViewDelegate *self, WMView *view,
282 unsigned *width, unsigned *height)
284 WMWindow *win = (WMWindow*)view->self;
286 if (win->minSize.width > 0 && win->minSize.height > 0) {
287 if (*width < win->minSize.width)
288 *width = win->minSize.width;
289 if (*height < win->minSize.height)
290 *height = win->minSize.height;
293 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
294 if (*width > win->maxSize.width)
295 *width = win->maxSize.width;
296 if (*height > win->maxSize.height)
297 *height = win->maxSize.height;
302 static void
303 setSizeHints(WMWindow *win)
305 XSizeHints *hints;
307 hints = XAllocSizeHints();
308 if (!hints) {
309 wwarning("could not allocate memory for window size hints");
310 return;
313 hints->flags = 0;
315 if (win->flags.setUPos) {
316 hints->flags |= USPosition;
317 hints->x = win->upos.x;
318 hints->y = win->upos.y;
320 if (win->minSize.width>0 && win->minSize.height>0) {
321 hints->flags |= PMinSize;
322 hints->min_width = win->minSize.width;
323 hints->min_height = win->minSize.height;
325 if (win->maxSize.width>0 && win->maxSize.height>0) {
326 hints->flags |= PMaxSize;
327 hints->max_width = win->maxSize.width;
328 hints->max_height = win->maxSize.height;
330 if (win->baseSize.width>0 && win->baseSize.height>0) {
331 hints->flags |= PBaseSize;
332 hints->base_width = win->baseSize.width;
333 hints->base_height = win->baseSize.height;
335 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
336 hints->flags |= PResizeInc;
337 hints->width_inc = win->resizeIncrement.width;
338 hints->height_inc = win->resizeIncrement.height;
340 if (win->flags.setAspect) {
341 hints->flags |= PAspect;
342 hints->min_aspect.x = win->minAspect.x;
343 hints->min_aspect.y = win->minAspect.y;
344 hints->max_aspect.x = win->maxAspect.x;
345 hints->max_aspect.y = win->maxAspect.y;
349 if (hints->flags) {
350 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
352 XFree(hints);
357 static void
358 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
360 unsigned long data[9];
362 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
363 data[0] = attr->flags;
364 data[1] = attr->window_style;
365 data[2] = attr->window_level;
366 data[3] = 0; /* reserved */
367 /* The X protocol says XIDs are 32bit */
368 data[4] = attr->miniaturize_pixmap;
369 data[5] = attr->close_pixmap;
370 data[6] = attr->miniaturize_mask;
371 data[7] = attr->close_mask;
372 data[8] = attr->extra_flags;
373 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
374 32, PropModeReplace, (unsigned char *)data, 9);
378 static void
379 setWindowMakerHints(WMWindow *win)
381 GNUstepWMAttributes attribs;
382 WMScreen *scr = WMWidgetScreen(win);
384 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
385 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
386 attribs.window_style = win->flags.style;
387 attribs.window_level = win->level;
388 if (win->flags.documentEdited)
389 attribs.extra_flags = GSDocumentEditedFlag;
390 else
391 attribs.extra_flags = 0;
393 writeGNUstepWMAttr(scr, win->view->window, &attribs);
397 static void
398 realizeWindow(WMWindow *win)
400 XWMHints *hints;
401 XClassHint *classHint;
402 WMScreen *scr = win->view->screen;
403 Atom atoms[4];
404 int count;
406 classHint = XAllocClassHint();
407 classHint->res_name = win->wname;
408 classHint->res_class = WMGetApplicationName();
409 XSetClassHint(scr->display, win->view->window, classHint);
410 XFree(classHint);
412 hints = XAllocWMHints();
413 hints->flags = 0;
414 if (!scr->aflags.simpleApplication) {
415 hints->flags |= WindowGroupHint;
416 hints->window_group = scr->groupLeader;
418 if (win->miniImage) {
419 hints->flags |= IconPixmapHint;
420 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
421 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
422 if (hints->icon_mask != None) {
423 hints->flags |= IconMaskHint;
426 if (hints->flags != 0)
427 XSetWMHints(scr->display, win->view->window, hints);
428 XFree(hints);
430 count = 0;
431 if (win->closeAction) {
432 atoms[count++] = scr->deleteWindowAtom;
435 if (count>0)
436 XSetWMProtocols(scr->display, win->view->window, atoms, count);
438 if (win->title || win->miniTitle)
439 XmbSetWMProperties(scr->display, win->view->window, win->title,
440 win->miniTitle, NULL, 0, NULL, NULL, NULL);
442 setWindowMakerHints(win);
444 setSizeHints(win);
446 if (win->owner) {
447 XSetTransientForHint(scr->display, win->view->window,
448 win->owner->view->window);
454 void
455 WMSetWindowAspectRatio(WMWindow *win, int minX, int minY,
456 int maxX, int maxY)
458 win->flags.setAspect = 1;
459 win->minAspect.x = minX;
460 win->minAspect.y = minY;
461 win->maxAspect.x = maxX;
462 win->maxAspect.y = maxY;
463 if (win->view->flags.realized)
464 setSizeHints(win);
469 void
470 WMSetWindowInitialPosition(WMWindow *win, int x, int y)
472 win->flags.setUPos = 1;
473 win->upos.x = x;
474 win->upos.y = y;
475 if (win->view->flags.realized)
476 setSizeHints(win);
481 void
482 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
484 win->minSize.width = width;
485 win->minSize.height = height;
486 if (win->view->flags.realized)
487 setSizeHints(win);
492 void
493 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
495 win->maxSize.width = width;
496 win->maxSize.height = height;
497 if (win->view->flags.realized)
498 setSizeHints(win);
502 void
503 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
505 /* TODO: validate sizes */
506 win->baseSize.width = width;
507 win->baseSize.height = height;
508 if (win->view->flags.realized)
509 setSizeHints(win);
513 void
514 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
516 win->resizeIncrement.width = wIncr;
517 win->resizeIncrement.height = hIncr;
518 if (win->view->flags.realized)
519 setSizeHints(win);
523 void
524 WMSetWindowLevel(WMWindow *win, int level)
526 win->level = level;
527 if (win->view->flags.realized)
528 setWindowMakerHints(win);
532 void
533 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
535 if (win->flags.documentEdited != flag) {
536 win->flags.documentEdited = flag;
537 if (win->view->flags.realized)
538 setWindowMakerHints(win);
543 void
544 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
546 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
547 if (win->miniImage)
548 WMReleasePixmap(win->miniImage);
550 if (pixmap)
551 win->miniImage = WMRetainPixmap(pixmap);
552 else
553 win->miniImage = NULL;
555 if (win->view->flags.realized) {
556 XWMHints *hints;
558 hints = XGetWMHints(win->view->screen->display, win->view->window);
559 if (!hints) {
560 hints = XAllocWMHints();
561 if (!hints) {
562 wwarning("could not allocate memory for WM hints");
563 return;
565 hints->flags = 0;
567 if (pixmap) {
568 hints->flags |= IconPixmapHint;
569 hints->icon_pixmap = WMGetPixmapXID(pixmap);
570 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
571 if (hints->icon_mask != None) {
572 hints->flags |= IconMaskHint;
575 XSetWMHints(win->view->screen->display, win->view->window, hints);
576 XFree(hints);
582 void
583 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
585 XTextProperty property;
586 int result;
588 if ((win->miniTitle && !title) || (!win->miniTitle && title)
589 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
590 if (win->miniTitle)
591 wfree(win->miniTitle);
593 if (title)
594 win->miniTitle = wstrdup(title);
595 else
596 win->miniTitle = NULL;
598 if (win->view->flags.realized) {
599 result = XmbTextListToTextProperty (win->view->screen->display,
600 &title, 1, XStdICCTextStyle,
601 &property);
602 if (result == XNoMemory || result == XLocaleNotSupported) {
603 wwarning("icon title conversion error..using STRING encoding");
604 XSetIconName(win->view->screen->display, win->view->window,
605 title);
606 } else {
607 XSetWMIconName(win->view->screen->display, win->view->window,
608 &property);
609 if (property.value)
610 XFree(property.value);
617 void
618 WMCloseWindow(WMWindow *win)
620 WMUnmapWidget(win);
621 /* withdraw the window */
622 if (win->view->flags.realized)
623 XWithdrawWindow(win->view->screen->display, win->view->window,
624 win->view->screen->screen);
628 static void
629 handleEvents(XEvent *event, void *clientData)
631 _Window *win = (_Window*)clientData;
632 W_View *view = win->view;
635 switch (event->type) {
636 case ClientMessage:
637 if (event->xclient.message_type == win->view->screen->protocolsAtom
638 && event->xclient.format == 32
639 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
641 if (win->closeAction) {
642 (*win->closeAction)(win, win->closeData);
645 break;
647 case UnmapNotify:
648 WMUnmapWidget(win);
649 break;
651 case DestroyNotify:
652 destroyWindow(win);
653 break;
655 case ConfigureNotify:
656 if (event->xconfigure.width != view->size.width
657 || event->xconfigure.height != view->size.height) {
659 view->size.width = event->xconfigure.width;
660 view->size.height = event->xconfigure.height;
662 if (view->flags.notifySizeChanged) {
663 WMPostNotificationName(WMViewSizeDidChangeNotification,
664 view, NULL);
667 if (event->xconfigure.x != view->pos.x
668 || event->xconfigure.y != view->pos.y) {
670 if (event->xconfigure.send_event) {
671 view->pos.x = event->xconfigure.x;
672 view->pos.y = event->xconfigure.y;
673 } else {
674 Window foo;
676 XTranslateCoordinates(view->screen->display,
677 view->window, view->screen->rootWin,
678 event->xconfigure.x, event->xconfigure.y,
679 &view->pos.x, &view->pos.y, &foo);
682 break;
689 static void
690 destroyWindow(_Window *win)
692 WMScreen *scr = win->view->screen;
694 WMRemoveNotificationObserver(win);
696 if (scr->windowList == win) {
697 scr->windowList = scr->windowList->nextPtr;
698 } else {
699 WMWindow *ptr;
700 ptr = scr->windowList;
702 if (ptr) {
703 while (ptr->nextPtr) {
704 if (ptr->nextPtr==win) {
705 ptr->nextPtr = ptr->nextPtr->nextPtr;
706 break;
708 ptr = ptr->nextPtr;
713 if (win->title) {
714 wfree(win->title);
717 if (win->miniTitle) {
718 wfree(win->miniTitle);
721 if (win->miniImage) {
722 WMReleasePixmap(win->miniImage);
725 if (win->wname)
726 wfree(win->wname);
728 wfree(win);