This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Fullscreen in VisualWorks
Feed Title: Michael Lucas-Smith
Feed URL: http://www.michaellucassmith.com/site.atom
Feed Description: Smalltalk and my misinterpretations of life
About two weeks ago there was a discussion about how to make a window fullscreen in VisualWorks. Fullscreen as in, over the top of the task bar and with no borders or decorations, title bar, etc.
The answers were unconvincing, ranging from "Sorry" to "Use SDL to draw directly to a full screen mode palette". Neither of those options appealed to me and since I've been making a slide show presentation program using WithStyle in my spare time for Smalltalk Solutions (I'll be using it to present!) I wanted to be able to run it full screen.
It dawned on me today that I didn't have to make it "full screen", I just had to size it to be the whole screen size, be on top and have no decorations. This, it turns out, is quite simple to do!
First of all, we need to hack how windows are opened. There are already a kind of window that are (a) on top and (b) have no decorations - they're called popups. Yes, menus! They use a TransparentWindow in a most perculiar way. What we want is a blend of ApplicationWindow behaviour and popup behaviour.
Amazingly, this can be achieved by doing only two things!
Make an override ApplicationWindow>>openIn:withType:
This is where the fun begins. Normally, when opening a window, the type is passed in from the UIBuilder which hard codes it based on its opening type in your window spec. If we change the type to be #popUp, then the window will open itself as a popup. The problem is, there's no easy way to hack in to this stuff and say "Hey you, open as a popUp". My attempts at changing a window in to a popup after the fact were met with strong resistant to any kind of useful result.
So, in our override, we check to see if we have a type:
Now, if the window has a type, it won't override it with #normal, it'll leave it how we set it.
Set the windowType to what we want, in this case #popUp, in postBuildWith:
In our ApplicationModel, we implement the method postBuildWith: aBuilder and in there we set the window type like so:
super postBuildWith: aBuilder.
aBuilder window windowType: #popUp
Now if you open the window, it'll be on top and have no decorations. Unfortunately, inspecting it has a tendency to make it magically close itself - as it thinks its a menu, not just a popup, and thus if you click somewhere else the window should go away. This isn't a huge problem, since the window is about to fill the entire screen.
Now we just need to make sure the window opens with the right coordinates. In our windowSpec, set the window to open at custom coordinates. Set it's initial X and Y to be 0 and 0 so that it's in the top-left of the screen.
Next, implement #windowSpec on the instance side so that we can change its values about to match the size of the screen. Unfortunately this isn't anywhere near as nice as it could be.. but here we go anyway:
I believe that when opening a window, the windowSpec is picked up from the instance side before the class side. If I'm wrong, then open the window from the instance side instead of the class side to make sure it uses the instance windowSpec method, eg: MyWindow new open instead of MyWindow open.
One important note: You should give your users some way to close your window! A developer can use the middle-click to get up the window options or you could alt-tab out of it, but a user doesn't know these tricks.
Draw backs: It seems that VisualWorks is immune to noticing that the screen resolution has changed. A call to getScreenDimensions renders you with the resolution the screen was in when VW opened up, not as it is now. This is an annoying flaw, as during a presentation I'm usually changing the screen resolution - I have to close VW down and open it up again for it to change with the operating system. (Yes, you can poke Screen default bounds to the new values, but the primitive won't give you the new values!)