Merge branch 'hotfix-1.7' into develop

This commit is contained in:
Jinhao
2019-04-16 04:01:44 +08:00
18 changed files with 460 additions and 101 deletions

View File

@@ -336,6 +336,43 @@ namespace nana
flags.action = act;
}
bool basic_window::try_lazy_update(bool try_refresh)
{
if (drawer.graphics.empty())
return true;
if (!this->root_widget->other.attribute.root->lazy_update)
return false;
if (nullptr == effect.bground)
{
if (try_refresh)
{
flags.refreshing = true;
drawer.refresh();
flags.refreshing = false;
}
}
for (auto i = this->root_widget->other.attribute.root->update_requesters.cbegin(); i != this->root_widget->other.attribute.root->update_requesters.cend();)
{
auto req = *i;
//Avoid redundancy, don't insert the window if it or its ancestor window already exist in the container.
if ((req == this) || req->is_ancestor_of(this))
return true;
//If there is a window which is a child or child's child of the window, remove it.
if (this->is_ancestor_of(req))
i = this->root_widget->other.attribute.root->update_requesters.erase(i);
else
++i;
}
this->root_widget->other.attribute.root->update_requesters.push_back(this);
return true;
}
void basic_window::_m_init_pos_and_size(basic_window* parent, const rectangle& r)
{
pos_owner = pos_root = r.position();
@@ -390,7 +427,6 @@ namespace nana
flags.ignore_menubar_focus = false;
flags.ignore_mouse_focus = false;
flags.space_click_enabled = false;
flags.ignore_child_mapping = false;
visible = false;

View File

@@ -641,13 +641,8 @@ namespace nana
if (update_state::none == wd->other.upd_state)
wd->other.upd_state = update_state::lazy;
auto ignore_mapping_value = wd->flags.ignore_child_mapping;
wd->flags.ignore_child_mapping = true;
_m_emit_core(evt_code, wd, false, arg, bForce__EmitInternal);
wd->flags.ignore_child_mapping = ignore_mapping_value;
bool good_wd = false;
if(wd_manager().available(wd))
{
@@ -658,10 +653,7 @@ namespace nana
wd_manager().do_lazy_refresh(wd, false, (event_code::resized == evt_code));
}
else
{
wd_manager().map_requester(wd);
wd->other.upd_state = update_state::none;
}
good_wd = true;
}

View File

@@ -16,6 +16,7 @@
#include <nana/system/platform.hpp>
#include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/window_layout.hpp>
#include <nana/gui/detail/element_store.hpp>
#include "inner_fwd_implement.hpp"
#include <errno.h>
@@ -555,6 +556,27 @@ namespace detail
context.is_alt_pressed = false;
}
class window_proc_guard
{
public:
window_proc_guard(detail::basic_window* wd) :
root_wd_(wd)
{
root_wd_->other.attribute.root->lazy_update = true;
}
~window_proc_guard()
{
if (!bedrock::instance().wd_manager().available(root_wd_))
return;
root_wd_->other.attribute.root->lazy_update = false;
root_wd_->other.attribute.root->update_requesters.clear();
}
private:
detail::basic_window* const root_wd_;
};
void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
{
typedef detail::bedrock::core_window_t core_window_t;
@@ -569,10 +591,13 @@ namespace detail
if(root_runtime)
{
auto msgwnd = root_runtime->window;
auto const root_wd = root_runtime->window;
auto msgwnd = root_wd;
window_proc_guard wp_guard{ root_wd };
auto& context = *brock.get_thread_context(msgwnd->thread_id);
auto pre_event_window = context.event_window;
auto const pre_event_window = context.event_window;
auto pressed_wd = root_runtime->condition.pressed;
auto pressed_wd_space = root_runtime->condition.pressed_by_space;
auto hovered_wd = root_runtime->condition.hovered;
@@ -1190,6 +1215,15 @@ namespace detail
}
}
if (wd_manager.available(root_wd) && root_wd->other.attribute.root->update_requesters.size())
{
for (auto wd : root_wd->other.attribute.root->update_requesters)
{
window_layout::paint(wd, window_layout::paint_operation::have_refreshed, false);
wd_manager.map(wd, true);
}
}
root_runtime = wd_manager.root_runtime(native_window);
if(root_runtime)
{

View File

@@ -21,6 +21,7 @@
#include <nana/gui.hpp>
#include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/window_layout.hpp>
#include <nana/gui/detail/element_store.hpp>
#include <nana/gui/detail/color_schemes.hpp>
#include "inner_fwd_implement.hpp"
@@ -37,6 +38,7 @@
#include "bedrock_types.hpp"
typedef void (CALLBACK *win_event_proc_t)(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
namespace nana
@@ -738,6 +740,27 @@ namespace detail
return static_cast<wchar_t>(vkey);
}
class window_proc_guard
{
public:
window_proc_guard(detail::basic_window* wd) :
root_wd_(wd)
{
root_wd_->other.attribute.root->lazy_update = true;
}
~window_proc_guard()
{
if (!bedrock::instance().wd_manager().available(root_wd_))
return;
root_wd_->other.attribute.root->lazy_update = false;
root_wd_->other.attribute.root->update_requesters.clear();
}
private:
detail::basic_window* const root_wd_;
};
LRESULT CALLBACK Bedrock_WIN32_WindowProc(HWND root_window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT window_proc_value = 0;
@@ -757,6 +780,7 @@ namespace detail
bool def_window_proc = false;
auto& context = *brock.get_thread_context();
auto const pre_event_window = context.event_window;
auto pressed_wd = root_runtime->condition.pressed;
auto pressed_wd_space = root_runtime->condition.pressed_by_space;
auto hovered_wd = root_runtime->condition.hovered;
@@ -766,7 +790,10 @@ namespace detail
pmdec.raw_param.wparam = wParam;
internal_scope_guard lock;
auto msgwnd = root_runtime->window;
auto const root_wd = root_runtime->window;
auto msgwnd = root_wd;
window_proc_guard wp_guard{ root_wd };
switch (message)
{
@@ -775,10 +802,7 @@ namespace detail
{
auto i = root_runtime->wpassoc->accel_commands.find(LOWORD(wParam));
if (i != root_runtime->wpassoc->accel_commands.end())
{
auto fn = i->second;
fn();
}
i->second();
}
break;
case WM_IME_STARTCOMPOSITION:
@@ -1092,7 +1116,9 @@ namespace detail
//The focus window receives the message in Windows system, it should be redirected to the hovered window
::POINT scr_pos{ pmdec.mouse.x, pmdec.mouse.y}; //Screen position
auto pointer_wd = ::WindowFromPoint(scr_pos);
if (pointer_wd == root_window)
//Ignore the message if the window is disabled.
if ((pointer_wd == root_window) && ::IsWindowEnabled(root_window))
{
::ScreenToClient(pointer_wd, &scr_pos);
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), { scr_pos.x, scr_pos.y });
@@ -1124,7 +1150,7 @@ namespace detail
wd_manager.do_lazy_refresh(scrolled_wd, false);
}
}
else
else if (pointer_wd != root_window)
{
DWORD pid = 0;
::GetWindowThreadProcessId(pointer_wd, &pid);
@@ -1450,7 +1476,7 @@ namespace detail
wd_manager.do_lazy_refresh(msgwnd, false);
}
}
return 0;
break;
case WM_KEYUP:
if(wParam != VK_MENU) //MUST NOT BE AN ALT
{
@@ -1551,13 +1577,28 @@ namespace detail
def_window_proc = true;
}
if (wd_manager.available(root_wd) && root_wd->other.attribute.root->update_requesters.size())
{
for (auto wd : root_wd->other.attribute.root->update_requesters)
{
window_layout::paint(wd, window_layout::paint_operation::have_refreshed, false);
wd_manager.map(wd, true);
}
}
root_runtime = wd_manager.root_runtime(native_window);
if(root_runtime)
{
context.event_window = pre_event_window;
root_runtime->condition.pressed = pressed_wd;
root_runtime->condition.hovered = hovered_wd;
root_runtime->condition.pressed_by_space = pressed_wd_space;
}
else
{
auto context = brock.get_thread_context();
if(context) context->event_window = pre_event_window;
}
if (!def_window_proc)
return 0;

