WPrefs appearance stuff update (shows preview)
[wmaker-crm.git] / WINGs / wwindow.c
blob5646f23b4cf2a3c09a4d53bf3d34dc2ceffac92c
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);
78 static void moveWindow(WMWidget *, int, int);
80 struct W_ViewProcedureTable _WindowViewProcedures = {
81 NULL,
82 resizeWindow,
83 NULL
87 #define DEFAULT_WIDTH 400
88 #define DEFAULT_HEIGHT 180
89 #define DEFAULT_TITLE ""
92 static void destroyWindow(_Window *win);
94 static void handleEvents();
96 static void realizeWindow();
98 static void
99 realizeObserver(void *self, WMNotification *not)
101 realizeWindow(self);
105 WMWindow*
106 WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
108 WMWindow *win;
110 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
111 win->owner = owner;
113 return win;
118 WMWindow*
119 WMCreatePanelForWindow(WMWindow *owner, char *name)
121 return WMCreatePanelWithStyleForWindow(owner, name,
122 WMTitledWindowMask
123 |WMClosableWindowMask
124 |WMResizableWindowMask);
128 void
129 WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
131 win->owner = newOwner;
133 if (win->view->flags.realized && newOwner) {
134 XSetTransientForHint(win->view->screen->display, win->view->window,
135 newOwner->view->window);
141 WMWindow*
142 WMCreateWindow(WMScreen *screen, char *name)
144 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
145 |WMClosableWindowMask
146 |WMMiniaturizableWindowMask
147 |WMResizableWindowMask);
152 WMWindow*
153 WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
155 _Window *win;
157 win = wmalloc(sizeof(_Window));
158 memset(win, 0, sizeof(_Window));
160 win->widgetClass = WC_Window;
162 win->view = W_CreateTopView(screen);
163 if (!win->view) {
164 free(win);
165 return NULL;
167 win->view->self = win;
169 win->wname = wstrdup(name);
171 /* add to the window list of the screen (application) */
172 win->nextPtr = screen->windowList;
173 screen->windowList = win;
175 WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
176 |ClientMessageMask|FocusChangeMask, handleEvents,
177 win);
179 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
181 WMAddNotificationObserver(realizeObserver, win,
182 WMViewRealizedNotification, win->view);
184 win->flags.style = style;
186 win->level = WMNormalWindowLevel;
188 /* kluge. Find a better solution */
189 W_SetFocusOfTopLevel(win->view, win->view);
191 return win;
195 void
196 WMSetWindowTitle(WMWindow *win, char *title)
198 XTextProperty property;
199 int result;
201 if (win->title!=NULL)
202 free(win->title);
203 if (title!=NULL)
204 win->title = wstrdup(title);
205 else
206 win->title = NULL;
208 if (win->view->flags.realized) {
209 result = XmbTextListToTextProperty (win->view->screen->display,
210 &title, 1, XStdICCTextStyle,
211 &property);
212 if (result == XNoMemory || result == XLocaleNotSupported) {
213 wwarning("window title conversion error... using STRING encoding");
214 XStoreName(win->view->screen->display, win->view->window, title);
215 } else {
216 XSetWMName(win->view->screen->display, win->view->window, &property);
217 if (property.value)
218 XFree(property.value);
226 void
227 WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
229 Atom *atoms = NULL;
230 Atom *newAtoms;
231 int count;
232 WMScreen *scr = win->view->screen;
234 if (win->view->flags.realized) {
235 if (action && !win->closeAction) {
236 if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
237 &count)) {
238 count = 0;
240 newAtoms = wmalloc((count+1)*sizeof(Atom));
241 if (count > 0)
242 memcpy(newAtoms, atoms, count*sizeof(Atom));
243 newAtoms[count++] = scr->deleteWindowAtom;
244 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
245 if (atoms)
246 XFree(atoms);
247 free(newAtoms);
248 } else if (!action && win->closeAction) {
249 int i, ncount;
251 if (XGetWMProtocols(scr->display, win->view->window, &atoms,
252 &count) && count>0) {
253 newAtoms = wmalloc((count-1)*sizeof(Atom));
254 ncount = 0;
255 for (i=0; i < count; i++) {
256 if (atoms[i]!=scr->deleteWindowAtom) {
257 newAtoms[i] = atoms[i];
258 ncount++;
261 XSetWMProtocols(scr->display, win->view->window, newAtoms,
262 ncount);
263 if (atoms)
264 XFree(atoms);
265 free(newAtoms);
269 win->closeAction = action;
270 win->closeData = clientData;
275 static void
276 resizeWindow(WMWidget *w, unsigned width, unsigned height)
278 WMWindow *win = (WMWindow*)w;
280 if (win->minSize.width > 0 && win->minSize.height > 0) {
281 if (width < win->minSize.width)
282 width = win->minSize.width;
283 if (height < win->minSize.height)
284 height = win->minSize.height;
287 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
288 if (width > win->maxSize.width)
289 width = win->maxSize.width;
290 if (height > win->maxSize.height)
291 height = win->maxSize.height;
294 W_ResizeView(win->view, width, height);
298 static void
299 setSizeHints(WMWindow *win)
301 XSizeHints *hints;
303 hints = XAllocSizeHints();
304 if (!hints) {
305 wwarning("could not allocate memory for window size hints");
306 return;
309 hints->flags = 0;
311 if (win->flags.upos_set) {
312 hints->flags |= USPosition;
313 hints->x = win->upos.x;
314 hints->y = win->upos.y;
316 if (win->usize.width>0 && win->usize.height>0) {
317 hints->flags |= USSize;
318 hints->width = win->usize.width;
319 hints->height = win->usize.height;
321 if (win->minSize.width>0 && win->minSize.height>0) {
322 hints->flags |= PMinSize;
323 hints->min_width = win->minSize.width;
324 hints->min_height = win->minSize.height;
326 if (win->maxSize.width>0 && win->maxSize.height>0) {
327 hints->flags |= PMaxSize;
328 hints->max_width = win->maxSize.width;
329 hints->max_height = win->maxSize.height;
331 if (win->baseSize.width>0 && win->baseSize.height>0) {
332 hints->flags |= PBaseSize;
333 hints->base_width = win->baseSize.width;
334 hints->base_height = win->baseSize.height;
336 if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
337 hints->flags |= PResizeInc;
338 hints->width_inc = win->resizeIncrement.width;
339 hints->height_inc = win->resizeIncrement.height;
342 if (hints->flags) {
343 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
345 XFree(hints);
350 static void
351 writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
353 unsigned long data[9];
355 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
356 data[0] = attr->flags;
357 data[1] = attr->window_style;
358 data[2] = attr->window_level;
359 data[3] = 0; /* reserved */
360 /* The X protocol says XIDs are 32bit */
361 data[4] = attr->miniaturize_pixmap;
362 data[5] = attr->close_pixmap;
363 data[6] = attr->miniaturize_mask;
364 data[7] = attr->close_mask;
365 data[8] = attr->extra_flags;
366 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
367 32, PropModeReplace, (unsigned char *)data, 9);
371 static void
372 setWindowMakerHints(WMWindow *win)
374 GNUstepWMAttributes attribs;
375 WMScreen *scr = WMWidgetScreen(win);
377 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
378 attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
379 attribs.window_style = win->flags.style;
380 attribs.window_level = win->level;
381 if (win->flags.documentEdited)
382 attribs.extra_flags = GSDocumentEditedFlag;
383 else
384 attribs.extra_flags = 0;
386 writeGNUstepWMAttr(scr, win->view->window, &attribs);
390 static void
391 realizeWindow(WMWindow *win)
393 XWMHints *hints;
394 XClassHint *classHint;
395 WMScreen *scr = win->view->screen;
396 Atom atoms[4];
397 int count;
399 classHint = XAllocClassHint();
400 classHint->res_name = win->wname;
401 classHint->res_class = WMGetApplicationName();
402 XSetClassHint(scr->display, win->view->window, classHint);
403 XFree(classHint);
405 hints = XAllocWMHints();
406 hints->flags = 0;
407 if (!scr->aflags.simpleApplication) {
408 hints->flags |= WindowGroupHint;
409 hints->window_group = scr->groupLeader;
411 if (win->miniImage) {
412 hints->flags |= IconPixmapHint;
413 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
414 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
415 if (hints->icon_mask != None) {
416 hints->flags |= IconMaskHint;
419 if (hints->flags != 0)
420 XSetWMHints(scr->display, win->view->window, hints);
421 XFree(hints);
423 count = 0;
424 if (win->closeAction) {
425 atoms[count++] = scr->deleteWindowAtom;
428 if (count>0)
429 XSetWMProtocols(scr->display, win->view->window, atoms, count);
431 if (win->title || win->miniTitle)
432 XmbSetWMProperties(scr->display, win->view->window, win->title,
433 win->miniTitle, NULL, 0, NULL, NULL, NULL);
435 setWindowMakerHints(win);
437 setSizeHints(win);
439 if (win->owner) {
440 XSetTransientForHint(scr->display, win->view->window,
441 win->owner->view->window);
447 void
448 WMSetWindowUPosition(WMWindow *win, int x, int y)
450 win->flags.upos_set = 1;
451 win->upos.x = x;
452 win->upos.y = y;
453 if (win->view->flags.realized)
454 setSizeHints(win);
459 void
460 WMSetWindowUSize(WMWindow *win, unsigned width, unsigned height)
462 win->usize.width = width;
463 win->usize.height = height;
464 if (win->view->flags.realized)
465 setSizeHints(win);
469 void
470 WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
472 win->minSize.width = width;
473 win->minSize.height = height;
474 if (win->view->flags.realized)
475 setSizeHints(win);
480 void
481 WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
483 win->maxSize.width = width;
484 win->maxSize.height = height;
485 if (win->view->flags.realized)
486 setSizeHints(win);
490 void
491 WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
493 /* TODO: validate sizes */
494 win->baseSize.width = width;
495 win->baseSize.height = height;
496 if (win->view->flags.realized)
497 setSizeHints(win);
501 void
502 WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
504 win->resizeIncrement.width = wIncr;
505 win->resizeIncrement.height = hIncr;
506 if (win->view->flags.realized)
507 setSizeHints(win);
511 void
512 WMSetWindowLevel(WMWindow *win, int level)
514 win->level = level;
515 if (win->view->flags.realized)
516 setWindowMakerHints(win);
520 void
521 WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
523 if (win->flags.documentEdited != flag) {
524 win->flags.documentEdited = flag;
525 if (win->view->flags.realized)
526 setWindowMakerHints(win);
531 void
532 WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
534 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
535 if (win->miniImage)
536 WMReleasePixmap(win->miniImage);
538 if (pixmap)
539 win->miniImage = WMRetainPixmap(pixmap);
540 else
541 win->miniImage = NULL;
543 if (win->view->flags.realized) {
544 XWMHints *hints;
546 hints = XGetWMHints(win->view->screen->display, win->view->window);
547 if (!hints) {
548 hints = XAllocWMHints();
549 if (!hints) {
550 wwarning("could not allocate memory for WM hints");
551 return;
553 hints->flags = 0;
555 if (pixmap) {
556 hints->flags |= IconPixmapHint;
557 hints->icon_pixmap = WMGetPixmapXID(pixmap);
558 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
559 if (hints->icon_mask != None) {
560 hints->flags |= IconMaskHint;
563 XSetWMHints(win->view->screen->display, win->view->window, hints);
564 XFree(hints);
570 void
571 WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
573 XTextProperty property;
574 int result;
576 if ((win->miniTitle && !title) || (!win->miniTitle && title)
577 || (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
578 if (win->miniTitle)
579 free(win->miniTitle);
581 if (title)
582 win->miniTitle = wstrdup(title);
583 else
584 win->miniTitle = NULL;
586 if (win->view->flags.realized) {
587 result = XmbTextListToTextProperty (win->view->screen->display,
588 &title, 1, XStdICCTextStyle,
589 &property);
590 if (result == XNoMemory || result == XLocaleNotSupported) {
591 wwarning("icon title conversion error..using STRING encoding");
592 XSetIconName(win->view->screen->display, win->view->window,
593 title);
594 } else {
595 XSetWMIconName(win->view->screen->display, win->view->window,
596 &property);
597 if (property.value)
598 XFree(property.value);
605 void
606 WMCloseWindow(WMWindow *win)
608 WMUnmapWidget(win);
609 /* withdraw the window */
610 if (win->view->flags.realized)
611 XWithdrawWindow(win->view->screen->display, win->view->window,
612 win->view->screen->screen);
616 static void
617 handleEvents(XEvent *event, void *clientData)
619 _Window *win = (_Window*)clientData;
622 switch (event->type) {
623 case ClientMessage:
624 if (event->xclient.message_type == win->view->screen->protocolsAtom
625 && event->xclient.format == 32
626 && event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
628 if (win->closeAction) {
629 (*win->closeAction)(win, win->closeData);
632 break;
633 case UnmapNotify:
634 WMUnmapWidget(win);
635 break;
636 case DestroyNotify:
637 destroyWindow(win);
638 break;
645 static void
646 destroyWindow(_Window *win)
648 WMScreen *scr = win->view->screen;
650 WMRemoveNotificationObserver(win);
652 if (scr->windowList == win) {
653 scr->windowList = scr->windowList->nextPtr;
654 } else {
655 WMWindow *ptr;
656 ptr = scr->windowList;
658 while (ptr->nextPtr) {
659 if (ptr->nextPtr==win) {
660 ptr->nextPtr = ptr->nextPtr->nextPtr;
661 break;
663 ptr = ptr->nextPtr;
667 if (win->title) {
668 free(win->title);
671 if (win->miniTitle) {
672 free(win->miniTitle);
675 if (win->miniImage) {
676 WMReleasePixmap(win->miniImage);
679 if (win->wname)
680 free(win->wname);
682 free(win);