From e60b16129818af60e9be25bbd52e9410725e81f1 Mon Sep 17 00:00:00 2001 From: Wysa Date: Fri, 19 Mar 2021 15:01:21 +0800 Subject: [PATCH 01/14] perf improvement --- build.gradle.kts | 1 + .../projector/client/common/DrawEvent.kt | 3 +- .../projector/client/common/Renderer.kt | 8 ++- .../common/SingleRenderingSurfaceProcessor.kt | 65 ++++++++++------- .../client/common/canvas/Context2d.kt | 2 +- .../client/common/canvas/Extensions.kt | 7 +- .../client/common/canvas/DomContext2d.kt | 4 +- .../client/common/canvas/SwingContext2d.kt | 2 +- .../client/swing/AbstractWindowManager.kt | 5 +- .../client/web/ServerEventsProcessor.kt | 4 +- .../projector/client/web/window/Window.kt | 4 +- .../web/window/WindowDataEventsProcessor.kt | 3 +- .../src/main/kotlin/ElectronApp.kt | 72 +++++++++++++++++-- projector-launcher/src/main/kotlin/app.kt | 2 +- .../src/main/resources/assets/js/main.js | 70 +++++++++--------- .../src/main/resources/assets/js/preload.js | 7 ++ 16 files changed, 173 insertions(+), 86 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index fecf18df6..034d7d2fe 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,6 +37,7 @@ subprojects { version = "1.0-SNAPSHOT" repositories { + mavenLocal() jcenter() } diff --git a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/DrawEvent.kt b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/DrawEvent.kt index ded1151ac..0419a5df1 100644 --- a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/DrawEvent.kt +++ b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/DrawEvent.kt @@ -23,10 +23,11 @@ */ package org.jetbrains.projector.client.common +import org.jetbrains.projector.common.protocol.toClient.ServerWindowEvent import org.jetbrains.projector.common.protocol.toClient.ServerWindowPaintEvent import org.jetbrains.projector.common.protocol.toClient.ServerWindowStateEvent data class DrawEvent( - val prerequisites: List, + val prerequisites: List, val paintEvent: ServerWindowPaintEvent, ) diff --git a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/Renderer.kt b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/Renderer.kt index 6d8ca2a16..eb76b824a 100644 --- a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/Renderer.kt +++ b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/Renderer.kt @@ -115,7 +115,13 @@ class Renderer(private val renderingSurface: RenderingSurface) { private fun ensureTransform() { requestedState.transform.let { requestedTransform -> canvasState.transform.let { currentTransform -> - if (currentTransform != requestedTransform) { + if (!(requestedTransform[0] == currentTransform[0] && + requestedTransform[1] == currentTransform[1] && + requestedTransform[2] == currentTransform[2] && + requestedTransform[3] == currentTransform[3] && + requestedTransform[4] == currentTransform[4] && + requestedTransform[5] == currentTransform[5] + )) { applyTransform(requestedTransform) } } diff --git a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/SingleRenderingSurfaceProcessor.kt b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/SingleRenderingSurfaceProcessor.kt index 6aa5ac658..8154033f2 100644 --- a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/SingleRenderingSurfaceProcessor.kt +++ b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/SingleRenderingSurfaceProcessor.kt @@ -41,21 +41,18 @@ class SingleRenderingSurfaceProcessor(renderingSurface: RenderingSurface) { private val stateSaver = StateSaver(renderer, renderingSurface) @OptIn(ExperimentalStdlibApi::class) - fun process(drawEvents: ArrayDeque) { + fun process(drawEvents: List): List { stateSaver.restoreIfNeeded() - var removing = true - - drawEvents.removeAll { drawEvent -> - val drawIsSuccessful = handleDrawEvent(drawEvent) - - if (!drawIsSuccessful && removing) { - stateSaver.save() - - removing = false + var failed = false + return drawEvents.filter { drawEvent -> + if (failed) { + if (!handleDrawEvent(drawEvent)) { + stateSaver.save() + failed = true; + } } - - removing + failed } } @@ -88,6 +85,9 @@ class SingleRenderingSurfaceProcessor(renderingSurface: RenderingSurface) { is ServerSetTransformEvent -> renderer.setTransform(it.tx) is ServerWindowToDoStateEvent -> logUnsupportedCommand(it) + + else -> + logger.error { "Unexpected prerequisites [${it.toString()}] of ${command.paintEvent.toString()}" } } } @@ -250,24 +250,35 @@ class SingleRenderingSurfaceProcessor(renderingSurface: RenderingSurface) { } } - fun List.shrinkByPaintEvents(): List { - val result = mutableListOf() - - var prerequisites = mutableListOf() - - this.forEach { - Do exhaustive when (it) { - is ServerWindowStateEvent -> prerequisites.add(it) + fun List.concat(other: List): List { + if(this.isEmpty()){ + return other + }else{ + return this + other + } + } - is ServerWindowPaintEvent -> { - result.add(DrawEvent(prerequisites, it)) - prerequisites = mutableListOf() - } - } + fun List.shrinkByPaintEvents(): List { + if(this.isEmpty()){ + return listOf() } - if (prerequisites.isNotEmpty()) { - logger.error { "Bad commands received from server: ${prerequisites.size} state events are at the end" } + val result = mutableListOf() + var lastIndex = 0; + var curr = 0; + while(curr < this.size){ + if(this[curr] is ServerWindowPaintEvent){ + result.add(DrawEvent( + if(curr - lastIndex > 0){ + this.subList(lastIndex,curr).toList() + }else{ + listOf() + }, + this[curr] as ServerWindowPaintEvent + )) + lastIndex = curr + } + curr ++ } return result diff --git a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Context2d.kt b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Context2d.kt index 5c9b9b6ce..b6515b0f8 100644 --- a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Context2d.kt +++ b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Context2d.kt @@ -89,7 +89,7 @@ interface Context2d { fun setTextBaseline(baseline: TextBaseline) fun setTextAlign(align: TextAlign) fun setTransform(m11: Double, m12: Double, m21: Double, m22: Double, dx: Double, dy: Double) - fun setLineDash(lineDash: DoubleArray) + fun setLineDash(lineDash: List) fun setLineDashOffset(offset: Double) fun measureText(str: String): Point diff --git a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Extensions.kt b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Extensions.kt index c84b0fe40..b110b5398 100644 --- a/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Extensions.kt +++ b/projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/Extensions.kt @@ -78,7 +78,7 @@ object Extensions { setLineCap(strokeData.endCap.toCanvasLineCap()) setLineJoin(strokeData.lineJoin.toCanvasLineJoin()) setMiterLimit(strokeData.miterLimit.toDouble()) - setLineDash(strokeData.dashArray?.map(Float::toDouble)?.toDoubleArray() ?: DoubleArray(0)) + setLineDash(strokeData.dashArray ?: listOf()) setLineDashOffset(strokeData.dashPhase.toDouble()) } } @@ -127,9 +127,8 @@ object Extensions { val b = colorValue and 0xFF val g = (colorValue ushr 8) and 0xFF val r = (colorValue ushr 16) and 0xFF - val a = ((colorValue ushr 24) and 0xFF) / 255.0 - - return "rgba($r,$g,$b,$a)" + val a = ((colorValue ushr 24) and 0xFF) + return "#" + ((r shl 24) or (g shl 16) or (b shl 8) or a).toString(16) } } diff --git a/projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomContext2d.kt b/projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomContext2d.kt index 9ba1fe102..aedea5974 100644 --- a/projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomContext2d.kt +++ b/projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomContext2d.kt @@ -276,8 +276,8 @@ internal class DomContext2d(private val myContext2d: CanvasRenderingContext2D) : myContext2d.setTransform(m11, m12, m21, m22, dx, dy) } - override fun setLineDash(lineDash: DoubleArray) { - myContext2d.setLineDash(lineDash.toTypedArray()) + override fun setLineDash(lineDash: List) { + myContext2d.setLineDash(lineDash as Array) } override fun setLineDashOffset(offset: Double) { diff --git a/projector-client-common/src/jvmMain/kotlin/org/jetbrains/projector/client/common/canvas/SwingContext2d.kt b/projector-client-common/src/jvmMain/kotlin/org/jetbrains/projector/client/common/canvas/SwingContext2d.kt index 9d27c22af..ca686f087 100644 --- a/projector-client-common/src/jvmMain/kotlin/org/jetbrains/projector/client/common/canvas/SwingContext2d.kt +++ b/projector-client-common/src/jvmMain/kotlin/org/jetbrains/projector/client/common/canvas/SwingContext2d.kt @@ -265,7 +265,7 @@ class SwingContext2d(graphics: Graphics2D) : Context2d { graphics.transform = AffineTransform(m11, m12, m21, m22, dx, dy) } - override fun setLineDash(lineDash: DoubleArray) { + override fun setLineDash(lineDash: List) { myCurrentStroke = myCurrentStroke.change(dash = if(lineDash.isEmpty()) null else FloatArray(lineDash.size) { lineDash[it].toFloat() }) } diff --git a/projector-client-swing/src/main/kotlin/org/jetbrains/projector/client/swing/AbstractWindowManager.kt b/projector-client-swing/src/main/kotlin/org/jetbrains/projector/client/swing/AbstractWindowManager.kt index 669ba29b1..aa4840386 100644 --- a/projector-client-swing/src/main/kotlin/org/jetbrains/projector/client/swing/AbstractWindowManager.kt +++ b/projector-client-swing/src/main/kotlin/org/jetbrains/projector/client/swing/AbstractWindowManager.kt @@ -69,9 +69,8 @@ abstract class AbstractWindowManager { return } - window.drawEvents.addAll(drawEvents.shrinkByPaintEvents()) - window.processor.process(window.drawEvents) + window.drawEvents = window.processor.process(window.drawEvents + drawEvents.shrinkByPaintEvents()) window.surface.flush() @@ -81,7 +80,7 @@ abstract class AbstractWindowManager { inner class FrameData( val frame: FrameType, var windowData: WindowData, - val drawEvents: ArrayDeque, + var drawEvents: List, val surface: DoubleBufferedRenderingSurface, val processor: SingleRenderingSurfaceProcessor, ) diff --git a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/ServerEventsProcessor.kt b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/ServerEventsProcessor.kt index c308e9b4d..f30ef4d01 100644 --- a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/ServerEventsProcessor.kt +++ b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/ServerEventsProcessor.kt @@ -98,9 +98,9 @@ class ServerEventsProcessor(private val windowDataEventsProcessor: WindowDataEve val offscreenProcessor = ImageCacher.getOffscreenProcessor(target) // todo: don't create this deque every time - val drawEvents = ArrayDeque().apply { addAll(event.drawEvents.shrinkByPaintEvents()) } + //val drawEvents = ArrayDeque().apply { addAll() } - offscreenProcessor.process(drawEvents) + offscreenProcessor.process(event.drawEvents.shrinkByPaintEvents()) windowDataEventsProcessor.redrawWindows() } diff --git a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/Window.kt b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/Window.kt index 0bf358a3c..9eed88dd0 100644 --- a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/Window.kt +++ b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/Window.kt @@ -53,7 +53,7 @@ class Window(windowData: WindowData, private val stateMachine: ClientStateMachin val id = windowData.id @OptIn(ExperimentalStdlibApi::class) - val drawEvents = ArrayDeque() + var drawEvents = listOf() var title: String? = null set(value) { @@ -256,7 +256,7 @@ class Window(windowData: WindowData, private val stateMachine: ClientStateMachin @OptIn(ExperimentalStdlibApi::class) fun drawBufferedEvents() { - commandProcessor.process(drawEvents) + drawEvents = commandProcessor.process(drawEvents) renderingSurface.flush() header?.draw() } diff --git a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/WindowDataEventsProcessor.kt b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/WindowDataEventsProcessor.kt index 5834ce2c5..b84c3cd2d 100644 --- a/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/WindowDataEventsProcessor.kt +++ b/projector-client-web/src/main/kotlin/org/jetbrains/projector/client/web/window/WindowDataEventsProcessor.kt @@ -24,6 +24,7 @@ package org.jetbrains.projector.client.web.window import kotlinx.browser.document +import org.jetbrains.projector.client.common.SingleRenderingSurfaceProcessor.Companion.concat import org.jetbrains.projector.client.common.SingleRenderingSurfaceProcessor.Companion.shrinkByPaintEvents import org.jetbrains.projector.client.common.misc.ImageCacher import org.jetbrains.projector.client.common.misc.ParamsProvider @@ -137,7 +138,7 @@ class WindowDataEventsProcessor(private val windowManager: WindowManager) { val newEvents = commands.shrinkByPaintEvents() if (newEvents.isNotEmpty()) { - window.drawEvents.addAll(newEvents) + window.drawEvents = window.drawEvents.concat(newEvents) window.drawBufferedEvents() } } diff --git a/projector-launcher/src/main/kotlin/ElectronApp.kt b/projector-launcher/src/main/kotlin/ElectronApp.kt index 23cf54435..bb98d8515 100644 --- a/projector-launcher/src/main/kotlin/ElectronApp.kt +++ b/projector-launcher/src/main/kotlin/ElectronApp.kt @@ -24,6 +24,7 @@ @file:Suppress("JSCODE_ARGUMENT_SHOULD_BE_CONSTANT") import Electron.* +import kotlinext.js.jsObject import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.await import kotlinx.coroutines.launch @@ -77,9 +78,18 @@ class ElectronApp(val url: String) { } } """ - - var preloadPath = path.normalize(path.join(__dirname, "../assets/js/preload.js")) - this.mainWindow = BrowserWindow(js(windowOptions)(workAreaSize.width, workAreaSize.height, preloadPath)) + //js(windowOptions)(workAreaSize.width, workAreaSize.height, preloadPath) + val preloadPath: String = path.normalize(path.join(__dirname, "../app/assets/js/preload.js")) + this.mainWindow = BrowserWindow( jsObject { + width = workAreaSize.width + height = workAreaSize.height + webPreferences = jsObject { + contextIsolation = true + webSecurity = false + worldSafeExecuteJavaScript = true + preload = preloadPath + } + }) if (process.platform.unsafeCast().toLowerCase() !in setOf("win32", "darwin")) { // change icon for Linux and other systems: @@ -167,9 +177,61 @@ class ElectronApp(val url: String) { } fun registerApplicationLevelEvents() { + Menu.setApplicationMenu(Menu.buildFromTemplate( + arrayOf( + jsObject{ + label = app.name + submenu = arrayOf( + jsObject { + role = "about" + }, + jsObject { + role = "quit" + } + ) + }, + jsObject { + label = "Edit" + submenu = arrayOf( + jsObject { + role = "cut" + }, + jsObject { + role = "copy" + }, + jsObject { + role = "paste" + }, + jsObject { + role = "undo" + }, + jsObject { + role = "redo" + } + ) + + }, + jsObject{ + label = "View" + submenu = arrayOf( + jsObject { + role = "forceReload" + } + ) + }, + jsObject { + label = "Developer" + submenu = arrayOf( + jsObject { + role = "toggleDevTools" + } + ) + } + ) + )) app.whenReady().then { this.createWindow() - ElectronUtil.disableAllStandardShortcuts() + //ElectronUtil.disableAllStandardShortcuts() if (GlobalSettings.DEVELOPER_TOOLS_ENABLED) { this.mainWindow.webContents.openDevTools() @@ -181,8 +243,6 @@ class ElectronApp(val url: String) { } ipcMain.on("projector-dom-ready") { event, _ -> - ElectronUtil.disableAllStandardShortcuts() - var defaultUrl = this.configData.defaultUrl if (null != defaultUrl) { event.sender.send("projector-set-url", defaultUrl) diff --git a/projector-launcher/src/main/kotlin/app.kt b/projector-launcher/src/main/kotlin/app.kt index caa140a43..7e5d5c8e2 100644 --- a/projector-launcher/src/main/kotlin/app.kt +++ b/projector-launcher/src/main/kotlin/app.kt @@ -31,7 +31,7 @@ fun main() { val argv = commandLineArguments() var url = argv.last() - if (url.endsWith("projector.exe")) { + if (url == null || !(url.startsWith("http") || url.startsWith("ws"))) { url = "" } diff --git a/projector-launcher/src/main/resources/assets/js/main.js b/projector-launcher/src/main/resources/assets/js/main.js index ebe078038..77ab4f45a 100644 --- a/projector-launcher/src/main/resources/assets/js/main.js +++ b/projector-launcher/src/main/resources/assets/js/main.js @@ -23,46 +23,48 @@ */ import {cacheNewUrlValue, populateDataList, projectorLauncherStorageKey, storage, urlCache} from './modules/urlcache.js'; -window.onload = function () { - document.getElementById("url-text-field").focus(); -}; +(function () { -if (storage.getItem(projectorLauncherStorageKey)) { - let parse = JSON.parse(storage.getItem(projectorLauncherStorageKey)); - parse.forEach(url => urlCache.set(url, url)); - populateDataList(); -} -document.querySelector('#connect-button').addEventListener('click', function () { - connect() -}); -document.querySelector('#url-text-field').addEventListener('keypress', function (e) { - if (e.key === 'Enter') { - connect() - } -}); -function connect() { - let url = document.getElementById("url-text-field").value; - if (isEmpty(url)) { - return; + window.onload = function () { + document.getElementById("url-text-field").focus(); + }; + + if (storage.getItem(projectorLauncherStorageKey)) { + let parse = JSON.parse(storage.getItem(projectorLauncherStorageKey)); + parse.forEach(url => urlCache.set(url, url)); + populateDataList(); } - const {ipcRenderer} = require('electron') - ipcRenderer.send("projector-connect", url); + document.querySelector('#connect-button').addEventListener('click', function () { + connect() + }); + + document.querySelector('#url-text-field').addEventListener('keypress', function (e) { + if (e.key === 'Enter') { + connect() + } + }); - cacheNewUrlValue(url); -} + function connect() { + let url = document.getElementById("url-text-field").value; + if (isEmpty(url)) { + return; + } -//$( document ).ready(function() { -const {ipcRenderer} = require('electron') -ipcRenderer.on('projector-set-url', (event, arg) => { - console.log("New URL: " + arg); - document.getElementById("url-text-field").value = arg -}) -//}); + window.ipcRenderer.send("projector-connect", url); -function isEmpty(str) { - return (!str || 0 === str.length); -} + cacheNewUrlValue(url); + } + + window.ipcRenderer.on('projector-set-url', (event, arg) => { + console.log("New URL: " + arg); + document.getElementById("url-text-field").value = arg + }) + + function isEmpty(str) { + return (!str || 0 === str.length); + } +})(); diff --git a/projector-launcher/src/main/resources/assets/js/preload.js b/projector-launcher/src/main/resources/assets/js/preload.js index e4e599efc..b5d2317fd 100644 --- a/projector-launcher/src/main/resources/assets/js/preload.js +++ b/projector-launcher/src/main/resources/assets/js/preload.js @@ -21,6 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +const electron = require('electron'); + function domReady(fn) { if (document.readyState === "complete" || document.readyState === "interactive") { setTimeout(fn, 1); @@ -30,6 +32,11 @@ function domReady(fn) { } } +electron.contextBridge.exposeInMainWorld('ipcRenderer', { + send: (name,param) => electron.ipcRenderer.send(name, param), + on: (name,callback) => electron.ipcRenderer.on(name,callback) +}) + domReady(function () { console.log("DOM loaded") const {ipcRenderer} = require('electron') From 4872a4e937f6523df443accf48f4e91bd8504bb4 Mon Sep 17 00:00:00 2001 From: Wysa Date: Thu, 1 Apr 2021 10:46:17 +0800 Subject: [PATCH 02/14] Performance tuning --- .idea/codeStyles/Project.xml | 27 +- gradle.properties | 10 +- projector-client-common/build.gradle.kts | 2 + .../projector/client/common/Renderer.kt | 61 ++-- .../common/RenderingSurfaceProcessor.kt | 31 ++ .../common/SingleRenderingSurfaceProcessor.kt | 22 +- .../projector/client/common/canvas/Canvas.kt | 8 +- .../client/common/canvas/CanvasFactory.kt | 1 + .../client/common/canvas/Context2d.kt | 4 +- .../common/canvas/ContextBitmapRenderer.kt | 30 ++ .../client/common/canvas/Extensions.kt | 21 +- .../client/common/canvas/RenderingContext.kt | 27 ++ .../DoubleBufferedRenderingSurface.kt | 24 +- .../buffering/UnbufferedRenderingSurface.kt | 1 + .../client/common/misc/ImageCacher.kt | 21 +- .../client/common/canvas/CanvasFactory.kt | 11 +- .../client/common/canvas/DomCanvas.kt | 51 +++- .../client/common/canvas/DomContext2d.kt | 40 ++- .../common/canvas/DomContextBitmapRenderer.kt | 39 +++ .../common/canvas/DomOffscreenCanvas.kt | 61 ++++ .../client/common/canvas/ExperimentalAPI.kt | 49 ++++ .../client/common/canvas/JsExtensions.kt | 48 ++++ .../JsSingleRenderingSurfaceProcessor.kt | 268 ++++++++++++++++++ .../client/common/canvas/SwingCanvas.kt | 17 +- .../client/common/canvas/SwingContext2d.kt | 3 +- .../client/swing/AbstractWindowManager.kt | 8 +- .../projector/client/swing/SwingClient.kt | 8 +- projector-client-web/build.gradle.kts | 4 + .../projector/client/web/Application.kt | 7 +- .../client/web/ServerEventsProcessor.kt | 13 +- .../ManualJsonToClientMessageDecoder.kt | 230 +++++++-------- .../projector/client/web/state/ClientState.kt | 45 +-- .../client/web/state/ClientStateMachine.kt | 1 + .../projector/client/web/state/ProjectorUI.kt | 2 +- .../client/web/window/OnScreenMessenger.kt | 2 +- .../projector/client/web/window/Window.kt | 137 +++++---- .../web/window/WindowDataEventsProcessor.kt | 24 +- .../client/web/window/WindowHeader.kt | 35 +-- .../src/main/resources/index.html | 15 +- .../common/protocol/data/StrokeData.kt | 2 +- .../protocol/toClient/ServerWindowEvent.kt | 155 ++++++++-- .../projector/intTest/ConnectionUtil.kt | 8 +- .../server/core/convert/toClient/Convert.kt | 4 +- settings.gradle.kts | 1 + 44 files changed, 1181 insertions(+), 397 deletions(-) create mode 100644 projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/RenderingSurfaceProcessor.kt create mode 100644 projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/ContextBitmapRenderer.kt create mode 100644 projector-client-common/src/commonMain/kotlin/org/jetbrains/projector/client/common/canvas/RenderingContext.kt create mode 100644 projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomContextBitmapRenderer.kt create mode 100644 projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/DomOffscreenCanvas.kt create mode 100644 projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/ExperimentalAPI.kt create mode 100644 projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/JsExtensions.kt create mode 100644 projector-client-common/src/jsMain/kotlin/org/jetbrains/projector/client/common/canvas/JsSingleRenderingSurfaceProcessor.kt diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 04bf1ebc5..cab3bdd39 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -39,16 +39,7 @@ - -