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?

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.

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?
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?
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