Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial PoC for wayland CSD window drag #11046

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 17 additions & 0 deletions crates/gpui/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,29 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
#[cfg(target_os = "windows")]
fn get_raw_handle(&self) -> windows::HWND;

#[cfg(target_os = "linux")]
fn mark_window_move(&self, move_state: WindowMoveState);

#[cfg(target_os = "linux")]
fn should_render_window_controls(&self) -> bool;

#[cfg(any(test, feature = "test-support"))]
fn as_test(&mut self) -> Option<&mut TestWindow> {
None
}
}

/// All the window move states needed for CSD based window move.
#[cfg(target_os = "linux")]
pub enum WindowMoveState {
/// Start marks the probable start of the move event
Start,
/// Moving marks the actual start of the drag event
Moving,
/// Stop marks the end of the drag event
Stop
}

/// This type is public so that our test macro can generate and use it, but it should not
/// be considered part of our public API.
#[doc(hidden)]
Expand Down
17 changes: 16 additions & 1 deletion crates/gpui/src/platform/linux/wayland/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use wayland_client::globals::{registry_queue_init, GlobalList, GlobalListContent
use wayland_client::protocol::wl_callback::{self, WlCallback};
use wayland_client::protocol::wl_data_device_manager::DndAction;
use wayland_client::protocol::wl_pointer::{AxisRelativeDirection, AxisSource};
use wayland_client::protocol::wl_seat::WlSeat;
use wayland_client::protocol::{
wl_data_device, wl_data_device_manager, wl_data_offer, wl_data_source, wl_output,
};
Expand Down Expand Up @@ -71,6 +72,7 @@ pub struct Globals {
pub data_device_manager: Option<wl_data_device_manager::WlDataDeviceManager>,
pub wm_base: xdg_wm_base::XdgWmBase,
pub shm: wl_shm::WlShm,
pub seat: wl_seat::WlSeat,
pub viewporter: Option<wp_viewporter::WpViewporter>,
pub fractional_scale_manager:
Option<wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1>,
Expand All @@ -83,6 +85,7 @@ impl Globals {
globals: GlobalList,
executor: ForegroundExecutor,
qh: QueueHandle<WaylandClientStatePtr>,
seat: wl_seat::WlSeat,
) -> Self {
Globals {
compositor: globals
Expand All @@ -101,6 +104,7 @@ impl Globals {
)
.ok(),
shm: globals.bind(&qh, 1..=1, ()).unwrap(),
seat: seat,
wm_base: globals.bind(&qh, 1..=1, ()).unwrap(),
viewporter: globals.bind(&qh, 1..=1, ()).ok(),
fractional_scale_manager: globals.bind(&qh, 1..=1, ()).ok(),
Expand Down Expand Up @@ -176,6 +180,10 @@ impl WaylandClientStatePtr {
.expect("The pointer should always be valid when dispatching in wayland")
}

pub fn get_event_serial(&self) -> u32 {
self.0.upgrade().unwrap().borrow().serial
}

pub fn drop_window(&self, surface_id: &ObjectId) {
let mut client = self.get_client();
let mut state = client.borrow_mut();
Expand Down Expand Up @@ -276,7 +284,12 @@ impl WaylandClient {
});

let seat = seat.unwrap();
let globals = Globals::new(globals, common.foreground_executor.clone(), qh.clone());
let globals = Globals::new(
globals,
common.foreground_executor.clone(),
qh.clone(),
seat.clone(),
);

let data_device = globals
.data_device_manager
Expand Down Expand Up @@ -899,6 +912,7 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientStatePtr {
} => {
state.serial = serial;
state.mouse_location = Some(point(px(surface_x as f32), px(surface_y as f32)));
state.button_pressed = None;

if let Some(window) = get_window(&mut state, &surface.id()) {
state.enter_token = Some(());
Expand All @@ -922,6 +936,7 @@ impl Dispatch<wl_pointer::WlPointer, ()> for WaylandClientStatePtr {
});
state.mouse_focused_window = None;
state.mouse_location = None;
state.button_pressed = None;

drop(state);
focused_window.handle_input(input);
Expand Down
35 changes: 29 additions & 6 deletions crates/gpui/src/platform/linux/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ use crate::platform::linux::wayland::display::WaylandDisplay;
use crate::platform::{PlatformAtlas, PlatformInputHandler, PlatformWindow};
use crate::scene::Scene;
use crate::{
px, size, Bounds, DevicePixels, Globals, Modifiers, Pixels, PlatformDisplay, PlatformInput,
Point, PromptLevel, Size, WaylandClientState, WaylandClientStatePtr, WindowAppearance,
WindowBackgroundAppearance, WindowParams,
px, size, Bounds, DevicePixels, Globals, Modifiers, Pixels, PlatformDisplay, PlatformInput, Point, PromptLevel, Size, WaylandClientState, WaylandClientStatePtr, WindowAppearance, WindowBackgroundAppearance, WindowMoveState, WindowParams
};

#[derive(Default)]
Expand Down Expand Up @@ -77,6 +75,7 @@ pub struct WaylandWindowState {
decoration_state: WaylandDecorationState,
fullscreen: bool,
maximized: bool,
window_move_event_serial: u32,
client: WaylandClientStatePtr,
callbacks: Callbacks,
}
Expand Down Expand Up @@ -146,6 +145,7 @@ impl WaylandWindowState {
decoration_state: WaylandDecorationState::Client,
fullscreen: false,
maximized: false,
window_move_event_serial: 0,
callbacks: Callbacks::default(),
client,
}
Expand Down Expand Up @@ -286,7 +286,7 @@ impl WaylandWindowStatePtr {
self.set_decoration_state(WaylandDecorationState::Server)
}
WEnum::Value(zxdg_toplevel_decoration_v1::Mode::ClientSide) => {
self.set_decoration_state(WaylandDecorationState::Server)
self.set_decoration_state(WaylandDecorationState::Client)
}
WEnum::Value(_) => {
log::warn!("Unknown decoration mode");
Expand Down Expand Up @@ -322,7 +322,7 @@ impl WaylandWindowStatePtr {
self.resize(width, height);
self.set_fullscreen(fullscreen);
let mut state = self.state.borrow_mut();
state.maximized = true;
state.maximized = maximized;

false
}
Expand Down Expand Up @@ -626,7 +626,11 @@ impl PlatformWindow for WaylandWindow {
}

fn zoom(&self) {
// todo(linux)
if self.is_maximized() {
self.borrow_mut().toplevel.unset_maximized()
} else {
self.borrow_mut().toplevel.set_maximized()
}
}

fn toggle_fullscreen(&self) {
Expand Down Expand Up @@ -697,6 +701,25 @@ impl PlatformWindow for WaylandWindow {
let state = self.borrow();
state.renderer.sprite_atlas().clone()
}

fn mark_window_move(&self, move_state: WindowMoveState) {
let mut state = self.borrow_mut();
match move_state {
WindowMoveState::Start => {
state.window_move_event_serial = state.client.get_event_serial();
}
WindowMoveState::Moving => {
state.toplevel._move(&state.globals.seat, state.window_move_event_serial);
}
WindowMoveState::Stop => {
state.window_move_event_serial = 0;
}
}
}

fn should_render_window_controls(&self) -> bool {
self.borrow().decoration_state == WaylandDecorationState::Client
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
Expand Down
11 changes: 9 additions & 2 deletions crates/gpui/src/platform/linux/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
use crate::{
platform::blade::BladeRenderer, size, Bounds, DevicePixels, Modifiers, Pixels, PlatformAtlas,
PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PromptLevel,
Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowOptions, WindowParams,
X11Client, X11ClientState,
Scene, Size, WindowAppearance, WindowBackgroundAppearance, WindowMoveState, WindowOptions,
WindowParams, X11Client, X11ClientState,
};

use blade_graphics as gpu;
use parking_lot::Mutex;
use raw_window_handle as rwh;
Expand Down Expand Up @@ -533,4 +534,10 @@ impl PlatformWindow for X11Window {
let inner = self.state.borrow();
inner.renderer.sprite_atlas().clone()
}

fn mark_window_move(&self, _: WindowMoveState) {}

fn should_render_window_controls(&self) -> bool {
false
}
}
11 changes: 11 additions & 0 deletions crates/gpui/src/platform/test/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
WindowBackgroundAppearance, WindowParams,
};
use crate::WindowMoveState;
use collections::HashMap;
use parking_lot::Mutex;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
Expand Down Expand Up @@ -267,6 +268,16 @@ impl PlatformWindow for TestWindow {
fn get_raw_handle(&self) -> windows::Win32::Foundation::HWND {
unimplemented!()
}

#[cfg(target_os = "linux")]
fn mark_window_move(&self, _: WindowMoveState) {
unimplemented!()
}

#[cfg(target_os = "linux")]
fn should_render_window_controls(&self) -> bool {
false
}
}

pub(crate) struct TestAtlasState {
Expand Down
40 changes: 25 additions & 15 deletions crates/gpui/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
use crate::{
hash, point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip,
AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow,
Context, Corners, CursorStyle, DevicePixels, DispatchActionListener, DispatchNodeId,
DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten,
FontId, Global, GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyBinding,
KeyContext, KeyDownEvent, KeyEvent, KeyMatch, KeymatchResult, Keystroke, KeystrokeEvent,
LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent,
MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels,
PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,
PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams,
RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style,
SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,
TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView,
WindowAppearance, WindowBackgroundAppearance, WindowOptions, WindowParams, WindowTextSystem,
SUBPIXEL_VARIANTS,
hash, point, prelude::*, px, size, transparent_black, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, Arena, Asset, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, Global, GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, KeyMatch, KeymatchResult, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Model, ModelContext, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowAppearance, WindowBackgroundAppearance, WindowMoveState, WindowOptions, WindowParams, WindowTextSystem, SUBPIXEL_VARIANTS
};
use anyhow::{anyhow, Context as _, Result};
use collections::{FxHashMap, FxHashSet};
Expand Down Expand Up @@ -1119,6 +1105,30 @@ impl<'a> WindowContext<'a> {
self.window.platform_window.zoom();
}

/// Mark the start of window move when using client side decorations in linux (only wayland)
pub fn mark_moving(&self) {
#[cfg(target_os = "linux")]
self.window.platform_window.mark_window_move(WindowMoveState::Start)
}

/// Mark the start of window move when using client side decorations in linux (only wayland)
pub fn start_moving(&self) {
#[cfg(target_os = "linux")]
self.window.platform_window.mark_window_move(WindowMoveState::Moving)
}

/// Mark the stop of window move when using client side decorations in linux (only wayland)
pub fn stop_moving(&self) {
#[cfg(target_os = "linux")]
self.window.platform_window.mark_window_move(WindowMoveState::Stop)
}

/// Specifies if the title bar window controls need to be rendered in linux (wayland and x11)
pub fn should_render_window_controls(&self) -> bool {
#[cfg(target_os = "linux")]
self.window.platform_window.should_render_window_controls()
}

/// Updates the window's title at the platform level.
pub fn set_window_title(&mut self, title: &str) {
self.window.platform_window.set_title(title);
Expand Down
1 change: 1 addition & 0 deletions crates/ui/src/components/title_bar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod title_bar;
mod windows_window_controls;
mod linux_window_controls;

pub use title_bar::*;