Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pynput reject input when terminal not focused

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.

like image 254
Matthew Rasa Avatar asked Oct 23 '25 05:10

Matthew Rasa


1 Answers

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

like image 183
Xin Jin Avatar answered Oct 25 '25 20:10

Xin Jin