Initial update from my source tree. For 0.52.0
[wmaker-crm.git] / WINGs / wwindow.c
blob145bbbc97f155cdf4e9433d5b41eb992f938273b
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 WMAction *closeAction;
30 void *closeData;
32 int level;
34 struct {
35 unsigned style:4;
36 unsigned configured:1;
37 unsigned documentEdited:1;
38 unsigned moved:1;
39 } flags;
40 } _Window;
44 typedef struct {
45 CARD32 flags;
46 CARD32 window_style;
47 CARD32 window_level;
48 CARD32 reserved;
49 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
50 Pixmap close_pixmap; /* pixmap for close button */
51 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
52 Pixmap close_mask; /* close pixmap mask */
53 CARD32 extra_flags;
54 } GNUstepWMAttributes;
56 #define GSWindowStyleAttr (1<<0)
57 #define GSWindowLevelAttr (1<<1)
58 #define GSMiniaturizePixmapAttr (1<<3)
59 #define GSClosePixmapAttr (1<<4)
60 #define GSMiniaturizeMaskAttr (1<<5)
61 #define GSCloseMaskAttr (1<<6)
62 #define GSExtraFlagsAttr (1<<7)
64 /* extra flags */
65 #define GSDocumentEditedFlag (1<<0)
66 #define GSNoApplicationIconFlag (1<<5)
68 #define WMFHideOtherApplications 10
69 #define WMFHideApplication 12
73 static void resizeWindow(WMWidget *, unsigned, unsigned);
74 static void moveWindow(WMWidget *, int, int);
76 struct W_ViewProcedureTable _WindowViewProcedures = {
77 NULL,
78 resizeWindow,
79 moveWindow
83 #define DEFAULT_WIDTH 400
84 #define DEFAULT_HEIGHT 180
85 #define DEFAULT_TITLE ""
88 static void destroyWindow(_Window *win);
90 static void handleEvents();
92 static void realizeWindow();
94 static void
95 realizeObserver(void *self, WMNotification *not)
97 realizeWindow(self);
101 WMWindow*
102 WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
104 WMWindow *win;
106 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
107 win->owner = owner;
109 return win;
114 WMWindow*
115 WMCreatePanelForWindow(WMWindow *owner, char *name)
117 return WMCreatePanelWithStyleForWindow(owner, name,
118 WMTitledWindowMask
119 |WMClosableWindowMask
120 |WMResizableWindowMask);
124 void
125 WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
127 win->owner = newOwner;
129 if (win->view->flags.realized && newOwner) {
130 XSetTransientForHint(win->view->screen->display, win->view->window,
131 newOwner->view->window);
137 WMWindow*
138 WMCreateWindow(WMScreen *screen, char *name)
140 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
141 |WMClosableWindowMask
142 |WMMiniaturizableWindowMask
143 |WMResizableWindowMask);
148 WMWindow*
149 WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
151 _Window *win;
153 win = wmalloc(sizeof(_Window));
154 memset(win, 0, sizeof(_Window));
156 win->widgetClass = WC_Window;
158 win->view = W_CreateTopView(screen);
159 if (!win->view) {
160 free(win);
161 return NULL;
163 win->view->self = win;
165 win->wname = wstrdup(name);
167 /* add to the window list of the screen (application) */
168 win->nextPtr = screen->windowList;
169 screen->windowList = win;
171 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
172 |ClientMessageMask|FocusChangeMask, handleEvents,
173 win);
175 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
177 WMAddNotificationObserver(realizeObserver, win,
178 WMViewRealizedNotification, win->view);
180 win->flags.style = style;
182 win->level = WMNormalWindowLevel;
184 /* kluge. Find a better solution */
185 W_SetFocusOfTopLevel(win->view, win->view);
187 return win;
191 void
192 WMSetWindowTitle(WMWindow *win, char *title)
194 XTextProperty property;
195 int result;
197 if (win->title!=NULL)
198 free(win->title);
199 if (title!=NULL)
200 win->title = wstrdup(title);
201 else
202 win->title = NULL;
204 if (win->view->flags.realized) {
205 result = XmbTextListToTextProperty (win->view->screen->display,
206 &title, 1, XStdICCTextStyle,
207 &property);
208 if (result == XNoMemory || result == XLocaleNotSupported) {
209 wwarning("window title conversion error... using STRING encoding");
210 XStoreName(win->view->screen->display, win->view->window, title);
211 } else {
212 XSetWMName(win->view->screen->display, win->view->window, &property);
213 if (property.value)
214 XFree(property.value);
222 void
223 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
225 Atom *atoms = NULL;
226 Atom *newAtoms;
227 int count;
228 WMScreen *scr = win->view->screen;
230 if (win->view->flags.realized) {
231 if (action && !win->closeAction) {
232 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
233 &count)) {
234 count = 0;
236 newAtoms = wmalloc((count+1)*sizeof(Atom));
237 if (count > 0)
238 memcpy(newAtoms, atoms, count*sizeof(Atom));
239 newAtoms[count++] = scr->deleteWindowAtom;
240 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
241 if (atoms)
242 XFree(atoms);
243 free(newAtoms);
244 } else if (!action && win->closeAction) {
245 int i, ncount;
247 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
248 &count) && count>0) {
249 newAtoms = wmalloc((count-1)*sizeof(Atom));
250 ncount = 0;
251 for (i=0; i < count; i++) {
252 if (atoms[i]!=scr->deleteWindowAtom) {
253 newAtoms[i] = atoms[i];
254 ncount++;
257 XSetWMProtocols(scr->display, win->view->window, newAtoms,
258 ncount);
259 if (atoms)
260 XFree(atoms);
261 free(newAtoms);
265 win->closeAction = action;
266 win->closeData = clientData;
270 static void
271 moveWindow(WMWidget *w, int x, int y)
273 ((WMWindow*)w)->flags.moved = 1;
275 W_MoveView(W_VIEW(w), x, y);
279 static void
280 resizeWindow(WMWidget *w, unsigned width, unsigned height)
282 WMWindow *win = (WMWindow*)w;
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;
298 W_ResizeView(win->view, width, 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;
314 if (win->minSize.width>0 && win->minSize.height>0) {
315 hints->flags |= PMinSize;
316 hints->min_width = win->minSize.width;
317 hints->min_height = win->minSize.height;
319 if (win->maxSize.width>0 && win->maxSize.height>0) {
320 hints->flags |= PMaxSize;
321 hints->max_width = win->maxSize.width;
322 hints->max_height = win->maxSize.height;
324 if (win->baseSize.width>0 && win->baseSize.height>0) {
325 hints->flags |= PBaseSize;
326 hints->base_width = win->baseSize.width;
327 hints->base_height = win->baseSize.height;
329 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
330 hints->flags |= PResizeInc;
331 hints->width_inc = win->resizeIncrement.width;
332 hints->height_inc = win->resizeIncrement.height;
335 if (hints->flags) {
336 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
338 XFree(hints);
343 static void
344 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
346 unsigned long data[9];
348 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
349 data[0] = attr->flags;
350 data[1] = attr->window_style;
351 data[2] = attr->window_level;
352 data[3] = 0; /* reserved */
353 /* The X protocol says XIDs are 32bit */
354 data[4] = attr->miniaturize_pixmap;
355 data[5] = attr->close_pixmap;
356 data[6] = attr->miniaturize_mask;
357 data[7] = attr->close_mask;
358 data[8] = attr->extra_flags;
359 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
360 32, PropModeReplace, (unsigned char *)data, 9);
364 static void
365 setWindowMakerHints(WMWindow *win)
367 GNUstepWMAttributes attribs;
368 WMScreen *scr = WMWidgetScreen(win);
370 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
371 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
372 attribs.window_style = win->flags.style;
373 attribs.window_level = win->level;
374 if (win->flags.documentEdited)
375 attribs.extra_flags = GSDocumentEditedFlag;
376 else
377 attribs.extra_flags = 0;
379 writeGNUstepWMAttr(scr, win->view->window, &attribs);
383 static void
384 realizeWindow(WMWindow *win)
386 XWMHints *hints;
387 XClassHint *classHint;
388 WMScreen *scr = win->view->screen;
389 Atom atoms[4];
390 int count;
392 if (!win->flags.moved && win->owner!=NULL) {
393 W_MoveView(win->view,
394 (scr->rootView->size.width-win->view->size.width)/2,
395 (scr->rootView->size.height-win->view->size.height)/2);
398 classHint = XAllocClassHint();
399 classHint->res_name = win->wname;
400 classHint->res_class = WMGetApplicationName();
401 XSetClassHint(scr->display, win->view->window, classHint);
402 XFree(classHint);
404 hints = XAllocWMHints();
405 hints->flags = 0;
406 if (!scr->aflags.simpleApplication) {
407 hints->flags |= WindowGroupHint;
408 hints->window_group = scr->groupLeader;
410 if (win->miniImage) {
411 hints->flags |= IconPixmapHint;
412 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
413 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
414 if (hints->icon_mask != None) {
415 hints->flags |= IconMaskHint;
418 if (hints->flags != 0)
419 XSetWMHints(scr->display, win->view->window, hints);
420 XFree(hints);
422 count = 0;
423 if (win->closeAction) {
424 atoms[count++] = scr->deleteWindowAtom;
427 if (count>0)
428 XSetWMProtocols(scr->display, win->view->window, atoms, count);
430 if (win->title || win->miniTitle)
431 XmbSetWMProperties(scr->display, win->view->window, win->title,
432 win->miniTitle, NULL, 0, NULL, NULL, NULL);
434 setWindowMakerHints(win);
436 setSizeHints(win);
438 if (win->owner) {
439 XSetTransientForHint(scr->display, win->view->window,
440 win->owner->view->window);
445 void
446 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
448 win->minSize.width = width;
449 win->minSize.height = height;
450 if (win->view->flags.realized)
451 setSizeHints(win);
456 void
457 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
459 win->maxSize.width = width;
460 win->maxSize.height = height;
461 if (win->view->flags.realized)
462 setSizeHints(win);
466 void
467 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
469 /* TODO: validate sizes */
470 win->baseSize.width = width;
471 win->baseSize.height = height;
472 if (win->view->flags.realized)
473 setSizeHints(win);
477 void
478 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
480 win->resizeIncrement.width = wIncr;
481 win->resizeIncrement.height = hIncr;
482 if (win->view->flags.realized)
483 setSizeHints(win);
487 void
488 WMSetWindowLevel(WMWindow *win, int level)
490 win->level = level;
491 if (win->view->flags.realized)
492 setWindowMakerHints(win);
496 void
497 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
499 if (win->flags.documentEdited != flag) {
500 win->flags.documentEdited = flag;
501 if (win->view->flags.realized)
502 setWindowMakerHints(win);
507 void
508 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
510 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
511 if (win->miniImage)
512 WMReleasePixmap(win->miniImage);
514 if (pixmap)
515 win->miniImage = WMRetainPixmap(pixmap);
516 else
517 win->miniImage = NULL;
519 if (win->view->flags.realized) {
520 XWMHints *hints;
522 hints = XGetWMHints(win->view->screen->display, win->view->window);
523 if (!hints) {
524 hints = XAllocWMHints();
525 if (!hints) {
526 wwarning("could not allocate memory for WM hints");
527 return;
529 hints->flags = 0;
531 if (pixmap) {
532 hints->flags |= IconPixmapHint;
533 hints->icon_pixmap = WMGetPixmapXID(pixmap);
534 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
535 if (hints->icon_mask != None) {
536 hints->flags |= IconMaskHint;
539 XSetWMHints(win->view->screen->display, win->view->window, hints);
540 XFree(hints);
546 void
547 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
549 XTextProperty property;
550 int result;
552 if ((win->miniTitle && !title) || (!win->miniTitle && title)
553 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
554 if (win->miniTitle)
555 free(win->miniTitle);
557 if (title)
558 win->miniTitle = wstrdup(title);
559 else
560 win->miniTitle = NULL;
562 if (win->view->flags.realized) {
563 result = XmbTextListToTextProperty (win->view->screen->display,
564 &title, 1, XStdICCTextStyle,
565 &property);
566 if (result == XNoMemory || result == XLocaleNotSupported) {
567 wwarning("icon title conversion error..using STRING encoding");
568 XSetIconName(win->view->screen->display, win->view->window,
569 title);
570 } else {
571 XSetWMIconName(win->view->screen->display, win->view->window,
572 &property);
573 if (property.value)
574 XFree(property.value);
581 void
582 WMCloseWindow(WMWindow *win)
584 WMUnmapWidget(win);
585 /* withdraw the window */
586 if (win->view->flags.realized)
587 XWithdrawWindow(win->view->screen->display, win->view->window,
588 win->view->screen->screen);
592 static void
593 handleEvents(XEvent *event, void *clientData)
595 _Window *win = (_Window*)clientData;
598 switch (event->type) {
599 case ClientMessage:
600 if (event->xclient.message_type == win->view->screen->protocolsAtom
601 && event->xclient.format == 32
602 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
604 if (win->closeAction) {
605 (*win->closeAction)(win, win->closeData);
608 break;
609 case UnmapNotify:
610 WMUnmapWidget(win);
611 break;
612 case DestroyNotify:
613 destroyWindow(win);
614 break;
621 static void
622 destroyWindow(_Window *win)
624 WMScreen *scr = win->view->screen;
626 WMRemoveNotificationObserver(win);
628 if (scr->windowList == win) {
629 scr->windowList = scr->windowList->nextPtr;
630 } else {
631 WMWindow *ptr;
632 ptr = scr->windowList;
634 while (ptr->nextPtr) {
635 if (ptr->nextPtr==win) {
636 ptr->nextPtr = ptr->nextPtr->nextPtr;
637 break;
639 ptr = ptr->nextPtr;
643 if (win->title) {
644 free(win->title);
647 if (win->miniTitle) {
648 free(win->miniTitle);
651 if (win->miniImage) {
652 WMReleasePixmap(win->miniImage);
655 if (win->wname)
656 free(win->wname);
658 free(win);