Skip to content
This repository has been archived by the owner on Mar 26, 2024. It is now read-only.

Commit

Permalink
Support proceeding ClientSpeculativeKeyPressEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
ARTI1208 committed Aug 25, 2021
1 parent 1b797b0 commit dc49e77
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 14 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ intellijPluginVersion=1.1.2
javassistVersion=3.27.0-GA
kotlinVersion=1.5.20
mockitoKotlinVersion=3.2.0
projectorClientVersion=7bff9b80
projectorClientVersion=b137a164
projectorClientGroup=com.github.JetBrains.projector-client
targetJvm=11
# Give JitPack some time to build projector-client:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

package org.jetbrains.projector.server

import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.command.executeCommand
import com.intellij.openapi.editor.EditorFactory
import org.java_websocket.WebSocket
import org.java_websocket.exceptions.WebsocketNotConnectedException
import org.jetbrains.projector.awt.PClipboard
Expand Down Expand Up @@ -111,6 +115,8 @@ class ProjectorServer private constructor(

private val markdownQueue = ConcurrentLinkedQueue<ServerMarkdownEvent>()

private val speculativeQueue = ConcurrentLinkedQueue<Pair<SpeculativeEvent, String>>()

private var windowColorsEvent: ServerWindowColorsEvent? = null

private val ideaColors = IdeColors { colors ->
Expand Down Expand Up @@ -273,7 +279,7 @@ class ProjectorServer private constructor(
}

@OptIn(ExperimentalStdlibApi::class)
private fun createDataToSend(): List<ServerEvent> {
private fun createDataToSend(): List<FilterableEvent<*>> {
val clipboardEvent = when (val clipboardContents = PClipboard.extractLastContents()) {
null -> emptyList()

Expand Down Expand Up @@ -326,17 +332,26 @@ class ProjectorServer private constructor(

val markdownEvents = extractData(markdownQueue)

val commandsCount = caretInfoEvents.size +
newImagesCopy.size + clipboardEvent.size + drawCommands.size + windowSetChangedEvent.size + markdownEvents.size + 1
val speculativeEvents = extractData(speculativeQueue).map {
FilterableEvent(it.first) { _, settings -> it.second == settings.address }
}

val commandsCount = caretInfoEvents.size + newImagesCopy.size + clipboardEvent.size + drawCommands.size +
windowSetChangedEvent.size + markdownEvents.size + speculativeEvents.size + 1

fun toFilterableEvent(event: ServerEvent): FilterableEvent<*> {
return FilterableEvent(event) { _, _ -> true }
}

val allEvents = buildList(commandsCount) {
addAll(caretInfoEvents)
addAll(newImagesCopy)
addAll(clipboardEvent)
addAll(drawCommands)
addAll(windowSetChangedEvent)
addAll(markdownEvents)
windowColorsEvent?.let { add(it); windowColorsEvent = null }
addAll(caretInfoEvents.map(::toFilterableEvent))
addAll(newImagesCopy.map(::toFilterableEvent))
addAll(clipboardEvent.map(::toFilterableEvent))
addAll(drawCommands.map(::toFilterableEvent))
addAll(windowSetChangedEvent.map(::toFilterableEvent))
addAll(markdownEvents.map(::toFilterableEvent))
addAll(speculativeEvents)
windowColorsEvent?.let { add(toFilterableEvent(it)); windowColorsEvent = null }
}

ProjectorImageCacher.collectGarbage()
Expand Down Expand Up @@ -493,6 +508,45 @@ class ProjectorServer private constructor(
}

is ClientWindowCloseEvent -> SwingUtilities.invokeLater { PWindow.getWindow(message.windowId)?.close() }
is ClientSpeculativeKeyPressEvent -> {

val editor = EditorFactory.getInstance().allEditors.find {
System.identityHashCode(it) == message.editorId
}

if (editor == null) {
processMessage(clientSettings, message.originalEvent) // fallback
} else {

invokeAndWaitIfNeeded {
runWriteAction {
executeCommand {
val insertedString = message.originalEvent.char.toString()

val selectionInfo = message.selectionInfo

editor.document.apply {
if (selectionInfo != null) {
replaceString(selectionInfo.startOffset, selectionInfo.endOffset, insertedString)
}
else {
insertString(message.offset, insertedString)
}
}

val newOffset = (selectionInfo?.startOffset ?: message.offset) + insertedString.length

editor.caretModel.primaryCaret.apply {
removeSelection()
moveToOffset(newOffset)
}
}
}
}
}

speculativeQueue.add(SpeculativeEvent.SpeculativeStringDrawnEvent(message.requestId) to clientSettings.address!!)
}
}
}

Expand Down Expand Up @@ -642,13 +696,18 @@ class ProjectorServer private constructor(
updateClientsCount()
}

private fun sendPictures(dataToSend: List<ServerEvent>) {
private fun sendPictures(dataToSend: List<FilterableEvent<*>>) {
httpWsTransport.forEachOpenedConnection { client ->
val readyClientSettings = client.getAttachment<ClientSettings?>() as? ReadyClientSettings ?: return@forEachOpenedConnection

val compressed = with(readyClientSettings.setUpClientData) {
val requestedData = extractData(readyClientSettings.requestedData)
val message = requestedData + dataToSend
val message = requestedData + dataToSend.mapNotNull {
when (it.isValidForClient(readyClientSettings)) {
true -> it.originalEvent
false -> null
}
}

if (message.isEmpty()) {
return@forEachOpenedConnection
Expand Down Expand Up @@ -919,4 +978,8 @@ class ProjectorServer private constructor(

fun getEnvPort() = (getProperty(PORT_PROPERTY_NAME) ?: getProperty(PORT_PROPERTY_NAME_OLD))?.toIntOrNull() ?: DEFAULT_PORT
}

class FilterableEvent<T: ServerEvent>(val originalEvent: T, private val filter: (T, ReadyClientSettings) -> Boolean) {
fun isValidForClient(clientSettings: ReadyClientSettings) = filter(originalEvent, clientSettings)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import org.jetbrains.projector.common.protocol.data.CommonRectangle
import org.jetbrains.projector.common.protocol.data.Point
import org.jetbrains.projector.common.protocol.toClient.ServerCaretInfoChangedEvent
import org.jetbrains.projector.common.protocol.toClient.data.idea.CaretInfo
import org.jetbrains.projector.common.protocol.toClient.data.idea.SelectionInfo
import org.jetbrains.projector.server.core.ij.invokeWhenIdeaIsInitialized
import org.jetbrains.projector.server.platform.getTextAttributesCompat
import org.jetbrains.projector.server.platform.readAction
Expand Down Expand Up @@ -123,12 +124,41 @@ class CaretInfoUpdater(private val onCaretInfoChanged: (ServerCaretInfoChangedEv
val points = focusedEditor.caretModel.allCarets.map {
val caretLocationInEditor = invokeAndWaitIfNeeded { it.editor.visualPositionToXY(it.visualPosition) }

val caretOffset = readAction { it.offset }
val selectionStart = readAction { it.selectionStart }
val selectionEnd = readAction { it.selectionEnd }

val selectionInfo = if (selectionStart == selectionEnd) {
null
} else {
val selectionStartPointVisual = invokeAndWaitIfNeeded { it.editor.visualPositionToXY(it.selectionStartPosition) }

val selectionStartPoint = Point(
x = (editorLocationInWindowX + selectionStartPointVisual.x).toDouble(),
y = (editorLocationInWindowY + selectionStartPointVisual.y).toDouble(),
)

val selectionEndPointVisual = invokeAndWaitIfNeeded { it.editor.visualPositionToXY(it.selectionEndPosition) }

val selectionEndPoint = Point(
x = (editorLocationInWindowX + selectionEndPointVisual.x).toDouble(),
y = (editorLocationInWindowY + selectionEndPointVisual.y).toDouble(),
)

SelectionInfo(
selectionStartPoint,
selectionStart,
selectionEndPoint,
selectionEnd,
)
}

val point = Point(
x = (editorLocationInWindowX + caretLocationInEditor.x).toDouble(),
y = (editorLocationInWindowY + caretLocationInEditor.y).toDouble(),
)

CaretInfo(point)
CaretInfo(point, caretOffset, selectionInfo)
}

val isVerticalScrollBarVisible = visibleEditorRect.height < focusedEditorComponent.height
Expand All @@ -154,6 +184,8 @@ class CaretInfoUpdater(private val onCaretInfoChanged: (ServerCaretInfoChangedEv
verticalScrollBarWidth = verticalScrollBarWidth,
textColor = textColor,
backgroundColor = backgroundColor,
editorScrolled = Point(visibleEditorRect.x.toDouble(), visibleEditorRect.y.toDouble()),
editorId = System.identityHashCode(focusedEditor),
)
}
}
Expand Down

0 comments on commit dc49e77

Please sign in to comment.