Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / guicast / bcwindowevents.C
diff --git a/cinelerra-5.1/guicast/bcwindowevents.C b/cinelerra-5.1/guicast/bcwindowevents.C
new file mode 100644 (file)
index 0000000..3d4dd5b
--- /dev/null
@@ -0,0 +1,128 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "bcdisplay.h"
+#include "bcsignals.h"
+#include "bcwindowbase.h"
+#include "bcwindowevents.h"
+#include "bctimer.h"
+#include "condition.h"
+#include <unistd.h>
+
+BC_WindowEvents::BC_WindowEvents(BC_WindowBase *window)
+ : Thread(1, 0, 0)
+{
+       this->window = window;
+       display = 0;
+       done = 0;
+}
+
+
+BC_WindowEvents::BC_WindowEvents(BC_Display *display)
+ : Thread(1, 0, 0)
+{
+       this->display = display;
+       window = 0;
+       done = 0;
+}
+
+BC_WindowEvents::~BC_WindowEvents()
+{
+// First set done, then send dummy event through XSendEvent to unlock the loop in ::run()
+//printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
+       done = 1;
+       XEvent event;
+       XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
+       event.type = ClientMessage;
+       ptr->message_type = XInternAtom(window->display, "DUMMY_XATOM", False);
+       ptr->format = 32;
+       XSendEvent(window->display,
+               window->win,
+               0,
+               0,
+               &event);
+       window->flush();
+       Thread::join();
+//printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
+}
+
+void BC_WindowEvents::start()
+{
+       done = 0;
+       Thread::start();
+}
+
+
+void BC_WindowEvents::run()
+{
+// Can't cancel in XNextEvent because X server never figures out it's not
+// listening anymore and XCloseDisplay locks up.
+       XEvent *event;
+#ifndef SINGLE_THREAD
+       int x_fd = ConnectionNumber(window->display);
+#endif
+
+
+
+       while(!done)
+       {
+
+// Can't cancel in XNextEvent because X server never figures out it's not
+// listening anymore and XCloseDisplay locks up.
+#ifdef SINGLE_THREAD
+               event = new XEvent;
+               XNextEvent(display->display, event);
+               display->put_event(event);
+#else
+// This came from a linuxquestions post.
+// We can get a file descriptor for the X display & use select instead of XNextEvent.  
+// The newest X11 library requires locking the display to use XNextEvent.
+               fd_set x_fds;
+               FD_ZERO(&x_fds);
+               FD_SET(x_fd, &x_fds);
+               struct timeval tv;
+               tv.tv_sec = 0;  tv.tv_usec = 200000;
+//printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
+               select(x_fd + 1, &x_fds, 0, 0, &tv);
+               XLockDisplay(window->display);
+               while(!done && XPending(window->display))
+               {
+                       event = new XEvent;
+                       XNextEvent(window->display, event);
+                       if( event->type == BC_WindowBase::shm_completion_event ) {
+                               window->top_level->active_bitmaps.reque(event);
+                               delete event;
+                               continue;
+                       }
+// HACK: delay is required to get the close event
+                       usleep(1);
+//if(window && event)
+//printf("BC_WindowEvents::run %d %s %d\n", __LINE__, window->title, event->type);
+                       window->put_event(event);
+               }
+               XUnlockDisplay(window->display);
+//printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
+#endif
+       }
+}
+
+
+