aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gtk/ScintillaGTK.cxx65
1 files changed, 58 insertions, 7 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 08d2714e7..33aec818b 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -307,8 +307,6 @@ private:
static void Destroy(GObject *object);
static void SelectionReceived(GtkWidget *widget, GtkSelectionData *selection_data,
guint time);
- static void ClipboardReceived(GtkClipboard *clipboard, GtkSelectionData *selection_data,
- gpointer data);
static void SelectionGet(GtkWidget *widget, GtkSelectionData *selection_data,
guint info, guint time);
static gint SelectionClear(GtkWidget *widget, GdkEventSelection *selection_event);
@@ -1452,10 +1450,39 @@ void ScintillaGTK::Copy() {
}
}
-void ScintillaGTK::ClipboardReceived(GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) {
- ScintillaGTK *sciThis = static_cast<ScintillaGTK *>(data);
- sciThis->ReceivedSelection(selection_data);
-}
+// helper class to watch a GObject lifetime and get notified when it dies
+class GObjectWatcher {
+ GObject *weakRef;
+
+ void WeakNotifyThis(GObject *obj) {
+ PLATFORM_ASSERT(obj == weakRef);
+
+ Destroyed();
+ weakRef = 0;
+ }
+
+ static void WeakNotify(gpointer data, GObject *obj) {
+ static_cast<GObjectWatcher*>(data)->WeakNotifyThis(obj);
+ }
+
+public:
+ GObjectWatcher(GObject *obj) :
+ weakRef(obj) {
+ g_object_weak_ref(weakRef, WeakNotify, this);
+ }
+
+ virtual ~GObjectWatcher() {
+ if (weakRef) {
+ g_object_weak_unref(weakRef, WeakNotify, this);
+ }
+ }
+
+ virtual void Destroyed() {}
+
+ bool IsDestroyed() {
+ return weakRef != 0;
+ }
+};
void ScintillaGTK::Paste() {
atomSought = atomUTF8;
@@ -1463,7 +1490,31 @@ void ScintillaGTK::Paste() {
gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL)
return;
- gtk_clipboard_request_contents(clipBoard, atomSought, ClipboardReceived, this);
+
+ // helper class for the asynchronous paste not to risk calling in a destroyed ScintillaGTK
+ class Helper : GObjectWatcher {
+ ScintillaGTK *sci;
+
+ virtual void Destroyed() {
+ sci = 0;
+ }
+
+ public:
+ Helper(ScintillaGTK *sci_) :
+ GObjectWatcher(G_OBJECT(PWidget(sci_->wMain))),
+ sci(sci_) {
+ }
+
+ static void ClipboardReceived(GtkClipboard *, GtkSelectionData *selection_data, gpointer data) {
+ Helper *self = static_cast<Helper*>(data);
+ if (self->sci != 0) {
+ self->sci->ReceivedSelection(selection_data);
+ }
+ delete self;
+ }
+ };
+
+ gtk_clipboard_request_contents(clipBoard, atomSought, Helper::ClipboardReceived, new Helper(this));
}
void ScintillaGTK::CreateCallTipWindow(PRectangle rc) {