Skip to content

Commit

Permalink
Merge branch 'master' into x11-split-event-loop
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj authored Apr 5, 2024
2 parents 6dd1c89 + be3d72d commit b6af2f1
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 47 deletions.
34 changes: 21 additions & 13 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
name: Rust

on: [push, pull_request]
env:
CARGO_TERM_COLOR: always

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

runs-on: ${{ matrix.os }}
env:
RUSTFLAGS: -D warnings
RUSTDOCFLAGS: -D warnings
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install XCB and GL dependencies
run: |
sudo apt update
sudo apt install libx11-xcb-dev libxcb-dri2-0-dev libgl1-mesa-dev libxcb-icccm4-dev libxcursor-dev
if: contains(matrix.os, 'ubuntu')
run: sudo apt-get install libx11-dev libxcb1-dev libx11-xcb-dev libgl1-mesa-dev
- name: Install rust stable
uses: actions-rs/toolchain@v1
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
override: true
- name: Build with default features
run: cargo build --examples --workspace --verbose
- name: Build again with all features
run: cargo build --examples --workspace --all-features --verbose
components: rustfmt, clippy
- name: Build Default
run: cargo build --workspace --all-targets --verbose
- name: Build All Features
run: cargo build --workspace --all-targets --all-features --verbose
- name: Run tests
run: cargo test --examples --workspace --all-features --verbose
run: cargo test --workspace --all-targets --all-features --verbose
- name: Check docs
run: cargo doc --examples --all-features --no-deps
- name: Clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- name: Check Formatting (rustfmt)
run: cargo fmt --all -- --check
15 changes: 14 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ raw-window-handle = "0.5"

[target.'cfg(target_os="linux")'.dependencies]
x11rb = { version = "0.13.0", features = ["cursor", "resource_manager", "allow-unsafe-code"] }
x11 = { version = "2.21", features = ["xlib", "xcursor", "xlib_xcb"] }
x11 = { version = "2.21", features = ["xlib", "xlib_xcb"] }
nix = "0.22.0"

[target.'cfg(target_os="windows")'.dependencies]
Expand All @@ -43,3 +43,16 @@ softbuffer = "0.3.4"

[workspace]
members = ["examples/render_femtovg"]

[lints.clippy]
missing-safety-doc = "allow"

[[example]]
name = "open_window"
test = true
doctest = true

[[example]]
name = "open_parented"
test = true
doctest = true
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ Below is a proposed list of milestones (roughly in-order) and their status. Subj

### Linux

Install dependencies, e.g.,
Install dependencies, e.g.:

```sh
sudo apt-get install libx11-dev libxcursor-dev libxcb-dri2-0-dev libxcb-icccm4-dev libx11-xcb-dev
sudo apt-get install libx11-dev libxcb1-dev libx11-xcb-dev libgl1-mesa-dev
```

