From d780907258a11d49ad43ecc54bc3c2767fb43206 Mon Sep 17 00:00:00 2001 From: Ariel Vina-Rodriguez Date: Tue, 30 Jul 2019 15:48:14 +0200 Subject: [PATCH 01/15] nana master points to nana-demo master --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 82604edf..e81bb117 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ matrix: before_install: - cd .. - - git clone --depth=1 --branch=develop https://github.com/qPCR4vir/nana-demo.git nana-demo + - git clone --depth=1 --branch=master https://github.com/qPCR4vir/nana-demo.git nana-demo - export PATH="$HOME/bin:$PATH" - wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.12/cmake-3.12.0-rc3-Linux-x86_64.sh || true - chmod -R +x /tmp/tools From 1b0ac1047562a14ced6d4f46cdef057f5b952880 Mon Sep 17 00:00:00 2001 From: ErrorFlynn Date: Mon, 5 Aug 2019 14:11:02 -0400 Subject: [PATCH 02/15] fixes for the listbox bugs described in issue #472 --- source/gui/widgets/listbox.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 7201af43..2a984cf5 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -2300,7 +2300,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 @@ -6062,7 +6063,15 @@ namespace nana auto listbox::last_visible() const -> index_pair { - return _m_ess().lister.advance(_m_ess().first_display(), static_cast(_m_ess().count_of_exposed(true))); + if(!const_cast(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(_m_ess().count_of_exposed(true)-1)); } auto listbox::visibles() const -> index_pairs From c8e1aace1ae7f300ef7ed8b8e841181e7f99b48e Mon Sep 17 00:00:00 2001 From: Yuchen Deng Date: Sun, 11 Aug 2019 15:44:35 +0800 Subject: [PATCH 03/15] On macOS and FreeBSD libc++ is the default standard library and the -stdlib=libc++ is not required. https://libcxx.llvm.org/docs/UsingLibcxx.html --- build/cmake/compilers.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build/cmake/compilers.cmake b/build/cmake/compilers.cmake index c8db4976..07729e3c 100644 --- a/build/cmake/compilers.cmake +++ b/build/cmake/compilers.cmake @@ -38,13 +38,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AN endif() -if (APPLE AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # APPLE Clang - target_compile_options(nana PUBLIC -stdlib=libstdc++) -endif () - - if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") target_compile_options(nana PRIVATE -fmax-errors=3) endif() - From 050742a9209c1eaebacf78fc456c20e08ee4f8dd Mon Sep 17 00:00:00 2001 From: ErrorFlynn Date: Mon, 5 Aug 2019 14:11:02 -0400 Subject: [PATCH 04/15] fixes for the listbox bugs described in issue #472 --- source/gui/widgets/listbox.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 41347095..2db0e5ab 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -2308,7 +2308,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 @@ -6073,7 +6074,15 @@ namespace nana auto listbox::last_visible() const -> index_pair { - return _m_ess().lister.advance(_m_ess().first_display(), static_cast(_m_ess().count_of_exposed(true))); + if(!const_cast(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(_m_ess().count_of_exposed(true)-1)); } auto listbox::visibles() const -> index_pairs From 0f1b5edc409ad9871f1d7a46ee45f9a46f21ff4a Mon Sep 17 00:00:00 2001 From: Yuchen Deng Date: Mon, 12 Aug 2019 21:03:59 +0800 Subject: [PATCH 05/15] fix compatibility on macOS --- include/nana/c++defines.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nana/c++defines.hpp b/include/nana/c++defines.hpp index 4f00e5f9..4dc62a65 100644 --- a/include/nana/c++defines.hpp +++ b/include/nana/c++defines.hpp @@ -89,7 +89,7 @@ #define NANA_MINGW #endif // MINGW -#elif defined(APPLE) //Mac OS X +#elif defined(__APPLE__) || defined(APPLE) //Mac OS X //Symbols for MACOS #define NANA_MACOS #define NANA_POSIX @@ -252,7 +252,7 @@ # if __has_include() # undef STD_FILESYSTEM_NOT_SUPPORTED # endif -# if __has_include() +# if __has_include() # if !(defined(NANA_MINGW) && !defined(_GLIBCXX_HAS_GTHREADS)) //See the comment above regarding MinGW's threading support # undef STD_THREAD_NOT_SUPPORTED From e37cc5ec3738395dcbe4c1b3268e08ad24ab97fa Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 14 Aug 2019 03:39:26 +0800 Subject: [PATCH 06/15] fix crash where a shared lib is loaded/unloaded repeatedly When a shared lib which uses nana is dynamic loaded/unloaded multiple times, the crash would occur when creating a form after reloading the shared lib --- source/gui/detail/bedrock_windows.cpp | 13 +++++++++++-- source/gui/detail/native_window_interface.cpp | 8 ++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index d05a6119..58044bb9 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -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(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()); } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index efe49d21..54404ceb 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -34,6 +34,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 @@ -315,7 +319,7 @@ namespace nana{ HWND native_wd = ::CreateWindowEx(style_ex, L"NanaWindowInternal", L"Nana Window", style, pt.x, pt.y, 100, 100, - reinterpret_cast(owner), 0, ::GetModuleHandle(0), 0); + reinterpret_cast(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 +508,7 @@ namespace nana{ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS, r.x, r.y, r.width, r.height, reinterpret_cast(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; From 942c6a4b48e38277803d3fc771fa4db19545699f Mon Sep 17 00:00:00 2001 From: dnso86 <7543050+dnso86@users.noreply.github.com> Date: Wed, 28 Aug 2019 10:42:10 +0200 Subject: [PATCH 07/15] Fixing incorrect buffer in WideCharToMultiByte call in wc2mb --- source/charset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/charset.cpp b/source/charset.cpp index 4ea53570..7ccafec3 100644 --- a/source/charset.cpp +++ b/source/charset.cpp @@ -246,7 +246,7 @@ namespace nana if(bytes > 1) { mbstr.resize(bytes - 1); - ::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes - 1, 0, 0); + ::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes, 0, 0); } return true; #else From 6d625a11e09ea940ea7d26644f0975f263ad36c5 Mon Sep 17 00:00:00 2001 From: dnso86 <7543050+dnso86@users.noreply.github.com> Date: Fri, 30 Aug 2019 14:27:49 +0200 Subject: [PATCH 08/15] Fixing incorrect buffer in MultiByteToWideChar call in wc2mb --- source/charset.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/charset.cpp b/source/charset.cpp index 7ccafec3..4188b418 100644 --- a/source/charset.cpp +++ b/source/charset.cpp @@ -280,7 +280,7 @@ namespace nana if(chars > 1) { wcstr.resize(chars - 1); - ::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars - 1); + ::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars); } #else locale_initializer::init(); From 8323064efceb2ac581983d569ee96fa39f5d6a80 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sun, 1 Sep 2019 18:49:19 +0800 Subject: [PATCH 09/15] improve the timer that it can be deleted in elapse handler --- include/nana/gui/timer.hpp | 4 ++-- source/gui/timer.cpp | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/include/nana/gui/timer.hpp b/include/nana/gui/timer.hpp index c360884b..0f28116e 100644 --- a/include/nana/gui/timer.hpp +++ b/include/nana/gui/timer.hpp @@ -48,7 +48,7 @@ namespace nana template void elapse(Function && fn) { - elapse_.connect(std::forward(fn)); + elapse_->connect(std::forward(fn)); } void reset(); @@ -66,7 +66,7 @@ namespace nana private: unsigned _m_interval() const; private: - nana::basic_event elapse_; + std::shared_ptr> elapse_; implement * const impl_; }; }//end namespace nana diff --git a/source/gui/timer.cpp b/source/gui/timer.cpp index 8374a5fb..5e0e75bb 100644 --- a/source/gui/timer.cpp +++ b/source/gui/timer.cpp @@ -111,13 +111,13 @@ namespace nana { public: #if defined(NANA_WINDOWS) - timer_core(timer* sender, timer_identifier tmid, basic_event& evt_elapse): + timer_core(timer* sender, timer_identifier tmid, std::shared_ptr> evt_elapse): sender_(sender), timer_(tmid), evt_elapse_(evt_elapse) {} #else - timer_core(timer* sender, basic_event& evt_elapse): + timer_core(timer* sender, std::shared_ptr> 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 & evt_elapse_; + std::shared_ptr> 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>()), + impl_(new implement) { } @@ -195,7 +199,7 @@ namespace nana void timer::reset() { stop(); - elapse_.clear(); + elapse_->clear(); } void timer::start() From 7c442360ba95b53e241e951960ba0a7faef743ad Mon Sep 17 00:00:00 2001 From: Zaha Mihai <1395028+mihaizh@users.noreply.github.com> Date: Sun, 1 Sep 2019 17:53:23 +0300 Subject: [PATCH 10/15] Fix inconsistency regarding filebox multi_select When only one file is selected, the lpstrFile variable contains only the path to that file, without the parent path before that, thus, the targets vector is empty and the path variable contains the actual path to the file. This is inconsistent with the scenario where multiple files are selected, in which targets contains the file paths and path contains the parent directory path. --- source/gui/filebox.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/source/gui/filebox.cpp b/source/gui/filebox.cpp index 06dfed84..f2417087 100644 --- a/source/gui/filebox.cpp +++ b/source/gui/filebox.cpp @@ -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 { From 66d038dbe3e8ab181fae689c9e1b145143d7caa6 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Mon, 2 Sep 2019 05:24:06 +0800 Subject: [PATCH 11/15] small improvement --- source/charset.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/charset.cpp b/source/charset.cpp index dd182f85..d9a0b0e0 100644 --- a/source/charset.cpp +++ b/source/charset.cpp @@ -1,7 +1,7 @@ /** * A Character Encoding Set Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -245,8 +245,12 @@ namespace nana int bytes = ::WideCharToMultiByte(CP_ACP, 0, s, -1, 0, 0, 0, 0); if(bytes > 1) { - mbstr.resize(bytes - 1); + // the bytes is the length of the string with null character. + mbstr.resize(bytes); ::WideCharToMultiByte(CP_ACP, 0, s, -1, &(mbstr[0]), bytes, 0, 0); + + //Remove the null character written by WideCharToMultiByte + mbstr.pop_back(); } return true; #else @@ -279,8 +283,12 @@ namespace nana int chars = ::MultiByteToWideChar(CP_ACP, 0, s, -1, 0, 0); if(chars > 1) { - wcstr.resize(chars - 1); + // the length of the string with null character. + wcstr.resize(chars); ::MultiByteToWideChar(CP_ACP, 0, s, -1, &wcstr[0], chars); + + // remove the null character written by MultiByteToWideChar + wcstr.pop_back(); } #else locale_initializer::init(); From 4dd1c0c7ef72847e83f42905e1ef064f196c7ae5 Mon Sep 17 00:00:00 2001 From: besh81 Date: Thu, 5 Sep 2019 17:37:40 +0200 Subject: [PATCH 12/15] dock_pane and toolbar bug fix fixed bug in dock_pane caption drawing function (used a workaround that hide the caption when the dock_pane width become too small) fixed small bug in toolbar --- source/gui/place_parts.hpp | 3 ++- source/gui/widgets/toolbar.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/gui/place_parts.hpp b/source/gui/place_parts.hpp index 85ef8dfe..8570c6b0 100644 --- a/source/gui/place_parts.hpp +++ b/source/gui/place_parts.hpp @@ -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(); diff --git a/source/gui/widgets/toolbar.cpp b/source/gui/widgets/toolbar.cpp index f8db43c4..7d1d18f4 100644 --- a/source/gui/widgets/toolbar.cpp +++ b/source/gui/widgets/toolbar.cpp @@ -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()); } } From 06ba591b6645ba948423025291fd0b8d82aa603a Mon Sep 17 00:00:00 2001 From: qPCR4vir Date: Mon, 9 Sep 2019 17:23:22 +0200 Subject: [PATCH 13/15] FIX old bug during resizing of header, when next column spring to second position --- source/gui/widgets/listbox.cpp | 36 +++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/source/gui/widgets/listbox.cpp b/source/gui/widgets/listbox.cpp index 2db0e5ab..16907610 100644 --- a/source/gui/widgets/listbox.cpp +++ b/source/gui/widgets/listbox.cpp @@ -3317,16 +3317,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 @@ -4274,7 +4285,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) @@ -4283,7 +4297,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(ptr_where.second)); @@ -4456,13 +4471,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); From 02676e9c752c59a0ccfd536020375808b61e6cdb Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 11 Sep 2019 00:07:07 +0800 Subject: [PATCH 14/15] fix missing weakly_canonical on GCC 7.3 --- include/nana/filesystem/filesystem.hpp | 4 ++-- source/filesystem/filesystem.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nana/filesystem/filesystem.hpp b/include/nana/filesystem/filesystem.hpp index 36f8776d..8aab0cea 100644 --- a/include/nana/filesystem/filesystem.hpp +++ b/include/nana/filesystem/filesystem.hpp @@ -560,7 +560,7 @@ namespace std { #endif } } // std -#else +#else //#if NANA_USING_NANA_FILESYSTEM //Implements the missing functions for various version of experimental/filesystem namespace std { @@ -568,7 +568,7 @@ namespace std { { //Visual Studio 2017 #if (defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) && defined(_MSC_VER) && (_MSC_VER > 1912)) || \ - (!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603)) + (!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603 || (__GNUC__* 100 + __GNUC_MINOR__ < 801))) path weakly_canonical(const path& p); path weakly_canonical(const path& p, std::error_code& err); #endif diff --git a/source/filesystem/filesystem.cpp b/source/filesystem/filesystem.cpp index ae812104..bcd5957c 100644 --- a/source/filesystem/filesystem.cpp +++ b/source/filesystem/filesystem.cpp @@ -1407,7 +1407,7 @@ namespace std namespace filesystem { #if (defined(NANA_USING_STD_EXPERIMENTAL_FILESYSTEM) && defined(_MSC_VER) && (_MSC_VER > 1912)) || \ - (!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603)) + (!defined(__clang__) && defined(__GNUC__) && (__cplusplus < 201603 || (__GNUC__* 100 + __GNUC_MINOR__ < 801))) namespace detail { From 0f66b0cb26468cfd8510744724b8c5d56044564a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 11 Sep 2019 00:10:11 +0800 Subject: [PATCH 15/15] improve wait of x11 event to avoid blocking --- source/gui/detail/bedrock_posix.cpp | 6 + source/gui/detail/inner_fwd_implement.hpp | 13 ++ source/gui/detail/native_window_interface.cpp | 117 +++++++++++++++--- 3 files changed, 117 insertions(+), 19 deletions(-) diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index b3ed3fb4..23f55fa8 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -622,6 +622,7 @@ namespace detail } break; case ConfigureNotify: + ++(root_runtime->x11msg.config); if(msgwnd->dimension.width != static_cast(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast(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; diff --git a/source/gui/detail/inner_fwd_implement.hpp b/source/gui/detail/inner_fwd_implement.hpp index af246905..a46d51eb 100644 --- a/source/gui/detail/inner_fwd_implement.hpp +++ b/source/gui/detail/inner_fwd_implement.hpp @@ -21,6 +21,10 @@ #include +#ifdef NANA_X11 +# include +#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 config{ 0 }; + std::atomic map{ 0 }; + std::atomic unmap{ 0 }; + }x11msg; +#endif private: root_misc(const root_misc&) = delete; root_misc& operator=(const root_misc&) = delete; diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index 54404ceb..3804b7e6 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -17,14 +17,15 @@ #include #if defined(NANA_WINDOWS) - #if defined(STD_THREAD_NOT_SUPPORTED) - #include - #else - #include - #endif - #include +# if defined(STD_THREAD_NOT_SUPPORTED) +# include +# else +# include +# endif +# include #elif defined(NANA_X11) - #include +# include +# include "inner_fwd_implement.hpp" #endif #include "../../paint/image_accessor.hpp" @@ -203,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(arg)); + auto p = reinterpret_cast(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(arg)); + { + auto p = reinterpret_cast(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(arg)); + { + auto p = reinterpret_cast(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(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(&wd)); + ::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast(&p)); } #endif @@ -762,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(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(wd), x11_wait::map); + x11_wait_for(reinterpret_cast(wd), x11_wait::map, cmp_value); Window grab = restrict::spec.grab(0); if(grab == reinterpret_cast(wd)) @@ -776,10 +842,12 @@ namespace nana{ } else { + std::size_t cmp_value = misc->x11msg.unmap; ::XUnmapWindow(disp, reinterpret_cast(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(wd), x11_wait::unmap); + x11_wait_for(reinterpret_cast(wd), x11_wait::unmap, cmp_value); } } static_cast(active); //eliminate unused parameter compiler warning. @@ -1023,11 +1091,15 @@ namespace nana{ y += origin_y; } + auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast(wd)); + std::size_t cmp_value = misc->x11msg.config; + ::XMoveWindow(disp, reinterpret_cast(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(wd), x11_wait::configure); + + x11_wait_for(reinterpret_cast(wd), x11_wait::configure, cmp_value); #endif } @@ -1113,6 +1185,9 @@ namespace nana{ y += origin_y; } + auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast(wd)); + std::size_t cmp_value = misc->x11msg.config; + ::XMoveResizeWindow(disp, reinterpret_cast(wd), x, y, r.width, r.height); //Wait for the configuration notify to update the local attribute of position so that @@ -1120,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(wd), x11_wait::configure); + x11_wait_for(reinterpret_cast(wd), x11_wait::configure, cmp_value); return true; #endif @@ -1287,11 +1362,15 @@ namespace nana{ hints.min_height = hints.max_height = sz.height; ::XSetWMNormalHints(disp, reinterpret_cast(wd), &hints); } + + auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast(wd)); + std::size_t cmp_value = misc->x11msg.config; + ::XResizeWindow(disp, reinterpret_cast(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(wd), x11_wait::configure); + x11_wait_for(reinterpret_cast(wd), x11_wait::configure, cmp_value); return true; #endif }