fix crash when close owner window

window position issue makes popup menu at wrong position
This commit is contained in:
Jinhao 2018-09-11 07:34:25 +08:00
parent 986c635548
commit aac9ef525a
4 changed files with 89 additions and 49 deletions

View File

@ -1,7 +1,7 @@
/*
* A Menubar implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2009-2018 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -34,26 +34,6 @@ namespace nana
color_proxy border_highlight{ colors::highlight };
};
class item_renderer
{
public:
enum class state
{
normal, highlighted, selected
};
using graph_reference = paint::graphics&;
using scheme = ::nana::drawerbase::menubar::scheme;
item_renderer(window, graph_reference);
virtual void background(const point&, const ::nana::size&, state);
virtual void caption(const point&, const native_string_type&);
scheme *scheme_ptr() const { return scheme_ptr_; };
private:
graph_reference graph_;
scheme *scheme_ptr_;
};
class trigger
: public drawer_trigger
{

View File

@ -658,21 +658,31 @@ namespace detail
platform_scope_guard lock;
if(umake_owner(wd))
{
auto & wd_manager = detail::bedrock::instance().wd_manager();
std::vector<native_window_type> owned_children;
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;
for(auto child : *i->second.owned)
owned_children.push_back(child);
}
}
//Closing a child will erase the wd from the table wincontext_, so the
//iterator i can't be reused after children closed.
set_error_handler();
for(auto u = owned_children.rbegin(); u != owned_children.rend(); ++u)
wd_manager.close(wd_manager.root(*u));
rev_error_handler();
i = wincontext_.find(wd);
if(i != wincontext_.end())
{
delete i->second.owned;
wincontext_.erase(i);
}
}

View File

@ -371,6 +371,8 @@ namespace nana{
}
Window parent = (owner ? reinterpret_cast<Window>(owner) : restrict::spec.root_window());
//The position passed to XCreateWindow is a screen coordinate.
nana::point pos(r.x, r.y);
if((false == nested) && owner)
{
@ -396,7 +398,9 @@ namespace nana{
{
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;
//The exposed_position is a relative position to its owner/parent.
exposed_positions[handle] = r.position();
}
XChangeWindowAttributes(disp, handle, attr_mask, &win_attr);
@ -945,13 +949,14 @@ namespace nana{
auto fm_extents = window_frame_extents(wd);
origin.x = -fm_extents.left;
origin.y = -fm_extents.top;
#if 0 //deprecated
if(reinterpret_cast<Window>(coord_wd) != restrict::spec.root_window())
{
fm_extents = window_frame_extents(coord_wd);
origin.x += fm_extents.left;
origin.y += fm_extents.top;
}
#endif
}
else
coord_wd = get_window(wd, window_relationship::parent);
@ -1010,8 +1015,14 @@ namespace nana{
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
{
auto origin = window_position(owner);
#if 0
x += origin.x;
y += origin.y;
#else
auto owner_extents = window_frame_extents(owner);
x += origin.x + owner_extents.left;
y += origin.y + owner_extents.top;
#endif
}
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
@ -1099,8 +1110,14 @@ namespace nana{
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
{
auto origin = window_position(owner);
#if 0
x += origin.x;
y += origin.y;
#else
auto owner_extents = window_frame_extents(owner);
x += origin.x + owner_extents.left;
y += origin.y + owner_extents.top;
#endif
}
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
@ -1580,14 +1597,21 @@ namespace nana{
pos.y = point.y;
return true;
}
return false;
#elif defined(NANA_X11)
nana::detail::platform_scope_guard psg;
int x = pos.x, y = pos.y;
Window child;
return (True == ::XTranslateCoordinates(restrict::spec.open_display(),
reinterpret_cast<Window>(wd), restrict::spec.root_window(), x, y, &pos.x, &pos.y, &child));
if(True == ::XTranslateCoordinates(restrict::spec.open_display(),
reinterpret_cast<Window>(wd), restrict::spec.root_window(), x, y, &pos.x, &pos.y, &child))
{
//deprecated
//auto fm_extents = window_frame_extents(wd);
//pos.x += fm_extents.left;
//pos.y += fm_extents.top;
return true;
}
#endif
return false;
}
bool native_interface::calc_window_point(native_window_type wd, nana::point& pos)
@ -1600,14 +1624,21 @@ namespace nana{
pos.y = point.y;
return true;
}
return false;
#elif defined(NANA_X11)
nana::detail::platform_scope_guard psg;
int x = pos.x, y = pos.y;
Window child;
return (True == ::XTranslateCoordinates(restrict::spec.open_display(),
restrict::spec.root_window(), reinterpret_cast<Window>(wd), x, y, &pos.x, &pos.y, &child));
if(True == ::XTranslateCoordinates(restrict::spec.open_display(), restrict::spec.root_window(), reinterpret_cast<Window>(wd), x, y, &pos.x, &pos.y, &child))
{
//deprecated
//Now the origin of pos is the left-top corner of the window(including titlebar and border)
//auto fm_extents = window_frame_extents(wd);
//pos.x += fm_extents.left;
//pos.y += fm_extents.top;
return true;
}
#endif
return false;
}
native_window_type native_interface::find_window(int x, int y)

View File

@ -1,7 +1,7 @@
/*
* A Menubar implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2009-2017 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2009-2018 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -215,6 +215,26 @@ namespace nana
};
//class item_renderer
class item_renderer
{
public:
enum class state
{
normal, highlighted, selected
};
using graph_reference = paint::graphics&;
using scheme = ::nana::drawerbase::menubar::scheme;
item_renderer(window, graph_reference);
virtual void background(const point&, const ::nana::size&, state);
virtual void caption(const point&, const native_string_type&);
scheme *scheme_ptr() const { return scheme_ptr_; };
private:
graph_reference graph_;
scheme *scheme_ptr_;
};
item_renderer::item_renderer(window wd, graph_reference graph)
:graph_(graph), scheme_ptr_(static_cast<scheme*>(API::dev::get_scheme(wd)))
{}
@ -250,7 +270,6 @@ namespace nana
void item_renderer::caption(const point& pos, const native_string_type& text)
{
graph_.string(pos, text, scheme_ptr_->text_fgcolor);
}
//end class item_renderer