Browse Source

GraphicsWindow::set_request_close_event()

David Rose 20 years ago
parent
commit
4e66269371

+ 47 - 0
panda/src/display/graphicsWindow.cxx

@@ -205,6 +205,53 @@ get_window_event() const {
   return result;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::set_close_request_event
+//       Access: Published
+//  Description: Sets the event that is triggered when the user
+//               requests to close the window, e.g. via alt-F4, or
+//               clicking on the close box.
+//
+//               The default for each window is for this event to be
+//               the empty string, which means the window-close
+//               request is handled immediately by Panda (and the
+//               window will be closed without the app getting a
+//               chance to intervene).  If you set this to a nonempty
+//               string, then the window is not closed, but instead
+//               the event is thrown.  It is then up to the app to
+//               respond appropriately, for instance by presenting an
+//               "are you sure?" dialog box, and eventually calling
+//               close_window() when the user is sure.
+//
+//               It is considered poor form to set this string and
+//               then not handle the event.  This can frustrate the
+//               user by making it difficult for him to cleanly shut
+//               down the application (and may force the user to
+//               hard-kill the app, or reboot the machine).
+////////////////////////////////////////////////////////////////////
+void GraphicsWindow::
+set_close_request_event(const string &close_request_event) {
+  MutexHolder holder(_properties_lock);
+  _close_request_event = close_request_event;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsWindow::get_close_request_event
+//       Access: Published
+//  Description: Returns the name of the event set via
+//               set_close_request_event().  If this string is
+//               nonempty, then when the user requests to close
+//               window, this event will be generated instead.  See
+//               set_close_request_event().
+////////////////////////////////////////////////////////////////////
+string GraphicsWindow::
+get_close_request_event() const {
+  string result;
+  MutexHolder holder(_properties_lock);
+  result = _close_request_event;
+  return result;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsWindow::get_num_input_devices
 //       Access: Published

+ 4 - 0
panda/src/display/graphicsWindow.h

@@ -57,6 +57,9 @@ PUBLISHED:
   void set_window_event(const string &window_event);
   string get_window_event() const;
 
+  void set_close_request_event(const string &close_request_event);
+  string get_close_request_event() const;
+
   // Mouse and keyboard routines
   int get_num_input_devices() const;
   string get_input_device_name(int device) const;
@@ -114,6 +117,7 @@ private:
   WindowProperties _requested_properties;
   WindowProperties _rejected_properties;
   string _window_event;
+  string _close_request_event;
   
 public:
   static TypeHandle get_class_type() {

+ 18 - 7
panda/src/glxdisplay/glxGraphicsWindow.cxx

@@ -28,6 +28,7 @@
 #include "clockObject.h"
 #include "pStatTimer.h"
 #include "textEncoder.h"
+#include "throw_event.h"
 
 #include <errno.h>
 #include <sys/time.h>
@@ -351,13 +352,23 @@ process_events() {
     case ClientMessage:
       if ((Atom)(event.xclient.data.l[0]) == _wm_delete_window) {
         // This is a message from the window manager indicating that
-        // the user has requested to close the window.  Honor the
-        // request.
-        // TODO: don't call release_gsg() in the window thread.
-        release_gsg();
-        close_window();
-        properties.set_open(false);
-        system_changed_properties(properties);
+        // the user has requested to close the window.
+        string close_request_event = get_close_request_event();
+        if (!close_request_event.empty()) {
+          // In this case, the app has indicated a desire to intercept
+          // the request and process it directly.
+          throw_event(close_request_event);
+
+        } else {
+          // In this case, the default case, the app does not intend
+          // to service the request, so we do by closing the window.
+
+          // TODO: don't call release_gsg() in the window thread.
+          release_gsg();
+          close_window();
+          properties.set_open(false);
+          system_changed_properties(properties);
+        }
       }
       break;