2 Copyright 1995-2011, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
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
;
18 struct TagItem modetags
[] =
20 { BIDTAG_DesiredWidth
, width
}, /* 0 */
21 { BIDTAG_DesiredHeight
, height
}, /* 1 */
22 { BIDTAG_Depth
, depth
}, /* 2 */
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
));
42 /*****************************************************************************
46 AROS_LH0(IPTR
, OpenWorkBench
,
51 struct IntuitionBase
*, IntuitionBase
, 35, Intuition
)
54 Attempt to open the Workbench screen.
60 Tries to (re)open WorkBench screen. If successful return value
61 is a pointer to the screen structure, which shouldn't be used,
62 because other programs may close the WorkBench and make the
64 If this function fails the return value is NULL.
77 *****************************************************************************/
81 struct GfxBase
*GfxBase
= GetPrivIBase(IntuitionBase
)->GfxBase
;
82 struct Screen
*wbscreen
;
84 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: <%s>\n",
85 FindTask(NULL
)->tc_Node
.ln_Name
));
87 /* Intuition not up yet? */
88 if (!GetPrivIBase(IntuitionBase
)->DefaultPointer
)
93 wbscreen
= GetPrivIBase(IntuitionBase
)->WorkBench
;
95 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: Workbench 0x%lx\n",
100 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: returning Workbench screen at 0x%lx\n",
103 UnlockPubScreenList();
105 FireScreenNotifyMessage((IPTR
) wbscreen
, SNOTIFY_AFTER_OPENWB
, IntuitionBase
);
107 return (IPTR
)wbscreen
;
111 /* Open the Workbench screen if we don't have one. */
113 WORD width
= GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Width
;
114 WORD height
= GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Height
;
115 WORD depth
= GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Depth
;
116 ULONG modeid
= GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_DisplayID
;
119 struct TagItem screenTags
[] =
121 { SA_Width
, 0 }, /* 0 */
122 { SA_Height
, 0 }, /* 1 */
123 { SA_Depth
, depth
}, /* 2 */
124 { SA_DisplayID
, 0 }, /* 3 */
125 { SA_LikeWorkbench
, TRUE
}, /* 4 */
126 { SA_Type
, WBENCHSCREEN
}, /* 5 */
127 { SA_Title
, (IPTR
) "Workbench Screen" }, /* 6 */
128 { SA_PubName
, (IPTR
) "Workbench" }, /* 7 */
129 { SA_SharePens
, TRUE
}, /* 8 */
133 D(bug("[OpenWorkbench] Requested size: %dx%d, depth: %d, ModeID: 0x%08lX\n", width
, height
, depth
, modeid
));
135 /* First check if the specified ModeID exists in the system */
136 disphandle
= FindDisplayInfo(modeid
);
139 D(bug("[OpenWorkbench] Invalid ModeID given\n"));
143 if (modeid
== INVALID_ID
)
146 * We were unable to find the ModeID specified in our prefs. Need to find a replacement.
147 * First we'll try to look up a mode corresponding to user-specified width, height and depth.
150 /* Specifying -1's here causes BestModeIDA() to fail, fix up the values */
151 if (width
== STDSCREENWIDTH
)
153 D(bug("[OpenWorkbench] Using default width %d\n", AROS_DEFAULT_WBWIDTH
));
154 width
= AROS_DEFAULT_WBWIDTH
;
156 if (height
== STDSCREENHEIGHT
)
158 D(bug("[OpenWorkbench] Using default height %d\n", AROS_DEFAULT_WBHEIGHT
));
159 height
= AROS_DEFAULT_WBHEIGHT
;
162 depth
= AROS_DEFAULT_WBDEPTH
;
165 /* FIXME: less hacky RTG detection */
166 /* select 640x480 if we appear to have RTG hardware (instead of standard PAL/NTSC mode) */
169 modeid
= BestModeID(BIDTAG_DesiredWidth
, 800, BIDTAG_DesiredHeight
, 600,
170 BIDTAG_Depth
, 8, TAG_DONE
);
172 if (modeid
!= INVALID_ID
)
174 /* If we have 800x600 or better mode, we assume we have RTG hardware */
180 modeid
= FindMode(width
, height
, depth
, IntuitionBase
);
183 if (modeid
== INVALID_ID
)
185 /* We don't have any modes with the specified resolution. Try SVGA default (800x600) */
186 modeid
= FindMode(800, 600, depth
, IntuitionBase
);
189 if (modeid
== INVALID_ID
)
191 /* We don't have any modes with the specified resolution. Try VGA default (640x480) */
192 modeid
= FindMode(640, 480, depth
, IntuitionBase
);
195 if (modeid
== INVALID_ID
)
197 /* We don't have any modes with the specified resolution. Try Amiga default (640x200) */
198 modeid
= FindMode(640, 200, depth
, IntuitionBase
);
201 if (modeid
== INVALID_ID
)
204 * There's no even 640x200. Perhaps we are on some mobile device.
205 * Here we try the smallest known screen. This size was picked up
206 * from configure's defaults for old PalmPilot port.
208 modeid
= FindMode(160, 160, depth
, IntuitionBase
);
211 if (modeid
!= INVALID_ID
)
213 struct DimensionInfo dim
;
215 #define BOUND(min, val, max) \
216 (((val) == -1) ? -1 : ((min) > (val)) ? (min) : ((max) < (val)) ? (max) : (val))
218 /* Now fix up our specified size to fit into mode's limits. */
219 if (GetDisplayInfoData(NULL
, (UBYTE
*)&dim
, sizeof(dim
), DTAG_DIMS
, modeid
))
221 D(bug("[OpenWorkbench] Minimum size: %dx%d\n", dim
.MinRasterWidth
, dim
.MinRasterHeight
));
222 D(bug("[OpenWorkbench] Maximum size: %dx%d\n", dim
.MaxRasterWidth
, dim
.MaxRasterHeight
));
223 D(bug("[OpenWorkbench] Maximum depth: %d\n", dim
.MaxDepth
));
225 width
= BOUND(dim
.MinRasterWidth
, width
, dim
.MaxRasterWidth
);
226 height
= BOUND(dim
.MinRasterHeight
, height
, dim
.MaxRasterHeight
);
227 depth
= BOUND(0, depth
, dim
.MaxDepth
);
228 D(bug("[OpenWorkbench] Corrected size: %dx%d %dbpp\n", width
, height
, depth
));
230 GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Width
= width
;
231 GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Height
= height
;
232 GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_Depth
= depth
;
236 * Remember this ModeID because OpenScreen() with SA_LikeWorkbench set to TRUE
237 * looks at this field. We MUST have something valid here.
239 GetPrivIBase(IntuitionBase
)->ScreenModePrefs
.smp_DisplayID
= modeid
;
241 screenTags
[0].ti_Data
= width
;
242 screenTags
[1].ti_Data
= height
;
243 screenTags
[2].ti_Data
= depth
;
244 screenTags
[3].ti_Data
= modeid
;
246 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: Trying to open Workbench screen\n"));
248 FireScreenNotifyMessage((IPTR
) NULL
, SNOTIFY_BEFORE_OPENWB
, IntuitionBase
);
250 wbscreen
= OpenScreenTagList(NULL
, screenTags
);
255 DEBUG_OPENWORKBENCH(dprintf("OpenWorkBench: failed to open Workbench screen !!!!\n"));
257 UnlockPubScreenList();
261 GetPrivIBase(IntuitionBase
)->WorkBench
= wbscreen
;
263 /* Make the screen public. */
264 PubScreenStatus( wbscreen
, 0 );
267 /* We have opened the Workbench Screen. Now tell the Workbench process
268 to open it's windows, if there is one. We still do have the pub screen
269 list locked. But while sending the Message to the Workbench task we
270 must unlock the semaphore, otherwise there can be deadlocks if the
271 Workbench task itself does something which locks the pub screen list.
273 But if we unlock the pub screen list, then some other task could try
274 to close the Workbench screen in the meantime. The trick to solve
275 this problem is to increase the psn_VisitorCount of the Workbench
276 screen here, before unlocking the pub screen list. This way the
277 Workbench screen cannot go away. */
279 GetPrivScreen(wbscreen
)->pubScrNode
->psn_VisitorCount
++;
280 DEBUG_VISITOR(dprintf("OpenWorkbench: new VisitorCount %ld\n",
281 GetPrivScreen(wbscreen
)->pubScrNode
->psn_VisitorCount
));
283 UnlockPubScreenList();
285 DEBUG_VISITOR(dprintf("OpenWorkbench: notify Workbench\n"));
287 /* Don't call this function while pub screen list is locked! */
288 TellWBTaskToOpenWindows(IntuitionBase
);
290 /* Now fix the psn_VisitorCount we have increased by one, above. It's probably
291 better to do this by hand, instead of calling UnlockPubScreen, because Un-
292 lockPubScreen can send signal to psn_SigTask. */
295 GetPrivScreen(wbscreen
)->pubScrNode
->psn_VisitorCount
--;
296 DEBUG_VISITOR(dprintf("OpenWorkbench: new VisitorCount %ld\n",
297 GetPrivScreen(wbscreen
)->pubScrNode
->psn_VisitorCount
));
298 UnlockPubScreenList();
300 FireScreenNotifyMessage((IPTR
) wbscreen
, SNOTIFY_AFTER_OPENWB
, IntuitionBase
);
302 return (IPTR
)wbscreen
;
306 } /* OpenWorkBench */