简体   繁体   中英

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

Basically, what I'm trying to do is have a sidebar, and have it show up when I move my mouse to the left edge of the screen, and have the sidebar disappear when I move my mouse TOO MUCH away from the sidebar.

So I made three widgets:

  • one that's one pixel wide on the side and that, when it detects the mouse entering, shows the sidebar

  • the actual sidebar

  • and a widget that's wider than the sidebar, is fully transparent, has input_passthrough set to true , and its only purpose is to look for the "mouse::leave" signal and when the mouse leaves, it would make itself and the sidebar disappear.

I got most of it to work but there's this particular error that I can't solve:

The wibox function takes as argument a table of fields. If you look through the code I provided, you can notice that the input_passthrough field of the sidebar_visible_limit hasn't been put in the body of the table, but supplied afterwards, right after the creation of the widget.

The problem with this is that it simply doesn't close the sidebar or itself when the mouse leaves. It doesn't detect the mouse leaving.

BUT if put the input_passthrough = true in the table provided to the wibox function, like this:

    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
    })

then everything works fine, EXCEPT that now it doesn't allow input to pass through.

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

This is the code:

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.

I think the X11 server reports mouse enter/exit relative to the input region of a window. With input_passthrough , the input region becomes empty. This means that the X11 server will now report the mouse pointer to be inside the window beneath your wibox and not inside of the wibox itself.

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.

In other words: In this case the input_passthrough property is not set. Seems like you found one of the properties that cannot be set this way. ;-)


Since I guess you also want some ideas on how you can do what you are trying to do: If you are running a compositing manager ( xcompmgr , compton , ...), you could make a wibox with a completely transparent background. That way, the X11 server will "think" that the window is there and report input events relative to it, but the wibox will not actually be visible on screen.

(And if you don't have a compositing manager: Make a widget that displays your wallpaper with the proper offset. A hint on how to do this can be found by reading /usr/share/awesome/lib/wibox/drawable.lua , the part that begins with if not capi.awesome.composite_manager_running then and that does something with the wallpaper. Feel free to ask for more details if necessary.)

You could use a mousegrabber to detect the position of the mouse:

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

Alternatively, you could use the same mousegrabber to decide when to show the sidebar too:

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)

I think this is nicer than creating an invisible wibox over the whole screen.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM