diff options
| author | Alan Third | 2017-01-04 12:41:29 +0000 |
|---|---|---|
| committer | Alan Third | 2017-01-04 21:00:52 +0000 |
| commit | 308d5962236448a84795f49d775601599688d78d (patch) | |
| tree | 3fed7f15fff4d3c25dc5304a5390b7d1e72a3694 /src | |
| parent | 44c588a25ce231ce05fb535cd6d7162e91214f45 (diff) | |
| download | emacs-308d5962236448a84795f49d775601599688d78d.tar.gz emacs-308d5962236448a84795f49d775601599688d78d.zip | |
Revert "Rework NS event handling (bug#25265)"
This reverts commit e0e5b0f4a4ce1d19ee0240c514dedd873d4165dc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.h | 1 | ||||
| -rw-r--r-- | src/nsterm.m | 380 |
2 files changed, 313 insertions, 68 deletions
diff --git a/src/nsterm.h b/src/nsterm.h index 161c3c29646..534ec68c22b 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -392,6 +392,7 @@ char const * nstrace_fullscreen_type_name (int); | |||
| 392 | - (void)sendEvent: (NSEvent *)theEvent; | 392 | - (void)sendEvent: (NSEvent *)theEvent; |
| 393 | - (void)showPreferencesWindow: (id)sender; | 393 | - (void)showPreferencesWindow: (id)sender; |
| 394 | - (BOOL) openFile: (NSString *)fileName; | 394 | - (BOOL) openFile: (NSString *)fileName; |
| 395 | - (void)fd_handler: (id)unused; | ||
| 395 | - (void)timeout_handler: (NSTimer *)timedEntry; | 396 | - (void)timeout_handler: (NSTimer *)timedEntry; |
| 396 | - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg; | 397 | - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg; |
| 397 | #ifdef NS_IMPL_GNUSTEP | 398 | #ifdef NS_IMPL_GNUSTEP |
diff --git a/src/nsterm.m b/src/nsterm.m index 1d038cdcb05..47fc6c18acd 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -279,10 +279,18 @@ static BOOL ns_menu_bar_is_hidden = NO; | |||
| 279 | /*static int debug_lock = 0; */ | 279 | /*static int debug_lock = 0; */ |
| 280 | 280 | ||
| 281 | /* event loop */ | 281 | /* event loop */ |
| 282 | static BOOL send_appdefined = YES; | ||
| 282 | #define NO_APPDEFINED_DATA (-8) | 283 | #define NO_APPDEFINED_DATA (-8) |
| 283 | static int last_appdefined_event_data = NO_APPDEFINED_DATA; | 284 | static int last_appdefined_event_data = NO_APPDEFINED_DATA; |
| 284 | static NSTimer *timed_entry = 0; | 285 | static NSTimer *timed_entry = 0; |
| 285 | static NSTimer *scroll_repeat_entry = nil; | 286 | static NSTimer *scroll_repeat_entry = nil; |
| 287 | static fd_set select_readfds, select_writefds; | ||
| 288 | enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 }; | ||
| 289 | static int select_nfds = 0, select_valid = 0; | ||
| 290 | static struct timespec select_timeout = { 0, 0 }; | ||
| 291 | static int selfds[2] = { -1, -1 }; | ||
| 292 | static pthread_mutex_t select_mutex; | ||
| 293 | static int apploopnr = 0; | ||
| 286 | static NSAutoreleasePool *outerpool; | 294 | static NSAutoreleasePool *outerpool; |
| 287 | static struct input_event *emacs_event = NULL; | 295 | static struct input_event *emacs_event = NULL; |
| 288 | static struct input_event *q_event_ptr = NULL; | 296 | static struct input_event *q_event_ptr = NULL; |
| @@ -449,6 +457,7 @@ hold_event (struct input_event *event) | |||
| 449 | hold_event_q.q[hold_event_q.nr++] = *event; | 457 | hold_event_q.q[hold_event_q.nr++] = *event; |
| 450 | /* Make sure ns_read_socket is called, i.e. we have input. */ | 458 | /* Make sure ns_read_socket is called, i.e. we have input. */ |
| 451 | raise (SIGIO); | 459 | raise (SIGIO); |
| 460 | send_appdefined = YES; | ||
| 452 | } | 461 | } |
| 453 | 462 | ||
| 454 | static Lisp_Object | 463 | static Lisp_Object |
| @@ -3863,17 +3872,31 @@ ns_send_appdefined (int value) | |||
| 3863 | return; | 3872 | return; |
| 3864 | } | 3873 | } |
| 3865 | 3874 | ||
| 3866 | /* Only post this event if we haven't already posted one. This will | 3875 | /* Only post this event if we haven't already posted one. This will end |
| 3867 | end the [NXApp run] main loop after having processed all events | 3876 | the [NXApp run] main loop after having processed all events queued at |
| 3868 | queued at this moment. */ | 3877 | this moment. */ |
| 3869 | NSEvent *appev = [NSApp nextEventMatchingMask:NSEventMaskApplicationDefined | 3878 | |
| 3870 | untilDate:[NSDate distantPast] | 3879 | #ifdef NS_IMPL_COCOA |
| 3871 | inMode:NSDefaultRunLoopMode | 3880 | if (! send_appdefined) |
| 3872 | dequeue:NO]; | 3881 | { |
| 3873 | if (! appev) | 3882 | /* OS X 10.10.1 swallows the AppDefined event we are sending ourselves |
| 3883 | in certain situations (rapid incoming events). | ||
| 3884 | So check if we have one, if not add one. */ | ||
| 3885 | NSEvent *appev = [NSApp nextEventMatchingMask:NSEventMaskApplicationDefined | ||
| 3886 | untilDate:[NSDate distantPast] | ||
| 3887 | inMode:NSDefaultRunLoopMode | ||
| 3888 | dequeue:NO]; | ||
| 3889 | if (! appev) send_appdefined = YES; | ||
| 3890 | } | ||
| 3891 | #endif | ||
| 3892 | |||
| 3893 | if (send_appdefined) | ||
| 3874 | { | 3894 | { |
| 3875 | NSEvent *nxev; | 3895 | NSEvent *nxev; |
| 3876 | 3896 | ||
| 3897 | /* We only need one NX_APPDEFINED event to stop NXApp from running. */ | ||
| 3898 | send_appdefined = NO; | ||
| 3899 | |||
| 3877 | /* Don't need wakeup timer any more */ | 3900 | /* Don't need wakeup timer any more */ |
| 3878 | if (timed_entry) | 3901 | if (timed_entry) |
| 3879 | { | 3902 | { |
| @@ -3988,6 +4011,14 @@ ns_check_pending_open_menu () | |||
| 3988 | } | 4011 | } |
| 3989 | #endif /* NS_IMPL_COCOA */ | 4012 | #endif /* NS_IMPL_COCOA */ |
| 3990 | 4013 | ||
| 4014 | static void | ||
| 4015 | unwind_apploopnr (Lisp_Object not_used) | ||
| 4016 | { | ||
| 4017 | --apploopnr; | ||
| 4018 | n_emacs_events_pending = 0; | ||
| 4019 | ns_finish_events (); | ||
| 4020 | q_event_ptr = NULL; | ||
| 4021 | } | ||
| 3991 | 4022 | ||
| 3992 | static int | 4023 | static int |
| 3993 | ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | 4024 | ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) |
| @@ -3998,10 +4029,13 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 3998 | -------------------------------------------------------------------------- */ | 4029 | -------------------------------------------------------------------------- */ |
| 3999 | { | 4030 | { |
| 4000 | struct input_event ev; | 4031 | struct input_event ev; |
| 4001 | int nevents = 0; | 4032 | int nevents; |
| 4002 | 4033 | ||
| 4003 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket"); | 4034 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket"); |
| 4004 | 4035 | ||
| 4036 | if (apploopnr > 0) | ||
| 4037 | return -1; /* Already within event loop. */ | ||
| 4038 | |||
| 4005 | #ifdef HAVE_NATIVE_FS | 4039 | #ifdef HAVE_NATIVE_FS |
| 4006 | check_native_fs (); | 4040 | check_native_fs (); |
| 4007 | #endif | 4041 | #endif |
| @@ -4018,50 +4052,55 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) | |||
| 4018 | return i; | 4052 | return i; |
| 4019 | } | 4053 | } |
| 4020 | 4054 | ||
| 4021 | if ([NSThread isMainThread]) | 4055 | block_input (); |
| 4056 | n_emacs_events_pending = 0; | ||
| 4057 | ns_init_events (&ev); | ||
| 4058 | q_event_ptr = hold_quit; | ||
| 4059 | |||
| 4060 | /* we manage autorelease pools by allocate/reallocate each time around | ||
| 4061 | the loop; strict nesting is occasionally violated but seems not to | ||
| 4062 | matter.. earlier methods using full nesting caused major memory leaks */ | ||
| 4063 | [outerpool release]; | ||
| 4064 | outerpool = [[NSAutoreleasePool alloc] init]; | ||
| 4065 | |||
| 4066 | /* If have pending open-file requests, attend to the next one of those. */ | ||
| 4067 | if (ns_pending_files && [ns_pending_files count] != 0 | ||
| 4068 | && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]]) | ||
| 4022 | { | 4069 | { |
| 4023 | block_input (); | 4070 | [ns_pending_files removeObjectAtIndex: 0]; |
| 4024 | n_emacs_events_pending = 0; | 4071 | } |
| 4025 | ns_init_events (&ev); | 4072 | /* Deal with pending service requests. */ |
| 4026 | q_event_ptr = hold_quit; | 4073 | else if (ns_pending_service_names && [ns_pending_service_names count] != 0 |
| 4027 | 4074 | && [(EmacsApp *) | |
| 4028 | /* we manage autorelease pools by allocate/reallocate each time around | 4075 | NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0] |
| 4029 | the loop; strict nesting is occasionally violated but seems not to | 4076 | withArg: [ns_pending_service_args objectAtIndex: 0]]) |
| 4030 | matter.. earlier methods using full nesting caused major memory leaks */ | 4077 | { |
| 4031 | [outerpool release]; | 4078 | [ns_pending_service_names removeObjectAtIndex: 0]; |
| 4032 | outerpool = [[NSAutoreleasePool alloc] init]; | 4079 | [ns_pending_service_args removeObjectAtIndex: 0]; |
| 4033 | 4080 | } | |
| 4034 | /* If have pending open-file requests, attend to the next one of those. */ | 4081 | else |
| 4035 | if (ns_pending_files && [ns_pending_files count] != 0 | 4082 | { |
| 4036 | && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]]) | 4083 | ptrdiff_t specpdl_count = SPECPDL_INDEX (); |
| 4037 | { | 4084 | /* Run and wait for events. We must always send one NX_APPDEFINED event |
| 4038 | [ns_pending_files removeObjectAtIndex: 0]; | 4085 | to ourself, otherwise [NXApp run] will never exit. */ |
| 4039 | } | 4086 | send_appdefined = YES; |
| 4040 | /* Deal with pending service requests. */ | 4087 | ns_send_appdefined (-1); |
| 4041 | else if (ns_pending_service_names && [ns_pending_service_names count] != 0 | ||
| 4042 | && [(EmacsApp *) | ||
| 4043 | NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0] | ||
| 4044 | withArg: [ns_pending_service_args objectAtIndex: 0]]) | ||
| 4045 | { | ||
| 4046 | [ns_pending_service_names removeObjectAtIndex: 0]; | ||
| 4047 | [ns_pending_service_args removeObjectAtIndex: 0]; | ||
| 4048 | } | ||
| 4049 | else | ||
| 4050 | { | ||
| 4051 | /* Run and wait for events. We must always send one NX_APPDEFINED event | ||
| 4052 | to ourself, otherwise [NXApp run] will never exit. */ | ||
| 4053 | ns_send_appdefined (-1); | ||
| 4054 | 4088 | ||
| 4055 | [NSApp run]; | 4089 | if (++apploopnr != 1) |
| 4090 | { | ||
| 4091 | emacs_abort (); | ||
| 4056 | } | 4092 | } |
| 4057 | 4093 | record_unwind_protect (unwind_apploopnr, Qt); | |
| 4058 | nevents = n_emacs_events_pending; | 4094 | [NSApp run]; |
| 4059 | n_emacs_events_pending = 0; | 4095 | unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */ |
| 4060 | ns_finish_events (); | ||
| 4061 | q_event_ptr = NULL; | ||
| 4062 | unblock_input (); | ||
| 4063 | } | 4096 | } |
| 4064 | 4097 | ||
| 4098 | nevents = n_emacs_events_pending; | ||
| 4099 | n_emacs_events_pending = 0; | ||
| 4100 | ns_finish_events (); | ||
| 4101 | q_event_ptr = NULL; | ||
| 4102 | unblock_input (); | ||
| 4103 | |||
| 4065 | return nevents; | 4104 | return nevents; |
| 4066 | } | 4105 | } |
| 4067 | 4106 | ||
| @@ -4075,11 +4114,15 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 4075 | -------------------------------------------------------------------------- */ | 4114 | -------------------------------------------------------------------------- */ |
| 4076 | { | 4115 | { |
| 4077 | int result; | 4116 | int result; |
| 4078 | NSDate *timeout_date = nil; | 4117 | int t, k, nr = 0; |
| 4079 | NSEvent *ns_event; | 4118 | struct input_event event; |
| 4119 | char c; | ||
| 4080 | 4120 | ||
| 4081 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select"); | 4121 | NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select"); |
| 4082 | 4122 | ||
| 4123 | if (apploopnr > 0) | ||
| 4124 | return -1; /* Already within event loop. */ | ||
| 4125 | |||
| 4083 | #ifdef HAVE_NATIVE_FS | 4126 | #ifdef HAVE_NATIVE_FS |
| 4084 | check_native_fs (); | 4127 | check_native_fs (); |
| 4085 | #endif | 4128 | #endif |
| @@ -4092,34 +4135,121 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, | |||
| 4092 | return -1; | 4135 | return -1; |
| 4093 | } | 4136 | } |
| 4094 | 4137 | ||
| 4138 | for (k = 0; k < nfds+1; k++) | ||
| 4139 | { | ||
| 4140 | if (readfds && FD_ISSET(k, readfds)) ++nr; | ||
| 4141 | if (writefds && FD_ISSET(k, writefds)) ++nr; | ||
| 4142 | } | ||
| 4143 | |||
| 4095 | if (NSApp == nil | 4144 | if (NSApp == nil |
| 4096 | || ![NSThread isMainThread] | ||
| 4097 | || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) | 4145 | || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) |
| 4098 | return pselect(nfds, readfds, writefds, | 4146 | return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); |
| 4099 | exceptfds, timeout, sigmask); | ||
| 4100 | |||
| 4101 | result = pselect(nfds, readfds, writefds, exceptfds, | ||
| 4102 | &(struct timespec){.tv_sec = 0, .tv_nsec = 100}, | ||
| 4103 | sigmask); | ||
| 4104 | 4147 | ||
| 4105 | [outerpool release]; | 4148 | [outerpool release]; |
| 4106 | outerpool = [[NSAutoreleasePool alloc] init]; | 4149 | outerpool = [[NSAutoreleasePool alloc] init]; |
| 4107 | 4150 | ||
| 4108 | if (timeout) | 4151 | |
| 4152 | send_appdefined = YES; | ||
| 4153 | if (nr > 0) | ||
| 4154 | { | ||
| 4155 | pthread_mutex_lock (&select_mutex); | ||
| 4156 | select_nfds = nfds; | ||
| 4157 | select_valid = 0; | ||
| 4158 | if (readfds) | ||
| 4159 | { | ||
| 4160 | select_readfds = *readfds; | ||
| 4161 | select_valid += SELECT_HAVE_READ; | ||
| 4162 | } | ||
| 4163 | if (writefds) | ||
| 4164 | { | ||
| 4165 | select_writefds = *writefds; | ||
| 4166 | select_valid += SELECT_HAVE_WRITE; | ||
| 4167 | } | ||
| 4168 | |||
| 4169 | if (timeout) | ||
| 4170 | { | ||
| 4171 | select_timeout = *timeout; | ||
| 4172 | select_valid += SELECT_HAVE_TMO; | ||
| 4173 | } | ||
| 4174 | |||
| 4175 | pthread_mutex_unlock (&select_mutex); | ||
| 4176 | |||
| 4177 | /* Inform fd_handler that select should be called */ | ||
| 4178 | c = 'g'; | ||
| 4179 | emacs_write_sig (selfds[1], &c, 1); | ||
| 4180 | } | ||
| 4181 | else if (nr == 0 && timeout) | ||
| 4109 | { | 4182 | { |
| 4183 | /* No file descriptor, just a timeout, no need to wake fd_handler */ | ||
| 4110 | double time = timespectod (*timeout); | 4184 | double time = timespectod (*timeout); |
| 4111 | timeout_date = [NSDate dateWithTimeIntervalSinceNow:time]; | 4185 | timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time |
| 4186 | target: NSApp | ||
| 4187 | selector: | ||
| 4188 | @selector (timeout_handler:) | ||
| 4189 | userInfo: 0 | ||
| 4190 | repeats: NO] | ||
| 4191 | retain]; | ||
| 4192 | } | ||
| 4193 | else /* No timeout and no file descriptors, can this happen? */ | ||
| 4194 | { | ||
| 4195 | /* Send appdefined so we exit from the loop */ | ||
| 4196 | ns_send_appdefined (-1); | ||
| 4197 | } | ||
| 4198 | |||
| 4199 | block_input (); | ||
| 4200 | ns_init_events (&event); | ||
| 4201 | if (++apploopnr != 1) | ||
| 4202 | { | ||
| 4203 | emacs_abort (); | ||
| 4112 | } | 4204 | } |
| 4113 | 4205 | ||
| 4114 | /* Listen for a new NSEvent. */ | 4206 | { |
| 4115 | ns_event = [NSApp nextEventMatchingMask:NSEventMaskAny | 4207 | ptrdiff_t specpdl_count = SPECPDL_INDEX (); |
| 4116 | untilDate:timeout_date | 4208 | record_unwind_protect (unwind_apploopnr, Qt); |
| 4117 | inMode:NSDefaultRunLoopMode | 4209 | [NSApp run]; |
| 4118 | dequeue:NO]; | 4210 | unbind_to (specpdl_count, Qnil); /* calls unwind_apploopnr */ |
| 4211 | } | ||
| 4119 | 4212 | ||
| 4120 | if (ns_event != nil) | 4213 | ns_finish_events (); |
| 4214 | if (nr > 0 && readfds) | ||
| 4121 | { | 4215 | { |
| 4122 | raise (SIGIO); | 4216 | c = 's'; |
| 4217 | emacs_write_sig (selfds[1], &c, 1); | ||
| 4218 | } | ||
| 4219 | unblock_input (); | ||
| 4220 | |||
| 4221 | t = last_appdefined_event_data; | ||
| 4222 | |||
| 4223 | if (t != NO_APPDEFINED_DATA) | ||
| 4224 | { | ||
| 4225 | last_appdefined_event_data = NO_APPDEFINED_DATA; | ||
| 4226 | |||
| 4227 | if (t == -2) | ||
| 4228 | { | ||
| 4229 | /* The NX_APPDEFINED event we received was a timeout. */ | ||
| 4230 | result = 0; | ||
| 4231 | } | ||
| 4232 | else if (t == -1) | ||
| 4233 | { | ||
| 4234 | /* The NX_APPDEFINED event we received was the result of | ||
| 4235 | at least one real input event arriving. */ | ||
| 4236 | errno = EINTR; | ||
| 4237 | result = -1; | ||
| 4238 | } | ||
| 4239 | else | ||
| 4240 | { | ||
| 4241 | /* Received back from select () in fd_handler; copy the results */ | ||
| 4242 | pthread_mutex_lock (&select_mutex); | ||
| 4243 | if (readfds) *readfds = select_readfds; | ||
| 4244 | if (writefds) *writefds = select_writefds; | ||
| 4245 | pthread_mutex_unlock (&select_mutex); | ||
| 4246 | result = t; | ||
| 4247 | } | ||
| 4248 | } | ||
| 4249 | else | ||
| 4250 | { | ||
| 4251 | errno = EINTR; | ||
| 4252 | result = -1; | ||
| 4123 | } | 4253 | } |
| 4124 | 4254 | ||
| 4125 | return result; | 4255 | return result; |
| @@ -4635,6 +4765,21 @@ ns_term_init (Lisp_Object display_name) | |||
| 4635 | baud_rate = 38400; | 4765 | baud_rate = 38400; |
| 4636 | Fset_input_interrupt_mode (Qnil); | 4766 | Fset_input_interrupt_mode (Qnil); |
| 4637 | 4767 | ||
| 4768 | if (selfds[0] == -1) | ||
| 4769 | { | ||
| 4770 | if (emacs_pipe (selfds) != 0) | ||
| 4771 | { | ||
| 4772 | fprintf (stderr, "Failed to create pipe: %s\n", | ||
| 4773 | emacs_strerror (errno)); | ||
| 4774 | emacs_abort (); | ||
| 4775 | } | ||
| 4776 | |||
| 4777 | fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL)); | ||
| 4778 | FD_ZERO (&select_readfds); | ||
| 4779 | FD_ZERO (&select_writefds); | ||
| 4780 | pthread_mutex_init (&select_mutex, NULL); | ||
| 4781 | } | ||
| 4782 | |||
| 4638 | ns_pending_files = [[NSMutableArray alloc] init]; | 4783 | ns_pending_files = [[NSMutableArray alloc] init]; |
| 4639 | ns_pending_service_names = [[NSMutableArray alloc] init]; | 4784 | ns_pending_service_names = [[NSMutableArray alloc] init]; |
| 4640 | ns_pending_service_args = [[NSMutableArray alloc] init]; | 4785 | ns_pending_service_args = [[NSMutableArray alloc] init]; |
| @@ -4647,6 +4792,11 @@ ns_term_init (Lisp_Object display_name) | |||
| 4647 | return NULL; | 4792 | return NULL; |
| 4648 | [NSApp setDelegate: NSApp]; | 4793 | [NSApp setDelegate: NSApp]; |
| 4649 | 4794 | ||
| 4795 | /* Start the select thread. */ | ||
| 4796 | [NSThread detachNewThreadSelector:@selector (fd_handler:) | ||
| 4797 | toTarget:NSApp | ||
| 4798 | withObject:nil]; | ||
| 4799 | |||
| 4650 | /* debugging: log all notifications */ | 4800 | /* debugging: log all notifications */ |
| 4651 | /* [[NSNotificationCenter defaultCenter] addObserver: NSApp | 4801 | /* [[NSNotificationCenter defaultCenter] addObserver: NSApp |
| 4652 | selector: @selector (logNotification:) | 4802 | selector: @selector (logNotification:) |
| @@ -5028,6 +5178,10 @@ ns_term_shutdown (int sig) | |||
| 5028 | last_appdefined_event_data = [theEvent data1]; | 5178 | last_appdefined_event_data = [theEvent data1]; |
| 5029 | [self stop: self]; | 5179 | [self stop: self]; |
| 5030 | } | 5180 | } |
| 5181 | else | ||
| 5182 | { | ||
| 5183 | send_appdefined = YES; | ||
| 5184 | } | ||
| 5031 | } | 5185 | } |
| 5032 | 5186 | ||
| 5033 | 5187 | ||
| @@ -5330,6 +5484,95 @@ not_in_argv (NSString *arg) | |||
| 5330 | ns_send_appdefined (nextappdefined); | 5484 | ns_send_appdefined (nextappdefined); |
| 5331 | } | 5485 | } |
| 5332 | 5486 | ||
| 5487 | - (void)fd_handler:(id)unused | ||
| 5488 | /* -------------------------------------------------------------------------- | ||
| 5489 | Check data waiting on file descriptors and terminate if so | ||
| 5490 | -------------------------------------------------------------------------- */ | ||
| 5491 | { | ||
| 5492 | int result; | ||
| 5493 | int waiting = 1, nfds; | ||
| 5494 | char c; | ||
| 5495 | |||
| 5496 | fd_set readfds, writefds, *wfds; | ||
| 5497 | struct timespec timeout, *tmo; | ||
| 5498 | NSAutoreleasePool *pool = nil; | ||
| 5499 | |||
| 5500 | /* NSTRACE ("fd_handler"); */ | ||
| 5501 | |||
| 5502 | for (;;) | ||
| 5503 | { | ||
| 5504 | [pool release]; | ||
| 5505 | pool = [[NSAutoreleasePool alloc] init]; | ||
| 5506 | |||
| 5507 | if (waiting) | ||
| 5508 | { | ||
| 5509 | fd_set fds; | ||
| 5510 | FD_ZERO (&fds); | ||
| 5511 | FD_SET (selfds[0], &fds); | ||
| 5512 | result = select (selfds[0]+1, &fds, NULL, NULL, NULL); | ||
| 5513 | if (result > 0 && read (selfds[0], &c, 1) == 1 && c == 'g') | ||
| 5514 | waiting = 0; | ||
| 5515 | } | ||
| 5516 | else | ||
| 5517 | { | ||
| 5518 | pthread_mutex_lock (&select_mutex); | ||
| 5519 | nfds = select_nfds; | ||
| 5520 | |||
| 5521 | if (select_valid & SELECT_HAVE_READ) | ||
| 5522 | readfds = select_readfds; | ||
| 5523 | else | ||
| 5524 | FD_ZERO (&readfds); | ||
| 5525 | |||
| 5526 | if (select_valid & SELECT_HAVE_WRITE) | ||
| 5527 | { | ||
| 5528 | writefds = select_writefds; | ||
| 5529 | wfds = &writefds; | ||
| 5530 | } | ||
| 5531 | else | ||
| 5532 | wfds = NULL; | ||
| 5533 | if (select_valid & SELECT_HAVE_TMO) | ||
| 5534 | { | ||
| 5535 | timeout = select_timeout; | ||
| 5536 | tmo = &timeout; | ||
| 5537 | } | ||
| 5538 | else | ||
| 5539 | tmo = NULL; | ||
| 5540 | |||
| 5541 | pthread_mutex_unlock (&select_mutex); | ||
| 5542 | |||
| 5543 | FD_SET (selfds[0], &readfds); | ||
| 5544 | if (selfds[0] >= nfds) nfds = selfds[0]+1; | ||
| 5545 | |||
| 5546 | result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL); | ||
| 5547 | |||
| 5548 | if (result == 0) | ||
| 5549 | ns_send_appdefined (-2); | ||
| 5550 | else if (result > 0) | ||
| 5551 | { | ||
| 5552 | if (FD_ISSET (selfds[0], &readfds)) | ||
| 5553 | { | ||
| 5554 | if (read (selfds[0], &c, 1) == 1 && c == 's') | ||
| 5555 | waiting = 1; | ||
| 5556 | } | ||
| 5557 | else | ||
| 5558 | { | ||
| 5559 | pthread_mutex_lock (&select_mutex); | ||
| 5560 | if (select_valid & SELECT_HAVE_READ) | ||
| 5561 | select_readfds = readfds; | ||
| 5562 | if (select_valid & SELECT_HAVE_WRITE) | ||
| 5563 | select_writefds = writefds; | ||
| 5564 | if (select_valid & SELECT_HAVE_TMO) | ||
| 5565 | select_timeout = timeout; | ||
| 5566 | pthread_mutex_unlock (&select_mutex); | ||
| 5567 | |||
| 5568 | ns_send_appdefined (result); | ||
| 5569 | } | ||
| 5570 | } | ||
| 5571 | waiting = 1; | ||
| 5572 | } | ||
| 5573 | } | ||
| 5574 | } | ||
| 5575 | |||
| 5333 | 5576 | ||
| 5334 | 5577 | ||
| 5335 | /* ========================================================================== | 5578 | /* ========================================================================== |
| @@ -6118,7 +6361,7 @@ not_in_argv (NSString *arg) | |||
| 6118 | help_echo_object, help_echo_pos); | 6361 | help_echo_object, help_echo_pos); |
| 6119 | } | 6362 | } |
| 6120 | 6363 | ||
| 6121 | if (emacsframe->mouse_moved) | 6364 | if (emacsframe->mouse_moved && send_appdefined) |
| 6122 | ns_send_appdefined (-1); | 6365 | ns_send_appdefined (-1); |
| 6123 | } | 6366 | } |
| 6124 | 6367 | ||
| @@ -6815,7 +7058,8 @@ not_in_argv (NSString *arg) | |||
| 6815 | SET_FRAME_VISIBLE (emacsframe, 1); | 7058 | SET_FRAME_VISIBLE (emacsframe, 1); |
| 6816 | SET_FRAME_GARBAGED (emacsframe); | 7059 | SET_FRAME_GARBAGED (emacsframe); |
| 6817 | 7060 | ||
| 6818 | ns_send_appdefined (-1); | 7061 | if (send_appdefined) |
| 7062 | ns_send_appdefined (-1); | ||
| 6819 | } | 7063 | } |
| 6820 | 7064 | ||
| 6821 | 7065 | ||