From bb47cdc6c9711c366f2fc5bd7e369ad2eab9f2fc Mon Sep 17 00:00:00 2001 From: cnjinhao Date: Fri, 22 Sep 2017 15:47:12 +0800 Subject: [PATCH 1/8] fix bug that DEL key is incorrect in key_press/key_release(#259) --- include/nana/gui/basis.hpp | 6 ++++-- source/gui/detail/bedrock_posix.cpp | 4 ++-- source/gui/detail/bedrock_windows.cpp | 17 +++++++++++++++-- source/gui/widgets/skeletons/text_editor.cpp | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index a13b3bac..69b97c1f 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -91,6 +91,8 @@ namespace nana substitute = 0x1A, //Ctrl+Z escape = 0x1B, space = 0x20, //Space + del = 0x7F, //Delete + os_del = del, //Deprecated //The following names are intuitive name of ASCII control codes select_all = start_of_headline, @@ -106,8 +108,8 @@ namespace nana os_ctrl = 0x11, os_pageup = 0x21, os_pagedown, os_arrow_left = 0x25, os_arrow_up, os_arrow_right, os_arrow_down, - os_insert = 0x2D, os_del , - os_end = 0x23 , os_home //Pos 1 + os_insert = 0x2D, + os_end = 0x23, os_home //Pos 1 }; }; diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 9b0e24e0..4e7c8a07 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -438,8 +438,8 @@ namespace detail keysym = keyboard::os_arrow_left + (keysym - XK_Left); break; case XK_Insert: keysym = keyboard::os_insert; break; - case XK_Delete: - keysym = keyboard::os_del; break; + case XK_Delete: case XK_KP_Delete: + keysym = keyboard::del; break; case XK_Shift_L: case XK_Shift_R: //shift keysym = keyboard::os_shift; break; case XK_Control_L: case XK_Control_R: //ctrl diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index ebf32705..67f40ffe 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -775,6 +775,19 @@ namespace detail if (thrd) thrd->event_window = prev_event_wd; } + //Translate OS Virtual-Key into ASCII code + wchar_t translate_virtual_key(WPARAM vkey) + { + switch (vkey) + { + case VK_DELETE: + return 127; + case VK_DECIMAL: + return 46; + } + return static_cast(vkey); + } + LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT window_proc_value = 0; @@ -1436,7 +1449,7 @@ namespace detail arg.evt_code = event_code::key_press; arg.window_handle = reinterpret_cast(msgwnd); arg.ignore = false; - arg.key = static_cast(wParam); + arg.key = translate_virtual_key(wParam); brock.get_key_state(arg); brock.emit(event_code::key_press, msgwnd, arg, true, &context); @@ -1522,7 +1535,7 @@ namespace detail arg_keyboard arg; arg.evt_code = event_code::key_release; arg.window_handle = reinterpret_cast(msgwnd); - arg.key = static_cast(wParam); + arg.key = translate_virtual_key(wParam); brock.get_key_state(arg); arg.ignore = false; brock.emit(event_code::key_release, msgwnd, arg, true, &context); diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 5688b2be..72cec7ee 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1233,7 +1233,7 @@ namespace nana{ namespace widgets case keyboard::os_pagedown: _m_handle_move_key(arg); break; - case keyboard::os_del: + case keyboard::del: // send delete to set_accept function if (this->attr().editable && (!impl_->capacities.pred_acceptive || impl_->capacities.pred_acceptive(key))) del(); From eec7344c6d11616b2198d8889e1e9ad29d7cb93a Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Sep 2017 07:25:16 +0800 Subject: [PATCH 2/8] fix issue that typing text for spinbox doesn't draw spin buttons border --- source/gui/widgets/skeletons/text_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 72cec7ee..fefaf1ed 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1689,7 +1689,7 @@ namespace nana{ namespace widgets impl_->try_refresh = sync_graph::refresh; //_m_put calcs the lines - _m_reset_content_size(false); + _m_reset_content_size(true); impl_->cview->sync(false); } } From 13761be5e9d83a8a49158efc1bb151e8d810b570 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 23 Sep 2017 07:33:31 +0800 Subject: [PATCH 3/8] fix crash where a menubar popups a menu and exits by shortcut(#261) --- source/gui/widgets/menubar.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/gui/widgets/menubar.cpp b/source/gui/widgets/menubar.cpp index a83c3d86..5071c094 100644 --- a/source/gui/widgets/menubar.cpp +++ b/source/gui/widgets/menubar.cpp @@ -403,8 +403,15 @@ namespace nana ess_->state.nullify_mouse = true; auto & menu_ptr = ess_->state.menu; + + //menu_wd will be assigned with the handle of a menu window, + //It is used for checking whether the menu is closed. A menu handler + //may close the form, checking with the data member of this trigger + //is invalid, because the form is closed, the object of menubar may not exist. + window menu_wd = nullptr; if(ess_->state.menu) { + menu_wd = menu_ptr->handle(); switch(arg.key) { case keyboard::os_arrow_down: @@ -466,8 +473,11 @@ namespace nana case keyboard::os_arrow_up: case keyboard::os_arrow_down: case keyboard::enter: - if(ess_->open_menu(true)) + if (ess_->open_menu(true)) + { + menu_wd = menu_ptr->handle(); menu_ptr->goto_next(true); + } break; case keyboard::escape: if(essence::behavior::focus == ess_->state.behave) @@ -481,15 +491,21 @@ namespace nana if(index != npos) { ess_->state.active = index; - if(ess_->open_menu(true)) + if (ess_->open_menu(true)) + { + menu_wd = menu_ptr->handle(); menu_ptr->goto_next(true); + } } break; } } - refresh(graph); - API::dev::lazy_refresh(); + if (API::is_window(menu_wd)) + { + refresh(graph); + API::dev::lazy_refresh(); + } } void trigger::key_release(graph_reference graph, const arg_keyboard& arg) From 8d9351e0519ca32bff2931cbcc1e4c7026b9799c Mon Sep 17 00:00:00 2001 From: Jinhao Date: Wed, 27 Sep 2017 08:13:55 +0800 Subject: [PATCH 4/8] graphics::make throws std::bad_alloc when it fails --- source/paint/graphics.cpp | 86 +++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index c617b3ee..6ced8b96 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -293,7 +293,7 @@ namespace paint void graphics::make(const ::nana::size& sz) { - if(impl_->handle == nullptr || impl_->size != sz) + if (impl_->handle == nullptr || impl_->size != sz) { if (sz.empty()) { @@ -302,9 +302,10 @@ namespace paint } //The object will be delete while dwptr_ is performing a release. - drawable_type dw = new nana::detail::drawable_impl_type; + std::shared_ptr dw{ new nana::detail::drawable_impl_type, detail::drawable_deleter{} }; + //Reuse the old font - if(impl_->platform_drawable) + if (impl_->platform_drawable) { drawable_type reuse = impl_->platform_drawable.get(); dw->font = reuse->font; @@ -314,8 +315,13 @@ namespace paint dw->font = impl_->font_shadow.impl_->real_font; #if defined(NANA_WINDOWS) - HDC hdc = ::GetDC(0); + HDC hdc = ::GetDC(nullptr); HDC cdc = ::CreateCompatibleDC(hdc); + if (nullptr == cdc) + { + ::ReleaseDC(nullptr, hdc); + throw std::bad_alloc{}; + } BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -328,34 +334,60 @@ namespace paint HBITMAP bmp = ::CreateDIBSection(cdc, &bmi, DIB_RGB_COLORS, reinterpret_cast(&(dw->pixbuf_ptr)), 0, 0); - if(bmp) - { - ::DeleteObject((HBITMAP)::SelectObject(cdc, bmp)); - ::DeleteObject(::SelectObject(cdc, dw->font->native_handle())); - - dw->context = cdc; - dw->pixmap = bmp; - ::SetBkMode(cdc, TRANSPARENT); - } - else + if (nullptr == bmp) { ::DeleteDC(cdc); - delete dw; - dw = nullptr; - release(); + ::ReleaseDC(nullptr, hdc); + throw std::bad_alloc{}; } + ::DeleteObject((HBITMAP)::SelectObject(cdc, bmp)); + ::DeleteObject(::SelectObject(cdc, dw->font->native_handle())); + + dw->context = cdc; + dw->pixmap = bmp; + ::SetBkMode(cdc, TRANSPARENT); + ::ReleaseDC(0, hdc); #elif defined(NANA_X11) auto & spec = nana::detail::platform_spec::instance(); - Display* disp = spec.open_display(); - int screen = DefaultScreen(disp); - Window root = ::XRootWindow(disp, screen); - dw->pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); - dw->context = ::XCreateGC(disp, dw->pixmap, 0, 0); - #if defined(NANA_USE_XFT) - dw->xftdraw = ::XftDrawCreate(disp, dw->pixmap, spec.screen_visual(), spec.colormap()); - #endif + { + nana::detail::platform_scope_guard psg; + + spec.set_error_handler(); + + Display* disp = spec.open_display(); + int screen = DefaultScreen(disp); + Window root = ::XRootWindow(disp, screen); + auto pixmap = ::XCreatePixmap(disp, root, sz.width, sz.height, DefaultDepth(disp, screen)); + if(spec.error_code) + { + spec.rev_error_handler(); + throw std::bad_alloc(); + } + auto context = ::XCreateGC(disp, pixmap, 0, 0); + if (spec.error_code) + { + ::XFreePixmap(disp, pixmap); + spec.rev_error_handler(); + throw std::bad_alloc(); + } +# if defined(NANA_USE_XFT) + auto xftdraw = ::XftDrawCreate(disp, pixmap, spec.screen_visual(), spec.colormap()); + if (spec.error_code) + { + ::XFreeGC(disp, context); + ::XFreePixmap(disp, pixmap); + + spec.rev_error_handler(); + throw std::bad_alloc(); + } + + dw->xftdraw = xftdraw; +# endif + dw->pixmap = pixmap; + dw->context = context; + } #endif if(dw) { @@ -366,8 +398,8 @@ namespace paint #else dw->update_text_color(); #endif - impl_->platform_drawable.reset(dw, detail::drawable_deleter{}); - impl_->handle = dw; + impl_->platform_drawable = dw; + impl_->handle = dw.get(); impl_->size = sz; impl_->handle->string.tab_pixels = detail::raw_text_extent_size(impl_->handle, L"\t", 1).width; From d715c87d933649cf25d38cab02dc0b24e9a265a5 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 28 Sep 2017 08:29:19 +0800 Subject: [PATCH 5/8] correct the process of failure of resizing a window --- .../gui/detail/native_window_interface.hpp | 6 +- include/nana/paint/graphics.hpp | 2 + source/detail/mswin/platform_spec.hpp | 11 -- source/gui/detail/bedrock_posix.cpp | 21 ++- source/gui/detail/bedrock_windows.cpp | 45 +------ source/gui/detail/native_window_interface.cpp | 126 ++++++++---------- source/gui/detail/window_manager.cpp | 29 +++- source/paint/graphics.cpp | 6 + 8 files changed, 115 insertions(+), 131 deletions(-) diff --git a/include/nana/gui/detail/native_window_interface.hpp b/include/nana/gui/detail/native_window_interface.hpp index c80d51f1..25b2fc7f 100644 --- a/include/nana/gui/detail/native_window_interface.hpp +++ b/include/nana/gui/detail/native_window_interface.hpp @@ -1,7 +1,7 @@ /* * Platform Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -66,11 +66,11 @@ namespace detail static nana::point window_position(native_window_type); static void move_window(native_window_type, int x, int y); - static void move_window(native_window_type, const rectangle&); + static bool move_window(native_window_type, const rectangle&); 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 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 window_caption(native_window_type, const native_string_type&); static native_string_type window_caption(native_window_type); diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index 8843a03f..7d6d6df8 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -91,6 +91,8 @@ namespace nana const void* pixmap() const; const void* context() const; + void swap(graphics& other); + /// Creates a graphics/drawable resource /** * @param sz The dimension of the graphics to be requested. If sz is empty, it performs as release(). diff --git a/source/detail/mswin/platform_spec.hpp b/source/detail/mswin/platform_spec.hpp index 30bc8b84..5eb6df45 100644 --- a/source/detail/mswin/platform_spec.hpp +++ b/source/detail/mswin/platform_spec.hpp @@ -47,16 +47,6 @@ namespace detail bool visible; }; - struct move_window - { - enum { Pos = 1, Size = 2}; - int x; - int y; - unsigned width; - unsigned height; - unsigned ignore; //determinate that pos or size would be ignored. - }; - struct map_thread { rectangle update_area; @@ -77,7 +67,6 @@ namespace detail async_set_focus, remote_flush_surface, remote_thread_destroy_window, - remote_thread_move_window, operate_caret, //wParam: 1=Destroy, 2=SetPos remote_thread_set_window_pos, remote_thread_set_window_text, diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 4e7c8a07..94dd0562 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -250,17 +250,24 @@ namespace detail _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); - //A child of wd may not be drawn if it was out of wd's range before wd resized, - //so refresh all children of wd when a resized occurs. - if(ask_update || (event_code::resized == evt_code)) + bool good_wd = false; + if(wd_manager().available(wd)) { - wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code)); + //A child of wd may not be drawn if it was out of wd's range before wd resized, + //so refresh all children of wd when a resized occurs. + if(ask_update || (event_code::resized == evt_code) || (update_state::refreshed == wd->other.upd_state)) + { + wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code)); + } + else + wd->other.upd_state = update_state::none; + + good_wd = true; } - else if(wd_manager().available(wd)) - wd->other.upd_state = core_window_t::update_state::none; + if(thrd) thrd->event_window = prev_wd; - return true; + return good_wd; } void assign_arg(arg_mouse& arg, basic_window* wd, unsigned msg, const XEvent& evt) diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 67f40ffe..2d75e7d4 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -601,40 +601,6 @@ namespace detail ::HeapFree(::GetProcessHeap(), 0, stru); } return true; - case nana::detail::messages::remote_thread_move_window: - { - auto * mw = reinterpret_cast(wParam); - - ::RECT r; - ::GetWindowRect(wd, &r); - if(mw->ignore & mw->Pos) - { - mw->x = r.left; - mw->y = r.top; - } - else - { - HWND owner = ::GetWindow(wd, GW_OWNER); - if(owner) - { - ::RECT owr; - ::GetWindowRect(owner, &owr); - ::POINT pos = {owr.left, owr.top}; - ::ScreenToClient(owner, &pos); - mw->x += (owr.left - pos.x); - mw->y += (owr.top - pos.y); - } - } - - if(mw->ignore & mw->Size) - { - mw->width = r.right - r.left; - mw->height = r.bottom - r.top; - } - ::MoveWindow(wd, mw->x, mw->y, mw->width, mw->height, true); - delete mw; - } - return true; case nana::detail::messages::remote_thread_set_window_pos: ::SetWindowPos(wd, reinterpret_cast(wParam), 0, 0, 0, 0, static_cast(lParam)); return true; @@ -1652,18 +1618,21 @@ namespace detail _m_event_filter(evt_code, wd, thrd); } - if (wd->other.upd_state == core_window_t::update_state::none) - wd->other.upd_state = core_window_t::update_state::lazy; + using update_state = basic_window::update_state; + + if (update_state::none == wd->other.upd_state) + wd->other.upd_state = update_state::lazy; _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); bool good_wd = false; if (wd_manager().available(wd)) { - if (ask_update) + //Ignore ask_update if update state is refreshed. + if (ask_update || (update_state::refreshed == wd->other.upd_state)) wd_manager().do_lazy_refresh(wd, false); else - wd->other.upd_state = basic_window::update_state::none; + wd->other.upd_state = update_state::none; good_wd = true; } diff --git a/source/gui/detail/native_window_interface.cpp b/source/gui/detail/native_window_interface.cpp index 821296c1..a054dba7 100644 --- a/source/gui/detail/native_window_interface.cpp +++ b/source/gui/detail/native_window_interface.cpp @@ -863,30 +863,27 @@ namespace nana{ void native_interface::move_window(native_window_type wd, int x, int y) { #if defined(NANA_WINDOWS) - if(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + ::RECT r; + ::GetWindowRect(reinterpret_cast(wd), &r); + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + if(owner) { - nana::detail::messages::move_window * mw = new nana::detail::messages::move_window; - mw->x = x; - mw->y = y; - mw->ignore = mw->Size; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::RECT owner_rect; + ::GetWindowRect(owner, &owner_rect); + ::POINT pos = {owner_rect.left, owner_rect.top}; + ::ScreenToClient(owner, &pos); + x += (owner_rect.left - pos.x); + y += (owner_rect.top - pos.y); } - else + + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) { - ::RECT r; - ::GetWindowRect(reinterpret_cast(wd), &r); - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - if(owner) - { - ::RECT owner_rect; - ::GetWindowRect(owner, &owner_rect); - ::POINT pos = {owner_rect.left, owner_rect.top}; - ::ScreenToClient(owner, &pos); - x += (owner_rect.left - pos.x); - y += (owner_rect.top - pos.y); - } + nana::internal_revert_guard irg; ::MoveWindow(reinterpret_cast(wd), x, y, r.right - r.left, r.bottom - r.top, true); } + else + ::MoveWindow(reinterpret_cast(wd), x, y, r.right - r.left, r.bottom - r.top, true); #elif defined(NANA_X11) Display * disp = restrict::spec.open_display(); @@ -908,41 +905,36 @@ namespace nana{ #endif } - void native_interface::move_window(native_window_type wd, const rectangle& r) + bool native_interface::move_window(native_window_type wd, const rectangle& r) { #if defined(NANA_WINDOWS) - if(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + + int x = r.x; + int y = r.y; + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + if(owner) { - auto * mw = new nana::detail::messages::move_window; - mw->x = r.x; - mw->y = r.y; - mw->width = r.width; - mw->height = r.height; - mw->ignore = 0; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::RECT owner_rect; + ::GetWindowRect(owner, &owner_rect); + ::POINT pos = {owner_rect.left, owner_rect.top}; + ::ScreenToClient(owner, &pos); + x += (owner_rect.left - pos.x); + y += (owner_rect.top - pos.y); } - else - { - int x = r.x; - int y = r.y; - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - if(owner) - { - ::RECT owner_rect; - ::GetWindowRect(owner, &owner_rect); - ::POINT pos = {owner_rect.left, owner_rect.top}; - ::ScreenToClient(owner, &pos); - x += (owner_rect.left - pos.x); - y += (owner_rect.top - pos.y); - } - RECT client, wd_area; - ::GetClientRect(reinterpret_cast(wd), &client); - ::GetWindowRect(reinterpret_cast(wd), &wd_area); - unsigned ext_w = (wd_area.right - wd_area.left) - client.right; - unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom; - ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true); + RECT client, wd_area; + ::GetClientRect(reinterpret_cast(wd), &client); + ::GetWindowRect(reinterpret_cast(wd), &wd_area); + unsigned ext_w = (wd_area.right - wd_area.left) - client.right; + unsigned ext_h = (wd_area.bottom - wd_area.top) - client.bottom; + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + { + nana::internal_revert_guard irg; + return (FALSE != ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true)); } + + return (FALSE != ::MoveWindow(reinterpret_cast(wd), x, y, r.width + ext_w, r.height + ext_h, true)); #elif defined(NANA_X11) Display * disp = restrict::spec.open_display(); long supplied; @@ -984,6 +976,7 @@ namespace nana{ ::XSetWMNormalHints(disp, reinterpret_cast(wd), &hints); ::XMoveResizeWindow(disp, reinterpret_cast(wd), x, y, r.width, r.height); + return true; #endif } @@ -1062,32 +1055,28 @@ namespace nana{ #endif } - void 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(::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) + ::RECT r; + ::GetWindowRect(reinterpret_cast(wd), &r); + HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); + HWND parent = ::GetParent(reinterpret_cast(wd)); + if(parent && (parent != owner)) { - auto * mw = new nana::detail::messages::move_window; - mw->width = sz.width; - mw->height = sz.height; - mw->ignore = mw->Pos; - ::PostMessage(reinterpret_cast(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast(mw), 0); + ::POINT pos = {r.left, r.top}; + ::ScreenToClient(parent, &pos); + r.left = pos.x; + r.top = pos.y; } - else + + if (::GetWindowThreadProcessId(reinterpret_cast(wd), 0) != ::GetCurrentThreadId()) { - ::RECT r; - ::GetWindowRect(reinterpret_cast(wd), &r); - HWND owner = ::GetWindow(reinterpret_cast(wd), GW_OWNER); - HWND parent = ::GetParent(reinterpret_cast(wd)); - if(parent && (parent != owner)) - { - ::POINT pos = {r.left, r.top}; - ::ScreenToClient(parent, &pos); - r.left = pos.x; - r.top = pos.y; - } - ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true); + nana::internal_revert_guard irg; + return (FALSE != ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true)); } + + return (FALSE != ::MoveWindow(reinterpret_cast(wd), r.left, r.top, static_cast(sz.width), static_cast(sz.height), true)); #elif defined(NANA_X11) auto disp = restrict::spec.open_display(); nana::detail::platform_scope_guard psg; @@ -1104,6 +1093,7 @@ namespace nana{ ::XSetWMNormalHints(disp, reinterpret_cast(wd), &hints); } ::XResizeWindow(disp, reinterpret_cast(wd), sz.width, sz.height); + return true; #endif } diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 701eb530..e948aeec 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -953,24 +953,45 @@ namespace detail if (wd->dimension == sz) return false; + //Before resiz the window, creates the new graphics + paint::graphics graph; + paint::graphics root_graph; + if (category::flags::lite_widget != wd->other.category) + { + //If allocation fails, here throws std::bad_alloc. + graph.make(sz); + if (category::flags::root == wd->other.category) + root_graph.make(sz); + } + + auto pre_sz = wd->dimension; + wd->dimension = sz; if(category::flags::lite_widget != wd->other.category) { bool graph_state = wd->drawer.graphics.empty(); - wd->drawer.graphics.make(sz); + wd->drawer.graphics.swap(graph); //It shall make a typeface_changed() call when the graphics state is changing. - //Because when a widget is created with zero-size, it may get some wrong result in typeface_changed() call + //Because when a widget is created with zero-size, it may get some wrong results in typeface_changed() call //due to the invaliable graphics object. if(graph_state != wd->drawer.graphics.empty()) wd->drawer.typeface_changed(); if(category::flags::root == wd->other.category) { - wd->root_graph->make(sz); + //wd->root_graph->make(sz); + wd->root_graph->swap(root_graph); if(false == passive) - native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height)); + if (!native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height))) + { + wd->dimension = pre_sz; + wd->drawer.graphics.swap(graph); + wd->root_graph->swap(root_graph); + wd->drawer.typeface_changed(); + return false; + } } #ifndef WIDGET_FRAME_DEPRECATED else if(category::flags::frame == wd->other.category) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 6ced8b96..a048423c 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -291,6 +291,12 @@ namespace paint return (impl_->handle ? impl_->handle->context : nullptr); } + void graphics::swap(graphics& other) + { + if (context() != other.context()) + impl_.swap(other.impl_); + } + void graphics::make(const ::nana::size& sz) { if (impl_->handle == nullptr || impl_->size != sz) From a3cd37b9d5a4cbc4901bd06db4c542c5ce4e3938 Mon Sep 17 00:00:00 2001 From: Jinhao Date: Thu, 28 Sep 2017 08:42:11 +0800 Subject: [PATCH 6/8] fix a GCC compiler error --- source/gui/detail/bedrock_posix.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 94dd0562..5f4fa1fa 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -245,8 +245,10 @@ namespace detail _m_event_filter(evt_code, wd, thrd); } - if(wd->other.upd_state == core_window_t::update_state::none) - wd->other.upd_state = core_window_t::update_state::lazy; + using update_state = basic_window::update_state; + + if(wd->other.upd_state == update_state::none) + wd->other.upd_state = update_state::lazy; _m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal); From 28e9bb8a7d04ec173168a50553348c4e08cd4b6f Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 30 Sep 2017 07:19:15 +0800 Subject: [PATCH 7/8] fix some legacy issues --- include/nana/paint/graphics.hpp | 4 ++-- source/paint/graphics.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nana/paint/graphics.hpp b/include/nana/paint/graphics.hpp index 7d6d6df8..9ce35704 100644 --- a/include/nana/paint/graphics.hpp +++ b/include/nana/paint/graphics.hpp @@ -85,13 +85,13 @@ namespace nana bool changed() const; ///< Returns true if the graphics object is operated bool empty() const; ///< Returns true if the graphics object does not refer to any resource. - operator const void*() const; + explicit operator bool() const noexcept; drawable_type handle() const; const void* pixmap() const; const void* context() const; - void swap(graphics& other); + void swap(graphics& other) noexcept; /// Creates a graphics/drawable resource /** diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index a048423c..00cb26de 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -269,7 +269,7 @@ namespace paint return (!impl_->handle); } - graphics::operator const void *() const + graphics::operator bool() const { return impl_->handle; } From b730f368a4edf83a3da6b32c3c5bb60476b8d81b Mon Sep 17 00:00:00 2001 From: Jinhao Date: Sat, 30 Sep 2017 07:29:27 +0800 Subject: [PATCH 8/8] fix syntax errors --- source/paint/graphics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/paint/graphics.cpp b/source/paint/graphics.cpp index 00cb26de..f31f3afd 100644 --- a/source/paint/graphics.cpp +++ b/source/paint/graphics.cpp @@ -269,7 +269,7 @@ namespace paint return (!impl_->handle); } - graphics::operator bool() const + graphics::operator bool() const noexcept { return impl_->handle; } @@ -291,7 +291,7 @@ namespace paint return (impl_->handle ? impl_->handle->context : nullptr); } - void graphics::swap(graphics& other) + void graphics::swap(graphics& other) noexcept { if (context() != other.context()) impl_.swap(other.impl_);