dvb chan tuner api upgrade, slip/ripple handle drag keyfrm fix, load menu tweaks
[goodguy/cinelerra.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 // no more external events, send one last event into X to flush out all of the
50 //  pending events so that no straglers or shm leaks are possible.
51 //printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
52         XSelectInput(window->display, window->win, 0);
53         XEvent event;  memset(&event,0,sizeof(event));
54         XClientMessageEvent *ptr = (XClientMessageEvent*)&event;
55         event.type = ClientMessage;
56         ptr->message_type = window->DestroyAtom;
57         ptr->format = 32;
58         XSendEvent(window->display, window->win, 0, 0, &event);
59         window->flush();
60         Thread::join();
61 //printf("BC_WindowEvents::~BC_WindowEvents %d %s\n", __LINE__, window->title);
62 }
63
64 void BC_WindowEvents::start()
65 {
66         done = 0;
67         Thread::start();
68 }
69
70
71 void BC_WindowEvents::run()
72 {
73 // Can't cancel in XNextEvent because X server never figures out it's not
74 // listening anymore and XCloseDisplay locks up.
75         XEvent *event;
76 #ifndef SINGLE_THREAD
77         int x_fd = ConnectionNumber(window->display);
78 #endif
79
80         while(!done)
81         {
82
83 // Can't cancel in XNextEvent because X server never figures out it's not
84 // listening anymore and XCloseDisplay locks up.
85 #ifdef SINGLE_THREAD
86                 event = new XEvent;
87                 XNextEvent(display->display, event);
88 #else
89 // This came from a linuxquestions post.
90 // We can get a file descriptor for the X display & use select instead of XNextEvent.
91 // The newest X11 library requires locking the display to use XNextEvent.
92                 fd_set x_fds;
93                 FD_ZERO(&x_fds);
94                 FD_SET(x_fd, &x_fds);
95                 struct timeval tv;
96                 tv.tv_sec = 0;  tv.tv_usec = 200000;
97 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
98                 select(x_fd + 1, &x_fds, 0, 0, &tv);
99                 XLockDisplay(window->display);
100                 while(!done && XPending(window->display))
101                 {
102                         event = new XEvent;
103                         XNextEvent(window->display, event);
104 #endif
105                         if( event->type == BC_WindowBase::shm_completion_event ) {
106                                 window->active_bitmaps.reque(event);
107                                 delete event;
108                                 continue;
109                         }
110                         if( event->type == ClientMessage ) {
111                                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
112                                 if( ptr->message_type == window->DestroyAtom ) {
113                                         delete event;
114                                         done = 1;
115                                         break;
116                                 }
117                         }
118 #ifndef SINGLE_THREAD
119 // HACK: delay is required to get the close event
120                         yield();
121 //if(window && event)
122 //printf("BC_WindowEvents::run %d %s %d\n", __LINE__, window->title, event->type);
123                         window->put_event(event);
124                 }
125                 XUnlockDisplay(window->display);
126 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
127 #else
128                 display->put_event(event);
129 #endif
130
131         }
132 }
133
134
135