Commit d76bdabf authored by Morten Sorvig's avatar Morten Sorvig

QtWS19 presentation

parent cad302fe
Qt for WebAssmebly (QtWS18)
Qt for WebAssmebly (QtWS19)
===========================
Currently this contains peresentation tech testing only.
Usage: Serve content from web server (e.g. python -m http.server 8000), open index.html in a web browser.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
File added
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>wasm</title>
<style>
html, body { padding: 0; margin : 0; }
.qtcontainer {
position: relative;
width: 400px;
height: 400px;
}
.qtcanvas {
position: absolute;
border: 0px none;
z-index: 1;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.qta11ycontainer {
position: absolute;
border: 0px none;
z-index: 0;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
.qta11y_item {
position: absolute;
}
</style>
</head>
<body onload="init()">
<figure style="overflow:visible;" id="spinner">
<center style="margin-top:1.5em; line-height:150%">
<img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
<strong>Qt for WebAssembly: wasm</strong>
<div id="status"></div>
<noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
</center>
</figure>
<div class="qtcontainer">
<canvas class="qtcanvas" id="canvas" aria-hidden=true role="presentation"> </canvas>
<div class="qta11ycontainer" id="htmluicontaner"> </div>
</div>
<script type='text/javascript'>
function init() {
var spinner = document.getElementById('spinner');
var canvas = document.getElementById('canvas');
var status = document.getElementById('status')
var qtLoader = QtLoader({
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
canvas.style.display = 'none';
status.innerHTML = loaderStatus + "...";
},
showError: function(errorText) {
status.innerHTML = errorText;
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showExit: function() {
status.innerHTML = "Application exit";
if (qtLoader.exitCode !== undefined)
status.innerHTML += " with code " + qtLoader.exitCode;
if (qtLoader.exitText !== undefined)
status.innerHTML += " (" + qtLoader.exitText + ")";
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showCanvas: function() {
spinner.style.display = 'none';
canvas.style.display = 'block';
window.setTimeout(function() {
populateHtmlUi();
}, 10);
return canvas;
},
});
qtLoader.loadEmscriptenModule("wasm");
}
</script>
<script type="text/javascript" src="htmlui.js"></script>
<script type="text/javascript" src="qtloader.js"></script>
</body>
</html>
function populateHtmlUi() {
console.log("populateHtmlUi");
const container = document.getElementById("htmluicontaner");
// Clear
while (container.firstChild)
container.removeChild(container.firstChild);
// Populate
const applicationRootAccessibilityInterface = 0;
populateHtmlUiFromInterfaceId(container, applicationRootAccessibilityInterface);
}
function setElementGeometry(element, geometryArray) {
element.style.position = "absolute";
element.style.left = geometryArray[0] + "px";
element.style.top = geometryArray[1] + "px";
element.style.width = geometryArray[2] + "px";
element.style.height = geometryArray[3] + "px";
}
function populateHtmlUiFromInterfaceIdArray(containerElement, interfaceIds) {
console.log(interfaceIds);
for (id of interfaceIds)
populateHtmlUiFromInterfaceId(containerElement, id);
}
function populateHtmlUiFromApplicationInterface(containerElement, interface) {
populateHtmlUiFromInterfaceIdArray(containerElement, interface.children);
}
function populateHtmlUiFromWindowInterface(containerElement, interface) {
populateHtmlUiFromInterfaceIdArray(containerElement, interface.children);
}
function populateHtmlUiFromButtonInterface(containerElement, interface) {
let element = document.createElement("Button");
setElementGeometry(element, interface.geometry);
element.innerHTML=interface.name;
element.addEventListener('click', function() {
console.log(interface)
if (interface.actions.includes("Press")) {
console.log(interface);
Module.performAction(interface.elementId, "Press");
populateHtmlUi(0); // cheat: update html since the button press might have changed the UI
}
});
containerElement.appendChild(element);
}
function populateHtmlUiFromStaticTextInterface(containerElement, interface) {
let element = document.createElement("div");
setElementGeometry(element, interface.geometry);
element.innerHTML=interface.name;
element.style.lineHeight = element.style.height; // vertically center label, like Qt.
containerElement.appendChild(element);
}
function populateHtmlUiFromEditableTextInterface(containerElement, interface) {
let element = document.createElement("input");
element.type = "text"
setElementGeometry(element, interface.geometry);
element.value= "This is a line edit";
containerElement.appendChild(element);
}
function populateHtmlUiFromUnknownInterface(containerElement, interface) {
// We don't know how to handle this interface, but maybe we can handle the children
populateHtmlUiFromInterfaceIdArray(containerElement, interface.children);
}
function populateHtmlUiFromInterfaceId(containerElement, accessibleInterfaceId) {
console.log("populateHtmlUiFromInterfaceId " + accessibleInterfaceId);
let rootJson = Module.getAccessibilityJson(accessibleInterfaceId);
var iface = JSON.parse(rootJson);
console.log(iface);
switch (iface.role) {
case "Application":
populateHtmlUiFromApplicationInterface(containerElement, iface)
break;
case "Window":
populateHtmlUiFromWindowInterface(containerElement, iface)
break;
case "Button":
populateHtmlUiFromButtonInterface(containerElement, iface)
break;
case "StaticText":
populateHtmlUiFromStaticTextInterface(containerElement, iface)
break;
case "EditableText":
populateHtmlUiFromEditableTextInterface(containerElement, iface)
break;
default:
console.log("Unknown interface role " + iface.role);
populateHtmlUiFromUnknownInterface(containerElement, iface);
break;
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Qt for Wasm</title>
<link rel="stylesheet" href="reveal.js/css/reveal.css">
<link rel="stylesheet" href="reveal.js/css/theme/white.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="reveal.js/lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'reveal.js/css/print/pdf.css' : 'reveal.js/css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h2>Accessibility for Qt on WebAssembly</h2>
<p>Support Screen Readers and other assistive tools</p>
</section>
<section>
<iframe width="1200" height="1200" src = "printjson.html"></iframe>
</section>
<section>
<iframe width="1200" height="1200" src = "htmluielements.html"></iframe>
</section>
<section>
<iframe width="1200" height="1200" src = "accessibleqt.html"></iframe>
</section>
</div>
</div>
<script src="reveal.js/lib/js/head.min.js"></script>
<script src="reveal.js/js/reveal.js"></script>
<script>
// More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({
history: true,
slideNumber: true,
viewDistance: 3,
dependencies: [
{ src: 'reveal.js/plugin/markdown/marked.js' },
{ src: 'reveal.js/plugin/markdown/markdown.js' },
{ src: 'reveal.js/plugin/notes/notes.js', async: true },
{ src: 'reveal.js/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }
]
});
</script>
</body>
</html>
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>wasm</title>
<style>
html, body { padding: 0; margin : 0; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas { border: 0px none; background-color: white; width : 50%;}
</style>
</head>
<body onload="init()">
<figure style="overflow:visible;" id="spinner">
<center style="margin-top:1.5em; line-height:150%">
<img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
<strong>Qt for WebAssembly: wasm</strong>
<div id="status"></div>
<noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
</center>
</figure>
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<div>
<button type="button" onclick="printAccessibilityJson()"> PrintJson </button>
<pre id="accessibilityJsonText"> </pre>
</div>
<script type='text/javascript'>
function printAccessibilityJson() {
document.getElementById("accessibilityJsonText").innerHTML = Module.getAccessibilityJsonTree(0);
}
function init() {
var spinner = document.getElementById('spinner');
var canvas = document.getElementById('canvas');
var status = document.getElementById('status')
var qtLoader = QtLoader({
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
canvas.style.display = 'none';
status.innerHTML = loaderStatus + "...";
},
showError: function(errorText) {
status.innerHTML = errorText;
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showExit: function() {
status.innerHTML = "Application exit";
if (qtLoader.exitCode !== undefined)
status.innerHTML += " with code " + qtLoader.exitCode;
if (qtLoader.exitText !== undefined)
status.innerHTML += " (" + qtLoader.exitText + ")";
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showCanvas: function() {
spinner.style.display = 'none';
canvas.style.display = 'block';
return canvas;
},
});
qtLoader.loadEmscriptenModule("wasm");
}
</script>
<script type="text/javascript" src="qtloader.js"></script>
</body>
</html>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="462pt"
height="339pt"
viewBox="0 0 462 339"
version="1.1"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="TheQtCompany_logo_2.svg">
<metadata
id="metadata20">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs18" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1536"
inkscape:window-height="801"
id="namedview16"
showgrid="false"
inkscape:zoom="1.1138643"
inkscape:cx="270.58047"
inkscape:cy="174.65092"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
fill="#41cd52"
d=" M 63.50 0.00 L 462.00 0.00 L 462.00 274.79 C 440.60 296.26 419.13 317.66 397.61 339.00 L 0.00 339.00 L 0.00 63.39 C 21.08 42.18 42.34 21.13 63.50 0.00 Z"
id="path6" />
<path
d=" M 122.37 71.33 C 137.50 61.32 156.21 58.79 174.00 58.95 C 190.94 59.16 208.72 62.13 222.76 72.24 C 232.96 79.41 239.59 90.48 244.01 101.93 C 251.16 120.73 253.26 141.03 253.50 161.01 C 253.53 181.13 252.62 201.69 245.96 220.86 C 241.50 233.90 233.01 245.48 221.81 253.52 C 229.87 266.58 238.09 279.54 246.15 292.60 C 236.02 297.27 225.92 301.97 215.78 306.62 C 207.15 292.38 198.56 278.11 189.90 263.89 C 178.19 265.81 166.21 265.66 154.44 264.36 C 140.34 262.67 125.97 258.37 115.09 248.88 C 106.73 241.64 101.48 231.51 97.89 221.21 C 92.01 203.79 90.43 185.25 90.16 166.97 C 90.02 147.21 91.28 127.14 97.24 108.18 C 101.85 93.92 109.48 79.69 122.37 71.33 Z"
id="path8"
fill="#ffffff" />
<path
d=" M 294.13 70.69 C 304.73 70.68 315.33 70.68 325.93 70.69 C 325.96 84.71 325.92 98.72 325.95 112.74 C 339.50 112.76 353.05 112.74 366.60 112.75 C 366.37 121.85 366.12 130.95 365.86 140.05 C 352.32 140.08 338.79 140.04 325.25 140.07 C 325.28 163.05 325.18 186.03 325.30 209.01 C 325.56 215.30 325.42 221.94 328.19 227.75 C 330.21 232.23 335.65 233.38 340.08 233.53 C 348.43 233.50 356.77 233.01 365.12 232.86 C 365.63 241.22 366.12 249.59 366.60 257.95 C 349.99 260.74 332.56 264.08 316.06 258.86 C 309.11 256.80 302.63 252.19 299.81 245.32 C 294.76 233.63 294.35 220.62 294.13 208.07 C 294.11 185.40 294.13 162.74 294.12 140.07 C 286.73 140.05 279.34 140.08 271.95 140.05 C 271.93 130.96 271.93 121.86 271.95 112.76 C 279.34 112.73 286.72 112.77 294.11 112.74 C 294.14 98.72 294.10 84.71 294.13 70.69 Z"
id="path10"
fill="#ffffff" />
<path
fill="#41cd52"
d=" M 160.51 87.70 C 170.80 86.36 181.60 86.72 191.34 90.61 C 199.23 93.73 205.93 99.84 209.47 107.58 C 214.90 119.31 216.98 132.26 218.03 145.05 C 219.17 162.07 219.01 179.25 216.66 196.17 C 215.01 206.24 212.66 216.85 205.84 224.79 C 198.92 232.76 188.25 236.18 178.01 236.98 C 167.21 237.77 155.82 236.98 146.07 231.87 C 140.38 228.84 135.55 224.09 132.73 218.27 C 129.31 211.30 127.43 203.69 126.11 196.07 C 122.13 171.91 121.17 146.91 126.61 122.89 C 128.85 113.83 132.11 104.53 138.73 97.70 C 144.49 91.85 152.51 88.83 160.51 87.70 Z"
id="path12" />
</svg>
#!/bin/sh
DYLD_FRAMEWORK_PATH=/Users/msorvig/code/qt-5.12/qtbase/lib${DYLD_FRAMEWORK_PATH:+:$DYLD_FRAMEWORK_PATH}
export DYLD_FRAMEWORK_PATH
QT_PLUGIN_PATH=/Users/msorvig/code/qt-5.12/qtbase/plugins${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}
export QT_PLUGIN_PATH
exec /Users/msorvig/code/qt-5.12/qtbase/bin/uic "$@"
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>wasm</title>
<style>
html, body { padding: 0; margin : 0; overflow:hidden; height: 100% }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas { border: 0px none; background-color: white; height:100%; width:100%; }
</style>
</head>
<body onload="init()">
<figure style="overflow:visible;" id="spinner">
<center style="margin-top:1.5em; line-height:150%">
<img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
<strong>Qt for WebAssembly: wasm</strong>
<div id="status"></div>
<noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
</center>
</figure>
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type='text/javascript'>
function init() {
var spinner = document.getElementById('spinner');
var canvas = document.getElementById('canvas');
var status = document.getElementById('status')
var qtLoader = QtLoader({
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
canvas.style.display = 'none';
status.innerHTML = loaderStatus + "...";
},
showError: function(errorText) {
status.innerHTML = errorText;
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showExit: function() {
status.innerHTML = "Application exit";
if (qtLoader.exitCode !== undefined)
status.innerHTML += " with code " + qtLoader.exitCode;
if (qtLoader.exitText !== undefined)
status.innerHTML += " (" + qtLoader.exitText + ")";
spinner.style.display = 'block';
canvas.style.display = 'none';
},
showCanvas: function() {
spinner.style.display = 'none';
canvas.style.display = 'block';
return canvas;
},
});
qtLoader.loadEmscriptenModule("wasm");
}
</script>
<script type="text/javascript" src="qtloader.js"></script>
</body>
</html>
This diff is collapsed.
<head>
<meta charset="utf-8">
<title>Multicanvas Qt</title>
</head>
<body unselectable="on">
<div id="appcontrol" style="width = 100%; height: 40px;">App Control:</div>
<div id="rafdebug" style="position: absolute; bottom: 30; width = 100%; height: 30px;">RAF Control:</div>
<div id="timerdebug" style="position: absolute; bottom: 0; width = 100%; height: 30px;">Timer Control:</div>
<script type="text/javascript" src="qtloader.js"></script>
<script type="text/javascript" src="qwm.js"></script>
<script type="text/javascript" src="qrafdebug.js"></script>
<script type="text/javascript" src="qtimerdebug.js"></script>
<script type="text/javascript" src="qwebui.js"></script>
<script type="text/javascript">
// Application/example code
var initialWindows = [];
var windowCascade = 50;
var windowIndex = 0;
var createWindowButton = undefined;
var qtLoader = undefined;
function init()
{
// Set up Application Control
let appcontrolelement = document.querySelector("#appcontrol");
let createApplicationButton = qwebui_button(appcontrolelement, "Create Application", () => {
createApplicationButton.setEnabled(false);
createApplication();
});
createWindowButton = qwebui_button(appcontrolelement, "Create Window", createAdditinalWindow);
createWindowButton.setEnabled(false);
// Set up RequestAnimationFrame Control
qrafdebug_interpose();
let rafdebugelement = document.querySelector("#rafdebug");
qwebui_checkbox(rafdebugelement, "run", true, (checked) => {
qrafdebug_setRunning(checked);
rafdebugstep.setEnabled(!checked);
});
let rafdebugstep = qwebui_button(rafdebugelement, "step", qrafdebug_step);
rafdebugstep.setEnabled(false);
let label = qwebui_label(rafdebugelement, "");
qrafdebug_setPendingRequestCallback((pending) => label.setText(pending ? "frame requested" : ""))
// Set up TimerDebug Control
qtimerdebug_interpose();
let timerdebugelement = document.querySelector("#timerdebug");
qwebui_checkbox(timerdebugelement, "run", true, (checked) => {
qtimerdebug_setRunning(checked);
timerdebugstep.setEnabled(!checked);
timerdebugstepall.setEnabled(!checked);
});
let timerdebugstep = qwebui_button(timerdebugelement, "step", qtimerdebug_step);
timerdebugstep.setEnabled(false);
let timerdebugstepall = qwebui_button(timerdebugelement, "step all", qtimerdebug_stepAll);
timerdebugstepall.setEnabled(false);
let timersLabel = qwebui_label(timerdebugelement, "Timer Ticks: 0 Active Timers []");
// let intervalsLabel = qwebui_label(timerdebugelement, "Active Intervals []");
qtimerdebug_setActiveTimersChangedCallback((ticks, timers, intervals) => {
timersLabel.setText("Timer Ticks: " + ticks + " Active Timers [" + timers.join(", ") + "]");
});
}
function createApplication()
{
// Create 1 inital window
initialWindows = [createNumberedWindow(1, 50, 50)];
windowIndex = 2;
// load Qt
loadQt();
}
function loadQt()
{
qtloader = QtLoader({
canvasElements: initialWindows.map(function(window) { console.log(window.content); return window.content }),
showError: function(errorText) {
console.log("error " + errorText);
},
showCanvas: qtReady
});
qtloader.loadEmscriptenModule("multicanvas");
}
function qtReady()
{
console.log("qtReady");
createWindowButton.setEnabled(true);
initialWindows.map(function(window) { window.visible = true });
}
// Creates a <canvas> which usess 100% of the available size.
function createCanvas(i) {
var canvas = document.createElement("canvas");
canvas.id = "QtCanvas" + i;
canvas.style.width = "100%";
canvas.style.height = "100%";
return canvas;
}
function createNumberedWindow(number, x, y, )
{
var window = new Window(x, y);
window.title = "Canvas / QScreen " + number;
window.content = createCanvas(number);
window.onClose(() => qtloader.removeCanvasElement(window.content));
window.onResize(() => qtloader.resizeCanvasElement(window.content));
return window;
}
function createAdditinalWindow()
{
console.log("createAdditinalWindow");
var window = createNumberedWindow(windowIndex, 10 + windowCascade, 10 + windowCascade);
qtloader.addCanvasElement(window.content);
window.visible = true;
windowCascade += 25;
windowIndex += 1;
}
document.addEventListener("DOMContentLoaded", init);
</script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
<head>
<meta charset="utf-8">
<title>Multicanvas Qt</title>
</head>
<body unselectable="on">
<div id="appcontrol" style="width = 100%; height: 40px;">App Control:</div>
<div id="rafdebug" style="position: absolute; bottom: 0; width = 100%; height: 40px;">RAF Control:</div>
<script type="text/javascript" src="qtloader.js"></script>
<script type="text/javascript" src="qwm.js"></script>
<script type="text/javascript" src="qrafdebug.js"></script>
<script type="text/javascript" src="qwebui.js"></script>
<script type="text/javascript">
// Application/example code
var initialWindows = [];
var windowCascade = 50;
var windowIndex = 0;
var createWindowButton = undefined;
var qtLoader = undefined;
function frame()
{
console.log("frame");
window.requestAnimationFrame(frame);
// setTimeout(newframe, 0);
}
function newframe()
{
window.requestAnimationFrame(frame);
}
function init()
{
console.log("init");
// Set up RequestAnimationFrame Control
qrafdebug_interpose();
let rafdebugelement = document.querySelector("#rafdebug");
qwebui_checkbox(rafdebugelement, "run", true, qrafdebug_setRunning);
qwebui_button(rafdebugelement, "step", qrafdebug_step);
let label = qwebui_label(rafdebugelement, "");
qrafdebug_setPendingRequestCallback((pending) => label.setText(pending ? "frame requested" : ""))
// Set up Application Control
let appcontrolelement = document.querySelector("#appcontrol");
let createApplicationButton = qwebui_button(appcontrolelement, "Create Application", () => {
createApplicationButton.setEnabled(false);
createApplication();
});
createWindowButton = qwebui_button(appcontrolelement, "Create Window", createAdditinalWindow);
createWindowButton.setEnabled(false);