Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/fhandler.h11
-rw-r--r--winsup/cygwin/fhandler_console.cc249
-rw-r--r--winsup/cygwin/select.cc6
4 files changed, 194 insertions, 92 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index d5fb16ba6..8fbe012c8 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,23 @@
+2009-12-16 Thomas Wolff <towo@towo.net>
+
+ * fhandler_console.cc (read): Detect and handle mouse wheel scrolling
+ events (for completion of mouse reporting mode 1000) and mouse
+ movement events (for additional mouse reporting modes 1002 and 1003).
+ Use mouse_aware() as a guard and only condition for mouse
+ reporting in order to enforce consistence of read() and select().
+ Add focus reports (for additional focus reporting mode 1004).
+ (mouse_aware): Enable detection of additional mouse events for select().
+ Tune function to precisely match actual reporting criteria.
+ Move adjustment of mouse position (by window scroll offset)
+ here to avoid duplicate code.
+ (char_command): Initialization of enhanced mouse reporting modes.
+ Initialization of focus reporting mode.
+ * fhandler.h (use_mouse): Change flag (bool->int) to indicate
+ additional mouse modes. Add flag to indicate focus reporting.
+ (mouse_aware): Move enhanced function into fhandler_console.cc.
+ * select.cc (peek_console): Use modified mouse_aware() for more
+ general detection of mouse events. Also check for focus reports.
+
2009-12-16 Corinna Vinschen <corinna@vinschen.de>
* registry.cc (cygnus_class): Remove.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 275509227..7da3aa618 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -936,11 +936,15 @@ class dev_console
} info;
COORD dwLastCursorPosition;
- DWORD dwLastButtonState;
+ COORD dwMousePosition; /* scroll-adjusted coord of mouse event */
+ COORD dwLastMousePosition; /* scroll-adjusted coord of previous mouse event */
+ DWORD dwLastButtonState; /* (not noting mouse wheel events) */
+ int last_button_code; /* transformed mouse report button code */
int nModifiers;
bool insert_mode;
- bool use_mouse;
+ int use_mouse;
+ bool use_focus;
bool raw_win32_keyboard_mode;
inline UINT get_console_cp ();
@@ -1012,7 +1016,8 @@ class fhandler_console: public fhandler_termios
int ioctl (unsigned int cmd, void *);
int init (HANDLE, DWORD, mode_t);
- bool mouse_aware () {return dev_state->use_mouse;}
+ bool mouse_aware (MOUSE_EVENT_RECORD& mouse_event);
+ bool focus_aware () {return dev_state->use_focus;}
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index d2dab95c0..1e08e2c60 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -100,6 +100,10 @@ fhandler_console::get_tty_stuff (int flags = 0)
dev_state->scroll_region.Bottom = -1;
dev_state->dwLastCursorPosition.X = -1;
dev_state->dwLastCursorPosition.Y = -1;
+ dev_state->dwLastMousePosition.X = -1;
+ dev_state->dwLastMousePosition.Y = -1;
+ dev_state->dwLastButtonState = 0; /* none pressed */
+ dev_state->last_button_code = 3; /* released */
dev_state->underline_color = FOREGROUND_GREEN | FOREGROUND_BLUE;
dev_state->dim_color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
dev_state->meta_mask = LEFT_ALT_PRESSED;
@@ -206,6 +210,45 @@ fhandler_console::send_winch_maybe ()
}
}
+/* Check whether a mouse event is to be reported as an escape sequence */
+bool
+fhandler_console::mouse_aware (MOUSE_EVENT_RECORD& mouse_event)
+{
+ if (! dev_state->use_mouse)
+ return 0;
+
+ /* Adjust mouse position by window scroll buffer offset
+ and remember adjusted position in state for use by read() */
+ CONSOLE_SCREEN_BUFFER_INFO now;
+ if (GetConsoleScreenBufferInfo (get_output_handle (), &now))
+ {
+ dev_state->dwMousePosition.X = mouse_event.dwMousePosition.X - now.srWindow.Left;
+ dev_state->dwMousePosition.Y = mouse_event.dwMousePosition.Y - now.srWindow.Top;
+ }
+ else
+ {
+ /* Cannot adjust position by window scroll buffer offset */
+ return 0;
+ }
+
+ /* Check whether adjusted mouse position can be reported */
+ if (dev_state->dwMousePosition.X > 0xFF - ' ' - 1
+ || dev_state->dwMousePosition.Y > 0xFF - ' ' - 1)
+ {
+ /* Mouse position out of reporting range */
+ return 0;
+ }
+
+ return ((mouse_event.dwEventFlags == 0 || mouse_event.dwEventFlags == DOUBLE_CLICK)
+ && mouse_event.dwButtonState != dev_state->dwLastButtonState)
+ || mouse_event.dwEventFlags == MOUSE_WHEELED
+ || (mouse_event.dwEventFlags == MOUSE_MOVED
+ && (dev_state->dwMousePosition.X != dev_state->dwLastMousePosition.X
+ || dev_state->dwMousePosition.Y != dev_state->dwLastMousePosition.Y)
+ && ((dev_state->use_mouse >= 2 && mouse_event.dwButtonState)
+ || dev_state->use_mouse >= 3));
+}
+
void __stdcall
fhandler_console::read (void *pv, size_t& buflen)
{
@@ -401,106 +444,125 @@ fhandler_console::read (void *pv, size_t& buflen)
case MOUSE_EVENT:
send_winch_maybe ();
- if (dev_state->use_mouse)
- {
- MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent;
-
- /* Treat the double-click event like a regular button press */
- if (mouse_event.dwEventFlags == DOUBLE_CLICK)
- {
- syscall_printf ("mouse: double-click -> click");
- mouse_event.dwEventFlags = 0;
- }
+ {
+ MOUSE_EVENT_RECORD& mouse_event = input_rec.Event.MouseEvent;
+ /* As a unique guard for mouse report generation,
+ call mouse_aware() which is common with select(), so the result
+ of select() and the actual read() will be consistent on the
+ issue of whether input (i.e. a mouse escape sequence) will
+ be available or not */
+ if (mouse_aware (mouse_event))
+ {
+ /* Note: Reported mouse position was already retrieved by
+ mouse_aware() and adjusted by window scroll buffer offset */
- /* Did something other than a click occur? */
- if (mouse_event.dwEventFlags)
- continue;
+ /* Treat the double-click event like a regular button press */
+ if (mouse_event.dwEventFlags == DOUBLE_CLICK)
+ {
+ syscall_printf ("mouse: double-click -> click");
+ mouse_event.dwEventFlags = 0;
+ }
- /* Retrieve reported mouse position */
- int x = mouse_event.dwMousePosition.X;
- int y = mouse_event.dwMousePosition.Y;
+ /* This code assumes Windows never reports multiple button
+ events at the same time. */
+ int b = 0;
+ char sz[32];
- /* Adjust mouse position by scroll buffer offset */
- CONSOLE_SCREEN_BUFFER_INFO now;
- if (GetConsoleScreenBufferInfo (get_output_handle (), &now))
- {
- y -= now.srWindow.Top;
- x -= now.srWindow.Left;
- }
- else
- {
- syscall_printf ("mouse: cannot adjust position by scroll buffer offset");
- continue;
- }
+ if (mouse_event.dwEventFlags == MOUSE_WHEELED)
+ {
+ if (mouse_event.dwButtonState & 0xFF800000)
+ {
+ b = 0x41;
+ strcpy (sz, "wheel down");
+ }
+ else
+ {
+ b = 0x40;
+ strcpy (sz, "wheel up");
+ }
+ }
+ else
+ {
+ /* Ignore unimportant mouse buttons */
+ mouse_event.dwButtonState &= 0x7;
- /* If the mouse event occurred out of the area we can handle,
- ignore it. */
- if ((x + ' ' + 1 > 0xFF) || (y + ' ' + 1 > 0xFF))
- {
- syscall_printf ("mouse: position out of range");
- continue;
- }
+ if (mouse_event.dwEventFlags == MOUSE_MOVED)
+ {
+ b = dev_state->last_button_code;
+ }
+ else if (mouse_event.dwButtonState < dev_state->dwLastButtonState)
+ {
+ b = 3;
+ strcpy (sz, "btn up");
+ }
+ else if ((mouse_event.dwButtonState & 1) != (dev_state->dwLastButtonState & 1))
+ {
+ b = 0;
+ strcpy (sz, "btn1 down");
+ }
+ else if ((mouse_event.dwButtonState & 2) != (dev_state->dwLastButtonState & 2))
+ {
+ b = 2;
+ strcpy (sz, "btn2 down");
+ }
+ else if ((mouse_event.dwButtonState & 4) != (dev_state->dwLastButtonState & 4))
+ {
+ b = 1;
+ strcpy (sz, "btn3 down");
+ }
- /* Ignore unimportant mouse buttons */
- mouse_event.dwButtonState &= 0x7;
+ dev_state->last_button_code = b;
- /* This code assumes Windows never reports multiple button
- events at the same time. */
- int b = 0;
- char sz[32];
- if (mouse_event.dwButtonState == dev_state->dwLastButtonState)
- {
- syscall_printf ("mouse: button state unchanged");
- continue;
- }
- else if (mouse_event.dwButtonState < dev_state->dwLastButtonState)
- {
- b = 3;
- strcpy (sz, "btn up");
- }
- else if ((mouse_event.dwButtonState & 1) != (dev_state->dwLastButtonState & 1))
- {
- b = 0;
- strcpy (sz, "btn1 down");
- }
- else if ((mouse_event.dwButtonState & 2) != (dev_state->dwLastButtonState & 2))
- {
- b = 2;
- strcpy (sz, "btn2 down");
- }
- else if ((mouse_event.dwButtonState & 4) != (dev_state->dwLastButtonState & 4))
- {
- b = 1;
- strcpy (sz, "btn3 down");
- }
+ if (mouse_event.dwEventFlags == MOUSE_MOVED)
+ {
+ b += 32;
+ strcpy (sz, "move");
+ }
+ else
+ {
+ /* Remember the modified button state */
+ dev_state->dwLastButtonState = mouse_event.dwButtonState;
+ }
+ }
- /* Remember the current button state */
- dev_state->dwLastButtonState = mouse_event.dwButtonState;
+ /* Remember mouse position */
+ dev_state->dwLastMousePosition.X = dev_state->dwMousePosition.X;
+ dev_state->dwLastMousePosition.Y = dev_state->dwMousePosition.Y;
- /* If a button was pressed, remember the modifiers */
- if (b != 3)
- {
- dev_state->nModifiers = 0;
- if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
+ /* Remember the modifiers */
+ dev_state->nModifiers = 0;
+ if (mouse_event.dwControlKeyState & SHIFT_PRESSED)
dev_state->nModifiers |= 0x4;
- if (mouse_event.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
+ if (mouse_event.dwControlKeyState & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
dev_state->nModifiers |= 0x8;
- if (mouse_event.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
+ if (mouse_event.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
dev_state->nModifiers |= 0x10;
- }
- b |= dev_state->nModifiers;
+ /* Indicate the modifiers */
+ b |= dev_state->nModifiers;
- /* We can now create the code. */
- sprintf (tmp, "\033[M%c%c%c", b + ' ', x + ' ' + 1, y + ' ' + 1);
- syscall_printf ("mouse: %s at (%d,%d)", sz, x, y);
+ /* We can now create the code. */
+ sprintf (tmp, "\033[M%c%c%c", b + ' ', dev_state->dwMousePosition.X + ' ' + 1, dev_state->dwMousePosition.Y + ' ' + 1);
+ syscall_printf ("mouse: %s at (%d,%d)", sz, dev_state->dwMousePosition.X, dev_state->dwMousePosition.Y);
- toadd = tmp;
- nread = 6;
- }
+ toadd = tmp;
+ nread = 6;
+ }
+ }
break;
case FOCUS_EVENT:
+ if (dev_state->use_focus) {
+ if (input_rec.Event.FocusEvent.bSetFocus)
+ sprintf (tmp, "\033[I");
+ else
+ sprintf (tmp, "\033[O");
+
+ toadd = tmp;
+ nread = 3;
+ }
+ break;
+
case WINDOW_BUFFER_SIZE_EVENT:
send_winch_maybe ();
/* fall through */
@@ -1282,9 +1344,24 @@ fhandler_console::char_command (char c)
}
break;
- case 1000: /* Mouse support */
- dev_state->use_mouse = (c == 'h') ? true : false;
- syscall_printf ("mouse support %sabled", dev_state->use_mouse ? "en" : "dis");
+ case 1000: /* Mouse tracking */
+ dev_state->use_mouse = (c == 'h') ? 1 : 0;
+ syscall_printf ("mouse support set to mode %d", dev_state->use_mouse);
+ break;
+
+ case 1002: /* Mouse button event tracking */
+ dev_state->use_mouse = (c == 'h') ? 2 : 0;
+ syscall_printf ("mouse support set to mode %d", dev_state->use_mouse);
+ break;
+
+ case 1003: /* Mouse any event tracking */
+ dev_state->use_mouse = (c == 'h') ? 3 : 0;
+ syscall_printf ("mouse support set to mode %d", dev_state->use_mouse);
+ break;
+
+ case 1004: /* Focus in/out event reporting */
+ dev_state->use_focus = (c == 'h') ? true : false;
+ syscall_printf ("focus reporting set to %d", dev_state->use_focus);
break;
case 2000: /* Raw keyboard mode */
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index cb58445c9..1cd18e720 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -823,9 +823,9 @@ peek_console (select_record *me, bool)
else
{
if (irec.EventType == MOUSE_EVENT
- && fh->mouse_aware ()
- && (irec.Event.MouseEvent.dwEventFlags == 0
- || irec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK))
+ && fh->mouse_aware (irec.Event.MouseEvent))
+ return me->read_ready = true;
+ if (irec.EventType == FOCUS_EVENT && fh->focus_aware ())
return me->read_ready = true;
}