diff --git a/_start.qml b/_start.qml
index 6b53ab9..121f608 100644
--- a/_start.qml
+++ b/_start.qml
@@ -2,6 +2,8 @@ import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 2.5
+import net.asivery.AppLoad 1.0
+
Window {
visible: true
title: qsTr("AppLoad - PC emulator")
@@ -30,7 +32,24 @@ Window {
anchors.centerIn: parent
- onLoaded: loader.item.visible = true
+ onLoaded: {
+ loader.item.visible = true;
+ loader.item.virtualKeyboardRef = keyboardLoader;
+ }
+ }
+ }
+ Loader {
+ property var layout: null
+ property var config: null
+ id: keyboardLoader
+ source: "qrc:/appload/qml/virtualKeyboard/Keyboard.qml"
+ active: false
+ width: parent.width
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ onLoaded: () => {
+ keyboardLoader.item.rebuildKeyboard(keyboardLoader.layout, keyboardLoader.config);
}
}
}
diff --git a/appload.pro b/appload.pro
index 4c8e16d..086a18f 100644
--- a/appload.pro
+++ b/appload.pro
@@ -4,9 +4,11 @@ TARGET = appload
TEMPLATE = app
SOURCES += src/main.cpp src/management.cpp src/AppLoad.cpp src/AppLoadCoordinator.cpp src/library.cpp src/libraryexternals.cpp \
- src/qtfb/fbmanagement.cpp src/qtfb/FBController.cpp
+ src/qtfb/fbmanagement.cpp src/qtfb/FBController.cpp \
+ src/keyboard/layout.cpp
HEADERS += src/AppLoad.h src/AppLoadCoordinator.h src/library.h src/AppLibrary.h \
- src/qtfb/FBController.h src/qtfb/fbmanagement.h src/Launcher.h
+ src/qtfb/FBController.h src/qtfb/fbmanagement.h \
+ src/keyboard/layout.h src/Launcher.h
RESOURCES += resources/resources.qrc
diff --git a/resources/icons/keyboard.svg b/resources/icons/keyboard.svg
new file mode 100644
index 0000000..08dcada
--- /dev/null
+++ b/resources/icons/keyboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/keyboard/backspace.png b/resources/keyboard/backspace.png
new file mode 100644
index 0000000..2bc3dc3
Binary files /dev/null and b/resources/keyboard/backspace.png differ
diff --git a/resources/keyboard/default.layout.json b/resources/keyboard/default.layout.json
new file mode 100644
index 0000000..314bb76
--- /dev/null
+++ b/resources/keyboard/default.layout.json
@@ -0,0 +1,78 @@
+[
+ [
+ ["esc", 27, "", 0],
+ [">", 62, "<", 60],
+ ["|", 124, "&", 38],
+ ["!", 33, "?", 63],
+ ["\"", 34, "$", 36],
+ ["'", 39, "`", 96],
+ ["_", 95, "@", 64],
+ ["=", 61, "~", 126],
+ ["/", 47, "\\", 92],
+ ["*", 42, "del", 127],
+ [":backspace", 128, "", 0]
+ ],
+ [
+ [":tab", 9, "", 0],
+ ["1", 49, "+", 43],
+ ["2", 50, "^", 94],
+ ["3", 51, "#", 35],
+ ["4", 52, "%", 37],
+ ["5", 53, "(", 40],
+ ["6", 54, ")", 41],
+ ["7", 55, "[", 91],
+ ["8", 56, "]", 93],
+ ["9", 57, "{", 123],
+ ["0", 48, "}", 125]
+ ],
+ [
+ ["q", 81, "", 0],
+ ["w", 87, "", 0],
+ ["e", 69, "", 0],
+ ["r", 82, "", 0],
+ ["t", 84, "", 0],
+ ["y", 89, "", 0],
+ ["u", 85, "", 0],
+ ["i", 73, "", 0],
+ ["o", 79, "", 0],
+ ["p", 80, "", 0],
+ [":enter", 13, "", 0]
+ ],
+ [
+ ["a", 65, "", 0],
+ ["s", 83, "", 0],
+ ["d", 68, "", 0],
+ ["f", 70, "", 0],
+ ["g", 71, "", 0],
+ ["h", 72, "", 0],
+ ["j", 74, "", 0],
+ ["k", 75, "", 0],
+ ["l", 76, "", 0],
+ [":", 58, "", 0],
+ ["pgup", 129, "home", 135]
+ ],
+ [
+ [":shift", 1048576, "", 0],
+ ["z", 90, "", 0],
+ ["x", 88, "", 0],
+ ["c", 67, "", 0],
+ ["v", 86, "", 0],
+ ["b", 66, "", 0],
+ ["n", 78, "", 0],
+ ["m", 77, "", 0],
+ [";", 59, "", 0],
+ [":up", 132, "", 0],
+ ["pgdn", 130, "end", 136]
+ ],
+ [
+ ["ctrl", 2097152, "", 0],
+ ["alt", 4194304, "", 0],
+ ["-", 45, "", 0],
+ [",", 44, "", 0],
+ [" ", 32, "", 0, 3],
+ [".", 46, "", 0],
+ [":left", 133, "", 0],
+ [":down", 131, "", 0],
+ [":right", 134, "", 0]
+ ]
+]
\ No newline at end of file
diff --git a/resources/keyboard/down.png b/resources/keyboard/down.png
new file mode 100644
index 0000000..8ac3a8b
Binary files /dev/null and b/resources/keyboard/down.png differ
diff --git a/resources/keyboard/enter.png b/resources/keyboard/enter.png
new file mode 100644
index 0000000..7e96698
Binary files /dev/null and b/resources/keyboard/enter.png differ
diff --git a/resources/keyboard/left.png b/resources/keyboard/left.png
new file mode 100644
index 0000000..e757e22
Binary files /dev/null and b/resources/keyboard/left.png differ
diff --git a/resources/keyboard/menu.png b/resources/keyboard/menu.png
new file mode 100644
index 0000000..49b62b5
Binary files /dev/null and b/resources/keyboard/menu.png differ
diff --git a/resources/keyboard/right.png b/resources/keyboard/right.png
new file mode 100644
index 0000000..d320c63
Binary files /dev/null and b/resources/keyboard/right.png differ
diff --git a/resources/keyboard/shift.png b/resources/keyboard/shift.png
new file mode 100644
index 0000000..7266a0c
Binary files /dev/null and b/resources/keyboard/shift.png differ
diff --git a/resources/keyboard/tab.png b/resources/keyboard/tab.png
new file mode 100644
index 0000000..8540f23
Binary files /dev/null and b/resources/keyboard/tab.png differ
diff --git a/resources/keyboard/up.png b/resources/keyboard/up.png
new file mode 100644
index 0000000..e1ec790
Binary files /dev/null and b/resources/keyboard/up.png differ
diff --git a/resources/qml/appload.qml b/resources/qml/appload.qml
index b9f398e..f73a0b4 100644
--- a/resources/qml/appload.qml
+++ b/resources/qml/appload.qml
@@ -11,6 +11,7 @@ Rectangle {
property var windowArchetype: Qt.createComponent("window.qml")
property var absoluteRoot: _appLoadView
+ property var virtualKeyboardRef: null
signal requestClose
@@ -56,8 +57,11 @@ Rectangle {
win.appName = modelData.name;
win.supportsScaling = modelData.supportsScaling;
+ win.virtualKeyboardLayout = modelData.virtualKeyboardLayout;
win.disablesWindowedMode = modelData.disablesWindowedMode;
+ win.virtualKeyboardRef = _appLoadView.virtualKeyboardRef;
+
win.globalWidth = Qt.binding(function() { return _appLoadView.width; })
win.globalHeight = Qt.binding(function() { return _appLoadView.height; })
let deviceAspectRatio, applicationAspectRatio = modelData.aspectRatio;
diff --git a/resources/qml/virtualKeyboard/Key.qml b/resources/qml/virtualKeyboard/Key.qml
new file mode 100644
index 0000000..95ea898
--- /dev/null
+++ b/resources/qml/virtualKeyboard/Key.qml
@@ -0,0 +1,211 @@
+/*
+ Copyright 2011-2012 Heikki Holstila
+
+ This work is free software. you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This work is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this work. If not, see .
+*/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: key
+ required property var vkb
+
+ property string label
+ property string label_alt
+ property int code
+ property int code_alt
+ property int currentCode: (shiftActive && label_alt != '') ? code_alt : code
+ property string currentLabel: (shiftActive && label_alt != '') ? label_alt : label
+ property bool sticky // can key be stickied?
+ property bool becomesSticky // will this become sticky after release?
+ property int stickiness // current stickiness status
+ property real labelOpacity: 1.0
+
+ // mouse input handling
+ property int clickThreshold: 20
+ property bool isClick
+ property int pressMouseY
+ property int pressMouseX
+ property bool shiftActive: (vkb.keyModifiers & 0x100000) && !sticky
+
+ width: vkb.keyWidth // some default
+ height: vkb.keyHeight
+ color: label=="" ? "transparent" : vkb.keyBgColor
+ border.color: label=="" ? "transparent" : vkb.keyBorderColor
+ border.width: 1
+ radius: 2
+
+ Image {
+ id: keyImage
+ anchors.centerIn: parent
+ opacity: key.labelOpacity
+ source: { if(key.label.length>1 && key.label.charAt(0)==':') return "qrc:/appload/keyboard/"+key.label.substring(1)+".png"; else return ""; }
+ }
+
+ Column {
+ visible: keyImage.source == ""
+ anchors.centerIn: parent
+ spacing: -17
+
+ Text {
+ id: keyAltLabel
+ property bool highlighted: key.shiftActive
+
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ text: key.label_alt
+ color: vkb.keyFgColor
+
+ opacity: key.labelOpacity * (highlighted ? 1.0 : 0.2)
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+
+ font.pointSize: 24 * (text.length > 1 ? 0.5 : 1.0)
+ Behavior on font.pointSize { NumberAnimation { duration: 100 } }
+ }
+
+ Text {
+ id: keyLabel
+ property bool highlighted: key.label_alt == '' || !key.shiftActive
+
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ text: {
+ if (key.label.length == 1 && key.label_alt == '') {
+ if (key.shiftActive) {
+ return key.label.toUpperCase();
+ } else {
+ return key.label.toLowerCase();
+ }
+ }
+
+ return key.label;
+ }
+
+ color: vkb.keyFgColor
+
+ opacity: key.labelOpacity * (highlighted ? 1.0 : 0.2)
+ Behavior on opacity { NumberAnimation { duration: 100 } }
+
+ font.pointSize: 24 * (text.length > 1 ? 0.5 : 1.0)
+ Behavior on font.pointSize { NumberAnimation { duration: 100 } }
+ }
+ }
+
+ Rectangle {
+ id: stickIndicator
+ visible: sticky && stickiness>0
+ color: vkb.keyHilightBgColor
+ anchors.fill: parent
+ radius: key.radius
+ opacity: 0.5
+ anchors.topMargin: key.height/2
+ }
+
+ function handlePress(touchArea, x, y) {
+ console.log("Press " + label)
+ isClick = true;
+ pressMouseX = x;
+ pressMouseY = y;
+
+ key.color = vkb.keyHilightBgColor
+
+ vkb.config.keyDown(currentCode | vkb.keyModifiers);
+
+ if (sticky) {
+ vkb.keyModifiers |= code;
+ key.becomesSticky = true;
+ vkb.currentStickyPressed = key;
+ } else {
+ if (vkb.currentStickyPressed != null) {
+ // Pressing a non-sticky key while a sticky key is pressed:
+ // the sticky key will not become sticky when released
+ vkb.currentStickyPressed.becomesSticky = false;
+ }
+ }
+ }
+
+ function handleMove(touchArea, x, y) {
+ var mappedPoint = key.mapFromItem(touchArea, x, y)
+ if (!key.contains(Qt.point(mappedPoint.x, mappedPoint.y))) {
+ key.handleRelease(touchArea, x, y);
+ return false;
+ }
+
+ if (key.isClick) {
+ if (Math.abs(x - key.pressMouseX) > key.clickThreshold
+ || Math.abs(y - key.pressMouseY) > key.clickThreshold) {
+ key.isClick = false
+ }
+ }
+
+ return true;
+ }
+
+ function handleRelease(touchArea, x, y) {
+ key.color = vkb.keyBgColor
+
+ if (sticky && !becomesSticky) {
+ vkb.keyModifiers &= ~code
+ vkb.currentStickyPressed = null
+ }
+ if(!sticky) {
+ vkb.config.keyUp(currentCode | vkb.keyModifiers);
+ }
+
+ if (vkb.keyAt(x, y) == key) {
+ if (key.sticky && key.becomesSticky) {
+ setStickiness(-1)
+ }
+
+ // first non-sticky press will cause the sticky to be released
+ if (!sticky && vkb.resetSticky && vkb.resetSticky !== key) {
+ resetSticky.setStickiness(0)
+ }
+ }
+ }
+
+ function setStickiness(val)
+ {
+ if(sticky) {
+ if( vkb.resetSticky && vkb.resetSticky !== key ) {
+ resetSticky.setStickiness(0)
+ }
+
+ if(val===-1)
+ stickiness = (stickiness+1) % 3
+ else
+ stickiness = val
+
+ // stickiness == 0 -> not pressed
+ // stickiness == 1 -> release after next keypress
+ // stickiness == 2 -> keep pressed
+
+ if(stickiness>0) {
+ vkb.keyModifiers |= code
+ } else {
+ vkb.config.keyUp(currentCode);
+ vkb.keyModifiers &= ~code
+ }
+
+ vkb.resetSticky = null
+
+ if(stickiness==1) {
+ stickIndicator.anchors.topMargin = key.height/2
+ vkb.resetSticky = key
+ } else if(stickiness==2) {
+ stickIndicator.anchors.topMargin = 0
+ }
+ }
+ }
+}
diff --git a/resources/qml/virtualKeyboard/Keyboard.qml b/resources/qml/virtualKeyboard/Keyboard.qml
new file mode 100644
index 0000000..4861c30
--- /dev/null
+++ b/resources/qml/virtualKeyboard/Keyboard.qml
@@ -0,0 +1,149 @@
+/*
+ Copyright 2011-2012 Heikki Holstila
+
+ This work is free software. you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This work is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this work. If not, see .
+*/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: keyboard
+
+ property int keyModifiers
+ property Key resetSticky
+ property Key currentStickyPressed
+ property string keyFgColor: "#000000"
+ property string keyBgColor: "#ffffff"
+ property string keyHilightBgColor: "#000000"
+ property string keyBorderColor: "#000000"
+
+
+ property int outmargins: 2
+ property int keyspacing: 6
+ property int keysPerRow: layout?.columns || 0
+ property real keywidth: (keyboard.width - keyspacing*keysPerRow - outmargins*2)/keysPerRow;
+ property int keyWidth: width / (layout.columns + 1)
+ property int keyHeight: window.height / 14 < 55 ? window.height / 14 : 55
+ property var config: null
+
+ property var layout: null
+
+ width: parent.width
+ height: keyboard.outmargins + keyboard.keyspacing * (layout?.rows ?? 0 - 1) + keyboard.keyHeight * (layout?.rows ?? 0)
+
+ Component {
+ id: keyboardContents
+ Column {
+ id: col
+
+ x: (keyboard.width-width)/2
+ spacing: keyboard.keyspacing
+
+ Repeater {
+ id: rowRepeater
+
+ model: layout?.rows || 0
+ delegate: Row {
+ spacing: keyboard.keyspacing
+ Repeater {
+ id: colRepeater
+ property int rowIndex: index
+
+ model: layout.columnsInRow(index)
+ delegate: Key {
+ required property int index
+ property var keydata: layout.key(index, colRepeater.rowIndex)
+ vkb: keyboard
+
+ label: keydata.label
+ code: keydata.code
+ label_alt: keydata.altLabel
+ code_alt: keydata.altCode
+ width: keyboard.keywidth * keydata.width + ((keydata.width-1)*keyboard.keyspacing) + 1
+ sticky: keydata.isModifier && (keyboard.config?.enableStickyness ?? true)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Loader {
+ id: keyboardLoader
+ anchors.fill: parent
+ }
+
+ function rebuildKeyboard(layoutData, config) {
+ keyboard.config = config;
+ keyboard.layout = layoutData;
+ keyboardLoader.sourceComponent = undefined;
+ keyboardLoader.sourceComponent = keyboardContents;
+ }
+
+ //borrowed from nemo-keyboard
+ //Parameters: (x, y) in view coordinates
+ function keyAt(x, y) {
+ var item = keyboardLoader.item
+ x -= keyboard.x
+ y -= keyboard.y
+
+ while ((item = item.childAt(x, y)) != null) {
+ //return the first "Key" element we find
+ if (typeof item.currentCode !== 'undefined') {
+ return item
+ }
+
+ // Cheaper mapToItem, assuming we're not using anything fancy.
+ x -= item.x
+ y -= item.y
+ }
+
+ return null
+ }
+
+ MultiPointTouchArea {
+ id: multiTouchArea
+ anchors.fill: parent
+ property var pressedKeys: ({})
+
+ onPressed: (touchPoints) => {
+ touchPoints.forEach(function (touchPoint) {
+ var key = keyboard.keyAt(touchPoint.x, touchPoint.y)
+ if (key != null) {
+ key.handlePress(multiTouchArea, touchPoint.x, touchPoint.y)
+ }
+ multiTouchArea.pressedKeys[touchPoint.pointId] = key
+ })
+ }
+ onUpdated: (touchPoints) => {
+ touchPoints.forEach(function (touchPoint) {
+ var key = multiTouchArea.pressedKeys[touchPoint.pointId]
+ if (key != null) {
+ if (!key.handleMove(multiTouchArea, touchPoint.x, touchPoint.y)) {
+ delete multiTouchArea.pressedKeys[touchPoint.pointId];
+ }
+ }
+ })
+ }
+ onReleased: (touchPoints) => {
+ touchPoints.forEach(function (touchPoint) {
+ var key = multiTouchArea.pressedKeys[touchPoint.pointId]
+ if (key != null) {
+ key.handleRelease(multiTouchArea, touchPoint.x, touchPoint.y)
+ }
+ delete multiTouchArea.pressedKeys[touchPoint.pointId]
+ })
+ }
+ }
+}
diff --git a/resources/qml/window.qml b/resources/qml/window.qml
index 73de1b7..e8b9c92 100644
--- a/resources/qml/window.qml
+++ b/resources/qml/window.qml
@@ -33,6 +33,15 @@ FocusScope {
property var _height: root.globalHeight / 3
property var beforeFullscreenData: null
+ // Keyboard handling:
+ property var virtualKeyboardLayout: null
+ property var virtualKeyboardRef: null
+ property var keyboardConfig: ({
+ enableStickyness: true,
+ keyUp: code => windowCanvas.virtualKeyboardKeyUp(code),
+ keyDown: code => windowCanvas.virtualKeyboardKeyDown(code),
+ })
+
// External I/O from this component:
signal closed
function loadApplication(appId) {
@@ -288,6 +297,39 @@ FocusScope {
}
}
+ Rectangle {
+ id: virtualKeyboardButton
+ width: parent.height
+ height: parent.height
+ anchors.left: parent.left
+ border.width: 2
+ border.color: "black"
+ color: parent.color
+ visible: virtualKeyboardLayout !== null
+
+ Image {
+ source: "qrc:/appload/icons/keyboard"
+ sourceSize.width: 120
+ sourceSize.height: 120
+ anchors.fill: parent
+ anchors.margins: 10
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: () => {
+ if(root.virtualKeyboardRef.active && root.virtualKeyboardRef.config === root.keyboardConfig) {
+ root.virtualKeyboardRef.active = false;
+ } else {
+ root.virtualKeyboardRef.config = root.keyboardConfig;
+ root.virtualKeyboardRef.layout = root.virtualKeyboardLayout;
+ root.virtualKeyboardRef.active = false;
+ root.virtualKeyboardRef.active = true;
+ }
+ }
+ }
+ }
+
Rectangle {
width: parent.width
height: 2
@@ -374,6 +416,7 @@ FocusScope {
unloadingFunction = loaderScaled.item?.unloading;
}
if(unloadingFunction) unloadingFunction();
+ root.virtualKeyboardRef.active = false;
root.closed();
}
}
diff --git a/resources/resources.qrc b/resources/resources.qrc
index 1db00f3..41af136 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -3,8 +3,22 @@
icons/appload.svg
icons/reload.svg
icons/exit.svg
+ icons/keyboard.svg
qml/appload.qml
qml/window.qml
+ qml/virtualKeyboard/Keyboard.qml
+ qml/virtualKeyboard/Key.qml
+
+ keyboard/default.layout.json
+ keyboard/backspace.png
+ keyboard/down.png
+ keyboard/enter.png
+ keyboard/left.png
+ keyboard/menu.png
+ keyboard/right.png
+ keyboard/shift.png
+ keyboard/tab.png
+ keyboard/up.png
diff --git a/shim/src/input-shim.cpp b/shim/src/input-shim.cpp
index 3e46e33..6630949 100644
--- a/shim/src/input-shim.cpp
+++ b/shim/src/input-shim.cpp
@@ -54,7 +54,7 @@
extern qtfb::ClientConnection *clientConnection;
extern int shimInputType;
-extern std::set *identDigitizer, *identTouchScreen, *identButtons, *identNull;
+extern std::set *identDigitizer, *identTouchScreen, *identButtons, *identVirtualKeyboard, *identNull;
struct TouchSlotState {
int x, y;
@@ -65,7 +65,8 @@ std::map touchStates;
#define QUEUE_TOUCH 1
#define QUEUE_PEN 2
#define QUEUE_BUTTONS 3
-#define QUEUE_NULL 4
+#define QUEUE_VIRTUALKEYBOARD 4
+#define QUEUE_NULL 5
struct PIDEventQueue *pidEventQueue;
@@ -98,6 +99,42 @@ static int mapKey(int x) {
return 0;
}
+int mapAsciiToX11Key(int ascii) {
+ // Pure modifiers:
+ switch(ascii){
+ case INPUT_VKB_SHIFTMOD: return 0xffe1;
+ case INPUT_VKB_CTRLMOD: return 0xffe3;
+ case INPUT_VKB_ALTMOD: return 0xffe9;
+ }
+ // So it's not a pure modifier.
+ // ASCII unprintable characters
+ switch (ascii & 0xFF) {
+ case 8: return 0xff08; // Backspace
+ case 9: return 0xff09; // Tab
+ case 13: return 0xff0d; // Enter/Return
+ case 27: return 0xff1b; // Escape
+ case 127: return 0xffff; // Delete
+ case INPUT_VKB_LEFT: return 0xff51;
+ case INPUT_VKB_UP: return 0xff52;
+ case INPUT_VKB_RIGHT: return 0xff53;
+ case INPUT_VKB_DOWN: return 0xff54;
+ case INPUT_VKB_HOME: return 0xff50;
+ case INPUT_VKB_END: return 0xff57;
+ case INPUT_VKB_PGUP: return 0xff55;
+ case INPUT_VKB_PGDOWN: return 0xff56;
+ }
+
+
+ // If shift key pressed, uppercase the ascii
+ if((ascii & INPUT_VKB_SHIFTMOD) && (ascii >= 'a') && (ascii <= 'z')) {
+ ascii -= ' ';
+ }
+ // Mask the pure ascii:
+ ascii &= 0xFF;
+
+ return 0;
+}
+
static void pushToAll(int queueType, struct input_event evt) {
struct PIDEventQueue *current = pidEventQueue;
while(current != NULL) {
@@ -225,6 +262,20 @@ static void pollInputUpdates() {
pushToAll(QUEUE_BUTTONS, evt(EV_KEY, mapKey(message.userInput.x), 0));
pushToAll(QUEUE_BUTTONS, evt(EV_SYN, SYN_REPORT, 0));
break;
+
+ case INPUT_VKB_PRESS: {
+ int code = mapAsciiToX11Key(message.userInput.x);
+ pushToAll(QUEUE_VIRTUALKEYBOARD, evt(EV_KEY, code, 1));
+ pushToAll(QUEUE_VIRTUALKEYBOARD, evt(EV_SYN, SYN_REPORT, 0));
+ break;
+ }
+ case INPUT_VKB_RELEASE: {
+ int code = mapAsciiToX11Key(message.userInput.x);
+ pushToAll(QUEUE_VIRTUALKEYBOARD, evt(EV_KEY, code, 0));
+ pushToAll(QUEUE_VIRTUALKEYBOARD, evt(EV_SYN, SYN_REPORT, 0));
+ break;
+ }
+
default: break;
}
}
@@ -267,6 +318,7 @@ int inputShimOpen(fileident_t identity, int flags, mode_t mode) {
e("dig", *identDigitizer);
e("tch", *identTouchScreen);
e("btn", *identButtons);
+ e("vkb", *identVirtualKeyboard);
e("null", *identNull);
#undef e
if(identDigitizer->find(identity) != identDigitizer->end()) {
@@ -285,6 +337,11 @@ int inputShimOpen(fileident_t identity, int flags, mode_t mode) {
CERR << "Open buttons " << fd << std::endl;
return fd;
}
+ if(identVirtualKeyboard->find(identity) != identVirtualKeyboard->end()) {
+ int fd = createInEventMap(QUEUE_VIRTUALKEYBOARD, flags);
+ CERR << "Open virtual keyboard " << fd << std::endl;
+ return fd;
+ }
if(identNull->find(identity) != identNull->end()) {
int fd = createInEventMap(QUEUE_NULL, flags);
CERR << "Open null " << fd << std::endl;
diff --git a/shim/src/shim.cpp b/shim/src/shim.cpp
index 372adec..b6a5d4d 100644
--- a/shim/src/shim.cpp
+++ b/shim/src/shim.cpp
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include "shim.h"
#include "fb-shim.h"
#include "input-shim.h"
@@ -40,7 +41,7 @@ bool shimModel;
bool shimInput;
bool shimFramebuffer;
int shimInputType = SHIM_INPUT_RM1;
-std::set *identDigitizer, *identTouchScreen, *identButtons, *identNull;
+std::set *identDigitizer, *identTouchScreen, *identButtons, *identVirtualKeyboard, *identNull;
int realDeviceType;
void readRealDeviceType() {
@@ -108,6 +109,7 @@ void __attribute__((constructor)) __construct () {
identDigitizer = new std::set();
identTouchScreen = new std::set();
identButtons = new std::set();
+ identVirtualKeyboard = new std::set();
identNull = new std::set();
readRealDeviceType();
@@ -192,7 +194,10 @@ void __attribute__((constructor)) __construct () {
CERR << "Configured FB type to " << shimType << ", input to " << shimInputType << std::endl;
- const char *pathDigitizer, *pathTouchScreen, *pathButtons, *pathNull;
+ const char *pathDigitizer, *pathTouchScreen, *pathButtons, *pathVirtualKeyboard, *pathNull;
+
+ pathVirtualKeyboard = "/dev/input/virtual_keyboard";
+ std::ofstream(pathVirtualKeyboard).close();
switch(shimInputType) {
case SHIM_INPUT_RM1:
@@ -233,6 +238,11 @@ void __attribute__((constructor)) __construct () {
}
iterStringCollectToIdentities(identButtons, temp);
+ if((temp = getenv("QTFB_SHIM_INPUT_PATH_KEYS")) == NULL) {
+ temp = pathVirtualKeyboard;
+ }
+ iterStringCollectToIdentities(identVirtualKeyboard, temp);
+
if((temp = getenv("QTFB_SHIM_INPUT_PATH_NULL")) == NULL) {
temp = pathNull;
}
@@ -247,6 +257,9 @@ void __attribute__((constructor)) __construct () {
for(const auto e : *identButtons) {
CERR << "Ident btn: " << e << std::endl;
}
+ for(const auto e : *identVirtualKeyboard) {
+ CERR << "Ident vkb: " << e << std::endl;
+ }
for(const auto e : *identNull) {
CERR << "Ident null: " << e << std::endl;
}
diff --git a/src/AppLibrary.h b/src/AppLibrary.h
index 007b2fb..18a82b3 100644
--- a/src/AppLibrary.h
+++ b/src/AppLibrary.h
@@ -13,6 +13,7 @@
#include
#include "library.h"
+#include "keyboard/layout.h"
#define INTERNAL 0
#define EXTERNAL_NOGUI 1
@@ -29,17 +30,39 @@ class AppLoadApplication : public QObject {
Q_PROPERTY(int externalType READ externalType) // 0 - not external, 1 - external (non-graphics), 2 - external (qtfb)
Q_PROPERTY(QString aspectRatio READ aspectRatio CONSTANT)
Q_PROPERTY(bool disablesWindowedMode READ disablesWindowedMode CONSTANT)
+ Q_PROPERTY(const appload::vk::Layout *const virtualKeyboardLayout READ virtualKeyboardLayout CONSTANT)
public:
explicit AppLoadApplication(QObject *parent = nullptr)
: QObject(parent) {}
- AppLoadApplication(const QString &id, const QString &name, const QString &icon, bool supportsScaling, bool canHaveMultipleFrontends, int externalType, appload::library::AspectRatio aspectRatio, bool disablesWindowedMode, QObject *parent = nullptr)
- : QObject(parent), _id(id), _name(name), _icon(icon), _supportsScaling(supportsScaling), _canHaveMultipleFrontends(canHaveMultipleFrontends), _externalType(externalType), _aspectRatio(aspectRatio), _disablesWindowedMode(disablesWindowedMode) {}
+ AppLoadApplication(
+ const QString &id,
+ const QString &name,
+ const QString &icon,
+ bool supportsScaling,
+ bool canHaveMultipleFrontends,
+ int externalType,
+ appload::library::AspectRatio aspectRatio,
+ bool disablesWindowedMode,
+ const appload::vk::Layout *vkLayout,
+ QObject *parent = nullptr
+ ):
+ QObject(parent),
+ _id(id),
+ _name(name),
+ _icon(icon),
+ _supportsScaling(supportsScaling),
+ _canHaveMultipleFrontends(canHaveMultipleFrontends),
+ _externalType(externalType),
+ _aspectRatio(aspectRatio),
+ _disablesWindowedMode(disablesWindowedMode),
+ _virtualKeyboardLayout(vkLayout) {}
QString id() const { return _id; }
QString name() const { return _name; }
QString icon() const { return _icon; }
QString aspectRatio() const { return appload::library::aspectRatioToString(_aspectRatio); }
+ const appload::vk::Layout *virtualKeyboardLayout() const { return _virtualKeyboardLayout; }
bool supportsScaling() const { return _supportsScaling; }
bool canHaveMultipleFrontends() const { return _canHaveMultipleFrontends; }
int externalType() const { return _externalType; }
@@ -50,15 +73,18 @@ class AppLoadApplication : public QObject {
QString _name;
QString _icon;
bool _supportsScaling;
+ bool _supportsVirtualKeyboard;
bool _canHaveMultipleFrontends;
int _externalType;
appload::library::AspectRatio _aspectRatio;
bool _disablesWindowedMode;
+ appload::vk::Layout const *_virtualKeyboardLayout;
};
class AppLoadLibrary : public QObject {
Q_OBJECT
Q_PROPERTY(QQmlListProperty applications READ applications NOTIFY applicationsChanged)
+ Q_PROPERTY(const appload::vk::Layout *defaultLayout READ defaultLayout CONSTANT)
public:
explicit AppLoadLibrary(QObject *parent = nullptr) : QObject(parent) { appload::library::addGlobalLibraryHandle(this); }
@@ -105,6 +131,8 @@ class AppLoadLibrary : public QObject {
appload::library::terminateExternal(pid);
}
+ const appload::vk::Layout *defaultLayout() const { return appload::library::defaultLayout; }
+
void loadList() {
clearApplications();
for (const auto &entry : appload::library::getRef()) {
@@ -116,6 +144,7 @@ class AppLoadLibrary : public QObject {
INTERNAL,
appload::library::AspectRatio::AUTO,
false,
+ NULL,
this));
}
for (const auto &entry : appload::library::getExternals()) {
@@ -127,6 +156,7 @@ class AppLoadLibrary : public QObject {
entry.second->isQTFB() ? EXTERNAL_QTFB : EXTERNAL_NOGUI,
entry.second->getAspectRatio(),
entry.second->disablesWindowedMode(),
+ entry.second->getVirtualKeyboardLayout(),
this));
}
}
diff --git a/src/keyboard/layout.cpp b/src/keyboard/layout.cpp
new file mode 100644
index 0000000..525c065
--- /dev/null
+++ b/src/keyboard/layout.cpp
@@ -0,0 +1,55 @@
+#include "layout.h"
+#include "../log.h"
+
+#include
+
+// Row 0 must not have any non-1 width keys!
+int appload::vk::Layout::rows() const { return _layout.size(); }
+int appload::vk::Layout::columns() const { return _layout.empty() ? 0 : _layout[0].size(); }
+int appload::vk::Layout::columnsInRow(int r) const { return (int) _layout.size() <= r ? 0 : _layout[r].size(); }
+
+const appload::vk::KeyData *appload::vk::Layout::key(int coln, int rown) const {
+ if((int) _layout.size() <= rown) return NULL;
+ const auto &row = _layout[rown];
+ return (int) row.size() <= coln ? NULL : &row[coln];
+}
+
+void appload::vk::Layout::load(const QByteArray &src) {
+ QJsonParseError err;
+ QJsonDocument doc = QJsonDocument::fromJson(src, &err);
+ if(err.error != QJsonParseError::NoError) {
+ QDEBUG << "Failed to load keyboard layout" << err.errorString() << "@" << err.offset;
+ return;
+ }
+ if(!doc.isArray()) {
+ QDEBUG << "Expected an array as the root object of keyboard layout";
+ return;
+ }
+ QJsonArray jsonRows = doc.array();
+ for(const auto &row : jsonRows) {
+ if(!row.isArray()) {
+ QDEBUG << "Expected the row to be an array of keys";
+ _layout.erase(_layout.begin(), _layout.end());
+ return;
+ }
+ auto &newRow = _layout.emplace_back();
+ for(const auto &key : row.toArray()) {
+ if(!key.isArray()) {
+ QDEBUG << "Expected the key definition tso be an array";
+ _layout.erase(_layout.begin(), _layout.end());
+ return;
+ }
+ const auto &keyArr = key.toArray();
+ int keyCode = keyArr[1].toInt();
+ newRow.emplace_back(
+ keyArr[0].toString(),
+ keyCode,
+ keyArr[2].toString(),
+ keyArr[3].toInt(),
+ keyArr[4].toInt(1),
+ keyCode >= 0x100000,
+ this
+ );
+ }
+ }
+}
diff --git a/src/keyboard/layout.h b/src/keyboard/layout.h
new file mode 100644
index 0000000..1126c54
--- /dev/null
+++ b/src/keyboard/layout.h
@@ -0,0 +1,69 @@
+#pragma once
+
+#include
+#include
+
+namespace appload::vk {
+class KeyData : public QObject{
+ Q_OBJECT
+ Q_PROPERTY(QString label READ label CONSTANT)
+ Q_PROPERTY(int code READ code CONSTANT)
+ Q_PROPERTY(QString altLabel READ altLabel CONSTANT)
+ Q_PROPERTY(int altCode READ altCode CONSTANT)
+ Q_PROPERTY(int width READ width CONSTANT)
+ Q_PROPERTY(bool isModifier READ isModifier CONSTANT)
+public:
+ QString label() const { return _label; }
+ QString altLabel() const { return _altLabel; }
+ int code() const { return _code; }
+ int altCode() const { return _altCode; }
+ int width() const { return _width; }
+ bool isModifier() const { return _isModifier; }
+ explicit KeyData(QObject *parent = nullptr): QObject(parent) {}
+
+ KeyData(QString label, int code, QString altLabel, int altCode, int width, int isModifier, QObject *parent):
+ QObject(parent),
+ _label(label),
+ _code(code),
+ _altLabel(altLabel),
+ _altCode(altCode),
+ _width(width),
+ _isModifier(isModifier) {}
+
+ KeyData(const appload::vk::KeyData& copy):
+ QObject(copy.parent()),
+ _label(copy._label),
+ _code(copy._code),
+ _altLabel(copy._altLabel),
+ _altCode(copy._altCode),
+ _width(copy._width),
+ _isModifier(copy._isModifier) {}
+
+
+private:
+ QString _label;
+ int _code;
+ QString _altLabel;
+ int _altCode;
+ int _width;
+ bool _isModifier;
+};
+
+class Layout : public QObject{
+ Q_OBJECT
+ // No `NOTIFY'. Once initialized, the Layout object is static.
+ Q_PROPERTY(int columns READ columns CONSTANT)
+ Q_PROPERTY(int rows READ rows CONSTANT)
+public:
+ explicit Layout(QObject *parent = 0): QObject(parent) {};
+ void load(const QByteArray &source);
+
+ Q_INVOKABLE const KeyData *key(int col, int row) const;
+ Q_INVOKABLE int columnsInRow(int row) const;
+ int columns() const;
+ int rows() const;
+private:
+ std::vector> _layout;
+};
+
+}
\ No newline at end of file
diff --git a/src/library.cpp b/src/library.cpp
index 29b4b1f..85184f1 100644
--- a/src/library.cpp
+++ b/src/library.cpp
@@ -152,9 +152,17 @@ appload::library::LoadedApplication::~LoadedApplication() {
}
}
static std::mutex loadingMutex;
+appload::vk::Layout *appload::library::defaultLayout = NULL;
int appload::library::loadApplications() {
loadingMutex.lock();
+ defaultLayout = new appload::vk::Layout(NULL);
+ QResource defaultKeyboardLayout(QString(":/appload/keyboard/default.layout.json"));
+ if(!defaultKeyboardLayout.isValid()) {
+ QDEBUG << "Invalid data in default layout!";
+ } else {
+ defaultLayout->load(defaultKeyboardLayout.uncompressedData());
+ }
// Make sure all apps are unloaded:
for(auto entry : appload::library::applications) {
if(entry.second->isFrontendRunning()) {
diff --git a/src/library.h b/src/library.h
index 4441967..fdcffd4 100644
--- a/src/library.h
+++ b/src/library.h
@@ -30,6 +30,7 @@
#include
#include
#include "config.h"
+#include "keyboard/layout.h"
class AppLoadLibrary;
@@ -38,6 +39,7 @@ namespace appload::library {
ORIGINAL, MOVE, AUTO,
};
QString aspectRatioToString(AspectRatio ratio);
+ extern appload::vk::Layout *defaultLayout;
class ExternalApplication {
public:
@@ -48,6 +50,8 @@ namespace appload::library {
bool isQTFB() const;
AspectRatio getAspectRatio() const;
bool disablesWindowedMode() const;
+ bool supportsVirtualKeyboard() const;
+ const appload::vk::Layout *getVirtualKeyboardLayout() const;
bool valid = false;
@@ -62,6 +66,7 @@ namespace appload::library {
std::map environment;
bool _isQTFB;
bool _disablesWindowedMode;
+ const appload::vk::Layout *_virtualKeyboardLayout;
AspectRatio aspectRatio;
void parseManifest();
diff --git a/src/libraryexternals.cpp b/src/libraryexternals.cpp
index 64318fa..1888f9d 100644
--- a/src/libraryexternals.cpp
+++ b/src/libraryexternals.cpp
@@ -28,8 +28,6 @@ void appload::library::removeGlobalLibraryHandle(AppLoadLibrary *ptr) {
}
}
-
-
void appload::library::ExternalApplication::parseManifest() {
QString filePath = root + "/external.manifest.json";
QFile file(filePath);
@@ -55,6 +53,10 @@ void appload::library::ExternalApplication::parseManifest() {
// Optional:
_isQTFB = jsonObject.value("qtfb").toBool(false);
_disablesWindowedMode = jsonObject.value("disablesWindowedMode").toBool(false);
+ bool supportsVirtualKeyboard = jsonObject.value("supportsVirtualKeyboard").toBool(false);
+ if(supportsVirtualKeyboard) {
+ this->_virtualKeyboardLayout = appload::library::defaultLayout;
+ }
workingDirectory = jsonObject.value("workingDirectory").toString(root);
args = jsonObject.value("args").toVariant().toStringList();
QJsonObject env = jsonObject.value("environment").toObject();
@@ -97,7 +99,6 @@ qint64 appload::library::ExternalApplication::launch(int qtfbKey, QStringList ex
process->setWorkingDirectory(workingDirectory);
process->setProcessChannelMode(QProcess::ForwardedChannels);
QStringList finalArgs = args + extraArgs;
- for(const auto &arg : extraArgs) finalArgs.append(arg);
process->start(execPath, finalArgs);
if (!process->waitForStarted()) {
@@ -142,6 +143,10 @@ bool appload::library::ExternalApplication::disablesWindowedMode() const {
return _disablesWindowedMode;
}
+const appload::vk::Layout *appload::library::ExternalApplication::getVirtualKeyboardLayout() const {
+ return _virtualKeyboardLayout;
+}
+
void appload::library::terminateExternal(qint64 pid) {
kill(pid, SIGTERM);
sendPidDiedMessage(pid);
diff --git a/src/qtfb/FBController.cpp b/src/qtfb/FBController.cpp
index 8653892..f022c33 100644
--- a/src/qtfb/FBController.cpp
+++ b/src/qtfb/FBController.cpp
@@ -137,7 +137,7 @@ void FBController::mouseMoveEvent(QMouseEvent *me) {
me->accept();
}
-static inline void sendSpecialKey(int key, int pkt, qtfb::FBKey _framebufferID) {
+static inline void sendKeyEvent(int key, int pkt, qtfb::FBKey _framebufferID) {
if(_framebufferID != -1) {
qtfb::UserInputContents packet {
.inputType = pkt,
@@ -150,12 +150,20 @@ static inline void sendSpecialKey(int key, int pkt, qtfb::FBKey _framebufferID)
}
}
+void FBController::virtualKeyboardKeyDown(int key) {
+ sendKeyEvent(key, INPUT_VKB_PRESS, _framebufferID);
+}
+
+void FBController::virtualKeyboardKeyUp(int key) {
+ sendKeyEvent(key, INPUT_VKB_RELEASE, _framebufferID);
+}
+
void FBController::specialKeyDown(int key) {
- sendSpecialKey(key, INPUT_BTN_PRESS, _framebufferID);
+ sendKeyEvent(key, INPUT_BTN_PRESS, _framebufferID);
}
void FBController::specialKeyUp(int key) {
- sendSpecialKey(key, INPUT_BTN_RELEASE, _framebufferID);
+ sendKeyEvent(key, INPUT_BTN_RELEASE, _framebufferID);
}
void FBController::mouseReleaseEvent(QMouseEvent *me) {
diff --git a/src/qtfb/FBController.h b/src/qtfb/FBController.h
index 54f3560..aa46b73 100644
--- a/src/qtfb/FBController.h
+++ b/src/qtfb/FBController.h
@@ -52,6 +52,8 @@ class FBController : public QQuickPaintedItem
virtual void keyPressEvent(QKeyEvent *ke) override;
virtual void keyReleaseEvent(QKeyEvent *ke) override;
+ Q_INVOKABLE void virtualKeyboardKeyDown(int key);
+ Q_INVOKABLE void virtualKeyboardKeyUp(int key);
Q_INVOKABLE void specialKeyDown(int key);
Q_INVOKABLE void specialKeyUp(int key);
diff --git a/src/qtfb/common.h b/src/qtfb/common.h
index 72ac6f1..4f4a2ba 100644
--- a/src/qtfb/common.h
+++ b/src/qtfb/common.h
@@ -50,10 +50,26 @@
#define INPUT_BTN_PRESS 0x30
#define INPUT_BTN_RELEASE 0x31
+#define INPUT_VKB_PRESS 0x40
+#define INPUT_VKB_RELEASE 0x41
+
#define INPUT_BTN_X_LEFT 0
#define INPUT_BTN_X_HOME 1
#define INPUT_BTN_X_RIGHT 2
+#define INPUT_VKB_SHIFTMOD 0x100000
+#define INPUT_VKB_CTRLMOD 0x200000
+#define INPUT_VKB_ALTMOD 0x400000
+#define INPUT_VKB_DEL 0x7f
+#define INPUT_VKB_PGUP 0x80
+#define INPUT_VKB_PGDOWN 0x81
+#define INPUT_VKB_DOWN 0x82
+#define INPUT_VKB_UP 0x83
+#define INPUT_VKB_LEFT 0x84
+#define INPUT_VKB_RIGHT 0x85
+#define INPUT_VKB_HOME 0x86
+#define INPUT_VKB_END 0x87
+
namespace qtfb {
typedef int FBKey;
diff --git a/xovi/make.sh b/xovi/make.sh
old mode 100644
new mode 100755
diff --git a/xovi/template/appload.pro b/xovi/template/appload.pro
index 7c8c9ed..2f9c00b 100644
--- a/xovi/template/appload.pro
+++ b/xovi/template/appload.pro
@@ -4,7 +4,7 @@ TARGET = appload
TEMPLATE = lib
CONFIG += shared plugin no_plugin_name_prefix
-SOURCES += src/main.cpp xovi.cpp src/management.cpp src/AppLoad.cpp src/AppLoadCoordinator.cpp src/library.cpp src/libraryexternals.cpp src/qtfb/fbmanagement.cpp src/qtfb/FBController.cpp
+SOURCES += src/main.cpp xovi.cpp src/management.cpp src/AppLoad.cpp src/AppLoadCoordinator.cpp src/library.cpp src/libraryexternals.cpp src/qtfb/fbmanagement.cpp src/qtfb/FBController.cpp src/keyboard/layout.cpp
HEADERS += src/AppLoad.h src/AppLoadCoordinator.h src/library.h src/AppLibrary.h \
- src/qtfb/FBController.h src/qtfb/fbmanagement.h src/Launcher.h
+ src/qtfb/FBController.h src/qtfb/fbmanagement.h src/keyboard/layout.h src/Launcher.h
diff --git a/xovi/template/appload.qmd b/xovi/template/appload.qmd
index bd0df1c..40a5ac3 100644
--- a/xovi/template/appload.qmd
+++ b/xovi/template/appload.qmd
@@ -25,7 +25,8 @@ AFFECT [[8850026134298937527]]
~&7083172477658&~: "qrc:/appload/qml/appload.qml"
~&7713401454751279&~: {
- _appLoadView.~&6503936152&~.absoluteRoot = ~&6504254477&~;
+ _appLoadView.~&6503936152&~.absoluteRoot = windowParent;
+ _appLoadView.item.virtualKeyboardRef = _apploadVirtualKeyboard;
}
}
@@ -37,6 +38,30 @@ AFFECT [[8850026134298937527]]
}
}
}
+ LOCATE AFTER ALL
+ INSERT {
+ Item {
+ id: windowParent
+ anchors.fill: parent
+ }
+ Loader {
+ id: _apploadVirtualKeyboard
+
+ property var layout: null
+ property var config: null
+ width: parent.width
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ active: false
+ visible: active
+ source: "qrc:/appload/qml/virtualKeyboard/Keyboard.qml"
+
+ onLoaded: () => {
+ console.log("Rebuild keyboard data: ", _apploadVirtualKeyboard.layout, _apploadVirtualKeyboard.config);
+ _apploadVirtualKeyboard.item.rebuildKeyboard(_apploadVirtualKeyboard.layout, _apploadVirtualKeyboard.config);
+ }
+ }
+ }
END TRAVERSE
END AFFECT
diff --git a/xovi/template/src/main.cpp b/xovi/template/src/main.cpp
index c343994..a744b8c 100644
--- a/xovi/template/src/main.cpp
+++ b/xovi/template/src/main.cpp
@@ -20,8 +20,6 @@ extern "C" {
static const char *applicationRoot;
void _xovi_construct() {
applicationRoot = Environment->getExtensionDirectory("appload");
- appload::library::loadApplications();
- qtfb::management::start();
qmlRegisterType("net.asivery.AppLoad", 1, 0, "AppLoad");
qmlRegisterType("net.asivery.AppLoad", 1, 0, "AppLoadCoordinator");
@@ -40,6 +38,9 @@ extern "C" {
qt_resource_rebuilder$qmldiff_disable_slots_while_processing();
qRegisterResourceData(3, qt_resource_struct, qt_resource_name, qt_resource_data);
qt_resource_rebuilder$qmldiff_enable_slots_while_processing();
+
+ appload::library::loadApplications();
+ qtfb::management::start();
}
}