Fix window positioning for multi-screen setups, and add config file versioning

With a multi-screen setup, pixel coordinates are expressed relative to the top left of the system's default screen. This means that with two screens where the default is on the right, for example, the x-coordinates of the pixels on the left screen are expressed as negative integers. So we cannot assume that valid window positions are only zero or positive.

Negative positions were being used to represent 'no specific position' as a default. That means that when the windows are created for the first time, we let the operating system decide where to place them. As we should not be using negative positions for this purpose, since they are in fact a valid range of pixel positions, use nullable types instead. The default 'no specific position' is now expressed when the positions are null.

Unfortunately, we still need to handle the special case where the window position is stored as -32000 in the config file. This was the previous default position for non-main windows (timer window, opponent window, and player window). So if the user has already used a previous version of this application, but has not yet opened a non-main window, they will have -32000 stored in the config file.

We obviously do not want to just blindly use this otherwise valid value as it will end up positioning the window far off the screen. To solve this issue, I have added config file versioning in order to handle all legacy config file logic in one place.

We now save a CreatedByVersion string in the config file. With this in place, we can determine which version of the application wrote the config file when we load it. If the version doesn't exist in the config file, we assume it was created prior to version tracking (i.e. prior to the version of the application with these changes that is next released to users). This allows us to change the semantics of config variables in the future and have a mechanism for handling those changes when loading users' legacy config files. We are able to interpret and update users' legacy config files to the current semantics.

With this in place, we can handle the -32000 value by just interpreting it (along with all other negative values) as the default 'no specific position', when we see that it comes from a legacy config file. If it doesn't come from a legacy file, we would instead interpret it as a valid position that has been legitimately set by the user (though you'd have to have a pretty insane screen resolution to get it!).

If we ever need to change these semantics again in the future, we can easily determine how to interpret the loaded config variables by looking at the range between the current version (of the time) and the CreatedByVersion loaded from the config file.

I have also updated the PlayerWindow/OpponentWindow default height logic to be more sensible, and also to be more consistent with the way that TimerWindow default dimensions are implemented. Player and opponent window heights were previously set to zero as a default, and then a bit of logic was used when creating the windows: if height == 0, then use a height of 400 instead. This was a little pointless, and inconsistent with the more sensible way that timer window default dimensions are handled. Unfortunately we cannot change this to be more consistent without breaking legacy config files, where the height may still be stored as zero. We don't want to set the height of a window to zero, so we handle the changed semantics here.