aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Innes1998-12-28 19:42:26 +0000
committerAndrew Innes1998-12-28 19:42:26 +0000
commit3ef68e6be28a206cc531b0fe113ad301b3447195 (patch)
tree491633d6ce383f974cb36337df711102970bbd45 /src
parent82e7c0a907a11f84d9eaf9750266db104974e9ab (diff)
downloademacs-3ef68e6be28a206cc531b0fe113ad301b3447195.tar.gz
emacs-3ef68e6be28a206cc531b0fe113ad301b3447195.zip
(w32_msg_pump): Ignore WM_NULL message posted to thread
by complete_deferred_msg. (post_character_message): Cancel all deferred messages when quit_char is typed, in order to break out of potential deadlocks. (cancel_all_deferred_msgs): New function. (complete_deferred_msg): Don't abort if msg not found; may have been cancelled. (Fw32_reconstruct_hot_key): Use pre-interned symbols. (Fw32_send_sys_command): Wait for system command to complete before returning.
Diffstat (limited to 'src')
-rw-r--r--src/w32fns.c135
1 files changed, 90 insertions, 45 deletions
diff --git a/src/w32fns.c b/src/w32fns.c
index 47423f466f8..000ebb54018 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -3355,45 +3355,6 @@ unregister_hot_keys (hwnd)
3355 } 3355 }
3356} 3356}
3357 3357
3358static void
3359post_character_message (hwnd, msg, wParam, lParam, modifiers)
3360 HWND hwnd;
3361 UINT msg;
3362 WPARAM wParam;
3363 LPARAM lParam;
3364 DWORD modifiers;
3365
3366{
3367 W32Msg wmsg;
3368
3369 wmsg.dwModifiers = modifiers;
3370
3371 /* Detect quit_char and set quit-flag directly. Note that we
3372 still need to post a message to ensure the main thread will be
3373 woken up if blocked in sys_select(), but we do NOT want to post
3374 the quit_char message itself (because it will usually be as if
3375 the user had typed quit_char twice). Instead, we post a dummy
3376 message that has no particular effect. */
3377 {
3378 int c = wParam;
3379 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
3380 c = make_ctrl_char (c) & 0377;
3381 if (c == quit_char)
3382 {
3383 Vquit_flag = Qt;
3384
3385 /* The choice of message is somewhat arbitrary, as long as
3386 the main thread handler just ignores it. */
3387 msg = WM_NULL;
3388
3389 /* Interrupt any blocking system calls. */
3390 signal_quit ();
3391 }
3392 }
3393
3394 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3395}
3396
3397/* Main message dispatch loop. */ 3358/* Main message dispatch loop. */
3398 3359
3399static void 3360static void
@@ -3411,6 +3372,9 @@ w32_msg_pump (deferred_msg * msg_buf)
3411 { 3372 {
3412 switch (msg.message) 3373 switch (msg.message)
3413 { 3374 {
3375 case WM_NULL:
3376 /* Produced by complete_deferred_msg; just ignore. */
3377 break;
3414 case WM_EMACS_CREATEWINDOW: 3378 case WM_EMACS_CREATEWINDOW:
3415 w32_createwindow ((struct frame *) msg.wParam); 3379 w32_createwindow ((struct frame *) msg.wParam);
3416 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) 3380 if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
@@ -3560,7 +3524,8 @@ complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3560 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg); 3524 deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
3561 3525
3562 if (msg_buf == NULL) 3526 if (msg_buf == NULL)
3563 abort (); 3527 /* Message may have been cancelled, so don't abort(). */
3528 return;
3564 3529
3565 msg_buf->result = result; 3530 msg_buf->result = result;
3566 msg_buf->completed = 1; 3531 msg_buf->completed = 1;
@@ -3569,6 +3534,26 @@ complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
3569 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); 3534 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3570} 3535}
3571 3536
3537void
3538cancel_all_deferred_msgs ()
3539{
3540 deferred_msg * item;
3541
3542 /* Don't actually need synchronization for read access, since
3543 modification of single pointer is always atomic. */
3544 /* enter_crit (); */
3545
3546 for (item = deferred_msg_head; item != NULL; item = item->next)
3547 {
3548 item->result = 0;
3549 item->completed = 1;
3550 }
3551
3552 /* leave_crit (); */
3553
3554 /* Ensure input thread is woken so it notices the completion. */
3555 PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
3556}
3572 3557
3573DWORD 3558DWORD
3574w32_msg_worker (dw) 3559w32_msg_worker (dw)
@@ -3595,6 +3580,66 @@ w32_msg_worker (dw)
3595 return 0; 3580 return 0;
3596} 3581}
3597 3582
3583static void
3584post_character_message (hwnd, msg, wParam, lParam, modifiers)
3585 HWND hwnd;
3586 UINT msg;
3587 WPARAM wParam;
3588 LPARAM lParam;
3589 DWORD modifiers;
3590
3591{
3592 W32Msg wmsg;
3593
3594 wmsg.dwModifiers = modifiers;
3595
3596 /* Detect quit_char and set quit-flag directly. Note that we
3597 still need to post a message to ensure the main thread will be
3598 woken up if blocked in sys_select(), but we do NOT want to post
3599 the quit_char message itself (because it will usually be as if
3600 the user had typed quit_char twice). Instead, we post a dummy
3601 message that has no particular effect. */
3602 {
3603 int c = wParam;
3604 if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
3605 c = make_ctrl_char (c) & 0377;
3606 if (c == quit_char)
3607 {
3608 Vquit_flag = Qt;
3609
3610 /* The choice of message is somewhat arbitrary, as long as
3611 the main thread handler just ignores it. */
3612 msg = WM_NULL;
3613
3614 /* Interrupt any blocking system calls. */
3615 signal_quit ();
3616
3617 /* As a safety precaution, forcibly complete any deferred
3618 messages. This is a kludge, but I don't see any particularly
3619 clean way to handle the situation where a deferred message is
3620 "dropped" in the lisp thread, and will thus never be
3621 completed, eg. by the user trying to activate the menubar
3622 when the lisp thread is busy, and then typing C-g when the
3623 menubar doesn't open promptly (with the result that the
3624 menubar never responds at all because the deferred
3625 WM_INITMENU message is never completed). Another problem
3626 situation is when the lisp thread calls SendMessage (to send
3627 a window manager command) when a message has been deferred;
3628 the lisp thread gets blocked indefinitely waiting for the
3629 deferred message to be completed, which itself is waiting for
3630 the lisp thread to respond.
3631
3632 Note that we don't want to block the input thread waiting for
3633 a reponse from the lisp thread (although that would at least
3634 solve the deadlock problem above), because we want to be able
3635 to receive C-g to interrupt the lisp thread. */
3636 cancel_all_deferred_msgs ();
3637 }
3638 }
3639
3640 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3641}
3642
3598/* Main window procedure */ 3643/* Main window procedure */
3599 3644
3600LRESULT CALLBACK 3645LRESULT CALLBACK
@@ -6524,7 +6569,7 @@ If optional parameter FRAME is not specified, use selected frame.")
6524 6569
6525 CHECK_NUMBER (command, 0); 6570 CHECK_NUMBER (command, 0);
6526 6571
6527 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0); 6572 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
6528 6573
6529 return Qnil; 6574 return Qnil;
6530} 6575}
@@ -6700,13 +6745,13 @@ DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key, Sw32_reconstruct_hot
6700 6745
6701 key = Fcons (key, Qnil); 6746 key = Fcons (key, Qnil);
6702 if (w32_modifiers & MOD_SHIFT) 6747 if (w32_modifiers & MOD_SHIFT)
6703 key = Fcons (intern ("shift"), key); 6748 key = Fcons (Qshift, key);
6704 if (w32_modifiers & MOD_CONTROL) 6749 if (w32_modifiers & MOD_CONTROL)
6705 key = Fcons (intern ("control"), key); 6750 key = Fcons (Qctrl, key);
6706 if (w32_modifiers & MOD_ALT) 6751 if (w32_modifiers & MOD_ALT)
6707 key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key); 6752 key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
6708 if (w32_modifiers & MOD_WIN) 6753 if (w32_modifiers & MOD_WIN)
6709 key = Fcons (intern ("hyper"), key); 6754 key = Fcons (Qhyper, key);
6710 6755
6711 return key; 6756 return key;
6712} 6757}