Added mouse support
If there is a curses library with support to mouse the `curses.KEY_MOUSE` constant will be defined with other constants and functions.
This commit is contained in:
@@ -65,7 +65,6 @@ Notes:
|
|||||||
|
|
||||||
#ifndef LUAJIT
|
#ifndef LUAJIT
|
||||||
# define LUA_COMPAT_5_1
|
# define LUA_COMPAT_5_1
|
||||||
# define LUA_COMPAT_5_3
|
|
||||||
# define LUA_COMPAT_ALL
|
# define LUA_COMPAT_ALL
|
||||||
#endif
|
#endif
|
||||||
#include "luaconf.h"
|
#include "luaconf.h"
|
||||||
@@ -623,7 +622,12 @@ static void register_curses_constants(lua_State *L)
|
|||||||
CC(KEY_CANCEL) CC(KEY_CLOSE) CC(KEY_COMMAND)
|
CC(KEY_CANCEL) CC(KEY_CLOSE) CC(KEY_COMMAND)
|
||||||
CC(KEY_COPY) CC(KEY_CREATE) CC(KEY_END)
|
CC(KEY_COPY) CC(KEY_CREATE) CC(KEY_END)
|
||||||
CC(KEY_EXIT) CC(KEY_FIND) CC(KEY_HELP)
|
CC(KEY_EXIT) CC(KEY_FIND) CC(KEY_HELP)
|
||||||
CC(KEY_MARK) CC(KEY_MESSAGE) CC(KEY_MOUSE)
|
CC(KEY_MARK) CC(KEY_MESSAGE)
|
||||||
|
#ifndef XCURSES
|
||||||
|
#ifndef NOMOUSE
|
||||||
|
CC(KEY_MOUSE)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
CC(KEY_MOVE) CC(KEY_NEXT) CC(KEY_OPEN)
|
CC(KEY_MOVE) CC(KEY_NEXT) CC(KEY_OPEN)
|
||||||
CC(KEY_OPTIONS) CC(KEY_PREVIOUS) CC(KEY_REDO)
|
CC(KEY_OPTIONS) CC(KEY_PREVIOUS) CC(KEY_REDO)
|
||||||
CC(KEY_REFERENCE) CC(KEY_REFRESH) CC(KEY_REPLACE)
|
CC(KEY_REFERENCE) CC(KEY_REFRESH) CC(KEY_REPLACE)
|
||||||
@@ -646,6 +650,29 @@ static void register_curses_constants(lua_State *L)
|
|||||||
CC2(KEY_F6, KEY_F(6)) CC2(KEY_F7, KEY_F(7)) CC2(KEY_F8, KEY_F(8))
|
CC2(KEY_F6, KEY_F(6)) CC2(KEY_F7, KEY_F(7)) CC2(KEY_F8, KEY_F(8))
|
||||||
CC2(KEY_F9, KEY_F(9)) CC2(KEY_F10, KEY_F(10)) CC2(KEY_F11, KEY_F(11))
|
CC2(KEY_F9, KEY_F(9)) CC2(KEY_F10, KEY_F(10)) CC2(KEY_F11, KEY_F(11))
|
||||||
CC2(KEY_F12, KEY_F(12))
|
CC2(KEY_F12, KEY_F(12))
|
||||||
|
#ifndef XCURSES
|
||||||
|
#ifndef NOMOUSE
|
||||||
|
/* Mouse Constants */
|
||||||
|
CC(BUTTON1_RELEASED); CC(BUTTON1_PRESSED); CC(BUTTON1_CLICKED);
|
||||||
|
CC(BUTTON1_DOUBLE_CLICKED); CC(BUTTON1_TRIPLE_CLICKED);
|
||||||
|
CC(BUTTON2_RELEASED); CC(BUTTON2_PRESSED); CC(BUTTON2_CLICKED);
|
||||||
|
CC(BUTTON2_DOUBLE_CLICKED); CC(BUTTON2_TRIPLE_CLICKED);
|
||||||
|
CC(BUTTON3_RELEASED); CC(BUTTON3_PRESSED); CC(BUTTON3_CLICKED);
|
||||||
|
CC(BUTTON3_DOUBLE_CLICKED); CC(BUTTON3_TRIPLE_CLICKED);
|
||||||
|
CC(BUTTON4_RELEASED); CC(BUTTON4_PRESSED); CC(BUTTON4_CLICKED);
|
||||||
|
CC(BUTTON4_DOUBLE_CLICKED); CC(BUTTON4_TRIPLE_CLICKED);
|
||||||
|
CC(BUTTON_CTRL); CC(BUTTON_SHIFT); CC(BUTTON_ALT);
|
||||||
|
CC(REPORT_MOUSE_POSITION); CC(ALL_MOUSE_EVENTS);
|
||||||
|
#if NCURSES_MOUSE_VERSION > 1
|
||||||
|
CC(BUTTON5_RELEASED); CC(BUTTON5_PRESSED); CC(BUTTON5_CLICKED);
|
||||||
|
CC(BUTTON5_DOUBLE_CLICKED); CC(BUTTON5_TRIPLE_CLICKED);
|
||||||
|
#else
|
||||||
|
CC(BUTTON1_RESERVED_EVENT); CC(BUTTON2_RESERVED_EVENT);
|
||||||
|
CC(BUTTON3_RESERVED_EVENT); CC(BUTTON4_RESERVED_EVENT);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -731,6 +758,107 @@ static int lc_stdscr(lua_State *L)
|
|||||||
LC_NUMBER2(COLS, COLS)
|
LC_NUMBER2(COLS, COLS)
|
||||||
LC_NUMBER2(LINES, LINES)
|
LC_NUMBER2(LINES, LINES)
|
||||||
|
|
||||||
|
/*
|
||||||
|
** =======================================================
|
||||||
|
** mouse
|
||||||
|
** =======================================================
|
||||||
|
*/
|
||||||
|
#ifndef XCURSES
|
||||||
|
#ifndef NOMOUSE
|
||||||
|
static int
|
||||||
|
lc_ungetmouse(lua_State *L)
|
||||||
|
{
|
||||||
|
MEVENT e;
|
||||||
|
e.bstate = luaL_checklong(L, 1);
|
||||||
|
e.x = luaL_checkint(L, 2);
|
||||||
|
e.y = luaL_checkint(L, 3);
|
||||||
|
e.z = luaL_checkint(L, 4);
|
||||||
|
e.id = luaL_checkint(L, 5);
|
||||||
|
|
||||||
|
lua_pushboolean(L, !(!ungetmouse(&e)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
Get a new mouse event
|
||||||
|
@function getmouse
|
||||||
|
@treturn unsigned long `bstate`, button state
|
||||||
|
@treturn int `x`, x coordinate
|
||||||
|
@treturn int `y`, y coordinate
|
||||||
|
@treturn int `z`, z coordinate
|
||||||
|
@treturn short `id`, ID to distinguish multiple devices
|
||||||
|
@see getmouse(3x)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lc_getmouse(lua_State *L)
|
||||||
|
{
|
||||||
|
MEVENT e;
|
||||||
|
if(getmouse(&e) == OK)
|
||||||
|
{
|
||||||
|
lua_pushinteger(L, e.bstate);
|
||||||
|
lua_pushinteger(L, e.x);
|
||||||
|
lua_pushinteger(L, e.y);
|
||||||
|
lua_pushinteger(L, e.z);
|
||||||
|
lua_pushinteger(L, e.id);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
Set a new mouse mask
|
||||||
|
@function mousemask
|
||||||
|
@unsigned long `new_mask`, the new mask of mouse events
|
||||||
|
@treturn unsigned long `mask`, with the mask of reported events
|
||||||
|
@treturn unsigned long `oldmask`, with the previous mouse mask
|
||||||
|
@see mousemask(3x)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lc_mousemask(lua_State *L)
|
||||||
|
{
|
||||||
|
mmask_t m = luaL_checkint(L, 1);
|
||||||
|
mmask_t om;
|
||||||
|
m = mousemask(m, &om);
|
||||||
|
lua_pushinteger(L, m);
|
||||||
|
lua_pushinteger(L, om);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
Sets the maximum time (in thousands of a second) that can elapse
|
||||||
|
between press and release events for them to be recognized as a click.
|
||||||
|
@function mouseinterval
|
||||||
|
@int time, the next time to be set or nothing to get the actual.
|
||||||
|
@treturn int returns the previous interval time
|
||||||
|
@see mouseinterval(3x)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lc_mouseinterval(lua_State *L)
|
||||||
|
{
|
||||||
|
if (!lua_gettop(L))
|
||||||
|
lua_pushinteger(L, mouseinterval(-1));
|
||||||
|
else
|
||||||
|
lua_pushinteger(L, mouseinterval(luaL_checkint(L, 1)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
Is the mouse driver initialized
|
||||||
|
@function has_mouse
|
||||||
|
@treturn bool `true`
|
||||||
|
@see has_mouse(3x)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lc_has_mouse(lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushboolean(L, has_mouse());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** =======================================================
|
** =======================================================
|
||||||
** color
|
** color
|
||||||
@@ -2315,6 +2443,16 @@ static const luaL_Reg curseslib[] =
|
|||||||
/* outopts */
|
/* outopts */
|
||||||
{ "nl", lc_nl },
|
{ "nl", lc_nl },
|
||||||
|
|
||||||
|
#ifndef XCURSES
|
||||||
|
#ifndef NOMOUSE
|
||||||
|
{ "mousemask", lc_mousemask },
|
||||||
|
{ "mouseinterval", lc_mouseinterval},
|
||||||
|
{ "has_mouse", lc_has_mouse },
|
||||||
|
{ "getmouse", lc_getmouse },
|
||||||
|
{ "ungetmouse", lc_ungetmouse },
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* slk */
|
/* slk */
|
||||||
ECF(slk_init)
|
ECF(slk_init)
|
||||||
ECF(slk_set)
|
ECF(slk_set)
|
||||||
|
@@ -76,6 +76,8 @@ event:register("cm_max", "cm_quit", "cm_exit", "cm_enter")
|
|||||||
--
|
--
|
||||||
event.keyboard = object {_init = { "key_code", "key_name", "key_meta" }, type = event.ev_keyboard}
|
event.keyboard = object {_init = { "key_code", "key_name", "key_meta" }, type = event.ev_keyboard}
|
||||||
|
|
||||||
|
event.mouse = object {_init = { "bstate", "x", "y", "id" }, type = event.ev_mouse}
|
||||||
|
|
||||||
-- define command event
|
-- define command event
|
||||||
event.command = object {_init = { "command", "extra" }, type = event.ev_command}
|
event.command = object {_init = { "command", "extra" }, type = event.ev_command}
|
||||||
|
|
||||||
|
@@ -44,6 +44,11 @@ function program:init(name, argv)
|
|||||||
-- disable newline
|
-- disable newline
|
||||||
curses.nl(false)
|
curses.nl(false)
|
||||||
|
|
||||||
|
-- init mouse support
|
||||||
|
if curses.KEY_MOUSE then
|
||||||
|
curses.mousemask(curses.BUTTON1_PRESSED)
|
||||||
|
end
|
||||||
|
|
||||||
-- to filter characters being output to the screen
|
-- to filter characters being output to the screen
|
||||||
-- this will filter all characters where a chtype or chstr is used
|
-- this will filter all characters where a chtype or chstr is used
|
||||||
curses.map_output(true)
|
curses.map_output(true)
|
||||||
@@ -135,6 +140,10 @@ function program:event()
|
|||||||
-- get input key
|
-- get input key
|
||||||
local key_code, key_name, key_meta = self:_input_key()
|
local key_code, key_name, key_meta = self:_input_key()
|
||||||
if key_code then
|
if key_code then
|
||||||
|
if key_code == curses.KEY_MOUSE then
|
||||||
|
local s, x, y, z, id = curses.getmouse()
|
||||||
|
return event.mouse{s, x, y, id}
|
||||||
|
end
|
||||||
return event.keyboard{key_code, key_name, key_meta}
|
return event.keyboard{key_code, key_name, key_meta}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
91
tests/getch_test.lua
Normal file
91
tests/getch_test.lua
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
--!A cross-platform terminal ui library based on Lua
|
||||||
|
--
|
||||||
|
-- Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
-- or more contributor license agreements. See the NOTICE file
|
||||||
|
-- distributed with this work for additional information
|
||||||
|
-- regarding copyright ownership. The ASF licenses this file
|
||||||
|
-- to you under the Apache License, Version 2.0 (the
|
||||||
|
-- "License"); you may not use this file except in compliance
|
||||||
|
-- with the License. You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing, software
|
||||||
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
-- See the License for the specific language governing permissions and
|
||||||
|
-- limitations under the License.
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2015-2020, TBOOX Open Source Group.
|
||||||
|
--
|
||||||
|
-- @author ruki
|
||||||
|
-- @file window.lua
|
||||||
|
--
|
||||||
|
require("tests/load")
|
||||||
|
|
||||||
|
-- requires
|
||||||
|
local ltui = require("ltui")
|
||||||
|
local application = ltui.application
|
||||||
|
local event = ltui.event
|
||||||
|
local rect = ltui.rect
|
||||||
|
local window = ltui.window
|
||||||
|
local label = ltui.label
|
||||||
|
|
||||||
|
-- the demo application
|
||||||
|
local demo = application()
|
||||||
|
|
||||||
|
-- init demo
|
||||||
|
function demo:init()
|
||||||
|
|
||||||
|
-- init name
|
||||||
|
application.init(self, "demo")
|
||||||
|
|
||||||
|
-- init background
|
||||||
|
self:background_set("black")
|
||||||
|
|
||||||
|
-- init body window
|
||||||
|
self:insert(self:body_window())
|
||||||
|
|
||||||
|
-- init teste
|
||||||
|
self:body_window():panel():insert(self:teste())
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get body window
|
||||||
|
function demo:body_window()
|
||||||
|
if not self._BODY_WINDOW then
|
||||||
|
self._BODY_WINDOW = window:new("window.body", rect {1, 1, self:width() - 1, self:height() - 1}, "main window")
|
||||||
|
end
|
||||||
|
return self._BODY_WINDOW
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get teste label
|
||||||
|
function demo:teste()
|
||||||
|
if not self._TESTE then
|
||||||
|
self._TESTE = label:new('demo.label', rect {0, 0, 40, 5}, 'this is a test')
|
||||||
|
end
|
||||||
|
return self._TESTE
|
||||||
|
end
|
||||||
|
|
||||||
|
-- on resize
|
||||||
|
function demo:on_resize()
|
||||||
|
self:body_window():bounds_set(rect {1, 1, self:width() - 1, self:height() - 1})
|
||||||
|
application.on_resize(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- on event
|
||||||
|
function demo:on_event(e)
|
||||||
|
if e.type < event.ev_max then
|
||||||
|
self:teste():text_set('tp: ' ..
|
||||||
|
tostring(e.type) ..
|
||||||
|
'; name: ' ..
|
||||||
|
tostring(e.key_name or e.bstate) ..
|
||||||
|
'; code: ' ..
|
||||||
|
tostring(e.key_code or e.x) ..
|
||||||
|
'; meta: ' ..
|
||||||
|
tostring(e.key_code or e.y))
|
||||||
|
end
|
||||||
|
application.on_event(self, e)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- run demo
|
||||||
|
demo:run()
|
Reference in New Issue
Block a user