brndnmtthws / conky

Light-weight system monitor for X, Wayland (sort of), and other things, too
https://conky.cc
GNU General Public License v3.0
7.17k stars 615 forks source link

[Bug]: Mouse clicks aren't consumed when llua_mouse_hook returns true. (X11) #1495

Closed ErskaConti closed 5 months ago

ErskaConti commented 1 year ago

What happened?

I noticed the (awesome) implementation of Mouse Events recently added to Conky.

but I think due to this being so new documentation does not exist... so i printed all the args passed to lua and explored stuff...

now I also love the fact that I can click-through the Conky window. but I'll want to consume^(aka, skip pass-through) the clicks from time to time.

I was expecting the event to be consumed by return true; in the hook-function. (I also tried return false;)

On a sidenote, each click-through also triggers Leave-Enter events (at least on KDE) as the desktop is selected so as to trigger the click on it.

Version

conky-cairo 1.19.0-1 (AUR)

Which OS/distro are you seeing the problem on?

Arch Linux

Conky config

No response

Stack trace

No response

Relevant log output

No response

ErskaConti commented 1 year ago

I upgraded my computer, which lead to re-installation of stuff.

now I'm running in OpenBox (ran in KDE^(why the f did I forget to say that) before) .

function mouse_hook(args)

  return true;
end

does consume clicks.

so seems to work as expected under OpenBox.


conky-cairo from AUR v 1.19.1-1

Caellian commented 10 months ago

Thanks for pointing out lack of documentation, I added it to the wiki so people can find out about it.

I was expecting the event to be consumed by return true; in the hook-function. (I also tried return false;)

The way I implemented it, if the hook returns true it should stop the propagation. Given that it works on some WMs, I'd guess that it has to do with how KDE handles events.

Maybe if an event isn't captured by any floating windows KDE notifies the desktop code, it's impossible to tell without the config though. Please provide the config so we can know how conky window is mounted.

click-through also triggers Leave-Enter events (at least on KDE) as the desktop is selected so as to trigger the click on it.

This is a bug in the merged PR and I'm certain it has to do with how the feature is implemented. Passing events through probably causes X11 to think the desktop is now under the cursor. This has to be handled by conky by making it remember it passed the event through and preventing the callback trigger for enter/leave events to avoid quirks.

ErskaConti commented 10 months ago

Please provide the config so we can know how conky window is mounted.

I have my screen-data in a separate .lua file.

.conkyrc

local fullpath = debug.getinfo(1, "S").source:sub(2);

local dirpath, filename = fullpath:match('^(.*/)([^/]-)$');
local conkyHomeDir = dirpath:match('^(.*/.conky)/');

dofile(conkyHomeDir..'/LayoutPlacement.lua');

local screen = LAYOUTS.left_fullscreen;

conky.config = {
  xinerama_head = screen:xinerama_head(),
  alignment = screen:alignment(),
  gap_x = screen:getX(),
  gap_y = screen:getY(),
  minimum_width = screen:getX() + screen:getWidth(),
  maximum_width = screen:getX() + screen:getWidth(),
  minimum_height = screen:getY() + screen:getHeight(), --comment this out to have height scale down.
  ----------------------------------------------------------------

  border_inner_margin = 1,
  border_outer_margin = 1,

  ----------------------------------------------------------------
  background = true,
  double_buffer = true,
  no_buffers = true,

  ----------------------------------------------------------------------
  own_window = true,
  own_window_colour = '000000',
  own_window_class = 'Conky',
  own_window_title = 'clickyAAA',
  own_window_type = 'normal';
  --own_window_type = 'desktop';
  --own_window_type = 'dock';
  --own_window_type = 'panel';
  --own_window_type = 'override';
  own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager',
  ---------------------------------------------
  own_window_transparent = true,
  own_window_argb_visual = true,
  own_window_argb_value = 0,
  ---------------------------------------------
  draw_borders = true,
  stippled_borders = 2,
  ----------------------------------------------------------------------

  ----------------------------------------------------------------
  update_interval = 1,
  cpu_avg_samples = 4,
  net_avg_samples = 2,
  temperature_unit = 'celsius',
  no_buffers = true, --Conky will show only actual amount of RAM being used.
  ----------------------------------------------------------------

  ----------------------------------------------------------------

  draw_shades = false,
  draw_outline = true,
  draw_graph_borders = false,
  ----------------------------------------------------------------

  ----------------------------------------------------------------
  use_xft = true,
  xftalpha = 1,
  --override_utf8_locale = true,
  font = 'Pf Tempesta Five:bold:size=12',
  uppercase = false,
  ----------------------------------------------------------------

  lua_load = dirpath..'addThis.lua', --dirpath..'' required due to this string replacing debug.getinfo(1, "S").source:sub(2)

  lua_startup_hook = 'startup',
  lua_draw_hook_pre = 'draw_pre',
  lua_draw_hook_post = 'draw_post',
  lua_shutdown_hook = 'shutdown',
  lua_mouse_hook = 'mouse_hook',

};
conky.text = [[]]..

