Merge remote-tracking branch 'nana_jinhao/hotfixes-1.0.1' into hotfixes-1.0.1
This commit is contained in:
@@ -347,6 +347,7 @@ namespace nana
|
||||
flags.destroying = false;
|
||||
flags.borderless = false;
|
||||
flags.make_bground_declared = false;
|
||||
flags.ignore_menubar_focus = false;
|
||||
|
||||
visible = false;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Bedrock Selector
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Nana Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
||||
@@ -102,27 +102,18 @@ namespace detail
|
||||
{
|
||||
struct thread_context_cache
|
||||
{
|
||||
unsigned tid;
|
||||
thread_context *object;
|
||||
unsigned tid{ 0 };
|
||||
thread_context *object{ nullptr };
|
||||
}tcontext;
|
||||
|
||||
cache_type()
|
||||
{
|
||||
tcontext.tid = 0;
|
||||
tcontext.object = nullptr;
|
||||
}
|
||||
}cache;
|
||||
|
||||
struct menu_tag
|
||||
{
|
||||
menu_tag()
|
||||
:taken_window(nullptr), window(nullptr), owner(nullptr), has_keyboard(false)
|
||||
{}
|
||||
|
||||
core_window_t* taken_window;
|
||||
native_window_type window;
|
||||
native_window_type owner;
|
||||
bool has_keyboard;
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{ false };
|
||||
}menu;
|
||||
|
||||
struct keyboard_tracking_state_tag
|
||||
@@ -282,14 +273,39 @@ namespace detail
|
||||
|
||||
void bedrock::set_menubar_taken(core_window_t* wd)
|
||||
{
|
||||
auto pre = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = wd;
|
||||
|
||||
//assigning of a nullptr taken window is to restore the focus of pre taken
|
||||
if ((!wd) && pre)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
wd_manager.set_focus(pre, false);
|
||||
wd_manager.update(pre, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
bedrock::core_window_t* bedrock::get_menubar_taken()
|
||||
//0:Enable delay, 1:Cancel, 2:Restores, 3: Restores when menu is destroying
|
||||
void bedrock::delay_restore(int state)
|
||||
{
|
||||
core_window_t* wd = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = nullptr;
|
||||
return wd;
|
||||
switch (state)
|
||||
{
|
||||
case 0: //Enable
|
||||
break;
|
||||
case 1: //Cancel
|
||||
break;
|
||||
case 2: //Restore if key released
|
||||
//restores the focus when menu is closed by pressing keyboard
|
||||
if (!impl_->menu.window)
|
||||
set_menubar_taken(nullptr);
|
||||
break;
|
||||
case 3: //Restores if destroying
|
||||
//when the menu is destroying, restores the focus if delay restore is not declared
|
||||
if (!impl_->menu.delay_restore)
|
||||
set_menubar_taken(nullptr);
|
||||
}
|
||||
|
||||
impl_->menu.delay_restore = (0 == state);
|
||||
}
|
||||
|
||||
bool bedrock::close_menu_if_focus_other_window(native_window_type wd)
|
||||
@@ -304,7 +320,7 @@ namespace detail
|
||||
else
|
||||
return false;
|
||||
}
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -314,7 +330,7 @@ namespace detail
|
||||
{
|
||||
if(menu_window && impl_->menu.window != menu_window)
|
||||
{
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
impl_->menu.window = menu_window;
|
||||
impl_->menu.owner = native_interface::get_owner_window(menu_window);
|
||||
impl_->menu.has_keyboard = has_keyboard;
|
||||
@@ -338,21 +354,13 @@ namespace detail
|
||||
return impl_->menu.window;
|
||||
}
|
||||
|
||||
void bedrock::remove_menu()
|
||||
void bedrock::erase_menu(bool try_destroy)
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
if (impl_->menu.window)
|
||||
{
|
||||
native_window_type delwin = impl_->menu.window;
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
native_interface::close_window(delwin);
|
||||
}
|
||||
}
|
||||
if (try_destroy)
|
||||
native_interface::close_window(impl_->menu.window);
|
||||
|
||||
void bedrock::empty_menu()
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
{
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
}
|
||||
@@ -372,6 +380,11 @@ namespace detail
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool bedrock::whether_keyboard_shortkey() const
|
||||
{
|
||||
return impl_->keyboard_tracking_state.has_shortkey_occured;
|
||||
}
|
||||
|
||||
element_store& bedrock::get_element_store() const
|
||||
{
|
||||
return impl_->estore;
|
||||
@@ -700,8 +713,8 @@ namespace detail
|
||||
msgwnd = brock.wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
|
||||
if(nullptr == msgwnd) break;
|
||||
|
||||
if((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.remove_menu();
|
||||
if ((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.erase_menu(true);
|
||||
else
|
||||
brock.close_menu_if_focus_other_window(msgwnd->root);
|
||||
|
||||
@@ -719,7 +732,7 @@ namespace detail
|
||||
if(kill_focus != new_focus)
|
||||
brock.wd_manager.do_lazy_refresh(kill_focus, false);
|
||||
}
|
||||
auto retain = msgwnd->together.event_ptr;
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
msgwnd->root_widget->other.attribute.root->context.focus_changed = false;
|
||||
context.event_window = msgwnd;
|
||||
|
||||
@@ -773,7 +786,7 @@ namespace detail
|
||||
msgwnd->flags.action = mouse_action::normal;
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
auto retain = msgwnd->together.event_ptr;
|
||||
auto retain = msgwnd->together.events_ptr;
|
||||
|
||||
arg_mouse arg;
|
||||
assign_arg(arg, msgwnd, message, xevent);
|
||||
@@ -829,8 +842,11 @@ namespace detail
|
||||
if(brock.wd_manager.available(msgwnd))
|
||||
{
|
||||
//The msgwnd may be destroyed if the window is destroyed by calling native interface of close_window().
|
||||
if(msgwnd->root == brock.get_menu())
|
||||
brock.empty_menu();
|
||||
if (msgwnd->root == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore not decleared
|
||||
}
|
||||
|
||||
spec.remove(native_window);
|
||||
brock.wd_manager.destroy(msgwnd);
|
||||
@@ -929,6 +945,9 @@ namespace detail
|
||||
nana::detail::platform_spec::instance().write_keystate(xevent.xkey);
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
if (brock.get_menu())
|
||||
brock.delay_restore(0); //Enable delay restore
|
||||
|
||||
if(msgwnd->root != brock.get_menu())
|
||||
msgwnd = brock.focus();
|
||||
|
||||
@@ -1011,12 +1030,31 @@ namespace detail
|
||||
else if(keyboard::alt == keychar)
|
||||
{
|
||||
context.is_alt_pressed = true;
|
||||
if (brock.whether_keyboard_shortkey() == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if (msgwnd)
|
||||
{
|
||||
bool focused = (brock.focus() == msgwnd);
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_press;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.ignore = false;
|
||||
arg.key = static_cast<nana::char_t>(keychar);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = (focused && (brock.focus() != msgwnd));
|
||||
}
|
||||
else
|
||||
brock.erase_menu(true);
|
||||
}
|
||||
}
|
||||
else if(keychar)
|
||||
else
|
||||
{
|
||||
arg_keyboard arg;
|
||||
arg.ignore = false;
|
||||
arg.key = keychar;
|
||||
arg.key = keychar ? keychar : xevent.xkey.keycode;
|
||||
arg.evt_code = event_code::key_press;
|
||||
brock.get_key_state(arg);
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@@ -1093,11 +1131,35 @@ namespace detail
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
}
|
||||
brock.delay_restore(2); //Restores while key release
|
||||
}
|
||||
else
|
||||
{
|
||||
context.is_alt_pressed = false;
|
||||
brock.set_keyboard_shortkey(false);
|
||||
if (brock.set_keyboard_shortkey(false) == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if (msgwnd)
|
||||
{
|
||||
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
|
||||
if (set_focus)
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_release;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
arg.ignore = false;
|
||||
arg.key = static_cast<nana::char_t>(context.platform.keychar);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
|
||||
if (!set_focus)
|
||||
{
|
||||
brock.set_menubar_taken(nullptr);
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -580,27 +580,30 @@ namespace nana{
|
||||
//event, when the client receives the event, the specified window has been already
|
||||
//destroyed. This is a feature which is different from Windows. So the following
|
||||
//works should be handled before calling XDestroyWindow.
|
||||
auto & bedrock = bedrock::instance();
|
||||
if(wd == bedrock.get_menu())
|
||||
bedrock.empty_menu();
|
||||
auto & brock = bedrock::instance();
|
||||
if(wd == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore is not decleard
|
||||
}
|
||||
|
||||
Display* disp = restrict::spec.open_display();
|
||||
restrict::spec.remove(wd);
|
||||
auto iwd = bedrock.wd_manager.root(wd);
|
||||
auto iwd = brock.wd_manager.root(wd);
|
||||
if(iwd)
|
||||
{
|
||||
{
|
||||
//Before calling window_manager::destroy, make sure the window is invisible.
|
||||
//It is a behavior like Windows.
|
||||
nana::detail::platform_scope_guard psg;
|
||||
nana::detail::platform_scope_guard lock;
|
||||
restrict::spec.set_error_handler();
|
||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||
::XFlush(disp);
|
||||
restrict::spec.rev_error_handler();
|
||||
}
|
||||
bedrock.wd_manager.destroy(iwd);
|
||||
bedrock.rt_manager.remove_if_exists(iwd);
|
||||
bedrock.wd_manager.destroy_handle(iwd);
|
||||
brock.wd_manager.destroy(iwd);
|
||||
brock.rt_manager.remove_if_exists(iwd);
|
||||
brock.wd_manager.destroy_handle(iwd);
|
||||
}
|
||||
|
||||
nana::detail::platform_scope_guard psg;
|
||||
|
||||
@@ -185,17 +185,18 @@ namespace detail
|
||||
{
|
||||
struct thread_context_cache
|
||||
{
|
||||
unsigned tid = 0;
|
||||
thread_context *object = nullptr;
|
||||
unsigned tid{ 0 };
|
||||
thread_context *object{ nullptr };
|
||||
}tcontext;
|
||||
}cache;
|
||||
|
||||
struct menu_tag
|
||||
{
|
||||
core_window_t* taken_window = nullptr;
|
||||
native_window_type window = nullptr;
|
||||
native_window_type owner = nullptr;
|
||||
bool has_keyboard = false;
|
||||
core_window_t* taken_window{ nullptr };
|
||||
bool delay_restore{ false };
|
||||
native_window_type window{ nullptr };
|
||||
native_window_type owner{ nullptr };
|
||||
bool has_keyboard{false};
|
||||
}menu;
|
||||
|
||||
struct keyboard_tracking_state_tag
|
||||
@@ -921,8 +922,8 @@ namespace detail
|
||||
if(nullptr == msgwnd) break;
|
||||
|
||||
//if event on the menubar, just remove the menu if it is not associating with the menubar
|
||||
if((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.remove_menu();
|
||||
if ((msgwnd == msgwnd->root_widget->other.attribute.root->menubar) && brock.get_menu(msgwnd->root, true))
|
||||
brock.erase_menu(true);
|
||||
else
|
||||
brock.close_menu_if_focus_other_window(msgwnd->root);
|
||||
|
||||
@@ -1322,13 +1323,12 @@ namespace detail
|
||||
def_window_proc = true;
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
if(brock.whether_keyboard_shortkey() == false)
|
||||
if (brock.whether_keyboard_shortkey() == false)
|
||||
{
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if(msgwnd)
|
||||
if (msgwnd)
|
||||
{
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
bool focused = (brock.focus() == msgwnd);
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_press;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@@ -1336,9 +1336,11 @@ namespace detail
|
||||
arg.key = static_cast<nana::char_t>(wParam);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = (focused && (brock.focus() != msgwnd));
|
||||
}
|
||||
else if(brock.get_menu())
|
||||
brock.remove_menu();
|
||||
else
|
||||
brock.erase_menu(true);
|
||||
}
|
||||
def_window_proc = true;
|
||||
break;
|
||||
@@ -1348,6 +1350,10 @@ namespace detail
|
||||
msgwnd = msgwnd->root_widget->other.attribute.root->menubar;
|
||||
if(msgwnd)
|
||||
{
|
||||
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
|
||||
if (set_focus)
|
||||
brock.wd_manager.set_focus(msgwnd, false);
|
||||
|
||||
arg_keyboard arg;
|
||||
arg.evt_code = event_code::key_release;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
@@ -1355,6 +1361,12 @@ namespace detail
|
||||
arg.key = static_cast<nana::char_t>(wParam);
|
||||
brock.get_key_state(arg);
|
||||
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
|
||||
|
||||
if (!set_focus)
|
||||
{
|
||||
brock.set_menubar_taken(nullptr);
|
||||
msgwnd->root_widget->flags.ignore_menubar_focus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
def_window_proc = true;
|
||||
@@ -1362,6 +1374,9 @@ namespace detail
|
||||
case WM_KEYDOWN:
|
||||
if(msgwnd->flags.enabled)
|
||||
{
|
||||
if (brock.get_menu())
|
||||
brock.delay_restore(0); //Enable delay restore
|
||||
|
||||
if(msgwnd->root != brock.get_menu())
|
||||
msgwnd = brock.focus();
|
||||
|
||||
@@ -1431,6 +1446,8 @@ namespace detail
|
||||
}
|
||||
else
|
||||
brock.set_keyboard_shortkey(false);
|
||||
|
||||
brock.delay_restore(2); //Restores while key release
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
{
|
||||
@@ -1448,8 +1465,12 @@ namespace detail
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY:
|
||||
if(msgwnd->root == brock.get_menu())
|
||||
brock.empty_menu();
|
||||
if (msgwnd->root == brock.get_menu())
|
||||
{
|
||||
brock.erase_menu(false);
|
||||
brock.delay_restore(3); //Restores if delay_restore not decleared
|
||||
}
|
||||
|
||||
brock.wd_manager.destroy(msgwnd);
|
||||
|
||||
nana::detail::platform_spec::instance().release_window_icon(msgwnd->root);
|
||||
@@ -1512,14 +1533,39 @@ namespace detail
|
||||
|
||||
void bedrock::set_menubar_taken(core_window_t* wd)
|
||||
{
|
||||
auto pre = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = wd;
|
||||
|
||||
//assigning of a nullptr taken window is to restore the focus of pre taken
|
||||
if ((!wd) && pre)
|
||||
{
|
||||
internal_scope_guard lock;
|
||||
wd_manager.set_focus(pre, false);
|
||||
wd_manager.update(pre, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
bedrock::core_window_t* bedrock::get_menubar_taken()
|
||||
//0:Enable delay, 1:Cancel, 2:Restores, 3: Restores when menu is destroying
|
||||
void bedrock::delay_restore(int state)
|
||||
{
|
||||
core_window_t* wd = impl_->menu.taken_window;
|
||||
impl_->menu.taken_window = nullptr;
|
||||
return wd;
|
||||
switch (state)
|
||||
{
|
||||
case 0: //Enable
|
||||
break;
|
||||
case 1: //Cancel
|
||||
break;
|
||||
case 2: //Restore if key released
|
||||
//restores the focus when menu is closed by pressing keyboard
|
||||
if (!impl_->menu.window)
|
||||
set_menubar_taken(nullptr);
|
||||
break;
|
||||
case 3: //Restores if destroying
|
||||
//when the menu is destroying, restores the focus if delay restore is not declared
|
||||
if (!impl_->menu.delay_restore)
|
||||
set_menubar_taken(nullptr);
|
||||
}
|
||||
|
||||
impl_->menu.delay_restore = (0 == state);
|
||||
}
|
||||
|
||||
bool bedrock::close_menu_if_focus_other_window(native_window_type wd)
|
||||
@@ -1534,7 +1580,7 @@ namespace detail
|
||||
else
|
||||
return false;
|
||||
}
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1544,7 +1590,7 @@ namespace detail
|
||||
{
|
||||
if(menu_wd && impl_->menu.window != menu_wd)
|
||||
{
|
||||
remove_menu();
|
||||
erase_menu(true);
|
||||
|
||||
impl_->menu.window = menu_wd;
|
||||
impl_->menu.owner = native_interface::get_owner_window(menu_wd);
|
||||
@@ -1568,21 +1614,13 @@ namespace detail
|
||||
return impl_->menu.window;
|
||||
}
|
||||
|
||||
void bedrock::remove_menu()
|
||||
void bedrock::erase_menu(bool try_destroy)
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
{
|
||||
auto delwin = impl_->menu.window;
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
native_interface::close_window(delwin);
|
||||
}
|
||||
}
|
||||
|
||||
void bedrock::empty_menu()
|
||||
{
|
||||
if(impl_->menu.window)
|
||||
if (impl_->menu.window)
|
||||
{
|
||||
if (try_destroy)
|
||||
native_interface::close_window(impl_->menu.window);
|
||||
|
||||
impl_->menu.window = impl_->menu.owner = nullptr;
|
||||
impl_->menu.has_keyboard = false;
|
||||
}
|
||||
|
||||
@@ -884,7 +884,8 @@ namespace detail
|
||||
if (wd == wd->root_widget->other.attribute.root->menubar)
|
||||
wd = prev_focus;
|
||||
|
||||
brock.set_menubar_taken(wd);
|
||||
if (wd != wd->root_widget->other.attribute.root->menubar)
|
||||
brock.set_menubar_taken(wd);
|
||||
}
|
||||
return prev_focus;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user