Conky: [Feature suggestion] Act on mouse-events / adding buttons to conky

Created on 9 Feb 2020  路  5Comments  路  Source: brndnmtthws/conky

This may require some discussion, so before I get to this point, allow me to summarize my suggestion (and the idea leading up to this suggestion):

  • I would like to be able to act on a conky part of a widget, e. g. a sub-area, via the mouse,
    on-click action. In other words, I'd like to have some means to "simulate" a button action or
    activity.

Reasoning for this suggestion:

  • Well, one primary reason is ... I'd like it. :)

But this is of course not a great reason per se, since many other people may use conky, and they may NOT need or want this; and more lines of code also create a burden. So I can understand if this is not added.

I use conky right now (managed to transition to the lua syntax really quickly and I semi-solved my older questions before here) and call several different ruby scripts. These tend to return/display a string, and this string is then displayed via conky. This works great! \o/

I would, however had, also like to use conky as some sort of interface builder, but really, just minimal.

For example, I would actually like to use conky for most of the desktop. The left side is reserved for oldschool desktop icons, but the right side is used by conky right now.

I would like to have different buttons which I can click, which should then launch custom files, apps, including ruby-gtk widgets. I can of course use regular icons for this, but this is a bit more annoying; conky would be MUCh easier for me and I could use it on a new computer device instantly, without having to autogenerate the .desktop files which are normally used.

I would also be independent of the functionality offered by the WM/DE at hand e. g. could use this perhaps on ion or whatever the name is now (i3m, ratpoison and similar WMs).

So I hope that I may not be the only one who would like to have "buttons".

When I write "buttons", I actually merely mean some kind of shape, a rectangle, and conky would have to respond to two issues:

  • left mouse button event

AND THEN

  • a custom action. E. g. if it is an existing file, it could just be run. We already can do the latter
    to some extent via execi and so forth.

I think what I would like to propose is to use conky as some kind of meta-launcher for other applications too, thus slightly repurposing conky.

I am not sure if this fits the original aims for conky, and it is fine if there is consensus against it, but I like the idea :P - I am not sure my own skills would allow me to add this, since I really don't know enough about C++, and conky is written in C++ mostly (excluding the lua parts). However had, even if this may not fit, I think it may be useful if others could chime in and say whether they think this may be useless or useful. Thanks. :)

enhancement

Most helpful comment

BAM!

You can download and build my fork if you want to try playing around with mouse events. There are several touchups I want to perform before creating a PR - ability to force events to pass through by returning true(consumed)/false(pass) in the hook, maybe clean up any remaining inconsistencies...

Hook name is lua_mouse_hook. Instead of defining 5+ hooks, I opted for creating just one and passing the data in a table.

Here's the list of supported events:

  • button_down
  • button_up
  • mouse_move
  • mouse_enter
  • mouse_leave

You're supposed to handle them by reading event.type string and putting logic into appropriate if-clauses - where event is the name of first (and only) argument and value is one from the above list.
Then, depending on event type, different data is provided:

Move event

event table has following keys:

  • x - window-relative cursor x position (int)
  • y - window-relative cursor y position (int)
  • x_abs - display-relative cursor x position (int)
  • y_abs - display-relative cursor y position (int)
  • time - time in ms provided by Xlib (ulong)

Button press and release event

event table has all movement event keys and additionally:

  • mods - table of buttons and modifier keys being held (name -> bool)

    • shift

    • lock

    • control

    • mod1

    • mod2

    • mod3

    • mod4

    • mod5

    • mouse_left

    • mouse_right

    • mouse_middle

    • scroll_up

    • scroll_down

  • button - number of the button being pressed/released (int)

    • Left button: 1

    • Right button: 2

    • Middle button: 3

    • Scroll up: 4

    • Scroll down: 5

      I intend on adding custom event type for scrolling, but Xorg handles it as mouse button presses (for both mods and button) so I'm just passing it through for now. I haven't tested mods scroll_up and down, might actually represent 2 extra buttons on some mice, haven't tested this properly.

Mouse enter/leave event

Called when the mouse enters or leaves conky window area. This might be useful for "turning off" "buttons" when the user drags their mouse outside the window while holding the mouse button pressed.
event fields are the same as in the movement event. There was some extra data being provided but I think most would find it useless so I left it out.

Additional info

If anyone wishes to ask for more data, here's what's provided by Xorg:

If you need dragging, provided events should suffice for simple drag implementation. Adding it as an event would make the C++ code less readable, harder to maintain and it wouldn't be used most of the time.

Movement event might end up slowing down conky just due to how much it's being called, so I might make it disableable or move it into its own hook.

All 5 comments

I never tried this feature, but we might had it in the past. Just that it might be broken right now. https://github.com/brndnmtthws/conky/issues/894

Yes this would be useful to show the weather like in Android.

In that when I click the weather button, it opens a browser tab to show me more details of the weather.

@lasers I think this is kinda a different request to that one. That one appears to be for applications outside of Conky, and this one Conky itself.

I'd like this too. I wanted to implement it locally several times in the past but never actually found it worth the trouble. As coronavirus is currently preventing me from working on any of other urgent(/I should really finish this) projects, might get around to doing it now and pimping out my configs.
Currently, there is a way of doing this without any code changes but it's very cumbersome.

Two things are very important and should be discussed further though:

  • What constitutes a button/clickable area?
  • What data and how that data should be provided?

