Merge remote-tracking branch 'cnjinhao/hotfix-1.6.1' into hotfix-1.6.1
This commit is contained in:
commit
e1df91f800
@ -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_;
|
||||||
|
@ -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,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;
|
||||||
|
@ -1028,6 +1028,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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
|
@ -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,21 +982,26 @@ 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)
|
|
||||||
{
|
|
||||||
Window child;
|
|
||||||
::XTranslateCoordinates(disp, owner, restrict::spec.root_window(),
|
|
||||||
x, 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)
|
||||||
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 +1051,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 +1059,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 +1164,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 +1242,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 +1375,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
|
||||||
return reinterpret_cast<native_window_type>(::GetParent(reinterpret_cast<HWND>(wd)));
|
if(window_relationship::either_po == rsp)
|
||||||
|
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 +1425,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))
|
||||||
{
|
{
|
||||||
|
@ -798,17 +798,20 @@ 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()
|
||||||
@ -2879,25 +2882,26 @@ namespace nana
|
|||||||
}
|
}
|
||||||
|
|
||||||
field_gather * attached_field = nullptr;
|
field_gather * attached_field = nullptr;
|
||||||
if (name.size())
|
|
||||||
|
//find the field with specified name.
|
||||||
|
//the field may not be created.
|
||||||
|
auto i = fields.find(name);
|
||||||
|
if (fields.end() != i)
|
||||||
{
|
{
|
||||||
//find the field with specified name.
|
attached_field = i->second;
|
||||||
//the field may not be created.
|
//the field is attached to a division, it means there is another division with same name.
|
||||||
auto i = fields.find(name);
|
if (attached_field->attached)
|
||||||
if (fields.end() != i)
|
throw std::runtime_error("place, the name '" + name + "' is redefined.");
|
||||||
{
|
|
||||||
attached_field = i->second;
|
|
||||||
//the field is attached to a division, it means there is another division with same name.
|
|
||||||
if (attached_field->attached)
|
|
||||||
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,11 +150,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A Combox Implementation
|
* A Combox 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
|
||||||
@ -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;
|
||||||
|
@ -267,7 +267,7 @@ namespace nana{
|
|||||||
//When the group is resized, the drawing is called before moving the caption, but
|
//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.
|
//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.
|
//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& arg){
|
impl_->caption.events().move([this](const arg_move&){
|
||||||
if (align::left != impl_->caption_align)
|
if (align::left != impl_->caption_align)
|
||||||
API::refresh_window(*this);
|
API::refresh_window(*this);
|
||||||
});
|
});
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
@ -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]);
|
||||||
@ -5378,6 +5377,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)
|
||||||
{
|
{
|
||||||
@ -5388,6 +5388,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();
|
||||||
|
|
||||||
@ -5486,6 +5487,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();
|
||||||
@ -5532,29 +5534,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);
|
||||||
|
|
||||||
@ -5566,27 +5573,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)
|
||||||
{
|
{
|
||||||
@ -5597,11 +5609,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();
|
||||||
@ -5625,6 +5639,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();
|
||||||
@ -5639,6 +5654,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();
|
||||||
@ -5663,6 +5679,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();
|
||||||
@ -5671,6 +5688,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);
|
||||||
@ -5720,6 +5739,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();
|
||||||
|
|
||||||
@ -5742,48 +5762,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();
|
||||||
}
|
}
|
||||||
@ -5795,6 +5824,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();
|
||||||
}
|
}
|
||||||
@ -5827,6 +5857,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;
|
||||||
@ -5834,6 +5865,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();
|
||||||
}
|
}
|
||||||
|
@ -498,41 +498,42 @@ 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] };
|
||||||
|
|
||||||
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
|
if (!text.empty())
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
int * dx = new int[text.size()];
|
|
||||||
SIZE 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]);
|
|
||||||
|
|
||||||
for (std::size_t i = 1; i < text.size(); ++i)
|
|
||||||
{
|
{
|
||||||
pxbuf[i] = (text[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]);
|
unsigned tab_pixels = impl_->handle->string.tab_length * impl_->handle->string.whitespace_pixels;
|
||||||
}
|
#if defined(NANA_WINDOWS)
|
||||||
delete[] dx;
|
int * dx = new int[text.size()];
|
||||||
|
SIZE extents;
|
||||||
|
::GetTextExtentExPoint(impl_->handle->context, text.data(), static_cast<int>(text.size()), 0, 0, dx, &extents);
|
||||||
|
|
||||||
|
pxbuf[0] = (text[0] == '\t' ? tab_pixels : dx[0]);
|
||||||
|
|
||||||
|
for (std::size_t i = 1; i < text.size(); ++i)
|
||||||
|
{
|
||||||
|
pxbuf[i] = (text[i] == '\t' ? tab_pixels : dx[i] - dx[i - 1]);
|
||||||
|
}
|
||||||
|
delete[] dx;
|
||||||
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
#elif defined(NANA_X11) && defined(NANA_USE_XFT)
|
||||||
|
|
||||||
auto disp = nana::detail::platform_spec::instance().open_display();
|
auto disp = nana::detail::platform_spec::instance().open_display();
|
||||||
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')
|
|
||||||
{
|
{
|
||||||
FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]);
|
if (text[i] != '\t')
|
||||||
::XftGlyphExtents(disp, xft, &glyphs, 1, &extents);
|
{
|
||||||
pxbuf[i] = extents.xOff;
|
FT_UInt glyphs = ::XftCharIndex(disp, xft, text[i]);
|
||||||
|
::XftGlyphExtents(disp, xft, &glyphs, 1, &extents);
|
||||||
|
pxbuf[i] = extents.xOff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pxbuf[i] = tab_pixels;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user