Update for 0.51.0
[wmaker-crm.git] / WINGs / wwindow.c
blob81a43a497a5dddc3197214baa7cab62234dcbe59
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 unsigned long 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 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
437 win->minSize.width = width;
438 win->minSize.height = height;
439 if (win->view->flags.realized)
440 setSizeHints(win);
445 void
446 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
448 win->maxSize.width = width;
449 win->maxSize.height = height;
450 if (win->view->flags.realized)
451 setSizeHints(win);
455 void
456 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
458 /* TODO: validate sizes */
459 win->baseSize.width = width;
460 win->baseSize.height = height;
461 if (win->view->flags.realized)
462 setSizeHints(win);
466 void
467 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
469 win->resizeIncrement.width = wIncr;
470 win->resizeIncrement.height = hIncr;
471 if (win->view->flags.realized)
472 setSizeHints(win);
476 void
477 WMSetWindowLevel(WMWindow *win, int level)
479 win->level = level;
480 if (win->view->flags.realized)
481 setWindowMakerHints(win);
485 void
486 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
488 if (win->flags.documentEdited != flag) {
489 win->flags.documentEdited = flag;
490 if (win->view->flags.realized)
491 setWindowMakerHints(win);
496 void
497 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
499 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
500 if (win->miniImage)
501 WMReleasePixmap(win->miniImage);
503 if (pixmap)
504 win->miniImage = WMRetainPixmap(pixmap);
505 else
506 win->miniImage = NULL;
508 if (win->view->flags.realized) {
509 XWMHints *hints;
511 hints = XGetWMHints(win->view->screen->display, win->view->window);
512 if (!hints) {
513 hints = XAllocWMHints();
514 if (!hints) {
515 wwarning("could not allocate memory for WM hints");
516 return;
518 hints->flags = 0;
520 if (pixmap) {
521 hints->flags |= IconPixmapHint;
522 hints->icon_pixmap = WMGetPixmapXID(pixmap);
523 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
524 if (hints->icon_mask != None) {
525 hints->flags |= IconMaskHint;
528 XSetWMHints(win->view->screen->display, win->view->window, hints);
529 XFree(hints);
535 void
536 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
538 if ((win->miniTitle && !title) || (!win->miniTitle && title)
539 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
540 if (win->miniTitle)
541 free(win->miniTitle);
543 if (title)
544 win->miniTitle = wstrdup(title);
545 else
546 win->miniTitle = NULL;
548 if (win->view->flags.realized) {
549 XSetIconName(win->view->screen->display, win->view->window, title);
555 void
556 WMCloseWindow(WMWindow *win)
558 WMUnmapWidget(win);
559 /* withdraw the window */
560 if (win->view->flags.realized)
561 XWithdrawWindow(win->view->screen->display, win->view->window,
562 win->view->screen->screen);
566 static void
567 handleEvents(XEvent *event, void *clientData)
569 _Window *win = (_Window*)clientData;
572 switch (event->type) {
573 case ClientMessage:
574 if (event->xclient.message_type == win->view->screen->protocolsAtom
575 && event->xclient.format == 32
576 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
578 if (win->closeAction) {
579 (*win->closeAction)(win, win->closeData);
582 break;
583 case UnmapNotify:
584 WMUnmapWidget(win);
585 break;
586 case DestroyNotify:
587 destroyWindow(win);
588 break;
595 static void
596 destroyWindow(_Window *win)
598 WMScreen *scr = win->view->screen;
600 WMRemoveNotificationObserver(win);
602 if (scr->windowList == win) {
603 scr->windowList = scr->windowList->nextPtr;
604 } else {
605 WMWindow *ptr;
606 ptr = scr->windowList;
608 while (ptr->nextPtr) {
609 if (ptr->nextPtr==win) {
610 ptr->nextPtr = ptr->nextPtr->nextPtr;
611 break;
613 ptr = ptr->nextPtr;
617 if (win->title) {
618 free(win->title);
621 if (win->miniTitle) {
622 free(win->miniTitle);
625 if (win->miniImage) {
626 WMReleasePixmap(win->miniImage);
629 if (win->wname)
630 free(win->wname);
632 free(win);