Custom Mouse Focus Regions

Can I customize which parts of my window respond to mouse focus? Like having some transparent areas that don't trigger focus events?

SDL2 doesn't directly support custom focus regions, but you can achieve this using a combination of window flags and shapes. The key is to use SDL_SetWindowShape() with a surface that defines which parts of your window are "active".

Here's how to create a window with a custom shape that only responds to mouse focus in specific areas:

#include <SDL.h>
#include <iostream>

// Helper function to create a shape mask
SDL_Surface* CreateShapeMask(
  int width, int height) {
  SDL_Surface* Mask = SDL_CreateRGBSurface(
    0, width, height, 32, 0xFF000000,
    0x00FF0000, 0x0000FF00, 0x000000FF);

  // Make the surface fully transparent
  SDL_FillRect(Mask, nullptr, 0x00000000);

  // Create a rectangular active region in the center
  SDL_Rect ActiveRegion = {
    width / 4, height / 4, width / 2,
    height / 2};
  SDL_FillRect(Mask, &ActiveRegion, 0xFFFFFFFF);

  return Mask;
}

int main(int argc, char** argv) {
  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    std::cerr << "Failed to initialize SDL: "
      << SDL_GetError() << "\n";
    return -1;
  }

  SDL_Window* Window = SDL_CreateShapedWindow(
    "Shaped Window", 100, 100, 400,
    300, SDL_WINDOW_SHOWN);

  if (!Window) {
    std::cerr
      << "Failed to create shaped window: "
      << SDL_GetError() << "\n";
    SDL_Quit();
    return -1;
  }

  // Create and apply the shape mask
  SDL_Surface* ShapeMask = CreateShapeMask(
    400, 300);

  // Define the shape mode
  SDL_WindowShapeMode ShapeMode;
  ShapeMode.mode = ShapeModeBinarizeAlpha;
  ShapeMode.parameters.binarizationCutoff = 128;

  if (SDL_SetWindowShape(Window, ShapeMask,
                         &ShapeMode) != 0) {
    std::cerr << "Failed to set window shape: "
      << SDL_GetError() << "\n";
    SDL_FreeSurface(ShapeMask);
    SDL_DestroyWindow(Window);
    SDL_Quit();
    return -1;
  }

  SDL_Event E;
  bool Running = true;

  while (Running) {
    while (SDL_PollEvent(&E)) {
      if (E.type == SDL_QUIT) {
        Running = false;
      } else if (
        E.type == SDL_WINDOWEVENT) {
        if (E.window.event ==
          SDL_WINDOWEVENT_ENTER) {
          std::cout <<
            "Mouse entered active region\n";
        } else if (E.window.event ==
          SDL_WINDOWEVENT_LEAVE) {
          std::cout <<
            "Mouse left active region\n";
        }
      }
    }

    SDL_Window* FocusedWindow =
      SDL_GetMouseFocus();
    if (FocusedWindow == Window) {
      // Mouse is over an active part of window
    }
  }

  SDL_FreeSurface(ShapeMask);
  SDL_DestroyWindow(Window);
  SDL_Quit();
  return 0;
}
Mouse entered active region
Mouse left active region
Mouse entered active region

Note that shaped windows have some limitations:

  • Not all platforms support window shaping
  • Performance might be impacted with complex shapes
  • Some window managers might ignore the shape
  • The shape affects both mouse input and window appearance

For more complex scenarios, you might want to handle the focus detection yourself by checking the mouse position against your custom regions:

#include <SDL.h>
#include <iostream>
#include <vector>
#include "Window.h"

struct FocusRegion {
  SDL_Rect Bounds;
  std::string Name;
};

bool IsPointInRect(
  int x, int y, const SDL_Rect& rect
) {
  return x >= rect.x &&
    x < rect.x + rect.w &&
    y >= rect.y &&
    y < rect.y + rect.h;
}

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  Window GameWindow;

  std::vector<FocusRegion> ActiveRegions{
    {{10, 10, 100, 100}, "Top Left"},
    {{200, 10, 100, 100}, "Top Right"},
    {{100, 100, 200, 100}, "Center"}};

  SDL_Event E;
  while (true) {
    while (SDL_PollEvent(&E)) {
      if (E.type == SDL_MOUSEMOTION) {
        int MouseX, MouseY;
        SDL_GetMouseState(&MouseX, &MouseY);

        for (const auto& Region :
             ActiveRegions) {
          if (IsPointInRect(MouseX, MouseY,
                            Region.Bounds)) {
            std::cout << "Mouse in region: " <<
              Region.Name << "\n";
          }
        }
      }
    }
    GameWindow.Update();
  }

  SDL_Quit();
  return 0;
}
Mouse in region: Center
Mouse in region: Center
Mouse in region: Top Right
Mouse in region: Top Left

This manual approach gives you more control but requires you to manage the focus state yourself rather than relying on SDL's built-in focus events.

Managing Mouse Focus with SDL2

Learn how to track and respond to mouse focus events in SDL2, including handling multiple windows and customizing focus-related click behavior.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Auto-Focus Windows on Mouse Hover
Can I make my game window automatically gain input focus when the mouse hovers over it?
Mouse Focus with Overlapping Windows
When using SDL_GetMouseFocus(), what happens if the mouse is over where two windows overlap?
Mouse Focus in Fullscreen Mode
How do I handle mouse focus in fullscreen mode? Does it work differently?
Picture-in-Picture Windows
How would I implement a picture-in-picture feature where a smaller window always stays on top of the main window?
Disabling Mouse Focus Events
How can I make certain windows in my game ignore mouse focus completely?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant