summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2015-03-22 10:08:44 +0000
committerMaxime Coste <frrrwww@gmail.com>2015-03-22 11:41:20 +0000
commit5eaf472fc0fd0d2e5a76ab91f685ea89018a6d33 (patch)
treeb9fcf32d5be1004248bc5d6c78a6134fdc8e03e0 /src
parentdef33de9bc78cb8109034ed5e015b5b39316cd55 (diff)
Experimental support for mouse
Diffstat (limited to 'src')
-rw-r--r--src/input_handler.cc47
-rw-r--r--src/keys.hh15
-rw-r--r--src/ncurses_ui.cc18
3 files changed, 78 insertions, 2 deletions
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 08412a02..7b6339ff 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -49,6 +49,45 @@ namespace InputModes
static constexpr std::chrono::milliseconds idle_timeout{50};
static constexpr std::chrono::milliseconds fs_check_timeout{500};
+struct MouseHandler
+{
+ bool handle_key(Key key, Context& context)
+ {
+ if (not context.has_window())
+ return false;
+
+ if (key.modifiers == Key::Modifiers::MousePress)
+ {
+ m_dragging = true;
+ m_anchor = context.window().buffer_coord(key.mouse_coord());
+ context.selections() = SelectionList{ context.buffer(), m_anchor };
+ return true;
+ }
+ if (key.modifiers == Key::Modifiers::MouseRelease)
+ {
+ if (not m_dragging)
+ return true;
+ m_dragging = false;
+ auto cursor = context.window().buffer_coord(key.mouse_coord());
+ context.selections() = SelectionList{ context.buffer(), Selection{m_anchor, cursor} };
+ return true;
+ }
+ if (key.modifiers == Key::Modifiers::MousePos)
+ {
+ if (not m_dragging)
+ return true;
+ auto cursor = context.window().buffer_coord(key.mouse_coord());
+ context.selections() = SelectionList{ context.buffer(), Selection{m_anchor, cursor} };
+ return true;
+ }
+ return false;
+ }
+
+private:
+ bool m_dragging = false;
+ ByteCoord m_anchor;
+};
+
class Normal : public InputMode
{
public:
@@ -87,6 +126,9 @@ public:
void on_key(Key key) override
{
+ if (m_mouse_handler.handle_key(key, context()))
+ return;
+
if (m_waiting_for_reg)
{
if (key.modifiers == Key::Modifiers::None)
@@ -139,6 +181,7 @@ public:
}
m_params = { 0, '"' };
}
+
context().hooks().run_hook("NormalKey", key_to_str(key), context());
m_idle_timer.set_next_date(Clock::now() + idle_timeout);
}
@@ -167,6 +210,7 @@ private:
bool m_waiting_for_reg = false;
Timer m_idle_timer;
Timer m_fs_check_timer;
+ MouseHandler m_mouse_handler;
};
template<WordType word_type>
@@ -1109,7 +1153,8 @@ void InputHandler::on_next_key(KeymapMode keymap_mode, KeyCallback callback)
static bool is_valid(Key key)
{
- return key != Key::Invalid and key.key <= 0x10FFFF;
+ return key != Key::Invalid and
+ ((key.modifiers & ~Key::Modifiers::ControlAlt) or key.key <= 0x10FFFF);
}
void InputHandler::handle_key(Key key)
diff --git a/src/keys.hh b/src/keys.hh
index c83e1361..54c6e175 100644
--- a/src/keys.hh
+++ b/src/keys.hh
@@ -5,6 +5,7 @@
#include "flags.hh"
#include "hash.hh"
#include "vector.hh"
+#include "coord.hh"
namespace Kakoune
{
@@ -16,7 +17,11 @@ struct Key
None = 0,
Control = 1 << 0,
Alt = 1 << 1,
- ControlAlt = Control | Alt
+ ControlAlt = Control | Alt,
+
+ MousePress = 1 << 2,
+ MouseRelease = 1 << 3,
+ MousePos = 1 << 4,
};
enum NamedKey : Codepoint
{
@@ -62,6 +67,8 @@ struct Key
constexpr bool operator==(Key other) const { return val() == other.val(); }
constexpr bool operator!=(Key other) const { return val() != other.val(); }
constexpr bool operator<(Key other) const { return val() < other.val(); }
+
+ constexpr CharCoord mouse_coord() const { return {(int)((key & 0xFFFF0000) >> 16), (int)(key & 0x0000FFFF)}; }
};
template<> struct WithBitOps<Key::Modifiers> : std::true_type {};
@@ -78,6 +85,12 @@ constexpr Key alt(Codepoint key) { return { Key::Modifiers::Alt, key }; }
constexpr Key ctrl(Codepoint key) { return { Key::Modifiers::Control, key }; }
constexpr Key ctrlalt(Codepoint key) { return { Key::Modifiers::ControlAlt, key }; }
+constexpr Codepoint encode_mouse_coord(CharCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
+
+constexpr Key mouse_press(CharCoord pos) { return { Key::Modifiers::MousePress, encode_mouse_coord(pos) }; }
+constexpr Key mouse_release(CharCoord pos) { return { Key::Modifiers::MouseRelease, encode_mouse_coord(pos) }; }
+constexpr Key mouse_pos(CharCoord pos) { return { Key::Modifiers::MousePos, encode_mouse_coord(pos) }; }
+
inline size_t hash_value(const Key& key) { return hash_values(key.modifiers, key.key); }
}
diff --git a/src/ncurses_ui.cc b/src/ncurses_ui.cc
index 13de9fd2..55dc3f75 100644
--- a/src/ncurses_ui.cc
+++ b/src/ncurses_ui.cc
@@ -260,6 +260,10 @@ NCursesUI::NCursesUI()
signal(SIGWINCH, on_term_resize);
signal(SIGINT, on_sigint);
+ mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nullptr);
+ mouseinterval(0);
+ // force enable report mouse position
+ printf("\033[?1002h");
update_dimensions();
wrefresh(stdscr);
@@ -267,6 +271,7 @@ NCursesUI::NCursesUI()
NCursesUI::~NCursesUI()
{
+ printf("\033[?1002l");
endwin();
signal(SIGWINCH, SIG_DFL);
signal(SIGINT, SIG_DFL);
@@ -442,6 +447,19 @@ Key NCursesUI::get_key()
check_resize();
const int c = getch();
+
+ if (c == KEY_MOUSE)
+ {
+ MEVENT ev;
+ if (getmouse(&ev) == OK)
+ {
+ CharCoord pos{ ev.y, ev.x };
+ if ((ev.bstate & BUTTON1_PRESSED) == BUTTON1_PRESSED) return mouse_press(pos);
+ if ((ev.bstate & BUTTON1_RELEASED) == BUTTON1_RELEASED) return mouse_release(pos);
+ else return mouse_pos(pos);
+ }
+ }
+
if (c > 0 and c < 27)
{
if (c == CTRL('l'))