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_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
|
||||
{
|
||||
//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
|
||||
@ -233,9 +264,16 @@ namespace detail
|
||||
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
|
||||
@ -506,6 +544,34 @@ namespace detail
|
||||
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)
|
||||
{
|
||||
typedef detail::bedrock::core_window_t core_window_t;
|
||||
@ -865,6 +931,9 @@ namespace detail
|
||||
|
||||
if(msgwnd)
|
||||
{
|
||||
arg_keyboard modifiers_status;
|
||||
brock.get_key_state(modifiers_status);
|
||||
|
||||
KeySym keysym;
|
||||
Status status;
|
||||
char fixbuf[33];
|
||||
@ -899,16 +968,20 @@ namespace detail
|
||||
|
||||
keybuf[len] = 0;
|
||||
wchar_t os_code = 0;
|
||||
bool accel_translated = false;
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case XLookupKeySym:
|
||||
case XLookupBoth:
|
||||
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
|
||||
{
|
||||
arg_keyboard argkey;
|
||||
brock.get_key_state(argkey);
|
||||
auto tstop_wd = wd_manager.tabstop(msgwnd, !argkey.shift);
|
||||
auto tstop_wd = wd_manager.tabstop(msgwnd, !modifiers_status.shift);
|
||||
if (tstop_wd)
|
||||
{
|
||||
root_runtime->condition.ignore_tab = true;
|
||||
@ -923,9 +996,9 @@ namespace detail
|
||||
if((nullptr == pressed_wd) && (nullptr == pressed_wd_space))
|
||||
{
|
||||
arg_mouse arg;
|
||||
arg.alt = false;
|
||||
arg.alt = modifiers_status.alt;
|
||||
arg.button = ::nana::mouse::left_button;
|
||||
arg.ctrl = false;
|
||||
arg.ctrl = modifiers_status.ctrl;
|
||||
arg.evt_code = event_code::mouse_down;
|
||||
arg.left_button = true;
|
||||
arg.mid_button = false;
|
||||
@ -971,11 +1044,10 @@ namespace detail
|
||||
if(keyboard::os_ctrl == os_code)
|
||||
context.is_ctrl_pressed = true;
|
||||
|
||||
arg_keyboard arg;
|
||||
arg_keyboard arg = modifiers_status;
|
||||
arg.ignore = false;
|
||||
arg.key = os_code;
|
||||
arg.evt_code = event_code::key_press;
|
||||
brock.get_key_state(arg);
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
|
||||
brock.emit(event_code::key_press, msgwnd, arg, true, &context);
|
||||
@ -1004,7 +1076,7 @@ namespace detail
|
||||
|
||||
for(int i = 0; i < len; ++i)
|
||||
{
|
||||
arg_keyboard arg;
|
||||
arg_keyboard arg = modifiers_status;
|
||||
arg.ignore = false;
|
||||
arg.key = charbuf[i];
|
||||
|
||||
@ -1027,7 +1099,6 @@ namespace detail
|
||||
}
|
||||
arg.evt_code = event_code::key_char;
|
||||
arg.window_handle = reinterpret_cast<window>(msgwnd);
|
||||
brock.get_key_state(arg);
|
||||
msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast<window>(msgwnd));
|
||||
if(arg.ignore == false && wd_manager.available(msgwnd))
|
||||
draw_invoker(&drawer::key_char, msgwnd, arg, &context);
|
||||
|
||||
@ -1650,8 +1650,7 @@ namespace detail
|
||||
auto misc = wd_manager().root_runtime(wd);
|
||||
if (nullptr == misc)
|
||||
return;
|
||||
|
||||
auto wpassoc = misc->wpassoc;
|
||||
|
||||
if (!misc->wpassoc)
|
||||
misc->wpassoc = new window_platform_assoc;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user