changeset 4304:a61b939ac01b

RT-31232 Gtk: Error when closing JavaFX stage by escape
author Alexander Zvegintsev
date Tue, 16 Jul 2013 15:47:38 +0400
parents 74ac20176fc5
children 9138b9b61850
files modules/graphics/src/main/native-glass/gtk/GlassApplication.cpp modules/graphics/src/main/native-glass/gtk/glass_window.cpp modules/graphics/src/main/native-glass/gtk/glass_window.h
diffstat 3 files changed, 109 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/native-glass/gtk/GlassApplication.cpp	Tue Jul 16 13:35:31 2013 +0200
+++ b/modules/graphics/src/main/native-glass/gtk/GlassApplication.cpp	Tue Jul 16 15:47:38 2013 +0400
@@ -463,6 +463,7 @@
     }
 
     if (ctx != NULL) {
+        EventsCounterHelper helper(ctx);
         try {
             switch (event->type) {
                 case GDK_PROPERTY_NOTIFY:
--- a/modules/graphics/src/main/native-glass/gtk/glass_window.cpp	Tue Jul 16 13:35:31 2013 +0200
+++ b/modules/graphics/src/main/native-glass/gtk/glass_window.cpp	Tue Jul 16 15:47:38 2013 +0400
@@ -85,10 +85,31 @@
     }
 }
 
+void WindowContextBase::increment_events_counter() {
+    ++events_processing_cnt;
+}
+
+void WindowContextBase::decrement_events_counter() {
+    --events_processing_cnt;
+}
+
+size_t WindowContextBase::get_events_count() {
+    return events_processing_cnt;
+}
+
+bool WindowContextBase::is_dead() {
+    return can_be_deleted;
+}
+
 void destroy_and_delete_ctx(WindowContext* ctx) {
     if (ctx) {
         ctx->process_destroy();
-        delete ctx;
+
+        if (!ctx->get_events_count()) {
+            delete ctx;
+        } 
+        // else: ctx will be deleted in EventsCounterHelper after completing
+        // an event processing
     }
 }
 
@@ -106,8 +127,20 @@
 
     if (jwindow) {
         mainEnv->CallVoidMethod(jwindow, jWindowNotifyDestroy);
-        CHECK_JNI_EXCEPTION(mainEnv)
+        EXCEPTION_OCCURED(mainEnv);
     }
+
+    if (jview) {
+        mainEnv->DeleteGlobalRef(jview);
+        jview = NULL;
+    }
+
+    if (jwindow) {
+        mainEnv->DeleteGlobalRef(jwindow);
+        jwindow = NULL;
+    }
+
+    can_be_deleted = true;
 }
 
 void WindowContextBase::process_delete() {
@@ -321,11 +354,7 @@
                     glassModifier);
             CHECK_JNI_EXCEPTION(mainEnv)
 
-            if (!jview) {
-                return;
-            }
-
-            if (key > 0) { // TYPED events should only be sent for printable characters.
+            if (jview && key > 0) { // TYPED events should only be sent for printable characters.
                 mainEnv->CallVoidMethod(jview, jViewNotifyKey,
                         com_sun_glass_events_KeyEvent_TYPED,
                         com_sun_glass_events_KeyEvent_VK_UNDEFINED,
@@ -462,20 +491,14 @@
 }
 
 WindowContextBase::~WindowContextBase() {
-    if (jview) {
-        mainEnv->DeleteGlobalRef(jview);
-    }
     if (xim.ic) {
         XDestroyIC(xim.ic);
     }
     if (xim.im) {
         XCloseIM(xim.im);
     }
+
     gtk_widget_destroy(gtk_widget);
-
-    if (jwindow) {
-        mainEnv->DeleteGlobalRef(jwindow);
-    }
 }
 
 ////////////////////////////// WindowContextTop /////////////////////////////////
@@ -1193,10 +1216,15 @@
     owner = owner_ctx;
 }
 
-WindowContextTop::~WindowContextTop() {
+void WindowContextTop::process_destroy() {
     if (owner) {
         owner->remove_child(this);
     }
+
+    WindowContextBase::process_destroy();
+}
+
+WindowContextTop::~WindowContextTop() {
     if (xshape.surface) {
         cairo_surface_destroy(xshape.surface);
         XFreePixmap(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), xshape.pixmap);
@@ -1285,10 +1313,12 @@
             }
         }
 
-        mainEnv->CallVoidMethod(jwindow,
-                jGtkWindowNotifyStateChanged,
-                stateChangeEvent);
-        CHECK_JNI_EXCEPTION(mainEnv);
+        if (jwindow) {
+            mainEnv->CallVoidMethod(jwindow,
+                    jGtkWindowNotifyStateChanged,
+                    stateChangeEvent);
+            CHECK_JNI_EXCEPTION(mainEnv);
+        }
     }
 }
 
@@ -1450,11 +1480,13 @@
 
     gtk_widget_set_size_request(gtk_widget, event->width, event->height);
 
-    mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
-            com_sun_glass_events_WindowEvent_RESIZE,
-            event->width,
-            event->height);
-    CHECK_JNI_EXCEPTION(mainEnv)
+    if (jwindow) {
+        mainEnv->CallVoidMethod(jwindow, jWindowNotifyResize,
+                com_sun_glass_events_WindowEvent_RESIZE,
+                event->width,
+                event->height);
+        CHECK_JNI_EXCEPTION(mainEnv)
+    }
 }
 
 void WindowContextChild::process_state(GdkEventWindowState *event) {
@@ -1479,10 +1511,12 @@
             CHECK_JNI_EXCEPTION(mainEnv);
         }
 