View File

@@ -701,19 +701,40 @@ namespace detail
return true;
}
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos)
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos, bool ignore_captured)
{
if (nullptr == root)
return nullptr;
if((false == attr_.capture.ignore_children) || (nullptr == attr_.capture.window) || (attr_.capture.window->root != root))
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
if (ignore_captured || (nullptr == attr_.capture.window))
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
auto rrt = root_runtime(root);
if (rrt && _m_effective(rrt->window, pos))
return _m_find(rrt->window, pos);
return nullptr;
}
if (attr_.capture.ignore_children)
return attr_.capture.window;
auto rrt = root_runtime(root);
if (rrt && _m_effective(rrt->window, pos))
{
auto target = _m_find(rrt->window, pos);
auto p = target;
while (p)
{
if (p == attr_.capture.window)
return target;
p = p->parent;
}
}
return attr_.capture.window;
}
@@ -980,28 +1001,7 @@ namespace detail
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
if (impl_->wd_register.available(wd) && !wd->is_draw_through())
{
auto parent = wd->parent;
while (parent)
{
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
{
auto top = parent;
while(parent->parent)
{
parent = parent->parent;
if(parent->flags.ignore_child_mapping || parent->flags.refreshing)
top = parent;
}
top->other.mapping_requester.push_back(wd);
return;
}
parent = parent->parent;
}
bedrock::instance().flush_surface(wd, forced, update_area);
}
}
//update
@@ -1028,8 +1028,11 @@ namespace detail
{
if (!wd->flags.refreshing)
{
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
this->map(wd, forced, update_area);
if (!wd->try_lazy_update(redraw))
{
window_layer::paint(wd, (redraw ? paint_operation::try_refresh : paint_operation::none), false);
this->map(wd, forced, update_area);
}
return true;
}
else if (forced)
@@ -1076,39 +1079,28 @@ namespace detail
{
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, (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);
if (!wd->try_lazy_update(wd->other.upd_state == core_window_t::update_state::request_refresh))
{
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)
{
//The window is still mapped because of edge nimbus effect.
//Avoid duplicate copy if action state is not changed and the window is not focused.
if (wd->flags.action != wd->flags.action_before)
this->map(wd, true);
{
if (!wd->try_lazy_update(false))
this->map(wd, true);
}
}
}
else
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;
wd->other.mapping_requester.clear();
}
void window_manager::map_requester(core_window_t* wd)
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
if (false == impl_->wd_register.available(wd))
return;
if (wd->visible_parents())
{
for(auto requestor : wd->other.mapping_requester)
this->map(requestor, true);
}
wd->other.mapping_requester.clear();
}
bool window_manager::set_parent(core_window_t* wd, core_window_t* newpa)