Skip to content

Commit 9d7ab04

Browse files
eholkdanilo-leal
andauthored
Round window corners on the sidebar side on Linux (#61229)
On Linux with client-side decorations, opening the workspace sidebar squared off the window corners on the sidebar's side while the rest of the window stayed rounded: Before: <img width="366" height="239" alt="image" src="https://github.com/user-attachments/assets/e0ee8d28-6143-42ea-bfd2-10d069df5492" /> After: <img width="426" height="219" alt="image" src="https://github.com/user-attachments/assets/51d2979d-0103-4742-90bd-a97f5837d99b" /> Previously, `client_side_decorations` took a `border_radius_tiling` override that `MultiWorkspace` used to deliberately square the window shape on the sidebar's side, since the sidebar painted a square background that would otherwise poke out past the rounded window border. The title bar and status bar already skip rounding their corners on the sidebar side, implying the sidebar is expected to own those window corners — it just never rounded them. This PR makes the sidebar round its outer corners the same way the title bar and status bar do (including overlapping the 1px window border on untiled edges to avoid a transparent gap in the rounded corners), and removes the now-unneeded `border_radius_tiling` parameter so the window border and backdrop round purely based on actual tiling state. Only applies when the window uses client-side decorations, so macOS and Windows are unaffected. Fixes #54724 Release Notes: - Fixed square window corners on the sidebar side of client-decorated (Linux) windows when the workspace sidebar is open. --------- Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
1 parent 7eb8af2 commit 9d7ab04

5 files changed

Lines changed: 54 additions & 37 deletions

File tree

crates/settings_ui/src/pages/audio_test_window.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use audio::{AudioSettings, CHANNEL_COUNT, RodioExt, SAMPLE_RATE};
22
use cpal::DeviceId;
33
use gpui::{
4-
App, Context, Entity, FocusHandle, Focusable, Render, Size, Tiling, Window, WindowBounds,
5-
WindowKind, WindowOptions, prelude::*, px,
4+
App, Context, Entity, FocusHandle, Focusable, Render, Size, Window, WindowBounds, WindowKind,
5+
WindowOptions, prelude::*, px,
66
};
77
use platform_title_bar::PlatformTitleBar;
88
use release_channel::ReleaseChannel;
@@ -244,7 +244,6 @@ impl Render for AudioTestWindow {
244244
.child(content),
245245
window,
246246
cx,
247-
Tiling::default(),
248247
)
249248
}
250249
}

crates/settings_ui/src/settings_ui.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use fuzzy::StringMatchCandidate;
1111
use gpui::{
1212
Action, App, AsyncApp, ClipboardItem, DEFAULT_ADDITIONAL_WINDOW_SIZE, Div, Entity, FocusHandle,
1313
Focusable, Global, KeyContext, ListState, ReadGlobal as _, Role, ScrollHandle, Stateful,
14-
Subscription, Task, Tiling, TitlebarOptions, UniformListScrollHandle, WeakEntity, Window,
15-
WindowBounds, WindowHandle, WindowOptions, actions, div, list, point, prelude::*, px,
16-
uniform_list,
14+
Subscription, Task, TitlebarOptions, UniformListScrollHandle, WeakEntity, Window, WindowBounds,
15+
WindowHandle, WindowOptions, actions, div, list, point, prelude::*, px, uniform_list,
1716
};
1817

1918
use language::Buffer;
@@ -4556,7 +4555,6 @@ impl Render for SettingsWindow {
45564555
),
45574556
window,
45584557
cx,
4559-
Tiling::default(),
45604558
)
45614559
}
45624560
}

