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.
+
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