Skip to content

Commit 876ef31

Browse files
committed
working window top bars (experimental)
1 parent e7e404c commit 876ef31

File tree

1 file changed

+82
-16
lines changed

1 file changed

+82
-16
lines changed

src/gridwm/mod.rs

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
3441
pub 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

Comments
 (0)