window: support extended urxvt mouse support if applicable
This commit is contained in:
@@ -1958,7 +1958,10 @@ void ToggleAddMode::run()
|
|||||||
void ToggleMouse::run()
|
void ToggleMouse::run()
|
||||||
{
|
{
|
||||||
Config.mouse_support = !Config.mouse_support;
|
Config.mouse_support = !Config.mouse_support;
|
||||||
mousemask(Config.mouse_support ? ALL_MOUSE_EVENTS : 0, 0);
|
if (Config.mouse_support)
|
||||||
|
NC::Mouse::enable();
|
||||||
|
else
|
||||||
|
NC::Mouse::disable();
|
||||||
Statusbar::printf("Mouse support %1%",
|
Statusbar::printf("Mouse support %1%",
|
||||||
Config.mouse_support ? "enabled" : "disabled"
|
Config.mouse_support ? "enabled" : "disabled"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ int main(int argc, char **argv)
|
|||||||
sigignore(SIGINT);
|
sigignore(SIGINT);
|
||||||
# endif // !WIN32
|
# endif // !WIN32
|
||||||
|
|
||||||
NC::initScreen(Config.colors_enabled);
|
NC::initScreen(Config.colors_enabled, Config.mouse_support);
|
||||||
|
|
||||||
Actions::OriginalStatusbarVisibility = Config.statusbar_visibility;
|
Actions::OriginalStatusbarVisibility = Config.statusbar_visibility;
|
||||||
|
|
||||||
@@ -152,13 +152,6 @@ int main(int argc, char **argv)
|
|||||||
auto connect_attempt = boost::posix_time::from_time_t(0);
|
auto connect_attempt = boost::posix_time::from_time_t(0);
|
||||||
auto past = boost::posix_time::from_time_t(0);
|
auto past = boost::posix_time::from_time_t(0);
|
||||||
|
|
||||||
// enable mouse
|
|
||||||
# if NCURSES_SEQUENCE_ESCAPING
|
|
||||||
mouseinterval(0);
|
|
||||||
# endif // NCURSES_SEQUENCE_ESCAPING
|
|
||||||
if (Config.mouse_support)
|
|
||||||
mousemask(ALL_MOUSE_EVENTS, nullptr);
|
|
||||||
|
|
||||||
while (!Actions::ExitMainLoop)
|
while (!Actions::ExitMainLoop)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
412
src/window.cpp
412
src/window.cpp
@@ -306,7 +306,51 @@ std::istream &operator>>(std::istream &is, Color &c)
|
|||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initScreen(bool enable_colors)
|
namespace Mouse {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool mouseEnabled = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable()
|
||||||
|
{
|
||||||
|
if (mouseEnabled)
|
||||||
|
return;
|
||||||
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
|
mousemask(ALL_MOUSE_EVENTS, nullptr);
|
||||||
|
# else
|
||||||
|
// save old highlight mouse tracking
|
||||||
|
printf("\e[?1001s");
|
||||||
|
// enable mouse tracking
|
||||||
|
printf("\e[?1000h");
|
||||||
|
// try to enable extended (urxvt) mouse tracking
|
||||||
|
printf("\e[?1015h");
|
||||||
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
|
mouseEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disable()
|
||||||
|
{
|
||||||
|
if (!mouseEnabled)
|
||||||
|
return;
|
||||||
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
|
mousemask(0, nullptr);
|
||||||
|
# else
|
||||||
|
// disable extended (urxvt) mouse tracking
|
||||||
|
printf("\e[?1015l");
|
||||||
|
// disable mouse tracking
|
||||||
|
printf("\e[?1000l");
|
||||||
|
// restore old highlight mouse tracking
|
||||||
|
printf("\e[?1001r");
|
||||||
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
|
mouseEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void initScreen(bool enable_colors, bool enable_mouse)
|
||||||
{
|
{
|
||||||
initscr();
|
initscr();
|
||||||
if (has_colors() && enable_colors)
|
if (has_colors() && enable_colors)
|
||||||
@@ -325,6 +369,13 @@ void initScreen(bool enable_colors)
|
|||||||
noecho();
|
noecho();
|
||||||
curs_set(0);
|
curs_set(0);
|
||||||
|
|
||||||
|
// setup mouse
|
||||||
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
|
mouseinterval(0);
|
||||||
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
|
if (enable_mouse)
|
||||||
|
Mouse::enable();
|
||||||
|
|
||||||
// initialize readline (needed, otherwise we get segmentation
|
// initialize readline (needed, otherwise we get segmentation
|
||||||
// fault on SIGWINCH). also, initialize first as doing this
|
// fault on SIGWINCH). also, initialize first as doing this
|
||||||
// later erases keys bound with rl_bind_key for some users.
|
// later erases keys bound with rl_bind_key for some users.
|
||||||
@@ -355,6 +406,7 @@ void initScreen(bool enable_colors)
|
|||||||
|
|
||||||
void destroyScreen()
|
void destroyScreen()
|
||||||
{
|
{
|
||||||
|
Mouse::disable();
|
||||||
curs_set(1);
|
curs_set(1);
|
||||||
endwin();
|
endwin();
|
||||||
}
|
}
|
||||||
@@ -693,190 +745,210 @@ int Window::getInputChar()
|
|||||||
# if NCURSES_SEQUENCE_ESCAPING
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
return wgetch(m_window);
|
return wgetch(m_window);
|
||||||
# else
|
# else
|
||||||
ScopedWindowTimeout swt(m_window, 0, m_window_timeout);
|
|
||||||
int key = wgetch(m_window);
|
int key = wgetch(m_window);
|
||||||
if (!m_escape_terminal_sequences || key != KEY_ESCAPE)
|
if (!m_escape_terminal_sequences || key != KEY_ESCAPE)
|
||||||
return key;
|
return key;
|
||||||
|
auto define_mouse_event = [this](int type) {
|
||||||
|
switch (type & ~28)
|
||||||
|
{
|
||||||
|
case 32:
|
||||||
|
m_mouse_event.bstate = BUTTON1_PRESSED;
|
||||||
|
break;
|
||||||
|
case 33:
|
||||||
|
m_mouse_event.bstate = BUTTON2_PRESSED;
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
m_mouse_event.bstate = BUTTON3_PRESSED;
|
||||||
|
break;
|
||||||
|
case 96:
|
||||||
|
m_mouse_event.bstate = BUTTON4_PRESSED;
|
||||||
|
break;
|
||||||
|
case 97:
|
||||||
|
m_mouse_event.bstate = BUTTON5_PRESSED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ERR;
|
||||||
|
}
|
||||||
|
if (type & 4)
|
||||||
|
m_mouse_event.bstate |= BUTTON_SHIFT;
|
||||||
|
if (type & 8)
|
||||||
|
m_mouse_event.bstate |= BUTTON_ALT;
|
||||||
|
if (type & 16)
|
||||||
|
m_mouse_event.bstate |= BUTTON_CTRL;
|
||||||
|
if (m_mouse_event.x < 0 || m_mouse_event.x >= COLS)
|
||||||
|
return ERR;
|
||||||
|
if (m_mouse_event.y < 0 || m_mouse_event.y >= LINES)
|
||||||
|
return ERR;
|
||||||
|
return KEY_MOUSE;
|
||||||
|
};
|
||||||
|
auto parse_number = [this](int &result) {
|
||||||
|
int x;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
x = wgetch(m_window);
|
||||||
|
if (!isdigit(x))
|
||||||
|
return x;
|
||||||
|
result = result*10 + x - '0';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ScopedWindowTimeout swt(m_window, 0, m_window_timeout);
|
||||||
key = wgetch(m_window);
|
key = wgetch(m_window);
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case '\t': // tty
|
case '\t': // tty
|
||||||
|
return KEY_SHIFT_TAB;
|
||||||
|
case 'O': // F1 to F4 in xterm
|
||||||
|
key = wgetch(m_window);
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 'P':
|
||||||
|
key = KEY_F1;
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
key = KEY_F2;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
key = KEY_F3;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
key = KEY_F4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
key = ERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
case '[':
|
||||||
|
key = wgetch(m_window);
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case 'A':
|
||||||
|
return KEY_UP;
|
||||||
|
case 'B':
|
||||||
|
return KEY_DOWN;
|
||||||
|
case 'C':
|
||||||
|
return KEY_RIGHT;
|
||||||
|
case 'D':
|
||||||
|
return KEY_LEFT;
|
||||||
|
case 'F': // xterm
|
||||||
|
return KEY_END;
|
||||||
|
case 'H': // xterm
|
||||||
|
return KEY_HOME;
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
key = wgetch(m_window);
|
||||||
|
int raw_x = wgetch(m_window);
|
||||||
|
int raw_y = wgetch(m_window);
|
||||||
|
// support coordinates up to 255
|
||||||
|
m_mouse_event.x = (raw_x - 33) & 0xff;
|
||||||
|
m_mouse_event.y = (raw_y - 33) & 0xff;
|
||||||
|
return define_mouse_event(key);
|
||||||
|
}
|
||||||
|
case 'Z':
|
||||||
return KEY_SHIFT_TAB;
|
return KEY_SHIFT_TAB;
|
||||||
case 'O': // F1 to F4 in xterm
|
case '[': // F1 to F5 in tty
|
||||||
key = wgetch(m_window);
|
key = wgetch(m_window);
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 'P':
|
case 'A':
|
||||||
key = KEY_F1;
|
key = KEY_F1;
|
||||||
break;
|
break;
|
||||||
case 'Q':
|
case 'B':
|
||||||
key = KEY_F2;
|
key = KEY_F2;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'C':
|
||||||
key = KEY_F3;
|
key = KEY_F3;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'D':
|
||||||
key = KEY_F4;
|
key = KEY_F4;
|
||||||
break;
|
break;
|
||||||
default:
|
case 'E':
|
||||||
key = ERR;
|
key = KEY_F5;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
key = ERR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
case '[':
|
case '1': case '2': case '3':
|
||||||
key = wgetch(m_window);
|
case '4': case '5': case '6':
|
||||||
switch (key)
|
case '7': case '8': case '9':
|
||||||
|
{
|
||||||
|
key -= '0';
|
||||||
|
int delim = parse_number(key);
|
||||||
|
switch (delim)
|
||||||
{
|
{
|
||||||
case 'A':
|
case '~':
|
||||||
return KEY_UP;
|
switch (key)
|
||||||
case 'B':
|
{
|
||||||
return KEY_DOWN;
|
case 1: // tty
|
||||||
case 'C':
|
|
||||||
return KEY_RIGHT;
|
|
||||||
case 'D':
|
|
||||||
return KEY_LEFT;
|
|
||||||
case 'F': // xterm
|
|
||||||
return KEY_END;
|
|
||||||
case 'H': // xterm
|
|
||||||
return KEY_HOME;
|
return KEY_HOME;
|
||||||
case 'M':
|
case 11:
|
||||||
key = wgetch(m_window);
|
return KEY_F1;
|
||||||
m_mouse_event.x = (wgetch(m_window) - 33) & 0xff;
|
case 12:
|
||||||
m_mouse_event.y = (wgetch(m_window) - 33) & 0xff;
|
return KEY_F2;
|
||||||
switch (key & ~24)
|
case 13:
|
||||||
{
|
return KEY_F3;
|
||||||
case ' ':
|
case 14:
|
||||||
m_mouse_event.bstate = BUTTON1_PRESSED;
|
return KEY_F4;
|
||||||
break;
|
case 15:
|
||||||
case '!':
|
return KEY_F5;
|
||||||
m_mouse_event.bstate = BUTTON2_PRESSED;
|
case 17: // not a typo
|
||||||
break;
|
return KEY_F6;
|
||||||
case '"':
|
case 18:
|
||||||
m_mouse_event.bstate = BUTTON3_PRESSED;
|
return KEY_F7;
|
||||||
break;
|
case 19:
|
||||||
case '`':
|
return KEY_F8;
|
||||||
m_mouse_event.bstate = BUTTON4_PRESSED;
|
case 2:
|
||||||
break;
|
return KEY_IC;
|
||||||
case 'a':
|
case 20:
|
||||||
m_mouse_event.bstate = BUTTON5_PRESSED;
|
return KEY_F9;
|
||||||
break;
|
case 21:
|
||||||
default:
|
return KEY_F10;
|
||||||
return ERR;
|
case 23: // not a typo
|
||||||
}
|
return KEY_F11;
|
||||||
if (key & 8)
|
case 24:
|
||||||
m_mouse_event.bstate |= BUTTON_ALT;
|
return KEY_F12;
|
||||||
if (key & 16)
|
case 3:
|
||||||
m_mouse_event.bstate |= BUTTON_CTRL;
|
return KEY_DC;
|
||||||
if (m_mouse_event.x < 0 || m_mouse_event.x >= COLS)
|
case 4:
|
||||||
return ERR;
|
return KEY_END;
|
||||||
if (m_mouse_event.y < 0 || m_mouse_event.y >= LINES)
|
case 5:
|
||||||
return ERR;
|
return KEY_PPAGE;
|
||||||
return KEY_MOUSE;
|
case 6:
|
||||||
case 'Z':
|
return KEY_NPAGE;
|
||||||
return KEY_SHIFT_TAB;
|
case 7:
|
||||||
case '[': // F1 to F5 in tty
|
return KEY_HOME;
|
||||||
key = wgetch(m_window);
|
case 8:
|
||||||
switch (key)
|
return KEY_END;
|
||||||
{
|
|
||||||
case 'A':
|
|
||||||
key = KEY_F1;
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
key = KEY_F2;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
key = KEY_F3;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
key = KEY_F4;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
key = KEY_F5;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
key = ERR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
case '1': // HOME in tty, F1 to F8
|
|
||||||
key = wgetch(m_window);
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case '~':
|
|
||||||
return KEY_HOME;
|
|
||||||
case '1':
|
|
||||||
key = KEY_F1;
|
|
||||||
break;
|
|
||||||
case '2':
|
|
||||||
key = KEY_F2;
|
|
||||||
break;
|
|
||||||
case '3':
|
|
||||||
key = KEY_F3;
|
|
||||||
break;
|
|
||||||
case '4':
|
|
||||||
key = KEY_F4;
|
|
||||||
break;
|
|
||||||
case '5':
|
|
||||||
key = KEY_F5;
|
|
||||||
break;
|
|
||||||
case '7': // not a typo
|
|
||||||
key = KEY_F6;
|
|
||||||
break;
|
|
||||||
case '8':
|
|
||||||
key = KEY_F7;
|
|
||||||
break;
|
|
||||||
case '9':
|
|
||||||
key = KEY_F8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
key = ERR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return wgetch(m_window) == '~' ? key : ERR;
|
|
||||||
case '2': // INSERT, F9 to F12
|
|
||||||
key = wgetch(m_window);
|
|
||||||
switch (key)
|
|
||||||
{
|
|
||||||
case '~':
|
|
||||||
return KEY_IC;
|
|
||||||
case '0':
|
|
||||||
key = KEY_F9;
|
|
||||||
break;
|
|
||||||
case '1':
|
|
||||||
key = KEY_F10;
|
|
||||||
break;
|
|
||||||
case '3': // not a typo
|
|
||||||
key = KEY_F11;
|
|
||||||
break;
|
|
||||||
case '4':
|
|
||||||
key = KEY_F12;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
key = ERR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return wgetch(m_window) == '~' ? key : ERR;
|
|
||||||
case '3':
|
|
||||||
return wgetch(m_window) == '~' ? KEY_DC : ERR;
|
|
||||||
case '4': // tty
|
|
||||||
return wgetch(m_window) == '~' ? KEY_END : ERR;
|
|
||||||
case '5':
|
|
||||||
return wgetch(m_window) == '~' ? KEY_PPAGE : ERR;
|
|
||||||
case '6':
|
|
||||||
return wgetch(m_window) == '~' ? KEY_NPAGE : ERR;
|
|
||||||
case '7':
|
|
||||||
return wgetch(m_window) == '~' ? KEY_HOME : ERR;
|
|
||||||
case '8':
|
|
||||||
return wgetch(m_window) == '~' ? KEY_END : ERR;
|
|
||||||
default:
|
default:
|
||||||
return ERR;
|
return ERR;
|
||||||
|
}
|
||||||
|
case ';': // urxvt mouse
|
||||||
|
m_mouse_event.x = 0;
|
||||||
|
delim = parse_number(m_mouse_event.x);
|
||||||
|
if (delim != ';')
|
||||||
|
return ERR;
|
||||||
|
m_mouse_event.y = 0;
|
||||||
|
delim = parse_number(m_mouse_event.y);
|
||||||
|
if (delim != 'M')
|
||||||
|
return ERR;
|
||||||
|
--m_mouse_event.x;
|
||||||
|
--m_mouse_event.y;
|
||||||
|
return define_mouse_event(key);
|
||||||
|
default:
|
||||||
|
return ERR;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case ERR:
|
|
||||||
return KEY_ESCAPE;
|
|
||||||
default:
|
default:
|
||||||
m_input_queue.push(key);
|
return ERR;
|
||||||
return KEY_ESCAPE;
|
}
|
||||||
|
break;
|
||||||
|
case ERR:
|
||||||
|
return KEY_ESCAPE;
|
||||||
|
default:
|
||||||
|
m_input_queue.push(key);
|
||||||
|
return KEY_ESCAPE;
|
||||||
}
|
}
|
||||||
# endif // NCURSES_SEQUENCE_ESCAPING
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
}
|
}
|
||||||
@@ -935,17 +1007,15 @@ std::string Window::prompt(const std::string &base, size_t width, bool encrypted
|
|||||||
rl::encrypted = encrypted;
|
rl::encrypted = encrypted;
|
||||||
rl::base = base.c_str();
|
rl::base = base.c_str();
|
||||||
|
|
||||||
mmask_t oldmask;
|
|
||||||
|
|
||||||
curs_set(1);
|
curs_set(1);
|
||||||
# if NCURSES_SEQUENCE_ESCAPING
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
keypad(m_window, 0);
|
keypad(m_window, 0);
|
||||||
# endif // NCURSES_SEQUENCE_ESCAPING
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
mousemask(0, &oldmask);
|
Mouse::disable();
|
||||||
m_escape_terminal_sequences = false;
|
m_escape_terminal_sequences = false;
|
||||||
char *input = readline(nullptr);
|
char *input = readline(nullptr);
|
||||||
m_escape_terminal_sequences = true;
|
m_escape_terminal_sequences = true;
|
||||||
mousemask(oldmask, nullptr);
|
Mouse::enable();
|
||||||
# if NCURSES_SEQUENCE_ESCAPING
|
# if NCURSES_SEQUENCE_ESCAPING
|
||||||
keypad(m_window, 1);
|
keypad(m_window, 1);
|
||||||
# endif // NCURSES_SEQUENCE_ESCAPING
|
# endif // NCURSES_SEQUENCE_ESCAPING
|
||||||
|
|||||||
@@ -215,9 +215,16 @@ enum class Format {
|
|||||||
/// This indicates how much the window has to be scrolled
|
/// This indicates how much the window has to be scrolled
|
||||||
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
||||||
|
|
||||||
|
namespace Mouse {
|
||||||
|
|
||||||
|
void enable();
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// Initializes curses screen and sets some additional attributes
|
/// Initializes curses screen and sets some additional attributes
|
||||||
/// @param enable_colors enables colors
|
/// @param enable_colors enables colors
|
||||||
void initScreen(bool enable_colors);
|
void initScreen(bool enable_colors, bool enable_mouse);
|
||||||
|
|
||||||
/// Destroys the screen
|
/// Destroys the screen
|
||||||
void destroyScreen();
|
void destroyScreen();
|
||||||
|
|||||||
Reference in New Issue
Block a user