1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/base/pointer/pointer_device.h"
#include <algorithm>
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/win/win_util.h"
#include "ui/base/win/hidden_window.h"
namespace ui {
namespace {
bool IsTouchDevicePresent() {
int value = GetSystemMetrics(SM_DIGITIZER);
return (value & NID_READY) &&
((value & NID_INTEGRATED_TOUCH) || (value & NID_EXTERNAL_TOUCH));
}
PointerDigitizerType ToPointerDigitizerType(
POINTER_DEVICE_TYPE pointer_device_type) {
switch (pointer_device_type) {
case POINTER_DEVICE_TYPE_INTEGRATED_PEN:
return PointerDigitizerType::kDirectPen;
case POINTER_DEVICE_TYPE_EXTERNAL_PEN:
return PointerDigitizerType::kIndirectPen;
case POINTER_DEVICE_TYPE_TOUCH:
return PointerDigitizerType::kTouch;
case POINTER_DEVICE_TYPE_TOUCH_PAD:
return PointerDigitizerType::kTouchPad;
default:
return PointerDigitizerType::kUnknown;
}
}
PointerDevice ToPointerDevice(const POINTER_DEVICE_INFO& device) {
return {.key = device.device,
.digitizer = ToPointerDigitizerType(device.pointerDeviceType),
.max_active_contacts = device.maxActiveContacts};
}
} // namespace
// The following method logic is as follow :
// - On versions prior to Windows 8 it will always return POINTER_TYPE_FINE
// and/or POINTER_TYPE_COARSE (if the device has a touch screen).
// - If the device is a detachable/convertible device and the keyboard/trackpad
// is detached/flipped it will always return POINTER_TYPE_COARSE.
// It does not cover the case where an external mouse/keyboard is connected
// while the device is used as a tablet. This is because Windows doesn't provide
// us a reliable way to detect keyboard/mouse presence with
// GetSystemMetrics(SM_MOUSEPRESENT).
// - If the device doesn't have a touch screen it will return POINTER_TYPE_FINE.
// In the rare cases (this is Microsoft documentation) where
// GetSystemMetrics(SM_MOUSEPRESENT) returns 0 we will return POINTER_TYPE_NONE.
// - If the device has a touch screen the available pointer devices are
// POINTER_TYPE_FINE and POINTER_TYPE_COARSE.
int GetAvailablePointerTypes() {
// IsTabletDevice guarantees us that :
// - The device has a touch screen.
// - It is used as a tablet which means that it has no keyboard connected.
// On Windows 10 it means that it is verifying with ConvertibleSlateMode.
if (base::win::IsDeviceUsedAsATablet(nullptr))
return POINTER_TYPE_COARSE;
bool is_touch_device_present = IsTouchDevicePresent();
if (GetSystemMetrics(SM_MOUSEPRESENT) == 0 && !is_touch_device_present)
return POINTER_TYPE_NONE;
int available_pointer_types = POINTER_TYPE_FINE;
if (is_touch_device_present)
available_pointer_types |= POINTER_TYPE_COARSE;
return available_pointer_types;
}
// This method follows the same logic as above but with hover types.
int GetAvailableHoverTypes() {
if (base::win::IsDeviceUsedAsATablet(nullptr))
return HOVER_TYPE_NONE;
if (GetSystemMetrics(SM_MOUSEPRESENT) != 0)
return HOVER_TYPE_HOVER;
return HOVER_TYPE_NONE;
}
TouchScreensAvailability GetTouchScreensAvailability() {
if (!IsTouchDevicePresent())
return TouchScreensAvailability::NONE;
return TouchScreensAvailability::ENABLED;
}
int MaxTouchPoints() {
return IsTouchDevicePresent() ? GetSystemMetrics(SM_MAXIMUMTOUCHES) : 0;
}
PointerType GetPrimaryPointerType(int available_pointer_types) {
if (available_pointer_types & POINTER_TYPE_FINE)
return POINTER_TYPE_FINE;
if (available_pointer_types & POINTER_TYPE_COARSE)
return POINTER_TYPE_COARSE;
DCHECK_EQ(available_pointer_types, POINTER_TYPE_NONE);
return POINTER_TYPE_NONE;
}
HoverType GetPrimaryHoverType(int available_hover_types) {
if (available_hover_types & HOVER_TYPE_HOVER)
return HOVER_TYPE_HOVER;
DCHECK_EQ(available_hover_types, HOVER_TYPE_NONE);
return HOVER_TYPE_NONE;
}
std::optional<PointerDevice> GetPointerDevice(PointerDevice::Key key) {
POINTER_DEVICE_INFO device;
return base::win::GetPointerDevice(key, device)
? std::make_optional(ToPointerDevice(device))
: std::nullopt;
}
std::vector<PointerDevice> GetPointerDevices() {
std::vector<PointerDevice> result;
if (std::optional<std::vector<POINTER_DEVICE_INFO>> pointer_devices =
base::win::GetPointerDevices()) {
result.reserve(pointer_devices->size());
std::transform(pointer_devices->cbegin(), pointer_devices->cend(),
std::back_inserter(result), &ToPointerDevice);
}
return result;
}
} // namespace ui
|