当 input_passthrough 为真时,awesome-wm wibox 不会对鼠标信号做出反应

awesome-wm wibox not reacting to mouse signals when input_passthrough is true

基本上,我想要做的是有一个侧边栏,当我将鼠标移到屏幕的左边缘时它会显示,当我将鼠标移得太远时它会消失来自侧边栏。

所以我制作了三个小部件:

我已经完成了大部分工作,但有一个我无法解决的特殊错误:

wibox 函数将 table 个字段作为参数。如果您查看我提供的代码,您会注意到 sidebar_visible_limitinput_passthrough 字段并未放入 table 的正文中,而是在之后提供,就在创建小部件。

问题是它不会在鼠标离开时关闭侧边栏或自身。它没有检测到鼠标离开。

但是如果把 input_passthrough = true 放在提供给 wibox 函数的 table 中,像这样:

    bar.sidebar_visible_limit = wibox({ 
    x = 0, 
    y = 0, 
    ontop = false, 
    visible = false,
    width = bar.sidebar.width + dpi(100),
    height = bar.sidebar.height,
    bg = '#000000',
    opacity = 0.3, -- when it's all done this will be '0'
    input_passthrough = true
    })

然后一切正常,除了现在它不允许输入通过。

如果能解释为什么会这样,我将不胜感激。

这是代码:

awful = require("awful")
local wibox = require("wibox")
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
xresources = require("beautiful.xresources")
dpi = xresources.apply_dpi

bar = {}

-- make the sidebar
bar.sidebar = wibox({ 
    x = 0, 
    y = 0,  
    ontop = false, 
    visible = false,
    width = beautiful.sidebar_width or dpi(450),
    bg = beautiful.sidebar_bg or "#2f2e3a",
    type = "dock",
    height = beautiful.sidebar_height or awful.screen.focused().geometry.height,
})

-- Hide sidebar when mouse leaves too much from the sidebar
-- It's incorporated along in the same table with the sidebar so the users
-- can implement these however they want, e.g. in the 'keys.lua' module

bar.sidebar_visible_limit = wibox({ 
    x = 0, 
    y = 0, 
    ontop = false, 
    visible = false,
    width = bar.sidebar.width + dpi(100),
    height = bar.sidebar.height,
    bg = '#000000',
    opacity = 0.3, --when it's all done this will be '0'
    })
bar.sidebar_visible_limit.input_passthrough = true

-- Show sidebar when mouse touches edge
local sidebar_displayer = wibox({ 
    x = 0,
    y = 0, 
    height = bar.sidebar.height,
    ontop = true,
    width = 1,
    visible = true, 
    opacity = 0,
    input_passthrough = true
})

function toggle_bar()

    -- they have to be in this order, so the sidebar will show first,
    -- and then the wibox that will close the sidebar when the mouse leaves
    -- second. If you do it the other way around, then if you go with the
    -- mouse on the sidebar-closing wibox , then if you try to go back 
    -- to the sidebar, it will close it because it's 'left' the widget.
    -- That's why you have the sidebar-closing wibox on top and allow
    -- input_passthrough for the sidebar-closing wibox

    bar.sidebar.visible = not bar.sidebar.visible
    bar.sidebar.ontop = not bar.sidebar.ontop

    bar.sidebar_visible_limit.visible = not bar.sidebar_visible_limit.visible
    bar.sidebar_visible_limit.ontop = not bar.sidebar_visible_limit.ontop

end

bar.sidebar_visible_limit:connect_signal( "mouse::leave", toggle_bar )
sidebar_displayer:connect_signal( "mouse::enter", toggle_bar )

I would greatly appreciate an explanation as to why this happens.

我认为 X11 服务器报告鼠标 enter/exit 相对于 window 的输入区域。使用 input_passthrough,输入区域变为空。这意味着 X11 服务器现在将报告鼠标指针位于您的 wibox 下方的 window 内,而不是 wibox 本身内。

BUT if put the input_passthrough = true in the table provided to the wibox function then everything works fine, EXCEPT that now it doesn't allow input to pass through.

换句话说:在这种情况下,input_passthrough 属性 未设置。似乎您发现了无法以这种方式设置的属性之一。 ;-)


因为我猜你也想知道如何做你想做的事情:如果你是 运行 合成经理(xcompmgrcompton、. ..),你可以制作一个背景完全透明的wibox。这样,X11 服务器将 "think" window 在那里并报告与其相关的输入事件,但 wibox 实际上不会在屏幕上可见。

(如果您没有合成管理器:制作一个显示具有适当偏移量的墙纸的小部件。可以通过阅读 /usr/share/awesome/lib/wibox/drawable.lua 找到有关如何执行此操作的提示,以 if not capi.awesome.composite_manager_running then 开头,这对墙纸有所帮助。如有必要,请随时询问更多详细信息。)

您可以使用 mousegrabber 来检测鼠标的位置:

bar.sidebar.ontop = true

function show_sidebar()
    bar.sidebar.visible = true
    mousegrabber.run(function(mouse)
        if mouse.x > bar.sidebar.width + dpi(100) then
            hide_sidebar()
            return false
        end
        return true
    end)
end

function hide_sidebar()
    bar.sidebar.visible = false
end

或者,您也可以使用相同的 mousegrabber 来决定何时显示边栏:

bar.sidebar.ontop = true

function show_sidebar()
    bar.sidebar.visible = true
end

function hide_sidebar()
    bar.sidebar.visible = false
end

mousegrabber.run(function(mouse)
    if bar.sidebar.visible then
        if mouse.x > bar.sidebar.width + dpi(100) then
            hide_sidebar()
        end
    else
        if mouse.x == 1 then
            show_sidebar()
        end
    end
    return true
end)

我认为这比在整个屏幕上创建一个不可见的 wibox 更好。