Skip to content

Commit

Permalink
add mac traffic lights position control
Browse files Browse the repository at this point in the history
  • Loading branch information
dzhou121 committed Nov 3, 2023
1 parent 96d8a1f commit 444ecd9
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 2 deletions.
14 changes: 14 additions & 0 deletions src/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ pub trait WindowBuilderExtMacOS {
fn with_fullsize_content_view(self, fullsize_content_view: bool) -> Self;
fn with_disallow_hidpi(self, disallow_hidpi: bool) -> Self;
fn with_has_shadow(self, has_shadow: bool) -> Self;
fn with_movable(self, movable: bool) -> Self;
fn with_traffic_lights_offset(self, x: f64, y: f64) -> Self;
/// Window accepts click-through mouse events.
fn with_accepts_first_mouse(self, accepts_first_mouse: bool) -> Self;
/// Defines the window tabbing identifier.
Expand Down Expand Up @@ -248,6 +250,18 @@ impl WindowBuilderExtMacOS for WindowBuilder {
self
}

#[inline]
fn with_movable(mut self, movable: bool) -> Self {
self.platform_specific.movable = movable;
self
}

#[inline]
fn with_traffic_lights_offset(mut self, x: f64, y: f64) -> Self {
self.platform_specific.traffic_lights_offset = Some((x, y));
self
}

#[inline]
fn with_fullsize_content_view(mut self, fullsize_content_view: bool) -> Self {
self.platform_specific.fullsize_content_view = fullsize_content_view;
Expand Down
8 changes: 7 additions & 1 deletion src/platform_impl/macos/appkit/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ffi::c_void;
use std::num::NonZeroIsize;
use std::ptr;

use icrate::Foundation::{NSObject, NSPoint, NSRect};
use icrate::Foundation::{CGPoint, NSObject, NSPoint, NSRect};
use objc2::rc::Id;
use objc2::runtime::AnyObject;
use objc2::{extern_class, extern_methods, mutability, ClassType};
Expand Down Expand Up @@ -91,6 +91,12 @@ extern_methods!(

#[method(setHidden:)]
pub fn setHidden(&self, hidden: bool);

#[method(setFrame:)]
pub fn setFrame(&self, rect: NSRect);

#[method(setFrameOrigin:)]
pub fn setFrameOrigin(&self, origin: CGPoint);
}
);

Expand Down
2 changes: 2 additions & 0 deletions src/platform_impl/macos/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use super::{
},
event::{code_to_key, code_to_location},
};
use crate::platform_impl::platform::window::position_traffic_lights;
use crate::{
dpi::{LogicalPosition, LogicalSize},
event::{
Expand Down Expand Up @@ -245,6 +246,7 @@ declare_class!(
let logical_size = LogicalSize::new(rect.size.width as f64, rect.size.height as f64);
let size = logical_size.to_physical::<u32>(self.scale_factor());
self.queue_event(WindowEvent::Resized(size));
position_traffic_lights(&self.window());
}

#[method(drawRect:)]
Expand Down
42 changes: 41 additions & 1 deletion src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,14 @@ pub struct PlatformSpecificWindowBuilderAttributes {
pub title_hidden: bool,
pub titlebar_hidden: bool,
pub titlebar_buttons_hidden: bool,
pub movable: bool,
pub fullsize_content_view: bool,
pub disallow_hidpi: bool,
pub has_shadow: bool,
pub accepts_first_mouse: bool,
pub tabbing_identifier: Option<String>,
pub option_as_alt: OptionAsAlt,
pub traffic_lights_offset: Option<(f64, f64)>,
}

impl Default for PlatformSpecificWindowBuilderAttributes {
Expand All @@ -137,11 +139,13 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
titlebar_hidden: false,
titlebar_buttons_hidden: false,
fullsize_content_view: false,
movable: true,
disallow_hidpi: false,
has_shadow: true,
accepts_first_mouse: true,
tabbing_identifier: None,
option_as_alt: Default::default(),
traffic_lights_offset: None,
}
}
}
Expand Down Expand Up @@ -242,6 +246,8 @@ pub struct SharedState {
pub(crate) option_as_alt: OptionAsAlt,

decorations: bool,

traffic_lights_offset: Option<(f64, f64)>,
}

impl SharedState {
Expand Down Expand Up @@ -370,6 +376,7 @@ impl WinitWindow {
resizable: attrs.resizable,
maximized: attrs.maximized,
decorations: attrs.decorations,
traffic_lights_offset: pl_attrs.traffic_lights_offset,
..Default::default()
};

Expand Down Expand Up @@ -415,6 +422,9 @@ impl WinitWindow {
if pl_attrs.title_hidden {
this.setTitleVisibility(NSWindowTitleVisibility::Hidden);
}
if !pl_attrs.movable {
this.setMovable(false);
}
if pl_attrs.titlebar_buttons_hidden {
for titlebar_button in &[
#[allow(deprecated)]
Expand Down Expand Up @@ -547,6 +557,7 @@ impl WinitWindow {
if attrs.maximized {
this.set_maximized(attrs.maximized);
}
position_traffic_lights(&this);

Ok((this, delegate))
}
Expand Down Expand Up @@ -578,7 +589,8 @@ impl WinitWindow {
}

pub fn set_title(&self, title: &str) {
self.setTitle(&NSString::from_str(title))
self.setTitle(&NSString::from_str(title));
position_traffic_lights(self);
}

pub fn set_transparent(&self, transparent: bool) {
Expand Down Expand Up @@ -1630,3 +1642,31 @@ fn set_ns_theme(theme: Option<Theme>) {
app.setAppearance(appearance.as_ref().map(|a| a.as_ref()));
}
}

pub(super) fn position_traffic_lights(window: &WinitWindow) -> Option<()> {
let offset = { window.shared_state.lock().ok()?.traffic_lights_offset? };

let close = window.standardWindowButton(NSWindowButton::Close)?;
let miniaturize = window.standardWindowButton(NSWindowButton::Miniaturize)?;
let zoom = window.standardWindowButton(NSWindowButton::Zoom)?;

let superview: &mut NSView = unsafe { msg_send![&close, superview] };
let title_bar_container_view: &mut NSView = unsafe { msg_send![superview, superview] };

let close_rect = close.frame();
let title_bar_frame_height = close_rect.size.height + offset.1;
let mut title_bar_rect = NSView::frame(title_bar_container_view);
title_bar_rect.size.height = title_bar_frame_height;
title_bar_rect.origin.y = window.frame().size.height - title_bar_frame_height;
title_bar_container_view.setFrame(title_bar_rect);

let space_between = miniaturize.frame().origin.x - close_rect.origin.x;
let window_buttons = vec![close, miniaturize, zoom];

for (i, button) in window_buttons.into_iter().enumerate() {
let mut rect = button.frame();
rect.origin.x = offset.0 + (i as f64 * space_between);
button.setFrameOrigin(rect.origin);
}
Some(())
}
2 changes: 2 additions & 0 deletions src/platform_impl/macos/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use super::{
window::{get_ns_theme, WinitWindow},
Fullscreen,
};
use crate::platform_impl::platform::window::position_traffic_lights;
use crate::{
dpi::{LogicalPosition, LogicalSize},
event::{Event, WindowEvent},
Expand Down Expand Up @@ -333,6 +334,7 @@ declare_class!(
if let Some(target_fullscreen) = target_fullscreen {
self.window.set_fullscreen(target_fullscreen);
}
position_traffic_lights(&self.window);
}

/// Invoked when fail to enter fullscreen
Expand Down

0 comments on commit 444ecd9

Please sign in to comment.