NAME

Term::Fabulous::Event::Mouse - A mouse click, release, drag or wheel turn from the terminal

SYNOPSIS

use Term::Fabulous::Termbox qw(TB_KEY_MOUSE_LEFT TB_KEY_MOUSE_RIGHT TB_KEY_MOUSE_WHEEL_UP TB_MOD_MOTION);

$panel->on( Mouse => sub ($event) {
	my ( $x, $y ) = ( $event->x, $event->y );    # terminal cell, from 0
	if ( $event->key == TB_KEY_MOUSE_LEFT ) {
		if ( $event->modifiers & TB_MOD_MOTION ) {
			drag_to( $x, $y );                   # moved with the left button held
		}
		else {
			start_at( $x, $y );                  # left button pressed
		}
	}
	return;
} );

DESCRIPTION

Term::Fabulous fires a Mouse event for every mouse report the terminal sends while "run" in Term::Fabulous is active and mouse input is enabled (the mouse parameter of "new" in Term::Fabulous, on by default except in inline mode, which has no mouse support). The event is fired on the topmost widget that painted the cell under the pointer in the last frame (see "MOUSE" in Term::Fabulous::Manual::Events for the exact rules), or on the root widget when there is none, and then bubbles up to the ancestors.

The class is a subclass of Clay::UI::Events::Event, so target, current_target, name ('Mouse' unless given to the constructor) and bubble_mode (IF_CONTINUE) are available as well.

What the terminal reports

Terminals report the mouse only in these cases:

  • a button is pressed: key is TB_KEY_MOUSE_LEFT, TB_KEY_MOUSE_MIDDLE or TB_KEY_MOUSE_RIGHT;

  • a button is released: key is TB_KEY_MOUSE_RELEASE, and released_button says which button it was when the terminal reports it (SGR mouse reports, which Term::Fabulous asks for, do);

  • the pointer moves while a button is held (a drag): key is the held button's key again and modifiers has TB_MOD_MOTION set;

  • the wheel turns: key is TB_KEY_MOUSE_WHEEL_UP or TB_KEY_MOUSE_WHEEL_DOWN, one event per notch; a horizontal wheel (or a sideways tilt of the wheel) gives TF_KEY_MOUSE_WHEEL_LEFT or TF_KEY_MOUSE_WHEEL_RIGHT.

The pointer moving without a button held is reported as well, but it is not a Mouse event: it fires MouseMove (Term::Fabulous::Event::MouseMove) instead.

Terminals encode Shift, Ctrl and Alt in their mouse reports; modifiers carries them as TB_MOD_SHIFT, TB_MOD_CTRL and TB_MOD_ALT, so a Shift+click can be told from a click.

CONSTRUCTOR

new

use Term::Fabulous::Termbox qw(TB_KEY_MOUSE_LEFT TB_KEY_MOUSE_RELEASE TB_MOD_MOTION);

my $press   = Term::Fabulous::Event::Mouse->new( key => TB_KEY_MOUSE_LEFT, x => 10, y => 3 );
my $drag    = Term::Fabulous::Event::Mouse->new( key => TB_KEY_MOUSE_LEFT, x => 12, y => 3, modifiers => TB_MOD_MOTION );
my $release = Term::Fabulous::Event::Mouse->new( key => TB_KEY_MOUSE_RELEASE, x => 12, y => 3 );

$canvas->fire_event($press);

Programs rarely build mouse events themselves; Term::Fabulous does it for every report. Building one by hand is useful in tests of one widget's Mouse listeners; the click method of Term::Fabulous::Terminal::Memory clicks like a real mouse (see "TESTING" in Term::Fabulous::Manual::Programs). Note that firing a hand-built event on a widget only runs the listeners. For a real left press, Term::Fabulous records the pointer position and moves the keyboard focus (see "FOCUS" in Term::Fabulous::Manual::Events) before it fires the Mouse event. Clay::UI's OnPress and OnRelease events (Clay::UI::Role::Interaction::Pressable) come later, during the next frame (within 1/30 second), when the recorded pointer is handed to Clay. A hand-built Mouse event does none of this. Unknown parameters die. Besides the parameters below, the name and bubble_mode parameters of Clay::UI::Events::Event are accepted.

key

Required. One of the TB_KEY_MOUSE_* constants listed under "key".

x

Required. The column of the pointer, counted from 0 at the left edge of the terminal.

y

Required. The row of the pointer, counted from 0 at the top edge of the terminal.

modifiers

Optional. A bit mask of TB_MOD_MOTION, TB_MOD_SHIFT, TB_MOD_ALT and TB_MOD_CTRL. Default: 0.

