use struct timeval to obtain the cputime. disable display atm until the code is corre...
[AROS.git] / rom / intuition / closescreen.c
blob239049c535aebe8a86a8994d1d7a331bc047e407
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2013, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Close a screen.
7 */
9 /*
10 * Things added by AROS, which needs to be kept when merging with newer MorphOS releases:
12 * 1. Explicit library bases
13 * 2. FireScreenNotifyMessage() calls
14 * 3. RemoveResourceFromList() call
15 * 4. int_ExitDecorator() call
16 * 5. Other placed marked by 'AROS:' in comments.
17 * 6. Check #ifdef's. Some of them were rearranged or completely deleted.
18 * We reuse MorphOS skin code where appropriate.
21 #include <graphics/videocontrol.h>
22 #include <proto/exec.h>
23 #include <proto/graphics.h>
24 #include <proto/layers.h>
25 #include "intuition_intern.h"
26 #include "intuition_customize.h"
27 #include "inputhandler_actions.h"
29 #ifndef DEBUG_CloseScreen
30 #define DEBUG_CloseScreen 0
31 #endif
32 #undef DEBUG
33 #if DEBUG_CloseScreen
34 #define DEBUG 1
35 #endif
36 #include <aros/debug.h>
38 struct CloseScreenActionMsg
40 struct IntuiActionMsg msg;
41 struct Screen *Screen;
44 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
45 struct IntuitionBase *IntuitionBase);
47 /*****************************************************************************
49 NAME */
50 #include <intuition/screens.h>
51 #include <proto/intuition.h>
53 AROS_LH1(BOOL, CloseScreen,
55 /* SYNOPSIS */
56 AROS_LHA(struct Screen *, screen, A0),
58 /* LOCATION */
59 struct IntuitionBase *, IntuitionBase, 11, Intuition)
61 /* FUNCTION
62 Release all resources held by a screen and close it down visually.
64 INPUTS
65 screen - pointer to the screen to be closed
67 RESULT
68 TRUE if the screen is successfully closed, FALSE if there were still
69 windows left on the screen (which means the screen is not closed).
71 NOTES
73 EXAMPLE
75 BUGS
77 SEE ALSO
79 INTERNALS
81 *****************************************************************************/
83 AROS_LIBFUNC_INIT
85 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
86 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
87 struct CloseScreenActionMsg msg;
88 // ULONG lock;
90 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", (ULONG)screen));
92 D(bug("CloseScreen (%p)\n", screen));
94 if ( screen == NULL )
96 ReturnBool("CloseScreen",TRUE);
99 #ifdef INTUITION_NOTIFY_SUPPORT
100 /* Notify that the screen is going to close */
101 sn_DoNotify(SCREENNOTIFY_TYPE_CLOSESCREEN, screen, IBase->ScreenNotifyBase);
102 #endif
103 if (screen != GetPrivIBase(IntuitionBase)->WorkBench)
104 FireScreenNotifyMessage((IPTR) screen, SNOTIFY_BEFORE_CLOSESCREEN, IntuitionBase);
106 /* there's a second check below for public screens */
107 if (screen->FirstWindow)
109 D(bug("CloseScreen: fail, window still opened\n"));
110 ReturnBool("CloseScreen",FALSE);
113 #ifdef USEWINDOWLOCK
114 /* let's wait for user to finish window drag/size actions to avoid
115 deadlocks and not break user's input */
116 if (IS(screen)->WindowLock)
118 struct Screen *ccs;
119 BOOL found = FALSE;
121 LOCKWINDOW;
123 /* !moron check here! */
124 for (ccs = IntuitionBase->FirstScreen; ccs; ccs = ccs->NextScreen)
126 if (ccs == screen) found = TRUE;
129 if (!found)
131 struct Task *caller = FindTask(NULL);
132 UNLOCKWINDOW;
134 dprintf("CloseScreen: task %p (%s) attempted a bogus CloseScreen(%p) !\n",
135 caller,(char*) (caller->tc_Node.ln_Name ? caller->tc_Node.ln_Name : ""),screen);
137 ReturnBool("closescreen",FALSE);
140 #endif
142 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
143 LockPubScreenList();
144 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
146 msg.Screen = screen;
147 DoSyncAction((APTR)int_closescreen,&msg.msg,IntuitionBase);
149 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
150 UnlockPubScreenList();
151 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
153 if (IS(screen)->pubScrNode != NULL)
155 #ifdef USEWINDOWLOCK
156 if (IS(screen)->WindowLock) UNLOCKWINDOW;
157 #endif
158 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
159 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
160 return FALSE;
163 /* AROS: Notify decorator */
164 int_ExitDecorator(screen);
166 /* kill screen bar */
167 KillScreenBar(screen, IntuitionBase);
169 /* kill depth gadget */
170 if (((struct IntScreen *)screen)->depthgadget)
172 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
174 DisposeObject(im);
175 DisposeObject(((struct IntScreen *)screen)->depthgadget);
178 if (IS(screen)->RestoreDBufInfo != NULL)
180 FreeDBufInfo(IS(screen)->RestoreDBufInfo);
183 RethinkDisplay();
184 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Rethink done\n"));
186 FreeVPortCopLists(&screen->ViewPort);
188 #ifdef __MORPHOS__
190 * AROS: According to documentation, VTAG_ATTACH_CM_GET should return a pointer
191 * to our ViewPort. ViewPort is part of struct Screen, so there's nothing to
192 * GfxFree(). Also, ViewPortExtra is GfxFree()d in FreeColorMap(), attempt to
193 * free it twice doesn't do good things. Looks like some MorphOS quirk. Note
194 * that the same thing is surrounded by #ifdef __MORPHOS__ in original MorphOS code.
195 * TODO: Check if our behavior is correct and adjust it to correspond AmigaOS v3.
198 struct TagItem tags[3];
200 tags[0].ti_Tag = VTAG_ATTACH_CM_GET;
201 tags[0].ti_Data = 0;
202 tags[1].ti_Tag = VTAG_VIEWPORTEXTRA_GET;
203 tags[1].ti_Data = 0;
204 tags[2].ti_Tag = VTAG_END_CM;
206 if (VideoControl(screen->ViewPort.ColorMap, tags) == NULL)
208 DEBUG_CLOSESCREEN(dprintf("CloseScreen: CM %lx EX %lx\n",tags[0].ti_Data,tags[1].ti_Data));
209 if (tags[0].ti_Data) GfxFree((APTR)tags[0].ti_Data);
210 if (tags[1].ti_Data) GfxFree((APTR)tags[1].ti_Data);
213 #endif
215 #ifdef USEWINDOWLOCK
216 if (IS(screen)->WindowLock) UNLOCKWINDOW;
217 #endif
219 /* Free the RasInfo of the viewport */
220 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
222 #if 0
223 /* Root layer now automatically freed in ThinLayerInfo() */
225 #ifdef CreateLayerTagList
226 /* Free the root layer */
227 DeleteLayer(0UL, ((struct IntScreen *)screen)->rootLayer);
228 #endif
229 #endif
230 /* Uninit the layerinfo */
232 ThinLayerInfo(&screen->LayerInfo);
233 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ThinLayer done\n"));
235 ReadPixel(&screen->RastPort,0,0);
237 /* Free the screen's bitmap */
238 if (IS(screen)->AllocatedBitMap)
240 FreeBitMap(IS(screen)->AllocatedBitMap);
243 screen->RastPort.BitMap = NULL;
245 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freebitmap done\n"));
247 /* Free the RastPort's contents */
248 DeinitRastPort(&screen->RastPort);
250 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
252 /* Free the skin */
253 /* AROS: submenu image moved out of #ifdef */
254 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
255 #ifdef SKINS
256 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
257 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
258 int_FreeTitlebarBuffer(screen,IntuitionBase);
259 #endif
260 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
263 #ifdef SKINS
264 if (((struct IntScreen *)screen)->DInfo.dri_Colors)
266 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Colors,4 * DRIPEN_NUMDRIPENS);
268 DEBUG_CLOSESCREEN(dprintf("CloseScreen: skins done\n"));
269 #endif
271 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_CheckMark);
272 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_AmigaKey);
274 /* Close the font */
275 CloseFont(((struct IntScreen *)screen)->DInfo.dri_Font);
277 /* Free the ColorMap */
278 FreeColorMap(screen->ViewPort.ColorMap);
280 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freecolormap done\n"));
282 /* Free the sprite */
283 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
285 /* Free the memory */
286 DisposeObject(screen);
288 /* AROS: Send notification */
289 if (screen != GetPrivIBase(IntuitionBase)->WorkBench)
290 FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
292 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
294 ReturnBool("CloseScreen",TRUE);
296 AROS_LIBFUNC_EXIT
297 } /* CloseScreen */
299 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
300 struct IntuitionBase *IntuitionBase)
302 struct Screen *parent,*screen = msg->Screen;
303 ULONG lock = 0;
305 DEBUG_CLOSESCREEN(dprintf("CloseScreen: welcome in inputhandler!\n"));
307 #ifdef SKINS
308 if (IntuitionBase->FirstScreen == screen) ScreenDepth(screen,SDEPTH_TOBACK,NULL);
309 DEBUG_CLOSESCREEN(dprintf("CloseScreen: put the screen to back\n"));
310 #endif
312 #if USE_NEWDISPLAYBEEP
313 /* we could be beeping this screen... */
314 /* NOTE: we're running under the windowlock here! */
315 if (IBase->BeepingScreens && (screen->Flags & BEEPING))
317 IBase->BeepingScreens --;
319 #endif
321 if (IBase->MenuVerifyScreen == IS(screen))
322 IBase->MenuVerifyScreen = NULL;
324 /* If this is a public screen, free related information if there are
325 no windows left on the screen */
326 if (IS(screen)->pubScrNode != NULL)
328 DEBUG_CLOSESCREEN(dprintf("CloseScreen: killing a pubscreen entry\n"));
330 if(IS(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
332 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
333 return;
336 Remove((struct Node *)IS(screen)->pubScrNode);
338 FreeVec(IS(screen)->pubScrNode->psn_Node.ln_Name);
340 FreeMem(IS(screen)->pubScrNode,
341 sizeof(struct PubScreenNode));
343 IS(screen)->pubScrNode = 0;
346 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
348 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
350 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) lock = LockIBase(0);
352 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
354 /* Trick: Since NextScreen is the first field of the structure,
355 we can use the pointer in the IntuitionBase as a screen with
356 the structure-size of one pointer */
357 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
359 /* For all screens... */
360 while (parent->NextScreen)
362 /* If the screen to close is the next screen... */
363 if (parent->NextScreen == screen)
366 /* Unlink it */
367 parent->NextScreen = screen->NextScreen;
369 /* Check ActiveScreen */
370 if (IntuitionBase->ActiveScreen == screen)
372 if (screen->NextScreen)
373 IntuitionBase->ActiveScreen = screen->NextScreen;
374 else if (IntuitionBase->FirstScreen)
375 IntuitionBase->ActiveScreen = parent;
376 else
377 IntuitionBase->ActiveScreen = NULL;
380 /* now let's set the default pub screen */
381 if (IBase->DefaultPubScreen == screen)
383 struct Screen *scr;
385 IBase->DefaultPubScreen = NULL;
386 scr = IntuitionBase->FirstScreen;
388 if (scr && IBase->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && IS(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
390 IBase->DefaultPubScreen = scr;
394 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
395 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
396 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
398 #ifdef TIMEVALWINDOWACTIVATION
399 if (IntuitionBase->FirstScreen && ((IBase->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
401 DeactivateWindow(NULL,msg->msg.task,IntuitionBase);
403 #endif
404 return;
406 parent = parent->NextScreen;
409 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
410 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
411 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
413 return;