2 Copyright 1995-2007, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
7 #include <proto/exec.h>
8 #include <proto/graphics.h>
9 #include <proto/layers.h>
10 #include <proto/timer.h>
11 #include "intuition_intern.h"
12 #include "inputhandler.h"
13 #include "inputhandler_actions.h"
14 #include "inputhandler_support.h"
15 //#include "segtracker.h"
16 #include <intuition/gadgetclass.h>
18 #ifndef DEBUG_CloseWindow
19 # define DEBUG_CloseWindow 1
25 # include <aros/debug.h>
27 /******************************************************************************/
29 #define MUST_UNLOCK_SCREEN(window,screen) (((GetPrivScreen(screen)->pubScrNode != NULL) && \
30 (window->MoreFlags & WMFLG_DO_UNLOCKPUBSCREEN)) ? TRUE : FALSE)
32 struct CloseWindowActionMsg
34 struct IntuiActionMsg msg
;
35 struct Window
*window
;
38 VOID
int_closewindow(struct CloseWindowActionMsg
*msg
,
39 struct IntuitionBase
*IntuitionBase
);
41 /*****************************************************************************
44 #include <proto/intuition.h>
46 AROS_LH1(void, CloseWindow
,
49 AROS_LHA(struct Window
*, window
, A0
),
52 struct IntuitionBase
*, IntuitionBase
, 12, Intuition
)
55 Closes a window. Depending on the display, this might not happen
56 at the time when this function returns, but you must not use
57 the window pointer after this function has been called.
60 window - The window to close
66 The window might not have been disappeared when this function returns.
73 OpenWindow(), OpenWindowTagList()
78 29-10-95 digulla automatically created from
79 intuition_lib.fd and clib/intuition_protos.h
81 *****************************************************************************/
85 struct CloseWindowActionMsg msg
;
87 struct MsgPort
*userport
;
88 #if USE_IDCMPUPDATE_MESSAGECACHE
89 struct IntuiMessage
*messagecache
;
91 struct Screen
*screen
;
94 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window
));
96 D(bug("CloseWindow (%p)\n", window
));
100 ReturnVoid ("CloseWindow");
103 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_BEFORE_CLOSEWINDOW
, IntuitionBase
);
105 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
107 screen
= window
->WScreen
;
108 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
111 /* We take a very simple approach to avoid race conditions with the
112 intuition input handler running one input.device 's task:
113 We just send it a msg about closing the window
115 if (HAS_CHILDREN(window
))
117 struct Window
* cw
= window
->firstchild
;
119 * First close all its children, we could also return
120 * a failure value which newer apps that use child windows
134 if (IS_CHILD(window
))
137 * Unlink the window from its parent or
138 * out of the list of child windows.
140 if (window
->parent
->firstchild
== window
)
141 window
->parent
->firstchild
= window
->nextchild
;
143 window
->prevchild
->nextchild
= window
->nextchild
;
145 if (window
->nextchild
)
146 window
->nextchild
->prevchild
= window
->prevchild
;
151 /* We must save this here, because after we have returned from
152 the Wait() the window is gone */
153 userport
= window
->UserPort
;
155 #if USE_IDCMPUPDATE_MESSAGECACHE
156 messagecache
= IW(window
)->messagecache
;
159 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport
));
161 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
164 /* wait until other open/close && move/size && menus actions are finished */
165 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
167 ObtainSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
172 DoSyncAction((APTR
)int_closewindow
, &msg
.msg
, IntuitionBase
);
175 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
177 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
181 if (do_unlockscreen
) UnlockPubScreen(NULL
, screen
);
183 /* As of now intuition has removed us from th list of
184 windows, and we will recieve no more messages
186 #if USE_IDCMPUPDATE_MESSAGECACHE
189 messagecache
->IDCMPWindow
= 0;//zero or we'll trash mem in inputhandler!
190 messagecache
->Code
= 0;
191 messagecache
->Qualifier
= 0;
192 ReplyMsg(&messagecache
->ExecMessage
);
198 struct IntuiMessage
*im
;
200 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
201 while ((im
= (struct IntuiMessage
*) GetMsg (userport
)))
206 ReplyMsg ((struct Message
*)im
);
209 /* Delete message port */
210 DeleteMsgPort (userport
);
213 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_AFTER_CLOSEWINDOW
, IntuitionBase
);
215 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
216 ReturnVoid ("CloseWindow");
220 /******************************************************************************/
223 /* This is called from the intuition input handler */
224 VOID
int_closewindow(struct CloseWindowActionMsg
*msg
,
225 struct IntuitionBase
*IntuitionBase
)
227 /* Free everything except the applications messageport */
228 struct Window
*window
, *win2
;
229 struct Screen
*screen
;
230 struct MsgPort
*userport
;
231 struct IIHData
*iihd
;
233 BOOL do_unlockscreen
;
235 D(bug("CloseWindow (%p)\n", window
));
237 window
= msg
->window
;
239 RemoveResourceFromList(window
, RESOURCE_WINDOW
, IntuitionBase
);
241 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
243 /* if there is an active gadget in the window being closed, then make
245 if (iihd
->ActiveGadget
&&
246 !IS_SCREEN_GADGET(iihd
->ActiveGadget
) &&
247 (iihd
->GadgetInfo
.gi_Window
== window
))
249 struct Gadget
*gadget
= iihd
->ActiveGadget
;
251 switch(gadget
->GadgetType
& GTYP_GTYPEMASK
)
253 case GTYP_CUSTOMGADGET
:
255 struct gpGoInactive gpgi
;
257 gpgi
.MethodID
= GM_GOINACTIVE
;
258 gpgi
.gpgi_GInfo
= &iihd
->GadgetInfo
;
261 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
263 if (iihd
->ActiveSysGadget
)
265 gadget
= iihd
->ActiveSysGadget
;
266 iihd
->ActiveSysGadget
= NULL
;
268 if (IS_BOOPSI_GADGET(gadget
))
270 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
277 case GTYP_BOOLGADGET
:
278 gadget
->Flags
&= ~GFLG_SELECTED
;
282 gadget
->Activation
&= ~GACT_ACTIVEGADGET
;
284 iihd
->ActiveGadget
= NULL
;
287 /* Need this in case of a window created under the input.device task context */
288 screen
= window
->WScreen
;
289 userport
= window
->UserPort
;
290 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
292 /* Check if there are still some requesters */
293 //jDc: do NOT use this! if there is a requester without ACTIVE flag set this routine will buysloop!
294 //jDc: moved this stuff down to layer dispose stuff!
295 /* while (window->FirstRequest)
296 EndRequest(window->FirstRequest, window);*/
298 lock
= LockIBase (0);
300 if (window
== IntuitionBase
->ActiveWindow
)
301 IntuitionBase
->ActiveWindow
= NULL
;
302 if (window
== iihd
->NewActWindow
) iihd
->NewActWindow
= NULL
;
304 /* Remove window from the parent/descendant chain and find next active window
307 ** before: parent win xyz
314 ** descendant win abc
316 ** after: parent win xyz
320 ** descendant win abc
324 if (window
->Descendant
)
325 window
->Descendant
->Parent
= window
->Parent
;
327 window
->Parent
->Descendant
= window
->Descendant
;
329 /* Was this the active window? */
330 if (!IntuitionBase
->ActiveWindow
)
332 /* If so, we need to find out which window to make
333 active now. We first check whether we have a "parent",
334 which is a window that was open before the one we're closing. */
336 ActivateWindow (window
->Parent
);
338 /* Otherwise, we find out which was the latest one, and activate it.
339 It's debatable whether this is the best policy, but this is how
340 AmigaOS(TM) does it. */
341 if ((win2
= window
->Descendant
))
343 for (;win2
->Descendant
; win2
= win2
->Descendant
);
344 ActivateWindow (win2
);
348 /* Make sure the Screen's window list is still valid */
350 if (window
== window
->WScreen
->FirstWindow
)
352 window
->WScreen
->FirstWindow
= window
->NextWindow
;
354 else if ((win2
= window
->WScreen
->FirstWindow
))
356 while (win2
->NextWindow
)
358 if (win2
->NextWindow
== window
)
360 win2
->NextWindow
= window
->NextWindow
;
363 win2
= win2
->NextWindow
;
369 #ifdef TIMEVALWINDOWACTIVATION
370 if (window
->WScreen
->FirstWindow
&& !IntuitionBase
->ActiveWindow
)
372 struct Window
*neww
= 0,*scanw
= 0;
374 for (scanw
= window
->WScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
378 if ((IW(scanw
)->activationtime
.tv_secs
> IW(neww
)->activationtime
.tv_secs
) ||
379 ((IW(scanw
)->activationtime
.tv_secs
== IW(neww
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(neww
)->activationtime
.tv_micro
)))
385 if (!neww
) neww
= scanw
;
388 if (neww
) ActivateWindow(neww
);
395 LOCK_REFRESH(screen
);
397 /* IFont may be NULL if we are called from an OpenWindow failure */
399 CloseFont (window
->IFont
);
402 if (IW(window
)->trashregion
) DisposeRegion(IW(window
)->trashregion
);
405 if (window
->FirstRequest
)
407 struct Requester
*r
= window
->FirstRequest
;
411 if (r
->ReqLayer
) DeleteLayer(0,r
->ReqLayer
);
417 // remove transparency!
421 InstallTransparentRegionHook(WLAYER(window
),NULL
);
422 InstallTransparentRegion(WLAYER(window
),NULL
);
425 if (((struct IntWindow
*)(window
))->transpregion
) DisposeRegion(((struct IntWindow
*)(window
))->transpregion
);
428 /* Let the driver clean up. Driver wil dealloc window's rastport */
429 intui_CloseWindow (window
, IntuitionBase
);
431 /* jDc: trash the screen pointer to avoid unnecessary checks in WindowValid() and
433 window
->WScreen
= (struct Screen
*)0xC0DEBAD0;
435 /* Remove the Window Outline Shape */
436 if (((struct IntWindow
*)window
)->OutlineShape
) DisposeRegion(((struct IntWindow
*)window
)->OutlineShape
);
437 /* Push ExitScreen Message to the Screensdecoration Class */
438 struct wdpExitWindow wemsg
;
440 wemsg
.MethodID
= WDM_EXITWINDOW
;
441 wemsg
.wdp_UserBuffer
= ((struct IntWindow
*)window
)->DecorUserBuffer
;
442 wemsg
.wdp_TrueColor
= (((struct IntScreen
*)screen
)->DInfo
.dri
.dri_Flags
& DRIF_DIRECTCOLOR
);
444 DoMethodA(((struct IntScreen
*)(screen
))->WinDecorObj
, (Msg
)&wemsg
);
446 if (((struct IntWindow
*)window
)->DecorUserBuffer
)
448 FreeMem((APTR
)((struct IntWindow
*)window
)->DecorUserBuffer
, ((struct IntWindow
*)window
)->DecorUserBufferSize
);
452 /* Free memory for the window */
453 FreeMem (window
, sizeof(struct IntWindow
));
455 CheckLayers(screen
, IntuitionBase
);
457 UNLOCK_REFRESH(screen
);
458 } /* int_closewindow */
461 /**********************************************************************************/
464 void intui_CloseWindow (struct Window
* w
,
465 struct IntuitionBase
* IntuitionBase
)
467 KillWinSysGadgets(w
, IntuitionBase
);
469 if (0 == (w
->Flags
& WFLG_GIMMEZEROZERO
))
471 /* not a GZZ window */
473 DeleteLayer(0, WLAYER(w
));
474 DeinitRastPort(w
->BorderRPort
);
475 FreeMem(w
->BorderRPort
, sizeof(struct RastPort
));
480 /* delete inner window */
481 if (NULL
!= WLAYER(w
))
482 DeleteLayer(0, WLAYER(w
));
484 /* delete outer window */
485 if (NULL
!= BLAYER(w
))
486 DeleteLayer(0, BLAYER(w
));
489 if (IW(w
)->free_pointer
)
490 DisposeObject(IW(w
)->pointer
);