[NTVDM]: Implement mouse capture. There are still "bugs" remaining, namely, if somebody moves the NTVDM console window, or, if resolution changes, the mouse clip rectangle is not recomputed. This is left as an exercice for the programmer (or, if I don't find patches in Jira soon, I or somebody else will fix it).

svn path=/trunk/; revision=69843
This commit is contained in:
Hermès Bélusca-Maïto 2015-11-07 23:40:26 +00:00
parent 29d481611e
commit 45a54c5b12
13 changed files with 89 additions and 64 deletions

View file

@ -20,7 +20,7 @@ static DWORD OrgConsoleInputMode, OrgConsoleOutputMode;
HWND hConsoleWnd = NULL; HWND hConsoleWnd = NULL;
static HMENU hConsoleMenu = NULL; static HMENU hConsoleMenu = NULL;
static INT VdmMenuPos = -1; static INT VdmMenuPos = -1;
static BOOLEAN ShowPointer = TRUE; static BOOL CaptureMouse = FALSE;
/* /*
* Those menu helpers were taken from the GUI frontend in winsrv.dll * Those menu helpers were taken from the GUI frontend in winsrv.dll
@ -48,7 +48,7 @@ static const VDM_MENUITEM VdmMenuItems[] =
static const VDM_MENUITEM VdmMainMenuItems[] = static const VDM_MENUITEM VdmMainMenuItems[] =
{ {
{ -1, NULL, 0 }, /* Separator */ { -1, NULL, 0 }, /* Separator */
{ IDS_HIDE_MOUSE, NULL, ID_SHOWHIDE_MOUSE }, /* "Hide mouse"; can be renamed to "Show mouse" */ { IDS_CAPTURE_MOUSE, NULL, ID_CAPTURE_MOUSE }, /* "Capture mouse"; can be renamed to "Release mouse" */
{ IDS_VDM_MENU , VdmMenuItems, 0 }, /* ReactOS VDM Menu */ { IDS_VDM_MENU , VdmMenuItems, 0 }, /* ReactOS VDM Menu */
{ 0, NULL, 0 } /* End of list */ { 0, NULL, 0 } /* End of list */
@ -116,7 +116,7 @@ VdmMenuExists(HMENU hConsoleMenu)
/* Check for the presence of one of the VDM menu items */ /* Check for the presence of one of the VDM menu items */
for (i = 0; i <= MenuPos; i++) for (i = 0; i <= MenuPos; i++)
{ {
if (GetMenuItemID(hConsoleMenu, i) == ID_SHOWHIDE_MOUSE) if (GetMenuItemID(hConsoleMenu, i) == ID_CAPTURE_MOUSE)
{ {
/* Set VdmMenuPos to the position of the existing menu */ /* Set VdmMenuPos to the position of the existing menu */
VdmMenuPos = i - 1; VdmMenuPos = i - 1;
@ -131,14 +131,14 @@ UpdateVdmMenuMouse(VOID)
{ {
WCHAR szMenuString[256]; WCHAR szMenuString[256];
/* Update "Hide/Show mouse" menu item */ /* Update "Capture/Release mouse" menu item */
if (LoadStringW(GetModuleHandle(NULL), if (LoadStringW(GetModuleHandle(NULL),
(!ShowPointer ? IDS_SHOW_MOUSE : IDS_HIDE_MOUSE), (CaptureMouse ? IDS_RELEASE_MOUSE : IDS_CAPTURE_MOUSE),
szMenuString, szMenuString,
ARRAYSIZE(szMenuString)) > 0) ARRAYSIZE(szMenuString)) > 0)
{ {
ModifyMenuW(hConsoleMenu, ID_SHOWHIDE_MOUSE, ModifyMenuW(hConsoleMenu, ID_CAPTURE_MOUSE,
MF_BYCOMMAND, ID_SHOWHIDE_MOUSE, szMenuString); MF_BYCOMMAND, ID_CAPTURE_MOUSE, szMenuString);
} }
} }
@ -210,7 +210,7 @@ CreateVdmMenu(HANDLE ConOutHandle)
WCHAR szMenuString1[256], szMenuString2[256]; WCHAR szMenuString1[256], szMenuString2[256];
hConsoleMenu = ConsoleMenuControl(ConOutHandle, hConsoleMenu = ConsoleMenuControl(ConOutHandle,
ID_SHOWHIDE_MOUSE, ID_CAPTURE_MOUSE,
ID_VDM_DRIVES + (2 * ARRAYSIZE(GlobalSettings.FloppyDisks))); ID_VDM_DRIVES + (2 * ARRAYSIZE(GlobalSettings.FloppyDisks)));
if (hConsoleMenu == NULL) return; if (hConsoleMenu == NULL) return;
@ -285,17 +285,33 @@ DestroyVdmMenu(VOID)
DrawMenuBar(hConsoleWnd); DrawMenuBar(hConsoleWnd);
} }
static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr) static VOID CaptureMousePointer(HANDLE ConOutHandle, BOOLEAN Capture)
{ {
if (ShowPtr) static BOOL IsClipped = FALSE; // For debugging purposes
UNREFERENCED_PARAMETER(IsClipped);
if (Capture)
{ {
/* Be sure the cursor will be shown */ RECT rcClip;
while (ShowConsoleCursor(ConOutHandle, TRUE) < 0) ;
// if (IsClipped) return;
/* Be sure the cursor will be hidden */
while (ShowConsoleCursor(ConOutHandle, FALSE) >= 0) ;
GetClientRect(hConsoleWnd, &rcClip);
MapWindowPoints(hConsoleWnd, HWND_DESKTOP /*NULL*/, (LPPOINT)&rcClip, 2 /* Magic value when the LPPOINT parameter is a RECT */);
IsClipped = ClipCursor(&rcClip);
} }
else else
{ {
/* Be sure the cursor will be hidden */ // if (!IsClipped) return;
while (ShowConsoleCursor(ConOutHandle, FALSE) >= 0) ;
ClipCursor(NULL);
IsClipped = FALSE;
/* Be sure the cursor will be shown */
while (ShowConsoleCursor(ConOutHandle, TRUE) < 0) ;
} }
} }
@ -373,7 +389,7 @@ static VOID
ConsoleCleanupUI(VOID) ConsoleCleanupUI(VOID)
{ {
/* Display again properly the mouse pointer */ /* Display again properly the mouse pointer */
if (ShowPointer) ShowHideMousePointer(ConsoleOutput, ShowPointer); if (CaptureMouse) CaptureMousePointer(ConsoleOutput, !CaptureMouse);
DestroyVdmMenu(); DestroyVdmMenu();
} }
@ -423,7 +439,7 @@ ConsoleReattach(HANDLE ConOutHandle)
CreateVdmMenu(ConOutHandle); CreateVdmMenu(ConOutHandle);
/* Synchronize mouse cursor display with console screenbuffer switches */ /* Synchronize mouse cursor display with console screenbuffer switches */
ShowHideMousePointer(CurrentConsoleOutput, ShowPointer); CaptureMousePointer(CurrentConsoleOutput, CaptureMouse);
} }
static BOOL static BOOL
@ -493,21 +509,25 @@ VOID MenuEventHandler(PMENU_EVENT_RECORD MenuEvent)
*/ */
case WM_INITMENU: case WM_INITMENU:
DPRINT1("WM_INITMENU\n");
break;
case WM_MENUSELECT: case WM_MENUSELECT:
DPRINT1("WM_MENUSELECT\n"); {
/*
* If the mouse is captured, release it or recapture it
* when the menu opens or closes, respectively.
*/
if (!CaptureMouse) break;
CaptureMousePointer(CurrentConsoleOutput, MenuEvent->dwCommandId == WM_INITMENU ? FALSE : TRUE);
break; break;
}
/* /*
* User-defined menu commands * User-defined menu commands
*/ */
case ID_SHOWHIDE_MOUSE: case ID_CAPTURE_MOUSE:
ShowPointer = !ShowPointer; CaptureMouse = !CaptureMouse;
ShowHideMousePointer(CurrentConsoleOutput, ShowPointer); CaptureMousePointer(CurrentConsoleOutput, CaptureMouse);
UpdateVdmMenuMouse(); UpdateVdmMenuMouse();
break; break;
@ -555,5 +575,10 @@ VOID MenuEventHandler(PMENU_EVENT_RECORD MenuEvent)
VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent) VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent)
{ {
DPRINT1("Focus events not handled\n"); /*
* If the mouse is captured, release it or recapture it
* when we lose or regain focus, respectively.
*/
if (!CaptureMouse) return;
CaptureMousePointer(CurrentConsoleOutput, FocusEvent->bSetFocus);
} }

