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:
Jinhao
2015-07-11 13:35:22 +08:00
43 changed files with 2614 additions and 760 deletions

View File

@@ -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)