window.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. use x11::{xlib,xinput2};
  2. use std::ffi::CString;
  3. use std::{mem,ptr};
  4. use std::os::raw::c_int;
  5. pub struct Window {
  6. pub display: *mut xlib::_XDisplay,
  7. pub screen: i32,
  8. pub window: u64,
  9. pub wm_protocols: u64,
  10. pub wm_delete_window: u64,
  11. }
  12. impl Window {
  13. pub fn create() -> Window {
  14. unsafe {
  15. let display = xlib::XOpenDisplay(ptr::null());
  16. let screen = xlib::XDefaultScreen(display);
  17. let window = xlib::XCreateSimpleWindow(
  18. display,
  19. xlib::XRootWindow(display, screen),
  20. 0,
  21. 0,
  22. 3840,
  23. 36,
  24. 1,
  25. xlib::XBlackPixel(display, screen),
  26. xlib::XWhitePixel(display, screen),
  27. );
  28. let wm_protocols = {
  29. let cstr = CString::new("WM_PROTOCOLS").unwrap();
  30. xlib::XInternAtom(display, cstr.as_ptr(), 0)
  31. };
  32. let wm_delete_window = {
  33. let cstr = CString::new("WM_DELETE_WINDOW").unwrap();
  34. xlib::XInternAtom(display, cstr.as_ptr(), 0)
  35. };
  36. Window {
  37. display,
  38. screen,
  39. window,
  40. wm_protocols,
  41. wm_delete_window,
  42. }
  43. }
  44. }
  45. pub fn set_protocols(&mut self) {
  46. let mut protocols = [self.intern("WM_DELETE_WINDOW")];
  47. unsafe {
  48. xlib::XSetWMProtocols(
  49. self.display,
  50. self.window,
  51. protocols.as_mut_ptr(),
  52. protocols.len() as c_int,
  53. );
  54. }
  55. }
  56. pub fn set_title(&mut self, name: &str) {
  57. unsafe {
  58. xlib::XStoreName(
  59. self.display,
  60. self.window,
  61. CString::new(name).unwrap().as_ptr(),
  62. );
  63. }
  64. }
  65. pub fn map(&mut self) {
  66. unsafe {
  67. xlib::XMapWindow(self.display, self.window);
  68. }
  69. }
  70. pub fn intern(&mut self, s: &str) -> u64 {
  71. unsafe {
  72. let cstr = CString::new(s).unwrap();
  73. xlib::XInternAtom(self.display, cstr.as_ptr(), 0)
  74. }
  75. }
  76. pub fn change_property(&mut self, prop: &str, val: &str) {
  77. let prop = self.intern(prop);
  78. let val = self.intern(val);
  79. unsafe {
  80. xlib::XChangeProperty(
  81. self.display,
  82. self.window,
  83. prop,
  84. xlib::XA_ATOM,
  85. 32,
  86. xlib::PropModeReplace,
  87. mem::transmute(&val),
  88. 1,
  89. );
  90. }
  91. }
  92. pub fn get_cairo_surface(&mut self) -> cairo::Surface {
  93. unsafe {
  94. let s = cairo_sys::cairo_xlib_surface_create(
  95. self.display,
  96. self.window,
  97. xlib::XDefaultVisual(self.display, self.screen),
  98. 3840,
  99. 64,
  100. );
  101. cairo::Surface::from_raw_none(s)
  102. }
  103. }
  104. pub fn handle(&mut self) -> Event {
  105. // to find out if we're getting a delete window event
  106. let mut e = unsafe { mem::uninitialized() };
  107. unsafe { xlib::XNextEvent(self.display, &mut e) };
  108. match e.get_type() {
  109. xlib::ClientMessage => {
  110. let xclient: xlib::XClientMessageEvent = From::from(e);
  111. if xclient.message_type == self.wm_protocols && xclient.format == 32 {
  112. let protocol = xclient.data.get_long(0) as xlib::Atom;
  113. if protocol == self.wm_delete_window {
  114. return Event::QuitEvent;
  115. }
  116. }
  117. }
  118. xlib::Expose => return Event::ShowEvent,
  119. xlib::GenericEvent => {
  120. let mut cookie: xlib::XGenericEventCookie = From::from(e);
  121. unsafe { xlib::XGetEventData(self.display, &mut cookie) };
  122. match cookie.evtype {
  123. xinput2::XI_ButtonPress => {
  124. let data: &xinput2::XIDeviceEvent = unsafe { mem::transmute(cookie.data) };
  125. return Event::MouseEvent { x: data.event_x, y: data.event_y };
  126. }
  127. _ => (),
  128. }
  129. }
  130. _ => (),
  131. }
  132. Event::Other
  133. }
  134. pub fn has_events(&mut self) -> bool {
  135. unsafe {
  136. xlib::XPending(self.display) != 0
  137. }
  138. }
  139. pub fn show(&mut self) {
  140. unsafe {
  141. xlib::XClearArea(
  142. self.display,
  143. self.window,
  144. 0,
  145. 0,
  146. 3840,
  147. 36,
  148. 1
  149. );
  150. }
  151. }
  152. pub fn get_fd(&mut self) -> i32 {
  153. unsafe {
  154. xlib::XConnectionNumber(self.display)
  155. }
  156. }
  157. }
  158. impl Drop for Window {
  159. fn drop(&mut self) {
  160. unsafe {
  161. xlib::XCloseDisplay(self.display);
  162. }
  163. }
  164. }
  165. #[derive(Debug)]
  166. pub enum Event {
  167. MouseEvent { x:f64, y: f64 },
  168. ShowEvent,
  169. QuitEvent,
  170. Other,
  171. }
  172. /*
  173. cairo_surface_t *cairo_create_x11_surface0(int x, int y)
  174. {
  175. Display *dsp;
  176. Drawable da;
  177. int screen;
  178. cairo_surface_t *sfc;
  179. if ((dsp = XOpenDisplay(NULL)) == NULL)
  180. exit(1);
  181. screen = DefaultScreen(dsp);
  182. da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp),
  183. 0, 0, x, y, 0, 0, 0);
  184. XSelectInput(dsp, da, ButtonPressMask | KeyPressMask);
  185. XMapWindow(dsp, da);
  186. sfc = cairo_xlib_surface_create(dsp, da,
  187. DefaultVisual(dsp, screen), x, y);
  188. cairo_xlib_surface_set_size(sfc, x, y);
  189. return sfc;
  190. }
  191. */