prompt-toolkit / python-prompt-toolkit

Library for building powerful interactive command line applications in Python
https://python-prompt-toolkit.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
9.1k stars 717 forks source link

Request for Enhanced Mouse Event Handling in Complex Widget Layouts #1818

Open gosirys opened 7 months ago

gosirys commented 7 months ago

Overview

I'm working on a project using Prompt Toolkit and facing challenges with mouse event handling for complex widget layouts. Specifically, I need to implement "on mouse over" and "on mouse out" events for widgets like Frame and Box, regardless of their nested content.

Objective

The goal is to enhance CLI interactivity by tracking mouse events across various widgets. This includes:

Challenge

Current Prompt Toolkit capabilities seem limited in handling mouse events for nested widgets. While Window controls support mouse events, extending this to more complex containers like Frame or Box with multiple children is problematic. The key issue is tracking mouse position relative to the widget layout, essential for determining widget interaction.

Request

  1. Existing Methods: Are there undocumented features or advanced techniques in Prompt Toolkit for such mouse event handling?
  2. Feature Consideration: If not presently possible, could this feature be a valuable addition to Prompt Toolkit?
  3. Implementation Guidance: Any suggestions for implementing this, either as a contribution or a custom extension, would be greatly appreciated.

This enhancement could significantly improve Prompt Toolkit's utility for interactive CLI applications.

Thank you for your time and consideration.

Osirys and ChatGPT, that helped writing this for me because I’m a stupid human

joouha commented 5 months ago

I've implemented this in euporie. I did it as follows:

  1. Add an attribute to the app which stores optional limits on the mouse position: https://github.com/joouha/euporie/blob/f1196539581f5f5c80bdca627c33a617ce330e24/euporie/core/app.py#L311
  2. Add an attribute to the app which stores the global mouse position: https://github.com/joouha/euporie/blob/f1196539581f5f5c80bdca627c33a617ce330e24/euporie/core/app.py#L312
  3. Add a custom mouse event handler to your app (this is just a special key-binding handler which listens for Keys.Vt100MouseEvent keys) which:
  4. Use this to write widgets that react to hover / mouse-out events, e.g. this container applies a style class to its contents when it is hovered: https://github.com/joouha/euporie/blob/f1196539581f5f5c80bdca627c33a617ce330e24/euporie/core/layout/decor.py#L201-L306