Initial revision
[wmaker-crm.git] / WINGs / wwindow.c
blobef6e1cc54470c402dee111e8c4389a569e040c0e
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;
152 static int initedApp = 0;
154 win = wmalloc(sizeof(_Window));
155 memset(win, 0, sizeof(_Window));
157 win->widgetClass = WC_Window;
159 win->view = W_CreateTopView(screen);
160 if (!win->view) {
161 free(win);
162 return NULL;
164 win->view->self = win;
166 win->wname = wstrdup(name);
168 /* add to the window list of the screen (application) */
169 win->nextPtr = screen->windowList;
170 screen->windowList = win;
172 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
173 |ClientMessageMask|FocusChangeMask, handleEvents,
174 win);
176 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
178 if (!initedApp) {
179 W_InitApplication(screen);
180 initedApp = 1;
183 WMAddNotificationObserver(realizeObserver, win,
184 WMViewRealizedNotification, win->view);
186 win->flags.style = style;
188 win->level = WMNormalWindowLevel;
190 /* kluge. Find a better solution */
191 W_SetFocusOfTopLevel(win->view, win->view);
193 return win;
197 void
198 WMSetWindowTitle(WMWindow *win, char *title)
200 if (win->title!=NULL)
201 free(win->title);
202 if (title!=NULL)
203 win->title = wstrdup(title);
204 else
205 win->title = NULL;
207 if (win->view->flags.realized) {
208 XStoreName(win->view->screen->display, win->view->window, title);
215 void
216 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
218 Atom *atoms = NULL;
219 Atom *newAtoms;
220 int count;
221 WMScreen *scr = win->view->screen;
223 if (win->view->flags.realized) {
224 if (action && !win->closeAction) {
225 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
226 &count)) {
227 count = 0;
229 newAtoms = wmalloc((count+1)*sizeof(Atom));
230 if (count > 0)
231 memcpy(newAtoms, atoms, count*sizeof(Atom));
232 newAtoms[count++] = scr->deleteWindowAtom;
233 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
234 if (atoms)
235 XFree(atoms);
236 free(newAtoms);
237 } else if (!action && win->closeAction) {
238 int i, ncount;
240 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
241 &count) && count>0) {
242 newAtoms = wmalloc((count-1)*sizeof(Atom));
243 ncount = 0;
244 for (i=0; i < count; i++) {
245 if (atoms[i]!=scr->deleteWindowAtom) {
246 newAtoms[i] = atoms[i];
247 ncount++;
250 XSetWMProtocols(scr->display, win->view->window, newAtoms,
251 ncount);
252 if (atoms)
253 XFree(atoms);
254 free(newAtoms);
258 win->closeAction = action;
259 win->closeData = clientData;
263 static void
264 moveWindow(WMWidget *w, int x, int y)
266 ((WMWindow*)w)->flags.moved = 1;
268 W_MoveView(W_VIEW(w), x, y);
272 static void
273 resizeWindow(WMWidget *w, unsigned width, unsigned height)
275 WMWindow *win = (WMWindow*)w;
277 if (win->minSize.width > 0 && win->minSize.height > 0) {
278 if (width < win->minSize.width)
279 width = win->minSize.width;
280 if (height < win->minSize.height)
281 height = win->minSize.height;
284 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
285 if (width > win->maxSize.width)
286 width = win->maxSize.width;
287 if (height > win->maxSize.height)
288 height = win->maxSize.height;
291 W_ResizeView(win->view, width, height);
295 static void
296 setSizeHints(WMWindow *win)
298 XSizeHints *hints;
300 hints = XAllocSizeHints();
301 if (!hints) {
302 wwarning("could not allocate memory for window size hints");
303 return;
306 hints->flags = 0;
307 if (win->minSize.width>0 && win->minSize.height>0) {
308 hints->flags |= PMinSize;
309 hints->min_width = win->minSize.width;
310 hints->min_height = win->minSize.height;
312 if (win->maxSize.width>0 && win->maxSize.height>0) {
313 hints->flags |= PMaxSize;
314 hints->max_width = win->maxSize.width;
315 hints->max_height = win->maxSize.height;
317 if (win->baseSize.width>0 && win->baseSize.height>0) {
318 hints->flags |= PBaseSize;
319 hints->base_width = win->baseSize.width;
320 hints->base_height = win->baseSize.height;
322 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
323 hints->flags |= PResizeInc;
324 hints->width_inc = win->resizeIncrement.width;
325 hints->height_inc = win->resizeIncrement.height;
328 if (hints->flags) {
329 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
331 XFree(hints);
336 static void
337 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
339 CARD32 data[9];
341 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
342 data[0] = attr->flags;
343 data[1] = attr->window_style;
344 data[2] = attr->window_level;
345 data[3] = 0; /* reserved */
346 /* The X protocol says XIDs are 32bit */
347 data[4] = attr->miniaturize_pixmap;
348 data[5] = attr->close_pixmap;
349 data[6] = attr->miniaturize_mask;
350 data[7] = attr->close_mask;
351 data[8] = attr->extra_flags;
352 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
353 32, PropModeReplace, (unsigned char *)data, 9);
357 static void
358 setWindowMakerHints(WMWindow *win)
360 GNUstepWMAttributes attribs;
361 WMScreen *scr = WMWidgetScreen(win);
363 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
364 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
365 attribs.window_style = win->flags.style;
366 attribs.window_level = win->level;
367 if (win->flags.documentEdited)
368 attribs.extra_flags = GSDocumentEditedFlag;
369 else
370 attribs.extra_flags = 0;
372 writeGNUstepWMAttr(scr, win->view->window, &attribs);
376 static void
377 realizeWindow(WMWindow *win)
379 XWMHints *hints;
380 XClassHint *classHint;
381 WMScreen *scr = win->view->screen;
382 Atom atoms[4];
383 int count;
385 if (!win->flags.moved && win->owner!=NULL) {
386 W_MoveView(win->view,
387 (scr->rootView->size.width-win->view->size.width)/2,
388 (scr->rootView->size.height-win->view->size.height)/2);
391 classHint = XAllocClassHint();
392 classHint->res_name = win->wname;
393 classHint->res_class = WMGetApplicationName();
394 XSetClassHint(scr->display, win->view->window, classHint);
395 XFree(classHint);
397 hints = XAllocWMHints();
398 hints->flags = 0;
399 if (!scr->aflags.simpleApplication) {
400 hints->flags |= WindowGroupHint;
401 hints->window_group = scr->groupLeader;
403 if (win->miniImage) {
404 hints->flags |= IconPixmapHint;
405 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
406 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
407 if (hints->icon_mask != None) {
408 hints->flags |= IconMaskHint;
411 if (hints->flags != 0)
412 XSetWMHints(scr->display, win->view->window, hints);
413 XFree(hints);
415 count = 0;
416 if (win->closeAction) {
417 atoms[count++] = scr->deleteWindowAtom;
420 if (count>0)
421 XSetWMProtocols(scr->display, win->view->window, atoms, count);
423 if (win->title)
424 XStoreName(scr->display, win->view->window, win->title);
426 if (win->miniTitle)
427 XSetIconName(scr->display, win->view->window, win->miniTitle);
429 setWindowMakerHints(win);
431 setSizeHints(win);
433 if (win->owner) {
434 XSetTransientForHint(scr->display, win->view->window,
435 win->owner->view->window);
440 void
441 WMHideWindow(WMWindow *win)
443 WMUnmapWidget(win);
444 XWithdrawWindow(win->view->screen->display, win->view->window,
445 win->view->screen->screen);
449 void
450 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
452 win->minSize.width = width;
453 win->minSize.height = height;
454 if (win->view->flags.realized)
455 setSizeHints(win);
460 void
461 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
463 win->maxSize.width = width;
464 win->maxSize.height = height;
465 if (win->view->flags.realized)
466 setSizeHints(win);
470 void
471 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
473 /* TODO: validate sizes */
474 win->baseSize.width = width;
475 win->baseSize.height = height;
476 if (win->view->flags.realized)
477 setSizeHints(win);
481 void
482 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
484 win->resizeIncrement.width = wIncr;
485 win->resizeIncrement.height = hIncr;
486 if (win->view->flags.realized)
487 setSizeHints(win);
491 void
492 WMSetWindowLevel(WMWindow *win, int level)
494 win->level = level;
495 if (win->view->flags.realized)
496 setWindowMakerHints(win);
500 void
501 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
503 if (win->flags.documentEdited != flag) {
504 win->flags.documentEdited = flag;
505 if (win->view->flags.realized)
506 setWindowMakerHints(win);
511 void
512 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
514 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
515 if (win->miniImage)
516 WMReleasePixmap(win->miniImage);
518 if (pixmap)
519 win->miniImage = WMRetainPixmap(pixmap);
520 else
521 win->miniImage = NULL;
523 if (win->view->flags.realized) {
524 XWMHints *hints;
526 hints = XGetWMHints(win->view->screen->display, win->view->window);
527 if (!hints) {
528 hints = XAllocWMHints();
529 if (!hints) {
530 wwarning("could not allocate memory for WM hints");
531 return;
533 hints->flags = 0;
535 if (pixmap) {
536 hints->flags |= IconPixmapHint;
537 hints->icon_pixmap = WMGetPixmapXID(pixmap);
538 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
539 if (hints->icon_mask != None) {
540 hints->flags |= IconMaskHint;
543 XSetWMHints(win->view->screen->display, win->view->window, hints);
544 XFree(hints);
550 void
551 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
553 if ((win->miniTitle && !title) || (!win->miniTitle && title)
554 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
555 if (win->miniTitle)
556 free(win->miniTitle);
558 if (title)
559 win->miniTitle = wstrdup(title);
560 else
561 win->miniTitle = NULL;
563 if (win->view->flags.realized) {
564 XSetIconName(win->view->screen->display, win->view->window, title);
570 void
571 WMCloseWindow(WMWindow *win)
573 /* withdraw the window */
574 if (win->view->flags.realized)
575 XWithdrawWindow(win->view->screen->display, win->view->window,
576 win->view->screen->screen);
580 static void
581 handleEvents(XEvent *event, void *clientData)
583 _Window *win = (_Window*)clientData;
586 switch (event->type) {
587 case ClientMessage:
588 if (event->xclient.message_type == win->view->screen->protocolsAtom
589 && event->xclient.format == 32
590 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
592 if (win->closeAction) {
593 (*win->closeAction)(win, win->closeData);
596 break;
597 case DestroyNotify:
598 destroyWindow(win);
599 break;
606 static void
607 destroyWindow(_Window *win)
609 WMScreen *scr = win->view->screen;
611 WMRemoveNotificationObserver(win);
613 if (scr->windowList == win) {
614 scr->windowList = scr->windowList->nextPtr;
615 } else {
616 WMWindow *ptr;
617 ptr = scr->windowList;
619 while (ptr->nextPtr) {
620 if (ptr->nextPtr==win) {
621 ptr->nextPtr = ptr->nextPtr->nextPtr;
622 break;
624 ptr = ptr->nextPtr;
628 if (win->title) {
629 free(win->title);
632 if (win->miniTitle) {
633 free(win->miniTitle);
636 if (win->miniImage) {
637 WMReleasePixmap(win->miniImage);
640 if (win->wname)
641 free(win->wname);
643 free(win);