diff --git a/winit-appkit/src/app.rs b/winit-appkit/src/app.rs index 00c672cd74..4916f809a6 100644 --- a/winit-appkit/src/app.rs +++ b/winit-appkit/src/app.rs @@ -110,28 +110,32 @@ fn maybe_dispatch_device_event(app_state: &Rc, event: &NSEvent) { if delta_x != 0.0 || delta_y != 0.0 { app_state.maybe_queue_with_handler(move |app, event_loop| { - app.device_event(event_loop, None, DeviceEvent::PointerMotion { - delta: (delta_x, delta_y), - }); + app.device_event( + event_loop, + None, + DeviceEvent::PointerMotion { delta: (delta_x, delta_y) }, + ); }); } }, NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => { let button = event.buttonNumber() as u32; app_state.maybe_queue_with_handler(move |app, event_loop| { - app.device_event(event_loop, None, DeviceEvent::Button { - button, - state: ElementState::Pressed, - }); + app.device_event( + event_loop, + None, + DeviceEvent::Button { button, state: ElementState::Pressed }, + ); }); }, NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => { let button = event.buttonNumber() as u32; app_state.maybe_queue_with_handler(move |app, event_loop| { - app.device_event(event_loop, None, DeviceEvent::Button { - button, - state: ElementState::Released, - }); + app.device_event( + event_loop, + None, + DeviceEvent::Button { button, state: ElementState::Released }, + ); }); }, _ => (), diff --git a/winit-appkit/src/view.rs b/winit-appkit/src/view.rs index 17bb40e399..1d8c243ddf 100644 --- a/winit-appkit/src/view.rs +++ b/winit-appkit/src/view.rs @@ -272,16 +272,15 @@ define_class!( // TODO: Use _replacement_range, requires changing the event to report surrounding text. trace_scope!("setMarkedText:selectedRange:replacementRange:"); - let (marked_text, string) = if let Some(string) = - string.downcast_ref::() - { - (NSMutableAttributedString::from_attributed_nsstring(string), string.string()) - } else if let Some(string) = string.downcast_ref::() { - (NSMutableAttributedString::from_nsstring(string), string.copy()) - } else { - // This method is guaranteed to get either a `NSString` or a `NSAttributedString`. - panic!("unexpected text {string:?}") - }; + let (marked_text, string) = + if let Some(string) = string.downcast_ref::() { + (NSMutableAttributedString::from_attributed_nsstring(string), string.string()) + } else if let Some(string) = string.downcast_ref::() { + (NSMutableAttributedString::from_nsstring(string), string.copy()) + } else { + // This method is guaranteed to get either a `NSString` or a `NSAttributedString`. + panic!("unexpected text {string:?}") + }; // Update marked text. *self.ivars().marked_text.borrow_mut() = marked_text; diff --git a/winit-core/src/event.rs b/winit-core/src/event.rs index 7ad984efea..7ad50a84d1 100644 --- a/winit-core/src/event.rs +++ b/winit-core/src/event.rs @@ -1558,24 +1558,24 @@ mod tests { const TILT_TO_ANGLE: &[(TabletToolTilt, TabletToolAngle)] = &[ (TabletToolTilt { x: 0, y: 0 }, TabletToolAngle { altitude: FRAC_PI_2, azimuth: 0. }), (TabletToolTilt { x: 0, y: 90 }, TabletToolAngle { altitude: 0., azimuth: FRAC_PI_2 }), - (TabletToolTilt { x: 0, y: -90 }, TabletToolAngle { - altitude: 0., - azimuth: 3. * FRAC_PI_2, - }), + ( + TabletToolTilt { x: 0, y: -90 }, + TabletToolAngle { altitude: 0., azimuth: 3. * FRAC_PI_2 }, + ), (TabletToolTilt { x: 90, y: 0 }, TabletToolAngle { altitude: 0., azimuth: 0. }), (TabletToolTilt { x: 90, y: 90 }, TabletToolAngle { altitude: 0., azimuth: 0. }), (TabletToolTilt { x: 90, y: -90 }, TabletToolAngle { altitude: 0., azimuth: 0. }), (TabletToolTilt { x: -90, y: 0 }, TabletToolAngle { altitude: 0., azimuth: PI }), (TabletToolTilt { x: -90, y: 90 }, TabletToolAngle { altitude: 0., azimuth: 0. }), (TabletToolTilt { x: -90, y: -90 }, TabletToolAngle { altitude: 0., azimuth: 0. }), - (TabletToolTilt { x: 0, y: 45 }, TabletToolAngle { - altitude: FRAC_PI_4, - azimuth: FRAC_PI_2, - }), - (TabletToolTilt { x: 0, y: -45 }, TabletToolAngle { - altitude: FRAC_PI_4, - azimuth: 3. * FRAC_PI_2, - }), + ( + TabletToolTilt { x: 0, y: 45 }, + TabletToolAngle { altitude: FRAC_PI_4, azimuth: FRAC_PI_2 }, + ), + ( + TabletToolTilt { x: 0, y: -45 }, + TabletToolAngle { altitude: FRAC_PI_4, azimuth: 3. * FRAC_PI_2 }, + ), (TabletToolTilt { x: 45, y: 0 }, TabletToolAngle { altitude: FRAC_PI_4, azimuth: 0. }), (TabletToolTilt { x: -45, y: 0 }, TabletToolAngle { altitude: FRAC_PI_4, azimuth: PI }), ]; @@ -1590,20 +1590,20 @@ mod tests { (TabletToolAngle { altitude: FRAC_PI_4, azimuth: 0. }, TabletToolTilt { x: 45, y: 0 }), (TabletToolAngle { altitude: FRAC_PI_2, azimuth: 0. }, TabletToolTilt { x: 0, y: 0 }), (TabletToolAngle { altitude: 0., azimuth: FRAC_PI_2 }, TabletToolTilt { x: 0, y: 90 }), - (TabletToolAngle { altitude: FRAC_PI_4, azimuth: FRAC_PI_2 }, TabletToolTilt { - x: 0, - y: 45, - }), + ( + TabletToolAngle { altitude: FRAC_PI_4, azimuth: FRAC_PI_2 }, + TabletToolTilt { x: 0, y: 45 }, + ), (TabletToolAngle { altitude: 0., azimuth: PI }, TabletToolTilt { x: -90, y: 0 }), (TabletToolAngle { altitude: FRAC_PI_4, azimuth: PI }, TabletToolTilt { x: -45, y: 0 }), - (TabletToolAngle { altitude: 0., azimuth: 3. * FRAC_PI_2 }, TabletToolTilt { - x: 0, - y: -90, - }), - (TabletToolAngle { altitude: FRAC_PI_4, azimuth: 3. * FRAC_PI_2 }, TabletToolTilt { - x: 0, - y: -45, - }), + ( + TabletToolAngle { altitude: 0., azimuth: 3. * FRAC_PI_2 }, + TabletToolTilt { x: 0, y: -90 }, + ), + ( + TabletToolAngle { altitude: FRAC_PI_4, azimuth: 3. * FRAC_PI_2 }, + TabletToolTilt { x: 0, y: -45 }, + ), ]; for (angle, tilt) in ANGLE_TO_TILT { diff --git a/winit-orbital/src/event_loop.rs b/winit-orbital/src/event_loop.rs index 77f1aaeaa3..65a447f312 100644 --- a/winit-orbital/src/event_loop.rs +++ b/winit-orbital/src/event_loop.rs @@ -406,35 +406,49 @@ impl EventLoop { ); }, EventOption::Mouse(MouseEvent { x, y }) => { - app.window_event(window_target, window_id, event::WindowEvent::PointerMoved { - device_id: None, - primary: true, - position: (x, y).into(), - source: event::PointerSource::Mouse, - }); + app.window_event( + window_target, + window_id, + event::WindowEvent::PointerMoved { + device_id: None, + primary: true, + position: (x, y).into(), + source: event::PointerSource::Mouse, + }, + ); }, EventOption::MouseRelative(MouseRelativeEvent { dx, dy }) => { - app.device_event(window_target, None, event::DeviceEvent::PointerMotion { - delta: (dx as f64, dy as f64), - }); + app.device_event( + window_target, + None, + event::DeviceEvent::PointerMotion { delta: (dx as f64, dy as f64) }, + ); }, EventOption::Button(ButtonEvent { left, middle, right }) => { while let Some((button, state)) = event_state.mouse(left, middle, right) { - app.window_event(window_target, window_id, event::WindowEvent::PointerButton { - device_id: None, - primary: true, - state, - position: dpi::PhysicalPosition::default(), - button: button.into(), - }); + app.window_event( + window_target, + window_id, + event::WindowEvent::PointerButton { + device_id: None, + primary: true, + state, + position: dpi::PhysicalPosition::default(), + button: button.into(), + }, + ); } }, EventOption::Scroll(ScrollEvent { x, y }) => { - app.window_event(window_target, window_id, event::WindowEvent::MouseWheel { - device_id: None, - delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32), - phase: event::TouchPhase::Moved, - }); + app.window_event( + window_target, + window_id, + event::WindowEvent::MouseWheel { + device_id: None, + delta: event::MouseScrollDelta::LineDelta(x as f32, y as f32), + phase: event::TouchPhase::Moved, + }, + ); }, EventOption::Quit(QuitEvent {}) => { app.window_event(window_target, window_id, event::WindowEvent::CloseRequested); diff --git a/winit-wayland/src/seat/pointer/relative_pointer.rs b/winit-wayland/src/seat/pointer/relative_pointer.rs index 8465b720d6..1b3135ea85 100644 --- a/winit-wayland/src/seat/pointer/relative_pointer.rs +++ b/winit-wayland/src/seat/pointer/relative_pointer.rs @@ -12,8 +12,8 @@ use sctk::reexports::protocols::wp::relative_pointer::zv1::{ use sctk::globals::GlobalData; -use winit_core::event::DeviceEvent; use crate::state::WinitState; +use winit_core::event::DeviceEvent; /// Wrapper around the relative pointer. #[derive(Debug)] diff --git a/winit-web/src/web_sys/canvas.rs b/winit-web/src/web_sys/canvas.rs index 3a9f8ae546..b04fe15e17 100644 --- a/winit-web/src/web_sys/canvas.rs +++ b/winit-web/src/web_sys/canvas.rs @@ -497,10 +497,13 @@ impl Canvas { self.set_current_size(current_size); let new_size = { let new_size = Arc::new(Mutex::new(current_size)); - event_handler(self.id, WindowEvent::ScaleFactorChanged { - scale_factor: scale, - surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_size)), - }); + event_handler( + self.id, + WindowEvent::ScaleFactorChanged { + scale_factor: scale, + surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_size)), + }, + ); let new_size = *new_size.lock().unwrap(); new_size diff --git a/winit-win32/src/event_loop.rs b/winit-win32/src/event_loop.rs index 7c3c3227bf..56e44afa31 100644 --- a/winit-win32/src/event_loop.rs +++ b/winit-win32/src/event_loop.rs @@ -1048,7 +1048,7 @@ unsafe fn public_window_callback_inner( window: HWND, msg: u32, wparam: WPARAM, - lparam: LPARAM, + mut lparam: LPARAM, userdata: &WindowData, ) -> LRESULT { let mut result = ProcResult::DefWindowProc(wparam); @@ -1071,11 +1071,14 @@ unsafe fn public_window_callback_inner( let events = userdata.key_event_builder.process_message(window, msg, wparam, lparam, &mut result); for event in events { - userdata.send_window_event(window, KeyboardInput { - device_id: None, - event: event.event, - is_synthetic: event.is_synthetic, - }); + userdata.send_window_event( + window, + KeyboardInput { + device_id: None, + event: event.event, + is_synthetic: event.is_synthetic, + }, + ); } }; userdata @@ -1089,6 +1092,28 @@ unsafe fn public_window_callback_inner( let callback = || match msg { WM_NCCALCSIZE => { let window_flags = userdata.window_state_lock().window_flags; + // Remove top resize border from an untitled window t to free up area for, eg, a custom + // title bar, which should then handle resizing events itself + if wparam != 0 + && !window_flags.contains(WindowFlags::TITLE_BAR) + && !window_flags.contains(WindowFlags::TOP_RESIZE_BORDER) + && window_flags.contains(WindowFlags::RESIZABLE) + && !util::is_maximized(window) + { + // maximized wins have no borders + result = ProcResult::DefWindowProc(wparam); + let rect = unsafe { &mut *(lparam as *mut RECT) }; + let adj_rect = userdata + .window_state_lock() + .window_flags + .adjust_rect(window, *rect) + .unwrap_or(*rect); + let border_top = rect.top - adj_rect.top; + let params = unsafe { &mut *(lparam as *mut NCCALCSIZE_PARAMS) }; + params.rgrc[0].top -= border_top; + return; + } + if wparam == 0 || window_flags.contains(WindowFlags::MARKER_DECORATIONS) { result = ProcResult::DefWindowProc(wparam); return; @@ -1107,7 +1132,9 @@ unsafe fn public_window_callback_inner( if let Ok(monitor_info) = monitor::get_monitor_info(monitor) { params.rgrc[0] = monitor_info.monitorInfo.rcWork; } - } else if window_flags.contains(WindowFlags::MARKER_UNDECORATED_SHADOW) { + } else if !window_flags.contains(WindowFlags::MARKER_DECORATIONS) + || window_flags.contains(WindowFlags::MARKER_UNDECORATED_SHADOW) + { // Extend the client area to cover the whole non-client area. // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-nccalcsize#remarks // @@ -1122,7 +1149,6 @@ unsafe fn public_window_callback_inner( params.rgrc[0].top += 1; params.rgrc[0].bottom += 1; } - result = ProcResult::Value(0); }, @@ -1564,12 +1590,15 @@ unsafe fn public_window_callback_inner( .ok(); drop(w); - userdata.send_window_event(window, PointerEntered { - device_id: None, - primary: true, - position, - kind: PointerKind::Mouse, - }); + userdata.send_window_event( + window, + PointerEntered { + device_id: None, + primary: true, + position, + kind: PointerKind::Mouse, + }, + ); // Calling TrackMouseEvent in order to receive mouse leave events. unsafe { @@ -1587,12 +1616,15 @@ unsafe fn public_window_callback_inner( .ok(); drop(w); - userdata.send_window_event(window, PointerLeft { - device_id: None, - primary: true, - position: Some(position), - kind: PointerKind::Mouse, - }); + userdata.send_window_event( + window, + PointerLeft { + device_id: None, + primary: true, + position: Some(position), + kind: PointerKind::Mouse, + }, + ); }, PointerMoveKind::None => drop(w), } @@ -1608,12 +1640,15 @@ unsafe fn public_window_callback_inner( if cursor_moved { update_modifiers(window, userdata); - userdata.send_window_event(window, PointerMoved { - device_id: None, - primary: true, - position, - source: PointerSource::Mouse, - }); + userdata.send_window_event( + window, + PointerMoved { + device_id: None, + primary: true, + position, + source: PointerSource::Mouse, + }, + ); } result = ProcResult::Value(0); @@ -1628,12 +1663,10 @@ unsafe fn public_window_callback_inner( w.mouse.set_cursor_flags(window, |f| f.set(CursorFlags::IN_WINDOW, false)).ok(); } - userdata.send_window_event(window, PointerLeft { - device_id: None, - primary: true, - position: None, - kind: Mouse, - }); + userdata.send_window_event( + window, + PointerLeft { device_id: None, primary: true, position: None, kind: Mouse }, + ); result = ProcResult::Value(0); }, @@ -1663,11 +1696,14 @@ unsafe fn public_window_callback_inner( 1 }; - userdata.send_window_event(window, WindowEvent::MouseWheel { - device_id: None, - delta: LineDelta(0.0, value * scroll_lines_multiplier as f32), - phase: TouchPhase::Moved, - }); + userdata.send_window_event( + window, + WindowEvent::MouseWheel { + device_id: None, + delta: LineDelta(0.0, value * scroll_lines_multiplier as f32), + phase: TouchPhase::Moved, + }, + ); result = ProcResult::Value(0); }, @@ -1694,11 +1730,14 @@ unsafe fn public_window_callback_inner( 1 }; - userdata.send_window_event(window, WindowEvent::MouseWheel { - device_id: None, - delta: LineDelta(value * scroll_characters_multiplier as f32, 0.0), - phase: TouchPhase::Moved, - }); + userdata.send_window_event( + window, + WindowEvent::MouseWheel { + device_id: None, + delta: LineDelta(value * scroll_characters_multiplier as f32, 0.0), + phase: TouchPhase::Moved, + }, + ); result = ProcResult::Value(0); }, @@ -1730,13 +1769,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: Left.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Pressed, + position, + button: Left.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1753,13 +1795,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: Left.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Released, + position, + button: Left.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1776,13 +1821,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: Right.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Pressed, + position, + button: Right.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1799,13 +1847,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: Right.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Released, + position, + button: Right.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1822,13 +1873,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: Middle.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Pressed, + position, + button: Middle.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1845,13 +1899,16 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: Middle.into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Released, + position, + button: Middle.into(), + }, + ); result = ProcResult::Value(0); }, @@ -1869,18 +1926,21 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Pressed, - position, - button: match xbutton { - 1 => Back, - 2 => Forward, - _ => Other(xbutton), - } - .into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Pressed, + position, + button: match xbutton { + 1 => Back, + 2 => Forward, + _ => Other(xbutton), + } + .into(), + }, + ); result = ProcResult::Value(0); }, @@ -1898,18 +1958,21 @@ unsafe fn public_window_callback_inner( let y = util::get_y_lparam(lparam as u32) as i32; let position = PhysicalPosition::new(x as f64, y as f64); - userdata.send_window_event(window, PointerButton { - device_id: None, - primary: true, - state: Released, - position, - button: match xbutton { - 1 => Back, - 2 => Forward, - _ => Other(xbutton), - } - .into(), - }); + userdata.send_window_event( + window, + PointerButton { + device_id: None, + primary: true, + state: Released, + position, + button: match xbutton { + 1 => Back, + 2 => Forward, + _ => Other(xbutton), + } + .into(), + }, + ); result = ProcResult::Value(0); }, @@ -1956,40 +2019,55 @@ unsafe fn public_window_callback_inner( let primary = util::has_flag(input.dwFlags, TOUCHEVENTF_PRIMARY); if util::has_flag(input.dwFlags, TOUCHEVENTF_DOWN) { - userdata.send_window_event(window, WindowEvent::PointerEntered { - device_id: None, - primary, - position, - kind: PointerKind::Touch(finger_id), - }); - userdata.send_window_event(window, WindowEvent::PointerButton { - device_id: None, - primary, - state: Pressed, - position, - button: Touch { finger_id, force: None }, - }); + userdata.send_window_event( + window, + WindowEvent::PointerEntered { + device_id: None, + primary, + position, + kind: PointerKind::Touch(finger_id), + }, + ); + userdata.send_window_event( + window, + WindowEvent::PointerButton { + device_id: None, + primary, + state: Pressed, + position, + button: Touch { finger_id, force: None }, + }, + ); } else if util::has_flag(input.dwFlags, TOUCHEVENTF_UP) { - userdata.send_window_event(window, WindowEvent::PointerButton { - device_id: None, - primary, - state: Released, - position, - button: Touch { finger_id, force: None }, - }); - userdata.send_window_event(window, WindowEvent::PointerLeft { - device_id: None, - primary, - position: Some(position), - kind: PointerKind::Touch(finger_id), - }); + userdata.send_window_event( + window, + WindowEvent::PointerButton { + device_id: None, + primary, + state: Released, + position, + button: Touch { finger_id, force: None }, + }, + ); + userdata.send_window_event( + window, + WindowEvent::PointerLeft { + device_id: None, + primary, + position: Some(position), + kind: PointerKind::Touch(finger_id), + }, + ); } else if util::has_flag(input.dwFlags, TOUCHEVENTF_MOVE) { - userdata.send_window_event(window, WindowEvent::PointerMoved { - device_id: None, - primary, - position, - source: PointerSource::Touch { finger_id, force: None }, - }); + userdata.send_window_event( + window, + WindowEvent::PointerMoved { + device_id: None, + primary, + position, + source: PointerSource::Touch { finger_id, force: None }, + }, + ); } else { continue; } @@ -2097,10 +2175,13 @@ unsafe fn public_window_callback_inner( let is_down = util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_DOWN); if is_down || util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UP) { let (kind, button) = match pointer_info.pointerType { - PT_TOUCH => (PointerKind::Touch(finger_id), ButtonSource::Touch { - finger_id, - force: force_for_touch(pointer_info.pointerId), - }), + PT_TOUCH => ( + PointerKind::Touch(finger_id), + ButtonSource::Touch { + finger_id, + force: force_for_touch(pointer_info.pointerId), + }, + ), PT_PEN => { let kind = PointerKind::TabletTool(TabletToolKind::Pen); let (mut pen_flags, data) = @@ -2124,34 +2205,46 @@ unsafe fn public_window_callback_inner( }; if is_down { - userdata.send_window_event(window, WindowEvent::PointerEntered { - device_id: None, - primary, - position, - kind, - }); - - userdata.send_window_event(window, WindowEvent::PointerButton { - device_id: None, - primary, - state: Pressed, - position, - button, - }); + userdata.send_window_event( + window, + WindowEvent::PointerEntered { + device_id: None, + primary, + position, + kind, + }, + ); + + userdata.send_window_event( + window, + WindowEvent::PointerButton { + device_id: None, + primary, + state: Pressed, + position, + button, + }, + ); } else { - userdata.send_window_event(window, WindowEvent::PointerButton { - device_id: None, - primary, - state: Released, - position, - button, - }); - userdata.send_window_event(window, WindowEvent::PointerLeft { - device_id: None, - primary, - position: Some(position), - kind, - }); + userdata.send_window_event( + window, + WindowEvent::PointerButton { + device_id: None, + primary, + state: Released, + position, + button, + }, + ); + userdata.send_window_event( + window, + WindowEvent::PointerLeft { + device_id: None, + primary, + position: Some(position), + kind, + }, + ); } } else if util::has_flag(pointer_info.pointerFlags, POINTER_FLAG_UPDATE) { let source = match pointer_info.pointerType { @@ -2166,12 +2259,15 @@ unsafe fn public_window_callback_inner( _ => PointerSource::Unknown, }; - userdata.send_window_event(window, WindowEvent::PointerMoved { - device_id: None, - primary, - position, - source, - }); + userdata.send_window_event( + window, + WindowEvent::PointerMoved { + device_id: None, + primary, + position, + source, + }, + ); } else { continue; } @@ -2183,6 +2279,13 @@ unsafe fn public_window_callback_inner( }, WM_NCACTIVATE => { + let window_flags = userdata.window_state_lock().window_flags; + if !window_flags.contains(WindowFlags::TITLE_BAR) + && !window_flags.contains(WindowFlags::TOP_RESIZE_BORDER) + && window_flags.contains(WindowFlags::RESIZABLE) + { + lparam = -1; + } let is_active = wparam != false.into(); let active_focus_changed = userdata.window_state_lock().set_active(is_active); if active_focus_changed { @@ -2333,10 +2436,13 @@ unsafe fn public_window_callback_inner( }; let new_surface_size = Arc::new(Mutex::new(new_physical_surface_size)); - userdata.send_window_event(window, ScaleFactorChanged { - scale_factor: new_scale_factor, - surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)), - }); + userdata.send_window_event( + window, + ScaleFactorChanged { + scale_factor: new_scale_factor, + surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&new_surface_size)), + }, + ); let new_physical_surface_size = *new_surface_size.lock().unwrap(); drop(new_surface_size); diff --git a/winit-win32/src/lib.rs b/winit-win32/src/lib.rs index 8a9474b51a..5dc682a7b0 100644 --- a/winit-win32/src/lib.rs +++ b/winit-win32/src/lib.rs @@ -285,6 +285,25 @@ pub trait WindowExtWindows { /// Supported starting with Windows 11 Build 22000. fn set_corner_preference(&self, preference: CornerPreference); + /// Turn window title bar on or off by setting `WS_CAPTION`. + /// By default this is enabled. Note that fullscreen windows + /// naturally do not have title bar. + fn set_titlebar(&self, titlebar: bool); + + /// Gets the window's current titlebar state. + /// + /// Returns `true` when windows have a titlebar (server-side or by Winit). + fn is_titlebar(&self) -> bool; + + /// Turn window top resize border on or off (for windows without a title bar). + /// By default this is enabled. + fn set_top_resize_border(&self, top_resize_border: bool); + + /// Gets the window's current top resize border state (for windows without a title bar). + /// + /// Returns `true` when windows have a top resize border. + fn is_top_resize_border(&self) -> bool; + /// Sets if the reported [`winit_core::event::WindowEvent::MouseWheel`] event /// should account for scroll speed system settings. /// @@ -423,6 +442,30 @@ impl WindowExtWindows for dyn CoreWindow + '_ { Ok(rwh_06::WindowHandle::borrow_raw(handle)) } } + + #[inline] + fn set_titlebar(&self, titlebar: bool) { + let window = self.cast_ref::().unwrap(); + window.set_titlebar(titlebar) + } + + #[inline] + fn is_titlebar(&self) -> bool { + let window = self.cast_ref::().unwrap(); + window.is_titlebar() + } + + #[inline] + fn set_top_resize_border(&self, top_resize_border: bool) { + let window = self.cast_ref::().unwrap(); + window.set_top_resize_border(top_resize_border) + } + + #[inline] + fn is_top_resize_border(&self) -> bool { + let window = self.cast_ref::().unwrap(); + window.is_top_resize_border() + } } /// Additional methods for anything that dereference to [`Window`]. @@ -474,6 +517,8 @@ pub struct WindowAttributesWindows { pub(crate) title_text_color: Option, pub(crate) corner_preference: Option, pub(crate) use_system_wheel_speed: bool, + pub(crate) titlebar: bool, + pub(crate) top_resize_border: bool, } impl Default for WindowAttributesWindows { @@ -494,6 +539,8 @@ impl Default for WindowAttributesWindows { title_text_color: None, corner_preference: None, use_system_wheel_speed: true, + titlebar: true, + top_resize_border: true, } } } @@ -603,6 +650,18 @@ impl WindowAttributesWindows { self } + /// Sets if titlebar should be painted. + pub fn with_titlebar(mut self, titlebar: bool) -> Self { + self.titlebar = titlebar; + self + } + + /// Sets if top border should be also resizable. + pub fn with_top_resize_border(mut self, top_border: bool) -> Self { + self.top_resize_border = top_border; + self + } + /// Sets the background color of the title bar. /// /// Supported starting with Windows 11 Build 22000. diff --git a/winit-win32/src/window.rs b/winit-win32/src/window.rs index e07384bedd..a035c4205e 100644 --- a/winit-win32/src/window.rs +++ b/winit-win32/src/window.rs @@ -344,6 +344,44 @@ impl Window { } } + #[inline] + pub fn set_titlebar(&self, titlebar: bool) { + let window = self.window; + let window_state = Arc::clone(&self.window_state); + + self.thread_executor.execute_in_thread(move || { + let _ = &window; + WindowState::set_window_flags(window_state.lock().unwrap(), window.hwnd(), |f| { + f.set(WindowFlags::TITLE_BAR, titlebar) + }); + }); + } + + #[inline] + pub fn is_titlebar(&self) -> bool { + let window_state = self.window_state_lock(); + window_state.window_flags.contains(WindowFlags::TITLE_BAR) + } + + #[inline] + pub fn set_top_resize_border(&self, top_resize_border: bool) { + let window = self.window; + let window_state = Arc::clone(&self.window_state); + + self.thread_executor.execute_in_thread(move || { + let _ = &window; + WindowState::set_window_flags(window_state.lock().unwrap(), window.hwnd(), |f| { + f.set(WindowFlags::TOP_RESIZE_BORDER, top_resize_border) + }); + }); + } + + #[inline] + pub fn is_top_resize_border(&self) -> bool { + let window_state = self.window_state_lock(); + window_state.window_flags.contains(WindowFlags::TOP_RESIZE_BORDER) + } + #[inline] pub fn set_use_system_scroll_speed(&self, should_use: bool) { self.window_state_lock().use_system_wheel_speed = should_use; @@ -1380,6 +1418,8 @@ unsafe fn init( let mut window_flags = WindowFlags::empty(); window_flags.set(WindowFlags::MARKER_DECORATIONS, attributes.decorations); window_flags.set(WindowFlags::MARKER_UNDECORATED_SHADOW, win_attributes.decoration_shadow); + window_flags.set(WindowFlags::TITLE_BAR, win_attributes.titlebar); + window_flags.set(WindowFlags::TOP_RESIZE_BORDER, win_attributes.top_resize_border); window_flags .set(WindowFlags::ALWAYS_ON_TOP, attributes.window_level == WindowLevel::AlwaysOnTop); window_flags diff --git a/winit-win32/src/window_state.rs b/winit-win32/src/window_state.rs index 78b36e5221..2715bbd8f4 100644 --- a/winit-win32/src/window_state.rs +++ b/winit-win32/src/window_state.rs @@ -136,6 +136,12 @@ bitflags! { const CLIP_CHILDREN = 1 << 22; + const TITLE_BAR = 1 << 23; //0x__800000 on Windows sets WS_CAPTION (0x__C00000) + + /// Unset to signal that a window without a title bar, eg, with a custom one, + /// does not need a ~6px resize border at the top. No effect on a titled window. + const TOP_RESIZE_BORDER = 1 << 24; //0x_1000000 + const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits(); } } @@ -287,6 +293,9 @@ impl WindowFlags { if self.contains(WindowFlags::ON_TASKBAR) { style_ex |= WS_EX_APPWINDOW; } + if !self.contains(WindowFlags::TITLE_BAR) { + style &= !WS_CAPTION; + } if self.contains(WindowFlags::ALWAYS_ON_TOP) { style_ex |= WS_EX_TOPMOST; } @@ -295,12 +304,13 @@ impl WindowFlags { } if self.contains(WindowFlags::CHILD) { style |= WS_CHILD; // This is incompatible with WS_POPUP if that gets added eventually. - - // Remove decorations window styles for child - if !self.contains(WindowFlags::MARKER_DECORATIONS) { - style &= !(WS_CAPTION | WS_BORDER); - style_ex &= !WS_EX_WINDOWEDGE; - } + } + if !self.contains(WindowFlags::MARKER_DECORATIONS) { + // WS_CAPTION is equal to (WS_BORDER | WS_DLGFRAME) + // The former is intended for overlapped windows, + // the latter are for child windows. + style &= !(WS_CAPTION | WS_SIZEBOX); + style_ex &= !WS_EX_WINDOWEDGE; } if self.contains(WindowFlags::POPUP) { style |= WS_POPUP; @@ -317,6 +327,11 @@ impl WindowFlags { if self.contains(WindowFlags::CLIP_CHILDREN) { style |= WS_CLIPCHILDREN; } + if self.contains(WindowFlags::TITLE_BAR) { + style |= WS_CAPTION; + } else { + style &= !WS_CAPTION; + } if self.intersects( WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN | WindowFlags::MARKER_BORDERLESS_FULLSCREEN, @@ -375,20 +390,26 @@ impl WindowFlags { if diff.contains(WindowFlags::MAXIMIZED) || new.contains(WindowFlags::MAXIMIZED) { unsafe { - ShowWindow(window, match new.contains(WindowFlags::MAXIMIZED) { - true => SW_MAXIMIZE, - false => SW_RESTORE, - }); + ShowWindow( + window, + match new.contains(WindowFlags::MAXIMIZED) { + true => SW_MAXIMIZE, + false => SW_RESTORE, + }, + ); } } // Minimize operations should execute after maximize for proper window animations if diff.contains(WindowFlags::MINIMIZED) { unsafe { - ShowWindow(window, match new.contains(WindowFlags::MINIMIZED) { - true => SW_MINIMIZE, - false => SW_RESTORE, - }); + ShowWindow( + window, + match new.contains(WindowFlags::MINIMIZED) { + true => SW_MINIMIZE, + false => SW_RESTORE, + }, + ); } diff.remove(WindowFlags::MINIMIZED); @@ -450,6 +471,10 @@ impl WindowFlags { style &= !(WS_CAPTION | WS_SIZEBOX); } + if !self.contains(WindowFlags::TITLE_BAR) { + style &= !WS_CAPTION; + } + util::win_to_err({ let b_menu = !GetMenu(hwnd).is_null(); if let (Some(get_dpi_for_window), Some(adjust_window_rect_ex_for_dpi)) = diff --git a/winit-x11/src/dnd.rs b/winit-x11/src/dnd.rs index 3c85e4fe2e..2e56ad96f7 100644 --- a/winit-x11/src/dnd.rs +++ b/winit-x11/src/dnd.rs @@ -90,13 +90,13 @@ impl Dnd { DndState::Rejected => (0, atoms[DndNone]), }; self.xconn - .send_client_msg(target_window, target_window, atoms[XdndStatus] as _, None, [ - this_window, - accepted, - 0, - 0, - action as _, - ])? + .send_client_msg( + target_window, + target_window, + atoms[XdndStatus] as _, + None, + [this_window, accepted, 0, 0, action as _], + )? .ignore_error(); Ok(()) @@ -114,13 +114,13 @@ impl Dnd { DndState::Rejected => (0, atoms[DndNone]), }; self.xconn - .send_client_msg(target_window, target_window, atoms[XdndFinished] as _, None, [ - this_window, - accepted, - action as _, - 0, - 0, - ])? + .send_client_msg( + target_window, + target_window, + atoms[XdndFinished] as _, + None, + [this_window, accepted, action as _, 0, 0], + )? .ignore_error(); Ok(()) diff --git a/winit-x11/src/event_loop.rs b/winit-x11/src/event_loop.rs index cd65c71aab..7fe95d1113 100644 --- a/winit-x11/src/event_loop.rs +++ b/winit-x11/src/event_loop.rs @@ -1042,15 +1042,18 @@ impl Device { let ty = unsafe { (*class_ptr)._type }; if ty == ffi::XIScrollClass { let info = unsafe { &*(class_ptr as *const ffi::XIScrollClassInfo) }; - scroll_axes.push((info.number, ScrollAxis { - increment: info.increment, - orientation: match info.scroll_type { - ffi::XIScrollTypeHorizontal => ScrollOrientation::Horizontal, - ffi::XIScrollTypeVertical => ScrollOrientation::Vertical, - _ => unreachable!(), + 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, }, - position: 0.0, - })); + )); } else if ty == ffi::XITouchClass { r#type = Some(DeviceType::Touch); } else if r#type.is_none() && ty == ffi::XIValuatorClass { diff --git a/winit-x11/src/event_processor.rs b/winit-x11/src/event_processor.rs index 2274f06562..c42a5e7e11 100644 --- a/winit-x11/src/event_processor.rs +++ b/winit-x11/src/event_processor.rs @@ -696,10 +696,14 @@ impl EventProcessor { drop(shared_state_lock); let surface_size = Arc::new(Mutex::new(new_surface_size)); - app.window_event(&self.target, window_id, WindowEvent::ScaleFactorChanged { - scale_factor: new_scale_factor, - surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)), - }); + app.window_event( + &self.target, + window_id, + WindowEvent::ScaleFactorChanged { + scale_factor: new_scale_factor, + surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)), + }, + ); let new_surface_size = *surface_size.lock().unwrap(); drop(surface_size); diff --git a/winit-x11/src/util/input.rs b/winit-x11/src/util/input.rs index 12a69bd0c7..b4f441436b 100644 --- a/winit-x11/src/util/input.rs +++ b/winit-x11/src/util/input.rs @@ -20,10 +20,10 @@ impl XConnection { mask: xinput::XIEventMask, ) -> Result, X11Error> { self.xcb_connection() - .xinput_xi_select_events(window, &[xinput::EventMask { - deviceid: device_id, - mask: vec![mask], - }]) + .xinput_xi_select_events( + window, + &[xinput::EventMask { deviceid: device_id, mask: vec![mask] }], + ) .map_err(Into::into) } diff --git a/winit-x11/src/window.rs b/winit-x11/src/window.rs index eaec3abdfe..8ad0bafd44 100644 --- a/winit-x11/src/window.rs +++ b/winit-x11/src/window.rs @@ -1238,10 +1238,14 @@ impl UnownedWindow { let old_surface_size = PhysicalSize::new(width, height); let surface_size = Arc::new(Mutex::new(PhysicalSize::new(new_width, new_height))); - app.window_event(event_loop, self.id(), WindowEvent::ScaleFactorChanged { - scale_factor: new_monitor.scale_factor, - surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)), - }); + app.window_event( + event_loop, + self.id(), + WindowEvent::ScaleFactorChanged { + scale_factor: new_monitor.scale_factor, + surface_size_writer: SurfaceSizeWriter::new(Arc::downgrade(&surface_size)), + }, + ); let new_surface_size = *surface_size.lock().unwrap(); drop(surface_size); diff --git a/winit/examples/application.rs b/winit/examples/application.rs index 2abc1b428b..cf504c017f 100644 --- a/winit/examples/application.rs +++ b/winit/examples/application.rs @@ -15,6 +15,30 @@ use std::time::Instant; use std::{fmt, mem}; use cursor_icon::CursorIcon; +use floem_winit::application::ApplicationHandler; +use floem_winit::cursor::{Cursor, CustomCursor, CustomCursorSource}; +use floem_winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize}; +use floem_winit::error::RequestError; +use floem_winit::event::{DeviceEvent, DeviceId, MouseButton, MouseScrollDelta, WindowEvent}; +use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; +use floem_winit::icon::{Icon, RgbaIcon}; +use floem_winit::keyboard::{Key, ModifiersState}; +use floem_winit::monitor::Fullscreen; +#[cfg(macos_platform)] +use floem_winit::platform::macos::{OptionAsAlt, WindowAttributesMacOS, WindowExtMacOS}; +#[cfg(any(x11_platform, wayland_platform))] +use floem_winit::platform::startup_notify::{ + self, EventLoopExtStartupNotify, WindowExtStartupNotify, +}; +#[cfg(wayland_platform)] +use floem_winit::platform::wayland::{ActiveEventLoopExtWayland, WindowAttributesWayland}; +#[cfg(web_platform)] +use floem_winit::platform::web::{ActiveEventLoopExtWeb, WindowAttributesWeb}; +#[cfg(x11_platform)] +use floem_winit::platform::x11::{ActiveEventLoopExtX11, WindowAttributesX11}; +use floem_winit::window::{ + CursorGrabMode, ResizeDirection, Theme, Window, WindowAttributes, WindowId, +}; #[cfg(not(android_platform))] use rwh_06::{DisplayHandle, HasDisplayHandle}; #[cfg(not(android_platform))] @@ -22,26 +46,6 @@ use softbuffer::{Context, Surface}; use tracing::{error, info}; #[cfg(all(web_platform, not(android_platform)))] use web_time::Instant; -use winit::application::ApplicationHandler; -use winit::cursor::{Cursor, CustomCursor, CustomCursorSource}; -use winit::dpi::{LogicalSize, PhysicalPosition, PhysicalSize}; -use winit::error::RequestError; -use winit::event::{DeviceEvent, DeviceId, MouseButton, MouseScrollDelta, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoop}; -use winit::icon::{Icon, RgbaIcon}; -use winit::keyboard::{Key, ModifiersState}; -use winit::monitor::Fullscreen; -#[cfg(macos_platform)] -use winit::platform::macos::{OptionAsAlt, WindowAttributesMacOS, WindowExtMacOS}; -#[cfg(any(x11_platform, wayland_platform))] -use winit::platform::startup_notify::{self, EventLoopExtStartupNotify, WindowExtStartupNotify}; -#[cfg(wayland_platform)] -use winit::platform::wayland::{ActiveEventLoopExtWayland, WindowAttributesWayland}; -#[cfg(web_platform)] -use winit::platform::web::{ActiveEventLoopExtWeb, WindowAttributesWeb}; -#[cfg(x11_platform)] -use winit::platform::x11::{ActiveEventLoopExtX11, WindowAttributesX11}; -use winit::window::{CursorGrabMode, ResizeDirection, Theme, Window, WindowAttributes, WindowId}; use winit_core::application::macos::ApplicationHandlerExtMacOS; #[path = "util/tracing.rs"] @@ -182,7 +186,7 @@ impl Application { #[cfg(ios_platform)] { - use winit::platform::ios::WindowExtIOS; + use floem_winit::platform::ios::WindowExtIOS; window.recognize_doubletap_gesture(true); window.recognize_pinch_gesture(true); window.recognize_rotation_gesture(true); diff --git a/winit/examples/child_window.rs b/winit/examples/child_window.rs index e87207828b..44a03b1be6 100644 --- a/winit/examples/child_window.rs +++ b/winit/examples/child_window.rs @@ -3,12 +3,12 @@ fn main() -> Result<(), impl std::error::Error> { use std::collections::HashMap; - use winit::application::ApplicationHandler; - use winit::dpi::{LogicalPosition, LogicalSize, Position}; - use winit::event::{ElementState, KeyEvent, WindowEvent}; - use winit::event_loop::{ActiveEventLoop, EventLoop}; - use winit::raw_window_handle::HasRawWindowHandle; - use winit::window::{Window, WindowAttributes, WindowId}; + use floem_winit::application::ApplicationHandler; + use floem_winit::dpi::{LogicalPosition, LogicalSize, Position}; + use floem_winit::event::{ElementState, KeyEvent, WindowEvent}; + use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; + use floem_winit::raw_window_handle::HasRawWindowHandle; + use floem_winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; @@ -47,7 +47,7 @@ fn main() -> Result<(), impl std::error::Error> { fn window_event( &mut self, event_loop: &dyn ActiveEventLoop, - window_id: winit::window::WindowId, + window_id: floem_winit::window::WindowId, event: WindowEvent, ) { match event { diff --git a/winit/examples/control_flow.rs b/winit/examples/control_flow.rs index 8fb09bb3f0..456aa11e14 100644 --- a/winit/examples/control_flow.rs +++ b/winit/examples/control_flow.rs @@ -5,13 +5,13 @@ use std::thread; use std::time; use ::tracing::{info, warn}; +use floem_winit::application::ApplicationHandler; +use floem_winit::event::{ElementState, KeyEvent, StartCause, WindowEvent}; +use floem_winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; +use floem_winit::keyboard::{Key, NamedKey}; +use floem_winit::window::{Window, WindowAttributes, WindowId}; #[cfg(web_platform)] use web_time as time; -use winit::application::ApplicationHandler; -use winit::event::{ElementState, KeyEvent, StartCause, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop}; -use winit::keyboard::{Key, NamedKey}; -use winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; diff --git a/winit/examples/dnd.rs b/winit/examples/dnd.rs index 8b21743bb1..1edbf967f5 100644 --- a/winit/examples/dnd.rs +++ b/winit/examples/dnd.rs @@ -1,9 +1,9 @@ use std::error::Error; -use winit::application::ApplicationHandler; -use winit::event::WindowEvent; -use winit::event_loop::{ActiveEventLoop, EventLoop}; -use winit::window::{Window, WindowAttributes, WindowId}; +use floem_winit::application::ApplicationHandler; +use floem_winit::event::WindowEvent; +use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; +use floem_winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; diff --git a/winit/examples/ime.rs b/winit/examples/ime.rs index 28e5c487c4..e26a6ab166 100644 --- a/winit/examples/ime.rs +++ b/winit/examples/ime.rs @@ -9,17 +9,17 @@ use std::cmp; use std::error::Error; use dpi::{LogicalPosition, PhysicalSize}; -use tracing::{error, info}; -use winit::application::ApplicationHandler; -use winit::event::{Ime, WindowEvent}; -use winit::event_loop::{ActiveEventLoop, EventLoop}; -use winit::keyboard::{Key, ModifiersState, NamedKey}; +use floem_winit::application::ApplicationHandler; +use floem_winit::event::{Ime, WindowEvent}; +use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; +use floem_winit::keyboard::{Key, ModifiersState, NamedKey}; #[cfg(web_platform)] -use winit::platform::web::WindowAttributesWeb; -use winit::window::{ +use floem_winit::platform::web::WindowAttributesWeb; +use floem_winit::window::{ ImeCapabilities, ImeEnableRequest, ImeHint, ImePurpose, ImeRequest, ImeRequestData, ImeSurroundingText, Window, WindowAttributes, WindowId, }; +use tracing::{error, info}; #[path = "util/fill.rs"] mod fill; @@ -146,7 +146,7 @@ impl ApplicationHandler for App { } impl App { - fn handle_key_pressed(&mut self, event: winit::event::KeyEvent, mods: ModifiersState) { + fn handle_key_pressed(&mut self, event: floem_winit::event::KeyEvent, mods: ModifiersState) { match event.key_without_modifiers.as_ref() { Key::Character("i") if mods == ModifiersState::CONTROL => self.toggle_ime(), Key::Character("p") if mods == ModifiersState::CONTROL => { diff --git a/winit/examples/pump_events.rs b/winit/examples/pump_events.rs index 4de531ac80..7fe8e0c2d4 100644 --- a/winit/examples/pump_events.rs +++ b/winit/examples/pump_events.rs @@ -7,11 +7,11 @@ fn main() -> std::process::ExitCode { use std::thread::sleep; use std::time::Duration; - use winit::application::ApplicationHandler; - use winit::event::WindowEvent; - use winit::event_loop::pump_events::{EventLoopExtPumpEvents, PumpStatus}; - use winit::event_loop::{ActiveEventLoop, EventLoop}; - use winit::window::{Window, WindowAttributes, WindowId}; + use floem_winit::application::ApplicationHandler; + use floem_winit::event::WindowEvent; + use floem_winit::event_loop::pump_events::{EventLoopExtPumpEvents, PumpStatus}; + use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; + use floem_winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; diff --git a/winit/examples/run_on_demand.rs b/winit/examples/run_on_demand.rs index f076b43b87..56c8d24ac1 100644 --- a/winit/examples/run_on_demand.rs +++ b/winit/examples/run_on_demand.rs @@ -5,11 +5,11 @@ fn main() -> Result<(), Box> { use std::time::Duration; - use winit::application::ApplicationHandler; - use winit::event::WindowEvent; - use winit::event_loop::run_on_demand::EventLoopExtRunOnDemand; - use winit::event_loop::{ActiveEventLoop, EventLoop}; - use winit::window::{Window, WindowAttributes, WindowId}; + use floem_winit::application::ApplicationHandler; + use floem_winit::event::WindowEvent; + use floem_winit::event_loop::run_on_demand::EventLoopExtRunOnDemand; + use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; + use floem_winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; @@ -31,7 +31,7 @@ fn main() -> Result<(), Box> { fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window_attributes = WindowAttributes::default() .with_title("Fantastic window number one!") - .with_surface_size(winit::dpi::LogicalSize::new(128.0, 128.0)); + .with_surface_size(floem_winit::dpi::LogicalSize::new(128.0, 128.0)); let window = event_loop.create_window(window_attributes).unwrap(); self.window_id = Some(window.id()); self.window = Some(window); diff --git a/winit/examples/util/fill.rs b/winit/examples/util/fill.rs index 0b1a4fb06a..70dfa197c7 100644 --- a/winit/examples/util/fill.rs +++ b/winit/examples/util/fill.rs @@ -26,10 +26,10 @@ mod platform { #[cfg(all(not(android_platform), not(web_platform)))] use std::time::Instant; + use floem_winit::window::{Window, WindowId}; use softbuffer::{Context, Surface}; #[cfg(all(web_platform, not(android_platform)))] use web_time::Instant; - use winit::window::{Window, WindowId}; thread_local! { // NOTE: You should never do things like that, create context and drop it before @@ -132,25 +132,25 @@ mod platform { #[cfg(any(target_os = "android", target_os = "ios"))] mod platform { #[allow(dead_code)] - pub fn fill_window(_window: &dyn winit::window::Window) { + pub fn fill_window(_window: &dyn floem_winit::window::Window) { // No-op on mobile platforms. } #[allow(dead_code)] - pub fn fill_window_with_color(_window: &dyn winit::window::Window, _color: u32) { + pub fn fill_window_with_color(_window: &dyn floem_winit::window::Window, _color: u32) { // No-op on mobile platforms. } #[allow(dead_code)] pub fn fill_window_with_animated_color( - _window: &dyn winit::window::Window, + _window: &dyn floem_winit::window::Window, _start: std::time::Instant, ) { // No-op on mobile platforms. } #[allow(dead_code)] - pub fn cleanup_window(_window: &dyn winit::window::Window) { + pub fn cleanup_window(_window: &dyn floem_winit::window::Window) { // No-op on mobile platforms. } } diff --git a/winit/examples/win_attributes.rs b/winit/examples/win_attributes.rs new file mode 100644 index 0000000000..eccc66eb72 --- /dev/null +++ b/winit/examples/win_attributes.rs @@ -0,0 +1,190 @@ +#![allow( + unused_imports, + unused_mut, + unused_variables, + dead_code, + unused_assignments, + unused_macros +)] +use std::error::Error; + +use floem_winit::application::ApplicationHandler; +use floem_winit::event::WindowEvent; +use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; +use floem_winit::window::{Window, WindowAttributes, WindowId}; +use winit_core::keyboard::NamedKey; + +#[path = "util/fill.rs"] +mod fill; +#[path = "util/tracing.rs"] +mod tracing; + +use ::tracing::info; +#[cfg(windows_platform)] +fn main() -> Result<(), Box> { + tracing::init(); + + println!( + "Windows Window Attributes tester: + − title bar (WS_CAPTION) via with_titlebar (false) + + resize border (WS_SIZEBOX) via with_resizable (true ) ≝ + − top resize border via with_top_resize_border(false) + ├ not a separate WS_ window style, 'manual' removal on NonClientArea events + └ only implemented for windows without a title bar, eg, with a custom title bar handling \ + resizing from the top + —————————————————————————————— + Press a key for (un)setting/querying a specific parameter (modifiers are ignored): + on off toggle status + title bar q w e r + resize border a s d f + ─ top resize border z x c v + theme b n + " + ); + + let event_loop = EventLoop::new()?; + + let app = Application::new(); + Ok(event_loop.run_app(app)?) +} + +/// Application state and event handling. +struct Application { + window: Option>, +} + +impl Application { + fn new() -> Self { + Self { window: None } + } +} + +use floem_winit::event::ElementState; +use floem_winit::keyboard::{Key, ModifiersState}; +#[cfg(windows_platform)] +use floem_winit::platform::windows::WindowAttributesWindows; +#[cfg(windows_platform)] +use floem_winit::platform::windows::WindowExtWindows; +#[cfg(windows_platform)] +impl ApplicationHandler for Application { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { + let window_attributes_win = Box::new( + WindowAttributesWindows::default() + .with_titlebar(false) // titlebar ≝true + .with_top_resize_border(false), // top_resize_border ≝true + ); + let window_attributes = WindowAttributes::default() + .with_title("Topless (unless you see this)!") + .with_decorations(true) // decorations ≝true + .with_resizable(true) // resizable ≝true + .with_platform_attributes(window_attributes_win) // + .with_position(dpi::Position::Logical(dpi::LogicalPosition::new(0.0, 0.0))); + self.window = Some(event_loop.create_window(window_attributes).unwrap()); + } + + fn window_event( + &mut self, + event_loop: &dyn ActiveEventLoop, + _window_id: WindowId, + event: WindowEvent, + ) { + let win = match self.window.as_ref() { + Some(win) => win, + None => return, + }; + let _modi = ModifiersState::default(); + match event { + WindowEvent::KeyboardInput { event, .. } => { + if event.state == ElementState::Pressed && !event.repeat { + match event.key_without_modifiers.as_ref() { + Key::Character("q") => { + win.set_titlebar(true); + info!("set_titlebar → true") + }, + Key::Character("w") => { + win.set_titlebar(false); + info!("set_titlebar → false") + }, + Key::Character("e") => { + let flip = !win.is_titlebar(); + win.set_titlebar(flip); + info!("set_titlebar → {flip}") + }, + Key::Character("r") => { + let is = win.is_titlebar(); + info!("is_titlebar = {is}") + }, + Key::Character("a") => { + win.set_resizable(true); + info!("set_resizable → true") + }, + Key::Character("s") => { + win.set_resizable(false); + info!("set_resizable → false") + }, + Key::Character("d") => { + let flip = !win.is_resizable(); + win.set_resizable(flip); + info!("set_resizable → {flip}") + }, + Key::Character("f") => { + let is = win.is_resizable(); + info!("is_resizable = {is}") + }, + Key::Character("z") => { + win.set_top_resize_border(true); + info!("set_top_resize_border→ true") + }, + Key::Character("x") => { + win.set_top_resize_border(false); + info!("set_top_resize_border→ false") + }, + Key::Character("c") => { + let flip = !win.is_top_resize_border(); + win.set_top_resize_border(flip); + info!("set_top_resize_border→ {flip}") + }, + Key::Character("v") => { + let is = win.is_top_resize_border(); + info!("is_top_resize_border = {is}") + }, + Key::Character("b") => { + use winit_core::window::Theme; + if let Some(theme) = win.theme() { + win.set_theme(Some(match theme { + Theme::Light => Theme::Dark, + Theme::Dark => Theme::Light, + })) + } else { + win.set_theme(Some(Theme::Light)) + } + }, + Key::Character("n") => { + let is = win.theme(); + info!("is_theme = {is:?}") + }, + Key::Named(NamedKey::Escape) => { + event_loop.exit(); + }, + _ => (), + } + } + }, + WindowEvent::RedrawRequested => { + let window = self.window.as_ref().unwrap(); + window.pre_present_notify(); + fill::fill_window(window.as_ref()); + }, + WindowEvent::CloseRequested => { + event_loop.exit(); + }, + _ => {}, + } + } +} + +#[cfg(not(windows))] +fn main() -> Result<(), Box> { + println!("This example is only supported on Windows."); + Ok(()) +} diff --git a/winit/examples/window.rs b/winit/examples/window.rs index 76c60c39e8..ca83e3f95e 100644 --- a/winit/examples/window.rs +++ b/winit/examples/window.rs @@ -2,12 +2,12 @@ use std::error::Error; -use winit::application::ApplicationHandler; -use winit::event::WindowEvent; -use winit::event_loop::{ActiveEventLoop, EventLoop}; +use floem_winit::application::ApplicationHandler; +use floem_winit::event::WindowEvent; +use floem_winit::event_loop::{ActiveEventLoop, EventLoop}; #[cfg(web_platform)] -use winit::platform::web::WindowAttributesWeb; -use winit::window::{Window, WindowAttributes, WindowId}; +use floem_winit::platform::web::WindowAttributesWeb; +use floem_winit::window::{Window, WindowAttributes, WindowId}; #[path = "util/fill.rs"] mod fill; diff --git a/winit/tests/send_objects.rs b/winit/tests/send_objects.rs index 48bfa3b94f..c136df17a4 100644 --- a/winit/tests/send_objects.rs +++ b/winit/tests/send_objects.rs @@ -3,28 +3,28 @@ fn needs_send() {} #[test] fn event_loop_proxy_send() { - needs_send::(); + needs_send::(); } #[test] fn window_send() { - needs_send::(); + needs_send::(); } #[test] fn window_builder_send() { - needs_send::(); + needs_send::(); } #[test] fn ids_send() { - needs_send::(); - needs_send::(); - needs_send::(); + needs_send::(); + needs_send::(); + needs_send::(); } #[test] fn custom_cursor_send() { - needs_send::(); - needs_send::(); + needs_send::(); + needs_send::(); } diff --git a/winit/tests/sync_object.rs b/winit/tests/sync_object.rs index 1c156c0120..5d5442dd74 100644 --- a/winit/tests/sync_object.rs +++ b/winit/tests/sync_object.rs @@ -3,21 +3,21 @@ fn needs_sync() {} #[test] fn event_loop_proxy_send() { - needs_sync::(); + needs_sync::(); } #[test] fn window_sync() { - needs_sync::(); + needs_sync::(); } #[test] fn window_builder_sync() { - needs_sync::(); + needs_sync::(); } #[test] fn custom_cursor_sync() { - needs_sync::(); - needs_sync::(); + needs_sync::(); + needs_sync::(); }