Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into x11-kbd
Browse files Browse the repository at this point in the history
  • Loading branch information
maan2003 committed Jul 4, 2021
2 parents 7398b77 + ead3d8f commit aa077cf
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 42 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ You can find its changes [documented below](#070---2021-01-01).
- X11 backend now supports custom cursors ([#1801] by [@psychon])
- X11: Add support for transparent windows ([#1803] by [@psychon])
- X11: Added support for `get_monitors` ([#1804] by [@psychon])
- x11: Remove some unnecessary casts ([#1851] by [@psychon])
- `has_focus` method on `WidgetPod` ([#1825] by [@ForLoveOfCats])
- x11: Add support for getting clipboard contents ([#1805] by [@psychon])

### Changed

Expand Down Expand Up @@ -734,8 +736,10 @@ Last release without a changelog :(
[#1802]: https://github.com/linebender/druid/pull/1802
[#1803]: https://github.com/linebender/druid/pull/1803
[#1804]: https://github.com/linebender/druid/pull/1804
[#1805]: https://github.com/linebender/druid/pull/1805
[#1820]: https://github.com/linebender/druid/pull/1820
[#1825]: https://github.com/linebender/druid/pull/1825
[#1851]: https://github.com/linebender/druid/pull/1851

[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
2 changes: 1 addition & 1 deletion druid-shell/src/platform/mac/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub(crate) struct KeyboardState {
/// Convert a macOS platform key code (keyCode field of NSEvent).
///
/// The primary source for this mapping is:
/// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
/// <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values>
///
/// It should also match up with CODE_MAP_MAC bindings in
/// NativeKeyToDOMCodeName.h.
Expand Down
2 changes: 2 additions & 0 deletions druid-shell/src/platform/mac/text_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ unsafe impl objc::Encode for NSRange {
}
}

// BOOL is i8 on x86, but bool on aarch64
#[cfg_attr(target_arch = "aarch64", allow(clippy::useless_conversion))]
pub extern "C" fn has_marked_text(this: &mut Object, _: Sel) -> BOOL {
with_edit_lock_from_window(this, false, |edit_lock| {
edit_lock.composition_range().is_some()
Expand Down
5 changes: 3 additions & 2 deletions druid-shell/src/platform/windows/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,9 @@ fn vk_to_key(vk: VkCode) -> Option<KbKey> {
/// map.
///
/// The virtual key code can have modifiers in the higher order byte when the
/// argument is a `Character` variant. See:
/// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscanw
/// argument is a `Character` variant. See [VkKeyScanW][].
///
/// [VkKeyScanW]: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-vkkeyscanw
pub(crate) fn key_to_vk(key: &KbKey) -> Option<i32> {
Some(match key {
KbKey::Character(s) => {
Expand Down
66 changes: 49 additions & 17 deletions druid-shell/src/platform/x11/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

//! X11 implementation of features at the application scope.
use std::cell::RefCell;
use std::collections::HashMap;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, VecDeque};
use std::convert::{TryFrom, TryInto};
use std::os::unix::io::RawFd;
use std::rc::Rc;
Expand All @@ -27,7 +27,7 @@ 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, Visualtype, WindowClass,
self, ConnectionExt, CreateWindowAux, EventMask, Timestamp, Visualtype, WindowClass,
};
use x11rb::protocol::Event;
use x11rb::resource_manager::Database as ResourceDb;
Expand All @@ -49,15 +49,19 @@ pub(crate) struct Application {
/// A display is a collection of screens.
connection: Rc<XCBConnection>,
/// An `XCBConnection` is *technically* safe to use from other threads, but there are
/// subtleties; see https://github.com/psychon/x11rb/blob/41ab6610f44f5041e112569684fc58cd6d690e57/src/event_loop_integration.rs.
/// subtleties; see [x11rb event loop integration notes][1] for more details.
/// Let's just avoid the issue altogether. As far as public API is concerned, this causes
/// `druid_shell::WindowHandle` to be `!Send` and `!Sync`.
///
/// [1]: https://github.com/psychon/x11rb/blob/41ab6610f44f5041e112569684fc58cd6d690e57/src/event_loop_integration.rs.
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>,
/// Pending events that need to be handled later
pending_events: Rc<RefCell<VecDeque<Event>>>,

/// The X11 resource database used to query dpi.
pub(crate) rdb: Rc<ResourceDb>,
Expand All @@ -72,7 +76,7 @@ pub(crate) struct Application {
/// In practice multiple physical monitor drawing areas are present on a single screen.
/// This is achieved via various X server extensions (XRandR/Xinerama/TwinView),
/// with XRandR seeming like the best choice.
screen_num: i32, // Needs a container when no longer const
screen_num: usize, // Needs a container when no longer const
/// The X11 window id of this `Application`.
///
/// This is an input-only non-visual X11 window that is created first during initialization,
Expand All @@ -93,6 +97,8 @@ pub(crate) struct Application {
present_opcode: Option<u8>,
/// Support for the render extension in at least version 0.5?
render_argb32_pictformat_cursor: Option<Pictformat>,
/// Newest timestamp that we received
timestamp: Rc<Cell<Timestamp>>,
xkb_context: xkb::Context,
}

Expand Down Expand Up @@ -131,7 +137,9 @@ impl Application {
let xkb_context = xkb::Context::new();
xkb_context.set_log_level(tracing::Level::DEBUG);
use x11rb::protocol::xkb::ConnectionExt;
conn.xkb_use_extension(1, 0)?.reply().context("init xkb extension")?;
conn.xkb_use_extension(1, 0)?
.reply()
.context("init xkb extension")?;
let device_id = xkb_context
.core_keyboard_device_id(&conn)
.context("get core keyboard device id")?;
Expand All @@ -142,8 +150,7 @@ impl Application {

let xkb_state = keymap.state();
let connection = Rc::new(conn);
let window_id = Application::create_event_window(&connection, screen_num as i32)?;

let window_id = Application::create_event_window(&connection, screen_num)?;
let state = Rc::new(RefCell::new(State {
quitting: false,
windows: HashMap::new(),
Expand Down Expand Up @@ -216,7 +223,7 @@ impl Application {
let screen = connection
.setup()
.roots
.get(screen_num as usize)
.get(screen_num)
.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"))?;
Expand All @@ -225,7 +232,7 @@ impl Application {
Ok(Application {
connection,
rdb,
screen_num: screen_num as i32,
screen_num,
window_id,
state,
idle_read,
Expand All @@ -234,8 +241,10 @@ impl Application {
present_opcode,
root_visual_type,
argb_visual_type,
pending_events: Default::default(),
marker: std::marker::PhantomData,
render_argb32_pictformat_cursor,
timestamp: Rc::new(Cell::new(x11rb::CURRENT_TIME)),
xkb_context,
})
}
Expand Down Expand Up @@ -293,12 +302,12 @@ impl Application {
self.render_argb32_pictformat_cursor
}

fn create_event_window(conn: &Rc<XCBConnection>, screen_num: i32) -> Result<u32, Error> {
fn create_event_window(conn: &Rc<XCBConnection>, screen_num: usize) -> Result<u32, Error> {
let id = conn.generate_id()?;
let setup = conn.setup();
let screen = setup
.roots
.get(screen_num as usize)
.get(screen_num)
.ok_or_else(|| anyhow!("invalid screen num: {}", screen_num))?;

// Create the actual window
Expand Down Expand Up @@ -358,7 +367,7 @@ impl Application {
}

#[inline]
pub(crate) fn screen_num(&self) -> i32 {
pub(crate) fn screen_num(&self) -> usize {
self.screen_num
}

Expand Down Expand Up @@ -391,6 +400,21 @@ impl Application {

/// Returns `Ok(true)` if we want to exit the main loop.
fn handle_event(&self, ev: &Event) -> Result<bool, Error> {
if ev.server_generated() {
// Update our latest timestamp
let timestamp = match ev {
Event::KeyPress(ev) => ev.time,
Event::KeyRelease(ev) => ev.time,
Event::ButtonPress(ev) => ev.time,
Event::ButtonRelease(ev) => ev.time,
Event::MotionNotify(ev) => ev.time,
Event::EnterNotify(ev) => ev.time,
Event::LeaveNotify(ev) => ev.time,
Event::PropertyNotify(ev) => ev.time,
_ => self.timestamp.get(),
};
self.timestamp.set(timestamp);
}
match ev {
// NOTE: When adding handling for any of the following events,
// there must be a check against self.window_id
Expand Down Expand Up @@ -548,10 +572,15 @@ impl Application {

self.connection.flush()?;

// Deal with pending events
let mut event = self.pending_events.borrow_mut().pop_front();

// Before we poll on the connection's file descriptor, check whether there are any
// events ready. It could be that XCB has some events in its internal buffers because
// of something that happened during the idle loop.
let mut event = self.connection.poll_for_event()?;
if event.is_none() {
event = self.connection.poll_for_event()?;
}

if event.is_none() {
poll_with_timeout(
Expand Down Expand Up @@ -641,9 +670,12 @@ impl Application {
}

pub fn clipboard(&self) -> Clipboard {
// TODO(x11/clipboard): implement Application::clipboard
tracing::warn!("Application::clipboard is currently unimplemented for X11 platforms.");
Clipboard {}
Clipboard::new(
Rc::clone(&self.connection),
self.screen_num,
Rc::clone(&self.pending_events),
Rc::clone(&self.timestamp),
)
}

pub fn get_locale() -> String {
Expand Down
Loading

0 comments on commit aa077cf

Please sign in to comment.