forked from androidx/androidx
-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Listen to browser clipboard events and bind them with Compose TextFie…
…ldSelectionManager and SelectionManager (#1206) **Notes:** I had to almost copy/paste the code for k/js and k/wasm because of k/wasm-js and k/js-js interop differences. The function is not too big, so I consider it as a compromise. **Test in mpp:demo:** - Components -> Selection : select some text and press Cmd + C or Ctrl + C, try to paste it then somewhere - Components -> TextFields -> Almost FullScreen: Try all cobminations --------- Co-authored-by: Shagen Ogandzhanian <shagen.ogandzhanian@jetbrains.com>
- Loading branch information
Showing
14 changed files
with
373 additions
and
15 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
...undation/src/commonMain/kotlin/androidx/compose/foundation/text/ClipboardEventsHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.foundation.text | ||
|
||
import androidx.compose.runtime.Composable | ||
|
||
@Composable | ||
internal expect inline fun rememberClipboardEventsHandler( | ||
crossinline onPaste: (String) -> Unit = {}, | ||
crossinline onCopy: () -> String? = { null }, | ||
crossinline onCut: () -> String? = { null }, | ||
isEnabled: Boolean | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
...oundation/src/jsMain/kotlin/androidx/compose/foundation/text/ClipboardEventsHandler.js.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.foundation.text | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.DisposableEffect | ||
import androidx.compose.runtime.NonRestartableComposable | ||
import kotlinx.browser.document | ||
import org.w3c.dom.clipboard.ClipboardEvent | ||
import org.w3c.dom.events.EventListener | ||
|
||
@Composable | ||
@NonRestartableComposable | ||
internal actual inline fun rememberClipboardEventsHandler( | ||
crossinline onPaste: (String) -> Unit, | ||
crossinline onCopy: () -> String?, | ||
crossinline onCut: () -> String?, | ||
isEnabled: Boolean | ||
) { | ||
if (isEnabled) { | ||
DisposableEffect(Unit) { | ||
|
||
val copyListener = EventListener { event -> | ||
val textToCopy = onCopy() | ||
if (textToCopy != null && event is ClipboardEvent) { | ||
event.clipboardData?.setData("text/plain", textToCopy) | ||
event.preventDefault() | ||
} | ||
} | ||
|
||
val pasteListener = EventListener { event -> | ||
if (event is ClipboardEvent) { | ||
val textToPaste = event.clipboardData?.getData("text/plain") ?: "" | ||
onPaste(textToPaste) | ||
event.preventDefault() | ||
} | ||
} | ||
|
||
val cutListener = EventListener { event -> | ||
val cutText = onCut() | ||
if (cutText != null && event is ClipboardEvent) { | ||
event.clipboardData?.setData("text/plain", cutText) | ||
event.preventDefault() | ||
} | ||
} | ||
|
||
document.addEventListener("copy", copyListener) | ||
document.addEventListener("paste", pasteListener) | ||
document.addEventListener("cut", cutListener) | ||
|
||
onDispose { | ||
document.removeEventListener("copy", copyListener) | ||
document.removeEventListener("paste", pasteListener) | ||
document.removeEventListener("cut", cutListener) | ||
} | ||
} | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...ation/foundation/src/jsWasmMain/kotlin/androidx/compose/foundation/text/KeyMapping.web.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright 2023 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.foundation.text | ||
|
||
import androidx.compose.ui.input.key.Key | ||
import androidx.compose.ui.input.key.KeyEvent | ||
import androidx.compose.ui.input.key.isCtrlPressed | ||
import androidx.compose.ui.input.key.isMetaPressed | ||
import androidx.compose.ui.input.key.key | ||
import org.jetbrains.skiko.OS | ||
import org.jetbrains.skiko.hostOs | ||
|
||
internal actual val platformDefaultKeyMapping: KeyMapping = createPlatformDefaultKeyMapping(hostOs) | ||
|
||
internal fun createPlatformDefaultKeyMapping(platform: OS): KeyMapping { | ||
val keyMapping = when (platform) { | ||
OS.MacOS -> createMacosDefaultKeyMapping() | ||
else -> defaultKeyMapping | ||
} | ||
return object : KeyMapping { | ||
private val clipboardKeys = setOf(Key.C, Key.V, Key.X) | ||
|
||
override fun map(event: KeyEvent): KeyCommand? { | ||
val isCtrlOrCmd = if (hostOs.isMacOS) event.isMetaPressed else event.isCtrlPressed | ||
if (isCtrlOrCmd && event.key in clipboardKeys) { | ||
// we let a browser dispatch a clipboard event | ||
return null | ||
} | ||
return keyMapping.map(event) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...ion/src/jvmMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.jvm.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.foundation.text.selection | ||
|
||
internal actual val SelectionManager.skipCopyKeyEvent: Boolean | ||
get() = false |
29 changes: 29 additions & 0 deletions
29
...ation/foundation/src/nativeMain/kotlin/androidx/compose/foundation/text/Actuals.native.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright 2024 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package androidx.compose.foundation.text | ||
|
||
import androidx.compose.runtime.Composable | ||
|
||
@Composable | ||
internal actual inline fun rememberClipboardEventsHandler( | ||
crossinline onPaste: (String) -> Unit, | ||
crossinline onCopy: () -> String?, | ||
crossinline onCut: () -> String?, | ||
isEnabled: Boolean | ||
) { | ||
// nothing to do | ||
} |
Oops, something went wrong.