fixed Restart() function, and crashing dialog call to this function
[wmaker-crm.git] / WINGs / wwindow.c
blob42d84e6f676d448a809d3b5bb406ba541a93202f
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 WMPoint upos;
30 WMSize usize;
32 WMAction *closeAction;
33 void *closeData;
35 int level;
37 struct {
38 unsigned style:4;
39 unsigned configured:1;
40 unsigned documentEdited:1;
42 unsigned upos_set:1;
43 } flags;
44 } _Window;
48 typedef struct {
49 CARD32 flags;
50 CARD32 window_style;
51 CARD32 window_level;
52 CARD32 reserved;
53 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
54 Pixmap close_pixmap; /* pixmap for close button */
55 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
56 Pixmap close_mask; /* close pixmap mask */
57 CARD32 extra_flags;
58 } GNUstepWMAttributes;
60 #define GSWindowStyleAttr (1<<0)
61 #define GSWindowLevelAttr (1<<1)
62 #define GSMiniaturizePixmapAttr (1<<3)
63 #define GSClosePixmapAttr (1<<4)
64 #define GSMiniaturizeMaskAttr (1<<5)
65 #define GSCloseMaskAttr (1<<6)
66 #define GSExtraFlagsAttr (1<<7)
68 /* extra flags */
69 #define GSDocumentEditedFlag (1<<0)
70 #define GSNoApplicationIconFlag (1<<5)
72 #define WMFHideOtherApplications 10
73 #define WMFHideApplication 12
77 static void resizeWindow(WMWidget *, unsigned, unsigned);
79 struct W_ViewProcedureTable _WindowViewProcedures = {
80 NULL,
81 resizeWindow,
82 NULL
86 #define DEFAULT_WIDTH 400
87 #define DEFAULT_HEIGHT 180
88 #define DEFAULT_TITLE ""
91 static void destroyWindow(_Window *win);
93 static void handleEvents();
95 static void realizeWindow();
97 static void
98 realizeObserver(void *self, WMNotification *not)
100 realizeWindow(self);
104 WMWindow*
105 WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
107 WMWindow *win;
109 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
110 win->owner = owner;
112 return win;
117 WMWindow*
118 WMCreatePanelForWindow(WMWindow *owner, char *name)
120 return WMCreatePanelWithStyleForWindow(owner, name,
121 WMTitledWindowMask
122 |WMClosableWindowMask
123 |WMResizableWindowMask);
127 void
128 WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
130 win->owner = newOwner;
132 if (win->view->flags.realized && newOwner) {
133 XSetTransientForHint(win->view->screen->display, win->view->window,
134 newOwner->view->window);
140 WMWindow*
141 WMCreateWindow(WMScreen *screen, char *name)
143 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
144 |WMClosableWindowMask
145 |WMMiniaturizableWindowMask
146 |WMResizableWindowMask);
151 WMWindow*
152 WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
154 _Window *win;
156 win = wmalloc(sizeof(_Window));
157 memset(win, 0, sizeof(_Window));
159 win->widgetClass = WC_Window;
161 win->view = W_CreateTopView(screen);
162 if (!win->view) {
163 free(win);
164 return NULL;
166 win->view->self = win;
168 win->wname = wstrdup(name);
170 /* add to the window list of the screen (application) */
171 win->nextPtr = screen->windowList;
172 screen->windowList = win;
174 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
175 |ClientMessageMask|FocusChangeMask, handleEvents,
176 win);
178 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
180 WMAddNotificationObserver(realizeObserver, win,
181 WMViewRealizedNotification, win->view);
183 win->flags.style = style;
185 win->level = WMNormalWindowLevel;
187 /* kluge. Find a better solution */
188 W_SetFocusOfTopLevel(win->view, win->view);
190 return win;
194 void
195 WMSetWindowTitle(WMWindow *win, char *title)
197 XTextProperty property;
198 int result;
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 result = XmbTextListToTextProperty (win->view->screen->display,
209 &title, 1, XStdICCTextStyle,
210 &property);
211 if (result == XNoMemory || result == XLocaleNotSupported) {
212 wwarning("window title conversion error... using STRING encoding");
213 XStoreName(win->view->screen->display, win->view->window, title);
214 } else {
215 XSetWMName(win->view->screen->display, win->view->window, &property);
216 if (property.value)
217 XFree(property.value);
225 void
226 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
228 Atom *atoms = NULL;
229 Atom *newAtoms;
230 int count;
231 WMScreen *scr = win->view->screen;
233 if (win->view->flags.realized) {
234 if (action && !win->closeAction) {
235 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
236 &count)) {
237 count = 0;
239 newAtoms = wmalloc((count+1)*sizeof(Atom));
240 if (count > 0)
241 memcpy(newAtoms, atoms, count*sizeof(Atom));
242 newAtoms[count++] = scr->deleteWindowAtom;
243 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
244 if (atoms)
245 XFree(atoms);
246 free(newAtoms);
247 } else if (!action && win->closeAction) {
248 int i, ncount;
250 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
251 &count) && count>0) {
252 newAtoms = wmalloc((count-1)*sizeof(Atom));
253 ncount = 0;
254 for (i=0; i < count; i++) {
255 if (atoms[i]!=scr->deleteWindowAtom) {
256 newAtoms[i] = atoms[i];
257 ncount++;
260 XSetWMProtocols(scr->display, win->view->window, newAtoms,
261 ncount);
262 if (atoms)
263 XFree(atoms);
264 free(newAtoms);
268 win->closeAction = action;
269 win->closeData = clientData;
274 static void
275 resizeWindow(WMWidget *w, unsigned width, unsigned height)
277 WMWindow *win = (WMWindow*)w;
279 if (win->minSize.width > 0 && win->minSize.height > 0) {
280 if (width < win->minSize.width)
281 width = win->minSize.width;
282 if (height < win->minSize.height)
283 height = win->minSize.height;
286 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
287 if (width > win->maxSize.width)
288 width = win->maxSize.width;
289 if (height > win->maxSize.height)
290 height = win->maxSize.height;
293 W_ResizeView(win->view, width, height);
297 static void
298 setSizeHints(WMWindow *win)
300 XSizeHints *hints;
302 hints = XAllocSizeHints();
303 if (!hints) {
304 wwarning("could not allocate memory for window size hints");
305 return;
308 hints->flags = 0;
310 if (win->flags.upos_set) {
311 hints->flags |= USPosition;
312 hints->x = win->upos.x;
313 hints->y = win->upos.y;
315 if (win->usize.width>0 && win->usize.height>0) {
316 hints->flags |= USSize;
317 hints->width = win->usize.width;
318 hints->height = win->usize.height;
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;
341 if (hints->flags) {
342 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
344 XFree(hints);
349 static void
350 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
352 unsigned long data[9];
354 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
355 data[0] = attr->flags;
356 data[1] = attr->window_style;
357 data[2] = attr->window_level;
358 data[3] = 0; /* reserved */
359 /* The X protocol says XIDs are 32bit */
360 data[4] = attr->miniaturize_pixmap;
361 data[5] = attr->close_pixmap;
362 data[6] = attr->miniaturize_mask;
363 data[7] = attr->close_mask;
364 data[8] = attr->extra_flags;
365 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
366 32, PropModeReplace, (unsigned char *)data, 9);
370 static void
371 setWindowMakerHints(WMWindow *win)
373 GNUstepWMAttributes attribs;
374 WMScreen *scr = WMWidgetScreen(win);
376 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
377 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
378 attribs.window_style = win->flags.style;
379 attribs.window_level = win->level;
380 if (win->flags.documentEdited)
381 attribs.extra_flags = GSDocumentEditedFlag;
382 else
383 attribs.extra_flags = 0;
385 writeGNUstepWMAttr(scr, win->view->window, &attribs);
389 static void
390 realizeWindow(WMWindow *win)
392 XWMHints *hints;
393 XClassHint *classHint;
394 WMScreen *scr = win->view->screen;
395 Atom atoms[4];
396 int count;
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);
446 void
447 WMSetWindowUPosition(WMWindow *win, int x, int y)
449 win->flags.upos_set = 1;
450 win->upos.x = x;
451 win->upos.y = y;
452 if (win->view->flags.realized)
453 setSizeHints(win);
458 void
459 WMSetWindowUSize(WMWindow *win, unsigned width, unsigned height)
461 win->usize.width = width;
462 win->usize.height = height;
463 if (win->view->flags.realized)
464 setSizeHints(win);
468 void
469 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
471 win->minSize.width = width;
472 win->minSize.height = height;
473 if (win->view->flags.realized)
474 setSizeHints(win);
479 void
480 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
482 win->maxSize.width = width;
483 win->maxSize.height = height;
484 if (win->view->flags.realized)
485 setSizeHints(win);
489 void
490 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
492 /* TODO: validate sizes */
493 win->baseSize.width = width;
494 win->baseSize.height = height;
495 if (win->view->flags.realized)
496 setSizeHints(win);
500 void
501 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
503 win->resizeIncrement.width = wIncr;
504 win->resizeIncrement.height = hIncr;
505 if (win->view->flags.realized)
506 setSizeHints(win);
510 void
511 WMSetWindowLevel(WMWindow *win, int level)
513 win->level = level;
514 if (win->view->flags.realized)
515 setWindowMakerHints(win);
519 void
520 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
522 if (win->flags.documentEdited != flag) {
523 win->flags.documentEdited = flag;
524 if (win->view->flags.realized)
525 setWindowMakerHints(win);
530 void
531 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
533 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
534 if (win->miniImage)
535 WMReleasePixmap(win->miniImage);
537 if (pixmap)
538 win->miniImage = WMRetainPixmap(pixmap);
539 else
540 win->miniImage = NULL;
542 if (win->view->flags.realized) {
543 XWMHints *hints;
545 hints = XGetWMHints(win->view->screen->display, win->view->window);
546 if (!hints) {
547 hints = XAllocWMHints();
548 if (!hints) {
549 wwarning("could not allocate memory for WM hints");
550 return;
552 hints->flags = 0;
554 if (pixmap) {
555 hints->flags |= IconPixmapHint;
556 hints->icon_pixmap = WMGetPixmapXID(pixmap);
557 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
558 if (hints->icon_mask != None) {
559 hints->flags |= IconMaskHint;
562 XSetWMHints(win->view->screen->display, win->view->window, hints);
563 XFree(hints);
569 void
570 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
572 XTextProperty property;
573 int result;
575 if ((win->miniTitle && !title) || (!win->miniTitle && title)
576 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
577 if (win->miniTitle)
578 free(win->miniTitle);
580 if (title)
581 win->miniTitle = wstrdup(title);
582 else
583 win->miniTitle = NULL;
585 if (win->view->flags.realized) {
586 result = XmbTextListToTextProperty (win->view->screen->display,
587 &title, 1, XStdICCTextStyle,
588 &property);
589 if (result == XNoMemory || result == XLocaleNotSupported) {
590 wwarning("icon title conversion error..using STRING encoding");
591 XSetIconName(win->view->screen->display, win->view->window,
592 title);
593 } else {
594 XSetWMIconName(win->view->screen->display, win->view->window,
595 &property);
596 if (property.value)
597 XFree(property.value);
604 void
605 WMCloseWindow(WMWindow *win)
607 WMUnmapWidget(win);
608 /* withdraw the window */
609 if (win->view->flags.realized)
610 XWithdrawWindow(win->view->screen->display, win->view->window,
611 win->view->screen->screen);
615 static void
616 handleEvents(XEvent *event, void *clientData)
618 _Window *win = (_Window*)clientData;
621 switch (event->type) {
622 case ClientMessage:
623 if (event->xclient.message_type == win->view->screen->protocolsAtom
624 && event->xclient.format == 32
625 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
627 if (win->closeAction) {
628 (*win->closeAction)(win, win->closeData);
631 break;
632 case UnmapNotify:
633 WMUnmapWidget(win);
634 break;
635 case DestroyNotify:
636 destroyWindow(win);
637 break;
644 static void
645 destroyWindow(_Window *win)
647 WMScreen *scr = win->view->screen;
649 WMRemoveNotificationObserver(win);
651 if (scr->windowList == win) {
652 scr->windowList = scr->windowList->nextPtr;
653 } else {
654 WMWindow *ptr;
655 ptr = scr->windowList;
657 while (ptr->nextPtr) {
658 if (ptr->nextPtr==win) {
659 ptr->nextPtr = ptr->nextPtr->nextPtr;
660 break;
662 ptr = ptr->nextPtr;
666 if (win->title) {
667 free(win->title);
670 if (win->miniTitle) {
671 free(win->miniTitle);
674 if (win->miniImage) {
675 WMReleasePixmap(win->miniImage);
678 if (win->wname)
679 free(win->wname);
681 free(win);