diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index 22f51122..6c66b709 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -118,6 +118,8 @@ namespace detail bool is_draw_through() const; ///< Determines whether it is a draw-through window. basic_window * seek_non_lite_widget_ancestor() const; + + void set_action(mouse_action); public: /// Override event_holder bool set_events(const std::shared_ptr&) override; @@ -169,6 +171,7 @@ namespace detail unsigned Reserved :18; unsigned char tab; ///< indicate a window that can receive the keyboard TAB mouse_action action; + mouse_action action_before; }flags; struct diff --git a/include/nana/gui/detail/effects_renderer.hpp b/include/nana/gui/detail/effects_renderer.hpp index 0304fcb9..1a55e2ab 100644 --- a/include/nana/gui/detail/effects_renderer.hpp +++ b/include/nana/gui/detail/effects_renderer.hpp @@ -24,7 +24,7 @@ namespace nana{ return object; } - unsigned weight() const + constexpr unsigned weight() const { return 2; } @@ -122,9 +122,22 @@ namespace nana{ } } + rectangle wd_r{ wd->pos_root, wd->dimension }; + wd_r.pare_off(-static_cast(this->weight())); //Render for (auto & rd : rd_set) - _m_render_edge_nimbus(rd.second, rd.first); + { + auto other_wd = rd.second; + + if (other_wd != wd) + { + rectangle other_r{ other_wd->pos_root, other_wd->dimension }; + other_r.pare_off(-static_cast(this->weight())); + if (!overlapped(wd_r, other_r)) + continue; + } + _m_render_edge_nimbus(other_wd, rd.first); + } } private: static bool _m_edge_nimbus(core_window_t * focused_wd, core_window_t * wd) @@ -138,6 +151,8 @@ namespace nana{ void _m_render_edge_nimbus(core_window_t* wd, const nana::rectangle & visual) { + wd->flags.action_before = wd->flags.action; + auto r = visual; r.pare_off(-static_cast(weight())); rectangle good_r; diff --git a/include/nana/gui/layout_utility.hpp b/include/nana/gui/layout_utility.hpp index 51d4d4ea..56127aac 100644 --- a/include/nana/gui/layout_utility.hpp +++ b/include/nana/gui/layout_utility.hpp @@ -18,7 +18,7 @@ namespace nana { //overlap test if overlaped between r1 and r2 - bool overlap(const rectangle& r1, const rectangle& r2); + bool overlapped(const rectangle& r1, const rectangle& r2); // overlap, compute the overlap area between r1 and r2. the r is for root bool overlap(const rectangle& r1, const rectangle& r2, rectangle& r); diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index 3b438e4e..0dad496e 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -256,7 +256,7 @@ namespace nana{ namespace widgets bool scroll(bool upwards, bool vertical); bool focus_changed(const arg_focus&); - bool mouse_enter(bool); + bool mouse_enter(bool entering); bool mouse_move(bool left_button, const point& screen_pos); bool mouse_pressed(const arg_mouse& arg); @@ -274,7 +274,7 @@ namespace nana{ namespace widgets ::nana::upoint _m_put(::std::wstring); ::nana::upoint _m_erase_select(); - bool _m_make_select_string(::std::wstring&) const; + ::std::wstring _m_make_select_string() const; static bool _m_resolve_text(const ::std::wstring&, std::vector> & lines); bool _m_cancel_select(int align); diff --git a/source/gui/detail/basic_window.cpp b/source/gui/detail/basic_window.cpp index 693a9bf7..6e592a0e 100644 --- a/source/gui/detail/basic_window.cpp +++ b/source/gui/detail/basic_window.cpp @@ -346,6 +346,12 @@ namespace nana return anc; } + void basic_window::set_action(mouse_action act) + { + flags.action_before = flags.action; + flags.action = act; + } + void basic_window::_m_init_pos_and_size(basic_window* parent, const rectangle& r) { pos_owner = pos_root = r; @@ -390,6 +396,8 @@ namespace nana flags.fullscreen = false; flags.tab = nana::detail::tab_type::none; flags.action = mouse_action::normal; + flags.action_before = mouse_action::normal; + flags.refreshing = false; flags.destroying = false; flags.borderless = false; diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 22bd4498..e3fb1c6b 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -165,8 +165,7 @@ namespace nana arg.window_handle = reinterpret_cast(wd); arg.x = x; arg.y = y; - if (emit(event_code::move, wd, arg, false, get_thread_context())) - wd_manager().update(wd, false, true); + emit(event_code::move, wd, arg, true, get_thread_context()); } } @@ -174,7 +173,7 @@ namespace nana { if (wd_manager().available(hovered) && hovered->flags.enabled) { - hovered->flags.action = mouse_action::normal; + hovered->set_action(mouse_action::normal); arg_mouse arg; arg.evt_code = event_code::mouse_leave; @@ -203,7 +202,7 @@ namespace nana if (root_wd->flags.enabled && root_wd->flags.take_active) { if (focused && focused->together.caret) - focused->together.caret->set_active(false); + focused->together.caret->set_active(true); if (!emit(event_code::focus, focused, arg, true, get_thread_context())) this->wd_manager().set_focus(root_wd, true, arg_focus::reason::general); diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 72e8b53f..af6a58c3 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -515,7 +515,8 @@ namespace detail if(msgwnd) { if (mouse_action::pressed != msgwnd->flags.action) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); + hovered_wd = msgwnd; arg_mouse arg; @@ -597,7 +598,8 @@ namespace detail context.event_window = msgwnd; pressed_wd = nullptr; - msgwnd->flags.action = mouse_action::pressed; + + msgwnd->set_action(mouse_action::pressed); arg_mouse arg; assign_arg(arg, msgwnd, ButtonPress, xevent); arg.evt_code = dbl_click ? event_code::dbl_click : event_code::mouse_down; @@ -610,7 +612,7 @@ namespace detail if (msgwnd->root != native_interface::get_focus_window()) { //call the drawer mouse up event for restoring the surface graphics - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); wd_manager.do_lazy_refresh(msgwnd, false); @@ -648,7 +650,7 @@ namespace detail if(nullptr == msgwnd) break; - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); if(msgwnd->flags.enabled) { auto retain = msgwnd->together.events_ptr; @@ -667,7 +669,7 @@ namespace detail { if((arg.button == ::nana::mouse::left_button) && hit) { - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); click_arg.window_handle = reinterpret_cast(msgwnd); draw_invoker(&drawer::click, msgwnd, click_arg, &context); @@ -678,7 +680,7 @@ namespace detail if(wd_manager.available(msgwnd) && msgwnd->flags.enabled) { if(hit) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); auto retain = msgwnd->together.events_ptr; auto evt_ptr = retain.get(); @@ -740,7 +742,7 @@ namespace detail if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd)) { brock.event_msleave(hovered_wd); - hovered_wd->flags.action = mouse_action::normal; + hovered_wd->set_action(mouse_action::normal); hovered_wd = nullptr; //if msgwnd is neither a captured window nor a child of captured window, @@ -758,13 +760,13 @@ namespace detail if(prev_captured_inside) { evt_code = event_code::mouse_leave; - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); } else { evt_code = event_code::mouse_enter; if (mouse_action::pressed != msgwnd->flags.action) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); } arg_mouse arg; assign_arg(arg, msgwnd, message, xevent); @@ -779,7 +781,7 @@ namespace detail assign_arg(arg, msgwnd, message, xevent); if (mouse_action::pressed != msgwnd->flags.action) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); if (hovered_wd != msgwnd) { @@ -890,7 +892,7 @@ namespace detail arg.pos.y = 0; arg.window_handle = reinterpret_cast(msgwnd); - msgwnd->flags.action = mouse_action::pressed; + msgwnd->set_action(mouse_action::pressed); pressed_wd_space = msgwnd; auto retain = msgwnd->together.events_ptr; @@ -1023,7 +1025,7 @@ namespace detail { if(msgwnd == pressed_wd_space) { - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); arg_click click_arg; click_arg.mouse_args = nullptr; diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 8e5f24da..098f7556 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -945,7 +945,7 @@ namespace detail arg_mouse arg; assign_arg(arg, msgwnd, message, pmdec); - msgwnd->flags.action = mouse_action::pressed; + msgwnd->set_action(mouse_action::pressed); auto retain = msgwnd->together.events_ptr; if (brock.emit(event_code::mouse_down, msgwnd, arg, true, &context)) @@ -959,7 +959,7 @@ namespace detail if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y)) { //call the drawer mouse up event for restoring the surface graphics - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); arg.evt_code = event_code::mouse_up; draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); @@ -983,7 +983,7 @@ namespace detail if(nullptr == msgwnd) break; - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); if(msgwnd->flags.enabled) { auto retain = msgwnd->together.events_ptr; @@ -999,7 +999,7 @@ namespace detail if (msgwnd->dimension.is_hit(arg.pos)) { - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); if ((::nana::mouse::left_button == arg.button) && (pressed_wd == msgwnd)) { click_arg.window_handle = reinterpret_cast(msgwnd); @@ -1038,7 +1038,7 @@ namespace detail if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd)) { brock.event_msleave(hovered_wd); - hovered_wd->flags.action = mouse_action::normal; + hovered_wd->set_action(mouse_action::normal); hovered_wd = nullptr; //if msgwnd is neither captured window nor the child of captured window, @@ -1057,15 +1057,15 @@ namespace detail if(prev_captured_inside) { evt_code = event_code::mouse_leave; - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); } else { evt_code = event_code::mouse_enter; if (pressed_wd == msgwnd) - msgwnd->flags.action = mouse_action::pressed; + msgwnd->set_action(mouse_action::pressed); else if (mouse_action::pressed != msgwnd->flags.action) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); } arg_mouse arg; assign_arg(arg, msgwnd, message, pmdec); @@ -1082,9 +1082,9 @@ namespace detail if (hovered_wd != msgwnd) { if (pressed_wd == msgwnd) - msgwnd->flags.action = mouse_action::pressed; + msgwnd->set_action(mouse_action::pressed); else if (mouse_action::pressed != msgwnd->flags.action) - msgwnd->flags.action = mouse_action::over; + msgwnd->set_action(mouse_action::over); hovered_wd = msgwnd; arg.evt_code = event_code::mouse_enter; @@ -1419,7 +1419,7 @@ namespace detail arg.pos.y = 0; arg.window_handle = reinterpret_cast(msgwnd); - msgwnd->flags.action = mouse_action::pressed; + msgwnd->set_action(mouse_action::pressed); pressed_wd_space = msgwnd; auto retain = msgwnd->together.events_ptr; @@ -1490,7 +1490,7 @@ namespace detail { if (msgwnd == pressed_wd_space) { - msgwnd->flags.action = mouse_action::normal; + msgwnd->set_action(mouse_action::normal); arg_click click_arg; click_arg.mouse_args = nullptr; diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index 1cce7648..c7605538 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -245,9 +245,7 @@ namespace nana if(wd) { 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())); + bool owns_caret = (iwd->together.caret) && (iwd->together.caret->visible()); //The caret in X11 is implemented by Nana, it is different from Windows' //the caret in X11 is asynchronous, it is hard to hide and show the caret @@ -256,7 +254,7 @@ namespace nana if(owns_caret) { #ifndef NANA_X11 - caret_wd->together.caret->visible(false); + iwd->together.caret->visible(false); #else owns_caret = nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, false); #endif @@ -267,7 +265,7 @@ namespace nana if(owns_caret) { #ifndef NANA_X11 - caret_wd->together.caret->visible(true); + iwd->together.caret->visible(true); #else nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, true); #endif diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 47fd3e06..509e3142 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -108,7 +108,7 @@ namespace nana { //Test if the root widget is overlapped the specified widget //the pos of root widget is (0, 0) - if (overlap(visual, rectangle{ wd->root_widget->pos_owner, wd->root_widget->dimension }) == false) + if (overlapped(visual, rectangle{ wd->root_widget->pos_owner, wd->root_widget->dimension }) == false) return false; } @@ -365,7 +365,7 @@ namespace nana for (auto wd : data_sect.effects_bground_windows) { if (wd == sigwd || !wd->displayed() || - (false == overlap(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd))) + (false == overlapped(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd))) continue; if (sigwd->parent == wd->parent) diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 5714789f..441a5ec5 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -845,13 +845,13 @@ namespace detail { window_layer::paint(wd, false, refresh_tree); this->map(wd, force_copy_to_screen); - - wd->drawer.graphics.save_as_file("d:\\button.bmp"); - wd->root_graph->save_as_file("d:\\button_root.bmp"); } else if (effects::edge_nimbus::none != wd->effect.edge_nimbus) { - this->map(wd, true); + //The window is still mapped because of edge nimbus effect. + //Avoid duplicate copy if action state is not changed and the window is not focused. + if ((wd->flags.action != wd->flags.action_before) || (bedrock::instance().focus() == wd)) + this->map(wd, true); } } else @@ -1398,9 +1398,10 @@ namespace detail if (!established) { + using effect_renderer = detail::edge_nimbus_renderer; + //remove the window from edge nimbus effect when it is destroying - using edge_nimbus = detail::edge_nimbus_renderer; - edge_nimbus::instance().erase(wd); + effect_renderer::instance().erase(wd); } else if (pa_root_attr != root_attr) { diff --git a/source/gui/layout_utility.cpp b/source/gui/layout_utility.cpp index c81273b3..3afc6e62 100644 --- a/source/gui/layout_utility.cpp +++ b/source/gui/layout_utility.cpp @@ -16,7 +16,7 @@ namespace nana { //overlap test if overlaped between r1 and r2 - bool overlap(const rectangle& r1, const rectangle& r2) + bool overlapped(const rectangle& r1, const rectangle& r2) { if (r1.y + (long long)(r1.height) <= r2.y) return false; if(r1.y >= r2.y + (long long)(r2.height)) return false; @@ -30,7 +30,7 @@ namespace nana //overlap, compute the overlap area between r1 and r2. the rect is for root bool overlap(const rectangle& r1, const rectangle& r2, rectangle& r) { - if(overlap(r1, r2)) + if(overlapped(r1, r2)) { auto l1 = static_cast(r1.x) + r1.width; auto l2 = static_cast(r2.x) + r2.width; diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 02639fc1..90b4bdce 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -42,7 +42,6 @@ namespace nana{ namespace widgets //sel_a_ and sel_b_ are not sorted, sel_b_ keeps the caret position. sel_a_ = editor_.select_.a; sel_b_ = editor_.select_.b; - editor_._m_make_select_string(selected_text_); } void set_caret_pos() @@ -227,8 +226,7 @@ namespace nana{ namespace widgets editor_.select_.b = dest_b_; editor_.points_.caret = (sel_a_ < sel_b_ ? sel_a_ : sel_b_); - std::wstring text; - editor_._m_make_select_string(text); + const auto text = editor_._m_make_select_string(); editor_._m_erase_select(); editor_._m_put(text); @@ -1684,16 +1682,12 @@ namespace nana{ namespace widgets return renderred; } - bool text_editor::mouse_enter(bool enter) + bool text_editor::mouse_enter(bool entering) { - if((false == enter) && (false == text_area_.captured)) + if ((false == entering) && (false == text_area_.captured)) API::window_cursor(window_, nana::cursor::arrow); - if(API::focus_window() == window_) - return false; - - render(false); - return true; + return false; } bool text_editor::mouse_move(bool left_button, const point& scrpos) @@ -2131,9 +2125,9 @@ namespace nana{ namespace widgets void text_editor::copy() const { - std::wstring str; - if(_m_make_select_string(str)) - nana::system::dataexch().set(str); + auto text = _m_make_select_string(); + if (!text.empty()) + nana::system::dataexch().set(text); } void text_editor::cut() @@ -2845,27 +2839,29 @@ namespace nana{ namespace widgets return points_.caret; } - bool text_editor::_m_make_select_string(std::wstring& text) const + std::wstring text_editor::_m_make_select_string() const { + std::wstring text; + nana::upoint a, b; - if (!_m_get_sort_select_points(a, b)) - return false; - - if(a.y != b.y) + if (_m_get_sort_select_points(a, b)) { - text = textbase_.getline(a.y).substr(a.x); - text += L"\r\n"; - for(unsigned i = a.y + 1; i < b.y; ++i) + if (a.y != b.y) { - text += textbase_.getline(i); + text = textbase_.getline(a.y).substr(a.x); text += L"\r\n"; + for (unsigned i = a.y + 1; i < b.y; ++i) + { + text += textbase_.getline(i); + text += L"\r\n"; + } + text += textbase_.getline(b.y).substr(0, b.x); } - text += textbase_.getline(b.y).substr(0, b.x); + else + text = textbase_.getline(a.y).substr(a.x, b.x - a.x); } - else - text = textbase_.getline(a.y).substr(a.x, b.x - a.x); - return true; + return text; } std::size_t eat_endl(const wchar_t* str, std::size_t pos) @@ -3021,8 +3017,8 @@ namespace nana{ namespace widgets bool text_editor::_m_move_select(bool record_undo) { nana::upoint caret = points_.caret; - std::wstring text; - if (_m_make_select_string(text)) + const auto text = _m_make_select_string(); + if (!text.empty()) { auto undo_ptr = std::unique_ptr(new undo_move_text(*this)); undo_ptr->set_selected_text();