From 4b52d16bc895f9d969383d7a7d6a3558c1972cc5 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 30 Aug 2016 16:26:57 +0300 Subject: [PATCH] Add an input method subsystem It's necessary for implementing keyboard navigation and virtual keyboards. --- source/dropdown.cpp | 3 +++ source/entry.cpp | 1 + source/image.cpp | 1 - source/indicator.cpp | 5 ----- source/indicator.h | 2 -- source/inputmethod.cpp | 11 ++++++++++ source/inputmethod.h | 28 +++++++++++++++++++++++++ source/label.cpp | 1 - source/panel.cpp | 4 +++- source/root.cpp | 37 ++++++---------------------------- source/root.h | 4 +--- source/systemkeyboardinput.cpp | 37 ++++++++++++++++++++++++++++++++++ source/systemkeyboardinput.h | 27 +++++++++++++++++++++++++ source/widget.cpp | 4 ++-- source/widget.h | 10 ++++++--- 15 files changed, 126 insertions(+), 49 deletions(-) create mode 100644 source/inputmethod.cpp create mode 100644 source/inputmethod.h create mode 100644 source/systemkeyboardinput.cpp create mode 100644 source/systemkeyboardinput.h diff --git a/source/dropdown.cpp b/source/dropdown.cpp index 34ca178..8cc6187 100644 --- a/source/dropdown.cpp +++ b/source/dropdown.cpp @@ -25,6 +25,9 @@ Dropdown::Dropdown(ListData &d): void Dropdown::init() { + // Necessary to have the parent container raise the dropdown on click + input_type = INPUT_TEXT; + dropped = false; add(list); diff --git a/source/entry.cpp b/source/entry.cpp index 43dad5e..16954a7 100644 --- a/source/entry.cpp +++ b/source/entry.cpp @@ -25,6 +25,7 @@ Entry::Entry(const string &t): slider(0), got_key_press(false) { + input_type = INPUT_TEXT; set_text(t); } diff --git a/source/image.cpp b/source/image.cpp index f1180c3..383f906 100644 --- a/source/image.cpp +++ b/source/image.cpp @@ -12,7 +12,6 @@ Image::Image(const GL::Texture2D *i): image(i), keep_aspect(true) { - focusable = false; } void Image::autosize_special(const Part &part, Geometry &ageom) const diff --git a/source/indicator.cpp b/source/indicator.cpp index fba8166..f9f6ed5 100644 --- a/source/indicator.cpp +++ b/source/indicator.cpp @@ -3,11 +3,6 @@ namespace Msp { namespace GLtk { -Indicator::Indicator() -{ - focusable = false; -} - void Indicator::set_active(bool a) { set_state(ACTIVE, (a ? ACTIVE : NORMAL)); diff --git a/source/indicator.h b/source/indicator.h index cf20e31..90c920c 100644 --- a/source/indicator.h +++ b/source/indicator.h @@ -12,8 +12,6 @@ An Indicator visualizes a boolean state. It can be either active or inactive. class Indicator: public Widget { public: - Indicator(); - virtual const char *get_class() const { return "indicator"; } void set_active(bool); diff --git a/source/inputmethod.cpp b/source/inputmethod.cpp new file mode 100644 index 0000000..3062a27 --- /dev/null +++ b/source/inputmethod.cpp @@ -0,0 +1,11 @@ +#include "inputmethod.h" + +namespace Msp { +namespace GLtk { + +InputMethod::InputMethod(Root &r): + root(r) +{ } + +} // namespace GLtk +} // namespace Msp diff --git a/source/inputmethod.h b/source/inputmethod.h new file mode 100644 index 0000000..31cbaf3 --- /dev/null +++ b/source/inputmethod.h @@ -0,0 +1,28 @@ +#ifndef INPUTMETHOD_H_ +#define INPUTMETHOD_H_ + +namespace Msp { +namespace GLtk { + +class Root; + +enum InputType +{ + INPUT_NONE, + INPUT_TEXT +}; + +class InputMethod +{ +protected: + Root &root; + + InputMethod(Root &); +public: + virtual ~InputMethod() { } +}; + +} // namespace GLtk +} // namespace Msp + +#endif diff --git a/source/label.cpp b/source/label.cpp index c59e718..263b2a4 100644 --- a/source/label.cpp +++ b/source/label.cpp @@ -9,7 +9,6 @@ namespace GLtk { Label::Label(const string &t) { - focusable = false; set_text(t); } diff --git a/source/panel.cpp b/source/panel.cpp index f1eef11..44c41ea 100644 --- a/source/panel.cpp +++ b/source/panel.cpp @@ -26,7 +26,9 @@ namespace GLtk { Panel::Panel(): layout(0) -{ } +{ + input_type = INPUT_TEXT; +} Panel::~Panel() { diff --git a/source/root.cpp b/source/root.cpp index c54ab7b..b4c16cf 100644 --- a/source/root.cpp +++ b/source/root.cpp @@ -8,6 +8,7 @@ #include "label.h" #include "style.h" #include "root.h" +#include "systemkeyboardinput.h" namespace Msp { namespace GLtk { @@ -15,6 +16,7 @@ namespace GLtk { Root::Root(const Resources &r, Graphics::Window &window): resources(r), keyboard(new Input::Keyboard(window)), + input_method(0), mouse(new Input::Mouse(window)), touchscreen(0), own_input(true) @@ -25,6 +27,7 @@ Root::Root(const Resources &r, Graphics::Window &window): Root::Root(const Resources &r, Graphics::Window *window, Input::Keyboard *k, Input::Mouse *m, Input::Touchscreen *t): resources(r), keyboard(k), + input_method(0), mouse(m), touchscreen(t), own_input(false) @@ -64,12 +67,8 @@ void Root::init(Graphics::Window *window) mouse->signal_axis_motion.connect(sigc::mem_fun(this, &Root::axis_motion_event)); } - if(keyboard) - { - keyboard->signal_button_press.connect(sigc::mem_fun(this, &Root::key_press_event)); - keyboard->signal_button_release.connect(sigc::mem_fun(this, &Root::key_release_event)); - keyboard->signal_character.connect(sigc::mem_fun(this, &Root::character_event)); - } + if(keyboard && !input_method) + input_method = new SystemKeyboardInput(*this, *keyboard); if(touchscreen) { @@ -82,6 +81,7 @@ void Root::init(Graphics::Window *window) Root::~Root() { delete shprog; + delete input_method; if(own_input) { delete keyboard; @@ -206,31 +206,6 @@ bool Root::axis_motion_event(unsigned, float, float) return false; } -bool Root::key_press_event(unsigned key) -{ - // XXX Modifiers - if(visible) - return key_press(key, 0); - - return false; -} - -bool Root::key_release_event(unsigned key) -{ - if(visible) - return key_release(key, 0); - - return false; -} - -bool Root::character_event(StringCodec::unichar ch) -{ - if(visible) - return character(ch); - - return false; -} - bool Root::touch_press_event(unsigned finger) { if(visible) diff --git a/source/root.h b/source/root.h index 5d721c0..b0751b6 100644 --- a/source/root.h +++ b/source/root.h @@ -28,6 +28,7 @@ public: private: const Resources &resources; Input::Keyboard *keyboard; + InputMethod *input_method; Input::Mouse *mouse; Input::Touchscreen *touchscreen; bool own_input; @@ -65,9 +66,6 @@ private: bool button_press_event(unsigned); bool button_release_event(unsigned); bool axis_motion_event(unsigned, float, float); - bool key_press_event(unsigned); - bool key_release_event(unsigned); - bool character_event(StringCodec::unichar); bool touch_press_event(unsigned); bool touch_release_event(unsigned); bool touch_motion_event(unsigned, float, float); diff --git a/source/systemkeyboardinput.cpp b/source/systemkeyboardinput.cpp new file mode 100644 index 0000000..cedddd1 --- /dev/null +++ b/source/systemkeyboardinput.cpp @@ -0,0 +1,37 @@ +#include +#include "root.h" +#include "systemkeyboardinput.h" + +namespace Msp { +namespace GLtk { + +SystemKeyboardInput::SystemKeyboardInput(Root &r, Input::Keyboard &k): + InputMethod(r), + keyboard(k) +{ + keyboard.signal_button_press.connect(sigc::mem_fun(this, &SystemKeyboardInput::key_press)); + keyboard.signal_button_release.connect(sigc::mem_fun(this, &SystemKeyboardInput::key_release)); + keyboard.signal_character.connect(sigc::mem_fun(this, &SystemKeyboardInput::character)); +} + +bool SystemKeyboardInput::key_press(unsigned key) +{ + // TODO modifiers + if(root.key_press(key, 0)) + return true; + + return false; +} + +bool SystemKeyboardInput::key_release(unsigned key) +{ + return root.key_release(key, 0); +} + +bool SystemKeyboardInput::character(StringCodec::unichar ch) +{ + return root.character(ch); +} + +} // namespace GLtk +} // namespace Msp diff --git a/source/systemkeyboardinput.h b/source/systemkeyboardinput.h new file mode 100644 index 0000000..ae988ca --- /dev/null +++ b/source/systemkeyboardinput.h @@ -0,0 +1,27 @@ +#ifndef MSP_GLTK_SYSTEMKEYBOARDINPUT_H_ +#define MSP_GLTK_SYSTEMKEYBOARDINPUT_H_ + +#include +#include "inputmethod.h" + +namespace Msp { +namespace GLtk { + +class SystemKeyboardInput: public InputMethod, public sigc::trackable +{ +private: + Input::Keyboard &keyboard; + +public: + SystemKeyboardInput(Root &, Input::Keyboard &); + +private: + bool key_press(unsigned); + bool key_release(unsigned); + bool character(StringCodec::unichar); +}; + +} // namespace GLtk +} // namespace Msp + +#endif diff --git a/source/widget.cpp b/source/widget.cpp index 38f8e92..5fc2082 100644 --- a/source/widget.cpp +++ b/source/widget.cpp @@ -14,7 +14,7 @@ Widget::Widget(): style(0), state(NORMAL), visible(true), - focusable(true), + input_type(INPUT_NONE), parent(0) { } @@ -162,7 +162,7 @@ void Widget::set_visible(bool v) void Widget::set_focusable(bool f) { - focusable = f; + input_type = (f ? INPUT_TEXT : INPUT_NONE); } void Widget::set_focus() diff --git a/source/widget.h b/source/widget.h index f852ec3..f1a83f7 100644 --- a/source/widget.h +++ b/source/widget.h @@ -5,6 +5,7 @@ #include #include #include "geometry.h" +#include "inputmethod.h" #include "partcache.h" #include "state.h" @@ -46,7 +47,7 @@ protected: const Style *style; State state; bool visible; - bool focusable; + InputType input_type; Container *parent; std::string tooltip; PartCache part_cache; @@ -107,12 +108,15 @@ public: void set_visible(bool); bool is_visible() const { return visible; } - void set_focusable(bool); - bool is_focusable() const { return focusable; } + InputType get_input_type() const { return input_type; } + bool is_focusable() const { return visible && input_type!=INPUT_NONE; } void set_focus(); void set_enabled(bool); bool is_enabled() const { return !(state&DISABLED); } + // Deprecated + void set_focusable(bool); + protected: void set_state(State s) { set_state(s, s); } void clear_state(State s) { set_state(s, NORMAL); } -- 2.43.0