9 typedef struct W_Window
{
13 struct W_Window
*nextPtr
; /* next in the window list */
15 struct W_Window
*owner
;
19 WMPixmap
*miniImage
; /* miniwindow */
24 WMSize resizeIncrement
;
34 WMAction
*closeAction
;
41 unsigned configured
:1;
42 unsigned documentEdited
:1;
57 Pixmap miniaturize_pixmap
; /* pixmap for miniaturize button */
58 Pixmap close_pixmap
; /* pixmap for close button */
59 Pixmap miniaturize_mask
; /* miniaturize pixmap mask */
60 Pixmap close_mask
; /* close pixmap mask */
62 } GNUstepWMAttributes
;
64 #define GSWindowStyleAttr (1<<0)
65 #define GSWindowLevelAttr (1<<1)
66 #define GSMiniaturizePixmapAttr (1<<3)
67 #define GSClosePixmapAttr (1<<4)
68 #define GSMiniaturizeMaskAttr (1<<5)
69 #define GSCloseMaskAttr (1<<6)
70 #define GSExtraFlagsAttr (1<<7)
73 #define GSDocumentEditedFlag (1<<0)
74 #define GSNoApplicationIconFlag (1<<5)
76 #define WMFHideOtherApplications 10
77 #define WMFHideApplication 12
81 static void willResizeWindow(W_ViewDelegate
*, WMView
*, unsigned*, unsigned*);
83 struct W_ViewDelegate _WindowViewDelegate
= {
92 #define DEFAULT_WIDTH 400
93 #define DEFAULT_HEIGHT 180
94 #define DEFAULT_TITLE ""
97 static void destroyWindow(_Window
*win
);
99 static void handleEvents();
101 static void realizeWindow();
104 realizeObserver(void *self
, WMNotification
*not)
111 WMCreatePanelWithStyleForWindow(WMWindow
*owner
, char *name
, int style
)
115 win
= WMCreateWindowWithStyle(owner
->view
->screen
, name
, style
);
124 WMCreatePanelForWindow(WMWindow
*owner
, char *name
)
126 return WMCreatePanelWithStyleForWindow(owner
, name
,
128 |WMClosableWindowMask
129 |WMResizableWindowMask
);
134 WMChangePanelOwner(WMWindow
*win
, WMWindow
*newOwner
)
136 win
->owner
= newOwner
;
138 if (win
->view
->flags
.realized
&& newOwner
) {
139 XSetTransientForHint(win
->view
->screen
->display
, win
->view
->window
,
140 newOwner
->view
->window
);
147 WMCreateWindow(WMScreen
*screen
, char *name
)
149 return WMCreateWindowWithStyle(screen
, name
, WMTitledWindowMask
150 |WMClosableWindowMask
151 |WMMiniaturizableWindowMask
152 |WMResizableWindowMask
);
158 WMCreateWindowWithStyle(WMScreen
*screen
, char *name
, int style
)
162 win
= wmalloc(sizeof(_Window
));
163 memset(win
, 0, sizeof(_Window
));
165 win
->widgetClass
= WC_Window
;
167 win
->view
= W_CreateTopView(screen
);
172 win
->view
->self
= win
;
174 win
->view
->delegate
= &_WindowViewDelegate
;
176 win
->wname
= wstrdup(name
);
178 /* add to the window list of the screen (application) */
179 win
->nextPtr
= screen
->windowList
;
180 screen
->windowList
= win
;
182 WMCreateEventHandler(win
->view
, ExposureMask
|StructureNotifyMask
183 |ClientMessageMask
|FocusChangeMask
,
186 W_ResizeView(win
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
188 WMAddNotificationObserver(realizeObserver
, win
,
189 WMViewRealizedNotification
, win
->view
);
191 win
->flags
.style
= style
;
193 win
->level
= WMNormalWindowLevel
;
195 /* kluge. Find a better solution */
196 W_SetFocusOfTopLevel(win
->view
, win
->view
);
204 setWindowTitle(WMWindow
*win
, const char *title
)
206 WMScreen
*scr
= win
->view
->screen
;
207 XTextProperty property
;
210 result
= XmbTextListToTextProperty(scr
->display
,
211 (char**)&title
, 1, XStdICCTextStyle
,
213 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
214 wwarning("window title conversion error... using STRING encoding");
215 XStoreName(scr
->display
, win
->view
->window
, title
);
217 XSetWMName(scr
->display
, win
->view
->window
, &property
);
219 XFree(property
.value
);
222 XChangeProperty(scr
->display
, win
->view
->window
,
223 scr
->netwmName
, scr
->utf8String
, 8,
224 PropModeReplace
, (unsigned char *)title
, strlen(title
));
229 setMiniwindowTitle(WMWindow
*win
, const char *title
)
231 WMScreen
*scr
= win
->view
->screen
;
232 XTextProperty property
;
235 result
= XmbTextListToTextProperty(scr
->display
,
236 (char**)&title
, 1, XStdICCTextStyle
,
238 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
239 wwarning("icon title conversion error..using STRING encoding");
240 XSetIconName(scr
->display
, win
->view
->window
, title
);
242 XSetWMIconName(scr
->display
, win
->view
->window
, &property
);
244 XFree(property
.value
);
247 XChangeProperty(scr
->display
, win
->view
->window
,
248 scr
->netwmIconName
, scr
->utf8String
, 8,
249 PropModeReplace
, (unsigned char *)title
, strlen(title
));
254 setMiniwindow(WMWindow
*win
, RImage
*image
)
256 WMScreen
*scr
= win
->view
->screen
;
264 data
= wmalloc((image
->width
* image
->height
+ 2) * sizeof(CARD32
));
267 data
[o
++] = image
->width
;
268 data
[o
++] = image
->height
;
270 for (y
= 0; y
< image
->height
; y
++) {
271 for (x
= 0; x
< image
->width
; x
++) {
273 int offs
= (x
+y
*image
->width
);
275 if (image
->format
== RRGBFormat
)
276 pixel
= image
->data
[offs
*3]<<16 | image
->data
[offs
*3+1]<<8 | image
->data
[offs
*3+2];
278 pixel
= image
->data
[offs
*4]<<16 | image
->data
[offs
*4+1]<<8 | image
->data
[offs
*4+2] | image
->data
[offs
*4+3] << 24;
284 XChangeProperty(scr
->display
, win
->view
->window
, scr
->netwmIcon
,
285 XA_CARDINAL
, 32, PropModeReplace
,
286 (unsigned char *)data
,
287 (image
->width
* image
->height
+ 2));
294 WMSetWindowTitle(WMWindow
*win
, char *title
)
296 if (win
->title
!=NULL
)
299 win
->title
= wstrdup(title
);
303 if (win
->view
->flags
.realized
) {
304 setWindowTitle(win
, title
);
312 WMSetWindowCloseAction(WMWindow
*win
, WMAction
*action
, void *clientData
)
317 WMScreen
*scr
= win
->view
->screen
;
319 if (win
->view
->flags
.realized
) {
320 if (action
&& !win
->closeAction
) {
321 if (!XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
325 newAtoms
= wmalloc((count
+1)*sizeof(Atom
));
327 memcpy(newAtoms
, atoms
, count
*sizeof(Atom
));
328 newAtoms
[count
++] = scr
->deleteWindowAtom
;
329 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
, count
);
333 } else if (!action
&& win
->closeAction
) {
336 if (XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
337 &count
) && count
>0) {
338 newAtoms
= wmalloc((count
-1)*sizeof(Atom
));
340 for (i
=0; i
< count
; i
++) {
341 if (atoms
[i
]!=scr
->deleteWindowAtom
) {
342 newAtoms
[i
] = atoms
[i
];
346 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
,
354 win
->closeAction
= action
;
355 win
->closeData
= clientData
;
361 willResizeWindow(W_ViewDelegate
*self
, WMView
*view
,
362 unsigned *width
, unsigned *height
)
364 WMWindow
*win
= (WMWindow
*)view
->self
;
366 if (win
->minSize
.width
> 0 && win
->minSize
.height
> 0) {
367 if (*width
< win
->minSize
.width
)
368 *width
= win
->minSize
.width
;
369 if (*height
< win
->minSize
.height
)
370 *height
= win
->minSize
.height
;
373 if (win
->maxSize
.width
> 0 && win
->maxSize
.height
> 0) {
374 if (*width
> win
->maxSize
.width
)
375 *width
= win
->maxSize
.width
;
376 if (*height
> win
->maxSize
.height
)
377 *height
= win
->maxSize
.height
;
383 setSizeHints(WMWindow
*win
)
387 hints
= XAllocSizeHints();
389 wwarning("could not allocate memory for window size hints");
395 if (win
->flags
.setPPos
) {
396 hints
->flags
|= PPosition
;
397 hints
->x
= win
->ppos
.x
;
398 hints
->y
= win
->ppos
.y
;
400 if (win
->flags
.setUPos
) {
401 hints
->flags
|= USPosition
;
402 hints
->x
= win
->upos
.x
;
403 hints
->y
= win
->upos
.y
;
405 if (win
->minSize
.width
>0 && win
->minSize
.height
>0) {
406 hints
->flags
|= PMinSize
;
407 hints
->min_width
= win
->minSize
.width
;
408 hints
->min_height
= win
->minSize
.height
;
410 if (win
->maxSize
.width
>0 && win
->maxSize
.height
>0) {
411 hints
->flags
|= PMaxSize
;
412 hints
->max_width
= win
->maxSize
.width
;
413 hints
->max_height
= win
->maxSize
.height
;
415 if (win
->baseSize
.width
>0 && win
->baseSize
.height
>0) {
416 hints
->flags
|= PBaseSize
;
417 hints
->base_width
= win
->baseSize
.width
;
418 hints
->base_height
= win
->baseSize
.height
;
420 if (win
->resizeIncrement
.width
>0 && win
->resizeIncrement
.height
>0) {
421 hints
->flags
|= PResizeInc
;
422 hints
->width_inc
= win
->resizeIncrement
.width
;
423 hints
->height_inc
= win
->resizeIncrement
.height
;
425 if (win
->flags
.setAspect
) {
426 hints
->flags
|= PAspect
;
427 hints
->min_aspect
.x
= win
->minAspect
.x
;
428 hints
->min_aspect
.y
= win
->minAspect
.y
;
429 hints
->max_aspect
.x
= win
->maxAspect
.x
;
430 hints
->max_aspect
.y
= win
->maxAspect
.y
;
435 XSetWMNormalHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
443 writeGNUstepWMAttr(WMScreen
*scr
, Window window
, GNUstepWMAttributes
*attr
)
445 unsigned long data
[9];
447 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
448 data
[0] = attr
->flags
;
449 data
[1] = attr
->window_style
;
450 data
[2] = attr
->window_level
;
451 data
[3] = 0; /* reserved */
452 /* The X protocol says XIDs are 32bit */
453 data
[4] = attr
->miniaturize_pixmap
;
454 data
[5] = attr
->close_pixmap
;
455 data
[6] = attr
->miniaturize_mask
;
456 data
[7] = attr
->close_mask
;
457 data
[8] = attr
->extra_flags
;
458 XChangeProperty(scr
->display
, window
, scr
->attribsAtom
, scr
->attribsAtom
,
459 32, PropModeReplace
, (unsigned char *)data
, 9);
464 setWindowMakerHints(WMWindow
*win
)
466 GNUstepWMAttributes attribs
;
467 WMScreen
*scr
= WMWidgetScreen(win
);
469 memset(&attribs
, 0, sizeof(GNUstepWMAttributes
));
470 attribs
.flags
= GSWindowStyleAttr
|GSWindowLevelAttr
|GSExtraFlagsAttr
;
471 attribs
.window_style
= win
->flags
.style
;
472 attribs
.window_level
= win
->level
;
473 if (win
->flags
.documentEdited
)
474 attribs
.extra_flags
= GSDocumentEditedFlag
;
476 attribs
.extra_flags
= 0;
478 writeGNUstepWMAttr(scr
, win
->view
->window
, &attribs
);
483 realizeWindow(WMWindow
*win
)
486 XClassHint
*classHint
;
487 WMScreen
*scr
= win
->view
->screen
;
491 classHint
= XAllocClassHint();
492 classHint
->res_name
= win
->wname
;
493 classHint
->res_class
= WMGetApplicationName();
494 XSetClassHint(scr
->display
, win
->view
->window
, classHint
);
497 hints
= XAllocWMHints();
499 if (!scr
->aflags
.simpleApplication
) {
500 hints
->flags
|= WindowGroupHint
;
501 hints
->window_group
= scr
->groupLeader
;
503 if (win
->miniImage
) {
504 hints
->flags
|= IconPixmapHint
;
505 hints
->icon_pixmap
= WMGetPixmapXID(win
->miniImage
);
506 hints
->icon_mask
= WMGetPixmapMaskXID(win
->miniImage
);
507 if (hints
->icon_mask
!= None
) {
508 hints
->flags
|= IconMaskHint
;
511 if (hints
->flags
!= 0)
512 XSetWMHints(scr
->display
, win
->view
->window
, hints
);
516 if (win
->closeAction
) {
517 atoms
[count
++] = scr
->deleteWindowAtom
;
521 XSetWMProtocols(scr
->display
, win
->view
->window
, atoms
, count
);
523 if (win
->title
|| win
->miniTitle
)
524 XmbSetWMProperties(scr
->display
, win
->view
->window
, win
->title
,
525 win
->miniTitle
, NULL
, 0, NULL
, NULL
, NULL
);
527 setWindowMakerHints(win
);
532 XSetTransientForHint(scr
->display
, win
->view
->window
,
533 win
->owner
->view
->window
);
537 setWindowTitle(win
, win
->title
);
543 WMSetWindowAspectRatio(WMWindow
*win
, int minX
, int minY
,
546 win
->flags
.setAspect
= 1;
547 win
->minAspect
.x
= minX
;
548 win
->minAspect
.y
= minY
;
549 win
->maxAspect
.x
= maxX
;
550 win
->maxAspect
.y
= maxY
;
551 if (win
->view
->flags
.realized
)
558 WMSetWindowInitialPosition(WMWindow
*win
, int x
, int y
)
560 win
->flags
.setPPos
= 1;
563 if (win
->view
->flags
.realized
)
565 WMMoveWidget(win
, x
, y
);
571 WMSetWindowUserPosition(WMWindow
*win
, int x
, int y
)
573 win
->flags
.setUPos
= 1;
576 if (win
->view
->flags
.realized
)
578 WMMoveWidget(win
, x
, y
);
585 WMSetWindowMinSize(WMWindow
*win
, unsigned width
, unsigned height
)
587 win
->minSize
.width
= width
;
588 win
->minSize
.height
= height
;
589 if (win
->view
->flags
.realized
)
596 WMSetWindowMaxSize(WMWindow
*win
, unsigned width
, unsigned height
)
598 win
->maxSize
.width
= width
;
599 win
->maxSize
.height
= height
;
600 if (win
->view
->flags
.realized
)
606 WMSetWindowBaseSize(WMWindow
*win
, unsigned width
, unsigned height
)
608 /* TODO: validate sizes */
609 win
->baseSize
.width
= width
;
610 win
->baseSize
.height
= height
;
611 if (win
->view
->flags
.realized
)
617 WMSetWindowResizeIncrements(WMWindow
*win
, unsigned wIncr
, unsigned hIncr
)
619 win
->resizeIncrement
.width
= wIncr
;
620 win
->resizeIncrement
.height
= hIncr
;
621 if (win
->view
->flags
.realized
)
627 WMSetWindowLevel(WMWindow
*win
, int level
)
630 if (win
->view
->flags
.realized
)
631 setWindowMakerHints(win
);
636 WMSetWindowDocumentEdited(WMWindow
*win
, Bool flag
)
638 flag
= ((flag
==0) ? 0 : 1);
639 if (win
->flags
.documentEdited
!= flag
) {
640 win
->flags
.documentEdited
= flag
;
641 if (win
->view
->flags
.realized
)
642 setWindowMakerHints(win
);
648 WMSetWindowMiniwindowImage(WMWindow
*win
, RImage
*image
)
650 if (win
->view
->flags
.realized
)
651 setMiniwindow(win
, image
);
656 WMSetWindowMiniwindowPixmap(WMWindow
*win
, WMPixmap
*pixmap
)
658 if ((win
->miniImage
&& !pixmap
) || (!win
->miniImage
&& pixmap
)) {
660 WMReleasePixmap(win
->miniImage
);
663 win
->miniImage
= WMRetainPixmap(pixmap
);
665 win
->miniImage
= NULL
;
667 if (win
->view
->flags
.realized
) {
670 hints
= XGetWMHints(win
->view
->screen
->display
, win
->view
->window
);
672 hints
= XAllocWMHints();
674 wwarning("could not allocate memory for WM hints");
680 hints
->flags
|= IconPixmapHint
;
681 hints
->icon_pixmap
= WMGetPixmapXID(pixmap
);
682 hints
->icon_mask
= WMGetPixmapMaskXID(pixmap
);
683 if (hints
->icon_mask
!= None
) {
684 hints
->flags
|= IconMaskHint
;
687 XSetWMHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
695 WMSetWindowMiniwindowTitle(WMWindow
*win
, char *title
)
697 if ((win
->miniTitle
&& !title
) || (!win
->miniTitle
&& title
)
698 || (title
&& win
->miniTitle
&& strcoll(title
, win
->miniTitle
)!=0)) {
700 wfree(win
->miniTitle
);
703 win
->miniTitle
= wstrdup(title
);
705 win
->miniTitle
= NULL
;
707 if (win
->view
->flags
.realized
) {
708 setMiniwindowTitle(win
, title
);
715 WMCloseWindow(WMWindow
*win
)
718 /* withdraw the window */
719 if (win
->view
->flags
.realized
)
720 XWithdrawWindow(win
->view
->screen
->display
, win
->view
->window
,
721 win
->view
->screen
->screen
);
726 handleEvents(XEvent
*event
, void *clientData
)
728 _Window
*win
= (_Window
*)clientData
;
729 W_View
*view
= win
->view
;
732 switch (event
->type
) {
734 if (event
->xclient
.message_type
== win
->view
->screen
->protocolsAtom
735 && event
->xclient
.format
== 32
736 && event
->xclient
.data
.l
[0]==win
->view
->screen
->deleteWindowAtom
) {
738 if (win
->closeAction
) {
739 (*win
->closeAction
)(win
, win
->closeData
);
744 * was causing windows to ignore commands like closeWindow
745 * after the windows is iconized/restored or a workspace change
746 * if this is really needed, put the MapNotify portion too and
747 * fix the restack bug in wmaker
761 case ConfigureNotify
:
762 if (event
->xconfigure
.width
!= view
->size
.width
763 || event
->xconfigure
.height
!= view
->size
.height
) {
765 view
->size
.width
= event
->xconfigure
.width
;
766 view
->size
.height
= event
->xconfigure
.height
;
768 if (view
->flags
.notifySizeChanged
) {
769 WMPostNotificationName(WMViewSizeDidChangeNotification
,
773 if (event
->xconfigure
.x
!= view
->pos
.x
774 || event
->xconfigure
.y
!= view
->pos
.y
) {
776 if (event
->xconfigure
.send_event
) {
777 view
->pos
.x
= event
->xconfigure
.x
;
778 view
->pos
.y
= event
->xconfigure
.y
;
782 XTranslateCoordinates(view
->screen
->display
,
783 view
->window
, view
->screen
->rootWin
,
784 event
->xconfigure
.x
, event
->xconfigure
.y
,
785 &view
->pos
.x
, &view
->pos
.y
, &foo
);
796 destroyWindow(_Window
*win
)
798 WMScreen
*scr
= win
->view
->screen
;
800 WMRemoveNotificationObserver(win
);
802 if (scr
->windowList
== win
) {
803 scr
->windowList
= scr
->windowList
->nextPtr
;
806 ptr
= scr
->windowList
;
809 while (ptr
->nextPtr
) {
810 if (ptr
->nextPtr
==win
) {
811 ptr
->nextPtr
= ptr
->nextPtr
->nextPtr
;
823 if (win
->miniTitle
) {
824 wfree(win
->miniTitle
);
827 if (win
->miniImage
) {
828 WMReleasePixmap(win
->miniImage
);