wmaker: removed unused constant SCROLL_STEPS in the switchpanel code
[wmaker-crm.git] / WINGs / wwindow.c
blob503611d0bb50f2b75f4e4c4725128e522b94c48e
2 #include <X11/Xmd.h>
4 #include "WINGsP.h"
6 #include "GNUstep.h"
8 #include <X11/Xatom.h>
10 typedef struct W_Window {
11 W_Class widgetClass;
12 W_View *view;
14 struct W_Window *nextPtr; /* next in the window list */
16 struct W_Window *owner;
18 char *title;
20 WMPixmap *miniImage; /* miniwindow */
21 char *miniTitle;
23 char *wname;
25 WMSize resizeIncrement;
26 WMSize baseSize;
27 WMSize minSize;
28 WMSize maxSize;
29 WMPoint minAspect;
30 WMPoint maxAspect;
32 WMPoint upos;
33 WMPoint ppos;
35 WMAction *closeAction;
36 void *closeData;
38 int level;
40 struct {
41 unsigned style:4;
42 unsigned configured:1;
43 unsigned documentEdited:1;
45 unsigned setUPos:1;
46 unsigned setPPos:1;
47 unsigned setAspect:1;
48 } flags;
49 } _Window;
52 static void willResizeWindow(W_ViewDelegate *, WMView *, unsigned *, unsigned *);
54 struct W_ViewDelegate _WindowViewDelegate = {
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 willResizeWindow
62 #define DEFAULT_WIDTH 400
63 #define DEFAULT_HEIGHT 180
65 static void destroyWindow(_Window * win);
67 static void handleEvents(XEvent * event, void *clientData);
69 static void realizeWindow(WMWindow * win);
71 static void realizeObserver(void *self, WMNotification * not)
73 /* Parameter not used, but tell the compiler that it is ok */
74 (void) not;
76 realizeWindow(self);
79 WMWindow *WMCreatePanelWithStyleForWindow(WMWindow * owner, const char *name, int style)
81 WMWindow *win;
83 win = WMCreateWindowWithStyle(owner->view->screen, name, style);
84 win->owner = owner;
86 return win;
89 WMWindow *WMCreatePanelForWindow(WMWindow * owner, const char *name)
91 return WMCreatePanelWithStyleForWindow(owner, name,
92 WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
95 void WMChangePanelOwner(WMWindow * win, WMWindow * newOwner)
97 win->owner = newOwner;
99 if (win->view->flags.realized && newOwner) {
100 XSetTransientForHint(win->view->screen->display, win->view->window, newOwner->view->window);
104 WMWindow *WMCreateWindow(WMScreen * screen, const char *name)
106 return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
107 | WMClosableWindowMask
108 | WMMiniaturizableWindowMask | WMResizableWindowMask);
111 WMWindow *WMCreateWindowWithStyle(WMScreen * screen, const char *name, int style)
113 _Window *win;
115 win = wmalloc(sizeof(_Window));
116 win->widgetClass = WC_Window;
118 win->view = W_CreateTopView(screen);
119 if (!win->view) {
120 wfree(win);
121 return NULL;
123 win->view->self = win;
125 win->view->delegate = &_WindowViewDelegate;
127 win->wname = wstrdup(name);
129 /* add to the window list of the screen (application) */
130 win->nextPtr = screen->windowList;
131 screen->windowList = win;
133 WMCreateEventHandler(win->view, ExposureMask | StructureNotifyMask
134 | ClientMessageMask | FocusChangeMask, handleEvents, win);
136 W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
138 WMAddNotificationObserver(realizeObserver, win, WMViewRealizedNotification, win->view);
140 win->flags.style = style;
142 win->level = WMNormalWindowLevel;
144 /* kluge. Find a better solution */
145 W_SetFocusOfTopLevel(win->view, win->view);
147 return win;
150 static void setWindowTitle(WMWindow * win, const char *title)
152 WMScreen *scr = win->view->screen;
153 XTextProperty property;
154 int result;
156 result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
157 if (result == XNoMemory || result == XLocaleNotSupported) {
158 wwarning("window title conversion error... using STRING encoding");
159 XStoreName(scr->display, win->view->window, title);
160 } else {
161 XSetWMName(scr->display, win->view->window, &property);
162 if (property.value)
163 XFree(property.value);
166 XChangeProperty(scr->display, win->view->window,
167 scr->netwmName, scr->utf8String, 8,
168 PropModeReplace, (unsigned char *)title, strlen(title));
171 static void setMiniwindowTitle(WMWindow * win, const char *title)
173 WMScreen *scr = win->view->screen;
174 XTextProperty property;
175 int result;
177 result = XmbTextListToTextProperty(scr->display, (char **)&title, 1, XStdICCTextStyle, &property);
178 if (result == XNoMemory || result == XLocaleNotSupported) {
179 wwarning("icon title conversion error..using STRING encoding");
180 XSetIconName(scr->display, win->view->window, title);
181 } else {
182 XSetWMIconName(scr->display, win->view->window, &property);
183 if (property.value)
184 XFree(property.value);
187 XChangeProperty(scr->display, win->view->window,
188 scr->netwmIconName, scr->utf8String, 8,
189 PropModeReplace, (unsigned char *)title, strlen(title));
192 static void setMiniwindow(WMWindow *win, RImage *image)
194 WMScreen *scr = win->view->screen;
195 unsigned long *data;
196 int x, y;
197 int o;
199 if (!image)
200 return;
202 data = wmalloc((image->width * image->height + 2) * sizeof(long));
204 o = 0;
205 data[o++] = image->width;
206 data[o++] = image->height;
208 for (y = 0; y < image->height; y++) {
209 for (x = 0; x < image->width; x++) {
210 unsigned long pixel;
211 int offs = (x + y * image->width);
213 if (image->format == RRGBFormat) {
214 pixel = ((unsigned long) image->data[offs * 3 ]) << 16;
215 pixel |= ((unsigned long) image->data[offs * 3 + 1]) << 8;
216 pixel |= ((unsigned long) image->data[offs * 3 + 2]);
217 } else {
218 pixel = ((unsigned long) image->data[offs * 4 ]) << 16;
219 pixel |= ((unsigned long) image->data[offs * 4 + 1]) << 8;
220 pixel |= ((unsigned long) image->data[offs * 4 + 2]);
221 pixel |= ((unsigned long) image->data[offs * 4 + 3]) << 24;
224 data[o++] = pixel;
228 XChangeProperty(scr->display, win->view->window, scr->netwmIcon,
229 XA_CARDINAL, 32, PropModeReplace,
230 (unsigned char *)data, (image->width * image->height + 2));
232 wfree(data);
235 void WMSetWindowTitle(WMWindow * win, const char *title)
237 wassertr(title != NULL);
239 if (win->title != NULL)
240 wfree(win->title);
242 win->title = wstrdup(title);
244 if (win->view->flags.realized) {
245 setWindowTitle(win, title);
249 void WMSetWindowCloseAction(WMWindow * win, WMAction * action, void *clientData)
251 Atom *atoms = NULL;
252 Atom *newAtoms;
253 int count;
254 WMScreen *scr = win->view->screen;
256 if (win->view->flags.realized) {
257 if (action && !win->closeAction) {
258 if (!XGetWMProtocols(scr->display, win->view->window, &atoms, &count)) {
259 count = 0;
261 newAtoms = wmalloc((count + 1) * sizeof(Atom));
262 if (count > 0)
263 memcpy(newAtoms, atoms, count * sizeof(Atom));
264 newAtoms[count++] = scr->deleteWindowAtom;
265 XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
266 if (atoms)
267 XFree(atoms);
268 wfree(newAtoms);
269 } else if (!action && win->closeAction) {
270 int i, ncount;
272 if (XGetWMProtocols(scr->display, win->view->window, &atoms, &count) && count > 0) {
273 newAtoms = wmalloc((count - 1) * sizeof(Atom));
274 ncount = 0;
275 for (i = 0; i < count; i++) {
276 if (atoms[i] != scr->deleteWindowAtom) {
277 newAtoms[i] = atoms[i];
278 ncount++;
281 XSetWMProtocols(scr->display, win->view->window, newAtoms, ncount);
282 if (atoms)
283 XFree(atoms);
284 wfree(newAtoms);
288 win->closeAction = action;
289 win->closeData = clientData;
292 static void willResizeWindow(W_ViewDelegate * self, WMView * view, unsigned *width, unsigned *height)
294 WMWindow *win = (WMWindow *) view->self;
296 /* Parameter not used, but tell the compiler that it is ok */
297 (void) self;
299 if (win->minSize.width > 0 && win->minSize.height > 0) {
300 if (*width < win->minSize.width)
301 *width = win->minSize.width;
302 if (*height < win->minSize.height)
303 *height = win->minSize.height;
306 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
307 if (*width > win->maxSize.width)
308 *width = win->maxSize.width;
309 if (*height > win->maxSize.height)
310 *height = win->maxSize.height;
314 static void setSizeHints(WMWindow * win)
316 XSizeHints *hints;
318 hints = XAllocSizeHints();
319 if (!hints) {
320 wwarning("could not allocate memory for window size hints");
321 return;
324 hints->flags = 0;
326 if (win->flags.setPPos) {
327 hints->flags |= PPosition;
328 hints->x = win->ppos.x;
329 hints->y = win->ppos.y;
331 if (win->flags.setUPos) {
332 hints->flags |= USPosition;
333 hints->x = win->upos.x;
334 hints->y = win->upos.y;
336 if (win->minSize.width > 0 && win->minSize.height > 0) {
337 hints->flags |= PMinSize;
338 hints->min_width = win->minSize.width;
339 hints->min_height = win->minSize.height;
341 if (win->maxSize.width > 0 && win->maxSize.height > 0) {
342 hints->flags |= PMaxSize;
343 hints->max_width = win->maxSize.width;
344 hints->max_height = win->maxSize.height;
346 if (win->baseSize.width > 0 && win->baseSize.height > 0) {
347 hints->flags |= PBaseSize;
348 hints->base_width = win->baseSize.width;
349 hints->base_height = win->baseSize.height;
351 if (win->resizeIncrement.width > 0 && win->resizeIncrement.height > 0) {
352 hints->flags |= PResizeInc;
353 hints->width_inc = win->resizeIncrement.width;
354 hints->height_inc = win->resizeIncrement.height;
356 if (win->flags.setAspect) {
357 hints->flags |= PAspect;
358 hints->min_aspect.x = win->minAspect.x;
359 hints->min_aspect.y = win->minAspect.y;
360 hints->max_aspect.x = win->maxAspect.x;
361 hints->max_aspect.y = win->maxAspect.y;
364 if (hints->flags) {
365 XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
367 XFree(hints);
370 static void writeGNUstepWMAttr(WMScreen * scr, Window window, GNUstepWMAttributes * attr)
372 unsigned long data[9];
374 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
375 data[0] = attr->flags;
376 data[1] = attr->window_style;
377 data[2] = attr->window_level;
378 data[3] = 0; /* reserved */
379 /* The X protocol says XIDs are 32bit */
380 data[4] = attr->miniaturize_pixmap;
381 data[5] = attr->close_pixmap;
382 data[6] = attr->miniaturize_mask;
383 data[7] = attr->close_mask;
384 data[8] = attr->extra_flags;
385 XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
386 32, PropModeReplace, (unsigned char *)data, 9);
389 static void setWindowMakerHints(WMWindow * win)
391 GNUstepWMAttributes attribs;
392 WMScreen *scr = WMWidgetScreen(win);
394 memset(&attribs, 0, sizeof(GNUstepWMAttributes));
395 attribs.flags = GSWindowStyleAttr | GSWindowLevelAttr | GSExtraFlagsAttr;
396 attribs.window_style = win->flags.style;
397 attribs.window_level = win->level;
398 if (win->flags.documentEdited)
399 attribs.extra_flags = GSDocumentEditedFlag;
400 else
401 attribs.extra_flags = 0;
403 writeGNUstepWMAttr(scr, win->view->window, &attribs);
406 static void realizeWindow(WMWindow * win)
408 XWMHints *hints;
409 XClassHint *classHint;
410 WMScreen *scr = win->view->screen;
411 Atom atoms[4];
412 int count;
414 classHint = XAllocClassHint();
415 classHint->res_name = win->wname;
416 classHint->res_class = WMGetApplicationName();
417 XSetClassHint(scr->display, win->view->window, classHint);
418 XFree(classHint);
420 hints = XAllocWMHints();
421 hints->flags = 0;
422 if (!scr->aflags.simpleApplication) {
423 hints->flags |= WindowGroupHint;
424 hints->window_group = scr->groupLeader;
426 if (win->miniImage) {
427 hints->flags |= IconPixmapHint;
428 hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
429 hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
430 if (hints->icon_mask != None) {
431 hints->flags |= IconMaskHint;
434 if (hints->flags != 0)
435 XSetWMHints(scr->display, win->view->window, hints);
436 XFree(hints);
438 count = 0;
439 if (win->closeAction) {
440 atoms[count++] = scr->deleteWindowAtom;
443 if (count > 0)
444 XSetWMProtocols(scr->display, win->view->window, atoms, count);
446 if (win->title || win->miniTitle)
447 XmbSetWMProperties(scr->display, win->view->window, win->title,
448 win->miniTitle, NULL, 0, NULL, NULL, NULL);
450 setWindowMakerHints(win);
452 setSizeHints(win);
454 if (win->owner) {
455 XSetTransientForHint(scr->display, win->view->window, win->owner->view->window);
458 if (win->title)
459 setWindowTitle(win, win->title);
462 void WMSetWindowAspectRatio(WMWindow * win, int minX, int minY, int maxX, int maxY)
464 win->flags.setAspect = 1;
465 win->minAspect.x = minX;
466 win->minAspect.y = minY;
467 win->maxAspect.x = maxX;
468 win->maxAspect.y = maxY;
469 if (win->view->flags.realized)
470 setSizeHints(win);
473 void WMSetWindowInitialPosition(WMWindow * win, int x, int y)
475 win->flags.setPPos = 1;
476 win->ppos.x = x;
477 win->ppos.y = y;
478 if (win->view->flags.realized)
479 setSizeHints(win);
480 WMMoveWidget(win, x, y);
483 void WMSetWindowUserPosition(WMWindow * win, int x, int y)
485 win->flags.setUPos = 1;
486 win->upos.x = x;
487 win->upos.y = y;
488 if (win->view->flags.realized)
489 setSizeHints(win);
490 WMMoveWidget(win, x, y);
493 void WMSetWindowMinSize(WMWindow * win, unsigned width, unsigned height)
495 win->minSize.width = width;
496 win->minSize.height = height;
497 if (win->view->flags.realized)
498 setSizeHints(win);
501 void WMSetWindowMaxSize(WMWindow * win, unsigned width, unsigned height)
503 win->maxSize.width = width;
504 win->maxSize.height = height;
505 if (win->view->flags.realized)
506 setSizeHints(win);
509 void WMSetWindowBaseSize(WMWindow * win, unsigned width, unsigned height)
511 /* TODO: validate sizes */
512 win->baseSize.width = width;
513 win->baseSize.height = height;
514 if (win->view->flags.realized)
515 setSizeHints(win);
518 void WMSetWindowResizeIncrements(WMWindow * win, unsigned wIncr, unsigned hIncr)
520 win->resizeIncrement.width = wIncr;
521 win->resizeIncrement.height = hIncr;
522 if (win->view->flags.realized)
523 setSizeHints(win);
526 void WMSetWindowLevel(WMWindow * win, int level)
528 win->level = level;
529 if (win->view->flags.realized)
530 setWindowMakerHints(win);
533 void WMSetWindowDocumentEdited(WMWindow * win, Bool flag)
535 flag = ((flag == 0) ? 0 : 1);
536 if (win->flags.documentEdited != flag) {
537 win->flags.documentEdited = flag;
538 if (win->view->flags.realized)
539 setWindowMakerHints(win);
543 void WMSetWindowMiniwindowImage(WMWindow * win, RImage * image)
545 if (win->view->flags.realized)
546 setMiniwindow(win, image);
549 void WMSetWindowMiniwindowPixmap(WMWindow * win, WMPixmap * pixmap)
551 if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
552 if (win->miniImage)
553 WMReleasePixmap(win->miniImage);
555 if (pixmap)
556 win->miniImage = WMRetainPixmap(pixmap);
557 else
558 win->miniImage = NULL;
560 if (win->view->flags.realized) {
561 XWMHints *hints;
563 hints = XGetWMHints(win->view->screen->display, win->view->window);
564 if (!hints) {
565 hints = XAllocWMHints();
566 if (!hints) {
567 wwarning("could not allocate memory for WM hints");
568 return;
570 hints->flags = 0;
572 if (pixmap) {
573 hints->flags |= IconPixmapHint;
574 hints->icon_pixmap = WMGetPixmapXID(pixmap);
575 hints->icon_mask = WMGetPixmapMaskXID(pixmap);
576 if (hints->icon_mask != None) {
577 hints->flags |= IconMaskHint;
580 XSetWMHints(win->view->screen->display, win->view->window, hints);
581 XFree(hints);
586 void WMSetWindowMiniwindowTitle(WMWindow * win, const char *title)
588 if (win && ((win->miniTitle && !title) || (!win->miniTitle && title)
589 || (title && win->miniTitle && strcoll(title, win->miniTitle) != 0))) {
590 if (win->miniTitle)
591 wfree(win->miniTitle);
593 if (title)
594 win->miniTitle = wstrdup(title);
595 else
596 win->miniTitle = NULL;
598 if (win->view->flags.realized) {
599 setMiniwindowTitle(win, title);
604 void WMCloseWindow(WMWindow * win)
606 WMUnmapWidget(win);
607 /* withdraw the window */
608 if (win->view->flags.realized)
609 XWithdrawWindow(win->view->screen->display, win->view->window, win->view->screen->screen);
612 static void handleEvents(XEvent * event, void *clientData)
614 _Window *win = (_Window *) clientData;
615 W_View *view = win->view;
617 switch (event->type) {
618 case ClientMessage:
619 if (event->xclient.message_type == win->view->screen->protocolsAtom
620 && event->xclient.format == 32
621 && event->xclient.data.l[0] == win->view->screen->deleteWindowAtom) {
623 if (win->closeAction) {
624 (*win->closeAction) (win, win->closeData);
627 break;
629 * was causing windows to ignore commands like closeWindow
630 * after the windows is iconized/restored or a workspace change
631 * if this is really needed, put the MapNotify portion too and
632 * fix the restack bug in wmaker
633 case UnmapNotify:
634 WMUnmapWidget(win);
635 break;
637 case MapNotify:
638 WMMapWidget(win);
639 break;
642 case DestroyNotify:
643 destroyWindow(win);
644 break;
646 case ConfigureNotify:
647 if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) {
649 view->size.width = event->xconfigure.width;
650 view->size.height = event->xconfigure.height;
652 if (view->flags.notifySizeChanged) {
653 WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
656 if (event->xconfigure.x != view->pos.x || event->xconfigure.y != view->pos.y) {
658 if (event->xconfigure.send_event) {
659 view->pos.x = event->xconfigure.x;
660 view->pos.y = event->xconfigure.y;
661 } else {
662 Window foo;
664 XTranslateCoordinates(view->screen->display,
665 view->window, view->screen->rootWin,
666 event->xconfigure.x, event->xconfigure.y,
667 &view->pos.x, &view->pos.y, &foo);
670 break;
674 static void destroyWindow(_Window * win)
676 WMScreen *scr = win->view->screen;
678 WMRemoveNotificationObserver(win);
680 if (scr->windowList == win) {
681 scr->windowList = scr->windowList->nextPtr;
682 } else {
683 WMWindow *ptr;
684 ptr = scr->windowList;
686 if (ptr) {
687 while (ptr->nextPtr) {
688 if (ptr->nextPtr == win) {
689 ptr->nextPtr = ptr->nextPtr->nextPtr;
690 break;
692 ptr = ptr->nextPtr;
697 if (win->title) {
698 wfree(win->title);
701 if (win->miniTitle) {
702 wfree(win->miniTitle);
705 if (win->miniImage) {
706 WMReleasePixmap(win->miniImage);
709 if (win->wname)
710 wfree(win->wname);
712 wfree(win);