2 * MACDRV Cocoa event queue code
4 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <sys/types.h>
22 #include <sys/event.h>
24 #include <libkern/OSAtomic.h>
26 #include "macdrv_cocoa.h"
27 #import "cocoa_event.h"
29 #import "cocoa_window.h"
32 @interface MacDrvEvent : NSObject
38 - (id) initWithEvent:(const macdrv_event*)event;
42 @implementation MacDrvEvent
44 - (id) initWithEvent:(const macdrv_event*)inEvent
57 @implementation WineEventQueue
66 events = [[NSMutableArray alloc] init];
67 eventsLock = [[NSLock alloc] init];
69 if (!events || !eventsLock)
76 fcntl(fds[0], F_SETFD, 1) == -1 ||
77 fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
78 fcntl(fds[1], F_SETFD, 1) == -1 ||
79 fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1)
93 if (fds[0] != -1) close(fds[0]);
94 if (fds[1] != -1) close(fds[1]);
99 - (void) signalEventAvailable
106 rc = write(fds[1], &junk, 1);
107 } while (rc < 0 && errno == EINTR);
109 if (rc < 0 && errno != EAGAIN)
110 ERR(@"%@: got error writing to event queue signaling pipe: %s\n", self, strerror(errno));
113 - (void) postEventObject:(MacDrvEvent*)event
116 [events addObject:event];
119 [self signalEventAvailable];
122 - (void) postEvent:(const macdrv_event*)inEvent
124 MacDrvEvent* event = [[MacDrvEvent alloc] initWithEvent:inEvent];
125 [self postEventObject:event];
129 - (MacDrvEvent*) getEventMatchingMask:(macdrv_event_mask)mask
136 /* Clear the pipe which signals there are pending events. */
139 rc = read(fds[0], buf, sizeof(buf));
140 } while (rc > 0 || (rc < 0 && errno == EINTR));
141 if (rc == 0 || (rc < 0 && errno != EAGAIN))
144 ERR(@"%@: event queue signaling pipe unexpectedly closed\n", self);
146 ERR(@"%@: got error reading from event queue signaling pipe: %s\n", self, strerror(errno));
153 for (event in events)
155 if (event_mask_for_type(event->event.type) & mask)
164 [events removeObjectAtIndex:index];
168 return [event autorelease];
171 - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)window
173 NSMutableIndexSet* indexes = [[[NSMutableIndexSet alloc] init] autorelease];
177 [events enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
178 MacDrvEvent* event = obj;
179 if ((event_mask_for_type(event->event.type) & mask) &&
180 (!window || event->event.window == (macdrv_window)window))
182 macdrv_cleanup_event(&event->event);
183 [indexes addIndex:idx];
187 [events removeObjectsAtIndexes:indexes];
193 /***********************************************************************
194 * macdrv_create_event_queue
196 * Register this thread with the application on the main thread, and set
197 * up an event queue on which it can deliver events to this thread.
199 macdrv_event_queue macdrv_create_event_queue(void)
201 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
203 WineEventQueue* queue = [[WineEventQueue alloc] init];
204 if (queue && ![NSApp registerEventQueue:queue])
211 return (macdrv_event_queue)queue;
214 /***********************************************************************
215 * macdrv_destroy_event_queue
217 * Tell the application that this thread is exiting and destroy the
218 * associated event queue.
220 void macdrv_destroy_event_queue(macdrv_event_queue queue)
222 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
223 WineEventQueue* q = (WineEventQueue*)queue;
225 [NSApp unregisterEventQueue:q];
231 /***********************************************************************
232 * macdrv_get_event_queue_fd
234 * Get the file descriptor whose readability signals that there are
235 * events on the event queue.
237 int macdrv_get_event_queue_fd(macdrv_event_queue queue)
239 WineEventQueue* q = (WineEventQueue*)queue;
243 /***********************************************************************
244 * macdrv_get_event_from_queue
246 * Pull an event matching the event mask from the event queue and store
247 * it in the event record pointed to by the event parameter. If a
248 * matching event was found, return non-zero; otherwise, return 0.
250 * The caller is responsible for calling macdrv_cleanup_event on any
251 * event returned by this function.
253 int macdrv_get_event_from_queue(macdrv_event_queue queue,
254 macdrv_event_mask mask, macdrv_event *event)
256 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
257 WineEventQueue* q = (WineEventQueue*)queue;
259 MacDrvEvent* macDrvEvent = [q getEventMatchingMask:mask];
261 *event = macDrvEvent->event;
264 return (macDrvEvent != nil);
267 /***********************************************************************
268 * macdrv_cleanup_event
270 * Performs cleanup of an event. For event types which carry resources
271 * such as allocated memory or retained objects, frees/releases those
274 void macdrv_cleanup_event(macdrv_event *event)
276 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
280 case WINDOW_GOT_FOCUS:
281 [(NSMutableSet*)event->window_got_focus.tried_windows release];
285 [(WineWindow*)event->window release];