align mouse button semantics to DF

we, um, had it backwards
develop
Myk Taylor 2023-09-26 03:52:24 -07:00 committed by Najeeb Al-Shabibi
parent 6ad724b483
commit 5c670d20db
17 changed files with 110 additions and 113 deletions

@ -66,6 +66,7 @@ Template for new versions:
## API ## API
## Lua ## Lua
- mouse key events are now aligned with internal DF semantics: ``_MOUSE_L`` indicates that the left mouse button has just been pressed and ``_MOUSE_L_DOWN`` indicates that the left mouse button is being held down. similar for ``_MOUSE_R`` and ``_MOUSE_M``. 3rd party scripts may have to adjust.
## Removed ## Removed

@ -2528,10 +2528,10 @@ Supported callbacks and fields are:
Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience. Maps to an integer in range 0-255. Duplicates a separate "STRING_A???" code for convenience.
``_MOUSE_L, _MOUSE_R, _MOUSE_M`` ``_MOUSE_L, _MOUSE_R, _MOUSE_M``
If the left, right, and/or middle mouse button is being pressed. If the left, right, and/or middle mouse button was just pressed.
``_MOUSE_L_DOWN, _MOUSE_R_DOWN, _MOUSE_M_DOWN`` ``_MOUSE_L_DOWN, _MOUSE_R_DOWN, _MOUSE_M_DOWN``
If the left, right, and/or middle mouse button was just pressed. If the left, right, and/or middle mouse button is being held down.
If this method is omitted, the screen is dismissed on reception of the ``LEAVESCREEN`` key. If this method is omitted, the screen is dismissed on reception of the ``LEAVESCREEN`` key.

@ -131,12 +131,12 @@ void DFHack::Lua::GetVector(lua_State *state, std::vector<std::string> &pvec, in
} }
} }
static bool trigger_inhibit_l_down = false; static bool trigger_inhibit_l = false;
static bool trigger_inhibit_r_down = false; static bool trigger_inhibit_r = false;
static bool trigger_inhibit_m_down = false; static bool trigger_inhibit_m = false;
static bool inhibit_l_down = false; static bool inhibit_l = false;
static bool inhibit_r_down = false; static bool inhibit_r = false;
static bool inhibit_m_down = false; static bool inhibit_m = false;
void DFHack::Lua::PushInterfaceKeys(lua_State *L, void DFHack::Lua::PushInterfaceKeys(lua_State *L,
const std::set<df::interface_key> &keys) { const std::set<df::interface_key> &keys) {
@ -161,32 +161,32 @@ void DFHack::Lua::PushInterfaceKeys(lua_State *L,
} }
if (df::global::enabler) { if (df::global::enabler) {
if (!inhibit_l_down && df::global::enabler->mouse_lbut_down) { if (!inhibit_l && df::global::enabler->mouse_lbut) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_L_DOWN"); lua_setfield(L, -2, "_MOUSE_L");
trigger_inhibit_l_down = true; trigger_inhibit_l = true;
} }
if (!inhibit_r_down && df::global::enabler->mouse_rbut_down) { if (!inhibit_r && df::global::enabler->mouse_rbut) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_R_DOWN"); lua_setfield(L, -2, "_MOUSE_R");
trigger_inhibit_r_down = true; trigger_inhibit_r = true;
} }
if (!inhibit_m_down && df::global::enabler->mouse_mbut_down) { if (!inhibit_m && df::global::enabler->mouse_mbut) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_M_DOWN"); lua_setfield(L, -2, "_MOUSE_M");
trigger_inhibit_m_down = true; trigger_inhibit_m = true;
} }
if (df::global::enabler->mouse_lbut) { if (df::global::enabler->mouse_lbut_down) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_L"); lua_setfield(L, -2, "_MOUSE_L_DOWN");
} }
if (df::global::enabler->mouse_rbut) { if (df::global::enabler->mouse_rbut_down) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_R"); lua_setfield(L, -2, "_MOUSE_R_DOWN");
} }
if (df::global::enabler->mouse_mbut) { if (df::global::enabler->mouse_mbut_down) {
lua_pushboolean(L, true); lua_pushboolean(L, true);
lua_setfield(L, -2, "_MOUSE_M"); lua_setfield(L, -2, "_MOUSE_M_DOWN");
} }
} }
} }
@ -2159,25 +2159,25 @@ void DFHack::Lua::Core::Reset(color_ostream &out, const char *where)
lua_settop(State, 0); lua_settop(State, 0);
} }
if (trigger_inhibit_l_down) { if (trigger_inhibit_l) {
trigger_inhibit_l_down = false; trigger_inhibit_l = false;
inhibit_l_down = true; inhibit_l = true;
} }
if (trigger_inhibit_r_down) { if (trigger_inhibit_r) {
trigger_inhibit_r_down = false; trigger_inhibit_r = false;
inhibit_r_down = true; inhibit_r = true;
} }
if (trigger_inhibit_m_down) { if (trigger_inhibit_m) {
trigger_inhibit_m_down = false; trigger_inhibit_m = false;
inhibit_m_down = true; inhibit_m = true;
} }
if (df::global::enabler) { if (df::global::enabler) {
if (!df::global::enabler->mouse_lbut) if (!df::global::enabler->mouse_lbut_down)
inhibit_l_down = false; inhibit_l = false;
if (!df::global::enabler->mouse_rbut) if (!df::global::enabler->mouse_rbut_down)
inhibit_r_down = false; inhibit_r = false;
if (!df::global::enabler->mouse_mbut) if (!df::global::enabler->mouse_mbut_down)
inhibit_m_down = false; inhibit_m = false;
} }
} }

