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;
}
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:
Remember that window management behavior can vary between operating systems, so test your PiP implementation thoroughly on all target platforms.
Answers to questions are automatically generated and may not have been reviewed.
Learn how to track and respond to mouse focus events in SDL2, including handling multiple windows and customizing focus-related click behavior.