try to make sure compiler/include/mmakefile is always refreshed correctly.
[AROS.git] / rom / intuition / closescreen.c
blobec24cefbb87d05ab644a7386dfb98e995f982bbd
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,
136 caller->tc_Node.ln_Name ?
137 (const char *)caller->tc_Node.ln_Name : "",
138 screen);
140 ReturnBool("closescreen",FALSE);
143 #endif
145 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
146 LockPubScreenList();
147 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
149 msg.Screen = screen;
150 DoSyncAction((APTR)int_closescreen,&msg.msg,IntuitionBase);
152 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
153 UnlockPubScreenList();
154 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
156 if (IS(screen)->pubScrNode != NULL)
158 #ifdef USEWINDOWLOCK
159 if (IS(screen)->WindowLock) UNLOCKWINDOW;
160 #endif
161 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
162 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
163 return FALSE;
166 /* AROS: Notify decorator */
167 int_ExitDecorator(screen);
169 /* kill screen bar */
170 KillScreenBar(screen, IntuitionBase);
172 /* kill depth gadget */
173 if (((struct IntScreen *)screen)->depthgadget)
175 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
177 DisposeObject(im);
178 DisposeObject(((struct IntScreen *)screen)->depthgadget);
181 if (IS(screen)->RestoreDBufInfo != NULL)
183 FreeDBufInfo(IS(screen)->RestoreDBufInfo);
186 RethinkDisplay();
187 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Rethink done\n"));
189 FreeVPortCopLists(&screen->ViewPort);
191 #ifdef __MORPHOS__
193 * AROS: According to documentation, VTAG_ATTACH_CM_GET should return a pointer
194 * to our ViewPort. ViewPort is part of struct Screen, so there's nothing to
195 * GfxFree(). Also, ViewPortExtra is GfxFree()d in FreeColorMap(), attempt to
196 * free it twice doesn't do good things. Looks like some MorphOS quirk. Note
197 * that the same thing is surrounded by #ifdef __MORPHOS__ in original MorphOS code.
198 * TODO: Check if our behavior is correct and adjust it to correspond AmigaOS v3.
201 struct TagItem tags[3];
203 tags[0].ti_Tag = VTAG_ATTACH_CM_GET;
204 tags[0].ti_Data = 0;
205 tags[1].ti_Tag = VTAG_VIEWPORTEXTRA_GET;
206 tags[1].ti_Data = 0;
207 tags[2].ti_Tag = VTAG_END_CM;
209 if (VideoControl(screen->ViewPort.ColorMap, tags) == NULL)
211 DEBUG_CLOSESCREEN(dprintf("CloseScreen: CM %lx EX %lx\n",tags[0].ti_Data,tags[1].ti_Data));
212 if (tags[0].ti_Data) GfxFree((APTR)tags[0].ti_Data);
213 if (tags[1].ti_Data) GfxFree((APTR)tags[1].ti_Data);
216 #endif
218 #ifdef USEWINDOWLOCK
219 if (IS(screen)->WindowLock) UNLOCKWINDOW;
220 #endif
222 /* Free the RasInfo of the viewport */
223 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
225 #if 0
226 /* Root layer now automatically freed in ThinLayerInfo() */
228 #ifdef CreateLayerTagList
229 /* Free the root layer */
230 DeleteLayer(0UL, ((struct IntScreen *)screen)->rootLayer);
231 #endif
232 #endif
233 /* Uninit the layerinfo */
235 ThinLayerInfo(&screen->LayerInfo);
236 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ThinLayer done\n"));
238 ReadPixel(&screen->RastPort,0,0);
240 /* Free the screen's bitmap */
241 if (IS(screen)->AllocatedBitMap)
243 FreeBitMap(IS(screen)->AllocatedBitMap);
246 screen->RastPort.BitMap = NULL;
248 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freebitmap done\n"));
250 /* Free the RastPort's contents */
251 DeinitRastPort(&screen->RastPort);
253 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
255 /* Free the skin */
256 /* AROS: submenu image moved out of #ifdef */
257 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
258 #ifdef SKINS
259 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
260 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
261 int_FreeTitlebarBuffer(screen,IntuitionBase);
262 #endif
263 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
266 #ifdef SKINS
267 if (((struct IntScreen *)screen)->DInfo.dri_Colors)
269 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Colors,4 * DRIPEN_NUMDRIPENS);
271 DEBUG_CLOSESCREEN(dprintf("CloseScreen: skins done\n"));
272 #endif
274 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_CheckMark);
275 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_AmigaKey);
277 /* Close the font */
278 CloseFont(((struct IntScreen *)screen)->DInfo.dri_Font);
280 /* Free the ColorMap */
281 FreeColorMap(screen->ViewPort.ColorMap);
283 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freecolormap done\n"));
285 /* Free the sprite */
286 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
288 /* Free the memory */
289 DisposeObject(screen);
291 /* AROS: Send notification */
292 if (screen != GetPrivIBase(IntuitionBase)->WorkBench)
293 FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
295 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
297 ReturnBool("CloseScreen",TRUE);
299 AROS_LIBFUNC_EXIT
300 } /* CloseScreen */
302 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
303 struct IntuitionBase *IntuitionBase)
305 struct Screen *parent,*screen = msg->Screen;
306 ULONG lock = 0;
308 DEBUG_CLOSESCREEN(dprintf("CloseScreen: welcome in inputhandler!\n"));
310 #ifdef SKINS
311 if (IntuitionBase->FirstScreen == screen) ScreenDepth(screen,SDEPTH_TOBACK,NULL);
312 DEBUG_CLOSESCREEN(dprintf("CloseScreen: put the screen to back\n"));
313 #endif
315 #if USE_NEWDISPLAYBEEP
316 /* we could be beeping this screen... */
317 /* NOTE: we're running under the windowlock here! */
318 if (IBase->BeepingScreens && (screen->Flags & BEEPING))
320 IBase->BeepingScreens --;
322 #endif
324 if (IBase->MenuVerifyScreen == IS(screen))
325 IBase->MenuVerifyScreen = NULL;
327 /* If this is a public screen, free related information if there are
328 no windows left on the screen */
329 if (IS(screen)->pubScrNode != NULL)
331 DEBUG_CLOSESCREEN(dprintf("CloseScreen: killing a pubscreen entry\n"));
333 if(IS(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
335 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
336 return;
339 Remove((struct Node *)IS(screen)->pubScrNode);
341 FreeVec(IS(screen)->pubScrNode->psn_Node.ln_Name);
343 FreeMem(IS(screen)->pubScrNode,
344 sizeof(struct PubScreenNode));
346 IS(screen)->pubScrNode = 0;
349 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
351 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
353 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) lock = LockIBase(0);
355 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
357 /* Trick: Since NextScreen is the first field of the structure,
358 we can use the pointer in the IntuitionBase as a screen with
359 the structure-size of one pointer */
360 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
362 /* For all screens... */
363 while (parent->NextScreen)
365 /* If the screen to close is the next screen... */
366 if (parent->NextScreen == screen)
369 /* Unlink it */
370 parent->NextScreen = screen->NextScreen;
372 /* Check ActiveScreen */
373 if (IntuitionBase->ActiveScreen == screen)
375 if (screen->NextScreen)
376 IntuitionBase->ActiveScreen = screen->NextScreen;
377 else if (IntuitionBase->FirstScreen)
378 IntuitionBase->ActiveScreen = parent;
379 else
380 IntuitionBase->ActiveScreen = NULL;
383 /* now let's set the default pub screen */
384 if (IBase->DefaultPubScreen == screen)
386 struct Screen *scr;
388 IBase->DefaultPubScreen = NULL;
389 scr = IntuitionBase->FirstScreen;
391 if (scr && IBase->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && IS(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
393 IBase->DefaultPubScreen = scr;
397 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
398 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
399 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
401 #ifdef TIMEVALWINDOWACTIVATION
402 if (IntuitionBase->FirstScreen && ((IBase->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
404 DeactivateWindow(NULL,msg->msg.task,IntuitionBase);
406 #endif
407 return;
409 parent = parent->NextScreen;
412 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
413 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
414 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
416 return;