Updating to version 0.20.2
[wmaker-crm.git] / WINGs / wwindow.c
blobbb5cb36cced1089668822fbe3ac5d28dd2a06037
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 if (win->title!=NULL)
195 free(win->title);
196 if (title!=NULL)
197 win->title = wstrdup(title);
198 else
199 win->title = NULL;
201 if (win->view->flags.realized) {
202 XStoreName(win->view->screen->display, win->view->window, title);
209 void
210 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
212 Atom *atoms = NULL;
213 Atom *newAtoms;
214 int count;
215 WMScreen *scr = win->view->screen;
217 if (win->view->flags.realized) {
218 if (action && !win->closeAction) {
219 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
220 &count)) {
221 count = 0;
223 newAtoms = wmalloc((count+1)*sizeof(Atom));
224 if (count > 0)
225 memcpy(newAtoms, atoms, count*sizeof(Atom));
226 newAtoms[count++] = scr->deleteWindowAtom;
227 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
228 if (atoms)
229 XFree(atoms);
230 free(newAtoms);
231 } else if (!action && win->closeAction) {
232 int i, ncount;
234 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
235 &count) && count>0) {
236 newAtoms = wmalloc((count-1)*sizeof(Atom));
237 ncount = 0;
238 for (i=0; i < count; i++) {
239 if (atoms[i]!=scr->deleteWindowAtom) {
240 newAtoms[i] = atoms[i];
241 ncount++;
244 XSetWMProtocols(scr->display, win->view->window, newAtoms,
245 ncount);
246 if (atoms)
247 XFree(atoms);
248 free(newAtoms);
252 win->closeAction = action;
253 win->closeData = clientData;
257 static void
258 moveWindow(WMWidget *w, int x, int y)
260 ((WMWindow*)w)->flags.moved = 1;
262 W_MoveView(W_VIEW(w), x, y);
266 static void
267 resizeWindow(WMWidget *w, unsigned width, unsigned height)
269 WMWindow *win = (WMWindow*)w;
271 if (win->minSize.width > 0 && win->minSize.height > 0) {
272 if (width < win->minSize.width)
273 width = win->minSize.width;
274 if (height < win->minSize.height)
275 height = win->minSize.height;
278 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
279 if (width > win->maxSize.width)
280 width = win->maxSize.width;
281 if (height > win->maxSize.height)
282 height = win->maxSize.height;
285 W_ResizeView(win->view, width, height);
289 static void
290 setSizeHints(WMWindow *win)
292 XSizeHints *hints;
294 hints = XAllocSizeHints();
295 if (!hints) {
296 wwarning("could not allocate memory for window size hints");
297 return;
300 hints->flags = 0;
301 if (win->minSize.width>0 && win->minSize.height>0) {
302 hints->flags |= PMinSize;
303 hints->min_width = win->minSize.width;
304 hints->min_height = win->minSize.height;
306 if (win->maxSize.width>0 && win->maxSize.height>0) {
307 hints->flags |= PMaxSize;
308 hints->max_width = win->maxSize.width;
309 hints->max_height = win->maxSize.height;
311 if (win->baseSize.width>0 && win->baseSize.height>0) {
312 hints->flags |= PBaseSize;
313 hints->base_width = win->baseSize.width;
314 hints->base_height = win->baseSize.height;
316 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
317 hints->flags |= PResizeInc;
318 hints->width_inc = win->resizeIncrement.width;
319 hints->height_inc = win->resizeIncrement.height;
322 if (hints->flags) {
323 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
325 XFree(hints);
330 static void
331 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
333 CARD32 data[9];
335 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
336 data[0] = attr->flags;
337 data[1] = attr->window_style;
338 data[2] = attr->window_level;
339 data[3] = 0; /* reserved */
340 /* The X protocol says XIDs are 32bit */
341 data[4] = attr->miniaturize_pixmap;
342 data[5] = attr->close_pixmap;
343 data[6] = attr->miniaturize_mask;
344 data[7] = attr->close_mask;
345 data[8] = attr->extra_flags;
346 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
347 32, PropModeReplace, (unsigned char *)data, 9);
351 static void
352 setWindowMakerHints(WMWindow *win)
354 GNUstepWMAttributes attribs;
355 WMScreen *scr = WMWidgetScreen(win);
357 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
358 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
359 attribs.window_style = win->flags.style;
360 attribs.window_level = win->level;
361 if (win->flags.documentEdited)
362 attribs.extra_flags = GSDocumentEditedFlag;
363 else
364 attribs.extra_flags = 0;
366 writeGNUstepWMAttr(scr, win->view->window, &attribs);
370 static void
371 realizeWindow(WMWindow *win)
373 XWMHints *hints;
374 XClassHint *classHint;
375 WMScreen *scr = win->view->screen;
376 Atom atoms[4];
377 int count;
379 if (!win->flags.moved && win->owner!=NULL) {
380 W_MoveView(win->view,
381 (scr->rootView->size.width-win->view->size.width)/2,
382 (scr->rootView->size.height-win->view->size.height)/2);
385 classHint = XAllocClassHint();
386 classHint->res_name = win->wname;
387 classHint->res_class = WMGetApplicationName();
388 XSetClassHint(scr->display, win->view->window, classHint);
389 XFree(classHint);
391 hints = XAllocWMHints();
392 hints->flags = 0;
393 if (!scr->aflags.simpleApplication) {
394 hints->flags |= WindowGroupHint;
395 hints->window_group = scr->groupLeader;
397 if (win->miniImage) {
398 hints->flags |= IconPixmapHint;
399 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
400 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
401 if (hints->icon_mask != None) {
402 hints->flags |= IconMaskHint;
405 if (hints->flags != 0)
406 XSetWMHints(scr->display, win->view->window, hints);
407 XFree(hints);
409 count = 0;
410 if (win->closeAction) {
411 atoms[count++] = scr->deleteWindowAtom;
414 if (count>0)
415 XSetWMProtocols(scr->display, win->view->window, atoms, count);
417 if (win->title)
418 XStoreName(scr->display, win->view->window, win->title);
420 if (win->miniTitle)
421 XSetIconName(scr->display, win->view->window, win->miniTitle);
423 setWindowMakerHints(win);
425 setSizeHints(win);
427 if (win->owner) {
428 XSetTransientForHint(scr->display, win->view->window,
429 win->owner->view->window);
434 void
435 WMHideWindow(WMWindow *win)
437 WMUnmapWidget(win);
438 XWithdrawWindow(win->view->screen->display, win->view->window,
439 win->view->screen->screen);
443 void
444 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
446 win->minSize.width = width;
447 win->minSize.height = height;
448 if (win->view->flags.realized)
449 setSizeHints(win);
454 void
455 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
457 win->maxSize.width = width;
458 win->maxSize.height = height;
459 if (win->view->flags.realized)
460 setSizeHints(win);
464 void
465 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
467 /* TODO: validate sizes */
468 win->baseSize.width = width;
469 win->baseSize.height = height;
470 if (win->view->flags.realized)
471 setSizeHints(win);
475 void
476 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
478 win->resizeIncrement.width = wIncr;
479 win->resizeIncrement.height = hIncr;
480 if (win->view->flags.realized)
481 setSizeHints(win);
485 void
486 WMSetWindowLevel(WMWindow *win, int level)
488 win->level = level;
489 if (win->view->flags.realized)
490 setWindowMakerHints(win);
494 void
495 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
497 if (win->flags.documentEdited != flag) {
498 win->flags.documentEdited = flag;
499 if (win->view->flags.realized)
500 setWindowMakerHints(win);
505 void
506 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
508 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
509 if (win->miniImage)
510 WMReleasePixmap(win->miniImage);
512 if (pixmap)
513 win->miniImage = WMRetainPixmap(pixmap);
514 else
515 win->miniImage = NULL;
517 if (win->view->flags.realized) {
518 XWMHints *hints;
520 hints = XGetWMHints(win->view->screen->display, win->view->window);
521 if (!hints) {
522 hints = XAllocWMHints();
523 if (!hints) {
524 wwarning("could not allocate memory for WM hints");
525 return;
527 hints->flags = 0;
529 if (pixmap) {
530 hints->flags |= IconPixmapHint;
531 hints->icon_pixmap = WMGetPixmapXID(pixmap);
532 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
533 if (hints->icon_mask != None) {
534 hints->flags |= IconMaskHint;
537 XSetWMHints(win->view->screen->display, win->view->window, hints);
538 XFree(hints);
544 void
545 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
547 if ((win->miniTitle && !title) || (!win->miniTitle && title)
548 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
549 if (win->miniTitle)
550 free(win->miniTitle);
552 if (title)
553 win->miniTitle = wstrdup(title);
554 else
555 win->miniTitle = NULL;
557 if (win->view->flags.realized) {
558 XSetIconName(win->view->screen->display, win->view->window, title);
564 void
565 WMCloseWindow(WMWindow *win)
567 /* withdraw the window */
568 if (win->view->flags.realized)
569 XWithdrawWindow(win->view->screen->display, win->view->window,
570 win->view->screen->screen);
574 static void
575 handleEvents(XEvent *event, void *clientData)
577 _Window *win = (_Window*)clientData;
580 switch (event->type) {
581 case ClientMessage:
582 if (event->xclient.message_type == win->view->screen->protocolsAtom
583 && event->xclient.format == 32
584 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
586 if (win->closeAction) {
587 (*win->closeAction)(win, win->closeData);
590 break;
591 case DestroyNotify:
592 destroyWindow(win);
593 break;
600 static void
601 destroyWindow(_Window *win)
603 WMScreen *scr = win->view->screen;
605 WMRemoveNotificationObserver(win);
607 if (scr->windowList == win) {
608 scr->windowList = scr->windowList->nextPtr;
609 } else {
610 WMWindow *ptr;
611 ptr = scr->windowList;
613 while (ptr->nextPtr) {
614 if (ptr->nextPtr==win) {
615 ptr->nextPtr = ptr->nextPtr->nextPtr;
616 break;
618 ptr = ptr->nextPtr;
622 if (win->title) {
623 free(win->title);
626 if (win->miniTitle) {
627 free(win->miniTitle);
630 if (win->miniImage) {
631 WMReleasePixmap(win->miniImage);
634 if (win->wname)
635 free(win->wname);
637 free(win);