Skip to content

Commit

Permalink
hiro: add cursor auto-hide
Browse files Browse the repository at this point in the history
  • Loading branch information
jcm committed Dec 6, 2023
1 parent e176d8b commit 7a816b9
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 2 deletions.
15 changes: 15 additions & 0 deletions desktop-ui/presentation/presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Presentation::Presentation() {

settingsMenu.setText("Settings");
videoSizeMenu.setText("Size").setIcon(Icon::Emblem::Image);

bool hideCursorImplemented = false;
#if defined(PLATFORM_MACOS)
hideCursorImplemented = true;
#endif

//generate size menu
u32 multipliers = 5;
Expand Down Expand Up @@ -95,6 +100,14 @@ Presentation::Presentation() {
muteAudioSetting.setText("Mute Audio").setChecked(settings.audio.mute).onToggle([&] {
settings.audio.mute = muteAudioSetting.checked();
});
autoHideCursorSetting.setText("Auto-Hide Cursor").setChecked(settings.general.autoHideCursor).onToggle([&] {
settings.general.autoHideCursor = autoHideCursorSetting.checked();
settingsWindow.optionSettings.autoHideCursorOption.setChecked(settings.general.autoHideCursor);
presentation.setHidesCursor(settings.general.autoHideCursor);
});
if(!hideCursorImplemented) {
autoHideCursorSetting.setVisible(false);
}
showStatusBarSetting.setText("Show Status Bar").setChecked(settings.general.showStatusBar).onToggle([&] {
settings.general.showStatusBar = showStatusBarSetting.checked();
if(!showStatusBarSetting.checked()) {
Expand Down Expand Up @@ -227,6 +240,8 @@ Presentation::Presentation() {
}
});

setHidesCursor(settings.general.autoHideCursor);

iconLayout.setCollapsible();

iconSpacer.setCollapsible().setColor({0, 0, 0}).setDroppable().onDrop([&](auto filenames) {
Expand Down
1 change: 1 addition & 0 deletions desktop-ui/presentation/presentation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct Presentation : Window {
Group preferRegionGroup{&preferNTSCU, &preferNTSCJ, &preferPAL};
MenuSeparator groupSettingsSeparatpr{&settingsMenu};
MenuCheckItem muteAudioSetting{&settingsMenu};
MenuCheckItem autoHideCursorSetting{&settingsMenu};
MenuCheckItem showStatusBarSetting{&settingsMenu};
MenuSeparator audioSettingsSeparator{&settingsMenu};
MenuItem videoSettingsAction{&settingsMenu};
Expand Down
14 changes: 14 additions & 0 deletions desktop-ui/settings/options.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
auto OptionSettings::construct() -> void {
setCollapsible();
setVisible(false);
bool hideCursorImplemented = false;
#if defined(PLATFORM_MACOS)
hideCursorImplemented = true;
#endif

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

Expand Down Expand Up @@ -37,5 +41,15 @@ auto OptionSettings::construct() -> void {
});
nintendo64ExpansionPakLayout.setAlignment(1).setPadding(12_sx, 0);
nintendo64ExpansionPakHint.setText("Enable/Disable the 4MB Expansion Pak").setFont(Font().setSize(7.0)).setForegroundColor(SystemColor::Sublabel);

miscellaneousSettingsLabel.setVisible(hideCursorImplemented).setText("Miscellaneous").setFont(Font().setBold());

autoHideCursorOption.setText("Auto-Hide Cursor").setVisible(hideCursorImplemented).setChecked(settings.general.autoHideCursor).onToggle([&] {
settings.general.autoHideCursor = autoHideCursorOption.checked();
presentation.setHidesCursor(settings.general.autoHideCursor);
presentation.autoHideCursorSetting.setChecked(settings.general.autoHideCursor);
});
autoHideCursorLayout.setAlignment(1).setPadding(12_sx, 0);
autoHideCursorHint.setVisible(hideCursorImplemented).setText("Hide the mouse cursor when idle over the game window").setFont(Font().setSize(7.0)).setForegroundColor(SystemColor::Sublabel);

}
1 change: 1 addition & 0 deletions desktop-ui/settings/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ auto Settings::process(bool load) -> void {
bind(boolean, "General/RunAhead", general.runAhead);
bind(boolean, "General/AutoSaveMemory", general.autoSaveMemory);
bind(boolean, "General/HomebrewMode", general.homebrewMode);
bind(boolean, "General/AutoHideCursor", general.autoHideCursor);

bind(natural, "Rewind/Length", rewind.length);
bind(natural, "Rewind/Frequency", rewind.frequency);
Expand Down
7 changes: 6 additions & 1 deletion desktop-ui/settings/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct Settings : Markup::Node {
bool runAhead = false;
bool autoSaveMemory = true;
bool homebrewMode = false;
bool autoHideCursor = true;
} general;

struct Rewind {
Expand Down Expand Up @@ -251,6 +252,10 @@ struct OptionSettings : VerticalLayout {
HorizontalLayout nintendo64ExpansionPakLayout{this, Size{~0, 0}, 5};
CheckLabel nintendo64ExpansionPakOption{&nintendo64ExpansionPakLayout, Size{0, 0}, 5};
Label nintendo64ExpansionPakHint{&nintendo64ExpansionPakLayout, Size{0, 0}};
Label miscellaneousSettingsLabel{this, Size{~0, 0}, 5};
HorizontalLayout autoHideCursorLayout{this, Size{~0, 0}, 5};
CheckLabel autoHideCursorOption{&autoHideCursorLayout, Size{0, 0}, 5};
Label autoHideCursorHint{&autoHideCursorLayout, Size{0,0}};
};

struct FirmwareSettings : VerticalLayout {
Expand Down Expand Up @@ -432,4 +437,4 @@ extern OptionSettings& optionSettings;
extern FirmwareSettings& firmwareSettings;
extern PathSettings& pathSettings;
extern DriverSettings& driverSettings;
extern DebugSettings& debugSettings;
extern DebugSettings& debugSettings;
38 changes: 38 additions & 0 deletions hiro/cocoa/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
window = &windowReference;

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

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

-(void) hideCursor:(NSTimer*)timer {
CFTimeInterval secondsSinceCursorMoved = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateCombinedSessionState, kCGEventMouseMoved);
if(secondsSinceCursorMoved >= 2.0 && hidesCursor && cursorIsInWindow) {
[NSCursor setHiddenUntilMouseMoves:YES];
}
}

-(NSMenu*) menuBar {
return menuBar;
}
Expand Down Expand Up @@ -205,6 +215,18 @@
window->state.fullScreen = true;
}

-(void)mouseEntered:(NSEvent *)theEvent {
cursorIsInWindow = true;
}

-(void)mouseExited:(NSEvent *)theEvent {
cursorIsInWindow = false;
}

-(void)setHidesCursor:(bool)hides {
hidesCursor = hides;
}

-(void)windowDidExitFullScreen:(NSNotification *)notification {
window->state.fullScreen = false;
}
Expand Down Expand Up @@ -368,6 +390,10 @@ auto pWindow::setResizable(bool resizable) -> void {
[cocoaWindow setStyleMask:style];
}

auto pWindow::setHidesCursor(bool hidesCursor) -> void {
[cocoaWindow setHidesCursor:hidesCursor];
}

auto pWindow::setTitle(const string& text) -> void {
[cocoaWindow setTitle:[NSString stringWithUTF8String:text]];
}
Expand Down Expand Up @@ -405,6 +431,18 @@ auto pWindow::sizeEvent() -> void {
}

statusBarReposition();

NSView* theView = [cocoaWindow contentView];
NSArray* trackingAreas = theView.trackingAreas;
for (NSTrackingArea* oldArea in trackingAreas) {
[theView removeTrackingArea:oldArea];
}
NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect: theView.bounds
options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
owner:cocoaWindow
userInfo:nil];
[theView addTrackingArea:area];


if(!locked()) self().doSize();
}
Expand Down
11 changes: 10 additions & 1 deletion hiro/cocoa/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@
@interface CocoaWindow : NSWindow <NSWindowDelegate> {
@public
hiro::mWindow* window;
bool hidesCursor;
bool cursorIsInWindow;
NSTimer* hideCursorTimer;
NSMenu* menuBar;
NSMenu* rootMenu;
NSMenuItem* disableGatekeeper;
NSTextField* statusBar;
NSTrackingArea* trackingArea;
}
-(id) initWith:(hiro::mWindow&)window;
-(BOOL) canBecomeKeyWindow;
-(BOOL) canBecomeMainWindow;
-(void) windowDidBecomeMain:(NSNotification*)notification;
-(void) windowDidMove:(NSNotification*)notification;
-(void) windowDidResize:(NSNotification*)notification;
-(void) mouseEntered:(NSEvent*)theEvent;
-(void) mouseExited:(NSEvent*)theEvent;
-(void) setHidesCursor:(bool)hidesCursor;
-(BOOL) windowShouldClose:(id)sender;
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
Expand All @@ -23,6 +30,7 @@
-(void) menuDisableGatekeeper;
-(void) menuQuit;
-(NSTextField*) statusBar;
-(void) hideCursor:(NSTimer*)timer;
@end

namespace hiro {
Expand Down Expand Up @@ -55,7 +63,8 @@ struct pWindow : pObject {
auto setTitle(const string& text) -> void;
auto setAssociatedFile(const string& filename) -> void;
auto setVisible(bool visible) -> void;

auto setHidesCursor(bool hidesCursor) -> void;

auto moveEvent() -> void;
auto sizeEvent() -> void;
auto statusBarHeight() -> u32;
Expand Down
2 changes: 2 additions & 0 deletions hiro/core/shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@ struct Window : sWindow {
auto remove(sStatusBar statusBar) { return self().remove(statusBar), *this; }
auto reset() { return self().reset(), *this; }
auto resizable() const { return self().resizable(); }
auto hidesCursor() const { return self().hidesCursor(); }
auto setAlignment(Alignment alignment = Alignment::Center) { return self().setAlignment(alignment), *this; }
auto setAlignment(sWindow relativeTo, Alignment alignment = Alignment::Center) { return self().setAlignment(relativeTo, alignment), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
Expand All @@ -953,6 +954,7 @@ struct Window : sWindow {
auto setPosition(Position position) { return self().setPosition(position), *this; }
auto setPosition(sWindow relativeTo, Position position) { return self().setPosition(relativeTo, position), *this; }
auto setResizable(bool resizable = true) { return self().setResizable(resizable), *this; }
auto setHidesCursor(bool hidesCursor = true) { return self().setHidesCursor(hidesCursor), *this; }
auto setSize(Size size) { return self().setSize(size), *this; }
auto setTitle(const string& title = "") { return self().setTitle(title), *this; }
auto setAssociatedFile(const string& filename = "") { return self().setAssociatedFile(filename), *this; }
Expand Down
10 changes: 10 additions & 0 deletions hiro/core/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ auto mWindow::resizable() const -> bool {
return state.resizable;
}

auto mWindow::hidesCursor() const -> bool {
return state.hidesCursor;
}

auto mWindow::setAlignment(Alignment alignment) -> type& {
auto workspace = Monitor::workspace();
auto geometry = frameGeometry();
Expand Down Expand Up @@ -349,6 +353,12 @@ auto mWindow::setResizable(bool resizable) -> type& {
return *this;
}

auto mWindow::setHidesCursor(bool hidesCursor) -> type& {
state.hidesCursor = hidesCursor;
signal(setHidesCursor, hidesCursor);
return *this;
}

auto mWindow::setSize(Size size) -> type& {
return setGeometry({
state.geometry.x(), state.geometry.y(),
Expand Down
3 changes: 3 additions & 0 deletions hiro/core/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct mWindow : mObject {
auto remove(sStatusBar statusBar) -> type&;
auto reset() -> type& override;
auto resizable() const -> bool;
auto hidesCursor() const -> bool;
auto setAlignment(Alignment = Alignment::Center) -> type&;
auto setAlignment(sWindow relativeTo, Alignment = Alignment::Center) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
Expand All @@ -58,6 +59,7 @@ struct mWindow : mObject {
auto setPosition(Position) -> type&;
auto setPosition(sWindow relativeTo, Position) -> type&;
auto setResizable(bool resizable = true) -> type&;
auto setHidesCursor(bool hidesCursor = true) -> type&;
auto setSize(Size size) -> type&;
auto setTitle(const string& title = "") -> type&;
auto setAssociatedFile(const string& filename = "") -> type&;
Expand Down Expand Up @@ -89,6 +91,7 @@ struct mWindow : mObject {
sSizable sizable;
sStatusBar statusBar;
string title;
bool hidesCursor;
} state;

auto destruct() -> void override;
Expand Down

0 comments on commit 7a816b9

Please sign in to comment.