implement keyboard accelerators for linux
This commit is contained in:
parent
244416088f
commit
457d86aa39
@ -104,9 +104,40 @@ namespace detail
|
|||||||
void window_proc_for_packet(Display *, nana::detail::msg_packet_tag&);
|
void window_proc_for_packet(Display *, nana::detail::msg_packet_tag&);
|
||||||
void window_proc_for_xevent(Display*, XEvent&);
|
void window_proc_for_xevent(Display*, XEvent&);
|
||||||
|
|
||||||
|
class accel_key_comparer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool operator()(const accel_key& a, const accel_key& b) const
|
||||||
|
{
|
||||||
|
auto va = a.case_sensitive ? a.key : std::tolower(a.key);
|
||||||
|
auto vb = b.case_sensitive ? b.key : std::tolower(b.key);
|
||||||
|
|
||||||
|
if(va < vb)
|
||||||
|
return true;
|
||||||
|
else if(va > vb)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (a.case_sensitive != b.case_sensitive)
|
||||||
|
return b.case_sensitive;
|
||||||
|
|
||||||
|
if (a.alt != b.alt)
|
||||||
|
return b.alt;
|
||||||
|
|
||||||
|
if (a.ctrl != b.ctrl)
|
||||||
|
return b.ctrl;
|
||||||
|
|
||||||
|
return ((a.shift != b.shift) && b.shift);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct accel_key_value
|
||||||
|
{
|
||||||
|
std::function<void()> command;
|
||||||
|
};
|
||||||
|
|
||||||
struct window_platform_assoc
|
struct window_platform_assoc
|
||||||
{
|
{
|
||||||
//Wait...
|
std::map<accel_key, accel_key_value, accel_key_comparer> accel_commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
//class bedrock defines a static object itself to implement a static singleton
|
//class bedrock defines a static object itself to implement a static singleton
|
||||||
@ -233,9 +264,16 @@ namespace detail
|
|||||||
delete passoc;
|
delete passoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bedrock::keyboard_accelerator(native_window_type, const accel_key&, const std::function<void()>& fn)
|
void bedrock::keyboard_accelerator(native_window_type wd, const accel_key& ackey, const std::function<void()>& fn)
|
||||||
{
|
{
|
||||||
|
auto misc = wd_manager().root_runtime(wd);
|
||||||
|
if (nullptr == misc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!misc->wpassoc)
|
||||||
|
misc->wpassoc = new window_platform_assoc;
|
||||||
|
|
||||||
|
misc->wpassoc->accel_commands[ackey].command = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
element_store& bedrock::get_element_store() const
|
element_store& bedrock::get_element_store() const
|
||||||
@ -506,6 +544,34 @@ namespace detail
|
|||||||
return wchar_t(keysym);
|
return wchar_t(keysym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool translate_keyboard_accelerator(root_misc* misc, char os_code, const arg_keyboard& modifiers)
|
||||||
|
{
|
||||||
|
if(!misc->wpassoc)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto lower_oc = std::tolower(os_code);
|
||||||
|
|
||||||
|
std::function<void()> command;
|
||||||
|
|
||||||
|
for(auto & accel : misc->wpassoc->accel_commands)
|
||||||
|
{
|
||||||
|
if(accel.first.key != (accel.first.case_sensitive ? os_code : lower_oc))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(accel.first.alt == modifiers.alt && accel.first.ctrl == modifiers.ctrl && accel.first.shift == modifiers.shift)
|
||||||
|
{
|
||||||
|
command = accel.second.command;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!command)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
command();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
|
void window_proc_for_xevent(Display* /*display*/, XEvent& xevent)
|
||||||
{
|
{
|
||||||
typedef detail::bedrock::core_window_t core_window_t;
|
typedef detail::bedrock::core_window_t core_window_t;
|
||||||
@ -865,6 +931,9 @@ namespace detail
|
|||||||
|
|
||||||
if(msgwnd)
|
if(msgwnd)
|
||||||
{
|
{
|
||||||
|
arg_keyboard modifiers_status;
|
||||||
|
brock.get_key_state(modifiers_status);
|
||||||
|
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
Status status;
|
Status status;
|
||||||
char fixbuf[33];
|
char fixbuf[33];
|
||||||
@ -899,16 +968,20 @@ namespace detail
|
|||||||
|
|
||||||
keybuf[len] = 0;
|
keybuf[len] = 0;
|
||||||
wchar_t os_code = 0;
|
wchar_t os_code = 0;
|
||||||
|
bool accel_translated = false;
|
||||||
|
|
||||||
switch(status)
|
switch(status)
|
||||||
{
|
{
|
||||||
case XLookupKeySym:
|
case XLookupKeySym:
|
||||||
case XLookupBoth:
|
case XLookupBoth:
|
||||||
os_code = os_code_from_keysym(keysym);
|
os_code = os_code_from_keysym(keysym);
|
||||||
|
accel_translated = translate_keyboard_accelerator(root_runtime, os_code, modifiers_status);
|
||||||
|
if(accel_translated)
|
||||||
|
break;
|
||||||
|
|
||||||
if(os_code == keyboard::tab && (false == (msgwnd->flags.tab & detail::tab_type::eating))) //Tab
|
if(os_code == keyboard::tab && (false == (msgwnd->flags.tab & detail::tab_type::eating))) //Tab
|
||||||
{
|
{
|
||||||
arg_keyboard argkey;
|
auto tstop_wd = wd_manager.tabstop(msgwnd, !modifiers_status.shift);
|
||||||
brock.get_key_state(argkey);
|
|
||||||
auto tstop_wd = wd_manager.tabstop(msgwnd, !argkey.shift);
|
|
||||||
if (tstop_wd)
|
if (tstop_wd)
|
||||||
{
|
{
|
||||||
root_runtime->condition.ignore_tab = true;
|
root_runtime->condition.ignore_tab = true;
|
||||||
@ -923,9 +996,9 @@ namespace detail
|
|||||||
if((nullptr == pressed_wd) && (nullptr == pressed_wd_space))
|
if((nullptr == pressed_wd) && (nullptr == pressed_wd_space))
|
||||||
{
|
{
|
||||||
arg_mouse arg;
|
arg_mouse arg;
|
||||||
arg.alt = false;
|
arg.alt = modifiers_status.alt;
|
||||||
arg.button = ::nana::mouse::left_button;
|
arg.button = ::nana::mouse::left_button;
|
||||||
arg.ctrl = false;
|
arg.ctrl = modifiers_status.ctrl;
|
||||||
arg.evt_code = event_code::mouse_down;
|
arg.evt_code = event_code::mouse_down;
|
||||||
arg.left_button = true;
|
arg.left_button = true;
|
||||||
arg.mid_button = false;
|
arg.mid_button = false;
|
||||||
@ -971,11 +1044,10 @@ namespace detail
|
|||||||
if(keyboard::os_ctrl == os_code)
|
if(keyboard::os_ctrl == os_code)
|
||||||
context.is_ctrl_pressed = true;
|
context.is_ctrl_pressed = true;
|
||||||
|
|
||||||
arg_keyboard arg;
|
arg_keyboard arg = modifiers_status;
|
||||||
arg.ignore = false;
|
arg.ignore = false;
|
||||||
arg.key = os_code;
|
arg.key = os_code;
|
||||||
arg.evt_code = event_code::key_press;
|
arg.evt_code = event_code::key_press;
|
||||||
brock.get_key_state(arg);
|
|
||||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||||
|
|
||||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||||
@ -1004,7 +1076,7 @@ namespace detail
|
|||||||
|
|
||||||
for(int i = 0; i < len; ++i)
|
for(int i = 0; i < len; ++i)
|
||||||
{
|
{
|
||||||
arg_keyboard arg;
|
arg_keyboard arg = modifiers_status;
|
||||||
arg.ignore = false;
|
arg.ignore = false;
|
||||||
arg.key = charbuf[i];
|
arg.key = charbuf[i];
|
||||||
|
|
||||||
@ -1027,7 +1099,6 @@ namespace detail
|
|||||||
}
|
}
|
||||||
arg.evt_code = event_code::key_char;
|
arg.evt_code = event_code::key_char;
|
||||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||||
brock.get_key_state(arg);
|
|
||||||
msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwnd));
|
msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwnd));
|
||||||
if(arg.ignore == false && wd_manager.available(msgwnd))
|
if(arg.ignore == false && wd_manager.available(msgwnd))
|
||||||
draw_invoker(&drawer::key_char, msgwnd, arg, &context);
|
draw_invoker(&drawer::key_char, msgwnd, arg, &context);
|
||||||
|
|||||||
@ -1651,7 +1651,6 @@ namespace detail
|
|||||||
if (nullptr == misc)
|
if (nullptr == misc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto wpassoc = misc->wpassoc;
|
|
||||||
if (!misc->wpassoc)
|
if (!misc->wpassoc)
|
||||||
misc->wpassoc = new window_platform_assoc;
|
misc->wpassoc = new window_platform_assoc;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user