gdk/
window.rs

1// Copyright 2013-2015, The Gtk-rs Project Developers.
2// See the COPYRIGHT file at the top-level directory of this distribution.
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5use cairo::{self, Surface};
6use gdk_pixbuf;
7use gdk_sys;
8use glib::object::IsA;
9use glib::translate::*;
10use libc::{c_char, c_int};
11use std::ptr;
12use Cursor;
13use Visual;
14use Window;
15
16use {WindowHints, WindowType, WindowTypeHint, WindowWindowClass};
17
18pub struct WindowAttr {
19    pub title: Option<String>,
20    pub event_mask: i32,
21    pub x: Option<i32>,
22    pub y: Option<i32>,
23    pub width: i32,
24    pub height: i32,
25    pub wclass: WindowWindowClass,
26    pub visual: Option<Visual>,
27    pub window_type: WindowType,
28    pub cursor: Option<Cursor>,
29    pub override_redirect: bool,
30    pub type_hint: Option<WindowTypeHint>,
31}
32
33impl Default for WindowAttr {
34    fn default() -> WindowAttr {
35        skip_assert_initialized!();
36        WindowAttr {
37            title: None,
38            event_mask: 0,
39            x: None,
40            y: None,
41            width: 400,
42            height: 300,
43            wclass: WindowWindowClass::InputOutput,
44            visual: None,
45            window_type: WindowType::Toplevel,
46            cursor: None,
47            override_redirect: false,
48            type_hint: None,
49        }
50    }
51}
52
53impl WindowAttr {
54    fn get_mask(&self) -> u32 {
55        let mut mask: gdk_sys::GdkWindowAttributesType = 0;
56        if self.title.is_some() {
57            mask |= gdk_sys::GDK_WA_TITLE;
58        }
59        if self.x.is_some() {
60            mask |= gdk_sys::GDK_WA_X;
61        }
62        if self.y.is_some() {
63            mask |= gdk_sys::GDK_WA_Y;
64        }
65        if self.cursor.is_some() {
66            mask |= gdk_sys::GDK_WA_CURSOR;
67        }
68        if self.visual.is_some() {
69            mask |= gdk_sys::GDK_WA_VISUAL;
70        }
71        if self.override_redirect {
72            mask |= gdk_sys::GDK_WA_NOREDIR;
73        }
74        if self.type_hint.is_some() {
75            mask |= gdk_sys::GDK_WA_TYPE_HINT;
76        }
77        mask
78    }
79}
80
81#[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
82impl<'a> ToGlibPtr<'a, *mut gdk_sys::GdkWindowAttr> for WindowAttr {
83    type Storage = (
84        Box<gdk_sys::GdkWindowAttr>,
85        Stash<'a, *mut gdk_sys::GdkVisual, Option<Visual>>,
86        Stash<'a, *mut gdk_sys::GdkCursor, Option<Cursor>>,
87        Stash<'a, *const c_char, Option<String>>,
88    );
89
90    fn to_glib_none(&'a self) -> Stash<'a, *mut gdk_sys::GdkWindowAttr, Self> {
91        let title = self.title.to_glib_none();
92        let visual = self.visual.to_glib_none();
93        let cursor = self.cursor.to_glib_none();
94
95        let mut attrs = Box::new(gdk_sys::GdkWindowAttr {
96            title: title.0 as *mut c_char,
97            event_mask: self.event_mask,
98            x: self.x.unwrap_or(0),
99            y: self.y.unwrap_or(0),
100            width: self.width,
101            height: self.height,
102            wclass: self.wclass.to_glib(),
103            visual: visual.0,
104            window_type: self.window_type.to_glib(),
105            cursor: cursor.0,
106            wmclass_name: ptr::null_mut(),
107            wmclass_class: ptr::null_mut(),
108            override_redirect: self.override_redirect.to_glib(),
109            type_hint: self.type_hint.unwrap_or(WindowTypeHint::Normal).to_glib(),
110        });
111
112        Stash(&mut *attrs, (attrs, visual, cursor, title))
113    }
114}
115
116impl Window {
117    pub fn new(parent: Option<&Window>, attributes: &WindowAttr) -> Window {
118        assert_initialized_main_thread!();
119        unsafe {
120            from_glib_full(gdk_sys::gdk_window_new(
121                parent.to_glib_none().0,
122                attributes.to_glib_none().0,
123                attributes.get_mask() as c_int,
124            ))
125        }
126    }
127
128    pub fn create_similar_surface(
129        &self,
130        content: cairo::Content,
131        width: i32,
132        height: i32,
133    ) -> Option<Surface> {
134        unsafe {
135            from_glib_full(gdk_sys::gdk_window_create_similar_surface(
136                self.to_glib_none().0,
137                content.into(),
138                width,
139                height,
140            ))
141        }
142    }
143}
144
145pub trait WindowExtManual: 'static {
146    unsafe fn set_user_data<T>(&self, user_data: &mut T);
147
148    #[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref))]
149    unsafe fn get_user_data<T>(&self) -> &mut T;
150
151    fn set_geometry_hints(&self, geometry: &gdk_sys::GdkGeometry, geom_mask: WindowHints);
152
153    fn get_default_root_window() -> Window;
154
155    fn offscreen_window_set_embedder(&self, embedder: &Window);
156
157    fn offscreen_window_get_embedder(&self) -> Option<Window>;
158
159    fn offscreen_window_get_surface(&self) -> Option<Surface>;
160
161    fn get_pixbuf(
162        &self,
163        src_x: i32,
164        src_y: i32,
165        width: i32,
166        height: i32,
167    ) -> Option<gdk_pixbuf::Pixbuf>;
168
169    fn get_background_pattern(&self) -> Option<cairo::Pattern>;
170
171    fn set_background_pattern(&self, pattern: Option<&cairo::Pattern>);
172}
173
174impl<O: IsA<Window>> WindowExtManual for O {
175    unsafe fn set_user_data<T>(&self, user_data: &mut T) {
176        gdk_sys::gdk_window_set_user_data(
177            self.as_ref().to_glib_none().0,
178            user_data as *mut T as *mut _,
179        )
180    }
181
182    unsafe fn get_user_data<T>(&self) -> &mut T {
183        let mut pointer = ::std::ptr::null_mut();
184        gdk_sys::gdk_window_get_user_data(self.as_ref().to_glib_none().0, &mut pointer);
185        &mut *(pointer as *mut T)
186    }
187
188    fn set_geometry_hints(&self, geometry: &gdk_sys::GdkGeometry, geom_mask: WindowHints) {
189        unsafe {
190            gdk_sys::gdk_window_set_geometry_hints(
191                self.as_ref().to_glib_none().0,
192                geometry,
193                geom_mask.to_glib(),
194            )
195        }
196    }
197
198    fn get_default_root_window() -> Window {
199        assert_initialized_main_thread!();
200        unsafe { from_glib_none(gdk_sys::gdk_get_default_root_window()) }
201    }
202
203    fn offscreen_window_set_embedder(&self, embedder: &Window) {
204        unsafe {
205            gdk_sys::gdk_offscreen_window_set_embedder(
206                self.as_ref().to_glib_none().0,
207                embedder.to_glib_none().0,
208            )
209        }
210    }
211
212    fn offscreen_window_get_embedder(&self) -> Option<Window> {
213        unsafe {
214            from_glib_none(gdk_sys::gdk_offscreen_window_get_embedder(
215                self.as_ref().to_glib_none().0,
216            ))
217        }
218    }
219
220    fn offscreen_window_get_surface(&self) -> Option<Surface> {
221        skip_assert_initialized!();
222        unsafe {
223            from_glib_none(gdk_sys::gdk_offscreen_window_get_surface(
224                self.as_ref().to_glib_none().0,
225            ))
226        }
227    }
228
229    fn get_pixbuf(
230        &self,
231        src_x: i32,
232        src_y: i32,
233        width: i32,
234        height: i32,
235    ) -> Option<gdk_pixbuf::Pixbuf> {
236        skip_assert_initialized!();
237        unsafe {
238            from_glib_full(gdk_sys::gdk_pixbuf_get_from_window(
239                self.as_ref().to_glib_none().0,
240                src_x,
241                src_y,
242                width,
243                height,
244            ))
245        }
246    }
247
248    fn get_background_pattern(&self) -> Option<cairo::Pattern> {
249        unsafe {
250            let ret = gdk_sys::gdk_window_get_background_pattern(self.as_ref().to_glib_none().0);
251            if ret.is_null() {
252                None
253            } else {
254                Some(cairo::Pattern::from_raw_none(ret))
255            }
256        }
257    }
258
259    fn set_background_pattern(&self, pattern: Option<&cairo::Pattern>) {
260        unsafe {
261            let ptr = if let Some(pattern) = pattern {
262                pattern.to_raw_none()
263            } else {
264                ::std::ptr::null_mut()
265            };
266            gdk_sys::gdk_window_set_background_pattern(self.as_ref().to_glib_none().0, ptr);
267        }
268    }
269}