diff options
| -rw-r--r-- | src/ChangeLog | 32 | ||||
| -rw-r--r-- | src/nsmenu.m | 43 | ||||
| -rw-r--r-- | src/nsterm.h | 4 | ||||
| -rw-r--r-- | src/nsterm.m | 322 |
4 files changed, 281 insertions, 120 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 04a0df774f9..6e49dd44fde 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,37 @@ | |||
| 1 | 2012-08-15 Jan Djärv <jan.h.d@swipnet.se> | 1 | 2012-08-15 Jan Djärv <jan.h.d@swipnet.se> |
| 2 | 2 | ||
| 3 | * nsmenu.m (popupSession): Remove. | ||
| 4 | (pop_down_menu): Remove endModalSession. | ||
| 5 | (timeout_handler:): New method. | ||
| 6 | (runDialogAt:): Get next timeout. Start a NSTimer with that timeout. | ||
| 7 | Call runModalForWindow. Check timer_fired when it returns. | ||
| 8 | If not set, cancel timer and break out of loop. | ||
| 9 | Otherwise loop again, with a new timeout. | ||
| 10 | |||
| 11 | * nsterm.m: Include fcntl.h if present. | ||
| 12 | (fd_entry, t_readfds, inNsSelect): Remove. | ||
| 13 | (select_writefds, select_valid, select_timeout, selfds) | ||
| 14 | (select_mutex, apploopnr): Add. | ||
| 15 | (EV_TRAILER): Call kbd_buffer_store_event_hold only if q_event_ptr. | ||
| 16 | Otherwise call kbd_buffer_store_event. | ||
| 17 | (ns_send_appdefined): Remove release of fd_entry. | ||
| 18 | (ns_read_socket): Always send appdefined. Remove inNsSelect check. | ||
| 19 | Increment and decrement apploopnr. | ||
| 20 | (ns_select): If no file descriptors, just do a NSTimer. | ||
| 21 | Otherwise copy read/write masks and start select thread (fd_handler). | ||
| 22 | Start main loop and wait for application defined event. | ||
| 23 | Inform select thread to stop selecting after main loop is exited. | ||
| 24 | (ns_term_init): Create selfds pipe and set non-blocking. | ||
| 25 | Initialize select_mutex. Start the select thread (fd_handler). | ||
| 26 | (fd_handler:): Loop forever, wait for info from the main thread | ||
| 27 | to either start or stop selecting. When select returns, send | ||
| 28 | and appdefined event. | ||
| 29 | (sendScrollEventAtLoc:fromEvent:): Check if q_event_ptr is set. | ||
| 30 | If not call kbd_buffer_store_event. | ||
| 31 | |||
| 32 | * nsterm.h (EmacsApp): fd_handler takes id argument. | ||
| 33 | (EmacsDialogPanel): Add timer_fired and timeout_handler. | ||
| 34 | |||
| 3 | * gtkutil.c (xg_mark_data): Use FRAME_X_P. | 35 | * gtkutil.c (xg_mark_data): Use FRAME_X_P. |
| 4 | 36 | ||
| 5 | 2012-08-15 Eli Zaretskii <eliz@gnu.org> | 37 | 2012-08-15 Eli Zaretskii <eliz@gnu.org> |
diff --git a/src/nsmenu.m b/src/nsmenu.m index 210f4530d7a..657b9306942 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m | |||
| @@ -73,7 +73,6 @@ EmacsMenu *mainMenu, *svcsMenu, *dockMenu; | |||
| 73 | 73 | ||
| 74 | /* Nonzero means a menu is currently active. */ | 74 | /* Nonzero means a menu is currently active. */ |
| 75 | static int popup_activated_flag; | 75 | static int popup_activated_flag; |
| 76 | static NSModalSession popupSession; | ||
| 77 | 76 | ||
| 78 | /* Nonzero means we are tracking and updating menus. */ | 77 | /* Nonzero means we are tracking and updating menus. */ |
| 79 | static int trackingMenu; | 78 | static int trackingMenu; |
| @@ -1365,8 +1364,6 @@ pop_down_menu (Lisp_Object arg) | |||
| 1365 | { | 1364 | { |
| 1366 | EmacsDialogPanel *panel = unwind_data->dialog; | 1365 | EmacsDialogPanel *panel = unwind_data->dialog; |
| 1367 | popup_activated_flag = 0; | 1366 | popup_activated_flag = 0; |
| 1368 | [NSApp endModalSession: popupSession]; | ||
| 1369 | |||
| 1370 | [panel close]; | 1367 | [panel close]; |
| 1371 | [unwind_data->pool release]; | 1368 | [unwind_data->pool release]; |
| 1372 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; | 1369 | [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; |
| @@ -1756,20 +1753,40 @@ void process_dialog (id window, Lisp_Object list) | |||
| 1756 | } | 1753 | } |
| 1757 | 1754 | ||
| 1758 | 1755 | ||
| 1756 | |||
| 1757 | - (void)timeout_handler: (NSTimer *)timedEntry | ||
| 1758 | { | ||
| 1759 | timer_fired = 1; | ||
| 1760 | [NSApp abortModal]; | ||
| 1761 | } | ||
| 1762 | |||
| 1759 | - (Lisp_Object)runDialogAt: (NSPoint)p | 1763 | - (Lisp_Object)runDialogAt: (NSPoint)p |
| 1760 | { | 1764 | { |
| 1761 | NSInteger ret; | 1765 | NSInteger ret = 0; |
| 1762 | 1766 | ||
| 1763 | /* initiate a session that will be ended by pop_down_menu */ | 1767 | while (popup_activated_flag) |
| 1764 | popupSession = [NSApp beginModalSessionForWindow: self]; | ||
| 1765 | while (popup_activated_flag | ||
| 1766 | && (ret = [NSApp runModalSession: popupSession]) | ||
| 1767 | == NSRunContinuesResponse) | ||
| 1768 | { | 1768 | { |
| 1769 | /* Run this for timers.el, indep of atimers; might not return. | 1769 | NSTimer *tmo = nil; |
| 1770 | TODO: use return value to avoid calling every iteration. */ | 1770 | EMACS_TIME next_time = timer_check (); |
| 1771 | timer_check (); | 1771 | |
| 1772 | [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]]; | 1772 | if (EMACS_TIME_VALID_P (next_time)) |
| 1773 | { | ||
| 1774 | double time = EMACS_TIME_TO_DOUBLE (next_time); | ||
| 1775 | tmo = [NSTimer timerWithTimeInterval: time | ||
| 1776 | target: self | ||
| 1777 | selector: @selector (timeout_handler:) | ||
| 1778 | userInfo: 0 | ||
| 1779 | repeats: NO]; | ||
| 1780 | [[NSRunLoop currentRunLoop] addTimer: tmo | ||
| 1781 | forMode: NSModalPanelRunLoopMode]; | ||
| 1782 | } | ||
| 1783 | timer_fired = 0; | ||
| 1784 | ret = [NSApp runModalForWindow: self]; | ||
| 1785 | if (! timer_fired) | ||
| 1786 | { | ||
| 1787 | if (tmo != nil) [tmo invalidate]; /* Cancels timer */ | ||
| 1788 | break; | ||
| 1789 | } | ||
| 1773 | } | 1790 | } |
| 1774 | 1791 | ||
| 1775 | { /* FIXME: BIG UGLY HACK!!! */ | 1792 | { /* FIXME: BIG UGLY HACK!!! */ |
diff --git a/src/nsterm.h b/src/nsterm.h index de41929e3fd..94984b3d35e 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 56 | - (void)sendEvent: (NSEvent *)theEvent; | 56 | - (void)sendEvent: (NSEvent *)theEvent; |
| 57 | - (void)showPreferencesWindow: (id)sender; | 57 | - (void)showPreferencesWindow: (id)sender; |
| 58 | - (BOOL) openFile: (NSString *)fileName; | 58 | - (BOOL) openFile: (NSString *)fileName; |
| 59 | - (void)fd_handler: (NSTimer *) fdEntry; | 59 | - (void)fd_handler: (id)unused; |
| 60 | - (void)timeout_handler: (NSTimer *)timedEntry; | 60 | - (void)timeout_handler: (NSTimer *)timedEntry; |
| 61 | - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg; | 61 | - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg; |
| 62 | @end | 62 | @end |
| @@ -195,12 +195,14 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 195 | NSTextField *title; | 195 | NSTextField *title; |
| 196 | NSMatrix *matrix; | 196 | NSMatrix *matrix; |
| 197 | int rows, cols; | 197 | int rows, cols; |
| 198 | int timer_fired; | ||
| 198 | } | 199 | } |
| 199 | - initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; | 200 | - initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; |
| 200 | - addButton: (char *)str value: (Lisp_Object)val row: (int)row; | 201 | - addButton: (char *)str value: (Lisp_Object)val row: (int)row; |
| 201 | - addString: (char *)str row: (int)row; | 202 | - addString: (char *)str row: (int)row; |
| 202 | - addSplit; | 203 | - addSplit; |
| 203 | - (Lisp_Object)runDialogAt: (NSPoint)p; | 204 | - (Lisp_Object)runDialogAt: (NSPoint)p; |
| 205 | - (void)timeout_handler: (NSTimer *)timedEntry; | ||
| 204 | @end | 206 | @end |
| 205 | 207 | ||
| 206 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | 208 | #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 |
diff --git a/src/nsterm.m b/src/nsterm.m index 5e3c3ac777f..76e6ee8fb40 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -39,6 +39,10 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) | |||
| 39 | #include <c-strcase.h> | 39 | #include <c-strcase.h> |
| 40 | #include <ftoastr.h> | 40 | #include <ftoastr.h> |
| 41 | 41 | ||
| 42 | #ifdef HAVE_FCNTL_H | ||
| 43 | #include <fcntl.h> | ||
| 44 | #endif | ||
| 45 | |||
| 42 | #include "lisp.h" | 46 | #include "lisp.h" |
| 43 | #include "blockinput.h" | 47 | #include "blockinput.h" |
| 44 | #include "sysselect.h" | 48 | #include "sysselect.h" |
| @@ -184,17 +188,20 @@ static BOOL ns_menu_bar_is_hidden = NO; | |||
| 184 | static BOOL send_appdefined = YES; | 188 | static BOOL send_appdefined = YES; |
| 185 | static NSEvent *last_appdefined_event = 0; | 189 | static NSEvent *last_appdefined_event = 0; |
| 186 | static NSTimer *timed_entry = 0; | 190 | static NSTimer *timed_entry = 0; |
| 187 | static NSTimer *fd_entry = nil; | ||
| 188 | static NSTimer *scroll_repeat_entry = nil; | 191 | static NSTimer *scroll_repeat_entry = nil; |
| 189 | static fd_set select_readfds, t_readfds; | 192 | static fd_set select_readfds, select_writefds; |
| 190 | static int select_nfds; | 193 | enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 }; |
| 194 | static int select_nfds = 0, select_valid = 0; | ||
| 195 | static EMACS_TIME select_timeout = { 0, 0 }; | ||
| 196 | static int selfds[2] = { -1, -1 }; | ||
| 197 | static pthread_mutex_t select_mutex; | ||
| 198 | static int apploopnr = 0; | ||
| 191 | static NSAutoreleasePool *outerpool; | 199 | static NSAutoreleasePool *outerpool; |
| 192 | static struct input_event *emacs_event = NULL; | 200 | static struct input_event *emacs_event = NULL; |
| 193 | static struct input_event *q_event_ptr = NULL; | 201 | static struct input_event *q_event_ptr = NULL; |
| 194 | static int n_emacs_events_pending = 0; | 202 | static int n_emacs_events_pending = 0; |
| 195 | static NSMutableArray *ns_pending_files, *ns_pending_service_names, | 203 | static NSMutableArray *ns_pending_files, *ns_pending_service_names, |
| 196 | *ns_pending_service_args; | 204 | *ns_pending_service_args; |
| 197 | static BOOL inNsSelect = 0; | ||
| 198 | static BOOL ns_do_open_file = NO; | 205 | static BOOL ns_do_open_file = NO; |
| 199 | 206 | ||
| 200 | /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ | 207 | /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ |
| @@ -252,15 +259,20 @@ static BOOL ns_do_open_file = NO; | |||
| 252 | 259 | ||
| 253 | /* This is a piece of code which is common to all the event handling | 260 | /* This is a piece of code which is common to all the event handling |
| 254 | methods. Maybe it should even be a function. */ | 261 | methods. Maybe it should even be a function. */ |
| 255 | #define EV_TRAILER(e) \ | 262 | #define EV_TRAILER(e) \ |
| 256 | { \ | 263 | { \ |
| 257 | XSETFRAME (emacs_event->frame_or_window, emacsframe); \ | 264 | XSETFRAME (emacs_event->frame_or_window, emacsframe); \ |
| 258 | if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ | 265 | if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ |
| 259 | n_emacs_events_pending++; \ | 266 | if (q_event_ptr) \ |
| 260 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ | 267 | { \ |
| 261 | EVENT_INIT (*emacs_event); \ | 268 | n_emacs_events_pending++; \ |
| 262 | ns_send_appdefined (-1); \ | 269 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ |
| 263 | } | 270 | } \ |
| 271 | else \ | ||
| 272 | kbd_buffer_store_event (emacs_event); \ | ||
| 273 | EVENT_INIT (*emacs_event); \ | ||
| 274 | ns_send_appdefined (-1); \ | ||
| 275 | } | ||
| 264 | 276 | ||
| 265 | void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); | 277 | void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); |
| 266 | 278 | ||
| @@ -3377,14 +3389,6 @@ ns_send_appdefined (int value) | |||
| 3377 | timed_entry = nil; | 3389 | timed_entry = nil; |
| 3378 | } | 3390 | } |
| 3379 | 3391 | ||
| 3380 | /* Ditto for file descriptor poller */ | ||
| 3381 | if (fd_entry) | ||
| 3382 | { | ||
| 3383 | [fd_entry invalidate]; | ||
| 3384 | [fd_entry release]; | ||
| 3385 | fd_entry = nil; | ||
| 3386 | } | ||
| 3387 | |||
| 3388 | nxev = [NSEvent otherEventWithType: NSApplicationDefined | 3392 | nxev = [NSEvent otherEventWithType: NSApplicationDefined |
| 3389 | location: NSMakePoint (0, 0) | 3393 | location: NSMakePoint (0, 0) |
| 3390 | modifierFlags: 0 | 3394 | modifierFlags: 0 |
| @@ -3402,7 +3406,6 @@ ns_send_appdefined (int value) | |||
| 3402 | } | 3406 | } |
| 3403 | } | 3407 | } |
| 3404 | 3408 | ||
| 3405 | |||
| 3406 | static int | 3409 | static int |
| 3407 | ns_read_socket (struct terminal *terminal, int expected, | 3410 | ns_read_socket (struct terminal *terminal, int expected, |
| 3408 | struct input_event *hold_quit) | 3411 | struct input_event *hold_quit) |
| @@ -3466,24 +3469,14 @@ ns_read_socket (struct terminal *terminal, int expected, | |||
| 3466 | /* Run and wait for events. We must always send one NX_APPDEFINED event | 3469 | /* Run and wait for events. We must always send one NX_APPDEFINED event |
| 3467 | to ourself, otherwise [NXApp run] will never exit. */ | 3470 | to ourself, otherwise [NXApp run] will never exit. */ |
| 3468 | send_appdefined = YES; | 3471 | send_appdefined = YES; |
| 3472 | ns_send_appdefined (-1); | ||
| 3469 | 3473 | ||
| 3470 | /* If called via ns_select, this is called once with expected=1, | 3474 | if (++apploopnr != 1) |
| 3471 | because we expect either the timeout or file descriptor activity. | ||
| 3472 | In this case the first event through will either be real input or | ||
| 3473 | one of these. read_avail_input() then calls once more with expected=0 | ||
| 3474 | and in that case we need to return quickly if there is nothing. | ||
| 3475 | If we're being called outside of that, it's also OK to return quickly | ||
| 3476 | after one iteration through the event loop, since other terms do | ||
| 3477 | this and emacs expects it. */ | ||
| 3478 | if (!(inNsSelect && expected)) | ||
| 3479 | { | 3475 | { |
| 3480 | /* Post an application defined event on the event queue. When this is | 3476 | abort (); |
| 3481 | received the [NXApp run] will return, thus having processed all | ||
| 3482 | events which are currently queued, if any. */ | ||
| 3483 | ns_send_appdefined (-1); | ||
| 3484 | } | 3477 | } |
| 3485 | |||
| 3486 | [NSApp run]; | 3478 | [NSApp run]; |
| 3479 | --apploopnr; | ||
| 3487 | } | 3480 | } |
| 3488 | 3481 | ||
| 3489 | nevents = n_emacs_events_pending; | 3482 | nevents = n_emacs_events_pending; |
| @@ -3503,65 +3496,89 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 3503 | -------------------------------------------------------------------------- */ | 3496 | -------------------------------------------------------------------------- */ |
| 3504 | { | 3497 | { |
| 3505 | int result; | 3498 | int result; |
| 3506 | double time; | ||
| 3507 | NSEvent *ev; | 3499 | NSEvent *ev; |
| 3508 | struct timespec select_timeout; | 3500 | int k, nr = 0; |
| 3501 | struct input_event event; | ||
| 3502 | char c; | ||
| 3509 | 3503 | ||
| 3510 | /* NSTRACE (ns_select); */ | 3504 | /* NSTRACE (ns_select); */ |
| 3511 | 3505 | ||
| 3512 | if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO && | 3506 | for (k = 0; readfds && k < nfds+1; k++) |
| 3513 | [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil | 3507 | if (FD_ISSET(k, readfds)) ++nr; |
| 3514 | inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */) | 3508 | |
| 3509 | if (NSApp == nil | ||
| 3510 | || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) | ||
| 3515 | return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); | 3511 | return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); |
| 3516 | 3512 | ||
| 3517 | /* Save file descriptor set, which gets overwritten in calls to select () | 3513 | [outerpool release]; |
| 3518 | Note, this is called from process.c, and only readfds is ever set */ | 3514 | outerpool = [[NSAutoreleasePool alloc] init]; |
| 3519 | if (readfds) | 3515 | |
| 3516 | |||
| 3517 | send_appdefined = YES; | ||
| 3518 | if (nr > 0) | ||
| 3520 | { | 3519 | { |
| 3521 | memcpy (&select_readfds, readfds, sizeof (fd_set)); | 3520 | pthread_mutex_lock (&select_mutex); |
| 3522 | select_nfds = nfds; | 3521 | select_nfds = nfds; |
| 3522 | select_valid = 0; | ||
| 3523 | if (readfds) | ||
| 3524 | { | ||
| 3525 | select_readfds = *readfds; | ||
| 3526 | select_valid += SELECT_HAVE_READ; | ||
| 3527 | } | ||
| 3528 | if (writefds) | ||
| 3529 | { | ||
| 3530 | select_writefds = *writefds; | ||
| 3531 | select_valid += SELECT_HAVE_WRITE; | ||
| 3532 | } | ||
| 3533 | |||
| 3534 | if (timeout) | ||
| 3535 | { | ||
| 3536 | select_timeout = *timeout; | ||
| 3537 | select_valid += SELECT_HAVE_TMO; | ||
| 3538 | } | ||
| 3539 | |||
| 3540 | pthread_mutex_unlock (&select_mutex); | ||
| 3541 | |||
| 3542 | /* Inform fd_handler that select should be called */ | ||
| 3543 | c = 'g'; | ||
| 3544 | write (selfds[1], &c, 1); | ||
| 3523 | } | 3545 | } |
| 3524 | else | 3546 | else if (nr == 0 && timeout) |
| 3525 | select_nfds = 0; | 3547 | { |
| 3526 | 3548 | /* No file descriptor, just a timeout, no need to wake fd_handler */ | |
| 3527 | /* Try an initial select for pending data on input files */ | 3549 | double time = EMACS_TIME_TO_DOUBLE (*timeout); |
| 3528 | select_timeout.tv_sec = select_timeout.tv_nsec = 0; | 3550 | timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time |
| 3529 | result = pselect (nfds, readfds, writefds, exceptfds, | 3551 | target: NSApp |
| 3530 | &select_timeout, sigmask); | 3552 | selector: |
| 3531 | if (result) | 3553 | @selector (timeout_handler:) |
| 3532 | return result; | 3554 | userInfo: 0 |
| 3533 | 3555 | repeats: NO] | |
| 3534 | /* if (!timeout || timed_entry || fd_entry) | 3556 | retain]; |
| 3535 | fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */ | 3557 | } |
| 3536 | 3558 | else /* No timeout and no file descriptors, can this happen? */ | |
| 3537 | /* set a timeout and run the main AppKit event loop while continuing | 3559 | { |
| 3538 | to monitor the files */ | 3560 | /* Send appdefined so we exit from the loop */ |
| 3539 | time = EMACS_TIME_TO_DOUBLE (*timeout); | 3561 | ns_send_appdefined (-1); |
| 3540 | timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time | 3562 | } |
| 3541 | target: NSApp | 3563 | |
| 3542 | selector: @selector (timeout_handler:) | 3564 | EVENT_INIT (event); |
| 3543 | userInfo: 0 | 3565 | BLOCK_INPUT; |
| 3544 | repeats: YES] /* for safe removal */ | 3566 | emacs_event = &event; |
| 3545 | retain]; | 3567 | if (++apploopnr != 1) |
| 3546 | 3568 | { | |
| 3547 | /* set a periodic task to try the pselect () again */ | 3569 | abort(); |
| 3548 | fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1 | 3570 | } |
| 3549 | target: NSApp | 3571 | [NSApp run]; |
| 3550 | selector: @selector (fd_handler:) | 3572 | --apploopnr; |
| 3551 | userInfo: 0 | 3573 | emacs_event = NULL; |
| 3552 | repeats: YES] | 3574 | if (nr > 0 && readfds) |
| 3553 | retain]; | 3575 | { |
| 3554 | 3576 | c = 's'; | |
| 3555 | /* Let Application dispatch events until it receives an event of the type | 3577 | write (selfds[1], &c, 1); |
| 3556 | NX_APPDEFINED, which should only be sent by timeout_handler. | 3578 | } |
| 3557 | We tell read_avail_input() that input is "expected" because we do expect | 3579 | UNBLOCK_INPUT; |
| 3558 | either the timeout or fd handler to fire, and if they don't, the original | 3580 | |
| 3559 | call from process.c that got us here expects us to wait until some input | ||
| 3560 | comes. */ | ||
| 3561 | inNsSelect = 1; | ||
| 3562 | gobble_input (1); | ||
| 3563 | ev = last_appdefined_event; | 3581 | ev = last_appdefined_event; |
| 3564 | inNsSelect = 0; | ||
| 3565 | 3582 | ||
| 3566 | if (ev) | 3583 | if (ev) |
| 3567 | { | 3584 | { |
| @@ -3575,25 +3592,28 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 3575 | if (t == -2) | 3592 | if (t == -2) |
| 3576 | { | 3593 | { |
| 3577 | /* The NX_APPDEFINED event we received was a timeout. */ | 3594 | /* The NX_APPDEFINED event we received was a timeout. */ |
| 3578 | return 0; | 3595 | result = 0; |
| 3579 | } | 3596 | } |
| 3580 | else if (t == -1) | 3597 | else if (t == -1) |
| 3581 | { | 3598 | { |
| 3582 | /* The NX_APPDEFINED event we received was the result of | 3599 | /* The NX_APPDEFINED event we received was the result of |
| 3583 | at least one real input event arriving. */ | 3600 | at least one real input event arriving. */ |
| 3584 | errno = EINTR; | 3601 | errno = EINTR; |
| 3585 | return -1; | 3602 | result = -1; |
| 3586 | } | 3603 | } |
| 3587 | else | 3604 | else |
| 3588 | { | 3605 | { |
| 3589 | /* Received back from pselect () in fd_handler; copy the results */ | 3606 | /* Received back from select () in fd_handler; copy the results */ |
| 3590 | if (readfds) | 3607 | pthread_mutex_lock (&select_mutex); |
| 3591 | memcpy (readfds, &select_readfds, sizeof (fd_set)); | 3608 | if (readfds) *readfds = select_readfds; |
| 3592 | return t; | 3609 | if (writefds) *writefds = select_writefds; |
| 3610 | if (timeout) *timeout = select_timeout; | ||
| 3611 | pthread_mutex_unlock (&select_mutex); | ||
| 3612 | result = t; | ||
| 3593 | } | 3613 | } |
| 3594 | } | 3614 | } |
| 3595 | /* never reached, shut compiler up */ | 3615 | |
| 3596 | return 0; | 3616 | return result; |
| 3597 | } | 3617 | } |
| 3598 | 3618 | ||
| 3599 | 3619 | ||
| @@ -4024,6 +4044,21 @@ ns_term_init (Lisp_Object display_name) | |||
| 4024 | { | 4044 | { |
| 4025 | baud_rate = 38400; | 4045 | baud_rate = 38400; |
| 4026 | Fset_input_interrupt_mode (Qnil); | 4046 | Fset_input_interrupt_mode (Qnil); |
| 4047 | |||
| 4048 | if (selfds[0] == -1) | ||
| 4049 | { | ||
| 4050 | if (pipe (selfds) == -1) | ||
| 4051 | { | ||
| 4052 | fprintf (stderr, "Failed to create pipe: %s\n", | ||
| 4053 | emacs_strerror (errno)); | ||
| 4054 | abort (); | ||
| 4055 | } | ||
| 4056 | |||
| 4057 | fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL)); | ||
| 4058 | FD_ZERO (&select_readfds); | ||
| 4059 | FD_ZERO (&select_writefds); | ||
| 4060 | pthread_mutex_init (&select_mutex, NULL); | ||
| 4061 | } | ||
| 4027 | ns_initialized = 1; | 4062 | ns_initialized = 1; |
| 4028 | } | 4063 | } |
| 4029 | 4064 | ||
| @@ -4039,6 +4074,11 @@ ns_term_init (Lisp_Object display_name) | |||
| 4039 | return NULL; | 4074 | return NULL; |
| 4040 | [NSApp setDelegate: NSApp]; | 4075 | [NSApp setDelegate: NSApp]; |
| 4041 | 4076 | ||
| 4077 | /* Start the select thread. */ | ||
| 4078 | [NSThread detachNewThreadSelector:@selector (fd_handler:) | ||
| 4079 | toTarget:NSApp | ||
| 4080 | withObject:nil]; | ||
| 4081 | |||
| 4042 | /* debugging: log all notifications */ | 4082 | /* debugging: log all notifications */ |
| 4043 | /* [[NSNotificationCenter defaultCenter] addObserver: NSApp | 4083 | /* [[NSNotificationCenter defaultCenter] addObserver: NSApp |
| 4044 | selector: @selector (logNotification:) | 4084 | selector: @selector (logNotification:) |
| @@ -4547,26 +4587,91 @@ not_in_argv (NSString *arg) | |||
| 4547 | ns_send_appdefined (-2); | 4587 | ns_send_appdefined (-2); |
| 4548 | } | 4588 | } |
| 4549 | 4589 | ||
| 4550 | - (void)fd_handler: (NSTimer *) fdEntry | 4590 | - (void)fd_handler:(id)unused |
| 4551 | /* -------------------------------------------------------------------------- | 4591 | /* -------------------------------------------------------------------------- |
| 4552 | Check data waiting on file descriptors and terminate if so | 4592 | Check data waiting on file descriptors and terminate if so |
| 4553 | -------------------------------------------------------------------------- */ | 4593 | -------------------------------------------------------------------------- */ |
| 4554 | { | 4594 | { |
| 4555 | int result; | 4595 | int result; |
| 4556 | struct timespec select_timeout; | 4596 | int waiting = 1, nfds; |
| 4557 | /* NSTRACE (fd_handler); */ | 4597 | char c; |
| 4558 | 4598 | ||
| 4559 | if (select_nfds == 0) | 4599 | SELECT_TYPE readfds, writefds, *wfds; |
| 4560 | return; | 4600 | EMACS_TIME timeout, *tmo; |
| 4561 | 4601 | ||
| 4562 | memcpy (&t_readfds, &select_readfds, sizeof (fd_set)); | 4602 | /* NSTRACE (fd_handler); */ |
| 4563 | 4603 | ||
| 4564 | select_timeout.tv_sec = select_timeout.tv_nsec = 0; | 4604 | for (;;) |
| 4565 | result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL); | ||
| 4566 | if (result) | ||
| 4567 | { | 4605 | { |
| 4568 | memcpy (&select_readfds, &t_readfds, sizeof (fd_set)); | 4606 | if (waiting) |
| 4569 | ns_send_appdefined (result); | 4607 | { |
| 4608 | SELECT_TYPE fds; | ||
| 4609 | |||
| 4610 | FD_SET (selfds[0], &fds); | ||
| 4611 | result = select (selfds[0]+1, &fds, NULL, NULL, NULL); | ||
| 4612 | if (result > 0) | ||
| 4613 | { | ||
| 4614 | read (selfds[0], &c, 1); | ||
| 4615 | if (c == 'g') waiting = 0; | ||
| 4616 | } | ||
| 4617 | } | ||
| 4618 | else | ||
| 4619 | { | ||
| 4620 | pthread_mutex_lock (&select_mutex); | ||
| 4621 | nfds = select_nfds; | ||
| 4622 | |||
| 4623 | if (select_valid & SELECT_HAVE_READ) | ||
| 4624 | readfds = select_readfds; | ||
| 4625 | else | ||
| 4626 | FD_ZERO (&readfds); | ||
| 4627 | |||
| 4628 | if (select_valid & SELECT_HAVE_WRITE) | ||
| 4629 | { | ||
| 4630 | writefds = select_writefds; | ||
| 4631 | wfds = &writefds; | ||
| 4632 | } | ||
| 4633 | else | ||
| 4634 | wfds = NULL; | ||
| 4635 | if (select_valid & SELECT_HAVE_TMO) | ||
| 4636 | { | ||
| 4637 | timeout = select_timeout; | ||
| 4638 | tmo = &timeout; | ||
| 4639 | } | ||
| 4640 | else | ||
| 4641 | tmo = NULL; | ||
| 4642 | |||
| 4643 | pthread_mutex_unlock (&select_mutex); | ||
| 4644 | |||
| 4645 | FD_SET (selfds[0], &readfds); | ||
| 4646 | if (selfds[0] >= nfds) nfds = selfds[0]+1; | ||
| 4647 | |||
| 4648 | result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL); | ||
| 4649 | |||
| 4650 | if (result == 0) | ||
| 4651 | ns_send_appdefined (-2); | ||
| 4652 | else if (result > 0) | ||
| 4653 | { | ||
| 4654 | if (FD_ISSET (selfds[0], &readfds)) | ||
| 4655 | { | ||
| 4656 | read (selfds[0], &c, 1); | ||
| 4657 | if (c == 's') waiting = 1; | ||
| 4658 | } | ||
| 4659 | else | ||
| 4660 | { | ||
| 4661 | pthread_mutex_lock (&select_mutex); | ||
| 4662 | if (select_valid & SELECT_HAVE_READ) | ||
| 4663 | select_readfds = readfds; | ||
| 4664 | if (select_valid & SELECT_HAVE_WRITE) | ||
| 4665 | select_writefds = writefds; | ||
| 4666 | if (select_valid & SELECT_HAVE_TMO) | ||
| 4667 | select_timeout = timeout; | ||
| 4668 | pthread_mutex_unlock (&select_mutex); | ||
| 4669 | |||
| 4670 | ns_send_appdefined (result); | ||
| 4671 | } | ||
| 4672 | } | ||
| 4673 | waiting = 1; | ||
| 4674 | } | ||
| 4570 | } | 4675 | } |
| 4571 | } | 4676 | } |
| 4572 | 4677 | ||
| @@ -6404,8 +6509,13 @@ not_in_argv (NSString *arg) | |||
| 6404 | XSETINT (emacs_event->x, loc * pixel_height); | 6509 | XSETINT (emacs_event->x, loc * pixel_height); |
| 6405 | XSETINT (emacs_event->y, pixel_height-20); | 6510 | XSETINT (emacs_event->y, pixel_height-20); |
| 6406 | 6511 | ||
| 6407 | n_emacs_events_pending++; | 6512 | if (q_event_ptr) |
| 6408 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); | 6513 | { |
| 6514 | n_emacs_events_pending++; | ||
| 6515 | kbd_buffer_store_event_hold (emacs_event, q_event_ptr); | ||
| 6516 | } | ||
| 6517 | else | ||
| 6518 | kbd_buffer_store_event (emacs_event); | ||
| 6409 | EVENT_INIT (*emacs_event); | 6519 | EVENT_INIT (*emacs_event); |
| 6410 | ns_send_appdefined (-1); | 6520 | ns_send_appdefined (-1); |
| 6411 | } | 6521 | } |