From 56c071e2734e3812c7c77b611637cbc2698eb7d3 Mon Sep 17 00:00:00 2001 From: Nathaniel Braun Date: Thu, 8 Jan 2026 08:22:01 +1100 Subject: Feature [feature-requests:#184]. Add option to disable drag/drop editing SCI_SETDRAGDROPENABLED. Fully implemented on Win32 but may only prevent dragging on other platforms. --- call/ScintillaCall.cxx | 8 ++++++++ doc/ScintillaDoc.html | 6 ++++++ doc/ScintillaHistory.html | 5 +++++ include/Scintilla.h | 2 ++ include/Scintilla.iface | 6 ++++++ include/ScintillaCall.h | 2 ++ include/ScintillaMessages.h | 2 ++ src/Editor.cxx | 12 ++++++++++-- src/Editor.h | 1 + test/simpleTests.py | 7 +++++++ win32/ScintillaWin.cxx | 13 +++++++++++-- 11 files changed, 60 insertions(+), 4 deletions(-) diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx index d1d4012b2..093cf9a0d 100644 --- a/call/ScintillaCall.cxx +++ b/call/ScintillaCall.cxx @@ -3391,6 +3391,14 @@ Position ScintillaCall::IndexPositionFromLine(Line line, Scintilla::LineCharacte return Call(Message::IndexPositionFromLine, line, static_cast(lineCharacterIndex)); } +bool ScintillaCall::DragDropEnabled() { + return Call(Message::GetDragDropEnabled); +} + +void ScintillaCall::SetDragDropEnabled(bool dragDropEnabled) { + Call(Message::SetDragDropEnabled, dragDropEnabled); +} + void ScintillaCall::StartRecord() { Call(Message::StartRecord); } diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 0dfe986f4..d432043f6 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -482,6 +482,8 @@ *text)
SCI_SETREADONLY(bool readOnly)
SCI_GETREADONLY → bool
+ SCI_GETDRAGDROPENABLED → bool
+ SCI_SETDRAGDROPENABLED(bool dragDropEnabled)
SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr) → position
SCI_GETTEXTRANGEFULL(<unused>, Sci_TextRangeFull *tr) → position
SCI_ALLOCATE(position bytes)
@@ -568,6 +570,10 @@ only, attempts to modify the text cause the SCN_MODIFYATTEMPTRO notification.

+

SCI_GETDRAGDROPENABLED → bool
+ SCI_SETDRAGDROPENABLED(bool dragDropEnabled)
+ These messages get and set the flag controlling whether drag-and-drop is enabled or not.

+

SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr) → position
SCI_GETTEXTRANGEFULL(<unused>, Sci_TextRangeFull *tr) → position
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 12b233b4f..1148abaa1 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -592,6 +592,7 @@ Ahmet Sait Sven Ritter Stefan Löffler + Nathaniel Braun

Releases

