mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-12 14:30:42 -08:00
Improve event loop on NS so that no polling is used.
* nsmenu.m (popupSession): Remove. (pop_down_menu): Remove endModalSession. (timeout_handler:): New method. (runDialogAt:): Get next timeout. Start a NSTimer with that timeout. Call runModalForWindow. Check timer_fired when it returns. If not set, cancel timer and break out of loop. Otherwise loop again, with a new timeout. * nsterm.h (EmacsApp): fd_handler takes id argument. (EmacsDialogPanel): Add timer_fired and timeout_handler. * nsterm.m: Include fcntl.h if present. (fd_entry, t_readfds, inNsSelect): Remove. (select_writefds, select_valid, select_timeout, selfds) (select_mutex, apploopnr): Add. (EV_TRAILER): Call kbd_buffer_store_event_hold only if q_event_ptr. Otherwise call kbd_buffer_store_event. (ns_send_appdefined): Remove release of fd_entry. (ns_read_socket): Always send appdefined. Remove inNsSelect check. Increment and decrement apploopnr. (ns_select): If no file descriptors, just do a NSTimer. Otherwise copy read/write masks and start select thread (fd_handler). Start main loop and wait for application defined event. Inform select thread to stop selecting after main loop is exited. (ns_term_init): Create selfds pipe and set non-blocking. Initialize select_mutex. Start the select thread (fd_handler). (fd_handler:): Loop forever, wait for info from the main thread to either start or stop selecting. When select returns, send and appdefined event. (sendScrollEventAtLoc:fromEvent:): Check if q_event_ptr is set. If not call kbd_buffer_store_event.
This commit is contained in:
parent
ac4845a68b
commit
ddee65158c
4 changed files with 280 additions and 119 deletions
|
|
@ -1,5 +1,37 @@
|
|||
2012-08-15 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* nsmenu.m (popupSession): Remove.
|
||||
(pop_down_menu): Remove endModalSession.
|
||||
(timeout_handler:): New method.
|
||||
(runDialogAt:): Get next timeout. Start a NSTimer with that timeout.
|
||||
Call runModalForWindow. Check timer_fired when it returns.
|
||||
If not set, cancel timer and break out of loop.
|
||||
Otherwise loop again, with a new timeout.
|
||||
|
||||
* nsterm.m: Include fcntl.h if present.
|
||||
(fd_entry, t_readfds, inNsSelect): Remove.
|
||||
(select_writefds, select_valid, select_timeout, selfds)
|
||||
(select_mutex, apploopnr): Add.
|
||||
(EV_TRAILER): Call kbd_buffer_store_event_hold only if q_event_ptr.
|
||||
Otherwise call kbd_buffer_store_event.
|
||||
(ns_send_appdefined): Remove release of fd_entry.
|
||||
(ns_read_socket): Always send appdefined. Remove inNsSelect check.
|
||||
Increment and decrement apploopnr.
|
||||
(ns_select): If no file descriptors, just do a NSTimer.
|
||||
Otherwise copy read/write masks and start select thread (fd_handler).
|
||||
Start main loop and wait for application defined event.
|
||||
Inform select thread to stop selecting after main loop is exited.
|
||||
(ns_term_init): Create selfds pipe and set non-blocking.
|
||||
Initialize select_mutex. Start the select thread (fd_handler).
|
||||
(fd_handler:): Loop forever, wait for info from the main thread
|
||||
to either start or stop selecting. When select returns, send
|
||||
and appdefined event.
|
||||
(sendScrollEventAtLoc:fromEvent:): Check if q_event_ptr is set.
|
||||
If not call kbd_buffer_store_event.
|
||||
|
||||
* nsterm.h (EmacsApp): fd_handler takes id argument.
|
||||
(EmacsDialogPanel): Add timer_fired and timeout_handler.
|
||||
|
||||
* gtkutil.c (xg_mark_data): Use FRAME_X_P.
|
||||
|
||||
2012-08-15 Eli Zaretskii <eliz@gnu.org>
|
||||
|
|
|
|||
43
src/nsmenu.m
43
src/nsmenu.m
|
|
@ -73,7 +73,6 @@ EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
|
|||
|
||||
/* Nonzero means a menu is currently active. */
|
||||
static int popup_activated_flag;
|
||||
static NSModalSession popupSession;
|
||||
|
||||
/* Nonzero means we are tracking and updating menus. */
|
||||
static int trackingMenu;
|
||||
|
|
@ -1365,8 +1364,6 @@ pop_down_menu (Lisp_Object arg)
|
|||
{
|
||||
EmacsDialogPanel *panel = unwind_data->dialog;
|
||||
popup_activated_flag = 0;
|
||||
[NSApp endModalSession: popupSession];
|
||||
|
||||
[panel close];
|
||||
[unwind_data->pool release];
|
||||
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
|
||||
|
|
@ -1756,20 +1753,40 @@ void process_dialog (id window, Lisp_Object list)
|
|||
}
|
||||
|
||||
|
||||
|
||||
- (void)timeout_handler: (NSTimer *)timedEntry
|
||||
{
|
||||
timer_fired = 1;
|
||||
[NSApp abortModal];
|
||||
}
|
||||
|
||||
- (Lisp_Object)runDialogAt: (NSPoint)p
|
||||
{
|
||||
NSInteger ret;
|
||||
NSInteger ret = 0;
|
||||
|
||||
/* initiate a session that will be ended by pop_down_menu */
|
||||
popupSession = [NSApp beginModalSessionForWindow: self];
|
||||
while (popup_activated_flag
|
||||
&& (ret = [NSApp runModalSession: popupSession])
|
||||
== NSRunContinuesResponse)
|
||||
while (popup_activated_flag)
|
||||
{
|
||||
/* Run this for timers.el, indep of atimers; might not return.
|
||||
TODO: use return value to avoid calling every iteration. */
|
||||
timer_check ();
|
||||
[NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
|
||||
NSTimer *tmo = nil;
|
||||
EMACS_TIME next_time = timer_check ();
|
||||
|
||||
if (EMACS_TIME_VALID_P (next_time))
|
||||
{
|
||||
double time = EMACS_TIME_TO_DOUBLE (next_time);
|
||||
tmo = [NSTimer timerWithTimeInterval: time
|
||||
target: self
|
||||
selector: @selector (timeout_handler:)
|
||||
userInfo: 0
|
||||
repeats: NO];
|
||||
[[NSRunLoop currentRunLoop] addTimer: tmo
|
||||
forMode: NSModalPanelRunLoopMode];
|
||||
}
|
||||
timer_fired = 0;
|
||||
ret = [NSApp runModalForWindow: self];
|
||||
if (! timer_fired)
|
||||
{
|
||||
if (tmo != nil) [tmo invalidate]; /* Cancels timer */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{ /* FIXME: BIG UGLY HACK!!! */
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
- (void)sendEvent: (NSEvent *)theEvent;
|
||||
- (void)showPreferencesWindow: (id)sender;
|
||||
- (BOOL) openFile: (NSString *)fileName;
|
||||
- (void)fd_handler: (NSTimer *) fdEntry;
|
||||
- (void)fd_handler: (id)unused;
|
||||
- (void)timeout_handler: (NSTimer *)timedEntry;
|
||||
- (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg;
|
||||
@end
|
||||
|
|
@ -195,12 +195,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
NSTextField *title;
|
||||
NSMatrix *matrix;
|
||||
int rows, cols;
|
||||
int timer_fired;
|
||||
}
|
||||
- initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ;
|
||||
- addButton: (char *)str value: (Lisp_Object)val row: (int)row;
|
||||
- addString: (char *)str row: (int)row;
|
||||
- addSplit;
|
||||
- (Lisp_Object)runDialogAt: (NSPoint)p;
|
||||
- (void)timeout_handler: (NSTimer *)timedEntry;
|
||||
@end
|
||||
|
||||
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
|
||||
|
|
|
|||
320
src/nsterm.m
320
src/nsterm.m
|
|
@ -39,6 +39,10 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
|
|||
#include <c-strcase.h>
|
||||
#include <ftoastr.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "lisp.h"
|
||||
#include "blockinput.h"
|
||||
#include "sysselect.h"
|
||||
|
|
@ -184,17 +188,20 @@ static BOOL ns_menu_bar_is_hidden = NO;
|
|||
static BOOL send_appdefined = YES;
|
||||
static NSEvent *last_appdefined_event = 0;
|
||||
static NSTimer *timed_entry = 0;
|
||||
static NSTimer *fd_entry = nil;
|
||||
static NSTimer *scroll_repeat_entry = nil;
|
||||
static fd_set select_readfds, t_readfds;
|
||||
static int select_nfds;
|
||||
static fd_set select_readfds, select_writefds;
|
||||
enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 };
|
||||
static int select_nfds = 0, select_valid = 0;
|
||||
static EMACS_TIME select_timeout = { 0, 0 };
|
||||
static int selfds[2] = { -1, -1 };
|
||||
static pthread_mutex_t select_mutex;
|
||||
static int apploopnr = 0;
|
||||
static NSAutoreleasePool *outerpool;
|
||||
static struct input_event *emacs_event = NULL;
|
||||
static struct input_event *q_event_ptr = NULL;
|
||||
static int n_emacs_events_pending = 0;
|
||||
static NSMutableArray *ns_pending_files, *ns_pending_service_names,
|
||||
*ns_pending_service_args;
|
||||
static BOOL inNsSelect = 0;
|
||||
static BOOL ns_do_open_file = NO;
|
||||
|
||||
/* Convert modifiers in a NeXTstep event to emacs style modifiers. */
|
||||
|
|
@ -252,15 +259,20 @@ static BOOL ns_do_open_file = NO;
|
|||
|
||||
/* This is a piece of code which is common to all the event handling
|
||||
methods. Maybe it should even be a function. */
|
||||
#define EV_TRAILER(e) \
|
||||
{ \
|
||||
XSETFRAME (emacs_event->frame_or_window, emacsframe); \
|
||||
if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
|
||||
n_emacs_events_pending++; \
|
||||
kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
|
||||
EVENT_INIT (*emacs_event); \
|
||||
ns_send_appdefined (-1); \
|
||||
}
|
||||
#define EV_TRAILER(e) \
|
||||
{ \
|
||||
XSETFRAME (emacs_event->frame_or_window, emacsframe); \
|
||||
if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
|
||||
if (q_event_ptr) \
|
||||
{ \
|
||||
n_emacs_events_pending++; \
|
||||
kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
|
||||
} \
|
||||
else \
|
||||
kbd_buffer_store_event (emacs_event); \
|
||||
EVENT_INIT (*emacs_event); \
|
||||
ns_send_appdefined (-1); \
|
||||
}
|
||||
|
||||
void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
|
||||
|
||||
|
|
@ -3377,14 +3389,6 @@ ns_send_appdefined (int value)
|
|||
timed_entry = nil;
|
||||
}
|
||||
|
||||
/* Ditto for file descriptor poller */
|
||||
if (fd_entry)
|
||||
{
|
||||
[fd_entry invalidate];
|
||||
[fd_entry release];
|
||||
fd_entry = nil;
|
||||
}
|
||||
|
||||
nxev = [NSEvent otherEventWithType: NSApplicationDefined
|
||||
location: NSMakePoint (0, 0)
|
||||
modifierFlags: 0
|
||||
|
|
@ -3402,7 +3406,6 @@ ns_send_appdefined (int value)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ns_read_socket (struct terminal *terminal, int expected,
|
||||
struct input_event *hold_quit)
|
||||
|
|
@ -3466,24 +3469,14 @@ ns_read_socket (struct terminal *terminal, int expected,
|
|||
/* Run and wait for events. We must always send one NX_APPDEFINED event
|
||||
to ourself, otherwise [NXApp run] will never exit. */
|
||||
send_appdefined = YES;
|
||||
ns_send_appdefined (-1);
|
||||
|
||||
/* If called via ns_select, this is called once with expected=1,
|
||||
because we expect either the timeout or file descriptor activity.
|
||||
In this case the first event through will either be real input or
|
||||
one of these. read_avail_input() then calls once more with expected=0
|
||||
and in that case we need to return quickly if there is nothing.
|
||||
If we're being called outside of that, it's also OK to return quickly
|
||||
after one iteration through the event loop, since other terms do
|
||||
this and emacs expects it. */
|
||||
if (!(inNsSelect && expected))
|
||||
if (++apploopnr != 1)
|
||||
{
|
||||
/* Post an application defined event on the event queue. When this is
|
||||
received the [NXApp run] will return, thus having processed all
|
||||
events which are currently queued, if any. */
|
||||
ns_send_appdefined (-1);
|
||||
abort ();
|
||||
}
|
||||
|
||||
[NSApp run];
|
||||
--apploopnr;
|
||||
}
|
||||
|
||||
nevents = n_emacs_events_pending;
|
||||
|
|
@ -3503,65 +3496,89 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
|
|||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
int result;
|
||||
double time;
|
||||
NSEvent *ev;
|
||||
struct timespec select_timeout;
|
||||
int k, nr = 0;
|
||||
struct input_event event;
|
||||
char c;
|
||||
|
||||
/* NSTRACE (ns_select); */
|
||||
|
||||
if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO &&
|
||||
[NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
|
||||
inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */)
|
||||
for (k = 0; readfds && k < nfds+1; k++)
|
||||
if (FD_ISSET(k, readfds)) ++nr;
|
||||
|
||||
if (NSApp == nil
|
||||
|| (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
|
||||
return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask);
|
||||
|
||||
/* Save file descriptor set, which gets overwritten in calls to select ()
|
||||
Note, this is called from process.c, and only readfds is ever set */
|
||||
if (readfds)
|
||||
[outerpool release];
|
||||
outerpool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
send_appdefined = YES;
|
||||
if (nr > 0)
|
||||
{
|
||||
memcpy (&select_readfds, readfds, sizeof (fd_set));
|
||||
pthread_mutex_lock (&select_mutex);
|
||||
select_nfds = nfds;
|
||||
select_valid = 0;
|
||||
if (readfds)
|
||||
{
|
||||
select_readfds = *readfds;
|
||||
select_valid += SELECT_HAVE_READ;
|
||||
}
|
||||
if (writefds)
|
||||
{
|
||||
select_writefds = *writefds;
|
||||
select_valid += SELECT_HAVE_WRITE;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
select_timeout = *timeout;
|
||||
select_valid += SELECT_HAVE_TMO;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock (&select_mutex);
|
||||
|
||||
/* Inform fd_handler that select should be called */
|
||||
c = 'g';
|
||||
write (selfds[1], &c, 1);
|
||||
}
|
||||
else if (nr == 0 && timeout)
|
||||
{
|
||||
/* No file descriptor, just a timeout, no need to wake fd_handler */
|
||||
double time = EMACS_TIME_TO_DOUBLE (*timeout);
|
||||
timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
|
||||
target: NSApp
|
||||
selector:
|
||||
@selector (timeout_handler:)
|
||||
userInfo: 0
|
||||
repeats: NO]
|
||||
retain];
|
||||
}
|
||||
else /* No timeout and no file descriptors, can this happen? */
|
||||
{
|
||||
/* Send appdefined so we exit from the loop */
|
||||
ns_send_appdefined (-1);
|
||||
}
|
||||
else
|
||||
select_nfds = 0;
|
||||
|
||||
/* Try an initial select for pending data on input files */
|
||||
select_timeout.tv_sec = select_timeout.tv_nsec = 0;
|
||||
result = pselect (nfds, readfds, writefds, exceptfds,
|
||||
&select_timeout, sigmask);
|
||||
if (result)
|
||||
return result;
|
||||
EVENT_INIT (event);
|
||||
BLOCK_INPUT;
|
||||
emacs_event = &event;
|
||||
if (++apploopnr != 1)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
[NSApp run];
|
||||
--apploopnr;
|
||||
emacs_event = NULL;
|
||||
if (nr > 0 && readfds)
|
||||
{
|
||||
c = 's';
|
||||
write (selfds[1], &c, 1);
|
||||
}
|
||||
UNBLOCK_INPUT;
|
||||
|
||||
/* if (!timeout || timed_entry || fd_entry)
|
||||
fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */
|
||||
|
||||
/* set a timeout and run the main AppKit event loop while continuing
|
||||
to monitor the files */
|
||||
time = EMACS_TIME_TO_DOUBLE (*timeout);
|
||||
timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
|
||||
target: NSApp
|
||||
selector: @selector (timeout_handler:)
|
||||
userInfo: 0
|
||||
repeats: YES] /* for safe removal */
|
||||
retain];
|
||||
|
||||
/* set a periodic task to try the pselect () again */
|
||||
fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1
|
||||
target: NSApp
|
||||
selector: @selector (fd_handler:)
|
||||
userInfo: 0
|
||||
repeats: YES]
|
||||
retain];
|
||||
|
||||
/* Let Application dispatch events until it receives an event of the type
|
||||
NX_APPDEFINED, which should only be sent by timeout_handler.
|
||||
We tell read_avail_input() that input is "expected" because we do expect
|
||||
either the timeout or fd handler to fire, and if they don't, the original
|
||||
call from process.c that got us here expects us to wait until some input
|
||||
comes. */
|
||||
inNsSelect = 1;
|
||||
gobble_input (1);
|
||||
ev = last_appdefined_event;
|
||||
inNsSelect = 0;
|
||||
|
||||
if (ev)
|
||||
{
|
||||
|
|
@ -3575,25 +3592,28 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
|
|||
if (t == -2)
|
||||
{
|
||||
/* The NX_APPDEFINED event we received was a timeout. */
|
||||
return 0;
|
||||
result = 0;
|
||||
}
|
||||
else if (t == -1)
|
||||
{
|
||||
/* The NX_APPDEFINED event we received was the result of
|
||||
at least one real input event arriving. */
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
result = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Received back from pselect () in fd_handler; copy the results */
|
||||
if (readfds)
|
||||
memcpy (readfds, &select_readfds, sizeof (fd_set));
|
||||
return t;
|
||||
/* Received back from select () in fd_handler; copy the results */
|
||||
pthread_mutex_lock (&select_mutex);
|
||||
if (readfds) *readfds = select_readfds;
|
||||
if (writefds) *writefds = select_writefds;
|
||||
if (timeout) *timeout = select_timeout;
|
||||
pthread_mutex_unlock (&select_mutex);
|
||||
result = t;
|
||||
}
|
||||
}
|
||||
/* never reached, shut compiler up */
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4024,6 +4044,21 @@ ns_term_init (Lisp_Object display_name)
|
|||
{
|
||||
baud_rate = 38400;
|
||||
Fset_input_interrupt_mode (Qnil);
|
||||
|
||||
if (selfds[0] == -1)
|
||||
{
|
||||
if (pipe (selfds) == -1)
|
||||
{
|
||||
fprintf (stderr, "Failed to create pipe: %s\n",
|
||||
emacs_strerror (errno));
|
||||
abort ();
|
||||
}
|
||||
|
||||
fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL));
|
||||
FD_ZERO (&select_readfds);
|
||||
FD_ZERO (&select_writefds);
|
||||
pthread_mutex_init (&select_mutex, NULL);
|
||||
}
|
||||
ns_initialized = 1;
|
||||
}
|
||||
|
||||
|
|
@ -4039,6 +4074,11 @@ ns_term_init (Lisp_Object display_name)
|
|||
return NULL;
|
||||
[NSApp setDelegate: NSApp];
|
||||
|
||||
/* Start the select thread. */
|
||||
[NSThread detachNewThreadSelector:@selector (fd_handler:)
|
||||
toTarget:NSApp
|
||||
withObject:nil];
|
||||
|
||||
/* debugging: log all notifications */
|
||||
/* [[NSNotificationCenter defaultCenter] addObserver: NSApp
|
||||
selector: @selector (logNotification:)
|
||||
|
|
@ -4547,26 +4587,91 @@ not_in_argv (NSString *arg)
|
|||
ns_send_appdefined (-2);
|
||||
}
|
||||
|
||||
- (void)fd_handler: (NSTimer *) fdEntry
|
||||
- (void)fd_handler:(id)unused
|
||||
/* --------------------------------------------------------------------------
|
||||
Check data waiting on file descriptors and terminate if so
|
||||
-------------------------------------------------------------------------- */
|
||||
{
|
||||
int result;
|
||||
struct timespec select_timeout;
|
||||
int waiting = 1, nfds;
|
||||
char c;
|
||||
|
||||
SELECT_TYPE readfds, writefds, *wfds;
|
||||
EMACS_TIME timeout, *tmo;
|
||||
|
||||
/* NSTRACE (fd_handler); */
|
||||
|
||||
if (select_nfds == 0)
|
||||
return;
|
||||
|
||||
memcpy (&t_readfds, &select_readfds, sizeof (fd_set));
|
||||
|
||||
select_timeout.tv_sec = select_timeout.tv_nsec = 0;
|
||||
result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL);
|
||||
if (result)
|
||||
for (;;)
|
||||
{
|
||||
memcpy (&select_readfds, &t_readfds, sizeof (fd_set));
|
||||
ns_send_appdefined (result);
|
||||
if (waiting)
|
||||
{
|
||||
SELECT_TYPE fds;
|
||||
|
||||
FD_SET (selfds[0], &fds);
|
||||
result = select (selfds[0]+1, &fds, NULL, NULL, NULL);
|
||||
if (result > 0)
|
||||
{
|
||||
read (selfds[0], &c, 1);
|
||||
if (c == 'g') waiting = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock (&select_mutex);
|
||||
nfds = select_nfds;
|
||||
|
||||
if (select_valid & SELECT_HAVE_READ)
|
||||
readfds = select_readfds;
|
||||
else
|
||||
FD_ZERO (&readfds);
|
||||
|
||||
if (select_valid & SELECT_HAVE_WRITE)
|
||||
{
|
||||
writefds = select_writefds;
|
||||
wfds = &writefds;
|
||||
}
|
||||
else
|
||||
wfds = NULL;
|
||||
if (select_valid & SELECT_HAVE_TMO)
|
||||
{
|
||||
timeout = select_timeout;
|
||||
tmo = &timeout;
|
||||
}
|
||||
else
|
||||
tmo = NULL;
|
||||
|
||||
pthread_mutex_unlock (&select_mutex);
|
||||
|
||||
FD_SET (selfds[0], &readfds);
|
||||
if (selfds[0] >= nfds) nfds = selfds[0]+1;
|
||||
|
||||
result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL);
|
||||
|
||||
if (result == 0)
|
||||
ns_send_appdefined (-2);
|
||||
else if (result > 0)
|
||||
{
|
||||
if (FD_ISSET (selfds[0], &readfds))
|
||||
{
|
||||
read (selfds[0], &c, 1);
|
||||
if (c == 's') waiting = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock (&select_mutex);
|
||||
if (select_valid & SELECT_HAVE_READ)
|
||||
select_readfds = readfds;
|
||||
if (select_valid & SELECT_HAVE_WRITE)
|
||||
select_writefds = writefds;
|
||||
if (select_valid & SELECT_HAVE_TMO)
|
||||
select_timeout = timeout;
|
||||
pthread_mutex_unlock (&select_mutex);
|
||||
|
||||
ns_send_appdefined (result);
|
||||
}
|
||||
}
|
||||
waiting = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6404,8 +6509,13 @@ not_in_argv (NSString *arg)
|
|||
XSETINT (emacs_event->x, loc * pixel_height);
|
||||
XSETINT (emacs_event->y, pixel_height-20);
|
||||
|
||||
n_emacs_events_pending++;
|
||||
kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
|
||||
if (q_event_ptr)
|
||||
{
|
||||
n_emacs_events_pending++;
|
||||
kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
|
||||
}
|
||||
else
|
||||
kbd_buffer_store_event (emacs_event);
|
||||
EVENT_INIT (*emacs_event);
|
||||
ns_send_appdefined (-1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue