fix transparent window bugs
This commit is contained in:
parent
7c36c27d46
commit
092ae97c66
@ -85,7 +85,7 @@ namespace detail
|
||||
|
||||
enum class update_state
|
||||
{
|
||||
none, lazy, refresh
|
||||
none, lazy, refreshed, request_refresh
|
||||
};
|
||||
|
||||
struct edge_nimbus_action
|
||||
|
@ -86,7 +86,7 @@ namespace nana{
|
||||
}
|
||||
|
||||
//Avoiding duplicated rendering. If the window is declared to lazy refresh, it should be rendered.
|
||||
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refresh))
|
||||
if ((forced && (action.window == wd)) || (focused == action.window) || !action.rendered || (action.window->other.upd_state == core_window_t::update_state::refreshed))
|
||||
{
|
||||
rd_set.emplace_back(r, action.window);
|
||||
action.rendered = true;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Window Layout Implementation
|
||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -42,10 +42,16 @@ namespace detail
|
||||
core_window_t * window;
|
||||
rectangle r;
|
||||
};
|
||||
public:
|
||||
static void paint(core_window_t*, bool is_redraw, bool is_child_refreshed);
|
||||
|
||||
static bool maproot(core_window_t*, bool have_refreshed, bool is_child_refreshed);
|
||||
enum class paint_operation {
|
||||
none,
|
||||
have_refreshed,
|
||||
try_refresh
|
||||
};
|
||||
public:
|
||||
static void paint(core_window_t*, paint_operation, bool request_refresh_children);
|
||||
|
||||
static bool maproot(core_window_t*, bool have_refreshed, bool request_refresh_children);
|
||||
|
||||
static void paste_children_to_graphics(core_window_t*, nana::paint::graphics& graph);
|
||||
|
||||
@ -68,13 +74,12 @@ namespace detail
|
||||
|
||||
//_m_paste_children
|
||||
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
|
||||
static void _m_paste_children(core_window_t*, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos);
|
||||
static void _m_paste_children(core_window_t*, bool have_refreshed, bool request_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos);
|
||||
|
||||
static void _m_paint_glass_window(core_window_t*, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other);
|
||||
|
||||
//_m_notify_glasses
|
||||
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
|
||||
static void _m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& r_visual);
|
||||
//Notify the windows which have brground to update their background buffer.
|
||||
static void _m_notify_glasses(core_window_t* const sigwd);
|
||||
private:
|
||||
struct data_section
|
||||
{
|
||||
|
@ -124,7 +124,7 @@ namespace detail
|
||||
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, bool refresh_tree = false);
|
||||
void do_lazy_refresh(core_window_t*, bool force_copy_to_screen, bool refresh_tree = false);
|
||||
|
||||
bool get_graphics(core_window_t*, nana::paint::graphics&);
|
||||
bool get_visual_rectangle(core_window_t*, nana::rectangle&);
|
||||
|
@ -323,7 +323,7 @@ namespace nana
|
||||
{
|
||||
for (auto wd = this; wd; wd = wd->parent)
|
||||
{
|
||||
if (basic_window::update_state::refresh == wd->other.upd_state)
|
||||
if (basic_window::update_state::refreshed == wd->other.upd_state)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1203,17 +1203,7 @@ namespace detail
|
||||
{
|
||||
thread_context* thrd = get_thread_context(0);
|
||||
if(thrd && thrd->event_window)
|
||||
{
|
||||
//the state none should be tested, becuase in an event, there would be draw after an update,
|
||||
//if the none is not tested, the draw after update will not be refreshed.
|
||||
switch(thrd->event_window->other.upd_state)
|
||||
{
|
||||
case core_window_t::update_state::none:
|
||||
case core_window_t::update_state::lazy:
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refresh;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refresh;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
|
@ -1691,17 +1691,7 @@ namespace detail
|
||||
{
|
||||
auto* thrd = get_thread_context(0);
|
||||
if (thrd && thrd->event_window)
|
||||
{
|
||||
//the state none should be tested, becuase in an event, there would be draw after an update,
|
||||
//if the none is not tested, the draw after update will not be refreshed.
|
||||
switch (thrd->event_window->other.upd_state)
|
||||
{
|
||||
case core_window_t::update_state::none:
|
||||
case core_window_t::update_state::lazy:
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refresh;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
thrd->event_window->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
|
||||
//Dynamically set a cursor for a window
|
||||
|
@ -391,7 +391,7 @@ namespace nana
|
||||
|
||||
bool drawer::_m_lazy_decleared() const
|
||||
{
|
||||
return (basic_window::update_state::refresh == data_impl_->window_handle->other.upd_state);
|
||||
return (basic_window::update_state::refreshed == data_impl_->window_handle->other.upd_state);
|
||||
}
|
||||
|
||||
drawer::method_state& drawer::_m_mth_state(int pos)
|
||||
|
@ -22,26 +22,26 @@ namespace nana
|
||||
namespace detail
|
||||
{
|
||||
//class window_layout
|
||||
void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed)
|
||||
void window_layout::paint(core_window_t* wd, paint_operation operation, bool req_refresh_children)
|
||||
{
|
||||
if (is_redraw && wd->flags.refreshing)
|
||||
if (wd->flags.refreshing && (paint_operation::try_refresh == operation))
|
||||
return;
|
||||
|
||||
if (nullptr == wd->effect.bground)
|
||||
{
|
||||
if (is_redraw && (!wd->drawer.graphics.empty()))
|
||||
if ((paint_operation::try_refresh == operation) && (!wd->drawer.graphics.empty()))
|
||||
{
|
||||
wd->flags.refreshing = true;
|
||||
wd->drawer.refresh();
|
||||
wd->flags.refreshing = false;
|
||||
}
|
||||
maproot(wd, is_redraw, is_child_refreshed);
|
||||
maproot(wd, (paint_operation::none != operation), req_refresh_children);
|
||||
}
|
||||
else
|
||||
_m_paint_glass_window(wd, is_redraw, is_child_refreshed, false, true);
|
||||
_m_paint_glass_window(wd, (paint_operation::try_refresh == operation), req_refresh_children, false, true);
|
||||
}
|
||||
|
||||
bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool is_child_refreshed)
|
||||
bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool req_refresh_children)
|
||||
{
|
||||
auto check_opaque = wd->seek_non_lite_widget_ancestor();
|
||||
if (check_opaque && check_opaque->flags.refreshing)
|
||||
@ -56,7 +56,7 @@ namespace nana
|
||||
if (category::flags::lite_widget != wd->other.category)
|
||||
graph.bitblt(vr, wd->drawer.graphics, nana::point(vr.x - wd->pos_root.x, vr.y - wd->pos_root.y));
|
||||
|
||||
_m_paste_children(wd, is_child_refreshed, have_refreshed, vr, graph, nana::point());
|
||||
_m_paste_children(wd, have_refreshed, req_refresh_children, vr, graph, nana::point());
|
||||
|
||||
if (wd->parent)
|
||||
{
|
||||
@ -81,11 +81,11 @@ namespace nana
|
||||
graph.bitblt(el.r, (el.window->drawer.graphics), p_src);
|
||||
}
|
||||
|
||||
_m_paste_children(el.window, is_child_refreshed, false, el.r, graph, nana::point{});
|
||||
_m_paste_children(el.window, false, req_refresh_children, el.r, graph, nana::point{});
|
||||
}
|
||||
}
|
||||
}
|
||||
_m_notify_glasses(wd, vr);
|
||||
_m_notify_glasses(wd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -255,8 +255,8 @@ namespace nana
|
||||
if (category::flags::lite_widget != child->other.category)
|
||||
glass_buffer.bitblt(nana::rectangle{ ovlp.x - wd->pos_owner.x, ovlp.y - wd->pos_owner.y, ovlp.width, ovlp.height }, child->drawer.graphics, {ovlp.position() - child->pos_owner});
|
||||
|
||||
ovlp.x += wd->pos_root.x;
|
||||
ovlp.y += wd->pos_root.y;
|
||||
ovlp.x += wd->parent->pos_root.x;
|
||||
ovlp.y += wd->parent->pos_root.y;
|
||||
_m_paste_children(child, false, false, ovlp, glass_buffer, rpos);
|
||||
}
|
||||
}
|
||||
@ -267,7 +267,7 @@ namespace nana
|
||||
|
||||
//_m_paste_children
|
||||
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
|
||||
void window_layout::_m_paste_children(core_window_t* wd, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos)
|
||||
void window_layout::_m_paste_children(core_window_t* wd, bool have_refreshed, bool req_refresh_children, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos)
|
||||
{
|
||||
nana::rectangle rect;
|
||||
for (auto child : wd->children)
|
||||
@ -278,7 +278,7 @@ namespace nana
|
||||
|
||||
if (category::flags::root == child->other.category)
|
||||
{
|
||||
paint(child, is_child_refreshed, is_child_refreshed);
|
||||
paint(child, (req_refresh_children ? paint_operation::try_refresh : paint_operation::none), req_refresh_children);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -289,7 +289,7 @@ namespace nana
|
||||
bool have_child_refreshed = false;
|
||||
if (category::flags::lite_widget != child->other.category)
|
||||
{
|
||||
if (is_child_refreshed && (false == child->flags.refreshing))
|
||||
if (req_refresh_children && (false == child->flags.refreshing))
|
||||
{
|
||||
have_child_refreshed = true;
|
||||
child->flags.refreshing = true;
|
||||
@ -300,13 +300,13 @@ namespace nana
|
||||
graph.bitblt(nana::rectangle(rect.x - graph_rpos.x, rect.y - graph_rpos.y, rect.width, rect.height),
|
||||
child->drawer.graphics, nana::point(rect.x - child->pos_root.x, rect.y - child->pos_root.y));
|
||||
}
|
||||
_m_paste_children(child, is_child_refreshed, have_child_refreshed, rect, graph, graph_rpos);
|
||||
_m_paste_children(child, req_refresh_children, have_child_refreshed, rect, graph, graph_rpos);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If have_refreshed, the glass should be notified.
|
||||
_m_paint_glass_window(child, false, is_child_refreshed, have_refreshed, false);
|
||||
//Update the glass window's background if the parent have_refreshed.
|
||||
_m_paint_glass_window(child, have_refreshed, req_refresh_children, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,16 +353,14 @@ namespace nana
|
||||
}
|
||||
|
||||
if (notify_other)
|
||||
_m_notify_glasses(wd, vr);
|
||||
_m_notify_glasses(wd);
|
||||
}
|
||||
}
|
||||
|
||||
//_m_notify_glasses
|
||||
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
|
||||
void window_layout::_m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& /*r_visual*/)
|
||||
/// Notify the glass windows that are overlapped with the specified visual rectangle.
|
||||
/// If a child window of sigwd is a glass window, it doesn't to be notified.
|
||||
void window_layout::_m_notify_glasses(core_window_t* const sigwd)
|
||||
{
|
||||
typedef category::flags cat_flags;
|
||||
|
||||
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
|
||||
for (auto wd : data_sect.effects_bground_windows)
|
||||
{
|
||||
@ -377,6 +375,8 @@ namespace nana
|
||||
}
|
||||
else if (sigwd != wd->parent)
|
||||
{
|
||||
using cat_flags = category::flags;
|
||||
|
||||
if (wd->parent && (cat_flags::lite_widget == wd->parent->other.category))
|
||||
{
|
||||
//Test if sigwd is an ancestor of the glass window, and there are lite widgets
|
||||
|
@ -759,6 +759,10 @@ namespace detail
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
arg.x = x;
|
||||
arg.y = y;
|
||||
|
||||
if (wd->effect.bground)
|
||||
wd->other.upd_state = basic_window::update_state::request_refresh;
|
||||
|
||||
brock.emit(event_code::move, wd, arg, true, brock.get_thread_context());
|
||||
return true;
|
||||
}
|
||||
@ -803,6 +807,9 @@ namespace detail
|
||||
_m_move_core(wd, delta);
|
||||
moved = true;
|
||||
|
||||
if ((!size_changed) && wd->effect.bground)
|
||||
wd->other.upd_state = basic_window::update_state::request_refresh;
|
||||
|
||||
arg_move arg;
|
||||
arg.window_handle = reinterpret_cast<window>(wd);
|
||||
arg.x = r.x;
|
||||
@ -989,26 +996,28 @@ namespace detail
|
||||
|
||||
if (wd->displayed())
|
||||
{
|
||||
using paint_operation = window_layer::paint_operation;
|
||||
|
||||
if(forced || (false == wd->belong_to_lazy()))
|
||||
{
|
||||
if (!wd->flags.refreshing)
|
||||
{
|
||||
window_layer::paint(wd, redraw, false);
|
||||
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
|
||||
this->map(wd, forced, update_area);
|
||||
return true;
|
||||
}
|
||||
else if (forced)
|
||||
{
|
||||
window_layer::paint(wd, false, false);
|
||||
window_layer::paint(wd, paint_operation::none, false);
|
||||
this->map(wd, true, update_area);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (redraw)
|
||||
window_layer::paint(wd, true, false);
|
||||
window_layer::paint(wd, paint_operation::try_refresh, false);
|
||||
|
||||
if (wd->other.upd_state == core_window_t::update_state::lazy)
|
||||
wd->other.upd_state = core_window_t::update_state::refresh;
|
||||
wd->other.upd_state = core_window_t::update_state::refreshed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1020,28 +1029,28 @@ namespace detail
|
||||
|
||||
//It's not worthy to redraw if visible is false
|
||||
if (impl_->wd_register.available(wd) && wd->displayed())
|
||||
window_layer::paint(wd, true, true);
|
||||
window_layer::paint(wd, window_layer::paint_operation::try_refresh, true);
|
||||
}
|
||||
|
||||
//do_lazy_refresh
|
||||
//@brief: defined a behavior of flush the screen
|
||||
//@return: it returns true if the wnd is available
|
||||
bool window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree)
|
||||
void window_manager::do_lazy_refresh(core_window_t* wd, bool force_copy_to_screen, bool refresh_tree)
|
||||
{
|
||||
//Thread-Safe Required!
|
||||
std::lock_guard<mutex_type> lock(mutex_);
|
||||
|
||||
if (false == impl_->wd_register.available(wd))
|
||||
return false;
|
||||
return;
|
||||
|
||||
//It's not worthy to redraw if visible is false
|
||||
if(wd->visible && (!wd->is_draw_through()))
|
||||
{
|
||||
using paint_operation = window_layer::paint_operation;
|
||||
if (wd->visible_parents())
|
||||
{
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refresh) || force_copy_to_screen)
|
||||
if ((wd->other.upd_state == core_window_t::update_state::refreshed) || (wd->other.upd_state == core_window_t::update_state::request_refresh) || force_copy_to_screen)
|
||||
{
|
||||
window_layer::paint(wd, false, refresh_tree);
|
||||
window_layer::paint(wd, (wd->other.upd_state == core_window_t::update_state::request_refresh ? paint_operation::try_refresh : paint_operation::have_refreshed), refresh_tree);
|
||||
this->map(wd, force_copy_to_screen);
|
||||
}
|
||||
else if (effects::edge_nimbus::none != wd->effect.edge_nimbus)
|
||||
@ -1053,10 +1062,10 @@ namespace detail
|
||||
}
|
||||
}
|
||||
else
|
||||
window_layer::paint(wd, true, refresh_tree); //only refreshing if it has an invisible parent
|
||||
window_layer::paint(wd, paint_operation::try_refresh, refresh_tree); //only refreshing if it has an invisible parent
|
||||
}
|
||||
wd->other.upd_state = core_window_t::update_state::none;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
//get_graphics
|
||||
|
Loading…
x
Reference in New Issue
Block a user