Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / guicast / bcwindowevents.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcdisplay.h"
23 #include "bcsignals.h"
24 #include "bcwindowbase.h"
25 #include "bcwindowevents.h"
26 #include "bctimer.h"
27 #include "condition.h"
28 #include <unistd.h>
29
30 BC_WindowEvents::BC_WindowEvents(BC_WindowBase *window)
31  : Thread(1, 0, 0)
32 {
33         this->window = window;
34         display = 0;
35         done = 0;
36 }
37
38
39 BC_WindowEvents::BC_WindowEvents(BC_Display *display)
40  : Thread(1, 0, 0)
41 {
42         this->display = display;
43         window = 0;
44         done = 0;
45 }
46
47 BC_WindowEvents::~BC_WindowEvents()
48 {
49 // First set done, then send dummy event through XSendEvent to unlock the loop in ::run()
50 //printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
51         done = 1;
52         XEvent event;
53         XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
54         event.type = ClientMessage;
55         ptr->message_type = XInternAtom(window->display, "DUMMY_XATOM", False);
56         ptr->format = 32;
57         XSendEvent(window->display,
58                 window->win,
59                 0,
60                 0,
61                 &event);
62         window->flush();
63         Thread::join();
64 //printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
65 }
66
67 void BC_WindowEvents::start()
68 {
69         done = 0;
70         Thread::start();
71 }
72
73
74 void BC_WindowEvents::run()
75 {
76 // Can't cancel in XNextEvent because X server never figures out it's not
77 // listening anymore and XCloseDisplay locks up.
78         XEvent *event;
79 #ifndef SINGLE_THREAD
80         int x_fd = ConnectionNumber(window->display);
81 #endif
82
83
84
85         while(!done)
86         {
87
88 // Can't cancel in XNextEvent because X server never figures out it's not
89 // listening anymore and XCloseDisplay locks up.
90 #ifdef SINGLE_THREAD
91                 event = new XEvent;
92                 XNextEvent(display->display, event);
93                 display->put_event(event);
94 #else
95 // This came from a linuxquestions post.
96 // We can get a file descriptor for the X display & use select instead of XNextEvent.  
97 // The newest X11 library requires locking the display to use XNextEvent.
98                 fd_set x_fds;
99                 FD_ZERO(&x_fds);
100                 FD_SET(x_fd, &x_fds);
101                 struct timeval tv;
102                 tv.tv_sec = 0;  tv.tv_usec = 200000;
103 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
104                 select(x_fd + 1, &x_fds, 0, 0, &tv);
105                 XLockDisplay(window->display);
106                 while(!done && XPending(window->display))
107                 {
108                         event = new XEvent;
109                         XNextEvent(window->display, event);
110                         if( event->type == BC_WindowBase::shm_completion_event ) {
111                                 window->top_level->active_bitmaps.reque(event);
112                                 delete event;
113                                 continue;
114                         }
115 // HACK: delay is required to get the close event
116                         usleep(1);
117 //if(window && event)
118 //printf("BC_WindowEvents::run %d %s %d\n", __LINE__, window->title, event->type);
119                         window->put_event(event);
120                 }
121                 XUnlockDisplay(window->display);
122 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
123 #endif
124         }
125 }
126
127
128