1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use static_assertions::assert_not_impl_all;
use std::ffi::CStr;
use std::marker::PhantomData;

use crate::{
    bind::{self, SDL_GL_SetAttribute},
    Result, Sdl, SdlError,
};

use self::display::Display;

pub mod clipboard;
pub mod color;
pub mod display;
pub mod gamma_ramp;
pub mod geo;
pub mod gl_context;
pub mod metal;
pub mod renderer;
pub mod screen_saver;
pub mod surface;
pub mod texture;
pub mod vulkan;
pub mod window;

/// A video controller by SDL2.
pub struct Video<'sdl> {
    _phantom: PhantomData<&'sdl Sdl>,
}

assert_not_impl_all!(Video: Send, Sync);

impl<'sdl> Video<'sdl> {
    /// Constructs a video controller from a root controller.
    #[must_use]
    pub fn new(_: &'sdl Sdl) -> Self {
        let ret = unsafe { bind::SDL_InitSubSystem(bind::SDL_INIT_VIDEO) };
        if ret != 0 {
            Sdl::error_then_panic("Sdl video")
        }
        Self {
            _phantom: PhantomData,
        }
    }

    /// Returns a list of displays.
    #[must_use]
    pub fn displays(&self) -> Vec<Display> {
        let ret = unsafe { bind::SDL_GetNumVideoDisplays() };
        if ret <= 0 {
            return vec![];
        }
        (0..ret).map(|idx| Display::new(idx, self)).collect()
    }

    /// Returns the names of the video drivers.
    #[must_use]
    pub fn video_drivers(&self) -> Vec<&str> {
        let num_drivers = unsafe { bind::SDL_GetNumVideoDrivers() };
        if num_drivers <= 0 {
            Sdl::error_then_panic("Getting number of drivers");
        }
        (0..num_drivers)
            .map(|idx| {
                let raw_str = unsafe { bind::SDL_GetVideoDriver(idx) };
                unsafe { CStr::from_ptr(raw_str) }
                    .to_str()
                    .unwrap_or_default()
            })
            .collect()
    }

    /// Returns the name of the current video driver.
    #[must_use]
    pub fn current_driver(&self) -> &str {
        let raw_str = unsafe { bind::SDL_GetCurrentVideoDriver() };
        unsafe { CStr::from_ptr(raw_str) }
            .to_str()
            .unwrap_or_default()
    }

    /// Returns whether the screen keyboard is supported.
    #[must_use]
    pub fn has_screen_keyboard(&self) -> bool {
        unsafe { bind::SDL_HasScreenKeyboardSupport() != 0 }
    }

    /// Resets all OpenGL attributes.
    pub fn reset_gl_attribute(&self) {
        unsafe { bind::SDL_GL_ResetAttributes() }
    }
}

impl<'sdl> Drop for Video<'sdl> {
    fn drop(&mut self) {
        unsafe { bind::SDL_QuitSubSystem(bind::SDL_INIT_VIDEO) }
    }
}