Make drag and double click enabled on the whole title bar on macOS (#41839)

Closes #4947

Taken inspiration from @tasuren implementation, plus the addition for
the double click enabled on the whole title bar too to
maximizes/restores the window.

I was not able to test the application on Linux, no need to test on
Windows since the feature is enabled by the OS.

Release Notes:

- Fixed title bar not fully draggable on macOS
- Fixed not being able to maximizes/restores the window with double
click on the whole title bar on macOS
This commit is contained in:
Ivan Pasquariello
2025-11-14 22:46:35 +00:00
committed by GitHub
parent c387203ac8
commit 305206fd48
3 changed files with 53 additions and 36 deletions
+11
View File
@@ -1543,6 +1543,17 @@ impl PlatformWindow for MacWindow {
})
.detach();
}
fn start_window_move(&self) {
let this = self.0.lock();
let window = this.native_window;
unsafe {
let app = NSApplication::sharedApplication(nil);
let mut event: id = msg_send![app, currentEvent];
let _: () = msg_send![window, performWindowDragWithEvent: event];
}
}
}
impl rwh::HasWindowHandle for MacWindow {
+1
View File
@@ -1819,6 +1819,7 @@ impl Window {
self.platform_window.show_window_menu(position)
}
/// Handle window movement for Linux and macOS.
/// Tells the compositor to take control of window movement (Wayland and X11)
///
/// Events may not be received during a move operation.
+41 -36
View File
@@ -77,6 +77,47 @@ impl Render for PlatformTitleBar {
.window_control_area(WindowControlArea::Drag)
.w_full()
.h(height)
.map(|this| {
this.on_mouse_down_out(cx.listener(move |this, _ev, _window, _cx| {
this.should_move = false;
}))
.on_mouse_up(
gpui::MouseButton::Left,
cx.listener(move |this, _ev, _window, _cx| {
this.should_move = false;
}),
)
.on_mouse_down(
gpui::MouseButton::Left,
cx.listener(move |this, _ev, _window, _cx| {
this.should_move = true;
}),
)
.on_mouse_move(cx.listener(move |this, _ev, window, _| {
if this.should_move {
this.should_move = false;
window.start_window_move();
}
}))
})
.map(|this| {
// Note: On Windows the title bar behavior is handled by the platform implementation.
this.id(self.id.clone())
.when(self.platform_style == PlatformStyle::Mac, |this| {
this.on_click(|event, window, _| {
if event.click_count() == 2 {
window.titlebar_double_click();
}
})
})
.when(self.platform_style == PlatformStyle::Linux, |this| {
this.on_click(|event, window, _| {
if event.click_count() == 2 {
window.zoom_window();
}
})
})
})
.map(|this| {
if window.is_fullscreen() {
this.pl_2()
@@ -112,21 +153,6 @@ impl Render for PlatformTitleBar {
.justify_between()
.overflow_x_hidden()
.w_full()
// Note: On Windows the title bar behavior is handled by the platform implementation.
.when(self.platform_style == PlatformStyle::Mac, |this| {
this.on_click(|event, window, _| {
if event.click_count() == 2 {
window.titlebar_double_click();
}
})
})
.when(self.platform_style == PlatformStyle::Linux, |this| {
this.on_click(|event, window, _| {
if event.click_count() == 2 {
window.zoom_window();
}
})
})
.children(children),
)
.when(!window.is_fullscreen(), |title_bar| {
@@ -142,27 +168,6 @@ impl Render for PlatformTitleBar {
window.show_window_menu(ev.position)
})
})
.on_mouse_move(cx.listener(move |this, _ev, window, _| {
if this.should_move {
this.should_move = false;
window.start_window_move();
}
}))
.on_mouse_down_out(cx.listener(move |this, _ev, _window, _cx| {
this.should_move = false;
}))
.on_mouse_up(
MouseButton::Left,
cx.listener(move |this, _ev, _window, _cx| {
this.should_move = false;
}),
)
.on_mouse_down(
MouseButton::Left,
cx.listener(move |this, _ev, _window, _cx| {
this.should_move = true;
}),
)
} else {
title_bar
}