Managing Mouse Focus with SDL2

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?

Abstract art representing computer programming

Creating a picture-in-picture (PiP) effect requires careful window management to ensure the child window stays above its parent and moves with it. Here's how to implement this:

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

class PictureInPicture {
public:
  PictureInPicture() {
    MainWindow.SDLWindow =
      SDL_CreateWindow("Main Window", 100, 100,
                       800, 600, 0);

    PiPWindow.SDLWindow = SDL_CreateWindow(
      "Picture in Picture",
      // Initially positioned to the right
      800, 100,
      200, 150, // Smaller size
      SDL_WINDOW_ALWAYS_ON_TOP 
    );

    // Store initial relative position
    SDL_GetWindowPosition(MainWindow.SDLWindow,
                          &MainX, &MainY);

    SDL_GetWindowPosition(PiPWindow.SDLWindow,
                          &PiPX, &PiPY);

    RelativeX = PiPX - MainX;
    RelativeY = PiPY - MainY;
  }

  void UpdatePiPPosition() {
    int CurrentX, CurrentY;
    SDL_GetWindowPosition(MainWindow.SDLWindow,
                          &CurrentX, &CurrentY);

    // Move PiP window to maintain relative position
    SDL_SetWindowPosition(PiPWindow.SDLWindow,
                          CurrentX + RelativeX,
                          CurrentY + RelativeY);
  }

  void HandleEvent(SDL_Event& E) {
    if (E.type == SDL_WINDOWEVENT) {
      if (E.window.windowID ==
        SDL_GetWindowID(MainWindow.SDLWindow)) {
        if (E.window.event ==
          SDL_WINDOWEVENT_MOVED) {
          UpdatePiPPosition();
        }
      }
    }
  }

  void Update() {
    MainWindow.Update();
    PiPWindow.Update();
  }

private:
  Window MainWindow;
  Window PiPWindow;
  int MainX, MainY;
  int PiPX, PiPY;
  int RelativeX, RelativeY;
};

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  PictureInPicture Windows;
  SDL_Event E;

  while (true) {
    while (SDL_PollEvent(&E)) {
      Windows.HandleEvent(E);
    }
    Windows.Update();
  }

  SDL_Quit();
  return 0;
}

Making the PiP Window Draggable

You can add dragging functionality to let users reposition the PiP window:

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

class PictureInPicture {
public:
  PictureInPicture();
  void UpdatePiPPosition();
  void HandleEvent(SDL_Event& E);
  void Update();

private:
  Window MainWindow;
  Window PiPWindow;
  int MainX, MainY;
  int PiPX, PiPY;
  int RelativeX, RelativeY;
  bool IsDragging{false};
  int DragOffsetX, DragOffsetY;

  void HandleMouseEvent(SDL_Event& E) {
    if (E.type == SDL_MOUSEBUTTONDOWN) {
      if (E.button.button == SDL_BUTTON_LEFT &&
        SDL_GetMouseFocus() == PiPWindow.SDLWindow
      ) {
        IsDragging = true;

        int MouseX, MouseY;
        SDL_GetMouseState(&MouseX, &MouseY);

        int WindowX, WindowY;
        SDL_GetWindowPosition(
          PiPWindow.SDLWindow, &WindowX,
          &WindowY);

        DragOffsetX = MouseX - WindowX;
        DragOffsetY = MouseY - WindowY;
      }
    } else if (E.type == SDL_MOUSEBUTTONUP) {
      if (E.button.button == SDL_BUTTON_LEFT) {
        IsDragging = false;

        // Update relative position after drag
        SDL_GetWindowPosition(
          MainWindow.SDLWindow, &MainX, &MainY);

        SDL_GetWindowPosition(
          PiPWindow.SDLWindow, &PiPX, &PiPY);

        RelativeX = PiPX - MainX;
        RelativeY = PiPY - MainY;
      }
    } else if (
      E.type == SDL_MOUSEMOTION &&
      IsDragging
    ) {
      int MouseX, MouseY;
      SDL_GetMouseState(&MouseX, &MouseY);

      SDL_SetWindowPosition(
        PiPWindow.SDLWindow,
        MouseX - DragOffsetX,
        MouseY - DragOffsetY
      );
    }
  }
};

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  PictureInPicture Windows;
  SDL_Event E;

  while (true) {
    while (SDL_PollEvent(&E)) {
      Windows.HandleEvent(E);
    }
    Windows.Update();
  }

  SDL_Quit();
  return 0;
}

Some tips for picture-in-picture implementation:

  • Consider adding a minimum distance the PiP window must stay from the main window edges
  • You might want to add snapping behavior to align with the main window edges
  • Add a way to toggle the PiP window visibility
  • Consider saving/loading the last PiP window position between program runs
  • You may want to add resize handles for the PiP window

Remember that window management behavior can vary between operating systems, so test your PiP implementation thoroughly on all target platforms.

This Question is from the Lesson:

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.

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

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.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 62 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved