2 Copyright © 1995-2003, 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(), OpenWindowTags()
78 29-10-95 digulla automatically created from
79 intuition_lib.fd and clib/intuition_protos.h
81 *****************************************************************************/
84 AROS_LIBBASE_EXT_DECL(struct IntuitionBase
*,IntuitionBase
)
86 struct CloseWindowActionMsg msg
;
88 struct MsgPort
*userport
;
89 #if USE_IDCMPUPDATE_MESSAGECACHE
90 struct IntuiMessage
*messagecache
;
92 struct Screen
*screen
;
95 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window
));
97 D(bug("CloseWindow (%p)\n", window
));
101 ReturnVoid ("CloseWindow");
104 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
106 screen
= window
->WScreen
;
107 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
110 /* We take a very simple approach to avoid race conditions with the
111 intuition input handler running one input.device 's task:
112 We just send it a msg about closing the window
114 if (HAS_CHILDREN(window
))
116 struct Window
* cw
= window
->firstchild
;
118 * First close all its children, we could also return
119 * a failure value which newer apps that use child windows
133 if (IS_CHILD(window
))
136 * Unlink the window from its parent or
137 * out of the list of child windows.
139 if (window
->parent
->firstchild
== window
)
140 window
->parent
->firstchild
= window
->nextchild
;
142 window
->prevchild
->nextchild
= window
->nextchild
;
144 if (window
->nextchild
)
145 window
->nextchild
->prevchild
= window
->prevchild
;
150 /* We must save this here, because after we have returned from
151 the Wait() the window is gone */
152 userport
= window
->UserPort
;
154 #if USE_IDCMPUPDATE_MESSAGECACHE
155 messagecache
= IW(window
)->messagecache
;
158 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport
));
160 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
163 /* wait until other open/close && move/size && menus actions are finished */
164 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
166 ObtainSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
171 DoSyncAction((APTR
)int_closewindow
, &msg
.msg
, IntuitionBase
);
174 if (!(FindTask(0) == ((struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
)->InputDeviceTask
))
176 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
180 if (do_unlockscreen
) UnlockPubScreen(NULL
, screen
);
182 /* As of now intuition has removed us from th list of
183 windows, and we will recieve no more messages
185 #if USE_IDCMPUPDATE_MESSAGECACHE
188 messagecache
->IDCMPWindow
= 0;//zero or we'll trash mem in inputhandler!
189 messagecache
->Code
= 0;
190 messagecache
->Qualifier
= 0;
191 ReplyMsg(&messagecache
->ExecMessage
);
197 struct IntuiMessage
*im
;
199 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
200 while ((im
= (struct IntuiMessage
*) GetMsg (userport
)))
205 ReplyMsg ((struct Message
*)im
);
208 /* Delete message port */
209 DeleteMsgPort (userport
);
212 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
213 ReturnVoid ("CloseWindow");
217 /******************************************************************************/
220 /* This is called from the intuition input handler */
221 VOID
int_closewindow(struct CloseWindowActionMsg
*msg
,
222 struct IntuitionBase
*IntuitionBase
)
224 /* Free everything except the applications messageport */
225 struct Window
*window
, *win2
;
226 struct Screen
*screen
;
227 struct MsgPort
*userport
;
228 struct IIHData
*iihd
;
230 BOOL do_unlockscreen
;
232 D(bug("CloseWindow (%p)\n", window
));
234 window
= msg
->window
;
236 RemoveResourceFromList(window
, RESOURCE_WINDOW
, IntuitionBase
);
238 iihd
= (struct IIHData
*)GetPrivIBase(IntuitionBase
)->InputHandler
->is_Data
;
240 /* if there is an active gadget in the window being closed, then make
242 if (iihd
->ActiveGadget
&&
243 !IS_SCREEN_GADGET(iihd
->ActiveGadget
) &&
244 (iihd
->GadgetInfo
.gi_Window
== window
))
246 struct Gadget
*gadget
= iihd
->ActiveGadget
;
248 switch(gadget
->GadgetType
& GTYP_GTYPEMASK
)
250 case GTYP_CUSTOMGADGET
:
252 struct gpGoInactive gpgi
;
254 gpgi
.MethodID
= GM_GOINACTIVE
;
255 gpgi
.gpgi_GInfo
= &iihd
->GadgetInfo
;
258 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
260 if (iihd
->ActiveSysGadget
)
262 gadget
= iihd
->ActiveSysGadget
;
263 iihd
->ActiveSysGadget
= NULL
;
265 if (IS_BOOPSI_GADGET(gadget
))
267 Locked_DoMethodA(window
, gadget
, (Msg
)&gpgi
, IntuitionBase
);
274 case GTYP_BOOLGADGET
:
275 gadget
->Flags
&= ~GFLG_SELECTED
;
279 gadget
->Activation
&= ~GACT_ACTIVEGADGET
;
281 iihd
->ActiveGadget
= NULL
;
284 /* Need this in case of a window created under the input.device task context */
285 screen
= window
->WScreen
;
286 userport
= window
->UserPort
;
287 do_unlockscreen
= MUST_UNLOCK_SCREEN(window
, screen
);
289 /* Check if there are still some requesters */
290 //jDc: do NOT use this! if there is a requester without ACTIVE flag set this routine will buysloop!
291 //jDc: moved this stuff down to layer dispose stuff!
292 /* while (window->FirstRequest)
293 EndRequest(window->FirstRequest, window);*/
295 lock
= LockIBase (0);
297 if (window
== IntuitionBase
->ActiveWindow
)
298 IntuitionBase
->ActiveWindow
= NULL
;
299 if (window
== iihd
->NewActWindow
) iihd
->NewActWindow
= NULL
;
301 /* Remove window from the parent/descendant chain and find next active window
304 ** before: parent win xyz
311 ** descendant win abc
313 ** after: parent win xyz
317 ** descendant win abc
321 if (window
->Descendant
)
322 window
->Descendant
->Parent
= window
->Parent
;
324 window
->Parent
->Descendant
= window
->Descendant
;
326 /* Was this the active window? */
327 if (!IntuitionBase
->ActiveWindow
)
329 /* If so, we need to find out which window to make
330 active now. We first check whether we have a "parent",
331 which is a window that was open before the one we're closing. */
333 ActivateWindow (window
->Parent
);
335 /* Otherwise, we find out which was the latest one, and activate it.
336 It's debatable whether this is the best policy, but this is how
337 AmigaOS(TM) does it. */
338 if ((win2
= window
->Descendant
))
340 for (;win2
->Descendant
; win2
= win2
->Descendant
);
341 ActivateWindow (win2
);
345 /* Make sure the Screen's window list is still valid */
347 if (window
== window
->WScreen
->FirstWindow
)
349 window
->WScreen
->FirstWindow
= window
->NextWindow
;
351 else if ((win2
= window
->WScreen
->FirstWindow
))
353 while (win2
->NextWindow
)
355 if (win2
->NextWindow
== window
)
357 win2
->NextWindow
= window
->NextWindow
;
360 win2
= win2
->NextWindow
;
366 #ifdef TIMEVALWINDOWACTIVATION
367 if (window
->WScreen
->FirstWindow
&& !IntuitionBase
->ActiveWindow
)
369 struct Window
*neww
= 0,*scanw
= 0;
371 for (scanw
= window
->WScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
375 if ((IW(scanw
)->activationtime
.tv_secs
> IW(neww
)->activationtime
.tv_secs
) ||
376 ((IW(scanw
)->activationtime
.tv_secs
== IW(neww
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(neww
)->activationtime
.tv_micro
)))
382 if (!neww
) neww
= scanw
;
385 if (neww
) ActivateWindow(neww
);
392 LOCK_REFRESH(screen
);
394 /* IFont may be NULL if we are called from an OpenWindow failure */
396 CloseFont (window
->IFont
);
399 if (IW(window
)->trashregion
) DisposeRegion(IW(window
)->trashregion
);
402 if (window
->FirstRequest
)
404 struct Requester
*r
= window
->FirstRequest
;
408 if (r
->ReqLayer
) DeleteLayer(0,r
->ReqLayer
);
414 // remove transparency!
418 InstallTransparentRegionHook(WLAYER(window
),NULL
);
419 InstallTransparentRegion(WLAYER(window
),NULL
);
422 if (((struct IntWindow
*)(window
))->transpregion
) DisposeRegion(((struct IntWindow
*)(window
))->transpregion
);
425 /* Let the driver clean up. Driver wil dealloc window's rastport */
426 intui_CloseWindow (window
, IntuitionBase
);
428 /* jDc: trash the screen pointer to avoid unnecessary checks in WindowValid() and
430 window
->WScreen
= (struct Screen
*)0xC0DEBAD0;
432 /* Free memory for the window */
433 FreeMem (window
, sizeof(struct IntWindow
));
435 CheckLayers(screen
, IntuitionBase
);
437 UNLOCK_REFRESH(screen
);
438 } /* int_closewindow */
441 /**********************************************************************************/
444 void intui_CloseWindow (struct Window
* w
,
445 struct IntuitionBase
* IntuitionBase
)
447 KillWinSysGadgets(w
, IntuitionBase
);
449 if (0 == (w
->Flags
& WFLG_GIMMEZEROZERO
))
451 /* not a GZZ window */
453 DeleteLayer(0, WLAYER(w
));
454 DeinitRastPort(w
->BorderRPort
);
455 FreeMem(w
->BorderRPort
, sizeof(struct RastPort
));
460 /* delete inner window */
461 if (NULL
!= WLAYER(w
))
462 DeleteLayer(0, WLAYER(w
));
464 /* delete outer window */
465 if (NULL
!= BLAYER(w
))
466 DeleteLayer(0, BLAYER(w
));
469 if (IW(w
)->free_pointer
)
470 DisposeObject(IW(w
)->pointer
);