OLD | NEW |
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 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 #include <set> | 12 #include <set> |
13 | 13 |
14 #include "app/gfx/font.h" | 14 #include "app/gfx/font.h" |
15 #include "app/l10n_util.h" | 15 #include "app/l10n_util.h" |
16 #include "app/win_util.h" | 16 #include "app/win_util.h" |
17 #include "base/file_util.h" | 17 #include "base/file_util.h" |
18 #include "base/registry.h" | 18 #include "base/registry.h" |
19 #include "base/scoped_comptr_win.h" | 19 #include "base/scoped_comptr_win.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/chrome_thread.h" |
23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
24 | 24 |
25 // 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 |
26 // block the UI of the entire app. | 26 // block the UI of the entire app. |
27 | 27 |
28 class ShellDialogThread : public base::Thread { | 28 class ShellDialogThread : public base::Thread { |
29 public: | 29 public: |
30 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } | 30 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } |
31 | 31 |
32 protected: | 32 protected: |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 // Disables the window |owner|. Can be run from either the ui or the dialog | 83 // Disables the window |owner|. Can be run from either the ui or the dialog |
84 // thread. Can be called on either the UI or the dialog thread. This function | 84 // thread. Can be called on either the UI or the dialog thread. This function |
85 // is called on the dialog thread after the modal Windows Common dialog | 85 // is called on the dialog thread after the modal Windows Common dialog |
86 // functions return because Windows automatically re-enables the owning | 86 // functions return because Windows automatically re-enables the owning |
87 // window when those functions return, but we don't actually want them to be | 87 // window when those functions return, but we don't actually want them to be |
88 // re-enabled until the response of the dialog propagates back to the UI | 88 // re-enabled until the response of the dialog propagates back to the UI |
89 // thread, so we disable the owner manually after the Common dialog function | 89 // thread, so we disable the owner manually after the Common dialog function |
90 // returns. | 90 // returns. |
91 void DisableOwner(HWND owner); | 91 void DisableOwner(HWND owner); |
92 | 92 |
93 // The UI thread's message loop. | |
94 MessageLoop* ui_loop_; | |
95 | |
96 private: | 93 private: |
97 // Creates a thread to run a shell dialog on. Each dialog requires its own | 94 // Creates a thread to run a shell dialog on. Each dialog requires its own |
98 // thread otherwise in some situations where a singleton owns a single | 95 // thread otherwise in some situations where a singleton owns a single |
99 // instance of this object we can have a situation where a modal dialog in | 96 // instance of this object we can have a situation where a modal dialog in |
100 // one window blocks the appearance of a modal dialog in another. | 97 // one window blocks the appearance of a modal dialog in another. |
101 static base::Thread* CreateDialogThread(); | 98 static base::Thread* CreateDialogThread(); |
102 | 99 |
103 // Enables the window |owner_|. Can only be run from the ui thread. | 100 // Enables the window |owner_|. Can only be run from the ui thread. |
104 void EnableOwner(HWND owner); | 101 void EnableOwner(HWND owner); |
105 | 102 |
(...skipping 13 matching lines...) Expand all Loading... |
119 static Owners owners_; | 116 static Owners owners_; |
120 static int instance_count_; | 117 static int instance_count_; |
121 | 118 |
122 DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl); | 119 DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl); |
123 }; | 120 }; |
124 | 121 |
125 // static | 122 // static |
126 BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_; | 123 BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_; |
127 int BaseShellDialogImpl::instance_count_ = 0; | 124 int BaseShellDialogImpl::instance_count_ = 0; |
128 | 125 |
129 BaseShellDialogImpl::BaseShellDialogImpl() | 126 BaseShellDialogImpl::BaseShellDialogImpl() { |
130 : ui_loop_(MessageLoop::current()) { | |
131 ++instance_count_; | 127 ++instance_count_; |
132 } | 128 } |
133 | 129 |
134 BaseShellDialogImpl::~BaseShellDialogImpl() { | 130 BaseShellDialogImpl::~BaseShellDialogImpl() { |
135 // All runs should be complete by the time this is called! | 131 // All runs should be complete by the time this is called! |
136 if (--instance_count_ == 0) | 132 if (--instance_count_ == 0) |
137 DCHECK(owners_.empty()); | 133 DCHECK(owners_.empty()); |
138 } | 134 } |
139 | 135 |
140 BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) { | 136 BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 path = FilePath::FromWStringHack(path_as_wstring); | 361 path = FilePath::FromWStringHack(path_as_wstring); |
366 } | 362 } |
367 DisableOwner(params.run_state.owner); | 363 DisableOwner(params.run_state.owner); |
368 } else if (params.type == SELECT_OPEN_FILE) { | 364 } else if (params.type == SELECT_OPEN_FILE) { |
369 success = RunOpenFileDialog(params.title, filter, | 365 success = RunOpenFileDialog(params.title, filter, |
370 params.run_state.owner, &path); | 366 params.run_state.owner, &path); |
371 } else if (params.type == SELECT_OPEN_MULTI_FILE) { | 367 } else if (params.type == SELECT_OPEN_MULTI_FILE) { |
372 std::vector<FilePath> paths; | 368 std::vector<FilePath> paths; |
373 if (RunOpenMultiFileDialog(params.title, filter, | 369 if (RunOpenMultiFileDialog(params.title, filter, |
374 params.run_state.owner, &paths)) { | 370 params.run_state.owner, &paths)) { |
375 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 371 ChromeThread::PostTask( |
376 &SelectFileDialogImpl::MultiFilesSelected, | 372 ChromeThread::UI, FROM_HERE, |
377 paths, params.params, params.run_state)); | 373 NewRunnableMethod( |
| 374 this, &SelectFileDialogImpl::MultiFilesSelected, paths, |
| 375 params.params, params.run_state)); |
378 return; | 376 return; |
379 } | 377 } |
380 } | 378 } |
381 | 379 |
382 if (success) { | 380 if (success) { |
383 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 381 ChromeThread::PostTask( |
384 &SelectFileDialogImpl::FileSelected, path, filter_index, | 382 ChromeThread::UI, FROM_HERE, |
385 params.params, params.run_state)); | 383 NewRunnableMethod( |
| 384 this, &SelectFileDialogImpl::FileSelected, path, filter_index, |
| 385 params.params, params.run_state)); |
386 } else { | 386 } else { |
387 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 387 ChromeThread::PostTask( |
388 &SelectFileDialogImpl::FileNotSelected, params.params, | 388 ChromeThread::UI, FROM_HERE, |
389 params.run_state)); | 389 NewRunnableMethod( |
| 390 this, &SelectFileDialogImpl::FileNotSelected, params.params, |
| 391 params.run_state)); |
390 } | 392 } |
391 } | 393 } |
392 | 394 |
393 void SelectFileDialogImpl::FileSelected(const FilePath& selected_folder, | 395 void SelectFileDialogImpl::FileSelected(const FilePath& selected_folder, |
394 int index, | 396 int index, |
395 void* params, | 397 void* params, |
396 RunState run_state) { | 398 RunState run_state) { |
397 if (listener_) | 399 if (listener_) |
398 listener_->FileSelected(selected_folder, index, params); | 400 listener_->FileSelected(selected_folder, index, params); |
399 EndRun(run_state); | 401 EndRun(run_state); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 void SelectFontDialogImpl::ExecuteSelectFont(RunState run_state, void* params) { | 652 void SelectFontDialogImpl::ExecuteSelectFont(RunState run_state, void* params) { |
651 LOGFONT logfont; | 653 LOGFONT logfont; |
652 CHOOSEFONT cf; | 654 CHOOSEFONT cf; |
653 cf.lStructSize = sizeof(cf); | 655 cf.lStructSize = sizeof(cf); |
654 cf.hwndOwner = run_state.owner; | 656 cf.hwndOwner = run_state.owner; |
655 cf.lpLogFont = &logfont; | 657 cf.lpLogFont = &logfont; |
656 cf.Flags = CF_SCREENFONTS; | 658 cf.Flags = CF_SCREENFONTS; |
657 bool success = !!ChooseFont(&cf); | 659 bool success = !!ChooseFont(&cf); |
658 DisableOwner(run_state.owner); | 660 DisableOwner(run_state.owner); |
659 if (success) { | 661 if (success) { |
660 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 662 ChromeThread::PostTask( |
661 &SelectFontDialogImpl::FontSelected, logfont, params, run_state)); | 663 ChromeThread::UI, FROM_HERE, |
| 664 NewRunnableMethod( |
| 665 this, &SelectFontDialogImpl::FontSelected, logfont, params, |
| 666 run_state)); |
662 } else { | 667 } else { |
663 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 668 ChromeThread::PostTask( |
664 &SelectFontDialogImpl::FontNotSelected, params, run_state)); | 669 ChromeThread::UI, FROM_HERE, |
| 670 NewRunnableMethod( |
| 671 this, &SelectFontDialogImpl::FontNotSelected, params, run_state)); |
665 } | 672 } |
666 } | 673 } |
667 | 674 |
668 void SelectFontDialogImpl::ExecuteSelectFontWithNameSize( | 675 void SelectFontDialogImpl::ExecuteSelectFontWithNameSize( |
669 RunState run_state, void* params, const std::wstring& font_name, | 676 RunState run_state, void* params, const std::wstring& font_name, |
670 int font_size) { | 677 int font_size) { |
671 // Create the HFONT from font name and size. | 678 // Create the HFONT from font name and size. |
672 HDC hdc = GetDC(NULL); | 679 HDC hdc = GetDC(NULL); |
673 long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72); | 680 long lf_height = -MulDiv(font_size, GetDeviceCaps(hdc, LOGPIXELSY), 72); |
674 ReleaseDC(NULL, hdc); | 681 ReleaseDC(NULL, hdc); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 CF_NOVERTFONTS | CF_SCRIPTSONLY | CF_LIMITSIZE; | 715 CF_NOVERTFONTS | CF_SCRIPTSONLY | CF_LIMITSIZE; |
709 | 716 |
710 // These limits are arbitrary and needs to be revisited. Is it bad | 717 // These limits are arbitrary and needs to be revisited. Is it bad |
711 // to clamp the size at 40 from A11Y point of view? | 718 // to clamp the size at 40 from A11Y point of view? |
712 cf.nSizeMin = 8; | 719 cf.nSizeMin = 8; |
713 cf.nSizeMax = 40; | 720 cf.nSizeMax = 40; |
714 | 721 |
715 bool success = !!ChooseFont(&cf); | 722 bool success = !!ChooseFont(&cf); |
716 DisableOwner(run_state.owner); | 723 DisableOwner(run_state.owner); |
717 if (success) { | 724 if (success) { |
718 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 725 ChromeThread::PostTask( |
719 &SelectFontDialogImpl::FontSelected, logfont, params, run_state)); | 726 ChromeThread::UI, FROM_HERE, |
| 727 NewRunnableMethod( |
| 728 this, &SelectFontDialogImpl::FontSelected, logfont, params, |
| 729 run_state)); |
720 } else { | 730 } else { |
721 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 731 ChromeThread::PostTask( |
722 &SelectFontDialogImpl::FontNotSelected, params, run_state)); | 732 ChromeThread::UI, FROM_HERE, |
| 733 NewRunnableMethod(this, &SelectFontDialogImpl::FontNotSelected, params, |
| 734 run_state)); |
723 } | 735 } |
724 } | 736 } |
725 | 737 |
726 void SelectFontDialogImpl::FontSelected(LOGFONT logfont, | 738 void SelectFontDialogImpl::FontSelected(LOGFONT logfont, |
727 void* params, | 739 void* params, |
728 RunState run_state) { | 740 RunState run_state) { |
729 if (listener_) { | 741 if (listener_) { |
730 HFONT font = CreateFontIndirect(&logfont); | 742 HFONT font = CreateFontIndirect(&logfont); |
731 if (font) { | 743 if (font) { |
732 listener_->FontSelected(gfx::Font::CreateFont(font), params); | 744 listener_->FontSelected(gfx::Font::CreateFont(font), params); |
733 DeleteObject(font); | 745 DeleteObject(font); |
734 } else { | 746 } else { |
735 listener_->FontSelectionCanceled(params); | 747 listener_->FontSelectionCanceled(params); |
736 } | 748 } |
737 } | 749 } |
738 EndRun(run_state); | 750 EndRun(run_state); |
739 } | 751 } |
740 | 752 |
741 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { | 753 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { |
742 if (listener_) | 754 if (listener_) |
743 listener_->FontSelectionCanceled(params); | 755 listener_->FontSelectionCanceled(params); |
744 EndRun(run_state); | 756 EndRun(run_state); |
745 } | 757 } |
746 | 758 |
747 // static | 759 // static |
748 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { | 760 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { |
749 return new SelectFontDialogImpl(listener); | 761 return new SelectFontDialogImpl(listener); |
750 } | 762 } |
OLD | NEW |