diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index 038acdbb..a21ef4ad 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -85,7 +85,7 @@ namespace detail enum class update_state { - none, lazy, refresh + none, lazy, refreshed, request_refresh }; struct edge_nimbus_action diff --git a/include/nana/gui/detail/effects_renderer.hpp b/include/nana/gui/detail/effects_renderer.hpp index 155fcb78..3727933a 100644 --- a/include/nana/gui/detail/effects_renderer.hpp +++ b/include/nana/gui/detail/effects_renderer.hpp @@ -86,7 +86,7 @@ namespace nana{ } //Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered. - if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh)) + if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refreshed)) { rd_set.emplace_back(r, action.window); action.rendered = true; diff --git a/include/nana/gui/detail/window_layout.hpp b/include/nana/gui/detail/window_layout.hpp index 34987291..da099cf5 100644 --- a/include/nana/gui/detail/window_layout.hpp +++ b/include/nana/gui/detail/window_layout.hpp @@ -1,6 +1,6 @@ /* * Window Layout Implementation - * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -42,10 +42,16 @@ namespace detail core_window_t * window; rectangle r; }; - public: - static void paint(core_window_t*, bool is_redraw, bool is_child_refreshed); - static bool maproot(core_window_t*, bool have_refreshed, bool is_child_refreshed); + enum class paint_operation { + none, + have_refreshed, + try_refresh + }; + public: + static void paint(core_window_t*, paint_operation, bool request_refresh_children); + + static bool maproot(core_window_t*, bool have_refreshed, bool request_refresh_children); static void paste_children_to_graphics(core_window_t*, nana::paint::graphics& graph); @@ -68,13 +74,12 @@ namespace detail //_m_paste_children //@brief:paste children window to the root graphics directly. just paste the visual rectangle - static void _m_paste_children(core_window_t*, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos); + static void _m_paste_children(core_window_t*, bool have_refreshed, bool request_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos); static void _m_paint_glass_window(core_window_t*, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other); - //_m_notify_glasses - //@brief: Notify the glass windows that are overlapped with the specified vis_rect - static void _m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& r_visual); + //Notify the windows which have brground to update their background buffer. + static void _m_notify_glasses(core_window_t* const sigwd); private: struct data_section { diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index 1548b79f..e3491ac0 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -124,7 +124,7 @@ namespace detail bool update(core_window_t*, bool redraw, bool force, const rectangle* update_area = nullptr); void refresh_tree(core_window_t*); - bool do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false); + void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false); bool get_graphics(core_window_t*, nana::paint::graphics&); bool get_visual_rectangle(core_window_t*, nana::rectangle&); diff --git a/source/gui/detail/basic_window.cpp b/source/gui/detail/basic_window.cpp index 3f5849cc..67b24139 100644 --- a/source/gui/detail/basic_window.cpp +++ b/source/gui/detail/basic_window.cpp @@ -323,7 +323,7 @@ namespace nana { for (auto wd = this; wd; wd = wd->parent) { - if (basic_window::update_state::refresh == wd->other.upd_state) + if (basic_window::update_state::refreshed == wd->other.upd_state) return true; } return false; diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 26de1dbc..6e6602d9 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -1203,17 +1203,7 @@ namespace detail { thread_context* thrd = get_thread_context(0); if(thrd && thrd->event_window) - { - //the state none should be tested, becuase in an event, there would be draw after an update, - //if the none is not tested, the draw after update will not be refreshed. - switch(thrd->event_window->other.upd_state) - { - case core_window_t::update_state::none: - case core_window_t::update_state::lazy: - thrd->event_window->other.upd_state = core_window_t::update_state::refresh; - default: break; - } - } + thrd->event_window->other.upd_state = core_window_t::update_state::refresh; } //Dynamically set a cursor for a window diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 300866f0..a790a0c2 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -1691,17 +1691,7 @@ namespace detail { auto* thrd = get_thread_context(0); if (thrd && thrd->event_window) - { - //the state none should be tested, becuase in an event, there would be draw after an update, - //if the none is not tested, the draw after update will not be refreshed. - switch (thrd->event_window->other.upd_state) - { - case core_window_t::update_state::none: - case core_window_t::update_state::lazy: - thrd->event_window->other.upd_state = core_window_t::update_state::refresh; - default: break; - } - } + thrd->event_window->other.upd_state = core_window_t::update_state::refreshed; } //Dynamically set a cursor for a window diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index 0ab725aa..0c69bee3 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -391,7 +391,7 @@ namespace nana bool drawer::_m_lazy_decleared() const { - return (basic_window::update_state::refresh == data_impl_->window_handle->other.upd_state); + return (basic_window::update_state::refreshed == data_impl_->window_handle->other.upd_state); } drawer::method_state& drawer::_m_mth_state(int pos) diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index ec69baa3..86439dec 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -22,26 +22,26 @@ namespace nana namespace detail { //class window_layout - void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed) + void window_layout::paint(core_window_t* wd, paint_operation operation, bool req_refresh_children) { - if (is_redraw && wd->flags.refreshing) + if (wd->flags.refreshing && (paint_operation::try_refresh == operation)) return; if (nullptr == wd->effect.bground) { - if (is_redraw && (!wd->drawer.graphics.empty())) + if ((paint_operation::try_refresh == operation) && (!wd->drawer.graphics.empty())) { wd->flags.refreshing = true; wd->drawer.refresh(); wd->flags.refreshing = false; } - maproot(wd, is_redraw, is_child_refreshed); + maproot(wd, (paint_operation::none != operation), req_refresh_children); } else - _m_paint_glass_window(wd, is_redraw, is_child_refreshed, false, true); + _m_paint_glass_window(wd, (paint_operation::try_refresh == operation), req_refresh_children, false, true); } - bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool is_child_refreshed) + bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool req_refresh_children) { auto check_opaque = wd->seek_non_lite_widget_ancestor(); if (check_opaque && check_opaque->flags.refreshing) @@ -56,7 +56,7 @@ namespace nana if (category::flags::lite_widget != wd->other.category) graph.bitblt(vr, wd->drawer.graphics, nana::point(vr.x - wd->pos_root.x, vr.y - wd->pos_root.y)); - _m_paste_children(wd, is_child_refreshed, have_refreshed, vr, graph, nana::point()); + _m_paste_children(wd, have_refreshed, req_refresh_children, vr, graph, nana::point()); if (wd->parent) { @@ -81,11 +81,11 @@ namespace nana graph.bitblt(el.r, (el.window->drawer.graphics), p_src); } - _m_paste_children(el.window, is_child_refreshed, false, el.r, graph, nana::point{}); + _m_paste_children(el.window, false, req_refresh_children, el.r, graph, nana::point{}); } } } - _m_notify_glasses(wd, vr); + _m_notify_glasses(wd); return true; } return false; @@ -255,8 +255,8 @@ namespace nana if (category::flags::lite_widget != child->other.category) glass_buffer.bitblt(nana::rectangle{ ovlp.x - wd->pos_owner.x, ovlp.y - wd->pos_owner.y, ovlp.width, ovlp.height }, child->drawer.graphics, {ovlp.position() - child->pos_owner}); - ovlp.x += wd->pos_root.x; - ovlp.y += wd->pos_root.y; + ovlp.x += wd->parent->pos_root.x; + ovlp.y += wd->parent->pos_root.y; _m_paste_children(child, false, false, ovlp, glass_buffer, rpos); } } @@ -267,7 +267,7 @@ namespace nana //_m_paste_children //@brief:paste children window to the root graphics directly. just paste the visual rectangle - void window_layout::_m_paste_children(core_window_t* wd, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos) + void window_layout::_m_paste_children(core_window_t* wd, bool have_refreshed, bool req_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos) { nana::rectangle rect; for (auto child : wd->children) @@ -278,7 +278,7 @@ namespace nana if (category::flags::root == child->other.category) { - paint(child, is_child_refreshed, is_child_refreshed); + paint(child, (req_refresh_children ? paint_operation::try_refresh : paint_operation::none), req_refresh_children); continue; } @@ -289,7 +289,7 @@ namespace nana bool have_child_refreshed = false; if (category::flags::lite_widget != child->other.category) { - if (is_child_refreshed && (false == child->flags.refreshing)) + if (req_refresh_children && (false == child->flags.refreshing)) { have_child_refreshed = true; child->flags.refreshing = true; @@ -300,13 +300,13 @@ namespace nana graph.bitblt(nana::rectangle(rect.x - graph_rpos.x, rect.y - graph_rpos.y, rect.width, rect.height), child->drawer.graphics, nana::point(rect.x - child->pos_root.x, rect.y - child->pos_root.y)); } - _m_paste_children(child, is_child_refreshed, have_child_refreshed, rect, graph, graph_rpos); + _m_paste_children(child, req_refresh_children, have_child_refreshed, rect, graph, graph_rpos); } } else { - //If have_refreshed, the glass should be notified. - _m_paint_glass_window(child, false, is_child_refreshed, have_refreshed, false); + //Update the glass window's background if the parent have_refreshed. + _m_paint_glass_window(child, have_refreshed, req_refresh_children, true, false); } } } @@ -353,16 +353,14 @@ namespace nana } if (notify_other) - _m_notify_glasses(wd, vr); + _m_notify_glasses(wd); } } - //_m_notify_glasses - //@brief: Notify the glass windows that are overlapped with the specified vis_rect - void window_layout::_m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& /*r_visual*/) + /// Notify the glass windows that are overlapped with the specified visual rectangle. + /// If a child window of sigwd is a glass window, it doesn't to be notified. + void window_layout::_m_notify_glasses(core_window_t* const sigwd) { - typedef category::flags cat_flags; - nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension); for (auto wd : data_sect.effects_bground_windows) { @@ -377,6 +375,8 @@ namespace nana } else if (sigwd != wd->parent) { + using cat_flags = category::flags; + if (wd->parent && (cat_flags::lite_widget == wd->parent->other.category)) { //Test if sigwd is an ancestor of the glass window, and there are lite widgets diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 5cfe1d10..984988ee 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -759,6 +759,10 @@ namespace detail arg.window_handle = reinterpret_cast(wd); arg.x = x; arg.y = y; + + if (wd->effect.bground) + wd->other.upd_state = basic_window::update_state::request_refresh; + brock.emit(event_code::move, wd, arg, true, brock.get_thread_context()); return true; } @@ -803,6 +807,9 @@ namespace detail _m_move_core(wd, delta); moved = true; + if ((!size_changed) && wd->effect.bground) + wd->other.upd_state = basic_window::update_state::request_refresh; + arg_move arg; arg.window_handle = reinterpret_cast(wd); arg.x = r.x; @@ -989,26 +996,28 @@ namespace detail if (wd->displayed()) { + using paint_operation = window_layer::paint_operation; + if(forced || (false == wd->belong_to_lazy())) { if (!wd->flags.refreshing) { - window_layer::paint(wd, redraw, false); + window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false); this->map(wd, forced, update_area); return true; } else if (forced) { - window_layer::paint(wd, false, false); + window_layer::paint(wd, paint_operation::none, false); this->map(wd, true, update_area); return true; } } else if (redraw) - window_layer::paint(wd, true, false); + window_layer::paint(wd, paint_operation::try_refresh, false); if (wd->other.upd_state == core_window_t::update_state::lazy) - wd->other.upd_state = core_window_t::update_state::refresh; + wd->other.upd_state = core_window_t::update_state::refreshed; } return true; } @@ -1020,28 +1029,28 @@ namespace detail //It's not worthy to redraw if visible is false if (impl_->wd_register.available(wd) && wd->displayed()) - window_layer::paint(wd, true, true); + window_layer::paint(wd, window_layer::paint_operation::try_refresh, true); } //do_lazy_refresh //@brief: defined a behavior of flush the screen - //@return: it returns true if the wnd is available - bool window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree) + void window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree) { //Thread-Safe Required! std::lock_guard lock(mutex_); if (false == impl_->wd_register.available(wd)) - return false; + return; //It's not worthy to redraw if visible is false if(wd->visible && (!wd->is_draw_through())) { + using paint_operation = window_layer::paint_operation; if (wd->visible_parents()) { - if ((wd->other.upd_state == core_window_t::update_state::refresh) || force_copy_to_screen) + if ((wd->other.upd_state == core_window_t::update_state::refreshed) || (wd->other.upd_state == core_window_t::update_state::request_refresh) || force_copy_to_screen) { - window_layer::paint(wd, false, refresh_tree); + window_layer::paint(wd, (wd->other.upd_state == core_window_t::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree); this->map(wd, force_copy_to_screen); } else if (effects::edge_nimbus::none != wd->effect.edge_nimbus) @@ -1053,10 +1062,10 @@ namespace detail } } else - window_layer::paint(wd, true, refresh_tree); //only refreshing if it has an invisible parent + window_layer::paint(wd, paint_operation::try_refresh, refresh_tree); //only refreshing if it has an invisible parent } wd->other.upd_state = core_window_t::update_state::none; - return true; + return; } //get_graphics