The end is nigh…

OK, so the official Summer of Code coding period has ended, so what better time to sum up the status of my project and the general experience I have had.

Project Status

The last two weeks have been pretty hectic, as I have been trying to make my finished code as complete and polished as possible. Generally, I feel like all the required functionality of the virtual keyboard and keymapper is there, but I am sure that there will still be bugs hiding in there. Here is a summary of the the work I achieved in the last couple weeks:

 

Virtual Keyboard:

  • New special events – added support for submit, cancel, delete, clear, and cursor movement, to add further control to VK users.
  • Added support to preview all keypresses – means that the VK display will show all key presses (not just those with ASCII codes)
  • Proper initialisation – throughout development I had been loading the VK pack the first time the VK was run, because the EventManager was constructed before we knew what screen resolution we were running on. To get round this I added an EventManager::init() method (where the VK pack is loaded), and called it from scummvm_main after the screen had been initialised.
  • Tons of memory-related bug-fixes (thanks to Valgrind!) as well as optimization and cleaning up of drawing code.

 

Keymapper:

  • Remap GUI dialog – which allowed keymaps to be re-configured
  • Stack-based active keymap system – taking inspiration from the CursorManager I realized it made a lot of sense to push and pop keymaps off a stack of active keymaps. Not only would it make it more intuitive for keymap switching, but also gave us the option to inherit key mappings from keymaps lower in the active stack – a very powerful and flexible option.
  • Parent keymap feature – linking into the stack-based keymap selection I made it an option for a Keymap to have a parent keymap. This would allow the automatic mapping algorithm to be more intelligent in assigning keys, considering that the keymap would usually inherit actions from its parent when it was active.
  • HardwareKey types – I realized that in many situations it made sense to say this key is a “shoulder button”, and that this action should be assigned to a shoulder button. So now HardwareKey’s have a type and a preferred action, whereas Action’s have a type and preferred key. Again, this provides us with a lot more flexibility!
  • Refactoring – got rid of redundant KeymapManager class and put its core functionality (saving, loading & automatic mapping) into the Keymap class

The one major thing that I simply did not have time for was proper documentation of all the virtual keyboard and keymapping features. This is something that I will work on over the next few weeks (at a somewhat more leisurely pace! :). I feel that overall I have achieved what was set out for me at the start of the project, and hope that I can do the required work to get my code merged into the trunk sometime soon.

My GSoC experience

