Skip to content

Commit

Permalink
centralize management of mouse state
Browse files Browse the repository at this point in the history
  • Loading branch information
myk002 committed Oct 1, 2023
1 parent 8ed4890 commit 5d29540
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 47 deletions.
3 changes: 0 additions & 3 deletions ci/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,6 @@ local function click_top_title_button(scr)
df.global.gps.mouse_y = (sh // 2) + 3
end
df.global.gps.precise_mouse_y = df.global.gps.mouse_y * df.global.gps.tile_pixel_y
df.global.enabler.tracking_on = 1
df.global.enabler.mouse_lbut = 1
df.global.enabler.mouse_lbut_down = 1
gui.simulateInput(scr, '_MOUSE_L')
end

Expand Down
8 changes: 8 additions & 0 deletions docs/dev/Lua API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3952,6 +3952,14 @@ Misc
of keycodes to *true* or *false*. For instance, it is possible to use the
table passed as argument to ``onInput``.

You can send mouse clicks as will by setting the ``_MOUSE_L`` key or other
mouse-related pseudo-keys documented with the ``screen:onInput(keys)``
function above. Note that if you are simulating a click at a specific spot on
the screen, you must set ``df.global.gps.mouse_x`` and
``df.global.gps.mouse_y`` if you are clicking on the interface layer or
``df.global.gps.precise_mouse_x`` and ``df.global.gps.precise_mouse_y`` if
you are clickin on the map.

* ``mkdims_xy(x1,y1,x2,y2)``

Returns a table containing the arguments as fields, and also ``width`` and
Expand Down
1 change: 1 addition & 0 deletions library/include/modules/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ namespace DFHack
virtual ~dfhack_lua_viewscreen();

static df::viewscreen *get_pointer(lua_State *L, int idx, bool make);
static void markInputAsHandled();

virtual bool is_lua_screen() { return true; }
virtual bool isFocused() { return !defocused; }
Expand Down
40 changes: 16 additions & 24 deletions library/lua/gui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ TRANSPARENT_PEN = to_pen{tile=0, ch=0}
KEEP_LOWER_PEN = to_pen{ch=32, fg=0, bg=0, keep_lower=true}

local MOUSE_KEYS = {
_MOUSE_L = true,
_MOUSE_R = true,
_MOUSE_L = function(is_set) df.global.enabler.mouse_lbut = is_set and 1 or 0 end,
_MOUSE_R = function(is_set) df.global.enabler.mouse_rbut = is_set and 1 or 0 end,
_MOUSE_M = true,
_MOUSE_L_DOWN = true,
_MOUSE_R_DOWN = true,
Expand All @@ -27,14 +27,18 @@ local FAKE_INPUT_KEYS = copyall(MOUSE_KEYS)
FAKE_INPUT_KEYS._STRING = true

function simulateInput(screen,...)
local keys = {}
local keys, enabled_mouse_keys = {}, {}
local function push_key(arg)
local kv = arg
if type(arg) == 'string' then
kv = df.interface_key[arg]
if kv == nil and not FAKE_INPUT_KEYS[arg] then
error('Invalid keycode: '..arg)
end
if MOUSE_KEYS[arg] then
df.global.enabler.tracking_on = 1
enabled_mouse_keys[arg] = true
end
end
if type(kv) == 'number' then
keys[#keys+1] = kv
Expand All @@ -57,6 +61,11 @@ function simulateInput(screen,...)
end
end
end
for mk, fn in pairs(MOUSE_KEYS) do
if type(fn) == 'function' then
fn(enabled_mouse_keys[mk])
end
end
dscreen._doSimulateInput(screen, keys)
end

Expand Down Expand Up @@ -696,17 +705,6 @@ end

DEFAULT_INITIAL_PAUSE = true

-- ensure underlying DF screens don't also react to handled clicks
function markMouseClicksHandled(keys)
if keys._MOUSE_L then
df.global.enabler.mouse_lbut = 0
end
if keys._MOUSE_R then
df.global.enabler.mouse_rbut_down = 0
df.global.enabler.mouse_rbut = 0
end
end

ZScreen = defclass(ZScreen, Screen)
ZScreen.ATTRS{
defocusable=true,
Expand Down Expand Up @@ -791,23 +789,17 @@ function ZScreen:onInput(keys)
self:raise()
else
self:sendInputToParent(keys)
return
return true
end
end

if ZScreen.super.onInput(self, keys) then
markMouseClicksHandled(keys)
return
end

if self.pass_mouse_clicks and keys._MOUSE_L and not has_mouse then
-- noop
elseif self.pass_mouse_clicks and keys._MOUSE_L and not has_mouse then
self.defocused = self.defocusable
self:sendInputToParent(keys)
return
elseif keys.LEAVESCREEN or keys._MOUSE_R then
self:dismiss()
markMouseClicksHandled(keys)
return
else
local passit = self.pass_pause and keys.D_PAUSE
if not passit and self.pass_mouse_clicks then
Expand All @@ -829,8 +821,8 @@ function ZScreen:onInput(keys)
if passit then
self:sendInputToParent(keys)
end
return
end
return true
end

function ZScreen:raise()
Expand Down
18 changes: 3 additions & 15 deletions library/lua/gui/dialogs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,9 @@ function MessageBox:onInput(keys)
elseif (keys.LEAVESCREEN or keys._MOUSE_R) and self.on_cancel then
self.on_cancel()
end
gui.markMouseClicksHandled(keys)
return true
end
if self:inputToSubviews(keys) then
gui.markMouseClicksHandled(keys)
return true
end
return self:inputToSubviews(keys)
end

function showMessage(title, text, tcolor, on_close)
Expand Down Expand Up @@ -137,13 +133,9 @@ function InputBox:onInput(keys)
if self.on_cancel then
self.on_cancel()
end
gui.markMouseClicksHandled(keys)
return true
end
if self:inputToSubviews(keys) then
gui.markMouseClicksHandled(keys)
return true
end
return self:inputToSubviews(keys)
end

function showInputPrompt(title, text, tcolor, input, on_input, on_cancel, min_width)
Expand Down Expand Up @@ -242,13 +234,9 @@ function ListBox:onInput(keys)
if self.on_cancel then
self.on_cancel()
end
gui.markMouseClicksHandled(keys)
return true
end
if self:inputToSubviews(keys) then
gui.markMouseClicksHandled(keys)
return true
end
return self:inputToSubviews(keys)
end

function showListPrompt(title, text, tcolor, choices, on_select, on_cancel, min_width, filter)
Expand Down
18 changes: 17 additions & 1 deletion library/modules/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,18 @@ int dfhack_lua_viewscreen::do_notify(lua_State *L)
return 1;
}

void dfhack_lua_viewscreen::markInputAsHandled() {
if (!enabler)
return;

// clear text buffer
enabler->last_text_input[0] = '\0';

// mark clicked mouse buttons as handled
enabler->mouse_lbut = 0;
enabler->mouse_rbut = 0;
}

int dfhack_lua_viewscreen::do_input(lua_State *L)
{
auto self = get_self(L);
Expand All @@ -977,7 +989,11 @@ int dfhack_lua_viewscreen::do_input(lua_State *L)
lua_pushvalue(L, -2);
Lua::PushInterfaceKeys(L, Screen::normalize_text_keys(*keys));

lua_call(L, 2, 0);
lua_call(L, 2, 1);
if (lua_toboolean(L, -1))
markInputAsHandled();
lua_pop(L, 1);

self->update_focus(L, -1);
return 0;
}
Expand Down
2 changes: 0 additions & 2 deletions plugins/lua/hotkeys.lua
Original file line number Diff line number Diff line change
Expand Up @@ -280,14 +280,12 @@ function Menu:onInput(keys)
local x = list:getMousePos()
if x == 0 then -- clicked on icon
self:onSubmit2(list:getSelected())
gui.markMouseClicksHandled(keys)
return true
end
if not self:getMouseFramePos() then
self.parent_view:dismiss()
return true
end
gui.markMouseClicksHandled(keys)
end
self:inputToSubviews(keys)
return true -- we're modal
Expand Down
1 change: 0 additions & 1 deletion plugins/lua/overlay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,6 @@ function feed_viewscreen_widgets(vs_name, vs, keys)
not _feed_viewscreen_widgets('all', nil, keys) then
return false
end
gui.markMouseClicksHandled(keys)
return true
end

Expand Down
2 changes: 1 addition & 1 deletion plugins/overlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ struct viewscreen_overlay : T {
if (!input_is_handled)
INTERPOSE_NEXT(feed)(input);
else
enabler->last_text_input[0] = '\0';
dfhack_lua_viewscreen::markInputAsHandled();
}
DEFINE_VMETHOD_INTERPOSE(void, render, ()) {
INTERPOSE_NEXT(render)();
Expand Down

0 comments on commit 5d29540

Please sign in to comment.