Credit Andrew - BSD fixes + a little more
[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 #ifndef NO_XSELECT
78         int x_fd = ConnectionNumber(window->display);
79 #endif
80 #endif
81
82         while(!done)
83         {
84
85 // Can't cancel in XNextEvent because X server never figures out it's not
86 // listening anymore and XCloseDisplay locks up.
87 #ifdef SINGLE_THREAD
88                 event = new XEvent;
89                 XNextEvent(display->display, event);
90 #else
91 // This came from a linuxquestions post.
92 // We can get a file descriptor for the X display & use select instead of XNextEvent.
93 // The newest X11 library requires locking the display to use XNextEvent.
94 #ifndef NO_XSELECT
95                 fd_set x_fds;
96                 FD_ZERO(&x_fds);
97                 FD_SET(x_fd, &x_fds);
98                 struct timeval tv;
99                 tv.tv_sec = 0;  tv.tv_usec = 200000;
100 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
101                 select(x_fd + 1, &x_fds, 0, 0, &tv);
102 #else
103                 usleep(100000);
104 #endif
105                 XLockDisplay(window->display);
106                 while(!done && XPending(window->display))
107                 {
108                         event = new XEvent;
109                         XNextEvent(window->display, event);
110 #endif
111                         if( event->type == BC_WindowBase::shm_completion_event ) {
112                                 window->active_bitmaps.reque(event);
113                                 delete event;
114                                 continue;
115                         }
116                         if( event->type == ClientMessage ) {
117                                 XClientMessageEvent *ptr = (XClientMessageEvent*)event;
118                                 if( ptr->message_type == window->DestroyAtom ) {
119                                         delete event;
120                                         done = 1;
121                                         break;
122                                 }
123                         }
124 #ifndef SINGLE_THREAD
125 // HACK: delay is required to get the close event
126                         yield();
127 //if(window && event)
128 //printf("BC_WindowEvents::run %d %s %d\n", __LINE__, window->title, event->type);
129                         window->put_event(event);
130                 }
131                 XUnlockDisplay(window->display);
132 //printf("BC_WindowEvents::run %d %s\n", __LINE__, window->title);
133 #else
134                 display->put_event(event);
135 #endif
136
137         }
138 }
139
140
141