@ -696,16 +696,12 @@ end
DEFAULT_INITIAL_PAUSE = true DEFAULT_INITIAL_PAUSE = true
local zscreen_inhibit_mouse_l = false
-- ensure underlying DF screens don't also react to handled clicks -- ensure underlying DF screens don't also react to handled clicks
function markMouseClicksHandled(keys) function markMouseClicksHandled(keys)
if keys._MOUSE_L_DOWN then if keys._MOUSE_L then
-- note we can't clear mouse_lbut here. otherwise we break dragging, df.global.enabler.mouse_lbut = 0
df.global.enabler.mouse_lbut_down = 0
zscreen_inhibit_mouse_l = true
end end
if keys._MOUSE_R_DOWN then if keys._MOUSE_R then
df.global.enabler.mouse_rbut_down = 0 df.global.enabler.mouse_rbut_down = 0
df.global.enabler.mouse_rbut = 0 df.global.enabler.mouse_rbut = 0
end end
@ -789,7 +785,7 @@ function ZScreen:onInput(keys)
local has_mouse = self:isMouseOver() local has_mouse = self:isMouseOver()
if not self:hasFocus() then if not self:hasFocus() then
if has_mouse and if has_mouse and
(keys._MOUSE_L_DOWN or keys._MOUSE_R_DOWN or (keys._MOUSE_L or keys._MOUSE_R or
keys.CONTEXT_SCROLL_UP or keys.CONTEXT_SCROLL_DOWN or keys.CONTEXT_SCROLL_UP or keys.CONTEXT_SCROLL_DOWN or
keys.CONTEXT_SCROLL_PAGEUP or keys.CONTEXT_SCROLL_PAGEDOWN) then keys.CONTEXT_SCROLL_PAGEUP or keys.CONTEXT_SCROLL_PAGEDOWN) then
self:raise() self:raise()
@ -804,22 +800,15 @@ function ZScreen:onInput(keys)
return return
end end
if self.pass_mouse_clicks and keys._MOUSE_L_DOWN and not has_mouse then if self.pass_mouse_clicks and keys._MOUSE_L and not has_mouse then
self.defocused = self.defocusable self.defocused = self.defocusable
self:sendInputToParent(keys) self:sendInputToParent(keys)
return return
elseif keys.LEAVESCREEN or keys._MOUSE_R_DOWN then elseif keys.LEAVESCREEN or keys._MOUSE_R then
self:dismiss() self:dismiss()
markMouseClicksHandled(keys) markMouseClicksHandled(keys)
return return
else else
if zscreen_inhibit_mouse_l then
if keys._MOUSE_L then
return
else
zscreen_inhibit_mouse_l = false
end
end
local passit = self.pass_pause and keys.D_PAUSE local passit = self.pass_pause and keys.D_PAUSE
if not passit and self.pass_mouse_clicks then if not passit and self.pass_mouse_clicks then
if keys.CONTEXT_SCROLL_UP or keys.CONTEXT_SCROLL_DOWN or if keys.CONTEXT_SCROLL_UP or keys.CONTEXT_SCROLL_DOWN or

