diff --git a/include/nana/gui/detail/handle_manager.hpp b/include/nana/gui/detail/handle_manager.hpp deleted file mode 100644 index 6319e319..00000000 --- a/include/nana/gui/detail/handle_manager.hpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Handle Manager Implementation - * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or copy at - * http://www.boost.org/LICENSE_1_0.txt) - * - * @file: nana/gui/detail/handle_manager.hpp - * - * @description: - * this manages all the window handles - */ - -#ifndef NANA_GUI_DETAIL_HANDLE_MANAGER_HPP -#define NANA_GUI_DETAIL_HANDLE_MANAGER_HPP - -#include -#include -#if defined(STD_THREAD_NOT_SUPPORTED) - #include -#else - #include -#endif - -#include -#include -#include - - -namespace nana -{ - namespace detail - { - template - class cache - : noncopyable - { - public: - typedef Key key_type; - typedef Value value_type; - typedef std::pair pair_type; - typedef std::size_t size_type; - - cache() - :addr_(reinterpret_cast(::operator new(sizeof(pair_type) * CacheSize))) - { - for(std::size_t i = 0; i < CacheSize; ++i) - { - bitmap_[i] = 0; - seq_[i] = nana::npos; - } - } - - ~cache() - { - for(std::size_t i = 0; i < CacheSize; ++i) - { - if(bitmap_[i]) - addr_[i].~pair_type(); - } - - ::operator delete(addr_); - } - - bool insert(key_type k, value_type v) - { - size_type pos = _m_find_key(k); - if(pos != nana::npos) - { - addr_[pos].second = v; - } - else - { - //No key exists - pos = _m_find_pos(); - - if(pos == nana::npos) - { //No room, and remove the last pair - pos = seq_[CacheSize - 1]; - (addr_ + pos)->~pair_type(); - } - - if(seq_[0] != nana::npos) - {//Need to move - for(int i = CacheSize - 1; i > 0; --i) - seq_[i] = seq_[i - 1]; - } - - seq_[0] = pos; - - new (addr_ + pos) pair_type(k, v); - bitmap_[pos] = 1; - } - return v; - } - - value_type * get(key_type k) - { - size_type pos = _m_find_key(k); - if(pos != nana::npos) - return &(addr_[pos].second); - return 0; - } - private: - size_type _m_find_key(key_type k) const - { - for(std::size_t i = 0; i < CacheSize; ++i) - { - if(bitmap_[i] && (addr_[i].first == k)) - return i; - } - return nana::npos; - } - - size_type _m_find_pos() const - { - for(std::size_t i = 0; i < CacheSize; ++i) - { - if(bitmap_[i] == 0) - return i; - } - return nana::npos; - } - private: - char bitmap_[CacheSize]; - size_type seq_[CacheSize]; - pair_type * addr_; - }; - - //handle_manager - //@brief - // handle_manager maintains handles of a type. removing a handle dose not destroy it, - // it will be inserted to a trash queue for deleting at a safe time. - // For efficiency, this class is not a thread-safe. - template - class handle_manager - : nana::noncopyable - { - public: - typedef HandleType handle_type; - typedef Condition cond_type; - typedef Deleter deleter_type; - typedef std::map handle_map_t; - typedef std::pair holder_pair; - - ~handle_manager() - { - delete_trash(0); - } - - void insert(handle_type handle, unsigned tid) - { - std::lock_guard lock(mutex_); - - holder_[handle] = tid; - - is_queue::value, std::vector >::insert(handle, queue_); - cacher_.insert(handle, true); - } - - void operator()(const handle_type handle) - { - remove(handle); - } - - void remove(const handle_type handle) - { - std::lock_guard lock(mutex_); - - auto i = static_cast(holder_).find(handle); - if(holder_.cend() != i) - { - is_queue::value, std::vector >::erase(handle, queue_); - cacher_.insert(handle, false); - trash_.push_back(*i); - holder_.erase(i); - } - } - - void delete_trash(unsigned tid) - { - std::lock_guard lock(mutex_); - - if(trash_.size()) - { - deleter_type del_functor; - if(tid == 0) - { - for(auto & m : trash_) - del_functor(m.first); - trash_.clear(); - } - else - { - for(auto i = trash_.begin(), end = trash_.end(); i != end;) - { - if(tid == i->second) - { - del_functor(i->first); - i = trash_.erase(i); - end = trash_.end(); - } - else - ++i; - } - } - } - } - - handle_type last() const - { - std::lock_guard lock(mutex_); - if(queue_.size()) - return queue_.back(); - return handle_type(); - } - - std::size_t size() const - { - return holder_.size(); - } - - handle_type get(unsigned index) const - { - std::lock_guard lock(mutex_); - if(index < queue_.size()) - return queue_[index]; - return handle_type(); - } - - bool available(const handle_type handle) const - { - if (nullptr == handle) - return false; - - std::lock_guard lock(mutex_); - bool * v = cacher_.get(handle); - if(v) return *v; - return cacher_.insert(handle, (holder_.count(handle) != 0)); - } - - void all(std::vector & v) const - { - std::lock_guard lock(mutex_); - std::copy(queue_.cbegin(), queue_.cend(), std::back_inserter(v)); - } - private: - - template - struct is_queue - { - public: - static void insert(handle_type handle, Container& queue) - { - if(cond_type::is_queue(handle)) - queue.push_back(handle); - } - - static void erase(handle_type handle, Container& queue) - { - if(cond_type::is_queue(handle)) - { - for (auto i = queue.begin(); i != queue.end(); ++i) - { - if (handle == *i) - { - queue.erase(i); - break; - } - } - } - } - }; - - template - struct is_queue - { - public: - static void insert(handle_type handle, Container& queue){} - static void erase(handle_type handle, Container& queue){} - }; - - private: - mutable std::recursive_mutex mutex_; - mutable cache cacher_; - handle_map_t holder_; - std::vector queue_; - std::vector trash_; - };//end class handle_manager - }//end namespace detail -}// end namespace nana -#include - -#endif diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index e3491ac0..8fa5cd53 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -1,7 +1,7 @@ /** * Window Manager Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -20,7 +20,6 @@ #include -#include "window_layout.hpp" #include "event_code.hpp" #include "inner_fwd.hpp" #include @@ -31,6 +30,7 @@ namespace nana namespace paint { class image; + class graphics; } } @@ -68,12 +68,10 @@ namespace detail using mutex_type = revertible_mutex; using core_window_t = basic_window; - using window_layer = window_layout; window_manager(); ~window_manager(); - static bool is_queue(core_window_t*); std::size_t number_of_core_window() const; mutex_type & internal_lock() const; void all_handles(std::vector&) const; @@ -103,12 +101,11 @@ namespace detail // 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); bool show(core_window_t* wd, bool visible); - core_window_t* find_window(native_window_type root, int x, int y); + core_window_t* find_window(native_window_type root, const point& pos); //move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window bool move(core_window_t*, int x, int y, bool passive); diff --git a/include/nana/paint/detail/native_paint_interface.hpp b/include/nana/paint/detail/native_paint_interface.hpp index 2afa8056..844427a5 100644 --- a/include/nana/paint/detail/native_paint_interface.hpp +++ b/include/nana/paint/detail/native_paint_interface.hpp @@ -25,7 +25,6 @@ namespace detail void free_fade_table(const unsigned char*); //color = bgcolor * fade_rate + fgcolor * (1 - fade_rate); - //nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, double fade_rate); //deprecated nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, const unsigned char* const fade_table); nana::pixel_color_t fade_color_intermedia(pixel_color_t fgcolor, const unsigned char* fade_table); nana::pixel_color_t fade_color_by_intermedia(pixel_color_t bgcolor, nana::pixel_color_t fgcolor_intermedia, const unsigned char* const fade_table); diff --git a/source/detail/platform_spec_posix.cpp b/source/detail/platform_spec_posix.cpp index cce9028f..f343d941 100644 --- a/source/detail/platform_spec_posix.cpp +++ b/source/detail/platform_spec_posix.cpp @@ -1381,7 +1381,7 @@ namespace detail Window child; ::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child); - auto wd = bedrock.wd_manager().find_window(reinterpret_cast(evt.xclient.window), self.xdnd_.pos.x, self.xdnd_.pos.y); + auto wd = bedrock.wd_manager().find_window(reinterpret_cast(evt.xclient.window), self.xdnd_.pos); if(wd && wd->flags.dropable) { accepted = true; diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 2532e15d..10f11828 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -258,7 +258,7 @@ namespace nana return; native_interface::calc_window_point(native_handle, pos); - if (wd != wd_manager().find_window(native_handle, pos.x, pos.y)) + if (wd != wd_manager().find_window(native_handle, pos)) return; set_cursor(wd, wd->predef_cursor, thrd); diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index f6a8740b..6c4320d3 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -376,7 +376,7 @@ namespace detail switch(msg.kind) { case nana::detail::msg_packet_tag::kind_mouse_drop: - msgwd = brock.wd_manager().find_window(native_window, msg.u.mouse_drop.x, msg.u.mouse_drop.y); + msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y}); if(msgwd) { arg_dropfiles arg; @@ -511,7 +511,7 @@ namespace detail if(pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, xevent.xcrossing.x, xevent.xcrossing.y); + msgwnd = wd_manager.find_window(native_window, {xevent.xcrossing.x, xevent.xcrossing.y}); if(msgwnd) { if (mouse_action::pressed != msgwnd->flags.action) @@ -568,7 +568,7 @@ namespace detail if(xevent.xbutton.button == Button4 || xevent.xbutton.button == Button5) break; - msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y); + msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y}); pressed_wd = nullptr; if(nullptr == msgwnd) @@ -614,7 +614,7 @@ namespace detail auto pos = native_interface::cursor_position(); auto rootwd = native_interface::find_window(pos.x, pos.y); native_interface::calc_window_point(rootwd, pos); - if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y)) + if(msgwnd != wd_manager.find_window(rootwd, pos)) { //call the drawer mouse up event for restoring the surface graphics msgwnd->set_action(mouse_action::normal); @@ -634,7 +634,7 @@ namespace detail if(pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y); + msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y}); if(nullptr == msgwnd) break; @@ -754,7 +754,7 @@ namespace detail if(pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, xevent.xmotion.x, xevent.xmotion.y); + msgwnd = wd_manager.find_window(native_window, {xevent.xmotion.x, xevent.xmotion.y}); if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd)) { brock.event_msleave(hovered_wd); @@ -1282,7 +1282,7 @@ namespace detail return; native_interface::calc_window_point(native_handle, pos); - auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y); + auto rev_wd = wd_manager().find_window(native_handle, pos); if (rev_wd) set_cursor(rev_wd, rev_wd->predef_cursor, thrd); } diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 58f706b3..4c0ecc0b 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -805,10 +805,10 @@ namespace detail internal_scope_guard lock; auto msgwnd = root_runtime->window; - switch(message) + switch (message) { case WM_IME_STARTCOMPOSITION: - if(msgwnd->other.attribute.root->ime_enabled) + if (msgwnd->other.attribute.root->ime_enabled) { auto native_font = msgwnd->drawer.graphics.typeface().handle(); LOGFONTW logfont; @@ -820,7 +820,7 @@ namespace detail POINT pos; ::GetCaretPos(&pos); - COMPOSITIONFORM cf = {CFS_POINT}; + COMPOSITIONFORM cf = { CFS_POINT }; cf.ptCurrentPos = pos; restrict::imm_set_composition_window(imc, &cf); restrict::imm_release_context(root_window, imc); @@ -828,36 +828,36 @@ namespace detail def_window_proc = true; break; case WM_GETMINMAXINFO: - { - bool take_over = false; - auto mmi = reinterpret_cast(lParam); + { + bool take_over = false; + auto mmi = reinterpret_cast(lParam); - if(!msgwnd->min_track_size.empty()) + if (!msgwnd->min_track_size.empty()) + { + mmi->ptMinTrackSize.x = static_cast(msgwnd->min_track_size.width + msgwnd->extra_width); + mmi->ptMinTrackSize.y = static_cast(msgwnd->min_track_size.height + msgwnd->extra_height); + take_over = true; + } + + if (false == msgwnd->flags.fullscreen) + { + if (msgwnd->max_track_size.width && msgwnd->max_track_size.height) { - mmi->ptMinTrackSize.x = static_cast(msgwnd->min_track_size.width + msgwnd->extra_width); - mmi->ptMinTrackSize.y = static_cast(msgwnd->min_track_size.height + msgwnd->extra_height); + mmi->ptMaxTrackSize.x = static_cast(msgwnd->max_track_size.width + msgwnd->extra_width); + mmi->ptMaxTrackSize.y = static_cast(msgwnd->max_track_size.height + msgwnd->extra_height); + if (mmi->ptMaxSize.x > mmi->ptMaxTrackSize.x) + mmi->ptMaxSize.x = mmi->ptMaxTrackSize.x; + if (mmi->ptMaxSize.y > mmi->ptMaxTrackSize.y) + mmi->ptMaxSize.y = mmi->ptMaxTrackSize.y; + take_over = true; } - - if(false == msgwnd->flags.fullscreen) - { - if(msgwnd->max_track_size.width && msgwnd->max_track_size.height) - { - mmi->ptMaxTrackSize.x = static_cast(msgwnd->max_track_size.width + msgwnd->extra_width); - mmi->ptMaxTrackSize.y = static_cast(msgwnd->max_track_size.height + msgwnd->extra_height); - if(mmi->ptMaxSize.x > mmi->ptMaxTrackSize.x) - mmi->ptMaxSize.x = mmi->ptMaxTrackSize.x; - if(mmi->ptMaxSize.y > mmi->ptMaxTrackSize.y) - mmi->ptMaxSize.y = mmi->ptMaxTrackSize.y; - - take_over = true; - } - } - - if (take_over) - return 0; } - break; + + if (take_over) + return 0; + } + break; case WM_SHOWWINDOW: if (msgwnd->visible == (FALSE == wParam)) brock.event_expose(msgwnd, !msgwnd->visible); @@ -882,7 +882,7 @@ namespace detail def_window_proc = true; break; case WM_MOUSEACTIVATE: - if(msgwnd->flags.take_active == false) + if (msgwnd->flags.take_active == false) return MA_NOACTIVATE; def_window_proc = true; @@ -893,8 +893,8 @@ namespace detail break; pressed_wd = nullptr; - msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y); - if(msgwnd && msgwnd->flags.enabled) + msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y }); + if (msgwnd && msgwnd->flags.enabled) { if (msgwnd->flags.take_active && !msgwnd->flags.ignore_mouse_focus) { @@ -918,7 +918,7 @@ namespace detail if (pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y); + msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y }); //Don't take care about whether msgwnd is equal to the pressed_wd. // @@ -934,7 +934,7 @@ namespace detail else brock.close_menu_if_focus_other_window(msgwnd->root); - if(msgwnd->flags.enabled) + if (msgwnd->flags.enabled) { pressed_wd = msgwnd; @@ -962,7 +962,7 @@ namespace detail auto pos = native_interface::cursor_position(); auto rootwd = native_interface::find_window(pos.x, pos.y); native_interface::calc_window_point(rootwd, pos); - if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y)) + if (msgwnd != wd_manager.find_window(rootwd, pos)) { //call the drawer mouse up event for restoring the surface graphics msgwnd->set_action(mouse_action::normal); @@ -977,7 +977,7 @@ namespace detail pressed_wd = nullptr; } break; - //mouse_click, mouse_up + //mouse_click, mouse_up case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: @@ -985,12 +985,12 @@ namespace detail if (pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y); - if(nullptr == msgwnd) + msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y }); + if (nullptr == msgwnd) break; msgwnd->set_action(mouse_action::normal); - if(msgwnd->flags.enabled) + if (msgwnd->flags.enabled) { auto retain = msgwnd->annex.events_ptr; @@ -1014,7 +1014,7 @@ namespace detail } //Do mouse_up, this handle may be closed by click handler. - if(wd_manager.available(msgwnd) && msgwnd->flags.enabled) + if (wd_manager.available(msgwnd) && msgwnd->flags.enabled) { arg.evt_code = event_code::mouse_up; draw_invoker(&drawer::mouse_up, msgwnd, arg, &context); @@ -1040,7 +1040,7 @@ namespace detail if (pressed_wd_space) break; - msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y); + msgwnd = wd_manager.find_window(native_window, {pmdec.mouse.x, pmdec.mouse.y}); if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd)) { brock.event_msleave(hovered_wd); @@ -1121,7 +1121,7 @@ namespace detail if (pointer_wd == root_window) { ::ScreenToClient(pointer_wd, &scr_pos); - auto scrolled_wd = wd_manager.find_window(reinterpret_cast(pointer_wd), scr_pos.x, scr_pos.y); + auto scrolled_wd = wd_manager.find_window(reinterpret_cast(pointer_wd), { scr_pos.x, scr_pos.y }); def_window_proc = true; auto evt_wd = scrolled_wd; @@ -1162,10 +1162,12 @@ namespace detail case WM_DROPFILES: { HDROP drop = reinterpret_cast(wParam); - POINT pos; - ::DragQueryPoint(drop, &pos); + POINT mswin_pos; + ::DragQueryPoint(drop, &mswin_pos); - msgwnd = wd_manager.find_window(native_window, pos.x, pos.y); + const point pos{ mswin_pos.x, mswin_pos.y }; + + msgwnd = wd_manager.find_window(native_window, pos); if(msgwnd) { arg_dropfiles dropfiles; @@ -1193,8 +1195,7 @@ namespace detail if(msgwnd) { - dropfiles.pos.x = pos.x; - dropfiles.pos.y = pos.y; + dropfiles.pos = pos; wd_manager.calc_window_point(msgwnd, dropfiles.pos); dropfiles.window_handle = reinterpret_cast(msgwnd); @@ -1783,7 +1784,7 @@ namespace detail } native_interface::calc_window_point(native_handle, pos); - auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y); + auto rev_wd = wd_manager().find_window(native_handle, pos); if (rev_wd) { set_cursor(rev_wd, rev_wd->predef_cursor, thrd); diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index df048946..47edee53 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -14,14 +14,17 @@ #include #include #include -#include #include +#include +#include "window_register.hpp" #include #include #include #include + #include #include +#include #if defined(STD_THREAD_NOT_SUPPORTED) #include @@ -34,6 +37,8 @@ namespace nana namespace detail { + using window_layer = window_layout; + //class shortkey_container struct shortkey_rep { @@ -266,7 +271,8 @@ namespace detail struct window_manager::wdm_private_impl { root_register misc_register; - handle_manager wd_register; + window_register wd_register; + paint::image default_icon_big; paint::image default_icon_small; @@ -443,13 +449,11 @@ namespace detail delete impl_; } - bool window_manager::is_queue(core_window_t* wd) - { - return (wd && (category::flags::root == wd->other.category)); - } - std::size_t window_manager::number_of_core_window() const { + //Thread-Safe Required! + std::lock_guard lock(mutex_); + return impl_->wd_register.size(); } @@ -460,7 +464,9 @@ namespace detail void window_manager::all_handles(std::vector &v) const { - impl_->wd_register.all(v); + //Thread-Safe Required! + std::lock_guard lock(mutex_); + v = impl_->wd_register.queue(); } void window_manager::event_filter(core_window_t* wd, bool is_make, event_code evtid) @@ -477,11 +483,15 @@ namespace detail bool window_manager::available(core_window_t* wd) { + //Thread-Safe Required! + std::lock_guard lock(mutex_); return impl_->wd_register.available(wd); } bool window_manager::available(core_window_t * a, core_window_t* b) { + //Thread-Safe Required! + std::lock_guard lock(mutex_); return (impl_->wd_register.available(a) && impl_->wd_register.available(b)); } @@ -533,7 +543,7 @@ namespace detail auto* value = impl_->misc_register.insert(result.native_handle, root_misc(wd, result.width, result.height)); wd->bind_native_window(result.native_handle, result.width, result.height, result.extra_width, result.extra_height, value->root_graph); - impl_->wd_register.insert(wd, wd->thread_id); + impl_->wd_register.insert(wd); #ifndef WIDGET_FRAME_DEPRECATED if (owner && (category::flags::frame == owner->other.category)) @@ -614,7 +624,8 @@ namespace detail wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::lite_widget_tag**)nullptr); else wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::widget_tag**)nullptr); - impl_->wd_register.insert(wd, wd->thread_id); + + impl_->wd_register.insert(wd); return wd; } @@ -701,21 +712,23 @@ namespace detail } } - void window_manager::default_icon(const nana::paint::image& _small, const nana::paint::image& big) - { - impl_->default_icon_big = big; - impl_->default_icon_small = _small; - } - void window_manager::icon(core_window_t* wd, const paint::image& small_icon, const paint::image& big_icon) { if(!big_icon.empty() || !small_icon.empty()) { - std::lock_guard lock(mutex_); - if (impl_->wd_register.available(wd)) + if (nullptr == wd) { - if(category::flags::root == wd->other.category) - native_interface::window_icon(wd->root, small_icon, big_icon); + impl_->default_icon_big = big_icon; + impl_->default_icon_small = small_icon; + } + else + { + std::lock_guard lock(mutex_); + if (impl_->wd_register.available(wd)) + { + if (category::flags::root == wd->other.category) + native_interface::window_icon(wd->root, small_icon, big_icon); + } } } } @@ -791,7 +804,7 @@ namespace detail return true; } - window_manager::core_window_t* window_manager::find_window(native_window_type root, int x, int y) + window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos) { if (nullptr == root) return nullptr; @@ -801,7 +814,6 @@ namespace detail //Thread-Safe Required! std::lock_guard lock(mutex_); auto rrt = root_runtime(root); - point pos{ x, y }; if (rrt && _m_effective(rrt->window, pos)) return _m_find(rrt->window, pos); } @@ -873,9 +885,8 @@ namespace detail //Move child widgets if(r.x != wd->pos_owner.x || r.y != wd->pos_owner.y) { - point delta{ r.x - wd->pos_owner.x, r.y - wd->pos_owner.y }; - wd->pos_owner.x = r.x; - wd->pos_owner.y = r.y; + auto delta = r.position() - wd->pos_owner; + wd->pos_owner = r.position(); _m_move_core(wd, delta); moved = true; @@ -1807,32 +1818,18 @@ namespace detail brock.emit(event_code::destroy, wd, arg, true, brock.get_thread_context()); //Delete the children widgets. - for (auto i = wd->children.rbegin(), end = wd->children.rend(); i != end;) + while (!wd->children.empty()) { - auto child = *i; - + auto child = wd->children.back(); if (category::flags::root == child->other.category) { - //closing a child root window erases itself from wd->children, - //to make sure the iterator is valid, it must be reloaded. - - auto offset = std::distance(wd->children.rbegin(), i); - - //!!! - //a potential issue is that if the calling thread is not same with child's thread, - //the child root window may not be erased from wd->children now. + //Only the nested_form meets the condition native_interface::close_window(child->root); - - i = wd->children.rbegin(); - std::advance(i, offset); - end = wd->children.rend(); continue; } _m_destroy(child); - ++i; + wd->children.pop_back(); } - wd->children.clear(); - _m_disengage(wd, nullptr); window_layer::enable_effects_bground(wd, false); diff --git a/source/gui/detail/window_register.hpp b/source/gui/detail/window_register.hpp new file mode 100644 index 00000000..c9586c89 --- /dev/null +++ b/source/gui/detail/window_register.hpp @@ -0,0 +1,201 @@ +#ifndef NANA_WINDOW_REGISTER_HEADER_INCLUDED +#define NANA_WINDOW_REGISTER_HEADER_INCLUDED + +#include +#include +#include +#include //std::find + +namespace nana +{ + namespace detail + { + template + class cache + : noncopyable + { + public: + typedef Key key_type; + typedef Value value_type; + typedef std::pair pair_type; + typedef std::size_t size_type; + + cache() + :addr_(reinterpret_cast(::operator new(sizeof(pair_type) * CacheSize))) + { + for (std::size_t i = 0; i < CacheSize; ++i) + { + bitmap_[i] = 0; + seq_[i] = nana::npos; + } + } + + ~cache() + { + for (std::size_t i = 0; i < CacheSize; ++i) + { + if (bitmap_[i]) + addr_[i].~pair_type(); + } + + ::operator delete(addr_); + } + + bool insert(key_type k, value_type v) + { + size_type pos = _m_find_key(k); + if (pos != nana::npos) + { + addr_[pos].second = v; + } + else + { + //No key exists + pos = _m_find_pos(); + + if (pos == nana::npos) + { //No room, and remove the last pair + pos = seq_[CacheSize - 1]; + (addr_ + pos)->~pair_type(); + } + + if (seq_[0] != nana::npos) + {//Need to move + for (int i = CacheSize - 1; i > 0; --i) + seq_[i] = seq_[i - 1]; + } + + seq_[0] = pos; + + new (addr_ + pos) pair_type(k, v); + bitmap_[pos] = 1; + } + return v; + } + + value_type * get(key_type k) + { + size_type pos = _m_find_key(k); + if (pos != nana::npos) + return &(addr_[pos].second); + return 0; + } + private: + size_type _m_find_key(key_type k) const + { + for (std::size_t i = 0; i < CacheSize; ++i) + { + if (bitmap_[i] && (addr_[i].first == k)) + return i; + } + return nana::npos; + } + + size_type _m_find_pos() const + { + for (std::size_t i = 0; i < CacheSize; ++i) + { + if (bitmap_[i] == 0) + return i; + } + return nana::npos; + } + private: + char bitmap_[CacheSize]; + size_type seq_[CacheSize]; + pair_type * addr_; + }; + + class window_register + { + public: + using window_handle_type = basic_window*; + + void insert(window_handle_type wd) + { + if (wd) + { + base_.insert(wd); + wdcache_.insert(wd, true); + + if (category::flags::root == wd->other.category) + queue_.push_back(wd); + } + } + + void operator()(window_handle_type wd) + { + remove(wd); + } + + void remove(window_handle_type wd) + { + if (base_.erase(wd)) + { + wdcache_.insert(wd, false); + if (category::flags::root == wd->other.category) + { + trash_.push_back(wd); + auto i = std::find(queue_.begin(), queue_.end(), wd); + if (i != queue_.end()) + queue_.erase(i); + } + } + } + + void delete_trash(unsigned thread_id) + { + if (0 == thread_id) + { + for (auto wd : trash_) + delete wd; + + trash_.clear(); + } + else + { + for (auto i = trash_.begin(); i != trash_.end();) + { + if (thread_id == (*i)->thread_id) + { + delete (*i); + i = trash_.erase(i); + } + else + ++i; + } + } + } + + const std::vector& queue() const + { + return queue_; + } + + /// Returns the number of registered windows + std::size_t size() const + { + return base_.size(); + } + + bool available(window_handle_type wd) const + { + if (nullptr == wd) + return false; + + auto exists = wdcache_.get(wd); + if (exists) + return *exists; + + return wdcache_.insert(wd, (base_.count(wd) != 0)); + } + private: + mutable cache wdcache_; + std::set base_; + std::vector trash_; + std::vector queue_; + }; + } +} + +#endif diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index c4ca6192..6f91756e 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -461,12 +461,13 @@ namespace API void window_icon_default(const paint::image& small_icon, const paint::image& big_icon) { - restrict::wd_manager().default_icon(small_icon, big_icon); + restrict::wd_manager().icon(nullptr, small_icon, big_icon); } void window_icon(window wd, const paint::image& small_icon, const paint::image& big_icon) { - restrict::wd_manager().icon(reinterpret_cast(wd), small_icon, big_icon); + if(nullptr != wd) + restrict::wd_manager().icon(reinterpret_cast(wd), small_icon, big_icon); } bool empty_window(window wd) @@ -1320,7 +1321,7 @@ namespace API ::nana::point clipos{pos}; interface_type::calc_window_point(wd, clipos); return reinterpret_cast( - restrict::wd_manager().find_window(wd, clipos.x, clipos.y)); + restrict::wd_manager().find_window(wd, clipos)); } return nullptr; } diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 51eb0b56..607cf05f 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -204,14 +204,12 @@ namespace nana range_width_px.first = minimum; range_width_px.second = maximum; - if (width_px < range_width_px.first) - width_px = range_width_px.first; - else if (range_width_px.second < width_px) - width_px = range_width_px.second; - else - return; - - _m_refresh(); + unsigned px = std::clamp(static_cast(width_px), static_cast(minimum), static_cast(maximum)); + if (width_px != px) + { + width_px = px; + _m_refresh(); + } } size_type position(bool disp_order) const noexcept override; //The definition is provided after essence @@ -3104,10 +3102,7 @@ namespace nana if (col.range_width_px.first != col.range_width_px.second) { //Column ranged width - if (new_w < col.range_width_px.first) - new_w = col.range_width_px.first; - else if (new_w > col.range_width_px.second) - new_w = col.range_width_px.second; + new_w = std::clamp(static_cast(new_w), static_cast(col.range_width_px.first), static_cast(col.range_width_px.second)); } else { @@ -3129,7 +3124,6 @@ namespace nana { const auto border_color = essence_->scheme_ptr->header_bgcolor.get_color().blend(colors::black, 0.2); - int text_top = (r.height - essence_->text_height) / 2 + r.y; auto text_color = essence_->scheme_ptr->header_fgcolor.get_color(); auto state = item_state::normal; @@ -3153,7 +3147,7 @@ namespace nana //Make sure the column is in the display area. if (right_pos > r.x) { - _m_draw_header_item(graph, column_r, text_top, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal)); + _m_draw_header_item(graph, column_r, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal)); graph.line({ right_pos - 1, r.y }, { right_pos - 1, r.bottom() - 2 }, border_color); } @@ -3191,10 +3185,8 @@ namespace nana { //convert x to header logic coordinate. auto const x_offset = essence_->content_view->origin().x; - if (x < x_offset) - x = x_offset; - else if (x > x_offset + static_cast(rect.width)) - x = x_offset + static_cast(rect.width); + + x = std::clamp(x, x_offset, x_offset + static_cast(rect.width)); auto i = essence_->header.column_from_point(x); @@ -3219,9 +3211,10 @@ namespace nana return npos; } - void _m_draw_header_item(graph_reference graph, const rectangle& column_r, int text_top, const ::nana::color& fgcolor, const es_header::column& column, item_state state) + void _m_draw_header_item(graph_reference graph, const rectangle& column_r, const ::nana::color& fgcolor, const es_header::column& column, item_state state) { ::nana::color bgcolor; + switch(state) { case item_state::normal: bgcolor = essence_->scheme_ptr->header_bgcolor.get_color(); break; @@ -3249,7 +3242,7 @@ namespace nana { graph.palette(true, fgcolor); - point text_pos{ column_r.x, text_top }; + point text_pos{ column_r.x, (static_cast(essence_->scheme_ptr->header_height) - static_cast(essence_->text_height)) / 2 }; if (align::left == column.alignment) text_pos.x += text_margin; @@ -3277,11 +3270,9 @@ namespace nana fl_graph.typeface(essence_->graph->typeface()); - int text_top = (essence_->scheme_ptr->header_height - essence_->text_height) / 2; - _m_draw_header_item(fl_graph, rectangle{ fl_graph.size()}, text_top, colors::white, col, item_state::floated); + _m_draw_header_item(fl_graph, rectangle{ fl_graph.size()}, colors::white, col, item_state::floated); auto xpos = essence_->header.position(col.index, nullptr) + pos.x - grabs_.start_pos; - essence_->graph->blend(rectangle{ point{ xpos - essence_->content_view->origin().x + rect.x, rect.y } , fl_graph.size() }, fl_graph, {}, 0.5); } diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 69b1d79e..eed730ea 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -419,8 +419,13 @@ namespace nana{ namespace widgets //Overrides methods of colored_area_access_interface std::shared_ptr get(std::size_t line_pos) override { +#ifdef _MSC_VER auto i = colored_areas_.cbegin(); for (; i != colored_areas_.cend(); ++i) +#else + auto i = colored_areas_.begin(); + for (; i != colored_areas_.end(); ++i) +#endif { auto & area = *(i->get()); if (area.begin <= line_pos && line_pos < area.begin + area.count) @@ -430,10 +435,9 @@ namespace nana{ namespace widgets break; } - auto iter = colored_areas_.emplace(i, std::make_shared(colored_area_type{line_pos})); - auto & area = *(iter->get()); - area.count = 1; - return *iter; + return *colored_areas_.emplace(i, + std::make_shared(colored_area_type{line_pos, 1, color{}, color{}}) + ); } bool clear() @@ -449,7 +453,11 @@ namespace nana{ namespace widgets bool remove(std::size_t pos) override { bool changed = false; +#ifdef _MSC_VER for (auto i = colored_areas_.cbegin(); i != colored_areas_.cend();) +#else + for (auto i = colored_areas_.begin(); i != colored_areas_.end();) +#endif { if (i->get()->begin <= pos && pos < i->get()->begin + i->get()->count) {