>From 9663d300d231242fc77f93a35219d56ba9c90601 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Tue, 3 Jan 2017 14:16:37 +0000 Subject: [PATCH] Improve NS event handling (bug#25265) * src/nsterm.h: Remove reference to timeout_handler. * src/nsterm.m (ns_select): Monitor fd changes using NSFileHandler. --- src/nsterm.h | 1 - src/nsterm.m | 62 +++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/nsterm.h b/src/nsterm.h index dc222a7..8b5b691 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -392,7 +392,6 @@ char const * nstrace_fullscreen_type_name (int); - (void)sendEvent: (NSEvent *)theEvent; - (void)showPreferencesWindow: (id)sender; - (BOOL) openFile: (NSString *)fileName; -- (void)timeout_handler: (NSTimer *)timedEntry; - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg; #ifdef NS_IMPL_GNUSTEP - (void)sendFromMainThread:(id)unused; diff --git a/src/nsterm.m b/src/nsterm.m index 98fd8ab..51cccd0 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -4098,28 +4098,55 @@ overwriting cursor (usually when cursor on a tab) */ return pselect(nfds, readfds, writefds, exceptfds, timeout, sigmask); - result = pselect(nfds, readfds, writefds, exceptfds, - &(struct timespec){.tv_sec = 0, .tv_nsec = 100}, - sigmask); - [outerpool release]; outerpool = [[NSAutoreleasePool alloc] init]; + /* Set up one NSFileHandle for each fd we want to monitor. */ + for (int i = 0 ; i < nfds ; i++) + { + if ((readfds != NULL && FD_ISSET(i, readfds)) + || (writefds != NULL && FD_ISSET(i, writefds)) + || (exceptfds != NULL &&FD_ISSET(i, exceptfds))) + { + NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor: i + closeOnDealloc: NO]; + /* Send a notification to EmacsApp:fileHandleDataAvailable, + which will raise an appDefined event. */ + /* NOTE: I don't think this will pick up writes and + exceptions, so ns_select may not always behave correctly. + I've yet to see a problem, though. */ + [fh waitForDataInBackgroundAndNotify]; + [fh autorelease]; + } + } + if (timeout) { double time = timespectod (*timeout); - timeout_date = [NSDate dateWithTimeIntervalSinceNow:time]; + timeout_date = [NSDate dateWithTimeIntervalSinceNow: time]; } /* Listen for a new NSEvent. */ - ns_event = [NSApp nextEventMatchingMask:NSEventMaskAny - untilDate:timeout_date - inMode:NSDefaultRunLoopMode - dequeue:NO]; + ns_event = [NSApp nextEventMatchingMask: NSEventMaskAny + untilDate: timeout_date + inMode: NSDefaultRunLoopMode + dequeue: NO]; if (ns_event != nil) { - raise (SIGIO); + if ([ns_event type] == NSEventTypeApplicationDefined + && [ns_event data1] == -3) + { + result = pselect(nfds, readfds, writefds, exceptfds, + &(struct timespec){.tv_sec = 0, .tv_nsec = 0}, + sigmask); + } + else + { + raise (SIGIO); + errno = EINTR; + return -1; + } } return result; @@ -5132,6 +5159,12 @@ - (void)applicationDidFinishLaunching: (NSNotification *)notification object:nil]; #endif + [[NSNotificationCenter defaultCenter] + addObserver: self + selector: @selector (fileHandleDataAvailable:) + name: NSFileHandleDataAvailableNotification + object: nil]; + ns_send_appdefined (-2); } @@ -5315,14 +5348,9 @@ - (void)applicationDidResignActive: (NSNotification *)notification ========================================================================== */ - -- (void)timeout_handler: (NSTimer *)timedEntry -/* -------------------------------------------------------------------------- - The timeout specified to ns_select has passed. - -------------------------------------------------------------------------- */ +- (void)fileHandleDataAvailable: (NSNotification *)notification { - /*NSTRACE ("timeout_handler"); */ - ns_send_appdefined (-2); + ns_send_appdefined (-3); } - (void)sendFromMainThread:(id)unused -- 2.10.2