From 253bacdf1d9c4eb925971859faafe4d5b8a21c51 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Dec 2014 11:27:38 -0800 Subject: [PATCH 1/3] win: Run async open dialog in new thread --- atom/browser/ui/file_dialog_win.cc | 46 ++++++++++++++++++++++++------ common.gypi | 1 + 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index 0bd0c521af87..804c0b279139 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -15,6 +15,7 @@ #include "base/strings/string_util.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread.h" #include "base/win/registry.h" #include "third_party/wtl/include/atlapp.h" #include "third_party/wtl/include/atldlgs.h" @@ -113,6 +114,26 @@ class FileDialog { DISALLOW_COPY_AND_ASSIGN(FileDialog); }; +struct RunState { + base::Thread* dialog_thread; + base::MessageLoop* ui_message_loop; +}; + +void RunOpenDialogInNewThread(const RunState& run_state, + atom::NativeWindow* parent, + const std::string& title, + const base::FilePath& default_path, + const Filters& filters, + int properties, + const OpenDialogCallback& callback) { + std::vector paths; + bool result = ShowOpenDialog(parent, title, default_path, filters, properties, + &paths); + run_state.ui_message_loop->PostTask(FROM_HERE, + base::Bind(callback, result, paths)); + run_state.ui_message_loop->DeleteSoon(FROM_HERE, run_state.dialog_thread); +} + } // namespace bool ShowOpenDialog(atom::NativeWindow* parent_window, @@ -162,20 +183,27 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window, return true; } -void ShowOpenDialog(atom::NativeWindow* parent_window, +void ShowOpenDialog(atom::NativeWindow* parent, const std::string& title, const base::FilePath& default_path, const Filters& filters, int properties, const OpenDialogCallback& callback) { - std::vector paths; - bool result = ShowOpenDialog(parent_window, - title, - default_path, - filters, - properties, - &paths); - callback.Run(result, paths); + base::Thread* thread = new base::Thread("AtomShell_FileDialogThread"); + thread->init_com_with_mta(false); + if (!thread->Start()) + return; + + if (parent) + EnableWindow( + static_cast(parent)->GetAcceleratedWidget(), + FALSE); + + RunState state = { thread, base::MessageLoop::current() }; + thread->message_loop()->PostTask( + FROM_HERE, + base::Bind(&RunOpenDialogInNewThread, state, parent, title, default_path, + filters, properties, callback)); } bool ShowSaveDialog(atom::NativeWindow* parent_window, diff --git a/common.gypi b/common.gypi index 7ee6d494a4dc..68d9418f23ed 100644 --- a/common.gypi +++ b/common.gypi @@ -136,6 +136,7 @@ 4005, # (node.h) macro redefinition 4189, # local variable is initialized but not referenced 4201, # (uv.h) nameless struct/union + 4503, # decorated name length exceeded, name was truncated 4800, # (v8.h) forcing value to bool 'true' or 'false' 4819, # The file contains a character that cannot be represented in the current code page 4996, # (atlapp.h) 'GetVersionExW': was declared deprecated From c20e1e9d82456ee750196fab30b197770bbf3420 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Dec 2014 12:27:26 -0800 Subject: [PATCH 2/3] win: Run async save dialog in new thread --- atom/browser/ui/file_dialog_win.cc | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index 804c0b279139..80281d885318 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -134,6 +134,19 @@ void RunOpenDialogInNewThread(const RunState& run_state, run_state.ui_message_loop->DeleteSoon(FROM_HERE, run_state.dialog_thread); } +void RunSaveDialogInNewThread(const RunState& run_state, + atom::NativeWindow* parent, + const std::string& title, + const base::FilePath& default_path, + const Filters& filters, + const SaveDialogCallback& callback) { + base::FilePath path; + bool result = ShowSaveDialog(parent, title, default_path, filters, &path); + run_state.ui_message_loop->PostTask(FROM_HERE, + base::Bind(callback, result, path)); + run_state.ui_message_loop->DeleteSoon(FROM_HERE, run_state.dialog_thread); +} + } // namespace bool ShowOpenDialog(atom::NativeWindow* parent_window, @@ -194,11 +207,6 @@ void ShowOpenDialog(atom::NativeWindow* parent, if (!thread->Start()) return; - if (parent) - EnableWindow( - static_cast(parent)->GetAcceleratedWidget(), - FALSE); - RunState state = { thread, base::MessageLoop::current() }; thread->message_loop()->PostTask( FROM_HERE, @@ -246,15 +254,21 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, return true; } -void ShowSaveDialog(atom::NativeWindow* parent_window, +void ShowSaveDialog(atom::NativeWindow* parent, const std::string& title, const base::FilePath& default_path, const Filters& filters, const SaveDialogCallback& callback) { - base::FilePath path; - bool result = ShowSaveDialog(parent_window, title, default_path, filters, - &path); - callback.Run(result, path); + base::Thread* thread = new base::Thread("AtomShell_FileDialogThread"); + thread->init_com_with_mta(false); + if (!thread->Start()) + return; + + RunState state = { thread, base::MessageLoop::current() }; + thread->message_loop()->PostTask( + FROM_HERE, + base::Bind(&RunSaveDialogInNewThread, state, parent, title, default_path, + filters, callback)); } } // namespace file_dialog From 63e83a7ef88191be32b93d40a2ace9194f03a04a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 16 Dec 2014 12:33:17 -0800 Subject: [PATCH 3/3] win: Don't hang when failed to create thread --- atom/browser/ui/file_dialog_win.cc | 39 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/atom/browser/ui/file_dialog_win.cc b/atom/browser/ui/file_dialog_win.cc index 80281d885318..47e2c72a6d8f 100644 --- a/atom/browser/ui/file_dialog_win.cc +++ b/atom/browser/ui/file_dialog_win.cc @@ -119,6 +119,17 @@ struct RunState { base::MessageLoop* ui_message_loop; }; +bool CreateDialogThread(RunState* run_state) { + base::Thread* thread = new base::Thread("AtomShell_FileDialogThread"); + thread->init_com_with_mta(false); + if (!thread->Start()) + return false; + + run_state->dialog_thread = thread; + run_state->ui_message_loop = base::MessageLoop::current(); + return true; +} + void RunOpenDialogInNewThread(const RunState& run_state, atom::NativeWindow* parent, const std::string& title, @@ -202,16 +213,16 @@ void ShowOpenDialog(atom::NativeWindow* parent, const Filters& filters, int properties, const OpenDialogCallback& callback) { - base::Thread* thread = new base::Thread("AtomShell_FileDialogThread"); - thread->init_com_with_mta(false); - if (!thread->Start()) + RunState run_state; + if (!CreateDialogThread(&run_state)) { + callback.Run(false, std::vector()); return; + } - RunState state = { thread, base::MessageLoop::current() }; - thread->message_loop()->PostTask( + run_state.dialog_thread->message_loop()->PostTask( FROM_HERE, - base::Bind(&RunOpenDialogInNewThread, state, parent, title, default_path, - filters, properties, callback)); + base::Bind(&RunOpenDialogInNewThread, run_state, parent, title, + default_path, filters, properties, callback)); } bool ShowSaveDialog(atom::NativeWindow* parent_window, @@ -259,16 +270,16 @@ void ShowSaveDialog(atom::NativeWindow* parent, const base::FilePath& default_path, const Filters& filters, const SaveDialogCallback& callback) { - base::Thread* thread = new base::Thread("AtomShell_FileDialogThread"); - thread->init_com_with_mta(false); - if (!thread->Start()) + RunState run_state; + if (!CreateDialogThread(&run_state)) { + callback.Run(false, base::FilePath()); return; + } - RunState state = { thread, base::MessageLoop::current() }; - thread->message_loop()->PostTask( + run_state.dialog_thread->message_loop()->PostTask( FROM_HERE, - base::Bind(&RunSaveDialogInNewThread, state, parent, title, default_path, - filters, callback)); + base::Bind(&RunSaveDialogInNewThread, run_state, parent, title, + default_path, filters, callback)); } } // namespace file_dialog