Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

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

share|improve this question

2 Answers 2

I'll just add a note here; I just learned of the keybinder library, which apparently is split from Tomboy notes (though it is Gtk2, and I just saw the label Gtk3):

It is compiled from C as a shared object library .so, and it has a Python interface:

python -c 'import pprint,inspect,keybinder; pprint.pprint(inspect.getmembers(keybinder))' | less

Look at the source in keybinder/libkeybinder at master · engla/keybinder · GitHub; I can see that even on a C level, the implementation is through signing up for keypress events - and there is nothing (apparent to me) holding the actual pressed state of keyboard keys. Which probably means that, unfortunately, there isn't a facility (function, array) to look up a pressed state of a(ny) key at any time.

share|improve this 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()
share|improve this answer
    
I need to go around the events because I need to start the application with a key shortcut and a wait to display, or do not display if the keys have been released. Similar to the Ubuntu Keyboard Shortcut Overlay, without having to have the application running in the background waiting to catch input. –  Sean Davis May 17 '12 at 18:05
    
Ahh, I'm afraid I still don't fully understand the logistics of you demands, but that probably just means is beyond my skills. Sorry about the noise and I hope you get a usable answer. –  TLE May 17 '12 at 19:40
    
I think I understand you problem better with the new description. This shortcut that you mention should start the program, is that a shortcut in a program that you control/write or a system global one like ctrl-alt-t to open a terminal etc.? –  TLE May 19 '12 at 10:52
    
Just to note my logistics demands for the same kind of problem: I am developing a plugin for a pygtk app; the app itself registers as a listener for a given shortcut. I'd like the plugin to do different things, based on whether the keys for that shortcut are still held or not - however, it seems that I'd have to change the core of the application, to have a management based on press/release events. If I had a way to "peek" into status of keyboard keys at any time - then the plugin could have used that, instead of changing the application core. –  sdaau Apr 8 '13 at 14:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.