@ -57,11 +57,11 @@ function MessageBox:onDestroy()
end end
function MessageBox:onInput(keys) function MessageBox:onInput(keys)
if keys.SELECT or keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.SELECT or keys.LEAVESCREEN or keys._MOUSE_R then
self:dismiss() self:dismiss()
if keys.SELECT and self.on_accept then if keys.SELECT and self.on_accept then
self.on_accept() self.on_accept()
elseif (keys.LEAVESCREEN or keys._MOUSE_R_DOWN) and self.on_cancel then elseif (keys.LEAVESCREEN or keys._MOUSE_R) and self.on_cancel then
self.on_cancel() self.on_cancel()
end end
gui.markMouseClicksHandled(keys) gui.markMouseClicksHandled(keys)
@ -129,7 +129,7 @@ function InputBox:onInput(keys)
self.on_input(self.subviews.edit.text) self.on_input(self.subviews.edit.text)
end end
return true return true
elseif keys.LEAVESCREEN or keys._MOUSE_R_DOWN then elseif keys.LEAVESCREEN or keys._MOUSE_R then
self:dismiss() self:dismiss()
if self.on_cancel then if self.on_cancel then
self.on_cancel() self.on_cancel()
@ -231,7 +231,7 @@ function ListBox:getWantedFrameSize()
end end
function ListBox:onInput(keys) function ListBox:onInput(keys)
if keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.LEAVESCREEN or keys._MOUSE_R then
self:dismiss() self:dismiss()
if self.on_cancel then if self.on_cancel then
self.on_cancel() self.on_cancel()

