00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CXWindowsEventQueueBuffer.h"
00020 #include "CLock.h"
00021 #include "CThread.h"
00022 #include "CEvent.h"
00023 #include "IEventQueue.h"
00024 #include <fcntl.h>
00025 #if HAVE_UNISTD_H
00026 # include <unistd.h>
00027 #endif
00028 #if HAVE_POLL
00029 # include <poll.h>
00030 #else
00031 # if HAVE_SYS_SELECT_H
00032 # include <sys/select.h>
00033 # endif
00034 # if HAVE_SYS_TIME_H
00035 # include <sys/time.h>
00036 # endif
00037 # if HAVE_SYS_TYPES_H
00038 # include <sys/types.h>
00039 # endif
00040 #endif
00041
00042
00043
00044
00045
00046 class CEventQueueTimer { };
00047
00048
00049
00050
00051
00052
00053 CXWindowsEventQueueBuffer::CXWindowsEventQueueBuffer(
00054 Display* display, Window window) :
00055 m_display(display),
00056 m_window(window),
00057 m_waiting(false)
00058 {
00059 assert(m_display != NULL);
00060 assert(m_window != None);
00061
00062 m_userEvent = XInternAtom(m_display, "SYNERGY_USER_EVENT", False);
00063
00064 int result = pipe(m_pipefd);
00065 assert(result == 0);
00066
00067 int pipeflags;
00068 pipeflags = fcntl(m_pipefd[0], F_GETFL);
00069 fcntl(m_pipefd[0], F_SETFL, pipeflags | O_NONBLOCK);
00070 pipeflags = fcntl(m_pipefd[1], F_GETFL);
00071 fcntl(m_pipefd[1], F_SETFL, pipeflags | O_NONBLOCK);
00072 }
00073
00074 CXWindowsEventQueueBuffer::~CXWindowsEventQueueBuffer()
00075 {
00076
00077 close(m_pipefd[0]);
00078 close(m_pipefd[1]);
00079 }
00080
00081 void
00082 CXWindowsEventQueueBuffer::waitForEvent(double dtimeout)
00083 {
00084 CThread::testCancel();
00085
00086
00087
00088 char buf[16];
00089 ssize_t read_response = read(m_pipefd[0], buf, 15);
00090
00091
00092 if (read_response < 0)
00093 {
00094
00095 }
00096
00097 {
00098 CLock lock(&m_mutex);
00099
00100 m_waiting = true;
00101
00102
00103 flush();
00104 }
00105
00106 if (!CXWindowsEventQueueBuffer::isEmpty()) {
00107 CThread::testCancel();
00108 return;
00109 }
00110
00111
00112
00113 #if HAVE_POLL
00114 struct pollfd pfds[2];
00115 pfds[0].fd = ConnectionNumber(m_display);
00116 pfds[0].events = POLLIN;
00117 pfds[1].fd = m_pipefd[0];
00118 pfds[1].events = POLLIN;
00119 int timeout = (dtimeout < 0.0) ? -1 :
00120 static_cast<int>(1000.0 * dtimeout);
00121 int remaining = timeout;
00122 int retval = 0;
00123 #else
00124 struct timeval timeout;
00125 struct timeval* timeoutPtr;
00126 if (dtimeout < 0.0) {
00127 timeoutPtr = NULL;
00128 }
00129 else {
00130 timeout.tv_sec = static_cast<int>(dtimeout);
00131 timeout.tv_usec = static_cast<int>(1.0e+6 *
00132 (dtimeout - timeout.tv_sec));
00133 timeoutPtr = &timeout;
00134 }
00135
00136
00137 fd_set rfds;
00138 FD_ZERO(&rfds);
00139 FD_SET(ConnectionNumber(m_display), &rfds);
00140 FD_SET(m_pipefd[0], &rfds);
00141 int nfds;
00142 if (ConnectionNumber(m_display) > m_pipefd[0]) {
00143 nfds = ConnectionNumber(m_display) + 1;
00144 }
00145 else {
00146 nfds = m_pipefd[0] + 1;
00147 }
00148 #endif
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 #define TIMEOUT_DELAY 25
00161
00162 while( ((dtimeout < 0.0) || (remaining > 0)) && QLength(m_display)==0 && retval==0){
00163 #if HAVE_POLL
00164 retval = poll(pfds, 2, TIMEOUT_DELAY);
00165 if (pfds[1].revents & POLLIN) {
00166 ssize_t read_response = read(m_pipefd[0], buf, 15);
00167
00168
00169 if (read_response < 0)
00170 {
00171
00172 }
00173
00174 }
00175 #else
00176 retval = select(nfds,
00177 SELECT_TYPE_ARG234 &rfds,
00178 SELECT_TYPE_ARG234 NULL,
00179 SELECT_TYPE_ARG234 NULL,
00180 SELECT_TYPE_ARG5 TIMEOUT_DELAY);
00181 if (FD_SET(m_pipefd[0], &rfds)) {
00182 read(m_pipefd[0], buf, 15);
00183 }
00184 #endif
00185 remaining-=TIMEOUT_DELAY;
00186 }
00187
00188 {
00189
00190 CLock lock(&m_mutex);
00191 m_waiting = false;
00192 }
00193
00194 CThread::testCancel();
00195 }
00196
00197 IEventQueueBuffer::Type
00198 CXWindowsEventQueueBuffer::getEvent(CEvent& event, UInt32& dataID)
00199 {
00200 CLock lock(&m_mutex);
00201
00202
00203 flush();
00204
00205
00206 XNextEvent(m_display, &m_event);
00207
00208
00209 if (m_event.xany.type == ClientMessage &&
00210 m_event.xclient.message_type == m_userEvent) {
00211 dataID = static_cast<UInt32>(m_event.xclient.data.l[0]);
00212 return kUser;
00213 }
00214 else {
00215 event = CEvent(CEvent::kSystem,
00216 IEventQueue::getSystemTarget(), &m_event);
00217 return kSystem;
00218 }
00219 }
00220
00221 bool
00222 CXWindowsEventQueueBuffer::addEvent(UInt32 dataID)
00223 {
00224
00225 XEvent xevent;
00226 xevent.xclient.type = ClientMessage;
00227 xevent.xclient.window = m_window;
00228 xevent.xclient.message_type = m_userEvent;
00229 xevent.xclient.format = 32;
00230 xevent.xclient.data.l[0] = static_cast<long>(dataID);
00231
00232
00233 CLock lock(&m_mutex);
00234 m_postedEvents.push_back(xevent);
00235
00236
00237
00238
00239
00240 if (m_waiting) {
00241 flush();
00242
00243
00244
00245
00246 ssize_t write_response = write(m_pipefd[1], "!", 1);
00247
00248
00249 if (write_response < 0)
00250 {
00251
00252 }
00253 }
00254
00255 return true;
00256 }
00257
00258 bool
00259 CXWindowsEventQueueBuffer::isEmpty() const
00260 {
00261 CLock lock(&m_mutex);
00262 return (XPending(m_display) == 0 );
00263 }
00264
00265 CEventQueueTimer*
00266 CXWindowsEventQueueBuffer::newTimer(double, bool) const
00267 {
00268 return new CEventQueueTimer;
00269 }
00270
00271 void
00272 CXWindowsEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const
00273 {
00274 delete timer;
00275 }
00276
00277 void
00278 CXWindowsEventQueueBuffer::flush()
00279 {
00280
00281
00282
00283 for (size_t i = 0; i < m_postedEvents.size(); ++i) {
00284 XSendEvent(m_display, m_window, False, 0, &m_postedEvents[i]);
00285 }
00286 XFlush(m_display);
00287 m_postedEvents.clear();
00288 }