Skip to content

Commit e70d785

Browse files
committed
Clean up DPI code, add file icon on macOS
1 parent 6409062 commit e70d785

File tree

6 files changed

+242
-195
lines changed

6 files changed

+242
-195
lines changed

frontend/desktop/src/config.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,18 @@ pub enum TitleBarMode {
376376

377377
impl TitleBarMode {
378378
#[cfg(target_os = "macos")]
379-
pub fn system_title_bar_is_hidden(&self) -> bool {
379+
pub fn system_title_bar_is_transparent(&self) -> bool {
380380
*self != TitleBarMode::System
381381
}
382+
383+
#[cfg(target_os = "macos")]
384+
pub fn should_show_system_title_bar(&self, show_menu_bar: bool) -> bool {
385+
match self {
386+
TitleBarMode::System => true,
387+
TitleBarMode::Mixed => show_menu_bar,
388+
TitleBarMode::Imgui => false,
389+
}
390+
}
382391
}
383392

384393
fn resolve_opt_nonzero_u32(

frontend/desktop/src/input/state.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ use crate::ui::utils::mul2s;
33
use ahash::AHashSet as HashSet;
44
use dust_core::emu::input::Keys as EmuKeys;
55
use winit::{
6-
dpi::{PhysicalPosition, PhysicalSize},
6+
dpi::{LogicalPosition, LogicalSize},
77
event::{Event, KeyEvent, MouseButton, WindowEvent},
88
};
99

1010
pub struct State {
1111
pressed_keys: HashSet<PressedKey>,
12-
touchscreen_center: PhysicalPosition<f64>,
13-
touchscreen_size: PhysicalSize<f64>,
14-
touchscreen_half_size: PhysicalSize<f64>,
12+
touchscreen_center: LogicalPosition<f64>,
13+
touchscreen_size: LogicalSize<f64>,
14+
touchscreen_half_size: LogicalSize<f64>,
1515
touchscreen_rot: (f64, f64),
16-
touchscreen_rot_center: PhysicalPosition<f64>,
17-
mouse_pos: PhysicalPosition<f64>,
16+
touchscreen_rot_center: LogicalPosition<f64>,
17+
mouse_pos: LogicalPosition<f64>,
1818
touch_pos: Option<[u16; 2]>,
1919
prev_touch_pos: Option<[u16; 2]>,
2020
pressed_emu_keys: EmuKeys,
@@ -50,18 +50,16 @@ impl State {
5050
center: [f32; 2],
5151
points: &[[f32; 2]; 4],
5252
rot: f32,
53-
scale_factor: f64,
5453
) {
5554
fn distance(a: [f32; 2], b: [f32; 2]) -> f32 {
5655
let x = b[0] - a[0];
5756
let y = b[1] - a[1];
5857
(x * x + y * y).sqrt()
5958
}
6059

61-
let center = center.map(|v| v as f64 * scale_factor);
6260
let size = [
63-
distance(points[0], points[1]) as f64 * scale_factor,
64-
(distance(points[1], points[2]) * 0.5) as f64 * scale_factor,
61+
distance(points[0], points[1]),
62+
distance(points[1], points[2]) * 0.5,
6563
];
6664
self.set_touchscreen_bounds(
6765
center.into(),
@@ -73,9 +71,9 @@ impl State {
7371

7472
pub fn set_touchscreen_bounds(
7573
&mut self,
76-
rot_center: PhysicalPosition<f64>,
77-
center: PhysicalPosition<f64>,
78-
size: PhysicalSize<f64>,
74+
rot_center: LogicalPosition<f64>,
75+
center: LogicalPosition<f64>,
76+
size: LogicalSize<f64>,
7977
rot: f64,
8078
) {
8179
self.touchscreen_center = center;
@@ -117,7 +115,12 @@ impl State {
117115
]);
118116
}
119117

120-
pub fn process_event<T: 'static>(&mut self, event: &Event<T>, catch_new: bool) {
118+
pub fn process_event<T: 'static>(
119+
&mut self,
120+
event: &Event<T>,
121+
scale_factor: f64,
122+
catch_new: bool,
123+
) {
121124
if let Event::WindowEvent { event, .. } = event {
122125
match event {
123126
WindowEvent::KeyboardInput {
@@ -142,7 +145,7 @@ impl State {
142145
}
143146

144147
WindowEvent::CursorMoved { position, .. } => {
145-
self.mouse_pos = *position;
148+
self.mouse_pos = position.to_logical(scale_factor);
146149
if self.touch_pos.is_some() {
147150
self.recalculate_touch_pos::<true>();
148151
}

frontend/desktop/src/ui.rs

+54-60
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ enum Renderer3dData {
7676
struct EmuState {
7777
playing: bool,
7878
title: String,
79+
#[cfg(target_os = "macos")]
80+
path: Option<PathBuf>,
7981
game_loaded: bool,
8082
save_path_update: Option<emu::SavePathUpdate>,
8183
#[cfg(feature = "gdb-server")]
@@ -217,8 +219,8 @@ pub struct UiState {
217219

218220
audio_channel: Option<audio::output::Channel>,
219221

220-
#[cfg(target_os = "windows")]
221-
icon_update: Option<Option<[u32; 32 * 32]>>,
222+
#[cfg(target_os = "macos")]
223+
shown_file_path: Option<PathBuf>,
222224

223225
#[cfg(feature = "logging")]
224226
log: Log,
@@ -499,7 +501,7 @@ impl UiState {
499501
let (ds_slot_rom, _ds_slot_rom_path) = ds_slot_rom.unzip();
500502
#[allow(unused_mut, clippy::bind_instead_of_map)]
501503
let ds_slot = ds_slot_rom.and_then(|mut rom| {
502-
#[cfg(target_os = "windows")]
504+
#[cfg(any(target_os = "linux", target_os = "windows"))]
503505
{
504506
use dust_core::{ds_slot, utils::Bytes};
505507
let mut header_bytes = Bytes::new([0; 0x170]);
@@ -508,7 +510,14 @@ impl UiState {
508510
// NOTE: The ROM file's size is ensured beforehand, this should never occur.
509511
.expect("couldn't read DS slot ROM header");
510512
let icon_title_offset = header.icon_title_offset() as usize;
511-
self.icon_update = Some(ds_slot::rom::icon::decode(icon_title_offset, &mut rom));
513+
let icon_pixels = ds_slot::rom::icon::decode(icon_title_offset, &mut rom);
514+
window.set_icon(icon_pixels.and_then(|icon_pixels| {
515+
let mut rgba = Vec::with_capacity(32 * 32 * 4);
516+
for pixel in icon_pixels {
517+
rgba.extend_from_slice(&pixel.to_le_bytes());
518+
}
519+
winit::window::Icon::from_rgba(rgba, 32, 32).ok()
520+
}));
512521
}
513522

514523
let game_code = rom.game_code();
@@ -658,6 +667,8 @@ impl UiState {
658667
self.emu = Some(EmuState {
659668
playing,
660669
title,
670+
#[cfg(target_os = "macos")]
671+
path: _ds_slot_rom_path.map(Path::to_path_buf),
661672
game_loaded,
662673
save_path_update: None,
663674
#[cfg(feature = "gdb-server")]
@@ -725,9 +736,9 @@ impl UiState {
725736
},
726737
);
727738

728-
#[cfg(target_os = "windows")]
739+
#[cfg(any(target_os = "linux", target_os = "windows"))]
729740
{
730-
self.icon_update = Some(None);
741+
window.set_icon(None);
731742
}
732743

733744
#[cfg(feature = "discord-presence")]
@@ -749,10 +760,8 @@ impl UiState {
749760
}
750761

751762
#[cfg(target_os = "macos")]
752-
{
753-
if let Some(mode) = config_changed_value!(config, title_bar_mode) {
754-
_window.set_macos_title_bar_hidden(mode.system_title_bar_is_hidden());
755-
}
763+
if let Some(mode) = config_changed_value!(config, title_bar_mode) {
764+
_window.set_macos_title_bar_transparent(mode.system_title_bar_is_transparent());
756765
}
757766
}
758767

@@ -789,19 +798,26 @@ impl UiState {
789798
buffer
790799
}
791800

792-
fn update_title(&self, _config: &config::Config, window: &window::Window) {
793-
#[cfg(target_os = "macos")]
794-
if match config!(_config, title_bar_mode) {
795-
TitleBarMode::System => false,
796-
TitleBarMode::Mixed => !self.show_menu_bar,
797-
TitleBarMode::Imgui => true,
798-
} {
799-
window.window().set_title("");
800-
return;
801+
#[cfg(not(target_os = "macos"))]
802+
fn update_title_bar(&mut self, _config: &config::Config, window: &window::Window) {
803+
window.set_title(&self.title(TitleComponents::all()));
804+
}
805+
806+
#[cfg(target_os = "macos")]
807+
fn update_title_bar(&mut self, _config: &config::Config, window: &window::Window) {
808+
let show_system_title_bar =
809+
config!(_config, title_bar_mode).should_show_system_title_bar(self.show_menu_bar);
810+
let shown_file_path = if show_system_title_bar {
811+
window.set_title(&self.title(TitleComponents::all()));
812+
self.emu.as_ref().and_then(|emu| emu.path.as_deref())
813+
} else {
814+
window.set_title("");
815+
None
816+
};
817+
if shown_file_path != self.shown_file_path.as_deref() {
818+
self.shown_file_path = shown_file_path.map(Path::to_path_buf);
819+
window.set_file_path(shown_file_path);
801820
}
802-
window
803-
.window()
804-
.set_title(&self.title(TitleComponents::all()));
805821
}
806822
}
807823

@@ -934,7 +950,7 @@ pub fn main() {
934950
config.config.window_size,
935951
window::SrgbMode::None,
936952
#[cfg(target_os = "macos")]
937-
config!(config.config, title_bar_mode).system_title_bar_is_hidden(),
953+
config!(config.config, title_bar_mode).system_title_bar_is_transparent(),
938954
));
939955
// TODO: Allow custom styles
940956
window_builder.apply_default_imgui_style();
@@ -985,8 +1001,8 @@ pub fn main() {
9851001

9861002
audio_channel,
9871003

988-
#[cfg(target_os = "windows")]
989-
icon_update: None,
1004+
#[cfg(target_os = "macos")]
1005+
shown_file_path: None,
9901006

9911007
#[cfg(feature = "logging")]
9921008
log,
@@ -1024,7 +1040,9 @@ pub fn main() {
10241040
state.load_from_rom_path(path, config, window);
10251041
}
10261042

1027-
state.input.process_event(event, state.screen_focused);
1043+
state
1044+
.input
1045+
.process_event(event, window.scale_factor(), state.screen_focused);
10281046

10291047
if let Some(config_editor) = &mut state.config_editor {
10301048
config_editor.process_event(event, config);
@@ -1680,18 +1698,15 @@ pub fn main() {
16801698
}
16811699
}
16821700

1683-
let window_size = window.window().inner_size();
1701+
let window_size = window.inner_size();
16841702
let screen_integer_scale = config!(config.config, screen_integer_scale);
16851703
let screen_rot = (config!(config.config, screen_rot) as f32).to_radians();
16861704
if config!(config.config, full_window_screen) {
16871705
let (center, points) = scale_to_fit_rotated(
16881706
[SCREEN_WIDTH as f32, (2 * SCREEN_HEIGHT) as f32],
16891707
screen_integer_scale,
16901708
screen_rot,
1691-
[
1692-
(window_size.width as f64 / window.scale_factor()) as f32,
1693-
(window_size.height as f64 / window.scale_factor()) as f32,
1694-
],
1709+
window_size.into(),
16951710
);
16961711
ui.get_background_draw_list()
16971712
.add_image_quad(
@@ -1704,12 +1719,9 @@ pub fn main() {
17041719
.build();
17051720
state.screen_focused =
17061721
!ui.is_window_focused_with_flags(imgui::WindowFocusedFlags::ANY_WINDOW);
1707-
state.input.set_touchscreen_bounds_from_points(
1708-
center,
1709-
&points,
1710-
screen_rot,
1711-
window.scale_factor(),
1712-
);
1722+
state
1723+
.input
1724+
.set_touchscreen_bounds_from_points(center, &points, screen_rot);
17131725
} else {
17141726
let _window_padding = ui.push_style_var(imgui::StyleVar::WindowPadding([0.0; 2]));
17151727
let title_bar_height = style!(ui, frame_padding)[1] * 2.0 + ui.current_font_size();
@@ -1725,8 +1737,8 @@ pub fn main() {
17251737
)
17261738
.position(
17271739
[
1728-
(window_size.width as f64 * 0.5 / window.scale_factor()) as f32,
1729-
(window_size.height as f64 * 0.5 / window.scale_factor()) as f32,
1740+
(window_size.width * 0.5) as f32,
1741+
(window_size.height * 0.5) as f32,
17301742
],
17311743
imgui::Condition::FirstUseEver,
17321744
)
@@ -1769,26 +1781,12 @@ pub fn main() {
17691781
[center[0] + upper_left[0], center[1] + upper_left[1]],
17701782
&abs_points,
17711783
screen_rot,
1772-
window.scale_factor(),
17731784
);
17741785
});
17751786
};
17761787

1777-
// Process icon and title changes
1778-
#[cfg(target_os = "windows")]
1779-
if let Some(icon) = state.icon_update.take() {
1780-
window
1781-
.window()
1782-
.set_window_icon(icon.and_then(|icon_pixels| {
1783-
let mut rgba = Vec::with_capacity(32 * 32 * 4);
1784-
for pixel in icon_pixels {
1785-
rgba.extend_from_slice(&pixel.to_le_bytes());
1786-
}
1787-
winit::window::Icon::from_rgba(rgba, 32, 32).ok()
1788-
}));
1789-
}
1790-
1791-
state.update_title(&config.config, window);
1788+
// Process title bar changes
1789+
state.update_title_bar(&config.config, window);
17921790

17931791
window::ControlFlow::Continue
17941792
},
@@ -1829,11 +1827,7 @@ pub fn main() {
18291827
move |window, (mut config, mut state)| {
18301828
state.stop_emu(&mut config);
18311829

1832-
config.config.window_size = window
1833-
.window()
1834-
.inner_size()
1835-
.to_logical::<u32>(window.scale_factor())
1836-
.into();
1830+
config.config.window_size = window.inner_size().into();
18371831

18381832
if let Some(path) = config.global_path {
18391833
let global_config = config::File {

0 commit comments

Comments
 (0)