summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgirard@chromium.org <girard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-05 16:43:25 +0000
committergirard@chromium.org <girard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-05 16:43:25 +0000
commit21a0707cca21ae5078671959e77d92ffe98b1245 (patch)
treea251479e88495789134580910e5b1a0d93ccbe8a
parent444c1b8d84709aca175ad67c048ea236cda92eba (diff)
downloadchromium_src-21a0707cca21ae5078671959e77d92ffe98b1245.zip
chromium_src-21a0707cca21ae5078671959e77d92ffe98b1245.tar.gz
chromium_src-21a0707cca21ae5078671959e77d92ffe98b1245.tar.bz2
Fix touch scaling for high dpi windows.
Touch events in windows are always expressed in screen coordinates, even if the target app is not dpi-aware. This patch determines the dpi scale used by the OS, and re-scales touch events accordingly. In some cases the touch events are sent to the wrong window. This is detected and corrected. BUG=175542 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=185474 Review URL: https://chromiumcodereview.appspot.com/12317157 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186187 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/render_widget_host_view_win.cc9
-rw-r--r--ui/base/win/dpi.cc48
-rw-r--r--ui/base/win/dpi.h2
-rw-r--r--ui/base/win/hwnd_subclass.cc20
4 files changed, 74 insertions, 5 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 6500a8b..048f3e4 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -2072,8 +2072,9 @@ WebKit::WebTouchPoint* WebTouchState::AddTouchPoint(
bool WebTouchState::UpdateTouchPoint(
WebKit::WebTouchPoint* touch_point,
TOUCHINPUT* touch_input) {
- CPoint coordinates(TOUCH_COORD_TO_PIXEL(touch_input->x),
- TOUCH_COORD_TO_PIXEL(touch_input->y));
+ CPoint coordinates(
+ TOUCH_COORD_TO_PIXEL(touch_input->x) / ui::win::GetDPIScaleFromRegistry(),
+ TOUCH_COORD_TO_PIXEL(touch_input->y) / ui::win::GetDPIScaleFromRegistry());
int radius_x = 1;
int radius_y = 1;
if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) {
@@ -2140,8 +2141,8 @@ LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
if (total == 1 && (points[0].dwFlags & TOUCHEVENTF_DOWN)) {
pointer_down_context_ = true;
last_touch_location_ = gfx::Point(
- TOUCH_COORD_TO_PIXEL(points[0].x),
- TOUCH_COORD_TO_PIXEL(points[0].y));
+ TOUCH_COORD_TO_PIXEL(points[0].x) / ui::win::GetDPIScaleFromRegistry(),
+ TOUCH_COORD_TO_PIXEL(points[0].y) / ui::win::GetDPIScaleFromRegistry());
}
bool should_forward = render_widget_host_->ShouldForwardTouchEvent() &&
diff --git a/ui/base/win/dpi.cc b/ui/base/win/dpi.cc
index b618df9..cc71331 100644
--- a/ui/base/win/dpi.cc
+++ b/ui/base/win/dpi.cc
@@ -8,6 +8,7 @@
#include "base/win/scoped_hdc.h"
#include "ui/base/layout.h"
+#include "base/win/registry.h"
#include "ui/gfx/display.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/rect_conversions.h"
@@ -30,6 +31,24 @@ float GetDeviceScaleFactorImpl() {
#endif
}
+FARPROC GetProcAddressWrapper(LPCSTR module_name, LPCSTR proc_name) {
+ HMODULE module = ::GetModuleHandleA(module_name);
+ if (module) {
+ return ::GetProcAddress(module, proc_name);
+ }
+ return NULL;
+}
+
+BOOL IsProcessDPIAwareWrapper() {
+ typedef BOOL(WINAPI *IsProcessDPIAwarePtr)(VOID);
+ IsProcessDPIAwarePtr is_process_dpi_aware_func =
+ reinterpret_cast<IsProcessDPIAwarePtr>(
+ GetProcAddressWrapper("user32.dll", "IsProcessDPIAware"));
+ if (is_process_dpi_aware_func)
+ return is_process_dpi_aware_func();
+ return FALSE;
+}
+
} // namespace
namespace ui {
@@ -65,7 +84,7 @@ void EnableHighDPISupport() {
typedef BOOL(WINAPI *SetProcessDPIAwarePtr)(VOID);
SetProcessDPIAwarePtr set_process_dpi_aware_func =
reinterpret_cast<SetProcessDPIAwarePtr>(
- GetProcAddress(GetModuleHandleA("user32.dll"), "SetProcessDPIAware"));
+ GetProcAddressWrapper("user32.dll", "SetProcessDPIAware"));
if (set_process_dpi_aware_func)
set_process_dpi_aware_func();
}
@@ -103,6 +122,33 @@ gfx::Size DIPToScreenSize(const gfx::Size& dip_size) {
return gfx::ToFlooredSize(gfx::ScaleSize(dip_size, GetDeviceScaleFactor()));
}
+double GetDPIScaleFromRegistry() {
+ static double scale = -1.0;
+ if (scale == -1.0) {
+ double result = 1.0;
+ if (!IsProcessDPIAwareWrapper()) {
+ //HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\AppliedDPI
+ base::win::RegKey key(HKEY_CURRENT_USER,
+ L"Control Panel\\Desktop\\WindowMetrics",
+ KEY_QUERY_VALUE);
+
+ if (key.Valid()) {
+ DWORD value = 0;
+ if (key.ReadValueDW(L"AppliedDPI", &value) == ERROR_SUCCESS) {
+ result = ((double)value) / kDefaultDPIX;
+ }
+ }
+ }
+ scale = result;
+ }
+
+ // Safety test to ignore invalid settings.
+ if (scale <= 0.0)
+ scale = 1.0;
+
+ return scale;
+}
+
} // namespace win
} // namespace ui
diff --git a/ui/base/win/dpi.h b/ui/base/win/dpi.h
index 99252c7..a33e0ab 100644
--- a/ui/base/win/dpi.h
+++ b/ui/base/win/dpi.h
@@ -38,6 +38,8 @@ UI_EXPORT gfx::Size ScreenToDIPSize(const gfx::Size& size_in_pixels);
UI_EXPORT gfx::Size DIPToScreenSize(const gfx::Size& dip_size);
+UI_EXPORT double GetDPIScaleFromRegistry();
+
} // namespace win
} // namespace ui
diff --git a/ui/base/win/hwnd_subclass.cc b/ui/base/win/hwnd_subclass.cc
index 94ab44c..c8102a2 100644
--- a/ui/base/win/hwnd_subclass.cc
+++ b/ui/base/win/hwnd_subclass.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
+#include "ui/base/win/dpi.h"
#include "ui/base/win/hwnd_util.h"
namespace {
@@ -119,6 +120,25 @@ LRESULT HWNDSubclass::OnWndProc(HWND hwnd,
UINT message,
WPARAM w_param,
LPARAM l_param) {
+
+ // Touch messages are always passed in screen coordinates. If the OS is
+ // scaled, but the app is not DPI aware, then then WM_TOUCH might be
+ // intended for a different window.
+ if (message == WM_TOUCH) {
+ TOUCHINPUT point;
+
+ if (GetTouchInputInfo((HTOUCHINPUT)l_param, 1,
+ &point, sizeof(TOUCHINPUT))) {
+ POINT touch_location = {
+ TOUCH_COORD_TO_PIXEL(point.x) / ui::win::GetDPIScaleFromRegistry(),
+ TOUCH_COORD_TO_PIXEL(point.y) / ui::win::GetDPIScaleFromRegistry()};
+ HWND actual_target = WindowFromPoint(touch_location);
+ if (actual_target != hwnd) {
+ return SendMessage(actual_target, message, w_param, l_param);
+ }
+ }
+ }
+
for (std::vector<HWNDMessageFilter*>::iterator it = filters_.begin();
it != filters_.end(); ++it) {
LRESULT l_result = 0;