Ubuntu – KEY.is_pressed() in gi.repository.Gdk

application-developmentgtkgtk3python

I was wondering if anyone knew how to detect if a key is currently pressed with either Gtk or Gdk and python? I don't want to use the key-pressed or key-released event for this scenario, but rather check if it is currently pressed on application startup.

Specifically, here is what I would like my application to do:

  1. Begin opening by keyboard shortcut.
  2. Wait 2 seconds.
  3. If keyboard shortcut is still held after 2 seconds, show the window.
  4. If, at any point during the 2 second timer, the keyboard shortcut was released, do not show the window, and exit.

This is similar to the functionality seen in the Unity Keyboard Shortcut Overlay, where you hold the SUPER key for 2 seconds and the window is displayed. If there is a better way to do this (preferably without the program running in the background and waiting), that would be acceptable as well.

Hoping for the best,

Sean

Best Answer

Assuming that you are talking about an ordinary button (as supposed to a togglebutton) you can see all the methods it has here. As I read it there does not seem to be a function for what you are looking for, probably because these things are designed to be event driven.

In any case, I am wondering, can't you just get the events to set a boolean and have a look at that to see if it is pressed. Otherwise, maybe you can explain the rationale of why it is important to you to go around the events.

EDIT

After realizing that I misread you original post and that you were talking about keyboard keys and not buttons I came up with the following suggestion.

When the program is run, it will make a gtk window and hide it, to make it possible to listen for keyboard events. Then it will listen for key released events from any of the keys that are in the shortcut that started the program (in this case ctrl-alt-u). If any of those keys are released, within the start up timeout, it will quit at the end of the timeout, otherwise, it will show the program.

If you want to delay the actual start of your program code to save resources, you can of course just use a dummy window and not load the real window or any of the underlying classes before in the start_or_not function.

import pygtk
pygtk.require('2.0')
import gtk

class DelayedStart:

    def __init__(self):
        self.w = gtk.Window()
        self.w.connect('destroy', gtk.main_quit)
        # Connect key released events to a function
        self.w.connect('key_release_event', self.on_key_press_event)
        self.w.show_all()
        # Hide the window, we actually need a gtk window to listen for
        # keyboard events, so we just hide it
        self.w.set_decorated(False)
        self.w.set_opacity(0)

        self.show_on_timeout = True
        # Ask gtk to call the this function in 2 seconds
        gtk.timeout_add(1000*2, self.start_or_not)
        gtk.main()

    def on_key_press_event(self, widget, event):
        """ Check if any of the key in the shortcut ctrl-alt-u is released """
        # ctrl = 65507, alt = 65513, u = 117
        keys = [65507, 65513, 117]
        if event.keyval in keys:
            self.show_on_timeout = False

    def start_or_not(self):
        """ Check if the program should be started or not """
        if self.show_on_timeout:
            self.w.set_decorated(True)
            self.w.set_opacity(1)
        else:
            gtk.main_quit()
        # Returning false will destroy the timer, we only want to run this once
        return False

if __name__ == "__main__":
    DELAYED_START = DelayedStart()