Merge branch 'hotfix-1.6.1' into develop
This commit is contained in:
		
						commit
						52d814673b
					
				@ -23,6 +23,8 @@
 | 
				
			|||||||
	#include <windows.h>
 | 
						#include <windows.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nana{	namespace audio
 | 
					namespace nana{	namespace audio
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	namespace detail
 | 
						namespace detail
 | 
				
			||||||
@ -52,8 +54,8 @@ namespace nana{	namespace audio
 | 
				
			|||||||
		private:
 | 
							private:
 | 
				
			||||||
			void _m_prepare_routine();
 | 
								void _m_prepare_routine();
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
			volatile bool running_;
 | 
								std::atomic<bool> running_;
 | 
				
			||||||
			volatile bool wait_for_buffer_;
 | 
								std::atomic<bool> wait_for_buffer_;
 | 
				
			||||||
			std::thread thr_;
 | 
								std::thread thr_;
 | 
				
			||||||
			mutable std::mutex token_buffer_, token_prepared_;
 | 
								mutable std::mutex token_buffer_, token_prepared_;
 | 
				
			||||||
			mutable std::condition_variable	cond_buffer_, cond_prepared_;
 | 
								mutable std::condition_variable	cond_buffer_, cond_prepared_;
 | 
				
			||||||
 | 
				
			|||||||
@ -220,12 +220,14 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#undef _nana_std_has_string_view
 | 
					#undef _nana_std_has_string_view
 | 
				
			||||||
 | 
					#undef _nana_std_has_returnable_emplace_back
 | 
				
			||||||
#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) ||				\
 | 
					#if ((defined(_MSC_VER) && (_MSC_VER >= 1912) && defined(_MSVC_LANG) && _MSVC_LANG >= 201703)) ||				\
 | 
				
			||||||
	((__cplusplus >= 201703L) && \
 | 
						((__cplusplus >= 201703L) && \
 | 
				
			||||||
		(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) ||		\
 | 
							(defined(__clang__) && (__clang_major__ * 100 + __clang_minor__ >= 400) ||		\
 | 
				
			||||||
		(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \
 | 
							(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 701))) \
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
#	define _nana_std_has_string_view
 | 
					#	define _nana_std_has_string_view
 | 
				
			||||||
 | 
					#	define _nana_std_has_returnable_emplace_back
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -51,6 +51,13 @@ namespace nana
 | 
				
			|||||||
		top_left, top_right, bottom_left, bottom_right
 | 
							top_left, top_right, bottom_left, bottom_right
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum class window_relationship
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							owner,		///< Owner window.
 | 
				
			||||||
 | 
							parent,		///< Parent window.
 | 
				
			||||||
 | 
							either_po 	///< One between owner and parent.
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum class bground_mode
 | 
						enum class bground_mode
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		none,
 | 
							none,
 | 
				
			||||||
 | 
				
			|||||||
@ -172,7 +172,7 @@ namespace nana
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			else if constexpr(std::is_invocable_v<Function>)
 | 
								else if constexpr(std::is_invocable_v<Function>)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return _m_emplace(new docker{ this, [fn](arg_reference){
 | 
									return _m_emplace(new docker{ this, [fn](arg_reference) mutable{
 | 
				
			||||||
					fn();
 | 
										fn();
 | 
				
			||||||
				}, false }, false);
 | 
									}, false }, false);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -200,7 +200,7 @@ namespace nana
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			else if constexpr(std::is_invocable_v<Function>)
 | 
								else if constexpr(std::is_invocable_v<Function>)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return _m_emplace(new docker{ this, [fn](arg_reference) {
 | 
									return _m_emplace(new docker{ this, [fn](arg_reference) mutable{
 | 
				
			||||||
					fn();
 | 
										fn();
 | 
				
			||||||
				}, true }, in_front);
 | 
									}, true }, in_front);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Platform Implementation
 | 
					 *	Platform Implementation
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0. 
 | 
					 *	Distributed under the Boost Software License, Version 1.0. 
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at 
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at 
 | 
				
			||||||
@ -36,6 +36,14 @@ namespace detail
 | 
				
			|||||||
			unsigned extra_height;	//extra border size, it is useful in Windows, ignore in X11 always 0
 | 
								unsigned extra_height;	//extra border size, it is useful in Windows, ignore in X11 always 0
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct frame_extents
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int left;
 | 
				
			||||||
 | 
								int right;
 | 
				
			||||||
 | 
								int top;
 | 
				
			||||||
 | 
								int bottom;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		using native_string_type = ::nana::detail::native_string_type;
 | 
							using native_string_type = ::nana::detail::native_string_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//Execute a function in a thread which is associated with the specified native window.
 | 
							//Execute a function in a thread which is associated with the specified native window.
 | 
				
			||||||
@ -70,14 +78,15 @@ namespace detail
 | 
				
			|||||||
		static void bring_top(native_window_type, bool activated);
 | 
							static void bring_top(native_window_type, bool activated);
 | 
				
			||||||
		static void	set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after);
 | 
							static void	set_window_z_order(native_window_type, native_window_type wd_after, z_order_action action_if_no_wd_after);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static frame_extents window_frame_extents(native_window_type);
 | 
				
			||||||
		static bool	window_size(native_window_type, const size&);
 | 
							static bool	window_size(native_window_type, const size&);
 | 
				
			||||||
		static void	get_window_rect(native_window_type, rectangle&);
 | 
							static void	get_window_rect(native_window_type, rectangle&);
 | 
				
			||||||
		static void	window_caption(native_window_type, const native_string_type&);
 | 
							static void	window_caption(native_window_type, const native_string_type&);
 | 
				
			||||||
		static native_string_type	window_caption(native_window_type);
 | 
							static native_string_type	window_caption(native_window_type);
 | 
				
			||||||
		static void	capture_window(native_window_type, bool);
 | 
							static void	capture_window(native_window_type, bool);
 | 
				
			||||||
		static nana::point	cursor_position();
 | 
							static nana::point	cursor_position();
 | 
				
			||||||
		static native_window_type get_owner_window(native_window_type);
 | 
					
 | 
				
			||||||
		static native_window_type parent_window(native_window_type);
 | 
							static native_window_type get_window(native_window_type wd, window_relationship);
 | 
				
			||||||
		static native_window_type parent_window(native_window_type child, native_window_type new_parent, bool returns_previous);
 | 
							static native_window_type parent_window(native_window_type child, native_window_type new_parent, bool returns_previous);
 | 
				
			||||||
		//For Caret
 | 
							//For Caret
 | 
				
			||||||
		static void caret_create(native_window_type, const ::nana::size&);
 | 
							static void caret_create(native_window_type, const ::nana::size&);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
*	A Message Box Class
 | 
					*	A Message Box Class
 | 
				
			||||||
*	Nana C++ Library(http://www.nanapro.org)
 | 
					*	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
*	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					*	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
*
 | 
					*
 | 
				
			||||||
*	Distributed under the Boost Software License, Version 1.0.
 | 
					*	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
*	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					*	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -255,7 +255,11 @@ namespace nana
 | 
				
			|||||||
		bool show_modal(Args&& ... args)
 | 
							bool show_modal(Args&& ... args)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::vector<abstract_content*> contents;
 | 
								std::vector<abstract_content*> contents;
 | 
				
			||||||
 | 
					#ifdef __cpp_fold_expressions
 | 
				
			||||||
 | 
								(contents.emplace_back(&args), ...);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
			_m_fetch_args(contents, std::forward<Args>(args)...);
 | 
								_m_fetch_args(contents, std::forward<Args>(args)...);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (contents.empty())
 | 
								if (contents.empty())
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	A Widget Iterator Template
 | 
					 *	A Widget Iterator Template
 | 
				
			||||||
 *	Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2017-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -23,6 +23,7 @@ namespace nana {
 | 
				
			|||||||
			template<typename Category, typename T>
 | 
								template<typename Category, typename T>
 | 
				
			||||||
			class widget_iterator
 | 
								class widget_iterator
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 | 
								public:
 | 
				
			||||||
				using iterator_category = Category;
 | 
									using iterator_category = Category;
 | 
				
			||||||
				using value_type = T;
 | 
									using value_type = T;
 | 
				
			||||||
				using difference_type = std::ptrdiff_t;
 | 
									using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
				
			|||||||
@ -1033,6 +1033,7 @@ namespace nana
 | 
				
			|||||||
				template<typename T>
 | 
									template<typename T>
 | 
				
			||||||
				void append_model(const T& t)
 | 
									void append_model(const T& t)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
 | 
										nana::internal_scope_guard lock;
 | 
				
			||||||
					_m_try_append_model(const_virtual_pointer{ &t });
 | 
										_m_try_append_model(const_virtual_pointer{ &t });
 | 
				
			||||||
					_m_update();
 | 
										_m_update();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Text Token Stream
 | 
					 *	Text Token Stream
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -22,6 +22,7 @@
 | 
				
			|||||||
#include <stdexcept>
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nana/push_ignore_diagnostic>
 | 
					#include <nana/push_ignore_diagnostic>
 | 
				
			||||||
 | 
					#include <nana/unicode_bidi.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nana{ namespace widgets{	namespace skeletons
 | 
					namespace nana{ namespace widgets{	namespace skeletons
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -95,10 +96,19 @@ namespace nana{ namespace widgets{	namespace skeletons
 | 
				
			|||||||
			return std::stoi(idstr_, nullptr, 0);
 | 
								return std::stoi(idstr_, nullptr, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		static bool _m_unicode_word_breakable(wchar_t ch)
 | 
							/*
 | 
				
			||||||
 | 
							static bool _m_unicode_word_breakable(wchar_t ch)	//deprecated
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			return ((0x4E00 <= ch) && (ch <= 0x9FFF));
 | 
								return ((0x4E00 <= ch) && (ch <= 0x9FFF));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static bool _m_unicode_word_breakable(const wchar_t* ch) noexcept
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (*ch)
 | 
				
			||||||
 | 
									return unicode_wordbreak(*ch, ch[1]);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//Read the data token
 | 
							//Read the data token
 | 
				
			||||||
		token _m_token()
 | 
							token _m_token()
 | 
				
			||||||
@ -112,14 +122,14 @@ namespace nana{ namespace widgets{	namespace skeletons
 | 
				
			|||||||
				idstr_.clear();
 | 
									idstr_.clear();
 | 
				
			||||||
				idstr_.append(1, ch);
 | 
									idstr_.append(1, ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(_m_unicode_word_breakable(ch))
 | 
									if (_m_unicode_word_breakable(iptr_))
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					++iptr_;
 | 
										++iptr_;
 | 
				
			||||||
					return token::data;
 | 
										return token::data;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				ch = *++iptr_;
 | 
									ch = *++iptr_;
 | 
				
			||||||
				while((iptr_ != endptr_) && (ch > 0xFF) && (false == _m_unicode_word_breakable(ch)))
 | 
									while((iptr_ != endptr_) && (ch > 0xFF) && (false == _m_unicode_word_breakable(iptr_)))
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					idstr_.append(1, ch);
 | 
										idstr_.append(1, ch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -170,7 +170,8 @@ namespace nana
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /// Base class of all the classes defined as a widget window. Defaultly a widget_tag
 | 
					            /// Base class of all the classes defined as a widget window. Defaultly a widget_tag
 | 
				
			||||||
	template<typename Category, typename DrawerTrigger, typename Events = ::nana::general_events, typename Scheme = ::nana::widget_geometrics>
 | 
						template<typename Category, typename DrawerTrigger, typename Events = ::nana::general_events, typename Scheme = ::nana::widget_geometrics,
 | 
				
			||||||
 | 
								typename = typename std::enable_if<std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value>::type> //type DrawerTrigger must be derived from nana::drawer_trigger
 | 
				
			||||||
	class widget_object: public detail::widget_base
 | 
						class widget_object: public detail::widget_base
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	protected:
 | 
						protected:
 | 
				
			||||||
@ -182,7 +183,9 @@ namespace nana
 | 
				
			|||||||
		widget_object()
 | 
							widget_object()
 | 
				
			||||||
			:	events_{ std::make_shared<Events>() },
 | 
								:	events_{ std::make_shared<Events>() },
 | 
				
			||||||
				scheme_{ API::dev::make_scheme<Scheme>() }
 | 
									scheme_{ API::dev::make_scheme<Scheme>() }
 | 
				
			||||||
		{}
 | 
							{
 | 
				
			||||||
 | 
								static_assert(std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value, "The type DrawerTrigger must be derived from nana::drawer_trigger");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~widget_object()
 | 
							~widget_object()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -291,7 +294,7 @@ namespace nana
 | 
				
			|||||||
	};//end class widget_object
 | 
						};//end class widget_object
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	        /// Base class of all the classes defined as a non-graphics-buffer widget window. The second template parameter DrawerTrigger is always ignored.\see nana::panel
 | 
						        /// Base class of all the classes defined as a non-graphics-buffer widget window. The second template parameter DrawerTrigger is always ignored.\see nana::panel
 | 
				
			||||||
	template<typename DrawerTrigger, typename Events, typename Scheme>
 | 
						template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger
 | 
				
			||||||
	class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
 | 
						class widget_object<category::lite_widget_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	protected:
 | 
						protected:
 | 
				
			||||||
@ -302,7 +305,9 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		widget_object()
 | 
							widget_object()
 | 
				
			||||||
			: events_{ std::make_shared<Events>() }, scheme_{ API::dev::make_scheme<scheme_type>() }
 | 
								: events_{ std::make_shared<Events>() }, scheme_{ API::dev::make_scheme<scheme_type>() }
 | 
				
			||||||
		{}
 | 
							{
 | 
				
			||||||
 | 
								static_assert(std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value, "The type DrawerTrigger must be derived from nana::drawer_trigger");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		~widget_object()
 | 
							~widget_object()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -355,7 +360,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	        /// Base class of all the classes defined as a root window. \see nana::form
 | 
						        /// Base class of all the classes defined as a root window. \see nana::form
 | 
				
			||||||
	template<typename DrawerTrigger, typename Events, typename Scheme>
 | 
						template<typename DrawerTrigger, typename Events, typename Scheme> //type DrawerTrigger must be derived from nana::drawer_trigger
 | 
				
			||||||
	class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
 | 
						class widget_object<category::root_tag, DrawerTrigger, Events, Scheme>: public detail::widget_base
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	protected:
 | 
						protected:
 | 
				
			||||||
@ -367,10 +372,12 @@ namespace nana
 | 
				
			|||||||
		widget_object()
 | 
							widget_object()
 | 
				
			||||||
			: widget_object(nullptr, false, API::make_center(300, 150), appearance(), this)
 | 
								: widget_object(nullptr, false, API::make_center(300, 150), appearance(), this)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								static_assert(std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value, "The type DrawerTrigger must be derived from nana::drawer_trigger");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		widget_object(window owner, bool nested, const rectangle& r = {}, const appearance& apr = {})
 | 
							widget_object(window owner, bool nested, const rectangle& r = {}, const appearance& apr = {})
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								static_assert(std::is_base_of<::nana::drawer_trigger, DrawerTrigger>::value, "The type DrawerTrigger must be derived from nana::drawer_trigger");
 | 
				
			||||||
			handle_ = API::dev::create_window(owner, nested, r, apr, this);
 | 
								handle_ = API::dev::create_window(owner, nested, r, apr, this);
 | 
				
			||||||
			_m_bind_and_attach();
 | 
								_m_bind_and_attach();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	An Implementation of i18n
 | 
					 *	An Implementation of i18n
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
 | 
				
			|||||||
@ -193,7 +193,7 @@ namespace nana{ namespace pat{
 | 
				
			|||||||
			cwrapper_.reset();
 | 
								cwrapper_.reset();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		operator operator_bool_t() const volatile noexcept
 | 
							operator operator_bool_t() const noexcept
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			return (fast_ptr_ ? &inner_bool::true_stand : nullptr);
 | 
								return (fast_ptr_ ? &inner_bool::true_stand : nullptr);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 6)
 | 
					#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 | 
				
			||||||
#	pragma GCC diagnostic pop
 | 
					#	pragma GCC diagnostic pop
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 6)
 | 
					#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 | 
				
			||||||
#	pragma GCC diagnostic push
 | 
					#	pragma GCC diagnostic push
 | 
				
			||||||
#	pragma GCC diagnostic ignored "-Weffc++"
 | 
					#	pragma GCC diagnostic ignored "-Weffc++"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Timepiece Implementation
 | 
					 *	Timepiece Implementation
 | 
				
			||||||
 *	Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -13,6 +13,8 @@
 | 
				
			|||||||
#ifndef NANA_SYSTEM_TIMEPIECE_HPP
 | 
					#ifndef NANA_SYSTEM_TIMEPIECE_HPP
 | 
				
			||||||
#define NANA_SYSTEM_TIMEPIECE_HPP
 | 
					#define NANA_SYSTEM_TIMEPIECE_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../c++defines.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nana
 | 
					namespace nana
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
namespace system
 | 
					namespace system
 | 
				
			||||||
@ -21,11 +23,11 @@ namespace system
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		timepiece();
 | 
							timepiece();
 | 
				
			||||||
		timepiece(const volatile timepiece&);
 | 
							timepiece(const timepiece&);
 | 
				
			||||||
		~timepiece();
 | 
							~timepiece();
 | 
				
			||||||
		timepiece & operator=(const volatile timepiece &);
 | 
							timepiece & operator=(const timepiece &);
 | 
				
			||||||
		void start() volatile;              ///<  	Set the begin time.
 | 
							void start() noexcept;              ///<  	Set the begin time.
 | 
				
			||||||
		double calc() const volatile;       ///<    Get the intervals from the begin time.
 | 
							double calc() const noexcept;       ///<    Get the intervals from the begin time.
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		struct impl_t;
 | 
							struct impl_t;
 | 
				
			||||||
		impl_t * impl_;
 | 
							impl_t * impl_;
 | 
				
			||||||
 | 
				
			|||||||
@ -71,6 +71,8 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	std::vector<unicode_bidi::entity> unicode_reorder(const wchar_t* text, std::size_t length);
 | 
						std::vector<unicode_bidi::entity> unicode_reorder(const wchar_t* text, std::size_t length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool unicode_wordbreak(wchar_t left, wchar_t right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#include <nana/pop_ignore_diagnostic>
 | 
					#include <nana/pop_ignore_diagnostic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Platform Specification Implementation
 | 
					 *	Platform Specification Implementation
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
 | 
				
			|||||||
@ -486,6 +486,7 @@ namespace detail
 | 
				
			|||||||
		atombase_.wm_protocols = ::XInternAtom(display_, "WM_PROTOCOLS", False);
 | 
							atombase_.wm_protocols = ::XInternAtom(display_, "WM_PROTOCOLS", False);
 | 
				
			||||||
		atombase_.wm_change_state = ::XInternAtom(display_, "WM_CHANGE_STATE", False);
 | 
							atombase_.wm_change_state = ::XInternAtom(display_, "WM_CHANGE_STATE", False);
 | 
				
			||||||
		atombase_.wm_delete_window = ::XInternAtom(display_, "WM_DELETE_WINDOW", False);
 | 
							atombase_.wm_delete_window = ::XInternAtom(display_, "WM_DELETE_WINDOW", False);
 | 
				
			||||||
 | 
							atombase_.net_frame_extents = ::XInternAtom(display_, "_NET_FRAME_EXTENTS", False);
 | 
				
			||||||
		atombase_.net_wm_state = ::XInternAtom(display_, "_NET_WM_STATE", False);
 | 
							atombase_.net_wm_state = ::XInternAtom(display_, "_NET_WM_STATE", False);
 | 
				
			||||||
		atombase_.net_wm_state_skip_taskbar = ::XInternAtom(display_, "_NET_WM_STATE_SKIP_TASKBAR", False);
 | 
							atombase_.net_wm_state_skip_taskbar = ::XInternAtom(display_, "_NET_WM_STATE_SKIP_TASKBAR", False);
 | 
				
			||||||
		atombase_.net_wm_state_fullscreen = ::XInternAtom(display_, "_NET_WM_STATE_FULLSCREEN", False);
 | 
							atombase_.net_wm_state_fullscreen = ::XInternAtom(display_, "_NET_WM_STATE_FULLSCREEN", False);
 | 
				
			||||||
@ -588,16 +589,59 @@ namespace detail
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//There are three members make_owner(), get_owner() and remove(),
 | 
						//There are three members make_owner(), get_owner() and remove(),
 | 
				
			||||||
	//they are maintain a table to discribe the owner of windows because the feature in X11, the
 | 
						//they are maintain a table to discribe the owner of windows because of the feature in X11, the
 | 
				
			||||||
	//owner of top level window must be RootWindow.
 | 
						//owner of top level window must be RootWindow.
 | 
				
			||||||
	void platform_spec::make_owner(native_window_type owner, native_window_type wd)
 | 
						void platform_spec::make_owner(native_window_type owner, native_window_type wd)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		platform_scope_guard psg;
 | 
							platform_scope_guard lock;
 | 
				
			||||||
		wincontext_[wd].owner = owner;
 | 
							wincontext_[wd].owner = owner;
 | 
				
			||||||
		window_context_t & context = wincontext_[owner];
 | 
							
 | 
				
			||||||
		if(context.owned == 0)
 | 
							auto& owner_ctx = wincontext_[owner];
 | 
				
			||||||
			context.owned = new std::vector<native_window_type>;
 | 
							if(!owner_ctx.owned)
 | 
				
			||||||
		context.owned->push_back(wd);
 | 
								owner_ctx.owned = new std::vector<native_window_type>;
 | 
				
			||||||
 | 
							owner_ctx.owned->push_back(wd);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool platform_spec::umake_owner(native_window_type child)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							platform_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto i = wincontext_.find(child);
 | 
				
			||||||
 | 
							if(i == wincontext_.end())
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(i->second.owner)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto u = wincontext_.find(i->second.owner);
 | 
				
			||||||
 | 
								if(u != wincontext_.end())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto * owned = u->second.owned;
 | 
				
			||||||
 | 
									if(owned)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										auto j = std::find(owned->begin(), owned->end(), child);
 | 
				
			||||||
 | 
										if(j != owned->end())
 | 
				
			||||||
 | 
											owned->erase(j);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if(owned->empty())
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											delete owned;
 | 
				
			||||||
 | 
											u->second.owned = nullptr;
 | 
				
			||||||
 | 
											//The owner owns no child. If it is not a child of other owners,
 | 
				
			||||||
 | 
											//remove it.
 | 
				
			||||||
 | 
											if(nullptr == u->second.owner)
 | 
				
			||||||
 | 
												wincontext_.erase(u);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								i->second.owner = nullptr;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Don't remove the ownerships which the child is a owner window.
 | 
				
			||||||
 | 
							if(nullptr == i->second.owned)
 | 
				
			||||||
 | 
								wincontext_.erase(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	native_window_type platform_spec::get_owner(native_window_type wd) const
 | 
						native_window_type platform_spec::get_owner(native_window_type wd) const
 | 
				
			||||||
@ -610,7 +654,9 @@ namespace detail
 | 
				
			|||||||
	void platform_spec::remove(native_window_type wd)
 | 
						void platform_spec::remove(native_window_type wd)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		msg_dispatcher_->erase(reinterpret_cast<Window>(wd));
 | 
							msg_dispatcher_->erase(reinterpret_cast<Window>(wd));
 | 
				
			||||||
		platform_scope_guard psg;
 | 
					
 | 
				
			||||||
 | 
							platform_scope_guard lock;
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
		auto i = wincontext_.find(wd);
 | 
							auto i = wincontext_.find(wd);
 | 
				
			||||||
		if(i == wincontext_.end()) return;
 | 
							if(i == wincontext_.end()) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -641,6 +687,28 @@ namespace detail
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		delete vec;
 | 
							delete vec;
 | 
				
			||||||
		wincontext_.erase(i);
 | 
							wincontext_.erase(i);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
							if(umake_owner(wd))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto i = wincontext_.find(wd);
 | 
				
			||||||
 | 
								if(i != wincontext_.end())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if(i->second.owned)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										set_error_handler();
 | 
				
			||||||
 | 
										auto & wd_manager = detail::bedrock::instance().wd_manager();
 | 
				
			||||||
 | 
										for(auto u = i->second.owned->rbegin(); u != i->second.owned->rend(); ++u)
 | 
				
			||||||
 | 
											wd_manager.close(wd_manager.root(*u));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										rev_error_handler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										delete i->second.owned;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									wincontext_.erase(i);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		iconbase_.erase(wd);
 | 
							iconbase_.erase(wd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 *	Platform Specification Implementation
 | 
					 *	Platform Specification Implementation
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Message Dispatcher Implementation
 | 
					 *	Message Dispatcher Implementation
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -26,6 +26,7 @@
 | 
				
			|||||||
#include <condition_variable>
 | 
					#include <condition_variable>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nana
 | 
					namespace nana
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -221,6 +222,8 @@ namespace detail
 | 
				
			|||||||
					case 0:
 | 
										case 0:
 | 
				
			||||||
						msg_pack.kind = msg_pack.kind_xevent;
 | 
											msg_pack.kind = msg_pack.kind_xevent;
 | 
				
			||||||
						msg_pack.u.xevent = event;
 | 
											msg_pack.u.xevent = event;
 | 
				
			||||||
 | 
											_m_msg_dispatch(msg_pack);
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
					case 1:
 | 
										case 1:
 | 
				
			||||||
						_m_msg_dispatch(msg_pack);
 | 
											_m_msg_dispatch(msg_pack);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -338,7 +341,7 @@ namespace detail
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		Display * display_;
 | 
							Display * display_;
 | 
				
			||||||
		volatile bool is_work_{ false };
 | 
							std::atomic<bool> is_work_{ false };
 | 
				
			||||||
		std::unique_ptr<std::thread> thrd_;
 | 
							std::unique_ptr<std::thread> thrd_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct table_tag
 | 
							struct table_tag
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Platform Specification Implementation
 | 
					 *	Platform Specification Implementation
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -20,6 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <nana/push_ignore_diagnostic>
 | 
					#include <nana/push_ignore_diagnostic>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include <thread>
 | 
					#include <thread>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
@ -132,6 +133,7 @@ namespace detail
 | 
				
			|||||||
		Atom wm_change_state;
 | 
							Atom wm_change_state;
 | 
				
			||||||
		Atom wm_delete_window;
 | 
							Atom wm_delete_window;
 | 
				
			||||||
		//ext
 | 
							//ext
 | 
				
			||||||
 | 
							Atom net_frame_extents;
 | 
				
			||||||
		Atom net_wm_state;
 | 
							Atom net_wm_state;
 | 
				
			||||||
		Atom net_wm_state_skip_taskbar;
 | 
							Atom net_wm_state_skip_taskbar;
 | 
				
			||||||
		Atom net_wm_state_fullscreen;
 | 
							Atom net_wm_state_fullscreen;
 | 
				
			||||||
@ -213,6 +215,9 @@ namespace detail
 | 
				
			|||||||
		const atombase_tag & atombase() const;
 | 
							const atombase_tag & atombase() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void make_owner(native_window_type owner, native_window_type wd);
 | 
							void make_owner(native_window_type owner, native_window_type wd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Cancel the ownership
 | 
				
			||||||
 | 
							bool umake_owner(native_window_type child);
 | 
				
			||||||
		native_window_type get_owner(native_window_type) const;
 | 
							native_window_type get_owner(native_window_type) const;
 | 
				
			||||||
		void remove(native_window_type);
 | 
							void remove(native_window_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -264,7 +269,7 @@ namespace detail
 | 
				
			|||||||
		std::recursive_mutex xlib_locker_;
 | 
							std::recursive_mutex xlib_locker_;
 | 
				
			||||||
		struct caret_holder_tag
 | 
							struct caret_holder_tag
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			volatile bool exit_thread;
 | 
								std::atomic<bool> exit_thread;
 | 
				
			||||||
			std::unique_ptr<std::thread> thr;
 | 
								std::unique_ptr<std::thread> thr;
 | 
				
			||||||
			std::map<native_window_type, caret_rep*> carets;
 | 
								std::map<native_window_type, caret_rep*> carets;
 | 
				
			||||||
		}caret_holder_;
 | 
							}caret_holder_;
 | 
				
			||||||
 | 
				
			|||||||
@ -308,11 +308,11 @@ namespace nana
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			if (pi_data_->menu.window && (pi_data_->menu.window != wd))
 | 
								if (pi_data_->menu.window && (pi_data_->menu.window != wd))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				wd = native_interface::get_owner_window(wd);
 | 
									wd = native_interface::get_window(wd, window_relationship::owner);
 | 
				
			||||||
				while (wd)
 | 
									while (wd)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if (wd != pi_data_->menu.window)
 | 
										if (wd != pi_data_->menu.window)
 | 
				
			||||||
						wd = native_interface::get_owner_window(wd);
 | 
											wd = native_interface::get_window(wd, window_relationship::owner);
 | 
				
			||||||
					else
 | 
										else
 | 
				
			||||||
						return false;
 | 
											return false;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -329,7 +329,7 @@ namespace nana
 | 
				
			|||||||
				erase_menu(true);
 | 
									erase_menu(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				pi_data_->menu.window = menu_wd;
 | 
									pi_data_->menu.window = menu_wd;
 | 
				
			||||||
				pi_data_->menu.owner = native_interface::get_owner_window(menu_wd);
 | 
									pi_data_->menu.owner = native_interface::get_window(menu_wd, window_relationship::owner);
 | 
				
			||||||
				pi_data_->menu.has_keyboard = has_keyboard;
 | 
									pi_data_->menu.has_keyboard = has_keyboard;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,9 @@ namespace nana
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
namespace detail
 | 
					namespace detail
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						//Declarations of helper functions defined in native_window_interface.cpp
 | 
				
			||||||
 | 
						void x11_apply_exposed_position(native_window_type wd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#pragma pack(1)
 | 
					#pragma pack(1)
 | 
				
			||||||
		union event_mask
 | 
							union event_mask
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -572,6 +575,62 @@ namespace detail
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void x_lookup_chars(const root_misc* rruntime, basic_window * msgwd, char* keybuf, std::size_t keybuf_len, const arg_keyboard& modifiers_status)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (!msgwd->flags.enabled)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static auto& brock = detail::bedrock::instance();
 | 
				
			||||||
 | 
							auto & wd_manager = brock.wd_manager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto& context = *brock.get_thread_context(msgwd->thread_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							auto const native_window = rruntime->window->root;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nana::detail::charset_conv charset(NANA_UNICODE, "UTF-8");
 | 
				
			||||||
 | 
							const std::string& str = charset.charset(std::string(keybuf, keybuf + keybuf_len));
 | 
				
			||||||
 | 
							auto const charbuf = reinterpret_cast<const wchar_t*>(str.c_str());
 | 
				
			||||||
 | 
							auto const len = str.size() / sizeof(wchar_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for(std::size_t i = 0; i < len; ++i)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								arg_keyboard arg = modifiers_status;
 | 
				
			||||||
 | 
								arg.ignore = false;
 | 
				
			||||||
 | 
								arg.key = charbuf[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// ignore Unicode BOM (it may or may not appear)
 | 
				
			||||||
 | 
								if (arg.key == 0xFEFF) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//Only accept tab when it is not ignored.
 | 
				
			||||||
 | 
								if ((keyboard::tab == arg.key) && rruntime->condition.ignore_tab)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(context.is_alt_pressed)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									arg.ctrl = arg.shift = false;
 | 
				
			||||||
 | 
									arg.evt_code = event_code::shortkey;
 | 
				
			||||||
 | 
									brock.shortkey_occurred(true);
 | 
				
			||||||
 | 
									auto shr_wd = wd_manager.find_shortkey(native_window, arg.key);
 | 
				
			||||||
 | 
									if(shr_wd)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										arg.window_handle = reinterpret_cast<window>(shr_wd);
 | 
				
			||||||
 | 
										brock.emit(event_code::shortkey, shr_wd, arg, true, &context);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								arg.evt_code = event_code::key_char;
 | 
				
			||||||
 | 
								arg.window_handle = reinterpret_cast<window>(msgwd);
 | 
				
			||||||
 | 
								msgwd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwd));
 | 
				
			||||||
 | 
								if(arg.ignore == false && wd_manager.available(msgwd))
 | 
				
			||||||
 | 
									draw_invoker(&drawer::key_char, msgwd, arg, &context);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(brock.shortkey_occurred(false))
 | 
				
			||||||
 | 
								context.is_alt_pressed = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
 | 
						void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		typedef detail::bedrock::core_window_t core_window_t;
 | 
							typedef detail::bedrock::core_window_t core_window_t;
 | 
				
			||||||
@ -905,6 +964,9 @@ namespace detail
 | 
				
			|||||||
				break;
 | 
									break;
 | 
				
			||||||
			case MapNotify:
 | 
								case MapNotify:
 | 
				
			||||||
			case UnmapNotify:
 | 
								case UnmapNotify:
 | 
				
			||||||
 | 
									if(xevent.type == MapNotify)
 | 
				
			||||||
 | 
										x11_apply_exposed_position(native_window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				brock.event_expose(msgwnd, (xevent.type == MapNotify));
 | 
									brock.event_expose(msgwnd, (xevent.type == MapNotify));
 | 
				
			||||||
				context.platform.motion_window = nullptr;
 | 
									context.platform.motion_window = nullptr;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
@ -1071,6 +1133,8 @@ namespace detail
 | 
				
			|||||||
								wd_manager.do_lazy_refresh(msgwnd, false);
 | 
													wd_manager.do_lazy_refresh(msgwnd, false);
 | 
				
			||||||
								break;
 | 
													break;
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
												//Fall through
 | 
				
			||||||
						case XLookupChars:
 | 
											case XLookupChars:
 | 
				
			||||||
							if (msgwnd->flags.enabled)
 | 
												if (msgwnd->flags.enabled)
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
@ -1118,6 +1182,13 @@ namespace detail
 | 
				
			|||||||
									context.is_alt_pressed = false;
 | 
														context.is_alt_pressed = false;
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
												x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status);
 | 
				
			||||||
 | 
												break;
 | 
				
			||||||
 | 
											case XLookupChars:
 | 
				
			||||||
 | 
												x_lookup_chars(root_runtime, msgwnd, keybuf, len, modifiers_status);
 | 
				
			||||||
 | 
												break;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						wd_manager.do_lazy_refresh(msgwnd, false);
 | 
											wd_manager.do_lazy_refresh(msgwnd, false);
 | 
				
			||||||
@ -1281,7 +1352,7 @@ namespace detail
 | 
				
			|||||||
		if(condition_wd && is_modal)
 | 
							if(condition_wd && is_modal)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			native_window_type modal = reinterpret_cast<core_window_t*>(condition_wd)->root;
 | 
								native_window_type modal = reinterpret_cast<core_window_t*>(condition_wd)->root;
 | 
				
			||||||
			owner_native = native_interface::get_owner_window(modal);
 | 
								owner_native = native_interface::get_window(modal, window_relationship::owner);
 | 
				
			||||||
			if(owner_native)
 | 
								if(owner_native)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				native_interface::enable_window(owner_native, false);
 | 
									native_interface::enable_window(owner_native, false);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Platform Implementation
 | 
					 *	Platform Implementation
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -129,6 +129,96 @@ namespace nana{
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		nana::detail::platform_spec & spec = nana::detail::platform_spec::instance();
 | 
							nana::detail::platform_spec & spec = nana::detail::platform_spec::instance();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//The XMoveWindow and XMoveResizeWindow don't take effect if the specified window is
 | 
				
			||||||
 | 
							//unmapped, and the members x and y of XSetSizeHints is obsoluted. So the position that
 | 
				
			||||||
 | 
							//set to a unmapped windows should be kept and use the position when the window is mapped.
 | 
				
			||||||
 | 
							std::map<Window, ::nana::point> exposed_positions;	//locked by platform_scope_guard
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//Returns the parent window.
 | 
				
			||||||
 | 
							//It may return a decoration frame window if the requested window is a top level and WM is a
 | 
				
			||||||
 | 
							//reparenting window manager.
 | 
				
			||||||
 | 
							native_window_type x11_parent_window(native_window_type wd)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Window root;
 | 
				
			||||||
 | 
								Window parent;
 | 
				
			||||||
 | 
								Window * children;
 | 
				
			||||||
 | 
								unsigned size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								platform_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(0 != ::XQueryTree(restrict::spec.open_display(), reinterpret_cast<Window>(wd),
 | 
				
			||||||
 | 
									&root, &parent, &children, &size))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									::XFree(children);
 | 
				
			||||||
 | 
									return reinterpret_cast<native_window_type>(parent);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							native_window_type x11_decoration_frame(native_window_type wd)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto const owner = restrict::spec.get_owner(wd);
 | 
				
			||||||
 | 
								auto const root_wd = restrict::spec.root_window();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(owner)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto test_wd = wd;
 | 
				
			||||||
 | 
									while(true)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										auto upper = x11_parent_window(test_wd);
 | 
				
			||||||
 | 
										if((reinterpret_cast<Window>(upper) != root_wd) && (upper != owner))
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											test_wd = upper;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else if(wd != test_wd)
 | 
				
			||||||
 | 
											return test_wd;
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
											return nullptr;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void x11_apply_exposed_position(native_window_type wd)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								nana::detail::platform_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto i = exposed_positions.find(reinterpret_cast<Window>(wd));
 | 
				
			||||||
 | 
								if(i == exposed_positions.cend())
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								native_interface::move_window(wd, i->second.x, i->second.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								exposed_positions.erase(i);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							namespace x11_wait
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								static Bool configure(Display *disp, XEvent *evt, char *arg)
 | 
				
			||||||
 | 
								{    
 | 
				
			||||||
 | 
								    return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								static Bool map(Display *disp, XEvent *evt, char *arg)
 | 
				
			||||||
 | 
								{    
 | 
				
			||||||
 | 
								    return disp && evt && arg && (evt->type == MapNotify) && (evt->xmap.window == *reinterpret_cast<Window*>(arg));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								static Bool unmap(Display *disp, XEvent *evt, char *arg)
 | 
				
			||||||
 | 
								{    
 | 
				
			||||||
 | 
								    return disp && evt && arg && (evt->type == MapNotify) && (evt->xunmap.window == *reinterpret_cast<Window*>(arg));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								XEvent dummy;
 | 
				
			||||||
 | 
								::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&wd));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//struct native_interface
 | 
						//struct native_interface
 | 
				
			||||||
@ -196,13 +286,6 @@ namespace nana{
 | 
				
			|||||||
			return rectangle{ primary_monitor_size() };
 | 
								return rectangle{ primary_monitor_size() };
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NANA_X11
 | 
					 | 
				
			||||||
		//The XMoveWindow and XMoveResizeWindow don't take effect if the specified window is
 | 
					 | 
				
			||||||
		//unmapped, and the members x and y of XSetSizeHints is obsoluted. So the position that
 | 
					 | 
				
			||||||
		//set to a unmapped windows should be kept and use the position when the window is mapped.
 | 
					 | 
				
			||||||
		std::map<Window, ::nana::point> exposed_positions;	//locked by platform_scope_guard
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		//platform-dependent
 | 
							//platform-dependent
 | 
				
			||||||
		native_interface::window_result native_interface::create_window(native_window_type owner, bool nested, const rectangle& r, const appearance& app)
 | 
							native_interface::window_result native_interface::create_window(native_window_type owner, bool nested, const rectangle& r, const appearance& app)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -267,7 +350,7 @@ namespace nana{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			XSetWindowAttributes win_attr;
 | 
								XSetWindowAttributes win_attr;
 | 
				
			||||||
			unsigned long attr_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
 | 
								unsigned long attr_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
 | 
				
			||||||
							CWWinGravity | CWBitGravity | CWColormap | CWEventMask;
 | 
												 CWColormap | CWEventMask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Display * disp = restrict::spec.open_display();
 | 
								Display * disp = restrict::spec.open_display();
 | 
				
			||||||
			win_attr.colormap = restrict::spec.colormap();
 | 
								win_attr.colormap = restrict::spec.colormap();
 | 
				
			||||||
@ -276,8 +359,6 @@ namespace nana{
 | 
				
			|||||||
			win_attr.background_pixel = 0xFFFFFF;
 | 
								win_attr.background_pixel = 0xFFFFFF;
 | 
				
			||||||
			win_attr.border_pixmap = None;
 | 
								win_attr.border_pixmap = None;
 | 
				
			||||||
			win_attr.border_pixel = 0x0;
 | 
								win_attr.border_pixel = 0x0;
 | 
				
			||||||
			win_attr.bit_gravity = 0;
 | 
					 | 
				
			||||||
			win_attr.win_gravity = NorthWestGravity;
 | 
					 | 
				
			||||||
			win_attr.backing_store = 0;
 | 
								win_attr.backing_store = 0;
 | 
				
			||||||
			win_attr.backing_planes = 0;
 | 
								win_attr.backing_planes = 0;
 | 
				
			||||||
			win_attr.backing_pixel = 0;
 | 
								win_attr.backing_pixel = 0;
 | 
				
			||||||
@ -296,6 +377,8 @@ namespace nana{
 | 
				
			|||||||
				win_attr.save_under = True;
 | 
									win_attr.save_under = True;
 | 
				
			||||||
				attr_mask |= CWSaveUnder;
 | 
									attr_mask |= CWSaveUnder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									///The parameter of XCreateWindow to create a top level window must be root.
 | 
				
			||||||
 | 
									///But after creation, the real parent is the reparenting frame window.
 | 
				
			||||||
				parent = restrict::spec.root_window();
 | 
									parent = restrict::spec.root_window();
 | 
				
			||||||
				calc_screen_point(owner, pos);
 | 
									calc_screen_point(owner, pos);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -309,9 +392,10 @@ namespace nana{
 | 
				
			|||||||
			if(handle)
 | 
								if(handle)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				//make owner if it is a popup window
 | 
									//make owner if it is a popup window
 | 
				
			||||||
				if((!nested) && owner)
 | 
									if(!nested)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					restrict::spec.make_owner(owner, reinterpret_cast<native_window_type>(handle));
 | 
										auto origin_owner = (owner ? owner : reinterpret_cast<native_window_type>(restrict::spec.root_window()));
 | 
				
			||||||
 | 
										restrict::spec.make_owner(origin_owner, reinterpret_cast<native_window_type>(handle));
 | 
				
			||||||
					exposed_positions[handle] = pos;
 | 
										exposed_positions[handle] = pos;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -421,7 +505,7 @@ namespace nana{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			XSetWindowAttributes win_attr;
 | 
								XSetWindowAttributes win_attr;
 | 
				
			||||||
			unsigned long attr_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
 | 
								unsigned long attr_mask = CWBackPixmap | CWBackPixel | CWBorderPixel |
 | 
				
			||||||
							CWWinGravity | CWBitGravity | CWColormap | CWEventMask;
 | 
												 CWColormap | CWEventMask | CWOverrideRedirect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Display * disp = restrict::spec.open_display();
 | 
								Display * disp = restrict::spec.open_display();
 | 
				
			||||||
			win_attr.colormap = restrict::spec.colormap();
 | 
								win_attr.colormap = restrict::spec.colormap();
 | 
				
			||||||
@ -430,15 +514,12 @@ namespace nana{
 | 
				
			|||||||
			win_attr.background_pixel = 0xFFFFFF;
 | 
								win_attr.background_pixel = 0xFFFFFF;
 | 
				
			||||||
			win_attr.border_pixmap = None;
 | 
								win_attr.border_pixmap = None;
 | 
				
			||||||
			win_attr.border_pixel = 0x0;
 | 
								win_attr.border_pixel = 0x0;
 | 
				
			||||||
			win_attr.bit_gravity = 0;
 | 
					 | 
				
			||||||
			win_attr.win_gravity = NorthWestGravity;
 | 
					 | 
				
			||||||
			win_attr.backing_store = 0;
 | 
								win_attr.backing_store = 0;
 | 
				
			||||||
			win_attr.backing_planes = 0;
 | 
								win_attr.backing_planes = 0;
 | 
				
			||||||
			win_attr.backing_pixel = 0;
 | 
								win_attr.backing_pixel = 0;
 | 
				
			||||||
			win_attr.colormap = restrict::spec.colormap();
 | 
								win_attr.colormap = restrict::spec.colormap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			win_attr.override_redirect = True;
 | 
								win_attr.override_redirect = True;
 | 
				
			||||||
			attr_mask |= CWOverrideRedirect;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			nana::point pos(r.x, r.y);
 | 
								nana::point pos(r.x, r.y);
 | 
				
			||||||
			win_attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask;
 | 
								win_attr.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ExposureMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask;
 | 
				
			||||||
@ -668,21 +749,21 @@ namespace nana{
 | 
				
			|||||||
				{
 | 
									{
 | 
				
			||||||
					::XMapWindow(disp, reinterpret_cast<Window>(wd));
 | 
										::XMapWindow(disp, reinterpret_cast<Window>(wd));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					auto i = exposed_positions.find(reinterpret_cast<Window>(wd));
 | 
										//Wait for the mapping notify to update the local attribute of visibility so that
 | 
				
			||||||
					if(i != exposed_positions.end())
 | 
										//the followed window_visible() call can return the updated visibility value.
 | 
				
			||||||
					{
 | 
										x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map);
 | 
				
			||||||
						::XMoveWindow(disp, reinterpret_cast<Window>(wd), i->second.x, i->second.y);
 | 
					 | 
				
			||||||
						exposed_positions.erase(i);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
					Window grab = restrict::spec.grab(0);
 | 
										Window grab = restrict::spec.grab(0);
 | 
				
			||||||
					if(grab == reinterpret_cast<Window>(wd))
 | 
										if(grab == reinterpret_cast<Window>(wd))
 | 
				
			||||||
						capture_window(wd, true);
 | 
											capture_window(wd, true);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
					::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
 | 
										::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
 | 
				
			||||||
 | 
										//Wait for the mapping notify to update the local attribute of visibility so that
 | 
				
			||||||
				::XFlush(disp);
 | 
										//the followed window_visible() call can return the updated visibility value.
 | 
				
			||||||
 | 
										x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			static_cast<void>(active);	//eliminate unused parameter compiler warning.
 | 
								static_cast<void>(active);	//eliminate unused parameter compiler warning.
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -844,19 +925,33 @@ namespace nana{
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return nana::point(r.left, r.top);
 | 
								return nana::point(r.left, r.top);
 | 
				
			||||||
#elif defined(NANA_X11)
 | 
					#elif defined(NANA_X11)
 | 
				
			||||||
			int x, y;
 | 
								point scr_pos;
 | 
				
			||||||
			nana::detail::platform_scope_guard psg;
 | 
								nana::detail::platform_scope_guard lock;
 | 
				
			||||||
			Window coord_wd = reinterpret_cast<Window>(restrict::spec.get_owner(wd));
 | 
					
 | 
				
			||||||
			if(!coord_wd)
 | 
					
 | 
				
			||||||
 | 
								point origin{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto coord_wd = restrict::spec.get_owner(wd);
 | 
				
			||||||
 | 
								if(coord_wd)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				coord_wd = reinterpret_cast<Window>(parent_window(wd));
 | 
									auto fm_extents = window_frame_extents(wd);
 | 
				
			||||||
				if(!coord_wd)
 | 
									origin.x = -fm_extents.left;
 | 
				
			||||||
					coord_wd = restrict::spec.root_window();
 | 
									origin.y = -fm_extents.top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if(reinterpret_cast<Window>(coord_wd) != restrict::spec.root_window())
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fm_extents = window_frame_extents(coord_wd);
 | 
				
			||||||
 | 
										origin.x += fm_extents.left;
 | 
				
			||||||
 | 
										origin.y += fm_extents.top;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									coord_wd = get_window(wd, window_relationship::parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Window child;
 | 
								Window child;
 | 
				
			||||||
			if(True == ::XTranslateCoordinates(restrict::spec.open_display(), reinterpret_cast<Window>(wd), coord_wd, 0, 0, &x, &y, &child))
 | 
								::XTranslateCoordinates(restrict::spec.open_display(), reinterpret_cast<Window>(wd), reinterpret_cast<Window>(coord_wd), origin.x, origin.y, &scr_pos.x, &scr_pos.y, &child);
 | 
				
			||||||
				return nana::point(x, y);
 | 
					
 | 
				
			||||||
			return nana::point(0, 0);
 | 
								return scr_pos;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -887,13 +982,15 @@ namespace nana{
 | 
				
			|||||||
#elif defined(NANA_X11)
 | 
					#elif defined(NANA_X11)
 | 
				
			||||||
			Display * disp = restrict::spec.open_display();
 | 
								Display * disp = restrict::spec.open_display();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			nana::detail::platform_scope_guard psg;
 | 
								nana::detail::platform_scope_guard lock;
 | 
				
			||||||
			Window owner = reinterpret_cast<Window>(restrict::spec.get_owner(wd));
 | 
					
 | 
				
			||||||
			if(owner)
 | 
								if(point{x, y} == window_position(wd))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Window child;
 | 
									//Returns if the requested position is same with the current position.
 | 
				
			||||||
				::XTranslateCoordinates(disp, owner, restrict::spec.root_window(),
 | 
									//In some X-Server versions/implementations, XMoveWindow() doesn't generate
 | 
				
			||||||
										x, y, &x, &y, &child);
 | 
									//a ConfigureNotify if the requested position is same with the current position.
 | 
				
			||||||
 | 
									//It causes that x11_wait_for always waiting for the ConfigureNotify.
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			XWindowAttributes attr;
 | 
								XWindowAttributes attr;
 | 
				
			||||||
@ -901,7 +998,19 @@ namespace nana{
 | 
				
			|||||||
			if(attr.map_state == IsUnmapped)
 | 
								if(attr.map_state == IsUnmapped)
 | 
				
			||||||
				exposed_positions[reinterpret_cast<Window>(wd)] = ::nana::point{x, y};
 | 
									exposed_positions[reinterpret_cast<Window>(wd)] = ::nana::point{x, y};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto const owner = restrict::spec.get_owner(wd);
 | 
				
			||||||
 | 
								if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto origin = window_position(owner);
 | 
				
			||||||
 | 
									x += origin.x;
 | 
				
			||||||
 | 
									y += origin.y;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
 | 
								::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//Wait for the configuration notify to update the local attribute of position so that
 | 
				
			||||||
 | 
								//the followed window_position() call can return the updated position value.
 | 
				
			||||||
 | 
								x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -951,16 +1060,6 @@ namespace nana{
 | 
				
			|||||||
			else
 | 
								else
 | 
				
			||||||
				hints.flags = 0;
 | 
									hints.flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			Window owner = reinterpret_cast<Window>(restrict::spec.get_owner(wd));
 | 
					 | 
				
			||||||
			int x = r.x;
 | 
					 | 
				
			||||||
			int y = r.y;
 | 
					 | 
				
			||||||
			if(owner)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				Window child;
 | 
					 | 
				
			||||||
				::XTranslateCoordinates(disp, owner, restrict::spec.root_window(),
 | 
					 | 
				
			||||||
										r.x, r.y, &x, &y, &child);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			XWindowAttributes attr;
 | 
								XWindowAttributes attr;
 | 
				
			||||||
			::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
 | 
								::XGetWindowAttributes(disp, reinterpret_cast<Window>(wd), &attr);
 | 
				
			||||||
			if(attr.map_state == IsUnmapped)
 | 
								if(attr.map_state == IsUnmapped)
 | 
				
			||||||
@ -969,13 +1068,32 @@ namespace nana{
 | 
				
			|||||||
				hints.width = r.width;
 | 
									hints.width = r.width;
 | 
				
			||||||
				hints.height = r.height;
 | 
									hints.height = r.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				exposed_positions[reinterpret_cast<Window>(wd)] = point{x, y};
 | 
									exposed_positions[reinterpret_cast<Window>(wd)] = r.position();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(hints.flags)
 | 
								if(hints.flags)
 | 
				
			||||||
				::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
 | 
									::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int x = r.x;
 | 
				
			||||||
 | 
								int y = r.y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto const owner = restrict::spec.get_owner(wd);
 | 
				
			||||||
 | 
								if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto origin = window_position(owner);
 | 
				
			||||||
 | 
									x += origin.x;
 | 
				
			||||||
 | 
									y += origin.y;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
 | 
								::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//Wait for the configuration notify to update the local attribute of position so that
 | 
				
			||||||
 | 
								//the followed window_position() call can return the updated position value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//It seems that XMoveResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
 | 
				
			||||||
 | 
								//to make sure the local attribute is updated.
 | 
				
			||||||
 | 
								x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -1055,6 +1173,46 @@ namespace nana{
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							native_interface::frame_extents native_interface::window_frame_extents(native_window_type wd)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								frame_extents fm_extents{0, 0, 0, 0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#if defined(NANA_WINDOWS)
 | 
				
			||||||
 | 
								::RECT client;
 | 
				
			||||||
 | 
								::GetClientRect(reinterpret_cast<HWND>(wd), &client);	//The right and bottom of client by GetClientRect indicate the width and height of the area
 | 
				
			||||||
 | 
								::RECT wd_area;
 | 
				
			||||||
 | 
								::GetWindowRect(reinterpret_cast<HWND>(wd), &wd_area);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fm_extents.left = client.left - wd_area.left;
 | 
				
			||||||
 | 
								fm_extents.right = wd_area.right - client.right;
 | 
				
			||||||
 | 
								fm_extents.top = client.top - wd_area.top;
 | 
				
			||||||
 | 
								fm_extents.bottom = wd_area.bottom - client.bottom;
 | 
				
			||||||
 | 
						#elif defined(NANA_X11)
 | 
				
			||||||
 | 
								Atom type;
 | 
				
			||||||
 | 
								int format;
 | 
				
			||||||
 | 
								unsigned long len, bytes_left = 0;
 | 
				
			||||||
 | 
								unsigned char *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								nana::detail::platform_scope_guard lock;
 | 
				
			||||||
 | 
								if(Success == ::XGetWindowProperty(restrict::spec.open_display(), reinterpret_cast<Window>(wd), 
 | 
				
			||||||
 | 
														restrict::spec.atombase().net_frame_extents, 0, 16, 0,
 | 
				
			||||||
 | 
														XA_CARDINAL, &type, &format,
 | 
				
			||||||
 | 
														&len, &bytes_left, &data))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if(type != None && len == 4)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										fm_extents.left = ((long*)data)[0];
 | 
				
			||||||
 | 
										fm_extents.right = ((long*)data)[1];
 | 
				
			||||||
 | 
										fm_extents.top = ((long*)data)[2];
 | 
				
			||||||
 | 
										fm_extents.bottom = ((long*)data)[3];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									::XFree(data);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
						#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return fm_extents;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool native_interface::window_size(native_window_type wd, const size& sz)
 | 
							bool native_interface::window_size(native_window_type wd, const size& sz)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#if defined(NANA_WINDOWS)
 | 
					#if defined(NANA_WINDOWS)
 | 
				
			||||||
@ -1093,6 +1251,10 @@ namespace nana{
 | 
				
			|||||||
				::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
 | 
									::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
 | 
								::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								//It seems that XResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
 | 
				
			||||||
 | 
								//to make sure the local attribute is updated.
 | 
				
			||||||
 | 
								x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -1222,41 +1384,37 @@ namespace nana{
 | 
				
			|||||||
			Window drop_wd;
 | 
								Window drop_wd;
 | 
				
			||||||
			int x, y;
 | 
								int x, y;
 | 
				
			||||||
			unsigned mask;
 | 
								unsigned mask;
 | 
				
			||||||
			nana::detail::platform_scope_guard psg;
 | 
								nana::detail::platform_scope_guard lock;
 | 
				
			||||||
			::XQueryPointer(restrict::spec.open_display(), restrict::spec.root_window(), &drop_wd, &drop_wd,  &pos.x, &pos.y, &x, &y, &mask);
 | 
								::XQueryPointer(restrict::spec.open_display(), restrict::spec.root_window(), &drop_wd, &drop_wd,  &pos.x, &pos.y, &x, &y, &mask);
 | 
				
			||||||
			return pos;
 | 
								return pos;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		native_window_type native_interface::get_owner_window(native_window_type wd)
 | 
							native_window_type native_interface::get_window(native_window_type wd, window_relationship rsp)
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
#if defined(NANA_WINDOWS)
 | 
					 | 
				
			||||||
			return reinterpret_cast<native_window_type>(::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER));
 | 
					 | 
				
			||||||
#elif defined(NANA_X11)
 | 
					 | 
				
			||||||
			return restrict::spec.get_owner(wd);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		native_window_type native_interface::parent_window(native_window_type wd)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#ifdef NANA_WINDOWS
 | 
					#ifdef NANA_WINDOWS
 | 
				
			||||||
 | 
								if(window_relationship::either_po == rsp)
 | 
				
			||||||
				return reinterpret_cast<native_window_type>(::GetParent(reinterpret_cast<HWND>(wd)));
 | 
									return reinterpret_cast<native_window_type>(::GetParent(reinterpret_cast<HWND>(wd)));
 | 
				
			||||||
 | 
								else if(window_relationship::parent == rsp)
 | 
				
			||||||
 | 
									return reinterpret_cast<native_window_type>(::GetAncestor(reinterpret_cast<HWND>(wd), GA_PARENT));
 | 
				
			||||||
 | 
								else if(window_relationship::owner == rsp)
 | 
				
			||||||
 | 
									return reinterpret_cast<native_window_type>(::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER));
 | 
				
			||||||
#elif defined(NANA_X11)
 | 
					#elif defined(NANA_X11)
 | 
				
			||||||
			Window root;
 | 
					 | 
				
			||||||
			Window parent;
 | 
					 | 
				
			||||||
			Window * children;
 | 
					 | 
				
			||||||
			unsigned size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			platform_scope_guard lock;
 | 
								platform_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(0 != ::XQueryTree(restrict::spec.open_display(), reinterpret_cast<Window>(wd),
 | 
								auto owner = restrict::spec.get_owner(wd);
 | 
				
			||||||
				&root, &parent, &children, &size))
 | 
					
 | 
				
			||||||
 | 
								if(window_relationship::either_po == rsp)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				::XFree(children);
 | 
									if(owner)
 | 
				
			||||||
				return reinterpret_cast<native_window_type>(parent);
 | 
										return owner;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return nullptr;
 | 
								else if(window_relationship::owner == rsp)
 | 
				
			||||||
 | 
									return owner;
 | 
				
			||||||
 | 
								else if(window_relationship::parent == rsp)
 | 
				
			||||||
 | 
									return x11_parent_window(wd);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
								return nullptr;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		native_window_type native_interface::parent_window(native_window_type child, native_window_type new_parent, bool returns_previous)
 | 
							native_window_type native_interface::parent_window(native_window_type child, native_window_type new_parent, bool returns_previous)
 | 
				
			||||||
@ -1276,11 +1434,21 @@ namespace nana{
 | 
				
			|||||||
			platform_scope_guard lock;
 | 
								platform_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(returns_previous)
 | 
								if(returns_previous)
 | 
				
			||||||
				prev = parent_window(child);
 | 
									prev = get_window(child, window_relationship::either_po);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(native_window_type{} == new_parent)
 | 
				
			||||||
 | 
									new_parent = reinterpret_cast<native_window_type>(restrict::spec.root_window());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			::XReparentWindow(restrict::spec.open_display(),
 | 
								::XReparentWindow(restrict::spec.open_display(),
 | 
				
			||||||
				reinterpret_cast<Window>(child), reinterpret_cast<Window>(new_parent),
 | 
									reinterpret_cast<Window>(child), reinterpret_cast<Window>(new_parent),
 | 
				
			||||||
				0, 0);
 | 
									0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If umake_owner returns true, it indicates the child windows is a popup window.
 | 
				
			||||||
 | 
								// So make the ownership of new_parent and child.
 | 
				
			||||||
 | 
								if(restrict::spec.umake_owner(child))
 | 
				
			||||||
 | 
									restrict::spec.make_owner(new_parent, child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return prev;
 | 
								return prev;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -166,10 +166,18 @@ namespace nana
 | 
				
			|||||||
							if (!cover->visible)
 | 
												if (!cover->visible)
 | 
				
			||||||
								continue;
 | 
													continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							if (is_wd_root ? 
 | 
												if (is_wd_root)
 | 
				
			||||||
								(category::flags::root == cover->other.category)
 | 
												{
 | 
				
			||||||
								:
 | 
													if(category::flags::root == cover->other.category)
 | 
				
			||||||
								((category::flags::root != cover->other.category) && (nullptr == cover->effect.bground)))
 | 
													{
 | 
				
			||||||
 | 
														if (overlap(vis_rect, rectangle{ native_interface::window_position(cover->root), cover->dimension }, block.r))
 | 
				
			||||||
 | 
														{
 | 
				
			||||||
 | 
															block.window = cover;
 | 
				
			||||||
 | 
															blocks.push_back(block);
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												else if((category::flags::root != cover->other.category) && (nullptr == cover->effect.bground))
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
								if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
 | 
													if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
 | 
				
			||||||
								{
 | 
													{
 | 
				
			||||||
 | 
				
			|||||||
@ -950,6 +950,19 @@ namespace detail
 | 
				
			|||||||
			if (wd->dimension == sz)
 | 
								if (wd->dimension == sz)
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::vector<core_window_t*> presence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (wd->dimension.width < sz.width || wd->dimension.height < sz.height)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									auto wd_r = rectangle{ wd->dimension };
 | 
				
			||||||
 | 
									for (auto child : wd->children)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										auto child_r = rectangle{ child->pos_owner, child->dimension };
 | 
				
			||||||
 | 
										if (!overlapped(wd_r, child_r))
 | 
				
			||||||
 | 
											presence.push_back(child);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			//Before resiz the window, creates the new graphics
 | 
								//Before resiz the window, creates the new graphics
 | 
				
			||||||
			paint::graphics graph;
 | 
								paint::graphics graph;
 | 
				
			||||||
			paint::graphics root_graph;
 | 
								paint::graphics root_graph;
 | 
				
			||||||
@ -1010,6 +1023,11 @@ namespace detail
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for (auto child : presence)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									refresh_tree(child);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			arg_resized arg;
 | 
								arg_resized arg;
 | 
				
			||||||
			arg.window_handle = reinterpret_cast<window>(wd);
 | 
								arg.window_handle = reinterpret_cast<window>(wd);
 | 
				
			||||||
			arg.width = sz.width;
 | 
								arg.width = sz.width;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	A Message Box Class
 | 
					 *	A Message Box Class
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -1294,7 +1294,7 @@ namespace nana
 | 
				
			|||||||
        min_width_entry_field_pixels_ = pixels;
 | 
					        min_width_entry_field_pixels_ = pixels;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _nana_cxx_folding_expression
 | 
					#ifndef __cpp_fold_expressions
 | 
				
			||||||
	void inputbox::_m_fetch_args(std::vector<abstract_content*>&)
 | 
						void inputbox::_m_fetch_args(std::vector<abstract_content*>&)
 | 
				
			||||||
	{}
 | 
						{}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -798,19 +798,22 @@ namespace nana
 | 
				
			|||||||
			case number_t::kind::real:
 | 
								case number_t::kind::real:
 | 
				
			||||||
				return static_cast<unsigned>(number.real());
 | 
									return static_cast<unsigned>(number.real());
 | 
				
			||||||
			case number_t::kind::percent:
 | 
								case number_t::kind::percent:
 | 
				
			||||||
				adjustable_px = area_px * number.real();
 | 
					 | 
				
			||||||
			case number_t::kind::none:
 | 
								case number_t::kind::none:
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					auto fpx = adjustable_px + precise_px;
 | 
					 | 
				
			||||||
					auto px = static_cast<unsigned>(fpx);
 | 
					 | 
				
			||||||
					precise_px = fpx - px;
 | 
					 | 
				
			||||||
					return px;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								default:
 | 
				
			||||||
				return 0; //Useless
 | 
									return 0; //Useless
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(number_t::kind::percent == number.kind_of())
 | 
				
			||||||
 | 
									adjustable_px = area_px * number.real() + precise_px;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									adjustable_px += precise_px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								auto const px = static_cast<unsigned>(adjustable_px);
 | 
				
			||||||
 | 
								precise_px = adjustable_px - px;
 | 
				
			||||||
 | 
								return px;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		std::pair<double, double> calc_weight_floor()
 | 
							std::pair<double, double> calc_weight_floor()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			std::pair<double, double> floor;
 | 
								std::pair<double, double> floor;
 | 
				
			||||||
@ -2879,8 +2882,7 @@ namespace nana
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		field_gather * attached_field = nullptr;
 | 
							field_gather * attached_field = nullptr;
 | 
				
			||||||
		if (name.size())
 | 
					
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		//find the field with specified name.
 | 
							//find the field with specified name.
 | 
				
			||||||
		//the field may not be created.
 | 
							//the field may not be created.
 | 
				
			||||||
		auto i = fields.find(name);
 | 
							auto i = fields.find(name);
 | 
				
			||||||
@ -2891,13 +2893,15 @@ namespace nana
 | 
				
			|||||||
			if (attached_field->attached)
 | 
								if (attached_field->attached)
 | 
				
			||||||
				throw std::runtime_error("place, the name '" + name + "' is redefined.");
 | 
									throw std::runtime_error("place, the name '" + name + "' is redefined.");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		token unmatch = token::width;
 | 
							token unmatch = token::width;
 | 
				
			||||||
		switch (div_type)
 | 
							switch (div_type)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
		case token::eof:  unmatch = token::height;  // "horitontal" div
 | 
							case token::eof:	// "horitontal" div
 | 
				
			||||||
		case token::vert:   // "vertical" div
 | 
							case token::vert:   // "vertical" div
 | 
				
			||||||
 | 
								if(token::eof == div_type)
 | 
				
			||||||
 | 
									unmatch = token::height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (auto& ch : children)
 | 
								for (auto& ch : children)
 | 
				
			||||||
				if (ch->weigth_type == unmatch)
 | 
									if (ch->weigth_type == unmatch)
 | 
				
			||||||
					throw std::invalid_argument("nana.place: unmatch vertical-heigth/horizontal-width betwen division '"
 | 
										throw std::invalid_argument("nana.place: unmatch vertical-heigth/horizontal-width betwen division '"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 *	Parts of Class Place
 | 
					 *	Parts of Class Place
 | 
				
			||||||
 *	Nana C++ Library(http://www.nanapro.org)
 | 
					 *	Nana C++ Library(http://www.nanapro.org)
 | 
				
			||||||
 *	Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
 | 
					 *	Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *	Distributed under the Boost Software License, Version 1.0.
 | 
					 *	Distributed under the Boost Software License, Version 1.0.
 | 
				
			||||||
 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
					 *	(See accompanying file LICENSE_1_0.txt or copy at
 | 
				
			||||||
@ -607,12 +607,16 @@ namespace nana
 | 
				
			|||||||
					it = ib = 0;
 | 
										it = ib = 0;
 | 
				
			||||||
					il = ir = 1;
 | 
										il = ir = 1;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					il = 3;	//left
 | 
					 | 
				
			||||||
				case 3:	//top, right, bottom
 | 
									case 3:	//top, right, bottom
 | 
				
			||||||
					it = 0;
 | 
										it = 0;
 | 
				
			||||||
					ir = 1;
 | 
										ir = 1;
 | 
				
			||||||
					ib = 2;
 | 
										ib = 2;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									default: //left, top, right, bottom, left
 | 
				
			||||||
 | 
										it = 0;
 | 
				
			||||||
 | 
										ir = 1;
 | 
				
			||||||
 | 
										ib = 2;
 | 
				
			||||||
 | 
										il = 3;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				int pos = 0;
 | 
									int pos = 0;
 | 
				
			||||||
@ -661,12 +665,16 @@ namespace nana
 | 
				
			|||||||
						it = ib = 0;
 | 
											it = ib = 0;
 | 
				
			||||||
						il = ir = 1;
 | 
											il = ir = 1;
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					default:
 | 
					 | 
				
			||||||
						il = 3;	//left
 | 
					 | 
				
			||||||
					case 3:	//top, right, bottom
 | 
										case 3:	//top, right, bottom
 | 
				
			||||||
						it = 0;
 | 
											it = 0;
 | 
				
			||||||
						ir = 1;
 | 
											ir = 1;
 | 
				
			||||||
						ib = 2;
 | 
											ib = 2;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										default: //left, top, right, bottom, left
 | 
				
			||||||
 | 
											it = 0;
 | 
				
			||||||
 | 
											ir = 1;
 | 
				
			||||||
 | 
											ib = 2;
 | 
				
			||||||
 | 
											il = 3;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					using px_type = decltype(r.height);
 | 
										using px_type = decltype(r.height);
 | 
				
			||||||
 | 
				
			|||||||
@ -669,7 +669,7 @@ namespace API
 | 
				
			|||||||
		internal_scope_guard lock;
 | 
							internal_scope_guard lock;
 | 
				
			||||||
		if(restrict::wd_manager().available(iwd) && (iwd->other.category == category::flags::root))
 | 
							if(restrict::wd_manager().available(iwd) && (iwd->other.category == category::flags::root))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto owner = interface_type::get_owner_window(iwd->root);
 | 
								auto owner = interface_type::get_window(iwd->root, window_relationship::owner);
 | 
				
			||||||
			if(owner)
 | 
								if(owner)
 | 
				
			||||||
				return reinterpret_cast<window>(restrict::wd_manager().root(owner));
 | 
									return reinterpret_cast<window>(restrict::wd_manager().root(owner));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -812,8 +812,14 @@ namespace API
 | 
				
			|||||||
			return{};
 | 
								return{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto sz = window_size(wd);
 | 
							auto sz = window_size(wd);
 | 
				
			||||||
		sz.width += iwd->extra_width;
 | 
					
 | 
				
			||||||
		sz.height += iwd->extra_height;
 | 
							if(category::flags::root == iwd->other.category)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto fm_extents = interface_type::window_frame_extents(iwd->root);
 | 
				
			||||||
 | 
								sz.width += fm_extents.left + fm_extents.right;
 | 
				
			||||||
 | 
								sz.height += fm_extents.top + fm_extents.bottom;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return sz;
 | 
							return sz;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -825,7 +831,11 @@ namespace API
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			if (category::flags::root == iwd->other.category)
 | 
								if (category::flags::root == iwd->other.category)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 | 
									auto fm_extents = interface_type::window_frame_extents(iwd->root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				size inner_size = sz;
 | 
									size inner_size = sz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
				if (inner_size.width < iwd->extra_width)
 | 
									if (inner_size.width < iwd->extra_width)
 | 
				
			||||||
					inner_size.width = 0;
 | 
										inner_size.width = 0;
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
@ -835,6 +845,17 @@ namespace API
 | 
				
			|||||||
					inner_size.height = 0;
 | 
										inner_size.height = 0;
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
					inner_size.height -= iwd->extra_height;
 | 
										inner_size.height -= iwd->extra_height;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
									if (inner_size.width < static_cast<unsigned>(fm_extents.left + fm_extents.right))
 | 
				
			||||||
 | 
										inner_size.width = 0;
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										inner_size.width -= static_cast<unsigned>(fm_extents.left + fm_extents.right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (inner_size.height < static_cast<unsigned>(fm_extents.top + fm_extents.bottom))
 | 
				
			||||||
 | 
										inner_size.height = 0;
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
										inner_size.height -= static_cast<unsigned>(fm_extents.top + fm_extents.bottom);			
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				window_size(wd, inner_size);
 | 
									window_size(wd, inner_size);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -150,12 +150,13 @@ namespace nana{	namespace drawerbase
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if (false == cite_.draw(graph, attr_.bgcolor, attr_.fgcolor, ::nana::rectangle{ graph.size() }, e_state))
 | 
								if (false == cite_.draw(graph, attr_.bgcolor, attr_.fgcolor, ::nana::rectangle{ graph.size() }, e_state))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (!API::is_transparent_background(*wdg_))
 | 
									if (API::is_transparent_background(*wdg_))
 | 
				
			||||||
				{
 | 
										API::dev::copy_transparent_background(*wdg_, graph);
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
					_m_draw_background(graph);
 | 
										_m_draw_background(graph);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				_m_draw_border(graph);
 | 
									_m_draw_border(graph);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_m_draw_title(graph, eb);
 | 
								_m_draw_title(graph, eb);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -732,7 +732,6 @@ namespace nana
 | 
				
			|||||||
				bool call_other_keys = false;
 | 
									bool call_other_keys = false;
 | 
				
			||||||
				if(drawer_->editable())
 | 
									if(drawer_->editable())
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					bool is_move_up = false;
 | 
					 | 
				
			||||||
					switch(arg.key)
 | 
										switch(arg.key)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
					case keyboard::os_arrow_left:
 | 
										case keyboard::os_arrow_left:
 | 
				
			||||||
@ -741,9 +740,8 @@ namespace nana
 | 
				
			|||||||
						drawer_->editor()->reset_caret();
 | 
											drawer_->editor()->reset_caret();
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					case keyboard::os_arrow_up:
 | 
										case keyboard::os_arrow_up:
 | 
				
			||||||
						is_move_up = true;
 | 
					 | 
				
			||||||
					case keyboard::os_arrow_down:
 | 
										case keyboard::os_arrow_down:
 | 
				
			||||||
						drawer_->move_items(is_move_up, true);
 | 
											drawer_->move_items((keyboard::os_arrow_up == arg.key), true);
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					default:
 | 
										default:
 | 
				
			||||||
						call_other_keys = true;
 | 
											call_other_keys = true;
 | 
				
			||||||
@ -751,15 +749,15 @@ namespace nana
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					bool is_move_up = false;
 | 
					 | 
				
			||||||
					switch(arg.key)
 | 
										switch(arg.key)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
					case keyboard::os_arrow_left:
 | 
										case keyboard::os_arrow_left:
 | 
				
			||||||
					case keyboard::os_arrow_up:
 | 
										case keyboard::os_arrow_up:
 | 
				
			||||||
						is_move_up = true;
 | 
											drawer_->move_items(true, true);
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
					case keyboard::os_arrow_right:
 | 
										case keyboard::os_arrow_right:
 | 
				
			||||||
					case keyboard::os_arrow_down:
 | 
										case keyboard::os_arrow_down:
 | 
				
			||||||
						drawer_->move_items(is_move_up, true);
 | 
											drawer_->move_items(false, true);
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					default:
 | 
										default:
 | 
				
			||||||
						call_other_keys = true;
 | 
											call_other_keys = true;
 | 
				
			||||||
 | 
				
			|||||||
@ -264,15 +264,22 @@ namespace nana{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		drawing dw(*this);
 | 
							drawing dw(*this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//When the group is resized, the drawing is called before moving the caption, but
 | 
				
			||||||
 | 
							//the drawing of group requires the lastest position of caption for gradual rectangle.
 | 
				
			||||||
 | 
							//For the requirement, a move event handler is required for listning the change of caption's position.
 | 
				
			||||||
 | 
							impl_->caption.events().move([this](const arg_move&){
 | 
				
			||||||
 | 
								if (align::left != impl_->caption_align)
 | 
				
			||||||
 | 
									API::refresh_window(*this);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !!
 | 
							// This drawing function is owner by the onwer of dw (the outer panel of the group widget), not by dw !!
 | 
				
			||||||
		dw.draw([this](paint::graphics& graph)
 | 
							dw.draw([this](paint::graphics& graph)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			auto gap_px = impl_->gap - 1;
 | 
								auto gap_px = impl_->gap - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			graph.rectangle(true, API::bgcolor(this->parent()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			auto const top_round_line = static_cast<int>(impl_->caption_dimension.height) / 2;
 | 
								auto const top_round_line = static_cast<int>(impl_->caption_dimension.height) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								graph.rectangle(true, API::bgcolor(this->parent()));
 | 
				
			||||||
			graph.round_rectangle(rectangle(point(gap_px, top_round_line),
 | 
								graph.round_rectangle(rectangle(point(gap_px, top_round_line),
 | 
				
			||||||
				nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px)
 | 
									nana::size(graph.width() - 2 * gap_px, graph.height() - top_round_line - gap_px)
 | 
				
			||||||
				),
 | 
									),
 | 
				
			||||||
@ -281,11 +288,10 @@ namespace nana{
 | 
				
			|||||||
			auto opt_r = API::window_rectangle(impl_->caption);
 | 
								auto opt_r = API::window_rectangle(impl_->caption);
 | 
				
			||||||
			if (opt_r)
 | 
								if (opt_r)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width, static_cast<unsigned>(top_round_line - opt_r->y) } };
 | 
									rectangle grad_r{ opt_r->position(), nana::size{ opt_r->width + 4, static_cast<unsigned>(top_round_line - opt_r->y) } };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				grad_r.y += top_round_line*2  / 3;
 | 
									grad_r.y += top_round_line*2  / 3;
 | 
				
			||||||
				grad_r.x -= 2;
 | 
									grad_r.x -= 2;
 | 
				
			||||||
				grad_r.width += 4;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				graph.gradual_rectangle(grad_r,
 | 
									graph.gradual_rectangle(grad_r,
 | 
				
			||||||
					API::bgcolor(this->parent()), this->bgcolor(), true
 | 
										API::bgcolor(this->parent()), this->bgcolor(), true
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,8 @@
 | 
				
			|||||||
#include <stdexcept>
 | 
					#include <stdexcept>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VISUAL_LINES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace nana
 | 
					namespace nana
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	namespace drawerbase
 | 
						namespace drawerbase
 | 
				
			||||||
@ -28,6 +30,7 @@ namespace nana
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			class renderer
 | 
								class renderer
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
				typedef widgets::skeletons::dstream::linecontainer::iterator iterator;
 | 
									typedef widgets::skeletons::dstream::linecontainer::iterator iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				struct pixel_tag
 | 
									struct pixel_tag
 | 
				
			||||||
@ -37,6 +40,32 @@ namespace nana
 | 
				
			|||||||
					std::size_t baseline;	//The baseline for drawing text.
 | 
										std::size_t baseline;	//The baseline for drawing text.
 | 
				
			||||||
					std::vector<iterator> values;	//line values
 | 
										std::vector<iterator> values;	//line values
 | 
				
			||||||
				};
 | 
									};
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
									//Iterator of content element in a line.
 | 
				
			||||||
 | 
									using content_element_iterator = widgets::skeletons::dstream::linecontainer::const_iterator; //subsitute for member type iterator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									struct visual_line //subsitute of pixel_tag
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										struct element
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											content_element_iterator content_element;
 | 
				
			||||||
 | 
											std::pair<std::size_t, std::size_t> range; //A part of text in a text element. first: text begin, second: text length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											element(const content_element_iterator& iterator, std::size_t range_begin, std::size_t range_end):
 | 
				
			||||||
 | 
												content_element(iterator),
 | 
				
			||||||
 | 
												range(range_begin, range_end)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										int x_base;	//The x position where this line starts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										std::size_t extent_height_px;
 | 
				
			||||||
 | 
										std::size_t baseline; //The baseline for rendering text.
 | 
				
			||||||
 | 
										std::vector<element> elements; //description of text element in this rendering line.
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//this is a helper variable, it just keeps the status while drawing.
 | 
									//this is a helper variable, it just keeps the status while drawing.
 | 
				
			||||||
				struct render_status
 | 
									struct render_status
 | 
				
			||||||
@ -46,8 +75,12 @@ namespace nana
 | 
				
			|||||||
					align_v text_align_v;
 | 
										align_v text_align_v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					nana::point pos;
 | 
										nana::point pos;
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
					std::vector<pixel_tag> pixels;
 | 
										std::vector<pixel_tag> pixels;
 | 
				
			||||||
					std::size_t index;
 | 
					#else
 | 
				
			||||||
 | 
										std::vector<visual_line> vslines; //The lines description of a line of text. substitute of member pixels.
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
										std::size_t index;	//indicates the current rendering visual line.
 | 
				
			||||||
				};
 | 
									};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				struct traceable
 | 
									struct traceable
 | 
				
			||||||
@ -102,18 +135,32 @@ namespace nana
 | 
				
			|||||||
					rs.text_align = th;
 | 
										rs.text_align = th;
 | 
				
			||||||
					rs.text_align_v = tv;
 | 
										rs.text_align_v = tv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
					std::deque<std::vector<pixel_tag> > pixel_lines;
 | 
										std::deque<std::vector<pixel_tag> > pixel_lines;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
										//All visual lines data of whole text.
 | 
				
			||||||
 | 
										std::deque<std::vector<visual_line>> content_lines;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					std::size_t extent_v_pixels = 0;	//the pixels, in height, that text will be painted.
 | 
										std::size_t extent_v_pixels = 0;	//the pixels, in height, that text will be painted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					for (auto & line : dstream_)
 | 
										for (auto & line : dstream_)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
						_m_line_pixels(line, def_line_pixels, rs);
 | 
											_m_line_pixels(line, def_line_pixels, rs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						for (auto & m : rs.pixels)
 | 
											for (auto & m : rs.pixels)
 | 
				
			||||||
							extent_v_pixels += m.pixels;
 | 
												extent_v_pixels += m.pixels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						pixel_lines.emplace_back(std::move(rs.pixels));
 | 
											pixel_lines.emplace_back(std::move(rs.pixels));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
											_m_prepare_visual_lines(graph, line, def_line_pixels, rs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											for (auto & vsline : rs.vslines)
 | 
				
			||||||
 | 
												extent_v_pixels += vsline.extent_height_px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											content_lines.emplace_back(std::move(rs.vslines));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if(extent_v_pixels >= graph.height())
 | 
											if(extent_v_pixels >= graph.height())
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
@ -129,13 +176,17 @@ namespace nana
 | 
				
			|||||||
					else
 | 
										else
 | 
				
			||||||
						rs.pos.y = 0;
 | 
											rs.pos.y = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
					auto pixels_iterator = pixel_lines.begin();
 | 
										auto pixels_iterator = pixel_lines.begin();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
										auto vsline_iterator = content_lines.begin();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
					for (auto & line : dstream_)
 | 
										for (auto & line : dstream_)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						if (rs.pos.y >= static_cast<int>(graph.height()))
 | 
											if (rs.pos.y >= static_cast<int>(graph.height()))
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
						rs.index = 0;
 | 
											rs.index = 0;
 | 
				
			||||||
						rs.pixels.clear();
 | 
											rs.pixels.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -148,6 +199,17 @@ namespace nana
 | 
				
			|||||||
							break;
 | 
												break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						rs.pos.y += static_cast<int>(rs.pixels.back().pixels);
 | 
											rs.pos.y += static_cast<int>(rs.pixels.back().pixels);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
											rs.index = 0;
 | 
				
			||||||
 | 
											rs.vslines.clear();
 | 
				
			||||||
 | 
											rs.vslines.swap(*vsline_iterator++);
 | 
				
			||||||
 | 
											rs.pos.x = rs.vslines.front().x_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (!_m_foreach_visual_line(graph, rs))
 | 
				
			||||||
 | 
												break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											rs.pos.y += static_cast<int>(rs.vslines.back().extent_height_px);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					graph.typeface(pre_font);
 | 
										graph.typeface(pre_font);
 | 
				
			||||||
@ -194,8 +256,13 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					for(auto & line: dstream_)
 | 
										for(auto & line: dstream_)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
						rs.pixels.clear();
 | 
											rs.pixels.clear();
 | 
				
			||||||
						unsigned w = _m_line_pixels(line, def_line_pixels, rs);
 | 
											unsigned w = _m_line_pixels(line, def_line_pixels, rs);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
											rs.vslines.clear();
 | 
				
			||||||
 | 
											auto w = _m_prepare_visual_lines(graph, line, def_line_pixels, rs);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if(limited && (w > limited))
 | 
											if(limited && (w > limited))
 | 
				
			||||||
							w = limited;
 | 
												w = limited;
 | 
				
			||||||
@ -203,8 +270,13 @@ namespace nana
 | 
				
			|||||||
						if(retsize.width < w)
 | 
											if(retsize.width < w)
 | 
				
			||||||
							retsize.width = w;
 | 
												retsize.width = w;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
						for (auto & px : rs.pixels)
 | 
											for (auto & px : rs.pixels)
 | 
				
			||||||
							retsize.height += static_cast<unsigned>(px.pixels);
 | 
												retsize.height += static_cast<unsigned>(px.pixels);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
											for (auto& vsline : rs.vslines)
 | 
				
			||||||
 | 
												retsize.height += static_cast<unsigned>(vsline.extent_height_px);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					return retsize;
 | 
										return retsize;
 | 
				
			||||||
@ -315,6 +387,7 @@ namespace nana
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
				void _m_align_x_base(const render_status& rs, pixel_tag & px, unsigned w) noexcept
 | 
									void _m_align_x_base(const render_status& rs, pixel_tag & px, unsigned w) noexcept
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					switch(rs.text_align)
 | 
										switch(rs.text_align)
 | 
				
			||||||
@ -330,7 +403,209 @@ namespace nana
 | 
				
			|||||||
						break;
 | 
											break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
									void _m_prepare_x(const render_status& rs, visual_line & vsline, unsigned w) noexcept
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										switch (rs.text_align)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
										case align::left:
 | 
				
			||||||
 | 
											vsline.x_base = 0;
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										case align::center:
 | 
				
			||||||
 | 
											vsline.x_base = (static_cast<int>(rs.allowed_width - w) >> 1);
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										case align::right:
 | 
				
			||||||
 | 
											vsline.x_base = static_cast<int>(rs.allowed_width - w);
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef VISUAL_LINES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									/**
 | 
				
			||||||
 | 
									 * prepare data for rendering a line of text.
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									unsigned _m_prepare_visual_lines(graph_reference graph, dstream::linecontainer& line, unsigned def_line_px, render_status& rs)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										unsigned abs_text_px = 0;
 | 
				
			||||||
 | 
										unsigned max_ascent = 0;
 | 
				
			||||||
 | 
										unsigned max_descent = 0;
 | 
				
			||||||
 | 
										unsigned max_content_height = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										int text_pos = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										std::vector<visual_line::element> vsline_elements;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for (auto i = line.cbegin(); i != line.cend(); ++i)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											auto const data = i->data_ptr;
 | 
				
			||||||
 | 
											auto fblock = i->fblock_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											abs_text_px += data->size().width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											unsigned ascent = 0;
 | 
				
			||||||
 | 
											unsigned descent = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											auto extent_size = data->size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											//Check if the content is displayed in current line.
 | 
				
			||||||
 | 
											if ((0 == rs.allowed_width) || (text_pos + extent_size.width <= rs.allowed_width))
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												text_pos += static_cast<int>(extent_size.width);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												//Adjust height of extent_size for special text alignement.
 | 
				
			||||||
 | 
												if (fblock::aligns::baseline == fblock->text_align)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													ascent = static_cast<unsigned>(data->ascent());
 | 
				
			||||||
 | 
													descent = static_cast<unsigned>(extent_size.height - ascent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													if (max_descent < descent)
 | 
				
			||||||
 | 
														max_descent = descent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													if ((false == data->is_text()) && (extent_size.height < max_ascent + max_descent))
 | 
				
			||||||
 | 
														extent_size.height = max_ascent + max_descent;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (max_ascent < ascent)	max_ascent = ascent;
 | 
				
			||||||
 | 
												if (max_descent < descent)	max_descent = descent;
 | 
				
			||||||
 | 
												if (max_content_height < extent_size.height)	max_content_height = extent_size.height;
 | 
				
			||||||
 | 
												vsline_elements.emplace_back(i, 0, data->text().size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												continue;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											//make a visual line for existing vsline elements
 | 
				
			||||||
 | 
											if (text_pos)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
					#ifdef _nana_std_has_returnable_emplace_back
 | 
				
			||||||
 | 
												auto & vsline = rs.vslines.emplace_back();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
												rs.vslines.emplace_back();
 | 
				
			||||||
 | 
												auto & vsline = rs.vslines.back();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
												_m_prepare_x(rs, vsline, static_cast<unsigned>(text_pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (max_ascent + max_descent > max_content_height)
 | 
				
			||||||
 | 
													max_content_height = max_descent + max_ascent;
 | 
				
			||||||
 | 
												else
 | 
				
			||||||
 | 
													max_ascent = max_content_height - max_descent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												vsline.extent_height_px = max_content_height;
 | 
				
			||||||
 | 
												vsline.baseline = max_ascent;
 | 
				
			||||||
 | 
												vsline.elements.swap(vsline_elements);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											text_pos = 0;
 | 
				
			||||||
 | 
											max_content_height = max_ascent = max_descent = 0;
 | 
				
			||||||
 | 
											//Adjust height of extent_size for special text alignement.
 | 
				
			||||||
 | 
											if (fblock::aligns::baseline == fblock->text_align)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												ascent = static_cast<unsigned>(data->ascent());
 | 
				
			||||||
 | 
												descent = static_cast<unsigned>(extent_size.height - ascent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (max_descent < descent)
 | 
				
			||||||
 | 
													max_descent = descent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if ((false == data->is_text()) && (extent_size.height < max_ascent + max_descent))
 | 
				
			||||||
 | 
													extent_size.height = max_ascent + max_descent;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (max_ascent < ascent)	max_ascent = ascent;
 | 
				
			||||||
 | 
											if (max_descent < descent)	max_descent = descent;
 | 
				
			||||||
 | 
											if (max_content_height < extent_size.height)	max_content_height = extent_size.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (data->is_text())
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												_m_change_font(graph, fblock);
 | 
				
			||||||
 | 
												//Split a text into multiple lines
 | 
				
			||||||
 | 
												auto rest_extent_size = extent_size.width;
 | 
				
			||||||
 | 
												std::size_t text_begin = 0;
 | 
				
			||||||
 | 
												while (text_begin < data->text().size())
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													unsigned sub_text_px = 0;
 | 
				
			||||||
 | 
													auto sub_text_len = _m_fit_text(graph, data->text().substr(text_begin), rs.allowed_width, sub_text_px);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													if (text_begin + sub_text_len < data->text().size())
 | 
				
			||||||
 | 
													{
 | 
				
			||||||
 | 
														//make a new visual line
 | 
				
			||||||
 | 
					#ifdef _nana_std_has_returnable_emplace_back
 | 
				
			||||||
 | 
														auto & vsline = rs.vslines.emplace_back();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
														rs.vslines.emplace_back();
 | 
				
			||||||
 | 
														auto & vsline = rs.vslines.back();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
														_m_prepare_x(rs, vsline, sub_text_px);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														vsline.extent_height_px = max_content_height;
 | 
				
			||||||
 | 
														vsline.baseline = max_ascent;
 | 
				
			||||||
 | 
														vsline.elements.emplace_back(i, text_begin, sub_text_len);
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
													else
 | 
				
			||||||
 | 
													{
 | 
				
			||||||
 | 
														//the last part, write it to vsline_elements to keep the status for next line element(next i)
 | 
				
			||||||
 | 
														vsline_elements.emplace_back(i, text_begin, sub_text_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														text_pos = sub_text_px;
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													text_begin += sub_text_len;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											else
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												//the last part, write it to vsline_elements to keep the status for next line element(next i)
 | 
				
			||||||
 | 
												vsline_elements.emplace_back(i, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												text_pos = static_cast<int>(i->data_ptr->size().width);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (!vsline_elements.empty())
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
					#ifdef _nana_std_has_returnable_emplace_back
 | 
				
			||||||
 | 
											auto & vsline = rs.vslines.emplace_back();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
											rs.vslines.emplace_back();
 | 
				
			||||||
 | 
											auto & vsline = rs.vslines.back();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
											_m_prepare_x(rs, vsline, static_cast<unsigned>(text_pos));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (max_ascent + max_descent > max_content_height)
 | 
				
			||||||
 | 
												max_content_height = max_descent + max_ascent;
 | 
				
			||||||
 | 
											else
 | 
				
			||||||
 | 
												max_ascent = max_content_height - max_descent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											vsline.extent_height_px = max_content_height;
 | 
				
			||||||
 | 
											vsline.baseline = max_ascent;
 | 
				
			||||||
 | 
											vsline.elements.swap(vsline_elements);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										return abs_text_px;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									//Get the length of characters in a text whose length in pixels doesn't beyond the limited width.
 | 
				
			||||||
 | 
									static unsigned _m_fit_text(graph_reference graph, const std::wstring& text, unsigned limited_width_px, unsigned& text_px) noexcept
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
					#ifdef _nana_std_has_string_view
 | 
				
			||||||
 | 
										auto pxbuf = graph.glyph_pixels(text);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
										std::unique_ptr<unsigned[]> pxbuf(new unsigned[text.size()]);
 | 
				
			||||||
 | 
										graph.glyph_pixels(text.c_str(), text.size(), pxbuf.get());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										text_px = 0;
 | 
				
			||||||
 | 
										for (std::size_t i = 0; i < text.size(); ++i)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											if (text_px + pxbuf[i] > limited_width_px)
 | 
				
			||||||
 | 
												return i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											text_px += pxbuf[i];
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return text.size();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
				unsigned _m_line_pixels(dstream::linecontainer& line, unsigned def_line_pixels, render_status & rs)
 | 
									unsigned _m_line_pixels(dstream::linecontainer& line, unsigned def_line_pixels, render_status & rs)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if (line.empty())
 | 
										if (line.empty())
 | 
				
			||||||
@ -441,7 +716,9 @@ namespace nana
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return total_w;
 | 
										return total_w;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef VISUAL_LINES
 | 
				
			||||||
				bool _m_each_line(graph_reference graph, dstream::linecontainer&, render_status& rs)
 | 
									bool _m_each_line(graph_reference graph, dstream::linecontainer&, render_status& rs)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					std::wstring text;
 | 
										std::wstring text;
 | 
				
			||||||
@ -501,7 +778,36 @@ namespace nana
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return (rs.pos.y <= lastpos);
 | 
										return (rs.pos.y <= lastpos);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
									bool _m_foreach_visual_line(graph_reference graph, render_status& rs)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										std::wstring text;
 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
 | 
										content_element_iterator block_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										auto const bottom = static_cast<int>(graph.height()) - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for (auto & vsline : rs.vslines)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											rs.pos.x = vsline.x_base;
 | 
				
			||||||
 | 
											for (auto& content_elm : vsline.elements)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												_m_draw_vsline_element(graph, content_elm, rs);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											++rs.index;	//next line index
 | 
				
			||||||
 | 
											rs.pos.y += vsline.extent_height_px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (rs.pos.y > bottom)
 | 
				
			||||||
 | 
												return false;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										return (rs.pos.y <= bottom);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0 //deprecated
 | 
				
			||||||
				static bool _m_overline(const render_status& rs, int right, bool equal_required) noexcept
 | 
									static bool _m_overline(const render_status& rs, int right, bool equal_required) noexcept
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if(align::left == rs.text_align)
 | 
										if(align::left == rs.text_align)
 | 
				
			||||||
@ -509,7 +815,24 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					return (equal_required ? rs.pixels[rs.index].x_base <= 0 : rs.pixels[rs.index].x_base < 0);
 | 
										return (equal_required ? rs.pixels[rs.index].x_base <= 0 : rs.pixels[rs.index].x_base < 0);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef VISUAL_LINES
 | 
				
			||||||
 | 
									static int _m_vsline_element_top(const visual_line& vsline, fblock* fblock_ptr, const data* data_ptr) noexcept
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										switch (fblock_ptr->text_align)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
										case fblock::aligns::center:
 | 
				
			||||||
 | 
											return static_cast<int>(vsline.extent_height_px - data_ptr->size().height) / 2;
 | 
				
			||||||
 | 
										case fblock::aligns::bottom:
 | 
				
			||||||
 | 
											return static_cast<int>(vsline.extent_height_px - data_ptr->size().height);
 | 
				
			||||||
 | 
										case fblock::aligns::baseline:
 | 
				
			||||||
 | 
											return static_cast<int>(vsline.baseline - (data_ptr->is_text() ? data_ptr->ascent() : data_ptr->size().height));
 | 
				
			||||||
 | 
										default:	break;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										return 0;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
				static int _m_text_top(const pixel_tag& px, fblock* fblock_ptr, const data* data_ptr)
 | 
									static int _m_text_top(const pixel_tag& px, fblock* fblock_ptr, const data* data_ptr)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					switch(fblock_ptr->text_align)
 | 
										switch(fblock_ptr->text_align)
 | 
				
			||||||
@ -524,7 +847,52 @@ namespace nana
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
					return 0;
 | 
										return 0;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef VISUAL_LINES
 | 
				
			||||||
 | 
									void _m_draw_vsline_element(graph_reference graph, const visual_line::element& vsline_elm, render_status& rs)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										auto data = vsline_elm.content_element->data_ptr;
 | 
				
			||||||
 | 
										auto fblock = vsline_elm.content_element->fblock_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (data->is_text())
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											auto const text = data->text().c_str() + vsline_elm.range.first;
 | 
				
			||||||
 | 
											auto const reordered = unicode_reorder(text, vsline_elm.range.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											_m_change_font(graph, fblock);
 | 
				
			||||||
 | 
											for (auto & bidi : reordered)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												auto extent_size = data->size();
 | 
				
			||||||
 | 
					#ifdef _nana_std_has_string_view
 | 
				
			||||||
 | 
												std::wstring_view text_sv{ bidi.begin, static_cast<std::size_t>(bidi.end - bidi.begin) };
 | 
				
			||||||
 | 
												if (data->text().size() != text_sv.size())
 | 
				
			||||||
 | 
													extent_size = graph.text_extent_size(text_sv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												const int y = rs.pos.y + _m_vsline_element_top(rs.vslines[rs.index], fblock, data);
 | 
				
			||||||
 | 
												graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
												std::wstring text{ bidi.begin, static_cast<std::size_t>(bidi.end - bidi.begin) };
 | 
				
			||||||
 | 
												if (data->text().size() != text.size())
 | 
				
			||||||
 | 
													extent_size = graph.text_extent_size(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												const int y = rs.pos.y + _m_vsline_element_top(rs.vslines[rs.index], fblock, data);
 | 
				
			||||||
 | 
												graph.string({ rs.pos.x, y }, text, _m_fgcolor(fblock));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
												_m_insert_if_traceable(rs.pos.x, y, extent_size, fblock);
 | 
				
			||||||
 | 
												rs.pos.x += static_cast<int>(extent_size.width);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											int y = rs.pos.y + _m_vsline_element_top(rs.vslines[rs.index], fblock, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											data->nontext_render(graph, rs.pos.x, y);
 | 
				
			||||||
 | 
											_m_insert_if_traceable(rs.pos.x, y, data->size(), fblock);
 | 
				
			||||||
 | 
											rs.pos.x += static_cast<int>(data->size().width);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
				void _m_draw_block(graph_reference graph, const std::wstring& s, dstream::linecontainer::iterator block_start, render_status& rs)
 | 
									void _m_draw_block(graph_reference graph, const std::wstring& s, dstream::linecontainer::iterator block_start, render_status& rs)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					auto const reordered = unicode_reorder(s.data(), s.length());
 | 
										auto const reordered = unicode_reorder(s.data(), s.length());
 | 
				
			||||||
@ -550,9 +918,35 @@ namespace nana
 | 
				
			|||||||
							fblock * fblock_ptr = i->fblock_ptr;
 | 
												fblock * fblock_ptr = i->fblock_ptr;
 | 
				
			||||||
							data * data_ptr = i->data_ptr;
 | 
												data * data_ptr = i->data_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 1
 | 
				
			||||||
 | 
												const int range_text_area = static_cast<int>(rs.allowed_width) - rs.pos.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												_m_change_font(graph, fblock_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												auto text_extent_size = data_ptr->size();
 | 
				
			||||||
 | 
					#ifndef _nana_std_has_string_view
 | 
				
			||||||
 | 
												std::wstring_view text_sv{ data_ptr->text().c_str() + text_range.first, text_range.second };
 | 
				
			||||||
 | 
												if (data_ptr->text().size() != text_sv.size())
 | 
				
			||||||
 | 
													text_extent_size = graph.text_extent_size(text_sv);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
												auto text_sv = data_ptr->text().substr(text_range.first, text_range.second);
 | 
				
			||||||
 | 
												if (data_ptr->text().size() != text_sv.size())
 | 
				
			||||||
 | 
													text_extent_size = graph.text_extent_size(text_sv);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
												if ((static_cast<int>(text_extent_size.width) > range_text_area) && (rs.pos.x != px.x_base))
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													//Change a new line
 | 
				
			||||||
 | 
													rs.pos.y += static_cast<int>(px.pixels);
 | 
				
			||||||
 | 
													px = rs.pixels[++rs.index];
 | 
				
			||||||
 | 
													rs.pos.x = px.x_base;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												const int y = rs.pos.y + _m_text_top(px, fblock_ptr, data_ptr);
 | 
				
			||||||
 | 
												graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
							const int w = static_cast<int>(rs.allowed_width) - rs.pos.x;
 | 
												const int w = static_cast<int>(rs.allowed_width) - rs.pos.x;
 | 
				
			||||||
							nana::size sz = data_ptr->size();
 | 
												nana::size text_extent_size = data_ptr->size();
 | 
				
			||||||
							if ((static_cast<int>(sz.width) > w) && (rs.pos.x != px.x_base))
 | 
												if ((static_cast<int>(text_extent_size.width) > w) && (rs.pos.x != px.x_base))
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
								//Change a new line
 | 
													//Change a new line
 | 
				
			||||||
								rs.pos.y += static_cast<int>(px.pixels);
 | 
													rs.pos.y += static_cast<int>(px.pixels);
 | 
				
			||||||
@ -569,7 +963,7 @@ namespace nana
 | 
				
			|||||||
							if (text_range.second != text_sv.size())
 | 
												if (text_range.second != text_sv.size())
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
								text_sv = text_sv.substr(text_range.first, text_range.second);
 | 
													text_sv = text_sv.substr(text_range.first, text_range.second);
 | 
				
			||||||
								sz = graph.text_extent_size(text_sv);
 | 
													text_extent_size = graph.text_extent_size(text_sv);
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr));
 | 
												graph.string({ rs.pos.x, y }, text_sv, _m_fgcolor(fblock_ptr));
 | 
				
			||||||
@ -581,15 +975,15 @@ namespace nana
 | 
				
			|||||||
							else
 | 
												else
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
								auto str = data_ptr->text().substr(text_range.first, text_range.second);
 | 
													auto str = data_ptr->text().substr(text_range.first, text_range.second);
 | 
				
			||||||
								sz = graph.text_extent_size(str);
 | 
													text_extent_size = graph.text_extent_size(str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
								graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
 | 
													graph.string({ rs.pos.x, y }, str, _m_fgcolor(fblock_ptr));
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#endif //#if 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												_m_insert_if_traceable(rs.pos.x, y, text_extent_size, fblock_ptr);
 | 
				
			||||||
							_m_insert_if_traceable(rs.pos.x, y, sz, fblock_ptr);
 | 
												rs.pos.x += static_cast<int>(text_extent_size.width);
 | 
				
			||||||
							rs.pos.x += static_cast<int>(sz.width);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
							if(text_range.second < len)
 | 
												if(text_range.second < len)
 | 
				
			||||||
							{
 | 
												{
 | 
				
			||||||
@ -601,6 +995,7 @@ namespace nana
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					#endif //VISUAL_LINES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				static std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
 | 
									static std::pair<std::size_t, std::size_t> _m_locate(dstream::linecontainer::iterator& i, std::size_t pos)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
 | 
				
			|||||||
@ -2934,9 +2934,9 @@ namespace nana
 | 
				
			|||||||
					cat_proxy(ess_, pos.cat).at(pos.item).select(true);
 | 
										cat_proxy(ess_, pos.cat).at(pos.item).select(true);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				void hovered(index_type /*pos*/) override
 | 
									void hovered(index_type pos) override
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					auto offset = ess_->content_view->origin().y / ess_->item_height();
 | 
										auto offset = ess_->lister.distance(ess_->first_display(), ess_->lister.index_cast(pos, false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (ess_->pointer_where.first != parts::list || ess_->pointer_where.second != offset)
 | 
										if (ess_->pointer_where.first != parts::list || ess_->pointer_where.second != offset)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
@ -2996,11 +2996,11 @@ namespace nana
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					auto last_off = this->distance(this->first(), this->last()) * ess_->item_height();
 | 
										auto const content_px = ess_->content_view->content_size().height;
 | 
				
			||||||
					if (last_off - off >= screen_px)
 | 
										if (content_px - off >= screen_px)
 | 
				
			||||||
						origin.y = static_cast<int>(off);
 | 
											origin.y = static_cast<int>(off);
 | 
				
			||||||
					else if (last_off >= screen_px)
 | 
										else if (content_px >= screen_px)
 | 
				
			||||||
						origin.y = static_cast<int>(last_off - screen_px);
 | 
											origin.y = static_cast<int>(content_px - screen_px);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (ess_->content_view->move_origin(origin - ess_->content_view->origin()))
 | 
									if (ess_->content_view->move_origin(origin - ess_->content_view->origin()))
 | 
				
			||||||
@ -4378,9 +4378,11 @@ namespace nana
 | 
				
			|||||||
					essence_->ptr_state = item_state::highlighted;
 | 
										essence_->ptr_state = item_state::highlighted;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					bool need_refresh = false;
 | 
										bool need_refresh = false;
 | 
				
			||||||
					//Do sort
 | 
					
 | 
				
			||||||
					if (essence_->header.sortable() && essence_->pointer_where.first == parts::header && prev_state == item_state::pressed)
 | 
										//Don't sort the column when the mouse is due to released for stopping resizing column.
 | 
				
			||||||
 | 
										if ((drawer_header_->splitter() == npos) && essence_->header.sortable() && essence_->pointer_where.first == parts::header && prev_state == item_state::pressed)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
 | 
											//Try to sort the column
 | 
				
			||||||
						if(essence_->pointer_where.second < essence_->header.cont().size())
 | 
											if(essence_->pointer_where.second < essence_->header.cont().size())
 | 
				
			||||||
							need_refresh = essence_->lister.sort_column(essence_->pointer_where.second, nullptr);
 | 
												need_refresh = essence_->lister.sort_column(essence_->pointer_where.second, nullptr);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -4475,14 +4477,11 @@ namespace nana
 | 
				
			|||||||
					if (list.first().empty())
 | 
										if (list.first().empty())
 | 
				
			||||||
						return;
 | 
											return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					bool upward = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					switch(arg.key)
 | 
										switch(arg.key)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
					case keyboard::os_arrow_up:
 | 
										case keyboard::os_arrow_up:
 | 
				
			||||||
						upward = true;
 | 
					 | 
				
			||||||
					case keyboard::os_arrow_down:
 | 
										case keyboard::os_arrow_down:
 | 
				
			||||||
						list.move_select(upward, !arg.shift, true);
 | 
											list.move_select((keyboard::os_arrow_up == arg.key), !arg.shift, true);
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					case L' ':
 | 
										case L' ':
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
@ -4494,9 +4493,9 @@ namespace nana
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					case keyboard::os_pageup :
 | 
										case keyboard::os_pageup :
 | 
				
			||||||
						upward = true;
 | 
					 | 
				
			||||||
					case keyboard::os_pagedown:
 | 
										case keyboard::os_pagedown:
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
 | 
												auto const upward = (keyboard::os_pageup == arg.key);
 | 
				
			||||||
							auto const item_px = essence_->item_height();
 | 
												auto const item_px = essence_->item_height();
 | 
				
			||||||
							auto picked_items = list.pick_items(true, true);
 | 
												auto picked_items = list.pick_items(true, true);
 | 
				
			||||||
							index_pair init_idx = (picked_items.empty() ? list.first() : picked_items[0]);
 | 
												index_pair init_idx = (picked_items.empty() ? list.first() : picked_items[0]);
 | 
				
			||||||
@ -5390,6 +5389,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::auto_draw(bool enabled) noexcept
 | 
							void listbox::auto_draw(bool enabled) noexcept
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
			if (ess.auto_draw != enabled)
 | 
								if (ess.auto_draw != enabled)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@ -5400,6 +5400,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::scroll(bool to_bottom, size_type cat_pos)
 | 
							void listbox::scroll(bool to_bottom, size_type cat_pos)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
			auto cats = this->size_categ();
 | 
								auto cats = this->size_categ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5498,6 +5499,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		rectangle listbox::content_area() const
 | 
							rectangle listbox::content_area() const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
			auto carea = ess.content_area();
 | 
								auto carea = ess.content_area();
 | 
				
			||||||
			carea.x += ess.header.margin();
 | 
								carea.x += ess.header.margin();
 | 
				
			||||||
@ -5544,29 +5546,34 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		listbox::cat_proxy listbox::at(size_type pos)
 | 
							listbox::cat_proxy listbox::at(size_type pos)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			check_range(pos, size_categ());
 | 
								check_range(pos, size_categ());
 | 
				
			||||||
			return{ &_m_ess(), pos };
 | 
								return{ &_m_ess(), pos };
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const listbox::cat_proxy listbox::at(size_type pos) const
 | 
							const listbox::cat_proxy listbox::at(size_type pos) const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			check_range(pos, size_categ());
 | 
								check_range(pos, size_categ());
 | 
				
			||||||
			return{ &_m_ess(), pos };
 | 
								return{ &_m_ess(), pos };
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		listbox::item_proxy listbox::at(const index_pair& abs_pos)
 | 
							listbox::item_proxy listbox::at(const index_pair& abs_pos)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return at(abs_pos.cat).at(abs_pos.item);
 | 
								return at(abs_pos.cat).at(abs_pos.item);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const listbox::item_proxy listbox::at(const index_pair& pos_abs) const
 | 
							const listbox::item_proxy listbox::at(const index_pair& pos_abs) const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return at(pos_abs.cat).at(pos_abs.item);
 | 
								return at(pos_abs.cat).at(pos_abs.item);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Contributed by leobackes(pr#97)
 | 
							// Contributed by leobackes(pr#97)
 | 
				
			||||||
		listbox::index_pair listbox::cast( const point& pos ) const
 | 
							listbox::index_pair listbox::cast( const point& pos ) const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess=_m_ess();
 | 
								auto & ess=_m_ess();
 | 
				
			||||||
			auto _where = ess.where(pos);
 | 
								auto _where = ess.where(pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5578,27 +5585,32 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		auto listbox::column_at(size_type pos, bool disp_order) -> column_interface&
 | 
							auto listbox::column_at(size_type pos, bool disp_order) -> column_interface&
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().header.at(pos, disp_order);
 | 
								return _m_ess().header.at(pos, disp_order);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto listbox::column_at(size_type pos, bool disp_order) const -> const column_interface&
 | 
							auto listbox::column_at(size_type pos, bool disp_order) const -> const column_interface&
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().header.at(pos, disp_order);
 | 
								return _m_ess().header.at(pos, disp_order);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto listbox::column_size() const ->size_type
 | 
							auto listbox::column_size() const ->size_type
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().header.cont().size();
 | 
								return _m_ess().header.cont().size();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		//Contributed by leobackes(pr#97)
 | 
							//Contributed by leobackes(pr#97)
 | 
				
			||||||
		listbox::size_type listbox::column_from_pos ( const point& pos ) const
 | 
							listbox::size_type listbox::column_from_pos ( const point& pos ) const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().column_from_pos(pos.x);
 | 
								return _m_ess().column_from_pos(pos.x);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void listbox::checkable(bool chkable)
 | 
							void listbox::checkable(bool chkable)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
			if(ess.checkable != chkable)
 | 
								if(ess.checkable != chkable)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@ -5609,11 +5621,13 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		auto listbox::checked() const -> index_pairs
 | 
							auto listbox::checked() const -> index_pairs
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().lister.pick_items(false);
 | 
								return _m_ess().lister.pick_items(false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void listbox::clear(size_type cat)
 | 
							void listbox::clear(size_type cat)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto origin = ess.content_view->origin();
 | 
								auto origin = ess.content_view->origin();
 | 
				
			||||||
@ -5637,6 +5651,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::clear()
 | 
							void listbox::clear()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ess.lister.clear();
 | 
								ess.lister.clear();
 | 
				
			||||||
@ -5651,6 +5666,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::erase(size_type cat)
 | 
							void listbox::erase(size_type cat)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto origin = ess.content_view->origin();
 | 
								auto origin = ess.content_view->origin();
 | 
				
			||||||
@ -5675,6 +5691,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::erase()
 | 
							void listbox::erase()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto & ess = _m_ess();
 | 
								auto & ess = _m_ess();
 | 
				
			||||||
			ess.lister.erase();
 | 
								ess.lister.erase();
 | 
				
			||||||
			ess.calc_content_size();
 | 
								ess.calc_content_size();
 | 
				
			||||||
@ -5683,6 +5700,8 @@ namespace nana
 | 
				
			|||||||
		
 | 
							
 | 
				
			||||||
		void listbox::erase(index_pairs indexes)
 | 
							void listbox::erase(index_pairs indexes)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::sort(indexes.begin(), indexes.end(), [](const index_pair& pos1, const index_pair& pos2)
 | 
								std::sort(indexes.begin(), indexes.end(), [](const index_pair& pos1, const index_pair& pos2)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				return (pos1 > pos2);
 | 
									return (pos1 > pos2);
 | 
				
			||||||
@ -5732,6 +5751,7 @@ namespace nana
 | 
				
			|||||||
			if(ip.empty())
 | 
								if(ip.empty())
 | 
				
			||||||
				return ip;
 | 
									return ip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			auto * ess = ip._m_ess();
 | 
								auto * ess = ip._m_ess();
 | 
				
			||||||
			auto _where = ip.pos();
 | 
								auto _where = ip.pos();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5754,48 +5774,57 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		bool listbox::sortable() const
 | 
							bool listbox::sortable() const
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().header.sortable();
 | 
								return _m_ess().header.sortable();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void listbox::sortable(bool enable)
 | 
							void listbox::sortable(bool enable)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().header.sortable(enable);
 | 
								_m_ess().header.sortable(enable);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void listbox::set_sort_compare(size_type col, std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> strick_ordering)
 | 
							void listbox::set_sort_compare(size_type col, std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> strick_ordering)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().header.at(col).weak_ordering = std::move(strick_ordering);
 | 
								_m_ess().header.at(col).weak_ordering = std::move(strick_ordering);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
 | 
					        /// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
 | 
				
			||||||
        void listbox::sort_col(size_type col, bool reverse)
 | 
					        void listbox::sort_col(size_type col, bool reverse)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().lister.sort_column(col, &reverse);
 | 
								_m_ess().lister.sort_column(col, &reverse);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto listbox::sort_col() const -> size_type
 | 
							auto listbox::sort_col() const -> size_type
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().lister.sort_attrs().column;
 | 
								return _m_ess().lister.sort_attrs().column;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
 | 
					        /// potencially ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
 | 
				
			||||||
		void listbox::unsort()
 | 
							void listbox::unsort()
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			this->sort_col(npos, false);
 | 
								this->sort_col(npos, false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool listbox::freeze_sort(bool freeze)
 | 
							bool listbox::freeze_sort(bool freeze)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return !_m_ess().lister.active_sort(!freeze);
 | 
								return !_m_ess().lister.active_sort(!freeze);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto listbox::selected() const -> index_pairs
 | 
							auto listbox::selected() const -> index_pairs
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			return _m_ess().lister.pick_items(true);   // absolute positions, no relative to display
 | 
								return _m_ess().lister.pick_items(true);   // absolute positions, no relative to display
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void listbox::show_header(bool sh)
 | 
							void listbox::show_header(bool sh)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().header.visible(sh);
 | 
								_m_ess().header.visible(sh);
 | 
				
			||||||
			_m_ess().update();
 | 
								_m_ess().update();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -5807,6 +5836,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		void listbox::move_select(bool upwards)  ///<Selects an item besides the current selected item in the display.
 | 
							void listbox::move_select(bool upwards)  ///<Selects an item besides the current selected item in the display.
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().lister.move_select(upwards, true, true);
 | 
								_m_ess().lister.move_select(upwards, true, true);
 | 
				
			||||||
			_m_ess().update();
 | 
								_m_ess().update();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -5839,6 +5869,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		listbox& listbox::category_icon(std::function<void(paint::graphics& graph, const rectangle& rt_icon, bool expanded)> icon_renderer)
 | 
							listbox& listbox::category_icon(std::function<void(paint::graphics& graph, const rectangle& rt_icon, bool expanded)> icon_renderer)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().ctg_icon_renderer.swap(icon_renderer);
 | 
								_m_ess().ctg_icon_renderer.swap(icon_renderer);
 | 
				
			||||||
			_m_ess().update();
 | 
								_m_ess().update();
 | 
				
			||||||
			return *this;
 | 
								return *this;
 | 
				
			||||||
@ -5846,6 +5877,7 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		listbox& listbox::category_icon(const paint::image& img_expanded, const paint::image&& img_collapsed)
 | 
							listbox& listbox::category_icon(const paint::image& img_expanded, const paint::image&& img_collapsed)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								internal_scope_guard lock;
 | 
				
			||||||
			_m_ess().ctg_icon_renderer = [img_expanded, img_collapsed](paint::graphics& graph, const rectangle& rt_icon, bool expanded)
 | 
								_m_ess().ctg_icon_renderer = [img_expanded, img_collapsed](paint::graphics& graph, const rectangle& rt_icon, bool expanded)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				if (expanded)
 | 
									if (expanded)
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,7 @@ namespace nana
 | 
				
			|||||||
					if (value_ptr)
 | 
										if (value_ptr)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						if (unknown_)
 | 
											if (unknown_)
 | 
				
			||||||
							value_ += (*value_ptr ? 5 : 0);
 | 
												value_ += 5;
 | 
				
			||||||
						else
 | 
											else
 | 
				
			||||||
							value_ = (std::min)(max_, *value_ptr);
 | 
												value_ = (std::min)(max_, *value_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,7 +99,7 @@ namespace nana
 | 
				
			|||||||
						auto value_px = (widget_->size().width - border_px * 2);
 | 
											auto value_px = (widget_->size().width - border_px * 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						//avoid overflow
 | 
											//avoid overflow
 | 
				
			||||||
						if (value_ < max_)
 | 
											if (unknown_ || (value_ < max_))
 | 
				
			||||||
							value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_)));
 | 
												value_px = static_cast<unsigned>(value_px * (double(value_) / double(max_)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if (value_px != value_px_)
 | 
											if (value_px != value_px_)
 | 
				
			||||||
 | 
				
			|||||||
@ -99,12 +99,14 @@ namespace nana
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					//Check scroll_area to avoiding division by zero.
 | 
										//Check scroll_area to avoiding division by zero.
 | 
				
			||||||
					if (scroll_area)
 | 
										if (scroll_area)
 | 
				
			||||||
						metrics_.value = pos * value_max / scroll_area;
 | 
											metrics_.value = static_cast<std::size_t>(pos * (static_cast<double>(value_max) / scroll_area));	//converting to double to avoid overflow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (metrics_.value < value_max)
 | 
										if (metrics_.value < value_max)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						int selfpos = static_cast<int>(metrics_.value * scroll_area / value_max);
 | 
											//converting to double to avoid overflow.
 | 
				
			||||||
						int nextpos = static_cast<int>((metrics_.value + 1) * scroll_area / value_max);
 | 
											auto const px_per_value = static_cast<double>(scroll_area) / value_max;
 | 
				
			||||||
 | 
											int selfpos = static_cast<int>(metrics_.value * px_per_value);
 | 
				
			||||||
 | 
											int nextpos = static_cast<int>((metrics_.value + 1) * px_per_value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if(selfpos != nextpos && (pos - selfpos > nextpos - pos))
 | 
											if(selfpos != nextpos && (pos - selfpos > nextpos - pos))
 | 
				
			||||||
							++metrics_.value;
 | 
												++metrics_.value;
 | 
				
			||||||
 | 
				
			|||||||
@ -1853,7 +1853,6 @@ namespace nana
 | 
				
			|||||||
					item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
 | 
										item_locator nl(impl_, xpos, arg.pos.x, arg.pos.y);
 | 
				
			||||||
					impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
 | 
										impl_->attr.tree_cont.for_each<item_locator&>(shape.first, nl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
					auto & node_state = impl_->node_state;
 | 
										auto & node_state = impl_->node_state;
 | 
				
			||||||
					node_state.pressed_node = nl.node();
 | 
										node_state.pressed_node = nl.node();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1869,7 +1868,6 @@ namespace nana
 | 
				
			|||||||
					else
 | 
										else
 | 
				
			||||||
						return;
 | 
											return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					
 | 
					 | 
				
			||||||
					impl_->draw(true);
 | 
										impl_->draw(true);
 | 
				
			||||||
					API::dev::lazy_refresh();
 | 
										API::dev::lazy_refresh();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
				
			|||||||
@ -417,7 +417,7 @@ namespace nana
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef _nana_cxx_folding_expression
 | 
					#ifndef __cpp_fold_expressions
 | 
				
			||||||
	void internationalization::_m_fetch_args(std::vector<std::string>&)
 | 
						void internationalization::_m_fetch_args(std::vector<std::string>&)
 | 
				
			||||||
	{}
 | 
						{}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -498,16 +498,16 @@ namespace paint
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			if (nullptr == impl_->handle || nullptr == impl_->handle->context) return {};
 | 
								if (nullptr == impl_->handle || nullptr == impl_->handle->context) return {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (text.empty()) return std::unique_ptr<unsigned[]>{new unsigned[1]};
 | 
								auto pxbuf = std::unique_ptr<unsigned[]>{ new unsigned[text.size() ? text.size() : 1] };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!text.empty())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
				unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
 | 
									unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
 | 
				
			||||||
#if defined(NANA_WINDOWS)
 | 
					#if defined(NANA_WINDOWS)
 | 
				
			||||||
				int * dx = new int[text.size()];
 | 
									int * dx = new int[text.size()];
 | 
				
			||||||
				SIZE extents;
 | 
									SIZE extents;
 | 
				
			||||||
				::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast<int>(text.size()), 0, 0, dx, &extents);
 | 
									::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast<int>(text.size()), 0, 0, dx, &extents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto pxbuf = std::unique_ptr<unsigned[]>{ new unsigned[text.size()] };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]);
 | 
									pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				for (std::size_t i = 1; i < text.size(); ++i)
 | 
									for (std::size_t i = 1; i < text.size(); ++i)
 | 
				
			||||||
@ -521,7 +521,7 @@ namespace paint
 | 
				
			|||||||
				auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
 | 
									auto xft = reinterpret_cast<XftFont*>(impl_->handle->font->native_handle());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				XGlyphInfo extents;
 | 
									XGlyphInfo extents;
 | 
				
			||||||
			for (std::size_t i = 0; i < len; ++i)
 | 
									for (std::size_t i = 0; i < text.size(); ++i)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					if (text[i] != '\t')
 | 
										if (text[i] != '\t')
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
@ -533,6 +533,7 @@ namespace paint
 | 
				
			|||||||
						pxbuf[i] = tab_pixels;
 | 
											pxbuf[i] = tab_pixels;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			return pxbuf;
 | 
								return pxbuf;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ namespace system
 | 
				
			|||||||
			: impl_(new impl_t)
 | 
								: impl_(new impl_t)
 | 
				
			||||||
		{}
 | 
							{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		timepiece::timepiece(const volatile timepiece& rhs)
 | 
							timepiece::timepiece(const timepiece& rhs)
 | 
				
			||||||
			: impl_(new impl_t(*rhs.impl_))
 | 
								: impl_(new impl_t(*rhs.impl_))
 | 
				
			||||||
		{}
 | 
							{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,7 +33,7 @@ namespace system
 | 
				
			|||||||
			delete impl_;
 | 
								delete impl_;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		timepiece & timepiece::operator=(const volatile timepiece & rhs)
 | 
							timepiece & timepiece::operator=(const timepiece & rhs)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(this != &rhs)
 | 
								if(this != &rhs)
 | 
				
			||||||
				*impl_ = *rhs.impl_;
 | 
									*impl_ = *rhs.impl_;
 | 
				
			||||||
@ -41,7 +41,7 @@ namespace system
 | 
				
			|||||||
			return *this;
 | 
								return *this;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void timepiece::start() volatile
 | 
							void timepiece::start() noexcept
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#if defined(NANA_WINDOWS)
 | 
					#if defined(NANA_WINDOWS)
 | 
				
			||||||
			::QueryPerformanceCounter(&impl_->beg_timestamp);
 | 
								::QueryPerformanceCounter(&impl_->beg_timestamp);
 | 
				
			||||||
@ -51,7 +51,7 @@ namespace system
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		double timepiece::calc() const volatile
 | 
							double timepiece::calc() const noexcept
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
#if defined(NANA_WINDOWS)
 | 
					#if defined(NANA_WINDOWS)
 | 
				
			||||||
			LARGE_INTEGER li;
 | 
								LARGE_INTEGER li;
 | 
				
			||||||
 | 
				
			|||||||
@ -946,4 +946,68 @@ namespace nana
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		return unicode_bidi{}.reorder(text, length);
 | 
							return unicode_bidi{}.reorder(text, length);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum class unicode_character_type
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							format,
 | 
				
			||||||
 | 
							katakana,
 | 
				
			||||||
 | 
							aletter,
 | 
				
			||||||
 | 
							midletter,
 | 
				
			||||||
 | 
							midnumlet,
 | 
				
			||||||
 | 
							midnum,
 | 
				
			||||||
 | 
							numeric,
 | 
				
			||||||
 | 
							other
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//http://www.unicode.org/reports/tr29/WordBreakTest.html
 | 
				
			||||||
 | 
						unicode_character_type unicode_char_type(unsigned long ch)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if ((0x0600 <= ch && ch <= 0x0603) || (0x06DD == ch || 0x070F == ch || 0x17B4 == ch || 0x17B5 == ch) || (0x200C <= ch && ch <= 0x200F) ||
 | 
				
			||||||
 | 
								(0x202A <= ch && ch <= 0x202E) || (0x2060 <= ch && ch <= 0x2063) || (0x206A <= ch && ch <= 0x206F) || (0xFEFF == ch) || (0xFFF9 <= ch && ch <= 0xFFFB) ||
 | 
				
			||||||
 | 
								(0x1D173 <= ch && ch <= 0x1D17A) || (0xE0001 == ch) || (0xE0020 <= ch && ch <= 0xE007F))
 | 
				
			||||||
 | 
								return unicode_character_type::format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((0x30A1 <= ch && ch <= 0x30FA) || (0x30FC <= ch && ch <= 0x30FF) || (0x31F0 <= ch && ch <= 0x31FF) || (0xFF66 <= ch && ch <= 0xFF9F))
 | 
				
			||||||
 | 
								return unicode_character_type::katakana;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || (0x00AA == ch || 0x00B5 == ch || 0x00BA == ch) || (0x00C0 <= ch && ch <= 0x00D6) ||
 | 
				
			||||||
 | 
								(0x00D8 <= ch && ch <= 0x00F6) || (0x00F8 <= ch && ch <= 0x0236) || (0x0250 <= ch || ch <= 0x02C1))
 | 
				
			||||||
 | 
								return unicode_character_type::aletter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ('\'' == ch || 0x00AD == ch || 0x00B7 == ch || 0x05F4 == ch || 0x2019 == ch || 0x2027 == ch)
 | 
				
			||||||
 | 
								return unicode_character_type::midletter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ('.' == ch || '\\' == ch || ':' == ch)
 | 
				
			||||||
 | 
								return unicode_character_type::midnumlet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (0x2024 <= ch && ch <= 0x2026)
 | 
				
			||||||
 | 
								return unicode_character_type::midnum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (('0' <= ch && ch <= '9') || (0x0660 <= ch && ch <= 0x0669) || (0x06F0 <= ch && ch <= 0x06F9))
 | 
				
			||||||
 | 
								return unicode_character_type::numeric;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return unicode_character_type::other;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool unicode_wordbreak(wchar_t left, wchar_t right)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							auto l_type = unicode_char_type(left);
 | 
				
			||||||
 | 
							auto r_type = unicode_char_type(right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (l_type)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
							case unicode_character_type::format:
 | 
				
			||||||
 | 
							case unicode_character_type::midletter:
 | 
				
			||||||
 | 
							case unicode_character_type::midnumlet:
 | 
				
			||||||
 | 
							case unicode_character_type::midnum:
 | 
				
			||||||
 | 
							case unicode_character_type::other:
 | 
				
			||||||
 | 
								return (r_type != unicode_character_type::format);
 | 
				
			||||||
 | 
							case unicode_character_type::katakana:
 | 
				
			||||||
 | 
								return !(unicode_character_type::format == r_type) || (unicode_character_type::katakana == r_type);
 | 
				
			||||||
 | 
							case unicode_character_type::aletter:
 | 
				
			||||||
 | 
							case unicode_character_type::numeric:
 | 
				
			||||||
 | 
								return !(unicode_character_type::format == r_type) || (unicode_character_type::aletter == r_type) || (unicode_character_type::numeric == r_type);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}//end namespace nana
 | 
					}//end namespace nana
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user