diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 738cf3dd..ceede127 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -7,7 +7,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "096.02"; + static const string Version = "096.03"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gb/cartridge/cartridge.cpp b/higan/gb/cartridge/cartridge.cpp index 69646cf6..5ec7b892 100644 --- a/higan/gb/cartridge/cartridge.cpp +++ b/higan/gb/cartridge/cartridge.cpp @@ -128,7 +128,7 @@ auto Cartridge::rom_write(uint addr, uint8 data) -> void { } auto Cartridge::ram_read(uint addr) -> uint8 { - if(ramsize == 0) return 0x00; + if(ramsize == 0) return 0xff; if(addr >= ramsize) addr %= ramsize; return ramdata[addr]; } @@ -140,7 +140,7 @@ auto Cartridge::ram_write(uint addr, uint8 data) -> void { } auto Cartridge::mmio_read(uint16 addr) -> uint8 { - if(addr == 0xff50) return 0x00; + if(addr == 0xff50) return 0xff; if(bootrom_enable) { const uint8* data = nullptr; diff --git a/higan/gb/cartridge/huc1/huc1.cpp b/higan/gb/cartridge/huc1/huc1.cpp index efc2cc84..fc65d59d 100644 --- a/higan/gb/cartridge/huc1/huc1.cpp +++ b/higan/gb/cartridge/huc1/huc1.cpp @@ -11,7 +11,7 @@ auto Cartridge::HuC1::mmio_read(uint16 addr) -> uint8 { return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); } - return 0x00; + return 0xff; } auto Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/huc3/huc3.cpp b/higan/gb/cartridge/huc3/huc3.cpp index 9d9500e9..b087f033 100644 --- a/higan/gb/cartridge/huc3/huc3.cpp +++ b/higan/gb/cartridge/huc3/huc3.cpp @@ -9,10 +9,10 @@ auto Cartridge::HuC3::mmio_read(uint16 addr) -> uint8 { if((addr & 0xe000) == 0xa000) { //$a000-bfff if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mbc0/mbc0.cpp b/higan/gb/cartridge/mbc0/mbc0.cpp index 9e214a1e..4d4f71a1 100644 --- a/higan/gb/cartridge/mbc0/mbc0.cpp +++ b/higan/gb/cartridge/mbc0/mbc0.cpp @@ -7,7 +7,7 @@ auto Cartridge::MBC0::mmio_read(uint16 addr) -> uint8 { return cartridge.ram_read(addr & 0x1fff); } - return 0x00; + return 0xff; } auto Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mbc1/mbc1.cpp b/higan/gb/cartridge/mbc1/mbc1.cpp index 499e05fe..b638324c 100644 --- a/higan/gb/cartridge/mbc1/mbc1.cpp +++ b/higan/gb/cartridge/mbc1/mbc1.cpp @@ -19,10 +19,10 @@ auto Cartridge::MBC1::mmio_read(uint16 addr) -> uint8 { return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); } } - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mbc2/mbc2.cpp b/higan/gb/cartridge/mbc2/mbc2.cpp index ec25e50a..b0d9a945 100644 --- a/higan/gb/cartridge/mbc2/mbc2.cpp +++ b/higan/gb/cartridge/mbc2/mbc2.cpp @@ -9,10 +9,10 @@ auto Cartridge::MBC2::mmio_read(uint16 addr) -> uint8 { if((addr & 0xee00) == 0xa000) { //$a000-a1ff if(ram_enable) return cartridge.ram_read(addr & 0x1ff); - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mbc3/mbc3.cpp b/higan/gb/cartridge/mbc3/mbc3.cpp index a90ce03f..7681bc37 100644 --- a/higan/gb/cartridge/mbc3/mbc3.cpp +++ b/higan/gb/cartridge/mbc3/mbc3.cpp @@ -36,10 +36,10 @@ auto Cartridge::MBC3::mmio_read(uint16 addr) -> uint8 { if(ram_select == 0x0b) return rtc_latch_day; if(ram_select == 0x0c) return (rtc_latch_day_carry << 7) | (rtc_latch_day >> 8); } - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mbc5/mbc5.cpp b/higan/gb/cartridge/mbc5/mbc5.cpp index 3793bbd6..f76c3e32 100644 --- a/higan/gb/cartridge/mbc5/mbc5.cpp +++ b/higan/gb/cartridge/mbc5/mbc5.cpp @@ -9,10 +9,10 @@ auto Cartridge::MBC5::mmio_read(uint16 addr) -> uint8 { if((addr & 0xe000) == 0xa000) { //$a000-bfff if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff)); - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cartridge/mmm01/mmm01.cpp b/higan/gb/cartridge/mmm01/mmm01.cpp index 5fa2d359..d70bd3cf 100644 --- a/higan/gb/cartridge/mmm01/mmm01.cpp +++ b/higan/gb/cartridge/mmm01/mmm01.cpp @@ -13,10 +13,10 @@ auto Cartridge::MMM01::mmio_read(uint16 addr) -> uint8 { if((addr & 0xe000) == 0xa000) { //$a000-bfff if(ram_enable) return cartridge.ram_read((ram_select << 13) + (addr & 0x1fff)); - return 0x00; + return 0xff; } - return 0x00; + return 0xff; } auto Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/cpu/memory.cpp b/higan/gb/cpu/memory.cpp index a699cbca..ac219397 100644 --- a/higan/gb/cpu/memory.cpp +++ b/higan/gb/cpu/memory.cpp @@ -6,7 +6,7 @@ auto CPU::op_io() -> void { auto CPU::op_read(uint16 addr) -> uint8 { cycle_edge(); add_clocks(4); - if(oamdma.active && (addr < 0xff80 || addr == 0xffff)) return 0x00; + if(oamdma.active && (addr < 0xff80 || addr == 0xffff)) return 0xff; return bus.read(addr); } @@ -27,9 +27,9 @@ auto CPU::cycle_edge() -> void { //VRAM DMA source can only be ROM or RAM auto CPU::dma_read(uint16 addr) -> uint8 { if(addr < 0x8000) return bus.read(addr); //0000-7fff - if(addr < 0xa000) return 0x00; //8000-9fff + if(addr < 0xa000) return 0xff; //8000-9fff if(addr < 0xe000) return bus.read(addr); //a000-dfff - return 0x00; //e000-ffff + return 0xff; //e000-ffff } //VRAM DMA target is always VRAM diff --git a/higan/gb/cpu/mmio.cpp b/higan/gb/cpu/mmio.cpp index cbb9b381..c9e5b29d 100644 --- a/higan/gb/cpu/mmio.cpp +++ b/higan/gb/cpu/mmio.cpp @@ -115,11 +115,11 @@ auto CPU::mmio_read(uint16 addr) -> uint8 { } if(addr == 0xff76) { //??? - return 0x00; + return 0xff; } if(addr == 0xff77) { //??? - return 0x00; + return 0xff; } if(addr == 0xffff) { //IE @@ -130,7 +130,7 @@ auto CPU::mmio_read(uint16 addr) -> uint8 { | (status.interrupt_enable_vblank << 0); } - return 0x00; + return 0xff; } auto CPU::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/gb/memory/memory.hpp b/higan/gb/memory/memory.hpp index 6165930d..56bd59e4 100644 --- a/higan/gb/memory/memory.hpp +++ b/higan/gb/memory/memory.hpp @@ -16,7 +16,7 @@ struct MMIO { }; struct Unmapped : MMIO { - auto mmio_read(uint16) -> uint8 { return 0x00; } + auto mmio_read(uint16) -> uint8 { return 0xff; } auto mmio_write(uint16, uint8) -> void {} }; diff --git a/higan/gb/ppu/mmio.cpp b/higan/gb/ppu/mmio.cpp index ed2c0da5..d7d13e2d 100644 --- a/higan/gb/ppu/mmio.cpp +++ b/higan/gb/ppu/mmio.cpp @@ -85,7 +85,7 @@ auto PPU::mmio_read(uint16 addr) -> uint8 { return obpd[status.obpi]; } - return 0x00; + return 0xff; } auto PPU::mmio_write(uint16 addr, uint8 data) -> void { diff --git a/higan/target-tomoko/settings/hotkeys.cpp b/higan/target-tomoko/settings/hotkeys.cpp index 5aeeec7f..da2bfff4 100644 --- a/higan/target-tomoko/settings/hotkeys.cpp +++ b/higan/target-tomoko/settings/hotkeys.cpp @@ -67,8 +67,12 @@ auto HotkeySettings::inputEvent(shared_pointer device, uint group, if(activeMapping->bind(device, group, input, oldValue, newValue)) { activeMapping = nullptr; - settingsManager->statusBar.setText(""); - settingsManager->layout.setEnabled(true); + settingsManager->statusBar.setText("Mapping assigned."); refreshMappings(); + timer.onActivate([&] { + timer.setEnabled(false); + settingsManager->statusBar.setText(); + settingsManager->layout.setEnabled(); + }).setInterval(1000).setEnabled(); } } diff --git a/higan/target-tomoko/settings/input.cpp b/higan/target-tomoko/settings/input.cpp index aa3a4581..1931668f 100644 --- a/higan/target-tomoko/settings/input.cpp +++ b/higan/target-tomoko/settings/input.cpp @@ -139,8 +139,12 @@ auto InputSettings::inputEvent(shared_pointer device, uint group, u if(activeMapping->bind(device, group, input, oldValue, newValue)) { activeMapping = nullptr; - settingsManager->statusBar.setText(""); - settingsManager->layout.setEnabled(true); + settingsManager->statusBar.setText("Mapping assigned."); refreshMappings(); + timer.onActivate([&] { + timer.setEnabled(false); + settingsManager->statusBar.setText(); + settingsManager->layout.setEnabled(); + }).setInterval(1000).setEnabled(); } } diff --git a/higan/target-tomoko/settings/settings.hpp b/higan/target-tomoko/settings/settings.hpp index eae9545a..21efb622 100644 --- a/higan/target-tomoko/settings/settings.hpp +++ b/higan/target-tomoko/settings/settings.hpp @@ -63,6 +63,7 @@ struct InputSettings : TabFrameItem { auto inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue, bool allowMouseInput = false) -> void; InputMapping* activeMapping = nullptr; + Timer timer; VerticalLayout layout{this}; HorizontalLayout selectionLayout{&layout, Size{~0, 0}}; @@ -87,6 +88,7 @@ struct HotkeySettings : TabFrameItem { auto inputEvent(shared_pointer device, uint group, uint input, int16 oldValue, int16 newValue) -> void; InputMapping* activeMapping = nullptr; + Timer timer; VerticalLayout layout{this}; ListView mappingList{&layout, Size{~0, ~0}}; diff --git a/higan/target-tomoko/tools/tools.hpp b/higan/target-tomoko/tools/tools.hpp index 67f62895..1c81b5b4 100644 --- a/higan/target-tomoko/tools/tools.hpp +++ b/higan/target-tomoko/tools/tools.hpp @@ -11,7 +11,7 @@ struct CheatDatabase : Window { Button selectAllButton{&controlLayout, Size{100, 0}}; Button unselectAllButton{&controlLayout, Size{100, 0}}; Widget spacer{&controlLayout, Size{~0, 0}}; - Button addCodesButton{&controlLayout, Size{80, 0}}; + Button addCodesButton{&controlLayout, Size{100, 0}}; }; struct CheatEditor : TabFrameItem { diff --git a/hiro/cocoa/application.cpp b/hiro/cocoa/application.cpp index 7ea0f6de..7cc054fd 100644 --- a/hiro/cocoa/application.cpp +++ b/hiro/cocoa/application.cpp @@ -85,8 +85,6 @@ auto pApplication::initialize() -> void { [NSApplication sharedApplication]; cocoaDelegate = [[CocoaDelegate alloc] init]; [NSApp setDelegate:cocoaDelegate]; - //every window has the default application menu; call this so it is displayed at startup -// [NSApp setMainMenu:[pWindow::none().p.cocoaWindow menu]]; } } diff --git a/hiro/cocoa/header.hpp b/hiro/cocoa/header.hpp index 7e7f4999..776e1d6f 100644 --- a/hiro/cocoa/header.hpp +++ b/hiro/cocoa/header.hpp @@ -2,3 +2,5 @@ #import #import #undef decimal + +#include diff --git a/hiro/cocoa/timer.cpp b/hiro/cocoa/timer.cpp index 82cfed60..91de0545 100644 --- a/hiro/cocoa/timer.cpp +++ b/hiro/cocoa/timer.cpp @@ -19,15 +19,18 @@ [instance invalidate]; instance = nil; } - if(!timer->enabled()) return; - instance = [NSTimer - scheduledTimerWithTimeInterval:timer->state.interval / 1000.0 - target:self selector:@selector(run:) userInfo:nil repeats:YES - ]; + if(timer->enabled()) { + instance = [NSTimer + scheduledTimerWithTimeInterval:timer->state.interval / 1000.0 + target:self selector:@selector(run:) userInfo:nil repeats:YES + ]; + } } -(void) run:(NSTimer*)instance { - timer->doActivate(); + if(timer->enabled()) { + timer->doActivate(); + } } @end diff --git a/hiro/cocoa/widget/canvas.cpp b/hiro/cocoa/widget/canvas.cpp index 1588ede3..6f2730e3 100644 --- a/hiro/cocoa/widget/canvas.cpp +++ b/hiro/cocoa/widget/canvas.cpp @@ -27,15 +27,19 @@ } -(void) mouseButton:(NSEvent*)event down:(BOOL)isDown { -/* - if(auto& callback = isDown ? canvas->onMousePress : canvas->onMouseRelease) { + if(isDown) { switch([event buttonNumber]) { - case 0: return callback(phoenix::Mouse::Button::Left); - case 1: return callback(phoenix::Mouse::Button::Right); - case 2: return callback(phoenix::Mouse::Button::Middle); + case 0: return canvas->doMousePress(hiro::Mouse::Button::Left); + case 1: return canvas->doMousePress(hiro::Mouse::Button::Right); + case 2: return canvas->doMousePress(hiro::Mouse::Button::Middle); + } + } else { + switch([event buttonNumber]) { + case 0: return canvas->doMouseRelease(hiro::Mouse::Button::Left); + case 1: return canvas->doMouseRelease(hiro::Mouse::Button::Right); + case 2: return canvas->doMouseRelease(hiro::Mouse::Button::Middle); } } -*/ } -(void) mouseExited:(NSEvent*)event { @@ -105,10 +109,12 @@ auto pCanvas::destruct() -> void { } auto pCanvas::minimumSize() const -> Size { + if(auto& icon = state().icon) return {(int)icon.width(), (int)icon.height()}; return {0, 0}; } auto pCanvas::setColor(Color color) -> void { + update(); } auto pCanvas::setDroppable(bool droppable) -> void { @@ -122,112 +128,79 @@ auto pCanvas::setDroppable(bool droppable) -> void { } auto pCanvas::setGeometry(Geometry geometry) -> void { -/* - if(canvas.state.width == 0 || canvas.state.height == 0) rasterize(); - - uint width = canvas.state.width; - uint height = canvas.state.height; - if(width == 0) width = widget.state.geometry.width; - if(height == 0) height = widget.state.geometry.height; - - if(width < geometry.width) { - geometry.x += (geometry.width - width) / 2; - geometry.width = width; - } - - if(height < geometry.height) { - geometry.y += (geometry.height - height) / 2; - geometry.height = height; - } -*/ - pWidget::setGeometry(geometry); + update(); } auto pCanvas::setGradient(Gradient gradient) -> void { + update(); } auto pCanvas::setIcon(const image& icon) -> void { + update(); } auto pCanvas::update() -> void { + _rasterize(); + @autoreleasepool { + [cocoaView setNeedsDisplay:YES]; + } } auto pCanvas::_rasterize() -> void { -/* @autoreleasepool { - unsigned width = canvas.state.width; - unsigned height = canvas.state.height; - if(width == 0) width = widget.state.geometry.width; - if(height == 0) height = widget.state.geometry.height; + int width = 0; + int height = 0; + + if(auto& icon = state().icon) { + width = icon.width(); + height = icon.height(); + } else { + width = pSizable::state().geometry.width(); + height = pSizable::state().geometry.height(); + } + if(width <= 0 || height <= 0) return; if(width != surfaceWidth || height != surfaceHeight) { - NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease]; - NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] + [cocoaView setImage:nil]; + [surface release]; + surface = nullptr; + bitmap = nullptr; + } + + surfaceWidth = width; + surfaceHeight = height; + + if(!surface) { + surface = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease]; + bitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil pixelsWide:width pixelsHigh:height bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSCalibratedRGBColorSpace bitmapFormat:NSAlphaNonpremultipliedBitmapFormat - bytesPerRow:width * 4 bitsPerPixel:32 + bytesPerRow:(width * 4) bitsPerPixel:32 ] autorelease]; - - [image addRepresentation:bitmap]; - [cocoaView setImage:image]; - - surfaceWidth = width; - surfaceHeight = height; + [surface addRepresentation:bitmap]; + [cocoaView setImage:surface]; } - if(NSBitmapImageRep* bitmap = [[[cocoaView image] representations] objectAtIndex:0]) { - uint32_t* target = (uint32_t*)[bitmap bitmapData]; + auto target = (uint32*)[bitmap bitmapData]; - if(canvas.state.mode == Canvas::Mode::Color) { - nall::image image; - image.allocate(width, height); - image.fill(canvas.state.color.argb()); - memcpy(target, image.data, image.size); - } - - if(canvas.state.mode == Canvas::Mode::Gradient) { - nall::image image; - image.allocate(width, height); - image.gradient( - canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb() - ); - memcpy(target, image.data, image.size); - } - - if(canvas.state.mode == Canvas::Mode::Image) { - nall::image image = canvas.state.image; - image.scale(width, height); - image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); - memcpy(target, image.data, image.size); - } - - if(canvas.state.mode == Canvas::Mode::Data) { - if(width == canvas.state.width && height == canvas.state.height) { - memcpy(target, canvas.state.data, width * height * sizeof(uint32_t)); - } else { - memset(target, 0x00, width * height * sizeof(uint32_t)); - } - } - - //ARGB -> ABGR transformation - for(unsigned n = 0; n < width * height; n++) { - uint32_t color = *target; - color = (color & 0xff00ff00) | ((color & 0xff0000) >> 16) | ((color & 0x0000ff) << 16); - *target++ = color; - } + if(auto icon = state().icon) { + icon.transform(); + memory::copy(target, icon.data(), icon.size()); + } else if(auto& gradient = state().gradient) { + auto& colors = gradient.state.colors; + image fill; + fill.allocate(width, height); + fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value()); + memory::copy(target, fill.data(), fill.size()); + } else { + uint32 color = state().color.value(); + for(auto n : range(width * height)) target[n] = color; } } -*/ -} - -auto pCanvas::_redraw() -> void { - @autoreleasepool { - [cocoaView setNeedsDisplay:YES]; - } } } diff --git a/hiro/cocoa/widget/canvas.hpp b/hiro/cocoa/widget/canvas.hpp index bc4774f3..64f77f19 100644 --- a/hiro/cocoa/widget/canvas.hpp +++ b/hiro/cocoa/widget/canvas.hpp @@ -35,9 +35,10 @@ struct pCanvas : pWidget { auto update() -> void; auto _rasterize() -> void; - auto _redraw() -> void; CocoaCanvas* cocoaCanvas = nullptr; + NSImage* surface = nullptr; + NSBitmapImageRep* bitmap = nullptr; uint surfaceWidth = 0; uint surfaceHeight = 0; }; diff --git a/hiro/cocoa/widget/list-view.cpp b/hiro/cocoa/widget/list-view.cpp index 56a995e4..987f549b 100644 --- a/hiro/cocoa/widget/list-view.cpp +++ b/hiro/cocoa/widget/list-view.cpp @@ -163,6 +163,7 @@ if(auto listViewCell = listViewItem->cell([view columnAtPoint:frame.origin])) { NSColor* backgroundColor = nil; if([self isHighlighted]) backgroundColor = [NSColor alternateSelectedControlColor]; + else if(!listView->enabled(true)) backgroundColor = [NSColor controlBackgroundColor]; else if(auto color = listViewCell->state.backgroundColor) backgroundColor = NSMakeColor(color); else backgroundColor = [NSColor controlBackgroundColor]; @@ -195,6 +196,7 @@ if(listViewCell->state.alignment.horizontal() > 0.666) paragraphStyle.alignment = NSTextAlignmentRight; NSColor* foregroundColor = nil; if([self isHighlighted]) foregroundColor = [NSColor alternateSelectedControlTextColor]; + else if(!listView->enabled(true)) foregroundColor = [NSColor disabledControlTextColor]; else if(auto color = listViewCell->state.foregroundColor) foregroundColor = NSMakeColor(color); else foregroundColor = [NSColor textColor]; NSString* text = [NSString stringWithUTF8String:listViewCell->state.text]; @@ -346,6 +348,13 @@ auto pListView::setBatchable(bool batchable) -> void { auto pListView::setBordered(bool bordered) -> void { } +auto pListView::setEnabled(bool enabled) -> void { + pWidget::setEnabled(enabled); + @autoreleasepool { + [[cocoaView content] setEnabled:enabled]; + } +} + auto pListView::setFont(const Font& font) -> void { @autoreleasepool { [cocoaView setFont:pFont::create(font)]; diff --git a/hiro/cocoa/widget/list-view.hpp b/hiro/cocoa/widget/list-view.hpp index f846c97e..e1f3fbac 100644 --- a/hiro/cocoa/widget/list-view.hpp +++ b/hiro/cocoa/widget/list-view.hpp @@ -55,6 +55,7 @@ struct pListView : pWidget { auto setBackgroundColor(Color color) -> void; auto setBatchable(bool batchable) -> void; auto setBordered(bool bordered) -> void; + auto setEnabled(bool enabled) -> void override; auto setFont(const Font& font) -> void override; auto setForegroundColor(Color color) -> void; diff --git a/hiro/cocoa/widget/text-edit.cpp b/hiro/cocoa/widget/text-edit.cpp index 862a12b6..c22756f4 100644 --- a/hiro/cocoa/widget/text-edit.cpp +++ b/hiro/cocoa/widget/text-edit.cpp @@ -82,6 +82,13 @@ auto pTextEdit::setEditable(bool editable) -> void { } } +auto pTextEdit::setEnabled(bool enabled) -> void { + pWidget::setEnabled(enabled); + @autoreleasepool { + [[cocoaView content] setEnabled:enabled]; + } +} + auto pTextEdit::setFont(const Font& font) -> void { @autoreleasepool { [[cocoaView content] setFont:pFont::create(font)]; diff --git a/hiro/cocoa/widget/text-edit.hpp b/hiro/cocoa/widget/text-edit.hpp index c00e2ce4..745784ea 100644 --- a/hiro/cocoa/widget/text-edit.hpp +++ b/hiro/cocoa/widget/text-edit.hpp @@ -19,6 +19,7 @@ struct pTextEdit : pWidget { auto setBackgroundColor(Color color) -> void; auto setCursor(Cursor cursor) -> void; auto setEditable(bool editable) -> void; + auto setEnabled(bool enabled) -> void override; auto setFont(const Font& font) -> void override; auto setForegroundColor(Color color) -> void; auto setText(const string& text) -> void; diff --git a/hiro/cocoa/widget/widget.cpp b/hiro/cocoa/widget/widget.cpp index bb8d82e6..0d0357d8 100644 --- a/hiro/cocoa/widget/widget.cpp +++ b/hiro/cocoa/widget/widget.cpp @@ -73,14 +73,6 @@ auto pWidget::setVisible(bool visible) -> void { } } -/* -bool pWidget::enabled() { - @autoreleasepool { - return [cocoaView respondsToSelector:@selector(enabled)] && [cocoaView enabled]; - } -} -*/ - } #endif diff --git a/hiro/cocoa/window.cpp b/hiro/cocoa/window.cpp index a95cd801..0debae81 100644 --- a/hiro/cocoa/window.cpp +++ b/hiro/cocoa/window.cpp @@ -34,9 +34,17 @@ [rootMenu addItem:item]; [rootMenu addItem:[NSMenuItem separatorItem]]; - item = [[[NSMenuItem alloc] initWithTitle:@"Preferences" action:@selector(menuPreferences) keyEquivalent:@""] autorelease]; + item = [[[NSMenuItem alloc] initWithTitle:@"Preferences ..." action:@selector(menuPreferences) keyEquivalent:@""] autorelease]; [item setTarget:self]; [rootMenu addItem:item]; + + string result = nall::execute("defaults", "read", "/Library/Preferences/com.apple.security", "GKAutoRearm").strip(); + if(result != "0") { + disableGatekeeperAutoRearm = [[[NSMenuItem alloc] initWithTitle:@"Disable Gatekeeper Auto-Rearm" action:@selector(menuDisableGatekeeperAutoRearm) keyEquivalent:@""] autorelease]; + [disableGatekeeperAutoRearm setTarget:self]; + [rootMenu addItem:disableGatekeeperAutoRearm]; + } + [rootMenu addItem:[NSMenuItem separatorItem]]; NSMenu* servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease]; @@ -58,6 +66,7 @@ item = [[[NSMenuItem alloc] initWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""] autorelease]; [item setTarget:NSApp]; [rootMenu addItem:item]; + [rootMenu addItem:[NSMenuItem separatorItem]]; item = [[[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"Quit %@", applicationName] action:@selector(menuQuit) keyEquivalent:@""] autorelease]; @@ -130,6 +139,24 @@ hiro::Application::Cocoa::doPreferences(); } +-(void) menuDisableGatekeeperAutoRearm { + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; + [alert setMessageText:@"Disable Gatekeeper Auto-Rearm"]; + + nall::execute("sudo", "defaults", "write", "/Library/Preferences/com.apple.security", "GKAutoRearm", "-bool", "NO"); + if(nall::execute("defaults", "read", "/Library/Preferences/com.apple.security", "GKAutoRearm").strip() == "0") { + [alert setAlertStyle:NSInformationalAlertStyle]; + [alert setInformativeText:@"Gatekeeper's automatic 30-day rearm behavior has been disabled successfully."]; + [disableGatekeeperAutoRearm setHidden:YES]; + } else { + [alert setAlertStyle:NSWarningAlertStyle]; + [alert setInformativeText:@"Error: failed to disable Gatekeeper's automatic rearm behavior."]; + } + + [alert addButtonWithTitle:@"Ok"]; + [alert runModal]; +} + -(void) menuQuit { hiro::Application::Cocoa::doQuit(); } @@ -142,15 +169,15 @@ namespace hiro { -auto pWindow::none() -> Window& { - static Window* window = nullptr; - if(window == nullptr) window = new Window; - return *window; -} - auto pWindow::construct() -> void { @autoreleasepool { cocoaWindow = [[CocoaWindow alloc] initWith:self()]; + + static bool once = true; + if(once) { + once = false; + [NSApp setMainMenu:[cocoaWindow menuBar]]; + } } } @@ -234,14 +261,17 @@ auto pWindow::setFocused() -> void { auto pWindow::setFullScreen(bool fullScreen) -> void { @autoreleasepool { - if(fullScreen == true) { + if(fullScreen) { + windowedGeometry = state().geometry; [NSApp setPresentationOptions:NSApplicationPresentationFullScreen]; [cocoaWindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; [cocoaWindow toggleFullScreen:nil]; + state().geometry = _geometry(); } else { [cocoaWindow toggleFullScreen:nil]; [cocoaWindow setCollectionBehavior:NSWindowCollectionBehaviorDefault]; [NSApp setPresentationOptions:NSApplicationPresentationDefault]; + state().geometry = windowedGeometry; } } } @@ -363,15 +393,18 @@ auto pWindow::_append(mWidget& widget) -> void { } } -/* -auto pWindow::geometry() -> Geometry { +auto pWindow::_geometry() -> Geometry { @autoreleasepool { NSRect area = [cocoaWindow contentRectForFrameRect:[cocoaWindow frame]]; area.size.height -= statusBarHeight(); - return {area.origin.x, Desktop::size().height - area.origin.y - area.size.height, area.size.width, area.size.height}; + return { + (int)area.origin.x, (int)(Monitor::geometry(Monitor::primary()).height() - area.origin.y - area.size.height), + (int)area.size.width, (int)area.size.height + }; } } +/* auto pWindow::remove(Widget& widget) -> void { @autoreleasepool { [widget.p.cocoaView removeFromSuperview]; diff --git a/hiro/cocoa/window.hpp b/hiro/cocoa/window.hpp index dae360e0..ef178a6a 100644 --- a/hiro/cocoa/window.hpp +++ b/hiro/cocoa/window.hpp @@ -5,6 +5,7 @@ hiro::mWindow* window; NSMenu* menuBar; NSMenu* rootMenu; + NSMenuItem* disableGatekeeperAutoRearm; NSTextField* statusBar; } -(id) initWith:(hiro::mWindow&)window; @@ -19,6 +20,7 @@ -(NSMenu*) menuBar; -(void) menuAbout; -(void) menuPreferences; +-(void) menuDisableGatekeeperAutoRearm; -(void) menuQuit; -(NSTextField*) statusBar; @end @@ -28,8 +30,6 @@ namespace hiro { struct pWindow : pObject { Declare(Window, Object) - static auto none() -> Window&; - auto append(sLayout layout) -> void; auto append(sMenuBar menuBar) -> void; auto append(sStatusBar statusBar) -> void; @@ -54,8 +54,10 @@ struct pWindow : pObject { auto statusBarReposition() -> void; auto _append(mWidget& widget) -> void; + auto _geometry() -> Geometry; CocoaWindow* cocoaWindow = nullptr; + Geometry windowedGeometry; }; } diff --git a/hiro/core/object.cpp b/hiro/core/object.cpp index 7262285b..810e9e0b 100644 --- a/hiro/core/object.cpp +++ b/hiro/core/object.cpp @@ -40,6 +40,10 @@ auto mObject::abstract() const -> bool { if(dynamic_cast(this)) return false; #endif + #if defined(Hiro_Timer) + if(dynamic_cast(this)) return false; + #endif + #if defined(Hiro_Window) if(dynamic_cast(this)) return false; #endif diff --git a/hiro/gtk/timer.hpp b/hiro/gtk/timer.hpp index 57671ae7..ce0d950d 100644 --- a/hiro/gtk/timer.hpp +++ b/hiro/gtk/timer.hpp @@ -5,7 +5,7 @@ namespace hiro { struct pTimer : pObject { Declare(Timer, Object) - auto setEnabled(bool enabled) -> void; + auto setEnabled(bool enabled) -> void override; auto setInterval(uint interval) -> void; }; diff --git a/hiro/qt/widget/canvas.cpp b/hiro/qt/widget/canvas.cpp index 8a82c651..fff7fa11 100644 --- a/hiro/qt/widget/canvas.cpp +++ b/hiro/qt/widget/canvas.cpp @@ -49,8 +49,8 @@ auto pCanvas::update() -> void { } auto pCanvas::_rasterize() -> void { - signed width = 0; - signed height = 0; + int width = 0; + int height = 0; if(auto& icon = state().icon) { width = icon.width(); diff --git a/icarus/GNUmakefile b/icarus/GNUmakefile index 8f1418a1..35253c2a 100644 --- a/icarus/GNUmakefile +++ b/icarus/GNUmakefile @@ -14,6 +14,7 @@ ifeq ($(platform),macosx) @if [ -d out/icarus.app ]; then rm -r out/icarus.app; fi mkdir -p out/icarus.app/Contents/MacOS/ mv out/icarus out/icarus.app/Contents/MacOS/ + cp icarus.plist out/icarus.app/Contents/Info.plist endif obj/hiro.o: ../hiro/hiro.cpp diff --git a/icarus/icarus.plist b/icarus/icarus.plist new file mode 100644 index 00000000..6298f8d6 --- /dev/null +++ b/icarus/icarus.plist @@ -0,0 +1,14 @@ + + + + + CFBundleDisplayName + icarus + CFBundleExecutable + icarus + + + diff --git a/icarus/settings.cpp b/icarus/settings.cpp index 90194ba8..66b22850 100644 --- a/icarus/settings.cpp +++ b/icarus/settings.cpp @@ -20,5 +20,6 @@ Settings::Settings() { } Settings::~Settings() { + directory::create({configpath(), "icarus/"}); file::write(locate({configpath(), "icarus/"}, "settings.bml"), BML::serialize(*this)); } diff --git a/nall/run.hpp b/nall/run.hpp index 01867a71..d6d1ab75 100644 --- a/nall/run.hpp +++ b/nall/run.hpp @@ -16,7 +16,7 @@ namespace nall { -#if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) +#if defined(PLATFORM_MACOSX) || defined(PLATFORM_LINUX) || defined(PLATFORM_BSD) template inline auto execute(const string& name, P&&... p) -> string { int fd[2]; diff --git a/nall/string/platform.hpp b/nall/string/platform.hpp index d327c219..6e30f761 100644 --- a/nall/string/platform.hpp +++ b/nall/string/platform.hpp @@ -24,11 +24,11 @@ auto realpath(rstring name) -> string { auto programpath() -> string { #if defined(PLATFORM_WINDOWS) - int argc = 0; - wchar_t** argv = CommandLineToArgvW(GetCommandLine(), &argc); - string argv0 = (const char*)utf8_t(argv[0]); - LocalFree(argv); - return realpath(argv0); + wchar_t path[PATH_MAX] = L""; + GetModuleFileName(nullptr, path, PATH_MAX); + string result = (const char*)utf8_t(path); + result.transform("\\", "/"); + return realpath(result); #else Dl_info info; dladdr((void*)&programpath, &info);