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
;
33 WMAction
*closeAction
;
40 unsigned configured
:1;
41 unsigned documentEdited
:1;
55 Pixmap miniaturize_pixmap
; /* pixmap for miniaturize button */
56 Pixmap close_pixmap
; /* pixmap for close button */
57 Pixmap miniaturize_mask
; /* miniaturize pixmap mask */
58 Pixmap close_mask
; /* close pixmap mask */
60 } GNUstepWMAttributes
;
62 #define GSWindowStyleAttr (1<<0)
63 #define GSWindowLevelAttr (1<<1)
64 #define GSMiniaturizePixmapAttr (1<<3)
65 #define GSClosePixmapAttr (1<<4)
66 #define GSMiniaturizeMaskAttr (1<<5)
67 #define GSCloseMaskAttr (1<<6)
68 #define GSExtraFlagsAttr (1<<7)
71 #define GSDocumentEditedFlag (1<<0)
72 #define GSNoApplicationIconFlag (1<<5)
74 #define WMFHideOtherApplications 10
75 #define WMFHideApplication 12
79 static void willResizeWindow(W_ViewDelegate
*, WMView
*, unsigned*, unsigned*);
81 struct W_ViewDelegate _WindowViewDelegate
= {
90 #define DEFAULT_WIDTH 400
91 #define DEFAULT_HEIGHT 180
92 #define DEFAULT_TITLE ""
95 static void destroyWindow(_Window
*win
);
97 static void handleEvents();
99 static void realizeWindow();
102 realizeObserver(void *self
, WMNotification
*not)
109 WMCreatePanelWithStyleForWindow(WMWindow
*owner
, char *name
, int style
)
113 win
= WMCreateWindowWithStyle(owner
->view
->screen
, name
, style
);
122 WMCreatePanelForWindow(WMWindow
*owner
, char *name
)
124 return WMCreatePanelWithStyleForWindow(owner
, name
,
126 |WMClosableWindowMask
127 |WMResizableWindowMask
);
132 WMChangePanelOwner(WMWindow
*win
, WMWindow
*newOwner
)
134 win
->owner
= newOwner
;
136 if (win
->view
->flags
.realized
&& newOwner
) {
137 XSetTransientForHint(win
->view
->screen
->display
, win
->view
->window
,
138 newOwner
->view
->window
);
145 WMCreateWindow(WMScreen
*screen
, char *name
)
147 return WMCreateWindowWithStyle(screen
, name
, WMTitledWindowMask
148 |WMClosableWindowMask
149 |WMMiniaturizableWindowMask
150 |WMResizableWindowMask
);
156 WMCreateWindowWithStyle(WMScreen
*screen
, char *name
, int style
)
160 win
= wmalloc(sizeof(_Window
));
161 memset(win
, 0, sizeof(_Window
));
163 win
->widgetClass
= WC_Window
;
165 win
->view
= W_CreateTopView(screen
);
170 win
->view
->self
= win
;
172 win
->view
->delegate
= &_WindowViewDelegate
;
174 win
->wname
= wstrdup(name
);
176 /* add to the window list of the screen (application) */
177 win
->nextPtr
= screen
->windowList
;
178 screen
->windowList
= win
;
180 WMCreateEventHandler(win
->view
, ExposureMask
|StructureNotifyMask
181 |ClientMessageMask
|FocusChangeMask
,
184 W_ResizeView(win
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
186 WMAddNotificationObserver(realizeObserver
, win
,
187 WMViewRealizedNotification
, win
->view
);
189 win
->flags
.style
= style
;
191 win
->level
= WMNormalWindowLevel
;
193 /* kluge. Find a better solution */
194 W_SetFocusOfTopLevel(win
->view
, win
->view
);
201 WMSetWindowTitle(WMWindow
*win
, char *title
)
203 XTextProperty property
;
206 if (win
->title
!=NULL
)
209 win
->title
= wstrdup(title
);
213 if (win
->view
->flags
.realized
) {
214 result
= XmbTextListToTextProperty (win
->view
->screen
->display
,
215 &title
, 1, XStdICCTextStyle
,
217 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
218 wwarning("window title conversion error... using STRING encoding");
219 XStoreName(win
->view
->screen
->display
, win
->view
->window
, title
);
221 XSetWMName(win
->view
->screen
->display
, win
->view
->window
, &property
);
223 XFree(property
.value
);
232 WMSetWindowCloseAction(WMWindow
*win
, WMAction
*action
, void *clientData
)
237 WMScreen
*scr
= win
->view
->screen
;
239 if (win
->view
->flags
.realized
) {
240 if (action
&& !win
->closeAction
) {
241 if (!XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
245 newAtoms
= wmalloc((count
+1)*sizeof(Atom
));
247 memcpy(newAtoms
, atoms
, count
*sizeof(Atom
));
248 newAtoms
[count
++] = scr
->deleteWindowAtom
;
249 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
, count
);
253 } else if (!action
&& win
->closeAction
) {
256 if (XGetWMProtocols(scr
->display
, win
->view
->window
, &atoms
,
257 &count
) && count
>0) {
258 newAtoms
= wmalloc((count
-1)*sizeof(Atom
));
260 for (i
=0; i
< count
; i
++) {
261 if (atoms
[i
]!=scr
->deleteWindowAtom
) {
262 newAtoms
[i
] = atoms
[i
];
266 XSetWMProtocols(scr
->display
, win
->view
->window
, newAtoms
,
274 win
->closeAction
= action
;
275 win
->closeData
= clientData
;
281 willResizeWindow(W_ViewDelegate
*self
, WMView
*view
,
282 unsigned *width
, unsigned *height
)
284 WMWindow
*win
= (WMWindow
*)view
->self
;
286 if (win
->minSize
.width
> 0 && win
->minSize
.height
> 0) {
287 if (*width
< win
->minSize
.width
)
288 *width
= win
->minSize
.width
;
289 if (*height
< win
->minSize
.height
)
290 *height
= win
->minSize
.height
;
293 if (win
->maxSize
.width
> 0 && win
->maxSize
.height
> 0) {
294 if (*width
> win
->maxSize
.width
)
295 *width
= win
->maxSize
.width
;
296 if (*height
> win
->maxSize
.height
)
297 *height
= win
->maxSize
.height
;
303 setSizeHints(WMWindow
*win
)
307 hints
= XAllocSizeHints();
309 wwarning("could not allocate memory for window size hints");
315 if (win
->flags
.setPPos
) {
316 hints
->flags
|= PPosition
;
317 hints
->x
= win
->upos
.x
;
318 hints
->y
= win
->upos
.y
;
320 if (win
->minSize
.width
>0 && win
->minSize
.height
>0) {
321 hints
->flags
|= PMinSize
;
322 hints
->min_width
= win
->minSize
.width
;
323 hints
->min_height
= win
->minSize
.height
;
325 if (win
->maxSize
.width
>0 && win
->maxSize
.height
>0) {
326 hints
->flags
|= PMaxSize
;
327 hints
->max_width
= win
->maxSize
.width
;
328 hints
->max_height
= win
->maxSize
.height
;
330 if (win
->baseSize
.width
>0 && win
->baseSize
.height
>0) {
331 hints
->flags
|= PBaseSize
;
332 hints
->base_width
= win
->baseSize
.width
;
333 hints
->base_height
= win
->baseSize
.height
;
335 if (win
->resizeIncrement
.width
>0 && win
->resizeIncrement
.height
>0) {
336 hints
->flags
|= PResizeInc
;
337 hints
->width_inc
= win
->resizeIncrement
.width
;
338 hints
->height_inc
= win
->resizeIncrement
.height
;
340 if (win
->flags
.setAspect
) {
341 hints
->flags
|= PAspect
;
342 hints
->min_aspect
.x
= win
->minAspect
.x
;
343 hints
->min_aspect
.y
= win
->minAspect
.y
;
344 hints
->max_aspect
.x
= win
->maxAspect
.x
;
345 hints
->max_aspect
.y
= win
->maxAspect
.y
;
350 XSetWMNormalHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
358 writeGNUstepWMAttr(WMScreen
*scr
, Window window
, GNUstepWMAttributes
*attr
)
360 unsigned long data
[9];
362 /* handle idiot compilers where array of CARD32 != struct of CARD32 */
363 data
[0] = attr
->flags
;
364 data
[1] = attr
->window_style
;
365 data
[2] = attr
->window_level
;
366 data
[3] = 0; /* reserved */
367 /* The X protocol says XIDs are 32bit */
368 data
[4] = attr
->miniaturize_pixmap
;
369 data
[5] = attr
->close_pixmap
;
370 data
[6] = attr
->miniaturize_mask
;
371 data
[7] = attr
->close_mask
;
372 data
[8] = attr
->extra_flags
;
373 XChangeProperty(scr
->display
, window
, scr
->attribsAtom
, scr
->attribsAtom
,
374 32, PropModeReplace
, (unsigned char *)data
, 9);
379 setWindowMakerHints(WMWindow
*win
)
381 GNUstepWMAttributes attribs
;
382 WMScreen
*scr
= WMWidgetScreen(win
);
384 memset(&attribs
, 0, sizeof(GNUstepWMAttributes
));
385 attribs
.flags
= GSWindowStyleAttr
|GSWindowLevelAttr
|GSExtraFlagsAttr
;
386 attribs
.window_style
= win
->flags
.style
;
387 attribs
.window_level
= win
->level
;
388 if (win
->flags
.documentEdited
)
389 attribs
.extra_flags
= GSDocumentEditedFlag
;
391 attribs
.extra_flags
= 0;
393 writeGNUstepWMAttr(scr
, win
->view
->window
, &attribs
);
398 realizeWindow(WMWindow
*win
)
401 XClassHint
*classHint
;
402 WMScreen
*scr
= win
->view
->screen
;
406 classHint
= XAllocClassHint();
407 classHint
->res_name
= win
->wname
;
408 classHint
->res_class
= WMGetApplicationName();
409 XSetClassHint(scr
->display
, win
->view
->window
, classHint
);
412 hints
= XAllocWMHints();
414 if (!scr
->aflags
.simpleApplication
) {
415 hints
->flags
|= WindowGroupHint
;
416 hints
->window_group
= scr
->groupLeader
;
418 if (win
->miniImage
) {
419 hints
->flags
|= IconPixmapHint
;
420 hints
->icon_pixmap
= WMGetPixmapXID(win
->miniImage
);
421 hints
->icon_mask
= WMGetPixmapMaskXID(win
->miniImage
);
422 if (hints
->icon_mask
!= None
) {
423 hints
->flags
|= IconMaskHint
;
426 if (hints
->flags
!= 0)
427 XSetWMHints(scr
->display
, win
->view
->window
, hints
);
431 if (win
->closeAction
) {
432 atoms
[count
++] = scr
->deleteWindowAtom
;
436 XSetWMProtocols(scr
->display
, win
->view
->window
, atoms
, count
);
438 if (win
->title
|| win
->miniTitle
)
439 XmbSetWMProperties(scr
->display
, win
->view
->window
, win
->title
,
440 win
->miniTitle
, NULL
, 0, NULL
, NULL
, NULL
);
442 setWindowMakerHints(win
);
447 XSetTransientForHint(scr
->display
, win
->view
->window
,
448 win
->owner
->view
->window
);
455 WMSetWindowAspectRatio(WMWindow
*win
, int minX
, int minY
,
458 win
->flags
.setAspect
= 1;
459 win
->minAspect
.x
= minX
;
460 win
->minAspect
.y
= minY
;
461 win
->maxAspect
.x
= maxX
;
462 win
->maxAspect
.y
= maxY
;
463 if (win
->view
->flags
.realized
)
470 WMSetWindowInitialPosition(WMWindow
*win
, int x
, int y
)
472 win
->flags
.setPPos
= 1;
475 if (win
->view
->flags
.realized
)
477 WMMoveWidget(win
, x
, y
);
484 WMSetWindowMinSize(WMWindow
*win
, unsigned width
, unsigned height
)
486 win
->minSize
.width
= width
;
487 win
->minSize
.height
= height
;
488 if (win
->view
->flags
.realized
)
495 WMSetWindowMaxSize(WMWindow
*win
, unsigned width
, unsigned height
)
497 win
->maxSize
.width
= width
;
498 win
->maxSize
.height
= height
;
499 if (win
->view
->flags
.realized
)
505 WMSetWindowBaseSize(WMWindow
*win
, unsigned width
, unsigned height
)
507 /* TODO: validate sizes */
508 win
->baseSize
.width
= width
;
509 win
->baseSize
.height
= height
;
510 if (win
->view
->flags
.realized
)
516 WMSetWindowResizeIncrements(WMWindow
*win
, unsigned wIncr
, unsigned hIncr
)
518 win
->resizeIncrement
.width
= wIncr
;
519 win
->resizeIncrement
.height
= hIncr
;
520 if (win
->view
->flags
.realized
)
526 WMSetWindowLevel(WMWindow
*win
, int level
)
529 if (win
->view
->flags
.realized
)
530 setWindowMakerHints(win
);
535 WMSetWindowDocumentEdited(WMWindow
*win
, Bool flag
)
537 if (win
->flags
.documentEdited
!= flag
) {
538 win
->flags
.documentEdited
= flag
;
539 if (win
->view
->flags
.realized
)
540 setWindowMakerHints(win
);
546 WMSetWindowMiniwindowImage(WMWindow
*win
, WMPixmap
*pixmap
)
548 if ((win
->miniImage
&& !pixmap
) || (!win
->miniImage
&& pixmap
)) {
550 WMReleasePixmap(win
->miniImage
);
553 win
->miniImage
= WMRetainPixmap(pixmap
);
555 win
->miniImage
= NULL
;
557 if (win
->view
->flags
.realized
) {
560 hints
= XGetWMHints(win
->view
->screen
->display
, win
->view
->window
);
562 hints
= XAllocWMHints();
564 wwarning("could not allocate memory for WM hints");
570 hints
->flags
|= IconPixmapHint
;
571 hints
->icon_pixmap
= WMGetPixmapXID(pixmap
);
572 hints
->icon_mask
= WMGetPixmapMaskXID(pixmap
);
573 if (hints
->icon_mask
!= None
) {
574 hints
->flags
|= IconMaskHint
;
577 XSetWMHints(win
->view
->screen
->display
, win
->view
->window
, hints
);
585 WMSetWindowMiniwindowTitle(WMWindow
*win
, char *title
)
587 XTextProperty property
;
590 if ((win
->miniTitle
&& !title
) || (!win
->miniTitle
&& title
)
591 || (title
&& win
->miniTitle
&& strcoll(title
, win
->miniTitle
)!=0)) {
593 wfree(win
->miniTitle
);
596 win
->miniTitle
= wstrdup(title
);
598 win
->miniTitle
= NULL
;
600 if (win
->view
->flags
.realized
) {
601 result
= XmbTextListToTextProperty (win
->view
->screen
->display
,
602 &title
, 1, XStdICCTextStyle
,
604 if (result
== XNoMemory
|| result
== XLocaleNotSupported
) {
605 wwarning("icon title conversion error..using STRING encoding");
606 XSetIconName(win
->view
->screen
->display
, win
->view
->window
,
609 XSetWMIconName(win
->view
->screen
->display
, win
->view
->window
,
612 XFree(property
.value
);
620 WMCloseWindow(WMWindow
*win
)
623 /* withdraw the window */
624 if (win
->view
->flags
.realized
)
625 XWithdrawWindow(win
->view
->screen
->display
, win
->view
->window
,
626 win
->view
->screen
->screen
);
631 handleEvents(XEvent
*event
, void *clientData
)
633 _Window
*win
= (_Window
*)clientData
;
634 W_View
*view
= win
->view
;
637 switch (event
->type
) {
639 if (event
->xclient
.message_type
== win
->view
->screen
->protocolsAtom
640 && event
->xclient
.format
== 32
641 && event
->xclient
.data
.l
[0]==win
->view
->screen
->deleteWindowAtom
) {
643 if (win
->closeAction
) {
644 (*win
->closeAction
)(win
, win
->closeData
);
657 case ConfigureNotify
:
658 if (event
->xconfigure
.width
!= view
->size
.width
659 || event
->xconfigure
.height
!= view
->size
.height
) {
661 view
->size
.width
= event
->xconfigure
.width
;
662 view
->size
.height
= event
->xconfigure
.height
;
664 if (view
->flags
.notifySizeChanged
) {
665 WMPostNotificationName(WMViewSizeDidChangeNotification
,
669 if (event
->xconfigure
.x
!= view
->pos
.x
670 || event
->xconfigure
.y
!= view
->pos
.y
) {
672 if (event
->xconfigure
.send_event
) {
673 view
->pos
.x
= event
->xconfigure
.x
;
674 view
->pos
.y
= event
->xconfigure
.y
;
678 XTranslateCoordinates(view
->screen
->display
,
679 view
->window
, view
->screen
->rootWin
,
680 event
->xconfigure
.x
, event
->xconfigure
.y
,
681 &view
->pos
.x
, &view
->pos
.y
, &foo
);
692 destroyWindow(_Window
*win
)
694 WMScreen
*scr
= win
->view
->screen
;
696 WMRemoveNotificationObserver(win
);
698 if (scr
->windowList
== win
) {
699 scr
->windowList
= scr
->windowList
->nextPtr
;
702 ptr
= scr
->windowList
;
705 while (ptr
->nextPtr
) {
706 if (ptr
->nextPtr
==win
) {
707 ptr
->nextPtr
= ptr
->nextPtr
->nextPtr
;
719 if (win
->miniTitle
) {
720 wfree(win
->miniTitle
);
723 if (win
->miniImage
) {
724 WMReleasePixmap(win
->miniImage
);