I think that adding lua_click_hook is a good choice. That way, configs are backwards compatible and familiar to users who already did some graphics rendering. Providing a global table (e.g. click_event) to those hooks containing x and y position of mouse click should be enough for users to calculate whether a specific (button) area has been clicked.
If instead of adding only the lua_click_hook hook, several different event hooks are added (lua_mouse_hook_press, lua_mouse_hook_release, lua_mouse_hook_drag), adding draggable elements becomes possible and even easy. This would, in turn, allow things like sliders to be created. Providing start and current x and y mouse positions would also be very useful for animations in lua_mouse_hook_release and lua_mouse_hook_drag.

I haven't actually looked at Conky source code yet, but on top of my head, it shouldn't take more than 20 or so lines of code (excluding construction of Lua objects/tables). I'm about to fork the repo and play with this so I'll post any further findings.

EDITS: Oh, and this behaviour should, in theory, be possible to disable with a compile-time flag if someone wants a "minimal"/non-clickable version of Conky. That way it becomes very trivial to maintain both versions.

This should be very straightforward to add. st by suckless handles all mentioned mouse events so it should be a great reference.

Status update:

I managed to add a new option to CMake for mouse events, info to conky -v output, and basically completely integrated this feature into the build system.
Mouse hooks are getting updated only when conky is NOT mounted on the root window (own_window="desktop" or "override"). Changing root window results in a crash. normal or dock & 'panel' work properly. I use bspwm, this might be a WM specific thing and should be further tested. Some WMs/DEs might require desktop or override to display conky in the background which means clicking won't work on those unless support for conky is added to their code (very unlikely). A possible (but overly complicated) solution is to add support for conky on your own and compile your WM/DE.

Clickable conky preview

I'm looking into passing tables to functions so that arguments are nicely packed into an event table instead of forcing users to write down arguments they might not use. This could also be done both ways, nothing special about passing tables (apart from them being harder to implement and having 0 existing support code), so opinions are welcome here.

Mouse press and release are straightforward (convert Xlib event to a Lua table, update global var, call Lua function, destroy global var/set to null). Dragging requires some extra code exploration to see where I can butt in info about drag start position and time. Initially, even a click should trigger the drag event, but maybe a delay option can be added later.
As similar code will be required for dragging, I'll add lua_mouse_hook_hover too for detecting mouse movement. That should allow changing "button" texture on hover.

st by suckless helped a lot with understanding Xlib code, conky already handles mouse events but only forwards the event to windows underneath (if any), also it only does it in a specific window mode (no longer sure which).

Questions:

  • How should conky handle mouse presses when it's overlayed over other windows - should it consume them, pass them through, both, or should Lua hook return value (bool) dictate what happens and default to pass through?
  • How should arguments be passed to hooks? Using direct values - simple to implement and very clear, but ugly and more verbose / tables - a bit complicated and might be hard for new users to understand but look a lot cleaner.

BAM!

You can download and build my fork if you want to try playing around with mouse events. There are several touchups I want to perform before creating a PR - ability to force events to pass through by returning true(consumed)/false(pass) in the hook, maybe clean up any remaining inconsistencies...

Hook name is lua_mouse_hook. Instead of defining 5+ hooks, I opted for creating just one and passing the data in a table.

Here's the list of supported events:

  • button_down
  • button_up
  • mouse_move
  • mouse_enter
  • mouse_leave

You're supposed to handle them by reading event.type string and putting logic into appropriate if-clauses - where event is the name of first (and only) argument and value is one from the above list.
Then, depending on event type, different data is provided:

Move event

event table has following keys:

  • x - window-relative cursor x position (int)
  • y - window-relative cursor y position (int)
  • x_abs - display-relative cursor x position (int)
  • y_abs - display-relative cursor y position (int)
  • time - time in ms provided by Xlib (ulong)

Button press and release event

event table has all movement event keys and additionally:

  • mods - table of buttons and modifier keys being held (name -> bool)

    • shift

    • lock

    • control

    • mod1

    • mod2

    • mod3

    • mod4

    • mod5

    • mouse_left

    • mouse_right

    • mouse_middle

    • scroll_up

    • scroll_down

  • button - number of the button being pressed/released (int)

    • Left button: 1

    • Right button: 2

    • Middle button: 3

    • Scroll up: 4

    • Scroll down: 5

      I intend on adding custom event type for scrolling, but Xorg handles it as mouse button presses (for both mods and button) so I'm just passing it through for now. I haven't tested mods scroll_up and down, might actually represent 2 extra buttons on some mice, haven't tested this properly.

Mouse enter/leave event

Called when the mouse enters or leaves conky window area. This might be useful for "turning off" "buttons" when the user drags their mouse outside the window while holding the mouse button pressed.
event fields are the same as in the movement event. There was some extra data being provided but I think most would find it useless so I left it out.

Additional info

If anyone wishes to ask for more data, here's what's provided by Xorg:

If you need dragging, provided events should suffice for simple drag implementation. Adding it as an event would make the C++ code less readable, harder to maintain and it wouldn't be used most of the time.

Movement event might end up slowing down conky just due to how much it's being called, so I might make it disableable or move it into its own hook.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mreinhardt picture mreinhardt  路  3Comments

moyamo picture moyamo  路  3Comments

Microcrap picture Microcrap  路  4Comments

Dimerbone picture Dimerbone  路  4Comments

bunder2015 picture bunder2015  路  4Comments