2 Copyright 1995-2011, 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
;
86 struct MsgPort
*userport
;
87 #if USE_IDCMPUPDATE_MESSAGECACHE
88 struct IntuiMessage
*messagecache
;
90 struct Screen
*screen
;
93 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window
));
95 D(bug("CloseWindow (%p)\n", window
));
99 ReturnVoid ("CloseWindow");
102 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_BEFORE_CLOSEWINDOW
, IntuitionBase
);
105 screen
= window
->WScreen
;
106 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
109 /* We take a very simple approach to avoid race conditions with the
110 intuition input handler running one input.device 's task:
111 We just send it a msg about closing the window
113 if (HAS_CHILDREN(window
))
115 struct Window
* cw
= window
->firstchild
;
117 * First close all its children, we could also return
118 * a failure value which newer apps that use child windows
132 if (IS_CHILD(window
))
135 * Unlink the window from its parent or
136 * out of the list of child windows.
138 if (window
->parent
->firstchild
== window
)
139 window
->parent
->firstchild
= window
->nextchild
;
141 window
->prevchild
->nextchild
= window
->nextchild
;
143 if (window
->nextchild
)
144 window
->nextchild
->prevchild
= window
->prevchild
;
149 /* We must save this here, because after we have returned from
150 the Wait() the window is gone */
151 userport
= window
->UserPort
;
153 #if USE_IDCMPUPDATE_MESSAGECACHE
154 messagecache
= IW(window
)->messagecache
;
157 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport
));
159 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
162 /* wait until other open/close && move/size && menus actions are finished */
163 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
165 ObtainSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
170 DoSyncAction((APTR
)int_closewindow
, &msg
.msg
, IntuitionBase
);
173 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
175 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
179 if (do_unlockscreen
) UnlockPubScreen(NULL
, screen
);
181 /* As of now intuition has removed us from the list of
182 windows, and we will receive no more messages
184 #if USE_IDCMPUPDATE_MESSAGECACHE
187 messagecache
->IDCMPWindow
= 0;//zero or we'll trash mem in inputhandler!
188 messagecache
->Code
= 0;
189 messagecache
->Qualifier
= 0;
190 ReplyMsg(&messagecache
->ExecMessage
);
196 struct IntuiMessage
*im
;
198 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
199 while ((im
= (struct IntuiMessage
*) GetMsg (userport
)))
204 ReplyMsg ((struct Message
*)im
);
207 /* Delete message port */
208 DeleteMsgPort (userport
);
211 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_AFTER_CLOSEWINDOW
, IntuitionBase
);
213 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
214 ReturnVoid ("CloseWindow");
218 /******************************************************************************/
221 /* This is called from the intuition input handler */
222 VOID
int_closewindow(struct CloseWindowActionMsg
*msg
,
223 struct IntuitionBase
*IntuitionBase
)
225 /* Free everything except the applications messageport */
226 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
227 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
228 struct Window
*window
, *win2
;
229 struct Screen
*screen
;
230 struct IIHData
*iihd
;
233 D(bug("CloseWindow (%p)\n", window
));
235 window
= msg
->window
;
237 RemoveResourceFromList(window
, RESOURCE_WINDOW
, IntuitionBase
);
239 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
241 /* if there is an active gadget in the window being closed, then make
243 if (iihd
->ActiveGadget
&&
244 !IS_SCREEN_GADGET(iihd
->ActiveGadget
) &&
245 (iihd
->GadgetInfo
.gi_Window
== window
))
247 struct Gadget
*gadget
= iihd
->ActiveGadget
;
249 switch(gadget
->GadgetType
& GTYP_GTYPEMASK
)
251 case GTYP_CUSTOMGADGET
:
253 struct gpGoInactive gpgi
;
255 gpgi
.MethodID
= GM_GOINACTIVE
;
256 gpgi
.gpgi_GInfo
= &iihd
->GadgetInfo
;
259 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
261 if (iihd
->ActiveSysGadget
)
263 gadget
= iihd
->ActiveSysGadget
;
264 iihd
->ActiveSysGadget
= NULL
;
266 if (IS_BOOPSI_GADGET(gadget
))
268 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
275 case GTYP_BOOLGADGET
:
276 gadget
->Flags
&= ~GFLG_SELECTED
;
280 gadget
->Activation
&= ~GACT_ACTIVEGADGET
;
282 iihd
->ActiveGadget
= NULL
;
285 /* Need this in case of a window created under the input.device task context */
286 screen
= window
->WScreen
;
288 /* Check if there are still some requesters */
289 //jDc: do NOT use this! if there is a requester without ACTIVE flag set this routine will buysloop!
290 //jDc: moved this stuff down to layer dispose stuff!
291 /* while (window->FirstRequest)
292 EndRequest(window->FirstRequest, window);*/
294 lock
= LockIBase (0);
296 if (window
== IntuitionBase
->ActiveWindow
)
297 IntuitionBase
->ActiveWindow
= NULL
;
298 if (window
== iihd
->NewActWindow
) iihd
->NewActWindow
= NULL
;
300 /* Remove window from the parent/descendant chain and find next active window
303 ** before: parent win xyz
310 ** descendant win abc
312 ** after: parent win xyz
316 ** descendant win abc
320 if (window
->Descendant
)
321 window
->Descendant
->Parent
= window
->Parent
;
323 window
->Parent
->Descendant
= window
->Descendant
;
325 /* Was this the active window? */
326 if (!IntuitionBase
->ActiveWindow
)
328 /* If so, we need to find out which window to make
329 active now. We first check whether we have a "parent",
330 which is a window that was open before the one we're closing. */
332 ActivateWindow (window
->Parent
);
334 /* Otherwise, we find out which was the latest one, and activate it.
335 It's debatable whether this is the best policy, but this is how
336 AmigaOS(TM) does it. */
337 if ((win2
= window
->Descendant
))
339 for (;win2
->Descendant
; win2
= win2
->Descendant
);
340 ActivateWindow (win2
);
344 /* Make sure the Screen's window list is still valid */
346 if (window
== window
->WScreen
->FirstWindow
)
348 window
->WScreen
->FirstWindow
= window
->NextWindow
;
350 else if ((win2
= window
->WScreen
->FirstWindow
))
352 while (win2
->NextWindow
)
354 if (win2
->NextWindow
== window
)
356 win2
->NextWindow
= window
->NextWindow
;
359 win2
= win2
->NextWindow
;
365 #ifdef TIMEVALWINDOWACTIVATION
366 if (window
->WScreen
->FirstWindow
&& !IntuitionBase
->ActiveWindow
)
368 struct Window
*neww
= 0,*scanw
= 0;
370 for (scanw
= window
->WScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
374 if ((IW(scanw
)->activationtime
.tv_secs
> IW(neww
)->activationtime
.tv_secs
) ||
375 ((IW(scanw
)->activationtime
.tv_secs
== IW(neww
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(neww
)->activationtime
.tv_micro
)))
381 if (!neww
) neww
= scanw
;
384 if (neww
) ActivateWindow(neww
);
391 LOCK_REFRESH(screen
);
393 /* IFont may be NULL if we are called from an OpenWindow failure */
395 CloseFont (window
->IFont
);
398 if (IW(window
)->trashregion
) DisposeRegion(IW(window
)->trashregion
);
401 if (window
->FirstRequest
)
403 struct Requester
*r
= window
->FirstRequest
;
407 if (r
->ReqLayer
) DeleteLayer(0,r
->ReqLayer
);
413 // remove transparency!
417 InstallTransparentRegionHook(WLAYER(window
),NULL
);
418 InstallTransparentRegion(WLAYER(window
),NULL
);
421 if (((struct IntWindow
*)(window
))->transpregion
) DisposeRegion(((struct IntWindow
*)(window
))->transpregion
);
424 /* Let the driver clean up. Driver wil dealloc window's rastport */
425 intui_CloseWindow (window
, IntuitionBase
);
427 /* jDc: trash the screen pointer to avoid unnecessary checks in WindowValid() and
429 window
->WScreen
= (struct Screen
*)0xC0DEBAD0;
431 /* Remove the Window Outline Shape */
432 if (((struct IntWindow
*)window
)->OutlineShape
) DisposeRegion(((struct IntWindow
*)window
)->OutlineShape
);
433 /* Push ExitScreen Message to the Screensdecoration Class */
434 struct wdpExitWindow wemsg
;
436 wemsg
.MethodID
= WDM_EXITWINDOW
;
437 wemsg
.wdp_UserBuffer
= ((struct IntWindow
*)window
)->DecorUserBuffer
;
438 wemsg
.wdp_TrueColor
= (((struct IntScreen
*)screen
)->DInfo
.dri
.dri_Flags
& DRIF_DIRECTCOLOR
);
440 DoMethodA(((struct IntScreen
*)(screen
))->WinDecorObj
, (Msg
)&wemsg
);
442 if (((struct IntWindow
*)window
)->DecorUserBuffer
)
444 FreeMem((APTR
)((struct IntWindow
*)window
)->DecorUserBuffer
, ((struct IntWindow
*)window
)->DecorUserBufferSize
);
448 /* Free memory for the window */
449 FreeMem (window
, sizeof(struct IntWindow
));
451 CheckLayers(screen
, IntuitionBase
);
453 UNLOCK_REFRESH(screen
);
454 } /* int_closewindow */
457 /**********************************************************************************/
460 void intui_CloseWindow (struct Window
* w
,
461 struct IntuitionBase
* IntuitionBase
)
463 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
464 KillWinSysGadgets(w
, IntuitionBase
);
466 if (0 == (w
->Flags
& WFLG_GIMMEZEROZERO
))
468 /* not a GZZ window */
470 DeleteLayer(0, WLAYER(w
));
471 DeinitRastPort(w
->BorderRPort
);
472 FreeMem(w
->BorderRPort
, sizeof(struct RastPort
));
477 /* delete inner window */
478 if (NULL
!= WLAYER(w
))
479 DeleteLayer(0, WLAYER(w
));
481 /* delete outer window */
482 if (NULL
!= BLAYER(w
))
483 DeleteLayer(0, BLAYER(w
));
486 if (IW(w
)->free_pointer
)
487 DisposeObject(IW(w
)->pointer
);