Screen Programming in AmigaOS 4
Under AmigaOS, a program window is always open on a screen. The operating system’s graphic environment can use multiple screens at the same time, providing a number of “virtual desktops” for you to work on. Screens may vary in size (resolution), colour depth, and they can also be mouse-dragged to reveal other screens hiding behind. Amiga programs can use their own, private (called “custom”) screens; they can open a “public” screen to share display with other programs; or they can open no screen at all and instead use another program’s public screen as visitors. Quite naturally, the most popular and most visited public screen is the Workbench.
Amigans have always been very proud of their screen system. It’s a well-established concept that hasn’t changed much throughout the years, unlike other parts of Intuition. Yet from a programmer’s point of view, screens have been redefined in AmigaOS Release 4. Well, not the screens per se – it’s the philosophy of their use that has changed. The following article helps understand the current mindset and explains certain new implications for screen programming and usage.
2. Past to present
In the past, Amiga programs made a heavy use of custom screens. As the resolution of the computer display was low – the typical screen resolution of the time was mere 640x256 pixels – one could quickly lose overview when having too many programs on the Workbench. It was, therefore, normal that individual programs opened their own screens, through which the user switched as needed. To that end software developers often provided screen configuration as part of their programs’ settings.
But now that AmigaOS-compatible computers use high-resolution displays with 16- or 32-bit depth, custom screens have become less useful than before. Why is that? Well, there are now a number of convincing reasons to open programs on the Workbench by default (especially if their GUI consists of a single window). First of all, a large Workbench can comfortably accommodate most programs you typically run during your computing session. Plus, the race for space on the Workbench has become less of an issue with the emergence of modern applications that are able to collapse (“iconify”) their windows to occupy next to no space on the screen. Moreover, running programs on the Workbench brings the benefit of accessibility: you do not need to swap screens to access other programs, disks or the handy features of OS4’s docking utility, AmiDock. Last but not least, using multiple large screens can really be taxing resource-wise. On some lower-end systems you may quickly run out of graphic memory and bring the OS to a crawl just because a couple of programs decided to open their own screen. Sharing a common public screen – such as the Workbench – is more economical.
3. Screens in AmigaOS 4.x
The decline in the importance of custom screens (brought about by hardware innovations) has further been accelerated by two new AmigaOS features that, instead, encourage the use of public screens:
3.1 Automatic public screens
AmigaOS 4.x received a new Preferences editor, Screens, which unfortunately seems to have been escaping the attention of many. The editor allows users to pre-define their own set of named public screens to utilize throughout the system. They are virtual, “automatic screens”: they exist as screen definitions known to Intuition, and are only opened when a program requires them. Let’s say you have a screen called “MyPublicScreen” pre-defined in the Screens editor, as the image below shows:
Now if you provide the following tag in your window creation code
- WA_PubScreen, “MyPublicScreen”,
the screen will be created and opened by Intuition automatically at program startup and the program’s GUI will open on the said screen. When the program closes its last window, Intuition will close and dispose of the screen. Again, automatically. (NOTE: For this to work the pre-defined screen must have “Open/close automatically” ticked in the Screens preferences editor – see the picture above.)
3.2 Greater window mobility
Using a new feature in Window Class (introduced in AmigaOS 4.1 Update 3), ReAction-based programs can now “jump” between screens freely during their runtime. This can greatly increase the usability of certain types of program (such as a calculator, a notepad or a dictionary) because they can be pushed to where they are currently needed, without having to reconfigure and restart the program.
However, screen jumping only works with public screens because custom screens cannot take visitor windows. Once again this shows that custom screens have become a thing of the past.
4. Programming implications
4.1 Use automatic public screens if you can
As it was mentioned above, screens can exist as virtual entities defined externally in the Screens preferences editor. Their creation and disposal is automatically handled by Intuition so no GUI code is required whatsoever. Of course you can still use OpenScreenTags() but why bother and do things the complicated way? Opening an automatic public screen by simply using its name is so much easier! (However, see below for Recommended practice.)
4.2 Screen configuration GUI
This also means that the screen configuration GUI, as we know it from older Amiga programs, will change. Options to open on a custom screen will be gone because custom screens are not practical anymore (see above). Public screen settings will shrink to a single string gadget for the screen name. Screens will be defined externally according to individual user needs. The screenmode-selection gadget and requester will be used rarely in program GUIs.
4.3 Iconification caveats
Older documentation mentioned that a screen can never get closed while there is a program window opened on it: the window works as a screen lock. Although this is perfectly true, some programmers misinterpreted it as “the screen pointer will be valid until your program exits”. Such an assumption no longer works for programs that can iconify their windows – which effectively means most programs of today.
It is not, and never has been, guaranteed that when the user decides to uniconify your program, its original public screen will still be available! Therefore, it is unwise to hold any pointers related to the original screen and/or its properties, such as VisualInfo, rastport, AmigaGuide context etc. If you ever need to keep them, NULL them all at iconify time – you'll obtain them again later. Before the uniconification takes place, first ensure that there is a place for the program to return: LockPubScreen() is a good thing to do. If your program normally opens on a named public screen, provide a Workbench fallback should the lock fail:
- if ( !(pubScreen = IIntuition->LockPubScreen("AnyName")) ) pubScreen = IIntuition->LockPubScreen(NULL);
- if (pubScreen)
- /* you can safely reopen your window now */
Once you have the new screen pointer, get all other screen-related pointers if your program needs them. If menus are attached using GadTools Library functions, make sure to obtain a new VisualInfo for the screen you'll reopen on, and relayout the menu strip: otherwise the program will crash if it returns to a different screen. When the window is back on, call UnlockPubScreen() and drop the screen lock. Holding locks throughout program runtime might jeopardise the use of automatic public screens.
4.4 Screen jumping caveats
To use the screen-jumping feature (see 3.2 above) successfully, you must understand how this feature works and what Window Class does internally. It performs the necessary housekeeping associated with screen change but it doesn't do everything for you. When the user decides to move the program to another screen and selects the screen name from the pop-up menu, WindowClass updates the program window's WA_PubScreen to point to the new screen, and then sends a WMHI_JUMPSCREEN message. It is fully up to the programmer to react upon this message and reopen the window on the new screen, obtaining or updating all relevant pointers in the process.
Be careful if your program uses sub-windows: whether you create them on-the-fly or at program startup, before opening you must always provide them with a WA_PubScreen tag containing the current screen pointer, otherwise the sub-window could end up on a different screen than the main program window. When travelling between places, do not leave your children behind.
Similarly, if your program uses the AmigaGuide Library to provide online help, remember that when the help system is set up, you receive a pointer to something called the “AmigaGuide context”. The context serves as a handle to your AmigaGuide file, and by design is tied to a particular screen on which the file will open when called for. By now it should be quite clear that if the program is designed to allow jumping between screens, the context for the help system must be re-established each time the screen is changed - otherwise the help file will open behind the current screen, which is not what the user expects.
4.5 Screen properties
If you need to know about a particular screen's properties (such as public screen name, font pointer etc.), use OS4's new function GetScreenAttr() – or GetScreenAttrs() if you want to query about several attributes in one go. Never peek in IntuitionBase or any other system structures.
However, refer to the respective autodocs and study the functions' parameters first! GetScreenAttr() and GetScreenAttrs() are not BOOPSI functions because screens cannot be created as objects. Therefore, although the names seem comfortingly similar to BOOPSI's GetAttr() and GetAttrs(), the obtained attribute values are stored rather differently.
5. Recommended practice
All of these things boil down to a couple of recommendations or guidelines to follow in your GUI programming under AmigaOS Release 4:
- If your program uses a simple GUI, always open on the Workbench by default.
- If you want to give users the option to open on a separate screen, let them define the screen parameters themselves using AmigaOS's Screens editor. In your program’s Settings, provide a string gadget for the public screen name. Alternatively, if your program has no Settings section in the GUI and uses Application Library’s XML-based preferences format, provide a key named “Public Screen” (or similar) for the users to enter the screen name. They can easily edit the prefs file with a text editor or the dedicated PrefsObjectsEditor located in the system's Utilities drawer.
- If your program must use a dedicated screen by default (typically: programs that open many sub-windows), open a public screen via OpenScreenTags(). In your program’s Settings, provide a standard screenmode selector and a checkbox option letting the user to clone the Workbench screen parameters (you’ll do this by passing “SA_LikeWorkbench, TRUE” in the OpenScreenTags() call). Make Clone Workbench the default setting.
- Do not use custom screens unless you absolutely have to. Expect that the user will want to open various programs on your screen.
- Do not keep public screens locked throughout program runtime. Call UnlockPubScreen() when your program window (re)opens.
- Be smart and careful in your code that handles window iconification and uniconification. Never assume that your program’s window will reopen on the same screen. Do not keep any global pointers or locks that refer to the original screen or its properties.
- Now that windows can jump freely to different screens, caching screen pointers does not make any sense. It never did, actually. Always query the window object using GetAttr() when you need the current screen pointer.
- Use Intuition's GetScreenAttr() or GetScreenAttrs() to find out about screen properties.