Skip to content

Commit

Permalink
Merge branch 'master' into x11-cursors
Browse files Browse the repository at this point in the history
  • Loading branch information
maan2003 committed Jun 14, 2021
2 parents 75aba5c + d2e46e6 commit 0c079e4
Show file tree
Hide file tree
Showing 33 changed files with 431 additions and 217 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ You can find its changes [documented below](#070---2021-01-01).
- Text input handles Delete key ([#1746] by [@bjorn])
- `lens` macro can access nested fields ([#1764] by [@Maan2003])
- X11 backend now supports custom cursors ([#1801] by [@psychon])
- X11: Add support for transparent windows ([#1803] by [@psychon])
- `has_focus` method on `WidgetPod` ([#1825] by [@ForLoveOfCats])

### Changed

- Warn on unhandled Commands ([#1533] by [@Maan2003])
- ~~Warn on unhandled Commands ([#1533] by [@Maan2003])~~ (Reverted in #1813)
- `WindowDesc::new` takes the root widget directly instead of a closure ([#1559] by [@lassipulkkinen])
- Switch to trace-based logging ([#1562] by [@PoignardAzur])
- Spacers in `Flex` are now implemented by calculating the space in `Flex` instead of creating a widget for it ([#1584] by [@JAicewizard])
Expand All @@ -68,6 +70,7 @@ You can find its changes [documented below](#070---2021-01-01).
- `Notification`s will not be delivered to the widget that sends them ([#1640] by [@cmyr])
- `TextBox` can handle standard keyboard shortcuts without needing menus ([#1660] by [@cmyr])
- GTK Shell: Prevent mangling of newline characters in clipboard ([#1695] by [@ForLoveOfCats])
- GTK: Replaced call to `std::str::from_utf8_unchecked` with `from_utf8` ([#1820] by [@psychon])
- Use correct fill rule when rendering SVG paths ([#1606] by [@SecondFlight])
- Correctly capture and use stroke properties when rendering SVG paths ([#1647] by [@SecondFlight])
- focus-chain now only includes non hidden (`should_propagate_to_hidden()` on `Event` and `Lifecylce`) widgets ([#1724] by [@xarvic])
Expand Down Expand Up @@ -728,6 +731,9 @@ Last release without a changelog :(
[#1787]: https://github.com/linebender/druid/pull/1787
[#1801]: https://github.com/linebender/druid/pull/1800
[#1802]: https://github.com/linebender/druid/pull/1802
[#1803]: https://github.com/linebender/druid/pull/1803
[#1820]: https://github.com/linebender/druid/pull/1820
[#1825]: https://github.com/linebender/druid/pull/1825

[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0
Expand Down
4 changes: 2 additions & 2 deletions druid-derive/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub enum FieldIdent {
impl FieldIdent {
pub fn unwrap_named(&self) -> syn::Ident {
if let FieldIdent::Named(s) = self {
syn::Ident::new(&s, Span::call_site())
syn::Ident::new(s, Span::call_site())
} else {
panic!("Unwrap named called on unnamed FieldIdent");
}
Expand Down Expand Up @@ -272,7 +272,7 @@ impl Field<LensAttrs> {
impl<Attrs> Field<Attrs> {
pub fn ident_tokens(&self) -> TokenTree {
match self.ident {
FieldIdent::Named(ref s) => Ident::new(&s, Span::call_site()).into(),
FieldIdent::Named(ref s) => Ident::new(s, Span::call_site()).into(),
FieldIdent::Unnamed(num) => Literal::usize_unsuffixed(num).into(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion druid-derive/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ fn derive_enum(
let impl_generics = generics_bounds(&input.generics);
let (_, ty_generics, where_clause) = &input.generics.split_for_impl();

if is_c_style_enum(&s) {
if is_c_style_enum(s) {
let res = quote! {
impl<#impl_generics> ::druid::Data for #ident #ty_generics #where_clause {
fn same(&self, other: &Self) -> bool { self == other }
Expand Down
2 changes: 1 addition & 1 deletion druid-derive/src/lens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn derive_struct(input: &syn::DeriveInput) -> Result<proc_macro2::TokenStream, s

let associated_items = fields.iter().filter(|f| !f.attrs.ignore).map(|f| {
let field_name = &f.ident.unwrap_named();
let lens_field_name = f.attrs.lens_name_override.as_ref().unwrap_or(&field_name);
let lens_field_name = f.attrs.lens_name_override.as_ref().unwrap_or(field_name);

quote! {
/// Lens for the corresponding field.
Expand Down
9 changes: 6 additions & 3 deletions druid-shell/src/platform/gtk/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ impl Clipboard {
let idx = idx as usize;
if idx < formats.len() {
let item = &formats[idx];
if item.identifier == ClipboardFormat::TEXT {
sel.set_text(unsafe { std::str::from_utf8_unchecked(&item.data) });
if let (ClipboardFormat::TEXT, Ok(data)) =
(item.identifier, std::str::from_utf8(&item.data))
{
sel.set_text(data);
} else {
let atom = Atom::intern(item.identifier);
let stride = 8;
Expand Down Expand Up @@ -130,7 +132,8 @@ impl Clipboard {
let targets = clipboard.wait_for_targets().unwrap_or_default();
targets
.iter()
.map(|atom| unsafe { format!("{} ({})", atom.name(), atom.value()) })
// SAFETY: Atom::value() is 'self.0 as usize'. No idea why that is unsafe.
.map(|atom| format!("{} ({})", atom.name(), unsafe { atom.value() }))
.collect()
}
}
Expand Down
6 changes: 3 additions & 3 deletions druid-shell/src/platform/gtk/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl WindowBuilder {
// region, because there might be parts of the drawing area that were
// invalidated by external forces).
let alloc = widget.get_allocation();
context.set_source_surface(&surface, 0.0, 0.0);
context.set_source_surface(surface, 0.0, 0.0);
context.rectangle(0.0, 0.0, alloc.width as f64, alloc.height as f64);
context.fill();
});
Expand Down Expand Up @@ -1170,7 +1170,7 @@ impl WindowHandle {
old_menubar.deactivate();
vbox.remove(first_child);
}
let menubar = menu.into_gtk_menubar(&self, &accel_group);
let menubar = menu.into_gtk_menubar(self, &accel_group);
vbox.pack_start(&menubar, false, false, 0);
menubar.show_all();
}
Expand Down Expand Up @@ -1234,7 +1234,7 @@ impl IdleHandle {
fn run_idle(state: &Arc<WindowState>) -> glib::source::Continue {
util::assert_main_thread();
let result = state.with_handler(|handler| {
let queue: Vec<_> = std::mem::replace(&mut state.idle_queue.lock().unwrap(), Vec::new());
let queue: Vec<_> = std::mem::take(&mut state.idle_queue.lock().unwrap());

for item in queue {
match item {
Expand Down
47 changes: 46 additions & 1 deletion druid-shell/src/platform/x11/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use x11rb::connection::{Connection, RequestConnection};
use x11rb::protocol::present::ConnectionExt as _;
use x11rb::protocol::render::{self, ConnectionExt as _, Pictformat};
use x11rb::protocol::xfixes::ConnectionExt as _;
use x11rb::protocol::xproto::{self, ConnectionExt, CreateWindowAux, EventMask, WindowClass};
use x11rb::protocol::xproto::{
self, ConnectionExt, CreateWindowAux, EventMask, Visualtype, WindowClass,
};
use x11rb::protocol::Event;
use x11rb::resource_manager::Database as ResourceDb;
use x11rb::xcb_ffi::XCBConnection;
Expand All @@ -52,6 +54,11 @@ pub(crate) struct Application {
/// `druid_shell::WindowHandle` to be `!Send` and `!Sync`.
marker: std::marker::PhantomData<*mut XCBConnection>,

/// The type of visual used by the root window
root_visual_type: Visualtype,
/// The visual for windows with transparent backgrounds, if supported
argb_visual_type: Option<Visualtype>,

/// The X11 resource database used to query dpi.
pub(crate) rdb: Rc<ResourceDb>,
pub(crate) cursors: Cursors,
Expand Down Expand Up @@ -189,6 +196,15 @@ impl Application {
col_resize: load_cursor("col-resize"),
};

let screen = connection
.setup()
.roots
.get(screen_num as usize)
.ok_or_else(|| anyhow!("Invalid screen num: {}", screen_num))?;
let root_visual_type = util::get_visual_from_screen(&screen)
.ok_or_else(|| anyhow!("Couldn't get visual from screen"))?;
let argb_visual_type = util::get_argb_visual_type(&*connection, &screen)?;

Ok(Application {
connection,
rdb,
Expand All @@ -199,6 +215,8 @@ impl Application {
cursors,
idle_write,
present_opcode,
root_visual_type,
argb_visual_type,
marker: std::marker::PhantomData,
render_argb32_pictformat_cursor,
})
Expand Down Expand Up @@ -326,6 +344,33 @@ impl Application {
self.screen_num
}

#[inline]
pub(crate) fn argb_visual_type(&self) -> Option<Visualtype> {
// Check if a composite manager is running
let atom_name = format!("_NET_WM_CM_S{}", self.screen_num);
let owner = self
.connection
.intern_atom(false, atom_name.as_bytes())
.ok()
.and_then(|cookie| cookie.reply().ok())
.map(|reply| reply.atom)
.and_then(|atom| self.connection.get_selection_owner(atom).ok())
.and_then(|cookie| cookie.reply().ok())
.map(|reply| reply.owner);

if Some(x11rb::NONE) == owner {
tracing::debug!("_NET_WM_CM_Sn selection is unowned, not providing ARGB visual");
None
} else {
self.argb_visual_type
}
}

#[inline]
pub(crate) fn root_visual_type(&self) -> Visualtype {
self.root_visual_type
}

/// Returns `Ok(true)` if we want to exit the main loop.
fn handle_event(&self, ev: &Event) -> Result<bool, Error> {
match ev {
Expand Down
68 changes: 65 additions & 3 deletions druid-shell/src/platform/x11/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ use std::rc::Rc;
use std::time::Instant;

use anyhow::{anyhow, Error};
use x11rb::connection::RequestConnection;
use x11rb::errors::ReplyError;
use x11rb::protocol::randr::{ConnectionExt, ModeFlag};
use x11rb::protocol::xproto::{Screen, Visualtype, Window};
use x11rb::protocol::render::{self, ConnectionExt as _};
use x11rb::protocol::xproto::{Screen, Visualid, Visualtype, Window};
use x11rb::xcb_ffi::XCBConnection;

use crate::window::TimerToken;
Expand Down Expand Up @@ -69,17 +72,76 @@ pub fn refresh_rate(conn: &Rc<XCBConnection>, window_id: Window) -> Option<f64>
}

// Apparently you have to get the visualtype this way :|
pub fn get_visual_from_screen(screen: &Screen) -> Option<Visualtype> {
fn find_visual_from_screen(screen: &Screen, visual_id: u32) -> Option<Visualtype> {
for depth in &screen.allowed_depths {
for visual in &depth.visuals {
if visual.visual_id == screen.root_visual {
if visual.visual_id == visual_id {
return Some(*visual);
}
}
}
None
}

pub fn get_visual_from_screen(screen: &Screen) -> Option<Visualtype> {
find_visual_from_screen(screen, screen.root_visual)
}

pub fn get_argb_visual_type(
conn: &XCBConnection,
screen: &Screen,
) -> Result<Option<Visualtype>, ReplyError> {
fn find_visual_for_format(
reply: &render::QueryPictFormatsReply,
id: render::Pictformat,
) -> Option<Visualid> {
let find_in_depth = |depth: &render::Pictdepth| {
depth
.visuals
.iter()
.find(|visual| visual.format == id)
.map(|visual| visual.visual)
};
let find_in_screen =
|screen: &render::Pictscreen| screen.depths.iter().find_map(find_in_depth);
reply.screens.iter().find_map(find_in_screen)
}

// Getting a visual is already funny, but finding the ARGB32 visual is even more fun.
// RENDER has picture formats. Each format corresponds to a visual. Thus, we first find the
// right picture format, then find the corresponding visual id, then the Visualtype.
if conn
.extension_information(render::X11_EXTENSION_NAME)?
.is_none()
{
// RENDER not supported
Ok(None)
} else {
let pict_formats = conn.render_query_pict_formats()?.reply()?;
// Find the ARGB32 standard format
let res = pict_formats
.formats
.iter()
.find(|format| {
format.type_ == render::PictType::DIRECT
&& format.depth == 32
&& format.direct.red_shift == 16
&& format.direct.red_mask == 0xff
&& format.direct.green_shift == 8
&& format.direct.green_mask == 0xff
&& format.direct.blue_shift == 0
&& format.direct.blue_mask == 0xff
&& format.direct.alpha_shift == 24
&& format.direct.alpha_mask == 0xff
})
// Now find the corresponding visual ID
.and_then(|format| find_visual_for_format(&pict_formats, format.id))
// And finally, we can find the visual
.and_then(|visual_id| find_visual_from_screen(screen, visual_id));
Ok(res)
}
}

macro_rules! log_x11 {
($val:expr) => {
if let Err(e) = $val {
Expand Down
Loading

0 comments on commit 0c079e4

Please sign in to comment.