Added kernel module for starting the usb stack at boot time. It's not activated thoug...
[cake.git] / rom / intuition / closewindow.c
blob2bd1c118c05933b15b2ff44b93273000dfd35fca
1 /*
2 Copyright 1995-2007, 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 IIHData *iihd;
87 struct MsgPort *userport;
88 #if USE_IDCMPUPDATE_MESSAGECACHE
89 struct IntuiMessage *messagecache;
90 #endif
91 struct Screen *screen;
92 BOOL do_unlockscreen;
94 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Window 0x%lx\n", window));
96 D(bug("CloseWindow (%p)\n", window));
98 if ( window == NULL )
100 ReturnVoid ("CloseWindow");
103 FireScreenNotifyMessage((IPTR) window, SNOTIFY_BEFORE_CLOSEWINDOW, IntuitionBase);
105 iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
107 screen = window->WScreen;
108 do_unlockscreen = MUST_UNLOCK_SCREEN(window, screen);
110 #ifndef __MORPHOS__
111 /* We take a very simple approach to avoid race conditions with the
112 intuition input handler running one input.device 's task:
113 We just send it a msg about closing the window
115 if (HAS_CHILDREN(window))
117 struct Window * cw = window->firstchild;
119 * First close all its children, we could also return
120 * a failure value which newer apps that use child windows
121 * have to look at.
123 while (cw)
125 struct Window * _cw;
127 _cw = cw->nextchild;
128 CloseWindow(cw);
129 cw = _cw;
134 if (IS_CHILD(window))
137 * Unlink the window from its parent or
138 * out of the list of child windows.
140 if (window->parent->firstchild == window)
141 window->parent->firstchild = window->nextchild;
142 else
143 window->prevchild->nextchild = window->nextchild;
145 if (window->nextchild)
146 window->nextchild->prevchild = window->prevchild;
149 #endif
151 /* We must save this here, because after we have returned from
152 the Wait() the window is gone */
153 userport = window->UserPort;
155 #if USE_IDCMPUPDATE_MESSAGECACHE
156 messagecache = IW(window)->messagecache;
157 #endif
159 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Userport 0x%lx\n", userport));
161 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: DoSyncAction\n"));
163 #ifdef USEWINDOWLOCK
164 /* wait until other open/close && move/size && menus actions are finished */
165 if (!(FindTask(0) == ((struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data)->InputDeviceTask))
167 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
169 #endif
171 msg.window = window;
172 DoSyncAction((APTR)int_closewindow, &msg.msg, IntuitionBase);
174 #ifdef USEWINDOWLOCK
175 if (!(FindTask(0) == ((struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data)->InputDeviceTask))
177 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
179 #endif
181 if (do_unlockscreen) UnlockPubScreen(NULL, screen);
183 /* As of now intuition has removed us from th list of
184 windows, and we will recieve no more messages
186 #if USE_IDCMPUPDATE_MESSAGECACHE
187 if (messagecache)
189 messagecache->IDCMPWindow = 0;//zero or we'll trash mem in inputhandler!
190 messagecache->Code = 0;
191 messagecache->Qualifier = 0;
192 ReplyMsg(&messagecache->ExecMessage);
194 #endif
196 if (userport)
198 struct IntuiMessage *im;
200 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: Reply UserPort Msgs\n"));
201 while ((im = (struct IntuiMessage *) GetMsg (userport)))
203 im->IDCMPWindow = 0;
204 im->Code = 0;
205 im->Qualifier = 0;
206 ReplyMsg ((struct Message *)im);
209 /* Delete message port */
210 DeleteMsgPort (userport);
213 FireScreenNotifyMessage((IPTR) window, SNOTIFY_AFTER_CLOSEWINDOW, IntuitionBase);
215 DEBUG_CLOSEWINDOW(dprintf("CloseWindow: done\n"));
216 ReturnVoid ("CloseWindow");
217 AROS_LIBFUNC_EXIT
218 } /* CloseWindow */
220 /******************************************************************************/
223 /* This is called from the intuition input handler */
224 VOID int_closewindow(struct CloseWindowActionMsg *msg,
225 struct IntuitionBase *IntuitionBase)
227 /* Free everything except the applications messageport */
228 struct Window *window, *win2;
229 struct Screen *screen;
230 struct MsgPort *userport;
231 struct IIHData *iihd;
232 ULONG lock;
233 BOOL do_unlockscreen;
235 D(bug("CloseWindow (%p)\n", window));
237 window = msg->window;
239 RemoveResourceFromList(window, RESOURCE_WINDOW, IntuitionBase);
241 iihd = (struct IIHData *)GetPrivIBase(IntuitionBase)->InputHandler->is_Data;
243 /* if there is an active gadget in the window being closed, then make
244 it inactive */
245 if (iihd->ActiveGadget &&
246 !IS_SCREEN_GADGET(iihd->ActiveGadget) &&
247 (iihd->GadgetInfo.gi_Window == window))
249 struct Gadget *gadget = iihd->ActiveGadget;
251 switch(gadget->GadgetType & GTYP_GTYPEMASK)
253 case GTYP_CUSTOMGADGET:
255 struct gpGoInactive gpgi;
257 gpgi.MethodID = GM_GOINACTIVE;
258 gpgi.gpgi_GInfo = &iihd->GadgetInfo;
259 gpgi.gpgi_Abort = 1;
261 Locked_DoMethodA(window, gadget, (Msg)&gpgi, IntuitionBase);
263 if (iihd->ActiveSysGadget)
265 gadget = iihd->ActiveSysGadget;
266 iihd->ActiveSysGadget = NULL;
268 if (IS_BOOPSI_GADGET(gadget))
270 Locked_DoMethodA(window, gadget, (Msg)&gpgi, IntuitionBase);
274 break;
276 case GTYP_STRGADGET:
277 case GTYP_BOOLGADGET:
278 gadget->Flags &= ~GFLG_SELECTED;
279 break;
282 gadget->Activation &= ~GACT_ACTIVEGADGET;
284 iihd->ActiveGadget = NULL;
287 /* Need this in case of a window created under the input.device task context */
288 screen = window->WScreen;
289 userport = window->UserPort;
290 do_unlockscreen = MUST_UNLOCK_SCREEN(window, screen);
292 /* Check if there are still some requesters */
293 //jDc: do NOT use this! if there is a requester without ACTIVE flag set this routine will buysloop!
294 //jDc: moved this stuff down to layer dispose stuff!
295 /* while (window->FirstRequest)
296 EndRequest(window->FirstRequest, window);*/
298 lock = LockIBase (0);
300 if (window == IntuitionBase->ActiveWindow)
301 IntuitionBase->ActiveWindow = NULL;
302 if (window == iihd->NewActWindow) iihd->NewActWindow = NULL;
304 /* Remove window from the parent/descendant chain and find next active window
307 ** before: parent win xyz
308 ** \
309 ** \
310 ** deadwindow window
311 ** /
312 ** /
313 ** /
314 ** descendant win abc
316 ** after: parent win xyz
317 ** |
318 ** |
319 ** |
320 ** descendant win abc
324 if (window->Descendant)
325 window->Descendant->Parent = window->Parent;
326 if (window->Parent)
327 window->Parent->Descendant = window->Descendant;
329 /* Was this the active window? */
330 if (!IntuitionBase->ActiveWindow)
332 /* If so, we need to find out which window to make
333 active now. We first check whether we have a "parent",
334 which is a window that was open before the one we're closing. */
335 if (window->Parent)
336 ActivateWindow (window->Parent);
337 else
338 /* Otherwise, we find out which was the latest one, and activate it.
339 It's debatable whether this is the best policy, but this is how
340 AmigaOS(TM) does it. */
341 if ((win2 = window->Descendant))
343 for (;win2->Descendant; win2 = win2->Descendant);
344 ActivateWindow (win2);
348 /* Make sure the Screen's window list is still valid */
350 if (window == window->WScreen->FirstWindow)
352 window->WScreen->FirstWindow = window->NextWindow;
354 else if ((win2 = window->WScreen->FirstWindow))
356 while (win2->NextWindow)
358 if (win2->NextWindow == window)
360 win2->NextWindow = window->NextWindow;
361 break;
363 win2 = win2->NextWindow;
367 UnlockIBase (lock);
369 #ifdef TIMEVALWINDOWACTIVATION
370 if (window->WScreen->FirstWindow && !IntuitionBase->ActiveWindow)
372 struct Window *neww = 0,*scanw = 0;
374 for (scanw = window->WScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
376 if (neww)
378 if ((IW(scanw)->activationtime.tv_secs > IW(neww)->activationtime.tv_secs) ||
379 ((IW(scanw)->activationtime.tv_secs == IW(neww)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(neww)->activationtime.tv_micro)))
381 neww = scanw;
385 if (!neww) neww = scanw;
388 if (neww) ActivateWindow(neww);
391 #endif
393 /* Free resources */
395 LOCK_REFRESH(screen);
397 /* IFont may be NULL if we are called from an OpenWindow failure */
398 if (window->IFont)
399 CloseFont (window->IFont);
401 #ifdef DAMAGECACHE
402 if (IW(window)->trashregion) DisposeRegion(IW(window)->trashregion);
403 #endif
405 if (window->FirstRequest)
407 struct Requester *r = window->FirstRequest;
409 while (r)
411 if (r->ReqLayer) DeleteLayer(0,r->ReqLayer);
412 r->ReqLayer = 0;
413 r = r->OlderRequest;
417 // remove transparency!
418 #ifdef SKINS
419 if (WLAYER(window))
421 InstallTransparentRegionHook(WLAYER(window),NULL);
422 InstallTransparentRegion(WLAYER(window),NULL);
425 if (((struct IntWindow *)(window))->transpregion) DisposeRegion(((struct IntWindow *)(window))->transpregion);
426 #endif
428 /* Let the driver clean up. Driver wil dealloc window's rastport */
429 intui_CloseWindow (window, IntuitionBase);
431 /* jDc: trash the screen pointer to avoid unnecessary checks in WindowValid() and
432 memory corruption */
433 window->WScreen = (struct Screen *)0xC0DEBAD0;
435 /* Remove the Window Outline Shape */
436 if (((struct IntWindow *)window)->OutlineShape) DisposeRegion(((struct IntWindow *)window)->OutlineShape);
437 /* Push ExitScreen Message to the Screensdecoration Class */
438 struct wdpExitWindow wemsg;
440 wemsg.MethodID = WDM_EXITWINDOW;
441 wemsg.wdp_UserBuffer = ((struct IntWindow *)window)->DecorUserBuffer;
442 wemsg.wdp_TrueColor = (((struct IntScreen *)screen)->DInfo.dri.dri_Flags & DRIF_DIRECTCOLOR);
444 DoMethodA(((struct IntScreen *)(screen))->WinDecorObj, (Msg)&wemsg);
446 if (((struct IntWindow *)window)->DecorUserBuffer)
448 FreeMem((APTR)((struct IntWindow *)window)->DecorUserBuffer, ((struct IntWindow *)window)->DecorUserBufferSize);
452 /* Free memory for the window */
453 FreeMem (window, sizeof(struct IntWindow));
455 CheckLayers(screen, IntuitionBase);
457 UNLOCK_REFRESH(screen);
458 } /* int_closewindow */
461 /**********************************************************************************/
464 void intui_CloseWindow (struct Window * w,
465 struct IntuitionBase * IntuitionBase)
467 KillWinSysGadgets(w, IntuitionBase);
469 if (0 == (w->Flags & WFLG_GIMMEZEROZERO))
471 /* not a GZZ window */
472 if (WLAYER(w))
473 DeleteLayer(0, WLAYER(w));
474 DeinitRastPort(w->BorderRPort);
475 FreeMem(w->BorderRPort, sizeof(struct RastPort));
477 else
479 /* a GZZ window */
480 /* delete inner window */
481 if (NULL != WLAYER(w))
482 DeleteLayer(0, WLAYER(w));
484 /* delete outer window */
485 if (NULL != BLAYER(w))
486 DeleteLayer(0, BLAYER(w));
489 if (IW(w)->free_pointer)
490 DisposeObject(IW(w)->pointer);