mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-26 22:53:15 -04:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3e6949007 | ||
|
|
a033b25ecb | ||
|
|
39dd30c239 | ||
|
|
c5c99d2357 | ||
|
|
25ff30ee8c | ||
|
|
6b250a74f8 | ||
|
|
5331397c6c | ||
|
|
0b39024133 | ||
|
|
438d286fd5 | ||
|
|
18a61f1058 | ||
|
|
20d012ae3f | ||
|
|
efc54ab8ba |
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -2,16 +2,8 @@ name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.rs'
|
||||
- '**.toml'
|
||||
- '.github/workflows/ci.yml'
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- '**.rs'
|
||||
- '**.toml'
|
||||
- '.github/workflows/ci.yml'
|
||||
|
||||
jobs:
|
||||
Check_Formatting:
|
||||
@@ -50,7 +42,7 @@ jobs:
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
RUSTFLAGS: "-C debuginfo=0"
|
||||
RUSTFLAGS: "-C debuginfo=0 --deny warnings"
|
||||
OPTIONS: ${{ matrix.platform.options }}
|
||||
FEATURES: ${{ format(',{0}', matrix.platform.features ) }}
|
||||
CMD: ${{ matrix.platform.cmd }}
|
||||
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,6 +1,14 @@
|
||||
# 0.26.1 (2022-01-05)
|
||||
|
||||
- Fix linking to the `ColorSync` framework on macOS 10.7, and in newer Rust versions.
|
||||
- On Web, implement cursor grabbing through the pointer lock API.
|
||||
- On X11, add mappings for numpad comma, numpad enter, numlock and pause.
|
||||
- On macOS, fix Pinyin IME input by reverting a change that intended to improve IME.
|
||||
- On Windows, fix a crash with transparent windows on Windows 11.
|
||||
|
||||
# 0.26.0 (2021-12-01)
|
||||
|
||||
- Update `raw-window-handle` to `v0.4`. This is _not_ a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74).
|
||||
- Update `raw-window-handle` to `v0.4`. This is _not_ a breaking change, we still implement `HasRawWindowHandle` from `v0.3`, see [rust-windowing/raw-window-handle#74](https://github.com/rust-windowing/raw-window-handle/pull/74). Note that you might have to run `cargo update -p raw-window-handle` after upgrading.
|
||||
- On X11, bump `mio` to 0.8.
|
||||
- On Android, fixed `WindowExtAndroid::config` initially returning an empty `Configuration`.
|
||||
- On Android, fixed `Window::scale_factor` and `MonitorHandle::scale_factor` initially always returning 1.0.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "winit"
|
||||
version = "0.26.0"
|
||||
version = "0.26.1"
|
||||
authors = ["The winit contributors", "Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
description = "Cross-platform window creation library."
|
||||
edition = "2018"
|
||||
@@ -48,7 +48,6 @@ cocoa = "0.24"
|
||||
core-foundation = "0.9"
|
||||
core-graphics = "0.22"
|
||||
dispatch = "0.2.0"
|
||||
block = "0.1"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies.core-video-sys]
|
||||
version = "0.1.4"
|
||||
|
||||
@@ -197,7 +197,7 @@ Legend:
|
||||
|----------------------- | ----- | ---- | ------- | ----------- | ----- | ----- | -------- |
|
||||
|Mouse events |✔️ |▢[#63] |✔️ |✔️ |**N/A**|**N/A**|✔️ |
|
||||
|Mouse set location |✔️ |✔️ |✔️ |❓ |**N/A**|**N/A**|**N/A**|
|
||||
|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|❓ |
|
||||
|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|✔️ |
|
||||
|Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ |
|
||||
|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ |
|
||||
|Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ |
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
winit = "0.26.0"
|
||||
winit = "0.26.1"
|
||||
```
|
||||
|
||||
## [Documentation](https://docs.rs/winit)
|
||||
@@ -19,9 +19,8 @@ For features _outside_ the scope of winit, see [Missing features provided by oth
|
||||
|
||||
Join us in any of these:
|
||||
|
||||
[](http://webchat.freenode.net?channels=%23glutin&uio=MTY9dHJ1ZSYyPXRydWUmND10cnVlJjExPTE4NSYxMj10cnVlJjE1PXRydWU7a)
|
||||
[](https://matrix.to/#/#Glutin:matrix.org)
|
||||
[](https://gitter.im/tomaka/glutin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://matrix.to/#/#rust-windowing:matrix.org)
|
||||
[](https://web.libera.chat/#winit)
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ fn main() {
|
||||
..
|
||||
} => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ fn main() {
|
||||
|
||||
let mut num = String::new();
|
||||
stdin().read_line(&mut num).unwrap();
|
||||
let num = num.trim().parse().ok().expect("Please enter a number");
|
||||
let num = num.trim().parse().expect("Please enter a number");
|
||||
|
||||
let fullscreen = Some(match num {
|
||||
1 => Fullscreen::Exclusive(prompt_for_video_mode(&prompt_for_monitor(&event_loop))),
|
||||
@@ -85,7 +85,7 @@ fn prompt_for_monitor(event_loop: &EventLoop<()>) -> MonitorHandle {
|
||||
|
||||
let mut num = String::new();
|
||||
stdin().read_line(&mut num).unwrap();
|
||||
let num = num.trim().parse().ok().expect("Please enter a number");
|
||||
let num = num.trim().parse().expect("Please enter a number");
|
||||
let monitor = event_loop
|
||||
.available_monitors()
|
||||
.nth(num)
|
||||
@@ -106,7 +106,7 @@ fn prompt_for_video_mode(monitor: &MonitorHandle) -> VideoMode {
|
||||
|
||||
let mut num = String::new();
|
||||
stdin().read_line(&mut num).unwrap();
|
||||
let num = num.trim().parse().ok().expect("Please enter a number");
|
||||
let num = num.trim().parse().expect("Please enter a number");
|
||||
let video_mode = monitor
|
||||
.video_modes()
|
||||
.nth(num)
|
||||
|
||||
@@ -34,10 +34,10 @@ fn main() {
|
||||
// We need to update our chosen video mode if the window
|
||||
// was moved to an another monitor, so that the window
|
||||
// appears on this monitor instead when we go fullscreen
|
||||
let previous_video_mode = video_modes.iter().cloned().nth(video_mode_id);
|
||||
let previous_video_mode = video_modes.get(video_mode_id).cloned();
|
||||
video_modes = window.current_monitor().unwrap().video_modes().collect();
|
||||
video_mode_id = video_mode_id.min(video_modes.len());
|
||||
let video_mode = video_modes.iter().nth(video_mode_id);
|
||||
let video_mode = video_modes.get(video_mode_id);
|
||||
|
||||
// Different monitors may support different video modes,
|
||||
// and the index we chose previously may now point to a
|
||||
@@ -45,7 +45,7 @@ fn main() {
|
||||
if video_mode != previous_video_mode.as_ref() {
|
||||
println!(
|
||||
"Window moved to another monitor, picked video mode: {}",
|
||||
video_modes.iter().nth(video_mode_id).unwrap()
|
||||
video_modes.get(video_mode_id).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -77,16 +77,13 @@ fn main() {
|
||||
Right => (video_modes.len() - 1).min(video_mode_id + 1),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
println!(
|
||||
"Picking video mode: {}",
|
||||
video_modes.iter().nth(video_mode_id).unwrap()
|
||||
);
|
||||
println!("Picking video mode: {}", video_modes[video_mode_id]);
|
||||
}
|
||||
F => window.set_fullscreen(match (state, modifiers.alt()) {
|
||||
(true, false) => Some(Fullscreen::Borderless(None)),
|
||||
(true, true) => Some(Fullscreen::Exclusive(
|
||||
video_modes.iter().nth(video_mode_id).unwrap().clone(),
|
||||
)),
|
||||
(true, true) => {
|
||||
Some(Fullscreen::Exclusive(video_modes[video_mode_id].clone()))
|
||||
}
|
||||
(false, _) => None,
|
||||
}),
|
||||
G => window.set_cursor_grab(state).unwrap(),
|
||||
@@ -173,7 +170,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => (),
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ fn main() {
|
||||
},
|
||||
..
|
||||
} => {
|
||||
let window = Window::new(&event_loop).unwrap();
|
||||
let window = Window::new(event_loop).unwrap();
|
||||
windows.insert(window.id(), window);
|
||||
}
|
||||
_ => (),
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::{thread, time};
|
||||
|
||||
use simple_logger::SimpleLogger;
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn main() {
|
||||
use std::{thread, time};
|
||||
|
||||
use simple_logger::SimpleLogger;
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
SimpleLogger::new().init().unwrap();
|
||||
let event_loop = EventLoop::new();
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ fn main() {
|
||||
..
|
||||
} => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ mod wasm {
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn run() {
|
||||
console_log::init_with_level(log::Level::Debug);
|
||||
console_log::init_with_level(log::Level::Debug).expect("error initializing logger");
|
||||
|
||||
super::main();
|
||||
}
|
||||
|
||||
@@ -345,9 +345,31 @@ pub trait WindowBuilderExtUnix {
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_gtk_theme_variant(self, variant: String) -> Self;
|
||||
/// Build window with resize increment hint. Only implemented on X11.
|
||||
///
|
||||
/// ```
|
||||
/// # use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
/// # use winit::window::WindowBuilder;
|
||||
/// # use winit::platform::unix::WindowBuilderExtUnix;
|
||||
/// // Specify the size in logical dimensions like this:
|
||||
/// WindowBuilder::new().with_resize_increments(LogicalSize::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the size in physical dimensions like this:
|
||||
/// WindowBuilder::new().with_resize_increments(PhysicalSize::new(400, 200));
|
||||
/// ```
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_resize_increments<S: Into<Size>>(self, increments: S) -> Self;
|
||||
/// Build window with base size hint. Only implemented on X11.
|
||||
///
|
||||
/// ```
|
||||
/// # use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
/// # use winit::window::WindowBuilder;
|
||||
/// # use winit::platform::unix::WindowBuilderExtUnix;
|
||||
/// // Specify the size in logical dimensions like this:
|
||||
/// WindowBuilder::new().with_base_size(LogicalSize::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the size in physical dimensions like this:
|
||||
/// WindowBuilder::new().with_base_size(PhysicalSize::new(400, 200));
|
||||
/// ```
|
||||
#[cfg(feature = "x11")]
|
||||
fn with_base_size<S: Into<Size>>(self, base_size: S) -> Self;
|
||||
|
||||
|
||||
@@ -168,7 +168,9 @@ impl Drop for MonitorHandle {
|
||||
|
||||
impl fmt::Debug for MonitorHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// TODO: Do this using the proper fmt API
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct MonitorHandle {
|
||||
name: Option<String>,
|
||||
size: PhysicalSize<u32>,
|
||||
|
||||
@@ -118,9 +118,9 @@ impl fmt::Display for OsError {
|
||||
#[cfg(feature = "x11")]
|
||||
OsError::XError(ref e) => _f.pad(&e.description),
|
||||
#[cfg(feature = "x11")]
|
||||
OsError::XMisc(ref e) => _f.pad(e),
|
||||
OsError::XMisc(e) => _f.pad(e),
|
||||
#[cfg(feature = "wayland")]
|
||||
OsError::WaylandMisc(ref e) => _f.pad(e),
|
||||
OsError::WaylandMisc(e) => _f.pad(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -409,7 +409,7 @@ impl Window {
|
||||
#[cfg(feature = "x11")]
|
||||
Window::X(ref w) => w.set_always_on_top(_always_on_top),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
Window::Wayland(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +419,7 @@ impl Window {
|
||||
#[cfg(feature = "x11")]
|
||||
Window::X(ref w) => w.set_window_icon(_window_icon),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
Window::Wayland(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ impl Window {
|
||||
#[cfg(feature = "x11")]
|
||||
Window::X(ref w) => w.focus_window(),
|
||||
#[cfg(feature = "wayland")]
|
||||
_ => (),
|
||||
Window::Wayland(_) => (),
|
||||
}
|
||||
}
|
||||
pub fn request_user_attention(&self, request_type: Option<UserAttentionType>) {
|
||||
|
||||
@@ -536,12 +536,12 @@ impl<T: 'static> EventLoop<T> {
|
||||
}
|
||||
|
||||
fn loop_dispatch<D: Into<Option<std::time::Duration>>>(&mut self, timeout: D) -> IOResult<()> {
|
||||
let mut state = match &mut self.window_target.p {
|
||||
let state = match &mut self.window_target.p {
|
||||
PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(),
|
||||
#[cfg(feature = "x11")]
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.event_loop.dispatch(timeout, &mut state)
|
||||
self.event_loop.dispatch(timeout, state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ impl<T: 'static> EventProcessor<T> {
|
||||
let mut devices = self.devices.borrow_mut();
|
||||
if let Some(info) = DeviceInfo::get(&wt.xconn, device) {
|
||||
for info in info.iter() {
|
||||
devices.insert(DeviceId(info.deviceid), Device::new(&self, info));
|
||||
devices.insert(DeviceId(info.deviceid), Device::new(self, info));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -925,7 +925,7 @@ impl<T: 'static> EventProcessor<T> {
|
||||
|
||||
// Issue key press events for all pressed keys
|
||||
Self::handle_pressed_keys(
|
||||
&wt,
|
||||
wt,
|
||||
window_id,
|
||||
ElementState::Pressed,
|
||||
&self.mod_keymap,
|
||||
@@ -949,7 +949,7 @@ impl<T: 'static> EventProcessor<T> {
|
||||
|
||||
// Issue key release events for all pressed keys
|
||||
Self::handle_pressed_keys(
|
||||
&wt,
|
||||
wt,
|
||||
window_id,
|
||||
ElementState::Released,
|
||||
&self.mod_keymap,
|
||||
@@ -1220,11 +1220,8 @@ impl<T: 'static> EventProcessor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
match self.ime_receiver.try_recv() {
|
||||
Ok((window_id, x, y)) => {
|
||||
wt.ime.borrow_mut().send_xim_spot(window_id, x, y);
|
||||
}
|
||||
Err(_) => (),
|
||||
if let Ok((window_id, x, y)) = self.ime_receiver.try_recv() {
|
||||
wt.ime.borrow_mut().send_xim_spot(window_id, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn keysym_to_element(keysym: libc::c_uint) -> Option<VirtualKeyCode> {
|
||||
//ffi::XK_Linefeed => VirtualKeyCode::Linefeed,
|
||||
//ffi::XK_Clear => VirtualKeyCode::Clear,
|
||||
ffi::XK_Return => VirtualKeyCode::Return,
|
||||
//ffi::XK_Pause => VirtualKeyCode::Pause,
|
||||
ffi::XK_Pause => VirtualKeyCode::Pause,
|
||||
//ffi::XK_Scroll_Lock => VirtualKeyCode::Scroll_lock,
|
||||
//ffi::XK_Sys_Req => VirtualKeyCode::Sys_req,
|
||||
ffi::XK_Escape => VirtualKeyCode::Escape,
|
||||
@@ -59,10 +59,10 @@ pub fn keysym_to_element(keysym: libc::c_uint) -> Option<VirtualKeyCode> {
|
||||
//ffi::XK_Break => VirtualKeyCode::Break,
|
||||
//ffi::XK_Mode_switch => VirtualKeyCode::Mode_switch,
|
||||
//ffi::XK_script_switch => VirtualKeyCode::Script_switch,
|
||||
//ffi::XK_Num_Lock => VirtualKeyCode::Num_lock,
|
||||
ffi::XK_Num_Lock => VirtualKeyCode::Numlock,
|
||||
//ffi::XK_KP_Space => VirtualKeyCode::Kp_space,
|
||||
//ffi::XK_KP_Tab => VirtualKeyCode::Kp_tab,
|
||||
//ffi::XK_KP_Enter => VirtualKeyCode::Kp_enter,
|
||||
ffi::XK_KP_Enter => VirtualKeyCode::NumpadEnter,
|
||||
//ffi::XK_KP_F1 => VirtualKeyCode::Kp_f1,
|
||||
//ffi::XK_KP_F2 => VirtualKeyCode::Kp_f2,
|
||||
//ffi::XK_KP_F3 => VirtualKeyCode::Kp_f3,
|
||||
@@ -83,7 +83,7 @@ pub fn keysym_to_element(keysym: libc::c_uint) -> Option<VirtualKeyCode> {
|
||||
ffi::XK_KP_Equal => VirtualKeyCode::NumpadEquals,
|
||||
ffi::XK_KP_Multiply => VirtualKeyCode::NumpadMultiply,
|
||||
ffi::XK_KP_Add => VirtualKeyCode::NumpadAdd,
|
||||
//ffi::XK_KP_Separator => VirtualKeyCode::Kp_separator,
|
||||
ffi::XK_KP_Separator => VirtualKeyCode::NumpadComma,
|
||||
ffi::XK_KP_Subtract => VirtualKeyCode::NumpadSubtract,
|
||||
ffi::XK_KP_Decimal => VirtualKeyCode::NumpadDecimal,
|
||||
ffi::XK_KP_Divide => VirtualKeyCode::NumpadDivide,
|
||||
|
||||
@@ -62,7 +62,7 @@ pub unsafe fn set_destroy_callback(
|
||||
inner: &ImeInner,
|
||||
) -> Result<(), XError> {
|
||||
xim_set_callback(
|
||||
&xconn,
|
||||
xconn,
|
||||
im,
|
||||
ffi::XNDestroyCallback_0.as_ptr() as *const _,
|
||||
&inner.destroy_callback as *const _ as *mut _,
|
||||
@@ -70,6 +70,7 @@ pub unsafe fn set_destroy_callback(
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
enum ReplaceImError {
|
||||
MethodOpenFailed(PotentialInputMethods),
|
||||
ContextCreationFailed(ImeContextCreationError),
|
||||
@@ -136,13 +137,17 @@ pub unsafe extern "C" fn xim_instantiate_callback(
|
||||
let inner: *mut ImeInner = client_data as _;
|
||||
if !inner.is_null() {
|
||||
let xconn = &(*inner).xconn;
|
||||
let result = replace_im(inner);
|
||||
if result.is_ok() {
|
||||
let _ = unset_instantiate_callback(xconn, client_data);
|
||||
(*inner).is_fallback = false;
|
||||
} else if result.is_err() && (*inner).is_destroyed {
|
||||
// We have no usable input methods!
|
||||
result.expect("Failed to reopen input method");
|
||||
match replace_im(inner) {
|
||||
Ok(()) => {
|
||||
let _ = unset_instantiate_callback(xconn, client_data);
|
||||
(*inner).is_fallback = false;
|
||||
}
|
||||
Err(err) => {
|
||||
if (*inner).is_destroyed {
|
||||
// We have no usable input methods!
|
||||
panic!("Failed to reopen input method: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,12 +168,12 @@ pub unsafe extern "C" fn xim_destroy_callback(
|
||||
if !(*inner).is_fallback {
|
||||
let _ = set_instantiate_callback(xconn, client_data);
|
||||
// Attempt to open fallback input method.
|
||||
let result = replace_im(inner);
|
||||
if result.is_ok() {
|
||||
(*inner).is_fallback = true;
|
||||
} else {
|
||||
// We have no usable input methods!
|
||||
result.expect("Failed to open fallback input method");
|
||||
match replace_im(inner) {
|
||||
Ok(()) => (*inner).is_fallback = true,
|
||||
Err(err) => {
|
||||
// We have no usable input methods!
|
||||
panic!("Failed to open fallback input method: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl ImeContext {
|
||||
|
||||
Ok(ImeContext {
|
||||
ic,
|
||||
ic_spot: ic_spot.unwrap_or_else(|| ffi::XPoint { x: 0, y: 0 }),
|
||||
ic_spot: ic_spot.unwrap_or(ffi::XPoint { x: 0, y: 0 }),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,8 @@ impl ImeInner {
|
||||
}
|
||||
|
||||
pub unsafe fn destroy_all_contexts_if_necessary(&self) -> Result<bool, XError> {
|
||||
for context in self.contexts.values() {
|
||||
if let &Some(ref context) = context {
|
||||
self.destroy_ic_if_necessary(context.ic)?;
|
||||
}
|
||||
for context in self.contexts.values().flatten() {
|
||||
self.destroy_ic_if_necessary(context.ic)?;
|
||||
}
|
||||
Ok(!self.is_destroyed)
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ unsafe fn open_im(xconn: &Arc<XConnection>, locale_modifiers: &CStr) -> Option<f
|
||||
#[derive(Debug)]
|
||||
pub struct InputMethod {
|
||||
pub im: ffi::XIM,
|
||||
name: String,
|
||||
_name: String,
|
||||
}
|
||||
|
||||
impl InputMethod {
|
||||
fn new(im: ffi::XIM, name: String) -> Self {
|
||||
InputMethod { im, name }
|
||||
InputMethod { im, _name: name }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,7 @@ pub enum InputMethodResult {
|
||||
|
||||
impl InputMethodResult {
|
||||
pub fn is_fallback(&self) -> bool {
|
||||
if let &InputMethodResult::Fallback(_) = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
matches!(self, InputMethodResult::Fallback(_))
|
||||
}
|
||||
|
||||
pub fn ok(self) -> Option<InputMethod> {
|
||||
@@ -249,7 +245,7 @@ impl PotentialInputMethods {
|
||||
pub fn open_im(
|
||||
&mut self,
|
||||
xconn: &Arc<XConnection>,
|
||||
callback: Option<&dyn Fn() -> ()>,
|
||||
callback: Option<&dyn Fn()>,
|
||||
) -> InputMethodResult {
|
||||
use self::InputMethodResult::*;
|
||||
|
||||
@@ -259,10 +255,8 @@ impl PotentialInputMethods {
|
||||
let im = input_method.open_im(xconn);
|
||||
if let Some(im) = im {
|
||||
return XModifiers(im);
|
||||
} else {
|
||||
if let Some(ref callback) = callback {
|
||||
callback();
|
||||
}
|
||||
} else if let Some(ref callback) = callback {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -592,7 +592,7 @@ fn mkdid(w: c_int) -> crate::event::DeviceId {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Device {
|
||||
name: String,
|
||||
_name: String,
|
||||
scroll_axes: Vec<(i32, ScrollAxis)>,
|
||||
// For master devices, this is the paired device (pointer <-> keyboard).
|
||||
// For slave devices, this is the master.
|
||||
@@ -634,31 +634,28 @@ impl Device {
|
||||
// Identify scroll axes
|
||||
for class_ptr in Device::classes(info) {
|
||||
let class = unsafe { &**class_ptr };
|
||||
match class._type {
|
||||
ffi::XIScrollClass => {
|
||||
let info = unsafe {
|
||||
mem::transmute::<&ffi::XIAnyClassInfo, &ffi::XIScrollClassInfo>(class)
|
||||
};
|
||||
scroll_axes.push((
|
||||
info.number,
|
||||
ScrollAxis {
|
||||
increment: info.increment,
|
||||
orientation: match info.scroll_type {
|
||||
ffi::XIScrollTypeHorizontal => ScrollOrientation::Horizontal,
|
||||
ffi::XIScrollTypeVertical => ScrollOrientation::Vertical,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
position: 0.0,
|
||||
if class._type == ffi::XIScrollClass {
|
||||
let info = unsafe {
|
||||
mem::transmute::<&ffi::XIAnyClassInfo, &ffi::XIScrollClassInfo>(class)
|
||||
};
|
||||
scroll_axes.push((
|
||||
info.number,
|
||||
ScrollAxis {
|
||||
increment: info.increment,
|
||||
orientation: match info.scroll_type {
|
||||
ffi::XIScrollTypeHorizontal => ScrollOrientation::Horizontal,
|
||||
ffi::XIScrollTypeVertical => ScrollOrientation::Vertical,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
position: 0.0,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut device = Device {
|
||||
name: name.into_owned(),
|
||||
_name: name.into_owned(),
|
||||
scroll_axes,
|
||||
attachment: info.attachment,
|
||||
};
|
||||
@@ -670,20 +667,17 @@ impl Device {
|
||||
if Device::physical_device(info) {
|
||||
for class_ptr in Device::classes(info) {
|
||||
let class = unsafe { &**class_ptr };
|
||||
match class._type {
|
||||
ffi::XIValuatorClass => {
|
||||
let info = unsafe {
|
||||
mem::transmute::<&ffi::XIAnyClassInfo, &ffi::XIValuatorClassInfo>(class)
|
||||
};
|
||||
if let Some(&mut (_, ref mut axis)) = self
|
||||
.scroll_axes
|
||||
.iter_mut()
|
||||
.find(|&&mut (axis, _)| axis == info.number)
|
||||
{
|
||||
axis.position = info.value;
|
||||
}
|
||||
if class._type == ffi::XIValuatorClass {
|
||||
let info = unsafe {
|
||||
mem::transmute::<&ffi::XIAnyClassInfo, &ffi::XIValuatorClassInfo>(class)
|
||||
};
|
||||
if let Some(&mut (_, ref mut axis)) = self
|
||||
.scroll_axes
|
||||
.iter_mut()
|
||||
.find(|&&mut (axis, _)| axis == info.number)
|
||||
{
|
||||
axis.position = info.value;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ impl Eq for MonitorHandle {}
|
||||
|
||||
impl PartialOrd for MonitorHandle {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ impl XConnection {
|
||||
let overlapping_area = window_rect.get_overlapping_area(&monitor.rect);
|
||||
if overlapping_area > largest_overlap {
|
||||
largest_overlap = overlapping_area;
|
||||
matched_monitor = &monitor;
|
||||
matched_monitor = monitor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,8 +242,11 @@ impl XConnection {
|
||||
if is_active {
|
||||
let is_primary = *(*crtc).outputs.offset(0) == primary;
|
||||
has_primary |= is_primary;
|
||||
MonitorHandle::new(self, resources, crtc_id, crtc, is_primary)
|
||||
.map(|monitor_id| available.push(monitor_id));
|
||||
if let Some(monitor_id) =
|
||||
MonitorHandle::new(self, resources, crtc_id, crtc, is_primary)
|
||||
{
|
||||
available.push(monitor_id)
|
||||
}
|
||||
}
|
||||
(self.xrandr.XRRFreeCrtcInfo)(crtc);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ impl Format {
|
||||
|
||||
pub fn get_actual_size(&self) -> usize {
|
||||
match self {
|
||||
&Format::Char => mem::size_of::<c_char>(),
|
||||
&Format::Short => mem::size_of::<c_short>(),
|
||||
&Format::Long => mem::size_of::<c_long>(),
|
||||
Format::Char => mem::size_of::<c_char>(),
|
||||
Format::Short => mem::size_of::<c_short>(),
|
||||
Format::Long => mem::size_of::<c_long>(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ impl XConnection {
|
||||
);
|
||||
|
||||
// The list of children isn't used
|
||||
if children != ptr::null_mut() {
|
||||
if !children.is_null() {
|
||||
(self.xlib.XFree)(children as *mut _);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ impl Icon {
|
||||
data.push(rgba_icon.height as Cardinal);
|
||||
let pixels = rgba_icon.rgba.as_ptr() as *const Pixel;
|
||||
for pixel_index in 0..pixel_count {
|
||||
let pixel = unsafe { &*pixels.offset(pixel_index as isize) };
|
||||
let pixel = unsafe { &*pixels.add(pixel_index) };
|
||||
data.push(pixel.to_packed_argb());
|
||||
}
|
||||
data
|
||||
|
||||
@@ -36,7 +36,7 @@ impl Iterator for KeymapIter<'_> {
|
||||
|
||||
fn next(&mut self) -> Option<ffi::KeyCode> {
|
||||
if self.item.is_none() {
|
||||
while let Some((index, &item)) = self.iter.next() {
|
||||
for (index, &item) in self.iter.by_ref() {
|
||||
if item != 0 {
|
||||
self.index = index;
|
||||
self.item = Some(item);
|
||||
|
||||
@@ -151,7 +151,7 @@ impl ModifierKeyState {
|
||||
|
||||
pub fn key_release(&mut self, keycode: ffi::KeyCode) {
|
||||
if let Some(modifier) = self.keys.remove(&keycode) {
|
||||
if self.keys.values().find(|&&m| m == modifier).is_none() {
|
||||
if !self.keys.values().any(|&m| m == modifier) {
|
||||
set_modifier(&mut self.state, modifier, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +39,15 @@ impl XConnection {
|
||||
pub unsafe fn get_xft_dpi(&self) -> Option<f64> {
|
||||
(self.xlib.XrmInitialize)();
|
||||
let resource_manager_str = (self.xlib.XResourceManagerString)(self.display);
|
||||
if resource_manager_str == ptr::null_mut() {
|
||||
if resource_manager_str.is_null() {
|
||||
return None;
|
||||
}
|
||||
if let Ok(res) = ::std::ffi::CStr::from_ptr(resource_manager_str).to_str() {
|
||||
let name: &str = "Xft.dpi:\t";
|
||||
for pair in res.split("\n") {
|
||||
for pair in res.split('\n') {
|
||||
if pair.starts_with(&name) {
|
||||
let res = &pair[name.len()..];
|
||||
return f64::from_str(&res).ok();
|
||||
return f64::from_str(res).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ impl XConnection {
|
||||
quantity_returned,
|
||||
new_data,
|
||||
);*/
|
||||
data.extend_from_slice(&new_data);
|
||||
data.extend_from_slice(new_data);
|
||||
// Fun fact: XGetWindowProperty allocates one extra byte at the end.
|
||||
(self.xlib.XFree)(buf as _); // Don't try to access new_data after this.
|
||||
} else {
|
||||
|
||||
@@ -62,11 +62,7 @@ impl XConnection {
|
||||
|
||||
let wm_check = result.ok().and_then(|wm_check| wm_check.get(0).cloned());
|
||||
|
||||
if let Some(wm_check) = wm_check {
|
||||
wm_check
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
wm_check?
|
||||
};
|
||||
|
||||
// Querying the same property on the child window we were given, we should get this child
|
||||
@@ -76,11 +72,7 @@ impl XConnection {
|
||||
|
||||
let wm_check = result.ok().and_then(|wm_check| wm_check.get(0).cloned());
|
||||
|
||||
if let Some(wm_check) = wm_check {
|
||||
wm_check
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
wm_check?
|
||||
};
|
||||
|
||||
// These values should be the same.
|
||||
|
||||
@@ -150,7 +150,7 @@ impl UnownedWindow {
|
||||
|
||||
let position = window_attrs
|
||||
.position
|
||||
.map(|position| position.to_physical::<i32>(scale_factor).into());
|
||||
.map(|position| position.to_physical::<i32>(scale_factor));
|
||||
|
||||
let dimensions = {
|
||||
// x11 only applies constraints when the window is actively resized
|
||||
@@ -184,7 +184,7 @@ impl UnownedWindow {
|
||||
// creating
|
||||
let (visual, depth, require_colormap) = match pl_attribs.visual_infos {
|
||||
Some(vi) => (vi.visual, vi.depth, false),
|
||||
None if window_attrs.transparent == true => {
|
||||
None if window_attrs.transparent => {
|
||||
// Find a suitable visual
|
||||
let mut vinfo = MaybeUninit::uninit();
|
||||
let vinfo_initialized = unsafe {
|
||||
@@ -341,7 +341,9 @@ impl UnownedWindow {
|
||||
} //.queue();
|
||||
}
|
||||
|
||||
window.set_pid().map(|flusher| flusher.queue());
|
||||
if let Some(flusher) = window.set_pid() {
|
||||
flusher.queue()
|
||||
}
|
||||
|
||||
window.set_window_types(pl_attribs.x11_window_types).queue();
|
||||
|
||||
@@ -430,8 +432,7 @@ impl UnownedWindow {
|
||||
}
|
||||
|
||||
// Select XInput2 events
|
||||
let mask = {
|
||||
let mask = ffi::XI_MotionMask
|
||||
let mask = ffi::XI_MotionMask
|
||||
| ffi::XI_ButtonPressMask
|
||||
| ffi::XI_ButtonReleaseMask
|
||||
//| ffi::XI_KeyPressMask
|
||||
@@ -443,8 +444,6 @@ impl UnownedWindow {
|
||||
| ffi::XI_TouchBeginMask
|
||||
| ffi::XI_TouchUpdateMask
|
||||
| ffi::XI_TouchEndMask;
|
||||
mask
|
||||
};
|
||||
xconn
|
||||
.select_xinput_events(window.xwindow, ffi::XIAllMasterDevices, mask)
|
||||
.queue();
|
||||
@@ -467,9 +466,10 @@ impl UnownedWindow {
|
||||
window.set_maximized_inner(window_attrs.maximized).queue();
|
||||
}
|
||||
if window_attrs.fullscreen.is_some() {
|
||||
window
|
||||
.set_fullscreen_inner(window_attrs.fullscreen.clone())
|
||||
.map(|flusher| flusher.queue());
|
||||
if let Some(flusher) = window.set_fullscreen_inner(window_attrs.fullscreen.clone())
|
||||
{
|
||||
flusher.queue()
|
||||
}
|
||||
|
||||
if let Some(PhysicalPosition { x, y }) = position {
|
||||
let shared_state = window.shared_state.get_mut();
|
||||
|
||||
@@ -118,8 +118,6 @@ pub enum NSWindowLevel {
|
||||
NSScreenSaverWindowLevel = kCGScreenSaverWindowLevelKey as _,
|
||||
}
|
||||
|
||||
pub const NSStringEnumerationByComposedCharacterSequences: NSUInteger = 2;
|
||||
|
||||
pub type CGDisplayFadeInterval = f32;
|
||||
pub type CGDisplayReservationInterval = f32;
|
||||
pub type CGDisplayBlendFraction = f32;
|
||||
@@ -165,9 +163,18 @@ pub const IO8BitOverlayPixels: &str = "O8";
|
||||
pub type CGWindowLevel = i32;
|
||||
pub type CGDisplayModeRef = *mut c_void;
|
||||
|
||||
// `CGDisplayCreateUUIDFromDisplayID` comes from the `ColorSync` framework.
|
||||
// However, that framework was only introduced "publicly" in macOS 10.13.
|
||||
//
|
||||
// Since we want to support older versions, we can't link to `ColorSync`
|
||||
// directly. Fortunately, it has always been available as a subframework of
|
||||
// `ApplicationServices`, see:
|
||||
// https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html#//apple_ref/doc/uid/TP40001067-CH210-BBCFFIEG
|
||||
//
|
||||
// TODO: Remove the WINIT_LINK_COLORSYNC hack, it is probably not needed.
|
||||
#[cfg_attr(
|
||||
not(use_colorsync_cgdisplaycreateuuidfromdisplayid),
|
||||
link(name = "CoreGraphics", kind = "framework")
|
||||
link(name = "ApplicationServices", kind = "framework")
|
||||
)]
|
||||
#[cfg_attr(
|
||||
use_colorsync_cgdisplaycreateuuidfromdisplayid,
|
||||
|
||||
@@ -162,6 +162,7 @@ impl fmt::Debug for MonitorHandle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// TODO: Do this using the proper fmt API
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
struct MonitorHandle {
|
||||
name: Option<String>,
|
||||
native_identifier: u32,
|
||||
|
||||
@@ -3,13 +3,8 @@ mod cursor;
|
||||
|
||||
pub use self::{cursor::*, r#async::*};
|
||||
|
||||
use std::{
|
||||
cell::Cell,
|
||||
ops::{BitAnd, Deref},
|
||||
rc::Rc,
|
||||
};
|
||||
use std::ops::{BitAnd, Deref};
|
||||
|
||||
use block::ConcreteBlock;
|
||||
use cocoa::{
|
||||
appkit::{NSApp, NSWindowStyleMask},
|
||||
base::{id, nil},
|
||||
@@ -18,12 +13,8 @@ use cocoa::{
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
||||
|
||||
use crate::{
|
||||
dpi::LogicalPosition,
|
||||
platform_impl::platform::ffi::{
|
||||
self, NSRange, NSStringEnumerationByComposedCharacterSequences,
|
||||
},
|
||||
};
|
||||
use crate::dpi::LogicalPosition;
|
||||
use crate::platform_impl::platform::ffi;
|
||||
|
||||
// Replace with `!` once stable
|
||||
#[derive(Debug)]
|
||||
@@ -113,31 +104,6 @@ pub unsafe fn ns_string_id_ref(s: &str) -> IdRef {
|
||||
IdRef::new(NSString::alloc(nil).init_str(s))
|
||||
}
|
||||
|
||||
/// Returns the number of characters in a string.
|
||||
/// (A single character may consist of multiple UTF-32 code units.
|
||||
/// This is possible when long sequences of composing characters are present)
|
||||
///
|
||||
/// Unsafe because assumes that the `string` is an `NSString` object
|
||||
pub unsafe fn ns_string_char_count(string: id) -> usize {
|
||||
let length: NSUInteger = msg_send![string, length];
|
||||
let range = NSRange {
|
||||
location: 0,
|
||||
length,
|
||||
};
|
||||
let char_count = Rc::new(Cell::new(0));
|
||||
let block = {
|
||||
let char_count = char_count.clone();
|
||||
ConcreteBlock::new(move || char_count.set(char_count.get() + 1)).copy()
|
||||
};
|
||||
let block = &*block;
|
||||
let () = msg_send![string,
|
||||
enumerateSubstringsInRange:range
|
||||
options:NSStringEnumerationByComposedCharacterSequences
|
||||
usingBlock:block
|
||||
];
|
||||
char_count.get()
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // In case we want to use this function in the future
|
||||
pub unsafe fn app_name() -> Option<id> {
|
||||
let bundle: id = msg_send![class!(NSBundle), mainBundle];
|
||||
|
||||
@@ -29,7 +29,7 @@ use crate::{
|
||||
scancode_to_keycode, EventWrapper,
|
||||
},
|
||||
ffi::*,
|
||||
util::{self, ns_string_char_count, IdRef},
|
||||
util::{self, IdRef},
|
||||
window::get_window_id,
|
||||
DEVICE_ID,
|
||||
},
|
||||
@@ -57,8 +57,6 @@ pub(super) struct ViewState {
|
||||
raw_characters: Option<String>,
|
||||
pub(super) modifiers: ModifiersState,
|
||||
tracking_rect: Option<NSInteger>,
|
||||
is_ime_activated: bool,
|
||||
marked_text: id,
|
||||
}
|
||||
|
||||
impl ViewState {
|
||||
@@ -70,8 +68,6 @@ impl ViewState {
|
||||
pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<CursorState>>) {
|
||||
let cursor_state = Default::default();
|
||||
let cursor_access = Arc::downgrade(&cursor_state);
|
||||
let marked_text =
|
||||
unsafe { <id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil)) };
|
||||
let state = ViewState {
|
||||
ns_window,
|
||||
cursor_state,
|
||||
@@ -79,8 +75,6 @@ pub fn new_view(ns_window: id) -> (IdRef, Weak<Mutex<CursorState>>) {
|
||||
raw_characters: None,
|
||||
modifiers: Default::default(),
|
||||
tracking_rect: None,
|
||||
is_ime_activated: false,
|
||||
marked_text,
|
||||
};
|
||||
unsafe {
|
||||
// This is free'd in `dealloc`
|
||||
@@ -153,10 +147,7 @@ lazy_static! {
|
||||
sel!(setMarkedText:selectedRange:replacementRange:),
|
||||
set_marked_text as extern "C" fn(&mut Object, Sel, id, NSRange, NSRange),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(unmarkText),
|
||||
unmark_text as extern "C" fn(&mut Object, Sel),
|
||||
);
|
||||
decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));
|
||||
decl.add_method(
|
||||
sel!(validAttributesForMarkedText),
|
||||
valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,
|
||||
@@ -168,7 +159,7 @@ lazy_static! {
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(insertText:replacementRange:),
|
||||
insert_text as extern "C" fn(&mut Object, Sel, id, NSRange),
|
||||
insert_text as extern "C" fn(&Object, Sel, id, NSRange),
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(characterIndexForPoint:),
|
||||
@@ -267,6 +258,7 @@ lazy_static! {
|
||||
accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,
|
||||
);
|
||||
decl.add_ivar::<*mut c_void>("winitState");
|
||||
decl.add_ivar::<id>("markedText");
|
||||
let protocol = Protocol::get("NSTextInputClient").unwrap();
|
||||
decl.add_protocol(&protocol);
|
||||
ViewClass(decl.register())
|
||||
@@ -276,9 +268,9 @@ lazy_static! {
|
||||
extern "C" fn dealloc(this: &Object, _sel: Sel) {
|
||||
unsafe {
|
||||
let state: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = state as *mut ViewState;
|
||||
let _: () = msg_send![(*state).marked_text, release];
|
||||
Box::from_raw(state);
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
let _: () = msg_send![marked_text, release];
|
||||
Box::from_raw(state as *mut ViewState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +279,9 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
|
||||
let this: id = msg_send![this, init];
|
||||
if this != nil {
|
||||
(*this).set_ivar("winitState", state);
|
||||
let marked_text =
|
||||
<id as NSMutableAttributedString>::init(NSMutableAttributedString::alloc(nil));
|
||||
(*this).set_ivar("markedText", marked_text);
|
||||
let _: () = msg_send![this, setPostsFrameChangedNotifications: YES];
|
||||
|
||||
let notification_center: &Object =
|
||||
@@ -393,20 +388,17 @@ extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
||||
extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
||||
unsafe {
|
||||
trace!("Triggered `hasMarkedText`");
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
let retval = (state.marked_text.length() > 0) as BOOL;
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
trace!("Completed `hasMarkedText`");
|
||||
retval
|
||||
(marked_text.length() > 0) as BOOL
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
||||
unsafe {
|
||||
trace!("Triggered `markedRange`");
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
let length = state.marked_text.length();
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
let length = marked_text.length();
|
||||
trace!("Completed `markedRange`");
|
||||
if length > 0 {
|
||||
NSRange::new(0, length - 1)
|
||||
@@ -431,62 +423,32 @@ extern "C" fn set_marked_text(
|
||||
) {
|
||||
trace!("Triggered `setMarkedText`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
||||
// Delete previous marked text
|
||||
let char_count = ns_string_char_count(state.marked_text.string());
|
||||
delete_marked_text(state, char_count);
|
||||
|
||||
state.is_ime_activated = true;
|
||||
|
||||
let _: () = msg_send![state.marked_text, release];
|
||||
state.marked_text = NSMutableAttributedString::alloc(nil);
|
||||
let marked_text_ref: &mut id = this.get_mut_ivar("markedText");
|
||||
let _: () = msg_send![(*marked_text_ref), release];
|
||||
let marked_text = NSMutableAttributedString::alloc(nil);
|
||||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)];
|
||||
if has_attr {
|
||||
state.marked_text.initWithAttributedString(string);
|
||||
marked_text.initWithAttributedString(string);
|
||||
} else {
|
||||
state.marked_text.initWithString(string);
|
||||
marked_text.initWithString(string);
|
||||
};
|
||||
|
||||
let text_ns_str = state.marked_text.string();
|
||||
let slice = slice::from_raw_parts(
|
||||
text_ns_str.UTF8String() as *const c_uchar,
|
||||
text_ns_str.len(),
|
||||
);
|
||||
let text_str = str::from_utf8_unchecked(slice);
|
||||
|
||||
for character in text_str.chars() {
|
||||
AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: WindowId(get_window_id(state.ns_window)),
|
||||
event: WindowEvent::ReceivedCharacter(character),
|
||||
}));
|
||||
}
|
||||
*marked_text_ref = marked_text;
|
||||
}
|
||||
trace!("Completed `setMarkedText`");
|
||||
}
|
||||
|
||||
extern "C" fn unmark_text(this: &mut Object, _sel: Sel) {
|
||||
extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
||||
trace!("Triggered `unmarkText`");
|
||||
unsafe {
|
||||
clear_marked_text(this);
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
let mutable_string = marked_text.mutableString();
|
||||
let _: () = msg_send![mutable_string, setString:""];
|
||||
let input_context: id = msg_send![this, inputContext];
|
||||
let _: () = msg_send![input_context, discardMarkedText];
|
||||
}
|
||||
trace!("Completed `unmarkText`");
|
||||
}
|
||||
|
||||
/// Unsafe because assumes that `this` is an instance of the `WinitView` class that we declare
|
||||
/// programmatically
|
||||
unsafe fn clear_marked_text(this: &mut Object) {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
||||
let _: () = msg_send![state.marked_text, release];
|
||||
state.marked_text = NSMutableAttributedString::alloc(nil);
|
||||
|
||||
let input_context: id = msg_send![this, inputContext];
|
||||
let _: () = msg_send![input_context, discardMarkedText];
|
||||
}
|
||||
|
||||
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
||||
trace!("Triggered `validAttributesForMarkedText`");
|
||||
trace!("Completed `validAttributesForMarkedText`");
|
||||
@@ -534,19 +496,12 @@ extern "C" fn first_rect_for_character_range(
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn insert_text(this: &mut Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||
extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||
trace!("Triggered `insertText`");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
||||
let is_ime_activated: bool = state.is_ime_activated;
|
||||
if is_ime_activated {
|
||||
clear_marked_text(this);
|
||||
state.is_ime_activated = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let has_attr = msg_send![string, isKindOfClass: class!(NSAttributedString)];
|
||||
let characters = if has_attr {
|
||||
// This is a *mut NSAttributedString
|
||||
@@ -613,15 +568,6 @@ extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
||||
trace!("Completed `doCommandBySelector`");
|
||||
}
|
||||
|
||||
fn delete_marked_text(state: &mut ViewState, count: usize) {
|
||||
for _ in 0..count {
|
||||
AppState::queue_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||
window_id: WindowId(get_window_id(state.ns_window)),
|
||||
event: WindowEvent::ReceivedCharacter('\u{7f}'), // fire DELETE
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
fn get_characters(event: id, ignore_modifiers: bool) -> String {
|
||||
unsafe {
|
||||
let characters: id = if ignore_modifiers {
|
||||
|
||||
@@ -89,6 +89,20 @@ impl Canvas {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), RootOE> {
|
||||
if grab {
|
||||
self.raw().request_pointer_lock();
|
||||
} else {
|
||||
let window = web_sys::window()
|
||||
.ok_or(os_error!(OsError("Failed to obtain window".to_owned())))?;
|
||||
let document = window
|
||||
.document()
|
||||
.ok_or(os_error!(OsError("Failed to obtain document".to_owned())))?;
|
||||
document.exit_pointer_lock();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_attribute(&self, attribute: &str, value: &str) {
|
||||
self.common
|
||||
.raw
|
||||
|
||||
@@ -79,9 +79,11 @@ impl PointerHandler {
|
||||
event::mouse_button(&event),
|
||||
event::mouse_modifiers(&event),
|
||||
);
|
||||
canvas
|
||||
.set_pointer_capture(event.pointer_id())
|
||||
.expect("Failed to set pointer capture");
|
||||
|
||||
// Error is swallowed here since the error would occur every time the mouse is
|
||||
// clicked when the cursor is grabbed, and there is probably not a situation where
|
||||
// this could fail, that we care if it fails.
|
||||
let _e = canvas.set_pointer_capture(event.pointer_id());
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
@@ -207,8 +207,11 @@ impl Window {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_cursor_grab(&self, _grab: bool) -> Result<(), ExternalError> {
|
||||
Err(ExternalError::NotSupported(NotSupportedError::new()))
|
||||
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
|
||||
self.canvas
|
||||
.borrow()
|
||||
.set_cursor_grab(grab)
|
||||
.map_err(|e| ExternalError::Os(e))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -16,6 +16,7 @@ use winapi::{
|
||||
shared::{
|
||||
minwindef::{HINSTANCE, LPARAM, UINT, WPARAM},
|
||||
windef::{HWND, POINT, POINTS, RECT},
|
||||
winerror::SUCCEEDED,
|
||||
},
|
||||
um::{
|
||||
combaseapi, dwmapi,
|
||||
@@ -699,22 +700,6 @@ impl<'a, T: 'static> InitData<'a, T> {
|
||||
let dpi = hwnd_dpi(window);
|
||||
let scale_factor = dpi_to_scale_factor(dpi);
|
||||
|
||||
// making the window transparent
|
||||
if self.attributes.transparent && !self.pl_attribs.no_redirection_bitmap {
|
||||
// Empty region for the blur effect, so the window is fully transparent
|
||||
let region = CreateRectRgn(0, 0, -1, -1);
|
||||
|
||||
let bb = dwmapi::DWM_BLURBEHIND {
|
||||
dwFlags: dwmapi::DWM_BB_ENABLE | dwmapi::DWM_BB_BLURREGION,
|
||||
fEnable: 1,
|
||||
hRgnBlur: region,
|
||||
fTransitionOnMaximized: 0,
|
||||
};
|
||||
|
||||
dwmapi::DwmEnableBlurBehindWindow(window, &bb);
|
||||
DeleteObject(region as _);
|
||||
}
|
||||
|
||||
// If the system theme is dark, we need to set the window theme now
|
||||
// before we update the window flags (and possibly show the
|
||||
// window for the first time).
|
||||
@@ -809,6 +794,28 @@ impl<'a, T: 'static> InitData<'a, T> {
|
||||
|
||||
pub unsafe fn on_create(&mut self) {
|
||||
let win = self.window.as_mut().expect("failed window creation");
|
||||
|
||||
// making the window transparent
|
||||
if self.attributes.transparent && !self.pl_attribs.no_redirection_bitmap {
|
||||
// Empty region for the blur effect, so the window is fully transparent
|
||||
let region = CreateRectRgn(0, 0, -1, -1);
|
||||
|
||||
let bb = dwmapi::DWM_BLURBEHIND {
|
||||
dwFlags: dwmapi::DWM_BB_ENABLE | dwmapi::DWM_BB_BLURREGION,
|
||||
fEnable: 1,
|
||||
hRgnBlur: region,
|
||||
fTransitionOnMaximized: 0,
|
||||
};
|
||||
let hr = dwmapi::DwmEnableBlurBehindWindow(win.hwnd(), &bb);
|
||||
if !SUCCEEDED(hr) {
|
||||
warn!(
|
||||
"Setting transparent window is failed. HRESULT Code: 0x{:X}",
|
||||
hr
|
||||
);
|
||||
}
|
||||
DeleteObject(region as _);
|
||||
}
|
||||
|
||||
let attributes = self.attributes.clone();
|
||||
|
||||
// Set visible before setting the size to ensure the
|
||||
|
||||
@@ -496,6 +496,19 @@ impl Window {
|
||||
/// See `outer_position` for more information about the coordinates. This automatically un-maximizes the
|
||||
/// window if it's maximized.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalPosition, PhysicalPosition};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the position in logical dimensions like this:
|
||||
/// window.set_outer_position(LogicalPosition::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the position in physical dimensions like this:
|
||||
/// window.set_outer_position(PhysicalPosition::new(400, 200));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS:** Can only be called on the main thread. Sets the top left coordinates of the
|
||||
@@ -528,6 +541,19 @@ impl Window {
|
||||
/// See `inner_size` for more information about the values. This automatically un-maximizes the
|
||||
/// window if it's maximized.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the size in logical dimensions like this:
|
||||
/// window.set_inner_size(LogicalSize::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the size in physical dimensions like this:
|
||||
/// window.set_inner_size(PhysicalSize::new(400, 200));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android:** Unsupported.
|
||||
@@ -555,6 +581,19 @@ impl Window {
|
||||
|
||||
/// Sets a minimum dimension size for the window.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the size in logical dimensions like this:
|
||||
/// window.set_min_inner_size(Some(LogicalSize::new(400.0, 200.0)));
|
||||
///
|
||||
/// // Or specify the size in physical dimensions like this:
|
||||
/// window.set_min_inner_size(Some(PhysicalSize::new(400, 200)));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web:** Unsupported.
|
||||
@@ -565,6 +604,19 @@ impl Window {
|
||||
|
||||
/// Sets a maximum dimension size for the window.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalSize, PhysicalSize};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the size in logical dimensions like this:
|
||||
/// window.set_max_inner_size(Some(LogicalSize::new(400.0, 200.0)));
|
||||
///
|
||||
/// // Or specify the size in physical dimensions like this:
|
||||
/// window.set_max_inner_size(Some(PhysicalSize::new(400, 200)));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web:** Unsupported.
|
||||
@@ -727,6 +779,19 @@ impl Window {
|
||||
|
||||
/// Sets location of IME candidate box in client area coordinates relative to the top left.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalPosition, PhysicalPosition};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the position in logical dimensions like this:
|
||||
/// window.set_ime_position(LogicalPosition::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the position in physical dimensions like this:
|
||||
/// window.set_ime_position(PhysicalPosition::new(400, 200));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web:** Unsupported.
|
||||
@@ -783,6 +848,19 @@ impl Window {
|
||||
|
||||
/// Changes the position of the cursor in window coordinates.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use winit::dpi::{LogicalPosition, PhysicalPosition};
|
||||
/// # use winit::event_loop::EventLoop;
|
||||
/// # use winit::window::Window;
|
||||
/// # let mut event_loop = EventLoop::new();
|
||||
/// # let window = Window::new(&event_loop).unwrap();
|
||||
/// // Specify the position in logical dimensions like this:
|
||||
/// window.set_cursor_position(LogicalPosition::new(400.0, 200.0));
|
||||
///
|
||||
/// // Or specify the position in physical dimensions like this:
|
||||
/// window.set_cursor_position(PhysicalPosition::new(400, 200));
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **iOS / Android / Web / Wayland:** Always returns an [`ExternalError::NotSupported`].
|
||||
@@ -799,7 +877,7 @@ impl Window {
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **macOS:** This locks the cursor in a fixed location, which looks visually awkward.
|
||||
/// - **iOS / Android / Web:** Always returns an [`ExternalError::NotSupported`].
|
||||
/// - **iOS / Android:** Always returns an [`ExternalError::NotSupported`].
|
||||
#[inline]
|
||||
pub fn set_cursor_grab(&self, grab: bool) -> Result<(), ExternalError> {
|
||||
self.window.set_cursor_grab(grab)
|
||||
|
||||
Reference in New Issue
Block a user