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",
135 caller
,(char*) (caller
->tc_Node
.ln_Name
? caller
->tc_Node
.ln_Name
: ""),screen
);
137 ReturnBool("closescreen",FALSE
);
142 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
144 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
147 DoSyncAction((APTR
)int_closescreen
,&msg
.msg
,IntuitionBase
);
149 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
150 UnlockPubScreenList();
151 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
153 if (IS(screen
)->pubScrNode
!= NULL
)
156 if (IS(screen
)->WindowLock
) UNLOCKWINDOW
;
158 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
159 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
163 /* AROS: Notify decorator */
164 int_ExitDecorator(screen
);
166 /* kill screen bar */
167 KillScreenBar(screen
, IntuitionBase
);
169 /* kill depth gadget */
170 if (((struct IntScreen
*)screen
)->depthgadget
)
172 Object
*im
= (Object
*)((struct Gadget
*)(((struct IntScreen
*)screen
)->depthgadget
))->GadgetRender
;
175 DisposeObject(((struct IntScreen
*)screen
)->depthgadget
);
178 if (IS(screen
)->RestoreDBufInfo
!= NULL
)
180 FreeDBufInfo(IS(screen
)->RestoreDBufInfo
);
184 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Rethink done\n"));
186 FreeVPortCopLists(&screen
->ViewPort
);
190 * AROS: According to documentation, VTAG_ATTACH_CM_GET should return a pointer
191 * to our ViewPort. ViewPort is part of struct Screen, so there's nothing to
192 * GfxFree(). Also, ViewPortExtra is GfxFree()d in FreeColorMap(), attempt to
193 * free it twice doesn't do good things. Looks like some MorphOS quirk. Note
194 * that the same thing is surrounded by #ifdef __MORPHOS__ in original MorphOS code.
195 * TODO: Check if our behavior is correct and adjust it to correspond AmigaOS v3.
198 struct TagItem tags
[3];
200 tags
[0].ti_Tag
= VTAG_ATTACH_CM_GET
;
202 tags
[1].ti_Tag
= VTAG_VIEWPORTEXTRA_GET
;
204 tags
[2].ti_Tag
= VTAG_END_CM
;
206 if (VideoControl(screen
->ViewPort
.ColorMap
, tags
) == NULL
)
208 DEBUG_CLOSESCREEN(dprintf("CloseScreen: CM %lx EX %lx\n",tags
[0].ti_Data
,tags
[1].ti_Data
));
209 if (tags
[0].ti_Data
) GfxFree((APTR
)tags
[0].ti_Data
);
210 if (tags
[1].ti_Data
) GfxFree((APTR
)tags
[1].ti_Data
);
216 if (IS(screen
)->WindowLock
) UNLOCKWINDOW
;
219 /* Free the RasInfo of the viewport */
220 FreeMem(screen
->ViewPort
.RasInfo
, sizeof (struct RasInfo
));
223 /* Root layer now automatically freed in ThinLayerInfo() */
225 #ifdef CreateLayerTagList
226 /* Free the root layer */
227 DeleteLayer(0UL, ((struct IntScreen
*)screen
)->rootLayer
);
230 /* Uninit the layerinfo */
232 ThinLayerInfo(&screen
->LayerInfo
);
233 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ThinLayer done\n"));
235 ReadPixel(&screen
->RastPort
,0,0);
237 /* Free the screen's bitmap */
238 if (IS(screen
)->AllocatedBitMap
)
240 FreeBitMap(IS(screen
)->AllocatedBitMap
);
243 screen
->RastPort
.BitMap
= NULL
;
245 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freebitmap done\n"));
247 /* Free the RastPort's contents */
248 DeinitRastPort(&screen
->RastPort
);
250 if (((struct IntScreen
*)screen
)->DInfo
.dri_Customize
)
253 /* AROS: submenu image moved out of #ifdef */
254 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
->submenu
);
256 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
->menutoggle
);
257 int_SkinAction(SKA_FreeSkin
,(ULONG
*)&((struct IntScreen
*)(screen
))->DInfo
,(struct Screen
*)screen
,IntuitionBase
);
258 int_FreeTitlebarBuffer(screen
,IntuitionBase
);
260 FreeMem(((struct IntScreen
*)screen
)->DInfo
.dri_Customize
,sizeof (struct IntuitionCustomize
));
264 if (((struct IntScreen
*)screen
)->DInfo
.dri_Colors
)
266 FreeMem(((struct IntScreen
*)screen
)->DInfo
.dri_Colors
,4 * DRIPEN_NUMDRIPENS
);
268 DEBUG_CLOSESCREEN(dprintf("CloseScreen: skins done\n"));
271 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_CheckMark
);
272 DisposeObject(((struct IntScreen
*)screen
)->DInfo
.dri_AmigaKey
);
275 CloseFont(((struct IntScreen
*)screen
)->DInfo
.dri_Font
);
277 /* Free the ColorMap */
278 FreeColorMap(screen
->ViewPort
.ColorMap
);
280 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freecolormap done\n"));
282 /* Free the sprite */
283 ReleaseSharedPointer(((struct IntScreen
*)screen
)->Pointer
, IntuitionBase
);
285 /* Free the memory */
286 DisposeObject(screen
);
288 /* AROS: Send notification */
289 if (screen
!= GetPrivIBase(IntuitionBase
)->WorkBench
)
290 FireScreenNotifyMessage((IPTR
) screen
, SNOTIFY_AFTER_CLOSESCREEN
, IntuitionBase
);
292 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
294 ReturnBool("CloseScreen",TRUE
);
299 static VOID
int_closescreen(struct CloseScreenActionMsg
*msg
,
300 struct IntuitionBase
*IntuitionBase
)
302 struct Screen
*parent
,*screen
= msg
->Screen
;
305 DEBUG_CLOSESCREEN(dprintf("CloseScreen: welcome in inputhandler!\n"));
308 if (IntuitionBase
->FirstScreen
== screen
) ScreenDepth(screen
,SDEPTH_TOBACK
,NULL
);
309 DEBUG_CLOSESCREEN(dprintf("CloseScreen: put the screen to back\n"));
312 #if USE_NEWDISPLAYBEEP
313 /* we could be beeping this screen... */
314 /* NOTE: we're running under the windowlock here! */
315 if (IBase
->BeepingScreens
&& (screen
->Flags
& BEEPING
))
317 IBase
->BeepingScreens
--;
321 if (IBase
->MenuVerifyScreen
== IS(screen
))
322 IBase
->MenuVerifyScreen
= NULL
;
324 /* If this is a public screen, free related information if there are
325 no windows left on the screen */
326 if (IS(screen
)->pubScrNode
!= NULL
)
328 DEBUG_CLOSESCREEN(dprintf("CloseScreen: killing a pubscreen entry\n"));
330 if(IS(screen
)->pubScrNode
->psn_VisitorCount
|| screen
->FirstWindow
)
332 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
336 Remove((struct Node
*)IS(screen
)->pubScrNode
);
338 FreeVec(IS(screen
)->pubScrNode
->psn_Node
.ln_Name
);
340 FreeMem(IS(screen
)->pubScrNode
,
341 sizeof(struct PubScreenNode
));
343 IS(screen
)->pubScrNode
= 0;
346 RemoveResourceFromList(screen
, RESOURCE_SCREEN
, IntuitionBase
);
348 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
350 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) lock
= LockIBase(0);
352 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
354 /* Trick: Since NextScreen is the first field of the structure,
355 we can use the pointer in the IntuitionBase as a screen with
356 the structure-size of one pointer */
357 parent
= (struct Screen
*)&(IntuitionBase
->FirstScreen
);
359 /* For all screens... */
360 while (parent
->NextScreen
)
362 /* If the screen to close is the next screen... */
363 if (parent
->NextScreen
== screen
)
367 parent
->NextScreen
= screen
->NextScreen
;
369 /* Check ActiveScreen */
370 if (IntuitionBase
->ActiveScreen
== screen
)
372 if (screen
->NextScreen
)
373 IntuitionBase
->ActiveScreen
= screen
->NextScreen
;
374 else if (IntuitionBase
->FirstScreen
)
375 IntuitionBase
->ActiveScreen
= parent
;
377 IntuitionBase
->ActiveScreen
= NULL
;
380 /* now let's set the default pub screen */
381 if (IBase
->DefaultPubScreen
== screen
)
385 IBase
->DefaultPubScreen
= NULL
;
386 scr
= IntuitionBase
->FirstScreen
;
388 if (scr
&& IBase
->IControlPrefs
.ic_Flags
& ICF_DEFPUBSCREEN
&& IS(scr
)->pubScrNode
&& (scr
->Flags
& (PUBLICSCREEN
| WBENCHSCREEN
)))
390 IBase
->DefaultPubScreen
= scr
;
394 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
395 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) UnlockIBase(lock
);
396 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
398 #ifdef TIMEVALWINDOWACTIVATION
399 if (IntuitionBase
->FirstScreen
&& ((IBase
->IControlPrefs
.ic_Flags
& ICF_SCREENACTIVATION
) || !IntuitionBase
->ActiveWindow
))
401 DeactivateWindow(NULL
,msg
->msg
.task
,IntuitionBase
);
406 parent
= parent
->NextScreen
;
409 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
410 if (!ILOCKCHECK(((struct IntuiActionMsg
*)msg
))) UnlockIBase(lock
);
411 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));