1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2004 Chris Schoeneman
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 LICENSE 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  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "platform/OSXEventQueueBuffer.h"
20 
21 #include "base/Event.h"
22 #include "base/IEventQueue.h"
23 
24 //
25 // EventQueueTimer
26 //
27 
28 class EventQueueTimer { };
29 
30 //
31 // OSXEventQueueBuffer
32 //
33 
OSXEventQueueBuffer(IEventQueue * events)34 OSXEventQueueBuffer::OSXEventQueueBuffer(IEventQueue* events) :
35     m_event(NULL),
36     m_eventQueue(events),
37     m_carbonEventQueue(NULL)
38 {
39     // do nothing
40 }
41 
~OSXEventQueueBuffer()42 OSXEventQueueBuffer::~OSXEventQueueBuffer()
43 {
44     // release the last event
45     if (m_event != NULL) {
46         ReleaseEvent(m_event);
47     }
48 }
49 
50 void
init()51 OSXEventQueueBuffer::init()
52 {
53     m_carbonEventQueue = GetCurrentEventQueue();
54 }
55 
56 void
waitForEvent(double timeout)57 OSXEventQueueBuffer::waitForEvent(double timeout)
58 {
59     EventRef event;
60     ReceiveNextEvent(0, NULL, timeout, false, &event);
61 }
62 
63 IEventQueueBuffer::Type
getEvent(Event & event,UInt32 & dataID)64 OSXEventQueueBuffer::getEvent(Event& event, UInt32& dataID)
65 {
66     // release the previous event
67     if (m_event != NULL) {
68         ReleaseEvent(m_event);
69         m_event = NULL;
70     }
71 
72     // get the next event
73     OSStatus error = ReceiveNextEvent(0, NULL, 0.0, true, &m_event);
74 
75     // handle the event
76     if (error == eventLoopQuitErr) {
77         event = Event(Event::kQuit);
78         return kSystem;
79     }
80     else if (error != noErr) {
81         return kNone;
82     }
83     else {
84         UInt32 eventClass = GetEventClass(m_event);
85         switch (eventClass) {
86         case 'Syne':
87             dataID = GetEventKind(m_event);
88             return kUser;
89 
90         default:
91             event = Event(Event::kSystem,
92                         m_eventQueue->getSystemTarget(), &m_event);
93             return kSystem;
94         }
95     }
96 }
97 
98 bool
addEvent(UInt32 dataID)99 OSXEventQueueBuffer::addEvent(UInt32 dataID)
100 {
101     EventRef event;
102     OSStatus error = CreateEvent(
103                             kCFAllocatorDefault,
104                             'Syne',
105                             dataID,
106                             0,
107                             kEventAttributeNone,
108                             &event);
109 
110     if (error == noErr) {
111 
112         assert(m_carbonEventQueue != NULL);
113 
114         error = PostEventToQueue(
115             m_carbonEventQueue,
116             event,
117             kEventPriorityStandard);
118 
119         ReleaseEvent(event);
120     }
121 
122     return (error == noErr);
123 }
124 
125 bool
isEmpty() const126 OSXEventQueueBuffer::isEmpty() const
127 {
128     EventRef event;
129     OSStatus status = ReceiveNextEvent(0, NULL, 0.0, false, &event);
130     return (status == eventLoopTimedOutErr);
131 }
132 
133 EventQueueTimer*
newTimer(double,bool) const134 OSXEventQueueBuffer::newTimer(double, bool) const
135 {
136     return new EventQueueTimer;
137 }
138 
139 void
deleteTimer(EventQueueTimer * timer) const140 OSXEventQueueBuffer::deleteTimer(EventQueueTimer* timer) const
141 {
142     delete timer;
143 }
144