2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2013, The MorphOS Development Team. All Rights Reserved.
10 * Things added by AROS, which needs to be kept when merging with newer MorphOS releases:
12 * 1. Explicit library bases
13 * 2. FireScreenNotifyMessage() calls
14 * 3. RemoveResourceFromList() call
15 * 4. int_ExitDecorator() call
16 * 5. Other placed marked by 'AROS:' in comments.
17 * 6. Check #ifdef's. Some of them were rearranged or completely deleted.
18 * We reuse MorphOS skin code where appropriate.
21 #include <graphics/videocontrol.h>
22 #include <proto/exec.h>
23 #include <proto/graphics.h>
24 #include <proto/layers.h>
25 #include "intuition_intern.h"
26 #include "intuition_customize.h"
27 #include "inputhandler_actions.h"
29 #ifndef DEBUG_CloseScreen
30 #define DEBUG_CloseScreen 0
36 #include <aros/debug.h>
38 struct CloseScreenActionMsg
40 struct IntuiActionMsg msg
;
41 struct Screen
*Screen
;
44 static VOID
int_closescreen(struct CloseScreenActionMsg
*msg
,
45 struct IntuitionBase
*IntuitionBase
);
47 /*****************************************************************************
50 #include <intuition/screens.h>
51 #include <proto/intuition.h>
53 AROS_LH1(BOOL
, CloseScreen
,
56 AROS_LHA(struct Screen
*, screen
, A0
),
59 struct IntuitionBase
*, IntuitionBase
, 11, Intuition
)
62 Release all resources held by a screen and close it down visually.
65 screen - pointer to the screen to be closed
68 TRUE if the screen is successfully closed, FALSE if there were still
69 windows left on the screen (which means the screen is not closed).
81 *****************************************************************************/
85 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
86 struct LayersBase
*LayersBase
= GetPrivIBase(IntuitionBase
)->LayersBase
;
87 struct CloseScreenActionMsg msg
;
90 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", (ULONG
)screen
));
92 D(bug("CloseScreen (%p)\n", screen
));
96 ReturnBool("CloseScreen",TRUE
);
99 #ifdef INTUITION_NOTIFY_SUPPORT
100 /* Notify that the screen is going to close */
101 sn_DoNotify(SCREENNOTIFY_TYPE_CLOSESCREEN
, screen
, IBase
->ScreenNotifyBase
);
103 if (screen
!= GetPrivIBase(IntuitionBase
)->WorkBench
)
104 FireScreenNotifyMessage((IPTR
) screen
, SNOTIFY_BEFORE_CLOSESCREEN
, IntuitionBase
);
106 /* there's a second check below for public screens */
107 if (screen
->FirstWindow
)
109 D(bug("CloseScreen: fail, window still opened\n"));
110 ReturnBool("CloseScreen",FALSE
);
114 /* let's wait for user to finish window drag/size actions to avoid
115 deadlocks and not break user's input */
116 if (IS(screen
)->WindowLock
)
123 /* !moron check here! */
124 for (ccs
= IntuitionBase
->FirstScreen
; ccs
; ccs
= ccs
->NextScreen
)
126 if (ccs
== screen
) found
= TRUE
;
131 struct Task
*caller
= FindTask(NULL
);
134 dprintf("CloseScreen: task %p (%s) attempted a bogus CloseScreen(%p) !\n",
136 caller
->tc_Node
.ln_Name
?
137 (const char *)caller
->tc_Node
.ln_Name
: "",
140 ReturnBool("closescreen",FALSE
);
145 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
147 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
150 DoSyncAction((APTR
)int_closescreen
,&msg
.msg
,IntuitionBase
);
152 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
153 UnlockPubScreenList();
154 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
156 if (IS(screen
)->pubScrNode
!= NULL
)
159 if (IS(screen
)->WindowLock
) UNLOCKWINDOW
;
161 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
162 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
166 /* AROS: Notify decorator */
167 int_ExitDecorator(screen
);
169 /* kill screen bar */
170 KillScreenBar(screen
, IntuitionBase
);
172 /* kill depth gadget */
173 if (((struct IntScreen
*)screen
)->depthgadget
)
175 Object
*im
= (Object
*)((struct Gadget
*)(((struct IntScreen
*)screen
)->depthgadget
))->GadgetRender
;
178 DisposeObject(((struct IntScreen
*)screen
)->depthgadget
);
181 if (IS(screen
)->RestoreDBufInfo
!= NULL
)
183 FreeDBufInfo(IS(screen
)->RestoreDBufInfo
);
187 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Rethink done\n"));
189 FreeVPortCopLists(&screen
->ViewPort
);
193 * AROS: According to documentation, VTAG_ATTACH_CM_GET should return a pointer
194 * to our ViewPort. ViewPort is part of struct Screen, so there's nothing to
195 * GfxFree(). Also, ViewPortExtra is GfxFree()d in FreeColorMap(), attempt to
196 * free it twice doesn't do good things. Looks like some MorphOS quirk. Note
197 * that the same thing is surrounded by #ifdef __MORPHOS__ in original MorphOS code.
198 * TODO: Check if our behavior is correct and adjust it to correspond AmigaOS v3.
201 struct TagItem tags
[3];
203 tags
[0].ti_Tag
= VTAG_ATTACH_CM_GET
;
205 tags
[1].ti_Tag
= VTAG_VIEWPORTEXTRA_GET
;
207 tags
[2].ti_Tag
= VTAG_END_CM
;
209 if (VideoControl(screen
->ViewPort
.ColorMap
, tags
) == NULL
)
211 DEBUG_CLOSESCREEN(dprintf("CloseScreen: CM %lx EX %lx\n",tags
[0].ti_Data
,tags
[1].ti_Data
));
212 if (tags
[0].ti_Data
) GfxFree((APTR
)tags
[0].ti_Data
);
213 if (tags
[1].ti_Data
) GfxFree((APTR
)tags
[1].ti_Data
);
219 if (IS(screen
)->WindowLock
) UNLOCKWINDOW
;
222 /* Free the RasInfo of the viewport */
223 FreeMem(screen
->ViewPort
.RasInfo
, sizeof (struct RasInfo
));
226 /* Root layer now automatically freed in ThinLayerInfo() */
228 #ifdef CreateLayerTagList
229 /* Free the root layer */
230 DeleteLayer(0UL, ((struct IntScreen
*)screen
)->rootLayer
);
233 /* Uninit the layerinfo */
235 ThinLayerInfo(&screen
->LayerInfo
);
236 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ThinLayer done\n"));
238 ReadPixel(&screen
->RastPort
,0,0);
240 /* Free the screen's bitmap */
241 if (IS(screen
)->AllocatedBitMap
)
243 FreeBitMap(IS(screen
)->AllocatedBitMap
);
246 screen
->RastPort
.BitMap
= NULL
;
248 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freebitmap done\n"));
250 /* Free the RastPort's contents */
251 DeinitRastPort(&screen
->RastPort
);
253 if (((struct IntScreen
*)screen
)->DInfo
.dri_Customize
)
256 /* AROS: submenu image moved out of #ifdef */
257 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
->submenu
);
259 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
->menutoggle
);
260 int_SkinAction(SKA_FreeSkin
,(ULONG
*)&((struct IntScreen
*)(screen
))->DInfo
,(struct Screen
*)screen
,IntuitionBase
);
261 int_FreeTitlebarBuffer(screen
,IntuitionBase
);
263 FreeMem(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
,sizeof (struct IntuitionCustomize
));
267 if (((struct IntScreen
*)screen
)->DInfo
.dri_Colors
)
269 FreeMem(((struct IntScreen
*)screen
)->DInfo
.dri_Colors
,4 * DRIPEN_NUMDRIPENS
);
271 DEBUG_CLOSESCREEN(dprintf("CloseScreen: skins done\n"));
274 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_CheckMark
);
275 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_AmigaKey
);
278 CloseFont(((struct IntScreen
*)screen
)->DInfo
.dri_Font
);
280 /* Free the ColorMap */
281 FreeColorMap(screen
->ViewPort
.ColorMap
);
283 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freecolormap done\n"));
285 /* Free the sprite */
286 ReleaseSharedPointer(((struct IntScreen
*)screen
)->Pointer
, IntuitionBase
);
288 /* Free the memory */
289 DisposeObject(screen
);
291 /* AROS: Send notification */
292 if (screen
!= GetPrivIBase(IntuitionBase
)->WorkBench
)
293 FireScreenNotifyMessage((IPTR
) screen
, SNOTIFY_AFTER_CLOSESCREEN
, IntuitionBase
);
295 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
297 ReturnBool("CloseScreen",TRUE
);
302 static VOID
int_closescreen(struct CloseScreenActionMsg
*msg
,
303 struct IntuitionBase
*IntuitionBase
)
305 struct Screen
*parent
,*screen
= msg
->Screen
;
308 DEBUG_CLOSESCREEN(dprintf("CloseScreen: welcome in inputhandler!\n"));
311 if (IntuitionBase
->FirstScreen
== screen
) ScreenDepth(screen
,SDEPTH_TOBACK
,NULL
);
312 DEBUG_CLOSESCREEN(dprintf("CloseScreen: put the screen to back\n"));
315 #if USE_NEWDISPLAYBEEP
316 /* we could be beeping this screen... */
317 /* NOTE: we're running under the windowlock here! */
318 if (IBase
->BeepingScreens
&& (screen
->Flags
& BEEPING
))
320 IBase
->BeepingScreens
--;
324 if (IBase
->MenuVerifyScreen
== IS(screen
))
325 IBase
->MenuVerifyScreen
= NULL
;
327 /* If this is a public screen, free related information if there are
328 no windows left on the screen */
329 if (IS(screen
)->pubScrNode
!= NULL
)
331 DEBUG_CLOSESCREEN(dprintf("CloseScreen: killing a pubscreen entry\n"));
333 if(IS(screen
)->pubScrNode
->psn_VisitorCount
|| screen
->FirstWindow
)
335 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
339 Remove((struct Node
*)IS(screen
)->pubScrNode
);
341 FreeVec(IS(screen
)->pubScrNode
->psn_Node
.ln_Name
);
343 FreeMem(IS(screen
)->pubScrNode
,
344 sizeof(struct PubScreenNode
));
346 IS(screen
)->pubScrNode
= 0;
349 RemoveResourceFromList(screen
, RESOURCE_SCREEN
, IntuitionBase
);
351 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
353 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) lock
= LockIBase(0);
355 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
357 /* Trick: Since NextScreen is the first field of the structure,
358 we can use the pointer in the IntuitionBase as a screen with
359 the structure-size of one pointer */
360 parent
= (struct Screen
*)&(IntuitionBase
->FirstScreen
);
362 /* For all screens... */
363 while (parent
->NextScreen
)
365 /* If the screen to close is the next screen... */
366 if (parent
->NextScreen
== screen
)
370 parent
->NextScreen
= screen
->NextScreen
;
372 /* Check ActiveScreen */
373 if (IntuitionBase
->ActiveScreen
== screen
)
375 if (screen
->NextScreen
)
376 IntuitionBase
->ActiveScreen
= screen
->NextScreen
;
377 else if (IntuitionBase
->FirstScreen
)
378 IntuitionBase
->ActiveScreen
= parent
;
380 IntuitionBase
->ActiveScreen
= NULL
;
383 /* now let's set the default pub screen */
384 if (IBase
->DefaultPubScreen
== screen
)
388 IBase
->DefaultPubScreen
= NULL
;
389 scr
= IntuitionBase
->FirstScreen
;
391 if (scr
&& IBase
->IControlPrefs
.ic_Flags
& ICF_DEFPUBSCREEN
&& IS(scr
)->pubScrNode
&& (scr
->Flags
& (PUBLICSCREEN
| WBENCHSCREEN
)))
393 IBase
->DefaultPubScreen
= scr
;
397 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
398 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) UnlockIBase(lock
);
399 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
401 #ifdef TIMEVALWINDOWACTIVATION
402 if (IntuitionBase
->FirstScreen
&& ((IBase
->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
) || !IntuitionBase
->ActiveWindow
))
404 DeactivateWindow(NULL
,msg
->msg
.task
,IntuitionBase
);
409 parent
= parent
->NextScreen
;
412 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
413 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) UnlockIBase(lock
);
414 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));