Skip to content

Commit 912991d

Browse files
committed
Fix cursor formats
While piet provides pixels in rgba order, the X11 server wants an u32 in its native endianness with order argb. I even called a variable argb32_format, but I still did not handle this difference. This commit premultiplies the color component with the alpha, handles the different component order and also converts to the server's endianness. Signed-off-by: Uli Schlachter <psychon@znc.in>
1 parent 8515c29 commit 912991d

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

druid-shell/src/platform/x11/window.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ use x11rb::protocol::render::{ConnectionExt as _, Pictformat};
3737
use x11rb::protocol::xfixes::{ConnectionExt as _, Region as XRegion};
3838
use x11rb::protocol::xproto::{
3939
self, AtomEnum, ChangeWindowAttributesAux, ConfigureNotifyEvent, ConnectionExt, CreateGCAux,
40-
EventMask, Gcontext, Pixmap, PropMode, Rectangle, Visualtype, WindowClass,
40+
EventMask, Gcontext, ImageOrder as X11ImageOrder, Pixmap, PropMode, Rectangle, Visualtype,
41+
WindowClass,
4142
};
4243
use x11rb::wrapper::ConnectionExt as _;
4344
use x11rb::xcb_ffi::XCBConnection;
@@ -1622,11 +1623,10 @@ impl WindowHandle {
16221623
None
16231624
}
16241625
Some(format) => {
1625-
// BEGIN: Lots of code just to get the image into a RENDER Picture
1626-
16271626
let conn = w.app.connection();
1628-
let screen = &conn.setup().roots[w.app.screen_num() as usize];
1629-
match make_cursor(&**conn, screen.root, format, desc) {
1627+
let setup = &conn.setup();
1628+
let screen = &setup.roots[w.app.screen_num() as usize];
1629+
match make_cursor(&**conn, setup.image_byte_order, screen.root, format, desc) {
16301630
// TODO: We 'leak' the cursor - nothing ever calls render_free_cursor
16311631
Ok(cursor) => Some(cursor),
16321632
Err(err) => {
@@ -1697,23 +1697,40 @@ unsafe impl HasRawWindowHandle for WindowHandle {
16971697

16981698
fn make_cursor(
16991699
conn: &XCBConnection,
1700+
byte_order: X11ImageOrder,
17001701
root_window: u32,
17011702
argb32_format: Pictformat,
17021703
desc: &CursorDesc,
17031704
) -> Result<Cursor, ReplyOrIdError> {
17041705
// BEGIN: Lots of code just to get the image into a RENDER Picture
17051706

1707+
fn multiply_alpha(color: u8, alpha: u8) -> u8 {
1708+
let (color, alpha) = (u16::from(color), u16::from(alpha));
1709+
let temp = color * alpha + 0x80u16;
1710+
((temp + (temp >> 8)) >> 8) as u8
1711+
}
1712+
17061713
// No idea how to sanely get the pixel values, so I'll go with 'insane':
17071714
// Iterate over all pixels and build an array
17081715
let pixels = desc
17091716
.image
17101717
.pixel_colors()
17111718
.flat_map(|row| {
17121719
row.flat_map(|color| {
1713-
// TODO: RENDER (likely) expects unpremultiplied alpha. We should convert.
17141720
let (r, g, b, a) = color.as_rgba8();
1721+
// RENDER wants premultiplied alpha
1722+
let (r, g, b) = (
1723+
multiply_alpha(r, a),
1724+
multiply_alpha(g, a),
1725+
multiply_alpha(b, a),
1726+
);
1727+
// piet gives us rgba in this order, the server expects an u32 with argb.
1728+
let (b0, b1, b2, b3) = match byte_order {
1729+
X11ImageOrder::LSB_FIRST => (b, g, r, a),
1730+
_ => (a, r, g, b),
1731+
};
17151732
// TODO Ownership and flat_map don't go well together :-(
1716-
vec![r, g, b, a]
1733+
vec![b0, b1, b2, b3]
17171734
})
17181735
})
17191736
.collect::<Vec<u8>>();

0 commit comments

Comments
 (0)