Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: chrome/browser/views/shell_dialogs_win.cc

Issue 206004: Merge 26135 - The focus is not restored properly when a Windows modal dialog... (Closed) Base URL: svn://chrome-svn/chrome/branches/195/src/
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | views/widget/widget_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Modified: svn:mergeinfo
Merged /trunk/src/chrome/browser/views/shell_dialogs_win.cc:r26135
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/shell_dialogs.h" 5 #include "chrome/browser/shell_dialogs.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <commdlg.h> 8 #include <commdlg.h>
9 #include <shlobj.h> 9 #include <shlobj.h>
10 #include <atlbase.h> 10 #include <atlbase.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <set> 13 #include <set>
14 14
15 #include "app/gfx/font.h" 15 #include "app/gfx/font.h"
16 #include "app/l10n_util.h" 16 #include "app/l10n_util.h"
17 #include "app/win_util.h" 17 #include "app/win_util.h"
18 #include "base/file_util.h" 18 #include "base/file_util.h"
19 #include "base/registry.h" 19 #include "base/registry.h"
20 #include "base/string_util.h" 20 #include "base/string_util.h"
21 #include "base/thread.h" 21 #include "base/thread.h"
22 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/browser_process.h"
23 #include "grit/generated_resources.h" 23 #include "grit/generated_resources.h"
24 #include "views/focus/focus_manager.h"
25 #include "views/focus/view_storage.h"
26 24
27 // Helpers to show certain types of Windows shell dialogs in a way that doesn't 25 // Helpers to show certain types of Windows shell dialogs in a way that doesn't
28 // block the UI of the entire app. 26 // block the UI of the entire app.
29 27
30 class ShellDialogThread : public base::Thread { 28 class ShellDialogThread : public base::Thread {
31 public: 29 public:
32 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } 30 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { }
33 31
34 protected: 32 protected:
35 void Init() { 33 void Init() {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // boxes active, this list will consist of the two browser windows' HWNDs. 109 // boxes active, this list will consist of the two browser windows' HWNDs.
112 // The derived class must call EndRun once the dialog is done showing to 110 // The derived class must call EndRun once the dialog is done showing to
113 // remove the owning HWND from this list. 111 // remove the owning HWND from this list.
114 // This object is static since it is maintained for all instances of this 112 // This object is static since it is maintained for all instances of this
115 // object - i.e. you can't have a font picker and a file picker open for the 113 // object - i.e. you can't have a font picker and a file picker open for the
116 // same owner, even though they might be represented by different instances 114 // same owner, even though they might be represented by different instances
117 // of this object. 115 // of this object.
118 // This set only contains non-null HWNDs. NULL hwnds are not added to this 116 // This set only contains non-null HWNDs. NULL hwnds are not added to this
119 // list. 117 // list.
120 typedef std::set<HWND> Owners; 118 typedef std::set<HWND> Owners;
121
122 // Storage id used to store the last focused view so we can restore focus
123 // appropriately.
124 int view_storage_id_;
125
126 static Owners owners_; 119 static Owners owners_;
127 static int instance_count_; 120 static int instance_count_;
128 121
129 DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl); 122 DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl);
130 }; 123 };
131 124
132 // static 125 // static
133 BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_; 126 BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_;
134 int BaseShellDialogImpl::instance_count_ = 0; 127 int BaseShellDialogImpl::instance_count_ = 0;
135 128
136 BaseShellDialogImpl::BaseShellDialogImpl() 129 BaseShellDialogImpl::BaseShellDialogImpl()
137 : ui_loop_(MessageLoop::current()), 130 : ui_loop_(MessageLoop::current()) {
138 view_storage_id_(views::ViewStorage::GetSharedInstance()->
139 CreateStorageID()) {
140 ++instance_count_; 131 ++instance_count_;
141 } 132 }
142 133
143 BaseShellDialogImpl::~BaseShellDialogImpl() { 134 BaseShellDialogImpl::~BaseShellDialogImpl() {
144 // All runs should be complete by the time this is called! 135 // All runs should be complete by the time this is called!
145 if (--instance_count_ == 0) 136 if (--instance_count_ == 0)
146 DCHECK(owners_.empty()); 137 DCHECK(owners_.empty());
147 } 138 }
148 139
149 BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) { 140 BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) {
150 // Cannot run a modal shell dialog if one is already running for this owner. 141 // Cannot run a modal shell dialog if one is already running for this owner.
151 DCHECK(!IsRunningDialogForOwner(owner)); 142 DCHECK(!IsRunningDialogForOwner(owner));
152 // The owner must be a top level window, otherwise we could end up with two 143 // The owner must be a top level window, otherwise we could end up with two
153 // entries in our map for the same top level window. 144 // entries in our map for the same top level window.
154 DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT)); 145 DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT));
155 RunState run_state; 146 RunState run_state;
156 run_state.dialog_thread = CreateDialogThread(); 147 run_state.dialog_thread = CreateDialogThread();
157 run_state.owner = owner; 148 run_state.owner = owner;
158 if (owner) { 149 if (owner) {
159 owners_.insert(owner); 150 owners_.insert(owner);
160 // Disabling the owner causes the browser to be disabled when the dialog is
161 // closed and the browser gets the activation. This messes up the normal
162 // focus restoration process. To work-around this, we'll restore the focus
163 // ourselves after we have reenabled the owner.
164 views::FocusManager* focus_manager =
165 views::FocusManager::GetFocusManagerForNativeView(owner);
166 if (focus_manager) {
167 views::View* focused_view = focus_manager->GetFocusedView();
168 if (focused_view)
169 views::ViewStorage::GetSharedInstance()->StoreView(view_storage_id_,
170 focused_view);
171 } else {
172 NOTREACHED();
173 }
174 DisableOwner(owner); 151 DisableOwner(owner);
175 } 152 }
176 return run_state; 153 return run_state;
177 } 154 }
178 155
179 void BaseShellDialogImpl::EndRun(RunState run_state) { 156 void BaseShellDialogImpl::EndRun(RunState run_state) {
180 if (run_state.owner) { 157 if (run_state.owner) {
181 DCHECK(IsRunningDialogForOwner(run_state.owner)); 158 DCHECK(IsRunningDialogForOwner(run_state.owner));
182 EnableOwner(run_state.owner); 159 EnableOwner(run_state.owner);
183 DCHECK(owners_.find(run_state.owner) != owners_.end()); 160 DCHECK(owners_.find(run_state.owner) != owners_.end());
184 owners_.erase(run_state.owner); 161 owners_.erase(run_state.owner);
185 // Now that the owner is enabled, restore the focus if applicable.
186 views::View* view_to_focus =
187 views::ViewStorage::GetSharedInstance()->RetrieveView(view_storage_id_);
188 if (view_to_focus) {
189 views::ViewStorage::GetSharedInstance()->RemoveView(view_storage_id_);
190 views::FocusManager* focus_manager =
191 views::FocusManager::GetFocusManagerForNativeView(run_state.owner);
192 if (focus_manager) {
193 // We need to clear focus as when the focus is restored when the dialog
194 // is closed, only setting the native focus fails. Meaning the focused
195 // manager still believes the right view has focus, and would ignore
196 // requesting focus to what it thinks is already focused.
197 focus_manager->ClearFocus();
198 view_to_focus->RequestFocus();
199 } else {
200 NOTREACHED();
201 }
202 }
203 } 162 }
204 DCHECK(run_state.dialog_thread); 163 DCHECK(run_state.dialog_thread);
205 delete run_state.dialog_thread; 164 delete run_state.dialog_thread;
206 } 165 }
207 166
208 bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const { 167 bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
209 return (owner && owners_.find(owner) != owners_.end()); 168 return (owner && owners_.find(owner) != owners_.end());
210 } 169 }
211 170
212 void BaseShellDialogImpl::DisableOwner(HWND owner) { 171 void BaseShellDialogImpl::DisableOwner(HWND owner) {
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { 741 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) {
783 if (listener_) 742 if (listener_)
784 listener_->FontSelectionCanceled(params); 743 listener_->FontSelectionCanceled(params);
785 EndRun(run_state); 744 EndRun(run_state);
786 } 745 }
787 746
788 // static 747 // static
789 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { 748 SelectFontDialog* SelectFontDialog::Create(Listener* listener) {
790 return new SelectFontDialogImpl(listener); 749 return new SelectFontDialogImpl(listener);
791 } 750 }
OLDNEW
« no previous file with comments | « no previous file | views/widget/widget_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698