Don't get OOPBase in this ugly way.
[tangerine.git] / rom / intuition / closewindow.c
blob7927758c7366ca3daa70e3853989303bc10646ff
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
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
20 #endif
21 #undef DEBUG
22 #if DEBUG_CloseWindow
23 # define DEBUG 1
24 #endif
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 /*****************************************************************************
43 NAME */
44 #include <proto/intuition.h>
46 AROS_LH1(void, CloseWindow,
48 /* SYNOPSIS */
49 AROS_LHA(struct Window *, window, A0),
51 /* LOCATION */
52 struct IntuitionBase *, IntuitionBase, 12, Intuition)
54 /* FUNCTION
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.
59 INPUTS
60 window - The window to close
62 RESULT
63 None.
65 NOTES
66 The window might not have been disappeared when this function returns.
68 EXAMPLE
70 BUGS
72 SEE ALSO
73 OpenWindow(), OpenWindowTags()
75 INTERNALS
77 HISTORY
78 29-10-95 digulla automatically created from
79 intuition_lib.fd and clib/intuition_protos.h
81 *****************************************************************************/
83 AROS_LIBFUNC_INIT
84 AROS_LIBBASE_EXT_DECL(struct IntuitionBase *,IntuitionBase)
86 struct CloseWindowActionMsg msg;
87 struct IIHData *iihd;
88 struct MsgPort *userport;
89 #if USE_IDCMPUPDATE_MESSAGECACHE
90 struct IntuiMessage *messagecache;
91 #endif
92 struct Screen *screen;
93 BOOL do_unlockscreen;
95 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window));
97 D(bug("CloseWindow (%p)\n", window));
99 if ( window == NULL )
101 ReturnVoid ("CloseWindow");
104 iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
106 screen = window->WScreen;
107 do_unlockscreen = MUST_UNLOCK_SCREEN(window, screen);
109 #ifndef __MORPHOS__
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
120 * have to look at.
122 while (cw)
124 struct Window * _cw;
126 _cw = cw->nextchild;
127 CloseWindow(cw);
128 cw = _cw;
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;
141 else
142 window->prevchild->nextchild = window->nextchild;
144 if (window->nextchild)
145 window->nextchild->prevchild = window->prevchild;
148 #endif
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;
156 #endif
158 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport));
160 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
162 #ifdef USEWINDOWLOCK
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);
168 #endif
170 msg.window = window;
171 DoSyncAction((APTR)int_closewindow, &msg.msg, IntuitionBase);
173 #ifdef USEWINDOWLOCK
174 if (!(FindTask(0) == ((struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data)->InputDeviceTask))
176 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
178 #endif
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
186 if (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);
193 #endif
195 if (userport)
197 struct IntuiMessage *im;
199 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
200 while ((im = (struct IntuiMessage *) GetMsg (userport)))
202 im->IDCMPWindow = 0;
203 im->Code = 0;
204 im->Qualifier = 0;
205 ReplyMsg ((struct Message *)im);
208 /* Delete message port */
209 DeleteMsgPort (userport);
212 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
213 ReturnVoid ("CloseWindow");
214 AROS_LIBFUNC_EXIT
215 } /* 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;
229 ULONG lock;
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
241 it inactive */
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;
256 gpgi.gpgi_Abort = 1;
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);
271 break;
273 case GTYP_STRGADGET:
274 case GTYP_BOOLGADGET:
275 gadget->Flags &= ~GFLG_SELECTED;
276 break;
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
305 ** \
306 ** \
307 ** deadwindow window
308 ** /
309 ** /
310 ** /
311 ** descendant win abc
313 ** after: parent win xyz
314 ** |
315 ** |
316 ** |
317 ** descendant win abc
321 if (window->Descendant)
322 window->Descendant->Parent = window->Parent;
323 if (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. */
332 if (window->Parent)
333 ActivateWindow (window->Parent);
334 else
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;
358 break;
360 win2 = win2->NextWindow;
364 UnlockIBase (lock);
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)
373 if (neww)
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)))
378 neww = scanw;
382 if (!neww) neww = scanw;
385 if (neww) ActivateWindow(neww);
388 #endif
390 /* Free resources */
392 LOCK_REFRESH(screen);
394 /* IFont may be NULL if we are called from an OpenWindow failure */
395 if (window->IFont)
396 CloseFont (window->IFont);
398 #ifdef DAMAGECACHE
399 if (IW(window)->trashregion) DisposeRegion(IW(window)->trashregion);
400 #endif
402 if (window->FirstRequest)
404 struct Requester *r = window->FirstRequest;
406 while (r)
408 if (r->ReqLayer) DeleteLayer(0,r->ReqLayer);
409 r->ReqLayer = 0;
410 r = r->OlderRequest;
414 // remove transparency!
415 #ifdef SKINS
416 if (WLAYER(window))
418 InstallTransparentRegionHook(WLAYER(window),NULL);
419 InstallTransparentRegion(WLAYER(window),NULL);
422 if (((struct IntWindow *)(window))->transpregion) DisposeRegion(((struct IntWindow *)(window))->transpregion);
423 #endif
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
429 memory corruption */
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 */
452 if (WLAYER(w))
453 DeleteLayer(0, WLAYER(w));
454 DeinitRastPort(w->BorderRPort);
455 FreeMem(w->BorderRPort, sizeof(struct RastPort));
457 else
459 /* a GZZ window */
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);