New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / rom / intuition / closescreen.c
bloba10821f7c724b78ee1e3607dd580e36b7f1c4b89
1 /*
2 Copyright 1995-2003, 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
78 AROS_LIBBASE_EXT_DECL(struct IntuitionBase *,IntuitionBase)
80 struct CloseScreenActionMsg msg;
82 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", screen));
84 D(bug("CloseScreen (%p)\n", screen));
86 if ( screen == NULL )
88 ReturnBool("CloseScreen",TRUE);
91 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 D(bug("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 /* kill screen bar */
129 KillScreenBar(screen, IntuitionBase);
131 /* kill depth gadget */
132 if (((struct IntScreen *)screen)->depthgadget)
134 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
136 DisposeObject(im);
137 DisposeObject(((struct IntScreen *)screen)->depthgadget);
140 #ifdef __MORPHOS__
141 RethinkDisplay();
143 FreeVPortCopLists(&screen->ViewPort);
146 struct TagItem tags[2];
148 tags[0].ti_Tag = VTAG_ATTACH_CM_GET;
149 tags[0].ti_Data = 0;
150 tags[1].ti_Tag = VTAG_END_CM;
152 if (VideoControl(screen->ViewPort.ColorMap, tags))
154 GfxFree((APTR)tags[0].ti_Data);
157 #else
158 /* !!! Setting a new front bitmap MUST be done before freeing the old one */
159 if (NULL != IntuitionBase->FirstScreen)
161 /* We MUST pas FALSE in the "copyback" parameter
162 since the old screen bitmap has been deleted
164 SetFrontBitMap(IntuitionBase->FirstScreen->RastPort.BitMap, FALSE);
167 else
169 SetFrontBitMap(NULL, FALSE);
171 #endif
173 #ifdef USEWINDOWLOCK
174 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
175 #endif
177 /* Free the RasInfo of the viewport */
178 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
180 /* Uninit the layerinfo */
182 ThinLayerInfo(&screen->LayerInfo);
184 /* Free the screen's bitmap */
186 if (GetPrivScreen(screen)->AllocatedBitmap)
187 FreeBitMap(GetPrivScreen(screen)->AllocatedBitmap);
188 screen->RastPort.BitMap = NULL;
190 /* Free the RastPort's contents */
191 DeinitRastPort(&screen->RastPort);
193 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_ScrDecorObj);
194 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_WinDecorObj);
196 #ifdef SKINS
197 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
199 /* Free the skin */
200 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
201 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
202 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
203 int_FreeTitlebarBuffer(((struct IntScreen *)(screen)),IntuitionBase);
204 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
206 #endif
208 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_CheckMark);
209 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_AmigaKey);
211 /* Close the font */
212 CloseFont(((struct IntScreen *)screen)->DInfo.dri.dri_Font);
214 /* Free the ColorMap */
215 FreeColorMap(screen->ViewPort.ColorMap);
217 /* Free the sprite */
218 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
220 /* Free the memory */
221 FreeMem(screen, sizeof (struct IntScreen));
223 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
225 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
227 ReturnBool("CloseScreen",TRUE);
229 AROS_LIBFUNC_EXIT
230 } /* CloseScreen */
232 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
233 struct IntuitionBase *IntuitionBase)
235 struct Screen *parent,*screen = msg->Screen;
236 struct Window *win = 0;
237 ULONG lock;
239 /* If this is a public screen, free related information if there are
240 no windows left on the screen */
241 if (GetPrivScreen(screen)->pubScrNode != NULL)
243 if(GetPrivScreen(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
245 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
246 return;
249 Remove((struct Node *)GetPrivScreen(screen)->pubScrNode);
251 if(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name != NULL)
252 FreeVec(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name);
254 FreeMem(GetPrivScreen(screen)->pubScrNode,
255 sizeof(struct PubScreenNode));
257 GetPrivScreen(screen)->pubScrNode = 0;
260 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
262 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
264 lock = LockIBase(0);
266 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
268 /* Trick: Since NextScreen is the first field of the structure,
269 we can use the pointer in the IntuitionBase as a screen with
270 the structure-size of one pointer */
271 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
273 /* For all screens... */
274 while (parent->NextScreen)
276 /* If the screen to close is the next screen... */
277 if (parent->NextScreen == screen)
280 /* Unlink it */
281 parent->NextScreen = screen->NextScreen;
283 /* Check ActiveScreen */
284 if (IntuitionBase->ActiveScreen == screen)
286 if (screen->NextScreen)
287 IntuitionBase->ActiveScreen = screen->NextScreen;
288 else if (IntuitionBase->FirstScreen)
289 IntuitionBase->ActiveScreen = parent;
290 else
291 IntuitionBase->ActiveScreen = NULL;
294 /* now let's set the default pub screen */
295 if (GetPrivIBase(IntuitionBase)->DefaultPubScreen == screen)
297 struct Screen *scr;
298 BOOL nexttry = TRUE;
300 GetPrivIBase(IntuitionBase)->DefaultPubScreen = NULL;
301 scr = IntuitionBase->FirstScreen;
303 if (scr && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && GetPrivScreen(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
305 GetPrivIBase(IntuitionBase)->DefaultPubScreen = scr;
309 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
310 UnlockIBase(lock);
311 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
313 #ifdef TIMEVALWINDOWACTIVATION
314 if (IntuitionBase->FirstScreen && ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
316 struct Window *scanw = 0;
318 for (scanw = IntuitionBase->FirstScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
320 if (win)
322 if ((IW(scanw)->activationtime.tv_secs > IW(win)->activationtime.tv_secs) ||
323 ((IW(scanw)->activationtime.tv_secs == IW(win)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(win)->activationtime.tv_micro)))
325 win = scanw;
329 if (!win) win = scanw;
332 if (!win) win = IntuitionBase->FirstScreen->FirstWindow;
333 if (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION)
334 if (IntuitionBase->ActiveWindow && IntuitionBase->ActiveWindow->WScreen == IntuitionBase->FirstScreen) win = NULL;
335 if (win) ActivateWindow(win);
337 #endif
338 return;
340 parent = parent->NextScreen;
343 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
344 UnlockIBase(lock);
345 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
347 return;