How can I check if a key is pressed together with a specific modifier in Gtk3 ? For example, here I want to check if CTRL+s is pressed:
use feature qw(say);
use strict;
use warnings;
use Gtk3 '-init';
use Glib qw(TRUE FALSE);
my $window = Gtk3::Window->new('toplevel');
$window->set_title('Hello world');
$window->set_position('center');
$window->set_default_size(500, 500);
$window->signal_connect('delete-event' => sub {
Gtk3->main_quit();
});
$window->signal_connect('key-press-event' => sub { handle_key( @_ ) } );
$window->show_all();
Gtk3->main();
sub handle_key {
my ( $widget, $event) = @_;
my $key = Gtk3::Gdk::keyval_name( $event->keyval );
if ( ($key eq 's') && control_pressed( $event ) ) {
say "CTRL+S";
}
return FALSE; # FALSE -> means propagate key further
}
How should I defined the function control_pressed()
above?
The $event->state
is of type Gtk3::Gdk::ModifierType
which has overloaded operators.
Flags have some additional magic abilities in the form of overloaded operators:
+ or | union of two flagsets ("add") - difference of two flagsets ("sub", "remove") * or & intersection of two bitsets ("and") / or ^ symmetric difference ("xor", you will rarely need this) >= contains-operator ("is the left set a superset of the right set?") == equality
In addition, flags in boolean context indicate whether they are empty or not, which allows you to write common operations naturally:
$widget->set_events ($widget->get_events - "motion_notify_mask"); $widget->set_events ($widget->get_events - ["motion_notify_mask", "button_press_mask"]); # shift pressed (both work, it's a matter of taste) if ($event->state >= "shift-mask") { ... if ($event->state * "shift-mask") { ... # either shift OR control pressed? if ($event->state * ["shift-mask", "control-mask"]) { ... # both shift AND control pressed? if ($event->state >= ["shift-mask", "control-mask"]) { ...
Also, the constants for the GdkModifierType enum becomes lower case strings in Perl. So the following should work:
sub control_pressed {
my ( $event ) = @_;
return $event->state & 'control-mask';
}