Просмотр исходного кода

x11 buttons are responsive now

David Rose 16 лет назад
Родитель
Сommit
da59dc9063
2 измененных файлов с 106 добавлено и 9 удалено
  1. 91 8
      direct/src/plugin/p3dX11SplashWindow.cxx
  2. 15 1
      direct/src/plugin/p3dX11SplashWindow.h

+ 91 - 8
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -24,12 +24,6 @@
 #include <sys/select.h>
 #include <signal.h>
 
-// Sleeps for a short time.
-#define MILLISLEEP() \
-  timespec ts; \
-  ts.tv_sec = 0; ts.tv_nsec = 100000; \
-  nanosleep(&ts, NULL);
-
 // Clamps a value to two boundaries.
 #define clamp(x, lb, hb) (x < lb ? lb : (x > hb ? hb : x))
 
@@ -45,6 +39,10 @@ P3DX11SplashWindow(P3DInstance *inst) :
   // Init for parent process
   _subprocess_pid = -1;
 
+  // Init for read thread
+  _started_read_thread = false;
+  INIT_THREAD(_read_thread);
+
   // Init for subprocess
   _display = None;
   _window = None;
@@ -185,6 +183,11 @@ button_click_detected() {
   // This method is called in the child process, and must relay
   // the information to the parent process.
   cerr << "click detected\n";
+
+  TiXmlDocument doc;
+  TiXmlElement *xcommand = new TiXmlElement("click");
+  doc.LinkEndChild(xcommand);
+  write_xml(_pipe_write, &doc, nout);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -198,18 +201,23 @@ void P3DX11SplashWindow::
 start_subprocess() {
   assert(_subprocess_pid == -1);
 
-  // Create a directional pipe to send messages to the sub-process.
-  // (We don't need a receive pipe.)
+  // Create a bi-directional pipe to communicate with the sub-process.
   int to_fd[2];
   if (pipe(to_fd) < 0) {
     perror("failed to create pipe");
   }
+  int from_fd[2];
+  if (pipe(from_fd) < 0) {
+    perror("failed to create pipe");
+  }
 
   // Fork and exec.
   pid_t child = fork();
   if (child < 0) {
     close(to_fd[0]);
     close(to_fd[1]);
+    close(from_fd[0]);
+    close(from_fd[1]);
     perror("fork");
     return;
   }
@@ -220,6 +228,8 @@ start_subprocess() {
     // Open the read end of the pipe, and close the write end.
     _pipe_read.open_read(to_fd[0]);
     close(to_fd[1]);
+    _pipe_write.open_write(from_fd[1]);
+    close(from_fd[0]);
 
     subprocess_run();
     _exit(0);
@@ -229,6 +239,10 @@ start_subprocess() {
   _subprocess_pid = child;
   _pipe_write.open_write(to_fd[1]);
   close(to_fd[0]);
+  _pipe_read.open_read(from_fd[0]);
+  close(from_fd[1]);
+
+  spawn_read_thread();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -300,6 +314,8 @@ stop_subprocess() {
   } else if (WIFSTOPPED(status)) {
     nout << "  stopped by " << WSTOPSIG(status) << "\n";
   }
+
+  join_read_thread();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -343,9 +359,76 @@ check_stopped() {
   }
 
   _subprocess_pid = -1;
+  join_read_thread();
+
   _inst->request_stop();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::spawn_read_thread
+//       Access: Private
+//  Description: Starts the read thread.  We need this thread to
+//               listen for feedback from the subprocess.  (At the
+//               moment, the only kind of feedback we might receive is
+//               whether the button has been clicked.)
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+spawn_read_thread() {
+  SPAWN_THREAD(_read_thread, rt_thread_run, this);
+  _started_read_thread = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::join_read_thread
+//       Access: Private
+//  Description: Waits for the read thread to stop.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+join_read_thread() {
+  if (!_started_read_thread) {
+    return;
+  }
+
+  JOIN_THREAD(_read_thread);
+  _started_read_thread = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::rt_thread_run
+//       Access: Private
+//  Description: The main function for the read thread.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+rt_thread_run() {
+  while (true) {
+    TiXmlDocument *doc = read_xml(_pipe_read, nout);
+    if (doc == NULL) {
+      // Some error on reading.
+      return;
+    }
+
+    // Successfully read an XML document.
+    rt_handle_request(doc);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DX11SplashWindow::rt_handle_request
+//       Access: Private
+//  Description: Processes a single request or notification received
+//               from an instance.
+////////////////////////////////////////////////////////////////////
+void P3DX11SplashWindow::
+rt_handle_request(TiXmlDocument *doc) {
+  // Eh, don't even bother decoding the XML.  We know it can only be a
+  // click notification.
+  delete doc;
+
+  ACQUIRE_LOCK(_api_lock);
+  P3DSplashWindow::button_click_detected();
+  RELEASE_LOCK(_api_lock);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DX11SplashWindow::subprocess_run
 //       Access: Private

+ 15 - 1
direct/src/plugin/p3dX11SplashWindow.h

@@ -51,11 +51,26 @@ private:
   void stop_subprocess();
   void check_stopped();
 
+  void spawn_read_thread();
+  void join_read_thread();
+
+private:
+  // These methods run only within the read thread.
+  THREAD_CALLBACK_DECLARATION(P3DX11SplashWindow, rt_thread_run);
+  void rt_thread_run();
+  void rt_terminate();
+  void rt_handle_request(TiXmlDocument *doc);
+
 private:
   // Data members that are stored in the parent process.
   pid_t _subprocess_pid;
+  HandleStream _pipe_read;
   HandleStream _pipe_write;
 
+  // The remaining members are manipulated by or for the read thread.
+  bool _started_read_thread;
+  THREAD _read_thread;
+
 private:
   // These methods run only within the subprocess.
   class X11ImageData;
@@ -93,7 +108,6 @@ private:
   X11ImageData _button_click_image;
 
   bool _subprocess_continue;
-  HandleStream _pipe_read;
   
   bool _own_display;
   string _install_label;