1use crate::{ffi, GLContext, GLDisplay};
7use glib::{
8    object::ObjectType as _,
9    prelude::*,
10    signal::{connect_raw, SignalHandlerId},
11    translate::*,
12};
13use std::boxed::Box as Box_;
14
15glib::wrapper! {
16    #[doc(alias = "GstGLWindow")]
64    pub struct GLWindow(Object<ffi::GstGLWindow, ffi::GstGLWindowClass>) @extends gst::Object;
65
66    match fn {
67        type_ => || ffi::gst_gl_window_get_type(),
68    }
69}
70
71impl GLWindow {
72    pub const NONE: Option<&'static GLWindow> = None;
73
74    #[doc(alias = "gst_gl_window_new")]
81    pub fn new(display: &impl IsA<GLDisplay>) -> GLWindow {
82        skip_assert_initialized!();
83        unsafe { from_glib_full(ffi::gst_gl_window_new(display.as_ref().to_glib_none().0)) }
84    }
85}
86
87unsafe impl Send for GLWindow {}
88unsafe impl Sync for GLWindow {}
89
90pub trait GLWindowExt: IsA<GLWindow> + 'static {
96    #[cfg(feature = "v1_16")]
102    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
103    #[doc(alias = "gst_gl_window_controls_viewport")]
104    fn controls_viewport(&self) -> bool {
105        unsafe {
106            from_glib(ffi::gst_gl_window_controls_viewport(
107                self.as_ref().to_glib_none().0,
108            ))
109        }
110    }
111
112    #[doc(alias = "gst_gl_window_draw")]
114    fn draw(&self) {
115        unsafe {
116            ffi::gst_gl_window_draw(self.as_ref().to_glib_none().0);
117        }
118    }
119
120    #[doc(alias = "gst_gl_window_get_context")]
125    #[doc(alias = "get_context")]
126    fn context(&self) -> GLContext {
127        unsafe {
128            from_glib_full(ffi::gst_gl_window_get_context(
129                self.as_ref().to_glib_none().0,
130            ))
131        }
132    }
133
134    #[cfg(feature = "v1_28")]
139    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
140    #[doc(alias = "gst_gl_window_get_request_output_surface")]
141    #[doc(alias = "get_request_output_surface")]
142    fn is_request_output_surface(&self) -> bool {
143        unsafe {
144            from_glib(ffi::gst_gl_window_get_request_output_surface(
145                self.as_ref().to_glib_none().0,
146            ))
147        }
148    }
149
150    #[doc(alias = "gst_gl_window_get_surface_dimensions")]
160    #[doc(alias = "get_surface_dimensions")]
161    fn surface_dimensions(&self) -> (u32, u32) {
162        unsafe {
163            let mut width = std::mem::MaybeUninit::uninit();
164            let mut height = std::mem::MaybeUninit::uninit();
165            ffi::gst_gl_window_get_surface_dimensions(
166                self.as_ref().to_glib_none().0,
167                width.as_mut_ptr(),
168                height.as_mut_ptr(),
169            );
170            (width.assume_init(), height.assume_init())
171        }
172    }
173
174    #[doc(alias = "gst_gl_window_handle_events")]
182    fn handle_events(&self, handle_events: bool) {
183        unsafe {
184            ffi::gst_gl_window_handle_events(
185                self.as_ref().to_glib_none().0,
186                handle_events.into_glib(),
187            );
188        }
189    }
190
191    #[cfg(feature = "v1_18")]
197    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
198    #[doc(alias = "gst_gl_window_has_output_surface")]
199    fn has_output_surface(&self) -> bool {
200        unsafe {
201            from_glib(ffi::gst_gl_window_has_output_surface(
202                self.as_ref().to_glib_none().0,
203            ))
204        }
205    }
206
207    #[doc(alias = "gst_gl_window_queue_resize")]
209    fn queue_resize(&self) {
210        unsafe {
211            ffi::gst_gl_window_queue_resize(self.as_ref().to_glib_none().0);
212        }
213    }
214
215    #[doc(alias = "gst_gl_window_quit")]
217    fn quit(&self) {
218        unsafe {
219            ffi::gst_gl_window_quit(self.as_ref().to_glib_none().0);
220        }
221    }
222
223    #[doc(alias = "gst_gl_window_resize")]
229    fn resize(&self, width: u32, height: u32) {
230        unsafe {
231            ffi::gst_gl_window_resize(self.as_ref().to_glib_none().0, width, height);
232        }
233    }
234
235    #[doc(alias = "gst_gl_window_run")]
237    fn run(&self) {
238        unsafe {
239            ffi::gst_gl_window_run(self.as_ref().to_glib_none().0);
240        }
241    }
242
243    #[doc(alias = "gst_gl_window_send_key_event")]
244    fn send_key_event(&self, event_type: &str, key_str: &str) {
245        unsafe {
246            ffi::gst_gl_window_send_key_event(
247                self.as_ref().to_glib_none().0,
248                event_type.to_glib_none().0,
249                key_str.to_glib_none().0,
250            );
251        }
252    }
253
254    #[doc(alias = "gst_gl_window_send_mouse_event")]
255    fn send_mouse_event(&self, event_type: &str, button: i32, posx: f64, posy: f64) {
256        unsafe {
257            ffi::gst_gl_window_send_mouse_event(
258                self.as_ref().to_glib_none().0,
259                event_type.to_glib_none().0,
260                button,
261                posx,
262                posy,
263            );
264        }
265    }
266
267    #[cfg(feature = "v1_18")]
278    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
279    #[doc(alias = "gst_gl_window_send_scroll_event")]
280    fn send_scroll_event(&self, posx: f64, posy: f64, delta_x: f64, delta_y: f64) {
281        unsafe {
282            ffi::gst_gl_window_send_scroll_event(
283                self.as_ref().to_glib_none().0,
284                posx,
285                posy,
286                delta_x,
287                delta_y,
288            );
289        }
290    }
291
292    #[doc(alias = "gst_gl_window_set_preferred_size")]
299    fn set_preferred_size(&self, width: i32, height: i32) {
300        unsafe {
301            ffi::gst_gl_window_set_preferred_size(self.as_ref().to_glib_none().0, width, height);
302        }
303    }
304
305    #[doc(alias = "gst_gl_window_set_render_rectangle")]
320    fn set_render_rectangle(
321        &self,
322        x: i32,
323        y: i32,
324        width: i32,
325        height: i32,
326    ) -> Result<(), glib::error::BoolError> {
327        unsafe {
328            glib::result_from_gboolean!(
329                ffi::gst_gl_window_set_render_rectangle(
330                    self.as_ref().to_glib_none().0,
331                    x,
332                    y,
333                    width,
334                    height
335                ),
336                "Failed to set the specified region"
337            )
338        }
339    }
340
341    #[cfg(feature = "v1_28")]
345    #[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
346    #[doc(alias = "gst_gl_window_set_request_output_surface")]
347    fn set_request_output_surface(&self, output_surface: bool) {
348        unsafe {
349            ffi::gst_gl_window_set_request_output_surface(
350                self.as_ref().to_glib_none().0,
351                output_surface.into_glib(),
352            );
353        }
354    }
355
356    #[doc(alias = "gst_gl_window_show")]
358    fn show(&self) {
359        unsafe {
360            ffi::gst_gl_window_show(self.as_ref().to_glib_none().0);
361        }
362    }
363
364    #[doc(alias = "key-event")]
370    fn connect_key_event<F: Fn(&Self, &str, &str) + Send + Sync + 'static>(
371        &self,
372        f: F,
373    ) -> SignalHandlerId {
374        unsafe extern "C" fn key_event_trampoline<
375            P: IsA<GLWindow>,
376            F: Fn(&P, &str, &str) + Send + Sync + 'static,
377        >(
378            this: *mut ffi::GstGLWindow,
379            id: *mut std::ffi::c_char,
380            key: *mut std::ffi::c_char,
381            f: glib::ffi::gpointer,
382        ) {
383            let f: &F = &*(f as *const F);
384            f(
385                GLWindow::from_glib_borrow(this).unsafe_cast_ref(),
386                &glib::GString::from_glib_borrow(id),
387                &glib::GString::from_glib_borrow(key),
388            )
389        }
390        unsafe {
391            let f: Box_<F> = Box_::new(f);
392            connect_raw(
393                self.as_ptr() as *mut _,
394                c"key-event".as_ptr() as *const _,
395                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
396                    key_event_trampoline::<Self, F> as *const (),
397                )),
398                Box_::into_raw(f),
399            )
400        }
401    }
402
403    #[doc(alias = "mouse-event")]
413    fn connect_mouse_event<F: Fn(&Self, &str, i32, f64, f64) + Send + Sync + 'static>(
414        &self,
415        f: F,
416    ) -> SignalHandlerId {
417        unsafe extern "C" fn mouse_event_trampoline<
418            P: IsA<GLWindow>,
419            F: Fn(&P, &str, i32, f64, f64) + Send + Sync + 'static,
420        >(
421            this: *mut ffi::GstGLWindow,
422            id: *mut std::ffi::c_char,
423            button: std::ffi::c_int,
424            x: std::ffi::c_double,
425            y: std::ffi::c_double,
426            f: glib::ffi::gpointer,
427        ) {
428            let f: &F = &*(f as *const F);
429            f(
430                GLWindow::from_glib_borrow(this).unsafe_cast_ref(),
431                &glib::GString::from_glib_borrow(id),
432                button,
433                x,
434                y,
435            )
436        }
437        unsafe {
438            let f: Box_<F> = Box_::new(f);
439            connect_raw(
440                self.as_ptr() as *mut _,
441                c"mouse-event".as_ptr() as *const _,
442                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
443                    mouse_event_trampoline::<Self, F> as *const (),
444                )),
445                Box_::into_raw(f),
446            )
447        }
448    }
449
450    #[cfg(feature = "v1_18")]
460    #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
461    #[doc(alias = "scroll-event")]
462    fn connect_scroll_event<F: Fn(&Self, f64, f64, f64, f64) + Send + Sync + 'static>(
463        &self,
464        f: F,
465    ) -> SignalHandlerId {
466        unsafe extern "C" fn scroll_event_trampoline<
467            P: IsA<GLWindow>,
468            F: Fn(&P, f64, f64, f64, f64) + Send + Sync + 'static,
469        >(
470            this: *mut ffi::GstGLWindow,
471            x: std::ffi::c_double,
472            y: std::ffi::c_double,
473            delta_x: std::ffi::c_double,
474            delta_y: std::ffi::c_double,
475            f: glib::ffi::gpointer,
476        ) {
477            let f: &F = &*(f as *const F);
478            f(
479                GLWindow::from_glib_borrow(this).unsafe_cast_ref(),
480                x,
481                y,
482                delta_x,
483                delta_y,
484            )
485        }
486        unsafe {
487            let f: Box_<F> = Box_::new(f);
488            connect_raw(
489                self.as_ptr() as *mut _,
490                c"scroll-event".as_ptr() as *const _,
491                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
492                    scroll_event_trampoline::<Self, F> as *const (),
493                )),
494                Box_::into_raw(f),
495            )
496        }
497    }
498
499    #[cfg(feature = "v1_20")]
504    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
505    #[doc(alias = "window-handle-changed")]
506    fn connect_window_handle_changed<F: Fn(&Self) + Send + Sync + 'static>(
507        &self,
508        f: F,
509    ) -> SignalHandlerId {
510        unsafe extern "C" fn window_handle_changed_trampoline<
511            P: IsA<GLWindow>,
512            F: Fn(&P) + Send + Sync + 'static,
513        >(
514            this: *mut ffi::GstGLWindow,
515            f: glib::ffi::gpointer,
516        ) {
517            let f: &F = &*(f as *const F);
518            f(GLWindow::from_glib_borrow(this).unsafe_cast_ref())
519        }
520        unsafe {
521            let f: Box_<F> = Box_::new(f);
522            connect_raw(
523                self.as_ptr() as *mut _,
524                c"window-handle-changed".as_ptr() as *const _,
525                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
526                    window_handle_changed_trampoline::<Self, F> as *const (),
527                )),
528                Box_::into_raw(f),
529            )
530        }
531    }
532}
533
534impl<O: IsA<GLWindow>> GLWindowExt for O {}