WinRTJournal

From Qt Wiki
Jump to navigation Jump to search
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

WinRT Port Journal

This page offers a place for thoughts, status reports and current issues connected with the Windows Runtime port of Qt (non desktop Windows (Phone) 8 applications). Feel free to add your topic and give some insight to your work.


Content

2013-03-19 - Maurice Kalinowski - Frameworks

Two weeks ago I had the chance to look at some parts of the Windows Runtime port again and now I have some time to write about the outcome. One of the tedious items when working on the port is that all applications have to be "pre-packaged" to be run on the host system. As this is not really a cross-compile environment, where you need to deploy an application and its dependees to a device, it feels weird. On the other hand it reflects the real world scenario pretty well, which helps you as an app developer so that you do not forget to put items into the final package. So right now the test build needs to look like this:

  • App.exe
  • AppManifest.XML
  • QtCore5d.dll
  • Platform plugin…

That implies that you need to copy Qt every time you want to test something. While this is not a problem for an application developer, who copies Qt once, doing that while developing on Qt is time consuming and error-prone. Browsing through the documentation I found the following option to be interesting: Framework

There is not much documentation about it, but what you basically can do is to create a "Framework bundle package" and install that. Applications can then specify in their manifest that they depend on it like documented here

There is no real information available how we can deploy that to a store, but what it basically would provide is something similar to Ministro on Android, meaning a Qt delivery package, which only needs to be downloaded once. You can check on your system, which frameworks are installed by calling "Get-AppXPackage" on the Windows Power Shell. For each package there is a section called "IsFramework". Parsing through that you will figure out that only the C-runtime is deployed currently as a framework, which proves that there is no documentation for good reason.

First let me describe how you can create a framework and how you depend on it before I will talk about the problems.

To prepare packaging you will need a certificate to sign your framework, you create it like that (in an Admin shell[[Image:|Image:]]):

 MakeCert /n "CN=QtProject, O=QtProject, L=Berlin, S=Berlin, C=Germany" /r /h 0 /eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /e 06/06/2013 /sv qtkey.pvk qtkey.cer

Write down the company specification, you will need it again at a later step. Now let's create the pfx file, again you need to be admin:

Pvk2Pfx /pvk qtkey.pvk /pi <password> /spc qtkey.cer /pfx qtkey.pfx /po <password><code>

<password> specifies the password you gave to the certificate in the first step.
Following we will create the framework bundle and install it to the system:

# Move all files you need to a directory where you do the packaging
# Create your ApplicationManifest.xml file and remember to specify the same company details as in the certificate above. Otherwise signing will fail!
# Create an framework package:

makeappx pack /d package /h SHA256 /p qt5.appx

  1. Sign the package:
    SignTool sign /a /v /fd SHA256 /f qtkey.pfx /p <password> qt5.appx<code>
    # Add yourself to the trusted area, otherwise Windows does not allow to side load the framework:
    
    Certutil -addStore TrustedPeople qtkey.cer
  2. Finally install the package to the system: Add-AppxPackage .5.appx

So, we have Qt5 installed as a framework, now what? To make use of that in the application, your application needs to specify Qt as a dependency in the manifest. Please note that you have to specify the minimum version correctly, you cannot just depend on Qt5 in general. In case you want to update the Qt5 package you must update the Qt Version number in the manifest. Windows does not allow to just exchange the package! Afterwards call makeappx/SignTool/Add-Appxpackage as described above. As you specified the minimum version in your application, it will automatically use that.

That is already the first limitation when working with frameworks. In case you remove the application, Qt will be deleted as well. As soon as no application depends on a framework, it is gone. Luckily the install steps are the same for first install and update install. Hence you will not notice this fact most of the time.

Also note that compared to application packages you cannot use "-Register". You have to fully package, sign and install Qt, there is no development version or such. However, debugging into the framework works.

So there are already a lot of steps required to use Qt as a framework, but still we are in a scenario we wanted to have. Exchanging Qt is simple and we could run the test apps against that without requiring to reinstall them all the time. Let us now go into further downsides of the frameworks:

What I have been curious about is how you parse the content of a framework. To summarize: you don't! You can only take what is inside the root directory and then you can also have libraries there only. Those libraries are then added to the resolving order for dependencies. So, if your app bundle depends on the Qt5 framework, when you launch your app the system will figure it requires for instance Qt5Core. After not finding it in the app bundle, it checks the Qt5 framework, locates it in the root folder and resolves it. For libraries everything is fine. But what about plugins? You cannot specify to search inside "platforms" inside the Qt5 framework.

What you could consider is frameworks for plugins. Then your app manifest could specify the plugins to use: "jpeg image handler, sql database, winrt platform plugin". It could actually simplify deployment, but it would cause troubles for startup times etc. Remember that all dependencies are in the root directory, either directory or mapped. So if the plugins are scanned it scans through all dlls in that directory including Qt libraries, different plugins and fitting plugins.

So you could still bundle the plugins inside the application package and have the Qt libraries inside the framework. This might work as long as we assume there is no behavior difference between different versions, nor compatibility breaks. Also, it does not help in our initial problem, meaning to speed up Qt development itself.

The result of this far too long entry? Frameworks seem to be an interesting approach, but they do not fulfill our needs for development on Qt, neither for application developers using Qt. At least right now, documentation is lacking, public information is basically non-existent. Maybe Microsoft still experiments with it…

2013-03-14- Oliver Wolff - Handling keys the "WinRT way"

After making Wiggly wiggle on my Windows 8 machine the first issue which came clear was that keyboard input does not work at all in the port's current state. The initial commit barely did any handling of the pressed keys and just created basic key events which were sent using QWindowSystemInterface. Unfortunately this was not event enough to get some text into the line edit from the example above. Using the desktop Windows implementation as a base for the work seemed to be a good idea so that was the starting point for the new key mapper. Unfortunately Microsoft decided to remove some quite important functions from the WinRT API (e.g. GetKeyboardState, GetKeyState, MapVirtualKey, ToUnicode, GetKeyboardLayout for example). Some of these can be worked around quite easily. The keyboard state for example can be kept in sync manually every time a key event occurs. On the other hand functions which convert virtual key and scancode to the actual unicode character are not as easy to replace. As the outcome of these functions is tightly coupled to the current keyboard layout mapping the key combinations to the resulting keys is tedious if not impossible. Even with a function to obtain the current keyboard layout the actual key mapping effort would be huge. All in all we have to find a way, to map the pressed keys to an actual character in order to have proper text input. I looked for replacements in the API but could not find any so more research has to be done there.