2 Copyright © 1995-2013, 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 disappeared when this function returns.
73 OpenWindow(), OpenWindowTagList()
77 *****************************************************************************/
81 struct CloseWindowActionMsg msg
;
82 struct MsgPort
*userport
;
83 #if USE_IDCMPUPDATE_MESSAGECACHE
84 struct IntuiMessage
*messagecache
;
86 struct Screen
*screen
;
89 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window
));
91 D(bug("CloseWindow (%p)\n", window
));
95 ReturnVoid ("CloseWindow");
98 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_BEFORE_CLOSEWINDOW
, IntuitionBase
);
101 screen
= window
->WScreen
;
102 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
105 /* We take a very simple approach to avoid race conditions with the
106 intuition input handler running one input.device 's task:
107 We just send it a msg about closing the window
109 if (HAS_CHILDREN(window
))
111 struct Window
* cw
= window
->firstchild
;
113 * First close all its children, we could also return
114 * a failure value which newer apps that use child windows
128 if (IS_CHILD(window
))
131 * Unlink the window from its parent or
132 * out of the list of child windows.
134 if (window
->parent
->firstchild
== window
)
135 window
->parent
->firstchild
= window
->nextchild
;
137 window
->prevchild
->nextchild
= window
->nextchild
;
139 if (window
->nextchild
)
140 window
->nextchild
->prevchild
= window
->prevchild
;
145 /* We must save this here, because after we have returned from
146 the Wait() the window is gone */
147 userport
= window
->UserPort
;
149 #if USE_IDCMPUPDATE_MESSAGECACHE
150 messagecache
= IW(window
)->messagecache
;
153 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport
));
155 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
158 /* wait until other open/close && move/size && menus actions are finished */
159 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
161 ObtainSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
166 DoSyncAction((APTR
)int_closewindow
, &msg
.msg
, IntuitionBase
);
169 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
171 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
175 if (do_unlockscreen
) UnlockPubScreen(NULL
, screen
);
177 /* As of now intuition has removed us from the list of
178 windows, and we will receive no more messages
180 #if USE_IDCMPUPDATE_MESSAGECACHE
183 messagecache
->IDCMPWindow
= 0;//zero or we'll trash mem in inputhandler!
184 messagecache
->Code
= 0;
185 messagecache
->Qualifier
= 0;
186 ReplyMsg(&messagecache
->ExecMessage
);
192 struct IntuiMessage
*im
;
194 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
195 while ((im
= (struct IntuiMessage
*) GetMsg (userport
)))
200 ReplyMsg ((struct Message
*)im
);
203 /* Delete message port */
204 DeleteMsgPort (userport
);
207 FireScreenNotifyMessage((IPTR
) window
, SNOTIFY_AFTER_CLOSEWINDOW
, IntuitionBase
);
209 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
210 ReturnVoid ("CloseWindow");
214 /******************************************************************************/
217 /* This is called from the intuition input handler */
218 VOID
int_closewindow(struct CloseWindowActionMsg
*msg
,
219 struct IntuitionBase
*IntuitionBase
)
221 /* Free everything except the applications messageport */
222 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
223 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
224 struct Window
*window
, *win2
;
225 struct Screen
*screen
;
226 struct IIHData
*iihd
;
229 window
= msg
->window
;
231 D(bug("CloseWindow (%p)\n", window
));
233 RemoveResourceFromList(window
, RESOURCE_WINDOW
, IntuitionBase
);
235 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
237 /* if there is an active gadget in the window being closed, then make
239 if (iihd
->ActiveGadget
&&
240 !IS_SCREEN_GADGET(iihd
->ActiveGadget
) &&
241 (iihd
->GadgetInfo
.gi_Window
== window
))
243 struct Gadget
*gadget
= iihd
->ActiveGadget
;
245 switch(gadget
->GadgetType
& GTYP_GTYPEMASK
)
247 case GTYP_CUSTOMGADGET
:
249 struct gpGoInactive gpgi
;
251 gpgi
.MethodID
= GM_GOINACTIVE
;
252 gpgi
.gpgi_GInfo
= &iihd
->GadgetInfo
;
255 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
257 if (iihd
->ActiveSysGadget
)
259 gadget
= iihd
->ActiveSysGadget
;
260 iihd
->ActiveSysGadget
= NULL
;
262 if (IS_BOOPSI_GADGET(gadget
))
264 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
271 case GTYP_BOOLGADGET
:
272 gadget
->Flags
&= ~GFLG_SELECTED
;
276 gadget
->Activation
&= ~GACT_ACTIVEGADGET
;
278 iihd
->ActiveGadget
= NULL
;
281 /* Need this in case of a window created under the input.device task context */
282 screen
= window
->WScreen
;
284 /* Check if there are still some requesters */
285 //jDc: do NOT use this! if there is a requester without ACTIVE flag set this routine will buysloop!
286 //jDc: moved this stuff down to layer dispose stuff!
287 /* while (window->FirstRequest)
288 EndRequest(window->FirstRequest, window);*/
290 lock
= LockIBase (0);
292 if (window
== IntuitionBase
->ActiveWindow
)
293 IntuitionBase
->ActiveWindow
= NULL
;
294 if (window
== iihd
->NewActWindow
) iihd
->NewActWindow
= NULL
;
296 /* Remove window from the parent/descendant chain and find next active window
299 ** before: parent win xyz
306 ** descendant win abc
308 ** after: parent win xyz
312 ** descendant win abc
316 if (window
->Descendant
)
317 window
->Descendant
->Parent
= window
->Parent
;
319 window
->Parent
->Descendant
= window
->Descendant
;
321 /* Was this the active window? */
322 if (!IntuitionBase
->ActiveWindow
)
324 /* If so, we need to find out which window to make
325 active now. We first check whether we have a "parent",
326 which is a window that was open before the one we're closing. */
328 ActivateWindow (window
->Parent
);
330 /* Otherwise, we find out which was the latest one, and activate it.
331 It's debatable whether this is the best policy, but this is how
332 AmigaOS(TM) does it. */
333 if ((win2
= window
->Descendant
))
335 for (;win2
->Descendant
; win2
= win2
->Descendant
);
336 ActivateWindow (win2
);
340 /* Make sure the Screen's window list is still valid */
342 if (window
== window
->WScreen
->FirstWindow
)
344 window
->WScreen
->FirstWindow
= window
->NextWindow
;
346 else if ((win2
= window
->WScreen
->FirstWindow
))
348 while (win2
->NextWindow
)
350 if (win2
->NextWindow
== window
)
352 win2
->NextWindow
= window
->NextWindow
;
355 win2
= win2
->NextWindow
;
361 #ifdef TIMEVALWINDOWACTIVATION
362 if (window
->WScreen
->FirstWindow
&& !IntuitionBase
->ActiveWindow
)
364 struct Window
*neww
= 0,*scanw
= 0;
366 for (scanw
= window
->WScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
370 if ((IW(scanw
)->activationtime
.tv_secs
> IW(neww
)->activationtime
.tv_secs
) ||
371 ((IW(scanw
)->activationtime
.tv_secs
== IW(neww
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(neww
)->activationtime
.tv_micro
)))
377 if (!neww
) neww
= scanw
;
380 if (neww
) ActivateWindow(neww
);
387 LOCK_REFRESH(screen
);
389 /* IFont may be NULL if we are called from an OpenWindow failure */
391 CloseFont (window
->IFont
);
394 if (IW(window
)->trashregion
) DisposeRegion(IW(window
)->trashregion
);
397 if (window
->FirstRequest
)
399 struct Requester
*r
= window
->FirstRequest
;
403 if (r
->ReqLayer
) DeleteLayer(0,r
->ReqLayer
);
409 // remove transparency!
413 InstallTransparentRegionHook(WLAYER(window
),NULL
);
414 InstallTransparentRegion(WLAYER(window
),NULL
);
417 if (((struct IntWindow
*)(window
))->transpregion
) DisposeRegion(((struct IntWindow
*)(window
))->transpregion
);
420 /* Let the driver clean up. Driver wil dealloc window's rastport */
421 intui_CloseWindow (window
, IntuitionBase
);
423 /* jDc: trash the screen pointer to avoid unnecessary checks in WindowValid() and
425 window
->WScreen
= (struct Screen
*)0xC0DEBAD0;
427 /* Remove the Window Outline Shape */
428 if (((struct IntWindow
*)window
)->OutlineShape
) DisposeRegion(((struct IntWindow
*)window
)->OutlineShape
);
429 /* Push ExitScreen Message to the Screensdecoration Class */
430 struct wdpExitWindow wemsg
;
432 wemsg
.MethodID
= WDM_EXITWINDOW
;
433 wemsg
.wdp_UserBuffer
= ((struct IntWindow
*)window
)->DecorUserBuffer
;
434 wemsg
.wdp_TrueColor
= (((struct IntScreen
*)screen
)->DInfo
.dri_Flags
& DRIF_DIRECTCOLOR
) ? TRUE
: FALSE
;
436 DoMethodA(((struct IntScreen
*)(screen
))->WinDecorObj
, (Msg
)&wemsg
);
438 if (((struct IntWindow
*)window
)->DecorUserBuffer
)
440 FreeMem((APTR
)((struct IntWindow
*)window
)->DecorUserBuffer
, ((struct IntWindow
*)window
)->DecorUserBufferSize
);
444 /* Free memory for the window */
445 FreeMem (window
, sizeof(struct IntWindow
));
447 CheckLayers(screen
, IntuitionBase
);
449 UNLOCK_REFRESH(screen
);
450 } /* int_closewindow */
453 /**********************************************************************************/
456 void intui_CloseWindow (struct Window
* w
,
457 struct IntuitionBase
* IntuitionBase
)
459 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
460 KillWinSysGadgets(w
, IntuitionBase
);
462 if (0 == (w
->Flags
& WFLG_GIMMEZEROZERO
))
464 /* not a GZZ window */
466 DeleteLayer(0, WLAYER(w
));
467 DeinitRastPort(w
->BorderRPort
);
468 FreeMem(w
->BorderRPort
, sizeof(struct RastPort
));
473 /* delete inner window */
474 if (NULL
!= WLAYER(w
))
475 DeleteLayer(0, WLAYER(w
));
477 /* delete outer window */
478 if (NULL
!= BLAYER(w
))
479 DeleteLayer(0, BLAYER(w
));
482 if (IW(w
)->free_pointer
)
483 DisposeObject(IW(w
)->pointer
);