NListtree.mcc: fix sorted insert
[AROS.git] / rom / intuition / openworkbench.c
blob3ade68c33283837a496a47e293d723bef3a25acf
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 Copyright © 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
5 */
7 #include <aros/config.h>
8 #include <intuition/intuition.h>
9 #include <proto/intuition.h>
10 #include <proto/graphics.h>
12 #include "intuition_intern.h"
14 static ULONG FindMode(ULONG width, ULONG height, ULONG depth, struct IntuitionBase *IntuitionBase)
16 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
17 ULONG modeid;
18 struct TagItem modetags[] =
20 { BIDTAG_DesiredWidth, width }, /* 0 */
21 { BIDTAG_DesiredHeight, height }, /* 1 */
22 { BIDTAG_Depth, depth }, /* 2 */
23 { TAG_DONE, 0 }
26 /* Try to find the specified mode */
27 modeid = BestModeIDA(modetags);
28 D(bug("[OpenWorkbench] Size: %dx%d, depth: %d, ModeID 0x%08X\n", width, height, depth, modeid));
30 if (modeid == INVALID_ID)
32 /* If failed, we can have this resolution, but not this depth. Try 4 colors. */
33 modetags[2].ti_Data = 2;
35 modeid = BestModeIDA(modetags);
36 D(bug("[OpenWorkbench] Size: %dx%d, depth: 2, ModeID 0x%08X\n", width, height, modeid));
39 return modeid;
42 /*****************************************************************************
44 NAME */
45 AROS_LH0(IPTR, OpenWorkBench,
47 /* SYNOPSIS */
49 /* LOCATION */
50 struct IntuitionBase *, IntuitionBase, 35, Intuition)
52 /* FUNCTION
53 Attempt to open the Workbench screen.
55 INPUTS
56 None.
58 RESULT
59 Tries to (re)open WorkBench screen. If successful return value
60 is a pointer to the screen structure, which shouldn't be used,
61 because other programs may close the WorkBench and make the
62 pointer invalid. If this function fails the return value is NULL.
64 NOTES
66 EXAMPLE
68 BUGS
70 SEE ALSO
71 CloseWorkBench()
73 INTERNALS
75 *****************************************************************************/
77 AROS_LIBFUNC_INIT
79 struct GfxBase *GfxBase = GetPrivIBase(IntuitionBase)->GfxBase;
80 struct Screen *wbscreen;
82 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: <%s>\n",
83 FindTask(NULL)->tc_Node.ln_Name));
85 /* Intuition not up yet? */
86 if (!GetPrivIBase(IntuitionBase)->DefaultPointer)
87 return FALSE;
89 LockPubScreenList();
91 wbscreen = GetPrivIBase(IntuitionBase)->WorkBench;
93 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: Workbench 0x%lx\n",
94 (ULONG) wbscreen));
96 if (wbscreen)
98 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: returning Workbench screen at 0x%lx\n",
99 (ULONG) wbscreen));
101 UnlockPubScreenList();
103 FireScreenNotifyMessage((IPTR) wbscreen, SNOTIFY_AFTER_OPENWB, IntuitionBase);
105 return (IPTR)wbscreen;
107 else
109 /* Open the Workbench screen if we don't have one. */
111 WORD width = GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Width;
112 WORD height = GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Height;
113 WORD depth = GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Depth;
114 ULONG modeid = GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_DisplayID;
115 APTR disphandle;
117 struct TagItem screenTags[] =
119 { SA_Width, 0 }, /* 0 */
120 { SA_Height, 0 }, /* 1 */
121 { SA_Depth, depth }, /* 2 */
122 { SA_DisplayID, 0 }, /* 3 */
123 { SA_LikeWorkbench, TRUE }, /* 4 */
124 { SA_Type, WBENCHSCREEN }, /* 5 */
125 { SA_Title, (IPTR) "Workbench Screen" }, /* 6 */
126 { SA_PubName, (IPTR) "Workbench" }, /* 7 */
127 { SA_SharePens, TRUE }, /* 8 */
128 { TAG_END, 0 }
131 D(bug("[OpenWorkbench] Requested size: %dx%d, depth: %d, ModeID: 0x%08lX\n", width, height, depth, modeid));
133 /* First check if the specified ModeID exists in the system */
134 disphandle = FindDisplayInfo(modeid);
135 if (!disphandle)
137 D(bug("[OpenWorkbench] Invalid ModeID given\n"));
138 modeid = INVALID_ID;
141 if (modeid == INVALID_ID)
144 * We were unable to find the ModeID specified in our prefs. Need to find a replacement.
145 * First we'll try to look up a mode corresponding to user-specified width, height and depth.
148 /* Specifying -1's here causes BestModeIDA() to fail, fix up the values */
149 if (width == STDSCREENWIDTH)
151 D(bug("[OpenWorkbench] Using default width %d\n", AROS_DEFAULT_WBWIDTH));
152 width = AROS_DEFAULT_WBWIDTH;
154 if (height == STDSCREENHEIGHT)
156 D(bug("[OpenWorkbench] Using default height %d\n", AROS_DEFAULT_WBHEIGHT));
157 height = AROS_DEFAULT_WBHEIGHT;
159 if (depth == -1)
160 depth = AROS_DEFAULT_WBDEPTH;
162 #ifdef __mc68000
163 /* FIXME: less hacky RTG detection */
164 /* select 640x480 if we appear to have RTG hardware (instead of standard PAL/NTSC mode) */
165 if (height < 480)
167 modeid = BestModeID(BIDTAG_DesiredWidth, 800, BIDTAG_DesiredHeight, 600,
168 BIDTAG_Depth, 8, TAG_DONE);
170 if (modeid != INVALID_ID)
172 /* If we have 800x600 or better mode, we assume we have RTG hardware */
173 height = 480;
176 #endif
178 modeid = FindMode(width, height, depth, IntuitionBase);
181 if (modeid == INVALID_ID)
183 /* We don't have any modes with the specified resolution. Try SVGA default (800x600) */
184 modeid = FindMode(800, 600, depth, IntuitionBase);
187 if (modeid == INVALID_ID)
189 /* We don't have any modes with the specified resolution. Try VGA default (640x480) */
190 modeid = FindMode(640, 480, depth, IntuitionBase);
193 if (modeid == INVALID_ID)
195 /* We don't have any modes with the specified resolution. Try Amiga default (640x200) */
196 modeid = FindMode(640, 200, depth, IntuitionBase);
199 if (modeid == INVALID_ID)
202 * There's no even 640x200. Perhaps we are on some mobile device.
203 * Here we try the smallest known screen. This size was picked up
204 * from configure's defaults for old PalmPilot port.
206 modeid = FindMode(160, 160, depth, IntuitionBase);
209 if (modeid != INVALID_ID)
211 struct DimensionInfo dim;
213 #define BOUND(min, val, max) \
214 (((val) == -1) ? -1 : ((min) > (val)) ? (min) : ((max) < (val)) ? (max) : (val))
216 /* Now fix up our specified size to fit into mode's limits. */
217 if (GetDisplayInfoData(NULL, (UBYTE *)&dim, sizeof(dim), DTAG_DIMS, modeid))
219 D(bug("[OpenWorkbench] Minimum size: %dx%d\n", dim.MinRasterWidth, dim.MinRasterHeight));
220 D(bug("[OpenWorkbench] Maximum size: %dx%d\n", dim.MaxRasterWidth, dim.MaxRasterHeight));
221 D(bug("[OpenWorkbench] Maximum depth: %d\n", dim.MaxDepth));
223 width = BOUND(dim.MinRasterWidth, width, dim.MaxRasterWidth);
224 height = BOUND(dim.MinRasterHeight, height, dim.MaxRasterHeight);
225 depth = BOUND(0, depth, dim.MaxDepth);
226 D(bug("[OpenWorkbench] Corrected size: %dx%d %dbpp\n", width, height, depth));
228 GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Width = width;
229 GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Height = height;
230 GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_Depth = depth;
234 * Remember this ModeID because OpenScreen() with SA_LikeWorkbench set to TRUE
235 * looks at this field. We MUST have something valid here.
237 GetPrivIBase(IntuitionBase)->ScreenModePrefs.smp_DisplayID = modeid;
239 screenTags[0].ti_Data = width;
240 screenTags[1].ti_Data = height;
241 screenTags[2].ti_Data = depth;
242 screenTags[3].ti_Data = modeid;
244 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: Trying to open Workbench screen\n"));
246 FireScreenNotifyMessage((IPTR) NULL, SNOTIFY_BEFORE_OPENWB, IntuitionBase);
248 wbscreen = OpenScreenTagList(NULL, screenTags);
251 if( !wbscreen )
253 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: failed to open Workbench screen !!!!\n"));
255 UnlockPubScreenList();
256 return 0;
259 GetPrivIBase(IntuitionBase)->WorkBench = wbscreen;
261 /* Make the screen public. */
262 PubScreenStatus( wbscreen, 0 );
265 /* We have opened the Workbench Screen. Now tell the Workbench process
266 to open it's windows, if there is one. We still do have the pub screen
267 list locked. But while sending the Message to the Workbench task we
268 must unlock the semaphore, otherwise there can be deadlocks if the
269 Workbench task itself does something which locks the pub screen list.
271 But if we unlock the pub screen list, then some other task could try
272 to close the Workbench screen in the meantime. The trick to solve
273 this problem is to increase the psn_VisitorCount of the Workbench
274 screen here, before unlocking the pub screen list. This way the
275 Workbench screen cannot go away. */
277 GetPrivScreen(wbscreen)->pubScrNode->psn_VisitorCount++;
278 DEBUG_VISITOR(dprintf("OpenWorkbench: new VisitorCount %ld\n",
279 GetPrivScreen(wbscreen)->pubScrNode->psn_VisitorCount));
281 UnlockPubScreenList();
283 DEBUG_VISITOR(dprintf("OpenWorkbench: notify Workbench\n"));
285 /* Don't call this function while pub screen list is locked! */
286 TellWBTaskToOpenWindows(IntuitionBase);
288 /* Now fix the psn_VisitorCount we have increased by one, above. It's probably
289 better to do this by hand, instead of calling UnlockPubScreen, because Un-
290 lockPubScreen can send signal to psn_SigTask. */
292 LockPubScreenList();
293 GetPrivScreen(wbscreen)->pubScrNode->psn_VisitorCount--;
294 DEBUG_VISITOR(dprintf("OpenWorkbench: new VisitorCount %ld\n",
295 GetPrivScreen(wbscreen)->pubScrNode->psn_VisitorCount));
296 UnlockPubScreenList();
298 FireScreenNotifyMessage((IPTR) wbscreen, SNOTIFY_AFTER_OPENWB, IntuitionBase);
300 return (IPTR)wbscreen;
302 AROS_LIBFUNC_EXIT
304 } /* OpenWorkBench */