Merge branch 'hotfixes-1.0.2' into develop
Conflicts: include/nana/gui/detail/basic_window.hpp include/nana/gui/widgets/listbox.hpp source/gui/detail/linux_X11/bedrock.cpp source/gui/detail/win32/bedrock.cpp source/gui/detail/window_layout.cpp source/gui/detail/window_manager.cpp source/gui/widgets/listbox.cpp source/gui/widgets/toolbar.cpp
This commit is contained in:
@@ -357,21 +357,26 @@ namespace detail
|
||||
//@brief: Delete the window handle
|
||||
void window_manager::destroy(core_window_t* wd)
|
||||
{
|
||||
core_window_t* parent = nullptr;
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return;
|
||||
|
||||
rectangle update_area(wd->pos_owner, wd->dimension);
|
||||
|
||||
auto parent = wd->parent;
|
||||
if (parent)
|
||||
utl::erase(parent->children, wd);
|
||||
|
||||
_m_destroy(wd);
|
||||
|
||||
while (parent && (parent->other.category == ::nana::category::flags::lite_widget))
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return;
|
||||
|
||||
if (wd->parent)
|
||||
{
|
||||
parent = wd->parent;
|
||||
utl::erase(wd->parent->children, wd);
|
||||
}
|
||||
|
||||
_m_destroy(wd);
|
||||
update_area.x += parent->pos_owner.x;
|
||||
update_area.y += parent->pos_owner.y;
|
||||
parent = parent->parent;
|
||||
}
|
||||
update(parent, false, false);
|
||||
|
||||
update(parent, false, false, &update_area);
|
||||
}
|
||||
|
||||
//destroy_handle
|
||||
@@ -408,35 +413,34 @@ namespace detail
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
if (!impl_->wd_register.available(wd))
|
||||
return false;
|
||||
|
||||
if(visible != wd->visible)
|
||||
{
|
||||
if(visible != wd->visible)
|
||||
native_window_type nv = nullptr;
|
||||
switch(wd->other.category)
|
||||
{
|
||||
native_window_type nv = nullptr;
|
||||
switch(wd->other.category)
|
||||
{
|
||||
case category::root_tag::value:
|
||||
nv = wd->root; break;
|
||||
case category::frame_tag::value:
|
||||
nv = wd->other.attribute.frame->container; break;
|
||||
default: //category::widget_tag, category::lite_widget_tag
|
||||
break;
|
||||
}
|
||||
|
||||
if(visible && wd->effect.bground)
|
||||
wndlayout_type::make_bground(wd);
|
||||
|
||||
//Don't set the visible attr of a window if it is a root.
|
||||
//The visible attr of a root will be set in the expose event.
|
||||
if(category::root_tag::value != wd->other.category)
|
||||
bedrock::instance().event_expose(wd, visible);
|
||||
|
||||
if(nv)
|
||||
native_interface::show_window(nv, visible, wd->flags.take_active);
|
||||
case category::root_tag::value:
|
||||
nv = wd->root; break;
|
||||
case category::frame_tag::value:
|
||||
nv = wd->other.attribute.frame->container; break;
|
||||
default: //category::widget_tag, category::lite_widget_tag
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
if(visible && wd->effect.bground)
|
||||
window_layer::make_bground(wd);
|
||||
|
||||
//Don't set the visible attr of a window if it is a root.
|
||||
//The visible attr of a root will be set in the expose event.
|
||||
if(category::flags::root != wd->other.category)
|
||||
bedrock::instance().event_expose(wd, visible);
|
||||
|
||||
if(nv)
|
||||
native_interface::show_window(nv, visible, wd->flags.take_active);
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
window_manager::core_window_t* window_manager::find_window(native_window_type root, int x, int y)
|
||||
@@ -474,9 +478,6 @@ namespace detail
|
||||
wd->pos_owner.y = y;
|
||||
_m_move_core(wd, delta);
|
||||
|
||||
if(wd->together.caret && wd->together.caret->visible())
|
||||
wd->together.caret->update();
|
||||
|
||||
auto &brock = bedrock::instance();
|
||||
arg_move arg;
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
@@ -503,7 +504,7 @@ namespace detail
|
||||
auto & brock = bedrock::instance();
|
||||
bool moved = false;
|
||||
const bool size_changed = (r.width != wd->dimension.width || r.height != wd->dimension.height);
|
||||
if(wd->other.category != category::root_tag::value)
|
||||
if(category::flags::root != wd->other.category)
|
||||
{
|
||||
//Move child widgets
|
||||
if(r.x != wd->pos_owner.x || r.y != wd->pos_owner.y)
|
||||
@@ -514,9 +515,6 @@ namespace detail
|
||||
_m_move_core(wd, delta);
|
||||
moved = true;
|
||||
|
||||
if(wd->together.caret && wd->together.caret->visible())
|
||||
wd->together.caret->update();
|
||||
|
||||
arg_move arg;
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
arg.x = r.x;
|
||||
@@ -625,7 +623,7 @@ namespace detail
|
||||
if(wd->effect.bground && wd->parent)
|
||||
{
|
||||
wd->other.glass_buffer.make(sz);
|
||||
wndlayout_type::make_bground(wd);
|
||||
window_layer::make_bground(wd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,7 +655,7 @@ namespace detail
|
||||
}
|
||||
|
||||
//Copy the root buffer that wnd specified into DeviceContext
|
||||
void window_manager::map(core_window_t* wd, bool forced)
|
||||
void window_manager::map(core_window_t* wd, bool forced, const rectangle* update_area)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
@@ -665,12 +663,12 @@ namespace detail
|
||||
{
|
||||
//Copy the root buffer that wd specified into DeviceContext
|
||||
#if defined(NANA_LINUX)
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced);
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
|
||||
#elif defined(NANA_WINDOWS)
|
||||
if(nana::system::this_thread_id() == wd->thread_id)
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced);
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
|
||||
else
|
||||
bedrock::instance().map_thread_root_buffer(wd, forced);
|
||||
bedrock::instance().map_thread_root_buffer(wd, forced, update_area);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -679,25 +677,25 @@ namespace detail
|
||||
//@brief: update is used for displaying the screen-off buffer.
|
||||
// Because of a good efficiency, if it is called in an event procedure and the event procedure window is the
|
||||
// same as update's, update would not map the screen-off buffer and just set the window for lazy refresh
|
||||
bool window_manager::update(core_window_t* wd, bool redraw, bool forced)
|
||||
bool window_manager::update(core_window_t* wd, bool redraw, bool forced, const rectangle* update_area)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return false;
|
||||
|
||||
if (wd->visible && wd->visible_parents())
|
||||
if (wd->displayed())
|
||||
{
|
||||
if(forced || (false == wd->belong_to_lazy()))
|
||||
{
|
||||
if (!wd->flags.refreshing)
|
||||
{
|
||||
wndlayout_type::paint(wd, redraw, false);
|
||||
this->map(wd, forced);
|
||||
window_layer::paint(wd, redraw, false);
|
||||
this->map(wd, forced, update_area);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(redraw)
|
||||
wndlayout_type::paint(wd, true, false);
|
||||
else if (redraw)
|
||||
window_layer::paint(wd, true, false);
|
||||
|
||||
if (wd->other.upd_state == core_window_t::update_state::lazy)
|
||||
wd->other.upd_state = core_window_t::update_state::refresh;
|
||||
@@ -711,8 +709,8 @@ namespace detail
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
|
||||
//It's not worthy to redraw if visible is false
|
||||
if (impl_->wd_register.available(wd) && wd->visible && wd->visible_parents())
|
||||
wndlayout_type::paint(wd, true, true);
|
||||
if (impl_->wd_register.available(wd) && wd->displayed())
|
||||
window_layer::paint(wd, true, true);
|
||||
}
|
||||
|
||||
//do_lazy_refresh
|
||||
@@ -733,18 +731,19 @@ namespace detail
|
||||
{
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refresh) || force_copy_to_screen)
|
||||
{
|
||||
wndlayout_type::paint(wd, false, false);
|
||||
window_layer::paint(wd, false, false);
|
||||
this->map(wd, force_copy_to_screen);
|
||||
}
|
||||
else if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
{
|
||||
//Update the nimbus effect
|
||||
using nimbus_renderer = detail::edge_nimbus_renderer<core_window_t>;
|
||||
nimbus_renderer::instance().render(wd, force_copy_to_screen);
|
||||
//using nimbus_renderer = detail::edge_nimbus_renderer<core_window_t>; //deprecated
|
||||
//nimbus_renderer::instance().render(wd, true);
|
||||
this->map(wd, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
wndlayout_type::paint(wd, true, false); //only refreshing if it has an invisible parent
|
||||
window_layer::paint(wd, true, false); //only refreshing if it has an invisible parent
|
||||
}
|
||||
wd->other.upd_state = core_window_t::update_state::none;
|
||||
return true;
|
||||
@@ -764,7 +763,7 @@ namespace detail
|
||||
|
||||
result.make(wd->drawer.graphics.size());
|
||||
result.bitblt(0, 0, wd->drawer.graphics);
|
||||
wndlayout_type::paste_children_to_graphics(wd, result);
|
||||
window_layer::paste_children_to_graphics(wd, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -773,7 +772,7 @@ namespace detail
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
return (impl_->wd_register.available(wd) ?
|
||||
wndlayout_type::read_visual_rectangle(wd, r) :
|
||||
window_layer::read_visual_rectangle(wd, r) :
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -1002,6 +1001,39 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// preconditions of get_tabstop: tabstop is not empty and at least one window is visible
|
||||
window_manager::core_window_t* get_tabstop(window_manager::core_window_t* wd, bool forward)
|
||||
{
|
||||
auto & tabs = wd->root_widget->other.attribute.root->tabstop;
|
||||
|
||||
if (forward)
|
||||
{
|
||||
if (detail::tab_type::none == wd->flags.tab)
|
||||
return (tabs.front());
|
||||
else if (detail::tab_type::tabstop & wd->flags.tab)
|
||||
{
|
||||
auto end = tabs.cend();
|
||||
auto i = std::find(tabs.cbegin(), end, wd);
|
||||
if (i != end)
|
||||
{
|
||||
++i;
|
||||
window_manager::core_window_t* ts = (i != end ? (*i) : tabs.front());
|
||||
return (ts != wd ? ts : 0);
|
||||
}
|
||||
else
|
||||
return tabs.front();
|
||||
}
|
||||
}
|
||||
else if (tabs.size() > 1) //at least 2 elments in tabs are required when moving backward.
|
||||
{
|
||||
auto i = std::find(tabs.cbegin(), tabs.cend(), wd);
|
||||
if (i != tabs.cend())
|
||||
return (tabs.cbegin() == i ? tabs.back() : *(i - 1));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto window_manager::tabstop(core_window_t* wd, bool forward) const -> core_window_t*
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
@@ -1013,21 +1045,30 @@ namespace detail
|
||||
if (tabs.empty())
|
||||
return nullptr;
|
||||
|
||||
if ((detail::tab_type::none == wd->flags.tab) || !(detail::tab_type::tabstop & wd->flags.tab))
|
||||
return (forward ? tabs.front() : tabs.back());
|
||||
|
||||
auto i = std::find(tabs.cbegin(), tabs.cend(), wd);
|
||||
if (tabs.cend() == i)
|
||||
return (forward ? tabs.front() : tabs.back());
|
||||
|
||||
if (forward)
|
||||
bool precondition = false;
|
||||
for (auto & tab_wd : tabs)
|
||||
{
|
||||
++i;
|
||||
core_window_t* ts = (i != tabs.cend() ? (*i) : tabs.front());
|
||||
return (ts != wd ? ts : nullptr);
|
||||
if (tab_wd->displayed())
|
||||
{
|
||||
precondition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (tabs.cbegin() == i ? tabs.back() : *(i - 1));
|
||||
|
||||
if (precondition)
|
||||
{
|
||||
auto new_stop = get_tabstop(wd, forward);
|
||||
|
||||
while (new_stop && (wd != new_stop))
|
||||
{
|
||||
if (new_stop->flags.enabled && new_stop->displayed())
|
||||
return new_stop;
|
||||
|
||||
new_stop = get_tabstop(new_stop, forward);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void window_manager::remove_trash_handle(unsigned tid)
|
||||
@@ -1040,7 +1081,7 @@ namespace detail
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd))
|
||||
return wndlayout_type::enable_effects_bground(wd, enabled);
|
||||
return window_layer::enable_effects_bground(wd, enabled);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1224,18 +1265,9 @@ namespace detail
|
||||
|
||||
if (!established)
|
||||
{
|
||||
if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
{
|
||||
auto & cont = root_attr->effects_edge_nimbus;
|
||||
for (auto i = cont.begin(); i != cont.end(); ++i)
|
||||
{
|
||||
if (i->window == wd)
|
||||
{
|
||||
cont.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//remove the window from edge nimbus effect when it is destroying
|
||||
using edge_nimbus = detail::edge_nimbus_renderer<core_window_t>;
|
||||
edge_nimbus::instance().erase(wd);
|
||||
}
|
||||
else if (pa_root_attr != root_attr)
|
||||
{
|
||||
@@ -1347,7 +1379,7 @@ namespace detail
|
||||
|
||||
|
||||
_m_disengage(wd, nullptr);
|
||||
wndlayout_type::enable_effects_bground(wd, false);
|
||||
window_layer::enable_effects_bground(wd, false);
|
||||
|
||||
wd->drawer.detached();
|
||||
wd->widget_notifier->destroy();
|
||||
@@ -1371,7 +1403,12 @@ namespace detail
|
||||
if(wd->other.category != category::root_tag::value) //A root widget always starts at (0, 0) and its childs are not to be changed
|
||||
{
|
||||
wd->pos_root += delta;
|
||||
if(wd->other.category == category::frame_tag::value)
|
||||
if (category::flags::frame != wd->other.category)
|
||||
{
|
||||
if (wd->together.caret && wd->together.caret->visible())
|
||||
wd->together.caret->update();
|
||||
}
|
||||
else
|
||||
native_interface::move_window(wd->other.attribute.frame->container, wd->pos_root.x, wd->pos_root.y);
|
||||
|
||||
for (auto child : wd->children)
|
||||
|
||||
Reference in New Issue
Block a user