HUNKF_FAST | HUNKF_CHIP = next long is memory flag. HUNKF_ADVISORY = ignore following...
[AROS.git] / rom / intuition / screendepth.c
blobaa7a494871bca856de1d55d82fb9d444312ea3af
1 /*
2 Copyright 1995-2010, The AROS Development Team. All rights reserved.
3 Copyright 2001-2003, The MorphOS Development Team. All Rights Reserved.
4 $Id$
6 Change order of screens.
7 */
9 #include <proto/graphics.h>
11 #include "intuition_intern.h"
12 #include "inputhandler.h"
13 #include "inputhandler_actions.h"
15 struct ScreenDepthActionMsg
17 struct IntuiActionMsg msg;
18 struct Screen *screen;
19 ULONG flags;
22 static VOID int_screendepth(struct ScreenDepthActionMsg *msg,
23 struct IntuitionBase *IntuitionBase);
25 /*****************************************************************************
27 NAME */
28 #include <proto/intuition.h>
30 AROS_LH3(void, ScreenDepth,
32 /* SYNOPSIS */
33 AROS_LHA(struct Screen *, screen, A0),
34 AROS_LHA(ULONG , flags, D0),
35 AROS_LHA(APTR , reserved, A1),
37 /* LOCATION */
38 struct IntuitionBase *, IntuitionBase, 131, Intuition)
40 /* FUNCTION
41 Move the specified screen to the front or back, based on passed flag.
42 If the screen is in a group, the screen will change its position in
43 the group only. If the screen is the parent of a group, the whole
44 group will be moved.
46 INPUTS
47 screen - Move this screen.
48 flags - SDEPTH_TOFRONT or SDEPTH_TOBACK for bringing the screen to
49 front or back.
50 If the screen is a child of another screen you may specify
51 SDEPTH_INFAMILY to move the screen within the family. If
52 not specified the whole family will move.
53 reserved - For future use. MUST be NULL by now.
55 RESULT
56 None.
58 NOTES
59 Only the owner of the screen should use SDEPTH_INFAMILY.
60 Intentionally commodities should not change the internal arrangement
61 of screen families.
63 EXAMPLE
65 BUGS
67 I am not sure, if it is enough, to just send a SNOTIFY message to one
68 screen. I would suggest, the former FirstScreen gets a SDEPTH_TOBACK
69 message and the new FirstScreen gets a SDEPTH_TOFRONT message.
70 Currently only the screen supplied with ScreenDepth gets a message.
72 But those messages need to be sent in front of the actual
73 screen depth change because of the SNOTIFY_WAIT_REPLY-flag must be
74 able to block the action. But we only know after int_screendepth(),
75 if there was a change and which change took place.
77 So I leave it, as it is. This way SNOTIFY_WAIT_REPLY should work
78 at least. Is there something written in the AutoDocs, how this has
79 to be done (each screen gets a message)?
81 (o1i)
83 SEE ALSO
84 ScreenToBack(), ScreenToFront()
86 INTERNALS
88 *****************************************************************************/
90 AROS_LIBFUNC_INIT
92 struct ScreenDepthActionMsg msg;
94 if (reserved != NULL) return;
95 SANITY_CHECK(screen)
97 FireScreenNotifyMessageCode((IPTR) screen, SNOTIFY_SCREENDEPTH, flags, IntuitionBase);
99 msg.screen = screen;
100 msg.flags = flags;
101 DoASyncAction((APTR)int_screendepth, &msg.msg, sizeof(msg), IntuitionBase);
103 AROS_LIBFUNC_EXIT
105 } /* ScreenDepth */
107 /*****************************************************************************************/
109 static VOID int_screendepth(struct ScreenDepthActionMsg *msg,
110 struct IntuitionBase *IntuitionBase)
112 struct Screen *screen = msg->screen;
113 ULONG flags = msg->flags;
114 ULONG ilock = LockIBase(0); /* before access to FirstScreen */
115 struct Screen *family = NULL,
116 *current = IntuitionBase->FirstScreen,
117 *previous = NULL,
118 *prefamily = NULL;
119 struct Window *win = NULL;
121 /* Find the screen in the list and check for family */
122 while ( current && current!=screen )
124 if ( flags & SDEPTH_INFAMILY )
126 /* Check if this is the first child in a family */
127 if ( !family && (GetPrivScreen(current)->SpecialFlags & SF_IsChild) )
129 family = current;
130 prefamily = previous;
132 /* Check if this screen is a child so next one belongs to current family */
133 if ( family && !(GetPrivScreen(current)->SpecialFlags & SF_IsChild) )
135 family = NULL;
136 prefamily = NULL;
139 previous = current;
140 current = current->NextScreen;
143 if ( current )
145 if ( ! (flags & SDEPTH_TOBACK) ) /* SDEPTH_TOFRONT is #defined as 0 */
147 BOOL changed = FALSE;
148 if ( previous ) /* I'm not the very first screen */
150 changed = TRUE;
151 if ( flags & SDEPTH_INFAMILY )
153 if ( GetPrivScreen(current)->SpecialFlags & SF_IsChild )
154 { /* Move me in the front of my family */
155 if ( family ) /* I'm not the first one in my family */
157 previous->NextScreen = current->NextScreen;
158 current->NextScreen = family;
159 if ( prefamily )
161 prefamily->NextScreen = current;
163 else
165 IntuitionBase->FirstScreen = current;
169 else if ( GetPrivScreen(current)->SpecialFlags & SF_IsParent )
170 { /* Move whole family */
171 if ( prefamily ) /* We are not the first family */
173 prefamily->NextScreen = current->NextScreen;
174 current->NextScreen = IntuitionBase->FirstScreen;
175 IntuitionBase->FirstScreen = family;
178 else
179 { /* I have no family */
180 previous->NextScreen = current->NextScreen;
181 current->NextScreen = IntuitionBase->FirstScreen;
182 IntuitionBase->FirstScreen = current;
185 } /* SDEPTH_INFAMILY */
186 else
188 if ( GetPrivScreen(current)->SpecialFlags & (SF_IsChild|SF_IsParent) )
189 { /* Move my whole family */
190 if ( !family )
192 prefamily = previous;
193 family = current;
195 if ( prefamily )
196 { /* We are not the first family */
197 while ( !(GetPrivScreen(current)->SpecialFlags & SF_IsParent) )
199 current = current->NextScreen;
201 prefamily->NextScreen = current->NextScreen;
202 current->NextScreen = IntuitionBase->FirstScreen;
203 IntuitionBase->FirstScreen = family;
206 else
207 { /* I have no family */
208 previous->NextScreen = current->NextScreen;
209 current->NextScreen = IntuitionBase->FirstScreen;
210 IntuitionBase->FirstScreen = current;
213 } /* ! SDEPTH_INFAMILY */
215 } /* if (previous) */
217 if (!changed)
218 goto end;
219 /* The screen has been made frontmost, activate its monitor */
220 ActivateMonitor(GetPrivScreen(IntuitionBase->FirstScreen)->MonitorObject, -1, -1, IntuitionBase);
221 IntuitionBase->ActiveScreen = IntuitionBase->FirstScreen;
222 } /* if SDEPTH_TO_FRONT */
224 else if ( flags & SDEPTH_TOBACK )
226 BOOL changed = FALSE;
227 if ( flags & SDEPTH_INFAMILY )
229 if ( GetPrivScreen(current)->SpecialFlags & SF_IsChild )
231 /* Go to last screen of this family */
232 while ( !GetPrivScreen(current->NextScreen)->SpecialFlags & SF_IsParent )
234 current = current->NextScreen;
236 if ( current != screen ) /* I'm not the last screen of my family */
238 if ( previous )
240 previous->NextScreen = screen->NextScreen;
242 else
244 IntuitionBase->FirstScreen = screen->NextScreen;
246 screen->NextScreen = current->NextScreen;
247 current->NextScreen = screen;
248 changed = TRUE;
251 else if ( GetPrivScreen(current)->SpecialFlags & SF_IsParent )
253 if ( current->NextScreen ) /* I'm not the last screen */
255 while ( current->NextScreen )
257 current = current->NextScreen;
259 if ( prefamily )
261 prefamily->NextScreen = screen->NextScreen;
263 else
265 IntuitionBase->FirstScreen = screen->NextScreen;
267 if ( family )
269 current->NextScreen = family;
271 else
273 current->NextScreen = screen;
275 screen->NextScreen = NULL;
276 changed = TRUE;
279 else
281 if ( current->NextScreen ) /* I'm not the last screen */
283 while ( current->NextScreen )
285 current = current->NextScreen;
287 if ( previous )
289 previous->NextScreen = screen->NextScreen;
291 else
293 IntuitionBase->FirstScreen = screen->NextScreen;
295 current->NextScreen = screen;
296 screen->NextScreen = NULL;
297 changed = TRUE;
301 } /* SDEPTH_INFAMILY */
302 else
304 struct Screen *last;
306 if ( GetPrivScreen(current)->SpecialFlags & (SF_IsChild|SF_IsParent) )
308 if ( !family )
310 family = current;
311 prefamily = previous;
313 /* Go to last screen of this family */
314 while ( !GetPrivScreen(current)->SpecialFlags & SF_IsParent )
316 current = current->NextScreen;
318 if ( current->NextScreen ) /* We are not the last family */
320 last = current->NextScreen;
321 while ( last->NextScreen )
323 last = last->NextScreen;
325 if ( prefamily )
327 prefamily->NextScreen = current->NextScreen;
329 else
331 IntuitionBase->FirstScreen = current->NextScreen;
333 last->NextScreen = family;
334 current->NextScreen = NULL;
335 changed = TRUE;
338 } /* if ( GetPrivScreen(current)->SpecialFlags & (SF_IsChild|SF_IsParent) ) */
339 else
341 if ( current->NextScreen ) /* I'm not the last screen */
343 while ( current->NextScreen )
345 current = current->NextScreen;
347 if ( previous )
349 previous->NextScreen = screen->NextScreen;
351 else
353 IntuitionBase->FirstScreen = screen->NextScreen;
355 current->NextScreen = screen;
356 screen->NextScreen = NULL;
357 changed = TRUE;
360 } /* current not SF_isChild | SF_IsParent */
362 } /* ! SDEPTH_INFAMILY */
363 if (!changed)
364 goto end;
365 /* We have just brought the screen to back. We want to stay on the current monitor,
366 so we activate the frontmost screen on THIS monitor */
367 IntuitionBase->ActiveScreen = FindFirstScreen(GetPrivIBase(IntuitionBase)->ActiveMonitor, IntuitionBase);
368 } /* if SDEPTH_TO_BACK */
369 } /* if (current) */
371 RethinkDisplay();
373 #if 0 /* FIXME: backport, disabled */
374 if (IntuitionBase->FirstScreen && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_SCREENACTIVATION)
376 struct Window *scanw = 0;
378 for (scanw = IntuitionBase->FirstScreen->FirstWindow; scanw ; scanw = scanw->NextWindow)
380 if (win)
382 if ((IW(scanw)->activationtime.tv_secs > IW(win)->activationtime.tv_secs) ||
383 ((IW(scanw)->activationtime.tv_secs == IW(win)->activationtime.tv_secs) && (IW(scanw)->activationtime.tv_micro > IW(win)->activationtime.tv_micro)))
385 win = scanw;
389 if (!win) win = scanw;
392 if (!win) win = IntuitionBase->FirstScreen->FirstWindow;
393 if (IntuitionBase->ActiveWindow && IntuitionBase->ActiveWindow->WScreen == IntuitionBase->FirstScreen) win = NULL;
395 #endif
397 /* now set the default pub screen */
398 /* if the screen is not a public one we just ignore this */
400 if (IntuitionBase->FirstScreen && GetPrivIBase(IntuitionBase)->IControlPrefs.ic_Flags & ICF_DEFPUBSCREEN)
402 if (GetPrivScreen(IntuitionBase->FirstScreen)->pubScrNode && (IntuitionBase->FirstScreen->Flags & (PUBLICSCREEN | WBENCHSCREEN)))
404 GetPrivIBase(IntuitionBase)->DefaultPubScreen = IntuitionBase->FirstScreen;
407 end:
408 UnlockIBase(ilock);
410 if (win)
412 ActivateWindow(win);