Bug 1493128 - Consider a single mouse type device queried by SetupDiEnumDeviceInterfaces on tablet or on system with a digitizer as COARSE type pointer device. r=masayuki

Unfortunately there is no realiable way to tell whether there is no mouse
connected or not.  So we are going to take a heuristic way here.  The way is
that;

1) Count mouse type devices with SetupDiEnumDeviceInterfaces [1]
2) If the count is 1 and if the system is used as tablet or has a touch device,
   the device should be COARSE

This way causes a misrecognition as if there is a mouse device in the case
where the touchscreen is disabled on the tablet even if there is no mouse
connected (i.e. the case where CountMouseDevices() returns 1 and the system
is on table mode).  We will try to fix the misrecognition in a later bug
(bug 1495938).

[1] https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdienumdeviceinterfaces

Differential Revision: https://phabricator.services.mozilla.com/D7565

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Hiroyuki Ikezoe 2018-10-04 07:23:57 +00:00
parent a4be0a2e71
commit 6f732cd3ed
3 changed files with 53 additions and 2 deletions

View File

@ -10,6 +10,7 @@
#include <dbt.h> #include <dbt.h>
#include <hidclass.h> #include <hidclass.h>
#include <ntddmou.h> #include <ntddmou.h>
#include <setupapi.h>
namespace mozilla { namespace mozilla {
namespace widget { namespace widget {
@ -37,5 +38,32 @@ InputDeviceUtils::UnregisterNotification(HDEVNOTIFY aHandle)
UnregisterDeviceNotification(aHandle); UnregisterDeviceNotification(aHandle);
} }
DWORD
InputDeviceUtils::CountMouseDevices()
{
HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVINTERFACE_MOUSE,
nullptr,
nullptr,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hdev == INVALID_HANDLE_VALUE) {
return 0;
}
DWORD count = 0;
SP_INTERFACE_DEVICE_DATA info = {};
info.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
while (SetupDiEnumDeviceInterfaces(hdev,
nullptr,
&GUID_DEVINTERFACE_MOUSE,
count,
&info)) {
if (info.Flags & SPINT_ACTIVE) {
count++;
}
}
SetupDiDestroyDeviceInfoList(hdev);
return count;
}
} // namespace widget } // namespace widget
} // namespace mozilla } // namespace mozilla

View File

@ -16,6 +16,9 @@ class InputDeviceUtils {
public: public:
static HDEVNOTIFY RegisterNotification(HWND aHwnd); static HDEVNOTIFY RegisterNotification(HWND aHwnd);
static void UnregisterNotification(HDEVNOTIFY aHandle); static void UnregisterNotification(HDEVNOTIFY aHandle);
// Returns the number of mouse type devices connected to this system.
static DWORD CountMouseDevices();
}; };
} // namespace widget } // namespace widget

View File

@ -13,6 +13,7 @@
#include "gfxUtils.h" #include "gfxUtils.h"
#include "nsWindow.h" #include "nsWindow.h"
#include "nsWindowDefs.h" #include "nsWindowDefs.h"
#include "InputDeviceUtils.h"
#include "KeyboardLayout.h" #include "KeyboardLayout.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/BackgroundHangMonitor.h" #include "mozilla/BackgroundHangMonitor.h"
@ -1900,7 +1901,26 @@ IsTabletDevice()
static bool static bool
IsMousePresent() IsMousePresent()
{ {
return ::GetSystemMetrics(SM_MOUSEPRESENT); if (!::GetSystemMetrics(SM_MOUSEPRESENT)) {
return false;
}
DWORD count = InputDeviceUtils::CountMouseDevices();
if (!count) {
return false;
}
// If there is a mouse device and if this machine is a tablet or has a
// digitizer, that's counted as the mouse device.
// FIXME: Bug 1495938: We should drop this heuristic way once we find out a
// reliable way to tell there is no mouse or not.
if (count == 1 &&
(WinUtils::IsTouchDeviceSupportPresent() ||
IsTabletDevice())) {
return false;
}
return true;
} }
/* static */ /* static */
@ -1912,7 +1932,7 @@ WinUtils::GetPrimaryPointerCapabilities()
} }
if (IsMousePresent()) { if (IsMousePresent()) {
return PointerCapabilities::Fine| return PointerCapabilities::Fine |
PointerCapabilities::Hover; PointerCapabilities::Hover;
} }