In pygame for event.type == ACTIVEEVENT, where is the documentation on what the different event.state and event.gain parameters mean?

Question:

I am writing a game in pygame and ran into a situation with needing to discover when the game gains and looses focus. This is indicated with the event.type ACTIVEEVENT, which has two parameters event.state and event.gain. However after looking all over I have been able to find only a little info on what these imply. There are at least 6 different state values that an ACTIVEEVENT can have and each of those states can have multiple gain values

There are snippets here and there, but I could not actually find actual documentation on it anywhere. There is a couple references to the ACTIVEEVENT in https://www.pygame.org/docs/ref/ but no actual information.

I am not looking for people to tell me bits and pieces of what they have discovered about how it works, I have already found it in dribs and drabs, and based on that and some experimenting I figured out what I need. (ACTIVEEVENT state 2, gain 0 seems to mean window lost focus, and ACTIVEEVENT state 6, gain 1 seems to mean window regained focus).

What I want to know is where there is any actual documentation on the ACTIVEEVENT event and/or where I can find it in the pygame documentation if I am missing it somehow?

Asked By: Glenn Mackintosh

||

Answers:

Here it says: “When the display mode is set, several events are placed on the pygame event queue. pygame.QUIT is sent when the user has requested the program to shut down. The window will receive pygame.ACTIVEEVENT events as the display gains and loses input focus. If the display is set with the pygame.RESIZABLE flag, pygame.VIDEORESIZE events will be sent when the user adjusts the window dimensions. Hardware displays that draw direct to the screen will get pygame.VIDEOEXPOSE events when portions of the window must be redrawn.”

It’s also mentioned here where it says the the event has the following attributes: gain & state.

Answered By: martineau

Since pygame is a thin SQL wrapper, it usually helps to look at libsdl itself:

/** @name The available application states */
/*@{*/
#define SDL_APPMOUSEFOCUS   0x01        /**< The app has mouse coverage */
#define SDL_APPINPUTFOCUS   0x02        /**< The app has input focus */
#define SDL_APPACTIVE       0x04        /**< The application is active */
/*@}*/

/* Function prototypes */
/** 
 * This function returns the current state of the application, which is a
 * bitwise combination of SDL_APPMOUSEFOCUS, SDL_APPINPUTFOCUS, and
 * SDL_APPACTIVE.  If SDL_APPACTIVE is set, then the user is able to
 * see your application, otherwise it has been iconified or disabled.
 */
extern DECLSPEC Uint8 SDLCALL SDL_GetAppState(void);

Here’s a little pygame script to see those values in action:

import pygame

pygame.init()

screen = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()

APPMOUSEFOCUS = 1
APPINPUTFOCUS = 2
APPACTIVE     = 4

def main():
  while True:
    for e in pygame.event.get():
      if e.type == pygame.QUIT: 
          return
      if e.type == pygame.ACTIVEEVENT:
          if e.state & APPMOUSEFOCUS == APPMOUSEFOCUS:
              print ('mouse focus ' + ('gained' if e.gain else 'lost'))
          if e.state & APPINPUTFOCUS == APPINPUTFOCUS:
              print ('input focus ' + ('gained' if e.gain else 'lost'))
          if e.state & APPACTIVE == APPACTIVE:
              print('app is ' + ('visibile' if e.gain else 'iconified'))
    screen.fill((30, 30, 30))
    pygame.display.flip()
    clock.tick(60)

main()

enter image description here

Note that SDL 2 no longer uses these values, but rather events like

SDL_WINDOWEVENT_ENTER
SDL_WINDOWEVENT_LEAVE
SDL_WINDOWEVENT_FOCUS_GAINED
SDL_WINDOWEVENT_FOCUS_LOST
SDL_WINDOWEVENT_MINIMIZED
SDL_WINDOWEVENT_RESTORED

That may be revelant if you want to use pygame 2 in the future.

Answered By: sloth

There seems to be a bug in Pygame version 2.1.2. When the event first occurs, the gain and state attributes do not appear to be present. However, you can retrieve the attributes after the first occurrence. Use hasattr to check if the attribute is present:

minimal example:

import pygame

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
pause_text = font.render("pause", True, (255, 255, 0))

pause = False 
run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.ACTIVEEVENT:
            print(event.__dict__ )
            if hasattr(event, 'gain'):
                pause = event.gain == 0

    window.fill(0)
    if pause:
        window.blit(pause_text, pause_text.get_rect(center = window.get_rect().center))
    pygame.display.update()

pygame.quit()
exit()

output:

{}
{'gain': 1, 'state': 1}
{'gain': 1, 'state': 0}
{'gain': 0, 'state': 0}
{'gain': 1, 'state': 0}
{'gain': 0, 'state': 0}

Answered By: Rabbid76
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.