View file

@ -8,8 +8,8 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Skrýt ukazatel myši" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Zobrazit ukazatel myši" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -2,9 +2,9 @@ LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "Mauszeiger &verstecken" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "Mauszeiger &anzeigen" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "&ReactOS VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END
STRINGTABLE STRINGTABLE

View file

@ -2,8 +2,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Hide Mouse Pointer" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Display Mouse Pointer" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -2,8 +2,8 @@ LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Ocultar puntero del ratón" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Mostrar puntero del ratón" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -2,8 +2,8 @@ LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "Mas&quer le pointeur de la souris" IDS_CAPTURE_MOUSE, "&Capturer le pointeur de la souris"
IDS_SHOW_MOUSE, "&Afficher le pointeur de la souris" IDS_RELEASE_MOUSE, "&Libérer le pointeur de la souris"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -2,8 +2,8 @@ LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Nascondi il mouse" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Mostra il mouse" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -4,8 +4,8 @@ LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Ukryj Wskaźnik Myszki" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Pokaż Wskaźnik Myszki" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -3,8 +3,8 @@ LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "Asc&unde indicatorul șoricelului" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "Afișea&ză indicatorul șoricelului" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -2,8 +2,8 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Спрятать указатель мыши" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "&Отобразить указатель мыши" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS &VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END

