Detailed changes
@@ -748,7 +748,7 @@ impl Size<Length> {
/// assert_eq!(bounds.origin, origin);
/// assert_eq!(bounds.size, size);
/// ```
-#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
+#[derive(Refineable, Copy, Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
#[refineable(Debug)]
#[repr(C)]
pub struct Bounds<T: Clone + Debug + Default + PartialEq> {
@@ -1676,8 +1676,6 @@ impl Bounds<DevicePixels> {
}
}
-impl<T: Copy + Clone + Debug + Default + PartialEq> Copy for Bounds<T> {}
-
/// Represents the edges of a box in a 2D space, such as padding or margin.
///
/// Each field represents the size of the edge on one side of the box: `top`, `right`, `bottom`, and `left`.
@@ -116,17 +116,16 @@ impl WindowsWindowInner {
}
fn handle_move_msg(&self, handle: HWND, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
let origin = logical_point(
lparam.signed_loword() as f32,
lparam.signed_hiword() as f32,
- lock.scale_factor,
+ self.state.scale_factor.get(),
);
- lock.origin = origin;
- let size = lock.logical_size;
+ self.state.origin.set(origin);
+ let size = self.state.logical_size.get();
let center_x = origin.x.0 + size.width.0 / 2.;
let center_y = origin.y.0 + size.height.0 / 2.;
- let monitor_bounds = lock.display.bounds();
+ let monitor_bounds = self.state.display.get().bounds();
if center_x < monitor_bounds.left().0
|| center_x > monitor_bounds.right().0
|| center_y < monitor_bounds.top().0
@@ -136,42 +135,42 @@ impl WindowsWindowInner {
let monitor = unsafe { MonitorFromWindow(handle, MONITOR_DEFAULTTONULL) };
// minimize the window can trigger this event too, in this case,
// monitor is invalid, we do nothing.
- if !monitor.is_invalid() && lock.display.handle != monitor {
+ if !monitor.is_invalid() && self.state.display.get().handle != monitor {
// we will get the same monitor if we only have one
- lock.display = WindowsDisplay::new_with_handle(monitor).log_err()?;
+ self.state
+ .display
+ .set(WindowsDisplay::new_with_handle(monitor).log_err()?);
}
}
- if let Some(mut callback) = lock.callbacks.moved.take() {
- drop(lock);
+ if let Some(mut callback) = self.state.callbacks.moved.take() {
callback();
- self.state.borrow_mut().callbacks.moved = Some(callback);
+ self.state.callbacks.moved.set(Some(callback));
}
Some(0)
}
fn handle_get_min_max_info_msg(&self, lparam: LPARAM) -> Option<isize> {
- let lock = self.state.borrow();
- let min_size = lock.min_size?;
- let scale_factor = lock.scale_factor;
- let boarder_offset = lock.border_offset;
- drop(lock);
+ let min_size = self.state.min_size?;
+ let scale_factor = self.state.scale_factor.get();
+ let boarder_offset = &self.state.border_offset;
+
unsafe {
let minmax_info = &mut *(lparam.0 as *mut MINMAXINFO);
minmax_info.ptMinTrackSize.x =
- min_size.width.scale(scale_factor).0 as i32 + boarder_offset.width_offset;
+ min_size.width.scale(scale_factor).0 as i32 + boarder_offset.width_offset.get();
minmax_info.ptMinTrackSize.y =
- min_size.height.scale(scale_factor).0 as i32 + boarder_offset.height_offset;
+ min_size.height.scale(scale_factor).0 as i32 + boarder_offset.height_offset.get();
}
Some(0)
}
fn handle_size_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
-
// Don't resize the renderer when the window is minimized, but record that it was minimized so
// that on restore the swap chain can be recreated via `update_drawable_size_even_if_unchanged`.
if wparam.0 == SIZE_MINIMIZED as usize {
- lock.restore_from_minimized = lock.callbacks.request_frame.take();
+ self.state
+ .restore_from_minimized
+ .set(self.state.callbacks.request_frame.take());
return Some(0);
}
@@ -179,14 +178,16 @@ impl WindowsWindowInner {
let height = lparam.hiword().max(1) as i32;
let new_size = size(DevicePixels(width), DevicePixels(height));
- let scale_factor = lock.scale_factor;
+ let scale_factor = self.state.scale_factor.get();
let mut should_resize_renderer = false;
- if lock.restore_from_minimized.is_some() {
- lock.callbacks.request_frame = lock.restore_from_minimized.take();
+ if let Some(restore_from_minimized) = self.state.restore_from_minimized.take() {
+ self.state
+ .callbacks
+ .request_frame
+ .set(Some(restore_from_minimized));
} else {
should_resize_renderer = true;
}
- drop(lock);
self.handle_size_change(new_size, scale_factor, should_resize_renderer);
Some(0)
@@ -199,17 +200,19 @@ impl WindowsWindowInner {
should_resize_renderer: bool,
) {
let new_logical_size = device_size.to_pixels(scale_factor);
- let mut lock = self.state.borrow_mut();
- lock.logical_size = new_logical_size;
- if should_resize_renderer && let Err(e) = lock.renderer.resize(device_size) {
+
+ self.state.logical_size.set(new_logical_size);
+ if should_resize_renderer
+ && let Err(e) = self.state.renderer.borrow_mut().resize(device_size)
+ {
log::error!("Failed to resize renderer, invalidating devices: {}", e);
- lock.invalidate_devices
+ self.state
+ .invalidate_devices
.store(true, std::sync::atomic::Ordering::Release);
}
- if let Some(mut callback) = lock.callbacks.resize.take() {
- drop(lock);
+ if let Some(mut callback) = self.state.callbacks.resize.take() {
callback(new_logical_size, scale_factor);
- self.state.borrow_mut().callbacks.resize = Some(callback);
+ self.state.callbacks.resize.set(Some(callback));
}
}
@@ -254,17 +257,14 @@ impl WindowsWindowInner {
}
fn handle_close_msg(&self) -> Option<isize> {
- let mut callback = self.state.borrow_mut().callbacks.should_close.take()?;
+ let mut callback = self.state.callbacks.should_close.take()?;
let should_close = callback();
- self.state.borrow_mut().callbacks.should_close = Some(callback);
+ self.state.callbacks.should_close.set(Some(callback));
if should_close { None } else { Some(0) }
}
fn handle_destroy_msg(&self, handle: HWND) -> Option<isize> {
- let callback = {
- let mut lock = self.state.borrow_mut();
- lock.callbacks.close.take()
- };
+ let callback = { self.state.callbacks.close.take() };
if let Some(callback) = callback {
callback();
}
@@ -283,12 +283,10 @@ impl WindowsWindowInner {
fn handle_mouse_move_msg(&self, handle: HWND, lparam: LPARAM, wparam: WPARAM) -> Option<isize> {
self.start_tracking_mouse(handle, TME_LEAVE);
- let mut lock = self.state.borrow_mut();
- let Some(mut func) = lock.callbacks.input.take() else {
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
- let scale_factor = lock.scale_factor;
- drop(lock);
+ let scale_factor = self.state.scale_factor.get();
let pressed_button = match MODIFIERKEYS_FLAGS(wparam.loword() as u32) {
flags if flags.contains(MK_LBUTTON) => Some(MouseButton::Left),
@@ -310,32 +308,32 @@ impl WindowsWindowInner {
modifiers: current_modifiers(),
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
fn handle_mouse_leave_msg(&self) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- lock.hovered = false;
- if let Some(mut callback) = lock.callbacks.hovered_status_change.take() {
- drop(lock);
+ self.state.hovered.set(false);
+ if let Some(mut callback) = self.state.callbacks.hovered_status_change.take() {
callback(false);
- self.state.borrow_mut().callbacks.hovered_status_change = Some(callback);
+ self.state
+ .callbacks
+ .hovered_status_change
+ .set(Some(callback));
}
Some(0)
}
fn handle_syskeyup_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- let input = handle_key_event(wparam, lparam, &mut lock, |keystroke, _| {
+ let input = handle_key_event(wparam, lparam, &self.state, |keystroke, _| {
PlatformInput::KeyUp(KeyUpEvent { keystroke })
})?;
- let mut func = lock.callbacks.input.take()?;
- drop(lock);
+ let mut func = self.state.callbacks.input.take()?;
+
func(input);
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
// Always return 0 to indicate that the message was handled, so we could properly handle `ModifiersChanged` event.
Some(0)
@@ -344,11 +342,10 @@ impl WindowsWindowInner {
// It's a known bug that you can't trigger `ctrl-shift-0`. See:
// https://superuser.com/questions/1455762/ctrl-shift-number-key-combination-has-stopped-working-for-a-few-numbers
fn handle_keydown_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
let Some(input) = handle_key_event(
wparam,
lparam,
- &mut lock,
+ &self.state,
|keystroke, prefer_character_input| {
PlatformInput::KeyDown(KeyDownEvent {
keystroke,
@@ -359,34 +356,31 @@ impl WindowsWindowInner {
) else {
return Some(1);
};
- drop(lock);
- let Some(mut func) = self.state.borrow_mut().callbacks.input.take() else {
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
fn handle_keyup_msg(&self, wparam: WPARAM, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- let Some(input) = handle_key_event(wparam, lparam, &mut lock, |keystroke, _| {
+ let Some(input) = handle_key_event(wparam, lparam, &self.state, |keystroke, _| {
PlatformInput::KeyUp(KeyUpEvent { keystroke })
}) else {
return Some(1);
};
- let Some(mut func) = lock.callbacks.input.take() else {
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
- drop(lock);
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
@@ -407,16 +401,15 @@ impl WindowsWindowInner {
lparam: LPARAM,
) -> Option<isize> {
unsafe { SetCapture(handle) };
- let mut lock = self.state.borrow_mut();
- let Some(mut func) = lock.callbacks.input.take() else {
+
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
let x = lparam.signed_loword();
let y = lparam.signed_hiword();
let physical_point = point(DevicePixels(x as i32), DevicePixels(y as i32));
- let click_count = lock.click_state.update(button, physical_point);
- let scale_factor = lock.scale_factor;
- drop(lock);
+ let click_count = self.state.click_state.update(button, physical_point);
+ let scale_factor = self.state.scale_factor.get();
let input = PlatformInput::MouseDown(MouseDownEvent {
button,
@@ -426,7 +419,7 @@ impl WindowsWindowInner {
first_mouse: false,
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
@@ -438,15 +431,14 @@ impl WindowsWindowInner {
lparam: LPARAM,
) -> Option<isize> {
unsafe { ReleaseCapture().log_err() };
- let mut lock = self.state.borrow_mut();
- let Some(mut func) = lock.callbacks.input.take() else {
+
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
let x = lparam.signed_loword() as f32;
let y = lparam.signed_hiword() as f32;
- let click_count = lock.click_state.current_count;
- let scale_factor = lock.scale_factor;
- drop(lock);
+ let click_count = self.state.click_state.current_count.get();
+ let scale_factor = self.state.scale_factor.get();
let input = PlatformInput::MouseUp(MouseUpEvent {
button,
@@ -455,7 +447,7 @@ impl WindowsWindowInner {
click_count,
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
@@ -482,24 +474,23 @@ impl WindowsWindowInner {
lparam: LPARAM,
) -> Option<isize> {
let modifiers = current_modifiers();
- let mut lock = self.state.borrow_mut();
- let Some(mut func) = lock.callbacks.input.take() else {
+
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
- let scale_factor = lock.scale_factor;
+ let scale_factor = self.state.scale_factor.get();
let wheel_scroll_amount = match modifiers.shift {
- true => {
- self.system_settings()
- .mouse_wheel_settings
- .wheel_scroll_chars
- }
- false => {
- self.system_settings()
- .mouse_wheel_settings
- .wheel_scroll_lines
- }
+ true => self
+ .system_settings()
+ .mouse_wheel_settings
+ .wheel_scroll_chars
+ .get(),
+ false => self
+ .system_settings()
+ .mouse_wheel_settings
+ .wheel_scroll_lines
+ .get(),
};
- drop(lock);
let wheel_distance =
(wparam.signed_hiword() as f32 / WHEEL_DELTA as f32) * wheel_scroll_amount as f32;
@@ -524,7 +515,7 @@ impl WindowsWindowInner {
touch_phase: TouchPhase::Moved,
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
@@ -535,16 +526,15 @@ impl WindowsWindowInner {
wparam: WPARAM,
lparam: LPARAM,
) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- let Some(mut func) = lock.callbacks.input.take() else {
+ let Some(mut func) = self.state.callbacks.input.take() else {
return Some(1);
};
- let scale_factor = lock.scale_factor;
+ let scale_factor = self.state.scale_factor.get();
let wheel_scroll_chars = self
.system_settings()
.mouse_wheel_settings
- .wheel_scroll_chars;
- drop(lock);
+ .wheel_scroll_chars
+ .get();
let wheel_distance =
(-wparam.signed_hiword() as f32 / WHEEL_DELTA as f32) * wheel_scroll_chars as f32;
@@ -563,7 +553,7 @@ impl WindowsWindowInner {
touch_phase: TouchPhase::Moved,
});
let handled = !func(event).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { Some(1) }
}
@@ -657,11 +647,11 @@ impl WindowsWindowInner {
wparam: WPARAM,
lparam: LPARAM,
) -> Option<isize> {
- if !self.hide_title_bar || self.state.borrow().is_fullscreen() || wparam.0 == 0 {
+ if !self.hide_title_bar || self.state.is_fullscreen() || wparam.0 == 0 {
return None;
}
- let is_maximized = self.state.borrow().is_maximized();
+ let is_maximized = self.state.is_maximized();
let insets = get_client_area_insets(handle, is_maximized, self.windows_version);
// wparam is TRUE so lparam points to an NCCALCSIZE_PARAMS structure
let mut params = lparam.0 as *mut NCCALCSIZE_PARAMS;
@@ -676,7 +666,7 @@ impl WindowsWindowInner {
// used by Chrome. However, it may result in one row of pixels being obscured
// in our client area. But as Chrome says, "there seems to be no better solution."
if is_maximized
- && let Some(ref taskbar_position) = self.system_settings().auto_hide_taskbar_position
+ && let Some(taskbar_position) = self.system_settings().auto_hide_taskbar_position.get()
{
// For the auto-hide taskbar, adjust in by 1 pixel on taskbar edge,
// so the window isn't treated as a "fullscreen app", which would cause
@@ -705,11 +695,9 @@ impl WindowsWindowInner {
let this = self.clone();
self.executor
.spawn(async move {
- let mut lock = this.state.borrow_mut();
- if let Some(mut func) = lock.callbacks.active_status_change.take() {
- drop(lock);
+ if let Some(mut func) = this.state.callbacks.active_status_change.take() {
func(activated);
- this.state.borrow_mut().callbacks.active_status_change = Some(func);
+ this.state.callbacks.active_status_change.set(Some(func));
}
})
.detach();
@@ -733,12 +721,11 @@ impl WindowsWindowInner {
lparam: LPARAM,
) -> Option<isize> {
let new_dpi = wparam.loword() as f32;
- let mut lock = self.state.borrow_mut();
- let is_maximized = lock.is_maximized();
+
+ let is_maximized = self.state.is_maximized();
let new_scale_factor = new_dpi / USER_DEFAULT_SCREEN_DPI as f32;
- lock.scale_factor = new_scale_factor;
- lock.border_offset.update(handle).log_err();
- drop(lock);
+ self.state.scale_factor.set(new_scale_factor);
+ self.state.border_offset.update(handle).log_err();
if is_maximized {
// Get the monitor and its work area at the new DPI
@@ -812,7 +799,7 @@ impl WindowsWindowInner {
// Because WM_DPICHANGED, WM_MOVE, WM_SIZE will come first, window reposition and resize
// are handled there.
// So we only care about if monitor is disconnected.
- let previous_monitor = self.state.borrow().display;
+ let previous_monitor = self.state.display.get();
if WindowsDisplay::is_connected(previous_monitor.handle) {
// we are fine, other display changed
return None;
@@ -830,24 +817,22 @@ impl WindowsWindowInner {
return None;
}
let new_display = WindowsDisplay::new_with_handle(new_monitor).log_err()?;
- self.state.borrow_mut().display = new_display;
+ self.state.display.set(new_display);
Some(0)
}
fn handle_hit_test_msg(&self, handle: HWND, lparam: LPARAM) -> Option<isize> {
- if !self.is_movable || self.state.borrow().is_fullscreen() {
+ if !self.is_movable || self.state.is_fullscreen() {
return None;
}
- let callback = self
- .state
- .borrow_mut()
- .callbacks
- .hit_test_window_control
- .take();
+ let callback = self.state.callbacks.hit_test_window_control.take();
let drag_area = if let Some(mut callback) = callback {
let area = callback();
- self.state.borrow_mut().callbacks.hit_test_window_control = Some(callback);
+ self.state
+ .callbacks
+ .hit_test_window_control
+ .set(Some(callback));
if let Some(area) = area {
match area {
WindowControlArea::Drag => Some(HTCAPTION as _),
@@ -878,7 +863,7 @@ impl WindowsWindowInner {
};
unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() };
- if !self.state.borrow().is_maximized() && 0 <= cursor_point.y && cursor_point.y <= frame_y {
+ if !self.state.is_maximized() && 0 <= cursor_point.y && cursor_point.y <= frame_y {
// x-axis actually goes from -frame_x to 0
return Some(if cursor_point.x <= 0 {
HTTOPLEFT
@@ -902,10 +887,8 @@ impl WindowsWindowInner {
fn handle_nc_mouse_move_msg(&self, handle: HWND, lparam: LPARAM) -> Option<isize> {
self.start_tracking_mouse(handle, TME_LEAVE | TME_NONCLIENT);
- let mut lock = self.state.borrow_mut();
- let mut func = lock.callbacks.input.take()?;
- let scale_factor = lock.scale_factor;
- drop(lock);
+ let mut func = self.state.callbacks.input.take()?;
+ let scale_factor = self.state.scale_factor.get();
let mut cursor_point = POINT {
x: lparam.signed_loword().into(),
@@ -918,7 +901,7 @@ impl WindowsWindowInner {
modifiers: current_modifiers(),
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled { Some(0) } else { None }
}
@@ -930,17 +913,15 @@ impl WindowsWindowInner {
wparam: WPARAM,
lparam: LPARAM,
) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- if let Some(mut func) = lock.callbacks.input.take() {
- let scale_factor = lock.scale_factor;
+ if let Some(mut func) = self.state.callbacks.input.take() {
+ let scale_factor = self.state.scale_factor.get();
let mut cursor_point = POINT {
x: lparam.signed_loword().into(),
y: lparam.signed_hiword().into(),
};
unsafe { ScreenToClient(handle, &mut cursor_point).ok().log_err() };
let physical_point = point(DevicePixels(cursor_point.x), DevicePixels(cursor_point.y));
- let click_count = lock.click_state.update(button, physical_point);
- drop(lock);
+ let click_count = self.state.click_state.update(button, physical_point);
let input = PlatformInput::MouseDown(MouseDownEvent {
button,
@@ -951,21 +932,20 @@ impl WindowsWindowInner {
});
let result = func(input);
let handled = !result.propagate || result.default_prevented;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled {
return Some(0);
}
} else {
- drop(lock);
};
// Since these are handled in handle_nc_mouse_up_msg we must prevent the default window proc
if button == MouseButton::Left {
match wparam.0 as u32 {
- HTMINBUTTON => self.state.borrow_mut().nc_button_pressed = Some(HTMINBUTTON),
- HTMAXBUTTON => self.state.borrow_mut().nc_button_pressed = Some(HTMAXBUTTON),
- HTCLOSE => self.state.borrow_mut().nc_button_pressed = Some(HTCLOSE),
+ HTMINBUTTON => self.state.nc_button_pressed.set(Some(HTMINBUTTON)),
+ HTMAXBUTTON => self.state.nc_button_pressed.set(Some(HTMAXBUTTON)),
+ HTCLOSE => self.state.nc_button_pressed.set(Some(HTCLOSE)),
_ => return None,
};
Some(0)
@@ -981,10 +961,8 @@ impl WindowsWindowInner {
wparam: WPARAM,
lparam: LPARAM,
) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
- if let Some(mut func) = lock.callbacks.input.take() {
- let scale_factor = lock.scale_factor;
- drop(lock);
+ if let Some(mut func) = self.state.callbacks.input.take() {
+ let scale_factor = self.state.scale_factor.get();
let mut cursor_point = POINT {
x: lparam.signed_loword().into(),
@@ -998,16 +976,15 @@ impl WindowsWindowInner {
click_count: 1,
});
let handled = !func(input).propagate;
- self.state.borrow_mut().callbacks.input = Some(func);
+ self.state.callbacks.input.set(Some(func));
if handled {
return Some(0);
}
} else {
- drop(lock);
}
- let last_pressed = self.state.borrow_mut().nc_button_pressed.take();
+ let last_pressed = self.state.nc_button_pressed.take();
if button == MouseButton::Left
&& let Some(last_pressed) = last_pressed
{
@@ -1017,7 +994,7 @@ impl WindowsWindowInner {
true
}
(HTMAXBUTTON, HTMAXBUTTON) => {
- if self.state.borrow().is_maximized() {
+ if self.state.is_maximized() {
unsafe { ShowWindowAsync(handle, SW_NORMAL).ok().log_err() };
} else {
unsafe { ShowWindowAsync(handle, SW_MAXIMIZE).ok().log_err() };
@@ -1042,17 +1019,16 @@ impl WindowsWindowInner {
}
fn handle_cursor_changed(&self, lparam: LPARAM) -> Option<isize> {
- let mut state = self.state.borrow_mut();
- let had_cursor = state.current_cursor.is_some();
+ let had_cursor = self.state.current_cursor.get().is_some();
- state.current_cursor = if lparam.0 == 0 {
+ self.state.current_cursor.set(if lparam.0 == 0 {
None
} else {
Some(HCURSOR(lparam.0 as _))
- };
+ });
- if had_cursor != state.current_cursor.is_some() {
- unsafe { SetCursor(state.current_cursor) };
+ if had_cursor != self.state.current_cursor.get().is_some() {
+ unsafe { SetCursor(self.state.current_cursor.get()) };
}
Some(0)
@@ -1075,7 +1051,7 @@ impl WindowsWindowInner {
return None;
}
unsafe {
- SetCursor(self.state.borrow().current_cursor);
+ SetCursor(self.state.current_cursor.get());
};
Some(0)
}
@@ -1087,13 +1063,12 @@ impl WindowsWindowInner {
lparam: LPARAM,
) -> Option<isize> {
if wparam.0 != 0 {
- let mut lock = self.state.borrow_mut();
- let display = lock.display;
- lock.click_state.system_update(wparam.0);
- lock.border_offset.update(handle).log_err();
- // system settings may emit a window message which wants to take the refcell lock, so drop it
- drop(lock);
- self.system_settings_mut().update(display, wparam.0);
+ let display = self.state.display.get();
+ self.state.click_state.system_update(wparam.0);
+ self.state.border_offset.update(handle).log_err();
+ // system settings may emit a window message which wants to take the refcell self.state, so drop it
+
+ self.system_settings().update(display, wparam.0);
} else {
self.handle_system_theme_changed(handle, lparam)?;
};
@@ -1116,13 +1091,13 @@ impl WindowsWindowInner {
let new_appearance = system_appearance()
.context("unable to get system appearance when handling ImmersiveColorSet")
.log_err()?;
- let mut lock = self.state.borrow_mut();
- if new_appearance != lock.appearance {
- lock.appearance = new_appearance;
- let mut callback = lock.callbacks.appearance_changed.take()?;
- drop(lock);
+
+ if new_appearance != self.state.appearance.get() {
+ self.state.appearance.set(new_appearance);
+ let mut callback = self.state.callbacks.appearance_changed.take()?;
+
callback();
- self.state.borrow_mut().callbacks.appearance_changed = Some(callback);
+ self.state.callbacks.appearance_changed.set(Some(callback));
configure_dwm_dark_mode(handle, new_appearance);
}
}
@@ -1151,10 +1126,14 @@ impl WindowsWindowInner {
}
fn handle_device_lost(&self, lparam: LPARAM) -> Option<isize> {
- let mut lock = self.state.borrow_mut();
let devices = lparam.0 as *const DirectXDevices;
let devices = unsafe { &*devices };
- if let Err(err) = lock.renderer.handle_device_lost(&devices) {
+ if let Err(err) = self
+ .state
+ .renderer
+ .borrow_mut()
+ .handle_device_lost(&devices)
+ {
panic!("Device lost: {err}");
}
Some(0)
@@ -1162,18 +1141,18 @@ impl WindowsWindowInner {
#[inline]
fn draw_window(&self, handle: HWND, force_render: bool) -> Option<isize> {
- let mut request_frame = self.state.borrow_mut().callbacks.request_frame.take()?;
+ let mut request_frame = self.state.callbacks.request_frame.take()?;
// we are instructing gpui to force render a frame, this will
// re-populate all the gpu textures for us so we can resume drawing in
// case we disabled drawing earlier due to a device loss
- self.state.borrow_mut().renderer.mark_drawable();
+ self.state.renderer.borrow_mut().mark_drawable();
request_frame(RequestFrameOptions {
require_presentation: false,
force_render,
});
- self.state.borrow_mut().callbacks.request_frame = Some(request_frame);
+ self.state.callbacks.request_frame.set(Some(request_frame));
unsafe { ValidateRect(Some(handle), None).ok().log_err() };
Some(0)
@@ -1182,16 +1161,16 @@ impl WindowsWindowInner {
#[inline]
fn parse_char_message(&self, wparam: WPARAM) -> Option<String> {
let code_point = wparam.loword();
- let mut lock = self.state.borrow_mut();
+
// https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-3/#G2630
match code_point {
0xD800..=0xDBFF => {
// High surrogate, wait for low surrogate
- lock.pending_surrogate = Some(code_point);
+ self.state.pending_surrogate.set(Some(code_point));
None
}
0xDC00..=0xDFFF => {
- if let Some(high_surrogate) = lock.pending_surrogate.take() {
+ if let Some(high_surrogate) = self.state.pending_surrogate.take() {
// Low surrogate, combine with pending high surrogate
String::from_utf16(&[high_surrogate, code_point]).ok()
} else {
@@ -1203,7 +1182,7 @@ impl WindowsWindowInner {
}
}
_ => {
- lock.pending_surrogate = None;
+ self.state.pending_surrogate.set(None);
char::from_u32(code_point as u32)
.filter(|c| !c.is_control())
.map(|c| c.to_string())
@@ -1212,9 +1191,8 @@ impl WindowsWindowInner {
}
fn start_tracking_mouse(&self, handle: HWND, flags: TRACKMOUSEEVENT_FLAGS) {
- let mut lock = self.state.borrow_mut();
- if !lock.hovered {
- lock.hovered = true;
+ if !self.state.hovered.get() {
+ self.state.hovered.set(true);
unsafe {
TrackMouseEvent(&mut TRACKMOUSEEVENT {
cbSize: std::mem::size_of::<TRACKMOUSEEVENT>() as u32,
@@ -1224,10 +1202,12 @@ impl WindowsWindowInner {
})
.log_err()
};
- if let Some(mut callback) = lock.callbacks.hovered_status_change.take() {
- drop(lock);
+ if let Some(mut callback) = self.state.callbacks.hovered_status_change.take() {
callback(true);
- self.state.borrow_mut().callbacks.hovered_status_change = Some(callback);
+ self.state
+ .callbacks
+ .hovered_status_change
+ .set(Some(callback));
}
}
}
@@ -1236,9 +1216,9 @@ impl WindowsWindowInner {
where
F: FnOnce(&mut PlatformInputHandler) -> R,
{
- let mut input_handler = self.state.borrow_mut().input_handler.take()?;
+ let mut input_handler = self.state.input_handler.take()?;
let result = f(&mut input_handler);
- self.state.borrow_mut().input_handler = Some(input_handler);
+ self.state.input_handler.set(Some(input_handler));
Some(result)
}
@@ -1246,12 +1226,11 @@ impl WindowsWindowInner {
where
F: FnOnce(&mut PlatformInputHandler, f32) -> Option<R>,
{
- let mut lock = self.state.borrow_mut();
- let mut input_handler = lock.input_handler.take()?;
- let scale_factor = lock.scale_factor;
- drop(lock);
+ let mut input_handler = self.state.input_handler.take()?;
+ let scale_factor = self.state.scale_factor.get();
+
let result = f(&mut input_handler, scale_factor);
- self.state.borrow_mut().input_handler = Some(input_handler);
+ self.state.input_handler.set(Some(input_handler));
result
}
}
@@ -1259,7 +1238,7 @@ impl WindowsWindowInner {
fn handle_key_event<F>(
wparam: WPARAM,
lparam: LPARAM,
- state: &mut WindowsWindowState,
+ state: &WindowsWindowState,
f: F,
) -> Option<PlatformInput>
where
@@ -1272,11 +1251,12 @@ where
VK_SHIFT | VK_CONTROL | VK_MENU | VK_LMENU | VK_RMENU | VK_LWIN | VK_RWIN => {
if state
.last_reported_modifiers
+ .get()
.is_some_and(|prev_modifiers| prev_modifiers == modifiers)
{
return None;
}
- state.last_reported_modifiers = Some(modifiers);
+ state.last_reported_modifiers.set(Some(modifiers));
Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
modifiers,
capslock: current_capslock(),
@@ -1287,11 +1267,12 @@ where
let capslock = current_capslock();
if state
.last_reported_capslock
+ .get()
.is_some_and(|prev_capslock| prev_capslock == capslock)
{
return None;
}
- state.last_reported_capslock = Some(capslock);
+ state.last_reported_capslock.set(Some(capslock));
Some(PlatformInput::ModifiersChanged(ModifiersChangedEvent {
modifiers,
capslock,
@@ -1,5 +1,5 @@
use std::{
- cell::RefCell,
+ cell::{Cell, RefCell},
ffi::OsStr,
path::{Path, PathBuf},
rc::{Rc, Weak},
@@ -47,7 +47,7 @@ pub(crate) struct WindowsPlatform {
}
struct WindowsPlatformInner {
- state: RefCell<WindowsPlatformState>,
+ state: WindowsPlatformState,
raw_window_handles: std::sync::Weak<RwLock<SmallVec<[SafeHwnd; 4]>>>,
// The below members will never change throughout the entire lifecycle of the app.
validation_number: usize,
@@ -57,22 +57,22 @@ struct WindowsPlatformInner {
pub(crate) struct WindowsPlatformState {
callbacks: PlatformCallbacks,
- menus: Vec<OwnedMenu>,
- jump_list: JumpList,
+ menus: RefCell<Vec<OwnedMenu>>,
+ jump_list: RefCell<JumpList>,
// NOTE: standard cursor handles don't need to close.
- pub(crate) current_cursor: Option<HCURSOR>,
- directx_devices: Option<DirectXDevices>,
+ pub(crate) current_cursor: Cell<Option<HCURSOR>>,
+ directx_devices: RefCell<Option<DirectXDevices>>,
}
#[derive(Default)]
struct PlatformCallbacks {
- open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
- quit: Option<Box<dyn FnMut()>>,
- reopen: Option<Box<dyn FnMut()>>,
- app_menu_action: Option<Box<dyn FnMut(&dyn Action)>>,
- will_open_app_menu: Option<Box<dyn FnMut()>>,
- validate_app_menu_command: Option<Box<dyn FnMut(&dyn Action) -> bool>>,
- keyboard_layout_change: Option<Box<dyn FnMut()>>,
+ open_urls: Cell<Option<Box<dyn FnMut(Vec<String>)>>>,
+ quit: Cell<Option<Box<dyn FnMut()>>>,
+ reopen: Cell<Option<Box<dyn FnMut()>>>,
+ app_menu_action: Cell<Option<Box<dyn FnMut(&dyn Action)>>>,
+ will_open_app_menu: Cell<Option<Box<dyn FnMut()>>>,
+ validate_app_menu_command: Cell<Option<Box<dyn FnMut(&dyn Action) -> bool>>>,
+ keyboard_layout_change: Cell<Option<Box<dyn FnMut()>>>,
}
impl WindowsPlatformState {
@@ -84,10 +84,10 @@ impl WindowsPlatformState {
Self {
callbacks,
- jump_list,
- current_cursor,
- directx_devices,
- menus: Vec::new(),
+ jump_list: RefCell::new(jump_list),
+ current_cursor: Cell::new(current_cursor),
+ directx_devices: RefCell::new(directx_devices),
+ menus: RefCell::new(Vec::new()),
}
}
}
@@ -194,14 +194,14 @@ impl WindowsPlatform {
WindowCreationInfo {
icon: self.icon,
executor: self.foreground_executor.clone(),
- current_cursor: self.inner.state.borrow().current_cursor,
+ current_cursor: self.inner.state.current_cursor.get(),
windows_version: self.windows_version,
drop_target_helper: self.drop_target_helper.clone(),
validation_number: self.inner.validation_number,
main_receiver: self.inner.main_receiver.clone(),
platform_window_handle: self.handle,
disable_direct_composition: self.disable_direct_composition,
- directx_devices: self.inner.state.borrow().directx_devices.clone().unwrap(),
+ directx_devices: self.inner.state.directx_devices.borrow().clone().unwrap(),
invalidate_devices: self.invalidate_devices.clone(),
}
}
@@ -213,9 +213,8 @@ impl WindowsPlatform {
actions.push(dock_menu);
}
});
- let mut lock = self.inner.state.borrow_mut();
- lock.jump_list.dock_menus = actions;
- update_jump_list(&lock.jump_list).log_err();
+ self.inner.state.jump_list.borrow_mut().dock_menus = actions;
+ update_jump_list(&self.inner.state.jump_list.borrow()).log_err();
}
fn update_jump_list(
@@ -229,12 +228,10 @@ impl WindowsPlatform {
actions.push(dock_menu);
}
});
- let mut lock = self.inner.state.borrow_mut();
- lock.jump_list.dock_menus = actions;
- lock.jump_list.recent_workspaces = entries;
- update_jump_list(&lock.jump_list)
- .log_err()
- .unwrap_or_default()
+ let mut jump_list = self.inner.state.jump_list.borrow_mut();
+ jump_list.dock_menus = actions;
+ jump_list.recent_workspaces = entries;
+ update_jump_list(&jump_list).log_err().unwrap_or_default()
}
fn find_current_active_window(&self) -> Option<HWND> {
@@ -250,7 +247,7 @@ impl WindowsPlatform {
}
fn begin_vsync_thread(&self) {
- let mut directx_device = self.inner.state.borrow().directx_devices.clone().unwrap();
+ let mut directx_device = self.inner.state.directx_devices.borrow().clone().unwrap();
let platform_window: SafeHwnd = self.handle.into();
let validation_number = self.inner.validation_number;
let all_windows = Arc::downgrade(&self.raw_window_handles);
@@ -334,9 +331,9 @@ impl Platform for WindowsPlatform {
fn on_keyboard_layout_change(&self, callback: Box<dyn FnMut()>) {
self.inner
.state
- .borrow_mut()
.callbacks
- .keyboard_layout_change = Some(callback);
+ .keyboard_layout_change
+ .set(Some(callback));
}
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {
@@ -354,7 +351,7 @@ impl Platform for WindowsPlatform {
}
self.inner
- .with_callback(|callbacks| &mut callbacks.quit, |callback| callback());
+ .with_callback(|callbacks| &callbacks.quit, |callback| callback());
}
fn quit(&self) {
@@ -473,7 +470,7 @@ impl Platform for WindowsPlatform {
}
fn on_open_urls(&self, callback: Box<dyn FnMut(Vec<String>)>) {
- self.inner.state.borrow_mut().callbacks.open_urls = Some(callback);
+ self.inner.state.callbacks.open_urls.set(Some(callback));
}
fn prompt_for_paths(
@@ -543,19 +540,19 @@ impl Platform for WindowsPlatform {
}
fn on_quit(&self, callback: Box<dyn FnMut()>) {
- self.inner.state.borrow_mut().callbacks.quit = Some(callback);
+ self.inner.state.callbacks.quit.set(Some(callback));
}
fn on_reopen(&self, callback: Box<dyn FnMut()>) {
- self.inner.state.borrow_mut().callbacks.reopen = Some(callback);
+ self.inner.state.callbacks.reopen.set(Some(callback));
}
fn set_menus(&self, menus: Vec<Menu>, _keymap: &Keymap) {
- self.inner.state.borrow_mut().menus = menus.into_iter().map(|menu| menu.owned()).collect();
+ *self.inner.state.menus.borrow_mut() = menus.into_iter().map(|menu| menu.owned()).collect();
}
fn get_menus(&self) -> Option<Vec<OwnedMenu>> {
- Some(self.inner.state.borrow().menus.clone())
+ Some(self.inner.state.menus.borrow().clone())
}
fn set_dock_menu(&self, menus: Vec<MenuItem>, _keymap: &Keymap) {
@@ -563,19 +560,27 @@ impl Platform for WindowsPlatform {
}
fn on_app_menu_action(&self, callback: Box<dyn FnMut(&dyn Action)>) {
- self.inner.state.borrow_mut().callbacks.app_menu_action = Some(callback);
+ self.inner
+ .state
+ .callbacks
+ .app_menu_action
+ .set(Some(callback));
}
fn on_will_open_app_menu(&self, callback: Box<dyn FnMut()>) {
- self.inner.state.borrow_mut().callbacks.will_open_app_menu = Some(callback);
+ self.inner
+ .state
+ .callbacks
+ .will_open_app_menu
+ .set(Some(callback));
}
fn on_validate_app_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
self.inner
.state
- .borrow_mut()
.callbacks
- .validate_app_menu_command = Some(callback);
+ .validate_app_menu_command
+ .set(Some(callback));
}
fn app_path(&self) -> Result<PathBuf> {
@@ -589,13 +594,13 @@ impl Platform for WindowsPlatform {
fn set_cursor_style(&self, style: CursorStyle) {
let hcursor = load_cursor(style);
- if self.inner.state.borrow_mut().current_cursor.map(|c| c.0) != hcursor.map(|c| c.0) {
+ if self.inner.state.current_cursor.get().map(|c| c.0) != hcursor.map(|c| c.0) {
self.post_message(
WM_GPUI_CURSOR_STYLE_CHANGED,
WPARAM(0),
LPARAM(hcursor.map_or(0, |c| c.0 as isize)),
);
- self.inner.state.borrow_mut().current_cursor = hcursor;
+ self.inner.state.current_cursor.set(hcursor);
}
}
@@ -721,12 +726,12 @@ impl Platform for WindowsPlatform {
impl WindowsPlatformInner {
fn new(context: &mut PlatformWindowCreateContext) -> Result<Rc<Self>> {
- let state = RefCell::new(WindowsPlatformState::new(
+ let state = WindowsPlatformState::new(
context
.directx_devices
.take()
.context("missing directx devices")?,
- ));
+ );
Ok(Rc::new(Self {
state,
raw_window_handles: context.raw_window_handles.clone(),
@@ -746,13 +751,13 @@ impl WindowsPlatformInner {
/// Calls `project` to project to the corresponding callback field, removes it from callbacks, calls `f` with the callback and then puts the callback back.
fn with_callback<T>(
&self,
- project: impl Fn(&mut PlatformCallbacks) -> &mut Option<T>,
+ project: impl Fn(&PlatformCallbacks) -> &Cell<Option<T>>,
f: impl FnOnce(&mut T),
) {
- let callback = project(&mut self.state.borrow_mut().callbacks).take();
+ let callback = project(&self.state.callbacks).take();
if let Some(mut callback) = callback {
f(&mut callback);
- *project(&mut self.state.borrow_mut().callbacks) = Some(callback)
+ project(&self.state.callbacks).set(Some(callback));
}
}
@@ -877,8 +882,8 @@ impl WindowsPlatformInner {
fn handle_dock_action_event(&self, action_idx: usize) -> Option<isize> {
let Some(action) = self
.state
- .borrow_mut()
.jump_list
+ .borrow()
.dock_menus
.get(action_idx)
.map(|dock_menu| dock_menu.action.boxed_clone())
@@ -887,7 +892,7 @@ impl WindowsPlatformInner {
return Some(1);
};
self.with_callback(
- |callbacks| &mut callbacks.app_menu_action,
+ |callbacks| &callbacks.app_menu_action,
|callback| callback(&*action),
);
Some(0)
@@ -895,7 +900,7 @@ impl WindowsPlatformInner {
fn handle_keyboard_layout_change(&self) -> Option<isize> {
self.with_callback(
- |callbacks| &mut callbacks.keyboard_layout_change,
+ |callbacks| &callbacks.keyboard_layout_change,
|callback| callback(),
);
Some(0)
@@ -904,9 +909,8 @@ impl WindowsPlatformInner {
fn handle_device_lost(&self, lparam: LPARAM) -> Option<isize> {
let directx_devices = lparam.0 as *const DirectXDevices;
let directx_devices = unsafe { &*directx_devices };
- let mut lock = self.state.borrow_mut();
- lock.directx_devices.take();
- lock.directx_devices = Some(directx_devices.clone());
+ self.state.directx_devices.borrow_mut().take();
+ *self.state.directx_devices.borrow_mut() = Some(directx_devices.clone());
Some(0)
}
@@ -1,4 +1,7 @@
-use std::ffi::{c_uint, c_void};
+use std::{
+ cell::Cell,
+ ffi::{c_uint, c_void},
+};
use ::util::ResultExt;
use windows::Win32::UI::{
@@ -15,18 +18,18 @@ use super::WindowsDisplay;
/// Windows settings pulled from SystemParametersInfo
/// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfow
-#[derive(Default, Debug, Clone, Copy)]
+#[derive(Default, Debug, Clone)]
pub(crate) struct WindowsSystemSettings {
pub(crate) mouse_wheel_settings: MouseWheelSettings,
- pub(crate) auto_hide_taskbar_position: Option<AutoHideTaskbarPosition>,
+ pub(crate) auto_hide_taskbar_position: Cell<Option<AutoHideTaskbarPosition>>,
}
-#[derive(Default, Debug, Clone, Copy)]
+#[derive(Default, Debug, Clone)]
pub(crate) struct MouseWheelSettings {
/// SEE: SPI_GETWHEELSCROLLCHARS
- pub(crate) wheel_scroll_chars: u32,
+ pub(crate) wheel_scroll_chars: Cell<u32>,
/// SEE: SPI_GETWHEELSCROLLLINES
- pub(crate) wheel_scroll_lines: u32,
+ pub(crate) wheel_scroll_lines: Cell<u32>,
}
impl WindowsSystemSettings {
@@ -36,12 +39,13 @@ impl WindowsSystemSettings {
settings
}
- fn init(&mut self, display: WindowsDisplay) {
+ fn init(&self, display: WindowsDisplay) {
self.mouse_wheel_settings.update();
- self.auto_hide_taskbar_position = AutoHideTaskbarPosition::new(display).log_err().flatten();
+ self.auto_hide_taskbar_position
+ .set(AutoHideTaskbarPosition::new(display).log_err().flatten());
}
- pub(crate) fn update(&mut self, display: WindowsDisplay, wparam: usize) {
+ pub(crate) fn update(&self, display: WindowsDisplay, wparam: usize) {
match wparam {
// SPI_SETWORKAREA
47 => self.update_taskbar_position(display),
@@ -51,22 +55,23 @@ impl WindowsSystemSettings {
}
}
- fn update_mouse_wheel_settings(&mut self) {
+ fn update_mouse_wheel_settings(&self) {
self.mouse_wheel_settings.update();
}
- fn update_taskbar_position(&mut self, display: WindowsDisplay) {
- self.auto_hide_taskbar_position = AutoHideTaskbarPosition::new(display).log_err().flatten();
+ fn update_taskbar_position(&self, display: WindowsDisplay) {
+ self.auto_hide_taskbar_position
+ .set(AutoHideTaskbarPosition::new(display).log_err().flatten());
}
}
impl MouseWheelSettings {
- fn update(&mut self) {
+ fn update(&self) {
self.update_wheel_scroll_chars();
self.update_wheel_scroll_lines();
}
- fn update_wheel_scroll_chars(&mut self) {
+ fn update_wheel_scroll_chars(&self) {
let mut value = c_uint::default();
let result = unsafe {
SystemParametersInfoW(
@@ -77,12 +82,12 @@ impl MouseWheelSettings {
)
};
- if result.log_err() != None && self.wheel_scroll_chars != value {
- self.wheel_scroll_chars = value;
+ if result.log_err() != None && self.wheel_scroll_chars.get() != value {
+ self.wheel_scroll_chars.set(value);
}
}
- fn update_wheel_scroll_lines(&mut self) {
+ fn update_wheel_scroll_lines(&self) {
let mut value = c_uint::default();
let result = unsafe {
SystemParametersInfoW(
@@ -93,8 +98,8 @@ impl MouseWheelSettings {
)
};
- if result.log_err() != None && self.wheel_scroll_lines != value {
- self.wheel_scroll_lines = value;
+ if result.log_err() != None && self.wheel_scroll_lines.get() != value {
+ self.wheel_scroll_lines.set(value);
}
}
}
@@ -1,7 +1,7 @@
#![deny(unsafe_op_in_unsafe_fn)]
use std::{
- cell::RefCell,
+ cell::{Cell, RefCell},
num::NonZeroIsize,
path::PathBuf,
rc::{Rc, Weak},
@@ -30,43 +30,51 @@ use crate::*;
pub(crate) struct WindowsWindow(pub Rc<WindowsWindowInner>);
+impl std::ops::Deref for WindowsWindow {
+ type Target = WindowsWindowInner;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
pub struct WindowsWindowState {
- pub origin: Point<Pixels>,
- pub logical_size: Size<Pixels>,
+ pub origin: Cell<Point<Pixels>>,
+ pub logical_size: Cell<Size<Pixels>>,
pub min_size: Option<Size<Pixels>>,
- pub fullscreen_restore_bounds: Bounds<Pixels>,
+ pub fullscreen_restore_bounds: Cell<Bounds<Pixels>>,
pub border_offset: WindowBorderOffset,
- pub appearance: WindowAppearance,
- pub scale_factor: f32,
- pub restore_from_minimized: Option<Box<dyn FnMut(RequestFrameOptions)>>,
+ pub appearance: Cell<WindowAppearance>,
+ pub scale_factor: Cell<f32>,
+ pub restore_from_minimized: Cell<Option<Box<dyn FnMut(RequestFrameOptions)>>>,
pub callbacks: Callbacks,
- pub input_handler: Option<PlatformInputHandler>,
- pub pending_surrogate: Option<u16>,
- pub last_reported_modifiers: Option<Modifiers>,
- pub last_reported_capslock: Option<Capslock>,
- pub hovered: bool,
+ pub input_handler: Cell<Option<PlatformInputHandler>>,
+ pub pending_surrogate: Cell<Option<u16>>,
+ pub last_reported_modifiers: Cell<Option<Modifiers>>,
+ pub last_reported_capslock: Cell<Option<Capslock>>,
+ pub hovered: Cell<bool>,
- pub renderer: DirectXRenderer,
+ pub renderer: RefCell<DirectXRenderer>,
pub click_state: ClickState,
- pub current_cursor: Option<HCURSOR>,
- pub nc_button_pressed: Option<u32>,
+ pub current_cursor: Cell<Option<HCURSOR>>,
+ pub nc_button_pressed: Cell<Option<u32>>,
- pub display: WindowsDisplay,
+ pub display: Cell<WindowsDisplay>,
/// Flag to instruct the `VSyncProvider` thread to invalidate the directx devices
/// as resizing them has failed, causing us to have lost at least the render target.
pub invalidate_devices: Arc<AtomicBool>,
- fullscreen: Option<StyleAndBounds>,
- initial_placement: Option<WindowOpenStatus>,
+ fullscreen: Cell<Option<StyleAndBounds>>,
+ initial_placement: Cell<Option<WindowOpenStatus>>,
hwnd: HWND,
}
pub(crate) struct WindowsWindowInner {
hwnd: HWND,
drop_target_helper: IDropTargetHelper,
- pub(crate) state: RefCell<WindowsWindowState>,
- system_settings: RefCell<WindowsSystemSettings>,
+ pub(crate) state: WindowsWindowState,
+ system_settings: WindowsSystemSettings,
pub(crate) handle: AnyWindowHandle,
pub(crate) hide_title_bar: bool,
pub(crate) is_movable: bool,
@@ -121,27 +129,27 @@ impl WindowsWindowState {
let initial_placement = None;
Ok(Self {
- origin,
- logical_size,
- fullscreen_restore_bounds,
+ origin: Cell::new(origin),
+ logical_size: Cell::new(logical_size),
+ fullscreen_restore_bounds: Cell::new(fullscreen_restore_bounds),
border_offset,
- appearance,
- scale_factor,
- restore_from_minimized,
+ appearance: Cell::new(appearance),
+ scale_factor: Cell::new(scale_factor),
+ restore_from_minimized: Cell::new(restore_from_minimized),
min_size,
callbacks,
- input_handler,
- pending_surrogate,
- last_reported_modifiers,
- last_reported_capslock,
- hovered,
- renderer,
+ input_handler: Cell::new(input_handler),
+ pending_surrogate: Cell::new(pending_surrogate),
+ last_reported_modifiers: Cell::new(last_reported_modifiers),
+ last_reported_capslock: Cell::new(last_reported_capslock),
+ hovered: Cell::new(hovered),
+ renderer: RefCell::new(renderer),
click_state,
- current_cursor,
- nc_button_pressed,
- display,
- fullscreen,
- initial_placement,
+ current_cursor: Cell::new(current_cursor),
+ nc_button_pressed: Cell::new(nc_button_pressed),
+ display: Cell::new(display),
+ fullscreen: Cell::new(fullscreen),
+ initial_placement: Cell::new(initial_placement),
hwnd,
invalidate_devices,
})
@@ -149,7 +157,7 @@ impl WindowsWindowState {
#[inline]
pub(crate) fn is_fullscreen(&self) -> bool {
- self.fullscreen.is_some()
+ self.fullscreen.get().is_some()
}
pub(crate) fn is_maximized(&self) -> bool {
@@ -158,8 +166,8 @@ impl WindowsWindowState {
fn bounds(&self) -> Bounds<Pixels> {
Bounds {
- origin: self.origin,
- size: self.logical_size,
+ origin: self.origin.get(),
+ size: self.logical_size.get(),
}
}
@@ -178,8 +186,8 @@ impl WindowsWindowState {
(
calculate_client_rect(
placement.rcNormalPosition,
- self.border_offset,
- self.scale_factor,
+ &self.border_offset,
+ self.scale_factor.get(),
),
placement.showCmd == SW_SHOWMAXIMIZED.0 as u32,
)
@@ -189,7 +197,7 @@ impl WindowsWindowState {
let (bounds, maximized) = self.calculate_window_bounds();
if self.is_fullscreen() {
- WindowBounds::Fullscreen(self.fullscreen_restore_bounds)
+ WindowBounds::Fullscreen(self.fullscreen_restore_bounds.get())
} else if maximized {
WindowBounds::Maximized(bounds)
} else {
@@ -202,13 +210,13 @@ impl WindowsWindowState {
/// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as
/// whether the mouse collides with other elements of GPUI).
fn content_size(&self) -> Size<Pixels> {
- self.logical_size
+ self.logical_size.get()
}
}
impl WindowsWindowInner {
fn new(context: &mut WindowCreateContext, hwnd: HWND, cs: &CREATESTRUCTW) -> Result<Rc<Self>> {
- let state = RefCell::new(WindowsWindowState::new(
+ let state = WindowsWindowState::new(
hwnd,
&context.directx_devices,
cs,
@@ -218,7 +226,7 @@ impl WindowsWindowInner {
context.appearance,
context.disable_direct_composition,
context.invalidate_devices.clone(),
- )?);
+ )?;
Ok(Rc::new(Self {
hwnd,
@@ -232,7 +240,7 @@ impl WindowsWindowInner {
validation_number: context.validation_number,
main_receiver: context.main_receiver.clone(),
platform_window_handle: context.platform_window_handle,
- system_settings: RefCell::new(WindowsSystemSettings::new(context.display)),
+ system_settings: WindowsSystemSettings::new(context.display),
}))
}
@@ -240,19 +248,17 @@ impl WindowsWindowInner {
let this = self.clone();
self.executor
.spawn(async move {
- let mut lock = this.state.borrow_mut();
let StyleAndBounds {
style,
x,
y,
cx,
cy,
- } = match lock.fullscreen.take() {
+ } = match this.state.fullscreen.take() {
Some(state) => state,
None => {
- let (window_bounds, _) = lock.calculate_window_bounds();
- lock.fullscreen_restore_bounds = window_bounds;
- drop(lock);
+ let (window_bounds, _) = this.state.calculate_window_bounds();
+ this.state.fullscreen_restore_bounds.set(window_bounds);
let style =
WINDOW_STYLE(unsafe { get_window_long(this.hwnd, GWL_STYLE) } as _);
@@ -260,22 +266,20 @@ impl WindowsWindowInner {
unsafe { GetWindowRect(this.hwnd, &mut rc) }
.context("failed to get window rect")
.log_err();
-
- lock = this.state.borrow_mut();
- let _ = lock.fullscreen.insert(StyleAndBounds {
+ let _ = this.state.fullscreen.set(Some(StyleAndBounds {
style,
x: rc.left,
y: rc.top,
cx: rc.right - rc.left,
cy: rc.bottom - rc.top,
- });
+ }));
let style = style
& !(WS_THICKFRAME
| WS_SYSMENU
| WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
| WS_CAPTION);
- let physical_bounds = lock.display.physical_bounds();
+ let physical_bounds = this.state.display.get().physical_bounds();
StyleAndBounds {
style,
x: physical_bounds.left().0,
@@ -285,7 +289,6 @@ impl WindowsWindowInner {
}
}
};
- drop(lock);
unsafe { set_window_long(this.hwnd, GWL_STYLE, style.0 as isize) };
unsafe {
SetWindowPos(
@@ -304,7 +307,7 @@ impl WindowsWindowInner {
}
fn set_window_placement(self: &Rc<Self>) -> Result<()> {
- let Some(open_status) = self.state.borrow_mut().initial_placement.take() else {
+ let Some(open_status) = self.state.initial_placement.take() else {
return Ok(());
};
match open_status.state {
@@ -328,27 +331,23 @@ impl WindowsWindowInner {
Ok(())
}
- pub(crate) fn system_settings(&self) -> std::cell::Ref<'_, WindowsSystemSettings> {
- self.system_settings.borrow()
- }
-
- pub(crate) fn system_settings_mut(&self) -> std::cell::RefMut<'_, WindowsSystemSettings> {
- self.system_settings.borrow_mut()
+ pub(crate) fn system_settings(&self) -> &WindowsSystemSettings {
+ &self.system_settings
}
}
#[derive(Default)]
pub(crate) struct Callbacks {
- pub(crate) request_frame: Option<Box<dyn FnMut(RequestFrameOptions)>>,
- pub(crate) input: Option<Box<dyn FnMut(crate::PlatformInput) -> DispatchEventResult>>,
- pub(crate) active_status_change: Option<Box<dyn FnMut(bool)>>,
- pub(crate) hovered_status_change: Option<Box<dyn FnMut(bool)>>,
- pub(crate) resize: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
- pub(crate) moved: Option<Box<dyn FnMut()>>,
- pub(crate) should_close: Option<Box<dyn FnMut() -> bool>>,
- pub(crate) close: Option<Box<dyn FnOnce()>>,
- pub(crate) hit_test_window_control: Option<Box<dyn FnMut() -> Option<WindowControlArea>>>,
- pub(crate) appearance_changed: Option<Box<dyn FnMut()>>,
+ pub(crate) request_frame: Cell<Option<Box<dyn FnMut(RequestFrameOptions)>>>,
+ pub(crate) input: Cell<Option<Box<dyn FnMut(crate::PlatformInput) -> DispatchEventResult>>>,
+ pub(crate) active_status_change: Cell<Option<Box<dyn FnMut(bool)>>>,
+ pub(crate) hovered_status_change: Cell<Option<Box<dyn FnMut(bool)>>>,
+ pub(crate) resize: Cell<Option<Box<dyn FnMut(Size<Pixels>, f32)>>>,
+ pub(crate) moved: Cell<Option<Box<dyn FnMut()>>>,
+ pub(crate) should_close: Cell<Option<Box<dyn FnMut() -> bool>>>,
+ pub(crate) close: Cell<Option<Box<dyn FnOnce()>>>,
+ pub(crate) hit_test_window_control: Cell<Option<Box<dyn FnMut() -> Option<WindowControlArea>>>>,
+ pub(crate) appearance_changed: Cell<Option<Box<dyn FnMut()>>>,
}
struct WindowCreateContext {
@@ -476,21 +475,21 @@ impl WindowsWindow {
register_drag_drop(&this)?;
configure_dwm_dark_mode(hwnd, appearance);
- this.state.borrow_mut().border_offset.update(hwnd)?;
+ this.state.border_offset.update(hwnd)?;
let placement = retrieve_window_placement(
hwnd,
display,
params.bounds,
- this.state.borrow().scale_factor,
- this.state.borrow().border_offset,
+ this.state.scale_factor.get(),
+ &this.state.border_offset,
)?;
if params.show {
unsafe { SetWindowPlacement(hwnd, &placement)? };
} else {
- this.state.borrow_mut().initial_placement = Some(WindowOpenStatus {
+ this.state.initial_placement.set(Some(WindowOpenStatus {
placement,
state: WindowOpenState::Windowed,
- });
+ }));
}
Ok(Self(this))
@@ -533,15 +532,15 @@ impl Drop for WindowsWindow {
impl PlatformWindow for WindowsWindow {
fn bounds(&self) -> Bounds<Pixels> {
- self.0.state.borrow().bounds()
+ self.state.bounds()
}
fn is_maximized(&self) -> bool {
- self.0.state.borrow().is_maximized()
+ self.state.is_maximized()
}
fn window_bounds(&self) -> WindowBounds {
- self.0.state.borrow().window_bounds()
+ self.state.window_bounds()
}
/// get the logical size of the app's drawable area.
@@ -549,14 +548,14 @@ impl PlatformWindow for WindowsWindow {
/// Currently, GPUI uses the logical size of the app to handle mouse interactions (such as
/// whether the mouse collides with other elements of GPUI).
fn content_size(&self) -> Size<Pixels> {
- self.0.state.borrow().content_size()
+ self.state.content_size()
}
fn resize(&mut self, size: Size<Pixels>) {
let hwnd = self.0.hwnd;
let bounds =
crate::bounds(self.bounds().origin, size).to_device_pixels(self.scale_factor());
- let rect = calculate_window_rect(bounds, self.0.state.borrow().border_offset);
+ let rect = calculate_window_rect(bounds, &self.state.border_offset);
self.0
.executor
@@ -579,15 +578,15 @@ impl PlatformWindow for WindowsWindow {
}
fn scale_factor(&self) -> f32 {
- self.0.state.borrow().scale_factor
+ self.state.scale_factor.get()
}
fn appearance(&self) -> WindowAppearance {
- self.0.state.borrow().appearance
+ self.state.appearance.get()
}
fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
- Some(Rc::new(self.0.state.borrow().display))
+ Some(Rc::new(self.state.display.get()))
}
fn mouse_position(&self) -> Point<Pixels> {
@@ -612,11 +611,11 @@ impl PlatformWindow for WindowsWindow {
}
fn set_input_handler(&mut self, input_handler: PlatformInputHandler) {
- self.0.state.borrow_mut().input_handler = Some(input_handler);
+ self.state.input_handler.set(Some(input_handler));
}
fn take_input_handler(&mut self) -> Option<PlatformInputHandler> {
- self.0.state.borrow_mut().input_handler.take()
+ self.state.input_handler.take()
}
fn prompt(
@@ -762,7 +761,7 @@ impl PlatformWindow for WindowsWindow {
}
fn is_hovered(&self) -> bool {
- self.0.state.borrow().hovered
+ self.state.hovered.get()
}
fn set_title(&mut self, title: &str) {
@@ -805,8 +804,9 @@ impl PlatformWindow for WindowsWindow {
unsafe {
if IsWindowVisible(self.0.hwnd).as_bool() {
ShowWindowAsync(self.0.hwnd, SW_MAXIMIZE).ok().log_err();
- } else if let Some(status) = self.0.state.borrow_mut().initial_placement.as_mut() {
+ } else if let Some(mut status) = self.state.initial_placement.take() {
status.state = WindowOpenState::Maximized;
+ self.state.initial_placement.set(Some(status));
}
}
}
@@ -814,61 +814,78 @@ impl PlatformWindow for WindowsWindow {
fn toggle_fullscreen(&self) {
if unsafe { IsWindowVisible(self.0.hwnd).as_bool() } {
self.0.toggle_fullscreen();
- } else if let Some(status) = self.0.state.borrow_mut().initial_placement.as_mut() {
+ } else if let Some(mut status) = self.state.initial_placement.take() {
status.state = WindowOpenState::Fullscreen;
+ self.state.initial_placement.set(Some(status));
}
}
fn is_fullscreen(&self) -> bool {
- self.0.state.borrow().is_fullscreen()
+ self.state.is_fullscreen()
}
fn on_request_frame(&self, callback: Box<dyn FnMut(RequestFrameOptions)>) {
- self.0.state.borrow_mut().callbacks.request_frame = Some(callback);
+ self.state.callbacks.request_frame.set(Some(callback));
}
fn on_input(&self, callback: Box<dyn FnMut(PlatformInput) -> DispatchEventResult>) {
- self.0.state.borrow_mut().callbacks.input = Some(callback);
+ self.state.callbacks.input.set(Some(callback));
}
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
- self.0.state.borrow_mut().callbacks.active_status_change = Some(callback);
+ self.0
+ .state
+ .callbacks
+ .active_status_change
+ .set(Some(callback));
}
fn on_hover_status_change(&self, callback: Box<dyn FnMut(bool)>) {
- self.0.state.borrow_mut().callbacks.hovered_status_change = Some(callback);
+ self.0
+ .state
+ .callbacks
+ .hovered_status_change
+ .set(Some(callback));
}
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
- self.0.state.borrow_mut().callbacks.resize = Some(callback);
+ self.state.callbacks.resize.set(Some(callback));
}
fn on_moved(&self, callback: Box<dyn FnMut()>) {
- self.0.state.borrow_mut().callbacks.moved = Some(callback);
+ self.state.callbacks.moved.set(Some(callback));
}
fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>) {
- self.0.state.borrow_mut().callbacks.should_close = Some(callback);
+ self.state.callbacks.should_close.set(Some(callback));
}
fn on_close(&self, callback: Box<dyn FnOnce()>) {
- self.0.state.borrow_mut().callbacks.close = Some(callback);
+ self.state.callbacks.close.set(Some(callback));
}
fn on_hit_test_window_control(&self, callback: Box<dyn FnMut() -> Option<WindowControlArea>>) {
- self.0.state.borrow_mut().callbacks.hit_test_window_control = Some(callback);
+ self.0
+ .state
+ .callbacks
+ .hit_test_window_control
+ .set(Some(callback));
}
fn on_appearance_changed(&self, callback: Box<dyn FnMut()>) {
- self.0.state.borrow_mut().callbacks.appearance_changed = Some(callback);
+ self.0
+ .state
+ .callbacks
+ .appearance_changed
+ .set(Some(callback));
}
fn draw(&self, scene: &Scene) {
- self.0.state.borrow_mut().renderer.draw(scene).log_err();
+ self.state.renderer.borrow_mut().draw(scene).log_err();
}
fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
- self.0.state.borrow().renderer.sprite_atlas()
+ self.state.renderer.borrow().sprite_atlas()
}
fn get_raw_handle(&self) -> HWND {
@@ -876,7 +893,7 @@ impl PlatformWindow for WindowsWindow {
}
fn gpu_specs(&self) -> Option<GpuSpecs> {
- self.0.state.borrow().renderer.gpu_specs().log_err()
+ self.state.renderer.borrow().gpu_specs().log_err()
}
fn update_ime_position(&self, _bounds: Bounds<Pixels>) {
@@ -889,11 +906,9 @@ struct WindowsDragDropHandler(pub Rc<WindowsWindowInner>);
impl WindowsDragDropHandler {
fn handle_drag_drop(&self, input: PlatformInput) {
- let mut lock = self.0.state.borrow_mut();
- if let Some(mut func) = lock.callbacks.input.take() {
- drop(lock);
+ if let Some(mut func) = self.0.state.callbacks.input.take() {
func(input);
- self.0.state.borrow_mut().callbacks.input = Some(func);
+ self.0.state.callbacks.input.set(Some(func));
}
}
}
@@ -937,7 +952,7 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
ScreenToClient(self.0.hwnd, &mut cursor_position)
.ok()
.log_err();
- let scale_factor = self.0.state.borrow().scale_factor;
+ let scale_factor = self.0.state.scale_factor.get();
let input = PlatformInput::FileDrop(FileDropEvent::Entered {
position: logical_point(
cursor_position.x as f32,
@@ -975,7 +990,7 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
.ok()
.log_err();
}
- let scale_factor = self.0.state.borrow().scale_factor;
+ let scale_factor = self.0.state.scale_factor.get();
let input = PlatformInput::FileDrop(FileDropEvent::Pending {
position: logical_point(
cursor_position.x as f32,
@@ -1017,7 +1032,7 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
.ok()
.log_err();
}
- let scale_factor = self.0.state.borrow().scale_factor;
+ let scale_factor = self.0.state.scale_factor.get();
let input = PlatformInput::FileDrop(FileDropEvent::Submit {
position: logical_point(
cursor_position.x as f32,
@@ -1031,15 +1046,15 @@ impl IDropTarget_Impl for WindowsDragDropHandler_Impl {
}
}
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone)]
pub(crate) struct ClickState {
- button: MouseButton,
- last_click: Instant,
- last_position: Point<DevicePixels>,
- double_click_spatial_tolerance_width: i32,
- double_click_spatial_tolerance_height: i32,
- double_click_interval: Duration,
- pub(crate) current_count: usize,
+ button: Cell<MouseButton>,
+ last_click: Cell<Instant>,
+ last_position: Cell<Point<DevicePixels>>,
+ double_click_spatial_tolerance_width: Cell<i32>,
+ double_click_spatial_tolerance_height: Cell<i32>,
+ double_click_interval: Cell<Duration>,
+ pub(crate) current_count: Cell<usize>,
}
impl ClickState {
@@ -1049,61 +1064,59 @@ impl ClickState {
let double_click_interval = Duration::from_millis(unsafe { GetDoubleClickTime() } as u64);
ClickState {
- button: MouseButton::Left,
- last_click: Instant::now(),
- last_position: Point::default(),
- double_click_spatial_tolerance_width,
- double_click_spatial_tolerance_height,
- double_click_interval,
- current_count: 0,
+ button: Cell::new(MouseButton::Left),
+ last_click: Cell::new(Instant::now()),
+ last_position: Cell::new(Point::default()),
+ double_click_spatial_tolerance_width: Cell::new(double_click_spatial_tolerance_width),
+ double_click_spatial_tolerance_height: Cell::new(double_click_spatial_tolerance_height),
+ double_click_interval: Cell::new(double_click_interval),
+ current_count: Cell::new(0),
}
}
/// update self and return the needed click count
- pub fn update(&mut self, button: MouseButton, new_position: Point<DevicePixels>) -> usize {
- if self.button == button && self.is_double_click(new_position) {
- self.current_count += 1;
+ pub fn update(&self, button: MouseButton, new_position: Point<DevicePixels>) -> usize {
+ if self.button.get() == button && self.is_double_click(new_position) {
+ self.current_count.update(|it| it + 1);
} else {
- self.current_count = 1;
+ self.current_count.set(1);
}
- self.last_click = Instant::now();
- self.last_position = new_position;
- self.button = button;
+ self.last_click.set(Instant::now());
+ self.last_position.set(new_position);
+ self.button.set(button);
- self.current_count
+ self.current_count.get()
}
- pub fn system_update(&mut self, wparam: usize) {
+ pub fn system_update(&self, wparam: usize) {
match wparam {
// SPI_SETDOUBLECLKWIDTH
- 29 => {
- self.double_click_spatial_tolerance_width =
- unsafe { GetSystemMetrics(SM_CXDOUBLECLK) }
- }
+ 29 => self
+ .double_click_spatial_tolerance_width
+ .set(unsafe { GetSystemMetrics(SM_CXDOUBLECLK) }),
// SPI_SETDOUBLECLKHEIGHT
- 30 => {
- self.double_click_spatial_tolerance_height =
- unsafe { GetSystemMetrics(SM_CYDOUBLECLK) }
- }
+ 30 => self
+ .double_click_spatial_tolerance_height
+ .set(unsafe { GetSystemMetrics(SM_CYDOUBLECLK) }),
// SPI_SETDOUBLECLICKTIME
- 32 => {
- self.double_click_interval =
- Duration::from_millis(unsafe { GetDoubleClickTime() } as u64)
- }
+ 32 => self
+ .double_click_interval
+ .set(Duration::from_millis(unsafe { GetDoubleClickTime() } as u64)),
_ => {}
}
}
#[inline]
fn is_double_click(&self, new_position: Point<DevicePixels>) -> bool {
- let diff = self.last_position - new_position;
+ let diff = self.last_position.get() - new_position;
- self.last_click.elapsed() < self.double_click_interval
- && diff.x.0.abs() <= self.double_click_spatial_tolerance_width
- && diff.y.0.abs() <= self.double_click_spatial_tolerance_height
+ self.last_click.get().elapsed() < self.double_click_interval.get()
+ && diff.x.0.abs() <= self.double_click_spatial_tolerance_width.get()
+ && diff.y.0.abs() <= self.double_click_spatial_tolerance_height.get()
}
}
+#[derive(Copy, Clone)]
struct StyleAndBounds {
style: WINDOW_STYLE,
x: i32,
@@ -1129,14 +1142,14 @@ struct AccentPolicy {
type Color = (u8, u8, u8, u8);
-#[derive(Debug, Default, Clone, Copy)]
+#[derive(Debug, Default, Clone)]
pub(crate) struct WindowBorderOffset {
- pub(crate) width_offset: i32,
- pub(crate) height_offset: i32,
+ pub(crate) width_offset: Cell<i32>,
+ pub(crate) height_offset: Cell<i32>,
}
impl WindowBorderOffset {
- pub(crate) fn update(&mut self, hwnd: HWND) -> anyhow::Result<()> {
+ pub(crate) fn update(&self, hwnd: HWND) -> anyhow::Result<()> {
let window_rect = unsafe {
let mut rect = std::mem::zeroed();
GetWindowRect(hwnd, &mut rect)?;
@@ -1147,19 +1160,21 @@ impl WindowBorderOffset {
GetClientRect(hwnd, &mut rect)?;
rect
};
- self.width_offset =
- (window_rect.right - window_rect.left) - (client_rect.right - client_rect.left);
- self.height_offset =
- (window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top);
+ self.width_offset
+ .set((window_rect.right - window_rect.left) - (client_rect.right - client_rect.left));
+ self.height_offset
+ .set((window_rect.bottom - window_rect.top) - (client_rect.bottom - client_rect.top));
Ok(())
}
}
+#[derive(Clone)]
struct WindowOpenStatus {
placement: WINDOWPLACEMENT,
state: WindowOpenState,
}
+#[derive(Clone, Copy)]
enum WindowOpenState {
Maximized,
Fullscreen,
@@ -1269,7 +1284,7 @@ fn register_drag_drop(window: &Rc<WindowsWindowInner>) -> Result<()> {
Ok(())
}
-fn calculate_window_rect(bounds: Bounds<DevicePixels>, border_offset: WindowBorderOffset) -> RECT {
+fn calculate_window_rect(bounds: Bounds<DevicePixels>, border_offset: &WindowBorderOffset) -> RECT {
// NOTE:
// The reason we're not using `AdjustWindowRectEx()` here is
// that the size reported by this function is incorrect.
@@ -1283,10 +1298,10 @@ fn calculate_window_rect(bounds: Bounds<DevicePixels>, border_offset: WindowBord
right: bounds.right().0,
bottom: bounds.bottom().0,
};
- let left_offset = border_offset.width_offset / 2;
- let top_offset = border_offset.height_offset / 2;
- let right_offset = border_offset.width_offset - left_offset;
- let bottom_offset = border_offset.height_offset - top_offset;
+ let left_offset = border_offset.width_offset.get() / 2;
+ let top_offset = border_offset.height_offset.get() / 2;
+ let right_offset = border_offset.width_offset.get() - left_offset;
+ let bottom_offset = border_offset.height_offset.get() - top_offset;
rect.left -= left_offset;
rect.top -= top_offset;
rect.right += right_offset;
@@ -1296,13 +1311,13 @@ fn calculate_window_rect(bounds: Bounds<DevicePixels>, border_offset: WindowBord
fn calculate_client_rect(
rect: RECT,
- border_offset: WindowBorderOffset,
+ border_offset: &WindowBorderOffset,
scale_factor: f32,
) -> Bounds<Pixels> {
- let left_offset = border_offset.width_offset / 2;
- let top_offset = border_offset.height_offset / 2;
- let right_offset = border_offset.width_offset - left_offset;
- let bottom_offset = border_offset.height_offset - top_offset;
+ let left_offset = border_offset.width_offset.get() / 2;
+ let top_offset = border_offset.height_offset.get() / 2;
+ let right_offset = border_offset.width_offset.get() - left_offset;
+ let bottom_offset = border_offset.height_offset.get() - top_offset;
let left = rect.left + left_offset;
let top = rect.top + top_offset;
let right = rect.right - right_offset;
@@ -1319,7 +1334,7 @@ fn retrieve_window_placement(
display: WindowsDisplay,
initial_bounds: Bounds<Pixels>,
scale_factor: f32,
- border_offset: WindowBorderOffset,
+ border_offset: &WindowBorderOffset,
) -> Result<WINDOWPLACEMENT> {
let mut placement = WINDOWPLACEMENT {
length: std::mem::size_of::<WINDOWPLACEMENT>() as u32,
@@ -1429,7 +1444,9 @@ mod tests {
state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))),
2
);
- state.last_click -= Duration::from_millis(700);
+ state
+ .last_click
+ .update(|it| it - Duration::from_millis(700));
assert_eq!(
state.update(MouseButton::Left, point(DevicePixels(0), DevicePixels(0))),
1