## License
Expand Down
2 changes: 2 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
msrv = '1.59'
check-private-items = true
4 changes: 2 additions & 2 deletions examples/open_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl WindowHandler for OpenWindowExample {
fn on_event(&mut self, _window: &mut Window, event: Event) -> EventStatus {
match &event {
#[cfg(target_os = "macos")]
Event::Mouse(MouseEvent::ButtonPressed { .. }) => copy_to_clipboard(&"This is a test!"),
Event::Mouse(MouseEvent::ButtonPressed { .. }) => copy_to_clipboard("This is a test!"),
Event::Window(WindowEvent::Resized(info)) => {
println!("Resized: {:?}", info);
let new_size = info.physical_size();
Expand Down Expand Up @@ -78,7 +78,7 @@ fn main() {
std::thread::spawn(move || loop {
std::thread::sleep(Duration::from_secs(5));

if let Err(_) = tx.push(Message::Hello) {
if tx.push(Message::Hello).is_err() {
println!("Failed sending message");
}
});
Expand Down
6 changes: 2 additions & 4 deletions src/gl/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,8 @@ impl GlContext {
let framework_name = CFString::from_str("com.apple.opengl").unwrap();
let framework =
unsafe { CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef()) };
let addr = unsafe {
CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef())
};
addr as *const c_void

unsafe { CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef()) }
}

pub fn swap_buffers(&self) {
Expand Down
5 changes: 3 additions & 2 deletions src/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ impl WindowHandle {
pub fn is_open(&self) -> bool {
self.state.window_inner.open.get()
}

}

unsafe impl HasRawWindowHandle for WindowHandle {
Expand Down Expand Up @@ -289,7 +288,9 @@ impl<'a> Window<'a> {
unsafe {
let view = self.inner.ns_view.as_mut().unwrap();
let window: id = msg_send![view, window];
if window == nil { return false; };
if window == nil {
return false;
};
let first_responder: id = msg_send![window, firstResponder];
let is_key_window: BOOL = msg_send![window, isKeyWindow];
let is_focused: BOOL = msg_send![view, isEqual: first_responder];
Expand Down
54 changes: 54 additions & 0 deletions src/win/cursor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::MouseCursor;
use winapi::{
shared::ntdef::LPCWSTR,
um::winuser::{
IDC_APPSTARTING, IDC_ARROW, IDC_CROSS, IDC_HAND, IDC_HELP, IDC_IBEAM, IDC_NO, IDC_SIZEALL,
IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZEWE, IDC_WAIT,
},
};

pub fn cursor_to_lpcwstr(cursor: MouseCursor) -> LPCWSTR {
match cursor {
MouseCursor::Default => IDC_ARROW,
MouseCursor::Hand => IDC_HAND,
MouseCursor::HandGrabbing => IDC_SIZEALL,
MouseCursor::Help => IDC_HELP,
// an empty LPCWSTR results in the cursor being hidden
MouseCursor::Hidden => std::ptr::null(),

MouseCursor::Text => IDC_IBEAM,
MouseCursor::VerticalText => IDC_IBEAM,

MouseCursor::Working => IDC_WAIT,
MouseCursor::PtrWorking => IDC_APPSTARTING,

MouseCursor::NotAllowed => IDC_NO,
MouseCursor::PtrNotAllowed => IDC_NO,

MouseCursor::ZoomIn => IDC_ARROW,
MouseCursor::ZoomOut => IDC_ARROW,

MouseCursor::Alias => IDC_ARROW,
MouseCursor::Copy => IDC_ARROW,
MouseCursor::Move => IDC_SIZEALL,
MouseCursor::AllScroll => IDC_SIZEALL,
MouseCursor::Cell => IDC_CROSS,
MouseCursor::Crosshair => IDC_CROSS,

MouseCursor::EResize => IDC_SIZEWE,
MouseCursor::NResize => IDC_SIZENS,
MouseCursor::NeResize => IDC_SIZENESW,
MouseCursor::NwResize => IDC_SIZENWSE,
MouseCursor::SResize => IDC_SIZENS,
MouseCursor::SeResize => IDC_SIZENWSE,
MouseCursor::SwResize => IDC_SIZENESW,
MouseCursor::WResize => IDC_SIZEWE,
MouseCursor::EwResize => IDC_SIZEWE,
MouseCursor::NsResize => IDC_SIZENS,
MouseCursor::NwseResize => IDC_SIZENWSE,
MouseCursor::NeswResize => IDC_SIZENESW,

MouseCursor::ColResize => IDC_SIZEWE,
MouseCursor::RowResize => IDC_SIZENS,
}
}
8 changes: 4 additions & 4 deletions src/win/drop_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use winapi::um::oleidl::{
IDropTarget, IDropTargetVtbl, DROPEFFECT_COPY, DROPEFFECT_LINK, DROPEFFECT_MOVE,
DROPEFFECT_NONE, DROPEFFECT_SCROLL,
};
use winapi::um::shellapi::DragQueryFileW;
use winapi::um::shellapi::{DragQueryFileW, HDROP};
use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl};
use winapi::um::winuser::CF_HDROP;
use winapi::Interface;
Expand Down Expand Up @@ -135,7 +135,7 @@ impl DropTarget {
return;
}

let hdrop = transmute((*medium.u).hGlobal());
let hdrop = *(*medium.u).hGlobal() as HDROP;

let item_count = DragQueryFileW(hdrop, 0xFFFFFFFF, null_mut(), 0);
if item_count == 0 {
Expand All @@ -153,7 +153,7 @@ impl DropTarget {
DragQueryFileW(
hdrop,
i,
transmute(buffer.spare_capacity_mut().as_mut_ptr()),
buffer.spare_capacity_mut().as_mut_ptr().cast(),
buffer_size as u32,
);
buffer.set_len(buffer_size);
Expand All @@ -175,7 +175,7 @@ impl DropTarget {
return S_OK;
}

return E_NOINTERFACE;
E_NOINTERFACE
}

unsafe extern "system" fn add_ref(this: *mut IUnknown) -> ULONG {
Expand Down
1 change: 1 addition & 0 deletions src/win/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod cursor;
mod drop_target;
mod keyboard;
mod window;
Expand Down
61 changes: 46 additions & 15 deletions src/win/window.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
use winapi::shared::guiddef::GUID;
use winapi::shared::minwindef::{ATOM, FALSE, LPARAM, LRESULT, UINT, WPARAM};
use winapi::shared::minwindef::{ATOM, FALSE, LOWORD, LPARAM, LRESULT, UINT, WPARAM};
use winapi::shared::windef::{HWND, RECT};
use winapi::um::combaseapi::CoCreateGuid;
use winapi::um::ole2::{OleInitialize, RegisterDragDrop, RevokeDragDrop};
use winapi::um::oleidl::LPDROPTARGET;
use winapi::um::winuser::{
AdjustWindowRectEx, CreateWindowExW, DefWindowProcW, DestroyWindow, DispatchMessageW,
GetDpiForWindow, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW, RegisterClassW,
ReleaseCapture, SetCapture, SetProcessDpiAwarenessContext, SetTimer, SetWindowLongPtrW,
SetWindowPos, SetFocus, GetFocus, TrackMouseEvent, TranslateMessage, UnregisterClassW, CS_OWNDC,
GET_XBUTTON_WPARAM, GWLP_USERDATA, IDC_ARROW, MSG, SWP_NOMOVE, SWP_NOZORDER, TRACKMOUSEEVENT,
WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED, WM_INPUTLANGCHANGE, WM_KEYDOWN,
WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL,
WM_MOUSELEAVE, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCDESTROY, WM_RBUTTONDOWN, WM_RBUTTONUP,
WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_TIMER, WM_USER,
WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX,
WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, XBUTTON1, XBUTTON2,
GetDpiForWindow, GetFocus, GetMessageW, GetWindowLongPtrW, LoadCursorW, PostMessageW,
RegisterClassW, ReleaseCapture, SetCapture, SetCursor, SetFocus, SetProcessDpiAwarenessContext,
SetTimer, SetWindowLongPtrW, SetWindowPos, TrackMouseEvent, TranslateMessage, UnregisterClassW,
CS_OWNDC, GET_XBUTTON_WPARAM, GWLP_USERDATA, HTCLIENT, IDC_ARROW, MSG, SWP_NOMOVE,
SWP_NOZORDER, TRACKMOUSEEVENT, WHEEL_DELTA, WM_CHAR, WM_CLOSE, WM_CREATE, WM_DPICHANGED,
WM_INPUTLANGCHANGE, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN,
WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSELEAVE, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_NCDESTROY,
WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SETCURSOR, WM_SHOWWINDOW, WM_SIZE, WM_SYSCHAR, WM_SYSKEYDOWN,
WM_SYSKEYUP, WM_TIMER, WM_USER, WM_XBUTTONDOWN, WM_XBUTTONUP, WNDCLASSW, WS_CAPTION, WS_CHILD,
WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX, WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
XBUTTON1, XBUTTON2,
};

use std::cell::{Cell, Ref, RefCell, RefMut};
Expand All @@ -37,6 +38,7 @@ use crate::{
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy,
};

use super::cursor::cursor_to_lpcwstr;
use super::drop_target::DropTarget;
use super::keyboard::KeyboardState;

Expand Down Expand Up @@ -174,7 +176,7 @@ unsafe fn wnd_proc_inner(
if *mouse_was_outside_window {
// this makes Windows track whether the mouse leaves the window.
// When the mouse leaves it results in a `WM_MOUSELEAVE` event.
let mut track_mouse =TRACKMOUSEEVENT {
let mut track_mouse = TRACKMOUSEEVENT {
cbSize: std::mem::size_of::<TRACKMOUSEEVENT>() as u32,
dwFlags: winapi::um::winuser::TME_LEAVE,
hwndTrack: hwnd,
Expand All @@ -186,7 +188,12 @@ unsafe fn wnd_proc_inner(
*mouse_was_outside_window = false;

let enter_event = Event::Mouse(MouseEvent::CursorEntered);
window_state.handler.borrow_mut().as_mut().unwrap().on_event(&mut window, enter_event);
window_state
.handler
.borrow_mut()
.as_mut()
.unwrap()
.on_event(&mut window, enter_event);
}

let x = (lparam & 0xFFFF) as i16 as i32;
Expand Down Expand Up @@ -423,6 +430,24 @@ unsafe fn wnd_proc_inner(

None
}
// If WM_SETCURSOR returns `None`, WM_SETCURSOR continues to get handled by the outer window(s),
// If it returns `Some(1)`, the current window decides what the cursor is
WM_SETCURSOR => {
let low_word = LOWORD(lparam as u32) as isize;
let mouse_in_window = low_word == HTCLIENT;
if mouse_in_window {
// Here we need to set the cursor back to what the state says, since it can have changed when outside the window
let cursor =
LoadCursorW(null_mut(), cursor_to_lpcwstr(window_state.cursor_icon.get()));
unsafe {
SetCursor(cursor);
}
Some(1)
} else {
// Cursor is being changed by some other window, e.g. when having mouse on the borders to resize it
None
}
}
// NOTE: `WM_NCDESTROY` is handled in the outer function because this deallocates the window
// state
BV_WINDOW_MUST_CLOSE => {
Expand Down Expand Up @@ -475,6 +500,7 @@ pub(super) struct WindowState {
keyboard_state: RefCell<KeyboardState>,
mouse_button_counter: Cell<usize>,
mouse_was_outside_window: RefCell<bool>,
cursor_icon: Cell<MouseCursor>,
// Initialized late so the `Window` can hold a reference to this `WindowState`
handler: RefCell<Option<Box<dyn WindowHandler>>>,
_drop_target: RefCell<Option<Rc<DropTarget>>>,
Expand Down Expand Up @@ -680,6 +706,7 @@ impl Window<'_> {
keyboard_state: RefCell::new(KeyboardState::new()),
mouse_button_counter: Cell::new(0),
mouse_was_outside_window: RefCell::new(true),
cursor_icon: Cell::new(MouseCursor::Default),
// The Window refers to this `WindowState`, so this `handler` needs to be
// initialized later
handler: RefCell::new(None),
Expand Down Expand Up @@ -785,8 +812,12 @@ impl Window<'_> {
self.state.deferred_tasks.borrow_mut().push_back(task);
}

pub fn set_mouse_cursor(&mut self, _mouse_cursor: MouseCursor) {
todo!()
pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) {
self.state.cursor_icon.set(mouse_cursor);
unsafe {
let cursor = LoadCursorW(null_mut(), cursor_to_lpcwstr(mouse_cursor));
SetCursor(cursor);
}
}

#[cfg(feature = "opengl")]
Expand Down
2 changes: 1 addition & 1 deletion src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct WindowHandle {

impl WindowHandle {
fn new(window_handle: platform::WindowHandle) -> Self {
Self { window_handle, phantom: PhantomData::default() }
Self { window_handle, phantom: PhantomData }
}

/// Close the window
Expand Down
4 changes: 1 addition & 3 deletions src/x11/xcb_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,8 @@ impl XcbConnection {
let _xres = width_px * 25.4 / width_mm;
let yres = height_px * 25.4 / height_mm;

let yscale = yres / 96.0;

// TODO: choose between `xres` and `yres`? (probably both are the same?)
yscale
yres / 96.0
}

#[inline]
Expand Down

0 comments on commit b6af2f1

Please sign in to comment.