correct the process of failure of resizing a window
This commit is contained in:
parent
8d9351e051
commit
d715c87d93
@ -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);
|
||||
|
@ -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().
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -601,40 +601,6 @@ namespace detail
|
||||
::HeapFree(::GetProcessHeap(), 0, stru);
|
||||
}
|
||||
return true;
|
||||
case nana::detail::messages::remote_thread_move_window:
|
||||
{
|
||||
auto * mw = reinterpret_cast<nana::detail::messages::move_window*>(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<HWND>(wParam), 0, 0, 0, 0, static_cast<UINT>(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;
|
||||
}
|
||||
|
@ -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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), x, y, r.right - r.left, r.bottom - r.top, true);
|
||||
}
|
||||
else
|
||||
::MoveWindow(reinterpret_cast<HWND>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
|
||||
int x = r.x;
|
||||
int y = r.y;
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(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<HWND>(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<HWND>(wd), &client);
|
||||
::GetWindowRect(reinterpret_cast<HWND>(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<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true);
|
||||
RECT client, wd_area;
|
||||
::GetClientRect(reinterpret_cast<HWND>(wd), &client);
|
||||
::GetWindowRect(reinterpret_cast<HWND>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
nana::internal_revert_guard irg;
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), x, y, r.width + ext_w, r.height + ext_h, true));
|
||||
}
|
||||
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(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<Window>(wd), &hints);
|
||||
|
||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(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<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
|
||||
HWND parent = ::GetParent(reinterpret_cast<HWND>(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<HWND>(wd), nana::detail::messages::remote_thread_move_window, reinterpret_cast<WPARAM>(mw), 0);
|
||||
::POINT pos = {r.left, r.top};
|
||||
::ScreenToClient(parent, &pos);
|
||||
r.left = pos.x;
|
||||
r.top = pos.y;
|
||||
}
|
||||
else
|
||||
|
||||
if (::GetWindowThreadProcessId(reinterpret_cast<HWND>(wd), 0) != ::GetCurrentThreadId())
|
||||
{
|
||||
::RECT r;
|
||||
::GetWindowRect(reinterpret_cast<HWND>(wd), &r);
|
||||
HWND owner = ::GetWindow(reinterpret_cast<HWND>(wd), GW_OWNER);
|
||||
HWND parent = ::GetParent(reinterpret_cast<HWND>(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<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true);
|
||||
nana::internal_revert_guard irg;
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(sz.height), true));
|
||||
}
|
||||
|
||||
return (FALSE != ::MoveWindow(reinterpret_cast<HWND>(wd), r.left, r.top, static_cast<int>(sz.width), static_cast<int>(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<Window>(wd), &hints);
|
||||
}
|
||||
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user