crates/sidebar/src/sidebar.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ use feature_flags::{
2828
AgentThreadWorktreeLabel, AgentThreadWorktreeLabelFlag, FeatureFlag, FeatureFlagAppExt as _,
2929
};
3030
use gpui::{
31-
Action as _, AnyElement, App, ClickEvent, Context, DismissEvent, Entity, EntityId, FocusHandle,
32-
Focusable, KeyContext, ListState, Modifiers, Pixels, Render, SharedString, Task, TaskExt,
33-
WeakEntity, Window, WindowBackgroundAppearance, WindowHandle, linear_color_stop,
31+
Action as _, AnyElement, App, ClickEvent, Context, Decorations, DismissEvent, Entity, EntityId,
32+
FocusHandle, Focusable, KeyContext, ListState, Modifiers, Pixels, Render, SharedString, Task,
33+
TaskExt, WeakEntity, Window, WindowBackgroundAppearance, WindowHandle, linear_color_stop,
3434
linear_gradient, list, prelude::*, px,
3535
};
3636
use itertools::Itertools;
@@ -52,7 +52,7 @@ use std::mem;
5252
use std::path::{Path, PathBuf};
5353
use std::rc::Rc;
5454
use std::sync::Arc;
55-
use theme::ActiveTheme;
55+
use theme::{ActiveTheme, CLIENT_SIDE_DECORATION_ROUNDING};
5656
use ui::{
5757
AgentThreadStatus, CommonAnimationExt, ContextMenu, ContextMenuEntry, Divider, GradientFade,
5858
HighlightedLabel, KeyBinding, PopoverMenu, PopoverMenuHandle, ProjectEmptyState, ScrollAxes,
@@ -8076,8 +8076,48 @@ impl Render for Sidebar {
80768076
this.recent_projects_popover_handle.toggle(window, cx);
80778077
}))
80788078
.font(ui_font)
8079-
.h_full()
8080-
.w(self.width)
8079+
.map(|el| {
8080+
let on_left = self.side(cx) == SidebarSide::Left;
8081+
match window.window_decorations() {
8082+
Decorations::Server => el.h_full().w(self.width),
8083+
// With client-side decorations the sidebar owns the window
8084+
// corners on its side, so round them like the title bar and
8085+
// status bar do. The sidebar is stretched 1px outwards over
8086+
// the window border on untiled edges (with compensating
8087+
// padding) so its rounded background lines up exactly with
8088+
// the window shape, avoiding a transparent gap in the
8089+
// rounded corners.
8090+
Decorations::Client { tiling, .. } => el
8091+
.absolute()
8092+
.top(if tiling.top { px(0.) } else { px(-1.) })
8093+
.bottom(if tiling.bottom { px(0.) } else { px(-1.) })
8094+
.when(!tiling.top, |el| el.pt_px())
8095+
.when(!tiling.bottom, |el| el.pb_px())
8096+
.map(|el| {
8097+
if on_left {
8098+
el.right(px(0.))
8099+
.left(if tiling.left { px(0.) } else { px(-1.) })
8100+
.when(!tiling.left, |el| el.pl(px(1.)))
8101+
} else {
8102+
el.left(px(0.))
8103+
.right(if tiling.right { px(0.) } else { px(-1.) })
8104+
.when(!tiling.right, |el| el.pr(px(1.)))
8105+
}
8106+
})
8107+
.when(on_left && !(tiling.top || tiling.left), |el| {
8108+
el.rounded_tl(CLIENT_SIDE_DECORATION_ROUNDING)
8109+
})
8110+
.when(on_left && !(tiling.bottom || tiling.left), |el| {
8111+
el.rounded_bl(CLIENT_SIDE_DECORATION_ROUNDING)
8112+
})
8113+
.when(!on_left && !(tiling.top || tiling.right), |el| {
8114+
el.rounded_tr(CLIENT_SIDE_DECORATION_ROUNDING)
8115+
})
8116+
.when(!on_left && !(tiling.bottom || tiling.right), |el| {
8117+
el.rounded_br(CLIENT_SIDE_DECORATION_ROUNDING)
8118+
}),
8119+
}
8120+
})
80818121
.bg(bg)
80828122
.when(self.side(cx) == SidebarSide::Left, |el| el.border_r_1())
80838123
.when(self.side(cx) == SidebarSide::Right, |el| el.border_l_1())