[[]];

addThis.lua, actually a Frankenstein's monster I copy pasted from main.lua which my actual addThis.lua executes... and other lua files I've cut up my project I tested this in into... might run without errors, might not.

local fullpath = debug.getinfo(1, "S").source:sub(2);
local dirpath, filename = fullpath:match('^(.*/)([^/]-)$');

local printMouse=false;
local printMouseArgs(args)
local printMouseArgs = function(args)
  print("type:"..args.type);
  if(args.button)then
    print("button: "..args.button);
  end
  if(args.direction)then
    print("direction: "..args.direction);
  end

  print("(x,y) "..args.x..","..args.y.."");
  print("(x,y)_abs "..args.x_abs..","..args.y_abs.." (global)");

  print("active mods");
  for key, value in pairs(args.mods) do
    if(value) then print("   "..key); end
  end
end;
end

local recognized_conky_mouse_events = {
  button_down = function(args)--on click
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------
    --handle click
    --------------------------------
    return true;
  end, -- called when a mouse button is clicked
  button_up = function(args)--on click
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------
    --------------------------------
    return true;
  end, -- called when a mouse button is released
  mouse_scroll = function(args)--on scrollwheel (up/down)
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------
    if(args.direction == "up")then

    else
      if(args.direction == "down")then

      end
    end
    --------------------------------
    return true;
  end, -- called on scroll action (X handles it the same way as button clicks)
  mouse_move = function(args)
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------
    Mouse.movedTo(args.x, args.y, args.x_abs, args.y_abs);
    --------------------------------
    --called only on coord changes
    return false;
  end, -- called when the pointer is being dragged across conky window
  mouse_enter = function(args)
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------

    --------------------------------
    --also called on clicks (due to click-through)
    return false;
  end, -- called when the pointer enters conky window
  mouse_leave = function(args)
    if(printMouse)then
      printMouseArgs(args);
    end;
    --------------------------------
    --------------------------------
    --also called on clicks (due to click-through)
    return false;
  end, -- called when the pointer leaves conky window

};

function HandleMouse(args)
    consume = false;
      local result = {};
      if not pcall(function()
        consume=recognized_conky_mouse_events[args.type](args);
      end, result)
      then
        print("HandleMouse()  "..args.type)
        print("Error");
        print(result[1]);
      end;
    if(consume)then console.warn("consume!"); end
    return consume;
end

function conky_startup (args)

end
function conky_draw_pre (args)

end
function conky_draw_post (args)

end

function conky_shutdown (args)

end

function mouse_hook(args)
  consume = handleMouse(args);
  return consume;
end

I trimmed the stuff down, haven't been messing with conky for a while, life got in the way.

I use a console.lua I've written to aproximate javascript's console (console.log() console.warn() console.error() console.group() console.groupEnd()) I think I replaced those with print("").

but the .lua shouldn't matter anyway, nor should you need the values of the screen:functions

Caellian commented 10 months ago

Alright, thanks. I'll check this out soon. I have midterms coming up so it might take some time as I'll have to install KDE and tinker with the sources.

This is my general overview for these issues rn, writing it down so I don't forget:

Caellian commented 10 months ago

Just letting you know that these issues have mostly been fixed in #1672.

The issue where an incorrect mouse_enter is produced on clicking remains (mouse_leave won't be reported anymore). I don't think there's a way around that other than every conky instance tracking the mouse and generating these events internally. They are passed into conky from the WM and while mouse_leave can be avoided with bounds checking, there's no trick to do that for mouse_enter. Having the conky constantly track the mouse movement seems like an overkill IMO given that these events will likely only ever be used to change how "components" are displayed and that multiple mouse_enter events won't affect that. Maybe there's a use case that I didn't think of, but not reporting mouse_leave should prevent flickering and such with that application.

Mouse movement is now propagated to the background as well, so hovering over KDE widgets through conky, for instance, produces popup bubbles as expected.

ErskaConti commented 10 months ago

This might be naive, but couldn't you stop Mouse_Enter by tracking Enter/Leave (boolean isInside), and doing if(isInside){return;} in Mouse_Enter event?

only problem I can see happening is somehow not firing off Mouse_Leave to turn isInside to false.

Caellian commented 10 months ago

With that, mouse_enter doesn't get reported when there's an app overlapping conky (because X11 doesn't tell conky mouse left; that's a new edge case). The only solution to this seems to be constantly tracking the mouse position and overlapping windows. I'll sleep on it and see whether there's something else that can be done.

EDIT: Okay, we can also listen for XCrossing events on other windows, which isn't much better, but at least it's more CPU friendly than what I had in mind.

Caellian commented 10 months ago

The only solution that woked was listening globally for all cursor movement events, then testing whether cusrsor is over conky and tracking it like you've said. Now it's 100% correct behavior. Though it required an additional X11 extension.

Caellian commented 5 months ago

This was fixed by commits that introduced Xinput.