@@ -86,6 +86,49 @@ impl ResizeEdge {
}
}
+#[derive(Debug)]
+struct EdgeConstraints {
+ top_tiled: bool,
+ #[allow(dead_code)]
+ top_resizable: bool,
+
+ right_tiled: bool,
+ #[allow(dead_code)]
+ right_resizable: bool,
+
+ bottom_tiled: bool,
+ #[allow(dead_code)]
+ bottom_resizable: bool,
+
+ left_tiled: bool,
+ #[allow(dead_code)]
+ left_resizable: bool,
+}
+
+impl EdgeConstraints {
+ fn from_atom(atom: u32) -> Self {
+ EdgeConstraints {
+ top_tiled: (atom & (1 << 0)) != 0,
+ top_resizable: (atom & (1 << 1)) != 0,
+ right_tiled: (atom & (1 << 2)) != 0,
+ right_resizable: (atom & (1 << 3)) != 0,
+ bottom_tiled: (atom & (1 << 4)) != 0,
+ bottom_resizable: (atom & (1 << 5)) != 0,
+ left_tiled: (atom & (1 << 6)) != 0,
+ left_resizable: (atom & (1 << 7)) != 0,
+ }
+ }
+
+ fn to_tiling(&self) -> Tiling {
+ Tiling {
+ top: self.top_tiled,
+ right: self.right_tiled,
+ bottom: self.bottom_tiled,
+ left: self.left_tiled,
+ }
+ }
+}
+
#[derive(Debug)]
struct Visual {
id: xproto::Visualid,
@@ -198,6 +241,7 @@ pub struct X11WindowState {
active: bool,
fullscreen: bool,
decorations: WindowDecorations,
+ edge_constraints: Option<EdgeConstraints>,
pub handle: AnyWindowHandle,
last_insets: [u32; 4],
}
@@ -497,6 +541,7 @@ impl X11WindowState {
destroyed: false,
decorations: WindowDecorations::Server,
last_insets: [0, 0, 0, 0],
+ edge_constraints: None,
counter_id: sync_request_counter,
last_sync_counter: None,
refresh_rate,
@@ -686,10 +731,32 @@ impl X11WindowStatePtr {
pub fn property_notify(&self, event: xproto::PropertyNotifyEvent) {
let mut state = self.state.borrow_mut();
- if event.atom == state.atoms._NET_WM_STATE
- || event.atom == state.atoms._GTK_EDGE_CONSTRAINTS
- {
+ if event.atom == state.atoms._NET_WM_STATE {
self.set_wm_properties(state);
+ } else if event.atom == state.atoms._GTK_EDGE_CONSTRAINTS {
+ self.set_edge_constraints(state);
+ }
+ }
+
+ fn set_edge_constraints(&self, mut state: std::cell::RefMut<X11WindowState>) {
+ let reply = self
+ .xcb_connection
+ .get_property(
+ false,
+ self.x_window,
+ state.atoms._GTK_EDGE_CONSTRAINTS,
+ xproto::AtomEnum::CARDINAL,
+ 0,
+ 4,
+ )
+ .unwrap()
+ .reply()
+ .unwrap();
+
+ if reply.value_len != 0 {
+ let atom = u32::from_ne_bytes(reply.value[0..4].try_into().unwrap());
+ let edge_constraints = EdgeConstraints::from_atom(atom);
+ state.edge_constraints.replace(edge_constraints);
}
}
@@ -1194,15 +1261,19 @@ impl PlatformWindow for X11Window {
match state.decorations {
WindowDecorations::Server => Decorations::Server,
WindowDecorations::Client => {
- // https://source.chromium.org/chromium/chromium/src/+/main:ui/ozone/platform/x11/x11_window.cc;l=2519;drc=1f14cc876cc5bf899d13284a12c451498219bb2d
- Decorations::Client {
- tiling: Tiling {
+ let tiling = if let Some(edge_constraints) = &state.edge_constraints {
+ edge_constraints.to_tiling()
+ } else {
+ // https://source.chromium.org/chromium/chromium/src/+/main:ui/ozone/platform/x11/x11_window.cc;l=2519;drc=1f14cc876cc5bf899d13284a12c451498219bb2d
+ Tiling {
top: state.maximized_vertical,
bottom: state.maximized_vertical,
left: state.maximized_horizontal,
right: state.maximized_horizontal,
- },
- }
+ }
+ };
+
+ Decorations::Client { tiling }
}
}
}
@@ -1212,17 +1283,26 @@ impl PlatformWindow for X11Window {
let dp = (inset.0 * state.scale_factor) as u32;
- let (left, right) = if state.maximized_horizontal {
- (0, 0)
- } else {
- (dp, dp)
- };
- let (top, bottom) = if state.maximized_vertical {
- (0, 0)
+ let insets = if let Some(edge_constraints) = &state.edge_constraints {
+ let left = if edge_constraints.left_tiled { 0 } else { dp };
+ let top = if edge_constraints.top_tiled { 0 } else { dp };
+ let right = if edge_constraints.right_tiled { 0 } else { dp };
+ let bottom = if edge_constraints.bottom_tiled { 0 } else { dp };
+
+ [left, right, top, bottom]
} else {
- (dp, dp)
+ let (left, right) = if state.maximized_horizontal {
+ (0, 0)
+ } else {
+ (dp, dp)
+ };
+ let (top, bottom) = if state.maximized_vertical {
+ (0, 0)
+ } else {
+ (dp, dp)
+ };
+ [left, right, top, bottom]
};
- let insets = [left, right, top, bottom];
if state.last_insets != insets {
state.last_insets = insets;