DisplayManager replaced the Palette tool in RISC OS 3.5, as the video system was reworked to allow for greater colour depth and a move away from a 16 colour palette. Along with the ScreenModes module and Kernel changes, it provided the user interface to select modes in a more user friendly manner. Previously, Palette only allowed modes to be selected using mode numbers. The newer mode selection was based on variable mode selectors, and allowed menus of possible modes to be offered.
When RISC OS 4 was shipped, we enabled a latent option in the DisplayManager menus which allowed the frequency to be selected, as well as the resolution and depth. It was a cheap change which offered the appearance of greater flexibility - it had always been possible to select frequencies, but had never been exposed through the interface.
RISC OS 4 also introduced a fade on mode change, using the gamma tables to change the output levels so that the screen mode change was smoother. This introduced a delay before the DisplayManager changed the mode, which could be annoying. When enabled, the option would fade out, change mode and then face back in from black. The effect was less attractive on some displays because the time taken for the hardware to synchronise itself to the new mode meant that the fade in was not visible - the hardware remained blank whilst the effective display was fading in.
Additionally, with some hardware this change in the gamma tables caused some nasty refresh effects which were worse than just blanking the screen. So by the time Select 1 was released, the option had been disabled.
When it came to Select 3, where video was a greater focus, the menu operation was changed so that the lowest frequencies were at the top of the menu - although the higher frequencies were more likely to be preferred, the other menus were in ascending order, so this made them more obvious. Of course, the frequency mattered a lot more with CRT displays than with the LCD displays that were becoming more common, but at least the change made it more obvious what frequencies were used.
Originally, the DisplayManager would read the entire palette and check the colours used to see whether it should be showing '256 Greyscale' (for example) as the selected mode. As part of the video changes, a flag was introduced to indicate that the mode was greyscale, and so all that was necessary was to check this flag. The flag is set by the Kernel as part of the mode flags which can be returned with SWI OS_ReadModeVariables.
Similarly, as the Kernel had gained functions to encode the mode into a string, this was used to create the string in the input box for DisplayManager. Previously, DisplayManager had constructed the mode string itself, which wasn't as nice.
The video system was finally abstracted sufficiently to allow different displays to be selected. This was a very powerful feature, but I really wanted to be able to also allow multiple displays to be active at once. Lacking in time, I couldn't define such interfaces. Instead I tidied up the single output, controlled for multiple displays to match ViewFinder's operation. This meant that you could select a second display, and the old display hardware would power down, and the new display would power up.
The display selection interface was very simple - single menu offering the a choice of the display hardware that was available. Actually the entire code to handle the display selection was all written and tested in C, and then integrated into the assembler source in the same way that other mixed assembler and C modules were provided.
I also wanted to allow for two displays - for example, running a debugger on one display and the main full screen application on another. However, there just wasn't time to organise that.
One of the first fun things (of those that I remember) that I did on RISC OS itself, and which made it into a release, was the blend of Pinboard's background. The background colour used for the top and bottom of the screen could be configured and they would be interpolated between. This made it very easy to create a prettier background for certain things - I created a small aquarium (which I mentioned in my previous ramble about the PinboardServer) which I used to use on the work machine, and I'm pretty sure I kept for the at least one of the shows.
Initially, the interpolation was based on RGB, but I wanted something a little more interesting, so I added the support for using the HSV colour space instead - which meant that the colours would become a prettier rainbow. I thought it was pretty, anyhow . The addition of the HSV blend did highlight problems with ColourTrans, though - invalid parameters to the conversion calls could cause aborts which wasn't particularly friendly as they were meant to be just numbers.
I had considered the possibility of vertical interpolation, so that the left and right were given different colours, but one of the reasons for using the top-to-bottom blend was that the rendering would be pretty fast - every section could be drawn as a solid horizontal line once the correct colour translation was selected, and these would be fast. Vertical rendering would be much slower, as it would have been many thin vertical lines across the screen.
If the acceleration interfaces had got there, the correct thing to do would have been to use a interpolated triangle plotting function to handle all these operations, producing a fast render processed by the accelerator (with optional software implementation, of course).
Background image rendering
Once ImageFileRender had stabilised it was obvious that it should be used wherever images were rendered. The Pinboard background was an obvious choice, as it would allow the background image to be rendered whatever type it was. Despite the fact that such operations generally required conversion from another format to sprite, this was still quite a nice thing to do - and of course it also meant that there was the possibility of using a DrawFile or !ArtWorks file on the background (or any other filetypes that were subsequently added).
The original aim for ImageFileRender had been that there would be a 'tile' rendering operation, which would fill the graphics rectangle. However, this was not implemented - partly because I had not got around to going through the maths required for it, and partly because it would be of limited use. As a result, Pinboard still tiled everything itself, which meant multiple calls to the ImageFileRender module. Fortunately, proxied conversions were cached so that they wouldn't be performed multiple times, but this still left quite a few slow operations.
Pinboard had two major paths for rendering - JPEG and Sprite. The Sprite rendering had been around for some time, but the JPEG was newer. The JPEG handling code was replaced with ImageFileRender, as it was the most isolated - the Sprite handler remained as it was, because it was still going to be the most common form, and didn't need to go through the new ImageFileRender interface.
During the changes, I noticed that the algorithms differed for tiled plotting. Sprites would plot tiled from the top left, whereas JPEGs (and therefore the new ImageFileRender formats) would be tiled from the bottom left. Fortunately it was pretty easy to ensure that they both tiled from the top left. It could have been optional, I guess, but I don't think that it ever occurred to me to make it so.
When the support arrived for accelerated tiled sprite plotting, Pinboard was updated to use that as well, which would make it significantly faster if the interface was implemented by the graphics driver. There were also amusing off-by-one mistakes which had to be fixed in the rendering of the sprites when used in EX0 EY0 modes, but they were quite simple.
The configuration for Pinboard, since RISC OS 4, had been part of the main !Configure application. Because of this move, it was less obvious how you could change its options.
There was a possibility of changing the behaviour so that some of the configuration options were still present in the Pinboard itself by enabling a build option. However, those options weren't complete.
Instead, I wanted to make a more general way of opening the options. A new switch was added to the top level !CPIShell invocation which the !Configure application used to allow the automatic opening of nested plug ins. This meant that the Pinboard could have a 'Configure...' option on its menu which merely ran a command to open the right !Configure plug in.
For RISC OS 4, we added an option to toggle the Pinboard to the front of the screen. This was triggered by sending (or broadcasting) a message to the Pinboard requesting that it move to the front, the back, toggle or you could just request the current state.
The Wimp had been updated at the same time so that it issued messages when then pointer rested at the edge of the screen. The messages for the edge of the screen were intended to reduce the work needed to perform special actions. A small application could be written to cause an action when the pointer was at the edge of the screen, such as issuing the 'toggle background' message.
Similarly, this also allowed a 'view background' icon application to be created. We never built one ourselves, but it could be provided by third parties.
Unfortunately this 'toggle to front' behaviour had a bad effect on the handling of the windows in the WindowManager - as discussed in the 'buggy bits' ramble. With this fixed, though, it was also necessary to change the behaviour of the Pinboard window so that when it was toggled to the front it also stopped being a background window. Fortunately that's pretty easy using the Nested Window variants of SWI Wimp_OpenWindow.
The Pinboard had always covered the entire background, excluding the IconBar. This made it useful to users (you couldn't accidentally pin an item below the IconBar) and easy to position (as the IconBar size was known). I wanted to change that. At the very least, I wanted an IconBar that could completely minimise off the screen, only appearing when needed. As such it would be necessary to change the size of the IconBar itself.
The first steps towards doing this - or more specifically, the step which involved removing a hard-coded constant from Pinboard - was to make the height of the IconBar dynamic. Instead of being just a fixed number in the Pinboard module, the height of the IconBar was exposed by the Wimp through a SWI Wimp_ReadSysInfo call. Bizarrely, as I look at the released documentation now, I think the call was documented as 'for internal use'. I'm not entirely sure why - it's possible it also exposed some other implementation specific details.
Eventually it was my intention that the IconBar itself be completely dynamic. Although the 'window' might continue to exist, the actual representation of the icons placed on the IconBar would be controlled by plug-in components that could present icons in different ways. I had prototypes working which could place the icons in different windows in different locations on the screen.
It should have been relatively easy, once an interface had been properly finalised, to move the IconBar around the screen through these extensions, rather than forcing it to be at the bottom of the screen. Moving it to the top, or the sides should have been relatively easy. Similarly, duplicating the IconBar in a different location (such that there were multiple copies) would have been a relatively simple operation. This might have been useful for dual screen displays when they became available.
The initial implementation of the IconBar abstraction allowed the icons to be separated by their type - specifically by their priority and edge to which they were attached. The IconBar priorities had been defined in the documentation, which further clarification organising the priorities into groups. This made it easier to separate the filing systems from the utilities or accelerators, if that was required. An interface that placed the drives on one edge, and the applications on another, was trivial to set up in the prototype. It would not have been a huge leap to tie accelerators to icons, if that was wanted by some third party.
The prototype was left unfinished, and in the few minutes I spent playing with it to try to get a screenshot, I couldn't seem to make any of it work. Ah-ha... it doesn't handle screen resizes, so it's fixed for my old screen width which is a bit tacky. It's not really worth taking a screenshot as it just shows icons in a window. You could click on them and they do the right thing. Messages to the icon in its new location didn't quite work right - they wouldn't be received by the right application. But that's the thing about a prototype - it doesn't work like the real thing would .
Back when we were doing RISC OS 4, we had a few components which were supplied by 3rd parties. These components needed to have some form of acknowledgements of their source. Whilst it was common to do so on the modules list, this was not particularly structured and didn't allow for any additional information. Plus there was the problem that it was necessary to access it from the command line, rather than through a desktop interface.
A new service was created to allow these acknowledgements to be collected for presentation, and the TaskManager was updated to request and display them. The acknowledgements window allowed many components to fulfil their license requirements that the authorship be asserted. I don't remember there being any other use of it by any component other than those supplied with the OS, though.
Shutdown failure warnings
With RISC OS 4 there was the advent of a new, larger, disc format which would potentially cache more data. It was also seen to buffer more data as well, which was an issue for some operations. If the system failed whilst filesystem writes were in progress, this would most likely cause partial data to be written. FileCore is not very resilient in the face of corrupted data.
Many users were still very much in the mindset that the system could be turned off without being shutdown properly and this would be just fine. In some cases, it was even said by them that this was because RISC OS was more reliable than Windows systems and it was safe to do so all the time. Given the development of Windows at the time (Windows '98 and soon after ME and 2000), there is some degree of truth to that, but not to the extent that many users cited. In truth, I believe that RISC OS' lack of aggressive buffering meant that most of the time things were safer.
With the addition of larger directories and disc maps, the likelihood of a partial write - from which FileCore was unable to recover - was greater. The number of image filing systems which were in use was increasing, particularly for extended filesystems such as !raFS (which provided longer filenames for those that didn't use the newer discs or transferred to older systems), and archive filesystems like !TBAFS and the longstanding !Compression and !SparkFS. These were inherently cached and buffered (unless they explicitly requested not to be - which would generally make the performance significantly worse), and they themselves relied on the back end filesystem for their storage.
Write buffering was implemented on some ATA devices, which also required time to ensure the data reached the disc. We had received warnings from a filesystem author that data loss was likely unless a short delay was inserted between the shutdown and reset operations.
All these factors were an influence in adding a flag to the NVRAM state to indicate that the system had not been shut down properly. The NVRAM already recorded a shutdown state which indicated that the system had been forcibly shutdown due to power loss, which dated from the portable system. Extending this, and the message which was generated on system start up, to include a state for 'system was shut down uncleanly', was pretty simple.
The system could also be configured to perform an automatic disc check on filesystems if the flag was found to be set during boot up. Whilst this was possible, the time taken for the check was large, so it is unlikely that this option would have been used by people. Instead of the built in disc check it was also possible to use tools like Sergio Monesi's fsck (despite the fact that it wasn't updated for the newer disc formats), or David Ruck's !DiscKnight, through a configuration option.
Even the warning, though, received a lot of negative feedback - to the point of some users producing tools which would ensure that the message was always disabled. I guess they're entitled to that, but the warning still stood - it hadn't been safe to just power off the system for quite some time and ignoring that fact was in their own hands.
The shutdown itself was tidied up through a few iterations of the OS. One of the very first things that I added to TaskManager for RISC OS 4 was to change its behaviour so that it was possible to prevent the system being unceremoniously shutdown if you accidentally pressed Shift-Ctrl-F12 rather than plain Ctrl-F12 (open TaskWindow) or Shift-F12 (toggle IconBar to front). Instead of just shutting down immediately, a dialogue would ask you to confirm the shutdown or cancel. This saved a few frustrating instances (at least for me) when the wrong key had been pressed!
The shutdown dialogue accepted key presses, so you could shut down the machine quickly with Shift-Ctrl-F12 then 'S' if you wanted. Or cancel with Escape.
Usually, once the system had been shutdown, you would be left with a single dialogue which said it was safe to power off, or a button to restart. However, it was possible to press F12 because TaskManager was still running. I disabled this, as the system shouldn't be able to launch new tasks without restarting. It was still possible to press Shift-Ctrl-F12 again to be dropped to a command prompt outside the desktop (TaskManager itself would exit on that key press).
The start up banner had been changed so that it was a full sprite to
introduce the system whilst booting, and so the same was done for the
shutdown dialogue - instead of just being a plain window, it had a
faded version of the start up banner. Thinking about it now,
the correct way to do this in the modern system would be to actually
use the same banner with a '
T0,000000' validation to
tint towards black - that would have saved a few Kilobytes.
Additionally, the background was set to solid black so that the system looked more obviously shutdown, and less harsh than the light grey it had previously been.
One mildly amusing part of the shutdown process was that the TaskManager would issue a *Shutdown despite the fact that this invokes the CLI and could therefore spin up one of the drives that had already been shutdown.
Somewhere along the way - I forget where - I removed the 'Exit' option entirely from the TaskManager menu. Essentially this was the same reason that the Shutdown option was reworked - you don't want to make it easy to exit right out of the desktop losing all your work. Although option was removed, it was always possible to exit by pressing Shift-Ctrl-F12 from the shutdown screen, as mentioned above. And in any case, you so rarely actually wanted to exit to a command prompt. Even whilst developing the system, you generally want to reboot rather than do that, as it's cleaner.
To make it easier to reboot the machine, I added an option for 'Reboot' to the shutdown dialogue, so that it was possible to automatically cause a restart once everything had shut down. This was mirrored by a change to the SWI TaskManager_Shutdown, with a new flag which indicated that we should reboot as well. This was particularly important for the !InetSetup which - in defiance of all logic - would just call SWI OS_Reset if you reconfigured the interfaces. Absolutely baffling. !InetSetup was updated so that it called the SWI TaskManager_Shutdown with the reboot flag set, so that the system restarted cleanly.
Later, as part of the work towards portable devices, the 'Off' button
was added to allow the system to power down after being shut down.
This was greyed out when the system did not support it. It was easy
enough to detect that the option was available - if the Portable
module was present, we can. Additionally, if the system claims to be
a HAL system and has support for power control (an
SWI OS_ReadSysInfo parameter), it can be shut down by that
mechanism - calling SWI OS_Reset with
R0 set to the word value
In my opinion, power control shouldn't be managed by the Kernel, and the SWI OS_Reset &0FF interface, though cute, wasn't really right. An interface had already been defined and was in use (albeit not actively by a modern OS version) in the Portable module, so it is better to use that where it exists. Better defined and more flexibly where possible, but retain the principles as they already exist. However, Castle wanted to do everything hardware related through the HAL, rather than defining calls through modules which implemented the access. Different way of looking at things, but it doesn't fit with the principles of modularity I was following, so wasn't the way I was taking things.
TaskManager shows a list of a number of 'system' dynamic areas, such as the RAM disc, stacks, video memory, system sprite area, etc. These areas were all originally controlled by the Kernel, back in early RISC OS days, and had slowly migrated towards being just like any other dynamic areas. Internally, these areas were mostly identical to the regular areas in any case. As part of the drive toward greater modularity and maintainability, many of the dynamic areas were moved from the Kernel's control to the relevant module's control.
Instead of the RAM disc being handled in the Kernel (with horrible collusion with FileCore) the dynamic area's support moved to RAMFS. This meant that RAMFS also became permanently resident, rather than being reinitialised by the Kernel when the dynamic area changed in size. Whilst the effect was nice - having a module only when needed - the fact that the Kernel managed it, and the excitingness that was caused by starting and killing modules during dynamic area resizes, meant that I didn't think it reasonable to keep that way. Really the way that Kernel managed the RAM disc was quite awful and it was nice to see the back of it.
SpriteUtils gained control of the System Sprite pool, which meant that killing the module removed all System Sprite pool support, and the dynamic area with it.
FontManager had control of the Font dynamic area. Again, this made it far easier to manage upgrades to the FontManager and, in any case, the format of the dynamic area would not remain fixed between versions so you could not be guaranteed to retain its content.
The Screen area was obsolete - with video abstraction it made no sense for there to be a single screen area, nor any sense for anyone other than the video system to control it. When multiple drivers were present there would be multiple areas, and that was just fine - but no system Screen area was needed.
The cursor/sound and system area - a strange blob of an area which had previously been grouped together because ... well, they just were - no longer had any place in handling by the Kernel, and in any case wasn't a real dynamic area. The TaskManager module just 'knew' that the area existed and included a section in the display for it . Cursor was managed by the video system, Sound was managed by the SoundDMA module (or others if it was replaced), and the system stacks area ... that became a real dynamic area instead.
All of these changes meant that the TaskManager itself couldn't display these dynamic areas. System Sprites, RAM disc and Fonts were retained, but the Screen area was just dropped entirely, as it has no meaning. Where the areas could come and go, the icons in the window would grey out when they were not relevant. It's possible that they should just have been enumerated like any other area in the regular Dynamic Area section, but they did tend to be thought of as more important, and significant changes to the area would inevitably cause users to complain.
There were, however, some changes to the dynamic area system that needed to be exposed. The video area, for example, was useful to be able to see how much space was set aside. However, as the area was itself a map on to hardware pages, it wasn't reasonable to show it as either the red (fixed sized area) or green (changeable area) - both of which indicated that they were real memory. I chose to add a blue bar for 'hardware areas' which allowed them to show their state whilst still appearing as different to the regular areas.
I had considered moving such areas to a new section in the display, but that seemed like a reasonable amount of work for little gain. In any case, hardware mapped areas also had the option to set a "don't display" flag to indicate that they did no want to be shown to the user. This was intended for areas that had little meaning, such as hardware mapped registers and the like.
The size of the dynamic areas (and all the other areas as well) had always been displayed in 'K', which looked fine but with larger applications and dynamic areas in the system, it seemed obvious to introduce the a 'M' unit instead. Initially I made this start at about 1 megabyte, but that was too difficult to measure when you were trying to drag bars around. Changing to 4 megabytes still didn't look right, so I settled on 16 megabytes as the transition - at that point the logarithmic bar meant that you couldn't accurately drag bars to useful kilobyte sizes really, so it wasn't as important.
Around the same time, the numbers were also given commas to separate them so that where there were big numbers they were easier to read. We even read the relevant values from the Territory module if it had them, defaulting to ',' every 3 characters from the end if the Territory module wasn't present, or didn't support the symbol sequence. Shouldn't be so impressed by that I guess, but the lack of general internationalisation across the system was a bit sad so even a nod in that direction was good to see.
One of the 'features' that I tried out in the TaskManager, Filer,
Filer_Action and Free displays (possibly others too - I don't remember)
was to change the unit labels beside operations. Instead of labelling
everything as '
xK', they would be labelled as
xKi'. Wow, yes, I inserted the letter 'i'.
Essentially, all the measurements that we present are actually in Kibibytes, Mebibytes, and so on, which are multiples of 1024, rather than the SI defined multiples of 1000 which 'Kilo', 'Mega' and other prefixes, indicate. Thus the change meant that the labels shown were actually correct for the size of the objects.
The downsides to this are that it looks weird, and you have to actually explain this to people - who look at you as if you've gone potty and then say 'call it a megabyte'. The additional issue is that you feel like an idiot saying 'Kibibyte' or 'Mebibyte'. The prototype, with the option to change the labelling enabled, was sent to a number of testers and received a very strong response that it was not liked.
So the option got turned off - it would have been easy to turn on at compile time in the future on the components that needed it, but in general I think people just didn't care for the correctness.
The Free module isn't a large module, but it is one of those that you forget is an application itself. It has a simple task - to display the free space available on a disc. Not complicated and it does a pretty good job. It was, however, a reason that machines used to crash, which is kind of amusing really. Back in RISC OS 3.1 days, Chris Johns and I independently discovered that leaving short disc names would cause the machine to crash. The problem was that in Free it didn't allocate space properly for the disc name, so a 4 character disc name would overflow its buffer and cause bad things to happen.
Amusing though that was, Free itself isn't particularly complicated - and so there's not a lot that should be done with it. There were a bunch of changes that tried to get sensible results when the filing system didn't return free space sizes that made sense. If the 'used' or 'free' space was larger than the 'total', there was clearly something wrong. To try to prevent the display showing silly values, I updated the code to include '?' displays instead of actual numbers.
There was the units change that I mentioned above - I tried out the
Mi' and so on, to see what they looked like
as part of the TaskManager change. I also tried out using SI units properly -
instead of using 1024 as the factor, I added code that would use 1000 instead.
This was slightly more complex as it wasn't just simple shifts, but not all that hard.
The numbers being reported differently just didn't seem right either. I wasn't
convinced, and the option (like the use of Kibibytes) was left disabled.
More usefully, I added support for free space on a path, rather than a disc. Instead of querying a filing system's free space entry point (which wasn't particularly flexible), you could specify a path and it would show the free space used by the disc on that path. The space might differ from that shown for the parent disc because of image filesystems, which is where I felt it would be quite useful. I'm not sure if it was ever used though - I just can't remember much about it.
I had plans to make the Free display prettier, utilising the DrawChart module that Ian Jeffray had written. Being able to render a little pie chart would have been quite nice, and made a nice option for the display. Sometimes a different representation makes things clearer. Sometimes, of course, it's just prettier . The DrawChart work was placed on hold whilst the system was being updated for 32 bit and never returned to. Oh well.