released_button

Optional. With key TB_KEY_MOUSE_RELEASE only: the button that was released, TB_KEY_MOUSE_LEFT, TB_KEY_MOUSE_MIDDLE or TB_KEY_MOUSE_RIGHT. Default: undef, the terminal did not say. Anything else dies.

An event object can be fired only once. Build a new one for every fire_event call.

of

my $event = Term::Fabulous::Event::Mouse->of($termbox_event);

Builds an event from a Term::Fabulous::Termbox::Event: key, x, y and modifiers from its key, x, y and mod, and for a release released_button from its ch (see "tf_install_input_parser" in Term::Fabulous::Termbox). Called by Term::Fabulous; class method.

METHODS

key

my $key = $event->key;

Which button or wheel direction the event is about. Import the constants from Term::Fabulous::Termbox:

use Term::Fabulous::Termbox qw(
	TB_KEY_MOUSE_LEFT TB_KEY_MOUSE_MIDDLE TB_KEY_MOUSE_RIGHT
	TB_KEY_MOUSE_RELEASE TB_KEY_MOUSE_WHEEL_UP TB_KEY_MOUSE_WHEEL_DOWN
	TF_KEY_MOUSE_WHEEL_LEFT TF_KEY_MOUSE_WHEEL_RIGHT
	TB_MOD_MOTION
);

Constant                  Meaning
------------------------  ------------------------------------------
TB_KEY_MOUSE_LEFT         left button pressed (or dragged)
TB_KEY_MOUSE_MIDDLE       middle button pressed (or dragged)
TB_KEY_MOUSE_RIGHT        right button pressed (or dragged)
TB_KEY_MOUSE_RELEASE      a button was released (see released_button)
TB_KEY_MOUSE_WHEEL_UP     wheel turned up (away from the user) one notch
TB_KEY_MOUSE_WHEEL_DOWN   wheel turned down one notch
TF_KEY_MOUSE_WHEEL_LEFT   horizontal wheel turned left one notch
TF_KEY_MOUSE_WHEEL_RIGHT  horizontal wheel turned right one notch

The TF_KEY_* constants are Term::Fabulous additions; termbox2 has no codes for a horizontal wheel.

x

my $column = $event->x;

The column of the cell under the pointer, an integer from 0 at the left edge of the terminal, also on terminals wider than 255 columns. To get a position inside a canvas, use "cell_at" in Term::Fabulous::Widget::Canvas or "pixel_at" in Term::Fabulous::Widget::PixelCanvas.

y

my $row = $event->y;

The row of the cell under the pointer, an integer from 0 at the top edge of the terminal.

modifiers

my $dragging = $event->modifiers & TB_MOD_MOTION;
my $shifted  = $event->modifiers & TB_MOD_SHIFT;

A bit mask. TB_MOD_MOTION is set when the event reports a move with a button held (a drag); TB_MOD_SHIFT, TB_MOD_ALT and TB_MOD_CTRL are set for the modifier keys held at the time.

released_button

use Term::Fabulous::Termbox qw(TB_KEY_MOUSE_RELEASE TB_KEY_MOUSE_RIGHT);

if ( $event->key == TB_KEY_MOUSE_RELEASE && ( $event->released_button // 0 ) == TB_KEY_MOUSE_RIGHT ) {
	close_context_menu();
}

For a TB_KEY_MOUSE_RELEASE: the key of the button that was released, TB_KEY_MOUSE_LEFT, TB_KEY_MOUSE_MIDDLE or TB_KEY_MOUSE_RIGHT; undef when the terminal did not say. Term::Fabulous takes a release that names no button for a release of the left button. For every other key: undef.

use_wheel

$event->use_wheel if $self->scroll_down_one_notch;

For a widget that scrolls itself with the wheel: marks the wheel notch of this event as used. Term::Fabulous scrolls the scroll containers around the pointer (Term::Fabulous::Widget::ScrollBox) by every notch no widget used, so call it only when the notch moved something; a widget that is already at its end leaves the notch to its scroll box. Whether the event bubbles on is up to the return value of the listener, as for any event. Returns the event.

wheel_used

my $scrolled_itself = $event->wheel_used;

1 after "use_wheel", otherwise 0.

SEE ALSO

"MOUSE" in Term::Fabulous::Manual::Events, Term::Fabulous, Term::Fabulous::Event::MouseMove, Term::Fabulous::Event::KeyPress, Clay::UI::Events::Event, Term::Fabulous::Termbox, "Paint with the mouse (Canvas, clicks and drags)" in Term::Fabulous::Cookbook::Canvases.