diff --git a/source/detail/mswin/platform_spec.hpp b/source/detail/mswin/platform_spec.hpp index a1845683..3505f6e3 100644 --- a/source/detail/mswin/platform_spec.hpp +++ b/source/detail/mswin/platform_spec.hpp @@ -1,7 +1,7 @@ /* * Platform Specification Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at diff --git a/source/detail/platform_spec_posix.cpp b/source/detail/platform_spec_posix.cpp index 8baf1d8f..da46d6ea 100644 --- a/source/detail/platform_spec_posix.cpp +++ b/source/detail/platform_spec_posix.cpp @@ -588,16 +588,59 @@ namespace detail } //There are three members make_owner(), get_owner() and remove(), - //they are maintain a table to discribe the owner of windows because the feature in X11, the + //they are maintain a table to discribe the owner of windows because of the feature in X11, the //owner of top level window must be RootWindow. void platform_spec::make_owner(native_window_type owner, native_window_type wd) { - platform_scope_guard psg; + platform_scope_guard lock; wincontext_[wd].owner = owner; - window_context_t & context = wincontext_[owner]; - if(context.owned == 0) - context.owned = new std::vector; - context.owned->push_back(wd); + + auto& owner_ctx = wincontext_[owner]; + if(!owner_ctx.owned) + owner_ctx.owned = new std::vector; + owner_ctx.owned->push_back(wd); + } + + bool platform_spec::umake_owner(native_window_type child) + { + platform_scope_guard lock; + + auto i = wincontext_.find(child); + if(i == wincontext_.end()) + return false; + + if(i->second.owner) + { + auto u = wincontext_.find(i->second.owner); + if(u != wincontext_.end()) + { + auto * owned = u->second.owned; + if(owned) + { + auto j = std::find(owned->begin(), owned->end(), child); + if(j != owned->end()) + owned->erase(j); + + if(owned->empty()) + { + delete owned; + u->second.owned = nullptr; + //The owner owns no child. If it is not a child of other owners, + //remove it. + if(nullptr == u->second.owner) + wincontext_.erase(u); + } + } + } + + i->second.owner = nullptr; + } + + //Don't remove the ownerships which the child is a owner window. + if(nullptr == i->second.owned) + wincontext_.erase(i); + + return true; } native_window_type platform_spec::get_owner(native_window_type wd) const @@ -610,7 +653,9 @@ namespace detail void platform_spec::remove(native_window_type wd) { msg_dispatcher_->erase(reinterpret_cast(wd)); - platform_scope_guard psg; + + platform_scope_guard lock; +#if 0 auto i = wincontext_.find(wd); if(i == wincontext_.end()) return; @@ -641,6 +686,28 @@ namespace detail } delete vec; wincontext_.erase(i); +#else + if(umake_owner(wd)) + { + auto i = wincontext_.find(wd); + if(i != wincontext_.end()) + { + if(i->second.owned) + { + set_error_handler(); + auto & wd_manager = detail::bedrock::instance().wd_manager(); + for(auto u = i->second.owned->rbegin(); u != i->second.owned->rend(); ++u) + wd_manager.close(wd_manager.root(*u)); + + rev_error_handler(); + + delete i->second.owned; + } + + wincontext_.erase(i); + } + } +#endif iconbase_.erase(wd); } diff --git a/source/detail/platform_spec_windows.cpp b/source/detail/platform_spec_windows.cpp index 179b87cf..812c2ed0 100644 --- a/source/detail/platform_spec_windows.cpp +++ b/source/detail/platform_spec_windows.cpp @@ -1,7 +1,7 @@ /** * Platform Specification Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at diff --git a/source/detail/posix/platform_spec.hpp b/source/detail/posix/platform_spec.hpp index e8b2be24..167295bb 100644 --- a/source/detail/posix/platform_spec.hpp +++ b/source/detail/posix/platform_spec.hpp @@ -1,7 +1,7 @@ /* * Platform Specification Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -213,6 +213,9 @@ namespace detail const atombase_tag & atombase() const; void make_owner(native_window_type owner, native_window_type wd); + + // Cancel the ownership + bool umake_owner(native_window_type child); native_window_type get_owner(native_window_type) const; void remove(native_window_type); diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index aee3ea8e..ed1e5772 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -296,6 +296,8 @@ namespace nana{ win_attr.save_under = True; attr_mask |= CWSaveUnder; + ///The parameter of XCreateWindow to create a top level window must be root. + ///But after creation, the real parent is the reparenting frame window. parent = restrict::spec.root_window(); calc_screen_point(owner, pos); } @@ -309,9 +311,10 @@ namespace nana{ if(handle) { //make owner if it is a popup window - if((!nested) && owner) + if(!nested) { - restrict::spec.make_owner(owner, reinterpret_cast(handle)); + auto origin_owner = (owner ? owner : reinterpret_cast(restrict::spec.root_window())); + restrict::spec.make_owner(origin_owner, reinterpret_cast(handle)); exposed_positions[handle] = pos; } @@ -1222,7 +1225,7 @@ namespace nana{ Window drop_wd; int x, y; unsigned mask; - nana::detail::platform_scope_guard psg; + nana::detail::platform_scope_guard lock; ::XQueryPointer(restrict::spec.open_display(), restrict::spec.root_window(), &drop_wd, &drop_wd, &pos.x, &pos.y, &x, &y, &mask); return pos; #endif @@ -1278,9 +1281,19 @@ namespace nana{ if(returns_previous) prev = parent_window(child); + if(native_window_type{} == new_parent) + new_parent = reinterpret_cast(restrict::spec.root_window()); + ::XReparentWindow(restrict::spec.open_display(), reinterpret_cast(child), reinterpret_cast(new_parent), 0, 0); + + + // If umake_owner returns true, it indicates the child windows is a popup window. + // So make the ownership of new_parent and child. + if(restrict::spec.umake_owner(child)) + restrict::spec.make_owner(new_parent, child); + return prev; #endif } diff --git a/source/gui/widgets/scroll.cpp b/source/gui/widgets/scroll.cpp index 01684d2b..10b2c6da 100644 --- a/source/gui/widgets/scroll.cpp +++ b/source/gui/widgets/scroll.cpp @@ -99,7 +99,7 @@ namespace nana //Check scroll_area to avoiding division by zero. if (scroll_area) - metrics_.value = pos * (static_cast(value_max) / scroll_area); //converting to double to avoid overflow. + metrics_.value = static_cast(pos * (static_cast(value_max) / scroll_area)); //converting to double to avoid overflow. if (metrics_.value < value_max) { diff --git a/source/gui/widgets/treebox.cpp b/source/gui/widgets/treebox.cpp index c68abb4c..3cbf61b7 100644 --- a/source/gui/widgets/treebox.cpp +++ b/source/gui/widgets/treebox.cpp @@ -1853,7 +1853,6 @@ namespace nana item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y); impl_->attr.tree_cont.for_each(shape.first, nl); - auto & node_state = impl_->node_state; node_state.pressed_node = nl.node(); @@ -1869,7 +1868,6 @@ namespace nana else return; - impl_->draw(true); API::dev::lazy_refresh(); }