WINGs: Added 'const' attribute to function 'WMCreateHashTable'
[wmaker-crm.git] / WINGs / wwindow.c
blobe600f89efc45db14f26e5df41c65aebd4a87f47d
2 #include <X11/Xmd.h>
4 #include "WINGsP.h"
6 #include <X11/Xatom.h>
8 typedef struct W_Window {
9 W_Class widgetClass;
10 W_View *view;
12 struct W_Window *nextPtr; /* next in the window list */
14 struct W_Window *owner;
16 char *title;
18 WMPixmap *miniImage; /* miniwindow */
19 char *miniTitle;
21 char *wname;
23 WMSize resizeIncrement;
24 WMSize baseSize;
25 WMSize minSize;
26 WMSize maxSize;
27 WMPoint minAspect;
28 WMPoint maxAspect;
30 WMPoint upos;
31 WMPoint ppos;
33 WMAction *closeAction;
34 void *closeData;
36 int level;
38 struct {
39 unsigned style:4;
40 unsigned configured:1;
41 unsigned documentEdited:1;
43 unsigned setUPos:1;
44 unsigned setPPos:1;
45 unsigned setAspect:1;
46 } flags;
47 } _Window;
49 typedef struct {
50 CARD32 flags;
51 CARD32 window_style;
52 CARD32 window_level;
53 CARD32 reserved;
54 Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
55 Pixmap close_pixmap; /* pixmap for close button */
56 Pixmap miniaturize_mask; /* miniaturize pixmap mask */
57 Pixmap close_mask; /* close pixmap mask */
58 CARD32 extra_flags;
59 } GNUstepWMAttributes;
61 #define GSWindowStyleAttr (1<<0)
62 #define GSWindowLevelAttr (1<<1)
63 #define GSMiniaturizePixmapAttr (1<<3)
64 #define GSClosePixmapAttr (1<<4)
65 #define GSMiniaturizeMaskAttr (1<<5)
66 #define GSCloseMaskAttr (1<<6)
67 #define GSExtraFlagsAttr (1<<7)
69 /* extra flags */
70 #define GSDocumentEditedFlag (1<<0)
71 #define GSNoApplicationIconFlag (1<<5)
73 #define WMFHideOtherApplications 10
74 #define WMFHideApplication 12
76 static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned *, unsigned *);
78 struct W_ViewDelegate _WindowViewDelegate = {
79 NULL,
80 NULL,
81 NULL,
82 NULL,
83 willResizeWindow
86 #define DEFAULT_WIDTH 400
87 #define DEFAULT_HEIGHT 180
88 #define DEFAULT_TITLE ""
90 static void destroyWindow(_Window * win);
92 static void handleEvents(XEvent * event, void *clientData);
94 static void realizeWindow(WMWindow * win);
96 static void realizeObserver(void *self, WMNotification * not)
98 /* Parameter not used, but tell the compiler that it is ok */
99 (void) not;
101 realizeWindow(self);
104 WMWindow *WMCreatePanelWithStyleForWindow(WMWindow * owner, const char *name, int style)
106 WMWindow *win;
108 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
109 win->owner = owner;
111 return win;
114 WMWindow *WMCreatePanelForWindow(WMWindow * owner, const char *name)
116 return WMCreatePanelWithStyleForWindow(owner, name,
117 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
120 void WMChangePanelOwner(WMWindow * win, WMWindow * newOwner)
122 win->owner = newOwner;
124 if (win->view->flags.realized && newOwner) {
125 XSetTransientForHint(win->view->screen->display, win->view->window, newOwner->view->window);
129 WMWindow *WMCreateWindow(WMScreen * screen, const char *name)
131 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
132 | WMClosableWindowMask
133 | WMMiniaturizableWindowMask | WMResizableWindowMask);
136 WMWindow *WMCreateWindowWithStyle(WMScreen * screen, const char *name, int style)
138 _Window *win;
140 win = wmalloc(sizeof(_Window));
141 win->widgetClass = WC_Window;
143 win->view = W_CreateTopView(screen);
144 if (!win->view) {
145 wfree(win);
146 return NULL;
148 win->view->self = win;
150 win->view->delegate = &_WindowViewDelegate;
152 win->wname = wstrdup(name);
154 /* add to the window list of the screen (application) */
155 win->nextPtr = screen->windowList;
156 screen->windowList = win;
158 WMCreateEventHandler(win->view, ExposureMask | StructureNotifyMask
159 | ClientMessageMask | FocusChangeMask, handleEvents, win);
161 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
163 WMAddNotificationObserver(realizeObserver, win, WMViewRealizedNotification, win->view);
165 win->flags.style = style;
167 win->level = WMNormalWindowLevel;
169 /* kluge. Find a better solution */
170 W_SetFocusOfTopLevel(win->view, win->view);
172 return win;
175 static void setWindowTitle(WMWindow * win, const char *title)
177 WMScreen *scr = win->view->screen;
178 XTextProperty property;
179 int result;
181 result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
182 if (result == XNoMemory || result == XLocaleNotSupported) {
183 wwarning("window title conversion error... using STRING encoding");
184 XStoreName(scr->display, win->view->window, title);
185 } else {
186 XSetWMName(scr->display, win->view->window, &property);
187 if (property.value)
188 XFree(property.value);
191 XChangeProperty(scr->display, win->view->window,
192 scr->netwmName, scr->utf8String, 8,
193 PropModeReplace, (unsigned char *)title, strlen(title));
196 static void setMiniwindowTitle(WMWindow * win, const char *title)
198 WMScreen *scr = win->view->screen;
199 XTextProperty property;
200 int result;
202 result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
203 if (result == XNoMemory || result == XLocaleNotSupported) {
204 wwarning("icon title conversion error..using STRING encoding");
205 XSetIconName(scr->display, win->view->window, title);
206 } else {
207 XSetWMIconName(scr->display, win->view->window, &property);
208 if (property.value)
209 XFree(property.value);
212 XChangeProperty(scr->display, win->view->window,
213 scr->netwmIconName, scr->utf8String, 8,
214 PropModeReplace, (unsigned char *)title, strlen(title));
217 static void setMiniwindow(WMWindow *win, RImage *image)
219 WMScreen *scr = win->view->screen;
220 long *data;
221 int x, y;
222 int o;
224 if (!image)
225 return;
227 data = wmalloc((image->width * image->height + 2) * sizeof(long));
229 o = 0;
230 data[o++] = image->width;
231 data[o++] = image->height;
233 for (y = 0; y < image->height; y++) {
234 for (x = 0; x < image->width; x++) {
235 long pixel;
236 int offs = (x + y * image->width);
238 if (image->format == RRGBFormat)
239 pixel = image->data[offs * 3] << 16 | image->data[offs * 3 + 1] << 8
240 | image->data[offs * 3 + 2];
241 else
242 pixel = image->data[offs * 4] << 16 | image->data[offs * 4 + 1] << 8
243 | image->data[offs * 4 + 2] | image->data[offs * 4 + 3] << 24;
245 data[o++] = pixel;
249 XChangeProperty(scr->display, win->view->window, scr->netwmIcon,
250 XA_CARDINAL, 32, PropModeReplace,
251 (unsigned char *)data, (image->width * image->height + 2));
253 wfree(data);
256 void WMSetWindowTitle(WMWindow * win, const char *title)
258 if (win->title != NULL)
259 wfree(win->title);
260 if (title != NULL)
261 win->title = wstrdup(title);
262 else
263 win->title = NULL;
265 if (win->view->flags.realized) {
266 setWindowTitle(win, title);
270 void WMSetWindowCloseAction(WMWindow * win, WMAction * action, void *clientData)
272 Atom *atoms = NULL;
273 Atom *newAtoms;
274 int count;
275 WMScreen *scr = win->view->screen;
277 if (win->view->flags.realized) {
278 if (action && !win->closeAction) {
279 if (!XGetWMProtocols(scr->display, win->view->window, &atoms, &count)) {
280 count = 0;
282 newAtoms = wmalloc((count + 1) * sizeof(Atom));
283 if (count > 0)
284 memcpy(newAtoms, atoms, count * sizeof(Atom));
285 newAtoms[count++] = scr->deleteWindowAtom;
286 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
287 if (atoms)
288 XFree(atoms);
289 wfree(newAtoms);
290 } else if (!action && win->closeAction) {
291 int i, ncount;
293 if (XGetWMProtocols(scr->display, win->view->window, &atoms, &count) && count > 0) {
294 newAtoms = wmalloc((count - 1) * sizeof(Atom));
295 ncount = 0;
296 for (i = 0; i < count; i++) {
297 if (atoms[i] != scr->deleteWindowAtom) {
298 newAtoms[i] = atoms[i];
299 ncount++;
302 XSetWMProtocols(scr->display, win->view->window, newAtoms, ncount);
303 if (atoms)
304 XFree(atoms);
305 wfree(newAtoms);
309 win->closeAction = action;
310 win->closeData = clientData;
313 static void willResizeWindow(W_ViewDelegate * self, WMView * view, unsigned *width, unsigned *height)
315 WMWindow *win = (WMWindow *) view->self;
317 /* Parameter not used, but tell the compiler that it is ok */
318 (void) self;
320 if (win->minSize.width > 0 && win->minSize.height > 0) {
321 if (*width < win->minSize.width)
322 *width = win->minSize.width;
323 if (*height < win->minSize.height)
324 *height = win->minSize.height;
327 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
328 if (*width > win->maxSize.width)
329 *width = win->maxSize.width;
330 if (*height > win->maxSize.height)
331 *height = win->maxSize.height;
335 static void setSizeHints(WMWindow * win)
337 XSizeHints *hints;
339 hints = XAllocSizeHints();
340 if (!hints) {
341 wwarning("could not allocate memory for window size hints");
342 return;
345 hints->flags = 0;
347 if (win->flags.setPPos) {
348 hints->flags |= PPosition;
349 hints->x = win->ppos.x;
350 hints->y = win->ppos.y;
352 if (win->flags.setUPos) {
353 hints->flags |= USPosition;
354 hints->x = win->upos.x;
355 hints->y = win->upos.y;
357 if (win->minSize.width > 0 && win->minSize.height > 0) {
358 hints->flags |= PMinSize;
359 hints->min_width = win->minSize.width;
360 hints->min_height = win->minSize.height;
362 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
363 hints->flags |= PMaxSize;
364 hints->max_width = win->maxSize.width;
365 hints->max_height = win->maxSize.height;
367 if (win->baseSize.width > 0 && win->baseSize.height > 0) {
368 hints->flags |= PBaseSize;
369 hints->base_width = win->baseSize.width;
370 hints->base_height = win->baseSize.height;
372 if (win->resizeIncrement.width > 0 && win->resizeIncrement.height > 0) {
373 hints->flags |= PResizeInc;
374 hints->width_inc = win->resizeIncrement.width;
375 hints->height_inc = win->resizeIncrement.height;
377 if (win->flags.setAspect) {
378 hints->flags |= PAspect;
379 hints->min_aspect.x = win->minAspect.x;
380 hints->min_aspect.y = win->minAspect.y;
381 hints->max_aspect.x = win->maxAspect.x;
382 hints->max_aspect.y = win->maxAspect.y;
385 if (hints->flags) {
386 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
388 XFree(hints);
391 static void writeGNUstepWMAttr(WMScreen * scr, Window window, GNUstepWMAttributes * attr)
393 unsigned long data[9];
395 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
396 data[0] = attr->flags;
397 data[1] = attr->window_style;
398 data[2] = attr->window_level;
399 data[3] = 0; /* reserved */
400 /* The X protocol says XIDs are 32bit */
401 data[4] = attr->miniaturize_pixmap;
402 data[5] = attr->close_pixmap;
403 data[6] = attr->miniaturize_mask;
404 data[7] = attr->close_mask;
405 data[8] = attr->extra_flags;
406 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
407 32, PropModeReplace, (unsigned char *)data, 9);
410 static void setWindowMakerHints(WMWindow * win)
412 GNUstepWMAttributes attribs;
413 WMScreen *scr = WMWidgetScreen(win);
415 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
416 attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr | GSExtraFlagsAttr;
417 attribs.window_style = win->flags.style;
418 attribs.window_level = win->level;
419 if (win->flags.documentEdited)
420 attribs.extra_flags = GSDocumentEditedFlag;
421 else
422 attribs.extra_flags = 0;
424 writeGNUstepWMAttr(scr, win->view->window, &attribs);
427 static void realizeWindow(WMWindow * win)
429 XWMHints *hints;
430 XClassHint *classHint;
431 WMScreen *scr = win->view->screen;
432 Atom atoms[4];
433 int count;
435 classHint = XAllocClassHint();
436 classHint->res_name = win->wname;
437 classHint->res_class = WMGetApplicationName();
438 XSetClassHint(scr->display, win->view->window, classHint);
439 XFree(classHint);
441 hints = XAllocWMHints();
442 hints->flags = 0;
443 if (!scr->aflags.simpleApplication) {
444 hints->flags |= WindowGroupHint;
445 hints->window_group = scr->groupLeader;
447 if (win->miniImage) {
448 hints->flags |= IconPixmapHint;
449 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
450 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
451 if (hints->icon_mask != None) {
452 hints->flags |= IconMaskHint;
455 if (hints->flags != 0)
456 XSetWMHints(scr->display, win->view->window, hints);
457 XFree(hints);
459 count = 0;
460 if (win->closeAction) {
461 atoms[count++] = scr->deleteWindowAtom;
464 if (count > 0)
465 XSetWMProtocols(scr->display, win->view->window, atoms, count);
467 if (win->title || win->miniTitle)
468 XmbSetWMProperties(scr->display, win->view->window, win->title,
469 win->miniTitle, NULL, 0, NULL, NULL, NULL);
471 setWindowMakerHints(win);
473 setSizeHints(win);
475 if (win->owner) {
476 XSetTransientForHint(scr->display, win->view->window, win->owner->view->window);
479 if (win->title)
480 setWindowTitle(win, win->title);
483 void WMSetWindowAspectRatio(WMWindow * win, int minX, int minY, int maxX, int maxY)
485 win->flags.setAspect = 1;
486 win->minAspect.x = minX;
487 win->minAspect.y = minY;
488 win->maxAspect.x = maxX;
489 win->maxAspect.y = maxY;
490 if (win->view->flags.realized)
491 setSizeHints(win);
494 void WMSetWindowInitialPosition(WMWindow * win, int x, int y)
496 win->flags.setPPos = 1;
497 win->ppos.x = x;
498 win->ppos.y = y;
499 if (win->view->flags.realized)
500 setSizeHints(win);
501 WMMoveWidget(win, x, y);
504 void WMSetWindowUserPosition(WMWindow * win, int x, int y)
506 win->flags.setUPos = 1;
507 win->upos.x = x;
508 win->upos.y = y;
509 if (win->view->flags.realized)
510 setSizeHints(win);
511 WMMoveWidget(win, x, y);
514 void WMSetWindowMinSize(WMWindow * win, unsigned width, unsigned height)
516 win->minSize.width = width;
517 win->minSize.height = height;
518 if (win->view->flags.realized)
519 setSizeHints(win);
522 void WMSetWindowMaxSize(WMWindow * win, unsigned width, unsigned height)
524 win->maxSize.width = width;
525 win->maxSize.height = height;
526 if (win->view->flags.realized)
527 setSizeHints(win);
530 void WMSetWindowBaseSize(WMWindow * win, unsigned width, unsigned height)
532 /* TODO: validate sizes */
533 win->baseSize.width = width;
534 win->baseSize.height = height;
535 if (win->view->flags.realized)
536 setSizeHints(win);
539 void WMSetWindowResizeIncrements(WMWindow * win, unsigned wIncr, unsigned hIncr)
541 win->resizeIncrement.width = wIncr;
542 win->resizeIncrement.height = hIncr;
543 if (win->view->flags.realized)
544 setSizeHints(win);
547 void WMSetWindowLevel(WMWindow * win, int level)
549 win->level = level;
550 if (win->view->flags.realized)
551 setWindowMakerHints(win);
554 void WMSetWindowDocumentEdited(WMWindow * win, Bool flag)
556 flag = ((flag == 0) ? 0 : 1);
557 if (win->flags.documentEdited != flag) {
558 win->flags.documentEdited = flag;
559 if (win->view->flags.realized)
560 setWindowMakerHints(win);
564 void WMSetWindowMiniwindowImage(WMWindow * win, RImage * image)
566 if (win->view->flags.realized)
567 setMiniwindow(win, image);
570 void WMSetWindowMiniwindowPixmap(WMWindow * win, WMPixmap * pixmap)
572 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
573 if (win->miniImage)
574 WMReleasePixmap(win->miniImage);
576 if (pixmap)
577 win->miniImage = WMRetainPixmap(pixmap);
578 else
579 win->miniImage = NULL;
581 if (win->view->flags.realized) {
582 XWMHints *hints;
584 hints = XGetWMHints(win->view->screen->display, win->view->window);
585 if (!hints) {
586 hints = XAllocWMHints();
587 if (!hints) {
588 wwarning("could not allocate memory for WM hints");
589 return;
591 hints->flags = 0;
593 if (pixmap) {
594 hints->flags |= IconPixmapHint;
595 hints->icon_pixmap = WMGetPixmapXID(pixmap);
596 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
597 if (hints->icon_mask != None) {
598 hints->flags |= IconMaskHint;
601 XSetWMHints(win->view->screen->display, win->view->window, hints);
602 XFree(hints);
607 void WMSetWindowMiniwindowTitle(WMWindow * win, const char *title)
609 if ((win->miniTitle && !title) || (!win->miniTitle && title)
610 || (title && win->miniTitle && strcoll(title, win->miniTitle) != 0)) {
611 if (win->miniTitle)
612 wfree(win->miniTitle);
614 if (title)
615 win->miniTitle = wstrdup(title);
616 else
617 win->miniTitle = NULL;
619 if (win->view->flags.realized) {
620 setMiniwindowTitle(win, title);
625 void WMCloseWindow(WMWindow * win)
627 WMUnmapWidget(win);
628 /* withdraw the window */
629 if (win->view->flags.realized)
630 XWithdrawWindow(win->view->screen->display, win->view->window, win->view->screen->screen);
633 static void handleEvents(XEvent * event, void *clientData)
635 _Window *win = (_Window *) clientData;
636 W_View *view = win->view;
638 switch (event->type) {
639 case ClientMessage:
640 if (event->xclient.message_type == win->view->screen->protocolsAtom
641 && event->xclient.format == 32
642 && event->xclient.data.l[0] == win->view->screen->deleteWindowAtom) {
644 if (win->closeAction) {
645 (*win->closeAction) (win, win->closeData);
648 break;
650 * was causing windows to ignore commands like closeWindow
651 * after the windows is iconized/restored or a workspace change
652 * if this is really needed, put the MapNotify portion too and
653 * fix the restack bug in wmaker
654 case UnmapNotify:
655 WMUnmapWidget(win);
656 break;
658 case MapNotify:
659 WMMapWidget(win);
660 break;
663 case DestroyNotify:
664 destroyWindow(win);
665 break;
667 case ConfigureNotify:
668 if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) {
670 view->size.width = event->xconfigure.width;
671 view->size.height = event->xconfigure.height;
673 if (view->flags.notifySizeChanged) {
674 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
677 if (event->xconfigure.x != view->pos.x || event->xconfigure.y != view->pos.y) {
679 if (event->xconfigure.send_event) {
680 view->pos.x = event->xconfigure.x;
681 view->pos.y = event->xconfigure.y;
682 } else {
683 Window foo;
685 XTranslateCoordinates(view->screen->display,
686 view->window, view->screen->rootWin,
687 event->xconfigure.x, event->xconfigure.y,
688 &view->pos.x, &view->pos.y, &foo);
691 break;
695 static void destroyWindow(_Window * win)
697 WMScreen *scr = win->view->screen;
699 WMRemoveNotificationObserver(win);
701 if (scr->windowList == win) {
702 scr->windowList = scr->windowList->nextPtr;
703 } else {
704 WMWindow *ptr;
705 ptr = scr->windowList;
707 if (ptr) {
708 while (ptr->nextPtr) {
709 if (ptr->nextPtr == win) {
710 ptr->nextPtr = ptr->nextPtr->nextPtr;
711 break;
713 ptr = ptr->nextPtr;
718 if (win->title) {
719 wfree(win->title);
722 if (win->miniTitle) {
723 wfree(win->miniTitle);
726 if (win->miniImage) {
727 WMReleasePixmap(win->miniImage);
730 if (win->wname)
731 wfree(win->wname);
733 wfree(win);