Minor fixes to comments.
[AROS.git] / rom / intuition / closewindow.c
blobe3dc74405c4e842029b7dacb50c631d288f10572
1 /*
2 Copyright 1995-2011, 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(), OpenWindowTagList()
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
85 struct CloseWindowActionMsg msg;
86 struct MsgPort *userport;
87 #if USE_IDCMPUPDATE_MESSAGECACHE
88 struct IntuiMessage *messagecache;
89 #endif
90 struct Screen *screen;
91 BOOL do_unlockscreen;
93 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window));
95 D(bug("CloseWindow (%p)\n", window));
97 if ( window == NULL )
99 ReturnVoid ("CloseWindow");
102 FireScreenNotifyMessage((IPTR) window, SNOTIFY_BEFORE_CLOSEWINDOW, IntuitionBase);
105 screen = window->WScreen;
106 do_unlockscreen = MUST_UNLOCK_SCREEN(window, screen);
108 #ifndef __MORPHOS__
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
119 * have to look at.
121 while (cw)
123 struct Window * _cw;
125 _cw = cw->nextchild;
126 CloseWindow(cw);
127 cw = _cw;
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;
140 else
141 window->prevchild->nextchild = window->nextchild;
143 if (window->nextchild)
144 window->nextchild->prevchild = window->prevchild;
147 #endif
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;
155 #endif
157 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport));
159 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
161 #ifdef USEWINDOWLOCK
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);
167 #endif
169 msg.window = window;
170 DoSyncAction((APTR)int_closewindow, &msg.msg, IntuitionBase);
172 #ifdef USEWINDOWLOCK
173 if (!(FindTask(0) == ((struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data)->InputDeviceTask))
175 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
177 #endif
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
185 if (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);
192 #endif
194 if (userport)
196 struct IntuiMessage *im;
198 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
199 while ((im = (struct IntuiMessage *) GetMsg (userport)))
201 im->IDCMPWindow = 0;
202 im->Code = 0;
203 im->Qualifier = 0;
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");
215 AROS_LIBFUNC_EXIT
216 } /* 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;
231 ULONG lock;
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
242 it inactive */
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;
257 gpgi.gpgi_Abort = 1;
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);
272 break;
274 case GTYP_STRGADGET:
275 case GTYP_BOOLGADGET:
276 gadget->Flags &= ~GFLG_SELECTED;
277 break;
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
304 ** \
305 ** \
306 ** deadwindow window
307 ** /
308 ** /
309 ** /
310 ** descendant win abc
312 ** after: parent win xyz
313 ** |
314 ** |
315 ** |
316 ** descendant win abc
320 if (window->Descendant)
321 window->Descendant->Parent = window->Parent;
322 if (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. */
331 if (window->Parent)
332 ActivateWindow (window->Parent);
333 else
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;
357 break;
359 win2 = win2->NextWindow;
363 UnlockIBase (lock);
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)
372 if (neww)
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)))
377 neww = scanw;
381 if (!neww) neww = scanw;
384 if (neww) ActivateWindow(neww);
387 #endif
389 /* Free resources */
391 LOCK_REFRESH(screen);
393 /* IFont may be NULL if we are called from an OpenWindow failure */
394 if (window->IFont)
395 CloseFont (window->IFont);
397 #ifdef DAMAGECACHE
398 if (IW(window)->trashregion) DisposeRegion(IW(window)->trashregion);
399 #endif
401 if (window->FirstRequest)
403 struct Requester *r = window->FirstRequest;
405 while (r)
407 if (r->ReqLayer) DeleteLayer(0,r->ReqLayer);
408 r->ReqLayer = 0;
409 r = r->OlderRequest;
413 // remove transparency!
414 #ifdef SKINS
415 if (WLAYER(window))
417 InstallTransparentRegionHook(WLAYER(window),NULL);
418 InstallTransparentRegion(WLAYER(window),NULL);
421 if (((struct IntWindow *)(window))->transpregion) DisposeRegion(((struct IntWindow *)(window))->transpregion);
422 #endif
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
428 memory corruption */
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 */
469 if (WLAYER(w))
470 DeleteLayer(0, WLAYER(w));
471 DeinitRastPort(w->BorderRPort);
472 FreeMem(w->BorderRPort, sizeof(struct RastPort));
474 else
476 /* a GZZ window */
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);