comparison src/event-msw.c @ 274:ca9a9ec9c1c1 r21-0b35

Import from CVS: tag r21-0b35
author cvs
date Mon, 13 Aug 2007 10:29:42 +0200
parents c5d627a313b1
children 6330739388db
comparison
equal deleted inserted replaced
273:411aac7253ef 274:ca9a9ec9c1c1
44 #endif 44 #endif
45 45
46 #include "device.h" 46 #include "device.h"
47 #include "events.h" 47 #include "events.h"
48 #include "frame.h" 48 #include "frame.h"
49 #include "lstream.h"
49 #include "process.h" 50 #include "process.h"
50 #include "redisplay.h" 51 #include "redisplay.h"
51 #include "sysproc.h" 52 #include "sysproc.h"
52 #include "syswait.h" 53 #include "syswait.h"
53 #include "systime.h" 54 #include "systime.h"
54 55
55 #include "events-mod.h" 56 #include "events-mod.h"
57
58 #include <errno.h>
56 59
57 #ifdef BROKEN_CYGWIN 60 #ifdef BROKEN_CYGWIN
58 int WINAPI DdeCmpStringHandles (HSZ, HSZ); 61 int WINAPI DdeCmpStringHandles (HSZ, HSZ);
59 HDDEDATA WINAPI DdeCreateDataHandle (DWORD, LPBYTE, DWORD, DWORD, HSZ, 62 HDDEDATA WINAPI DdeCreateDataHandle (DWORD, LPBYTE, DWORD, DWORD, HSZ,
60 UINT, UINT); 63 UINT, UINT);
100 103
101 /* The number of things we can wait on */ 104 /* The number of things we can wait on */
102 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1) 105 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1)
103 106
104 /* List of mswindows waitable handles. */ 107 /* List of mswindows waitable handles. */
105 static HANDLE mswindows_waitable[MAX_WAITABLE]; 108 static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
109
110 /* Number of wait handles */
111 static int mswindows_waitable_count=0;
106 112
107 /* Count of quit chars currently in the queue */ 113 /* Count of quit chars currently in the queue */
108 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc() 114 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc()
109 Decremented in mswindows_dequeue_dispatch_event() */ 115 Decremented in mswindows_dequeue_dispatch_event() */
110 int mswindows_quit_chars_count = 0; 116 int mswindows_quit_chars_count = 0;
114 int mswindows_num_mouse_buttons; 120 int mswindows_num_mouse_buttons;
115 int mswindows_mouse_button_max_skew_x; 121 int mswindows_mouse_button_max_skew_x;
116 int mswindows_mouse_button_max_skew_y; 122 int mswindows_mouse_button_max_skew_y;
117 int mswindows_mouse_button_tolerance; 123 int mswindows_mouse_button_tolerance;
118 124
119 /* Number of wait handles */
120 static int mswindows_waitable_count=0;
121
122 /* This is the event signaled by the event pump. 125 /* This is the event signaled by the event pump.
123 See mswindows_pump_outstanding_events for comments */ 126 See mswindows_pump_outstanding_events for comments */
124 static Lisp_Object mswindows_error_caught_in_modal_loop; 127 static Lisp_Object mswindows_error_caught_in_modal_loop;
125 static int mswindows_in_modal_loop; 128 static int mswindows_in_modal_loop;
126 129
127 /* Count of wound timers */ 130 /* Count of wound timers */
128 static int mswindows_pending_timers_count; 131 static int mswindows_pending_timers_count;
132
133 /************************************************************************/
134 /* Pipe instream - reads process output */
135 /************************************************************************/
136
137 #define PIPE_READ_DELAY 20
138
139 #define HANDLE_TO_USID(h) ((USID)(h))
140
141 #define NTPIPE_SLURP_STREAM_DATA(stream) \
142 LSTREAM_TYPE_DATA (stream, ntpipe_slurp)
143
144 struct ntpipe_slurp_stream
145 {
146 LPARAM user_data; /* Any user data stored in the stream object */
147 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
148 /* This is a manual-reset object. */
149 HANDLE hev_caller; /* Caller blocks on this, and we signal it */
150 /* This is a manual-reset object. */
151 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */
152 /* This is a manual-reset object. */
153 HANDLE hpipe; /* Pipe read end handle. */
154 HANDLE hthread; /* Reader thread handle. */
155 BYTE onebyte; /* One byte buffer read by thread */
156 DWORD die_p; /* Thread must exit ASAP if non-zero */
157 BOOL eof_p : 1; /* Set when thread saw EOF */
158 BOOL error_p : 1; /* Read error other than EOF/broken pipe */
159 };
160
161 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-input", lstream_ntpipe_slurp,
162 sizeof (struct ntpipe_slurp_stream));
163
164 static DWORD WINAPI
165 slurp_thread (LPVOID vparam)
166 {
167 struct ntpipe_slurp_stream *s = (struct ntpipe_slurp_stream*)vparam;
168
169 for (;;)
170 {
171 /* Read one byte from the pipe */
172 DWORD actually_read;
173 if (!ReadFile (s->hpipe, &s->onebyte, 1, &actually_read, NULL))
174 {
175 DWORD err = GetLastError ();
176 if (err == ERROR_BROKEN_PIPE || err == ERROR_NO_DATA)
177 s->eof_p = TRUE;
178 else
179 s->error_p = TRUE;
180 }
181 else if (actually_read == 0)
182 s->eof_p = TRUE;
183
184 /* We must terminate on an error or eof */
185 if (s->eof_p || s->error_p)
186 InterlockedIncrement (&s->die_p);
187
188 /* Before we notify caller, we unsignal our event. */
189 ResetEvent (s->hev_thread);
190
191 /* Now we got something to notify caller, either a byte or an
192 error/eof indication. Before we do, allow internal pipe
193 buffer to accumulate little bit more data.
194 Reader function pulses this event before waiting for
195 a character, to avoid pipde delay, and to get the byte
196 immediately. */
197 if (!s->die_p)
198 WaitForSingleObject (s->hev_unsleep, PIPE_READ_DELAY);
199
200 /* Either make event loop generate a process event, or
201 inblock reader */
202 SetEvent (s->hev_caller);
203
204 /* Cleanup and exit if we're shot off */
205 if (s->die_p)
206 break;
207
208 /* Block until the client finishes with retireving the rest of
209 pipe data */
210 WaitForSingleObject (s->hev_thread, INFINITE);
211 }
212
213 return 0;
214 }
215
216 static Lisp_Object
217 make_ntpipe_input_stream (HANDLE hpipe, LPARAM param)
218 {
219 Lisp_Object obj;
220 Lstream *lstr = Lstream_new (lstream_ntpipe_slurp, "r");
221 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA (lstr);
222 DWORD thread_id_unused;
223
224 /* We deal only with pipes, for we're using PeekNamedPipe api */
225 assert (GetFileType (hpipe) == FILE_TYPE_PIPE);
226
227 s->die_p = 0;
228 s->eof_p = FALSE;
229 s->error_p = FALSE;
230 s->hpipe = hpipe;
231 s->user_data = param;
232
233 /* Create reader thread. This could fail, so do not
234 create events until thread is created */
235 s->hthread = CreateThread (NULL, 0, slurp_thread, (LPVOID)s,
236 CREATE_SUSPENDED, &thread_id_unused);
237 if (s->hthread == NULL)
238 {
239 Lstream_delete (lstr);
240 return Qnil;
241 }
242
243 /* hev_thread is a manual-reset event, initially signaled */
244 s->hev_thread = CreateEvent (NULL, TRUE, TRUE, NULL);
245 /* hev_caller is a manual-reset event, initially nonsignaled */
246 s->hev_caller = CreateEvent (NULL, TRUE, FALSE, NULL);
247 /* hev_unsleep is a manual-reset event, initially nonsignaled */
248 s->hev_unsleep = CreateEvent (NULL, TRUE, FALSE, NULL);
249
250 /* Now let it go */
251 ResumeThread (s->hthread);
252
253 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
254 XSETLSTREAM (obj, lstr);
255 return obj;
256 }
257
258 static LPARAM
259 get_ntpipe_input_stream_param (Lstream *stream)
260 {
261 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream);
262 return s->user_data;
263 }
264
265 static HANDLE
266 get_ntpipe_input_stream_waitable (Lstream *stream)
267 {
268 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream);
269 return s->hev_caller;
270 }
271
272 static int
273 ntpipe_slurp_reader (Lstream *stream, unsigned char *data, size_t size)
274 {
275 /* This function must be called from the main thread only */
276 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream);
277
278 if (!s->die_p)
279 {
280 DWORD wait_result;
281 /* Disallow pipe read delay for the thread: we need a character ASAP */
282 SetEvent (s->hev_unsleep);
283
284 /* Check if we have a character ready. Give it a short delay, for
285 the thread to awake from pipe delay, just ion case*/
286 wait_result = WaitForSingleObject (s->hev_caller, 2);
287
288 /* Revert to the normal sleep behavior. */
289 ResetEvent (s->hev_unsleep);
290
291 /* If there's no byte buffered yet, give up */
292 if (wait_result == WAIT_TIMEOUT)
293 {
294 errno = EAGAIN;
295 return -1;
296 }
297 }
298
299 /* Reset caller unlock event now, as we've handled the pending
300 process output event */
301 ResetEvent (s->hev_caller);
302
303 /* It is now safe to do anything with contents of S, except for
304 changing s->die_p, which still should be interlocked */
305
306 if (s->eof_p)
307 return 0;
308 if (s->error_p || s->die_p)
309 return -1;
310
311 /* Ok, there were no error neither eof - we've got a byte from the pipe */
312 *(data++) = s->onebyte;
313 --size;
314
315 if (size > 0)
316 {
317 DWORD bytes_available, bytes_read;
318
319 /* If the api call fails, return at least one byte already read.
320 ReadFile in thread will return error */
321 if (!PeekNamedPipe (s->hpipe, NULL, 0, NULL, &bytes_available, NULL))
322 return 1;
323
324 /* Fetch available bytes. The same consideration applies, so do
325 not check for errors. ReadFile in the thread will fail if the
326 next call fails. */
327 ReadFile (s->hpipe, data, min (bytes_available, size), &bytes_read, NULL);
328
329 /* Now we can unblock thread, so it attempts to read more */
330 SetEvent (s->hev_thread);
331 return bytes_read + 1;
332 }
333 else
334 {
335 SetEvent (s->hev_thread);
336 return 1;
337 }
338 }
339
340 static int
341 ntpipe_slurp_closer (Lstream *stream)
342 {
343 /* This function must be called from the main thread only */
344 struct ntpipe_slurp_stream* s = NTPIPE_SLURP_STREAM_DATA(stream);
345
346 /* Force thread to stop */
347 InterlockedIncrement (&s->die_p);
348
349 /* Break the pipe, in case the thread still blocked on read */
350 CloseHandle (s->hpipe);
351
352 /* Set events which could possibly block slurper */
353 SetEvent (s->hev_unsleep);
354 SetEvent (s->hev_thread);
355
356 /* Wait while thread terminates */
357 WaitForSingleObject (s->hthread, INFINITE);
358 CloseHandle (s->hthread);
359
360 /* Destroy events */
361 CloseHandle (s->hev_thread);
362 CloseHandle (s->hev_caller);
363 CloseHandle (s->hev_unsleep);
364
365 return 0;
366 }
367
368 static void
369 init_slurp_stream (void)
370 {
371 LSTREAM_HAS_METHOD (ntpipe_slurp, reader);
372 LSTREAM_HAS_METHOD (ntpipe_slurp, closer);
373 }
374
375 /************************************************************************/
376 /* Pipe outstream - writes process input */
377 /************************************************************************/
378
379 #define MAX_FLUSH_TIME 500
380
381 #define NTPIPE_SHOVE_STREAM_DATA(stream) \
382 LSTREAM_TYPE_DATA (stream, ntpipe_shove)
383
384 struct ntpipe_shove_stream
385 {
386 LPARAM user_data; /* Any user data stored in the stream object */
387 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */
388 /* This is an auto-reset object. */
389 HANDLE hpipe; /* Pipe write end handle. */
390 HANDLE hthread; /* Reader thread handle. */
391 LPVOID buffer; /* Buffer being written */
392 DWORD size; /* Number of bytes to write */
393 DWORD die_p; /* Thread must exit ASAP if non-zero */
394 DWORD idle_p; /* Non-zero if thread is waiting for job */
395 BOOL error_p : 1; /* Read error other than EOF/broken pipe */
396 BOOL blocking_p : 1;/* Last write attempt would cause blocking */
397 };
398
399 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove,
400 sizeof (struct ntpipe_shove_stream));
401
402 static DWORD WINAPI
403 shove_thread (LPVOID vparam)
404 {
405 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam;
406
407 for (;;)
408 {
409 DWORD bytes_written;
410
411 /* Block on event and wait for a job */
412 InterlockedIncrement (&s->idle_p);
413 WaitForSingleObject (s->hev_thread, INFINITE);
414
415 if (s->die_p)
416 break;
417
418 /* Write passed buffer */
419 if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL)
420 || bytes_written != s->size)
421 {
422 s->error_p = TRUE;
423 InterlockedIncrement (&s->die_p);
424 }
425
426 /* free it */
427 LocalFree ((HLOCAL)s->buffer);
428
429 if (s->die_p)
430 break;
431 }
432
433 return 0;
434 }
435
436 static Lisp_Object
437 make_ntpipe_output_stream (HANDLE hpipe, LPARAM param)
438 {
439 Lisp_Object obj;
440 Lstream *lstr = Lstream_new (lstream_ntpipe_shove, "w");
441 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA (lstr);
442 DWORD thread_id_unused;
443
444 s->die_p = 0;
445 s->error_p = FALSE;
446 s->hpipe = hpipe;
447 s->user_data = param;
448
449 /* Create reader thread. This could fail, so do not
450 create the event until thread is created */
451 s->hthread = CreateThread (NULL, 0, shove_thread, (LPVOID)s,
452 CREATE_SUSPENDED, &thread_id_unused);
453 if (s->hthread == NULL)
454 {
455 Lstream_delete (lstr);
456 return Qnil;
457 }
458
459 /* hev_thread is an auto-reset event, initially nonsignaled */
460 s->hev_thread = CreateEvent (NULL, FALSE, FALSE, NULL);
461
462 /* Now let it go */
463 ResumeThread (s->hthread);
464
465 lstr->flags |= LSTREAM_FL_CLOSE_AT_DISKSAVE;
466 XSETLSTREAM (obj, lstr);
467 return obj;
468 }
469
470 static LPARAM
471 get_ntpipe_output_stream_param (Lstream *stream)
472 {
473 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
474 return s->user_data;
475 }
476
477 static int
478 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
479 {
480 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
481
482 if (s->error_p)
483 return -1;
484
485 s->blocking_p = !s->idle_p;
486 if (s->blocking_p)
487 return 0;
488
489 /* Make a copy of data to be written. We intentionally avoid using
490 xalloc/xfree, because gnu malloc is not thread-safe */
491 s->buffer = (LPVOID) LocalAlloc (LMEM_FIXED, size);
492 if (s->buffer == NULL)
493 return -1;
494 memcpy (s->buffer, data, size);
495 s->size = size;
496
497 /* Start output */
498 InterlockedDecrement (&s->idle_p);
499 SetEvent (s->hev_thread);
500 return size;
501 }
502
503 static int
504 ntpipe_shove_was_blocked_p (Lstream *stream)
505 {
506 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
507 return s->blocking_p;
508 }
509
510 static int
511 ntpipe_shove_flusher (Lstream *stream)
512 {
513 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
514 int i;
515
516 if (s->error_p)
517 return -1;
518
519 /* We do not want to be blocked forever. Instead, we wait
520 about 0.5 second for output to finish. If this does
521 not help, we just return flush failure. */
522 for (i = 0; i < MAX_FLUSH_TIME / 50; ++i)
523 {
524 if (s->idle_p)
525 return 0;
526 Sleep (50);
527 }
528 return -1;
529 }
530
531 static int
532 ntpipe_shove_closer (Lstream *stream)
533 {
534 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
535
536 /* Force thread stop */
537 InterlockedIncrement (&s->die_p);
538
539 /* Close pipe handle, possibly breaking it */
540 CloseHandle (s->hpipe);
541
542 /* Thread will end upon unblocking */
543 SetEvent (s->hev_thread);
544
545 /* Wait while thread terminates */
546 WaitForSingleObject (s->hthread, INFINITE);
547 CloseHandle (s->hthread);
548
549 /* Destroy the event */
550 CloseHandle (s->hev_thread);
551
552 return 0;
553 }
554
555 static void
556 init_shove_stream (void)
557 {
558 LSTREAM_HAS_METHOD (ntpipe_shove, writer);
559 LSTREAM_HAS_METHOD (ntpipe_shove, flusher);
560 LSTREAM_HAS_METHOD (ntpipe_shove, was_blocked_p);
561 LSTREAM_HAS_METHOD (ntpipe_shove, closer);
562 }
563
564 /************************************************************************/
565 /* Dispatch queue management */
566 /************************************************************************/
129 567
130 static int 568 static int
131 mswindows_user_event_p (struct Lisp_Event* sevt) 569 mswindows_user_event_p (struct Lisp_Event* sevt)
132 { 570 {
133 return (sevt->event_type == key_press_event 571 return (sevt->event_type == key_press_event
134 || sevt->event_type == button_press_event 572 || sevt->event_type == button_press_event
135 || sevt->event_type == button_release_event 573 || sevt->event_type == button_release_event
136 || sevt->event_type == dnd_drop_event); 574 || sevt->event_type == dnd_drop_event);
137 } 575 }
138
139 /************************************************************************/
140 /* Dispatch queue management */
141 /************************************************************************/
142 576
143 /* 577 /*
144 * Add an emacs event to the proper dispatch queue 578 * Add an emacs event to the proper dispatch queue
145 */ 579 */
146 void 580 void
166 600
167 event->channel = mswindows_find_frame (hwnd); 601 event->channel = mswindows_find_frame (hwnd);
168 event->timestamp = GetMessageTime(); 602 event->timestamp = GetMessageTime();
169 event->event_type = magic_event; 603 event->event_type = magic_event;
170 EVENT_MSWINDOWS_MAGIC_TYPE (event) = message; 604 EVENT_MSWINDOWS_MAGIC_TYPE (event) = message;
605
606 mswindows_enqueue_dispatch_event (emacs_event);
607 }
608
609 static void
610 mswindows_enqueue_process_event (struct Lisp_Process* p)
611 {
612 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
613 struct Lisp_Event* event = XEVENT (emacs_event);
614 Lisp_Object process;
615 XSETPROCESS (process, p);
616
617 event->event_type = process_event;
618 event->timestamp = GetTickCount ();
619 event->event.process.process = process;
171 620
172 mswindows_enqueue_dispatch_event (emacs_event); 621 mswindows_enqueue_dispatch_event (emacs_event);
173 } 622 }
174 623
175 static void 624 static void
305 } 754 }
306 previous_event = event; 755 previous_event = event;
307 } 756 }
308 return Qnil; 757 return Qnil;
309 } 758 }
310 759
311 760 /************************************************************************/
761 /* Waitable handles manipulation */
762 /************************************************************************/
763 static int
764 find_waitable_handle (HANDLE h)
765 {
766 int i;
767 for (i = 0; i < mswindows_waitable_count; ++i)
768 if (mswindows_waitable_handles[i] == h)
769 return i;
770
771 return -1;
772 }
773
774 static BOOL
775 add_waitable_handle (HANDLE h)
776 {
777 assert (find_waitable_handle (h) < 0);
778 if (mswindows_waitable_count == MAX_WAITABLE)
779 return FALSE;
780
781 mswindows_waitable_handles [mswindows_waitable_count++] = h;
782 return TRUE;
783 }
784
785 static void
786 remove_waitable_handle (HANDLE h)
787 {
788 int ix = find_waitable_handle (h);
789 if (ix < 0)
790 return;
791
792 mswindows_waitable_handles [ix] =
793 mswindows_waitable_handles [--mswindows_waitable_count];
794 }
795
796
312 /************************************************************************/ 797 /************************************************************************/
313 /* Event pump */ 798 /* Event pump */
314 /************************************************************************/ 799 /************************************************************************/
315 800
316 static Lisp_Object 801 static Lisp_Object
453 * 938 *
454 * To detect this, we use a counter of active timers, and allow 939 * To detect this, we use a counter of active timers, and allow
455 * fetching WM_TIMER messages. Instead of trying to fetch a WM_TIMER 940 * fetching WM_TIMER messages. Instead of trying to fetch a WM_TIMER
456 * which will never come when there are no pending timers, which leads 941 * which will never come when there are no pending timers, which leads
457 * to deadlock, we simply signal an error. 942 * to deadlock, we simply signal an error.
458 *
459 * The implementation does not honor user_p by design.
460 */ 943 */
461 static void 944 static void
462 mswindows_need_event_in_modal_loop (int user_p, int badly_p) 945 mswindows_need_event_in_modal_loop (int badly_p)
463 { 946 {
464 MSG msg; 947 MSG msg;
465 948
466 /* Check if already have one */ 949 /* Check if already have one */
467 if (!NILP (mswindows_u_dispatch_event_queue) 950 if (!NILP (mswindows_u_dispatch_event_queue)
487 970
488 /* 971 /*
489 * This drains the event queue and fills up two internal queues until 972 * This drains the event queue and fills up two internal queues until
490 * an event of a type specified by USER_P is retrieved. 973 * an event of a type specified by USER_P is retrieved.
491 * 974 *
492 * If user_p, then the function drains until the first user event, or
493 * the first non-user event if there no user events. Otherwise, If
494 * not user_p, it does not give preference to user events.
495 *
496 * If badly_p, then the function does not return until an event is
497 * available.
498 *
499 * The code does not rely on MsgWaitForMultipleObjects preference for
500 * messages over waitable handles.
501 * 975 *
502 * Used by emacs_mswindows_event_pending_p and emacs_mswindows_next_event 976 * Used by emacs_mswindows_event_pending_p and emacs_mswindows_next_event
503 */ 977 */
504 static void 978 static void
505 mswindows_need_event (int user_p, int badly_p) 979 mswindows_need_event (int badly_p)
506 { 980 {
507 int active; 981 int active;
508 982
509 if (mswindows_in_modal_loop) 983 if (mswindows_in_modal_loop)
510 { 984 {
511 mswindows_need_event_in_modal_loop (user_p, badly_p); 985 mswindows_need_event_in_modal_loop (badly_p);
512 return; 986 return;
513 } 987 }
514 988
515 /* Have to drain Windows message queue first, otherwise, we may miss 989 /* Have to drain Windows message queue first, otherwise, we may miss
516 quit char when called from quit_p */ 990 quit char when called from quit_p */
517 mswindows_drain_windows_queue (); 991 mswindows_drain_windows_queue ();
518 992
519 while (NILP (mswindows_u_dispatch_event_queue) && 993 while (NILP (mswindows_u_dispatch_event_queue)
520 (user_p || NILP (mswindows_s_dispatch_event_queue))) 994 && NILP (mswindows_s_dispatch_event_queue))
521 { 995 {
522 /* If we already have an event, we've got someting to return - no wait! */ 996 /* Now try getting a message or process event */
523 if (!NILP (mswindows_u_dispatch_event_queue)
524 || !NILP (mswindows_s_dispatch_event_queue))
525 badly_p = 0;
526
527 /* Now try getting a message */
528 active = MsgWaitForMultipleObjects (mswindows_waitable_count, 997 active = MsgWaitForMultipleObjects (mswindows_waitable_count,
529 mswindows_waitable, 998 mswindows_waitable_handles,
530 FALSE, badly_p ? INFINITE : 0, 999 FALSE, badly_p ? INFINITE : 0,
531 QS_ALLINPUT); 1000 QS_ALLINPUT);
532 1001
533 /* This will assert if handle being waited for becomes abandoned. 1002 /* This will assert if handle being waited for becomes abandoned.
534 Not the case currently tho */ 1003 Not the case currently tho */
546 /* Got your message, thanks */ 1015 /* Got your message, thanks */
547 mswindows_drain_windows_queue (); 1016 mswindows_drain_windows_queue ();
548 } 1017 }
549 else 1018 else
550 { 1019 {
551 /* XXX FIXME: We should do some kind of round-robin scheme to ensure fairness */ 1020 int ix = active - WAIT_OBJECT_0;
552 int waitable = active - WAIT_OBJECT_0; 1021 /* First, try to find which process' ouptut has signaled */
553 assert(0); /* #### */ 1022 struct Lisp_Process *p =
1023 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix]));
1024 if (p != NULL)
1025 {
1026 /* Found a signaled process input handle */
1027 mswindows_enqueue_process_event (p);
1028 }
1029 else
1030 {
1031 /* None. This means that the process handle itself has signaled.
1032 Remove the handle from the wait vector, and make status_ntoify
1033 note the exited process */
1034 CloseHandle (mswindows_waitable_handles[ix]);
1035 mswindows_waitable_handles [ix] =
1036 mswindows_waitable_handles [--mswindows_waitable_count];
1037 kick_status_notify ();
1038 }
554 } 1039 }
555 } /* while */ 1040 } /* while */
556
557 return;
558 } 1041 }
559 1042
560 /************************************************************************/ 1043 /************************************************************************/
561 /* Event generators */ 1044 /* Event generators */
562 /************************************************************************/ 1045 /************************************************************************/
1006 GetClientRect(hwnd, &rect); 1489 GetClientRect(hwnd, &rect);
1007 FRAME_PIXWIDTH(frame) = rect.right; 1490 FRAME_PIXWIDTH(frame) = rect.right;
1008 FRAME_PIXHEIGHT(frame) = rect.bottom; 1491 FRAME_PIXHEIGHT(frame) = rect.bottom;
1009 1492
1010 pixel_to_real_char_size (frame, rect.right, rect.bottom, 1493 pixel_to_real_char_size (frame, rect.right, rect.bottom,
1011 &MSWINDOWS_FRAME_CHARWIDTH (frame), 1494 &FRAME_MSWINDOWS_CHARWIDTH (frame),
1012 &MSWINDOWS_FRAME_CHARHEIGHT (frame)); 1495 &FRAME_MSWINDOWS_CHARHEIGHT (frame));
1013 1496
1014 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows); 1497 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows);
1015 change_frame_size (frame, rows, columns, 1); 1498 change_frame_size (frame, rows, columns, 1);
1016 1499
1017 /* If we are inside frame creation, we have to apply geometric 1500 /* If we are inside frame creation, we have to apply geometric
1427 * Find the console that matches the supplied mswindows window handle 1910 * Find the console that matches the supplied mswindows window handle
1428 */ 1911 */
1429 Lisp_Object 1912 Lisp_Object
1430 mswindows_find_console (HWND hwnd) 1913 mswindows_find_console (HWND hwnd)
1431 { 1914 {
1432 Lisp_Object concons; 1915 /* We only support one console */
1433 1916 return XCAR (Vconsole_list);
1434 CONSOLE_LOOP (concons)
1435 {
1436 Lisp_Object console = XCAR (concons);
1437 /* We only support one console so this must be it */
1438 return console;
1439 }
1440
1441 return Qnil;
1442 } 1917 }
1443 1918
1444 /* 1919 /*
1445 * Find the frame that matches the supplied mswindows window handle 1920 * Find the frame that matches the supplied mswindows window handle
1446 */ 1921 */
1510 * emacs_mswindows_next_event() would not block. 1985 * emacs_mswindows_next_event() would not block.
1511 */ 1986 */
1512 static int 1987 static int
1513 emacs_mswindows_event_pending_p (int user_p) 1988 emacs_mswindows_event_pending_p (int user_p)
1514 { 1989 {
1515 mswindows_need_event (user_p, 0); 1990 mswindows_need_event (0);
1516
1517 return (!NILP (mswindows_u_dispatch_event_queue) 1991 return (!NILP (mswindows_u_dispatch_event_queue)
1518 || (!user_p && !NILP (mswindows_s_dispatch_event_queue))); 1992 || (!user_p && !NILP (mswindows_s_dispatch_event_queue)));
1519 } 1993 }
1520 1994
1521 /* 1995 /*
1524 static void 1998 static void
1525 emacs_mswindows_next_event (struct Lisp_Event *emacs_event) 1999 emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
1526 { 2000 {
1527 Lisp_Object event, event2; 2001 Lisp_Object event, event2;
1528 2002
1529 /* Give strong preference to user events */ 2003 mswindows_need_event (1);
1530 mswindows_need_event (1, 1); 2004
1531
1532 /* XXX Copied from event-Xt.c */
1533 event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue)); 2005 event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue));
1534 XSETEVENT (event2, emacs_event); 2006 XSETEVENT (event2, emacs_event);
1535 Fcopy_event (event, event2); 2007 Fcopy_event (event, event2);
1536 Fdeallocate_event (event); 2008 Fdeallocate_event (event);
1537 } 2009 }
1591 default: 2063 default:
1592 assert(0); 2064 assert(0);
1593 } 2065 }
1594 } 2066 }
1595 2067
2068 static HANDLE
2069 get_process_input_waitable (struct Lisp_Process *process)
2070 {
2071 Lisp_Object instr, outstr;
2072 get_process_streams (process, &instr, &outstr);
2073 assert (!NILP (instr));
2074 return get_ntpipe_input_stream_waitable (XLSTREAM (instr));
2075 }
2076
2077 static HANDLE
2078 get_process_handle (struct Lisp_Process *p)
2079 {
2080 /* #### The guess is that cygwin uses the same algorithm for
2081 computing pids: negate if less than zero, '95 case */
2082 Lisp_Object process, pid;
2083 XSETPROCESS (process, p);
2084 pid = Fprocess_id (process);
2085 if (INTP (pid))
2086 {
2087 HANDLE hproc;
2088 int ipid = XINT (pid);
2089 if (ipid < 0)
2090 ipid = -ipid;
2091 hproc = OpenProcess (SYNCHRONIZE, FALSE, ipid);
2092 /* #### This is WRONG! The process migh have ended before we got here. */
2093 /* assert (hproc != NULL); */
2094 /* Instead, we fake "a signaled hadle", which will trigger
2095 immediately upon entering the message loop */
2096 if (hproc = NULL)
2097 hproc = CreateEvent (NULL, TRUE, TRUE, NULL);
2098 return hproc;
2099 }
2100 else
2101 return NULL;
2102 }
2103
1596 static void 2104 static void
1597 emacs_mswindows_select_process (struct Lisp_Process *process) 2105 emacs_mswindows_select_process (struct Lisp_Process *process)
1598 { 2106 {
2107 HANDLE hev = get_process_input_waitable (process);
2108 HANDLE hprocess;
2109
2110 if (!add_waitable_handle (hev))
2111 error ("Too many active processes");
2112
2113 hprocess = get_process_handle (process);
2114 if (hprocess)
2115 {
2116 if (!add_waitable_handle (hprocess))
2117 {
2118 remove_waitable_handle (hev);
2119 CloseHandle (hprocess);
2120 error ("Too many active processes");
2121 }
2122 }
1599 } 2123 }
1600 2124
1601 static void 2125 static void
1602 emacs_mswindows_unselect_process (struct Lisp_Process *process) 2126 emacs_mswindows_unselect_process (struct Lisp_Process *process)
1603 { 2127 {
2128 /* Process handle is removed in the event loop as soon
2129 as it is signaled, so don't bother here about it */
2130 HANDLE hev = get_process_input_waitable (process);
2131 remove_waitable_handle (hev);
1604 } 2132 }
1605 2133
1606 static void 2134 static void
1607 emacs_mswindows_select_console (struct console *con) 2135 emacs_mswindows_select_console (struct console *con)
1608 { 2136 {
1614 } 2142 }
1615 2143
1616 static void 2144 static void
1617 emacs_mswindows_quit_p (void) 2145 emacs_mswindows_quit_p (void)
1618 { 2146 {
1619 mswindows_need_event (1, 0); 2147 /* Drain windows queue. This sets up number of quit
2148 characters in in the queue */
2149 mswindows_drain_windows_queue ();
1620 2150
1621 if (mswindows_quit_chars_count > 0) 2151 if (mswindows_quit_chars_count > 0)
1622 { 2152 {
1623 /* Yes there's a hidden one... Throw it away */ 2153 /* Yes there's a hidden one... Throw it away */
1624 struct Lisp_Event match_against; 2154 struct Lisp_Event match_against;
1635 2165
1636 Fdeallocate_event(emacs_event); 2166 Fdeallocate_event(emacs_event);
1637 --mswindows_quit_chars_count; 2167 --mswindows_quit_chars_count;
1638 } 2168 }
1639 } 2169 }
2170
2171 USID
2172 emacs_mswindows_create_stream_pair (void* inhandle, void* outhandle,
2173 Lisp_Object* instream,
2174 Lisp_Object* outstream,
2175 int flags)
2176 {
2177 /* Handles for streams */
2178 HANDLE hin, hout;
2179 /* fds. These just stored along with the streams, and are closed in
2180 delete stream pair method, because we need to handle fake unices
2181 here. */
2182 int fdi, fdo;
2183
2184 /* Decode inhandle and outhandle. Their meaning depends on
2185 the process implementation being used. */
2186 #if defined (HAVE_WIN32_PROCESSES)
2187 /* We're passed in Windows handles. That's what we like most... */
2188 hin = (HANDLE) inhandle;
2189 hout = (HANDLE) outhandle;
2190 fdi = fdo = -1;
2191 #elif defined (HAVE_UNIX_PROCESSES)
2192 /* We are passed UNIX fds. This must be Cygwin.
2193 Fetch os handles */
2194 hin = inhandle >= 0 ? get_osfhandle ((int)inhandle) : INVALID_HANDLE_VALUE;
2195 hout = outhandle >= 0 ? get_sfhandle ((int)outhandle) : INVALID_HANDLE_VALUE;
2196 #else
2197 #error "So, WHICH kind of processes do you want?"
2198 #endif
2199
2200 *instream = (hin != INVALID_HANDLE_VALUE
2201 ? make_ntpipe_input_stream (hin, fdi)
2202 : Qnil);
2203
2204 *outstream = (hout != INVALID_HANDLE_VALUE
2205 ? make_ntpipe_output_stream (hout, fdo)
2206 : Qnil);
2207
2208 return (NILP (*instream) ? USID_ERROR
2209 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream))));
2210 }
2211
2212 USID
2213 emacs_mswindows_delete_stream_pair (Lisp_Object instream,
2214 Lisp_Object outstream)
2215 {
2216 /* Oh nothing special here for Win32 at all */
2217 #if defined (HAVE_UNIX_PROCESSES)
2218 int in = (NILP(instream) ? -1
2219 : get_ntpipe_input_stream_param (XLSTREAM (instream)));
2220 int out = (NILP(outstream) ? -1
2221 : get_ntpipe_output_stream_param (XLSTREAM (outstream)));
2222
2223 if (in >= 0)
2224 close (in);
2225 if (out != in && out >= 0)
2226 close (out);
2227 #endif
2228
2229 return (NILP (instream) ? USID_DONTHASH
2230 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (instream))));
2231 }
2232
1640 2233
1641 #ifndef HAVE_X_WINDOWS 2234 #ifndef HAVE_X_WINDOWS
1642 /* This is called from GC when a process object is about to be freed. 2235 /* This is called from GC when a process object is about to be freed.
1643 If we've still got pointers to it in this file, we're gonna lose hard. 2236 If we've still got pointers to it in this file, we're gonna lose hard.
1644 */ 2237 */
1688 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; 2281 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console;
1689 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; 2282 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console;
1690 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; 2283 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process;
1691 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; 2284 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process;
1692 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; 2285 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p;
2286 mswindows_event_stream->create_stream_pair_cb = emacs_mswindows_create_stream_pair;
2287 mswindows_event_stream->delete_stream_pair_cb = emacs_mswindows_delete_stream_pair;
1693 2288
1694 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /* 2289 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /*
1695 *Controls redrawing frame contents during mouse-drag or keyboard resize 2290 *Controls redrawing frame contents during mouse-drag or keyboard resize
1696 operation. When non-nil, the frame is redrawn while being resized. When 2291 operation. When non-nil, the frame is redrawn while being resized. When
1697 nil, frame is not redrawn, and exposed areas are filled with default 2292 nil, frame is not redrawn, and exposed areas are filled with default
1741 syms_of_event_mswindows (void) 2336 syms_of_event_mswindows (void)
1742 { 2337 {
1743 } 2338 }
1744 2339
1745 void 2340 void
2341 lstream_type_create_mswindows_selectable (void)
2342 {
2343 init_slurp_stream ();
2344 init_shove_stream ();
2345 }
2346
2347 void
1746 init_event_mswindows_late (void) 2348 init_event_mswindows_late (void)
1747 { 2349 {
1748 event_stream = mswindows_event_stream; 2350 event_stream = mswindows_event_stream;
1749 2351
1750 mswindows_dynamic_frame_resize = !GetSystemMetrics (SM_SLOWMACHINE); 2352 mswindows_dynamic_frame_resize = !GetSystemMetrics (SM_SLOWMACHINE);