Firstly, I would like to say that I have thoroughly enjoyed my summer working with the ScummVM team. I will be the first to say that we didn’t exactly get off on the right foot, and that my participation has been a bit ‘patchy’, but after all is said and done I hope that I have made a valuable contribution to this project! Has been great having Joost as a mentor, was always there to answer my questions and encourage my progress. Was also very helpful to hear Eugene and Max’s opinions when I was unsure about my project’s direction. The only regret I have is that I feel that I could have maybe pushed myself to acheive more if I had gone for a more ambitious project, but then again I would not have wanted it to all end in failure! At the end of the day, I think the GSoC is a wonderful experience and will be returning next year, maybe even for ScummVM (if you’ll take me! 😉 So, thats it for now. Over the coming weeks I will write proper documentation, and continue working towards making my code stable enough for ScummVM. Thank you, and good night!

Latest developments

Time for another quick update on my progress recently. Generally, I think I am still on track with my plan of action that I set out a couple weeks ago.

Virtual Keyboard:

  • Major refactoring of GUI code into a separate VirtualKeyboardGUI class. This meant VirtualKeyboard class only handled the detection of keypresses and the queuing of resulting events.
    • This abstraction should make it easier to modify VK to use ScummVM’s GUI rather than being responsible for its own drawing like present.
  • Display functionality complete – now a virtual keyboard pack can specify a rectangular area that will be used to display the virtual key presses that have occured.
    • This was implemented by firstly creating a KeyPressQueue support class that not only kept track of the queue of KeyPress’s that the VK was generating, but also maintained a string representation of these.
    • Then I added methods to the VirtualKeyboardGUI class to draw this String in the required area. I had to include textbox-like functionality e.g. handling when the string was too big for the area, drawing a caret, etc.

Keymapper:

  • Saving/loading of keymaps to config file is implemented (but not tested extensively and saving of keymaps is not integrated yet)
  • Simple automatic mapping algorithm has been implemented
  • Keymapper class now uses a stack-based implementation for switching between active keymaps.
    • This will make it easier for switching as we can push and pop keymaps onto the active stack (like ScummVM’s CursorManager does)
    • The pushKeymap() method also takes an inherit boolean argument which says whether the Keymapper should use iterate down the active Keymap stack when a mapping for the given key is not found. This should be very powerful feature because it could allow the new keymap to only remap one or two keys, and get the rest of its mappings from the last active map.
  • Started proper testing by integrating Keymapper into SDL backend. Just added method that sets up a simple HardwareKeySet and a simple Keymap.

Next steps:

  • Develop the automatic mapping algorithm, considering the new stack-based implementation of the keymapper. My current thoughts:
    • The automatic mapping algorithm should look at the maps that have already been added, so that it can use HardwareKeys that either have not been mapped yet, or at least have been mapped to a Action with low priority.
    • This could be further improved by defining which keymaps will be parents of other keymaps. Then we only have to check the mappings of the parent Keymaps.
    • In fact, the idea of keymaps having parents, and therefore being arranged in a tree structure, does seem like a good idea.
  • More extensive testing of these new features
  • Keymap dialog

So, finger’s crosses, I should have most of this done by the weekend. That leaves next week to really finish and clean up the code, test thoroughly and write documentation. OK…back to work!

Keymapper coming along nicely…

Thought it was a good time for a quick update. I’ve made a lot of progress on the keymapper since my last update, with most of the infrastructure in place now. Most of the interface to the rest of the system is implemented (in the Keymapper class). The KeymapManager (where the loading/saving and automatic mapping will be done) still needs work, and will probably be quite tricky! Anyway, here is a summary of my major progress and any design decisions I have made since my last post:

  • KeymapManager now uses Domain classes to separate out global and game-specific keymaps – this was inspired by ScummVM’s ConfigManager. Each domain has a default keymap, which incorporates the idea of a “super-global” keymap. Also, this means that a game can provide a specialised version of a global keymap, because keymaps are only requested by name (not domain) and if a keymap of the given name exists in the game-specific domain it is given priority over a global keymap with that name.
  • Keymapper has initGame and cleanupGame methods. The idea here is that these methods need to be called before and after a new game is run. In initGame the keymapper looks at the ConfigManager’s active domain (to obtain the gameid). In cleanupGame the keymapper tells the KeymapManager to free up all the game specific keymaps in has loaded. This should provide support for when we have to return to launcher feature.
  • Where it comes to actually adding keymaps to the Keymapper we have addGlobalKeyMap(name, map) and addGameKeyMap(name, map). All these methods do is register the new Keymap with the KeymapManager (which is where the loading / automatic mapping of the keymap will occur).
  • So the idea is that whenever part of the system needs a specific keymap they will call one of these methods in their initialisation code. Then when they actually want that keymapping to be used they call switchMapping(name).
  • The actual mapping of the keys is done (see Keymapper::mapKey). The key point here is that both KEYUP and KEYDOWN events are mapped, and the mapped event is modified to make sure it correlates with the type of event that prompted it.
  • The instantiation of the Keymapper and the calling of mapKey has been integrated into the DefaultEventManager.

So I am well on track with my schedule at the moment. For the next few days I will go back to working on the Virtual Keyboard, as there are a couple of features that are still needed.

One last thing…thought I’d better let you know that I’m going to stay with my gran up in Scotland from tomorrow till Monday, which means I probably won’t be online much. But, I’ll be taking my laptop and should be able to work without it.

More boring planning…

So its been a while since my last update, and for most of the time I’ve been busy planning the rest of my project. I’ll get on to that later, but first let me sum up exactly where I got to with my coding.

Virtual Keyboard

  • Dragging feature
    • made it possible to drag the keyboard around the screen when part of it that was not a key was clicked
    • also made it snap to the sides of the screen
  • Fixed bug in event delivery
    • found that when many key presses were delivered after keyboard was shut the SCUMM game that I was testing with would ignore the first few keypresses and only register the final one
    • fixed this by implementing a delay in the event manager’s delivery of queued events
  • Handling of GUI and VK displaying at same time
    • before I would unconditionally clear the overlay before displaying the keyboard, but if the GUI had been displaying then bad things would happen once the keyboard was closed
    • to get round this, when the GUI was active I would save the overlays contents when the keyboard was opened
    • then this would be the background to blit the keyboard into, every time it had to be redrawn
    • and when the keyboard was hidden, the original overlay contents would be written back to the overlay
  • Documentation
    • added comments to public interface of classes
    • added explanation of XML file format to VirtualKeyboardParser.h, which will later be added to wiki

After doing this, I started researching the keymapper task, so that I could get a better idea of all the stuff I have left to do. After reading up and asking questions on the mailing list I was ready to come up with a breakdown of my design.

Keymapper breakdown:

I chose to break down the keymapper task into four main classes that I would need to implement.

  • Mapping class:
    • will store details of a particular key mapping and offer simple methods to carry out the mapping
    • will also provide methods to edit the mapping (which will be called by the Edit Mapping GUI dialog)
  • Keymapper class
    • will provide interface to rest of system, and will be accessible via EventManager
    • will store a pointer to the active Mapping class
    • and other state such as the active gameid, etc…
    • will provide method to switch to a different Mapping (which will be called by engines or other parts of system, e.g. main menu dialog)
    • engine will call methods on game start that will allow it to specify game-specific Mappings (and the UserActions they require)
    • backend will call methods (or possibly subclass?) that will allow it to specify which HardwareKey’s are available
  • MappingManager class:
    • will be responsible for managing all the different mappings that are available
    • involves the loading and saving of mappings to the standard ini file
    • will load global mappings on creation, and will load game-specific mappings when prompted by engine calling methods on Keymapper class
    • if no valid game-specific mappings can be loaded from the ini file the automatic mapping algorithm will be run
  • Edit Mapping GUI dialog:
    • will be implemented using the existing GUI toolkit
    • using the descriptions from the UserAction and HardwareKey structs will make the dialog easily understandable
    • the will be a number of label / button pairs
    • each label will contain the UserAction description text
    • each button will contain the mapped HardwareKey description text
    • clicking the button will start an event loop, and the first event that is recognised to have come from a particular HardwareKey will re-assign that HardwareKey to the UserAction in question

Now that I had a good understanding of the second part of my project I came up with a rough TODO list.

TODO list:

Virtual Keyboard

  • prepare a complete virtual keyboard pack
    • waiting on original images from rob (IRC: sanguineh)
  • add textbox to show what user has entered – 2 days
    • maybe a special part of the keyboard image could be marked with a rectangular imagemap area
    • then this area will be filled with text as user clicks keys
    • will then need left/right arrows and backspace keys to alter this text
  • shift key functionality – 2-3 days
    • currently the keyboard only offers functionality of a caps lock key because mode can be changed to caps but then must be switched back to normal
    • should be easy to offer a key that switches the mode but only until another key is pressed, at which point the mode is switched back to the original mode
    • this leads to a separate point – do we require the virtual keyboard to offer functionality of control / alt keys?
    • if so, then shift functionality should probably be done without mode switching but by implementing modifier keys in the keyboard – I think this is the most flexible approach

Keymapper

  • Mapping class – 1-2 days
  • Keymapper class – 3-4 days
  • MappingManager class – 4-5 days
  • Edit Mapping GUI dialog – 2-3 days
  • Integration into system for testing purposes – 2-3 days

The last part of my planning extravaganza was to plan how I would spend my time over the remaining weeks.

Plan of Action

I have decided to get going on the Keymapper class in the next few days, before hopefully coming back to finish the Virtual Keyboard once I have some good images available. 18th July – 23rd July

  • Mapping class – complete
  • Keymapper class – complete
  • MappingManager class – basic outline done

24th July – 28rd July

  • Finish remaining features of Virtual Keyboard

29th July – 8th August

  • Bulk of the MappingManager class
  • Integration with rest of system

8th August – 11th August

  • Edit Mapping GUI Dialog

12 August onwards

  • Cleanup and finishing off code
  • Writing documentation
  • Preparing for final evaluations

Done! Sorry for boring you guys with all my planning, but I guess this benefits us all! Time to get back to the code…

Progress Update

Time for a quick update on the huge progress I have made in the past few days.

Virtual Keyboard Parser

Thanks to Vicent’s great work implementing the XMLParser base class this was a relatively simple task. There was a lot of error handling code to write, and I added a couple of new features to the base class. Apart from that it didn’t take me long at all to have a parser that was parsing the file format that I had earlier settled upon.

Keyboard’s main loop

This involved writing the event loop that would be run while the virtual keyboard was visible. It involved catching all the mouse click events, and passing them to the processClick() method. I also had to ensure the screen was being updated (so that the mouse cursor continued to move) and that EVENT_QUIT events were handled properly (so that closing the window had an effect).

Displaying the keyboard

The main challenge here was implementing keycolor transparency for the keyboard bitmap. To do this I created a subclass of Surface, SurfaceKeyColored, that provided a blit() method. This method would be passed a source Surface and a transparency color, and any pixels in the source Surface that was not the same color as the transparency color, would be copied into the Surface. Once I had this class, I could grab the overlay into an instance of SurfaceKeyColored, then blit the keyboard bitmap’s Surface into it, before copying the SurfaceKeyColored’s pixels back into the overlay. Below are some images demonstrating it in action:

Imagemap testing

After I had the bitmap’s being displayed and the event loop implemented, I could test my image map code that I had written last week. The processClick() method of my VirtualKeyboard class simply had to pass the mouse co-ordinates to the corresponding ImageMap class and it would return the ID string (ie. the target attribute) of the matching area. I created a few image map areas for some keys of my test image in GIMP (making sure to use rectangle and polygon areas), then used the exported HTML in my keyboard pack XML file. After a couple of bugfixes I got the ImageMap working perfectly, proving that my Polygon::contains() method was correct.

Delivery of virtual events

I had written the VirtualKeyboard class to save all the key presses it created into a queue. But, once it was no longer visible it had to insert these key press events into the main event queue. I decided that the VirtualKeyboard should have a pollEvent() method, that would return an event if the keyboard was closed and there was a key press in the queue. Then all I had to do was modify the DefaultEventManager to first poll the VirtualKeyboard, and then poll the backend, but only if the VirtualKeyboard did not return an event. The DefaultEventManager class was also made responsible for showing the virtual keyboard when a special button press was made. While writing this code, it was decided that the VirtualKeyboard class should be instantiated from within the DefaultEventManager class, because they were very closely related.

Next…

Tomorrow I will try to create a complete keyboard pack, with multiple modes and resolutions, together with complete image maps, and event specifications. This will allow me to fully test my current code, as well as test the little bits of code that I am still to write.

XML file format

Before I start work on writing the parser for the virtual keyboard’s XML file, I need to tie down the format of the file. Yesterday I came up with the following as my first idea:

<keyboard modes="normal,caps,symbols1,symbols2">
  <mode name="normal" resolutions="320x200, 640x480">
    <layout resolution="320x200" bitmap="normal_320x200.bmp">
      <map>
        <area shape="rect" coords="84,64,246,146">
          <event type="key" code="97" ascii="A" modifiers="shift" />
        </area>
        <area shape="poly" coords="2,12,25,9,34,8,19,22">
          <event type="mode_switch" name="caps" />
        </area>
        ...
      </map>
    </layout>
    <layout resolution="640x480" bitmap="normal_320x200.bmp">
      ...
    </layout>
  </mode>
  <mode name="caps" resolutions="320x200, 640x480">
    ...
  </mode>
</keyboard>

Here each mode tag refers to a different keyboard display, and each mode has a number of layouts – which provide different resolutions for each mode. Doing it this way – rather than having layout as the parent of mode – was a pretty arbitrary choice, with a slight advantage of being more flexible.

The main flaw I noticed here was that the event tags would have to be repeated for each different layout resolution. If we can assume that all different layout resolutions will contain the same events then we can do this:

<keyboard modes="normal,caps,symbols1,symbols2">
  <mode name="normal" resolutions="320x200, 640x480">
    <event name="A" type="key" code="97" ascii="A" modifiers="shift" />
    <event name="shift" type="mode_switch" name="caps" />
    ...
    <layout resolution="320x200" bitmap="normal_320x200.bmp">
      <map>
        <area shape="rect" coords="84,64,246,146" target="A" />
        <area shape="poly" coords="2,12,25,9,34,8,19,22" target="shift" />
        ...
      </map>
    </layout>
    <layout resolution="640x480" bitmap="normal_320x200.bmp">
      ...
    </layout>
  </mode>
  <mode name="caps" resolutions="320x200, 640x480">
    ...
  </mode>
</keyboard>

Where the target of each area refers to an event tag by its name property. This is nice because it means the map sections now use pure HTML IMGMAP syntax. This means the target property can be specified when using an image map tool, and then the output just pasted into the file without any additions.

Therefore I think this format will be the basis for my first attempt at the parser. However, any comments on it will be much appreciated!

Revised schedule

We are now in the 6th week of the Summer of Code and through a number of circumstances, both in and out of my control, I am pretty behind schedule. My coding in the last few days has shown great promise that I can quickly get back on top of things, but I think it is time for me to lay down a revised schedule for the coming months. The first stage of my schedule is pretty tight – but I have ample time at the moment and am willing to work all the hours in the day to make up for lost time.

Now – July 12th

  • Write all the code for virtual keyboard
  • ALREADY DONE
    • implementation of image map functionality (ie. polygon/rectangle intersection code)
    • Skeletal version of main virtual keyboard class
    • XML file format has been defined
  • TO DO
    • XML parser – a case of extending Vicent’s XML parser to parse my file format = 2 days
    • Keyboard main loop – to handle mouse clicks when keyboard visible and draw the keyboard to the overlay layer = 1-2 days
    • modification of event manager to receive events from keyboard and handle mode switching of keyboard = 2 days
    • integration of virtual keyboard into rest of system = 1-2 days
    • Other stuff – extracting from zip file & creation of example keyboard pack = 1-2 days

July 13th – July 14th

  • Prepare mid-term evaluation material

July 15th – July 20th

  • Clean up of existing code
  • Make sure code is commented clearly
  • Extensive testing of virtual keyboard

July 20th – July 25th

  • Detailed research into keymapping task

The following is slightly vague, due to my lack of knowledge

July 25th – August 2nd

  • Writing of general keymapper interface
  • involves providing the link between engines and backends
  • working out how each is going to tell the keymapper what it needs to know

August 2nd – August 9th

  • Writing of algorithm to automatically map actions to buttons
  • gui to allow user to change these mappings
  • saving of these mappings to ini file

August 10th – August 20th

  • Additional key mapping features

August 20th – Sept 1st

  • prepare for final deadline
  • Lots of testing, code cleanup and documentation

PS – progress report coming tomorrow (including details of XML file format)

Back in the game

Just returned from sunny Barcelona. Had a great time there, and I feel well rejuvenated and ready to continue coding again. In other news, I am writing this post from my university computer labs because my new student flat does not have an internet connection yet. This means I may not be online a lot in the next week but I will be able to get on with coding anyway. In terms of my progress I will first be concentrating on finishing up the code I made for polygonal / rectangle intersections for the imagemap. Sev commented that it would be useful to provide a standardised way for people to reuse this code so I will abstract the intersection stuff away from my imagemap-specific code. After that is done I will move on to the parser for the XML-based virtual keyboard info file. Thanks to Vincent / Tanoku the has developed a base XML parser that I can extend for my own needs. So I will first have to understand his code, tie down the exact format, then write my Parser class to parse the format. I’m very excited to finally be fully concentrating on the project. If my plans go without a hitch I think I should still be on track to have a good amount of code completed by the first evaluation.

Finally started coding

Been a while since I’ve updated my blog, but rest assured my project work has been progressing well. I’ve made tremendous progress in terms of my understanding and ideas for the project, and have even made a substantial start on coding….finally!

Progression of ideas

Since my last post I have gone from understanding the general techniques that my virtual keyboard will utilise, to the details of the project. I have also discussed my progress with Eugene, and he helped me by further explaining his original ideas for the keyboard. Some of the key areas I have looked are discussed below.

Handling of images

Had to look into what code existed to load images. Found that the ImageManager class would do all the hard work, including the loading of images from within a zip archive. The ThemeModern class of the GUI helped me understand how I would use this.

Format of the keyboard’s ini file

I adopted Eugene’s original idea of extended the HTML imagemap format, to give a simple XML file that would encapsulate all the information needed to describe the different resolutions. For example:

<keyboard> <resolution=320xy> <mode=normal>
<image="key_normal.bmp"> <map> ... </map> </mode> ...
</resolution> ... </keyboard>

I will write a very simple, specialised XML parser for parsing this file, and the specific format of it will be tied down at a later date.

Polygon intersection methods

As I needed to allow for polygonal areas in the image map for the keyboard I had to research algorithms for determining whether a point is inside a polygon. This was known as the Point In Polygon problem. There were a number of different algorithms, but the one that seemed to be simple and quick was the ray casting method. This method works by testing how many times a ray starting from the point intersects the edges of the polygon. If this number is odd then the point is inside the polygon.

Idea of having hierarchy of image map areas

After looking into polygonal intersection routines, I thought that my virtual keyboard could run into efficiency issues when it tries to find out which area of a map was clicked, because there would be alot of different areas it could be. This lead me to think that I could arrange all the imagemap areas into a hierarchy based on areas of the keyboard. It would be similar to the Bounding Volume Hierarchy technique that I used when implementing a ray tracer for my Computer Graphics assignment. Whether this will be needed or not will remain to be seen, but the idea is there.

Started coding

I felt that now was a good time to start writing code. I started by:

  • Writing the header file for the VirtualKeyboard class – defining its interface and key methods
  • Writing support classes for the image map areas – including intersection method (that would detect whether a point was inside the area or not)
  • Made a start on writing of simple XML parser for the ini file

I’m off on holiday tomorrow, so I won’t be around for a week. But once i’m back i’ll be able to really crack on with the coding.

Events & Graphics in ScummVM

After my initial research into the virtual keyboard implementation on the PSP port, I thought it was time to start working out how my generalised virtual keyboard would be implemented. This involved me looking further into ScummVM’s event management system, working out how the graphics would be displayed, and thinking about how it will all fit together.

Event Management

I had already discovered that each OSystem had a pollEvent() function that assigned the state of the system’s input device to an Event object. But I needed to extend my knowledge, working out how the game engine came into it. To do this I chose to look at the source code of the Scumm engine. In the main loop of the Scumm engine – ScummEngine::go() – two important things occurred on each iteration:

  • waitForTimer() is called to limit scumm update
  • the scummLoop() is called to update engine

waitForTimer() basically just pauses the thread for a specified time, but as user input may occur in this time it has to handle it. So:

  • waitForTimer() calls parseEvents() every 10 ms.
  • parseEvents() calls EventManager::pollEvent() in a loop until it returns false (ie. no more events)
  • EventManager::pollEvent() just calls OSystem::pollEvent() and also adds record/playback functionality, as well as key repeat functionality
  • for each event returned by the EventManager, parseEvents() sets up engine-specific input state variables

Then from within scummLoop(), processInput() is called. This function sets up the mouseAndKeyboardStat variable which is used by the Verbs part of the engine to execute scripts. So, as the EventManager already handles special input events it makes sense for this class to be responsible for feeding virtual keyboard events back to the game engine. I envisage the EventManager::pollEvent() method including code like this:

result = virtualKbd->pollEvent(event);
if (!result) result = system->pollEvent(event);

Graphical display

In Eugene’s ideas for the virtual keyboard he had recommended that the virtual keyboard should live in the same 16-bit surface as the GUI. This made sense to me, as it should not be mixed up with the game graphics, but I did not really have a proper grasp of how the graphical layers of ScummVM were organised. Therefore I looked at the OSystem interface, and found out that graphics in ScummVM were implemented in three layers: game, overlay and mouse, and it was the backends job to draw these layers to its screen in that order. The OSystem interface provided a method for each of these layers that copies (or blits) a given bitmap into the layer. So for my virtual keyboard implementation I would have to call the OSystem::copyRectToOverlay() function in order to copy the keyboard’s bitmap into the overlay. If I were to implement some sort of roll-over or keypress effects then that would involve additional calls to this function to update the key concerned.

GUI loop

While investigating the way overlay graphics are done, I looked through a lot of the existing ScummVM GUI code. As well as looking at the graphics stuff, I also had a look at how the GUI main loop is carried out. This main loop basically allowed the GUI to process all the user input until all dialogs were closed. It made sense for my virtual keyboard to use a similar method as Eugene’s notes said that it was safe to assume the game engine would be paused when the keyboard was active. What this meant was that while the virtual keyboard was active it would process the mouse clicks, and build up a list of virtual key pressed events. Then once the virtual keyboard is inactive, it will deliver these events to the EventManager via its pollEvent() method (see the code fragment above).

Conclusions

My plans for the virtual keyboard are coming together well. The main concern I have at the moment is whether my assumption of having a separate virtual keyboard class is a good one. I have considered these other approaches:

  • build functionality into base OSystem class – probably not a good idea because it may involve modifying existed back-end implementations.
  • implement as a GUI dialog – makes sense in that its use will be very similar to a GUI dialog. However, probably not a good idea to tie it to the existing GUI implementation, especially as it will use its own configuration files. Although separate from GUI there is nothing stopping us making the keyboard look consistent with the GUI theme.

The obvious next step is to start thinking about the various initialisation files that the virtual keyboard will need, this will include:

  • what extra information needs to be stored in the imagemap file?
  • how will this imagemap file be parsed – using an xml library (e.g. TinyXML) or by writing my own specialised code?
  • ini file – what information is needed in here?

If having rollover effects will be a good feature to include, I will also investigate some efficient way to do this.