8 typedef struct W_Window
{
12 struct W_Window
*nextPtr
; /* next in the window list */
14 struct W_Window
*owner
;
18 WMPixmap
*miniImage
; /* miniwindow */
23 WMSize resizeIncrement
;
33 WMAction
*closeAction
;
40 unsigned configured
:1;
41 unsigned documentEdited
:1;
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 */
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)
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
= {
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 */
104 WMWindow
*WMCreatePanelWithStyleForWindow(WMWindow
* owner
, const char *name
, int style
)
108 win
= WMCreateWindowWithStyle(owner
->view
->screen
, name
, style
);
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
)
140 win
= wmalloc(sizeof(_Window
));
141 win
->widgetClass
= WC_Window
;
143 win
->view
= W_CreateTopView(screen
);
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
);
175 static void setWindowTitle(WMWindow
* win
, const char *title
)
177 WMScreen
*scr
= win
->view
->screen
;
178 XTextProperty property
;
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
);
186 XSetWMName(scr
->display
, win
->view
->window
, &property
);
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
;
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
);
207 XSetWMIconName(scr
->display
, win
->view
->window
, &property
);
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
;
227 data
= wmalloc((image
->width
* image
->height
+ 2) * sizeof(long));
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
++) {
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];
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;
249 XChangeProperty(scr
->display
, win
->view
->window
, scr
->netwmIcon
,
250 XA_CARDINAL
, 32, PropModeReplace
,
251 (unsigned char *)data
, (image
->width
* image
->height
+ 2));
256 void WMSetWindowTitle(WMWindow
* win
, const char *title
)
258 wassertr(title
!= NULL
);
260 if (win
->title
!= NULL
)
263 win
->title
= wstrdup(title
);
265 if (win
->view
->flags
.realized
) {
266 setWindowTitle(win
, title
);
270 void WMSetWindowCloseAction(WMWindow
* win
, WMAction
* action
, void *clientData
)
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
)) {
282 newAtoms
= wmalloc((count
+ 1) * sizeof(Atom
));
284 memcpy(newAtoms
, atoms
, count
* sizeof(Atom
));
285 newAtoms
[count
++] = scr
->deleteWindowAtom
;
286 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
, count
);
290 } else if (!action
&& win
->closeAction
) {
293 if (XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
, &count
) && count
> 0) {
294 newAtoms
= wmalloc((count
- 1) * sizeof(Atom
));
296 for (i
= 0; i
< count
; i
++) {
297 if (atoms
[i
] != scr
->deleteWindowAtom
) {
298 newAtoms
[i
] = atoms
[i
];
302 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
, ncount
);
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 */
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
)
339 hints
= XAllocSizeHints();
341 wwarning("could not allocate memory for window size hints");
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
;
386 XSetWMNormalHints(win
->view
->screen
->display
, win
->view
->window
, 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
;
422 attribs
.extra_flags
= 0;
424 writeGNUstepWMAttr(scr
, win
->view
->window
, &attribs
);
427 static void realizeWindow(WMWindow
* win
)
430 XClassHint
*classHint
;
431 WMScreen
*scr
= win
->view
->screen
;
435 classHint
= XAllocClassHint();
436 classHint
->res_name
= win
->wname
;
437 classHint
->res_class
= WMGetApplicationName();
438 XSetClassHint(scr
->display
, win
->view
->window
, classHint
);
441 hints
= XAllocWMHints();
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
);
460 if (win
->closeAction
) {
461 atoms
[count
++] = scr
->deleteWindowAtom
;
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
);
476 XSetTransientForHint(scr
->display
, win
->view
->window
, win
->owner
->view
->window
);
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
)
494 void WMSetWindowInitialPosition(WMWindow
* win
, int x
, int y
)
496 win
->flags
.setPPos
= 1;
499 if (win
->view
->flags
.realized
)
501 WMMoveWidget(win
, x
, y
);
504 void WMSetWindowUserPosition(WMWindow
* win
, int x
, int y
)
506 win
->flags
.setUPos
= 1;
509 if (win
->view
->flags
.realized
)
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
)
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
)
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
)
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
)
547 void WMSetWindowLevel(WMWindow
* win
, int 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
)) {
574 WMReleasePixmap(win
->miniImage
);
577 win
->miniImage
= WMRetainPixmap(pixmap
);
579 win
->miniImage
= NULL
;
581 if (win
->view
->flags
.realized
) {
584 hints
= XGetWMHints(win
->view
->screen
->display
, win
->view
->window
);
586 hints
= XAllocWMHints();
588 wwarning("could not allocate memory for WM hints");
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
);
607 void WMSetWindowMiniwindowTitle(WMWindow
* win
, const char *title
)
609 if (win
&& ((win
->miniTitle
&& !title
) || (!win
->miniTitle
&& title
)
610 || (title
&& win
->miniTitle
&& strcoll(title
, win
->miniTitle
) != 0))) {
612 wfree(win
->miniTitle
);
615 win
->miniTitle
= wstrdup(title
);
617 win
->miniTitle
= NULL
;
619 if (win
->view
->flags
.realized
) {
620 setMiniwindowTitle(win
, title
);
625 void WMCloseWindow(WMWindow
* 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
) {
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
);
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
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
;
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
);
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
;
705 ptr
= scr
->windowList
;
708 while (ptr
->nextPtr
) {
709 if (ptr
->nextPtr
== win
) {
710 ptr
->nextPtr
= ptr
->nextPtr
->nextPtr
;
722 if (win
->miniTitle
) {
723 wfree(win
->miniTitle
);
726 if (win
->miniImage
) {
727 WMReleasePixmap(win
->miniImage
);