@@ -603,6 +604,10 @@ Released 10 November 2025.
  • + Add option to disable drag/drop editing. + Feature #184. +
  • +
  • Fix SCI_SETSELECTIONNSTART and SCI_SETSELECTIONNEND to behave more sensibly. Bug #2488.
  • diff --git a/include/Scintilla.h b/include/Scintilla.h index f7afa4f50..b6786097e 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -1194,6 +1194,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SCI_RELEASELINECHARACTERINDEX 2712 #define SCI_LINEFROMINDEXPOSITION 2713 #define SCI_INDEXPOSITIONFROMLINE 2714 +#define SCI_GETDRAGDROPENABLED 2818 +#define SCI_SETDRAGDROPENABLED 2819 #define SCI_STARTRECORD 3001 #define SCI_STOPRECORD 3002 #define SCI_GETLEXER 4002 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 9ba834aed..6262f7c1b 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -3258,6 +3258,12 @@ fun line LineFromIndexPosition=2713(position pos, LineCharacterIndexType lineCha # Retrieve the position measured in index units at the start of a document line. fun position IndexPositionFromLine=2714(line line, LineCharacterIndexType lineCharacterIndex) +# Get whether drag-and-drop is enabled or disabled +get bool GetDragDropEnabled=2818(,) + +# Enable or disable drag-and-drop +set void SetDragDropEnabled=2819(bool dragDropEnabled,) + # Start notifying the container of all key presses and commands. fun void StartRecord=3001(,) diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h index 7a98c7e3d..2c065c03f 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -893,6 +893,8 @@ public: void ReleaseLineCharacterIndex(Scintilla::LineCharacterIndexType lineCharacterIndex); Line LineFromIndexPosition(Position pos, Scintilla::LineCharacterIndexType lineCharacterIndex); Position IndexPositionFromLine(Line line, Scintilla::LineCharacterIndexType lineCharacterIndex); + bool DragDropEnabled(); + void SetDragDropEnabled(bool dragDropEnabled); void StartRecord(); void StopRecord(); int Lexer(); diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h index 6a33f5c6d..d327bf7c1 100644 --- a/include/ScintillaMessages.h +++ b/include/ScintillaMessages.h @@ -799,6 +799,8 @@ enum class Message { ReleaseLineCharacterIndex = 2712, LineFromIndexPosition = 2713, IndexPositionFromLine = 2714, + GetDragDropEnabled = 2818, + SetDragDropEnabled = 2819, StartRecord = 3001, StopRecord = 3002, GetLexer = 4002, diff --git a/src/Editor.cxx b/src/Editor.cxx index 1ad99c3ca..a2c3e0fe9 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -143,6 +143,7 @@ Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) { dwelling = false; ptMouseLast.x = 0; ptMouseLast.y = 0; + dragDropEnabled = true; inDragDrop = DragDrop::none; dropWentOutside = false; posDrop = SelectionPosition(Sci::invalidPosition); @@ -5041,7 +5042,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) { AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular())); movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position()); - if (inDragDrop == DragDrop::initial) { + if (dragDropEnabled && inDragDrop == DragDrop::initial) { if (DragThreshold(ptMouseLast, pt)) { ChangeMouseCapture(false); SetDragPosition(movePos); @@ -5139,7 +5140,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) { } } // Display regular (drag) cursor over selection - if (PointInSelection(pt) && !SelectionEmpty()) { + if (PointInSelection(pt) && !SelectionEmpty() && dragDropEnabled) { DisplayCursor(Window::Cursor::arrow); SetHoverIndicatorPosition(Sci::invalidPosition); } else { @@ -7084,6 +7085,13 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case Message::GetBufferedDraw: return view.bufferedDraw; + case Message::GetDragDropEnabled: + return dragDropEnabled; + + case Message::SetDragDropEnabled: + dragDropEnabled = wParam != 0; + break; + #ifdef INCLUDE_DEPRECATED_FEATURES case SCI_GETTWOPHASEDRAW: return view.phasesDraw == EditView::phasesTwo; diff --git a/src/Editor.h b/src/Editor.h index f8bc18970..95b83f1f7 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -238,6 +238,7 @@ protected: // ScintillaBase subclass needs access to much of Editor bool dwelling; enum class TextUnit { character, word, subLine, wholeLine } selectionUnit; Point ptMouseLast; + bool dragDropEnabled; enum class DragDrop { none, initial, dragging } inDragDrop; bool dropWentOutside; SelectionPosition posDrop; diff --git a/test/simpleTests.py b/test/simpleTests.py index 4e6a51d59..0a14a4bdb 100644 --- a/test/simpleTests.py +++ b/test/simpleTests.py @@ -260,6 +260,13 @@ class TestSimple(unittest.TestCase): self.assertEqual(self.ed.CanUndo(), 0) self.ed.UndoCollection = 1 + def testDragDrop(self): + self.assertEqual(self.ed.DragDropEnabled, 1) + self.ed.DragDropEnabled = 0 + self.assertEqual(self.ed.DragDropEnabled, 0) + self.ed.DragDropEnabled = 1 + self.assertEqual(self.ed.DragDropEnabled, 1) + def testGetColumn(self): self.ed.AddText(1, b"x") self.assertEqual(self.ed.GetColumn(0), 0) diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index dfe075293..17f686c21 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -1754,7 +1754,7 @@ Window::Cursor ScintillaWin::ContextCursor(Point pt) { // Display regular (drag) cursor over selection if (PointInSelMargin(pt)) { return GetMarginCursor(pt); - } else if (!SelectionEmpty() && PointInSelection(pt)) { + } else if (!SelectionEmpty() && PointInSelection(pt) && dragDropEnabled) { return Window::Cursor::arrow; } else if (PointIsHotspot(pt)) { return Window::Cursor::hand; @@ -3721,6 +3721,10 @@ STDMETHODIMP_(ULONG) ScintillaWin::Release() { /// Implement IDropTarget STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL, PDWORD pdwEffect) { + if (!dragDropEnabled) { + *pdwEffect = DROPEFFECT_NONE; + return S_OK; + } if (!pIDataSource ) return E_POINTER; FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; @@ -3737,7 +3741,7 @@ STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyStat STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) { try { - if (!hasOKText || pdoc->IsReadOnly()) { + if (!dragDropEnabled || !hasOKText || pdoc->IsReadOnly()) { *pdwEffect = DROPEFFECT_NONE; return S_OK; } @@ -3771,6 +3775,11 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, try { *pdwEffect = EffectFromState(grfKeyState); + if (!dragDropEnabled) { + *pdwEffect = DROPEFFECT_NONE; + return S_OK; + } + if (!pIDataSource) return E_POINTER; -- cgit v1.2.3