diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index 965be995..d3468483 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -104,13 +104,13 @@ namespace detail //destroy_handle //@brief: Delete window handle, the handle type must be a root and a frame. + + // Deletes a window whose category type is a root type or a frame type. void destroy_handle(core_window_t*); void default_icon(const paint::image& _small_icon, const paint::image& big_icon); void icon(core_window_t*, const paint::image& small_icon, const paint::image& big_icon); - //show - //@brief: show or hide a window bool show(core_window_t* wd, bool visible); core_window_t* find_window(native_window_type root, int x, int y); @@ -139,10 +139,10 @@ namespace detail core_window_t* set_focus(core_window_t*, bool root_has_been_focused, arg_focus::reason); core_window_t* capture_redirect(core_window_t*); - void capture_ignore_children(bool ignore); + bool capture_window_entered(int root_x, int root_y, bool& prev); core_window_t * capture_window() const; - core_window_t* capture_window(core_window_t*, bool value); + void capture_window(core_window_t*, bool capture, bool ignore_children_if_captured); void enable_tabstop(core_window_t*); core_window_t* tabstop(core_window_t*, bool forward) const; //forward means move to next in logic. diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 03138a04..85196997 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -268,10 +268,13 @@ namespace API */ void lazy_refresh(); - /** @brief: calls refresh() of a widget's drawer. if currently state is lazy_refresh, Nana.GUI may paste the drawing on the window after an event processing. - * @param window: specify a window to be refreshed. + + /// Refresh the window and display it immediately calling the refresh function of its drawer_trigger. + /* + * The drawer::refresh() will be called. If the currently state is lazy_refrsh, the window is delayed to update the graphics until an event is finished. + * @param window_handle A handle to the window to be refreshed. */ - void refresh_window(window); ///< Refreshs the window and display it immediately calling the refresh method of its drawer_trigger.. + void refresh_window(window window_handle); void refresh_window_tree(window); ///< Refreshs the specified window and all it’s children windows, then display it immediately void update_window(window); ///< Copies the off-screen buffer to the screen for immediate display. @@ -294,8 +297,20 @@ namespace API void focus_window(window); window capture_window(); - window capture_window(window, bool); ///< Enables or disables the window to grab the mouse input - void capture_ignore_children(bool ignore); ///< Enables or disables the captured window whether redirects the mouse input to its children if the mouse is over its children. + + /// Enables a window to grab the mouse input. + /** + * @param window_handle A handle to a window to grab the mouse input. + * @param ignore_children Indicates whether to redirect the mouse input to its children if the mouse pointer is over its children. + */ + void set_capture(window window_handle, bool ignore_children); + + /// Disable a window to grab the mouse input. + /** + * @param window handle A handle to a window to release grab of mouse input. + */ + void release_capture(window window_handle); + void modal_window(window); ///< Blocks the routine til the specified window is closed. void wait_for(window); @@ -316,10 +331,25 @@ namespace API void caret_visible(window, bool is_show); bool caret_visible(window); - void tabstop(window); ///< Sets the window that owns the tabstop. - /// treu: The focus is not to be changed when Tab key is pressed, and a key_char event with tab will be generated. - void eat_tabstop(window, bool); - window move_tabstop(window, bool next); ///< Sets the focus to the window which tabstop is near to the specified window. + /// Enables that the user can give input focus to the specified window using TAB key. + void tabstop(window); + + /// Enables or disables a window to receive a key_char event for pressing TAB key. + /* + * @param window_handle A handle to the window to catch TAB key through key_char event. + * @param enable Indicates whether to enable or disable catch of TAB key. If this parameter is *true*, the window is + * received a key_char when pressing TAB key, and the input focus is not changed. If this parameter is *false*, the + * input focus is changed to the next tabstop window. + */ + void eat_tabstop(window window_handle, bool enable); + + /// Sets the input focus to the window which the tabstop is near to the specified window. + /* + * @param window_handle A handle to the window. + * @param forward Indicates whether forward or backward window to be given the input focus. + * @return A handle to the window which to be given the input focus. + */ + window move_tabstop(window window_handle, bool forward); /// Sets the window active state. If a window active state is false, the window will not obtain the focus when a mouse clicks on it wich will be obteined by take_if_has_active_false. void take_active(window, bool has_active, window take_if_has_active_false); @@ -349,6 +379,7 @@ namespace API void at_safe_place(window, std::function); }//end namespace API + }//end namespace nana #endif diff --git a/include/nana/gui/widgets/scroll.hpp b/include/nana/gui/widgets/scroll.hpp index 1cf5bb83..00107b5f 100644 --- a/include/nana/gui/widgets/scroll.hpp +++ b/include/nana/gui/widgets/scroll.hpp @@ -262,7 +262,7 @@ namespace nana timer_.start(); break; case buttons::scroll: - API::capture_window(widget_->handle(), true); + widget_->set_capture(true); metrics_.scroll_mouse_offset = (Vertical ? arg.pos.y : arg.pos.x) - metrics_.scroll_pos; break; case buttons::forward: @@ -286,7 +286,7 @@ namespace nana { timer_.stop(); - API::capture_window(widget_->handle(), false); + widget_->release_capture(); metrics_.pressed = false; metrics_.what = drawer_.what(graph, arg.pos); diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index cfc174f7..14b6f2bd 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -78,6 +78,15 @@ namespace nana nana::size size() const; void size(const nana::size&); + + /// Enables the widget to grab the mouse input. + /* + * @param ignore_children Indicates whether to redirect the mouse input to its children if the mouse pointer is over its children. + */ + void set_capture(bool ignore_children); + + /// Disables the widget to grab the mouse input. + void release_capture(); point pos() const; void move(int x, int y); diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 928c422a..d705261c 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -310,7 +310,7 @@ namespace nana return (is_keyboard_condition ? (pi_data_->menu.has_keyboard ? pi_data_->menu.window : nullptr) : pi_data_->menu.window); } - return 0; + return nullptr; } native_window_type bedrock::get_menu() diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 39e88c87..29e7b97a 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -455,8 +455,6 @@ namespace detail update(parent, false, false, &update_area); } - //destroy_handle - //@brief: Delete window handle, the handle type must be a root and a frame. void window_manager::destroy_handle(core_window_t* wd) { //Thread-Safe Required! @@ -975,7 +973,7 @@ namespace detail //A fix by Katsuhisa Yuasa //The menubar token window will be redirected to the prev focus window when the new //focus window is a menubar. - //The focus window will be restore to the prev focus which losts the focus becuase of + //The focus window will be restored to the prev focus which losts the focus becuase of //memberbar. if (prev_focus && (wd == wd->root_widget->other.attribute.root->menubar)) wd = prev_focus; @@ -998,11 +996,6 @@ namespace detail return attr_.capture.window; } - void window_manager::capture_ignore_children(bool ignore) - { - attr_.capture.ignore_children = ignore; - } - bool window_manager::capture_window_entered(int root_x, int root_y, bool& prev) { if(attr_.capture.window) @@ -1023,19 +1016,15 @@ namespace detail return attr_.capture.window; } - //capture_window - //@brief: set a window that always captures the mouse event if it is not in the range of window - //@return: this function dose return the previous captured window. If the wnd set captured twice, - // the return value is NULL - window_manager::core_window_t* window_manager::capture_window(core_window_t* wd, bool value) + void window_manager::capture_window(core_window_t* wd, bool captured, bool ignore_children) { if (!this->available(wd)) - return nullptr; + return; nana::point pos = native_interface::cursor_position(); auto & attr_cap = attr_.capture.history; - if(value) + if (captured) { if(wd != attr_.capture.window) { @@ -1045,19 +1034,17 @@ namespace detail if (impl_->wd_register.available(wd)) { wd->flags.captured = true; - native_interface::capture_window(wd->root, value); - auto prev = attr_.capture.window; - if(prev && (prev != wd)) - attr_cap.emplace_back(prev, attr_.capture.ignore_children); + native_interface::capture_window(wd->root, captured); + + if (attr_.capture.window) + attr_cap.emplace_back(attr_.capture.window, attr_.capture.ignore_children); attr_.capture.window = wd; - attr_.capture.ignore_children = true; + attr_.capture.ignore_children = ignore_children; native_interface::calc_window_point(wd->root, pos); attr_.capture.inside = _m_effective(wd, pos); - return prev; } } - return attr_.capture.window; } else if(wd == attr_.capture.window) { @@ -1092,10 +1079,7 @@ namespace detail break; } } - - return attr_.capture.window; } - return wd; } //enable_tabstop @@ -1356,7 +1340,7 @@ namespace detail if (established) { if (check_tree(wd, attr_.capture.window)) - capture_window(attr_.capture.window, false); + capture_window(attr_.capture.window, false, false); //The 3rd parameter is ignored if (root_attr->focus && check_tree(wd, root_attr->focus)) root_attr->focus = nullptr; @@ -1369,7 +1353,7 @@ namespace detail else { if (wd == attr_.capture.window) - capture_window(attr_.capture.window, false); + capture_window(attr_.capture.window, false, false); //The 3rd parameter is ignored. if (root_attr->focus == wd) root_attr->focus = nullptr; diff --git a/source/gui/dragger.cpp b/source/gui/dragger.cpp index 43a56ba2..459d9833 100644 --- a/source/gui/dragger.cpp +++ b/source/gui/dragger.cpp @@ -47,7 +47,7 @@ namespace nana API::umake_event(t.over); API::umake_event(t.release); API::umake_event(t.destroy); - API::capture_window(t.wd, false); + API::release_capture(t.wd); } } @@ -87,7 +87,8 @@ namespace nana { case event_code::mouse_down: dragging_ = true; - API::capture_window(arg.window_handle, true); + API::set_capture(arg.window_handle, true); + origin_ = API::cursor_position(); for (auto & t : targets_) { @@ -133,7 +134,8 @@ namespace nana } break; case event_code::mouse_up: - API::capture_window(arg.window_handle, false); + API::release_capture(arg.window_handle); + dragging_ = false; break; default: @@ -151,7 +153,7 @@ namespace nana if (i->wd == arg.window_handle) { triggers_.erase(i); - API::capture_window(arg.window_handle, false); + API::release_capture(arg.window_handle); return; } } diff --git a/source/gui/place.cpp b/source/gui/place.cpp index d0796c90..48ba39bc 100644 --- a/source/gui/place.cpp +++ b/source/gui/place.cpp @@ -1775,7 +1775,8 @@ namespace nana bool is_vert = _m_is_vert(dir_); - API::capture_window(this->handle(), true); + this->set_capture(true); + auto basepos = API::cursor_position(); base_pos_.x = (is_vert ? basepos.y : basepos.x); @@ -1838,7 +1839,7 @@ namespace nana dock_dv_->collocate(wd); } else - API::capture_window(this->handle(), false); //release mouse button + this->release_capture(); }; auto & evt = this->events(); diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 1d21d600..8cd0e418 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -240,7 +240,7 @@ namespace nana moves_.started = true; moves_.start_pos = API::cursor_position(); moves_.start_container_pos = (floating() ? container_->pos() : this->pos()); - API::capture_window(caption_, true); + caption_.set_capture(true); } } else if (event_code::mouse_move == arg.evt_code) @@ -266,7 +266,7 @@ namespace nana if ((::nana::mouse::left_button == arg.button) && moves_.started) { moves_.started = false; - API::capture_window(caption_, false); + caption_.release_capture(); notifier_->notify_move_stopped(); } } @@ -345,7 +345,7 @@ namespace nana if (container_) return; - API::capture_window(caption_, false); + caption_.release_capture(); rectangle r{ pos() + move_pos, size() }; container_.reset(new form(host_window_, r.pare_off(-1), form::appear::bald())); @@ -364,14 +364,15 @@ namespace nana }); container_->show(); - API::capture_window(caption_, true); + caption_.set_capture(true); notifier_->notify_float(); } void dock() { - API::capture_window(caption_, false); + caption_.release_capture(); + API::set_parent_window(handle(), host_window_); container_.reset(); notifier_->notify_dock(); diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index a13e81cd..75f34ebe 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -937,16 +937,15 @@ namespace API return reinterpret_cast(restrict::wd_manager().capture_window()); } - window capture_window(window wd, bool value) + void set_capture(window wd, bool ignore_children) { - return reinterpret_cast( - restrict::wd_manager().capture_window(reinterpret_cast(wd), value) - ); + restrict::wd_manager().capture_window(reinterpret_cast(wd), true, ignore_children); } - void capture_ignore_children(bool ignore) + void release_capture(window wd) { - restrict::wd_manager().capture_ignore_children(ignore); + //The 3rd parameter is useless when the 2nd parameter is false. + restrict::wd_manager().capture_window(reinterpret_cast(wd), false, false); } void modal_window(window wd) diff --git a/source/gui/widgets/button.cpp b/source/gui/widgets/button.cpp index 1b7aa835..ec0b6e85 100644 --- a/source/gui/widgets/button.cpp +++ b/source/gui/widgets/button.cpp @@ -321,11 +321,12 @@ namespace nana{ namespace drawerbase attr_.e_state = element_state::pressed; attr_.keep_pressed = true; - API::capture_window(*wdg_, true); + wdg_->set_capture(true); } else { - API::capture_window(*wdg_, false); + wdg_->release_capture(); + attr_.keep_pressed = false; if (attr_.enable_pushed && (false == attr_.pushed)) { diff --git a/source/gui/widgets/float_listbox.cpp b/source/gui/widgets/float_listbox.cpp index d2591ac0..c51c8342 100644 --- a/source/gui/widgets/float_listbox.cpp +++ b/source/gui/widgets/float_listbox.cpp @@ -469,8 +469,8 @@ namespace nana float_listbox::float_listbox(window wd, const rectangle & r, bool is_ignore_first_mouse_up) :base_type(wd, false, r, appear::bald()) { - API::capture_window(handle(), true); - API::capture_ignore_children(false); + this->set_capture(false); + API::take_active(handle(), false, parent()); auto & impl = get_drawer_trigger().get_drawer_impl(); impl.clear_state(); diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 007615cd..030283ad 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3343,7 +3343,8 @@ namespace nana nana::point pos = arg.pos; essence_->widget_to_header(pos); drawer_header_->grab(pos, true); - API::capture_window(essence_->lister.wd_ptr()->handle(), true); + essence_->lister.wd_ptr()->set_capture(true); + update = 2; } } @@ -3535,7 +3536,7 @@ namespace nana drawer_header_->grab(pos, false); refresh(graph); API::lazy_refresh(); - API::capture_window(essence_->lister.wd_ptr()->handle(), false); + essence_->lister.wd_ptr()->release_capture(); } } diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 3c372903..747e29a9 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1719,7 +1719,7 @@ namespace nana{ namespace widgets if (::nana::mouse::left_button == arg.button) { - API::capture_window(window_, true); + API::set_capture(window_, true); text_area_.captured = true; //Set caret pos by screen point and get the caret pos. @@ -1764,7 +1764,8 @@ namespace nana{ namespace widgets } select_.dragged = false; - API::capture_window(window_, false); + API::release_capture(window_); + text_area_.captured = false; if (hit_text_area(arg.pos) == false) API::window_cursor(window_, nana::cursor::arrow); diff --git a/source/gui/widgets/slider.cpp b/source/gui/widgets/slider.cpp index 45fbd122..38ba84e7 100644 --- a/source/gui/widgets/slider.cpp +++ b/source/gui/widgets/slider.cpp @@ -263,14 +263,15 @@ namespace nana slider_state_.trace = slider_state_.TraceCapture; slider_state_.snap_pos = static_cast(attr_.pos); slider_state_.refpos = pos; - API::capture_window(other_.wd, true); + API::set_capture(other_.wd, true); } bool release_slider() { if(slider_state_.trace == slider_state_.TraceCapture) { - API::capture_window(other_.wd, false); + API::release_capture(other_.wd); + if(other_.wd != API::find_window(API::cursor_position())) { slider_state_.trace = slider_state_.TraceNone; diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index 90397d41..427dc47d 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -351,7 +351,8 @@ namespace nana { if (!pressed) { - API::capture_window(editor_->window_handle(), false); + API::release_capture(editor_->window_handle()); + timer_.stop(); timer_.interval(600); } @@ -361,7 +362,7 @@ namespace nana //Spins the value when mouse button is released if (pressed) { - API::capture_window(editor_->window_handle(), true); + API::set_capture(editor_->window_handle(), true); range_->spin(buttons::increase == spin_stated_); reset_text(); timer_.start(); diff --git a/source/gui/widgets/widget.cpp b/source/gui/widgets/widget.cpp index 1169e59e..ac50687b 100644 --- a/source/gui/widgets/widget.cpp +++ b/source/gui/widgets/widget.cpp @@ -183,6 +183,16 @@ namespace nana _m_size(sz); } + void widget::set_capture(bool ignore_children) + { + API::set_capture(*this, ignore_children); + } + + void widget::release_capture() + { + API::release_capture(*this); + } + nana::point widget::pos() const { return API::window_position(handle());