[PyCharm] PY-79133 disabled updateSelectionAfterClick in case alt/opt pressed

GitOrigin-RevId: 81a08122758733401ae2f2a2271eb75223144d96
This commit is contained in:
bogdan.kirilenko
2026-01-15 21:58:01 +00:00
committed by intellij-monorepo-bot
parent 56fba1781f
commit 4e43029a13
3 changed files with 53 additions and 22 deletions
@@ -0,0 +1,31 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.notebooks.visualization.ui
import com.intellij.openapi.client.ClientSystemInfo
import java.awt.event.InputEvent
import java.awt.event.MouseEvent
data class ClickModifiers(
val isCtrlPressed: Boolean = false,
val isShiftPressed: Boolean = false,
val isAltPressed: Boolean = false,
val mouseButton: Int = MouseEvent.BUTTON1
) {
companion object {
fun fromEvent(e: MouseEvent) = ClickModifiers(
isCtrlPressed = e.isCtrlPressed(),
isShiftPressed = e.isShiftPressed(),
isAltPressed = e.isAltPressed(),
mouseButton = e.button
)
}
}
private fun MouseEvent.isCtrlPressed(): Boolean =
(modifiersEx and if (ClientSystemInfo.isMac()) InputEvent.META_DOWN_MASK else InputEvent.CTRL_DOWN_MASK) != 0
private fun MouseEvent.isShiftPressed(): Boolean =
(modifiersEx and InputEvent.SHIFT_DOWN_MASK) != 0
private fun MouseEvent.isAltPressed(): Boolean =
(modifiersEx and InputEvent.ALT_DOWN_MASK) != 0
@@ -8,14 +8,12 @@ import com.intellij.notebooks.visualization.cellSelectionModel
import com.intellij.notebooks.visualization.getCells
import com.intellij.notebooks.visualization.ui.EditorLayerController.Companion.EDITOR_LAYER_CONTROLLER_KEY
import com.intellij.openapi.Disposable
import com.intellij.openapi.client.ClientSystemInfo
import com.intellij.openapi.editor.event.EditorMouseEventArea
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.observable.properties.AtomicProperty
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.removeUserData
import com.intellij.ui.ComponentUtil
import java.awt.event.InputEvent
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionAdapter
@@ -68,7 +66,8 @@ class DecoratedEditor private constructor(
if (editorImpl.getMouseEventArea(event) != EditorMouseEventArea.EDITING_AREA) {
editorImpl.setMode(NotebookEditorMode.COMMAND)
}
updateSelectionAfterClick(hoveredCell.interval, event.isCtrlPressed(), event.isShiftPressed(), event.button)
updateSelectionAfterClick(hoveredCell.interval, ClickModifiers.fromEvent(event))
}
private fun sendMouseEventToNestedScroll(event: MouseEvent) {
@@ -83,15 +82,18 @@ class DecoratedEditor private constructor(
editorComponentWrapper.addEditorMouseWheelEvent { nestedScrollingSupport.processMouseWheelEvent(it) }
}
override fun inlayClicked(clickedCell: NotebookCellLines.Interval, ctrlPressed: Boolean, shiftPressed: Boolean, mouseButton: Int) {
override fun inlayClicked(clickedCell: NotebookCellLines.Interval, clickModifiers: ClickModifiers) {
editorImpl.setMode(NotebookEditorMode.COMMAND)
updateSelectionAfterClick(clickedCell, ctrlPressed, shiftPressed, mouseButton)
updateSelectionAfterClick(clickedCell, clickModifiers)
}
fun updateSelectionAfterClick(clickedCell: NotebookCellLines.Interval, ctrlPressed: Boolean, shiftPressed: Boolean, mouseButton: Int) {
fun updateSelectionAfterClick(
clickedCell: NotebookCellLines.Interval,
clickModifiers: ClickModifiers
) {
val model = editorImpl.cellSelectionModel!!
when {
ctrlPressed -> {
clickModifiers.isCtrlPressed -> {
if (model.isSelectedCell(clickedCell)) {
model.removeSelection(clickedCell)
}
@@ -99,7 +101,7 @@ class DecoratedEditor private constructor(
model.selectCell(clickedCell, makePrimary = true)
}
}
shiftPressed -> {
clickModifiers.isShiftPressed -> {
// select or deselect all cells from primary to the selected one
val primaryCell = model.primarySelectedCell
val line1 = primaryCell.lines.first
@@ -115,21 +117,28 @@ class DecoratedEditor private constructor(
}
}
else {
for (cell in (affectedSelectedCells - cellsInRange)) {
for (cell in (affectedSelectedCells - cellsInRange.toSet())) {
model.removeSelection(cell)
}
for (cell in (cellsInRange - affectedSelectedCells)) {
for (cell in (cellsInRange - affectedSelectedCells.toSet())) {
model.selectCell(cell)
}
}
}
mouseButton == MouseEvent.BUTTON1 && !model.isSelectedCell(clickedCell) -> {
clickModifiers.isAltPressed -> {
// don't change selection in this case
}
clickModifiers.mouseButton == MouseEvent.BUTTON1 && !model.isSelectedCell(clickedCell) -> {
model.selectSingleCell(clickedCell)
}
}
}
companion object {
/** lists assumed to be ordered and non-empty */
private fun hasIntersection(cells: List<NotebookCellLines.Interval>, others: List<NotebookCellLines.Interval>): Boolean =
!(cells.last().ordinal < others.first().ordinal || cells.first().ordinal > others.last().ordinal)
fun install(original: EditorImpl, manager: NotebookCellInlayManager) {
val decoratedEditor = DecoratedEditor(original, manager)
val controller = EditorLayerController(
@@ -143,14 +152,5 @@ class DecoratedEditor private constructor(
}
}
}
}
/** lists assumed to be ordered and non-empty */
private fun hasIntersection(cells: List<NotebookCellLines.Interval>, others: List<NotebookCellLines.Interval>): Boolean =
!(cells.last().ordinal < others.first().ordinal || cells.first().ordinal > others.last().ordinal)
private fun MouseEvent.isCtrlPressed(): Boolean =
(modifiersEx and if (ClientSystemInfo.isMac()) InputEvent.META_DOWN_MASK else InputEvent.CTRL_DOWN_MASK) != 0
private fun MouseEvent.isShiftPressed(): Boolean =
(modifiersEx and InputEvent.SHIFT_DOWN_MASK) != 0
@@ -6,7 +6,7 @@ import com.intellij.openapi.observable.properties.AtomicProperty
import com.intellij.openapi.util.Key
interface NotebookEditor {
fun inlayClicked(clickedCell: NotebookCellLines.Interval, ctrlPressed: Boolean, shiftPressed: Boolean, mouseButton: Int)
fun inlayClicked(clickedCell: NotebookCellLines.Interval, clickModifiers: ClickModifiers)
val editorPositionKeeper: NotebookPositionKeeper
/** Updated by JupyterAboveCellToolbarManager. When set, we are hiding the cell action toolbar in the top right corner. */