2 Copyright 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
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"
17 # include "intuition_customize.h"
20 #ifndef DEBUG_CloseScreen
21 #define DEBUG_CloseScreen 0
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 /*****************************************************************************
41 #include <intuition/screens.h>
42 #include <proto/intuition.h>
44 AROS_LH1(BOOL
, CloseScreen
,
47 AROS_LHA(struct Screen
*, screen
, A0
),
50 struct IntuitionBase
*, IntuitionBase
, 11, Intuition
)
54 Release all resources held by a screen and close it down visually.
58 screen -- pointer to the screen to be closed
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).
75 *****************************************************************************/
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
));
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
);
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
);
107 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
109 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
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
)
121 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
123 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
124 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
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
;
145 DisposeObject(((struct IntScreen
*)screen
)->depthgadget
);
150 FreeVPortCopLists(&screen
->ViewPort
);
153 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
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
);
173 if (((struct IntScreen
*)screen
)->DInfo
.dri_Customize
)
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
));
184 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri
.dri_CheckMark
);
185 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri
.dri_AmigaKey
);
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 DisposeObject(((struct IntScreen
*)screen
)->WinDecorObj
);
197 DisposeObject(((struct IntScreen
*)screen
)->MenuDecorObj
);
198 DisposeObject(((struct IntScreen
*)screen
)->ScrDecorObj
);
200 /* Free the memory */
201 if (((struct IntScreen
*)screen
)->DecorUserBuffer
)
203 FreeMem((APTR
)((struct IntScreen
*)screen
)->DecorUserBuffer
, ((struct IntScreen
*)screen
)->DecorUserBufferSize
);
207 ObtainSemaphore(&((struct IntIntuitionBase
*)(IntuitionBase
))->ScrDecorSem
);
208 ULONG lock
= LockIBase(0);
210 struct NewDecorator
*nd
= ((struct IntScreen
*)screen
)->Decorator
;
212 if ((nd
!= ((struct IntIntuitionBase
*)(IntuitionBase
))->Decorator
) && (nd
!= NULL
))
216 if ((nd
->nd_cnt
== 0) && (nd
->nd_Port
!= NULL
) && (nd
->nd_IntPattern
== NULL
))
218 struct DecoratorMessage msg
;
219 struct MsgPort
*port
= CreateMsgPort();
222 Remove((struct Node
*)nd
);
224 if (nd
->nd_IntPattern
) FreeVec(nd
->nd_IntPattern
);
226 msg
.dm_Message
.mn_ReplyPort
= port
;
227 msg
.dm_Message
.mn_Magic
= MAGIC_DECORATOR
;
228 msg
.dm_Message
.mn_Version
= DECORATOR_VERSION
;
229 msg
.dm_Class
= DM_CLASS_DESTROYDECORATOR
;
232 msg
.dm_Object
= (IPTR
) nd
;
233 PutMsg(nd
->nd_Port
, (struct Message
*) &msg
);
241 ReleaseSemaphore(&((struct IntIntuitionBase
*)(IntuitionBase
))->ScrDecorSem
);
244 /* Free the memory */
245 FreeMem(screen
, sizeof (struct IntScreen
));
247 if (screen
!= GetPrivIBase(IntuitionBase
)->WorkBench
) FireScreenNotifyMessage((IPTR
) screen
, SNOTIFY_AFTER_CLOSESCREEN
, IntuitionBase
);
249 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
251 ReturnBool("CloseScreen",TRUE
);
256 static VOID
int_closescreen(struct CloseScreenActionMsg
*msg
,
257 struct IntuitionBase
*IntuitionBase
)
259 struct Screen
*parent
,*screen
= msg
->Screen
;
262 /* If this is a public screen, free related information if there are
263 no windows left on the screen */
264 if (GetPrivScreen(screen
)->pubScrNode
!= NULL
)
266 if(GetPrivScreen(screen
)->pubScrNode
->psn_VisitorCount
|| screen
->FirstWindow
)
268 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
272 Remove((struct Node
*)GetPrivScreen(screen
)->pubScrNode
);
274 if(GetPrivScreen(screen
)->pubScrNode
->psn_Node
.ln_Name
!= NULL
)
275 FreeVec(GetPrivScreen(screen
)->pubScrNode
->psn_Node
.ln_Name
);
277 FreeMem(GetPrivScreen(screen
)->pubScrNode
,
278 sizeof(struct PubScreenNode
));
280 GetPrivScreen(screen
)->pubScrNode
= 0;
283 RemoveResourceFromList(screen
, RESOURCE_SCREEN
, IntuitionBase
);
285 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
289 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
291 /* Trick: Since NextScreen is the first field of the structure,
292 we can use the pointer in the IntuitionBase as a screen with
293 the structure-size of one pointer */
294 parent
= (struct Screen
*)&(IntuitionBase
->FirstScreen
);
296 /* For all screens... */
297 while (parent
->NextScreen
)
299 /* If the screen to close is the next screen... */
300 if (parent
->NextScreen
== screen
)
304 parent
->NextScreen
= screen
->NextScreen
;
306 /* Check ActiveScreen */
307 if (IntuitionBase
->ActiveScreen
== screen
)
309 if (screen
->NextScreen
)
310 IntuitionBase
->ActiveScreen
= screen
->NextScreen
;
311 else if (IntuitionBase
->FirstScreen
)
312 IntuitionBase
->ActiveScreen
= parent
;
314 IntuitionBase
->ActiveScreen
= NULL
;
317 /* now let's set the default pub screen */
318 if (GetPrivIBase(IntuitionBase
)->DefaultPubScreen
== screen
)
322 GetPrivIBase(IntuitionBase
)->DefaultPubScreen
= NULL
;
323 scr
= IntuitionBase
->FirstScreen
;
325 if (scr
&& GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_DEFPUBSCREEN
&& GetPrivScreen(scr
)->pubScrNode
&& (scr
->Flags
& (PUBLICSCREEN
| WBENCHSCREEN
)))
327 GetPrivIBase(IntuitionBase
)->DefaultPubScreen
= scr
;
331 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
333 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
335 #ifdef TIMEVALWINDOWACTIVATION
336 if (IntuitionBase
->FirstScreen
&& ((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
) || !IntuitionBase
->ActiveWindow
))
338 struct Window
*scanw
= 0;
339 struct Window
*win
= 0;
341 for (scanw
= IntuitionBase
->FirstScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
345 if ((IW(scanw
)->activationtime
.tv_secs
> IW(win
)->activationtime
.tv_secs
) ||
346 ((IW(scanw
)->activationtime
.tv_secs
== IW(win
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(win
)->activationtime
.tv_micro
)))
352 if (!win
) win
= scanw
;
355 if (!win
) win
= IntuitionBase
->FirstScreen
->FirstWindow
;
356 if (GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
)
357 if (IntuitionBase
->ActiveWindow
&& IntuitionBase
->ActiveWindow
->WScreen
== IntuitionBase
->FirstScreen
) win
= NULL
;
358 if (win
) ActivateWindow(win
);
363 parent
= parent
->NextScreen
;
366 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
368 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));