diff --git a/include/nana/detail/win32/platform_spec.hpp b/include/nana/detail/win32/platform_spec.hpp index dba6062a..179204e5 100644 --- a/include/nana/detail/win32/platform_spec.hpp +++ b/include/nana/detail/win32/platform_spec.hpp @@ -1,7 +1,7 @@ /* * Platform Specification Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -25,6 +25,7 @@ #include #include #include +#include namespace nana { @@ -63,9 +64,15 @@ namespace detail bool forced; }; + struct arg_affinity_execute + { + const std::function * function_ptr; + }; + enum { tray = 0x501, + async_activate, async_set_focus, map_thread_root_buffer, @@ -74,6 +81,10 @@ namespace detail operate_caret, //wParam: 1=Destroy, 2=SetPos remote_thread_set_window_pos, remote_thread_set_window_text, + + //Execute a function in a thread with is associated with a specified native window + affinity_execute, + user, }; }; diff --git a/include/nana/gui/detail/internal_scope_guard.hpp b/include/nana/gui/detail/internal_scope_guard.hpp index c4bdaaf6..6ad8ae80 100644 --- a/include/nana/gui/detail/internal_scope_guard.hpp +++ b/include/nana/gui/detail/internal_scope_guard.hpp @@ -1,7 +1,7 @@ /* * Forward Declaration of Internal Scope Guard * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -26,6 +26,18 @@ namespace nana internal_scope_guard(); ~internal_scope_guard(); }; + + class internal_revert_guard + { + internal_revert_guard(const internal_revert_guard&) = delete; + internal_revert_guard(internal_revert_guard&&) = delete; + + internal_revert_guard& operator=(const internal_revert_guard&) = delete; + internal_revert_guard& operator=(internal_revert_guard&&) = delete; + public: + internal_revert_guard(); + ~internal_revert_guard(); + }; } #endif \ No newline at end of file diff --git a/include/nana/gui/detail/native_window_interface.hpp b/include/nana/gui/detail/native_window_interface.hpp index aade67a5..737423bf 100644 --- a/include/nana/gui/detail/native_window_interface.hpp +++ b/include/nana/gui/detail/native_window_interface.hpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -36,6 +36,9 @@ namespace detail using native_string_type = ::nana::detail::native_string_type; + //Execute a function in a thread which is associated with the specified native window. + static void affinity_execute(native_window_type, const std::function&); + static nana::size primary_monitor_size(); static rectangle screen_area_from_point(const point&); static window_result create_window(native_window_type, bool nested, const rectangle&, const appearance&); diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index db8ffc1c..ffb5a5dd 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -60,6 +60,8 @@ namespace API //@brief: The interfaces defined in namespace dev are used for developing the nana.gui namespace dev { + void affinity_execute(window window_handle, const std::function&); + bool set_events(window, const std::shared_ptr&); template diff --git a/include/nana/pat/cloneable.hpp b/include/nana/pat/cloneable.hpp index 7cff2638..c6f5d1c9 100644 --- a/include/nana/pat/cloneable.hpp +++ b/include/nana/pat/cloneable.hpp @@ -97,13 +97,6 @@ namespace nana{ namespace pat{ typedef int inner_bool::* operator_bool_t; - /* - template - struct member_enabled //deprecated - : public std::enable_if<(!std::is_base_of::type>::value) && std::is_base_of::type>::value, int> - {}; - */ - template using member_enabled = std::enable_if<(!std::is_base_of::type>::value) && std::is_base_of::type>::value, int>; public: diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 830887ea..f4716435 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -1,7 +1,7 @@ /* * A Bedrock Platform-Independent Implementation * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -36,6 +36,18 @@ namespace nana detail::bedrock::instance().wd_manager().internal_lock().unlock(); } //end class internal_scope_guard + + //class internal_revert_guard + internal_revert_guard::internal_revert_guard() + { + detail::bedrock::instance().wd_manager().internal_lock().revert(); + } + + internal_revert_guard::~internal_revert_guard() + { + detail::bedrock::instance().wd_manager().internal_lock().forward(); + } + //end class internal_revert_guard //class event_arg void event_arg::stop_propagation() const diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index bf1b5c28..7bd5d505 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -669,6 +669,14 @@ namespace detail case nana::detail::messages::tray: notifications_window_proc(wd, wParam, lParam); return true; + case nana::detail::messages::affinity_execute: + if (wParam) + { + auto arg = reinterpret_cast(wParam); + if (arg->function_ptr) + (*arg->function_ptr)(); + } + break; default: break; } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index 258f3d1c..b21eb270 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -13,6 +13,9 @@ #include #include #include +#include +#include + #if defined(NANA_WINDOWS) #if defined(STD_THREAD_NOT_SUPPORTED) #include @@ -23,8 +26,6 @@ #include "../../paint/detail/image_ico.hpp" #elif defined(NANA_X11) #include - #include - #include #endif namespace nana{ @@ -131,9 +132,13 @@ namespace nana{ } } if (async) + { ::ShowWindowAsync(wd, cmd); - else - ::ShowWindow(wd, cmd); + return; + } + + internal_revert_guard revert; + ::ShowWindow(wd, cmd); } #elif defined(NANA_X11) namespace restrict @@ -143,6 +148,33 @@ namespace nana{ #endif //struct native_interface + void native_interface::affinity_execute(native_window_type native_handle, const std::function& fn) + { + if (!fn) + return; + +#if defined(NANA_WINDOWS) + auto mswin = reinterpret_cast(native_handle); + if (::IsWindow(mswin)) + { + if (::GetCurrentThreadId() != ::GetWindowThreadProcessId(mswin, nullptr)) + { + detail::messages::arg_affinity_execute arg; + arg.function_ptr = &fn; + + internal_revert_guard revert; + ::SendMessage(mswin, detail::messages::affinity_execute, reinterpret_cast(&arg), 0); + + return; + } + } + + fn(); +#else + fn(); +#endif + } + nana::size native_interface::primary_monitor_size() { #if defined(NANA_WINDOWS) @@ -1119,11 +1151,18 @@ namespace nana{ auto native_interface::window_caption(native_window_type wd) -> native_string_type { + native_string_type str; + #if defined(NANA_WINDOWS) + auto & lock = bedrock::instance().wd_manager().internal_lock(); + bool is_current_thread = (::GetCurrentThreadId() == ::GetWindowThreadProcessId(reinterpret_cast(wd), nullptr)); + + if (!is_current_thread) + lock.revert(); + int length = ::GetWindowTextLength(reinterpret_cast(wd)); if(length > 0) { - native_string_type str; //One for NULL terminator which GetWindowText will write. str.resize(length+1); @@ -1131,9 +1170,11 @@ namespace nana{ //Remove the null terminator writtien by GetWindowText str.resize(length); - - return str; } + + if (!is_current_thread) + lock.forward(); + #elif defined(NANA_X11) nana::detail::platform_scope_guard psg; ::XTextProperty txtpro; @@ -1145,14 +1186,13 @@ namespace nana{ { if(size > 1) { - std::string text = *strlist; + str = *strlist; ::XFreeStringList(strlist); - return text; } } } #endif - return native_string_type(); + return str; } void native_interface::capture_window(native_window_type wd, bool cap) @@ -1314,7 +1354,10 @@ namespace nana{ if(::GetCurrentThreadId() != ::GetWindowThreadProcessId(reinterpret_cast(wd), nullptr)) ::PostMessage(reinterpret_cast(wd), nana::detail::messages::async_set_focus, 0, 0); else + { + internal_revert_guard revert; ::SetFocus(reinterpret_cast(wd)); + } } #elif defined(NANA_X11) nana::detail::platform_scope_guard lock; diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 25708b93..da6291f1 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -1,7 +1,7 @@ /* * Parts of Class Place * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -277,66 +277,11 @@ namespace nana void add_pane(factory & fn) { - rectangle r{ point(), this->size()}; - - //get a rectangle excluding caption - r.y = 20; - if (r.height > 20) - r.height -= 20; - else - r.height = 0; - - if (!tabbar_) + auto fn_ptr = &fn; + API::dev::affinity_execute(*this, [this, fn_ptr] { - if (panels_.size() > 0) - { - tabbar_.reset(new tabbar_lite(*this)); - - tabbar_->events().selected.clear(); - tabbar_->events().selected([this] - { - auto handle = tabbar_->attach(tabbar_->selected()); - if (handle) - caption_.caption(API::window_caption(handle)); - else - caption_.caption(::std::string()); - }); - - tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); - r.height -= 20; - - std::size_t pos = 0; - for (auto & pn : panels_) - { - tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); - tabbar_->attach(pos++, *pn.widget_ptr); - } - } - } - else - r.height -= 20; - - auto wdg = fn(*this); - - if (tabbar_) - { - tabbar_->push_back(::nana::charset(wdg->caption())); - tabbar_->attach(panels_.size(), wdg->handle()); - } - - if (panels_.empty()) - { - caption_.caption(wdg->caption()); - } - - panels_.emplace_back(); - panels_.back().widget_ptr.swap(wdg); - - for (auto & pn : panels_) - { - if (pn.widget_ptr) - pn.widget_ptr->move(r); - } + _m_add_pane(*fn_ptr); + }); } void float_away(const ::nana::point& move_pos) @@ -382,6 +327,72 @@ namespace nana { return (nullptr != container_); } + private: + void _m_add_pane(factory & fn) + { + rectangle r{ point(), this->size() }; + + //get a rectangle excluding caption + r.y = 20; + if (r.height > 20) + r.height -= 20; + else + r.height = 0; + + if (!tabbar_) + { + if (panels_.size() > 0) + { + tabbar_.reset(new tabbar_lite(*this)); + + tabbar_->events().selected.clear(); + tabbar_->events().selected([this] + { + auto handle = tabbar_->attach(tabbar_->selected()); + if (handle) + caption_.caption(API::window_caption(handle)); + else + caption_.caption(::std::string()); + }); + + tabbar_->move({ 0, r.bottom() - 20, r.width, 20 }); + r.height -= 20; + + std::size_t pos = 0; + for (auto & pn : panels_) + { + tabbar_->push_back(::nana::charset(pn.widget_ptr->caption())); + tabbar_->attach(pos++, *pn.widget_ptr); + } + } + } + else + r.height -= 20; + + auto wdg = fn(*this); + if (wdg) + { + if (tabbar_) + { + tabbar_->push_back(::nana::charset(wdg->caption())); + tabbar_->attach(panels_.size(), wdg->handle()); + } + + if (panels_.empty()) + { + caption_.caption(wdg->caption()); + } + + panels_.emplace_back(); + panels_.back().widget_ptr.swap(wdg); + + for (auto & pn : panels_) + { + if (pn.widget_ptr) + pn.widget_ptr->move(r); + } + } + } private: window host_window_{nullptr}; place_parts::dock_notifier_interface* notifier_{ nullptr }; diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index e36e1a36..d3075bcf 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -179,6 +179,11 @@ namespace API namespace dev { + void affinity_execute(window window_handle, const std::function& fn) + { + interface_type::affinity_execute(root(window_handle), fn); + } + bool set_events(window wd, const std::shared_ptr& gep) { auto iwd = reinterpret_cast(wd);