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
;
32 WMAction
*closeAction
;
39 unsigned configured
:1;
40 unsigned documentEdited
:1;
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 */
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)
69 #define GSDocumentEditedFlag (1<<0)
70 #define GSNoApplicationIconFlag (1<<5)
72 #define WMFHideOtherApplications 10
73 #define WMFHideApplication 12
77 static void willResizeWindow(W_ViewDelegate
*, WMView
*, unsigned*, unsigned*);
79 struct W_ViewDelegate _WindowViewDelegate
= {
88 #define DEFAULT_WIDTH 400
89 #define DEFAULT_HEIGHT 180
90 #define DEFAULT_TITLE ""
93 static void destroyWindow(_Window
*win
);
95 static void handleEvents();
97 static void realizeWindow();
100 realizeObserver(void *self
, WMNotification
*not)
107 WMCreatePanelWithStyleForWindow(WMWindow
*owner
, char *name
, int style
)
111 win
= WMCreateWindowWithStyle(owner
->view
->screen
, name
, style
);
120 WMCreatePanelForWindow(WMWindow
*owner
, char *name
)
122 return WMCreatePanelWithStyleForWindow(owner
, name
,
124 |WMClosableWindowMask
125 |WMResizableWindowMask
);
130 WMChangePanelOwner(WMWindow
*win
, WMWindow
*newOwner
)
132 win
->owner
= newOwner
;
134 if (win
->view
->flags
.realized
&& newOwner
) {
135 XSetTransientForHint(win
->view
->screen
->display
, win
->view
->window
,
136 newOwner
->view
->window
);
143 WMCreateWindow(WMScreen
*screen
, char *name
)
145 return WMCreateWindowWithStyle(screen
, name
, WMTitledWindowMask
146 |WMClosableWindowMask
147 |WMMiniaturizableWindowMask
148 |WMResizableWindowMask
);
154 WMCreateWindowWithStyle(WMScreen
*screen
, char *name
, int style
)
158 win
= wmalloc(sizeof(_Window
));
159 memset(win
, 0, sizeof(_Window
));
161 win
->widgetClass
= WC_Window
;
163 win
->view
= W_CreateTopView(screen
);
168 win
->view
->self
= win
;
170 win
->view
->delegate
= &_WindowViewDelegate
;
172 win
->wname
= wstrdup(name
);
174 /* add to the window list of the screen (application) */
175 win
->nextPtr
= screen
->windowList
;
176 screen
->windowList
= win
;
178 WMCreateEventHandler(win
->view
, ExposureMask
|StructureNotifyMask
179 |ClientMessageMask
|FocusChangeMask
,
182 W_ResizeView(win
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
184 WMAddNotificationObserver(realizeObserver
, win
,
185 WMViewRealizedNotification
, win
->view
);
187 win
->flags
.style
= style
;
189 win
->level
= WMNormalWindowLevel
;
191 /* kluge. Find a better solution */
192 W_SetFocusOfTopLevel(win
->view
, win
->view
);
199 WMSetWindowTitle(WMWindow
*win
, char *title
)
201 XTextProperty property
;
204 if (win
->title
!=NULL
)
207 win
->title
= wstrdup(title
);
211 if (win
->view
->flags
.realized
) {
212 result
= XmbTextListToTextProperty (win
->view
->screen
->display
,
213 &title
, 1, XStdICCTextStyle
,
215 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
216 wwarning("window title conversion error... using STRING encoding");
217 XStoreName(win
->view
->screen
->display
, win
->view
->window
, title
);
219 XSetWMName(win
->view
->screen
->display
, win
->view
->window
, &property
);
221 XFree(property
.value
);
230 WMSetWindowCloseAction(WMWindow
*win
, WMAction
*action
, void *clientData
)
235 WMScreen
*scr
= win
->view
->screen
;
237 if (win
->view
->flags
.realized
) {
238 if (action
&& !win
->closeAction
) {
239 if (!XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
243 newAtoms
= wmalloc((count
+1)*sizeof(Atom
));
245 memcpy(newAtoms
, atoms
, count
*sizeof(Atom
));
246 newAtoms
[count
++] = scr
->deleteWindowAtom
;
247 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
, count
);
251 } else if (!action
&& win
->closeAction
) {
254 if (XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
255 &count
) && count
>0) {
256 newAtoms
= wmalloc((count
-1)*sizeof(Atom
));
258 for (i
=0; i
< count
; i
++) {
259 if (atoms
[i
]!=scr
->deleteWindowAtom
) {
260 newAtoms
[i
] = atoms
[i
];
264 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
,
272 win
->closeAction
= action
;
273 win
->closeData
= clientData
;
279 willResizeWindow(W_ViewDelegate
*self
, WMView
*view
,
280 unsigned *width
, unsigned *height
)
282 WMWindow
*win
= (WMWindow
*)view
->self
;
284 if (win
->minSize
.width
> 0 && win
->minSize
.height
> 0) {
285 if (*width
< win
->minSize
.width
)
286 *width
= win
->minSize
.width
;
287 if (*height
< win
->minSize
.height
)
288 *height
= win
->minSize
.height
;
291 if (win
->maxSize
.width
> 0 && win
->maxSize
.height
> 0) {
292 if (*width
> win
->maxSize
.width
)
293 *width
= win
->maxSize
.width
;
294 if (*height
> win
->maxSize
.height
)
295 *height
= win
->maxSize
.height
;
301 setSizeHints(WMWindow
*win
)
305 hints
= XAllocSizeHints();
307 wwarning("could not allocate memory for window size hints");
313 if (win
->flags
.upos_set
) {
314 hints
->flags
|= USPosition
;
315 hints
->x
= win
->upos
.x
;
316 hints
->y
= win
->upos
.y
;
318 if (win
->usize
.width
>0 && win
->usize
.height
>0) {
319 hints
->flags
|= USSize
;
320 hints
->width
= win
->usize
.width
;
321 hints
->height
= win
->usize
.height
;
323 if (win
->minSize
.width
>0 && win
->minSize
.height
>0) {
324 hints
->flags
|= PMinSize
;
325 hints
->min_width
= win
->minSize
.width
;
326 hints
->min_height
= win
->minSize
.height
;
328 if (win
->maxSize
.width
>0 && win
->maxSize
.height
>0) {
329 hints
->flags
|= PMaxSize
;
330 hints
->max_width
= win
->maxSize
.width
;
331 hints
->max_height
= win
->maxSize
.height
;
333 if (win
->baseSize
.width
>0 && win
->baseSize
.height
>0) {
334 hints
->flags
|= PBaseSize
;
335 hints
->base_width
= win
->baseSize
.width
;
336 hints
->base_height
= win
->baseSize
.height
;
338 if (win
->resizeIncrement
.width
>0 && win
->resizeIncrement
.height
>0) {
339 hints
->flags
|= PResizeInc
;
340 hints
->width_inc
= win
->resizeIncrement
.width
;
341 hints
->height_inc
= win
->resizeIncrement
.height
;
345 XSetWMNormalHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
353 writeGNUstepWMAttr(WMScreen
*scr
, Window window
, GNUstepWMAttributes
*attr
)
355 unsigned long data
[9];
357 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
358 data
[0] = attr
->flags
;
359 data
[1] = attr
->window_style
;
360 data
[2] = attr
->window_level
;
361 data
[3] = 0; /* reserved */
362 /* The X protocol says XIDs are 32bit */
363 data
[4] = attr
->miniaturize_pixmap
;
364 data
[5] = attr
->close_pixmap
;
365 data
[6] = attr
->miniaturize_mask
;
366 data
[7] = attr
->close_mask
;
367 data
[8] = attr
->extra_flags
;
368 XChangeProperty(scr
->display
, window
, scr
->attribsAtom
, scr
->attribsAtom
,
369 32, PropModeReplace
, (unsigned char *)data
, 9);
374 setWindowMakerHints(WMWindow
*win
)
376 GNUstepWMAttributes attribs
;
377 WMScreen
*scr
= WMWidgetScreen(win
);
379 memset(&attribs
, 0, sizeof(GNUstepWMAttributes
));
380 attribs
.flags
= GSWindowStyleAttr
|GSWindowLevelAttr
|GSExtraFlagsAttr
;
381 attribs
.window_style
= win
->flags
.style
;
382 attribs
.window_level
= win
->level
;
383 if (win
->flags
.documentEdited
)
384 attribs
.extra_flags
= GSDocumentEditedFlag
;
386 attribs
.extra_flags
= 0;
388 writeGNUstepWMAttr(scr
, win
->view
->window
, &attribs
);
393 realizeWindow(WMWindow
*win
)
396 XClassHint
*classHint
;
397 WMScreen
*scr
= win
->view
->screen
;
401 classHint
= XAllocClassHint();
402 classHint
->res_name
= win
->wname
;
403 classHint
->res_class
= WMGetApplicationName();
404 XSetClassHint(scr
->display
, win
->view
->window
, classHint
);
407 hints
= XAllocWMHints();
409 if (!scr
->aflags
.simpleApplication
) {
410 hints
->flags
|= WindowGroupHint
;
411 hints
->window_group
= scr
->groupLeader
;
413 if (win
->miniImage
) {
414 hints
->flags
|= IconPixmapHint
;
415 hints
->icon_pixmap
= WMGetPixmapXID(win
->miniImage
);
416 hints
->icon_mask
= WMGetPixmapMaskXID(win
->miniImage
);
417 if (hints
->icon_mask
!= None
) {
418 hints
->flags
|= IconMaskHint
;
421 if (hints
->flags
!= 0)
422 XSetWMHints(scr
->display
, win
->view
->window
, hints
);
426 if (win
->closeAction
) {
427 atoms
[count
++] = scr
->deleteWindowAtom
;
431 XSetWMProtocols(scr
->display
, win
->view
->window
, atoms
, count
);
433 if (win
->title
|| win
->miniTitle
)
434 XmbSetWMProperties(scr
->display
, win
->view
->window
, win
->title
,
435 win
->miniTitle
, NULL
, 0, NULL
, NULL
, NULL
);
437 setWindowMakerHints(win
);
442 XSetTransientForHint(scr
->display
, win
->view
->window
,
443 win
->owner
->view
->window
);
450 WMSetWindowUPosition(WMWindow
*win
, int x
, int y
)
452 win
->flags
.upos_set
= 1;
455 if (win
->view
->flags
.realized
)
462 WMSetWindowUSize(WMWindow
*win
, unsigned width
, unsigned height
)
464 win
->usize
.width
= width
;
465 win
->usize
.height
= height
;
466 if (win
->view
->flags
.realized
)
472 WMSetWindowMinSize(WMWindow
*win
, unsigned width
, unsigned height
)
474 win
->minSize
.width
= width
;
475 win
->minSize
.height
= height
;
476 if (win
->view
->flags
.realized
)
483 WMSetWindowMaxSize(WMWindow
*win
, unsigned width
, unsigned height
)
485 win
->maxSize
.width
= width
;
486 win
->maxSize
.height
= height
;
487 if (win
->view
->flags
.realized
)
493 WMSetWindowBaseSize(WMWindow
*win
, unsigned width
, unsigned height
)
495 /* TODO: validate sizes */
496 win
->baseSize
.width
= width
;
497 win
->baseSize
.height
= height
;
498 if (win
->view
->flags
.realized
)
504 WMSetWindowResizeIncrements(WMWindow
*win
, unsigned wIncr
, unsigned hIncr
)
506 win
->resizeIncrement
.width
= wIncr
;
507 win
->resizeIncrement
.height
= hIncr
;
508 if (win
->view
->flags
.realized
)
514 WMSetWindowLevel(WMWindow
*win
, int level
)
517 if (win
->view
->flags
.realized
)
518 setWindowMakerHints(win
);
523 WMSetWindowDocumentEdited(WMWindow
*win
, Bool flag
)
525 if (win
->flags
.documentEdited
!= flag
) {
526 win
->flags
.documentEdited
= flag
;
527 if (win
->view
->flags
.realized
)
528 setWindowMakerHints(win
);
534 WMSetWindowMiniwindowImage(WMWindow
*win
, WMPixmap
*pixmap
)
536 if ((win
->miniImage
&& !pixmap
) || (!win
->miniImage
&& pixmap
)) {
538 WMReleasePixmap(win
->miniImage
);
541 win
->miniImage
= WMRetainPixmap(pixmap
);
543 win
->miniImage
= NULL
;
545 if (win
->view
->flags
.realized
) {
548 hints
= XGetWMHints(win
->view
->screen
->display
, win
->view
->window
);
550 hints
= XAllocWMHints();
552 wwarning("could not allocate memory for WM hints");
558 hints
->flags
|= IconPixmapHint
;
559 hints
->icon_pixmap
= WMGetPixmapXID(pixmap
);
560 hints
->icon_mask
= WMGetPixmapMaskXID(pixmap
);
561 if (hints
->icon_mask
!= None
) {
562 hints
->flags
|= IconMaskHint
;
565 XSetWMHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
573 WMSetWindowMiniwindowTitle(WMWindow
*win
, char *title
)
575 XTextProperty property
;
578 if ((win
->miniTitle
&& !title
) || (!win
->miniTitle
&& title
)
579 || (title
&& win
->miniTitle
&& strcoll(title
, win
->miniTitle
)!=0)) {
581 free(win
->miniTitle
);
584 win
->miniTitle
= wstrdup(title
);
586 win
->miniTitle
= NULL
;
588 if (win
->view
->flags
.realized
) {
589 result
= XmbTextListToTextProperty (win
->view
->screen
->display
,
590 &title
, 1, XStdICCTextStyle
,
592 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
593 wwarning("icon title conversion error..using STRING encoding");
594 XSetIconName(win
->view
->screen
->display
, win
->view
->window
,
597 XSetWMIconName(win
->view
->screen
->display
, win
->view
->window
,
600 XFree(property
.value
);
608 WMCloseWindow(WMWindow
*win
)
611 /* withdraw the window */
612 if (win
->view
->flags
.realized
)
613 XWithdrawWindow(win
->view
->screen
->display
, win
->view
->window
,
614 win
->view
->screen
->screen
);
619 handleEvents(XEvent
*event
, void *clientData
)
621 _Window
*win
= (_Window
*)clientData
;
622 W_View
*view
= win
->view
;
625 switch (event
->type
) {
627 if (event
->xclient
.message_type
== win
->view
->screen
->protocolsAtom
628 && event
->xclient
.format
== 32
629 && event
->xclient
.data
.l
[0]==win
->view
->screen
->deleteWindowAtom
) {
631 if (win
->closeAction
) {
632 (*win
->closeAction
)(win
, win
->closeData
);
645 case ConfigureNotify
:
646 if (event
->xconfigure
.width
!= view
->size
.width
647 || 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
,
657 if (event
->xconfigure
.x
!= view
->pos
.x
658 || event
->xconfigure
.y
!= view
->pos
.y
) {
660 if (event
->xconfigure
.send_event
) {
661 view
->pos
.x
= event
->xconfigure
.x
;
662 view
->pos
.y
= event
->xconfigure
.y
;
666 XTranslateCoordinates(view
->screen
->display
,
667 view
->window
, view
->screen
->rootWin
,
668 event
->xconfigure
.x
, event
->xconfigure
.y
,
669 &view
->pos
.x
, &view
->pos
.y
, &foo
);
680 destroyWindow(_Window
*win
)
682 WMScreen
*scr
= win
->view
->screen
;
684 WMRemoveNotificationObserver(win
);
686 if (scr
->windowList
== win
) {
687 scr
->windowList
= scr
->windowList
->nextPtr
;
690 ptr
= scr
->windowList
;
692 while (ptr
->nextPtr
) {
693 if (ptr
->nextPtr
==win
) {
694 ptr
->nextPtr
= ptr
->nextPtr
->nextPtr
;
705 if (win
->miniTitle
) {
706 free(win
->miniTitle
);
709 if (win
->miniImage
) {
710 WMReleasePixmap(win
->miniImage
);