Merge branch 'hotfix-1.7.2' into develop
This commit is contained in:
@@ -622,6 +622,7 @@ namespace detail
|
||||
}
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
++(root_runtime->x11msg.config);
|
||||
if(msgwnd->dimension.width != static_cast<unsigned>(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast<unsigned>(xevent.xconfigure.height))
|
||||
{
|
||||
auto & cf = xevent.xconfigure;
|
||||
@@ -890,7 +891,12 @@ namespace detail
|
||||
case MapNotify:
|
||||
case UnmapNotify:
|
||||
if(xevent.type == MapNotify)
|
||||
{
|
||||
++(root_runtime->x11msg.map);
|
||||
x11_apply_exposed_position(native_window);
|
||||
}
|
||||
else
|
||||
++(root_runtime->x11msg.unmap);
|
||||
|
||||
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
||||
context.platform.motion_window = nullptr;
|
||||
|
||||
@@ -173,15 +173,22 @@ namespace detail
|
||||
|
||||
static LRESULT WINAPI Bedrock_WIN32_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
HINSTANCE windows_module_handle()
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
static int dummy;
|
||||
VirtualQuery(&dummy, &mbi, sizeof(mbi));
|
||||
return reinterpret_cast<HINSTANCE>(mbi.AllocationBase);
|
||||
}
|
||||
|
||||
bedrock::bedrock()
|
||||
: pi_data_(new pi_data),
|
||||
impl_(new private_impl)
|
||||
{
|
||||
nana::detail::platform_spec::instance(); //to guaranty the platform_spec object is initialized before using.
|
||||
|
||||
|
||||
WNDCLASSEX wincl;
|
||||
wincl.hInstance = ::GetModuleHandle(0);
|
||||
wincl.hInstance = windows_module_handle();
|
||||
wincl.lpszClassName = L"NanaWindowInternal";
|
||||
wincl.lpfnWndProc = &Bedrock_WIN32_WindowProc;
|
||||
wincl.style = CS_DBLCLKS | CS_OWNDC;
|
||||
@@ -229,6 +236,8 @@ namespace detail
|
||||
|
||||
delete impl_;
|
||||
delete pi_data_;
|
||||
|
||||
::UnregisterClass(L"NanaWindowInternal", windows_module_handle());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef NANA_X11
|
||||
# include <atomic>
|
||||
#endif
|
||||
|
||||
namespace nana{
|
||||
namespace detail
|
||||
{
|
||||
@@ -75,6 +79,15 @@ namespace nana{
|
||||
root_misc(root_misc&&);
|
||||
root_misc(basic_window * wd, unsigned width, unsigned height);
|
||||
~root_misc();
|
||||
|
||||
#ifdef NANA_X11
|
||||
struct x11msg_confirm
|
||||
{
|
||||
std::atomic<std::size_t> config{ 0 };
|
||||
std::atomic<std::size_t> map{ 0 };
|
||||
std::atomic<std::size_t> unmap{ 0 };
|
||||
}x11msg;
|
||||
#endif
|
||||
private:
|
||||
root_misc(const root_misc&) = delete;
|
||||
root_misc& operator=(const root_misc&) = delete;
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
#include <nana/gui/detail/window_manager.hpp>
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
#if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
#include <nana/std_mutex.hpp>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
#include <map>
|
||||
# if defined(STD_THREAD_NOT_SUPPORTED)
|
||||
# include <nana/std_mutex.hpp>
|
||||
# else
|
||||
# include <mutex>
|
||||
# endif
|
||||
# include <map>
|
||||
#elif defined(NANA_X11)
|
||||
#include <nana/system/platform.hpp>
|
||||
# include <nana/system/platform.hpp>
|
||||
# include "inner_fwd_implement.hpp"
|
||||
#endif
|
||||
|
||||
#include "../../paint/image_accessor.hpp"
|
||||
@@ -34,6 +35,10 @@ namespace nana{
|
||||
namespace detail{
|
||||
|
||||
#if defined(NANA_WINDOWS)
|
||||
|
||||
//This function is defined in bedrock_windows.cpp
|
||||
HINSTANCE windows_module_handle();
|
||||
|
||||
class tray_manager
|
||||
{
|
||||
struct window_extra_t
|
||||
@@ -199,26 +204,87 @@ namespace nana{
|
||||
|
||||
namespace x11_wait
|
||||
{
|
||||
struct param
|
||||
{
|
||||
Window handle;
|
||||
root_misc * misc;
|
||||
std::size_t comp_value;
|
||||
};
|
||||
|
||||
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
||||
{
|
||||
return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
|
||||
auto p = reinterpret_cast<param*>(arg);
|
||||
if(p)
|
||||
{
|
||||
if(p->misc->x11msg.config != p->comp_value)
|
||||
return true;
|
||||
|
||||
if(disp && evt && (evt->type == ConfigureNotify))
|
||||
{
|
||||
if(evt->xconfigure.window == p->handle)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bool map(Display *disp, XEvent *evt, char *arg)
|
||||
{
|
||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xmap.window == *reinterpret_cast<Window*>(arg));
|
||||
{
|
||||
auto p = reinterpret_cast<param*>(arg);
|
||||
if(p)
|
||||
{
|
||||
if(p->misc->x11msg.map != p->comp_value)
|
||||
return true;
|
||||
|
||||
if(disp && evt && (evt->type == MapNotify))
|
||||
{
|
||||
if(evt->xmap.window == p->handle)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bool unmap(Display *disp, XEvent *evt, char *arg)
|
||||
{
|
||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xunmap.window == *reinterpret_cast<Window*>(arg));
|
||||
{
|
||||
auto p = reinterpret_cast<param*>(arg);
|
||||
if(p)
|
||||
{
|
||||
if(p->misc->x11msg.unmap != p->comp_value)
|
||||
return true;
|
||||
|
||||
if(disp && evt && (evt->type == UnmapNotify))
|
||||
{
|
||||
if(evt->xunmap.window == p->handle)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*))
|
||||
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*), std::size_t comp_value)
|
||||
{
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||
x11_wait::param p;
|
||||
p.handle = wd;
|
||||
p.misc = misc;
|
||||
|
||||
if(pred_fn == &x11_wait::configure)
|
||||
p.comp_value = misc->x11msg.config;
|
||||
else if(pred_fn == &x11_wait::map)
|
||||
p.comp_value = misc->x11msg.map;
|
||||
else if(pred_fn == &x11_wait::unmap)
|
||||
p.comp_value = misc->x11msg.unmap;
|
||||
|
||||
//Checks whether the msg is received.
|
||||
if(p.comp_value != comp_value)
|
||||
return;
|
||||
|
||||
p.comp_value = comp_value;
|
||||
|
||||
XEvent dummy;
|
||||
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&wd));
|
||||
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&p));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -315,7 +381,7 @@ namespace nana{
|
||||
HWND native_wd = ::CreateWindowEx(style_ex, L"NanaWindowInternal", L"Nana Window",
|
||||
style,
|
||||
pt.x, pt.y, 100, 100,
|
||||
reinterpret_cast<HWND>(owner), 0, ::GetModuleHandle(0), 0);
|
||||
reinterpret_cast<HWND>(owner), 0, windows_module_handle(), 0);
|
||||
|
||||
//A window may have a border, this should be adjusted the client area fit for the specified size.
|
||||
::RECT client;
|
||||
@@ -504,7 +570,7 @@ namespace nana{
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||
r.x, r.y, r.width, r.height,
|
||||
reinterpret_cast<HWND>(parent), // The window is a child-window to desktop
|
||||
0, ::GetModuleHandle(0), 0);
|
||||
0, windows_module_handle(), 0);
|
||||
#elif defined(NANA_X11)
|
||||
nana::detail::platform_scope_guard psg;
|
||||
|
||||
@@ -758,13 +824,17 @@ namespace nana{
|
||||
if(show == is_window_visible(wd))
|
||||
return;
|
||||
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(wd);
|
||||
|
||||
if(show)
|
||||
{
|
||||
std::size_t cmp_value = misc->x11msg.map;
|
||||
|
||||
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
|
||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||
//the followed window_visible() call can return the updated visibility value.
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map);
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map, cmp_value);
|
||||
|
||||
Window grab = restrict::spec.grab(0);
|
||||
if(grab == reinterpret_cast<Window>(wd))
|
||||
@@ -772,10 +842,12 @@ namespace nana{
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t cmp_value = misc->x11msg.unmap;
|
||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
|
||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||
//the followed window_visible() call can return the updated visibility value.
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap);
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap, cmp_value);
|
||||
}
|
||||
}
|
||||
static_cast<void>(active); //eliminate unused parameter compiler warning.
|
||||
@@ -1019,11 +1091,15 @@ namespace nana{
|
||||
y += origin_y;
|
||||
}
|
||||
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||
std::size_t cmp_value = misc->x11msg.config;
|
||||
|
||||
::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);
|
||||
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1109,6 +1185,9 @@ namespace nana{
|
||||
y += origin_y;
|
||||
}
|
||||
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||
std::size_t cmp_value = misc->x11msg.config;
|
||||
|
||||
::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
|
||||
@@ -1116,7 +1195,7 @@ namespace nana{
|
||||
|
||||
//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);
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
@@ -1283,11 +1362,15 @@ namespace nana{
|
||||
hints.min_height = hints.max_height = sz.height;
|
||||
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
||||
}
|
||||
|
||||
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||
std::size_t cmp_value = misc->x11msg.config;
|
||||
|
||||
::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);
|
||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1516,14 +1516,24 @@ namespace nana
|
||||
|
||||
path_type parent_path{ str };
|
||||
str += (len + 1);
|
||||
|
||||
while(*str)
|
||||
|
||||
// if only one file was selected, the ofn.lpstrFile
|
||||
// is returning only that file, without any parent
|
||||
if (!*str)
|
||||
{
|
||||
len = ::wcslen(str);
|
||||
targets.emplace_back(parent_path / path_type{str});
|
||||
str += (len + 1);
|
||||
targets.emplace_back(parent_path);
|
||||
impl_->path = parent_path.parent_path().u8string();
|
||||
}
|
||||
else
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
len = ::wcslen(str);
|
||||
targets.emplace_back(parent_path / path_type{str});
|
||||
str += (len + 1);
|
||||
}
|
||||
impl_->path = parent_path.u8string();
|
||||
}
|
||||
impl_->path = parent_path.u8string();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -146,7 +146,8 @@ namespace nana
|
||||
|
||||
//draw caption
|
||||
auto text = to_wstring(API::window_caption(window_handle_));
|
||||
text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, paint::text_renderer::mode::truncate_with_ellipsis);
|
||||
if((graph.size().width > 20) && (graph.size().width - 20 > 10))
|
||||
text_rd_->render({ 3, 1 }, text.data(), text.size(), graph.size().width - 20, paint::text_renderer::mode::truncate_with_ellipsis);
|
||||
|
||||
//draw x button
|
||||
auto r = _m_button_area();
|
||||
|
||||
@@ -111,13 +111,13 @@ namespace nana
|
||||
{
|
||||
public:
|
||||
#if defined(NANA_WINDOWS)
|
||||
timer_core(timer* sender, timer_identifier tmid, basic_event<arg_elapse>& evt_elapse):
|
||||
timer_core(timer* sender, timer_identifier tmid, std::shared_ptr<basic_event<arg_elapse>> evt_elapse):
|
||||
sender_(sender),
|
||||
timer_(tmid),
|
||||
evt_elapse_(evt_elapse)
|
||||
{}
|
||||
#else
|
||||
timer_core(timer* sender, basic_event<arg_elapse>& evt_elapse):
|
||||
timer_core(timer* sender, std::shared_ptr<basic_event<arg_elapse>> evt_elapse):
|
||||
sender_(sender),
|
||||
timer_(this),
|
||||
evt_elapse_(evt_elapse)
|
||||
@@ -142,12 +142,15 @@ namespace nana
|
||||
{
|
||||
arg_elapse arg;
|
||||
arg.sender = sender_;
|
||||
evt_elapse_.emit(arg, nullptr);
|
||||
|
||||
//retain the object to avoid it to be deleted during calling of emit
|
||||
auto retain = evt_elapse_;
|
||||
retain->emit(arg, nullptr);
|
||||
}
|
||||
private:
|
||||
timer * const sender_;
|
||||
const timer_identifier timer_;
|
||||
nana::basic_event<arg_elapse> & evt_elapse_;
|
||||
std::shared_ptr<nana::basic_event<arg_elapse>> evt_elapse_;
|
||||
}; //end class timer_core
|
||||
|
||||
|
||||
@@ -175,8 +178,9 @@ namespace nana
|
||||
};
|
||||
|
||||
//class timer
|
||||
timer::timer()
|
||||
: impl_(new implement)
|
||||
timer::timer():
|
||||
elapse_(std::make_shared<nana::basic_event<arg_elapse>>()),
|
||||
impl_(new implement)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -195,7 +199,7 @@ namespace nana
|
||||
void timer::reset()
|
||||
{
|
||||
stop();
|
||||
elapse_.clear();
|
||||
elapse_->clear();
|
||||
}
|
||||
|
||||
void timer::start()
|
||||
|
||||
@@ -2314,7 +2314,8 @@ namespace nana
|
||||
size_type count_of_exposed(bool with_rest) const
|
||||
{
|
||||
auto lister_s = this->content_view->view_area().height;
|
||||
return (lister_s / item_height()) + (with_rest && (lister_s % item_height()) ? 1 : 0);
|
||||
return (lister_s / item_height()) + (with_rest &&
|
||||
listbox_ptr->scroll_operation()->visible(true) && (lister_s % item_height()) ? 1 : 0);
|
||||
}
|
||||
|
||||
void update(bool ignore_auto_draw = false) noexcept
|
||||
@@ -3338,16 +3339,27 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
// init ir end to grab a header
|
||||
void grab(const nana::point& pos, bool is_grab)
|
||||
{
|
||||
if(is_grab)
|
||||
if(is_grab) // init grabbing the header
|
||||
{
|
||||
grabs_.start_pos = pos.x;
|
||||
if(grabs_.splitter != npos) // resize header item, not move it
|
||||
grabs_.item_width = essence_->header.at(grabs_.splitter).width_px;
|
||||
if(grabs_.splitter == npos) // No splitter, no resize header, just moving
|
||||
return;
|
||||
|
||||
// splitter grabbed - resize the header: take initial width
|
||||
grabs_.item_width = essence_->header.at(grabs_.splitter).width_px;
|
||||
}
|
||||
else if((grab_terminal_.index != npos) && (grab_terminal_.index != essence_->pointer_where.second))
|
||||
essence_->header.move(essence_->pointer_where.second, grab_terminal_.index, grab_terminal_.place_front);
|
||||
else // end to grab the header
|
||||
if (grabs_.splitter != npos) // some Splitter grab, just resizing, no need to move
|
||||
return;
|
||||
else if( (grab_terminal_.index != npos)
|
||||
&& (grab_terminal_.index != essence_->pointer_where.second) )
|
||||
// move header to terminal position
|
||||
essence_->header.move(essence_->pointer_where.second, // from
|
||||
grab_terminal_.index, // to
|
||||
grab_terminal_.place_front);
|
||||
}
|
||||
|
||||
//grab_move
|
||||
@@ -4295,7 +4307,10 @@ namespace nana
|
||||
auto const good_list_r = essence_->rect_lister(list_r);
|
||||
|
||||
auto & ptr_where = essence_->pointer_where;
|
||||
if((ptr_where.first == parts::header) && (ptr_where.second != npos || (drawer_header_->splitter() != npos)))
|
||||
|
||||
if( (ptr_where.first == parts::header) // click on header
|
||||
&& ( ptr_where.second != npos // in ..
|
||||
|| (drawer_header_->splitter() != npos))) // or splitter
|
||||
{
|
||||
essence_->ptr_state = item_state::pressed;
|
||||
if(good_head_r)
|
||||
@@ -4304,7 +4319,8 @@ namespace nana
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
else if(ptr_where.first == parts::list || ptr_where.first == parts::checker)
|
||||
else if( ptr_where.first == parts::list // click on list
|
||||
|| ptr_where.first == parts::checker) // on a checker
|
||||
{
|
||||
index_pair item_pos = lister.advance(essence_->first_display(), static_cast<int>(ptr_where.second));
|
||||
|
||||
@@ -4477,13 +4493,16 @@ namespace nana
|
||||
bool need_refresh = false;
|
||||
|
||||
//Don't sort the column when the mouse is due to released for stopping resizing column.
|
||||
if ((drawer_header_->splitter() == npos) && essence_->header.attrib().sortable && essence_->pointer_where.first == parts::header && prev_state == item_state::pressed)
|
||||
if ( (drawer_header_->splitter() == npos) // no header splitter was selected
|
||||
&& essence_->header.attrib().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())
|
||||
need_refresh = essence_->lister.sort_column(essence_->pointer_where.second, nullptr);
|
||||
}
|
||||
else if (item_state::grabbed == prev_state)
|
||||
else if (item_state::grabbed == prev_state) // selected splitter and grabbed
|
||||
{
|
||||
nana::point pos = arg.pos;
|
||||
essence_->widget_to_header(pos);
|
||||
@@ -6095,7 +6114,15 @@ namespace nana
|
||||
|
||||
auto listbox::last_visible() const -> index_pair
|
||||
{
|
||||
return _m_ess().lister.advance(_m_ess().first_display(), static_cast<int>(_m_ess().count_of_exposed(true)));
|
||||
if(!const_cast<listbox*>(this)->scroll_operation()->visible(true))
|
||||
{
|
||||
auto last_cat = size_categ()-1;
|
||||
index_pair ip(last_cat, at(last_cat).size()-1);
|
||||
if(last_cat == 0 && ip.item == npos) // if the listbox is empty
|
||||
ip.cat = npos; // return empty index_pair
|
||||
return ip;
|
||||
}
|
||||
return _m_ess().lister.advance(_m_ess().first_display(), static_cast<int>(_m_ess().count_of_exposed(true)-1));
|
||||
}
|
||||
|
||||
auto listbox::visibles() const -> index_pairs
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace nana
|
||||
delete ptr;
|
||||
|
||||
cont_.clear();
|
||||
right_ = npos;
|
||||
}
|
||||
|
||||
|
||||
@@ -683,6 +684,7 @@ namespace nana
|
||||
if(m && (m->textout != show))
|
||||
{
|
||||
m->textout = show;
|
||||
m->pixels = 0; //force width calculation
|
||||
API::refresh_window(this->handle());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user