aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii1998-10-20 14:25:38 +0000
committerEli Zaretskii1998-10-20 14:25:38 +0000
commit0c7bc1aabdf734481c244925b6c4de65b8fea4eb (patch)
tree678ab8872d4586de6bc1b52e5d67f859fd6476e9 /src
parent32372ef84c272010ae644eb5f6e63ac5bae23b18 (diff)
downloademacs-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.
Diffstat (limited to 'src')
-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)
214 return (regs.x.bx != 0); 214 return (regs.x.bx != 0);
215} 215}
216 216
217static int
218mouse_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, &regs, &regs);
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
217void 236void
218mouse_get_pos (f, insist, bar_window, part, x, y, time) 237mouse_get_pos (f, insist, bar_window, part, x, y, time)
219 FRAME_PTR *f; 238 FRAME_PTR *f;
@@ -252,6 +271,7 @@ void
252mouse_init () 271mouse_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, &regs, &regs); 280 int86 (0x33, &regs, &regs);
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
1693extern void kbd_buffer_store_event (struct input_event *); 1725extern void kbd_buffer_store_event (struct input_event *);
1726static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
1694 1727
1695static int 1728static int
1696dos_rawgetc () 1729dos_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