4

I have a python graphical application that runs in a terminal and accepts keyboard input using the pynput module. The issue I am having is that pynput accepts input all the time, even when the terminal running the application is not in focus by my window manager. This makes it difficult to shift focus to another task without accidentally typing into the application.

Ideally, I would like to be able to either:

  1. Have pynput reject input when the terminal is not in focus

OR

  1. Have some way of determining when the application gains/loses focus (so I can simulate #1 myself)

I have searched the pynput documentation, but I cannot find a solution. Any advice on how to accomplish this is appreciated. I am using Linux.

2
  • 2
    pynput is a horribly inappropriate choice for your application - its whole point is to monitor/control the keyboard and mouse input of other programs. You mentioned that this is a graphical application, whatever library you're using to implement that certainly has a more appropriate form of keyboard input already. Commented Nov 28, 2017 at 13:35
  • That's good to know, I misunderstood its usage. Commented Nov 28, 2017 at 13:39

1 Answer 1

2
import time
from threading import Thread
from pynput import keyboard
from win32gui import GetWindowText, GetForegroundWindow

class KeyLogger:
    def __init__(self) -> None:
        self.is_paused=False  # pause keylog listener
        self.is_closed=False  # stop and close keylog
        self.l=None  # listener

        self.listened_window=GetWindowText(GetForegroundWindow())  # set listened window name
        self.focused_checker=Thread(target=self.check_focused)  # check if out of focused window in a thread
        self.focused_checker.start()
    
    def start(self):
        # initialize and start listener
        self.l=keyboard.Listener( on_press=self.on_press, on_release=self.on_release)
        self.l.start()

    def close(self):
        # stop and close keylog
        self.is_closed=True
        self.stop()

    def stop(self):
        # stop listener
        self.l.stop()
        self.l.join()
        
    def check_focused(self):
        while not self.is_closed:
            if GetWindowText(GetForegroundWindow())!=self.listened_window:  # compare now focused window with listened window
                if not self.is_paused:  # if different and not paused, stop listening
                    self.stop()
                    self.is_paused=True
            elif self.is_paused:  # if same but paused, restart listening
                    self.start()
                    self.is_paused=False
            time.sleep(0.1)

Hi, I faced a similar problem on windows, and this is my solution. Different platform, but may give you some inspirations.

In short, you need a function to check out the focused window in a loop, and change the state of listener by a boolean variable as an internal flag.

Not a built-in function, but the solution is indicated in documentation, listed as below.

Once pynput.keyboard.Listener.stop has been called, the listener cannot be restarted, since listeners are instances of threading.Thread.

If your application requires toggling listening events, you must either add an internal flag to ignore events when not required, or create a new listener when resuming listening.

pynput documentation

Sign up to request clarification or add additional context in comments.

1 Comment

update: self.listened_window="keyboard_listener" c='echo -n -e "\033]0;{}\007"'.format(self.listened_window) os.system(c) In terminal, this altered script can make keyboard listener only wake at the tab named "keyboard_listener". The principle is simple, renaming the tab and differentiating it from other tabs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.