@ -273,7 +273,7 @@ end
function Panel:onInput(keys) function Panel:onInput(keys)
if self.kbd_get_pos then if self.kbd_get_pos then
if keys.SELECT or keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.SELECT or keys.LEAVESCREEN or keys._MOUSE_R then
Panel_end_drag(self, not keys.SELECT and self.saved_frame or nil, Panel_end_drag(self, not keys.SELECT and self.saved_frame or nil,
not not keys.SELECT) not not keys.SELECT)
return true return true
@ -281,7 +281,6 @@ function Panel:onInput(keys)
for code in pairs(keys) do for code in pairs(keys) do
local dx, dy = guidm.get_movement_delta(code, 1, 10) local dx, dy = guidm.get_movement_delta(code, 1, 10)
if dx then if dx then
local frame_rect = self.frame_rect
local kbd_pos = self.kbd_get_pos() local kbd_pos = self.kbd_get_pos()
kbd_pos.x = kbd_pos.x + dx kbd_pos.x = kbd_pos.x + dx
kbd_pos.y = kbd_pos.y + dy kbd_pos.y = kbd_pos.y + dy
@ -292,9 +291,9 @@ function Panel:onInput(keys)
return return
end end
if self.drag_offset then if self.drag_offset then
if keys._MOUSE_R_DOWN then if keys._MOUSE_R then
Panel_end_drag(self, self.saved_frame) Panel_end_drag(self, self.saved_frame)
elseif keys._MOUSE_L then elseif keys._MOUSE_L_DOWN then
Panel_update_frame(self, Panel_make_frame(self)) Panel_update_frame(self, Panel_make_frame(self))
end end
return true return true
@ -302,7 +301,7 @@ function Panel:onInput(keys)
if Panel.super.onInput(self, keys) then if Panel.super.onInput(self, keys) then
return true return true
end end
if not keys._MOUSE_L_DOWN then return end if not keys._MOUSE_L then return end
local x,y = self:getMouseFramePos() local x,y = self:getMouseFramePos()
if not x then return end if not x then return end
@ -489,7 +488,7 @@ function Panel:onRenderFrame(dc, rect)
dc:seek(pos.x, pos.y):pen(pen):char(string.char(0xDB)) dc:seek(pos.x, pos.y):pen(pen):char(string.char(0xDB))
end end
if self.drag_offset and not self.kbd_get_pos if self.drag_offset and not self.kbd_get_pos
and df.global.enabler.mouse_lbut == 0 then and df.global.enabler.mouse_lbut_down == 0 then
Panel_end_drag(self, nil, true) Panel_end_drag(self, nil, true)
end end
end end
@ -718,7 +717,7 @@ function EditField:onInput(keys)
end end
end end
if self.key and (keys.LEAVESCREEN or keys._MOUSE_R_DOWN) then if self.key and (keys.LEAVESCREEN or keys._MOUSE_R) then
self:setText(self.saved_text) self:setText(self.saved_text)
self:setFocus(false) self:setFocus(false)
return true return true
@ -740,8 +739,8 @@ function EditField:onInput(keys)
end end
end end
return not not self.key return not not self.key
elseif keys._MOUSE_L then elseif keys._MOUSE_L_DOWN then
local mouse_x, mouse_y = self:getMousePos() local mouse_x = self:getMousePos()
if mouse_x then if mouse_x then
self:setCursor(self.start_pos + mouse_x - (self.text_offset or 0)) self:setCursor(self.start_pos + mouse_x - (self.text_offset or 0))
return true return true
@ -986,7 +985,7 @@ function Scrollbar:onRenderBody(dc)
if self.is_dragging then if self.is_dragging then
scrollbar_do_drag(self) scrollbar_do_drag(self)
end end
if df.global.enabler.mouse_lbut == 0 then if df.global.enabler.mouse_lbut_down == 0 then
self.last_scroll_ms = 0 self.last_scroll_ms = 0
self.is_dragging = false self.is_dragging = false
self.scroll_spec = nil self.scroll_spec = nil
@ -1023,7 +1022,7 @@ function Scrollbar:onInput(keys)
return true return true
end end
end end
if not keys._MOUSE_L_DOWN then return false end if not keys._MOUSE_L then return false end
local _,y = self:getMousePos() local _,y = self:getMousePos()
if not y then return false end if not y then return false end
local scroll_spec = nil local scroll_spec = nil
@ -1386,11 +1385,11 @@ function Label:onInput(keys)
if self:inputToSubviews(keys) then if self:inputToSubviews(keys) then
return true return true
end end
if keys._MOUSE_L_DOWN and self:getMousePos() and self.on_click then if keys._MOUSE_L and self:getMousePos() and self.on_click then
self.on_click() self.on_click()
return true return true
end end
if keys._MOUSE_R_DOWN and self:getMousePos() and self.on_rclick then if keys._MOUSE_R and self:getMousePos() and self.on_rclick then
self.on_rclick() self.on_rclick()
return true return true
end end
@ -1498,7 +1497,7 @@ end
function HotkeyLabel:onInput(keys) function HotkeyLabel:onInput(keys)
if HotkeyLabel.super.onInput(self, keys) then if HotkeyLabel.super.onInput(self, keys) then
return true return true
elseif keys._MOUSE_L_DOWN and self:getMousePos() and self.on_activate elseif keys._MOUSE_L and self:getMousePos() and self.on_activate
and not is_disabled(self) then and not is_disabled(self) then
self.on_activate() self.on_activate()
return true return true
@ -1658,7 +1657,7 @@ end
function CycleHotkeyLabel:onInput(keys) function CycleHotkeyLabel:onInput(keys)
if CycleHotkeyLabel.super.onInput(self, keys) then if CycleHotkeyLabel.super.onInput(self, keys) then
return true return true
elseif keys._MOUSE_L_DOWN and self:getMousePos() and not is_disabled(self) then elseif keys._MOUSE_L and self:getMousePos() and not is_disabled(self) then
self:cycle() self:cycle()
return true return true
end end
@ -1962,7 +1961,7 @@ function List:onInput(keys)
return self:submit() return self:submit()
elseif keys.CUSTOM_SHIFT_ENTER then elseif keys.CUSTOM_SHIFT_ENTER then
return self:submit2() return self:submit2()
elseif keys._MOUSE_L_DOWN then elseif keys._MOUSE_L then
local idx = self:getIdxUnderMouse() local idx = self:getIdxUnderMouse()
if idx then if idx then
local now_ms = dfhack.getTickCount() local now_ms = dfhack.getTickCount()
@ -2317,7 +2316,7 @@ end
function Tab:onInput(keys) function Tab:onInput(keys)
if Tab.super.onInput(self, keys) then return true end if Tab.super.onInput(self, keys) then return true end
if keys._MOUSE_L_DOWN and self:getMousePos() then if keys._MOUSE_L and self:getMousePos() then
self.on_select(self.id) self.on_select(self.id)
return true return true
end end
@ -2419,7 +2418,7 @@ local function rangeslider_get_width_per_idx(self)
end end
function RangeSlider:onInput(keys) function RangeSlider:onInput(keys)
if not keys._MOUSE_L_DOWN then return false end if not keys._MOUSE_L then return false end
local x = self:getMousePos() local x = self:getMousePos()
if not x then return false end if not x then return false end
local left_idx, right_idx = self.get_left_idx_fn(), self.get_right_idx_fn() local left_idx, right_idx = self.get_left_idx_fn(), self.get_right_idx_fn()
@ -2527,7 +2526,7 @@ function RangeSlider:onRenderBody(dc, rect)
if self.is_dragging_target then if self.is_dragging_target then
rangeslider_do_drag(self, width_per_idx) rangeslider_do_drag(self, width_per_idx)
end end
if df.global.enabler.mouse_lbut == 0 then if df.global.enabler.mouse_lbut_down == 0 then
self.is_dragging_target = nil self.is_dragging_target = nil
self.is_dragging_idx = nil self.is_dragging_idx = nil
end end

