Mouse Capture and Global Mouse State

Out-of-Window Selection Rectangle

How can I implement a selection rectangle that works even if the user drags outside the window?

Abstract art representing computer programming

Implementing a selection rectangle that works outside the window requires combining mouse capture with proper state tracking. Here's a complete implementation that handles this scenario:

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

class SelectionRectangle {
public:
  SelectionRectangle() : isSelecting{false} {}

  void HandleMouseDown(
    const SDL_MouseButtonEvent& event) {
    if (event.button == SDL_BUTTON_LEFT) {
      startX = event.x;
      startY = event.y;
      currentX = event.x;
      currentY = event.y;
      isSelecting = true;

      // Enable mouse capture for out-of-window
      // tracking
      SDL_CaptureMouse(SDL_TRUE); 
    }
  }

  void HandleMouseUp(
    const SDL_MouseButtonEvent& event) {
    if (event.button == SDL_BUTTON_LEFT) {
      isSelecting = false;
      SDL_CaptureMouse(SDL_FALSE);

      // Calculate final selection area
      int width = std::abs(currentX - startX);
      int height = std::abs(currentY - startY);
      std::cout << "Final selection: " << width
        << "x" << height << " pixels\n";
    }
  }

  void HandleMouseMotion(
    const SDL_MouseMotionEvent& event) {
    if (isSelecting) {
      currentX = event.x;
      currentY = event.y;
    }
  }

  void Render(SDL_Renderer* renderer) {
    if (isSelecting) {
      // Calculate rectangle dimensions
      int x = std::min(startX, currentX);
      int y = std::min(startY, currentY);
      int w = std::abs(currentX - startX);
      int h = std::abs(currentY - startY);

      // Draw selection rectangle
      SDL_SetRenderDrawColor(
        renderer, 0, 120, 255, 255);
      SDL_Rect selectionRect{x, y, w, h};
      SDL_RenderDrawRect(renderer,
                         &selectionRect);

      // Draw semi-transparent fill
      SDL_SetRenderDrawColor(
        renderer, 0, 120, 255, 64);
      SDL_SetRenderDrawBlendMode(
        renderer, SDL_BLENDMODE_BLEND);
      SDL_RenderFillRect(renderer,
                         &selectionRect);
    }
  }

  bool IsSelecting() const {
    return isSelecting;
  }

private:
  bool isSelecting;
  int startX, startY;
  int currentX, currentY;
};

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window =
    SDL_CreateWindow("Selection Rectangle",
                     SDL_WINDOWPOS_CENTERED,
                     SDL_WINDOWPOS_CENTERED,
                     800, 600,
                     SDL_WINDOW_SHOWN);
  SDL_Renderer* renderer =
    SDL_CreateRenderer(window, -1,
                       SDL_RENDERER_ACCELERATED);

  SelectionRectangle selection;
  bool running = true;

  while (running) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      if (event.type ==
        SDL_QUIT) { running = false; } else if (
        event.type == SDL_MOUSEBUTTONDOWN) {
        selection.HandleMouseDown(event.button);
      } else if (event.type ==
        SDL_MOUSEBUTTONUP) {
        selection.HandleMouseUp(event.button);
      } else if (event.type ==
        SDL_MOUSEMOTION) {
        selection.HandleMouseMotion(
          event.motion);
      }
    }

    // Clear and render
    SDL_SetRenderDrawColor(renderer, 255, 255,
                           255, 255);
    SDL_RenderClear(renderer);
    selection.Render(renderer);
    SDL_RenderPresent(renderer);
  }

  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

Key features of this implementation:

Mouse Capture Management

  • Enables capture when selection starts
  • Disables capture when selection ends
  • Handles out-of-window mouse movement

Selection State Tracking

  • Stores both start and current positions
  • Updates continuously during mouse movement
  • Calculates correct dimensions regardless of drag direction

Visual Feedback

  • Renders selection rectangle with outline
  • Includes semi-transparent fill
  • Updates in real-time as selection changes

Error Handling

  • Safely manages mouse capture state
  • Handles window focus changes properly
  • Cleans up resources appropriately
This Question is from the Lesson:

Mouse Capture and Global Mouse State

Learn how to track mouse movements and button states across your entire application, even when the mouse leaves your window.

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

This Question is from the Lesson:

Mouse Capture and Global Mouse State

Learn how to track mouse movements and button states across your entire application, even when the mouse leaves your window.

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:

  • 75 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 © 2025 - All Rights Reserved