crates/workspace/src/multi_workspace.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use fs::Fs;
33

44
use gpui::{
55
AnyView, App, Context, DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
6-
ManagedView, MouseButton, Pixels, Render, Subscription, Task, TaskExt, Tiling, WeakEntity,
7-
Window, WindowId, actions, deferred, px,
6+
ManagedView, MouseButton, Pixels, Render, Subscription, Task, TaskExt, WeakEntity, Window,
7+
WindowId, actions, deferred, px,
88
};
99
pub use project::ProjectGroupKey;
1010
use project::{DisableAiSettings, Project};
@@ -2292,11 +2292,6 @@ impl Render for MultiWorkspace {
22922292
})),
22932293
window,
22942294
cx,
2295-
Tiling {
2296-
left: !sidebar_on_right && multi_workspace_enabled && self.sidebar_open(),
2297-
right: sidebar_on_right && multi_workspace_enabled && self.sidebar_open(),
2298-
..Tiling::default()
2299-
},
23002295
)
23012296
}
23022297
}

crates/workspace/src/workspace.rs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11103,32 +11103,17 @@ fn parse_pixel_size_env_var(value: &str) -> Option<Size<Pixels>> {
1110311103

1110411104
/// Add client-side decorations (rounded corners, shadows, resize handling) when
1110511105
/// appropriate.
11106-
///
11107-
/// The `border_radius_tiling` parameter allows overriding which corners get
11108-
/// rounded, independently of the actual window tiling state. This is used
11109-
/// specifically for the workspace switcher sidebar: when the sidebar is open,
11110-
/// we want square corners on the left (so the sidebar appears flush with the
11111-
/// window edge) but we still need the shadow padding for proper visual
11112-
/// appearance. Unlike actual window tiling, this only affects border radius -
11113-
/// not padding or shadows.
1111411106
pub fn client_side_decorations(
1111511107
element: impl IntoElement,
1111611108
window: &mut Window,
1111711109
cx: &mut App,
11118-
border_radius_tiling: Tiling,
1111911110
) -> Stateful<Div> {
1112011111
const BORDER_SIZE: Pixels = px(1.0);
1112111112
let decorations = window.window_decorations();
1112211113
let tiling = match decorations {
1112311114
Decorations::Server => Tiling::default(),
1112411115
Decorations::Client { tiling } => tiling,
1112511116
};
11126-
let corner_tiling = Tiling {
11127-
top: tiling.top || border_radius_tiling.top,
11128-
bottom: tiling.bottom || border_radius_tiling.bottom,
11129-
left: tiling.left || border_radius_tiling.left,
11130-
right: tiling.right || border_radius_tiling.right,
11131-
};
1113211117

1113311118
match decorations {
1113411119
Decorations::Client { .. } => window.set_client_inset(theme::CLIENT_SIDE_DECORATION_SHADOW),
@@ -11144,7 +11129,7 @@ pub fn client_side_decorations(
1114411129
.map(|div| match decorations {
1114511130
Decorations::Server => div,
1114611131
Decorations::Client { .. } => div
11147-
.rounded_client_corners(corner_tiling)
11132+
.rounded_client_corners(tiling)
1114811133
.when(!tiling.top, |div| {
1114911134
div.pt(theme::CLIENT_SIDE_DECORATION_SHADOW)
1115011135
})
@@ -11199,7 +11184,7 @@ pub fn client_side_decorations(
1119911184
Decorations::Server => div,
1120011185
Decorations::Client { .. } => div
1120111186
.border_color(cx.theme().colors().border)
11202-
.rounded_client_corners(corner_tiling)
11187+
.rounded_client_corners(tiling)
1120311188
.when(!tiling.top, |div| div.border_t(BORDER_SIZE))
1120411189
.when(!tiling.bottom, |div| div.border_b(BORDER_SIZE))
1120511190
.when(!tiling.left, |div| div.border_l(BORDER_SIZE))

0 commit comments

Comments
 (0)