diff options
author | girard@chromium.org <girard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-05 16:43:25 +0000 |
---|---|---|
committer | girard@chromium.org <girard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-05 16:43:25 +0000 |
commit | 21a0707cca21ae5078671959e77d92ffe98b1245 (patch) | |
tree | a251479e88495789134580910e5b1a0d93ccbe8a /ui/base | |
parent | 444c1b8d84709aca175ad67c048ea236cda92eba (diff) | |
download | chromium_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
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/win/dpi.cc | 48 | ||||
-rw-r--r-- | ui/base/win/dpi.h | 2 | ||||
-rw-r--r-- | ui/base/win/hwnd_subclass.cc | 20 |
3 files changed, 69 insertions, 1 deletions
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; |