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