diff options
author | Neil Hodgson <nyamatongwe@gmail.com> | 2021-04-28 14:54:36 +1000 |
---|---|---|
committer | Neil Hodgson <nyamatongwe@gmail.com> | 2021-04-28 14:54:36 +1000 |
commit | c84506e472724377b9e8e4038eee15629046f942 (patch) | |
tree | 5ea426190acaa5fb4e5489674b78b4f64d9c5901 | |
parent | 2a884698e73fc35319236ca56a25c0bc663f315b (diff) | |
download | scintilla-mirror-c84506e472724377b9e8e4038eee15629046f942.tar.gz |
Bug [#2227]. On GTK 3 with Wayland, fix primary selection.
-rw-r--r-- | doc/ScintillaHistory.html | 4 | ||||
-rwxr-xr-x | gtk/ScintillaGTK.cxx | 102 | ||||
-rwxr-xr-x | gtk/ScintillaGTK.h | 10 |
3 files changed, 68 insertions, 48 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 3245c8159..46dc0ba26 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -579,6 +579,10 @@ Released 23 April 2021. </li> <li> + On GTK 3 with Wayland, fix primary selection. + <a href="https://sourceforge.net/p/scintilla/bugs/2227/">Bug #2227</a>. + </li> + <li> Update to Unicode 13. <a href="https://sourceforge.net/p/scintilla/feature-requests/1379/">Feature #1379</a>. </li> diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 1296bb2dd..9a70ed463 100755 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -243,6 +243,7 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) : #else linesPerScroll = 4; #endif + primarySelection = false; Init(); } @@ -256,6 +257,7 @@ ScintillaGTK::~ScintillaGTK() { gdk_event_free(evbtn); evbtn = nullptr; } + ClearPrimarySelection(); wPreedit.Destroy(); } @@ -334,12 +336,6 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) { cursor = gdk_cursor_new_for_display(pdisplay, GDK_LEFT_PTR); gdk_window_set_cursor(PWindow(scrollbarh), cursor); UnRefCursor(cursor); - - wSelection = gtk_invisible_new(); - g_signal_connect(PWidget(wSelection), "selection_get", G_CALLBACK(PrimarySelection), (gpointer) this); - g_signal_connect(PWidget(wSelection), "selection_clear_event", G_CALLBACK(PrimaryClear), (gpointer) this); - gtk_selection_add_targets(PWidget(wSelection), GDK_SELECTION_PRIMARY, - clipboardCopyTargets, nClipboardCopyTargets); } void ScintillaGTK::Realize(GtkWidget *widget) { @@ -349,9 +345,6 @@ void ScintillaGTK::Realize(GtkWidget *widget) { void ScintillaGTK::UnRealizeThis(GtkWidget *widget) { try { - gtk_selection_clear_targets(PWidget(wSelection), GDK_SELECTION_PRIMARY); - wSelection.Destroy(); - if (IS_WIDGET_MAPPED(widget)) { gtk_widget_unmap(widget); } @@ -1416,26 +1409,66 @@ void ScintillaGTK::AddToPopUp(const char *label, int cmd, bool enabled) { } bool ScintillaGTK::OwnPrimarySelection() { - return (wSelection.Created() && - (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == PWindow(wSelection)) && - (PWindow(wSelection) != nullptr)); + return primarySelection; +} + +void ScintillaGTK::ClearPrimarySelection() { + if (primarySelection) { + inClearSelection++; + // Calls PrimaryClearSelection: primarySelection -> false + gtk_clipboard_clear(gtk_clipboard_get(GDK_SELECTION_PRIMARY)); + inClearSelection--; + } +} + +void ScintillaGTK::PrimaryGetSelectionThis(GtkClipboard *clip, GtkSelectionData *selection_data, guint info) { + try { + if (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY) { + if (primary.Empty()) { + CopySelectionRange(&primary); + } + GetSelection(selection_data, info, &primary); + } + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::PrimaryGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, gpointer pSci) { + static_cast<ScintillaGTK *>(pSci)->PrimaryGetSelectionThis(clip, selection_data, info); +} + +void ScintillaGTK::PrimaryClearSelectionThis(GtkClipboard *clip) { + try { + primarySelection = false; + primary.Clear(); + if (!inClearSelection) { + // Called because of another application or window claiming primary selection + // so redraw to show selection in secondary colour. + Redraw(); + } + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } +} + +void ScintillaGTK::PrimaryClearSelection(GtkClipboard *clip, gpointer pSci) { + static_cast<ScintillaGTK *>(pSci)->PrimaryClearSelectionThis(clip); } void ScintillaGTK::ClaimSelection() { // X Windows has a 'primary selection' as well as the clipboard. // Whenever the user selects some text, we become the primary selection - if (!sel.Empty() && wSelection.Created() && IS_WIDGET_REALIZED(GTK_WIDGET(PWidget(wSelection)))) { - primarySelection = true; - gtk_selection_owner_set(GTK_WIDGET(PWidget(wSelection)), - GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - primary.Clear(); - } else if (OwnPrimarySelection()) { - primarySelection = true; - if (primary.Empty()) - gtk_selection_owner_set(nullptr, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); - } else { - primarySelection = false; - primary.Clear(); + ClearPrimarySelection(); + if (!sel.Empty()) { + if (gtk_clipboard_set_with_data( + gtk_clipboard_get(GDK_SELECTION_PRIMARY), + clipboardCopyTargets, nClipboardCopyTargets, + PrimaryGetSelection, + PrimaryClearSelection, + this)) { + primarySelection = true; + } } } @@ -1663,27 +1696,6 @@ void ScintillaGTK::UnclaimSelection(GdkEventSelection *selection_event) { } } -void ScintillaGTK::PrimarySelection(GtkWidget *, GtkSelectionData *selection_data, guint info, guint, ScintillaGTK *sciThis) { - try { - if (SelectionOfGSD(selection_data) == GDK_SELECTION_PRIMARY) { - if (sciThis->primary.Empty()) { - sciThis->CopySelectionRange(&sciThis->primary); - } - sciThis->GetSelection(selection_data, info, &sciThis->primary); - } - } catch (...) { - sciThis->errorStatus = SC_STATUS_FAILURE; - } -} - -gboolean ScintillaGTK::PrimaryClear(GtkWidget *widget, GdkEventSelection *event, ScintillaGTK *sciThis) { - sciThis->UnclaimSelection(event); - if (GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event) { - return GTK_WIDGET_CLASS(sciThis->parentClass)->selection_clear_event(widget, event); - } - return TRUE; -} - void ScintillaGTK::Resize(int width, int height) { //Platform::DebugPrintf("Resize %d %d\n", width, height); //printf("Resize %d %d\n", width, height); diff --git a/gtk/ScintillaGTK.h b/gtk/ScintillaGTK.h index 58f395432..5461ff37b 100755 --- a/gtk/ScintillaGTK.h +++ b/gtk/ScintillaGTK.h @@ -30,7 +30,6 @@ class ScintillaGTK : public ScintillaBase { Window scrollbarh; GtkAdjustment *adjustmentv; GtkAdjustment *adjustmenth; - Window wSelection; int verticalScrollBarWidth; int horizontalScrollBarHeight; @@ -51,6 +50,7 @@ class ScintillaGTK : public ScintillaBase { static inline GdkAtom atomUriList {}; static inline GdkAtom atomDROPFILES_DND {}; GdkAtom atomSought; + size_t inClearSelection = 0; #if PLAT_GTK_WIN32 CLIPFORMAT cfColumnSelect; @@ -160,9 +160,13 @@ private: static void ClipboardGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, void *data); static void ClipboardClearSelection(GtkClipboard *clip, void *data); + void ClearPrimarySelection(); + void PrimaryGetSelectionThis(GtkClipboard *clip, GtkSelectionData *selection_data, guint info); + static void PrimaryGetSelection(GtkClipboard *clip, GtkSelectionData *selection_data, guint info, gpointer pSci); + void PrimaryClearSelectionThis(GtkClipboard *clip); + static void PrimaryClearSelection(GtkClipboard *clip, gpointer pSci); + void UnclaimSelection(GdkEventSelection *selection_event); - static void PrimarySelection(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint time_stamp, ScintillaGTK *sciThis); - static gboolean PrimaryClear(GtkWidget *widget, GdkEventSelection *event, ScintillaGTK *sciThis); void Resize(int width, int height); // Callback functions |