Skip to content

Commit

Permalink
linux/x11: Support window icons
Browse files Browse the repository at this point in the history
  • Loading branch information
not-fl3 committed Oct 19, 2024
1 parent 5a9a76b commit 1c5729b
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/native/linux_x11/libx11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,8 @@ pub struct X11Extensions {
pub _wm_state: Atom,
pub net_wm_name: Atom,
pub net_wm_icon_name: Atom,
pub net_wm_icon: Atom,
pub cardinal: Atom,
}

#[derive(Clone)]
Expand Down Expand Up @@ -1133,6 +1135,16 @@ impl LibX11 {
b"_NET_WM_ICON_NAME\x00" as *const u8 as *const libc::c_char,
false as _,
),
net_wm_icon: (self.XInternAtom)(
display,
b"_NET_WM_ICON\x00" as *const u8 as *const libc::c_char,
false as _,
),
cardinal: (self.XInternAtom)(
display,
b"CARDINAL\x00" as *const u8 as *const libc::c_char,
false as _,
),
};
}
}
Expand Down
54 changes: 53 additions & 1 deletion src/native/linux_x11/libx11_ex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl LibX11 {
window,
self.extensions.net_wm_name,
self.extensions.utf8_string,
8 as libc::c_int,
8,
PropModeReplace,
c_title.as_ptr() as *mut libc::c_uchar,
libc::strlen(c_title.as_ptr()) as libc::c_int,
Expand All @@ -103,6 +103,53 @@ impl LibX11 {
(self.XFlush)(display);
}

pub unsafe fn update_window_icon(
&mut self,
display: *mut Display,
window: Window,
icon: &crate::conf::Icon,
) {
let bytes_length = (icon.small.len() + icon.medium.len() + icon.big.len()) / 4 + 3 * 2;

// "This is an array of 32bit packed CARDINAL ARGB" (c) freedesktop
// While, in fact, X11 expect this to be 64bit on 64bit systems, which is proved
// by quite a few "unsigned long icon[]" I've seen in quite a few real-life programs.
// Leaving this comment nn case of icon-related bugs in the future.
let mut icon_bytes: Vec<usize> = vec![0; bytes_length];
let icons = [
(16, &icon.small[..]),
(32, &icon.medium[..]),
(65, &icon.big[..]),
];

{
let mut target = icon_bytes.iter_mut();
for (dim, pixels) in icons {
*target.next().unwrap() = dim;
*target.next().unwrap() = dim;
for pixels in pixels.chunks(4) {
let r = pixels[0] as u32;
let g = pixels[1] as u32;
let b = pixels[2] as u32;
let a = pixels[3] as u32;

*target.next().unwrap() = ((r << 16) | (g << 8) | (b << 0) | (a << 24)) as usize;
}
}
}

(self.XChangeProperty)(
display,
window,
self.extensions.net_wm_icon,
self.extensions.cardinal,
32,
PropModeReplace,
icon_bytes.as_mut_ptr() as *mut _ as *mut _,
icon_bytes.len() as _,
);
}

pub unsafe fn create_window(
&mut self,
root: Window,
Expand Down Expand Up @@ -186,6 +233,11 @@ impl LibX11 {
(self.XSetWMNormalHints)(display, window, hints);
(self.XFree)(hints as *mut libc::c_void);

if let Some(ref icon) = conf.icon {
self.update_window_icon(display, window, icon);
}
// For an unknown reason, this should happen after update_window_icon,
// otherwise X11 will skip ChangeProperty(WM_ICON)
self.update_window_title(display, window, &conf.window_title);

window
Expand Down

0 comments on commit 1c5729b

Please sign in to comment.