@@ -17,6 +17,10 @@ use processing_input::{
1717} ;
1818use processing_render:: surface:: { MonitorWorkarea , WindowControls } ;
1919
20+ fn is_wayland ( glfw : & Glfw ) -> bool {
21+ cfg ! ( target_os = "linux" ) && glfw. get_platform ( ) == glfw:: Platform :: Wayland
22+ }
23+
2024/// A single GLFW instance drives every window (GLFW's event pump is global). The
2125/// main window is `windows[0]`; `create_window` appends more.
2226pub struct GlfwContext {
@@ -96,30 +100,33 @@ impl GlfwContext {
96100
97101 // Set _NET_WM_WINDOW_TYPE_DIALOG so tiling WMs (i3, sway) float the window
98102 #[ cfg( all( target_os = "linux" , feature = "x11" ) ) ]
99- unsafe {
103+ if glfw . get_platform ( ) == glfw :: Platform :: X11 {
100104 use std:: ffi:: CString ;
101- let display = window. glfw . get_x11_display ( ) as * mut x11:: xlib:: Display ;
102- let xwindow = window. get_x11_window ( ) as x11:: xlib:: Window ;
103- let net_wm_window_type = x11:: xlib:: XInternAtom (
104- display,
105- CString :: new ( "_NET_WM_WINDOW_TYPE" ) . unwrap ( ) . as_ptr ( ) ,
106- 0 ,
107- ) ;
108- let net_wm_window_type_dialog = x11:: xlib:: XInternAtom (
109- display,
110- CString :: new ( "_NET_WM_WINDOW_TYPE_DIALOG" ) . unwrap ( ) . as_ptr ( ) ,
111- 0 ,
112- ) ;
113- x11:: xlib:: XChangeProperty (
114- display,
115- xwindow,
116- net_wm_window_type,
117- x11:: xlib:: XA_ATOM ,
118- 32 ,
119- x11:: xlib:: PropModeReplace ,
120- & net_wm_window_type_dialog as * const _ as * const u8 ,
121- 1 ,
122- ) ;
105+ // SAFETY: GLFW is on X11, so the display and window handles are live Xlib objects.
106+ unsafe {
107+ let display = window. glfw . get_x11_display ( ) as * mut x11:: xlib:: Display ;
108+ let xwindow = window. get_x11_window ( ) as x11:: xlib:: Window ;
109+ let net_wm_window_type = x11:: xlib:: XInternAtom (
110+ display,
111+ CString :: new ( "_NET_WM_WINDOW_TYPE" ) . unwrap ( ) . as_ptr ( ) ,
112+ 0 ,
113+ ) ;
114+ let net_wm_window_type_dialog = x11:: xlib:: XInternAtom (
115+ display,
116+ CString :: new ( "_NET_WM_WINDOW_TYPE_DIALOG" ) . unwrap ( ) . as_ptr ( ) ,
117+ 0 ,
118+ ) ;
119+ x11:: xlib:: XChangeProperty (
120+ display,
121+ xwindow,
122+ net_wm_window_type,
123+ x11:: xlib:: XA_ATOM ,
124+ 32 ,
125+ x11:: xlib:: PropModeReplace ,
126+ & net_wm_window_type_dialog as * const _ as * const u8 ,
127+ 1 ,
128+ ) ;
129+ }
123130 }
124131
125132 window. show ( ) ;
@@ -275,19 +282,41 @@ impl GlfwContext {
275282 let handle = self . windows [ idx] . window . get_win32_window ( ) as u64 ;
276283 surface_create_windows ( handle, width, height, scale_factor, transparent) ?
277284 } ;
278- #[ cfg( all( target_os = "linux" , feature = "wayland" ) ) ]
279- let entity = {
280- use processing_render:: surface_create_wayland;
281- let wh = self . windows [ idx] . window . get_wayland_window ( ) as u64 ;
282- let dh = self . glfw . get_wayland_display ( ) as u64 ;
283- surface_create_wayland ( wh, dh, width, height, scale_factor, transparent) ?
284- } ;
285- #[ cfg( all( target_os = "linux" , feature = "x11" , not( feature = "wayland" ) ) ) ]
286- let entity = {
287- use processing_render:: surface_create_x11;
288- let wh = self . windows [ idx] . window . get_x11_window ( ) as u64 ;
289- let dh = self . glfw . get_x11_display ( ) as u64 ;
290- surface_create_x11 ( wh, dh, width, height, scale_factor, transparent) ?
285+ #[ cfg( target_os = "linux" ) ]
286+ let entity = match self . glfw . get_platform ( ) {
287+ #[ cfg( feature = "wayland" ) ]
288+ glfw:: Platform :: Wayland => {
289+ let wh = self . windows [ idx] . window . get_wayland_window ( ) as u64 ;
290+ let dh = self . glfw . get_wayland_display ( ) as u64 ;
291+ processing_render:: surface_create_wayland (
292+ wh,
293+ dh,
294+ width,
295+ height,
296+ scale_factor,
297+ transparent,
298+ ) ?
299+ }
300+ #[ cfg( feature = "x11" ) ]
301+ glfw:: Platform :: X11 => {
302+ let wh = self . windows [ idx] . window . get_x11_window ( ) as u64 ;
303+ let dh = self . glfw . get_x11_display ( ) as u64 ;
304+ processing_render:: surface_create_x11 (
305+ wh,
306+ dh,
307+ width,
308+ height,
309+ scale_factor,
310+ transparent,
311+ ) ?
312+ }
313+ platform => {
314+ return Err ( processing_core:: error:: ProcessingError :: InvalidArgument (
315+ format ! (
316+ "GLFW is running on {platform:?}, which this build doesn't support; enable the matching `x11`/`wayland` feature"
317+ ) ,
318+ ) ) ;
319+ }
291320 } ;
292321
293322 self . windows [ idx] . surface = Some ( entity) ;
@@ -438,8 +467,7 @@ impl ManagedWindow {
438467 if desired. maximize {
439468 self . window . maximize ( ) ;
440469 }
441- #[ cfg( not( all( target_os = "linux" , feature = "wayland" ) ) ) ]
442- if desired. focus {
470+ if desired. focus && !is_wayland ( glfw) {
443471 self . window . focus ( ) ;
444472 }
445473
@@ -463,28 +491,25 @@ impl ManagedWindow {
463491 self . last_applied . size = bevy:: math:: UVec2 :: new ( w. max ( 0 ) as u32 , h. max ( 0 ) as u32 ) ;
464492 }
465493
466- #[ cfg( not( feature = "wayland" ) ) ]
467494 fn frame_pos ( & self ) -> IVec2 {
495+ if is_wayland ( & self . window . glfw ) {
496+ return self . last_applied . position ;
497+ }
468498 let ( cx, cy) = self . window . get_pos ( ) ;
469499 let ( inset_l, inset_t, _, _) = self . window . get_frame_size ( ) ;
470500 IVec2 :: new ( cx - inset_l, cy - inset_t)
471501 }
472502
473- #[ cfg( feature = "wayland" ) ]
474- fn frame_pos ( & self ) -> IVec2 {
475- self . last_applied . position
476- }
477-
478503 fn apply_window ( & mut self , glfw : & mut Glfw , desired : & DesiredWindow ) {
479504 let last = & mut self . last_applied ;
480505
481506 if desired. title != last. title {
482507 self . window . set_title ( & desired. title ) ;
483508 last. title . clone_from ( & desired. title ) ;
484509 }
485- #[ cfg( not( feature = "wayland" ) ) ]
486510 if let Some ( pos) = desired. position
487511 && pos != last. position
512+ && !is_wayland ( glfw)
488513 {
489514 let ( inset_l, inset_t, _, _) = self . window . get_frame_size ( ) ;
490515 self . window . set_pos ( pos. x + inset_l, pos. y + inset_t) ;
@@ -512,16 +537,18 @@ impl ManagedWindow {
512537 last. decorations = desired. decorations ;
513538 }
514539 if desired. window_level != last. window_level {
515- #[ cfg( not( all( target_os = "linux" , feature = "wayland" ) ) ) ]
516- self . window
517- . set_floating ( matches ! ( desired. window_level, BevyWindowLevel :: AlwaysOnTop ) ) ;
540+ if !is_wayland ( glfw) {
541+ self . window
542+ . set_floating ( matches ! ( desired. window_level, BevyWindowLevel :: AlwaysOnTop ) ) ;
543+ }
518544 last. window_level = desired. window_level ;
519545 }
520546 if let Some ( opacity) = desired. opacity
521547 && ( opacity - last. opacity ) . abs ( ) > f32:: EPSILON
522548 {
523- #[ cfg( not( all( target_os = "linux" , feature = "wayland" ) ) ) ]
524- self . window . set_opacity ( opacity) ;
549+ if !is_wayland ( glfw) {
550+ self . window . set_opacity ( opacity) ;
551+ }
525552 last. opacity = opacity;
526553 }
527554 if desired. fullscreen_on != last. fullscreen_on {
@@ -590,7 +617,6 @@ impl ManagedWindow {
590617#[ derive( Clone , Debug ) ]
591618struct DesiredWindow {
592619 title : String ,
593- #[ cfg( not( feature = "wayland" ) ) ]
594620 position : Option < IVec2 > ,
595621 size : bevy:: math:: UVec2 ,
596622 visible : bool ,
@@ -602,7 +628,6 @@ struct DesiredWindow {
602628 iconify : bool ,
603629 restore : bool ,
604630 maximize : bool ,
605- #[ cfg( not( all( target_os = "linux" , feature = "wayland" ) ) ) ]
606631 focus : bool ,
607632}
608633
@@ -624,7 +649,6 @@ fn read_desired_window(surface: Entity) -> Option<DesiredWindow> {
624649 } ;
625650 Ok ( Some ( DesiredWindow {
626651 title : window. title . clone ( ) ,
627- #[ cfg( not( feature = "wayland" ) ) ]
628652 position : match window. position {
629653 WindowPosition :: At ( p) => Some ( p) ,
630654 _ => None ,
@@ -642,7 +666,6 @@ fn read_desired_window(surface: Entity) -> Option<DesiredWindow> {
642666 iconify : controls. pending_iconify ,
643667 restore : controls. pending_restore ,
644668 maximize : controls. pending_maximize ,
645- #[ cfg( not( all( target_os = "linux" , feature = "wayland" ) ) ) ]
646669 focus : controls. pending_focus ,
647670 } ) )
648671 } )
0 commit comments