diff options
| author | Eli Zaretskii | 1998-10-20 14:25:38 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 1998-10-20 14:25:38 +0000 |
| commit | 0c7bc1aabdf734481c244925b6c4de65b8fea4eb (patch) | |
| tree | 678ab8872d4586de6bc1b52e5d67f859fd6476e9 | |
| parent | 32372ef84c272010ae644eb5f6e63ac5bae23b18 (diff) | |
| download | emacs-0c7bc1aabdf734481c244925b6c4de65b8fea4eb.tar.gz emacs-0c7bc1aabdf734481c244925b6c4de65b8fea4eb.zip | |
(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.
| -rw-r--r-- | src/msdos.c | 66 |
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) | |||
| 214 | return (regs.x.bx != 0); | 214 | return (regs.x.bx != 0); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static int | ||
| 218 | mouse_button_depressed (b, xp, yp) | ||
| 219 | int b, *xp, *yp; | ||
| 220 | { | ||
| 221 | union REGS regs; | ||
| 222 | |||
| 223 | if (b >= mouse_button_count) | ||
| 224 | return 0; | ||
| 225 | regs.x.ax = 0x0003; | ||
| 226 | int86 (0x33, ®s, ®s); | ||
| 227 | if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0) | ||
| 228 | { | ||
| 229 | *xp = regs.x.cx / 8; | ||
| 230 | *yp = regs.x.dx / 8; | ||
| 231 | return 1; | ||
| 232 | } | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 217 | void | 236 | void |
| 218 | mouse_get_pos (f, insist, bar_window, part, x, y, time) | 237 | mouse_get_pos (f, insist, bar_window, part, x, y, time) |
| 219 | FRAME_PTR *f; | 238 | FRAME_PTR *f; |
| @@ -252,6 +271,7 @@ void | |||
| 252 | mouse_init () | 271 | mouse_init () |
| 253 | { | 272 | { |
| 254 | union REGS regs; | 273 | union REGS regs; |
| 274 | int b; | ||
| 255 | 275 | ||
| 256 | if (termscript) | 276 | if (termscript) |
| 257 | fprintf (termscript, "<M_INIT>"); | 277 | fprintf (termscript, "<M_INIT>"); |
| @@ -259,6 +279,18 @@ mouse_init () | |||
| 259 | regs.x.ax = 0x0021; | 279 | regs.x.ax = 0x0021; |
| 260 | int86 (0x33, ®s, ®s); | 280 | int86 (0x33, ®s, ®s); |
| 261 | 281 | ||
| 282 | /* Reset the mouse last press/release info. It seems that Windows | ||
| 283 | doesn't do that automatically when function 21h is called, which | ||
| 284 | causes Emacs to ``remember'' the click that switched focus to the | ||
| 285 | window just before Emacs was started from that window. */ | ||
| 286 | for (b = 0; b < mouse_button_count; b++) | ||
| 287 | { | ||
| 288 | int dummy_x, dummy_y; | ||
| 289 | |||
| 290 | (void) mouse_pressed (b, &dummy_x, &dummy_y); | ||
| 291 | (void) mouse_released (b, &dummy_x, &dummy_y); | ||
| 292 | } | ||
| 293 | |||
| 262 | regs.x.ax = 0x0007; | 294 | regs.x.ax = 0x0007; |
| 263 | regs.x.cx = 0; | 295 | regs.x.cx = 0; |
| 264 | regs.x.dx = 8 * (ScreenCols () - 1); | 296 | regs.x.dx = 8 * (ScreenCols () - 1); |
| @@ -1691,6 +1723,7 @@ and then the scan code.") | |||
| 1691 | /* Get a char from keyboard. Function keys are put into the event queue. */ | 1723 | /* Get a char from keyboard. Function keys are put into the event queue. */ |
| 1692 | 1724 | ||
| 1693 | extern void kbd_buffer_store_event (struct input_event *); | 1725 | extern void kbd_buffer_store_event (struct input_event *); |
| 1726 | static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */ | ||
| 1694 | 1727 | ||
| 1695 | static int | 1728 | static int |
| 1696 | dos_rawgetc () | 1729 | dos_rawgetc () |
| @@ -1898,7 +1931,7 @@ dos_rawgetc () | |||
| 1898 | kbd_buffer_store_event (&event); | 1931 | kbd_buffer_store_event (&event); |
| 1899 | } | 1932 | } |
| 1900 | 1933 | ||
| 1901 | if (have_mouse > 0) | 1934 | if (have_mouse > 0 && !mouse_preempted) |
| 1902 | { | 1935 | { |
| 1903 | int but, press, x, y, ok; | 1936 | int but, press, x, y, ok; |
| 1904 | 1937 | ||
| @@ -2264,6 +2297,10 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 2264 | if (y0 <= 0) | 2297 | if (y0 <= 0) |
| 2265 | y0 = 1; | 2298 | y0 = 1; |
| 2266 | 2299 | ||
| 2300 | /* We will process all the mouse events directly, so we had | ||
| 2301 | better prevented dos_rawgetc from stealing them from us. */ | ||
| 2302 | mouse_preempted++; | ||
| 2303 | |||
| 2267 | state = alloca (menu->panecount * sizeof (struct IT_menu_state)); | 2304 | state = alloca (menu->panecount * sizeof (struct IT_menu_state)); |
| 2268 | screensize = screen_size * 2; | 2305 | screensize = screen_size * 2; |
| 2269 | faces[0] | 2306 | faces[0] |
| @@ -2386,11 +2423,22 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 2386 | state[statecount - 1].x, | 2423 | state[statecount - 1].x, |
| 2387 | faces); | 2424 | faces); |
| 2388 | } | 2425 | } |
| 2389 | for (b = 0; b < mouse_button_count; b++) | 2426 | else |
| 2427 | /* We are busy-waiting for the mouse to move, so let's be nice | ||
| 2428 | to other Windows applications by releasing our time slice. */ | ||
| 2429 | __dpmi_yield (); | ||
| 2430 | for (b = 0; b < mouse_button_count && !leave; b++) | ||
| 2390 | { | 2431 | { |
| 2391 | (void) mouse_pressed (b, &x, &y); | 2432 | /* Only leave if user both pressed and released the mouse, and in |
| 2392 | if (mouse_released (b, &x, &y)) | 2433 | that order. This avoids popping down the menu pane unless |
| 2393 | leave = 1; | 2434 | the user is really done with it. */ |
| 2435 | if (mouse_pressed (b, &x, &y)) | ||
| 2436 | { | ||
| 2437 | while (mouse_button_depressed (b, &x, &y)) | ||
| 2438 | __dpmi_yield (); | ||
| 2439 | leave = 1; | ||
| 2440 | } | ||
| 2441 | (void) mouse_released (b, &x, &y); | ||
| 2394 | } | 2442 | } |
| 2395 | } | 2443 | } |
| 2396 | 2444 | ||
| @@ -2401,6 +2449,14 @@ XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx, | |||
| 2401 | while (statecount--) | 2449 | while (statecount--) |
| 2402 | xfree (state[statecount].screen_behind); | 2450 | xfree (state[statecount].screen_behind); |
| 2403 | IT_display_cursor (1); /* turn cursor back on */ | 2451 | IT_display_cursor (1); /* turn cursor back on */ |
| 2452 | /* Clean up any mouse events that are waiting inside Emacs event queue. | ||
| 2453 | These events are likely to be generated before the menu was even | ||
| 2454 | displayed, probably because the user pressed and released the button | ||
| 2455 | (which invoked the menu) too quickly. If we don't remove these events, | ||
| 2456 | Emacs will process them after we return and surprise the user. */ | ||
| 2457 | discard_mouse_events (); | ||
| 2458 | /* Allow mouse events generation by dos_rawgetc. */ | ||
| 2459 | mouse_preempted--; | ||
| 2404 | return result; | 2460 | return result; |
| 2405 | } | 2461 | } |
| 2406 | 2462 | ||