mirror of
https://github.com/airstruck/luigi.git
synced 2026-01-09 15:58:22 +00:00
Allow removal of default layout behaviors (tab nav, mouse scroll, etc.)
This commit is contained in:
153
luigi/layout.lua
153
luigi/layout.lua
@@ -324,6 +324,7 @@ function Layout:placeNear (left, top, width, height)
|
|||||||
root.top = top
|
root.top = top
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Add handlers for keyboard shortcuts, tab focus, and mouse wheel scroll
|
-- Add handlers for keyboard shortcuts, tab focus, and mouse wheel scroll
|
||||||
function Layout:addDefaultHandlers ()
|
function Layout:addDefaultHandlers ()
|
||||||
self.shortcuts = {}
|
self.shortcuts = {}
|
||||||
@@ -332,85 +333,107 @@ function Layout:addDefaultHandlers ()
|
|||||||
self.shortcuts[i] = {}
|
self.shortcuts[i] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
self:onPressStart(function (event)
|
self.behavior = {}
|
||||||
-- show context menu on right click
|
|
||||||
if event.button ~= 'right' then return end
|
|
||||||
local menu = event.target.context
|
|
||||||
if not menu then return end
|
|
||||||
menu:bubbleEvent('PressStart', event)
|
|
||||||
-- make sure it fits in the window
|
|
||||||
-- TODO: open in a new borderless window under SDL?
|
|
||||||
menu.menuLayout:placeNear(event.x - 1, event.y - 1, 2, 2)
|
|
||||||
return false
|
|
||||||
end)
|
|
||||||
|
|
||||||
self:onKeyPress(function (event)
|
local function createBehavior (name, hooks)
|
||||||
-- keyboard shortcuts
|
self.behavior[name] = hooks
|
||||||
local entry = self.shortcuts[event.modifierFlags]
|
function hooks.destroy ()
|
||||||
local widget = entry and entry[event.key]
|
for _, hook in ipairs(hooks) do
|
||||||
if widget then
|
hook:unhook()
|
||||||
|
end
|
||||||
|
self.behavior[name] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
createBehavior('context', {
|
||||||
|
self:onPressStart(function (event)
|
||||||
|
-- show context menu on right click
|
||||||
|
if event.button ~= 'right' then return end
|
||||||
|
local menu = event.target.context
|
||||||
|
if not menu then return end
|
||||||
|
menu:bubbleEvent('PressStart', event)
|
||||||
|
-- make sure it fits in the window
|
||||||
|
-- TODO: open in a new borderless window under SDL?
|
||||||
|
menu.menuLayout:placeNear(event.x - 1, event.y - 1, 2, 2)
|
||||||
|
return false
|
||||||
|
end)
|
||||||
|
})
|
||||||
|
|
||||||
|
createBehavior('shortcut', {
|
||||||
|
self:onKeyPress(function (event)
|
||||||
|
local entry = self.shortcuts[event.modifierFlags]
|
||||||
|
local widget = entry and entry[event.key]
|
||||||
|
if not widget then return end
|
||||||
widget.hovered = true
|
widget.hovered = true
|
||||||
self.input:handlePressStart(self, 'left', event.x, event.y,
|
self.input:handlePressStart(self, 'left', event.x, event.y,
|
||||||
widget, widget.shortcut)
|
widget, widget.shortcut)
|
||||||
return false
|
return false
|
||||||
end
|
end),
|
||||||
|
|
||||||
-- tab/shift-tab cycles focused widget
|
self:onKeyRelease(function (event)
|
||||||
if event.key == 'tab' then
|
local entry = self.shortcuts[event.modifierFlags]
|
||||||
if Backend.isKeyDown('lshift', 'rshift') then
|
local widget = entry and entry[event.key]
|
||||||
self:focusPreviousWidget()
|
if not widget then return end
|
||||||
else
|
|
||||||
self:focusNextWidget()
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- space/enter presses focused widget
|
|
||||||
local widget = self.focusedWidget
|
|
||||||
if widget and event.key == 'space' or event.key == ' '
|
|
||||||
or event.key == 'return' then
|
|
||||||
self.input:handlePressStart(self, 'left', event.x, event.y,
|
|
||||||
widget, event.key)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
self:onKeyRelease(function (event)
|
|
||||||
-- shortcuts
|
|
||||||
local entry = self.shortcuts[event.modifierFlags]
|
|
||||||
local widget = entry and entry[event.key]
|
|
||||||
if widget then
|
|
||||||
widget.hovered = false
|
widget.hovered = false
|
||||||
self.input:handlePressEnd(self, 'left', event.x, event.y,
|
self.input:handlePressEnd(self, 'left', event.x, event.y,
|
||||||
widget, widget.shortcut)
|
widget, widget.shortcut)
|
||||||
return false
|
return false
|
||||||
end
|
end)
|
||||||
|
})
|
||||||
|
|
||||||
-- space / enter presses focused widget
|
createBehavior('navigate', {
|
||||||
local widget = self.focusedWidget
|
self:onKeyPress(function (event)
|
||||||
if widget and event.key == 'space' or event.key == ' '
|
-- tab/shift-tab cycles focused widget
|
||||||
or event.key == 'return' then
|
if event.key == 'tab' then
|
||||||
self.input:handlePressEnd(self, 'left', event.x, event.y,
|
if Backend.isKeyDown('lshift', 'rshift') then
|
||||||
widget, event.key)
|
self:focusPreviousWidget()
|
||||||
|
else
|
||||||
|
self:focusNextWidget()
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- space/enter presses focused widget
|
||||||
|
local widget = self.focusedWidget
|
||||||
|
if widget and event.key == 'space' or event.key == ' '
|
||||||
|
or event.key == 'return' then
|
||||||
|
self.input:handlePressStart(self, 'left', event.x, event.y,
|
||||||
|
widget, event.key)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
|
||||||
|
self:onKeyRelease(function (event)
|
||||||
|
-- space / enter presses focused widget
|
||||||
|
local widget = self.focusedWidget
|
||||||
|
if widget and event.key == 'space' or event.key == ' '
|
||||||
|
or event.key == 'return' then
|
||||||
|
self.input:handlePressEnd(self, 'left', event.x, event.y,
|
||||||
|
widget, event.key)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
})
|
||||||
|
|
||||||
|
createBehavior('scroll', {
|
||||||
|
self:onWheelMove(function (event)
|
||||||
|
if not event.hit then return end
|
||||||
|
for widget in event.target:eachAncestor(true) do
|
||||||
|
if widget:scrollBy(nil, event.y) then return false end
|
||||||
|
end -- ancestor loop
|
||||||
return false
|
return false
|
||||||
end
|
end) -- wheel move
|
||||||
end)
|
})
|
||||||
|
|
||||||
self:onWheelMove(function (event)
|
createBehavior('status', {
|
||||||
if not event.hit then return end
|
self:onEnter(function (event)
|
||||||
for widget in event.target:eachAncestor(true) do
|
local statusWidget = (self.master or self).statusWidget
|
||||||
if widget:scrollBy(nil, event.y) then return false end
|
if not statusWidget then return end
|
||||||
end -- ancestor loop
|
|
||||||
return false
|
|
||||||
end) -- wheel move
|
|
||||||
|
|
||||||
self:onEnter(function (event)
|
statusWidget.text = event.target.status
|
||||||
local statusWidget = (self.master or self).statusWidget
|
return false
|
||||||
if not statusWidget then return end
|
end)
|
||||||
|
})
|
||||||
statusWidget.text = event.target.status
|
|
||||||
return false
|
|
||||||
end)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user