mirror of https://github.com/bsnes-emu/bsnes.git
v108.11
* added (primary-monitor only) fullscreen support for macOS * improved settings windows a bit * correct Program::focused() move from Video::exclusive()->fullScreen()
This commit is contained in:
parent
ab25877af4
commit
95831d3675
|
@ -29,7 +29,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "bsnes";
|
static const string Name = "bsnes";
|
||||||
static const string Version = "108.10";
|
static const string Version = "108.11";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://byuu.org";
|
static const string Website = "https://byuu.org";
|
||||||
|
|
|
@ -18,8 +18,8 @@ auto Configuration::process(Markup::Node document, bool load) -> void {
|
||||||
|
|
||||||
bind(natural, "Hacks/CPU/Overclock", hacks.cpu.overclock);
|
bind(natural, "Hacks/CPU/Overclock", hacks.cpu.overclock);
|
||||||
bind(boolean, "Hacks/PPU/Fast", hacks.ppu.fast);
|
bind(boolean, "Hacks/PPU/Fast", hacks.ppu.fast);
|
||||||
bind(boolean, "Hacks/PPU/NoSpriteLimit", hacks.ppu.noSpriteLimit);
|
|
||||||
bind(boolean, "Hacks/PPU/Deinterlace", hacks.ppu.deinterlace);
|
bind(boolean, "Hacks/PPU/Deinterlace", hacks.ppu.deinterlace);
|
||||||
|
bind(boolean, "Hacks/PPU/NoSpriteLimit", hacks.ppu.noSpriteLimit);
|
||||||
bind(natural, "Hacks/PPU/Mode7/Scale", hacks.ppu.mode7.scale);
|
bind(natural, "Hacks/PPU/Mode7/Scale", hacks.ppu.mode7.scale);
|
||||||
bind(boolean, "Hacks/PPU/Mode7/Perspective", hacks.ppu.mode7.perspective);
|
bind(boolean, "Hacks/PPU/Mode7/Perspective", hacks.ppu.mode7.perspective);
|
||||||
bind(boolean, "Hacks/PPU/Mode7/Supersample", hacks.ppu.mode7.supersample);
|
bind(boolean, "Hacks/PPU/Mode7/Supersample", hacks.ppu.mode7.supersample);
|
||||||
|
|
|
@ -30,8 +30,8 @@ struct Configuration {
|
||||||
} cpu;
|
} cpu;
|
||||||
struct PPU {
|
struct PPU {
|
||||||
bool fast = true;
|
bool fast = true;
|
||||||
bool noSpriteLimit = true;
|
|
||||||
bool deinterlace = true;
|
bool deinterlace = true;
|
||||||
|
bool noSpriteLimit = false;
|
||||||
struct Mode7 {
|
struct Mode7 {
|
||||||
uint scale = 1;
|
uint scale = 1;
|
||||||
bool perspective = true;
|
bool perspective = true;
|
||||||
|
|
|
@ -3,8 +3,8 @@ auto Program::load() -> void {
|
||||||
|
|
||||||
emulator->configure("Hacks/CPU/Overclock", settings.emulator.hack.cpu.overclock);
|
emulator->configure("Hacks/CPU/Overclock", settings.emulator.hack.cpu.overclock);
|
||||||
emulator->configure("Hacks/PPU/Fast", settings.emulator.hack.ppu.fast);
|
emulator->configure("Hacks/PPU/Fast", settings.emulator.hack.ppu.fast);
|
||||||
emulator->configure("Hacks/PPU/NoSpriteLimit", settings.emulator.hack.ppu.noSpriteLimit);
|
|
||||||
emulator->configure("Hacks/PPU/Deinterlace", settings.emulator.hack.ppu.deinterlace);
|
emulator->configure("Hacks/PPU/Deinterlace", settings.emulator.hack.ppu.deinterlace);
|
||||||
|
emulator->configure("Hacks/PPU/NoSpriteLimit", settings.emulator.hack.ppu.noSpriteLimit);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Scale", settings.emulator.hack.ppu.mode7.scale);
|
emulator->configure("Hacks/PPU/Mode7/Scale", settings.emulator.hack.ppu.mode7.scale);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective);
|
emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective);
|
||||||
emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample);
|
emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample);
|
||||||
|
|
|
@ -74,8 +74,8 @@ auto Program::inactive() -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Program::focused() -> bool {
|
auto Program::focused() -> bool {
|
||||||
//exclusive mode creates its own top-level window: presentation window will not have focus
|
//full-screen mode creates its own top-level window: presentation window will not have focus
|
||||||
if(video.exclusive() || presentation.focused()) {
|
if(video.fullScreen() || presentation.focused()) {
|
||||||
mute &= ~Mute::Unfocused;
|
mute &= ~Mute::Unfocused;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,13 +8,13 @@ auto DriverSettings::create() -> void {
|
||||||
videoDriverUpdate.setText(videoDriverOption.selected().text() != video.driver() ? "Change" : "Reload");
|
videoDriverUpdate.setText(videoDriverOption.selected().text() != video.driver() ? "Change" : "Reload");
|
||||||
});
|
});
|
||||||
videoDriverUpdate.setText("Change").onActivate([&] { videoDriverChange(); });
|
videoDriverUpdate.setText("Change").onActivate([&] { videoDriverChange(); });
|
||||||
videoMonitorLabel.setText("Fullscreen Monitor:").setToolTip(
|
videoMonitorLabel.setText("Fullscreen monitor:").setToolTip(
|
||||||
"Sets which monitor video is sent to in fullscreen mode."
|
"Sets which monitor video is sent to in fullscreen mode."
|
||||||
);
|
);
|
||||||
videoMonitorOption.onChange([&] { videoMonitorChange(); });
|
videoMonitorOption.onChange([&] { videoMonitorChange(); });
|
||||||
videoFormatLabel.setText("Format:");
|
videoFormatLabel.setText("Format:");
|
||||||
videoFormatOption.onChange([&] { videoFormatChange(); });
|
videoFormatOption.onChange([&] { videoFormatChange(); });
|
||||||
videoExclusiveToggle.setText("Exclusive").setToolTip(
|
videoExclusiveToggle.setText("Exclusive mode").setToolTip(
|
||||||
"Causes fullscreen mode to take over all monitors.\n"
|
"Causes fullscreen mode to take over all monitors.\n"
|
||||||
"This allows adaptive sync to work better and reduces input latency.\n"
|
"This allows adaptive sync to work better and reduces input latency.\n"
|
||||||
"However, multi-monitor users should turn this option off.\n"
|
"However, multi-monitor users should turn this option off.\n"
|
||||||
|
@ -47,13 +47,12 @@ auto DriverSettings::create() -> void {
|
||||||
videoSpacer.setColor({192, 192, 192});
|
videoSpacer.setColor({192, 192, 192});
|
||||||
|
|
||||||
audioLabel.setText("Audio").setFont(Font().setBold());
|
audioLabel.setText("Audio").setFont(Font().setBold());
|
||||||
audioLayout.setSize({2, 2});
|
|
||||||
audioDriverLabel.setText("Driver:");
|
audioDriverLabel.setText("Driver:");
|
||||||
audioDriverOption.onChange([&] {
|
audioDriverOption.onChange([&] {
|
||||||
audioDriverUpdate.setText(audioDriverOption.selected().text() != audio.driver() ? "Change" : "Reload");
|
audioDriverUpdate.setText(audioDriverOption.selected().text() != audio.driver() ? "Change" : "Reload");
|
||||||
});
|
});
|
||||||
audioDriverUpdate.setText("Change").onActivate([&] { audioDriverChange(); });
|
audioDriverUpdate.setText("Change").onActivate([&] { audioDriverChange(); });
|
||||||
audioDeviceLabel.setText("Device:");
|
audioDeviceLabel.setText("Output device:");
|
||||||
audioDeviceOption.onChange([&] { audioDeviceChange(); });
|
audioDeviceOption.onChange([&] { audioDeviceChange(); });
|
||||||
audioFrequencyLabel.setText("Frequency:");
|
audioFrequencyLabel.setText("Frequency:");
|
||||||
audioFrequencyOption.onChange([&] { audioFrequencyChange(); });
|
audioFrequencyOption.onChange([&] { audioFrequencyChange(); });
|
||||||
|
@ -92,7 +91,6 @@ auto DriverSettings::create() -> void {
|
||||||
audioSpacer.setColor({192, 192, 192});
|
audioSpacer.setColor({192, 192, 192});
|
||||||
|
|
||||||
inputLabel.setText("Input").setFont(Font().setBold());
|
inputLabel.setText("Input").setFont(Font().setBold());
|
||||||
inputLayout.setSize({2, 1});
|
|
||||||
inputDriverLabel.setText("Driver:");
|
inputDriverLabel.setText("Driver:");
|
||||||
inputDriverOption.onChange([&] {
|
inputDriverOption.onChange([&] {
|
||||||
inputDriverUpdate.setText(inputDriverOption.selected().text() != input.driver() ? "Change" : "Reload");
|
inputDriverUpdate.setText(inputDriverOption.selected().text() != input.driver() ? "Change" : "Reload");
|
||||||
|
@ -167,7 +165,7 @@ auto DriverSettings::videoFormatChanged() -> void {
|
||||||
item.setText(format);
|
item.setText(format);
|
||||||
if(format == video.format()) item.setSelected();
|
if(format == video.format()) item.setSelected();
|
||||||
}
|
}
|
||||||
//videoFormatOption.setEnabled(video.hasFormat());
|
videoFormatOption.setEnabled(videoFormatOption.itemCount() > 1);
|
||||||
setGeometry(geometry());
|
setGeometry(geometry());
|
||||||
videoFormatChange();
|
videoFormatChange();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,13 @@ auto EmulatorSettings::create() -> void {
|
||||||
mode7Layout.setEnabled(true);
|
mode7Layout.setEnabled(true);
|
||||||
}
|
}
|
||||||
}).doToggle();
|
}).doToggle();
|
||||||
noSpriteLimit.setText("No sprite limit").setChecked(settings.emulator.hack.ppu.noSpriteLimit).onToggle([&] {
|
|
||||||
settings.emulator.hack.ppu.noSpriteLimit = noSpriteLimit.checked();
|
|
||||||
});
|
|
||||||
deinterlace.setText("Deinterlace").setChecked(settings.emulator.hack.ppu.deinterlace).onToggle([&] {
|
deinterlace.setText("Deinterlace").setChecked(settings.emulator.hack.ppu.deinterlace).onToggle([&] {
|
||||||
settings.emulator.hack.ppu.deinterlace = deinterlace.checked();
|
settings.emulator.hack.ppu.deinterlace = deinterlace.checked();
|
||||||
emulator->configure("Hacks/PPU/Deinterlace", settings.emulator.hack.ppu.deinterlace);
|
emulator->configure("Hacks/PPU/Deinterlace", settings.emulator.hack.ppu.deinterlace);
|
||||||
});
|
});
|
||||||
|
noSpriteLimit.setText("No sprite limit").setChecked(settings.emulator.hack.ppu.noSpriteLimit).onToggle([&] {
|
||||||
|
settings.emulator.hack.ppu.noSpriteLimit = noSpriteLimit.checked();
|
||||||
|
});
|
||||||
mode7Label.setText("HD Mode 7 (fast PPU only)").setFont(Font().setBold());
|
mode7Label.setText("HD Mode 7 (fast PPU only)").setFont(Font().setBold());
|
||||||
mode7ScaleLabel.setText("Scale:");
|
mode7ScaleLabel.setText("Scale:");
|
||||||
mode7Scale.append(ComboButtonItem().setText( "240p").setProperty("multiplier", 1));
|
mode7Scale.append(ComboButtonItem().setText( "240p").setProperty("multiplier", 1));
|
||||||
|
|
|
@ -114,8 +114,8 @@ auto Settings::process(bool load) -> void {
|
||||||
bind(boolean, "Emulator/AutoLoadStateOnLoad", emulator.autoLoadStateOnLoad);
|
bind(boolean, "Emulator/AutoLoadStateOnLoad", emulator.autoLoadStateOnLoad);
|
||||||
bind(natural, "Emulator/Hack/CPU/Overclock", emulator.hack.cpu.overclock);
|
bind(natural, "Emulator/Hack/CPU/Overclock", emulator.hack.cpu.overclock);
|
||||||
bind(boolean, "Emulator/Hack/PPU/Fast", emulator.hack.ppu.fast);
|
bind(boolean, "Emulator/Hack/PPU/Fast", emulator.hack.ppu.fast);
|
||||||
bind(boolean, "Emulator/Hack/PPU/NoSpriteLimit", emulator.hack.ppu.noSpriteLimit);
|
|
||||||
bind(boolean, "Emulator/Hack/PPU/Deinterlace", emulator.hack.ppu.deinterlace);
|
bind(boolean, "Emulator/Hack/PPU/Deinterlace", emulator.hack.ppu.deinterlace);
|
||||||
|
bind(boolean, "Emulator/Hack/PPU/NoSpriteLimit", emulator.hack.ppu.noSpriteLimit);
|
||||||
bind(natural, "Emulator/Hack/PPU/Mode7/Scale", emulator.hack.ppu.mode7.scale);
|
bind(natural, "Emulator/Hack/PPU/Mode7/Scale", emulator.hack.ppu.mode7.scale);
|
||||||
bind(boolean, "Emulator/Hack/PPU/Mode7/Perspective", emulator.hack.ppu.mode7.perspective);
|
bind(boolean, "Emulator/Hack/PPU/Mode7/Perspective", emulator.hack.ppu.mode7.perspective);
|
||||||
bind(boolean, "Emulator/Hack/PPU/Mode7/Supersample", emulator.hack.ppu.mode7.supersample);
|
bind(boolean, "Emulator/Hack/PPU/Mode7/Supersample", emulator.hack.ppu.mode7.supersample);
|
||||||
|
|
|
@ -100,8 +100,8 @@ struct Settings : Markup::Node {
|
||||||
} cpu;
|
} cpu;
|
||||||
struct PPU {
|
struct PPU {
|
||||||
bool fast = true;
|
bool fast = true;
|
||||||
bool noSpriteLimit = true;
|
|
||||||
bool deinterlace = true;
|
bool deinterlace = true;
|
||||||
|
bool noSpriteLimit = false;
|
||||||
struct Mode7 {
|
struct Mode7 {
|
||||||
uint scale = 1;
|
uint scale = 1;
|
||||||
bool perspective = true;
|
bool perspective = true;
|
||||||
|
@ -334,8 +334,8 @@ public:
|
||||||
Label ppuLabel{this, Size{~0, 0}, 2};
|
Label ppuLabel{this, Size{~0, 0}, 2};
|
||||||
HorizontalLayout ppuLayout{this, Size{~0, 0}};
|
HorizontalLayout ppuLayout{this, Size{~0, 0}};
|
||||||
CheckLabel fastPPU{&ppuLayout, Size{0, 0}};
|
CheckLabel fastPPU{&ppuLayout, Size{0, 0}};
|
||||||
CheckLabel noSpriteLimit{&ppuLayout, Size{0, 0}};
|
|
||||||
CheckLabel deinterlace{&ppuLayout, Size{0, 0}};
|
CheckLabel deinterlace{&ppuLayout, Size{0, 0}};
|
||||||
|
CheckLabel noSpriteLimit{&ppuLayout, Size{0, 0}};
|
||||||
Label mode7Label{this, Size{~0, 0}, 2};
|
Label mode7Label{this, Size{~0, 0}, 2};
|
||||||
HorizontalLayout mode7Layout{this, Size{~0, 0}};
|
HorizontalLayout mode7Layout{this, Size{~0, 0}};
|
||||||
Label mode7ScaleLabel{&mode7Layout, Size{0, 0}};
|
Label mode7ScaleLabel{&mode7Layout, Size{0, 0}};
|
||||||
|
@ -392,14 +392,14 @@ public:
|
||||||
CheckLabel videoFlushToggle{&videoToggleLayout, Size{0, 0}};
|
CheckLabel videoFlushToggle{&videoToggleLayout, Size{0, 0}};
|
||||||
Canvas videoSpacer{this, Size{~0, 1}};
|
Canvas videoSpacer{this, Size{~0, 1}};
|
||||||
Label audioLabel{this, Size{~0, 0}, 2};
|
Label audioLabel{this, Size{~0, 0}, 2};
|
||||||
TableLayout audioLayout{this, Size{~0, 0}};
|
VerticalLayout audioLayout{this, Size{~0, 0}};
|
||||||
Label audioDriverLabel{&audioLayout, Size{0, 0}};
|
|
||||||
HorizontalLayout audioDriverLayout{&audioLayout, Size{~0, 0}};
|
HorizontalLayout audioDriverLayout{&audioLayout, Size{~0, 0}};
|
||||||
|
Label audioDriverLabel{&audioDriverLayout, Size{0, 0}};
|
||||||
ComboButton audioDriverOption{&audioDriverLayout, Size{0, 0}};
|
ComboButton audioDriverOption{&audioDriverLayout, Size{0, 0}};
|
||||||
Button audioDriverUpdate{&audioDriverLayout, Size{0, 0}};
|
Button audioDriverUpdate{&audioDriverLayout, Size{0, 0}};
|
||||||
Label audioDriverActive{&audioDriverLayout, Size{0, 0}};
|
Label audioDriverActive{&audioDriverLayout, Size{0, 0}};
|
||||||
Label audioDeviceLabel{&audioLayout, Size{0, 0}};
|
|
||||||
HorizontalLayout audioPropertyLayout{&audioLayout, Size{~0, 0}};
|
HorizontalLayout audioPropertyLayout{&audioLayout, Size{~0, 0}};
|
||||||
|
Label audioDeviceLabel{&audioPropertyLayout, Size{0, 0}};
|
||||||
ComboButton audioDeviceOption{&audioPropertyLayout, Size{0, 0}};
|
ComboButton audioDeviceOption{&audioPropertyLayout, Size{0, 0}};
|
||||||
Label audioFrequencyLabel{&audioPropertyLayout, Size{0, 0}};
|
Label audioFrequencyLabel{&audioPropertyLayout, Size{0, 0}};
|
||||||
ComboButton audioFrequencyOption{&audioPropertyLayout, Size{0, 0}};
|
ComboButton audioFrequencyOption{&audioPropertyLayout, Size{0, 0}};
|
||||||
|
@ -411,9 +411,9 @@ public:
|
||||||
CheckLabel audioDynamicToggle{&audioToggleLayout, Size{0, 0}};
|
CheckLabel audioDynamicToggle{&audioToggleLayout, Size{0, 0}};
|
||||||
Canvas audioSpacer{this, Size{~0, 1}};
|
Canvas audioSpacer{this, Size{~0, 1}};
|
||||||
Label inputLabel{this, Size{~0, 0}, 2};
|
Label inputLabel{this, Size{~0, 0}, 2};
|
||||||
TableLayout inputLayout{this, Size{~0, 0}};
|
VerticalLayout inputLayout{this, Size{~0, 0}};
|
||||||
Label inputDriverLabel{&inputLayout, Size{0, 0}};
|
|
||||||
HorizontalLayout inputDriverLayout{&inputLayout, Size{~0, 0}};
|
HorizontalLayout inputDriverLayout{&inputLayout, Size{~0, 0}};
|
||||||
|
Label inputDriverLabel{&inputDriverLayout, Size{0, 0}};
|
||||||
ComboButton inputDriverOption{&inputDriverLayout, Size{0, 0}};
|
ComboButton inputDriverOption{&inputDriverLayout, Size{0, 0}};
|
||||||
Button inputDriverUpdate{&inputDriverLayout, Size{0, 0}};
|
Button inputDriverUpdate{&inputDriverLayout, Size{0, 0}};
|
||||||
Label inputDriverActive{&inputDriverLayout, Size{0, 0}};
|
Label inputDriverActive{&inputDriverLayout, Size{0, 0}};
|
||||||
|
|
|
@ -9,6 +9,16 @@ struct VideoCGL;
|
||||||
}
|
}
|
||||||
-(id) initWith:(VideoCGL*)video pixelFormat:(NSOpenGLPixelFormat*)pixelFormat;
|
-(id) initWith:(VideoCGL*)video pixelFormat:(NSOpenGLPixelFormat*)pixelFormat;
|
||||||
-(void) reshape;
|
-(void) reshape;
|
||||||
|
-(BOOL) acceptsFirstResponder;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface RubyWindowCGL : NSWindow <NSWindowDelegate> {
|
||||||
|
@public
|
||||||
|
VideoCGL* video;
|
||||||
|
}
|
||||||
|
-(id) initWith:(VideoCGL*)video;
|
||||||
|
-(BOOL) canBecomeKeyWindow;
|
||||||
|
-(BOOL) canBecomeMainWindow;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
struct VideoCGL : VideoDriver, OpenGL {
|
struct VideoCGL : VideoDriver, OpenGL {
|
||||||
|
@ -23,11 +33,16 @@ struct VideoCGL : VideoDriver, OpenGL {
|
||||||
auto driver() -> string override { return "OpenGL 3.2"; }
|
auto driver() -> string override { return "OpenGL 3.2"; }
|
||||||
auto ready() -> bool override { return _ready; }
|
auto ready() -> bool override { return _ready; }
|
||||||
|
|
||||||
|
auto hasFullScreen() -> bool override { return true; }
|
||||||
auto hasContext() -> bool override { return true; }
|
auto hasContext() -> bool override { return true; }
|
||||||
auto hasBlocking() -> bool override { return true; }
|
auto hasBlocking() -> bool override { return true; }
|
||||||
auto hasFlush() -> bool override { return true; }
|
auto hasFlush() -> bool override { return true; }
|
||||||
auto hasShader() -> bool override { return true; }
|
auto hasShader() -> bool override { return true; }
|
||||||
|
|
||||||
|
auto setFullScreen(bool fullScreen) -> bool override {
|
||||||
|
return initialize();
|
||||||
|
}
|
||||||
|
|
||||||
auto setContext(uintptr context) -> bool override {
|
auto setContext(uintptr context) -> bool override {
|
||||||
return initialize();
|
return initialize();
|
||||||
}
|
}
|
||||||
|
@ -100,9 +115,16 @@ struct VideoCGL : VideoDriver, OpenGL {
|
||||||
private:
|
private:
|
||||||
auto initialize() -> bool {
|
auto initialize() -> bool {
|
||||||
terminate();
|
terminate();
|
||||||
if(!self.context) return false;
|
if(!self.fullScreen && !self.context) return false;
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
if(self.fullScreen) {
|
||||||
|
window = [[RubyWindowCGL alloc] initWith:this];
|
||||||
|
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||||
|
[window toggleFullScreen:nil];
|
||||||
|
//[NSApp setPresentationOptions:NSApplicationPresentationFullScreen];
|
||||||
|
}
|
||||||
|
|
||||||
NSOpenGLPixelFormatAttribute attributeList[] = {
|
NSOpenGLPixelFormatAttribute attributeList[] = {
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||||
NSOpenGLPFAColorSize, 24,
|
NSOpenGLPFAColorSize, 24,
|
||||||
|
@ -111,7 +133,7 @@ private:
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
auto context = (NSView*)self.context;
|
auto context = self.fullScreen ? [window contentView] : (NSView*)self.context;
|
||||||
auto size = [context frame].size;
|
auto size = [context frame].size;
|
||||||
auto format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributeList] autorelease];
|
auto format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributeList] autorelease];
|
||||||
auto openGLContext = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease];
|
auto openGLContext = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease];
|
||||||
|
@ -123,7 +145,7 @@ private:
|
||||||
[view setWantsBestResolutionOpenGLSurface:YES];
|
[view setWantsBestResolutionOpenGLSurface:YES];
|
||||||
[context addSubview:view];
|
[context addSubview:view];
|
||||||
[openGLContext setView:view];
|
[openGLContext setView:view];
|
||||||
|
[[view window] makeFirstResponder:view];
|
||||||
[view lockFocus];
|
[view lockFocus];
|
||||||
|
|
||||||
OpenGL::initialize(self.shader);
|
OpenGL::initialize(self.shader);
|
||||||
|
@ -142,15 +164,26 @@ private:
|
||||||
_ready = false;
|
_ready = false;
|
||||||
OpenGL::terminate();
|
OpenGL::terminate();
|
||||||
|
|
||||||
if(!view) return;
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[view removeFromSuperview];
|
if(view) {
|
||||||
[view release];
|
[view removeFromSuperview];
|
||||||
view = nil;
|
[view release];
|
||||||
|
view = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(window) {
|
||||||
|
//[NSApp setPresentationOptions:NSApplicationPresentationDefault];
|
||||||
|
[window toggleFullScreen:nil];
|
||||||
|
[window setCollectionBehavior:NSWindowCollectionBehaviorDefault];
|
||||||
|
[window close];
|
||||||
|
[window release];
|
||||||
|
window = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RubyVideoCGL* view = nullptr;
|
RubyVideoCGL* view = nullptr;
|
||||||
|
RubyWindowCGL* window = nullptr;
|
||||||
|
|
||||||
bool _ready = false;
|
bool _ready = false;
|
||||||
};
|
};
|
||||||
|
@ -168,4 +201,39 @@ private:
|
||||||
video->output(0, 0);
|
video->output(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(BOOL) acceptsFirstResponder {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) keyDown:(NSEvent*)event {
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) keyUp:(NSEvent*)event {
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RubyWindowCGL : NSWindow
|
||||||
|
|
||||||
|
-(id) initWith:(VideoCGL*)videoPointer {
|
||||||
|
auto primaryRect = [[[NSScreen screens] objectAtIndex:0] frame];
|
||||||
|
if(self = [super initWithContentRect:primaryRect styleMask:0 backing:NSBackingStoreBuffered defer:YES]) {
|
||||||
|
video = videoPointer;
|
||||||
|
[self setDelegate:self];
|
||||||
|
[self setReleasedWhenClosed:NO];
|
||||||
|
[self setAcceptsMouseMovedEvents:YES];
|
||||||
|
[self setTitle:@""];
|
||||||
|
[self makeKeyAndOrderFront:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) canBecomeKeyWindow {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) canBecomeMainWindow {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -327,14 +327,14 @@ auto Video::hasMonitors() -> vector<Monitor> {
|
||||||
auto displayID = [screenID unsignedIntValue];
|
auto displayID = [screenID unsignedIntValue];
|
||||||
auto displayPort = CGDisplayIOServicePort(displayID);
|
auto displayPort = CGDisplayIOServicePort(displayID);
|
||||||
auto dictionary = IODisplayCreateInfoDictionary(displayPort, 0);
|
auto dictionary = IODisplayCreateInfoDictionary(displayPort, 0);
|
||||||
if(auto names = CFDictionaryGetValue(dictionary, CFSTR(kDisplayProductName))) {
|
if(auto names = (CFDictionaryRef)CFDictionaryGetValue(dictionary, CFSTR(kDisplayProductName))) {
|
||||||
auto languageKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
auto languageKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||||
CFDictionaryApplyFunction((CFDictionaryRef)names, MonitorKeyArrayCallback, (void*)languageKeys);
|
CFDictionaryApplyFunction(names, MonitorKeyArrayCallback, (void*)languageKeys);
|
||||||
auto orderLanguageKeys = CFBundleCopyPreferredLocalizationsFromArray(languageKeys);
|
auto orderLanguageKeys = CFBundleCopyPreferredLocalizationsFromArray(languageKeys);
|
||||||
CFRelease(languageKeys);
|
CFRelease(languageKeys);
|
||||||
if(orderLanguageKeys && CFArrayGetCount(orderLanguageKeys)) {
|
if(orderLanguageKeys && CFArrayGetCount(orderLanguageKeys)) {
|
||||||
auto languageKey = CFArrayGetValueAtIndex(orderLanguageKeys, 0);
|
auto languageKey = CFArrayGetValueAtIndex(orderLanguageKeys, 0);
|
||||||
auto localName = CFDictionaryGetValue((CFDictionaryRef)names, languageKey);
|
auto localName = CFDictionaryGetValue(names, languageKey);
|
||||||
monitor.name = {1 + monitors.size(), ": ", [(__bridge NSString*)localName UTF8String]};
|
monitor.name = {1 + monitors.size(), ": ", [(__bridge NSString*)localName UTF8String]};
|
||||||
CFRelease(localName);
|
CFRelease(localName);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue