dont try to convert the pixfmt while calculating the "shade"
[AROS.git] / rom / intuition / closescreen.c
blobcbbd27e278f99d43bd4585626218b496ea0de26e
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2013, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Close a screen.
7 */
9 /*
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
31 #endif
32 #undef DEBUG
33 #if DEBUG_CloseScreen
34 #define DEBUG 1
35 #endif
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 /*****************************************************************************
49 NAME */
50 #include <intuition/screens.h>
51 #include <proto/intuition.h>
53 AROS_LH1(BOOL, CloseScreen,
55 /* SYNOPSIS */
56 AROS_LHA(struct Screen *, screen, A0),
58 /* LOCATION */
59 struct IntuitionBase *, IntuitionBase, 11, Intuition)
61 /* FUNCTION
63 Release all resources held by a screen and close it down visually.
65 INPUTS
67 screen -- pointer to the screen to be closed
69 RESULT
71 TRUE if the screen is successfully closed, FALSE if there were still
72 windows left on the screen (which means the screen is not closed).
74 NOTES
76 EXAMPLE
78 BUGS
80 SEE ALSO
82 INTERNALS
84 HISTORY
85 29-10-95 digulla automatically created from
86 intuition_lib.fd and clib/intuition_protos.h
88 *****************************************************************************/
90 AROS_LIBFUNC_INIT
92 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
93 struct LayersBase *LayersBase = GetPrivIBase(IntuitionBase)->LayersBase;
94 struct CloseScreenActionMsg msg;
95 // ULONG lock;
97 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Screen 0x%lx\n", (ULONG)screen));
99 D(bug("CloseScreen (%p)\n", screen));
101 if ( screen == NULL )
103 ReturnBool("CloseScreen",TRUE);
106 #ifdef INTUITION_NOTIFY_SUPPORT
107 /* Notify that the screen is going to close */
108 sn_DoNotify(SCREENNOTIFY_TYPE_CLOSESCREEN, screen, IBase->ScreenNotifyBase);
109 #endif
110 if (screen != GetPrivIBase(IntuitionBase)->WorkBench)
111 FireScreenNotifyMessage((IPTR) screen, SNOTIFY_BEFORE_CLOSESCREEN, IntuitionBase);
113 /* there's a second check below for public screens */
114 if (screen->FirstWindow)
116 D(bug("CloseScreen: fail, window still opened\n"));
117 ReturnBool("CloseScreen",FALSE);
120 #ifdef USEWINDOWLOCK
121 /* let's wait for user to finish window drag/size actions to avoid
122 deadlocks and not break user's input */
123 if (IS(screen)->WindowLock)
125 struct Screen *ccs;
126 BOOL found = FALSE;
128 LOCKWINDOW;
130 /* !moron check here! */
131 for (ccs = IntuitionBase->FirstScreen; ccs; ccs = ccs->NextScreen)
133 if (ccs == screen) found = TRUE;
136 if (!found)
138 struct Task *caller = FindTask(NULL);
139 UNLOCKWINDOW;
141 dprintf("CloseScreen: task %p (%s) attempted a bogus CloseScreen(%p) !\n",
142 caller,(char*) (caller->tc_Node.ln_Name ? caller->tc_Node.ln_Name : ""),screen);
144 ReturnBool("closescreen",FALSE);
147 #endif
149 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList\n"));
150 LockPubScreenList();
151 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockPubScreenList done\n"));
153 msg.Screen = screen;
154 DoSyncAction((APTR)int_closescreen,&msg.msg,IntuitionBase);
156 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList\n"));
157 UnlockPubScreenList();
158 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockPubScreenList done\n"));
160 if (IS(screen)->pubScrNode != NULL)
162 #ifdef USEWINDOWLOCK
163 if (IS(screen)->WindowLock) UNLOCKWINDOW;
164 #endif
165 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
166 //something went wrong! int_closescreen is supposed to clear pubScrNode ptr!
167 return FALSE;
170 /* AROS: Notify decorator */
171 int_ExitDecorator(screen);
173 /* kill screen bar */
174 KillScreenBar(screen, IntuitionBase);
176 /* kill depth gadget */
177 if (((struct IntScreen *)screen)->depthgadget)
179 Object *im = (Object*)((struct Gadget *)(((struct IntScreen *)screen)->depthgadget))->GadgetRender;
181 DisposeObject(im);
182 DisposeObject(((struct IntScreen *)screen)->depthgadget);
185 if (IS(screen)->RestoreDBufInfo != NULL)
187 FreeDBufInfo(IS(screen)->RestoreDBufInfo);
190 RethinkDisplay();
191 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Rethink done\n"));
193 FreeVPortCopLists(&screen->ViewPort);
195 #ifdef __MORPHOS__
197 * AROS: According to documentation, VTAG_ATTACH_CM_GET should return a pointer
198 * to our ViewPort. ViewPort is part of struct Screen, so there's nothing to
199 * GfxFree(). Also, ViewPortExtra is GfxFree()d in FreeColorMap(), attempt to
200 * free it twice doesn't do good things. Looks like some MorphOS quirk. Note
201 * that the same thing is surrounded by #ifdef __MORPHOS__ in original MorphOS code.
202 * TODO: Check if our behavior is correct and adjust it to correspond AmigaOS v3.
205 struct TagItem tags[3];
207 tags[0].ti_Tag = VTAG_ATTACH_CM_GET;
208 tags[0].ti_Data = 0;
209 tags[1].ti_Tag = VTAG_VIEWPORTEXTRA_GET;
210 tags[1].ti_Data = 0;
211 tags[2].ti_Tag = VTAG_END_CM;
213 if (VideoControl(screen->ViewPort.ColorMap, tags) == NULL)
215 DEBUG_CLOSESCREEN(dprintf("CloseScreen: CM %lx EX %lx\n",tags[0].ti_Data,tags[1].ti_Data));
216 if (tags[0].ti_Data) GfxFree((APTR)tags[0].ti_Data);
217 if (tags[1].ti_Data) GfxFree((APTR)tags[1].ti_Data);
220 #endif
222 #ifdef USEWINDOWLOCK
223 if (IS(screen)->WindowLock) UNLOCKWINDOW;
224 #endif
226 /* Free the RasInfo of the viewport */
227 FreeMem(screen->ViewPort.RasInfo, sizeof (struct RasInfo));
229 #if 0
230 /* Root layer now automatically freed in ThinLayerInfo() */
232 #ifdef CreateLayerTagList
233 /* Free the root layer */
234 DeleteLayer(0UL, ((struct IntScreen *)screen)->rootLayer);
235 #endif
236 #endif
237 /* Uninit the layerinfo */
239 ThinLayerInfo(&screen->LayerInfo);
240 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ThinLayer done\n"));
242 ReadPixel(&screen->RastPort,0,0);
244 /* Free the screen's bitmap */
245 if (IS(screen)->AllocatedBitMap)
247 FreeBitMap(IS(screen)->AllocatedBitMap);
250 screen->RastPort.BitMap = NULL;
252 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freebitmap done\n"));
254 /* Free the RastPort's contents */
255 DeinitRastPort(&screen->RastPort);
257 if (((struct IntScreen *)screen)->DInfo.dri_Customize)
259 /* Free the skin */
260 /* AROS: submenu image moved out of #ifdef */
261 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->submenu);
262 #ifdef SKINS
263 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_Customize->menutoggle);
264 int_SkinAction(SKA_FreeSkin,(ULONG*)&((struct IntScreen *)(screen))->DInfo,(struct Screen *)screen,IntuitionBase);
265 int_FreeTitlebarBuffer(screen,IntuitionBase);
266 #endif
267 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Customize,sizeof (struct IntuitionCustomize));
270 #ifdef SKINS
271 if (((struct IntScreen *)screen)->DInfo.dri_Colors)
273 FreeMem(((struct IntScreen *)screen)->DInfo.dri_Colors,4 * DRIPEN_NUMDRIPENS);
275 DEBUG_CLOSESCREEN(dprintf("CloseScreen: skins done\n"));
276 #endif
278 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_CheckMark);
279 DisposeObject(((struct IntScreen *)screen)->DInfo.dri_AmigaKey);
281 /* Close the font */
282 CloseFont(((struct IntScreen *)screen)->DInfo.dri_Font);
284 /* Free the ColorMap */
285 FreeColorMap(screen->ViewPort.ColorMap);
287 DEBUG_CLOSESCREEN(dprintf("CloseScreen: Freecolormap done\n"));
289 /* Free the sprite */
290 ReleaseSharedPointer(((struct IntScreen *)screen)->Pointer, IntuitionBase);
292 /* Free the memory */
293 DisposeObject(screen);
295 /* AROS: Send notification */
296 if (screen != GetPrivIBase(IntuitionBase)->WorkBench)
297 FireScreenNotifyMessage((IPTR) screen, SNOTIFY_AFTER_CLOSESCREEN, IntuitionBase);
299 DEBUG_CLOSESCREEN(dprintf("CloseScreen: ok\n"));
301 ReturnBool("CloseScreen",TRUE);
303 AROS_LIBFUNC_EXIT
304 } /* CloseScreen */
306 static VOID int_closescreen(struct CloseScreenActionMsg *msg,
307 struct IntuitionBase *IntuitionBase)
309 struct Screen *parent,*screen = msg->Screen;
310 ULONG lock = 0;
312 DEBUG_CLOSESCREEN(dprintf("CloseScreen: welcome in inputhandler!\n"));
314 #ifdef SKINS
315 if (IntuitionBase->FirstScreen == screen) ScreenDepth(screen,SDEPTH_TOBACK,NULL);
316 DEBUG_CLOSESCREEN(dprintf("CloseScreen: put the screen to back\n"));
317 #endif
319 #if USE_NEWDISPLAYBEEP
320 /* we could be beeping this screen... */
321 /* NOTE: we're running under the windowlock here! */
322 if (IBase->BeepingScreens && (screen->Flags & BEEPING))
324 IBase->BeepingScreens --;
326 #endif
328 if (IBase->MenuVerifyScreen == IS(screen))
329 IBase->MenuVerifyScreen = NULL;
331 /* If this is a public screen, free related information if there are
332 no windows left on the screen */
333 if (IS(screen)->pubScrNode != NULL)
335 DEBUG_CLOSESCREEN(dprintf("CloseScreen: killing a pubscreen entry\n"));
337 if(IS(screen)->pubScrNode->psn_VisitorCount || screen->FirstWindow)
339 DEBUG_CLOSESCREEN(dprintf("CloseScreen: failed\n"));
340 return;
343 Remove((struct Node *)IS(screen)->pubScrNode);
345 if(IS(screen)->pubScrNode->psn_Node.ln_Name != NULL)
346 FreeVec(IS(screen)->pubScrNode->psn_Node.ln_Name);
348 FreeMem(IS(screen)->pubScrNode,
349 sizeof(struct PubScreenNode));
351 IS(screen)->pubScrNode = 0;
354 RemoveResourceFromList(screen, RESOURCE_SCREEN, IntuitionBase);
356 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase\n"));
358 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) lock = LockIBase(0);
360 DEBUG_CLOSESCREEN(dprintf("CloseScreen: LockIBase done\n"));
362 /* Trick: Since NextScreen is the first field of the structure,
363 we can use the pointer in the IntuitionBase as a screen with
364 the structure-size of one pointer */
365 parent = (struct Screen *)&(IntuitionBase->FirstScreen);
367 /* For all screens... */
368 while (parent->NextScreen)
370 /* If the screen to close is the next screen... */
371 if (parent->NextScreen == screen)
374 /* Unlink it */
375 parent->NextScreen = screen->NextScreen;
377 /* Check ActiveScreen */
378 if (IntuitionBase->ActiveScreen == screen)
380 if (screen->NextScreen)
381 IntuitionBase->ActiveScreen = screen->NextScreen;
382 else if (IntuitionBase->FirstScreen)
383 IntuitionBase->ActiveScreen = parent;
384 else
385 IntuitionBase->ActiveScreen = NULL;
388 /* now let's set the default pub screen */
389 if (IBase->DefaultPubScreen == screen)
391 struct Screen *scr;
393 IBase->DefaultPubScreen = NULL;
394 scr = IntuitionBase->FirstScreen;
396 if (scr && IBase->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN && IS(scr)->pubScrNode && (scr->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
398 IBase->DefaultPubScreen = scr;
402 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
403 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
404 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
406 #ifdef TIMEVALWINDOWACTIVATION
407 if (IntuitionBase->FirstScreen && ((IBase->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION) || !IntuitionBase->ActiveWindow))
409 DeactivateWindow(NULL,msg->msg.task,IntuitionBase);
411 #endif
412 return;
414 parent = parent->NextScreen;
417 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase\n"));
418 if (!ILOCKCHECK(((struct IntuiActionMsg *)msg))) UnlockIBase(lock);
419 DEBUG_CLOSESCREEN(dprintf("CloseScreen: UnLockIBase done\n"));
421 return;