2 Copyright 1995-2007, 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 CloseScreenActionMsg msg
;
81 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", screen
));
83 D(bug("CloseScreen (%p)\n", screen
));
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
);
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
);
113 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
115 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
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
)
127 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
129 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
130 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
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
;
143 DisposeObject(((struct IntScreen
*)screen
)->depthgadget
);
149 FreeVPortCopLists(&screen
->ViewPort
);
152 struct TagItem tags
[2];
154 tags
[0].ti_Tag
= VTAG_ATTACH_CM_GET
;
156 tags
[1].ti_Tag
= VTAG_END_CM
;
158 if (VideoControl(screen
->ViewPort
.ColorMap
, tags
))
160 GfxFree((APTR
)tags
[0].ti_Data
);
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
);
175 SetFrontBitMap(NULL
, FALSE
);
180 ReleaseSemaphore(&GetPrivIBase(IntuitionBase
)->WindowLock
);
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
);
200 if (((struct IntScreen
*)screen
)->DInfo
.dri_Customize
)
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
));
211 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri
.dri_CheckMark
);
212 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri
.dri_AmigaKey
);
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((IPTR
) ((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
))
239 if ((nd
->nd_cnt
== 0) && (nd
->nd_Port
!= NULL
) && (nd
->nd_IntPattern
== NULL
))
241 struct DecoratorMessage msg
;
242 struct MsgPort
*port
= CreateMsgPort();
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
;
255 msg
.dm_Object
= (IPTR
) nd
;
256 PutMsg(nd
->nd_Port
, (struct Message
*) &msg
);
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
);
279 static VOID
int_closescreen(struct CloseScreenActionMsg
*msg
,
280 struct IntuitionBase
*IntuitionBase
)
282 struct Screen
*parent
,*screen
= msg
->Screen
;
283 struct Window
*win
= 0;
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"));
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"));
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
)
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
;
338 IntuitionBase
->ActiveScreen
= NULL
;
341 /* now let's set the default pub screen */
342 if (GetPrivIBase(IntuitionBase
)->DefaultPubScreen
== screen
)
347 GetPrivIBase(IntuitionBase
)->DefaultPubScreen
= NULL
;
348 scr
= IntuitionBase
->FirstScreen
;
350 if (scr
&& GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_DEFPUBSCREEN
&& GetPrivScreen(scr
)->pubScrNode
&& (scr
->Flags
& (PUBLICSCREEN
| WBENCHSCREEN
)))
352 GetPrivIBase(IntuitionBase
)->DefaultPubScreen
= scr
;
356 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
358 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
360 #ifdef TIMEVALWINDOWACTIVATION
361 if (IntuitionBase
->FirstScreen
&& ((GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
) || !IntuitionBase
->ActiveWindow
))
363 struct Window
*scanw
= 0;
365 for (scanw
= IntuitionBase
->FirstScreen
->FirstWindow
; scanw
; scanw
= scanw
->NextWindow
)
369 if ((IW(scanw
)->activationtime
.tv_secs
> IW(win
)->activationtime
.tv_secs
) ||
370 ((IW(scanw
)->activationtime
.tv_secs
== IW(win
)->activationtime
.tv_secs
) && (IW(scanw
)->activationtime
.tv_micro
> IW(win
)->activationtime
.tv_micro
)))
376 if (!win
) win
= scanw
;
379 if (!win
) win
= IntuitionBase
->FirstScreen
->FirstWindow
;
380 if (GetPrivIBase(IntuitionBase
)->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
)
381 if (IntuitionBase
->ActiveWindow
&& IntuitionBase
->ActiveWindow
->WScreen
== IntuitionBase
->FirstScreen
) win
= NULL
;
382 if (win
) ActivateWindow(win
);
387 parent
= parent
->NextScreen
;
390 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
392 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));