re-enable atomic access to transfermode/command for bcm2835 sd controller, and tidy...
[AROS.git] / rom / intuition / closescreen.c
blobcdc386c24dfde3869af14712ce6e2ce8f6956092
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Close a screen.
7 */
9 #include <graphics/videocontrol.h>
10 #include <proto/exec.h>
11 #include <proto/graphics.h>
12 #include <proto/layers.h>
13 #include "intuition_intern.h"
14 #include "inputhandler_actions.h"
16 #ifdef SKINS
17 # include "intuition_customize.h"
18 #endif
20 #ifndef DEBUG_CloseScreen
21 #define DEBUG_CloseScreen 0
22 #endif
23 #undef DEBUG
24 #if DEBUG_CloseScreen
25 #define DEBUG 1
26 #endif
27 #include <aros/debug.h>
29 struct CloseScreenActionMsg
31 struct IntuiActionMsg msg;
32 struct Screen *Screen;
35 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
36 struct IntuitionBase *IntuitionBase);
38 /*****************************************************************************
40 NAME */
41 #include <intuition/screens.h>
42 #include <proto/intuition.h>
44 AROS_LH1(BOOL, CloseScreen,
46 /* SYNOPSIS */
47 AROS_LHA(struct Screen *, screen, A0),
49 /* LOCATION */
50 struct IntuitionBase *, IntuitionBase, 11, Intuition)
52 /* FUNCTION
54 Release all resources held by a screen and close it down visually.
56 INPUTS
58 screen -- pointer to the screen to be closed
60 RESULT
62 TRUE if the screen is successfully closed, FALSE if there were still
63 windows left on the screen (which means the screen is not closed).
65 NOTES
67 EXAMPLE
69 BUGS
71 SEE ALSO
73 INTERNALS
75 *****************************************************************************/
77 AROS_LIBFUNC_INIT
79 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
80 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
81 struct CloseScreenActionMsg msg;
83 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", screen));
85 D(bug("CloseScreen (%p)\n", screen));
87 if ( screen == NULL )
89 ReturnBool("CloseScreen",TRUE);
92 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_BEFORE_CLOSESCREEN, IntuitionBase);
94 /* there's a second check below for public screens */
95 if (screen->FirstWindow)
97 DEBUG_CLOSESCREEN(dprintf("CloseScreen: fail, window still opened\n"));
98 ReturnBool("CloseScreen",FALSE);
101 #ifdef USEWINDOWLOCK
102 /* let's wait for user to finish window drag/size actions to avoid
103 deadlocks and not break user's input */
104 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
105 #endif
107 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
108 LockPubScreenList();
109 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
111 msg.Screen = screen;
112 DoSyncAction((APTR)int_closescreen,&msg.msg,IntuitionBase);
114 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
115 UnlockPubScreenList();
116 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
118 if (GetPrivScreen(screen)->pubScrNode != NULL)
120 #ifdef USEWINDOWLOCK
121 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
122 #endif
123 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
124 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
125 return FALSE;
128 /* Push ExitScreen Message to the Screensdecoration Class */
129 struct sdpExitScreen semsg;
131 semsg.MethodID = SDM_EXITSCREEN;
132 semsg.sdp_UserBuffer = ((struct IntScreen *)screen)->DecorUserBuffer;
133 semsg.sdp_TrueColor = (((struct IntScreen *)screen)->DInfo.dri.dri_Flags & DRIF_DIRECTCOLOR);
134 DoMethodA(((struct IntScreen *)screen)->ScrDecorObj, (Msg)&semsg);
136 /* kill screen bar */
137 KillScreenBar(screen, IntuitionBase);
139 /* kill depth gadget */
140 if (((struct IntScreen *)screen)->depthgadget)
142 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
144 DisposeObject(im);
145 DisposeObject(((struct IntScreen *)screen)->depthgadget);
148 RethinkDisplay();
150 FreeVPortCopLists(&screen->ViewPort);
152 #ifdef USEWINDOWLOCK
153 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
154 #endif
156 /* Free the RasInfo of the viewport */
157 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
159 /* Uninit the layerinfo */
161 ThinLayerInfo(&screen->LayerInfo);
163 /* Free the screen's bitmap */
165 if (GetPrivScreen(screen)->AllocatedBitmap)
166 FreeBitMap(GetPrivScreen(screen)->AllocatedBitmap);
167 screen->RastPort.BitMap = NULL;
169 /* Free the RastPort's contents */
170 DeinitRastPort(&screen->RastPort);
172 #ifdef SKINS
173 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
175 /* Free the skin */
176 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
177 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
178 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
179 int_FreeTitlebarBuffer(((struct IntScreen *)(screen)),IntuitionBase);
180 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
182 #endif
184 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_CheckMark);
185 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_AmigaKey);
187 /* Close the font */
188 CloseFont(((struct IntScreen *)screen)->DInfo.dri.dri_Font);
190 /* Free the ColorMap */
191 FreeColorMap(screen->ViewPort.ColorMap);
193 /* Free the sprite */
194 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
196 /* Free decoration objects */
197 DisposeObject(((struct IntScreen *)screen)->WinDecorObj);
198 DisposeObject(((struct IntScreen *)screen)->MenuDecorObj);
199 DisposeObject(((struct IntScreen *)screen)->ScrDecorObj);
201 /* Free decoration buffer */
202 if (((struct IntScreen *)screen)->DecorUserBuffer)
204 FreeMem((APTR)((struct IntScreen *)screen)->DecorUserBuffer, ((struct IntScreen *)screen)->DecorUserBufferSize);
208 ObtainSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
209 ULONG lock = LockIBase(0);
211 struct NewDecorator *nd = ((struct IntScreen *)screen)->Decorator;
213 if ((nd != ((struct IntIntuitionBase *)(IntuitionBase))->Decorator) && (nd != NULL))
215 nd->nd_cnt--;
217 if ((nd->nd_cnt == 0) && (nd->nd_Port != NULL) && (nd->nd_IntPattern == NULL))
219 struct DecoratorMessage msg;
220 struct MsgPort *port = CreateMsgPort();
221 if (port)
223 Remove((struct Node *)nd);
225 if (nd->nd_IntPattern) FreeVec(nd->nd_IntPattern);
227 msg.dm_Message.mn_ReplyPort = port;
228 msg.dm_Message.mn_Magic = MAGIC_DECORATOR;
229 msg.dm_Message.mn_Version = DECORATOR_VERSION;
230 msg.dm_Class = DM_CLASS_DESTROYDECORATOR;
231 msg.dm_Code = 0;
232 msg.dm_Flags = 0;
233 msg.dm_Object = (IPTR) nd;
234 PutMsg(nd->nd_Port, (struct Message *) &msg);
235 WaitPort(port);
236 GetMsg(port);
237 DeleteMsgPort(port);
241 UnlockIBase(lock);
242 ReleaseSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
245 /* Free the memory */
246 FreeMem(screen, sizeof (struct IntScreen));
248 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
250 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
252 ReturnBool("CloseScreen",TRUE);
254 AROS_LIBFUNC_EXIT
255 } /* CloseScreen */
257 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
258 struct IntuitionBase *IntuitionBase)
260 struct Screen *parent,*screen = msg->Screen;
261 ULONG lock;
263 /* If this is a public screen, free related information if there are
264 no windows left on the screen */
265 if (GetPrivScreen(screen)->pubScrNode != NULL)
267 if(GetPrivScreen(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
269 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
270 return;
273 Remove((struct Node *)GetPrivScreen(screen)->pubScrNode);
275 if(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name != NULL)
276 FreeVec(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name);
278 FreeMem(GetPrivScreen(screen)->pubScrNode,
279 sizeof(struct PubScreenNode));
281 GetPrivScreen(screen)->pubScrNode = 0;
284 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
286 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
288 lock = LockIBase(0);
290 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
292 /* Trick: Since NextScreen is the first field of the structure,
293 we can use the pointer in the IntuitionBase as a screen with
294 the structure-size of one pointer */
295 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
297 /* For all screens... */
298 while (parent->NextScreen)
300 /* If the screen to close is the next screen... */
301 if (parent->NextScreen == screen)
304 /* Unlink it */
305 parent->NextScreen = screen->NextScreen;
307 /* Check ActiveScreen */
308 if (IntuitionBase->ActiveScreen == screen)
310 if (screen->NextScreen)
311 IntuitionBase->ActiveScreen = screen->NextScreen;
312 else if (IntuitionBase->FirstScreen)
313 IntuitionBase->ActiveScreen = parent;
314 else
315 IntuitionBase->ActiveScreen = NULL;
318 /* now let's set the default pub screen */
319 if (GetPrivIBase(IntuitionBase)->DefaultPubScreen == screen)
321 struct Screen *scr;
323 GetPrivIBase(IntuitionBase)->DefaultPubScreen = NULL;
324 scr = IntuitionBase->FirstScreen;
326 if (scr && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && GetPrivScreen(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
328 GetPrivIBase(IntuitionBase)->DefaultPubScreen = scr;
332 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
333 UnlockIBase(lock);
334 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
336 #ifdef TIMEVALWINDOWACTIVATION
337 if (IntuitionBase->FirstScreen && ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
339 struct Window *scanw = 0;
340 struct Window *win = 0;
342 for (scanw = IntuitionBase->FirstScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
344 if (win)
346 if ((IW(scanw)->activationtime.tv_secs > IW(win)->activationtime.tv_secs) ||
347 ((IW(scanw)->activationtime.tv_secs == IW(win)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(win)->activationtime.tv_micro)))
349 win = scanw;
353 if (!win) win = scanw;
356 if (!win) win = IntuitionBase->FirstScreen->FirstWindow;
357 if (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION)
358 if (IntuitionBase->ActiveWindow && IntuitionBase->ActiveWindow->WScreen == IntuitionBase->FirstScreen) win = NULL;
359 if (win) ActivateWindow(win);
361 #endif
362 return;
364 parent = parent->NextScreen;
367 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
368 UnlockIBase(lock);
369 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
371 return;