summaryrefslogtreecommitdiff
path: root/src/msdos.c
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>1998-10-20 14:25:38 +0000
committerEli Zaretskii <eliz@gnu.org>1998-10-20 14:25:38 +0000
commit0c7bc1aabdf734481c244925b6c4de65b8fea4eb (patch)
tree678ab8872d4586de6bc1b52e5d67f859fd6476e9 /src/msdos.c
parent32372ef84c272010ae644eb5f6e63ac5bae23b18 (diff)
downloademacs-0c7bc1aabdf734481c244925b6c4de65b8fea4eb.tar.gz
(mouse_init): Reset the button press/release info of the mouse driver.
(mouse_preempted): New variable. (dos_rawgetc): Don't generate mouse events if mouse is preempted. (XMenuActivate): Preempt the mouse during menu-handling loop. Release the current time slice while idling in the menu-handling loop. Leave the loop only if the user pressed, then released the same button. Discard all mouse events that are pending in the event queue before exiting.
Diffstat (limited to 'src/msdos.c')
-rw-r--r--src/msdos.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/src/msdos.c b/src/msdos.c
index fc9d3e29925..f70c196c012 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -214,6 +214,25 @@ mouse_released (b, xp, yp)
return (regs.x.bx != 0);
}
+static int
+mouse_button_depressed (b, xp, yp)
+ int b, *xp, *yp;
+{
+ union REGS regs;
+
+ if (b >= mouse_button_count)
+ return 0;
+ regs.x.ax = 0x0003;
+ int86 (0x33, &regs, &regs);
+ if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
+ {
+ *xp = regs.x.cx / 8;
+ *yp = regs.x.dx / 8;
+ return 1;
+ }
+ return 0;
+}
+
void
mouse_get_pos (f, insist, bar_window, part, x, y, time)
FRAME_PTR *f;
@@ -252,6 +271,7 @@ void
mouse_init ()
{
union REGS regs;
+ int b;
if (termscript)
fprintf (termscript, "<M_INIT>");
@@ -259,6 +279,18 @@ mouse_init ()
regs.x.ax = 0x0021;
int86 (0x33, &regs, &regs);
+ /* Reset the mouse last press/release info. It seems that Windows
+ doesn't do that automatically when function 21h is called, which
+ causes Emacs to ``remember'' the click that switched focus to the
+ window just before Emacs was started from that window. */
+ for (b = 0; b < mouse_button_count; b++)
+ {
+ int dummy_x, dummy_y;
+
+ (void) mouse_pressed (b, &dummy_x, &dummy_y);
+ (void) mouse_released (b, &dummy_x, &dummy_y);
+ }
+
regs.x.ax = 0x0007;
regs.x.cx = 0;
regs.x.dx = 8 * (ScreenCols () - 1);
@@ -1691,6 +1723,7 @@ and then the scan code.")
/* Get a char from keyboard. Function keys are put into the event queue. */
extern void kbd_buffer_store_event (struct input_event *);
+static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
static int
dos_rawgetc ()
@@ -1898,7 +1931,7 @@ dos_rawgetc ()
kbd_buffer_store_event (&event);
}
- if (have_mouse > 0)
+ if (have_mouse > 0 && !mouse_preempted)
{
int but, press, x, y, ok;
@@ -2264,6 +2297,10 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
if (y0 <= 0)
y0 = 1;
+ /* We will process all the mouse events directly, so we had
+ better prevented dos_rawgetc from stealing them from us. */
+ mouse_preempted++;
+
state = alloca (menu->panecount * sizeof (struct IT_menu_state));
screensize = screen_size * 2;
faces[0]
@@ -2386,11 +2423,22 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
state[statecount - 1].x,
faces);
}
- for (b = 0; b < mouse_button_count; b++)
+ else
+ /* We are busy-waiting for the mouse to move, so let's be nice
+ to other Windows applications by releasing our time slice. */
+ __dpmi_yield ();
+ for (b = 0; b < mouse_button_count && !leave; b++)
{
- (void) mouse_pressed (b, &x, &y);
- if (mouse_released (b, &x, &y))
- leave = 1;
+ /* Only leave if user both pressed and released the mouse, and in
+ that order. This avoids popping down the menu pane unless
+ the user is really done with it. */
+ if (mouse_pressed (b, &x, &y))
+ {
+ while (mouse_button_depressed (b, &x, &y))
+ __dpmi_yield ();
+ leave = 1;
+ }
+ (void) mouse_released (b, &x, &y);
}
}
@@ -2401,6 +2449,14 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
while (statecount--)
xfree (state[statecount].screen_behind);
IT_display_cursor (1); /* turn cursor back on */
+ /* Clean up any mouse events that are waiting inside Emacs event queue.
+ These events are likely to be generated before the menu was even
+ displayed, probably because the user pressed and released the button
+ (which invoked the menu) too quickly. If we don't remove these events,
+ Emacs will process them after we return and surprise the user. */
+ discard_mouse_events ();
+ /* Allow mouse events generation by dos_rawgetc. */
+ mouse_preempted--;
return result;
}