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
|
||||
# define LUA_COMPAT_5_1
|
||||
# define LUA_COMPAT_5_3
|
||||
# define LUA_COMPAT_ALL
|
||||
#endif
|
||||
#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_COPY) CC(KEY_CREATE) CC(KEY_END)
|
||||
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_OPTIONS) CC(KEY_PREVIOUS) CC(KEY_REDO)
|
||||
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_F9, KEY_F(9)) CC2(KEY_F10, KEY_F(10)) CC2(KEY_F11, KEY_F(11))
|
||||
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(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
|
||||
@@ -2315,6 +2443,16 @@ static const luaL_Reg curseslib[] =
|
||||
/* outopts */
|
||||
{ "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 */
|
||||
ECF(slk_init)
|
||||
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.mouse = object {_init = { "bstate", "x", "y", "id" }, type = event.ev_mouse}
|
||||
|
||||
-- define command event
|
||||
event.command = object {_init = { "command", "extra" }, type = event.ev_command}
|
||||
|
||||
|
@@ -44,6 +44,11 @@ function program:init(name, argv)
|
||||
-- disable newline
|
||||
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
|
||||
-- this will filter all characters where a chtype or chstr is used
|
||||
curses.map_output(true)
|
||||
@@ -135,6 +140,10 @@ function program:event()
|
||||
-- get input key
|
||||
local key_code, key_name, key_meta = self:_input_key()
|
||||
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}
|
||||
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