summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-11 22:15:32 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-11 22:15:32 +0000
commit26012f91aa8cb47d845d68af6afdcec483e92754 (patch)
treea54f903d79ed3ddfb368eadcd6fc21a55bec4ca0
parente32642f68ec20a267002648f335b0ca7c94dd4c3 (diff)
downloadchromium_src-26012f91aa8cb47d845d68af6afdcec483e92754.zip
chromium_src-26012f91aa8cb47d845d68af6afdcec483e92754.tar.gz
chromium_src-26012f91aa8cb47d845d68af6afdcec483e92754.tar.bz2
The shell dialog code explicitly disables the browser HWND before calling the Windows API to select a file.
When the dialog is closed, the browser HWND gets a WM_ACTIVATE but is still disabled, which messes up with the focus restoration. This patch ensures we restore the focus explicitly when the browser HWND is reenabled to work-around that issue. BUG=3380 TEST=Set the focus on a page with scroll-bars, right-click to do a 'save as'. Close the dialog. The arrow keys should let you scroll the page. Accelerators such as Ctrl-T should still work. Test 'open a file', 'print' and the font selection dialog (in the options). When closing the dialog the focus should return to the view that last had focus. Review URL: http://codereview.chromium.org/195065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26029 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/views/shell_dialogs_win.cc43
1 files changed, 42 insertions, 1 deletions
diff --git a/chrome/browser/views/shell_dialogs_win.cc b/chrome/browser/views/shell_dialogs_win.cc
index 5c5b1f9..fa2b6f0 100644
--- a/chrome/browser/views/shell_dialogs_win.cc
+++ b/chrome/browser/views/shell_dialogs_win.cc
@@ -21,6 +21,8 @@
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "grit/generated_resources.h"
+#include "views/focus/focus_manager.h"
+#include "views/focus/view_storage.h"
// Helpers to show certain types of Windows shell dialogs in a way that doesn't
// block the UI of the entire app.
@@ -116,6 +118,11 @@ class BaseShellDialogImpl {
// This set only contains non-null HWNDs. NULL hwnds are not added to this
// list.
typedef std::set<HWND> Owners;
+
+ // Storage id used to store the last focused view so we can restore focus
+ // appropriately.
+ int view_storage_id_;
+
static Owners owners_;
static int instance_count_;
@@ -127,7 +134,9 @@ BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_;
int BaseShellDialogImpl::instance_count_ = 0;
BaseShellDialogImpl::BaseShellDialogImpl()
- : ui_loop_(MessageLoop::current()) {
+ : ui_loop_(MessageLoop::current()),
+ view_storage_id_(views::ViewStorage::GetSharedInstance()->
+ CreateStorageID()) {
++instance_count_;
}
@@ -148,6 +157,20 @@ BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) {
run_state.owner = owner;
if (owner) {
owners_.insert(owner);
+ // Disabling the owner causes the browser to be disabled when the dialog is
+ // closed and the browser gets the activation. This messes up the normal
+ // focus restoration process. To work-around this, we'll restore the focus
+ // ourselves after we have reenabled the owner.
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManagerForNativeView(owner);
+ if (focus_manager) {
+ views::View* focused_view = focus_manager->GetFocusedView();
+ if (focused_view)
+ views::ViewStorage::GetSharedInstance()->StoreView(view_storage_id_,
+ focused_view);
+ } else {
+ NOTREACHED();
+ }
DisableOwner(owner);
}
return run_state;
@@ -159,6 +182,24 @@ void BaseShellDialogImpl::EndRun(RunState run_state) {
EnableOwner(run_state.owner);
DCHECK(owners_.find(run_state.owner) != owners_.end());
owners_.erase(run_state.owner);
+ // Now that the owner is enabled, restore the focus if applicable.
+ views::View* view_to_focus =
+ views::ViewStorage::GetSharedInstance()->RetrieveView(view_storage_id_);
+ if (view_to_focus) {
+ views::ViewStorage::GetSharedInstance()->RemoveView(view_storage_id_);
+ views::FocusManager* focus_manager =
+ views::FocusManager::GetFocusManagerForNativeView(run_state.owner);
+ if (focus_manager) {
+ // We need to clear focus as when the focus is restored when the dialog
+ // is closed, only setting the native focus fails. Meaning the focused
+ // manager still believes the right view has focus, and would ignore
+ // requesting focus to what it thinks is already focused.
+ focus_manager->ClearFocus();
+ view_to_focus->RequestFocus();
+ } else {
+ NOTREACHED();
+ }
+ }
}
DCHECK(run_state.dialog_thread);
delete run_state.dialog_thread;