@ -1004,6 +1004,8 @@ dfhack_lua_viewscreen::~dfhack_lua_viewscreen()
void dfhack_lua_viewscreen::render() void dfhack_lua_viewscreen::render()
{ {
using df::global::enabler;
if (Screen::isDismissed(this)) if (Screen::isDismissed(this))
{ {
if (parent) if (parent)
@ -1011,6 +1013,14 @@ void dfhack_lua_viewscreen::render()
return; return;
} }
if (enabler &&
(enabler->mouse_lbut_down || enabler->mouse_rbut_down || enabler->mouse_mbut_down))
{
// synthesize feed events for held mouse buttons
std::set<df::interface_key> keys;
feed(&keys);
}
dfhack_viewscreen::render(); dfhack_viewscreen::render();
safe_call_lua(do_render, 0, 0); safe_call_lua(do_render, 0, 0);

@ -127,9 +127,9 @@ function InspectorOverlay:onInput(keys)
if not require('plugins.buildingplan').isPlannedBuilding(dfhack.gui.getSelectedBuilding(true)) then if not require('plugins.buildingplan').isPlannedBuilding(dfhack.gui.getSelectedBuilding(true)) then
return false return false
end end
if keys._MOUSE_L_DOWN and mouse_is_over_resume_button(self.frame_parent_rect) then if keys._MOUSE_L and mouse_is_over_resume_button(self.frame_parent_rect) then
return true return true
elseif keys._MOUSE_L_DOWN or keys._MOUSE_R_DOWN or keys.LEAVESCREEN then elseif keys._MOUSE_L or keys._MOUSE_R or keys.LEAVESCREEN then
self:reset() self:reset()
end end
return InspectorOverlay.super.onInput(self, keys) return InspectorOverlay.super.onInput(self, keys)

@ -366,10 +366,10 @@ function ItemSelection:submit(choices)
end end
function ItemSelection:onInput(keys) function ItemSelection:onInput(keys)
if keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.LEAVESCREEN or keys._MOUSE_R then
self.on_cancel() self.on_cancel()
return true return true
elseif keys._MOUSE_L_DOWN then elseif keys._MOUSE_L then
local list = self.subviews.flist.list local list = self.subviews.flist.list
local idx = list:getIdxUnderMouse() local idx = list:getIdxUnderMouse()
if idx then if idx then

@ -272,7 +272,7 @@ function ItemLine:reset()
end end
function ItemLine:onInput(keys) function ItemLine:onInput(keys)
if keys._MOUSE_L_DOWN and self:getMousePos() then if keys._MOUSE_L and self:getMousePos() then
self.on_select(self.idx) self.on_select(self.idx)
end end
return ItemLine.super.onInput(self, keys) return ItemLine.super.onInput(self, keys)
@ -739,7 +739,7 @@ end
function PlannerOverlay:onInput(keys) function PlannerOverlay:onInput(keys)
if not is_plannable() then return false end if not is_plannable() then return false end
if keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.LEAVESCREEN or keys._MOUSE_R then
if uibs.selection_pos:isValid() then if uibs.selection_pos:isValid() then
uibs.selection_pos:clear() uibs.selection_pos:clear()
return true return true
@ -758,7 +758,7 @@ function PlannerOverlay:onInput(keys)
return true return true
end end
if self:is_minimized() then return false end if self:is_minimized() then return false end
if keys._MOUSE_L_DOWN then if keys._MOUSE_L then
if is_over_options_panel() then return false end if is_over_options_panel() then return false end
local detect_rect = copyall(self.frame_rect) local detect_rect = copyall(self.frame_rect)
detect_rect.height = self.subviews.main.frame_rect.height + detect_rect.height = self.subviews.main.frame_rect.height +
@ -828,7 +828,7 @@ function PlannerOverlay:onInput(keys)
end end
end end
end end
return keys._MOUSE_L or keys.SELECT return keys._MOUSE_L_DOWN or keys.SELECT
end end
function PlannerOverlay:render(dc) function PlannerOverlay:render(dc)

@ -269,24 +269,24 @@ function Menu:onSubmit2(_, choice)
end end
function Menu:onInput(keys) function Menu:onInput(keys)
if keys.LEAVESCREEN or keys._MOUSE_R_DOWN then if keys.LEAVESCREEN or keys._MOUSE_R then
return false return false
elseif keys.KEYBOARD_CURSOR_RIGHT then elseif keys.KEYBOARD_CURSOR_RIGHT then
self:onSubmit2(self.subviews.list:getSelected()) self:onSubmit2(self.subviews.list:getSelected())
return true return true
elseif keys._MOUSE_L_DOWN then elseif keys._MOUSE_L then
local list = self.subviews.list local list = self.subviews.list
local x = list:getMousePos() local x = list:getMousePos()
if x == 0 then -- clicked on icon if x == 0 then -- clicked on icon
self:onSubmit2(list:getSelected()) self:onSubmit2(list:getSelected())
df.global.enabler.mouse_lbut = 0 gui.markMouseClicksHandled(keys)
return true return true
end end
if not self:getMouseFramePos() then if not self:getMouseFramePos() then
self.parent_view:dismiss() self.parent_view:dismiss()
return true return true
end end
df.global.enabler.mouse_lbut = 0 gui.markMouseClicksHandled(keys)
end end
self:inputToSubviews(keys) self:inputToSubviews(keys)
return true -- we're modal return true -- we're modal

@ -507,9 +507,6 @@ function feed_viewscreen_widgets(vs_name, vs, keys)
return false return false
end end
gui.markMouseClicksHandled(keys) gui.markMouseClicksHandled(keys)
if keys._MOUSE_L_DOWN then
df.global.enabler.mouse_lbut = 0
end
return true return true
end end

@ -1148,9 +1148,7 @@ function SquadAssignmentOverlay:refresh_list(sort_widget, sort_fn)
end end
function SquadAssignmentOverlay:onInput(keys) function SquadAssignmentOverlay:onInput(keys)
if keys._MOUSE_R_DOWN or if keys._MOUSE_R or (keys._MOUSE_L and not self:getMouseFramePos()) then
keys._MOUSE_L_DOWN and not self:getMouseFramePos()
then
-- if any click is made outside of our window, we may need to refresh our list -- if any click is made outside of our window, we may need to refresh our list
self.dirty = true self.dirty = true
end end

@ -801,10 +801,12 @@ end
function AssignAnimalScreen:onInput(keys) function AssignAnimalScreen:onInput(keys)
local handled = AssignAnimalScreen.super.onInput(self, keys) local handled = AssignAnimalScreen.super.onInput(self, keys)
if not self.is_valid_ui_state() then if not self.is_valid_ui_state() then
view:dismiss() if view then
view:dismiss()
end
return return
end end
if keys._MOUSE_L_DOWN then if keys._MOUSE_L then
-- if any click is made outside of our window, we need to recheck unit properties -- if any click is made outside of our window, we need to recheck unit properties
local window = self.subviews[1] local window = self.subviews[1]
if not window:getMouseFramePos() then if not window:getMouseFramePos() then
@ -818,7 +820,7 @@ function AssignAnimalScreen:onInput(keys)
end end
function AssignAnimalScreen:onRenderFrame() function AssignAnimalScreen:onRenderFrame()
if not self.is_valid_ui_state() then if view and not self.is_valid_ui_state() then
view:dismiss() view:dismiss()
end end
end end
@ -1072,6 +1074,7 @@ function CageChainOverlay:init()
frame={t=0, l=0, r=0, h=1}, frame={t=0, l=0, r=0, h=1},
label='DFHack assign', label='DFHack assign',
key='CUSTOM_CTRL_T', key='CUSTOM_CTRL_T',
visible=is_valid_building,
on_activate=function() view = view and view:raise() or show_cage_chain_screen() end, on_activate=function() view = view and view:raise() or show_cage_chain_screen() end,
}, },
} }

