Skip to content

Commit 7a816b9

Browse files
author
jcm
committed
hiro: add cursor auto-hide
1 parent e176d8b commit 7a816b9

File tree

10 files changed

+100
-2
lines changed

10 files changed

+100
-2
lines changed

Diff for: desktop-ui/presentation/presentation.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ Presentation::Presentation() {
1515

1616
settingsMenu.setText("Settings");
1717
videoSizeMenu.setText("Size").setIcon(Icon::Emblem::Image);
18+
19+
bool hideCursorImplemented = false;
20+
#if defined(PLATFORM_MACOS)
21+
hideCursorImplemented = true;
22+
#endif
1823

1924
//generate size menu
2025
u32 multipliers = 5;
@@ -95,6 +100,14 @@ Presentation::Presentation() {
95100
muteAudioSetting.setText("Mute Audio").setChecked(settings.audio.mute).onToggle([&] {
96101
settings.audio.mute = muteAudioSetting.checked();
97102
});
103+
autoHideCursorSetting.setText("Auto-Hide Cursor").setChecked(settings.general.autoHideCursor).onToggle([&] {
104+
settings.general.autoHideCursor = autoHideCursorSetting.checked();
105+
settingsWindow.optionSettings.autoHideCursorOption.setChecked(settings.general.autoHideCursor);
106+
presentation.setHidesCursor(settings.general.autoHideCursor);
107+
});
108+
if(!hideCursorImplemented) {
109+
autoHideCursorSetting.setVisible(false);
110+
}
98111
showStatusBarSetting.setText("Show Status Bar").setChecked(settings.general.showStatusBar).onToggle([&] {
99112
settings.general.showStatusBar = showStatusBarSetting.checked();
100113
if(!showStatusBarSetting.checked()) {
@@ -227,6 +240,8 @@ Presentation::Presentation() {
227240
}
228241
});
229242

243+
setHidesCursor(settings.general.autoHideCursor);
244+
230245
iconLayout.setCollapsible();
231246

232247
iconSpacer.setCollapsible().setColor({0, 0, 0}).setDroppable().onDrop([&](auto filenames) {

Diff for: desktop-ui/presentation/presentation.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct Presentation : Window {
3939
Group preferRegionGroup{&preferNTSCU, &preferNTSCJ, &preferPAL};
4040
MenuSeparator groupSettingsSeparatpr{&settingsMenu};
4141
MenuCheckItem muteAudioSetting{&settingsMenu};
42+
MenuCheckItem autoHideCursorSetting{&settingsMenu};
4243
MenuCheckItem showStatusBarSetting{&settingsMenu};
4344
MenuSeparator audioSettingsSeparator{&settingsMenu};
4445
MenuItem videoSettingsAction{&settingsMenu};

Diff for: desktop-ui/settings/options.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
auto OptionSettings::construct() -> void {
22
setCollapsible();
33
setVisible(false);
4+
bool hideCursorImplemented = false;
5+
#if defined(PLATFORM_MACOS)
6+
hideCursorImplemented = true;
7+
#endif
48

59
commonSettingsLabel.setText("Emulator Options").setFont(Font().setBold());
610

@@ -37,5 +41,15 @@ auto OptionSettings::construct() -> void {
3741
});
3842
nintendo64ExpansionPakLayout.setAlignment(1).setPadding(12_sx, 0);
3943
nintendo64ExpansionPakHint.setText("Enable/Disable the 4MB Expansion Pak").setFont(Font().setSize(7.0)).setForegroundColor(SystemColor::Sublabel);
44+
45+
miscellaneousSettingsLabel.setVisible(hideCursorImplemented).setText("Miscellaneous").setFont(Font().setBold());
46+
47+
autoHideCursorOption.setText("Auto-Hide Cursor").setVisible(hideCursorImplemented).setChecked(settings.general.autoHideCursor).onToggle([&] {
48+
settings.general.autoHideCursor = autoHideCursorOption.checked();
49+
presentation.setHidesCursor(settings.general.autoHideCursor);
50+
presentation.autoHideCursorSetting.setChecked(settings.general.autoHideCursor);
51+
});
52+
autoHideCursorLayout.setAlignment(1).setPadding(12_sx, 0);
53+
autoHideCursorHint.setVisible(hideCursorImplemented).setText("Hide the mouse cursor when idle over the game window").setFont(Font().setSize(7.0)).setForegroundColor(SystemColor::Sublabel);
4054

4155
}

Diff for: desktop-ui/settings/settings.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ auto Settings::process(bool load) -> void {
100100
bind(boolean, "General/RunAhead", general.runAhead);
101101
bind(boolean, "General/AutoSaveMemory", general.autoSaveMemory);
102102
bind(boolean, "General/HomebrewMode", general.homebrewMode);
103+
bind(boolean, "General/AutoHideCursor", general.autoHideCursor);
103104

104105
bind(natural, "Rewind/Length", rewind.length);
105106
bind(natural, "Rewind/Frequency", rewind.frequency);

Diff for: desktop-ui/settings/settings.hpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct Settings : Markup::Node {
6666
bool runAhead = false;
6767
bool autoSaveMemory = true;
6868
bool homebrewMode = false;
69+
bool autoHideCursor = true;
6970
} general;
7071

7172
struct Rewind {
@@ -251,6 +252,10 @@ struct OptionSettings : VerticalLayout {
251252
HorizontalLayout nintendo64ExpansionPakLayout{this, Size{~0, 0}, 5};
252253
CheckLabel nintendo64ExpansionPakOption{&nintendo64ExpansionPakLayout, Size{0, 0}, 5};
253254
Label nintendo64ExpansionPakHint{&nintendo64ExpansionPakLayout, Size{0, 0}};
255+
Label miscellaneousSettingsLabel{this, Size{~0, 0}, 5};
256+
HorizontalLayout autoHideCursorLayout{this, Size{~0, 0}, 5};
257+
CheckLabel autoHideCursorOption{&autoHideCursorLayout, Size{0, 0}, 5};
258+
Label autoHideCursorHint{&autoHideCursorLayout, Size{0,0}};
254259
};
255260

256261
struct FirmwareSettings : VerticalLayout {
@@ -432,4 +437,4 @@ extern OptionSettings& optionSettings;
432437
extern FirmwareSettings& firmwareSettings;
433438
extern PathSettings& pathSettings;
434439
extern DriverSettings& driverSettings;
435-
extern DebugSettings& debugSettings;
440+
extern DebugSettings& debugSettings;

Diff for: hiro/cocoa/window.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
window = &windowReference;
77

88
NSUInteger style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
9+
hidesCursor = false;
10+
cursorIsInWindow = false;
911
if(window->state.resizable) style |= NSResizableWindowMask;
12+
hideCursorTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(hideCursor:) userInfo:nil repeats:YES];
1013

1114
if(self = [super initWithContentRect:NSMakeRect(0, 0, 640, 480) styleMask:style backing:NSBackingStoreBuffered defer:YES]) {
1215
[self setDelegate:self];
@@ -137,6 +140,13 @@
137140
return YES;
138141
}
139142

143+
-(void) hideCursor:(NSTimer*)timer {
144+
CFTimeInterval secondsSinceCursorMoved = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventMouseMoved);
145+
if(secondsSinceCursorMoved >= 2.0 && hidesCursor && cursorIsInWindow) {
146+
[NSCursor setHiddenUntilMouseMoves:YES];
147+
}
148+
}
149+
140150
-(NSMenu*) menuBar {
141151
return menuBar;
142152
}
@@ -205,6 +215,18 @@
205215
window->state.fullScreen = true;
206216
}
207217

218+
-(void)mouseEntered:(NSEvent *)theEvent {
219+
cursorIsInWindow = true;
220+
}
221+
222+
-(void)mouseExited:(NSEvent *)theEvent {
223+
cursorIsInWindow = false;
224+
}
225+
226+
-(void)setHidesCursor:(bool)hides {
227+
hidesCursor = hides;
228+
}
229+
208230
-(void)windowDidExitFullScreen:(NSNotification *)notification {
209231
window->state.fullScreen = false;
210232
}
@@ -368,6 +390,10 @@ auto pWindow::setResizable(bool resizable) -> void {
368390
[cocoaWindow setStyleMask:style];
369391
}
370392

393+
auto pWindow::setHidesCursor(bool hidesCursor) -> void {
394+
[cocoaWindow setHidesCursor:hidesCursor];
395+
}
396+
371397
auto pWindow::setTitle(const string& text) -> void {
372398
[cocoaWindow setTitle:[NSString stringWithUTF8String:text]];
373399
}
@@ -405,6 +431,18 @@ auto pWindow::sizeEvent() -> void {
405431
}
406432

407433
statusBarReposition();
434+
435+
NSView* theView = [cocoaWindow contentView];
436+
NSArray* trackingAreas = theView.trackingAreas;
437+
for (NSTrackingArea* oldArea in trackingAreas) {
438+
[theView removeTrackingArea:oldArea];
439+
}
440+
NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect: theView.bounds
441+
options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
442+
owner:cocoaWindow
443+
userInfo:nil];
444+
[theView addTrackingArea:area];
445+
408446

409447
if(!locked()) self().doSize();
410448
}

Diff for: hiro/cocoa/window.hpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@
33
@interface CocoaWindow : NSWindow <NSWindowDelegate> {
44
@public
55
hiro::mWindow* window;
6+
bool hidesCursor;
7+
bool cursorIsInWindow;
8+
NSTimer* hideCursorTimer;
69
NSMenu* menuBar;
710
NSMenu* rootMenu;
811
NSMenuItem* disableGatekeeper;
912
NSTextField* statusBar;
13+
NSTrackingArea* trackingArea;
1014
}
1115
-(id) initWith:(hiro::mWindow&)window;
1216
-(BOOL) canBecomeKeyWindow;
1317
-(BOOL) canBecomeMainWindow;
1418
-(void) windowDidBecomeMain:(NSNotification*)notification;
1519
-(void) windowDidMove:(NSNotification*)notification;
1620
-(void) windowDidResize:(NSNotification*)notification;
21+
-(void) mouseEntered:(NSEvent*)theEvent;
22+
-(void) mouseExited:(NSEvent*)theEvent;
23+
-(void) setHidesCursor:(bool)hidesCursor;
1724
-(BOOL) windowShouldClose:(id)sender;
1825
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
1926
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
@@ -23,6 +30,7 @@
2330
-(void) menuDisableGatekeeper;
2431
-(void) menuQuit;
2532
-(NSTextField*) statusBar;
33+
-(void) hideCursor:(NSTimer*)timer;
2634
@end
2735

2836
namespace hiro {
@@ -55,7 +63,8 @@ struct pWindow : pObject {
5563
auto setTitle(const string& text) -> void;
5664
auto setAssociatedFile(const string& filename) -> void;
5765
auto setVisible(bool visible) -> void;
58-
66+
auto setHidesCursor(bool hidesCursor) -> void;
67+
5968
auto moveEvent() -> void;
6069
auto sizeEvent() -> void;
6170
auto statusBarHeight() -> u32;

Diff for: hiro/core/shared.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ struct Window : sWindow {
934934
auto remove(sStatusBar statusBar) { return self().remove(statusBar), *this; }
935935
auto reset() { return self().reset(), *this; }
936936
auto resizable() const { return self().resizable(); }
937+
auto hidesCursor() const { return self().hidesCursor(); }
937938
auto setAlignment(Alignment alignment = Alignment::Center) { return self().setAlignment(alignment), *this; }
938939
auto setAlignment(sWindow relativeTo, Alignment alignment = Alignment::Center) { return self().setAlignment(relativeTo, alignment), *this; }
939940
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
@@ -953,6 +954,7 @@ struct Window : sWindow {
953954
auto setPosition(Position position) { return self().setPosition(position), *this; }
954955
auto setPosition(sWindow relativeTo, Position position) { return self().setPosition(relativeTo, position), *this; }
955956
auto setResizable(bool resizable = true) { return self().setResizable(resizable), *this; }
957+
auto setHidesCursor(bool hidesCursor = true) { return self().setHidesCursor(hidesCursor), *this; }
956958
auto setSize(Size size) { return self().setSize(size), *this; }
957959
auto setTitle(const string& title = "") { return self().setTitle(title), *this; }
958960
auto setAssociatedFile(const string& filename = "") { return self().setAssociatedFile(filename), *this; }

Diff for: hiro/core/window.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ auto mWindow::resizable() const -> bool {
187187
return state.resizable;
188188
}
189189

190+
auto mWindow::hidesCursor() const -> bool {
191+
return state.hidesCursor;
192+
}
193+
190194
auto mWindow::setAlignment(Alignment alignment) -> type& {
191195
auto workspace = Monitor::workspace();
192196
auto geometry = frameGeometry();
@@ -349,6 +353,12 @@ auto mWindow::setResizable(bool resizable) -> type& {
349353
return *this;
350354
}
351355

356+
auto mWindow::setHidesCursor(bool hidesCursor) -> type& {
357+
state.hidesCursor = hidesCursor;
358+
signal(setHidesCursor, hidesCursor);
359+
return *this;
360+
}
361+
352362
auto mWindow::setSize(Size size) -> type& {
353363
return setGeometry({
354364
state.geometry.x(), state.geometry.y(),

Diff for: hiro/core/window.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct mWindow : mObject {
3939
auto remove(sStatusBar statusBar) -> type&;
4040
auto reset() -> type& override;
4141
auto resizable() const -> bool;
42+
auto hidesCursor() const -> bool;
4243
auto setAlignment(Alignment = Alignment::Center) -> type&;
4344
auto setAlignment(sWindow relativeTo, Alignment = Alignment::Center) -> type&;
4445
auto setBackgroundColor(Color color = {}) -> type&;
@@ -58,6 +59,7 @@ struct mWindow : mObject {
5859
auto setPosition(Position) -> type&;
5960
auto setPosition(sWindow relativeTo, Position) -> type&;
6061
auto setResizable(bool resizable = true) -> type&;
62+
auto setHidesCursor(bool hidesCursor = true) -> type&;
6163
auto setSize(Size size) -> type&;
6264
auto setTitle(const string& title = "") -> type&;
6365
auto setAssociatedFile(const string& filename = "") -> type&;
@@ -89,6 +91,7 @@ struct mWindow : mObject {
8991
sSizable sizable;
9092
sStatusBar statusBar;
9193
string title;
94+
bool hidesCursor;
9295
} state;
9396

9497
auto destruct() -> void override;

0 commit comments

Comments
 (0)