Belarusian
[AROS.git] / rom / intuition / closescreen.c
blobe39119eefdc6549c4768362d4e9d1f45be95d8cd
1 /*
2 Copyright 1995-2010, 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 DEBUG_CLOSESCREEN(dprintf("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 RethinkDisplay();
148 FreeVPortCopLists(&screen->ViewPort);
150 #ifdef USEWINDOWLOCK
151 ReleaseSemaphore(&GetPrivIBase(IntuitionBase)->WindowLock);
152 #endif
154 /* Free the RasInfo of the viewport */
155 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
157 /* Uninit the layerinfo */
159 ThinLayerInfo(&screen->LayerInfo);
161 /* Free the screen's bitmap */
163 if (GetPrivScreen(screen)->AllocatedBitmap)
164 FreeBitMap(GetPrivScreen(screen)->AllocatedBitmap);
165 screen->RastPort.BitMap = NULL;
167 /* Free the RastPort's contents */
168 DeinitRastPort(&screen->RastPort);
170 #ifdef SKINS
171 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
173 /* Free the skin */
174 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
175 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
176 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
177 int_FreeTitlebarBuffer(((struct IntScreen *)(screen)),IntuitionBase);
178 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
180 #endif
182 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_CheckMark);
183 DisposeObject(((struct IntScreen *)screen)->DInfo.dri.dri_AmigaKey);
185 /* Close the font */
186 CloseFont(((struct IntScreen *)screen)->DInfo.dri.dri_Font);
188 /* Free the ColorMap */
189 FreeColorMap(screen->ViewPort.ColorMap);
191 /* Free the sprite */
192 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
194 /* Free the memory */
195 if (((struct IntScreen *)screen)->DecorUserBuffer)
197 FreeMem((APTR)((struct IntScreen *)screen)->DecorUserBuffer, ((struct IntScreen *)screen)->DecorUserBufferSize);
201 ObtainSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
202 ULONG lock = LockIBase(0);
204 struct NewDecorator *nd = ((struct IntScreen *)screen)->Decorator;
206 if ((nd != ((struct IntIntuitionBase *)(IntuitionBase))->Decorator) && (nd != NULL))
208 nd->nd_cnt--;
210 if ((nd->nd_cnt == 0) && (nd->nd_Port != NULL) && (nd->nd_IntPattern == NULL))
212 struct DecoratorMessage msg;
213 struct MsgPort *port = CreateMsgPort();
214 if (port)
216 Remove((struct Node *)nd);
218 if (nd->nd_IntPattern) FreeVec(nd->nd_IntPattern);
220 msg.dm_Message.mn_ReplyPort = port;
221 msg.dm_Message.mn_Magic = MAGIC_DECORATOR;
222 msg.dm_Message.mn_Version = DECORATOR_VERSION;
223 msg.dm_Class = DM_CLASS_DESTROYDECORATOR;
224 msg.dm_Code = 0;
225 msg.dm_Flags = 0;
226 msg.dm_Object = (IPTR) nd;
227 PutMsg(nd->nd_Port, (struct Message *) &msg);
228 WaitPort(port);
229 GetMsg(port);
230 DeleteMsgPort(port);
234 UnlockIBase(lock);
235 ReleaseSemaphore(&((struct IntIntuitionBase *)(IntuitionBase))->ScrDecorSem);
238 /* Free the memory */
239 FreeMem(screen, sizeof (struct IntScreen));
241 if (screen != GetPrivIBase(IntuitionBase)->WorkBench) FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
243 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
245 ReturnBool("CloseScreen",TRUE);
247 AROS_LIBFUNC_EXIT
248 } /* CloseScreen */
250 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
251 struct IntuitionBase *IntuitionBase)
253 struct Screen *parent,*screen = msg->Screen;
254 struct Window *win = 0;
255 ULONG lock;
257 /* If this is a public screen, free related information if there are
258 no windows left on the screen */
259 if (GetPrivScreen(screen)->pubScrNode != NULL)
261 if(GetPrivScreen(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
263 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
264 return;
267 Remove((struct Node *)GetPrivScreen(screen)->pubScrNode);
269 if(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name != NULL)
270 FreeVec(GetPrivScreen(screen)->pubScrNode->psn_Node.ln_Name);
272 FreeMem(GetPrivScreen(screen)->pubScrNode,
273 sizeof(struct PubScreenNode));
275 GetPrivScreen(screen)->pubScrNode = 0;
278 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
280 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
282 lock = LockIBase(0);
284 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
286 /* Trick: Since NextScreen is the first field of the structure,
287 we can use the pointer in the IntuitionBase as a screen with
288 the structure-size of one pointer */
289 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
291 /* For all screens... */
292 while (parent->NextScreen)
294 /* If the screen to close is the next screen... */
295 if (parent->NextScreen == screen)
298 /* Unlink it */
299 parent->NextScreen = screen->NextScreen;
301 /* Check ActiveScreen */
302 if (IntuitionBase->ActiveScreen == screen)
304 if (screen->NextScreen)
305 IntuitionBase->ActiveScreen = screen->NextScreen;
306 else if (IntuitionBase->FirstScreen)
307 IntuitionBase->ActiveScreen = parent;
308 else
309 IntuitionBase->ActiveScreen = NULL;
312 /* now let's set the default pub screen */
313 if (GetPrivIBase(IntuitionBase)->DefaultPubScreen == screen)
315 struct Screen *scr;
317 GetPrivIBase(IntuitionBase)->DefaultPubScreen = NULL;
318 scr = IntuitionBase->FirstScreen;
320 if (scr && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && GetPrivScreen(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
322 GetPrivIBase(IntuitionBase)->DefaultPubScreen = scr;
326 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
327 UnlockIBase(lock);
328 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
330 #ifdef TIMEVALWINDOWACTIVATION
331 if (IntuitionBase->FirstScreen && ((GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
333 struct Window *scanw = 0;
335 for (scanw = IntuitionBase->FirstScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
337 if (win)
339 if ((IW(scanw)->activationtime.tv_secs > IW(win)->activationtime.tv_secs) ||
340 ((IW(scanw)->activationtime.tv_secs == IW(win)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(win)->activationtime.tv_micro)))
342 win = scanw;
346 if (!win) win = scanw;
349 if (!win) win = IntuitionBase->FirstScreen->FirstWindow;
350 if (GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION)
351 if (IntuitionBase->ActiveWindow && IntuitionBase->ActiveWindow->WScreen == IntuitionBase->FirstScreen) win = NULL;
352 if (win) ActivateWindow(win);
354 #endif
355 return;
357 parent = parent->NextScreen;
360 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
361 UnlockIBase(lock);
362 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
364 return;