@@ -31,6 +31,13 @@ use x11::{
3131 } ,
3232} ;
3333
34+ unsafe extern "C" fn x_error_handler (
35+ _display : * mut xlib:: Display ,
36+ _event : * mut xlib:: XErrorEvent ,
37+ ) -> i32 {
38+ 0
39+ }
40+
3441pub struct GridWM {
3542 display : * mut xlib:: Display ,
3643 config : Config ,
@@ -161,6 +168,10 @@ impl GridWM {
161168 }
162169 }
163170
171+ unsafe {
172+ xlib:: XSetErrorHandler ( Some ( x_error_handler) ) ;
173+ }
174+
164175 // set keyboard layout
165176 if !self . config . keyboard . layout . is_empty ( ) {
166177 match Command :: new ( "setxkbmap" )
@@ -628,7 +639,12 @@ impl GridWM {
628639 desktop. remove ( & event. window ) ;
629640 self . set_desktop ( self . current_desktop , desktop) ;
630641 self . floating_windows . remove ( & event. window ) ;
631- self . win_bar_windows . remove ( & event. window ) ;
642+
643+ if let Some ( bar_win) = self . win_bar_windows . remove ( & event. window ) {
644+ unsafe {
645+ xlib:: XDestroyWindow ( self . display , bar_win) ;
646+ }
647+ }
632648 }
633649
634650 fn move_window ( & self , window : Window , x : i32 , y : i32 ) {
@@ -784,6 +800,9 @@ impl GridWM {
784800 xlib:: CurrentTime ,
785801 ) ;
786802 xlib:: XRaiseWindow ( self . display , clicked_win) ;
803+ if let Some ( & bar_win) = self . win_bar_windows . get ( & clicked_win) {
804+ xlib:: XRaiseWindow ( self . display , bar_win) ;
805+ }
787806 }
788807 }
789808 unsafe {
@@ -796,10 +815,19 @@ impl GridWM {
796815 return ;
797816 }
798817 unsafe {
799- for window in self . get_desktop ( self . current_desktop ) {
818+ let old_desktop = self . get_desktop ( self . current_desktop ) ;
819+
820+ for window in & old_desktop {
821+ if let Some ( bar_win) = self . win_bar_windows . remove ( window) {
822+ xlib:: XDestroyWindow ( self . display , bar_win) ;
823+ }
824+ }
825+
826+ for window in old_desktop {
800827 xlib:: XUnmapWindow ( self . display , window) ;
801828 xlib:: XUnmapSubwindows ( self . display , window) ;
802829 }
830+
803831 for window in self . get_desktop ( index) {
804832 xlib:: XMapWindow ( self . display , window) ;
805833 xlib:: XMapSubwindows ( self . display , window) ;
@@ -816,6 +844,7 @@ impl GridWM {
816844 let valid_windows: HashSet < Window > = desktop. iter ( ) . copied ( ) . collect ( ) ;
817845 self . win_bar_windows . retain ( |parent_win, bar_win| {
818846 if !valid_windows. contains ( parent_win) {
847+ xlib:: XDestroyWindow ( self . display , * bar_win) ;
819848 false
820849 } else {
821850 let mut attrs = std:: mem:: zeroed ( ) ;
@@ -825,22 +854,37 @@ impl GridWM {
825854 } ) ;
826855
827856 for window in & desktop {
857+ if self
858+ . win_bar_windows
859+ . values ( )
860+ . any ( |& bar_win| bar_win == * window)
861+ {
862+ continue ;
863+ }
864+
865+ let mut check_attrs: XWindowAttributes = std:: mem:: zeroed ( ) ;
866+ if xlib:: XGetWindowAttributes ( self . display , * window, & mut check_attrs) == 0 {
867+ continue ;
868+ }
869+
828870 if !self . is_tileable ( * window) {
829871 continue ;
830872 }
831873
832874 let attrs = self . get_window_attributes ( * window) ;
875+ let root = XDefaultRootWindow ( self . display ) ;
833876
834877 // create or get bar window
835- let bar_window = if let Some ( & bar_win) = self . win_bar_windows . get ( window) {
836- bar_win
878+ let ( bar_window, is_new) = if let Some ( & bar_win) = self . win_bar_windows . get ( window)
879+ {
880+ ( bar_win, false )
837881 } else {
838- // create a new child window for the bar
882+ // create a new window for the bar
839883 let bar_win = xlib:: XCreateSimpleWindow (
840884 self . display ,
841- * window ,
842- 0 ,
843- - ( self . config . window . window_bar_height as i32 ) ,
885+ root ,
886+ attrs . x ,
887+ attrs . y - ( self . config . window . window_bar_height as i32 ) ,
844888 attrs. width as u32 ,
845889 self . config . window . window_bar_height ,
846890 0 ,
@@ -849,19 +893,23 @@ impl GridWM {
849893 ) ;
850894 xlib:: XMapWindow ( self . display , bar_win) ;
851895 self . win_bar_windows . insert ( * window, bar_win) ;
852- bar_win
896+ ( bar_win, true )
853897 } ;
854898
855899 // resize bar window if parent window size changed
856900 xlib:: XMoveResizeWindow (
857901 self . display ,
858902 bar_window,
859- 0 ,
860- - ( self . config . window . window_bar_height as i32 ) ,
903+ attrs . x ,
904+ attrs . y - ( self . config . window . window_bar_height as i32 ) ,
861905 attrs. width as u32 ,
862906 self . config . window . window_bar_height ,
863907 ) ;
864908
909+ if is_new {
910+ xlib:: XRaiseWindow ( self . display , bar_window) ;
911+ }
912+
865913 let win_name = self . get_name ( * window) . unwrap_or_default ( ) ;
866914 let win_name_c = match CString :: new ( win_name) {
867915 Ok ( name) => name,
@@ -873,7 +921,7 @@ impl GridWM {
873921 bar_window,
874922 self . win_bar_background_gc ,
875923 0 ,
876- - ( self . config . window . window_bar_height as i32 ) ,
924+ 0 ,
877925 attrs. width as u32 ,
878926 self . config . window . window_bar_height ,
879927 ) ;
@@ -885,7 +933,7 @@ impl GridWM {
885933 bar_window,
886934 self . win_bar_gc ,
887935 5 ,
888- - ( self . config . window . window_bar_height as i32 ) + text_offset,
936+ text_offset,
889937 win_name_c. as_ptr ( ) ,
890938 win_name_c. to_bytes ( ) . len ( ) as i32 ,
891939 ) ;
@@ -945,7 +993,14 @@ impl GridWM {
945993 let tileable: Vec < Window > = desktop
946994 . iter ( )
947995 . copied ( )
948- . filter ( |& w| self . is_tileable ( w) && !self . floating_windows . contains ( & w) )
996+ . filter ( |& w| {
997+ if !self . is_tileable ( w) || self . floating_windows . contains ( & w) {
998+ return false ;
999+ }
1000+ // check if still exists
1001+ let mut attrs: XWindowAttributes = unsafe { std:: mem:: zeroed ( ) } ;
1002+ unsafe { xlib:: XGetWindowAttributes ( self . display , w, & mut attrs) != 0 }
1003+ } )
9491004 . collect ( ) ;
9501005
9511006 if tileable. is_empty ( ) {
@@ -1183,11 +1238,22 @@ impl GridWM {
11831238
11841239 fn handle_drag_start ( & mut self , event : xlib:: XButtonEvent ) {
11851240 if event. subwindow == 0 {
1241+ // allow events
1242+ unsafe {
1243+ xlib:: XAllowEvents ( self . display , xlib:: ReplayPointer , xlib:: CurrentTime ) ;
1244+ }
11861245 return ;
11871246 }
11881247
1189- // use toplevel window instead of child subwindow
1190- let win = self . get_toplevel ( event. subwindow ) ;
1248+ let win = if let Some ( ( & parent_win, _) ) = self
1249+ . win_bar_windows
1250+ . iter ( )
1251+ . find ( |( _, bar_win) | * * bar_win == event. subwindow )
1252+ {
1253+ parent_win
1254+ } else {
1255+ self . get_toplevel ( event. subwindow )
1256+ } ;
11911257
11921258 self . floating_windows . insert ( win) ;
11931259
0 commit comments