diff --git a/include/nana/gui/detail/effects_renderer.hpp b/include/nana/gui/detail/effects_renderer.hpp index b9b1b785..6b189d84 100644 --- a/include/nana/gui/detail/effects_renderer.hpp +++ b/include/nana/gui/detail/effects_renderer.hpp @@ -23,7 +23,7 @@ namespace nana{ return object; } - std::size_t weight() const + unsigned weight() const { return 2; } @@ -55,22 +55,23 @@ namespace nana{ } } - bool render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr) + void render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr) { - bool rendered = false; - core_window_t * root_wd = wd->root_widget; - auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus; + bool copy_separately = true; + std::vector> rd_set; - if(nimbus.size()) + if (wd->root_widget->other.attribute.root->effects_edge_nimbus.size()) { - core_window_t * focused = root_wd->other.attribute.root->focus; - native_window_type native = root_wd->root; - std::size_t pixels = weight(); + auto root_wd = wd->root_widget; + + auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus; + + auto focused = root_wd->other.attribute.root->focus; + + const unsigned pixels = weight(); auto graph = root_wd->root_graph; - std::vector erase; - std::vector> rd_set; nana::rectangle r; for(auto & action : nimbus) { @@ -80,11 +81,11 @@ namespace nana{ { if (update_area) ::nana::overlap(*update_area, rectangle(r), r); - rendered = true; + copy_separately = false; } //Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered. - if ((forced && (action.window == wd)) || !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::refresh)) { rd_set.emplace_back(r, action.window); action.rendered = true; @@ -93,29 +94,36 @@ namespace nana{ else if(action.rendered) { action.rendered = false; - erase.push_back(action.window); + + if (action.window == wd) + copy_separately = false; + + ::nana::rectangle erase_r( + action.window->pos_root.x - static_cast(pixels), + action.window->pos_root.y - static_cast(pixels), + static_cast(action.window->dimension.width + (pixels << 1)), + static_cast(action.window->dimension.height + (pixels << 1)) + ); + + graph->paste(root_wd->root, erase_r, erase_r.x, erase_r.y); } } - - //Erase - for(auto el : erase) - { - if(el == wd) - rendered = true; - - r.x = el->pos_root.x - static_cast(pixels); - r.y = el->pos_root.y - static_cast(pixels); - r.width = static_cast(el->dimension.width + (pixels << 1)); - r.height = static_cast(el->dimension.height + (pixels << 1)); - - graph->paste(native, r, r.x, r.y); - } - - //Render - for (auto & rd : rd_set) - _m_render_edge_nimbus(rd.second, rd.first); } - return rendered; + + if (copy_separately) + { + rectangle vr; + if (window_layer::read_visual_rectangle(wd, vr)) + { + if (update_area) + ::nana::overlap(*update_area, rectangle(vr), vr); + wd->root_graph->paste(wd->root, vr, vr.x, vr.y); + } + } + + //Render + for (auto & rd : rd_set) + _m_render_edge_nimbus(rd.second, rd.first); } private: static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd) @@ -134,8 +142,8 @@ namespace nana{ nana::rectangle good_r; if(overlap(r, wd->root_graph->size(), good_r)) { - if( (good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) || - (good_r.x + good_r.width > visual.x + visual.width) || (good_r.y + good_r.height > visual.y + visual.height)) + if ((good_r.x < wd->pos_root.x) || (good_r.y < wd->pos_root.y) || + (good_r.right() > visual.right()) || (good_r.bottom() > visual.bottom())) { auto graph = wd->root_graph; nana::paint::pixel_buffer pixbuf(graph->handle(), r); diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index ce84ed94..fc41706c 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -103,7 +103,7 @@ namespace nana arg.x = x; arg.y = y; if (emit(event_code::move, wd, arg, false, get_thread_context())) - wd_manager.update(wd, true, true); + wd_manager.update(wd, false, true); } } diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index 69c47190..f1308677 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -244,8 +244,8 @@ namespace nana { if(wd) { - bedrock_type::core_window_t* iwd = reinterpret_cast(wd); - bedrock_type::core_window_t * caret_wd = iwd->root_widget->other.attribute.root->focus; + auto iwd = reinterpret_cast(wd); + auto caret_wd = iwd->root_widget->other.attribute.root->focus; bool owns_caret = (caret_wd && (caret_wd->together.caret) && (caret_wd->together.caret->visible())); @@ -262,16 +262,7 @@ namespace nana #endif } - if (false == edge_nimbus_renderer_t::instance().render(iwd, forced, update_area)) - { - rectangle vr; - if (bedrock_type::window_manager_t::window_layer::read_visual_rectangle(iwd, vr)) - { - if (update_area) - ::nana::overlap(*update_area, rectangle(vr), vr); - iwd->root_graph->paste(iwd->root, vr, vr.x, vr.y); - } - } + edge_nimbus_renderer_t::instance().render(iwd, forced, update_area); if(owns_caret) { diff --git a/source/gui/detail/linux_X11/bedrock.cpp b/source/gui/detail/linux_X11/bedrock.cpp index d1632f7c..65414360 100644 --- a/source/gui/detail/linux_X11/bedrock.cpp +++ b/source/gui/detail/linux_X11/bedrock.cpp @@ -937,11 +937,10 @@ namespace detail if(msgwnd->visible && (msgwnd->root_graph->empty() == false)) { nana::detail::platform_scope_guard psg; - nana::detail::drawable_impl_type* drawer_impl = msgwnd->root_graph->handle(); - ::XCopyArea(display, drawer_impl->pixmap, reinterpret_cast(native_window), drawer_impl->context, - xevent.xexpose.x, xevent.xexpose.y, - xevent.xexpose.width, xevent.xexpose.height, - xevent.xexpose.x, xevent.xexpose.y); + //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. + ::nana::rectangle update_area(xevent.xexpose.x, xevent.xexpose.y, xevent.xexpose.width, xevent.xexpose.height); + if (!update_area.empty()) + msgwnd->drawer.map(reinterpret_cast(msgwnd), true, &update_area); } break; case KeyPress: diff --git a/source/gui/detail/win32/bedrock.cpp b/source/gui/detail/win32/bedrock.cpp index 682f371b..65e29071 100644 --- a/source/gui/detail/win32/bedrock.cpp +++ b/source/gui/detail/win32/bedrock.cpp @@ -1310,13 +1310,11 @@ namespace detail ::PAINTSTRUCT ps; ::HDC dc = ::BeginPaint(root_window, &ps); - if((ps.rcPaint.left != ps.rcPaint.right) && (ps.rcPaint.bottom != ps.rcPaint.top)) - { - ::BitBlt(dc, - ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top, - reinterpret_cast(msgwnd->root_graph->handle()->context), - ps.rcPaint.left, ps.rcPaint.top, SRCCOPY); - } + //Don't copy root_graph to the window directly, otherwise the edge nimbus effect will be missed. + ::nana::rectangle update_area(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top); + if (!update_area.empty()) + msgwnd->drawer.map(reinterpret_cast(msgwnd), true, &update_area); + ::EndPaint(root_window, &ps); } break; diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 11d59f9b..5734acbe 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -59,7 +59,6 @@ namespace nana if (wd->parent) { std::vector blocks; - blocks.reserve(10); if (read_overlaps(wd, vr, blocks)) { nana::point p_src;