fix a refreshing issue
bad refreshing when a lite_widget is destroying if the lite_widget's parent is also a type of lite_widget
This commit is contained in:
parent
331f19e679
commit
e8ae11e208
@ -55,6 +55,13 @@ namespace detail
|
||||
unsigned ignore; //determinate that pos or size would be ignored.
|
||||
};
|
||||
|
||||
struct map_thread
|
||||
{
|
||||
rectangle update_area;
|
||||
bool ignore_update_area;
|
||||
bool forced;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
tray = 0x501,
|
||||
|
||||
@ -42,7 +42,7 @@ namespace detail
|
||||
|
||||
~bedrock();
|
||||
void pump_event(window, bool is_modal);
|
||||
void map_thread_root_buffer(core_window_t*, bool forced);
|
||||
void map_thread_root_buffer(core_window_t*, bool forced, const rectangle* update_area = nullptr);
|
||||
static int inc_window(unsigned tid = 0);
|
||||
thread_context* open_thread_context(unsigned tid = 0);
|
||||
thread_context* get_thread_context(unsigned tid = 0);
|
||||
|
||||
@ -110,7 +110,7 @@ namespace nana
|
||||
void key_char(const arg_keyboard&);
|
||||
void key_release(const arg_keyboard&);
|
||||
void shortkey(const arg_keyboard&);
|
||||
void map(window, bool forced); //Copy the root buffer to screen
|
||||
void map(window, bool forced, const rectangle* update_area = nullptr); //Copy the root buffer to screen
|
||||
void refresh();
|
||||
drawer_trigger* realizer() const;
|
||||
void attached(widget&, drawer_trigger&);
|
||||
|
||||
@ -13,9 +13,9 @@ namespace nana{
|
||||
{
|
||||
edge_nimbus_renderer() = default;
|
||||
public:
|
||||
typedef CoreWindow core_window_t;
|
||||
typedef window_layout window_layer;
|
||||
typedef nana::paint::graphics & graph_reference;
|
||||
using core_window_t = CoreWindow;
|
||||
using window_layer = window_layout;
|
||||
using graph_reference = ::nana::paint::graphics&;
|
||||
|
||||
static edge_nimbus_renderer& instance()
|
||||
{
|
||||
@ -28,7 +28,34 @@ namespace nana{
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool render(core_window_t * wd, bool forced)
|
||||
void erase(core_window_t* wd)
|
||||
{
|
||||
if (effects::edge_nimbus::none == wd->effect.edge_nimbus)
|
||||
return;
|
||||
|
||||
core_window_t * root_wd = wd->root_widget;
|
||||
auto & nimbus = root_wd->other.attribute.root->effects_edge_nimbus;
|
||||
|
||||
for (auto i = nimbus.cbegin(); i != nimbus.cend(); ++i)
|
||||
{
|
||||
if (i->window == wd)
|
||||
{
|
||||
auto pixels = weight();
|
||||
rectangle r{wd->pos_root, wd->dimension};
|
||||
r.x -= static_cast<int>(pixels);
|
||||
r.y -= static_cast<int>(pixels);
|
||||
r.width += static_cast<unsigned>(pixels << 1);
|
||||
r.height += static_cast<unsigned>(pixels << 1);
|
||||
|
||||
root_wd->root_graph->paste(root_wd->root, r, r.x, r.y);
|
||||
|
||||
nimbus.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool render(core_window_t * wd, bool forced, const rectangle* update_area = nullptr)
|
||||
{
|
||||
bool rendered = false;
|
||||
core_window_t * root_wd = wd->root_widget;
|
||||
@ -49,8 +76,12 @@ namespace nana{
|
||||
{
|
||||
if(_m_edge_nimbus(focused, action.window) && window_layer::read_visual_rectangle(action.window, r))
|
||||
{
|
||||
if(action.window == wd)
|
||||
if (action.window == wd)
|
||||
{
|
||||
if (update_area)
|
||||
::nana::overlap(*update_area, rectangle(r), r);
|
||||
rendered = true;
|
||||
}
|
||||
|
||||
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
|
||||
if ((forced && (action.window == wd)) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
|
||||
|
||||
@ -150,9 +150,9 @@ namespace detail
|
||||
core_window_t* root(native_window_type) const;
|
||||
|
||||
//Copy the root buffer that wnd specified into DeviceContext
|
||||
void map(core_window_t*, bool forced);
|
||||
void map(core_window_t*, bool forced, const rectangle* update_area = nullptr);
|
||||
|
||||
bool update(core_window_t*, bool redraw, bool force);
|
||||
bool update(core_window_t*, bool redraw, bool force, const rectangle* update_area = nullptr);
|
||||
void refresh_tree(core_window_t*);
|
||||
|
||||
bool do_lazy_refresh(core_window_t*, bool force_copy_to_screen);
|
||||
|
||||
@ -240,7 +240,7 @@ namespace nana
|
||||
_m_emit(event_code::shortkey, arg, &drawer_trigger::shortkey);
|
||||
}
|
||||
|
||||
void drawer::map(window wd, bool forced) //Copy the root buffer to screen
|
||||
void drawer::map(window wd, bool forced, const rectangle* update_area) //Copy the root buffer to screen
|
||||
{
|
||||
if(wd)
|
||||
{
|
||||
@ -262,11 +262,15 @@ namespace nana
|
||||
#endif
|
||||
}
|
||||
|
||||
if (false == edge_nimbus_renderer_t::instance().render(iwd, forced))
|
||||
if (false == edge_nimbus_renderer_t::instance().render(iwd, forced, update_area))
|
||||
{
|
||||
nana::rectangle vr;
|
||||
if(bedrock_type::window_manager_t::wndlayout_type::read_visual_rectangle(iwd, vr))
|
||||
rectangle vr;
|
||||
if (bedrock_type::window_manager_t::wndlayout_type::read_visual_rectangle(iwd, vr))
|
||||
{
|
||||
if (update_area)
|
||||
::nana::overlap(*update_area, rectangle(vr), vr);
|
||||
iwd->root_graph->paste(iwd->root, vr, vr.x, vr.y);
|
||||
}
|
||||
}
|
||||
|
||||
if(owns_caret)
|
||||
|
||||
@ -167,7 +167,7 @@ namespace detail
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void bedrock::map_thread_root_buffer(core_window_t*, bool forced)
|
||||
void bedrock::map_thread_root_buffer(core_window_t*, bool forced, const rectangle*)
|
||||
{
|
||||
//GUI in X11 is thread-independent, so no implementation.
|
||||
}
|
||||
|
||||
@ -338,9 +338,14 @@ namespace detail
|
||||
return bedrock_object;
|
||||
}
|
||||
|
||||
void bedrock::map_thread_root_buffer(core_window_t* wd, bool forced)
|
||||
void bedrock::map_thread_root_buffer(core_window_t* wd, bool forced, const rectangle* update_area)
|
||||
{
|
||||
::PostMessage(reinterpret_cast<HWND>(wd->root), nana::detail::messages::map_thread_root_buffer, reinterpret_cast<WPARAM>(wd), static_cast<LPARAM>(forced ? TRUE : FALSE));
|
||||
auto stru = reinterpret_cast<detail::messages::map_thread*>(::HeapAlloc(::GetProcessHeap(), 0, sizeof(detail::messages::map_thread)));
|
||||
if (stru)
|
||||
{
|
||||
if (FALSE == ::PostMessage(reinterpret_cast<HWND>(wd->root), nana::detail::messages::map_thread_root_buffer, reinterpret_cast<WPARAM>(wd), reinterpret_cast<LPARAM>(stru)))
|
||||
::HeapFree(::GetProcessHeap(), 0, stru);
|
||||
}
|
||||
}
|
||||
|
||||
void interior_helper_for_menu(MSG& msg, native_window_type menu_window)
|
||||
@ -591,8 +596,12 @@ namespace detail
|
||||
}
|
||||
return true;
|
||||
case nana::detail::messages::map_thread_root_buffer:
|
||||
bedrock.wd_manager.map(reinterpret_cast<bedrock::core_window_t*>(wParam), (TRUE == lParam));
|
||||
::UpdateWindow(wd);
|
||||
{
|
||||
auto stru = reinterpret_cast<detail::messages::map_thread*>(lParam);
|
||||
bedrock.wd_manager.map(reinterpret_cast<bedrock::core_window_t*>(wParam), stru->forced, (stru->ignore_update_area ? nullptr : &stru->update_area));
|
||||
::UpdateWindow(wd);
|
||||
::HeapFree(::GetProcessHeap(), 0, stru);
|
||||
}
|
||||
return true;
|
||||
case nana::detail::messages::remote_thread_move_window:
|
||||
{
|
||||
|
||||
@ -372,21 +372,26 @@ namespace detail
|
||||
//@brief: Delete the window handle
|
||||
void window_manager::destroy(core_window_t* wd)
|
||||
{
|
||||
core_window_t* parent = nullptr;
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return;
|
||||
|
||||
rectangle update_area(wd->pos_owner, wd->dimension);
|
||||
|
||||
auto parent = wd->parent;
|
||||
if (parent)
|
||||
utl::erase(parent->children, wd);
|
||||
|
||||
_m_destroy(wd);
|
||||
|
||||
while (parent && (parent->other.category == ::nana::category::flags::lite_widget))
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
if (impl_->wd_register.available(wd) == false) return;
|
||||
|
||||
if (wd->parent)
|
||||
{
|
||||
parent = wd->parent;
|
||||
utl::erase(wd->parent->children, wd);
|
||||
}
|
||||
|
||||
_m_destroy(wd);
|
||||
update_area.x += parent->pos_owner.x;
|
||||
update_area.y += parent->pos_owner.y;
|
||||
parent = parent->parent;
|
||||
}
|
||||
update(parent, false, false);
|
||||
|
||||
update(parent, false, false, &update_area);
|
||||
}
|
||||
|
||||
//destroy_handle
|
||||
@ -672,7 +677,7 @@ namespace detail
|
||||
}
|
||||
|
||||
//Copy the root buffer that wnd specified into DeviceContext
|
||||
void window_manager::map(core_window_t* wd, bool forced)
|
||||
void window_manager::map(core_window_t* wd, bool forced, const rectangle* update_area)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
@ -680,12 +685,12 @@ namespace detail
|
||||
{
|
||||
//Copy the root buffer that wd specified into DeviceContext
|
||||
#if defined(NANA_LINUX)
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced);
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
|
||||
#elif defined(NANA_WINDOWS)
|
||||
if(nana::system::this_thread_id() == wd->thread_id)
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced);
|
||||
wd->drawer.map(reinterpret_cast<window>(wd), forced, update_area);
|
||||
else
|
||||
bedrock::instance().map_thread_root_buffer(wd, forced);
|
||||
bedrock::instance().map_thread_root_buffer(wd, forced, update_area);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -694,7 +699,7 @@ namespace detail
|
||||
//@brief: update is used for displaying the screen-off buffer.
|
||||
// Because of a good efficiency, if it is called in an event procedure and the event procedure window is the
|
||||
// same as update's, update would not map the screen-off buffer and just set the window for lazy refresh
|
||||
bool window_manager::update(core_window_t* wd, bool redraw, bool forced)
|
||||
bool window_manager::update(core_window_t* wd, bool redraw, bool forced, const rectangle* update_area)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||
@ -705,7 +710,7 @@ namespace detail
|
||||
if(forced || (false == wd->belong_to_lazy()))
|
||||
{
|
||||
wndlayout_type::paint(wd, redraw, false);
|
||||
this->map(wd, forced);
|
||||
this->map(wd, forced, update_area);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1252,18 +1257,9 @@ namespace detail
|
||||
|
||||
if (!established)
|
||||
{
|
||||
if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
{
|
||||
auto & cont = root_attr->effects_edge_nimbus;
|
||||
for (auto i = cont.begin(); i != cont.end(); ++i)
|
||||
{
|
||||
if (i->window == wd)
|
||||
{
|
||||
cont.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//remove the window from edge nimbus effect when it is destroying
|
||||
using edge_nimbus = detail::edge_nimbus_renderer<core_window_t>;
|
||||
edge_nimbus::instance().erase(wd);
|
||||
}
|
||||
else if (pa_root_attr != root_attr)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user