@ -42,17 +42,17 @@ function test.editfield_click()
expect.eq(5, e.cursor) expect.eq(5, e.cursor)
mock.patch(e, 'getMousePos', mock.func(0), function() mock.patch(e, 'getMousePos', mock.func(0), function()
e:onInput{_MOUSE_L=true} e:onInput{_MOUSE_L_DOWN=true}
expect.eq(1, e.cursor) expect.eq(1, e.cursor)
end) end)
mock.patch(e, 'getMousePos', mock.func(20), function() mock.patch(e, 'getMousePos', mock.func(20), function()
e:onInput{_MOUSE_L=true} e:onInput{_MOUSE_L_DOWN=true}
expect.eq(5, e.cursor, 'should only seek to end of text') expect.eq(5, e.cursor, 'should only seek to end of text')
end) end)
mock.patch(e, 'getMousePos', mock.func(2), function() mock.patch(e, 'getMousePos', mock.func(2), function()
e:onInput{_MOUSE_L=true} e:onInput{_MOUSE_L_DOWN=true}
expect.eq(3, e.cursor) expect.eq(3, e.cursor)
end) end)
end end

@ -59,37 +59,37 @@ function test.onInput()
s:update(23, 10, 50) s:update(23, 10, 50)
expect.false_(s:onInput{}, 'no mouse down') expect.false_(s:onInput{}, 'no mouse down')
expect.false_(s:onInput{_MOUSE_L_DOWN=true}, 'no y coord') expect.false_(s:onInput{_MOUSE_L=true}, 'no y coord')
spec, y = nil, 0 spec, y = nil, 0
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('up_small', spec, 'on up arrow') expect.eq('up_small', spec, 'on up arrow')
spec, y = nil, 1 spec, y = nil, 1
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('up_large', spec, 'on body above bar') expect.eq('up_large', spec, 'on body above bar')
spec, y = nil, 44 spec, y = nil, 44
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('up_large', spec, 'on body just above bar') expect.eq('up_large', spec, 'on body just above bar')
spec, y = nil, 45 spec, y = nil, 45
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.nil_(spec, 'on top of bar') expect.nil_(spec, 'on top of bar')
spec, y = nil, 63 spec, y = nil, 63
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.nil_(spec, 'on bottom of bar') expect.nil_(spec, 'on bottom of bar')
spec, y = nil, 64 spec, y = nil, 64
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('down_large', spec, 'on body just below bar') expect.eq('down_large', spec, 'on body just below bar')
spec, y = nil, 98 spec, y = nil, 98
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('down_large', spec, 'on body below bar') expect.eq('down_large', spec, 'on body below bar')
spec, y = nil, 99 spec, y = nil, 99
expect.true_(s:onInput{_MOUSE_L_DOWN=true}) expect.true_(s:onInput{_MOUSE_L=true})
expect.eq('down_small', spec, 'on down arrow') expect.eq('down_small', spec, 'on down arrow')
end end

@ -7,7 +7,7 @@ function test.hotkeylabel_click()
local l = widgets.HotkeyLabel{key='SELECT', on_activate=func} local l = widgets.HotkeyLabel{key='SELECT', on_activate=func}
mock.patch(l, 'getMousePos', mock.func(0), function() mock.patch(l, 'getMousePos', mock.func(0), function()
l:onInput{_MOUSE_L_DOWN=true} l:onInput{_MOUSE_L=true}
expect.eq(1, func.call_count) expect.eq(1, func.call_count)
end) end)
end end
@ -33,7 +33,7 @@ function test.togglehotkeylabel_click()
local l = widgets.ToggleHotkeyLabel{} local l = widgets.ToggleHotkeyLabel{}
expect.true_(l:getOptionValue()) expect.true_(l:getOptionValue())
mock.patch(l, 'getMousePos', mock.func(0), function() mock.patch(l, 'getMousePos', mock.func(0), function()
l:onInput{_MOUSE_L_DOWN=true} l:onInput{_MOUSE_L=true}
expect.false_(l:getOptionValue()) expect.false_(l:getOptionValue())
end) end)
end end