mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-10 12:44:53 +00:00
[lua] Add onkeydown/onkeyup events to canvas widget
This commit is contained in:
parent
420278d5a4
commit
17825921e0
@ -182,6 +182,7 @@ if(ENABLE_SCRIPTING)
|
|||||||
script/image_iterator_class.cpp
|
script/image_iterator_class.cpp
|
||||||
script/image_spec_class.cpp
|
script/image_spec_class.cpp
|
||||||
script/images_class.cpp
|
script/images_class.cpp
|
||||||
|
script/keys.cpp
|
||||||
script/layer_class.cpp
|
script/layer_class.cpp
|
||||||
script/layers_class.cpp
|
script/layers_class.cpp
|
||||||
script/luacpp.cpp
|
script/luacpp.cpp
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2022 Igara Studio S.A.
|
// Copyright (c) 2022-2023 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -29,6 +29,15 @@ ui::WidgetType Canvas::Type()
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool Canvas::s_stopKeyEventPropagation = false;
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Canvas::stopKeyEventPropagation()
|
||||||
|
{
|
||||||
|
s_stopKeyEventPropagation = true;
|
||||||
|
}
|
||||||
|
|
||||||
Canvas::Canvas() : ui::Widget(Type())
|
Canvas::Canvas() : ui::Widget(Type())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -64,6 +73,26 @@ bool Canvas::onProcessMessage(ui::Message* msg)
|
|||||||
{
|
{
|
||||||
switch (msg->type()) {
|
switch (msg->type()) {
|
||||||
|
|
||||||
|
case ui::kKeyDownMessage:
|
||||||
|
if (hasFocus()) {
|
||||||
|
s_stopKeyEventPropagation = false;
|
||||||
|
auto keyMsg = static_cast<ui::KeyMessage*>(msg);
|
||||||
|
KeyDown(keyMsg);
|
||||||
|
if (s_stopKeyEventPropagation)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ui::kKeyUpMessage:
|
||||||
|
if (hasFocus()) {
|
||||||
|
s_stopKeyEventPropagation = false;
|
||||||
|
auto keyMsg = static_cast<ui::KeyMessage*>(msg);
|
||||||
|
KeyUp(keyMsg);
|
||||||
|
if (s_stopKeyEventPropagation)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ui::kSetCursorMessage:
|
case ui::kSetCursorMessage:
|
||||||
ui::set_mouse_cursor(m_cursorType);
|
ui::set_mouse_cursor(m_cursorType);
|
||||||
return true;
|
return true;
|
||||||
@ -78,6 +107,9 @@ bool Canvas::onProcessMessage(ui::Message* msg)
|
|||||||
if (!hasCapture())
|
if (!hasCapture())
|
||||||
captureMouse();
|
captureMouse();
|
||||||
|
|
||||||
|
if (isFocusStop() && !hasFocus())
|
||||||
|
requestFocus();
|
||||||
|
|
||||||
auto mouseMsg = static_cast<ui::MouseMessage*>(msg);
|
auto mouseMsg = static_cast<ui::MouseMessage*>(msg);
|
||||||
MouseDown(mouseMsg);
|
MouseDown(mouseMsg);
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (c) 2022 Igara Studio S.A.
|
// Copyright (c) 2022-2023 Igara Studio S.A.
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
// the End-User License Agreement for Aseprite.
|
// the End-User License Agreement for Aseprite.
|
||||||
@ -36,13 +36,19 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
obs::signal<void(GraphicsContext&)> Paint;
|
obs::signal<void(GraphicsContext&)> Paint;
|
||||||
|
obs::signal<void(ui::KeyMessage*)> KeyDown;
|
||||||
|
obs::signal<void(ui::KeyMessage*)> KeyUp;
|
||||||
obs::signal<void(ui::MouseMessage*)> MouseMove;
|
obs::signal<void(ui::MouseMessage*)> MouseMove;
|
||||||
obs::signal<void(ui::MouseMessage*)> MouseDown;
|
obs::signal<void(ui::MouseMessage*)> MouseDown;
|
||||||
obs::signal<void(ui::MouseMessage*)> MouseUp;
|
obs::signal<void(ui::MouseMessage*)> MouseUp;
|
||||||
obs::signal<void(ui::MouseMessage*)> Wheel;
|
obs::signal<void(ui::MouseMessage*)> Wheel;
|
||||||
obs::signal<void(ui::TouchMessage*)> TouchMagnify;
|
obs::signal<void(ui::TouchMessage*)> TouchMagnify;
|
||||||
|
|
||||||
|
static void stopKeyEventPropagation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static bool s_stopKeyEventPropagation;
|
||||||
|
|
||||||
void onInitTheme(ui::InitThemeEvent& ev) override;
|
void onInitTheme(ui::InitThemeEvent& ev) override;
|
||||||
bool onProcessMessage(ui::Message* msg) override;
|
bool onProcessMessage(ui::Message* msg) override;
|
||||||
void onResize(ui::ResizeEvent& ev) override;
|
void onResize(ui::ResizeEvent& ev) override;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Aseprite
|
// Aseprite
|
||||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
// Copyright (C) 2018-2023 Igara Studio S.A.
|
||||||
// Copyright (C) 2018 David Capello
|
// Copyright (C) 2018 David Capello
|
||||||
//
|
//
|
||||||
// This program is distributed under the terms of
|
// This program is distributed under the terms of
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "app/script/canvas_widget.h"
|
#include "app/script/canvas_widget.h"
|
||||||
#include "app/script/engine.h"
|
#include "app/script/engine.h"
|
||||||
#include "app/script/graphics_context.h"
|
#include "app/script/graphics_context.h"
|
||||||
|
#include "app/script/keys.h"
|
||||||
#include "app/script/luacpp.h"
|
#include "app/script/luacpp.h"
|
||||||
#include "app/ui/color_button.h"
|
#include "app/ui/color_button.h"
|
||||||
#include "app/ui/color_shades.h"
|
#include "app/ui/color_shades.h"
|
||||||
@ -914,6 +915,7 @@ int Dialog_canvas(lua_State* L)
|
|||||||
|
|
||||||
widget->setSizeHint(sz);
|
widget->setSizeHint(sz);
|
||||||
|
|
||||||
|
bool handleKeyEvents = false;
|
||||||
if (lua_istable(L, 2)) {
|
if (lua_istable(L, 2)) {
|
||||||
int type = lua_getfield(L, 2, "onpaint");
|
int type = lua_getfield(L, 2, "onpaint");
|
||||||
if (type == LUA_TFUNCTION) {
|
if (type == LUA_TFUNCTION) {
|
||||||
@ -927,6 +929,47 @@ int Dialog_canvas(lua_State* L)
|
|||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// Auxiliary callbacks used in Canvas events
|
// Auxiliary callbacks used in Canvas events
|
||||||
|
auto keyCallback =
|
||||||
|
[](lua_State* L, ui::KeyMessage* msg) {
|
||||||
|
ASSERT(msg->recipient());
|
||||||
|
if (!msg->recipient())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Key modifiers
|
||||||
|
lua_pushboolean(L, msg->modifiers() & ui::kKeyAltModifier);
|
||||||
|
lua_setfield(L, -2, "altKey");
|
||||||
|
|
||||||
|
lua_pushboolean(L, msg->modifiers() & (ui::kKeyCmdModifier | ui::kKeyWinModifier));
|
||||||
|
lua_setfield(L, -2, "metaKey");
|
||||||
|
|
||||||
|
lua_pushboolean(L, msg->modifiers() & ui::kKeyCtrlModifier);
|
||||||
|
lua_setfield(L, -2, "ctrlKey");
|
||||||
|
|
||||||
|
lua_pushboolean(L, msg->modifiers() & ui::kKeyShiftModifier);
|
||||||
|
lua_setfield(L, -2, "shiftKey");
|
||||||
|
|
||||||
|
lua_pushboolean(L, msg->modifiers() & ui::kKeySpaceModifier);
|
||||||
|
lua_setfield(L, -2, "spaceKey");
|
||||||
|
|
||||||
|
// KeyMessage specifics
|
||||||
|
lua_pushinteger(L, msg->repeat());
|
||||||
|
lua_setfield(L, -2, "repeat");
|
||||||
|
|
||||||
|
// TODO improve this (create an Event metatable)
|
||||||
|
lua_pushcfunction(L, [](lua_State*) -> int {
|
||||||
|
Canvas::stopKeyEventPropagation();
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
lua_setfield(L, -2, "stopPropagation");
|
||||||
|
|
||||||
|
std::wstring keyString(1, (wchar_t)msg->unicodeChar());
|
||||||
|
lua_pushstring(L, base::to_utf8(keyString).c_str());
|
||||||
|
lua_setfield(L, -2, "key");
|
||||||
|
|
||||||
|
lua_pushstring(L, vkcode_to_code(msg->scancode()));
|
||||||
|
lua_setfield(L, -2, "code");
|
||||||
|
};
|
||||||
|
|
||||||
auto mouseCallback =
|
auto mouseCallback =
|
||||||
[](lua_State* L, ui::MouseMessage* msg) {
|
[](lua_State* L, ui::MouseMessage* msg) {
|
||||||
ASSERT(msg->recipient());
|
ASSERT(msg->recipient());
|
||||||
@ -970,6 +1013,20 @@ int Dialog_canvas(lua_State* L)
|
|||||||
lua_setfield(L, -2, "magnification");
|
lua_setfield(L, -2, "magnification");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type = lua_getfield(L, 2, "onkeydown");
|
||||||
|
if (type == LUA_TFUNCTION) {
|
||||||
|
Dialog_connect_signal(L, 1, widget->KeyDown, keyCallback);
|
||||||
|
handleKeyEvents = true;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
type = lua_getfield(L, 2, "onkeyup");
|
||||||
|
if (type == LUA_TFUNCTION) {
|
||||||
|
Dialog_connect_signal(L, 1, widget->KeyUp, keyCallback);
|
||||||
|
handleKeyEvents = true;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
type = lua_getfield(L, 2, "onmousemove");
|
type = lua_getfield(L, 2, "onmousemove");
|
||||||
if (type == LUA_TFUNCTION) {
|
if (type == LUA_TFUNCTION) {
|
||||||
Dialog_connect_signal(L, 1, widget->MouseMove, mouseCallback);
|
Dialog_connect_signal(L, 1, widget->MouseMove, mouseCallback);
|
||||||
@ -1000,6 +1057,11 @@ int Dialog_canvas(lua_State* L)
|
|||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this canvas handle keydown/up events, we set it as a focus
|
||||||
|
// stop.
|
||||||
|
if (handleKeyEvents)
|
||||||
|
widget->setFocusStop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Dialog_add_widget(L, widget);
|
return Dialog_add_widget(L, widget);
|
||||||
|
165
src/app/script/keys.cpp
Normal file
165
src/app/script/keys.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2023 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ui/keys.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
namespace script {
|
||||||
|
|
||||||
|
// Same order that os::KeyScancode
|
||||||
|
// Based on code values of the KeyboardEvent on web code:
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
|
||||||
|
static const char* vkcode_to_code_table[] = {
|
||||||
|
"Unidentified",
|
||||||
|
"KeyA",
|
||||||
|
"KeyB",
|
||||||
|
"KeyC",
|
||||||
|
"KeyD",
|
||||||
|
"KeyE",
|
||||||
|
"KeyF",
|
||||||
|
"KeyG",
|
||||||
|
"KeyH",
|
||||||
|
"KeyI",
|
||||||
|
"KeyJ",
|
||||||
|
"KeyK",
|
||||||
|
"KeyL",
|
||||||
|
"KeyM",
|
||||||
|
"KeyN",
|
||||||
|
"KeyO",
|
||||||
|
"KeyP",
|
||||||
|
"KeyQ",
|
||||||
|
"KeyR",
|
||||||
|
"KeyS",
|
||||||
|
"KeyT",
|
||||||
|
"KeyU",
|
||||||
|
"KeyV",
|
||||||
|
"KeyW",
|
||||||
|
"KeyX",
|
||||||
|
"KeyY",
|
||||||
|
"KeyZ",
|
||||||
|
"Digit0",
|
||||||
|
"Digit1",
|
||||||
|
"Digit2",
|
||||||
|
"Digit3",
|
||||||
|
"Digit4",
|
||||||
|
"Digit5",
|
||||||
|
"Digit6",
|
||||||
|
"Digit7",
|
||||||
|
"Digit8",
|
||||||
|
"Digit9",
|
||||||
|
"Numpad0",
|
||||||
|
"Numpad1",
|
||||||
|
"Numpad2",
|
||||||
|
"Numpad3",
|
||||||
|
"Numpad4",
|
||||||
|
"Numpad5",
|
||||||
|
"Numpad6",
|
||||||
|
"Numpad7",
|
||||||
|
"Numpad8",
|
||||||
|
"Numpad9",
|
||||||
|
"F1",
|
||||||
|
"F2",
|
||||||
|
"F3",
|
||||||
|
"F4",
|
||||||
|
"F5",
|
||||||
|
"F6",
|
||||||
|
"F7",
|
||||||
|
"F8",
|
||||||
|
"F9",
|
||||||
|
"F10",
|
||||||
|
"F11",
|
||||||
|
"F12",
|
||||||
|
"Escape",
|
||||||
|
"Backquote",
|
||||||
|
"Minus",
|
||||||
|
"Equal",
|
||||||
|
"Backspace",
|
||||||
|
"Tab",
|
||||||
|
"BracketLeft",
|
||||||
|
"BracketRight",
|
||||||
|
"Enter",
|
||||||
|
"Semicolon",
|
||||||
|
"Quote",
|
||||||
|
"Backslash",
|
||||||
|
nullptr, // kKeyBackslash2,
|
||||||
|
"Comma",
|
||||||
|
"Period",
|
||||||
|
"Slash",
|
||||||
|
"Space",
|
||||||
|
"Insert",
|
||||||
|
"Delete",
|
||||||
|
"Home",
|
||||||
|
"End",
|
||||||
|
"PageUp",
|
||||||
|
"PageDown",
|
||||||
|
"ArrowLeft",
|
||||||
|
"ArrowRight",
|
||||||
|
"ArrowUp",
|
||||||
|
"ArrowDown",
|
||||||
|
"NumpadDivide",
|
||||||
|
"NumpadMultiply",
|
||||||
|
"NumpadSubtract",
|
||||||
|
"NumpadAdd",
|
||||||
|
"NumpadComma",
|
||||||
|
"NumpadEnter",
|
||||||
|
"PrintScreen",
|
||||||
|
"Pause",
|
||||||
|
nullptr, // kKeyAbntC1
|
||||||
|
"IntlYen",
|
||||||
|
"KanaMode",
|
||||||
|
"Convert",
|
||||||
|
"NonConvert",
|
||||||
|
nullptr, // kKeyAt
|
||||||
|
nullptr, // kKeyCircumflex
|
||||||
|
nullptr, // kKeyColon2
|
||||||
|
nullptr, // kKeyKanji
|
||||||
|
"NumpadEqual", // kKeyEqualsPad
|
||||||
|
"Backquote",
|
||||||
|
nullptr, // kKeySemicolon
|
||||||
|
nullptr, // kKeyUnknown1
|
||||||
|
nullptr, // kKeyUnknown2
|
||||||
|
nullptr, // kKeyUnknown3
|
||||||
|
nullptr, // kKeyUnknown4
|
||||||
|
nullptr, // kKeyUnknown5
|
||||||
|
nullptr, // kKeyUnknown6
|
||||||
|
nullptr, // kKeyUnknown7
|
||||||
|
nullptr, // kKeyUnknown8
|
||||||
|
"ShiftLeft",
|
||||||
|
"ShiftRight",
|
||||||
|
"ControlLeft",
|
||||||
|
"ControlRight",
|
||||||
|
"AltLeft",
|
||||||
|
"AltRight"
|
||||||
|
"MetaLeft",
|
||||||
|
"MetaRight",
|
||||||
|
"ContextMenu",
|
||||||
|
"MetaLeft", // kKeyCommand
|
||||||
|
"ScrollLock",
|
||||||
|
"NumLock",
|
||||||
|
"CapsLock",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int vkcode_to_code_table_size =
|
||||||
|
sizeof(vkcode_to_code_table) / sizeof(vkcode_to_code_table[0]);
|
||||||
|
|
||||||
|
const char* vkcode_to_code(const ui::KeyScancode vkcode)
|
||||||
|
{
|
||||||
|
if (vkcode >= 0 &&
|
||||||
|
vkcode < vkcode_to_code_table_size &&
|
||||||
|
vkcode_to_code_table[vkcode]) {
|
||||||
|
return vkcode_to_code_table[vkcode];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return vkcode_to_code_table[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace script
|
||||||
|
} // namespace app
|
21
src/app/script/keys.h
Normal file
21
src/app/script/keys.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Aseprite
|
||||||
|
// Copyright (C) 2023 Igara Studio S.A.
|
||||||
|
//
|
||||||
|
// This program is distributed under the terms of
|
||||||
|
// the End-User License Agreement for Aseprite.
|
||||||
|
|
||||||
|
#ifndef APP_SCRIPT_KEYS_H_INCLUDED
|
||||||
|
#define APP_SCRIPT_KEYS_H_INCLUDED
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/keys.h"
|
||||||
|
|
||||||
|
namespace app {
|
||||||
|
namespace script {
|
||||||
|
|
||||||
|
const char* vkcode_to_code(const ui::KeyScancode vkcode);
|
||||||
|
|
||||||
|
} // namespace script
|
||||||
|
} // namespace app
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user