-        mainEnv->CallVoidMethod(jwindow,
-                jGtkWindowNotifyStateChanged,
-                stateChangeEvent);
-        CHECK_JNI_EXCEPTION(mainEnv);
+        if (jwindow) {
+            mainEnv->CallVoidMethod(jwindow,
+                    jGtkWindowNotifyStateChanged,
+                    stateChangeEvent);
+            CHECK_JNI_EXCEPTION(mainEnv);
+        }
     }
 }
 
@@ -1509,10 +1543,12 @@
     if (x > 0 || y > 0 || xSet || ySet) {
         gint newX, newY;
         gdk_window_get_origin(gdk_window, &newX, &newY);
-        mainEnv->CallVoidMethod(jwindow,
-                jWindowNotifyMove,
-                newX, newY);
-        CHECK_JNI_EXCEPTION(mainEnv)
+        if (jwindow) {
+            mainEnv->CallVoidMethod(jwindow,
+                    jWindowNotifyMove,
+                    newX, newY);
+            CHECK_JNI_EXCEPTION(mainEnv)
+        }
     }
 
     // As we have no frames, there's no difference between the calls
@@ -1592,8 +1628,10 @@
     full_screen_window->set_visible(true);
     full_screen_window->enter_fullscreen();
 
-    mainEnv->CallVoidMethod(jwindow, jWindowNotifyDelegatePtr, (jlong)full_screen_window);
-    CHECK_JNI_EXCEPTION(mainEnv)
+    if (jwindow) {
+        mainEnv->CallVoidMethod(jwindow, jWindowNotifyDelegatePtr, (jlong)full_screen_window);
+        CHECK_JNI_EXCEPTION(mainEnv)
+    }
 
     if (jview) {
         this->view = (GlassView*)mainEnv->GetLongField(jview, jViewPtr);
@@ -1631,14 +1669,14 @@
     
     full_screen_window->set_visible(false);
 
-    delete full_screen_window;
+    destroy_and_delete_ctx(full_screen_window);
     full_screen_window = NULL;
     this->view = NULL;
 }
 
-WindowContextChild::~WindowContextChild() {
+void WindowContextChild::process_destroy() {
     if (full_screen_window) {
-        delete full_screen_window;
+        destroy_and_delete_ctx(full_screen_window);
     }
 
     std::vector<WindowContextChild*> &embedded_children =
@@ -1649,4 +1687,6 @@
     if (pos != embedded_children.end()) {
         embedded_children.erase((pos));
     }
+
+    WindowContextBase::process_destroy();
 }
--- a/modules/graphics/src/main/native-glass/gtk/glass_window.h	Tue Jul 16 13:35:31 2013 +0200
+++ b/modules/graphics/src/main/native-glass/gtk/glass_window.h	Tue Jul 16 15:47:38 2013 +0400
@@ -161,6 +161,11 @@
     virtual int getEmbeddedX() = 0;
     virtual int getEmbeddedY() = 0;
 
+
+    virtual void increment_events_counter() = 0;
+    virtual void decrement_events_counter() = 0;
+    virtual size_t get_events_count() = 0;
+    virtual bool is_dead() = 0;
     virtual ~WindowContext() {}
 };
 
@@ -173,6 +178,8 @@
         bool enabled;
     } xim;
 
+    size_t events_processing_cnt;
+    bool can_be_deleted;
 protected:
     jobject jwindow;
     jobject jview;
@@ -218,6 +225,11 @@
     int getEmbeddedX() { return 0; }
     int getEmbeddedY() { return 0; }
 
+    void increment_events_counter();
+    void decrement_events_counter();
+    size_t get_events_count();
+    bool is_dead();
+
     ~WindowContextBase();
 protected:
     virtual void applyShapeMask(cairo_surface_t*, uint width, uint height) = 0;
@@ -297,6 +309,7 @@
     void process_property_notify(GdkEventProperty*) {}
     void process_configure(GdkEventConfigure*);
     void process_state(GdkEventWindowState*);
+    void process_destroy();
     void set_visible(bool visible);
 
     int getEmbeddedX();
@@ -306,7 +319,6 @@
     GtkWindow *get_gtk_window(); // TODO, get window from parent
 
     WindowContextChild(jobject, void*, GtkWidget *parent_widget, WindowContextPlug *parent_context);
-    ~WindowContextChild();
 private:
     WindowContextChild(WindowContextChild&);
     WindowContextChild& operator= (const WindowContextChild&);
@@ -340,6 +352,7 @@
     void process_property_notify(GdkEventProperty*);
     void process_configure(GdkEventConfigure*);
     void process_state(GdkEventWindowState*);
+    void process_destroy();
     WindowFrameExtents get_frame_extents();
 
     void set_minimized(bool);
@@ -382,5 +395,22 @@
 
 void destroy_and_delete_ctx(WindowContext* ctx);
 
+class EventsCounterHelper {
+private:
+    WindowContext* ctx;
+public:
+    explicit EventsCounterHelper(WindowContext* context) {
+        ctx = context;
+        ctx->increment_events_counter();
+    }
+    ~EventsCounterHelper() {
+        ctx->decrement_events_counter();
+        if (ctx->is_dead() && ctx->get_events_count() == 0) {
+            delete ctx;
+        }
+        ctx = NULL;
+    }
+};
+
 #endif        /* GLASS_WINDOW_H */