Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed drag-and-drop in the case when there are multiple compositions …
…attached to the same root (AWT) container. (#1493) There is currently a problem with the DnD implementation because on the one hand the API implies a `DragAndDropManager` instance for each composition (`RootNodeOwner`) and on other hand, `AwtDragAndDropManager` needs to install its own AWT `TransferHandler` and `DropTarget` into the root container. In this PR the first attached `AwtDragAndDropManager` installs a `TransferHandler` and a `DropTarget` into the root container, and the following `AwtDragAndDropManager`s reuse them. The `DropTarget` forwards its events to the `AwtDragAndDropManager` of the top-most "focusable" `RootNodeOwner`. Fixes https://youtrack.jetbrains.com/issue/CMP-5855/Popup-breaks-drag-and-drop-functionality-on-Desktop ## Testing Tested manually with ``` @OptIn(ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class) fun main() = singleWindowApplication { val exportedText = "Hello, DnD!" Row( horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxSize() ) { val textMeasurer = rememberTextMeasurer() Box(Modifier .size(200.dp) .background(Color.LightGray) .dragAndDropSource( drawDragDecoration = { drawRect( color = Color.White, topLeft = Offset(x = 0f, y = size.height/4), size = Size(size.width, size.height/2) ) val textLayoutResult = textMeasurer.measure( text = AnnotatedString(exportedText), layoutDirection = layoutDirection, density = this ) drawText( textLayoutResult = textLayoutResult, topLeft = Offset( x = (size.width - textLayoutResult.size.width) / 2, y = (size.height - textLayoutResult.size.height) / 2, ) ) } ) { detectDragGestures( onDragStart = { offset -> startTransfer( DragAndDropTransferData( transferable = DragAndDropTransferable( StringSelection(exportedText) ), supportedActions = listOf( DragAndDropTransferAction.Copy, DragAndDropTransferAction.Move, DragAndDropTransferAction.Link, ), dragDecorationOffset = offset, onTransferCompleted = { action -> println("Action at source: $action") } ) ) }, onDrag = { _, _ -> }, ) } ) { Text("Drag Me", Modifier.align(Alignment.Center)) } var showTargetBorder by remember { mutableStateOf(false)} var targetText by remember { mutableStateOf("Drop Here") } val coroutineScope = rememberCoroutineScope() val dragAndDropTarget = remember { object: DragAndDropTarget { override fun onStarted(event: DragAndDropEvent) { showTargetBorder = true } override fun onEnded(event: DragAndDropEvent) { showTargetBorder = false } override fun onDrop(event: DragAndDropEvent): Boolean { println("Action at target: ${event.action}") val result = (targetText == "Drop Here")// && (event.action == DragAndDropTransferAction.Link) targetText = event.awtTransferable.let { if (it.isDataFlavorSupported(DataFlavor.stringFlavor)) it.getTransferData(DataFlavor.stringFlavor) as String else it.transferDataFlavors.first().humanPresentableName } coroutineScope.launch { delay(2000) targetText = "Drop Here" } return result } } } Box(Modifier .size(200.dp) .background(Color.LightGray) .then( if (showTargetBorder) Modifier.border(BorderStroke(3.dp, Color.Black)) else Modifier ) .dragAndDropTarget( shouldStartDragAndDrop = { true }, target = dragAndDropTarget ) ) { Text(targetText, Modifier.align(Alignment.Center)) } } var showPopup by remember { mutableStateOf(false) } if (showPopup) { Popup { Text("Popup is shown") } } LaunchedEffect(Unit) { delay(5000) showPopup = true delay(5000) showPopup = false } } ``` This should be tested by QA ## Release Notes ### Fixes - Desktop - _(prerelease fix)_ Fixed drag-and-drop not working after a popup is displayed in the window.
- Loading branch information