diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9c148058..00228be82 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: args: ['--fix=lf'] - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.26.3 + rev: 0.27.0 hooks: - id: check-github-workflows - repo: https://github.com/Lucas-C/pre-commit-hooks diff --git a/ci/test.lua b/ci/test.lua index 372d8f262..9a7c0d345 100644 --- a/ci/test.lua +++ b/ci/test.lua @@ -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 diff --git a/docs/changelog.txt b/docs/changelog.txt index 3c6cc2e73..ee608652c 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -52,6 +52,7 @@ Template for new versions: # Future ## New Tools +- `spectate`: automatically follow productive dwarves (returned to availability) - `preserve-tombs`: tracks tomb assignments to living units and ensures that the tomb stays assigned to them when they die. ## New Features diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index 6eeb2dbe7..49f0b3633 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -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 clicking on the map. + * ``mkdims_xy(x1,y1,x2,y2)`` Returns a table containing the arguments as fields, and also ``width`` and diff --git a/docs/plugins/spectate.rst b/docs/plugins/spectate.rst index 95ce852ae..f54d68142 100644 --- a/docs/plugins/spectate.rst +++ b/docs/plugins/spectate.rst @@ -3,7 +3,7 @@ spectate .. dfhack-tool:: :summary: Automatically follow productive dwarves. - :tags: unavailable fort interface + :tags: fort interface Usage ----- diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index 681398f89..96f1f6642 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -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; } diff --git a/library/lua/gui.lua b/library/lua/gui.lua index ba49e0cdc..bb29124a5 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -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, @@ -27,7 +27,7 @@ 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 @@ -35,6 +35,10 @@ function simulateInput(screen,...) 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 @@ -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 @@ -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, @@ -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 @@ -829,8 +821,8 @@ function ZScreen:onInput(keys) if passit then self:sendInputToParent(keys) end - return end + return true end function ZScreen:raise() diff --git a/library/lua/gui/dialogs.lua b/library/lua/gui/dialogs.lua index 5778cc767..7a0f86b3f 100644 --- a/library/lua/gui/dialogs.lua +++ b/library/lua/gui/dialogs.lua @@ -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) @@ -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) @@ -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) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index a5b347493..dee7e2b75 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -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); @@ -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; } diff --git a/library/xml b/library/xml index f38f3c495..aeab463a0 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit f38f3c4955d604f2b5a8e0d952e676a0ab05c053 +Subproject commit aeab463a0d35ac9ff896db840735cabfa12df712 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 80a7d9f35..be690edf1 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -159,7 +159,7 @@ if(BUILD_SUPPORTED) #dfhack_plugin(siege-engine siege-engine.cpp LINK_LIBRARIES lua) dfhack_plugin(sort sort.cpp LINK_LIBRARIES lua) #dfhack_plugin(steam-engine steam-engine.cpp) - #add_subdirectory(spectate) + add_subdirectory(spectate) #dfhack_plugin(stockflow stockflow.cpp LINK_LIBRARIES lua) add_subdirectory(stockpiles) #dfhack_plugin(stocks stocks.cpp) diff --git a/plugins/lua/hotkeys.lua b/plugins/lua/hotkeys.lua index 6335de5e5..4c33f93ca 100644 --- a/plugins/lua/hotkeys.lua +++ b/plugins/lua/hotkeys.lua @@ -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 diff --git a/plugins/lua/overlay.lua b/plugins/lua/overlay.lua index cd5286d0d..9751561a8 100644 --- a/plugins/lua/overlay.lua +++ b/plugins/lua/overlay.lua @@ -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 diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 3fec6091b..c94397956 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -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)(); diff --git a/scripts b/scripts index d2ad86165..28bcd6e31 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit d2ad86165e89dc3b0f262eea00db8e2347cc4421 +Subproject commit 28bcd6e313ea6f87ffd805c8cf40360da5f21509