1 | /*
|
---|
2 | * synergy -- mouse and keyboard sharing utility
|
---|
3 | * Copyright (C) 2004 Chris Schoeneman
|
---|
4 | * Copyright (C) 2006 Knut St. Osmundsen
|
---|
5 | *
|
---|
6 | * This package is free software; you can redistribute it and/or
|
---|
7 | * modify it under the terms of the GNU General Public License
|
---|
8 | * found in the file COPYING that should have accompanied this file.
|
---|
9 | *
|
---|
10 | * This package is distributed in the hope that it will be useful,
|
---|
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
13 | * GNU General Public License for more details.
|
---|
14 | */
|
---|
15 |
|
---|
16 | #include "CPMEventQueueBuffer.h"
|
---|
17 | #include "CThread.h"
|
---|
18 | #include "CLog.h"
|
---|
19 | #include "IEventQueue.h"
|
---|
20 | #include "CPMUtil.h"
|
---|
21 | #include <unistd.h>
|
---|
22 |
|
---|
23 | //
|
---|
24 | // CEventQueueTimer
|
---|
25 | //
|
---|
26 |
|
---|
27 | class CEventQueueTimer { };
|
---|
28 |
|
---|
29 |
|
---|
30 | //
|
---|
31 | // CPMEventQueueBuffer
|
---|
32 | //
|
---|
33 |
|
---|
34 | CPMEventQueueBuffer::CPMEventQueueBuffer()
|
---|
35 | {
|
---|
36 | // the anchor block. Remeber it for use when waiting, peeking, and getting events.
|
---|
37 | m_hab = NULLHANDLE;
|
---|
38 | PTIB pTib;
|
---|
39 | PPIB pPib;
|
---|
40 | DosGetInfoBlocks(&pTib, &pPib);
|
---|
41 | LOG((CLOG_DEBUG2 "CPMEventQueueBuffer: ultype=%lx tid=%lx", pPib->pib_ultype, pTib->tib_ptib2->tib2_ultid));
|
---|
42 | if (pPib->pib_ultype != 3) {
|
---|
43 | pPib->pib_ultype = 3;
|
---|
44 | m_shallTerminate = true;
|
---|
45 | m_hab = WinInitialize(0);
|
---|
46 | }
|
---|
47 | if (m_hab == NULLHANDLE) {
|
---|
48 | m_hab = CPMUtil::getHAB();
|
---|
49 | if (m_hab == NULLHANDLE) {
|
---|
50 | m_shallTerminate = true;
|
---|
51 | m_hab = WinInitialize(0);
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | // the message queue. remember it so we can post and get messages.
|
---|
56 | m_hmq = CPMUtil::getHMQ(m_hab);
|
---|
57 | if (m_hmq == NULLHANDLE) {
|
---|
58 | m_shallDestroyMsgQueue = true;
|
---|
59 | m_hmq = WinCreateMsgQueue(m_hab, 0);
|
---|
60 | }
|
---|
61 |
|
---|
62 | // check that we succeeded the two previous steps.
|
---|
63 | if (m_hab == NULLHANDLE || m_hmq == NULLHANDLE) {
|
---|
64 | LOG((CLOG_CRIT "couldn't get the hab(%lx)/hmq(%lx) of the current thread!", m_hab, m_hmq));
|
---|
65 | assert(m_hab != NULLHANDLE && m_hmq != NULLHANDLE);
|
---|
66 | }
|
---|
67 | assert(CPMUtil::getHAB() == m_hab);
|
---|
68 |
|
---|
69 | // create a message type for custom events
|
---|
70 | m_userEvent = WM_USER + 42 + 42 + 42;
|
---|
71 |
|
---|
72 | // get message type for daemon quit
|
---|
73 | m_daemonQuit = WM_USER + 666;
|
---|
74 |
|
---|
75 | // create the event semaphore we'll be waiting on when waiting for messages.
|
---|
76 | m_hev = NULLHANDLE;
|
---|
77 | APIRET rc = DosCreateEventSem(NULL, &m_hev, 0, FALSE);
|
---|
78 | assert(rc == NO_ERROR);
|
---|
79 | LOG((CLOG_DEBUG2 "CPMEventQueueBuffer: m_userEvent=%#lx m_daemonQuit=%#lx m_hev=%#lx m_hab=%#lx m_hmq=%#lx m_shallTermiate=%d m_shallDestroyMsgQueue=%d",
|
---|
80 | m_userEvent, m_daemonQuit, m_hev, m_hab, m_hmq, m_shallTerminate, m_shallDestroyMsgQueue));
|
---|
81 | }
|
---|
82 |
|
---|
83 | CPMEventQueueBuffer::~CPMEventQueueBuffer()
|
---|
84 | {
|
---|
85 | // do nothing
|
---|
86 | DosCloseEventSem(m_hev);
|
---|
87 | if (m_shallDestroyMsgQueue) {
|
---|
88 | WinDestroyMsgQueue(m_hmq);
|
---|
89 | }
|
---|
90 | if (m_shallTerminate) {
|
---|
91 | WinTerminate(m_hab);
|
---|
92 | }
|
---|
93 | }
|
---|
94 |
|
---|
95 | void
|
---|
96 | CPMEventQueueBuffer::waitForEvent(double timeout)
|
---|
97 | {
|
---|
98 | // check if messages are available first.
|
---|
99 | ULONG fStatus = WinQueryQueueStatus(HWND_DESKTOP);
|
---|
100 | if (!fStatus) {
|
---|
101 | ULONG cPosts;
|
---|
102 | DosResetEventSem(m_hev, &cPosts);
|
---|
103 | fStatus = WinQueryQueueStatus(HWND_DESKTOP);
|
---|
104 | }
|
---|
105 | LOG((CLOG_DEBUG2 "waitForEvent: %#lx", fStatus));
|
---|
106 | if (!fStatus) {
|
---|
107 | // convert timeout and wait.
|
---|
108 | ULONG ulPMTimeout = timeout < 0.0
|
---|
109 | ? SEM_INDEFINITE_WAIT
|
---|
110 | : (ULONG)(1000.0 * timeout);
|
---|
111 | WinWaitEventSem(m_hev, ulPMTimeout);
|
---|
112 | LOG((CLOG_DEBUG2 "waitForEvent: ulPMTimeout=%ld", ulPMTimeout));
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | IEventQueueBuffer::Type
|
---|
117 | CPMEventQueueBuffer::getEvent(CEvent& event, UInt32& dataID)
|
---|
118 | {
|
---|
119 | // peek at messages first.
|
---|
120 | QMSG qmsg;
|
---|
121 | if (!WinPeekMsg(m_hab, &qmsg, NULLHANDLE, 0, 0, PM_NOREMOVE)) {
|
---|
122 | LOG((CLOG_DEBUG2 "getEvent: kNone"));
|
---|
123 | return kNone;
|
---|
124 | }
|
---|
125 |
|
---|
126 | // get the message
|
---|
127 | if ( !WinGetMsg(m_hab, &m_event, NULLHANDLE, 0, 0)
|
---|
128 | || (m_event.msg == m_daemonQuit && m_daemonQuit != 0)) {
|
---|
129 | event = CEvent(CEvent::kQuit);
|
---|
130 | return kSystem;
|
---|
131 | }
|
---|
132 |
|
---|
133 | if (m_event.msg == m_userEvent) {
|
---|
134 | dataID = (UInt32)(uintptr_t)m_event.mp1;
|
---|
135 | LOG((CLOG_DEBUG2 "getEvent: dataID=%#x", dataID));
|
---|
136 | return kUser;
|
---|
137 | }
|
---|
138 |
|
---|
139 | event = CEvent(CEvent::kSystem, IEventQueue::getSystemTarget(), &m_event);
|
---|
140 | LOG((CLOG_DEBUG2 "getEvent: kSystem"));
|
---|
141 | return kSystem;
|
---|
142 | }
|
---|
143 |
|
---|
144 | bool
|
---|
145 | CPMEventQueueBuffer::addEvent(UInt32 dataID)
|
---|
146 | {
|
---|
147 | LOG((CLOG_DEBUG2 "addEvent: dataID=%#x", dataID));
|
---|
148 | BOOL fRc = WinPostQueueMsg(m_hmq, m_userEvent, (MPARAM)dataID, 0) != FALSE;
|
---|
149 | if (fRc) {
|
---|
150 | DosPostEventSem(m_hev);
|
---|
151 | } else {
|
---|
152 | LOG((CLOG_CRIT "addEvent: dataID=%#x fRc=%d lasterr=%d", dataID, WinGetLastError(CPMUtil::getHAB())));
|
---|
153 | }
|
---|
154 | return fRc;
|
---|
155 | }
|
---|
156 |
|
---|
157 | bool
|
---|
158 | CPMEventQueueBuffer::isEmpty() const
|
---|
159 | {
|
---|
160 | ULONG fStatus = WinQueryQueueStatus(HWND_DESKTOP);
|
---|
161 | LOG((CLOG_DEBUG2 "isEmpty: %#lx", fStatus));
|
---|
162 | return fStatus == 0;
|
---|
163 | }
|
---|
164 |
|
---|
165 | CEventQueueTimer*
|
---|
166 | CPMEventQueueBuffer::newTimer(double, bool) const
|
---|
167 | {
|
---|
168 | return new CEventQueueTimer;
|
---|
169 | }
|
---|
170 |
|
---|
171 | void
|
---|
172 | CPMEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const
|
---|
173 | {
|
---|
174 | delete timer;
|
---|
175 | }
|
---|
176 |
|
---|
177 | /*
|
---|
178 | * Local Variables:
|
---|
179 | * mode: c
|
---|
180 | * c-file-style: "k&r"
|
---|
181 | * c-basic-offset: 4
|
---|
182 | * tab-width: 4
|
---|
183 | * indent-tabs-mode: t
|
---|
184 | * End:
|
---|
185 | */
|
---|
186 |
|
---|