1use std::cell::{Cell, RefCell};
4use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
5use std::sync::atomic::{AtomicUsize, Ordering};
6use std::{mem, ptr, slice};
7
8use crate::color::Color;
9use crate::renderer::Renderer;
10use crate::Mode;
11use crate::WindowFlag;
12use crate::{event::*, SurfaceFlag};
13
14static SDL_USAGES: AtomicUsize = AtomicUsize::new(0);
15static mut SDL_CTX: *mut sdl2::Sdl = ptr::null_mut();
17static mut VIDEO_CTX: *mut sdl2::VideoSubsystem = ptr::null_mut();
19static mut EVENT_PUMP: *mut sdl2::EventPump = ptr::null_mut();
21
22#[inline]
24unsafe fn init() {
25 if SDL_USAGES.fetch_add(1, Ordering::Relaxed) == 0 {
26 SDL_CTX = Box::into_raw(Box::new(sdl2::init().unwrap()));
27 VIDEO_CTX = Box::into_raw(Box::new((*SDL_CTX).video().unwrap()));
28 EVENT_PUMP = Box::into_raw(Box::new((*SDL_CTX).event_pump().unwrap()));
29 }
30}
31
32#[inline]
34unsafe fn cleanup() {
35 if SDL_USAGES.fetch_sub(1, Ordering::Relaxed) == 0 {
36 return;
37 }
38
39 drop(Box::from_raw(SDL_CTX));
40 drop(Box::from_raw(VIDEO_CTX));
41 drop(Box::from_raw(EVENT_PUMP));
42}
43
44pub fn get_display_size() -> Result<(u32, u32), String> {
46 unsafe { init() };
47 unsafe { &*VIDEO_CTX }
48 .display_bounds(0)
49 .map(|rect| (rect.width(), rect.height()))
50}
51
52#[allow(dead_code)]
54pub struct Window {
55 x: i32,
57 y: i32,
59 w: u32,
61 h: u32,
63 t: String,
65 window_async: bool,
67 mode: Cell<Mode>,
69 inner: sdl2::render::WindowCanvas,
71 mouse_relative: bool,
73 drop_content: RefCell<Option<String>>,
75}
76
77impl Drop for Window {
78 fn drop(&mut self) {
79 unsafe {
80 cleanup();
81 }
82 }
83}
84
85impl AsRawFd for Window {
86 fn as_raw_fd(&self) -> RawFd {
87 unimplemented!()
88 }
89}
90
91impl FromRawFd for Window {
92 unsafe fn from_raw_fd(_fd: RawFd) -> Window {
93 unimplemented!()
94 }
95}
96
97impl IntoRawFd for Window {
98 fn into_raw_fd(self) -> RawFd {
99 unimplemented!()
100 }
101}
102
103impl Renderer for Window {
104 fn width(&self) -> u32 {
106 self.w
107 }
108
109 fn height(&self) -> u32 {
111 self.h
112 }
113
114 fn data(&self) -> &[Color] {
116 let window = self.inner.window();
117 let surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
118 let bytes = surface.without_lock().unwrap();
119 unsafe {
120 slice::from_raw_parts(
121 bytes.as_ptr() as *const Color,
122 bytes.len() / mem::size_of::<Color>(),
123 )
124 }
125 }
126
127 fn data_mut(&mut self) -> &mut [Color] {
129 let window = self.inner.window_mut();
130 let mut surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
131 let bytes = surface.without_lock_mut().unwrap();
132 unsafe {
133 slice::from_raw_parts_mut(
134 bytes.as_mut_ptr() as *mut Color,
135 bytes.len() / mem::size_of::<Color>(),
136 )
137 }
138 }
139
140 fn sync(&mut self) -> bool {
142 self.inner.present();
143 true
144 }
145
146 fn update(&mut self) -> bool {
148 let window = self.inner.window_mut();
149 let surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
150 surface.update_window().is_ok()
151 }
152
153 fn update_rects(&mut self, rects: &[(i32, i32, u32, u32)]) -> bool {
155 let window = self.inner.window_mut();
156 let surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
157 surface
158 .update_window_rects(
159 &rects
160 .iter()
161 .cloned()
162 .map(|(x, y, w, h)| sdl2::rect::Rect::new(x, y, w, h))
163 .collect::<Vec<_>>()[..],
164 )
165 .is_ok()
166 }
167
168 fn mode(&self) -> &Cell<Mode> {
170 &self.mode
171 }
172}
173
174impl Window {
175 pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
177 Window::new_flags(x, y, w, h, title, &[])
178 }
179
180 pub fn new_flags(
182 x: i32,
183 y: i32,
184 w: u32,
185 h: u32,
186 title: &str,
187 flags: &[WindowFlag],
188 ) -> Option<Self> {
189 unsafe { init() };
191
192 let mut window_async = false;
193 let mut _back = false;
195 let mut _front = false;
196 let mut borderless = false;
197 let mut resizable = false;
198 let mut _transparent = false;
200 let mut _unclosable = false;
202 for &flag in flags.iter() {
203 match flag {
204 WindowFlag::Async => window_async = true,
205 WindowFlag::Back => _back = true,
206 WindowFlag::Front => _front = true,
207 WindowFlag::Borderless => borderless = true,
208 WindowFlag::Resizable => resizable = true,
209 WindowFlag::Transparent => _transparent = true,
210 WindowFlag::Unclosable => _unclosable = true,
211 }
212 }
213
214 let mut builder = unsafe { &*VIDEO_CTX }.window(title, w, h);
215
216 {
217 builder.allow_highdpi();
218 }
219
220 if borderless {
221 builder.borderless();
222 }
223
224 if resizable {
225 builder.resizable();
226 }
227
228 if x >= 0 || y >= 0 {
229 builder.position(x, y);
230 }
231
232 match builder.build() {
233 Ok(window) => Some(Window {
234 x,
235 y,
236 w,
237 h,
238 t: title.to_string(),
239 window_async,
240 mode: Cell::new(Mode::Blend),
241 inner: window.into_canvas().software().build().unwrap(),
242 mouse_relative: false,
243 drop_content: RefCell::new(None),
244 }),
245 Err(_) => None,
246 }
247 }
248
249 pub fn event_sender(&self) -> sdl2::event::EventSender {
250 unsafe { &mut *SDL_CTX }.event().unwrap().event_sender()
251 }
252
253 pub fn clipboard(&self) -> String {
254 let result = unsafe { &*VIDEO_CTX }.clipboard().clipboard_text();
255
256 match result {
257 Ok(value) => return value,
258 Err(message) => println!("{}", message),
259 }
260
261 String::default()
262 }
263
264 pub fn set_clipboard(&mut self, text: &str) {
265 let result = unsafe { &*VIDEO_CTX }.clipboard().set_clipboard_text(text);
266
267 if let Err(message) = result {
268 println!("{}", message);
269 }
270 }
271
272 pub fn pop_drop_content(&self) -> Option<String> {
274 let result = self.drop_content.borrow().clone();
275 *self.drop_content.borrow_mut() = None;
276
277 result
278 }
279
280 pub fn sync_path(&mut self) {
281 let window = self.inner.window();
282 let pos = window.position();
283 let size = window.size();
284 let title = window.title();
285 self.x = pos.0;
286 self.y = pos.1;
287 self.w = size.0;
288 self.h = size.1;
289 self.t = title.to_string();
290 }
291
292 pub fn x(&self) -> i32 {
295 self.x
296 }
297
298 pub fn y(&self) -> i32 {
301 self.y
302 }
303
304 pub fn title(&self) -> String {
306 self.t.clone()
307 }
308
309 pub fn is_async(&self) -> bool {
311 self.window_async
312 }
313
314 pub fn set_async(&mut self, is_async: bool) {
316 self.window_async = is_async;
317 }
318
319 pub fn set_mouse_cursor(&mut self, visible: bool) {
321 unsafe { &mut *SDL_CTX }.mouse().show_cursor(visible);
322 }
323
324 pub fn set_mouse_grab(&mut self, grab: bool) {
326 unsafe { &mut *SDL_CTX }.mouse().capture(grab);
327 }
328
329 pub fn set_mouse_relative(&mut self, relative: bool) {
331 unsafe { &mut *SDL_CTX }
332 .mouse()
333 .set_relative_mouse_mode(relative);
334 self.mouse_relative = relative;
335 }
336
337 pub fn set_pos(&mut self, x: i32, y: i32) {
339 self.inner.window_mut().set_position(
340 sdl2::video::WindowPos::Positioned(x),
341 sdl2::video::WindowPos::Positioned(y),
342 );
343 self.sync_path();
344 }
345
346 pub fn set_size(&mut self, width: u32, height: u32) {
348 let _ = self.inner.window_mut().set_size(width, height);
349 self.sync_path();
350 }
351
352 pub fn set_title(&mut self, title: &str) {
354 let _ = self.inner.window_mut().set_title(title);
355 self.sync_path();
356 }
357
358 fn convert_scancode(
359 &self,
360 scancode_option: Option<sdl2::keyboard::Scancode>,
361 shift: bool,
362 ) -> Option<(char, u8)> {
363 if let Some(scancode) = scancode_option {
364 match scancode {
365 sdl2::keyboard::Scancode::A => Some((if shift { 'A' } else { 'a' }, K_A)),
366 sdl2::keyboard::Scancode::B => Some((if shift { 'B' } else { 'b' }, K_B)),
367 sdl2::keyboard::Scancode::C => Some((if shift { 'C' } else { 'c' }, K_C)),
368 sdl2::keyboard::Scancode::D => Some((if shift { 'D' } else { 'd' }, K_D)),
369 sdl2::keyboard::Scancode::E => Some((if shift { 'E' } else { 'e' }, K_E)),
370 sdl2::keyboard::Scancode::F => Some((if shift { 'F' } else { 'f' }, K_F)),
371 sdl2::keyboard::Scancode::G => Some((if shift { 'G' } else { 'g' }, K_G)),
372 sdl2::keyboard::Scancode::H => Some((if shift { 'H' } else { 'h' }, K_H)),
373 sdl2::keyboard::Scancode::I => Some((if shift { 'I' } else { 'i' }, K_I)),
374 sdl2::keyboard::Scancode::J => Some((if shift { 'J' } else { 'j' }, K_J)),
375 sdl2::keyboard::Scancode::K => Some((if shift { 'K' } else { 'k' }, K_K)),
376 sdl2::keyboard::Scancode::L => Some((if shift { 'L' } else { 'l' }, K_L)),
377 sdl2::keyboard::Scancode::M => Some((if shift { 'M' } else { 'm' }, K_M)),
378 sdl2::keyboard::Scancode::N => Some((if shift { 'N' } else { 'n' }, K_N)),
379 sdl2::keyboard::Scancode::O => Some((if shift { 'O' } else { 'o' }, K_O)),
380 sdl2::keyboard::Scancode::P => Some((if shift { 'P' } else { 'p' }, K_P)),
381 sdl2::keyboard::Scancode::Q => Some((if shift { 'Q' } else { 'q' }, K_Q)),
382 sdl2::keyboard::Scancode::R => Some((if shift { 'R' } else { 'r' }, K_R)),
383 sdl2::keyboard::Scancode::S => Some((if shift { 'S' } else { 's' }, K_S)),
384 sdl2::keyboard::Scancode::T => Some((if shift { 'T' } else { 't' }, K_T)),
385 sdl2::keyboard::Scancode::U => Some((if shift { 'U' } else { 'u' }, K_U)),
386 sdl2::keyboard::Scancode::V => Some((if shift { 'V' } else { 'v' }, K_V)),
387 sdl2::keyboard::Scancode::W => Some((if shift { 'W' } else { 'w' }, K_W)),
388 sdl2::keyboard::Scancode::X => Some((if shift { 'X' } else { 'x' }, K_X)),
389 sdl2::keyboard::Scancode::Y => Some((if shift { 'Y' } else { 'y' }, K_Y)),
390 sdl2::keyboard::Scancode::Z => Some((if shift { 'Z' } else { 'z' }, K_Z)),
391 sdl2::keyboard::Scancode::Num0 => Some((if shift { ')' } else { '0' }, K_0)),
392 sdl2::keyboard::Scancode::Num1 => Some((if shift { '!' } else { '1' }, K_1)),
393 sdl2::keyboard::Scancode::Num2 => Some((if shift { '@' } else { '2' }, K_2)),
394 sdl2::keyboard::Scancode::Num3 => Some((if shift { '#' } else { '3' }, K_3)),
395 sdl2::keyboard::Scancode::Num4 => Some((if shift { '$' } else { '4' }, K_4)),
396 sdl2::keyboard::Scancode::Num5 => Some((if shift { '%' } else { '5' }, K_5)),
397 sdl2::keyboard::Scancode::Num6 => Some((if shift { '^' } else { '6' }, K_6)),
398 sdl2::keyboard::Scancode::Num7 => Some((if shift { '&' } else { '7' }, K_7)),
399 sdl2::keyboard::Scancode::Num8 => Some((if shift { '*' } else { '8' }, K_8)),
400 sdl2::keyboard::Scancode::Num9 => Some((if shift { '(' } else { '9' }, K_9)),
401 sdl2::keyboard::Scancode::Grave => Some((if shift { '~' } else { '`' }, K_TICK)),
402 sdl2::keyboard::Scancode::Minus => Some((if shift { '_' } else { '-' }, K_MINUS)),
403 sdl2::keyboard::Scancode::Equals => Some((if shift { '+' } else { '=' }, K_EQUALS)),
404 sdl2::keyboard::Scancode::LeftBracket => {
405 Some((if shift { '{' } else { '[' }, K_BRACE_OPEN))
406 }
407 sdl2::keyboard::Scancode::RightBracket => {
408 Some((if shift { '}' } else { ']' }, K_BRACE_CLOSE))
409 }
410 sdl2::keyboard::Scancode::Backslash => {
411 Some((if shift { '|' } else { '\\' }, K_BACKSLASH))
412 }
413 sdl2::keyboard::Scancode::Semicolon => {
414 Some((if shift { ':' } else { ';' }, K_SEMICOLON))
415 }
416 sdl2::keyboard::Scancode::Apostrophe => {
417 Some((if shift { '"' } else { '\'' }, K_QUOTE))
418 }
419 sdl2::keyboard::Scancode::Comma => Some((if shift { '<' } else { ',' }, K_COMMA)),
420 sdl2::keyboard::Scancode::Period => Some((if shift { '>' } else { '.' }, K_PERIOD)),
421 sdl2::keyboard::Scancode::Slash => Some((if shift { '?' } else { '/' }, K_SLASH)),
422 sdl2::keyboard::Scancode::Space => Some((' ', K_SPACE)),
423 sdl2::keyboard::Scancode::Backspace => Some(('\0', K_BKSP)),
424 sdl2::keyboard::Scancode::Tab => Some(('\t', K_TAB)),
425 sdl2::keyboard::Scancode::LCtrl => Some(('\0', K_CTRL)),
426 sdl2::keyboard::Scancode::RCtrl => Some(('\0', K_CTRL)),
427 sdl2::keyboard::Scancode::LAlt => Some(('\0', K_ALT)),
428 sdl2::keyboard::Scancode::RAlt => Some(('\0', K_ALT)),
429 sdl2::keyboard::Scancode::Return => Some(('\n', K_ENTER)),
430 sdl2::keyboard::Scancode::Escape => Some(('\x1B', K_ESC)),
431 sdl2::keyboard::Scancode::F1 => Some(('\0', K_F1)),
432 sdl2::keyboard::Scancode::F2 => Some(('\0', K_F2)),
433 sdl2::keyboard::Scancode::F3 => Some(('\0', K_F3)),
434 sdl2::keyboard::Scancode::F4 => Some(('\0', K_F4)),
435 sdl2::keyboard::Scancode::F5 => Some(('\0', K_F5)),
436 sdl2::keyboard::Scancode::F6 => Some(('\0', K_F6)),
437 sdl2::keyboard::Scancode::F7 => Some(('\0', K_F7)),
438 sdl2::keyboard::Scancode::F8 => Some(('\0', K_F8)),
439 sdl2::keyboard::Scancode::F9 => Some(('\0', K_F9)),
440 sdl2::keyboard::Scancode::F10 => Some(('\0', K_F10)),
441 sdl2::keyboard::Scancode::Home => Some(('\0', K_HOME)),
442 sdl2::keyboard::Scancode::LGui => Some(('\0', K_HOME)),
443 sdl2::keyboard::Scancode::Up => Some(('\0', K_UP)),
444 sdl2::keyboard::Scancode::PageUp => Some(('\0', K_PGUP)),
445 sdl2::keyboard::Scancode::Left => Some(('\0', K_LEFT)),
446 sdl2::keyboard::Scancode::Right => Some(('\0', K_RIGHT)),
447 sdl2::keyboard::Scancode::End => Some(('\0', K_END)),
448 sdl2::keyboard::Scancode::Down => Some(('\0', K_DOWN)),
449 sdl2::keyboard::Scancode::PageDown => Some(('\0', K_PGDN)),
450 sdl2::keyboard::Scancode::Delete => Some(('\0', K_DEL)),
451 sdl2::keyboard::Scancode::F11 => Some(('\0', K_F11)),
452 sdl2::keyboard::Scancode::F12 => Some(('\0', K_F12)),
453 sdl2::keyboard::Scancode::LShift => Some(('\0', K_LEFT_SHIFT)),
454 sdl2::keyboard::Scancode::RShift => Some(('\0', K_RIGHT_SHIFT)),
455 _ => None,
456 }
457 } else {
458 None
459 }
460 }
461
462 fn get_mouse_position(&self) -> (i32, i32) {
463 let mouse_state = unsafe { &mut *EVENT_PUMP }.mouse_state();
464 (mouse_state.x(), mouse_state.y())
465 }
466
467 fn convert_event(&self, event: sdl2::event::Event) -> Vec<Event> {
468 let mut events = Vec::new();
469
470 let button_event = || -> Event {
471 let mouse = unsafe { &mut *EVENT_PUMP }.mouse_state();
472 ButtonEvent {
473 left: mouse.left(),
474 middle: mouse.middle(),
475 right: mouse.right(),
476 }
477 .to_event()
478 };
479
480 let mods = unsafe { &mut *SDL_CTX }.keyboard().mod_state();
481 let shift = mods.contains(sdl2::keyboard::Mod::CAPSMOD)
482 || mods.contains(sdl2::keyboard::Mod::LSHIFTMOD)
483 || mods.contains(sdl2::keyboard::Mod::RSHIFTMOD);
484
485 match event {
486 sdl2::event::Event::RenderTargetsReset { .. } => {
487 events.push(Event::new());
488 }
489 sdl2::event::Event::Window { win_event, .. } => match win_event {
490 sdl2::event::WindowEvent::Moved(x, y) => events.push(MoveEvent { x, y }.to_event()),
491 sdl2::event::WindowEvent::Resized(w, h) => events.push(
492 ResizeEvent {
493 width: w as u32,
494 height: h as u32,
495 }
496 .to_event(),
497 ),
498 sdl2::event::WindowEvent::FocusGained => {
499 events.push(FocusEvent { focused: true }.to_event())
500 }
501 sdl2::event::WindowEvent::FocusLost => {
502 events.push(FocusEvent { focused: false }.to_event())
503 }
504 sdl2::event::WindowEvent::Enter => {
505 events.push(HoverEvent { entered: true }.to_event())
506 }
507 sdl2::event::WindowEvent::Leave => {
508 events.push(HoverEvent { entered: false }.to_event())
509 }
510 sdl2::event::WindowEvent::None => events.push(Event::new()),
511 _ => (),
512 },
513 sdl2::event::Event::ClipboardUpdate { .. } => {
514 events.push(ClipboardUpdateEvent.to_event())
515 }
516 sdl2::event::Event::MouseMotion {
517 x, y, xrel, yrel, ..
518 } => {
519 if self.mouse_relative {
520 events.push(MouseRelativeEvent { dx: xrel, dy: yrel }.to_event())
521 } else {
522 events.push(MouseEvent { x, y }.to_event())
523 }
524 }
525 sdl2::event::Event::MouseButtonDown { .. } => events.push(button_event()),
526 sdl2::event::Event::MouseButtonUp { .. } => events.push(button_event()),
527 sdl2::event::Event::MouseWheel { x, y, .. } => {
528 events.push(ScrollEvent { x, y }.to_event())
529 }
530 sdl2::event::Event::TextInput { text, .. } => {
531 for character in text.chars() {
532 events.push(TextInputEvent { character }.to_event());
533 }
534 }
535 sdl2::event::Event::KeyDown { scancode, .. } => {
536 if let Some(code) = self.convert_scancode(scancode, shift) {
537 events.push(
538 KeyEvent {
539 character: code.0,
540 scancode: code.1,
541 pressed: true,
542 }
543 .to_event(),
544 );
545 }
546 }
547 sdl2::event::Event::DropFile { filename, .. } => {
548 *self.drop_content.borrow_mut() = Some(filename);
549
550 let (x, y) = self.get_mouse_position();
551
552 events.push(MouseEvent { x, y }.to_event());
553
554 events.push(DropEvent { kind: DROP_FILE }.to_event())
555 }
556 sdl2::event::Event::DropText { filename, .. } => {
557 *self.drop_content.borrow_mut() = Some(filename);
558
559 let (x, y) = self.get_mouse_position();
560
561 events.push(MouseEvent { x, y }.to_event());
562 events.push(DropEvent { kind: DROP_TEXT }.to_event())
563 }
564 sdl2::event::Event::KeyUp { scancode, .. } => {
565 if let Some(code) = self.convert_scancode(scancode, shift) {
566 events.push(
567 KeyEvent {
568 character: code.0,
569 scancode: code.1,
570 pressed: false,
571 }
572 .to_event(),
573 );
574 }
575 }
576 sdl2::event::Event::Quit { .. } => events.push(QuitEvent.to_event()),
577 _ => (),
578 }
579
580 events
581 }
582
583 pub fn events(&mut self) -> EventIter {
585 let mut iter = EventIter {
586 events: [Event::new(); 16],
587 i: 0,
588 count: 0,
589 };
590
591 if !self.window_async {
592 let event = unsafe { &mut *EVENT_PUMP }.wait_event();
593 if let sdl2::event::Event::Window { .. } = event {
594 self.sync_path();
595 }
596 for converted_event in self.convert_event(event) {
597 if iter.count < iter.events.len() {
598 iter.events[iter.count] = converted_event;
599 iter.count += 1;
600 } else {
601 break;
602 }
603 }
604 }
605
606 while let Some(event) = unsafe { &mut *EVENT_PUMP }.poll_event() {
607 if let sdl2::event::Event::Window { .. } = event {
608 self.sync_path();
609 }
610 for converted_event in self.convert_event(event) {
611 if iter.count < iter.events.len() {
612 iter.events[iter.count] = converted_event;
613 iter.count += 1;
614 } else {
615 break;
616 }
617 }
618 if iter.count + 2 < iter.events.len() {
619 break;
620 }
621 }
622
623 iter
624 }
625
626 pub fn id(&self) -> u32 {
628 self.inner.window().id()
629 }
630}
631
632pub struct EventIter {
634 events: [Event; 16],
635 i: usize,
636 count: usize,
637}
638
639impl Iterator for EventIter {
640 type Item = Event;
641 fn next(&mut self) -> Option<Event> {
642 if self.i < self.count {
643 if let Some(event) = self.events.get(self.i) {
644 self.i += 1;
645 Some(*event)
646 } else {
647 None
648 }
649 } else {
650 None
651 }
652 }
653}
654
655pub struct Surface {
657 w: u32,
659 h: u32,
661 mode: Cell<Mode>,
663 file_opt: Option<sdl2::surface::Surface<'static>>,
665}
666
667impl Renderer for Surface {
668 fn width(&self) -> u32 {
670 self.w
671 }
672
673 fn height(&self) -> u32 {
675 self.h
676 }
677
678 fn data(&self) -> &[Color] {
680 let raw = self.file().without_lock().unwrap();
681 unsafe {
682 let raw_pixels = core::ptr::from_ref(raw) as *const Color;
683 std::slice::from_raw_parts(raw_pixels, raw.len() / 4)
684 }
685 }
686
687 fn data_mut(&mut self) -> &mut [Color] {
689 let file = self.file_opt.as_mut().unwrap();
690 let raw = file.without_lock_mut().unwrap();
691 unsafe {
692 let raw_pixels = core::ptr::from_mut(raw) as *mut Color;
693 std::slice::from_raw_parts_mut(raw_pixels, raw.len() / 4)
694 }
695 }
696
697 fn sync(&mut self) -> bool {
699 true
700 }
701
702 fn update(&mut self) -> bool {
704 true
705 }
706
707 fn update_rects(&mut self, _rects: &[(i32, i32, u32, u32)]) -> bool {
709 true
710 }
711
712 fn mode(&self) -> &Cell<Mode> {
714 &self.mode
715 }
716}
717
718impl Surface {
719 pub fn new(w: u32, h: u32) -> Option<Self> {
721 Surface::new_flags(w, h, &[])
722 }
723
724 pub fn new_flags(w: u32, h: u32, _flags: &[SurfaceFlag]) -> Option<Self> {
726 let mut surface = Surface {
727 w,
728 h,
729 mode: Cell::new(Mode::Blend),
730 file_opt: None,
731 };
732 unsafe {
733 surface.remap();
734 }
735 if surface.file_opt.is_some() {
736 Some(surface)
737 } else {
738 None
739 }
740 }
741
742 fn file(&self) -> &sdl2::surface::Surface<'static> {
743 self.file_opt.as_ref().unwrap()
744 }
745
746 pub fn set_size(&mut self, width: u32, height: u32) {
748 unsafe {
750 self.unmap();
751 }
752 self.w = width;
753 self.h = height;
754 unsafe {
755 self.remap();
756 }
757 }
758
759 unsafe fn remap(&mut self) {
760 if let Ok(shm) =
761 sdl2::surface::Surface::new(self.w, self.h, sdl2::pixels::PixelFormatEnum::ARGB8888)
762 {
763 self.file_opt = Some(shm)
764 }
765 }
766
767 unsafe fn unmap(&mut self) {
768 self.file_opt.take();
769 }
770}
771
772impl Drop for Surface {
773 fn drop(&mut self) {
774 unsafe {
775 self.unmap();
776 }
777 }
778}
779
780