fix bug that window_position returns the pos of WM reparenting frame

This commit is contained in:
Jinhao 2018-08-01 07:31:02 +08:00
parent df5fda9096
commit 1339658c4c
7 changed files with 97 additions and 16 deletions

View File

@ -1,7 +1,7 @@
/* /*
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at

View File

@ -588,16 +588,59 @@ namespace detail
} }
//There are three members make_owner(), get_owner() and remove(), //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. //owner of top level window must be RootWindow.
void platform_spec::make_owner(native_window_type owner, native_window_type wd) 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; wincontext_[wd].owner = owner;
window_context_t & context = wincontext_[owner];
if(context.owned == 0) auto& owner_ctx = wincontext_[owner];
context.owned = new std::vector<native_window_type>; if(!owner_ctx.owned)
context.owned->push_back(wd); owner_ctx.owned = new std::vector<native_window_type>;
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 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) void platform_spec::remove(native_window_type wd)
{ {
msg_dispatcher_->erase(reinterpret_cast<Window>(wd)); msg_dispatcher_->erase(reinterpret_cast<Window>(wd));
platform_scope_guard psg;
platform_scope_guard lock;
#if 0
auto i = wincontext_.find(wd); auto i = wincontext_.find(wd);
if(i == wincontext_.end()) return; if(i == wincontext_.end()) return;
@ -641,6 +686,28 @@ namespace detail
} }
delete vec; delete vec;
wincontext_.erase(i); 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); iconbase_.erase(wd);
} }

View File

@ -1,7 +1,7 @@
/** /**
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at

View File

@ -1,7 +1,7 @@
/* /*
* Platform Specification Implementation * Platform Specification Implementation
* Nana C++ Library(http://www.nanapro.org) * 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. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@ -213,6 +213,9 @@ namespace detail
const atombase_tag & atombase() const; const atombase_tag & atombase() const;
void make_owner(native_window_type owner, native_window_type wd); 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; native_window_type get_owner(native_window_type) const;
void remove(native_window_type); void remove(native_window_type);

View File

@ -296,6 +296,8 @@ namespace nana{
win_attr.save_under = True; win_attr.save_under = True;
attr_mask |= CWSaveUnder; 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(); parent = restrict::spec.root_window();
calc_screen_point(owner, pos); calc_screen_point(owner, pos);
} }
@ -309,9 +311,10 @@ namespace nana{
if(handle) if(handle)
{ {
//make owner if it is a popup window //make owner if it is a popup window
if((!nested) && owner) if(!nested)
{ {
restrict::spec.make_owner(owner, reinterpret_cast<native_window_type>(handle)); auto origin_owner = (owner ? owner : reinterpret_cast<native_window_type>(restrict::spec.root_window()));
restrict::spec.make_owner(origin_owner, reinterpret_cast<native_window_type>(handle));
exposed_positions[handle] = pos; exposed_positions[handle] = pos;
} }
@ -1222,7 +1225,7 @@ namespace nana{
Window drop_wd; Window drop_wd;
int x, y; int x, y;
unsigned mask; 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); ::XQueryPointer(restrict::spec.open_display(), restrict::spec.root_window(), &drop_wd, &drop_wd, &pos.x, &pos.y, &x, &y, &mask);
return pos; return pos;
#endif #endif
@ -1278,9 +1281,19 @@ namespace nana{
if(returns_previous) if(returns_previous)
prev = parent_window(child); prev = parent_window(child);
if(native_window_type{} == new_parent)
new_parent = reinterpret_cast<native_window_type>(restrict::spec.root_window());
::XReparentWindow(restrict::spec.open_display(), ::XReparentWindow(restrict::spec.open_display(),
reinterpret_cast<Window>(child), reinterpret_cast<Window>(new_parent), reinterpret_cast<Window>(child), reinterpret_cast<Window>(new_parent),
0, 0); 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; return prev;
#endif #endif
} }

View File

@ -99,7 +99,7 @@ namespace nana
//Check scroll_area to avoiding division by zero. //Check scroll_area to avoiding division by zero.
if (scroll_area) if (scroll_area)
metrics_.value = pos * (static_cast<double>(value_max) / scroll_area); //converting to double to avoid overflow. metrics_.value = static_cast<std::size_t>(pos * (static_cast<double>(value_max) / scroll_area)); //converting to double to avoid overflow.
if (metrics_.value < value_max) if (metrics_.value < value_max)
{ {

View File

@ -1853,7 +1853,6 @@ namespace nana
item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y); item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl); impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
auto & node_state = impl_->node_state; auto & node_state = impl_->node_state;
node_state.pressed_node = nl.node(); node_state.pressed_node = nl.node();
@ -1869,7 +1868,6 @@ namespace nana
else else
return; return;
impl_->draw(true); impl_->draw(true);
API::dev::lazy_refresh(); API::dev::lazy_refresh();
} }