- Give PCI controllers lower unit numbers than legacy controllers.
[cake.git] / rom / intuition / closescreen.c
blob73162fbfcc1c542c274ebae4b6fed41adb5ef3ee
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$
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 CloseScreenActionMsg msg;
81 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", screen));
83 D(bug("CloseScreen (%p)\n", screen));
85 if ( screen == NULL )
87 ReturnBool("CloseScreen",TRUE);
90 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_BEFORE_CLOSESCREEN, IntuitionBase);
92 /* Push ExitScreen Message to the Screensdecoration Class */
93 struct sdpExitScreen semsg;
95 semsg.MethodID = SDM_EXITSCREEN;
96 semsg.sdp_UserBuffer = ((struct IntScreen *)screen)->DecorUserBuffer;
97 semsg.sdp_TrueColor = (((struct IntScreen *)screen)->DInfo.dri.dri_Flags & DRIF_DIRECTCOLOR);
98 DoMethodA(((struct IntScreen *)screen)->ScrDecorObj, (Msg)&semsg);
100 /* there's a second check below for public screens */
101 if (screen->FirstWindow)
103 D(bug("CloseScreen: fail, window still opened\n"));
104 ReturnBool("CloseScreen",FALSE);
107 #ifdef USEWINDOWLOCK
108 /* let's wait for user to finish window drag/size actions to avoid
109 deadlocks and not break user's input */
110 ObtainSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
111 #endif
113 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
114 LockPubScreenList();
115 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
117 msg.Screen = screen;
118 DoSyncAction((APTR)int_closescreen,&msg.msg,IntuitionBase);
120 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
121 UnlockPubScreenList();
122 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
124 if (GetPrivScreen(screen)->pubScrNode != NULL)
126 #ifdef USEWINDOWLOCK
127 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
128 #endif
129 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
130 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
131 return FALSE;
134 /* kill screen bar */
135 KillScreenBar(screen, IntuitionBase);
137 /* kill depth gadget */
138 if (((struct IntScreen *)screen)->depthgadget)
140 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
142 DisposeObject(im);
143 DisposeObject(((struct IntScreen *)screen)->depthgadget);
146 #ifdef __MORPHOS__
147 RethinkDisplay();
149 FreeVPortCopLists(&screen->ViewPort);
152 struct TagItem tags[2];
154 tags[0].ti_Tag = VTAG_ATTACH_CM_GET;
155 tags[0].ti_Data = 0;
156 tags[1].ti_Tag = VTAG_END_CM;
158 if (VideoControl(screen->ViewPort.ColorMap, tags))
160 GfxFree((APTR)tags[0].ti_Data);
163 #else
164 /* !!! Setting a new front bitmap MUST be done before freeing the old one */
165 if (NULL != IntuitionBase->FirstScreen)
167 /* We MUST pas FALSE in the "copyback" parameter
168 since the old screen bitmap has been deleted
170 SetFrontBitMap(IntuitionBase->FirstScreen->RastPort.BitMap, FALSE);
173 else
175 SetFrontBitMap(NULL, FALSE);
177 #endif
179 #ifdef USEWINDOWLOCK
180 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
181 #endif
183 /* Free the RasInfo of the viewport */
184 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
186 /* Uninit the layerinfo */
188 ThinLayerInfo(&screen->LayerInfo);
190 /* Free the screen's bitmap */
192 if (GetPrivScreen(screen)->AllocatedBitmap)
193 FreeBitMap(GetPrivScreen(screen)->AllocatedBitmap);
194 screen->RastPort.BitMap = NULL;
196 /* Free the RastPort's contents */
197 DeinitRastPort(&screen->RastPort);
199 #ifdef SKINS
200 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
202 /* Free the skin */
203 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
204 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
205 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
206 int_FreeTitlebarBuffer(((struct IntScreen *)(screen)),IntuitionBase);
207 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
209 #endif
211 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_CheckMark);
212 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_AmigaKey);
214 /* Close the font */
215 CloseFont(((struct IntScreen *)screen)->DInfo.dri.dri_Font);
217 /* Free the ColorMap */
218 FreeColorMap(screen->ViewPort.ColorMap);
220 /* Free the sprite */
221 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
223 /* Free the memory */
224 if (((struct IntScreen *)screen)->DecorUserBuffer)
226 FreeMem((APTR)((struct IntScreen *)screen)->DecorUserBuffer, ((struct IntScreen *)screen)->DecorUserBufferSize);
230 ObtainSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
231 ULONG lock = LockIBase(0);
233 struct NewDecorator *nd = ((struct IntScreen *)screen)->Decorator;
235 if ((nd != ((struct IntIntuitionBase *)(IntuitionBase))->Decorator) && (nd != NULL))
237 nd->nd_cnt--;
239 if ((nd->nd_cnt == 0) && (nd->nd_Port != NULL) && (nd->nd_IntPattern == NULL))
241 struct DecoratorMessage msg;
242 struct MsgPort *port = CreateMsgPort();
243 if (port)
245 Remove((struct Node *)nd);
247 if (nd->nd_IntPattern) FreeVec(nd->nd_IntPattern);
249 msg.dm_Message.mn_ReplyPort = port;
250 msg.dm_Message.mn_Magic = MAGIC_DECORATOR;
251 msg.dm_Message.mn_Version = DECORATOR_VERSION;
252 msg.dm_Class = DM_CLASS_DESTROYDECORATOR;
253 msg.dm_Code = 0;
254 msg.dm_Flags = 0;
255 msg.dm_Object = (IPTR) nd;
256 PutMsg(nd->nd_Port, (struct Message *) &msg);
257 WaitPort(port);
258 GetMsg(port);
259 DeleteMsgPort(port);
263 UnlockIBase(lock);
264 ReleaseSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
267 /* Free the memory */
268 FreeMem(screen, sizeof (struct IntScreen));
270 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
272 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
274 ReturnBool("CloseScreen",TRUE);
276 AROS_LIBFUNC_EXIT
277 } /* CloseScreen */
279 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
280 struct IntuitionBase *IntuitionBase)
282 struct Screen *parent,*screen = msg->Screen;
283 struct Window *win = 0;
284 ULONG lock;
286 /* If this is a public screen, free related information if there are
287 no windows left on the screen */
288 if (GetPrivScreen(screen)->pubScrNode != NULL)
290 if(GetPrivScreen(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
292 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
293 return;
296 Remove((struct Node *)GetPrivScreen(screen)->pubScrNode);
298 if(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name != NULL)
299 FreeVec(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name);
301 FreeMem(GetPrivScreen(screen)->pubScrNode,
302 sizeof(struct PubScreenNode));
304 GetPrivScreen(screen)->pubScrNode = 0;
307 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
309 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
311 lock = LockIBase(0);
313 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
315 /* Trick: Since NextScreen is the first field of the structure,
316 we can use the pointer in the IntuitionBase as a screen with
317 the structure-size of one pointer */
318 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
320 /* For all screens... */
321 while (parent->NextScreen)
323 /* If the screen to close is the next screen... */
324 if (parent->NextScreen == screen)
327 /* Unlink it */
328 parent->NextScreen = screen->NextScreen;
330 /* Check ActiveScreen */
331 if (IntuitionBase->ActiveScreen == screen)
333 if (screen->NextScreen)
334 IntuitionBase->ActiveScreen = screen->NextScreen;
335 else if (IntuitionBase->FirstScreen)
336 IntuitionBase->ActiveScreen = parent;
337 else
338 IntuitionBase->ActiveScreen = NULL;
341 /* now let's set the default pub screen */
342 if (GetPrivIBase(IntuitionBase)->DefaultPubScreen == screen)
344 struct Screen *scr;
346 GetPrivIBase(IntuitionBase)->DefaultPubScreen = NULL;
347 scr = IntuitionBase->FirstScreen;
349 if (scr && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && GetPrivScreen(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
351 GetPrivIBase(IntuitionBase)->DefaultPubScreen = scr;
355 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
356 UnlockIBase(lock);
357 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
359 #ifdef TIMEVALWINDOWACTIVATION
360 if (IntuitionBase->FirstScreen && ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
362 struct Window *scanw = 0;
364 for (scanw = IntuitionBase->FirstScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
366 if (win)
368 if ((IW(scanw)->activationtime.tv_secs > IW(win)->activationtime.tv_secs) ||
369 ((IW(scanw)->activationtime.tv_secs == IW(win)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(win)->activationtime.tv_micro)))
371 win = scanw;
375 if (!win) win = scanw;
378 if (!win) win = IntuitionBase->FirstScreen->FirstWindow;
379 if (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION)
380 if (IntuitionBase->ActiveWindow && IntuitionBase->ActiveWindow->WScreen == IntuitionBase->FirstScreen) win = NULL;
381 if (win) ActivateWindow(win);
383 #endif
384 return;
386 parent = parent->NextScreen;
389 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
390 UnlockIBase(lock);
391 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
393 return;