summaryrefslogtreecommitdiff
path: root/chromium/ui/base/win
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/base/win')
-rw-r--r--chromium/ui/base/win/direct_manipulation.cc121
-rw-r--r--chromium/ui/base/win/direct_manipulation.h88
-rw-r--r--chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.cc379
-rw-r--r--chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.h60
-rw-r--r--chromium/ui/base/win/shell.cc50
-rw-r--r--chromium/ui/base/win/shell.h4
6 files changed, 666 insertions, 36 deletions
diff --git a/chromium/ui/base/win/direct_manipulation.cc b/chromium/ui/base/win/direct_manipulation.cc
new file mode 100644
index 00000000000..78f19277727
--- /dev/null
+++ b/chromium/ui/base/win/direct_manipulation.cc
@@ -0,0 +1,121 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/win/direct_manipulation.h"
+
+#include <objbase.h>
+
+#include "base/win/windows_version.h"
+
+namespace ui {
+namespace win {
+
+// static
+std::unique_ptr<DirectManipulationHelper>
+DirectManipulationHelper::CreateInstance() {
+ // TODO(dtapuska): Do not create a DirectManipulationHelper on any windows
+ // versions as it only causes issues. High Precision Touchpad events seem to
+ // always be sent to apps with recent Windows 10 versions. This class should
+ // eventually be removed. See https://crbug.com/647038.
+ return nullptr;
+}
+
+DirectManipulationHelper::DirectManipulationHelper() {}
+
+DirectManipulationHelper::~DirectManipulationHelper() {
+ if (view_port_outer_)
+ view_port_outer_->Abandon();
+}
+
+void DirectManipulationHelper::Initialize(HWND window) {
+ DCHECK(::IsWindow(window));
+
+ // TODO(ananta)
+ // Remove the CHECK statements here and below and replace them with logs
+ // when this code stabilizes.
+ HRESULT hr =
+ ::CoCreateInstance(CLSID_DirectManipulationManager, nullptr,
+ CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&manager_));
+ CHECK(SUCCEEDED(hr));
+
+ hr = ::CoCreateInstance(CLSID_DCompManipulationCompositor, nullptr,
+ CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&compositor_));
+ CHECK(SUCCEEDED(hr));
+
+ hr = manager_->GetUpdateManager(IID_PPV_ARGS(update_manager_.GetAddressOf()));
+ CHECK(SUCCEEDED(hr));
+
+ hr = compositor_->SetUpdateManager(update_manager_.Get());
+ CHECK(SUCCEEDED(hr));
+
+ hr = compositor_.CopyTo(frame_info_.GetAddressOf());
+ CHECK(SUCCEEDED(hr));
+
+ hr = manager_->CreateViewport(frame_info_.Get(), window,
+ IID_PPV_ARGS(view_port_outer_.GetAddressOf()));
+ CHECK(SUCCEEDED(hr));
+
+ //
+ // Enable the desired configuration for each viewport.
+ //
+ DIRECTMANIPULATION_CONFIGURATION configuration =
+ DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
+ DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
+ DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y |
+ DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_INERTIA |
+ DIRECTMANIPULATION_CONFIGURATION_RAILS_X |
+ DIRECTMANIPULATION_CONFIGURATION_RAILS_Y |
+ DIRECTMANIPULATION_CONFIGURATION_SCALING |
+ DIRECTMANIPULATION_CONFIGURATION_SCALING_INERTIA;
+
+ hr = view_port_outer_->ActivateConfiguration(configuration);
+ CHECK(SUCCEEDED(hr));
+}
+
+void DirectManipulationHelper::SetBounds(const gfx::Rect& bounds) {
+ Microsoft::WRL::ComPtr<IDirectManipulationPrimaryContent>
+ primary_content_outer;
+ HRESULT hr = view_port_outer_->GetPrimaryContent(
+ IID_PPV_ARGS(primary_content_outer.GetAddressOf()));
+ CHECK(SUCCEEDED(hr));
+
+ Microsoft::WRL::ComPtr<IDirectManipulationContent> content_outer;
+ hr = primary_content_outer.CopyTo(content_outer.GetAddressOf());
+ CHECK(SUCCEEDED(hr));
+
+ RECT rect = bounds.ToRECT();
+
+ hr = view_port_outer_->SetViewportRect(&rect);
+ CHECK(SUCCEEDED(hr));
+
+ hr = content_outer->SetContentRect(&rect);
+ CHECK(SUCCEEDED(hr));
+}
+
+void DirectManipulationHelper::Activate(HWND window) {
+ DCHECK(::IsWindow(window));
+ manager_->Activate(window);
+}
+
+void DirectManipulationHelper::Deactivate(HWND window) {
+ DCHECK(::IsWindow(window));
+ manager_->Deactivate(window);
+}
+
+void DirectManipulationHelper::HandleMouseWheel(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ MSG msg = {window, message, w_param, l_param};
+
+ HRESULT hr = view_port_outer_->SetContact(DIRECTMANIPULATION_MOUSEFOCUS);
+ if (SUCCEEDED(hr)) {
+ BOOL handled = FALSE;
+ manager_->ProcessInput(&msg, &handled);
+ view_port_outer_->ReleaseContact(DIRECTMANIPULATION_MOUSEFOCUS);
+ }
+}
+
+} // namespace win.
+} // namespace ui.
diff --git a/chromium/ui/base/win/direct_manipulation.h b/chromium/ui/base/win/direct_manipulation.h
new file mode 100644
index 00000000000..af7ad807f2e
--- /dev/null
+++ b/chromium/ui/base/win/direct_manipulation.h
@@ -0,0 +1,88 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WIN_DIRECT_MANIPULATION_H_
+#define UI_WIN_DIRECT_MANIPULATION_H_
+
+#include <directmanipulation.h>
+#include <wrl/client.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/base/ui_base_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+namespace win {
+
+// Windows 10 provides a new API called Direct Manipulation which generates
+// smooth scroll events via WM_MOUSEWHEEL messages with predictable deltas
+// on high precision touch pads. This basically requires the application window
+// to register as a Direct Manipulation consumer. The way mouse wheel messages
+// are dispatched is
+// 1. The foreground window is checked to see if it is a Direct Manipulation
+// consumer.
+// 2. If it is then Direct Manipulation takes over and sends the following
+// messages. WM_POINTERACTIVATE, WM_POINTERDOWN and DM_POINTERHITTEST.
+// 3. It then posts WM_MOUSEWHEEL messages with precision deltas which vary
+// based on the amount of the scroll.
+// 4. If the foreground window is not a Direct Manipulation consumer, it
+// then takes a fallback route where it posts WM_MOUSEWHEEL messages
+// with precision but varying deltas to the window. There is a also
+// a slight delay in receiving the first set of mouse wheel messages.
+// This causes scrolling to appear janky and jumpy.
+// Our approach for addressing this is to do the absolute minimum to
+// register our window as a Direct Manipulation consumer. This class
+// provides the necessary functionality to register the passed in HWND as a
+// Direct Manipulation consumer. We don't rely on Direct manipulation
+// to do the smooth scrolling in the background thread as documented on
+// msdn.
+class UI_BASE_EXPORT DirectManipulationHelper {
+ public:
+ // Creates an instance of this class if Direct Manipulation is enabled on
+ // the platform. If not returns NULL.
+ static std::unique_ptr<DirectManipulationHelper> CreateInstance();
+
+ // This function instantiates Direct Manipulation and creates a viewport for
+ // the passed in |window|.
+ // consumer. Most of the code is boiler plate and is based on the sample.
+ void Initialize(HWND window);
+
+ // Sets the bounds of the fake Direct manipulation viewport to match those
+ // of the legacy window.
+ void SetBounds(const gfx::Rect& bounds);
+
+ // Registers and activates the passed in |window| as a Direct Manipulation
+ // consumer.
+ void Activate(HWND window);
+
+ // Deactivates Direct Manipulation processing on the passed in |window|.
+ void Deactivate(HWND window);
+
+ // Passes the WM_MOUSEWHEEL messages to Direct Manipulation. This is for
+ // logistics purposes.
+ void HandleMouseWheel(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param);
+
+ ~DirectManipulationHelper();
+
+ private:
+ DirectManipulationHelper();
+
+ Microsoft::WRL::ComPtr<IDirectManipulationManager2> manager_;
+ Microsoft::WRL::ComPtr<IDirectManipulationCompositor> compositor_;
+ Microsoft::WRL::ComPtr<IDirectManipulationUpdateManager> update_manager_;
+ Microsoft::WRL::ComPtr<IDirectManipulationFrameInfoProvider> frame_info_;
+ Microsoft::WRL::ComPtr<IDirectManipulationViewport2> view_port_outer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper);
+};
+
+} // namespace win
+} // namespace ui
+
+#endif // UI_WIN_DIRECT_MANIPULATION_H_
diff --git a/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.cc b/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.cc
new file mode 100644
index 00000000000..bbce7bda6eb
--- /dev/null
+++ b/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.cc
@@ -0,0 +1,379 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/win/osk_display_manager.h"
+
+#include <windows.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <shobjidl.h> // Must be before propkey.
+
+#include "base/bind.h"
+#include "base/debug/leak_annotations.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_co_mem.h"
+#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
+#include "ui/base/win/hidden_window.h"
+#include "ui/base/win/osk_display_observer.h"
+#include "ui/display/win/dpi.h"
+#include "ui/gfx/geometry/dip_util.h"
+
+namespace {
+
+constexpr int kCheckOSKDelayMs = 1000;
+constexpr int kDismissKeyboardRetryTimeoutMs = 100;
+constexpr int kDismissKeyboardMaxRetries = 5;
+
+constexpr wchar_t kOSKClassName[] = L"IPTip_Main_Window";
+
+constexpr wchar_t kWindows8OSKRegPath[] =
+ L"Software\\Classes\\CLSID\\{054AAE20-4BEA-4347-8A35-64A533254A9D}"
+ L"\\LocalServer32";
+
+} // namespace
+
+namespace ui {
+
+// This class provides functionality to detect when the on screen keyboard
+// is displayed and move the main window up if it is obscured by the keyboard.
+class OnScreenKeyboardDetector {
+ public:
+ OnScreenKeyboardDetector();
+ ~OnScreenKeyboardDetector();
+
+ // Schedules a delayed task which detects if the on screen keyboard was
+ // displayed.
+ void DetectKeyboard(HWND main_window);
+
+ // Dismisses the on screen keyboard. If a call to display the keyboard was
+ // made, this function waits for the keyboard to become visible by retrying
+ // upto a maximum of kDismissKeyboardMaxRetries.
+ bool DismissKeyboard();
+
+ // Add/Remove keyboard observers.
+ // Please note that this class does not track the |observer| destruction. It
+ // is upto the classes which set up these observers to remove them when they
+ // are destroyed.
+ void AddObserver(OnScreenKeyboardObserver* observer);
+ void RemoveObserver(OnScreenKeyboardObserver* observer);
+
+ // Returns true if the osk is visible. Sets osk bounding rect if non-null
+ static bool IsKeyboardVisible(gfx::Rect* osk_bounding_rect);
+
+ private:
+ // Executes as a task and detects if the on screen keyboard is displayed.
+ // Once the keyboard is displayed it schedules the HideIfNecessary() task to
+ // detect when the keyboard is or should be hidden.
+ void CheckIfKeyboardVisible();
+
+ // Executes as a task and detects if the keyboard was hidden or should be
+ // hidden.
+ void HideIfNecessary();
+
+ // Notifies observers that the keyboard was displayed.
+ // A recurring task HideIfNecessary() is started to detect when the OSK
+ // disappears.
+ void HandleKeyboardVisible();
+
+ // Notifies observers that the keyboard was hidden.
+ // The observer list is cleared out after this notification.
+ void HandleKeyboardHidden();
+
+ // Removes all observers from the list.
+ void ClearObservers();
+
+ // The main window which displays the on screen keyboard.
+ HWND main_window_ = nullptr;
+
+ // Tracks if the keyboard was displayed.
+ bool osk_visible_notification_received_ = false;
+
+ // The keyboard dimensions in pixels.
+ gfx::Rect osk_rect_pixels_;
+
+ // Set to true if a call to DetectKeyboard() was made.
+ bool keyboard_detect_requested_ = false;
+
+ // Contains the number of attempts made to dismiss the keyboard. Please refer
+ // to the DismissKeyboard() function for more information.
+ int keyboard_dismiss_retry_count_ = 0;
+
+ base::ObserverList<OnScreenKeyboardObserver, false> observers_;
+
+ // Should be the last member in the class. Helps ensure that tasks spawned
+ // by this class instance are canceled when it is destroyed.
+ base::WeakPtrFactory<OnScreenKeyboardDetector> keyboard_detector_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnScreenKeyboardDetector);
+};
+
+// OnScreenKeyboardDetector member definitions.
+OnScreenKeyboardDetector::OnScreenKeyboardDetector()
+ : keyboard_detector_factory_(this) {}
+
+OnScreenKeyboardDetector::~OnScreenKeyboardDetector() {
+ ClearObservers();
+}
+
+void OnScreenKeyboardDetector::DetectKeyboard(HWND main_window) {
+ main_window_ = main_window;
+ keyboard_detect_requested_ = true;
+ // The keyboard is displayed by TabTip.exe which is launched via a
+ // ShellExecute call in the
+ // OnScreenKeyboardDisplayManager::DisplayVirtualKeyboard() function. We use
+ // a delayed task to check if the keyboard is visible because of the possible
+ // delay between the ShellExecute call and the keyboard becoming visible.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&OnScreenKeyboardDetector::CheckIfKeyboardVisible,
+ keyboard_detector_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs));
+}
+
+bool OnScreenKeyboardDetector::DismissKeyboard() {
+ // We dismiss the virtual keyboard by generating the ESC keystroke
+ // programmatically.
+ HWND osk = ::FindWindow(kOSKClassName, nullptr);
+ if (::IsWindow(osk) && ::IsWindowEnabled(osk)) {
+ keyboard_detect_requested_ = false;
+ keyboard_dismiss_retry_count_ = 0;
+ HandleKeyboardHidden();
+ PostMessage(osk, WM_SYSCOMMAND, SC_CLOSE, 0);
+ return true;
+ } else if (keyboard_detect_requested_) {
+ if (keyboard_dismiss_retry_count_ < kDismissKeyboardMaxRetries) {
+ keyboard_dismiss_retry_count_++;
+ // Please refer to the comments in the DetectKeyboard() function for more
+ // information as to why we need a delayed task here.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(base::IgnoreResult(
+ &OnScreenKeyboardDetector::DismissKeyboard),
+ keyboard_detector_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kDismissKeyboardRetryTimeoutMs));
+ } else {
+ keyboard_dismiss_retry_count_ = 0;
+ }
+ }
+ return false;
+}
+
+void OnScreenKeyboardDetector::AddObserver(OnScreenKeyboardObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void OnScreenKeyboardDetector::RemoveObserver(
+ OnScreenKeyboardObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+// static
+bool OnScreenKeyboardDetector::IsKeyboardVisible(gfx::Rect* osk_bounding_rect) {
+ HWND osk = ::FindWindow(kOSKClassName, nullptr);
+ if (!::IsWindow(osk))
+ return false;
+ if (osk_bounding_rect) {
+ RECT osk_rect = {};
+ ::GetWindowRect(osk, &osk_rect);
+ *osk_bounding_rect = gfx::Rect(osk_rect);
+ }
+ return ::IsWindowVisible(osk) && ::IsWindowEnabled(osk);
+}
+
+void OnScreenKeyboardDetector::CheckIfKeyboardVisible() {
+ if (IsKeyboardVisible(&osk_rect_pixels_)) {
+ if (!osk_visible_notification_received_)
+ HandleKeyboardVisible();
+ } else {
+ DVLOG(1) << "OSK did not come up in 1 second. Something wrong.";
+ }
+}
+
+void OnScreenKeyboardDetector::HideIfNecessary() {
+ HWND osk = ::FindWindow(kOSKClassName, nullptr);
+ if (!::IsWindow(osk))
+ return;
+
+ // Three cases here.
+ // 1. OSK was hidden because the user dismissed it.
+ // 2. We are no longer in the foreground.
+ // 3. The OSK is still visible.
+ // In the first case we just have to notify the observers that the OSK was
+ // hidden.
+ // In the second case we need to dismiss the OSK which internally will
+ // notify the observers about the OSK being hidden.
+ if (!::IsWindowEnabled(osk)) {
+ if (osk_visible_notification_received_) {
+ if (main_window_ == ::GetForegroundWindow()) {
+ DVLOG(1) << "OSK window hidden while we are in the foreground.";
+ HandleKeyboardHidden();
+ }
+ }
+ } else if (main_window_ != ::GetForegroundWindow()) {
+ if (osk_visible_notification_received_) {
+ DVLOG(1) << "We are no longer in the foreground. Dismising OSK.";
+ DismissKeyboard();
+ }
+ } else {
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&OnScreenKeyboardDetector::HideIfNecessary,
+ keyboard_detector_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs));
+ }
+}
+
+void OnScreenKeyboardDetector::HandleKeyboardVisible() {
+ DCHECK(!osk_visible_notification_received_);
+ osk_visible_notification_received_ = true;
+
+ for (OnScreenKeyboardObserver& observer : observers_)
+ observer.OnKeyboardVisible(osk_rect_pixels_);
+
+ // Now that the keyboard is visible, run the task to detect if it was hidden.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&OnScreenKeyboardDetector::HideIfNecessary,
+ keyboard_detector_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kCheckOSKDelayMs));
+}
+
+void OnScreenKeyboardDetector::HandleKeyboardHidden() {
+ osk_visible_notification_received_ = false;
+ for (OnScreenKeyboardObserver& observer : observers_)
+ observer.OnKeyboardHidden(osk_rect_pixels_);
+ ClearObservers();
+}
+
+void OnScreenKeyboardDetector::ClearObservers() {
+ for (auto& observer : observers_)
+ RemoveObserver(&observer);
+}
+
+// OnScreenKeyboardDisplayManager member definitions.
+OnScreenKeyboardDisplayManager::OnScreenKeyboardDisplayManager() {}
+
+OnScreenKeyboardDisplayManager::~OnScreenKeyboardDisplayManager() {}
+
+OnScreenKeyboardDisplayManager* OnScreenKeyboardDisplayManager::GetInstance() {
+ static OnScreenKeyboardDisplayManager* instance = nullptr;
+ if (!instance) {
+ instance = new OnScreenKeyboardDisplayManager;
+ ANNOTATE_LEAKING_OBJECT_PTR(instance);
+ }
+ return instance;
+}
+
+bool OnScreenKeyboardDisplayManager::DisplayVirtualKeyboard(
+ OnScreenKeyboardObserver* observer) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return false;
+
+ if (base::win::IsKeyboardPresentOnSlate(nullptr, ui::GetHiddenWindow()))
+ return false;
+
+ if (osk_path_.empty() && !GetOSKPath(&osk_path_)) {
+ DLOG(WARNING) << "Failed to get on screen keyboard path from registry";
+ return false;
+ }
+
+ HINSTANCE ret = ::ShellExecuteW(nullptr, L"", osk_path_.c_str(), nullptr,
+ nullptr, SW_SHOW);
+
+ bool success = reinterpret_cast<intptr_t>(ret) > 32;
+ if (success) {
+ // If multiple calls to DisplayVirtualKeyboard occur one after the other,
+ // the last observer would be the one to get notifications.
+ keyboard_detector_.reset(new OnScreenKeyboardDetector);
+ if (observer)
+ keyboard_detector_->AddObserver(observer);
+ keyboard_detector_->DetectKeyboard(::GetForegroundWindow());
+ }
+ return success;
+}
+
+bool OnScreenKeyboardDisplayManager::DismissVirtualKeyboard() {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return false;
+
+ return keyboard_detector_ ? keyboard_detector_->DismissKeyboard() : false;
+}
+
+void OnScreenKeyboardDisplayManager::RemoveObserver(
+ OnScreenKeyboardObserver* observer) {
+ if (keyboard_detector_)
+ keyboard_detector_->RemoveObserver(observer);
+}
+
+bool OnScreenKeyboardDisplayManager::GetOSKPath(base::string16* osk_path) {
+ DCHECK(osk_path);
+
+ // We need to launch TabTip.exe from the location specified under the
+ // LocalServer32 key for the {{054AAE20-4BEA-4347-8A35-64A533254A9D}}
+ // CLSID.
+ // TabTip.exe is typically found at
+ // c:\program files\common files\microsoft shared\ink on English Windows.
+ // We don't want to launch TabTip.exe from
+ // c:\program files (x86)\common files\microsoft shared\ink. This path is
+ // normally found on 64 bit Windows.
+ base::win::RegKey key(HKEY_LOCAL_MACHINE, kWindows8OSKRegPath,
+ KEY_READ | KEY_WOW64_64KEY);
+ DWORD osk_path_length = 1024;
+ if (key.ReadValue(nullptr, base::WriteInto(osk_path, osk_path_length),
+ &osk_path_length, nullptr) != ERROR_SUCCESS) {
+ return false;
+ }
+
+ osk_path->resize(base::string16::traits_type::length(osk_path->c_str()));
+
+ *osk_path = base::ToLowerASCII(*osk_path);
+
+ size_t common_program_files_offset = osk_path->find(L"%commonprogramfiles%");
+ // Typically the path to TabTip.exe read from the registry will start with
+ // %CommonProgramFiles% which needs to be replaced with the corrsponding
+ // expanded string.
+ // If the path does not begin with %CommonProgramFiles% we use it as is.
+ if (common_program_files_offset != base::string16::npos) {
+ // Preserve the beginning quote in the path.
+ osk_path->erase(common_program_files_offset,
+ wcslen(L"%commonprogramfiles%"));
+ // The path read from the registry contains the %CommonProgramFiles%
+ // environment variable prefix. On 64 bit Windows the SHGetKnownFolderPath
+ // function returns the common program files path with the X86 suffix for
+ // the FOLDERID_ProgramFilesCommon value.
+ // To get the correct path to TabTip.exe we first read the environment
+ // variable CommonProgramW6432 which points to the desired common
+ // files path. Failing that we fallback to the SHGetKnownFolderPath API.
+
+ // We then replace the %CommonProgramFiles% value with the actual common
+ // files path found in the process.
+ base::string16 common_program_files_path;
+ DWORD buffer_size =
+ GetEnvironmentVariable(L"CommonProgramW6432", nullptr, 0);
+ if (buffer_size) {
+ GetEnvironmentVariable(
+ L"CommonProgramW6432",
+ base::WriteInto(&common_program_files_path, buffer_size),
+ buffer_size);
+ DCHECK(!common_program_files_path.empty());
+ } else {
+ base::win::ScopedCoMem<wchar_t> common_program_files;
+ if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, nullptr,
+ &common_program_files))) {
+ return false;
+ }
+ common_program_files_path = common_program_files;
+ }
+ osk_path->insert(common_program_files_offset, common_program_files_path);
+ }
+ return !osk_path->empty();
+}
+
+bool OnScreenKeyboardDisplayManager::IsKeyboardVisible() const {
+ return OnScreenKeyboardDetector::IsKeyboardVisible(nullptr);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.h b/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.h
new file mode 100644
index 00000000000..b5392c4b686
--- /dev/null
+++ b/chromium/ui/base/win/on_screen_keyboard_display_manager_tab_tip.h
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_WIN_OSK_DISPLAY_MANAGER_H_
+#define UI_BASE_WIN_OSK_DISPLAY_MANAGER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/strings/string16.h"
+#include "ui/base/ui_base_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+class OnScreenKeyboardDetector;
+class OnScreenKeyboardObserver;
+
+// This class provides functionality to display the on screen keyboard on
+// Windows 8+. It optionally notifies observers that the OSK is displayed,
+// hidden, etc.
+class UI_BASE_EXPORT OnScreenKeyboardDisplayManager {
+ public:
+ static OnScreenKeyboardDisplayManager* GetInstance();
+
+ ~OnScreenKeyboardDisplayManager();
+
+ // Functions to display and dismiss the keyboard.
+ // The optional |observer| parameter allows callers to be notified when the
+ // keyboard is displayed, dismissed, etc.
+ bool DisplayVirtualKeyboard(OnScreenKeyboardObserver* observer);
+ // When the keyboard is dismissed, the registered observer if any is removed
+ // after notifying it.
+ bool DismissVirtualKeyboard();
+
+ // Removes a registered observer.
+ void RemoveObserver(OnScreenKeyboardObserver* observer);
+
+ // Returns the path of the on screen keyboard exe (TabTip.exe) in the
+ // |osk_path| parameter.
+ // Returns true on success.
+ bool GetOSKPath(base::string16* osk_path);
+
+ // Returns true if the virtual keyboard is currently visible.
+ bool IsKeyboardVisible() const;
+
+ private:
+ OnScreenKeyboardDisplayManager();
+
+ std::unique_ptr<OnScreenKeyboardDetector> keyboard_detector_;
+
+ // The location of TabTip.exe.
+ base::string16 osk_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnScreenKeyboardDisplayManager);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_WIN_OSK_DISPLAY_MANAGER_H_
diff --git a/chromium/ui/base/win/shell.cc b/chromium/ui/base/win/shell.cc
index ebd6c65d481..b5afdead174 100644
--- a/chromium/ui/base/win/shell.cc
+++ b/chromium/ui/base/win/shell.cc
@@ -27,29 +27,21 @@ namespace win {
namespace {
-// Default ShellExecuteEx flags used with the "openas" verb.
+// Default ShellExecuteEx flags used with "openas", "explore", and default
+// verbs.
//
// SEE_MASK_NOASYNC is specified so that ShellExecuteEx can be invoked from a
// thread whose message loop may not wait around long enough for the
// asynchronous tasks initiated by ShellExecuteEx to complete. Using this flag
// causes ShellExecuteEx() to block until these tasks complete.
-const DWORD kDefaultOpenAsFlags = SEE_MASK_NOASYNC;
-
-// Default ShellExecuteEx flags used with the "explore", "open" or default verb.
-//
-// See kDefaultOpenFlags for description SEE_MASK_NOASYNC flag.
-// SEE_MASK_FLAG_NO_UI is used to suppress any error message boxes that might be
-// displayed if there is an error in opening the file. Failure in invoking the
-// "open" actions result in invocation of the "saveas" verb, making the error
-// dialog superfluous.
-const DWORD kDefaultOpenFlags = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI;
+const DWORD kDefaultShellExecuteFlags = SEE_MASK_NOASYNC;
// Invokes ShellExecuteExW() with the given parameters.
-DWORD InvokeShellExecute(const base::string16 path,
- const base::string16 working_directory,
- const base::string16 args,
- const base::string16 verb,
- DWORD mask) {
+bool InvokeShellExecute(const base::string16 path,
+ const base::string16 working_directory,
+ const base::string16 args,
+ const base::string16 verb,
+ DWORD mask) {
base::AssertBlockingAllowed();
SHELLEXECUTEINFO sei = {sizeof(sei)};
sei.fMask = mask;
@@ -59,7 +51,7 @@ DWORD InvokeShellExecute(const base::string16 path,
sei.lpDirectory =
(working_directory.empty() ? nullptr : working_directory.c_str());
sei.lpParameters = (args.empty() ? nullptr : args.c_str());
- return ::ShellExecuteExW(&sei) ? ERROR_SUCCESS : ::GetLastError();
+ return ::ShellExecuteExW(&sei);
}
} // namespace
@@ -68,32 +60,22 @@ bool OpenAnyViaShell(const base::string16& full_path,
const base::string16& directory,
const base::string16& args,
DWORD mask) {
- DWORD open_result =
- InvokeShellExecute(full_path, directory, args, base::string16(), mask);
- if (open_result == ERROR_SUCCESS)
- return true;
- // Show the Windows "Open With" dialog box to ask the user to pick an app to
- // open the file with. Note that we are not forwarding |args| for the "openas"
- // call since the target application is nolonger known at this point.
- if (open_result == ERROR_NO_ASSOCIATION)
- return InvokeShellExecute(full_path, directory, base::string16(), L"openas",
- kDefaultOpenAsFlags) == ERROR_SUCCESS;
- return false;
+ return InvokeShellExecute(full_path, directory, args, base::string16(), mask);
}
bool OpenFileViaShell(const base::FilePath& full_path) {
- return OpenAnyViaShell(full_path.value(), full_path.DirName().value(),
- base::string16(), kDefaultOpenFlags);
+ // Invoke the default verb on the file with no arguments.
+ return InvokeShellExecute(full_path.value(), full_path.DirName().value(),
+ base::string16(), base::string16(),
+ kDefaultShellExecuteFlags);
}
bool OpenFolderViaShell(const base::FilePath& full_path) {
// The "explore" verb causes the folder at |full_path| to be displayed in a
- // file browser. This will fail if |full_path| is not a directory. The
- // resulting error does not cause UI due to the SEE_MASK_FLAG_NO_UI flag in
- // kDefaultOpenFlags.
+ // file browser. This will fail if |full_path| is not a directory.
return InvokeShellExecute(full_path.value(), full_path.value(),
base::string16(), L"explore",
- kDefaultOpenFlags) == ERROR_SUCCESS;
+ kDefaultShellExecuteFlags);
}
bool PreventWindowFromPinning(HWND hwnd) {
diff --git a/chromium/ui/base/win/shell.h b/chromium/ui/base/win/shell.h
index df784a6e13b..c47e5ce3f47 100644
--- a/chromium/ui/base/win/shell.h
+++ b/chromium/ui/base/win/shell.h
@@ -17,8 +17,8 @@ class FilePath;
namespace ui {
namespace win {
-// Open the folder at |full_path| via the Windows shell. Does nothing if
-// |full_path| is not a folder.
+// Open the folder at |full_path| via the Windows shell. It is an error if
+// |full_path| does not refer to a folder.
//
// Note: Must be called on a thread that allows blocking.
UI_BASE_EXPORT bool OpenFolderViaShell(const base::FilePath& full_path);