View file

@ -4,9 +4,9 @@ LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "&Fâre İmlecini Gizle" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "Fâre &İmlecini Göster" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "&ReactOS VDM" IDS_VDM_MENU , "ReactOS &VDM"
END END
STRINGTABLE STRINGTABLE

View file

@ -4,8 +4,8 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
STRINGTABLE STRINGTABLE
BEGIN BEGIN
IDS_HIDE_MOUSE, "隐藏鼠标指针 (&H)" IDS_CAPTURE_MOUSE, "&Capture Mouse Pointer"
IDS_SHOW_MOUSE, "显示鼠标指针 (&D)" IDS_RELEASE_MOUSE, "&Release Mouse Pointer"
IDS_VDM_MENU , "ReactOS DOS 虚拟机 (&V)" IDS_VDM_MENU , "ReactOS DOS 虚拟机 (&V)"
END END

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
/* Menu IDs */ /* Menu IDs */
#define ID_SHOWHIDE_MOUSE 1000 #define ID_CAPTURE_MOUSE 1000
#define ID_VDM_DUMPMEM_TXT 1001 #define ID_VDM_DUMPMEM_TXT 1001
#define ID_VDM_DUMPMEM_BIN 1002 #define ID_VDM_DUMPMEM_BIN 1002
#define ID_VDM_QUIT 1003 #define ID_VDM_QUIT 1003
@ -10,8 +10,8 @@
#define ID_VDM_DRIVES 1010 #define ID_VDM_DRIVES 1010
/* String IDs */ /* String IDs */
#define IDS_HIDE_MOUSE 100 #define IDS_CAPTURE_MOUSE 100
#define IDS_SHOW_MOUSE 101 #define IDS_RELEASE_MOUSE 101
#define IDS_VDM_MENU 102 #define IDS_VDM_MENU 102
#define IDS_VDM_DUMPMEM_TXT 200 #define IDS_VDM_DUMPMEM_TXT 200