SwiftKit Mac v0.3.0b
Since Lion came out RuneScape on the Mac has had a lot of issues. Between v0.1.7b and v0.3.0b you may think not much has happened, but it’s actually quite the contrary. For one, you may notice that version 0.2.0b has been skipped. Not really, v0.2.0b was coded but never released, here is a detailed rundown of everything since Lion came out.
The day Lion was released every Mac user was complaining about the lag. RuneScape was completely unplayable. Many people thought this was a symptom of SwiftKit, but it happened in any browser. Somebody on the RuneScape forum figured out how to use the .jar from the Windows client and mix it with the .jar loader template app to create a playable executable that would open just an applet. This applet was also plagued with problems, one being if you resized the window the game would crash. The upside was that issues from loading RuneScape in a browser/SwiftKit (which also runs in a ‘browser’, technically) were now gone, with the addition of a few others (such as odd behaviour on Software mode, and graphical glitches
At this point it looked like this was going to be it for RuneScape on the Mac, inside this volatile client. I decided to take a look at tracking another application’s window. This was easier said than done, it’s something there was little to no documentation on. Eventually I used AppleScript, which I admit is definitely not the best and most elegant solution but it’s all I could come up with at the time. It did work, but only managed to get me position and size updates after they had been made, they were not live, meaning if you moved the window around the screen the client would only adjust it’s window’s positions after you let go of your mouse. A feature I am quite proud of is a resize window that sat over the client’s window, allowing you to resize the client without crashing (again, this was done with AppleScript, bridging my resize window’s position and size to the applet window’s position and size).
I played with this for a week or so to test it out, it was good for what I had to work with but I wasn’t 100% happy. Just before we planned to release this, Jagex made yet another update to their game, popping out the applet from the game when loaded in a browser, which was now made the gameplay perfect, there was just one problem, having the game in another window was quite annoying, not to mention if you closed the window that spawned it, the spawned applet would close. I decided the client-based version I had created just wasn’t going to cut it, so I scrapped it. This was the version 0.2.0b nobody ever saw.
The SwiftKit Mac project was becoming quite messy. Previously a lot of things were setup in “Interface Builder”, which is a tool that allows you drag buttons, images and other controls onto a canvas to populate your interface, which I consider to be lazy. Since then I have done all my other interfaces (on other projects) in pure code. Doing it this way makes it very easy to make interfaces dynamic, and being able to reuse custom components, the downside being coding things takes about 3x as long as using IB.
SwiftKit was now going to be completely focused around this pop out applet. There was going to be an immense amount of code to make this experience as seamless as possible for the user. Taking this and the messiness of the current state of the projects into account, I decided to recreate everything from scratch, starting with the hardest part, tracking the applet.
My previous method of doing this using AppleScript no longer worked. It would only work from anything launched from a .app bundle. This pop out applet was different, and launched directly from a process instead. If you open the Activity Monitor while the pop out is running, you will see it under the list identified as ‘Java’. I managed to find another way of getting another process’ window position and size, again very undocumented. This was a lot faster than my previous AppleScript implementation, and now I could get another windows’ frame even when it was being dragged around the screen. With this out of the way I found a way to reposition and resize the applet, which allowed me to restore the applet’s previous frame whenever SwiftKit was opened (by default it opens to a set size in the middle of your screen).
This version was looking to be pretty good, but it needed just one more thing. Because the applet is another process none of my shortcut keys would work outside SwiftKit. I had to register all the shortcuts I wanted the applet to access as global, meaning you could use them anywhere on the Mac, even if SwiftKit was in the background and another program was in the foreground. Of course, I didn’t want Command + S (used for screenshots) overriding save functionality in another program, such as Word, so I have to turn them on when either SwiftKit or the applet are in the foreground, and then turn them off when any other program is moved into the foreground.
Obviously there’s a lot more work involved in all of this, compared to me explaining it in a 2 minute blog post. I also work as a full time developer during the day, and coding when I come home is usually not a priority. I will end this post with a reassuring final note, I have tested v0.3.0b on Mountain Lion, and it’s flawless 😉
(RuneScape on the other hand, not so great, it only works in OpenGL mode, although it could be worse)