1use libc::{c_char, c_float, c_int, c_uint};
2use std::convert::TryFrom;
3use std::error::Error;
4use std::ffi::{CStr, CString, NulError};
5use std::ops::{Deref, DerefMut};
6use std::rc::Rc;
7use std::{fmt, mem, ptr};
8
9use crate::common::{validate_int, IntegerOrSdlError};
10use crate::pixels::PixelFormatEnum;
11use crate::rect::Rect;
12use crate::render::CanvasBuilder;
13use crate::surface::SurfaceRef;
14use crate::EventPump;
15use crate::VideoSubsystem;
16
17use crate::get_error;
18
19use crate::sys;
20
21pub use crate::sys::{VkInstance, VkSurfaceKHR};
22
23pub struct WindowSurfaceRef<'a>(&'a mut SurfaceRef, &'a Window);
24
25impl<'a> Deref for WindowSurfaceRef<'a> {
26 type Target = SurfaceRef;
27
28 #[inline]
29 fn deref(&self) -> &SurfaceRef {
30 self.0
31 }
32}
33
34impl<'a> DerefMut for WindowSurfaceRef<'a> {
35 #[inline]
36 fn deref_mut(&mut self) -> &mut SurfaceRef {
37 self.0
38 }
39}
40
41impl<'a> WindowSurfaceRef<'a> {
42 #[doc(alias = "SDL_UpdateWindowSurface")]
46 pub fn update_window(&self) -> Result<(), String> {
47 unsafe {
48 if sys::SDL_UpdateWindowSurface(self.1.context.raw) == 0 {
49 Ok(())
50 } else {
51 Err(get_error())
52 }
53 }
54 }
55
56 #[doc(alias = "SDL_UpdateWindowSurfaceRects")]
59 pub fn update_window_rects(&self, rects: &[Rect]) -> Result<(), String> {
60 unsafe {
61 if sys::SDL_UpdateWindowSurfaceRects(
62 self.1.context.raw,
63 Rect::raw_slice(rects),
64 rects.len() as c_int,
65 ) == 0
66 {
67 Ok(())
68 } else {
69 Err(get_error())
70 }
71 }
72 }
73
74 pub fn finish(self) -> Result<(), String> {
81 self.update_window()
82 }
83}
84
85#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
86pub enum GLProfile {
87 Core,
89 Compatibility,
91 GLES,
93 Unknown(i32),
96}
97
98trait GLAttrTypeUtil {
99 fn to_gl_value(self) -> i32;
100 fn from_gl_value(value: i32) -> Self;
101}
102
103impl GLAttrTypeUtil for u8 {
104 fn to_gl_value(self) -> i32 {
105 self as i32
106 }
107 fn from_gl_value(value: i32) -> u8 {
108 value as u8
109 }
110}
111
112impl GLAttrTypeUtil for bool {
113 fn to_gl_value(self) -> i32 {
114 if self {
115 1
116 } else {
117 0
118 }
119 }
120 fn from_gl_value(value: i32) -> bool {
121 value != 0
122 }
123}
124
125impl GLAttrTypeUtil for GLProfile {
126 fn to_gl_value(self) -> i32 {
127 use self::GLProfile::*;
128
129 match self {
130 Unknown(i) => i,
131 Core => 1,
132 Compatibility => 2,
133 GLES => 4,
134 }
135 }
136 fn from_gl_value(value: i32) -> GLProfile {
137 use self::GLProfile::*;
138
139 match value {
140 1 => Core,
141 2 => Compatibility,
142 4 => GLES,
143 i => Unknown(i),
144 }
145 }
146}
147
148macro_rules! attrs {
149 (
150 $(($attr_name:ident, $set_property:ident, $get_property:ident, $t:ty, $doc:expr)),*
151 ) => (
152
153 $(
154 #[doc = "**Sets** the attribute: "]
155 #[doc = $doc]
156 #[inline]
157 pub fn $set_property(&self, value: $t) {
158 gl_set_attribute!($attr_name, value.to_gl_value());
159 }
160
161 #[doc = "**Gets** the attribute: "]
162 #[doc = $doc]
163 #[inline]
164 pub fn $get_property(&self) -> $t {
165 let value = gl_get_attribute!($attr_name);
166 GLAttrTypeUtil::from_gl_value(value)
167 }
168 )*
169 );
170}
171
172pub mod gl_attr {
203 use super::{GLAttrTypeUtil, GLProfile};
204 use crate::get_error;
205 use crate::sys;
206 use std::marker::PhantomData;
207
208 pub struct GLAttr<'a> {
210 _marker: PhantomData<&'a crate::VideoSubsystem>,
211 }
212
213 impl crate::VideoSubsystem {
214 pub fn gl_attr(&self) -> GLAttr {
216 GLAttr {
217 _marker: PhantomData,
218 }
219 }
220 }
221
222 macro_rules! gl_set_attribute {
223 ($attr:ident, $value:expr) => {{
224 let result = unsafe { sys::SDL_GL_SetAttribute(sys::SDL_GLattr::$attr, $value) };
225
226 if result != 0 {
227 panic!(
229 "couldn't set attribute {}: {}",
230 stringify!($attr),
231 get_error()
232 );
233 }
234 }};
235 }
236
237 macro_rules! gl_get_attribute {
238 ($attr:ident) => {{
239 let mut value = 0;
240 let result = unsafe { sys::SDL_GL_GetAttribute(sys::SDL_GLattr::$attr, &mut value) };
241 if result != 0 {
242 panic!(
244 "couldn't get attribute {}: {}",
245 stringify!($attr),
246 get_error()
247 );
248 }
249 value
250 }};
251 }
252
253 impl<'a> GLAttr<'a> {
254 attrs! {
257 (SDL_GL_RED_SIZE, set_red_size, red_size, u8,
258 "the minimum number of bits for the red channel of the color buffer; defaults to 3"),
259
260 (SDL_GL_GREEN_SIZE, set_green_size, green_size, u8,
261 "the minimum number of bits for the green channel of the color buffer; defaults to 3"),
262
263 (SDL_GL_BLUE_SIZE, set_blue_size, blue_size, u8,
264 "the minimum number of bits for the blue channel of the color buffer; defaults to 2"),
265
266 (SDL_GL_ALPHA_SIZE, set_alpha_size, alpha_size, u8,
267 "the minimum number of bits for the alpha channel of the color buffer; defaults to 0"),
268
269 (SDL_GL_BUFFER_SIZE, set_buffer_size, buffer_size, u8,
270 "the minimum number of bits for frame buffer size; defaults to 0"),
271
272 (SDL_GL_DOUBLEBUFFER, set_double_buffer, double_buffer, bool,
273 "whether the output is single or double buffered; defaults to double buffering on"),
274
275 (SDL_GL_DEPTH_SIZE, set_depth_size, depth_size, u8,
276 "the minimum number of bits in the depth buffer; defaults to 16"),
277
278 (SDL_GL_STENCIL_SIZE, set_stencil_size, stencil_size, u8,
279 "the minimum number of bits in the stencil buffer; defaults to 0"),
280
281 (SDL_GL_ACCUM_RED_SIZE, set_accum_red_size, accum_red_size, u8,
282 "the minimum number of bits for the red channel of the accumulation buffer; defaults to 0"),
283
284 (SDL_GL_ACCUM_GREEN_SIZE, set_accum_green_size, accum_green_size, u8,
285 "the minimum number of bits for the green channel of the accumulation buffer; defaults to 0"),
286
287 (SDL_GL_ACCUM_BLUE_SIZE, set_accum_blue_size, accum_blue_size, u8,
288 "the minimum number of bits for the blue channel of the accumulation buffer; defaults to 0"),
289
290 (SDL_GL_ACCUM_ALPHA_SIZE, set_accum_alpha_size, accum_alpha_size, u8,
291 "the minimum number of bits for the alpha channel of the accumulation buffer; defaults to 0"),
292
293 (SDL_GL_STEREO, set_stereo, stereo, bool,
294 "whether the output is stereo 3D; defaults to off"),
295
296 (SDL_GL_MULTISAMPLEBUFFERS, set_multisample_buffers, multisample_buffers, u8,
297 "the number of buffers used for multisample anti-aliasing; defaults to 0"),
298
299 (SDL_GL_MULTISAMPLESAMPLES, set_multisample_samples, multisample_samples, u8,
300 "the number of samples used around the current pixel used for multisample anti-aliasing; defaults to 0"),
301
302 (SDL_GL_ACCELERATED_VISUAL, set_accelerated_visual, accelerated_visual, bool,
303 "whether to require hardware acceleration; false to force software rendering; defaults to allow either"),
304
305 (SDL_GL_CONTEXT_MAJOR_VERSION, set_context_major_version, context_major_version, u8,
306 "OpenGL context major version"),
307
308 (SDL_GL_CONTEXT_MINOR_VERSION, set_context_minor_version, context_minor_version, u8,
309 "OpenGL context minor version"),
310
311 (SDL_GL_CONTEXT_PROFILE_MASK, set_context_profile, context_profile, GLProfile,
312 "type of GL context (Core, Compatibility, ES)"),
313
314 (SDL_GL_SHARE_WITH_CURRENT_CONTEXT, set_share_with_current_context, share_with_current_context, bool,
315 "OpenGL context sharing; defaults to false"),
316
317 (SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, set_framebuffer_srgb_compatible, framebuffer_srgb_compatible, bool,
318 "requests sRGB capable visual; defaults to false (>= SDL 2.0.1)"),
319
320 (SDL_GL_CONTEXT_NO_ERROR, set_context_no_error, context_no_error, bool,
321 "disables OpenGL error checking; defaults to false (>= SDL 2.0.6)")
322 }
323
324 #[inline]
326 pub fn set_context_version(&self, major: u8, minor: u8) {
327 self.set_context_major_version(major);
328 self.set_context_minor_version(minor);
329 }
330
331 #[inline]
333 pub fn context_version(&self) -> (u8, u8) {
334 (self.context_major_version(), self.context_minor_version())
335 }
336 }
337
338 pub struct ContextFlagsBuilder<'a> {
340 flags: i32,
341 _marker: PhantomData<&'a crate::VideoSubsystem>,
342 }
343
344 impl<'a> ContextFlagsBuilder<'a> {
345 #[inline]
347 pub fn set(&self) {
348 gl_set_attribute!(SDL_GL_CONTEXT_FLAGS, self.flags);
349 }
350
351 #[inline]
353 pub fn debug(&mut self) -> &mut ContextFlagsBuilder<'a> {
354 self.flags |= 0x0001;
355 self
356 }
357
358 #[inline]
360 pub fn forward_compatible(&mut self) -> &mut ContextFlagsBuilder<'a> {
361 self.flags |= 0x0002;
362 self
363 }
364
365 #[inline]
366 pub fn robust_access(&mut self) -> &mut ContextFlagsBuilder<'a> {
367 self.flags |= 0x0004;
368 self
369 }
370
371 #[inline]
372 pub fn reset_isolation(&mut self) -> &mut ContextFlagsBuilder<'a> {
373 self.flags |= 0x0008;
374 self
375 }
376 }
377
378 pub struct ContextFlags {
379 flags: i32,
380 }
381
382 impl ContextFlags {
383 #[inline]
384 pub const fn has_debug(&self) -> bool {
385 self.flags & 0x0001 != 0
386 }
387
388 #[inline]
389 pub const fn has_forward_compatible(&self) -> bool {
390 self.flags & 0x0002 != 0
391 }
392
393 #[inline]
394 pub const fn has_robust_access(&self) -> bool {
395 self.flags & 0x0004 != 0
396 }
397
398 #[inline]
399 pub const fn has_reset_isolation(&self) -> bool {
400 self.flags & 0x0008 != 0
401 }
402 }
403
404 impl<'a> GLAttr<'a> {
405 pub fn set_context_flags(&self) -> ContextFlagsBuilder {
419 ContextFlagsBuilder {
420 flags: 0,
421 _marker: PhantomData,
422 }
423 }
424
425 pub fn context_flags(&self) -> ContextFlags {
439 let flags = gl_get_attribute!(SDL_GL_CONTEXT_FLAGS);
440
441 ContextFlags { flags }
442 }
443 }
444}
445
446#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
447pub struct DisplayMode {
448 pub format: PixelFormatEnum,
449 pub w: i32,
450 pub h: i32,
451 pub refresh_rate: i32,
452}
453
454impl DisplayMode {
455 pub fn new(format: PixelFormatEnum, w: i32, h: i32, refresh_rate: i32) -> DisplayMode {
456 DisplayMode {
457 format,
458 w,
459 h,
460 refresh_rate,
461 }
462 }
463
464 pub fn from_ll(raw: &sys::SDL_DisplayMode) -> DisplayMode {
465 DisplayMode::new(
466 PixelFormatEnum::try_from(raw.format).unwrap_or(PixelFormatEnum::Unknown),
467 raw.w,
468 raw.h,
469 raw.refresh_rate,
470 )
471 }
472
473 pub fn to_ll(&self) -> sys::SDL_DisplayMode {
474 sys::SDL_DisplayMode {
475 format: self.format as u32,
476 w: self.w as c_int,
477 h: self.h as c_int,
478 refresh_rate: self.refresh_rate as c_int,
479 driverdata: ptr::null_mut(),
480 }
481 }
482}
483
484#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
485pub enum FullscreenType {
486 Off = 0,
487 True = 0x00_00_00_01,
488 Desktop = 0x00_00_10_01,
489}
490
491impl FullscreenType {
492 pub fn from_window_flags(window_flags: u32) -> FullscreenType {
493 if window_flags & FullscreenType::Desktop as u32 == FullscreenType::Desktop as u32 {
494 FullscreenType::Desktop
495 } else if window_flags & FullscreenType::True as u32 == FullscreenType::True as u32 {
496 FullscreenType::True
497 } else {
498 FullscreenType::Off
499 }
500 }
501}
502
503#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
504pub enum WindowPos {
505 Undefined,
506 Centered,
507 Positioned(i32),
508}
509
510impl From<i32> for WindowPos {
511 fn from(pos: i32) -> Self {
512 WindowPos::Positioned(pos)
513 }
514}
515
516fn to_ll_windowpos(pos: WindowPos) -> c_int {
517 match pos {
518 WindowPos::Undefined => sys::SDL_WINDOWPOS_UNDEFINED_MASK as c_int,
519 WindowPos::Centered => sys::SDL_WINDOWPOS_CENTERED_MASK as c_int,
520 WindowPos::Positioned(x) => x as c_int,
521 }
522}
523
524pub struct GLContext {
525 raw: sys::SDL_GLContext,
526}
527
528impl Drop for GLContext {
529 #[doc(alias = "SDL_GL_DeleteContext")]
530 fn drop(&mut self) {
531 unsafe { sys::SDL_GL_DeleteContext(self.raw) }
532 }
533}
534
535impl GLContext {
536 #[doc(alias = "SDL_GL_GetCurrentContext")]
538 pub fn is_current(&self) -> bool {
539 let current_raw = unsafe { sys::SDL_GL_GetCurrentContext() };
540 self.raw == current_raw
541 }
542}
543
544pub struct WindowContext {
548 subsystem: VideoSubsystem,
549 raw: *mut sys::SDL_Window,
550 pub(crate) metal_view: sys::SDL_MetalView,
551}
552
553impl Drop for WindowContext {
554 #[inline]
555 #[doc(alias = "SDL_DestroyWindow")]
556 fn drop(&mut self) {
557 unsafe {
558 if !self.metal_view.is_null() {
559 sys::SDL_Metal_DestroyView(self.metal_view);
560 }
561 sys::SDL_DestroyWindow(self.raw)
562 };
563 }
564}
565
566impl WindowContext {
567 #[inline]
568 pub unsafe fn from_ll(
572 subsystem: VideoSubsystem,
573 raw: *mut sys::SDL_Window,
574 metal_view: sys::SDL_MetalView,
575 ) -> WindowContext {
576 WindowContext {
577 subsystem: subsystem.clone(),
578 raw,
579 metal_view,
580 }
581 }
582}
583
584#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
586#[repr(i32)]
587pub enum SwapInterval {
588 Immediate = 0,
589 VSync = 1,
590 LateSwapTearing = -1,
591}
592
593impl From<i32> for SwapInterval {
594 fn from(i: i32) -> Self {
595 match i {
596 -1 => SwapInterval::LateSwapTearing,
597 0 => SwapInterval::Immediate,
598 1 => SwapInterval::VSync,
599 other => panic!(
600 "Invalid value for SwapInterval: {}; valid values are -1, 0, 1",
601 other
602 ),
603 }
604 }
605}
606
607#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
609#[repr(i32)]
610pub enum Orientation {
611 Unknown = sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN as i32,
613 Landscape = sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE as i32,
615 LandscapeFlipped = sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED as i32,
617 Portrait = sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT as i32,
619 PortraitFlipped = sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED as i32,
621}
622
623impl Orientation {
624 pub fn from_ll(orientation: sys::SDL_DisplayOrientation) -> Orientation {
625 match orientation {
626 sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN => Orientation::Unknown,
627 sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE => Orientation::Landscape,
628 sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED => {
629 Orientation::LandscapeFlipped
630 }
631 sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT => Orientation::Portrait,
632 sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED => {
633 Orientation::PortraitFlipped
634 }
635 }
636 }
637
638 pub fn to_ll(self) -> sys::SDL_DisplayOrientation {
639 match self {
640 Orientation::Unknown => sys::SDL_DisplayOrientation::SDL_ORIENTATION_UNKNOWN,
641 Orientation::Landscape => sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE,
642 Orientation::LandscapeFlipped => {
643 sys::SDL_DisplayOrientation::SDL_ORIENTATION_LANDSCAPE_FLIPPED
644 }
645 Orientation::Portrait => sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT,
646 Orientation::PortraitFlipped => {
647 sys::SDL_DisplayOrientation::SDL_ORIENTATION_PORTRAIT_FLIPPED
648 }
649 }
650 }
651}
652
653#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
655#[repr(i32)]
656pub enum FlashOperation {
657 Cancel = sys::SDL_FlashOperation::SDL_FLASH_CANCEL as i32,
659 Briefly = sys::SDL_FlashOperation::SDL_FLASH_BRIEFLY as i32,
661 UntilFocused = sys::SDL_FlashOperation::SDL_FLASH_UNTIL_FOCUSED as i32,
663}
664
665impl FlashOperation {
666 pub fn from_ll(flash_operation: sys::SDL_FlashOperation) -> FlashOperation {
667 match flash_operation {
668 sys::SDL_FlashOperation::SDL_FLASH_CANCEL => FlashOperation::Cancel,
669 sys::SDL_FlashOperation::SDL_FLASH_BRIEFLY => FlashOperation::Briefly,
670 sys::SDL_FlashOperation::SDL_FLASH_UNTIL_FOCUSED => FlashOperation::UntilFocused,
671 }
672 }
673
674 pub fn to_ll(self) -> sys::SDL_FlashOperation {
675 match self {
676 FlashOperation::Cancel => sys::SDL_FlashOperation::SDL_FLASH_CANCEL,
677 FlashOperation::Briefly => sys::SDL_FlashOperation::SDL_FLASH_BRIEFLY,
678 FlashOperation::UntilFocused => sys::SDL_FlashOperation::SDL_FLASH_UNTIL_FOCUSED,
679 }
680 }
681}
682
683#[derive(Clone)]
694pub struct Window {
695 context: Rc<WindowContext>,
696}
697
698impl From<WindowContext> for Window {
699 fn from(context: WindowContext) -> Window {
700 Window {
701 context: Rc::new(context),
702 }
703 }
704}
705
706impl_raw_accessors!((GLContext, sys::SDL_GLContext));
707
708impl VideoSubsystem {
709 pub fn window(&self, title: &str, width: u32, height: u32) -> WindowBuilder {
711 WindowBuilder::new(self, title, width, height)
712 }
713
714 #[doc(alias = "SDL_GetCurrentVideoDriver")]
715 pub fn current_video_driver(&self) -> &'static str {
716 use std::str;
717
718 unsafe {
719 let buf = sys::SDL_GetCurrentVideoDriver();
720 assert!(!buf.is_null());
721
722 str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap()
723 }
724 }
725
726 #[doc(alias = "SDL_GetNumVideoDisplays")]
727 pub fn num_video_displays(&self) -> Result<i32, String> {
728 let result = unsafe { sys::SDL_GetNumVideoDisplays() };
729 if result < 0 {
730 Err(get_error())
731 } else {
732 Ok(result as i32)
733 }
734 }
735
736 #[doc(alias = "SDL_GetDisplayName")]
741 pub fn display_name(&self, display_index: i32) -> Result<String, String> {
742 unsafe {
743 let display = sys::SDL_GetDisplayName(display_index as c_int);
744 if display.is_null() {
745 Err(get_error())
746 } else {
747 Ok(CStr::from_ptr(display as *const _)
748 .to_str()
749 .unwrap()
750 .to_owned())
751 }
752 }
753 }
754
755 #[doc(alias = "SDL_GetDisplayBounds")]
756 pub fn display_bounds(&self, display_index: i32) -> Result<Rect, String> {
757 let mut out = mem::MaybeUninit::uninit();
758 let result =
759 unsafe { sys::SDL_GetDisplayBounds(display_index as c_int, out.as_mut_ptr()) == 0 };
760
761 if result {
762 let out = unsafe { out.assume_init() };
763 Ok(Rect::from_ll(out))
764 } else {
765 Err(get_error())
766 }
767 }
768
769 #[doc(alias = "SDL_GetDisplayUsableBounds")]
770 pub fn display_usable_bounds(&self, display_index: i32) -> Result<Rect, String> {
771 let mut out = mem::MaybeUninit::uninit();
772 let result =
773 unsafe { sys::SDL_GetDisplayUsableBounds(display_index as c_int, out.as_mut_ptr()) };
774 if result == 0 {
775 let out = unsafe { out.assume_init() };
776 Ok(Rect::from_ll(out))
777 } else {
778 Err(get_error())
779 }
780 }
781
782 #[doc(alias = "SDL_GetNumDisplayModes")]
783 pub fn num_display_modes(&self, display_index: i32) -> Result<i32, String> {
784 let result = unsafe { sys::SDL_GetNumDisplayModes(display_index as c_int) };
785 if result < 0 {
786 Err(get_error())
787 } else {
788 Ok(result as i32)
789 }
790 }
791
792 #[doc(alias = "SDL_GetDisplayMode")]
793 pub fn display_mode(&self, display_index: i32, mode_index: i32) -> Result<DisplayMode, String> {
794 let mut dm = mem::MaybeUninit::uninit();
795 let result = unsafe {
796 sys::SDL_GetDisplayMode(display_index as c_int, mode_index as c_int, dm.as_mut_ptr())
797 == 0
798 };
799
800 if result {
801 let dm = unsafe { dm.assume_init() };
802 Ok(DisplayMode::from_ll(&dm))
803 } else {
804 Err(get_error())
805 }
806 }
807
808 #[doc(alias = "SDL_GetDesktopDisplayMode")]
809 pub fn desktop_display_mode(&self, display_index: i32) -> Result<DisplayMode, String> {
810 let mut dm = mem::MaybeUninit::uninit();
811 let result =
812 unsafe { sys::SDL_GetDesktopDisplayMode(display_index as c_int, dm.as_mut_ptr()) == 0 };
813
814 if result {
815 let dm = unsafe { dm.assume_init() };
816 Ok(DisplayMode::from_ll(&dm))
817 } else {
818 Err(get_error())
819 }
820 }
821
822 #[doc(alias = "SDL_GetCurrentDisplayMode")]
823 pub fn current_display_mode(&self, display_index: i32) -> Result<DisplayMode, String> {
824 let mut dm = mem::MaybeUninit::uninit();
825 let result =
826 unsafe { sys::SDL_GetCurrentDisplayMode(display_index as c_int, dm.as_mut_ptr()) == 0 };
827
828 if result {
829 let dm = unsafe { dm.assume_init() };
830 Ok(DisplayMode::from_ll(&dm))
831 } else {
832 Err(get_error())
833 }
834 }
835
836 #[doc(alias = "SDL_GetClosestDisplayMode")]
837 pub fn closest_display_mode(
838 &self,
839 display_index: i32,
840 mode: &DisplayMode,
841 ) -> Result<DisplayMode, String> {
842 let input = mode.to_ll();
843 let mut dm = mem::MaybeUninit::uninit();
844
845 let result = unsafe {
846 sys::SDL_GetClosestDisplayMode(display_index as c_int, &input, dm.as_mut_ptr())
847 };
848
849 if result.is_null() {
850 Err(get_error())
851 } else {
852 let dm = unsafe { dm.assume_init() };
853 Ok(DisplayMode::from_ll(&dm))
854 }
855 }
856
857 #[doc(alias = "SDL_GetDisplayDPI")]
860 pub fn display_dpi(&self, display_index: i32) -> Result<(f32, f32, f32), String> {
861 let mut ddpi = 0.0;
862 let mut hdpi = 0.0;
863 let mut vdpi = 0.0;
864 let result = unsafe {
865 sys::SDL_GetDisplayDPI(display_index as c_int, &mut ddpi, &mut hdpi, &mut vdpi)
866 };
867 if result < 0 {
868 Err(get_error())
869 } else {
870 Ok((ddpi, hdpi, vdpi))
871 }
872 }
873
874 #[doc(alias = "SDL_GetDisplayOrientation")]
876 pub fn display_orientation(&self, display_index: i32) -> Orientation {
877 Orientation::from_ll(unsafe { sys::SDL_GetDisplayOrientation(display_index as c_int) })
878 }
879
880 #[doc(alias = "SDL_IsScreenSaverEnabled")]
881 pub fn is_screen_saver_enabled(&self) -> bool {
882 unsafe { sys::SDL_IsScreenSaverEnabled() == sys::SDL_bool::SDL_TRUE }
883 }
884
885 #[doc(alias = "SDL_EnableScreenSaver")]
886 pub fn enable_screen_saver(&self) {
887 unsafe { sys::SDL_EnableScreenSaver() }
888 }
889
890 #[doc(alias = "SDL_DisableScreenSaver")]
891 pub fn disable_screen_saver(&self) {
892 unsafe { sys::SDL_DisableScreenSaver() }
893 }
894
895 #[doc(alias = "SDL_GL_LoadLibrary")]
902 pub fn gl_load_library_default(&self) -> Result<(), String> {
903 unsafe {
904 if sys::SDL_GL_LoadLibrary(ptr::null()) == 0 {
905 Ok(())
906 } else {
907 Err(get_error())
908 }
909 }
910 }
911
912 #[doc(alias = "SDL_GL_LoadLibrary")]
919 pub fn gl_load_library<P: AsRef<::std::path::Path>>(&self, path: P) -> Result<(), String> {
920 unsafe {
921 let path = CString::new(path.as_ref().to_str().unwrap()).unwrap();
923 if sys::SDL_GL_LoadLibrary(path.as_ptr() as *const c_char) == 0 {
924 Ok(())
925 } else {
926 Err(get_error())
927 }
928 }
929 }
930
931 #[doc(alias = "SDL_GL_UnloadLibrary")]
936 pub fn gl_unload_library(&self) {
937 unsafe {
938 sys::SDL_GL_UnloadLibrary();
939 }
940 }
941
942 #[doc(alias = "SDL_GL_GetProcAddress")]
946 pub fn gl_get_proc_address(&self, procname: &str) -> *const () {
947 match CString::new(procname) {
948 Ok(procname) => unsafe {
949 sys::SDL_GL_GetProcAddress(procname.as_ptr() as *const c_char) as *const ()
950 },
951 Err(_) => ptr::null(),
953 }
954 }
955
956 #[doc(alias = "SDL_GL_ExtensionSupported")]
957 pub fn gl_extension_supported(&self, extension: &str) -> bool {
958 match CString::new(extension) {
959 Ok(extension) => unsafe {
960 sys::SDL_GL_ExtensionSupported(extension.as_ptr() as *const c_char)
961 != sys::SDL_bool::SDL_FALSE
962 },
963 Err(_) => false,
965 }
966 }
967
968 #[doc(alias = "SDL_GL_GetCurrentWindow")]
969 pub fn gl_get_current_window_id(&self) -> Result<u32, String> {
970 let raw = unsafe { sys::SDL_GL_GetCurrentWindow() };
971 if raw.is_null() {
972 Err(get_error())
973 } else {
974 let id = unsafe { sys::SDL_GetWindowID(raw) };
975 Ok(id)
976 }
977 }
978
979 #[doc(alias = "SDL_GL_MakeCurrent")]
981 pub fn gl_release_current_context(&self) -> Result<(), String> {
982 let result = unsafe { sys::SDL_GL_MakeCurrent(ptr::null_mut(), ptr::null_mut()) };
983
984 if result == 0 {
985 Ok(())
986 } else {
987 Err(get_error())
988 }
989 }
990
991 #[doc(alias = "SDL_GL_SetSwapInterval")]
992 pub fn gl_set_swap_interval<S: Into<SwapInterval>>(&self, interval: S) -> Result<(), String> {
993 let result = unsafe { sys::SDL_GL_SetSwapInterval(interval.into() as c_int) };
994 if result == 0 {
995 Ok(())
996 } else {
997 Err(get_error())
998 }
999 }
1000
1001 #[doc(alias = "SDL_GL_GetSwapInterval")]
1002 pub fn gl_get_swap_interval(&self) -> SwapInterval {
1003 unsafe {
1004 let interval = sys::SDL_GL_GetSwapInterval() as i32;
1005 assert!(interval == -1 || interval == 0 || interval == 1);
1006 mem::transmute(interval)
1007 }
1008 }
1009
1010 #[doc(alias = "SDL_Vulkan_LoadLibrary")]
1017 pub fn vulkan_load_library_default(&self) -> Result<(), String> {
1018 unsafe {
1019 if sys::SDL_Vulkan_LoadLibrary(ptr::null()) == 0 {
1020 Ok(())
1021 } else {
1022 Err(get_error())
1023 }
1024 }
1025 }
1026
1027 #[doc(alias = "SDL_Vulkan_LoadLibrary")]
1034 pub fn vulkan_load_library<P: AsRef<::std::path::Path>>(&self, path: P) -> Result<(), String> {
1035 unsafe {
1036 let path = CString::new(path.as_ref().to_str().unwrap()).unwrap();
1038 if sys::SDL_Vulkan_LoadLibrary(path.as_ptr() as *const c_char) == 0 {
1039 Ok(())
1040 } else {
1041 Err(get_error())
1042 }
1043 }
1044 }
1045
1046 #[doc(alias = "SDL_Vulkan_UnloadLibrary")]
1051 pub fn vulkan_unload_library(&self) {
1052 unsafe {
1053 sys::SDL_Vulkan_UnloadLibrary();
1054 }
1055 }
1056
1057 #[doc(alias = "SDL_Vulkan_GetVkGetInstanceProcAddr")]
1062 pub fn vulkan_get_proc_address_function(&self) -> Result<*const (), String> {
1063 let result = unsafe { sys::SDL_Vulkan_GetVkGetInstanceProcAddr() as *const () };
1064 if result.is_null() {
1065 Err(get_error())
1066 } else {
1067 Ok(result)
1068 }
1069 }
1070}
1071
1072#[derive(Debug, Clone)]
1073pub enum WindowBuildError {
1074 HeightOverflows(u32),
1075 WidthOverflows(u32),
1076 InvalidTitle(NulError),
1077 SdlError(String),
1078}
1079
1080impl fmt::Display for WindowBuildError {
1081 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1082 use self::WindowBuildError::*;
1083
1084 match *self {
1085 HeightOverflows(h) => write!(f, "Window height ({}) is too high.", h),
1086 WidthOverflows(w) => write!(f, "Window width ({}) is too high.", w),
1087 InvalidTitle(ref e) => write!(f, "Invalid window title: {}", e),
1088 SdlError(ref e) => write!(f, "SDL error: {}", e),
1089 }
1090 }
1091}
1092
1093impl Error for WindowBuildError {
1094 fn source(&self) -> Option<&(dyn Error + 'static)> {
1095 match self {
1096 Self::InvalidTitle(err) => Some(err),
1097 Self::HeightOverflows(_) | Self::WidthOverflows(_) | Self::SdlError(_) => None,
1098 }
1099 }
1100}
1101
1102#[derive(Debug)]
1104pub struct WindowBuilder {
1105 title: String,
1106 width: u32,
1107 height: u32,
1108 x: WindowPos,
1109 y: WindowPos,
1110 window_flags: u32,
1111 create_metal_view: bool,
1112 subsystem: VideoSubsystem,
1115 shaped: bool,
1116}
1117
1118impl WindowBuilder {
1119 pub fn new(v: &VideoSubsystem, title: &str, width: u32, height: u32) -> WindowBuilder {
1121 WindowBuilder {
1122 title: title.to_owned(),
1123 width,
1124 height,
1125 x: WindowPos::Undefined,
1126 y: WindowPos::Undefined,
1127 window_flags: 0,
1128 subsystem: v.clone(),
1129 create_metal_view: false,
1130 shaped: false,
1131 }
1132 }
1133
1134 #[doc(alias = "SDL_CreateWindow")]
1136 pub fn build(&self) -> Result<Window, WindowBuildError> {
1137 use self::WindowBuildError::*;
1138 let title = match CString::new(self.title.as_bytes()) {
1139 Ok(t) => t,
1140 Err(err) => return Err(InvalidTitle(err)),
1141 };
1142 if self.width >= (1 << 31) {
1143 return Err(WidthOverflows(self.width));
1144 }
1145 if self.height >= (1 << 31) {
1146 return Err(HeightOverflows(self.width));
1147 }
1148
1149 let raw_width = self.width as c_int;
1150 let raw_height = self.height as c_int;
1151 unsafe {
1152 let raw = if self.shaped {
1153 sys::SDL_CreateShapedWindow(
1154 title.as_ptr() as *const c_char,
1155 to_ll_windowpos(self.x) as u32,
1156 to_ll_windowpos(self.y) as u32,
1157 raw_width as u32,
1158 raw_height as u32,
1159 self.window_flags,
1160 )
1161 } else {
1162 sys::SDL_CreateWindow(
1163 title.as_ptr() as *const c_char,
1164 to_ll_windowpos(self.x),
1165 to_ll_windowpos(self.y),
1166 raw_width,
1167 raw_height,
1168 self.window_flags,
1169 )
1170 };
1171
1172 if raw.is_null() {
1173 Err(SdlError(get_error()))
1174 } else {
1175 let metal_view = match self.create_metal_view {
1176 #[cfg(target_os = "macos")]
1177 true => sys::SDL_Metal_CreateView(raw),
1178 _ => 0 as sys::SDL_MetalView,
1179 };
1180
1181 Ok(Window::from_ll(self.subsystem.clone(), raw, metal_view))
1182 }
1183 }
1184 }
1185
1186 pub fn window_flags(&self) -> u32 {
1188 self.window_flags
1189 }
1190
1191 pub fn set_window_flags(&mut self, flags: u32) -> &mut WindowBuilder {
1194 self.window_flags = flags;
1195 self
1196 }
1197
1198 pub fn position(&mut self, x: i32, y: i32) -> &mut WindowBuilder {
1200 self.x = WindowPos::Positioned(x);
1201 self.y = WindowPos::Positioned(y);
1202 self
1203 }
1204
1205 pub fn position_centered(&mut self) -> &mut WindowBuilder {
1207 self.x = WindowPos::Centered;
1208 self.y = WindowPos::Centered;
1209 self
1210 }
1211
1212 pub fn fullscreen(&mut self) -> &mut WindowBuilder {
1214 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_FULLSCREEN as u32;
1215 self
1216 }
1217
1218 pub fn fullscreen_desktop(&mut self) -> &mut WindowBuilder {
1220 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_FULLSCREEN_DESKTOP as u32;
1221 self
1222 }
1223
1224 pub fn opengl(&mut self) -> &mut WindowBuilder {
1226 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_OPENGL as u32;
1227 self
1228 }
1229
1230 pub fn vulkan(&mut self) -> &mut WindowBuilder {
1232 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_VULKAN as u32;
1233 self
1234 }
1235
1236 pub fn hidden(&mut self) -> &mut WindowBuilder {
1238 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_HIDDEN as u32;
1239 self
1240 }
1241
1242 pub fn borderless(&mut self) -> &mut WindowBuilder {
1244 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_BORDERLESS as u32;
1245 self
1246 }
1247
1248 pub fn resizable(&mut self) -> &mut WindowBuilder {
1250 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_RESIZABLE as u32;
1251 self
1252 }
1253
1254 pub fn minimized(&mut self) -> &mut WindowBuilder {
1256 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_MINIMIZED as u32;
1257 self
1258 }
1259
1260 pub fn maximized(&mut self) -> &mut WindowBuilder {
1262 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_MAXIMIZED as u32;
1263 self
1264 }
1265
1266 pub fn input_grabbed(&mut self) -> &mut WindowBuilder {
1268 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_INPUT_GRABBED as u32;
1269 self
1270 }
1271
1272 pub fn allow_highdpi(&mut self) -> &mut WindowBuilder {
1274 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_ALLOW_HIGHDPI as u32;
1275 self
1276 }
1277
1278 pub fn always_on_top(&mut self) -> &mut WindowBuilder {
1280 self.window_flags |= sys::SDL_WindowFlags::SDL_WINDOW_ALWAYS_ON_TOP as u32;
1281 self
1282 }
1283
1284 pub fn metal_view(&mut self) -> &mut WindowBuilder {
1288 self.create_metal_view = true;
1289 self
1290 }
1291
1292 pub fn set_shaped(&mut self) -> &mut WindowBuilder {
1294 self.shaped = true;
1295 self
1296 }
1297}
1298
1299impl From<Window> for CanvasBuilder {
1300 fn from(window: Window) -> CanvasBuilder {
1301 CanvasBuilder::new(window)
1302 }
1303}
1304
1305impl Window {
1306 #[inline]
1307 #[allow(clippy::trivially_copy_pass_by_ref)]
1310 pub fn raw(&self) -> *mut sys::SDL_Window {
1311 self.context.raw
1312 }
1313
1314 #[inline]
1315 pub unsafe fn from_ll(
1316 subsystem: VideoSubsystem,
1317 raw: *mut sys::SDL_Window,
1318 metal_view: sys::SDL_MetalView,
1319 ) -> Window {
1320 let context = WindowContext::from_ll(subsystem, raw, metal_view);
1321 context.into()
1322 }
1323
1324 #[inline]
1325 pub const fn from_ref(context: Rc<WindowContext>) -> Window {
1327 Window { context }
1328 }
1329
1330 #[inline]
1331 pub fn subsystem(&self) -> &VideoSubsystem {
1332 &self.context.subsystem
1333 }
1334
1335 pub fn into_canvas(self) -> CanvasBuilder {
1337 self.into()
1338 }
1339
1340 pub fn context(&self) -> Rc<WindowContext> {
1341 self.context.clone()
1342 }
1343
1344 #[doc(alias = "SDL_GetWindowID")]
1345 pub fn id(&self) -> u32 {
1346 unsafe { sys::SDL_GetWindowID(self.context.raw) }
1347 }
1348
1349 #[doc(alias = "SDL_GL_CreateContext")]
1350 pub fn gl_create_context(&self) -> Result<GLContext, String> {
1351 let result = unsafe { sys::SDL_GL_CreateContext(self.context.raw) };
1352 if result.is_null() {
1353 Err(get_error())
1354 } else {
1355 Ok(GLContext { raw: result })
1356 }
1357 }
1358
1359 #[doc(alias = "SDL_GL_GetCurrentContext")]
1360 pub unsafe fn gl_get_current_context(&self) -> Option<GLContext> {
1361 let context_raw = sys::SDL_GL_GetCurrentContext();
1362
1363 if !context_raw.is_null() {
1364 Some(GLContext { raw: context_raw })
1365 } else {
1366 None
1367 }
1368 }
1369
1370 #[doc(alias = "SDL_GL_MakeCurrent")]
1372 pub fn gl_set_context_to_current(&self) -> Result<(), String> {
1373 unsafe {
1374 let context_raw = sys::SDL_GL_GetCurrentContext();
1375
1376 if !context_raw.is_null() && sys::SDL_GL_MakeCurrent(self.context.raw, context_raw) == 0
1377 {
1378 Ok(())
1379 } else {
1380 Err(get_error())
1381 }
1382 }
1383 }
1384
1385 #[doc(alias = "SDL_GL_MakeCurrent")]
1386 pub fn gl_make_current(&self, context: &GLContext) -> Result<(), String> {
1387 unsafe {
1388 if sys::SDL_GL_MakeCurrent(self.context.raw, context.raw) == 0 {
1389 Ok(())
1390 } else {
1391 Err(get_error())
1392 }
1393 }
1394 }
1395
1396 #[doc(alias = "SDL_GL_SwapWindow")]
1397 pub fn gl_swap_window(&self) {
1398 unsafe { sys::SDL_GL_SwapWindow(self.context.raw) }
1399 }
1400
1401 #[doc(alias = "SDL_Vulkan_GetInstanceExtensions")]
1403 pub fn vulkan_instance_extensions(&self) -> Result<Vec<&'static str>, String> {
1404 let mut count: c_uint = 0;
1405 if unsafe {
1406 sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, ptr::null_mut())
1407 } == sys::SDL_bool::SDL_FALSE
1408 {
1409 return Err(get_error());
1410 }
1411 let mut names: Vec<*const c_char> = vec![ptr::null(); count as usize];
1412 if unsafe {
1413 sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, names.as_mut_ptr())
1414 } == sys::SDL_bool::SDL_FALSE
1415 {
1416 return Err(get_error());
1417 }
1418 Ok(names
1419 .iter()
1420 .map(|&val| unsafe { CStr::from_ptr(val) }.to_str().unwrap())
1421 .collect())
1422 }
1423
1424 #[doc(alias = "SDL_Vulkan_CreateSurface")]
1430 pub fn vulkan_create_surface(&self, instance: VkInstance) -> Result<VkSurfaceKHR, String> {
1431 let mut surface: VkSurfaceKHR = 0;
1432 if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance, &mut surface) }
1433 == sys::SDL_bool::SDL_FALSE
1434 {
1435 Err(get_error())
1436 } else {
1437 Ok(surface)
1438 }
1439 }
1440
1441 #[doc(alias = "SDL_GetWindowDisplayIndex")]
1442 pub fn display_index(&self) -> Result<i32, String> {
1443 let result = unsafe { sys::SDL_GetWindowDisplayIndex(self.context.raw) };
1444 if result < 0 {
1445 Err(get_error())
1446 } else {
1447 Ok(result as i32)
1448 }
1449 }
1450
1451 #[doc(alias = "SDL_SetWindowDisplayMode")]
1452 pub fn set_display_mode<D>(&mut self, display_mode: D) -> Result<(), String>
1453 where
1454 D: Into<Option<DisplayMode>>,
1455 {
1456 unsafe {
1457 let result = sys::SDL_SetWindowDisplayMode(
1458 self.context.raw,
1459 match display_mode.into() {
1460 Some(ref mode) => &mode.to_ll(),
1461 None => ptr::null(),
1462 },
1463 );
1464 if result < 0 {
1465 Err(get_error())
1466 } else {
1467 Ok(())
1468 }
1469 }
1470 }
1471
1472 #[doc(alias = "SDL_GetWindowDisplayMode")]
1473 pub fn display_mode(&self) -> Result<DisplayMode, String> {
1474 let mut dm = mem::MaybeUninit::uninit();
1475
1476 let result =
1477 unsafe { sys::SDL_GetWindowDisplayMode(self.context.raw, dm.as_mut_ptr()) == 0 };
1478
1479 if result {
1480 let dm = unsafe { dm.assume_init() };
1481 Ok(DisplayMode::from_ll(&dm))
1482 } else {
1483 Err(get_error())
1484 }
1485 }
1486
1487 #[doc(alias = "SDL_GetWindowICCProfile")]
1488 pub fn icc_profile(&self) -> Result<Vec<u8>, String> {
1489 unsafe {
1490 let mut size: libc::size_t = 0;
1491 let data = sys::SDL_GetWindowICCProfile(self.context.raw, &mut size as *mut _);
1492 if data.is_null() {
1493 return Err(get_error());
1494 }
1495 let mut result = vec![0; size as usize];
1496 result.copy_from_slice(std::slice::from_raw_parts(data as *const u8, size as usize));
1497 sys::SDL_free(data);
1498 Ok(result)
1499 }
1500 }
1501
1502 #[doc(alias = "SDL_GetWindowPixelFormat")]
1503 pub fn window_pixel_format(&self) -> PixelFormatEnum {
1504 unsafe {
1505 PixelFormatEnum::try_from(sys::SDL_GetWindowPixelFormat(self.context.raw) as u32)
1506 .unwrap()
1507 }
1508 }
1509
1510 #[doc(alias = "SDL_GetWindowFlags")]
1511 pub fn window_flags(&self) -> u32 {
1512 unsafe { sys::SDL_GetWindowFlags(self.context.raw) }
1513 }
1514
1515 pub fn has_input_focus(&self) -> bool {
1517 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_INPUT_FOCUS as u32
1518 }
1519
1520 pub fn has_input_grabbed(&self) -> bool {
1522 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_INPUT_GRABBED as u32
1523 }
1524
1525 pub fn has_mouse_focus(&self) -> bool {
1527 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_MOUSE_FOCUS as u32
1528 }
1529
1530 pub fn is_maximized(&self) -> bool {
1532 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_MAXIMIZED as u32
1533 }
1534
1535 pub fn is_minimized(&self) -> bool {
1537 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_MINIMIZED as u32
1538 }
1539
1540 pub fn is_always_on_top(&self) -> bool {
1542 0 != self.window_flags() & sys::SDL_WindowFlags::SDL_WINDOW_ALWAYS_ON_TOP as u32
1543 }
1544
1545 #[doc(alias = "SDL_SetWindowTitle")]
1546 pub fn set_title(&mut self, title: &str) -> Result<(), NulError> {
1547 let title = CString::new(title)?;
1548 unsafe {
1549 sys::SDL_SetWindowTitle(self.context.raw, title.as_ptr() as *const c_char);
1550 }
1551 Ok(())
1552 }
1553
1554 #[doc(alias = "SDL_SetWindowResizable")]
1555 pub fn set_resizable(&mut self, resizable: bool) {
1556 let resizable = if resizable {
1557 sys::SDL_bool::SDL_TRUE
1558 } else {
1559 sys::SDL_bool::SDL_FALSE
1560 };
1561 unsafe {
1562 sys::SDL_SetWindowResizable(self.context.raw, resizable);
1563 }
1564 }
1565
1566 pub fn set_window_shape_alpha<S: AsRef<SurfaceRef>>(
1573 &mut self,
1574 shape: S,
1575 binarization_cutoff: u8,
1576 ) -> Result<(), i32> {
1577 let mode = sys::WindowShapeMode::ShapeModeBinarizeAlpha;
1578 let parameters = sys::SDL_WindowShapeParams {
1579 binarizationCutoff: binarization_cutoff,
1580 };
1581 let mut shape_mode = sys::SDL_WindowShapeMode { mode, parameters };
1582 let result = unsafe {
1583 sys::SDL_SetWindowShape(self.context.raw, shape.as_ref().raw(), &mut shape_mode)
1584 };
1585 if result == 0 {
1586 Ok(())
1587 } else {
1588 Err(result)
1589 }
1590 }
1591
1592 #[doc(alias = "SDL_GetWindowTitle")]
1593 pub fn title(&self) -> &str {
1594 unsafe {
1595 let buf = sys::SDL_GetWindowTitle(self.context.raw);
1596
1597 CStr::from_ptr(buf as *const _).to_str().unwrap()
1599 }
1600 }
1601
1602 #[doc(alias = "SDL_SetWindowIcon")]
1613 pub fn set_icon<S: AsRef<SurfaceRef>>(&mut self, icon: S) {
1614 unsafe { sys::SDL_SetWindowIcon(self.context.raw, icon.as_ref().raw()) }
1615 }
1616
1617 #[doc(alias = "SDL_SetWindowPosition")]
1621 pub fn set_position(&mut self, x: WindowPos, y: WindowPos) {
1622 unsafe {
1623 sys::SDL_SetWindowPosition(self.context.raw, to_ll_windowpos(x), to_ll_windowpos(y))
1624 }
1625 }
1626
1627 #[doc(alias = "SDL_GetWindowPosition")]
1628 pub fn position(&self) -> (i32, i32) {
1629 let mut x: c_int = 0;
1630 let mut y: c_int = 0;
1631 unsafe { sys::SDL_GetWindowPosition(self.context.raw, &mut x, &mut y) };
1632 (x as i32, y as i32)
1633 }
1634
1635 #[doc(alias = "SDL_GetWindowBordersSize")]
1640 pub fn border_size(&self) -> Result<(u16, u16, u16, u16), String> {
1641 let mut top: c_int = 0;
1642 let mut left: c_int = 0;
1643 let mut bottom: c_int = 0;
1644 let mut right: c_int = 0;
1645 let result = unsafe {
1646 sys::SDL_GetWindowBordersSize(
1647 self.context.raw,
1648 &mut top,
1649 &mut left,
1650 &mut bottom,
1651 &mut right,
1652 )
1653 };
1654 if result < 0 {
1655 Err(get_error())
1656 } else {
1657 Ok((top as u16, left as u16, bottom as u16, right as u16))
1658 }
1659 }
1660
1661 #[doc(alias = "SDL_SetWindowSize")]
1662 pub fn set_size(&mut self, width: u32, height: u32) -> Result<(), IntegerOrSdlError> {
1663 let w = validate_int(width, "width")?;
1664 let h = validate_int(height, "height")?;
1665 unsafe {
1666 sys::SDL_SetWindowSize(self.context.raw, w, h);
1667 }
1668 Ok(())
1669 }
1670
1671 #[doc(alias = "SDL_GetWindowSize")]
1672 pub fn size(&self) -> (u32, u32) {
1673 let mut w: c_int = 0;
1674 let mut h: c_int = 0;
1675 unsafe { sys::SDL_GetWindowSize(self.context.raw, &mut w, &mut h) };
1676 (w as u32, h as u32)
1677 }
1678
1679 #[doc(alias = "SDL_GL_GetDrawableSize")]
1680 pub fn drawable_size(&self) -> (u32, u32) {
1681 let mut w: c_int = 0;
1682 let mut h: c_int = 0;
1683 unsafe { sys::SDL_GL_GetDrawableSize(self.context.raw, &mut w, &mut h) };
1684 (w as u32, h as u32)
1685 }
1686
1687 #[doc(alias = "SDL_Vulkan_GetDrawableSize")]
1688 pub fn vulkan_drawable_size(&self) -> (u32, u32) {
1689 let mut w: c_int = 0;
1690 let mut h: c_int = 0;
1691 unsafe { sys::SDL_Vulkan_GetDrawableSize(self.context.raw, &mut w, &mut h) };
1692 (w as u32, h as u32)
1693 }
1694
1695 #[doc(alias = "SDL_SetWindowMinimumSize")]
1696 pub fn set_minimum_size(&mut self, width: u32, height: u32) -> Result<(), IntegerOrSdlError> {
1697 let w = validate_int(width, "width")?;
1698 let h = validate_int(height, "height")?;
1699 unsafe {
1700 sys::SDL_SetWindowMinimumSize(self.context.raw, w, h);
1701 }
1702 Ok(())
1703 }
1704
1705 #[doc(alias = "SDL_GetWindowMinimumSize")]
1706 pub fn minimum_size(&self) -> (u32, u32) {
1707 let mut w: c_int = 0;
1708 let mut h: c_int = 0;
1709 unsafe { sys::SDL_GetWindowMinimumSize(self.context.raw, &mut w, &mut h) };
1710 (w as u32, h as u32)
1711 }
1712
1713 #[doc(alias = "SDL_SetWindowMaximumSize")]
1714 pub fn set_maximum_size(&mut self, width: u32, height: u32) -> Result<(), IntegerOrSdlError> {
1715 let w = validate_int(width, "width")?;
1716 let h = validate_int(height, "height")?;
1717 unsafe {
1718 sys::SDL_SetWindowMaximumSize(self.context.raw, w, h);
1719 }
1720 Ok(())
1721 }
1722
1723 #[doc(alias = "SDL_GetWindowMaximumSize")]
1724 pub fn maximum_size(&self) -> (u32, u32) {
1725 let mut w: c_int = 0;
1726 let mut h: c_int = 0;
1727 unsafe { sys::SDL_GetWindowMaximumSize(self.context.raw, &mut w, &mut h) };
1728 (w as u32, h as u32)
1729 }
1730
1731 #[doc(alias = "SDL_SetWindowBordered")]
1732 pub fn set_bordered(&mut self, bordered: bool) {
1733 unsafe {
1734 sys::SDL_SetWindowBordered(
1735 self.context.raw,
1736 if bordered {
1737 sys::SDL_bool::SDL_TRUE
1738 } else {
1739 sys::SDL_bool::SDL_FALSE
1740 },
1741 )
1742 }
1743 }
1744
1745 #[doc(alias = "SDL_ShowWindow")]
1746 pub fn show(&mut self) {
1747 unsafe { sys::SDL_ShowWindow(self.context.raw) }
1748 }
1749
1750 #[doc(alias = "SDL_HideWindow")]
1751 pub fn hide(&mut self) {
1752 unsafe { sys::SDL_HideWindow(self.context.raw) }
1753 }
1754
1755 #[doc(alias = "SDL_RaiseWindow")]
1756 pub fn raise(&mut self) {
1757 unsafe { sys::SDL_RaiseWindow(self.context.raw) }
1758 }
1759
1760 #[doc(alias = "SDL_MaximizeWindow")]
1761 pub fn maximize(&mut self) {
1762 unsafe { sys::SDL_MaximizeWindow(self.context.raw) }
1763 }
1764
1765 #[doc(alias = "SDL_MinimizeWindow")]
1766 pub fn minimize(&mut self) {
1767 unsafe { sys::SDL_MinimizeWindow(self.context.raw) }
1768 }
1769
1770 #[doc(alias = "SDL_RestoreWindow")]
1771 pub fn restore(&mut self) {
1772 unsafe { sys::SDL_RestoreWindow(self.context.raw) }
1773 }
1774
1775 pub fn fullscreen_state(&self) -> FullscreenType {
1776 FullscreenType::from_window_flags(self.window_flags())
1777 }
1778
1779 #[doc(alias = "SDL_SetWindowFullscreen")]
1780 pub fn set_fullscreen(&mut self, fullscreen_type: FullscreenType) -> Result<(), String> {
1781 unsafe {
1782 let result = sys::SDL_SetWindowFullscreen(self.context.raw, fullscreen_type as u32);
1783 if result == 0 {
1784 Ok(())
1785 } else {
1786 Err(get_error())
1787 }
1788 }
1789 }
1790
1791 #[doc(alias = "SDL_GetWindowSurface")]
1804 pub fn surface<'a>(&'a self, _e: &'a EventPump) -> Result<WindowSurfaceRef<'a>, String> {
1805 let raw = unsafe { sys::SDL_GetWindowSurface(self.context.raw) };
1806
1807 if raw.is_null() {
1808 Err(get_error())
1809 } else {
1810 let surface_ref = unsafe { SurfaceRef::from_ll_mut(raw) };
1811 Ok(WindowSurfaceRef(surface_ref, self))
1812 }
1813 }
1814
1815 #[doc(alias = "SDL_SetWindowGrab")]
1816 pub fn set_grab(&mut self, grabbed: bool) {
1817 unsafe {
1818 sys::SDL_SetWindowGrab(
1819 self.context.raw,
1820 if grabbed {
1821 sys::SDL_bool::SDL_TRUE
1822 } else {
1823 sys::SDL_bool::SDL_FALSE
1824 },
1825 )
1826 }
1827 }
1828
1829 #[doc(alias = "SDL_SetWindowKeyboardGrab")]
1830 pub fn set_keyboard_grab(&mut self, grabbed: bool) {
1831 unsafe {
1832 sys::SDL_SetWindowKeyboardGrab(
1833 self.context.raw,
1834 if grabbed {
1835 sys::SDL_bool::SDL_TRUE
1836 } else {
1837 sys::SDL_bool::SDL_FALSE
1838 },
1839 )
1840 }
1841 }
1842
1843 #[doc(alias = "SDL_SetWindowMouseGrab")]
1844 pub fn set_mouse_grab(&mut self, grabbed: bool) {
1845 unsafe {
1846 sys::SDL_SetWindowMouseGrab(
1847 self.context.raw,
1848 if grabbed {
1849 sys::SDL_bool::SDL_TRUE
1850 } else {
1851 sys::SDL_bool::SDL_FALSE
1852 },
1853 )
1854 }
1855 }
1856
1857 #[doc(alias = "SDL_GetWindowGrab")]
1858 pub fn grab(&self) -> bool {
1859 unsafe { sys::SDL_GetWindowGrab(self.context.raw) == sys::SDL_bool::SDL_TRUE }
1860 }
1861
1862 #[doc(alias = "SDL_GetWindowKeyboardGrab")]
1863 pub fn keyboard_grab(&self) -> bool {
1864 unsafe { sys::SDL_GetWindowKeyboardGrab(self.context.raw) == sys::SDL_bool::SDL_TRUE }
1865 }
1866
1867 #[doc(alias = "SDL_GetWindowMouseGrab")]
1868 pub fn mouse_grab(&self) -> bool {
1869 unsafe { sys::SDL_GetWindowMouseGrab(self.context.raw) == sys::SDL_bool::SDL_TRUE }
1870 }
1871
1872 #[doc(alias = "SDL_SetWindowMouseRect")]
1873 pub fn set_mouse_rect<R>(&self, rect: R) -> Result<(), String>
1874 where
1875 R: Into<Option<Rect>>,
1876 {
1877 let rect = rect.into();
1878 let rect_raw_ptr = match rect {
1879 Some(ref rect) => rect.raw(),
1880 None => ptr::null(),
1881 };
1882
1883 unsafe {
1884 if sys::SDL_SetWindowMouseRect(self.context.raw, rect_raw_ptr) == 0 {
1885 Ok(())
1886 } else {
1887 Err(get_error())
1888 }
1889 }
1890 }
1891
1892 #[doc(alias = "SDL_GetWindowMouseRect")]
1893 pub fn mouse_rect(&self) -> Option<Rect> {
1894 unsafe {
1895 let raw_rect = sys::SDL_GetWindowMouseRect(self.context.raw);
1896 if raw_rect.is_null() {
1897 None
1898 } else {
1899 Some(Rect::new(
1900 (*raw_rect).x,
1901 (*raw_rect).y,
1902 (*raw_rect).w as u32,
1903 (*raw_rect).h as u32,
1904 ))
1905 }
1906 }
1907 }
1908
1909 #[doc(alias = "SDL_SetWindowBrightness")]
1910 pub fn set_brightness(&mut self, brightness: f64) -> Result<(), String> {
1911 unsafe {
1912 if sys::SDL_SetWindowBrightness(self.context.raw, brightness as c_float) == 0 {
1913 Ok(())
1914 } else {
1915 Err(get_error())
1916 }
1917 }
1918 }
1919
1920 #[doc(alias = "SDL_GetWindowBrightness")]
1921 pub fn brightness(&self) -> f64 {
1922 unsafe { sys::SDL_GetWindowBrightness(self.context.raw) as f64 }
1923 }
1924
1925 #[doc(alias = "SDL_SetWindowGammaRamp")]
1926 pub fn set_gamma_ramp<'a, 'b, 'c, R, G, B>(
1927 &mut self,
1928 red: R,
1929 green: G,
1930 blue: B,
1931 ) -> Result<(), String>
1932 where
1933 R: Into<Option<&'a [u16; 256]>>,
1934 G: Into<Option<&'b [u16; 256]>>,
1935 B: Into<Option<&'c [u16; 256]>>,
1936 {
1937 let unwrapped_red = match red.into() {
1938 Some(values) => values.as_ptr(),
1939 None => ptr::null(),
1940 };
1941 let unwrapped_green = match green.into() {
1942 Some(values) => values.as_ptr(),
1943 None => ptr::null(),
1944 };
1945 let unwrapped_blue = match blue.into() {
1946 Some(values) => values.as_ptr(),
1947 None => ptr::null(),
1948 };
1949 let result = unsafe {
1950 sys::SDL_SetWindowGammaRamp(
1951 self.context.raw,
1952 unwrapped_red,
1953 unwrapped_green,
1954 unwrapped_blue,
1955 )
1956 };
1957 if result != 0 {
1958 Err(get_error())
1959 } else {
1960 Ok(())
1961 }
1962 }
1963
1964 #[allow(clippy::type_complexity)]
1965 #[doc(alias = "SDL_GetWindowGammaRamp")]
1966 pub fn gamma_ramp(&self) -> Result<(Vec<u16>, Vec<u16>, Vec<u16>), String> {
1967 let mut red: Vec<u16> = vec![0; 256];
1968 let mut green: Vec<u16> = vec![0; 256];
1969 let mut blue: Vec<u16> = vec![0; 256];
1970 let result = unsafe {
1971 sys::SDL_GetWindowGammaRamp(
1972 self.context.raw,
1973 red.as_mut_ptr(),
1974 green.as_mut_ptr(),
1975 blue.as_mut_ptr(),
1976 )
1977 };
1978 if result == 0 {
1979 Ok((red, green, blue))
1980 } else {
1981 Err(get_error())
1982 }
1983 }
1984
1985 #[doc(alias = "SDL_SetWindowOpacity")]
1990 pub fn set_opacity(&mut self, opacity: f32) -> Result<(), String> {
1991 let result = unsafe { sys::SDL_SetWindowOpacity(self.context.raw, opacity) };
1992 if result < 0 {
1993 Err(get_error())
1994 } else {
1995 Ok(())
1996 }
1997 }
1998
1999 #[doc(alias = "SDL_GetWindowOpacity")]
2005 pub fn opacity(&self) -> Result<f32, String> {
2006 let mut opacity = 0.0;
2007 let result = unsafe { sys::SDL_GetWindowOpacity(self.context.raw, &mut opacity) };
2008 if result < 0 {
2009 Err(get_error())
2010 } else {
2011 Ok(opacity)
2012 }
2013 }
2014
2015 #[doc(alias = "SDL_FlashWindow")]
2017 pub fn flash(&mut self, operation: FlashOperation) -> Result<(), String> {
2018 let result = unsafe { sys::SDL_FlashWindow(self.context.raw, operation.to_ll()) };
2019 if result == 0 {
2020 Ok(())
2021 } else {
2022 Err(get_error())
2023 }
2024 }
2025
2026 #[doc(alias = "SDL_SetWindowAlwaysOnTop")]
2028 pub fn set_always_on_top(&mut self, on_top: bool) {
2029 unsafe {
2030 sys::SDL_SetWindowAlwaysOnTop(
2031 self.context.raw,
2032 if on_top {
2033 sys::SDL_bool::SDL_TRUE
2034 } else {
2035 sys::SDL_bool::SDL_FALSE
2036 },
2037 )
2038 };
2039 }
2040}
2041
2042#[derive(Copy, Clone)]
2043#[doc(alias = "SDL_GetVideoDriver")]
2044pub struct DriverIterator {
2045 length: i32,
2046 index: i32,
2047}
2048
2049fn get_video_driver(index: i32) -> &'static str {
2053 use std::str;
2054
2055 unsafe {
2056 let buf = sys::SDL_GetVideoDriver(index);
2057 assert!(!buf.is_null());
2058
2059 str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap()
2060 }
2061}
2062
2063impl Iterator for DriverIterator {
2064 type Item = &'static str;
2065
2066 #[inline]
2067 fn next(&mut self) -> Option<&'static str> {
2068 if self.index >= self.length {
2069 None
2070 } else {
2071 let driver = get_video_driver(self.index);
2072 self.index += 1;
2073
2074 Some(driver)
2075 }
2076 }
2077
2078 #[inline]
2079 fn size_hint(&self) -> (usize, Option<usize>) {
2080 let remaining = (self.length - self.index) as usize;
2081 (remaining, Some(remaining))
2082 }
2083
2084 #[inline]
2085 fn nth(&mut self, n: usize) -> Option<&'static str> {
2086 use std::convert::TryInto;
2087
2088 self.index = match n.try_into().ok().and_then(|n| self.index.checked_add(n)) {
2089 Some(index) if index < self.length => index,
2090 _ => self.length,
2091 };
2092
2093 self.next()
2094 }
2095}
2096
2097impl DoubleEndedIterator for DriverIterator {
2098 #[inline]
2099 fn next_back(&mut self) -> Option<&'static str> {
2100 if self.index >= self.length {
2101 None
2102 } else {
2103 self.length -= 1;
2104
2105 Some(get_video_driver(self.length))
2106 }
2107 }
2108
2109 #[inline]
2110 fn nth_back(&mut self, n: usize) -> Option<&'static str> {
2111 use std::convert::TryInto;
2112
2113 self.length = match n.try_into().ok().and_then(|n| self.length.checked_sub(n)) {
2114 Some(length) if length > self.index => length,
2115 _ => self.index,
2116 };
2117
2118 self.next_back()
2119 }
2120}
2121
2122impl ExactSizeIterator for DriverIterator {}
2123
2124impl std::iter::FusedIterator for DriverIterator {}
2125
2126#[inline]
2128#[doc(alias = "SDL_GetVideoDriver")]
2129pub fn drivers() -> DriverIterator {
2130 DriverIterator {
2135 length: unsafe { sys::SDL_GetNumVideoDrivers() },
2136 index: 0,
2137 }
2138}