diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index aa2293d4..cb23ec68 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "103.12"; + static const string Version = "103.13"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/gb/interface/game-boy-color.cpp b/higan/gb/interface/game-boy-color.cpp index 681de929..80c2213d 100644 --- a/higan/gb/interface/game-boy-color.cpp +++ b/higan/gb/interface/game-boy-color.cpp @@ -3,7 +3,7 @@ GameBoyColorInterface::GameBoyColorInterface() { information.name = "Game Boy Color"; information.overscan = false; - media.append({ID::GameBoyColor, "Game Boy Color", "gb"}); + media.append({ID::GameBoyColor, "Game Boy Color", "gbc"}); } auto GameBoyColorInterface::videoColors() -> uint32 { diff --git a/higan/ms/interface/master-system.cpp b/higan/ms/interface/master-system.cpp index 6b0529a0..9ef6213c 100644 --- a/higan/ms/interface/master-system.cpp +++ b/higan/ms/interface/master-system.cpp @@ -5,15 +5,9 @@ MasterSystemInterface::MasterSystemInterface() { media.append({ID::MasterSystem, "Master System", "ms"}); - Port hardware{ID::Port::Hardware, "Hardware"}; Port controllerPort1{ID::Port::Controller1, "Controller Port 1"}; Port controllerPort2{ID::Port::Controller2, "Controller Port 2"}; - - { Device device{ID::Device::MasterSystemControls, "Controls"}; - device.inputs.append({0, "Reset"}); - device.inputs.append({0, "Pause"}); - hardware.devices.append(device); - } + Port hardware{ID::Port::Hardware, "Hardware"}; { Device device{ID::Device::None, "None"}; controllerPort1.devices.append(device); @@ -31,9 +25,15 @@ MasterSystemInterface::MasterSystemInterface() { controllerPort2.devices.append(device); } - ports.append(move(hardware)); + { Device device{ID::Device::MasterSystemControls, "Controls"}; + device.inputs.append({0, "Reset"}); + device.inputs.append({0, "Pause"}); + hardware.devices.append(device); + } + ports.append(move(controllerPort1)); ports.append(move(controllerPort2)); + ports.append(move(hardware)); } auto MasterSystemInterface::videoResolution() -> VideoResolution { diff --git a/higan/sfc/ppu/io.cpp b/higan/sfc/ppu/io.cpp index 4587f92f..36b7edb8 100644 --- a/higan/sfc/ppu/io.cpp +++ b/higan/sfc/ppu/io.cpp @@ -293,8 +293,9 @@ auto PPU::writeIO(uint24 addr, uint8 data) -> void { io.hoffsetMode7 = data << 8 | latch.mode7; latch.mode7 = data; - bg1.io.hoffset = data << 8 | (latch.bgofs & ~7) | (bg1.io.hoffset >> 8 & 7); - latch.bgofs = data; + bg1.io.hoffset = data << 8 | (latch.bgofsPPU1 & ~7) | (latch.bgofsPPU2 & 7); + latch.bgofsPPU1 = data; + latch.bgofsPPU2 = data; return; } @@ -303,50 +304,53 @@ auto PPU::writeIO(uint24 addr, uint8 data) -> void { io.voffsetMode7 = data << 8 | latch.mode7; latch.mode7 = data; - bg1.io.voffset = data << 8 | latch.bgofs; - latch.bgofs = data; + bg1.io.voffset = data << 8 | latch.bgofsPPU1; + latch.bgofsPPU1 = data; return; } //BG2HOFS case 0x210f: { - bg2.io.hoffset = data << 8 | (latch.bgofs & ~7) | (bg2.io.hoffset >> 8 & 7); - latch.bgofs = data; + bg2.io.hoffset = data << 8 | (latch.bgofsPPU1 & ~7) | (latch.bgofsPPU2 & 7); + latch.bgofsPPU1 = data; + latch.bgofsPPU2 = data; return; } //BG2VOFS case 0x2110: { - bg2.io.voffset = data << 8 | latch.bgofs; - latch.bgofs = data; + bg2.io.voffset = data << 8 | latch.bgofsPPU1; + latch.bgofsPPU1 = data; return; } //BG3HOFS case 0x2111: { - bg3.io.hoffset = data << 8 | (latch.bgofs & ~7) | (bg3.io.hoffset >> 8 & 7); - latch.bgofs = data; + bg3.io.hoffset = data << 8 | (latch.bgofsPPU1 & ~7) | (latch.bgofsPPU2 & 7); + latch.bgofsPPU1 = data; + latch.bgofsPPU2 = data; return; } //BG3VOFS case 0x2112: { - bg3.io.voffset = data << 8 | latch.bgofs; - latch.bgofs = data; + bg3.io.voffset = data << 8 | latch.bgofsPPU1; + latch.bgofsPPU1 = data; return; } //BG4HOFS case 0x2113: { - bg4.io.hoffset = data << 8 | (latch.bgofs & ~7) | (bg4.io.hoffset >> 8 & 7); - latch.bgofs = data; + bg4.io.hoffset = data << 8 | (latch.bgofsPPU1 & ~7) | (latch.bgofsPPU2 & 7); + latch.bgofsPPU1 = data; + latch.bgofsPPU2 = data; return; } //BG4VOFS case 0x2114: { - bg4.io.voffset = data << 8 | latch.bgofs; - latch.bgofs = data; + bg4.io.voffset = data << 8 | latch.bgofsPPU1; + latch.bgofsPPU1 = data; return; } diff --git a/higan/sfc/ppu/ppu.cpp b/higan/sfc/ppu/ppu.cpp index 98871815..fefde62c 100644 --- a/higan/sfc/ppu/ppu.cpp +++ b/higan/sfc/ppu/ppu.cpp @@ -103,7 +103,8 @@ auto PPU::power() -> void { latch.vram = random(0x0000); latch.oam = random(0x00); latch.cgram = random(0x00); - latch.bgofs = random(0x00); + latch.bgofsPPU1 = random(0x00); + latch.bgofsPPU2 = random(0x00); latch.mode7 = random(0x00); latch.counters = false; latch.hcounter = 0; diff --git a/higan/sfc/ppu/ppu.hpp b/higan/sfc/ppu/ppu.hpp index 1bd3ab70..1b50335f 100644 --- a/higan/sfc/ppu/ppu.hpp +++ b/higan/sfc/ppu/ppu.hpp @@ -55,7 +55,8 @@ private: uint16 vram; uint8 oam; uint8 cgram; - uint8 bgofs; + uint8 bgofsPPU1; + uint3 bgofsPPU2; uint8 mode7; uint1 counters; uint1 hcounter; diff --git a/higan/sfc/ppu/serialization.cpp b/higan/sfc/ppu/serialization.cpp index 7cc41b4f..297da7ab 100644 --- a/higan/sfc/ppu/serialization.cpp +++ b/higan/sfc/ppu/serialization.cpp @@ -29,7 +29,8 @@ auto PPU::serialize(serializer& s) -> void { s.integer(latch.vram); s.integer(latch.oam); s.integer(latch.cgram); - s.integer(latch.bgofs); + s.integer(latch.bgofsPPU1); + s.integer(latch.bgofsPPU2); s.integer(latch.mode7); s.integer(latch.counters); s.integer(latch.hcounter); diff --git a/higan/target-tomoko/input/hotkeys.cpp b/higan/target-tomoko/input/hotkeys.cpp index e390bda1..543590ca 100644 --- a/higan/target-tomoko/input/hotkeys.cpp +++ b/higan/target-tomoko/input/hotkeys.cpp @@ -96,12 +96,12 @@ auto InputManager::appendHotkeys() -> void { } auto InputManager::pollHotkeys() -> void { - if(program->allowInput(true)) { - for(auto& hotkey : hotkeys) { - int16 state = hotkey->poll(); - if(hotkey->state == 0 && state == 1 && hotkey->press) hotkey->press(); - if(hotkey->state == 1 && state == 0 && hotkey->release) hotkey->release(); - hotkey->state = state; - } + if(!program->focused()) return; + + for(auto& hotkey : hotkeys) { + int16 state = hotkey->poll(); + if(hotkey->state == 0 && state == 1 && hotkey->press) hotkey->press(); + if(hotkey->state == 1 && state == 0 && hotkey->release) hotkey->release(); + hotkey->state = state; } } diff --git a/higan/target-tomoko/input/input.cpp b/higan/target-tomoko/input/input.cpp index eb0a339a..b8230e7e 100644 --- a/higan/target-tomoko/input/input.cpp +++ b/higan/target-tomoko/input/input.cpp @@ -192,27 +192,29 @@ InputManager::InputManager() { frequency = max(1u, settings["Input/Frequency"].natural()); for(auto& emulator : program->emulators) { - auto& inputEmulator = emulators(emulators.size()); + InputEmulator inputEmulator; inputEmulator.interface = emulator; inputEmulator.name = emulator->information.name; - for(auto& port : emulator->ports) { - auto& inputPort = inputEmulator.ports(port.id); - inputPort.name = port.name; + InputPort inputPort{port.id, port.name}; for(auto& device : port.devices) { - auto& inputDevice = inputPort.devices(device.id); - inputDevice.name = device.name; + InputDevice inputDevice{device.id, device.name}; for(auto& input : device.inputs) { - auto& inputMapping = inputDevice.mappings(inputDevice.mappings.size()); + InputMapping inputMapping; inputMapping.name = input.name; inputMapping.type = input.type; inputMapping.path = string{inputEmulator.name, "/", inputPort.name, "/", inputDevice.name, "/", inputMapping.name}.replace(" ", ""); inputMapping.assignment = settings(inputMapping.path).text(); inputMapping.bind(); + + inputDevice.mappings.append(inputMapping); } + inputPort.devices.append(inputDevice); } + inputEmulator.ports.append(move(inputPort)); } + emulators.append(move(inputEmulator)); } appendHotkeys(); @@ -278,6 +280,19 @@ auto InputManager::quit() -> void { hotkeys.reset(); } +auto InputManager::mapping(uint port, uint device, uint input) -> maybe { + if(!emulator) return nothing; + for(auto& inputPort : emulator->ports) { + if(inputPort.id != port) continue; + for(auto& inputDevice : inputPort.devices) { + if(inputDevice.id != device) continue; + if(input >= inputDevice.mappings.size()) return nothing; + return inputDevice.mappings[input]; + } + } + return nothing; +} + auto InputManager::findMouse() -> shared_pointer { for(auto& device : devices) { if(device->isMouse()) return device; diff --git a/higan/target-tomoko/input/input.hpp b/higan/target-tomoko/input/input.hpp index f1012fa8..09c23b2d 100644 --- a/higan/target-tomoko/input/input.hpp +++ b/higan/target-tomoko/input/input.hpp @@ -39,11 +39,13 @@ struct InputHotkey : InputMapping { }; struct InputDevice { + uint id; string name; vector mappings; }; struct InputPort { + uint id; string name; vector devices; }; @@ -62,6 +64,7 @@ struct InputManager { auto onChange(shared_pointer device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void; auto quit() -> void; + auto mapping(uint port, uint device, uint input) -> maybe; auto findMouse() -> shared_pointer; //hotkeys.cpp diff --git a/higan/target-tomoko/presentation/about.cpp b/higan/target-tomoko/presentation/about.cpp index 782fc834..8899cd3b 100644 --- a/higan/target-tomoko/presentation/about.cpp +++ b/higan/target-tomoko/presentation/about.cpp @@ -23,4 +23,5 @@ AboutWindow::AboutWindow() { setResizable(false); setSize(layout.minimumSize()); setCentered(); + setDismissable(); } diff --git a/higan/target-tomoko/program/interface.cpp b/higan/target-tomoko/program/interface.cpp index 9d487224..89c1c233 100644 --- a/higan/target-tomoko/program/interface.cpp +++ b/higan/target-tomoko/program/interface.cpp @@ -96,18 +96,20 @@ auto Program::audioSample(const double* samples, uint channels) -> void { } auto Program::inputPoll(uint port, uint device, uint input) -> int16 { - if(allowInput()) { + if(focused() || settings["Input/FocusLoss/AllowInput"].boolean()) { inputManager->poll(); - auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input]; - return mapping.poll(); + if(auto mapping = inputManager->mapping(port, device, input)) { + return mapping->poll(); + } } return 0; } auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void { - if(allowInput() || !enable) { - auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input]; - return mapping.rumble(enable); + if(focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) { + if(auto mapping = inputManager->mapping(port, device, input)) { + return mapping->rumble(enable); + } } } diff --git a/higan/target-tomoko/program/program.cpp b/higan/target-tomoko/program/program.cpp index b6df8342..fd455097 100644 --- a/higan/target-tomoko/program/program.cpp +++ b/higan/target-tomoko/program/program.cpp @@ -84,7 +84,7 @@ auto Program::main() -> void { inputManager->poll(); inputManager->pollHotkeys(); - if(!emulator || !emulator->loaded() || pause || (!presentation->focused() && settings["Input/FocusLoss/Pause"].boolean())) { + if(!emulator || !emulator->loaded() || pause || (!focused() && settings["Input/FocusLoss/Pause"].boolean())) { audio->clear(); usleep(20 * 1000); return; diff --git a/higan/target-tomoko/program/program.hpp b/higan/target-tomoko/program/program.hpp index 39def148..f3a17008 100644 --- a/higan/target-tomoko/program/program.hpp +++ b/higan/target-tomoko/program/program.hpp @@ -35,7 +35,7 @@ struct Program : Emulator::Platform { auto updateVideoShader() -> void; auto updateAudioDriver() -> void; auto updateAudioEffects() -> void; - auto allowInput(bool hotkey = false) -> bool; + auto focused() -> bool; bool hasQuit = false; bool pause = false; diff --git a/higan/target-tomoko/program/utility.cpp b/higan/target-tomoko/program/utility.cpp index a7e11ccc..9056be12 100644 --- a/higan/target-tomoko/program/utility.cpp +++ b/higan/target-tomoko/program/utility.cpp @@ -93,7 +93,7 @@ auto Program::updateAudioEffects() -> void { Emulator::audio.setReverb(reverbEnable); } -auto Program::allowInput(bool hotkey) -> bool { +auto Program::focused() -> bool { //exclusive mode creates its own top-level window: presentation window will not have focus if(video->cap(Video::Exclusive)) { auto value = video->get(Video::Exclusive); @@ -102,7 +102,5 @@ auto Program::allowInput(bool hotkey) -> bool { if(presentation && presentation->focused()) return true; - if(!hotkey && settings["Input/FocusLoss/AllowInput"].boolean()) return true; - return false; } diff --git a/higan/target-tomoko/settings/settings.cpp b/higan/target-tomoko/settings/settings.cpp index aef02e1c..698a1d18 100644 --- a/higan/target-tomoko/settings/settings.cpp +++ b/higan/target-tomoko/settings/settings.cpp @@ -15,6 +15,7 @@ SettingsManager::SettingsManager() { setTitle("Configuration Settings"); setSize({600, 405}); setAlignment({0.0, 1.0}); + setDismissable(); onSize([&] { input.mappingList.resizeColumns(); diff --git a/higan/target-tomoko/tools/cheat-database.cpp b/higan/target-tomoko/tools/cheat-database.cpp index 78fec79a..d219506c 100644 --- a/higan/target-tomoko/tools/cheat-database.cpp +++ b/higan/target-tomoko/tools/cheat-database.cpp @@ -12,6 +12,7 @@ CheatDatabase::CheatDatabase() { setSize({800, 400}); setAlignment({0.5, 1.0}); + setDismissable(); } auto CheatDatabase::findCodes() -> void { diff --git a/higan/target-tomoko/tools/tools.cpp b/higan/target-tomoko/tools/tools.cpp index 8b5b2276..cb07cf4c 100644 --- a/higan/target-tomoko/tools/tools.cpp +++ b/higan/target-tomoko/tools/tools.cpp @@ -14,6 +14,7 @@ ToolsManager::ToolsManager() { setTitle("Tools"); setSize({600, 405}); setAlignment({1.0, 1.0}); + setDismissable(); onSize([&] { cheatEditor.cheatList.resizeColumns(); diff --git a/hiro/cocoa/window.cpp b/hiro/cocoa/window.cpp index 6b4d4597..93fd41e8 100644 --- a/hiro/cocoa/window.cpp +++ b/hiro/cocoa/window.cpp @@ -243,6 +243,10 @@ auto pWindow::setBackgroundColor(Color color) -> void { } } +auto pWindow::setDismissable(bool dismissable) -> void { + //todo: not implemented +} + auto pWindow::setDroppable(bool droppable) -> void { @autoreleasepool { if(droppable) { @@ -404,15 +408,6 @@ auto pWindow::_geometry() -> Geometry { } } -/* -auto pWindow::remove(Widget& widget) -> void { - @autoreleasepool { - [widget.p.cocoaView removeFromSuperview]; - [[cocoaWindow contentView] setNeedsDisplay:YES]; - } -} -*/ - } #endif diff --git a/hiro/cocoa/window.hpp b/hiro/cocoa/window.hpp index ef178a6a..49dc140d 100644 --- a/hiro/cocoa/window.hpp +++ b/hiro/cocoa/window.hpp @@ -39,6 +39,7 @@ struct pWindow : pObject { auto remove(sMenuBar menuBar) -> void; auto remove(sStatusBar statusBar) -> void; auto setBackgroundColor(Color color) -> void; + auto setDismissable(bool dismissable) -> void; auto setDroppable(bool droppable) -> void; auto setFocused() -> void override; auto setFullScreen(bool fullScreen) -> void; diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 002fefbf..ae84e196 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -672,6 +672,7 @@ struct mWindow : mObject { auto append(sMenuBar menuBar) -> type&; auto append(sStatusBar statusBar) -> type&; auto backgroundColor() const -> Color; + auto dismissable() const -> bool; auto doClose() const -> void; auto doDrop(string_vector) const -> void; auto doKeyPress(signed) const -> void; @@ -699,6 +700,7 @@ struct mWindow : mObject { auto setAlignment(Alignment alignment) -> type&; auto setBackgroundColor(Color color = {}) -> type&; auto setCentered(sWindow parent = {}) -> type&; + auto setDismissable(bool dismissable = true) -> type&; auto setDroppable(bool droppable = true) -> type&; auto setFrameGeometry(Geometry geometry) -> type&; auto setFramePosition(Position position) -> type&; @@ -716,6 +718,7 @@ struct mWindow : mObject { //private: struct State { Color backgroundColor; + bool dismissable = false; bool droppable = false; bool fullScreen = false; Geometry geometry = {128, 128, 256, 256}; diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp index 6b4d28f8..2d3a398d 100644 --- a/hiro/core/shared.hpp +++ b/hiro/core/shared.hpp @@ -936,6 +936,7 @@ struct Window : sWindow { auto append(sMenuBar menuBar) { return self().append(menuBar), *this; } auto append(sStatusBar statusBar) { return self().append(statusBar), *this; } auto backgroundColor() const { return self().backgroundColor(); } + auto dismissable() const { return self().dismissable(); } auto doClose() const { return self().doClose(); } auto doDrop(string_vector names) const { return self().doDrop(names); } auto doKeyPress(signed key) const { return self().doKeyPress(key); } @@ -963,6 +964,7 @@ struct Window : sWindow { auto setAlignment(Alignment alignment) { return self().setAlignment(alignment), *this; } auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; } auto setCentered(sWindow parent = {}) { return self().setCentered(parent), *this; } + auto setDismissable(bool dismissable = true) { return self().setDismissable(dismissable), *this; } auto setDroppable(bool droppable = true) { return self().setDroppable(droppable), *this; } auto setFrameGeometry(Geometry geometry) { return self().setFrameGeometry(geometry), *this; } auto setFramePosition(Position position) { return self().setFramePosition(position), *this; } diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp index 5229ba86..874519c2 100644 --- a/hiro/core/window.cpp +++ b/hiro/core/window.cpp @@ -43,6 +43,10 @@ auto mWindow::backgroundColor() const -> Color { return state.backgroundColor; } +auto mWindow::dismissable() const -> bool { + return state.dismissable; +} + auto mWindow::doClose() const -> void { if(state.onClose) return state.onClose(); } @@ -188,6 +192,12 @@ auto mWindow::setCentered(sWindow parent) -> type& { return setFrameGeometry({x, y, geometry.width(), geometry.height()}); } +auto mWindow::setDismissable(bool dismissable) -> type& { + state.dismissable = dismissable; + signal(setDismissable, dismissable); + return *this; +} + auto mWindow::setDroppable(bool droppable) -> type& { state.droppable = droppable; signal(setDroppable, droppable); diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index 05e31dd7..d2d83def 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -153,6 +153,7 @@ auto BrowserDialogWindow::run() -> BrowserDialog::Response { window.setTitle(state.title); window.setSize({640, 480}); window.setCentered(state.parent); + window.setDismissable(); window.setVisible(); view.setFocused(); window.setModal(); diff --git a/hiro/extension/message-dialog.cpp b/hiro/extension/message-dialog.cpp index 6b5969e2..ce7a9835 100644 --- a/hiro/extension/message-dialog.cpp +++ b/hiro/extension/message-dialog.cpp @@ -71,6 +71,7 @@ auto MessageDialog::_run() -> string { window.setResizable(false); window.setSize({width, layout.minimumSize().height()}); window.setCentered(state.parent); + window.setDismissable(); window.setVisible(); window.setModal(); window.setVisible(false); diff --git a/hiro/gtk/window.cpp b/hiro/gtk/window.cpp index f4c7e050..3273fd11 100644 --- a/hiro/gtk/window.cpp +++ b/hiro/gtk/window.cpp @@ -89,6 +89,14 @@ static auto Window_keyPress(GtkWidget* widget, GdkEventKey* event, pWindow* p) - if(auto key = pKeyboard::_translate(event->keyval)) { p->self().doKeyPress(key); } + if(p->state().dismissable && event->keyval == GDK_Escape) { + if(p->state().onClose) { + p->self().doClose(); + } else { + p->self().setVisible(false); + } + if(p->state().modal && !p->pObject::state().visible) p->self().setModal(false); + } return false; } @@ -234,6 +242,9 @@ auto pWindow::setBackgroundColor(Color color) -> void { gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr); } +auto pWindow::setDismissable(bool dismissable) -> void { +} + auto pWindow::setDroppable(bool droppable) -> void { gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY); if(droppable) gtk_drag_dest_add_uri_targets(widget); diff --git a/hiro/gtk/window.hpp b/hiro/gtk/window.hpp index 132f294f..3b79e228 100644 --- a/hiro/gtk/window.hpp +++ b/hiro/gtk/window.hpp @@ -14,6 +14,7 @@ struct pWindow : pObject { auto remove(sMenuBar menuBar) -> void; auto remove(sStatusBar statusBar) -> void; auto setBackgroundColor(Color color) -> void; + auto setDismissable(bool dismissable) -> void; auto setDroppable(bool droppable) -> void; auto setEnabled(bool enabled) -> void override; auto setFocused() -> void override; diff --git a/hiro/qt/window.cpp b/hiro/qt/window.cpp index e28452d4..8e253391 100644 --- a/hiro/qt/window.cpp +++ b/hiro/qt/window.cpp @@ -100,6 +100,9 @@ auto pWindow::setBackgroundColor(Color color) -> void { } } +auto pWindow::setDismissable(bool dismissable) -> void { +} + auto pWindow::setDroppable(bool droppable) -> void { qtWindow->setAcceptDrops(droppable); } @@ -144,10 +147,6 @@ auto pWindow::setGeometry(Geometry geometry) -> void { qtContainer->setMinimumSize(1, 1); } -// for(auto& layout : window.state.layout) { -// geometry.x = geometry.y = 0; -// layout.setGeometry(geometry); -// } unlock(); } @@ -194,20 +193,6 @@ auto pWindow::setVisible(bool visible) -> void { unlock(); } -/* - if(!widget.font() && window.state.widgetFont) { - widget.setFont(window.state.widgetFont); - } - if(!widget.font()) widget.p.setFont(Font::sans(8)); - if(GetParentWidget(&widget)) { - widget.p.qtWidget->setParent(GetParentWidget(&widget)->p.container(widget)); - } else { - widget.p.qtWidget->setParent(qtContainer); - } - widget.setVisible(widget.visible()); -} -*/ - auto pWindow::_append(mWidget& widget) -> void { if(auto self = widget.self()) { self->qtWidget->setParent(qtContainer); @@ -274,13 +259,19 @@ auto QtWindow::dropEvent(QDropEvent* event) -> void { } auto QtWindow::keyPressEvent(QKeyEvent* event) -> void { -// Keyboard::Keycode sym = Keysym(event->nativeVirtualKey()); -// if(sym != Keyboard::Keycode::None && self.window.onKeyPress) self.window.onKeyPress(sym); +//Keyboard::Keycode sym = Keysym(event->nativeVirtualKey()); +//if(sym != Keyboard::Keycode::None && self.window.onKeyPress) self.window.onKeyPress(sym); + + if(p.state().dismissable && event->key() == Qt::Key_Escape) { + if(p.state().onClose) p.self().doClose(); + else p.self().setVisible(false); + if(p.state().modal && !p.self().visible()) p.self().setModal(false); + } } auto QtWindow::keyReleaseEvent(QKeyEvent* event) -> void { -// Keyboard::Keycode sym = Keysym(event->nativeVirtualKey()); -// if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym); +//Keyboard::Keycode sym = Keysym(event->nativeVirtualKey()); +//if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym); } auto QtWindow::resizeEvent(QResizeEvent*) -> void { diff --git a/hiro/qt/window.hpp b/hiro/qt/window.hpp index 0073689f..c9abee81 100644 --- a/hiro/qt/window.hpp +++ b/hiro/qt/window.hpp @@ -14,6 +14,7 @@ struct pWindow : pObject { auto remove(sMenuBar menuBar) -> void; auto remove(sStatusBar statusBar) -> void; auto setBackgroundColor(Color color) -> void; + auto setDismissable(bool dismissable) -> void; auto setDroppable(bool droppable) -> void; auto setEnabled(bool enabled) -> void override; auto setFocused() -> void override; diff --git a/hiro/windows/application.cpp b/hiro/windows/application.cpp index 9b80eba4..f4d12970 100644 --- a/hiro/windows/application.cpp +++ b/hiro/windows/application.cpp @@ -146,8 +146,15 @@ static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if(auto self = window->self()) { if(!self->_modalityDisabled()) { if(auto code = pKeyboard::_translate(wparam, lparam)) { - if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) window->doKeyPress(code); - if(msg == WM_KEYUP || msg == WM_SYSKEYUP) window->doKeyRelease(code); + if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) { + window->doKeyPress(code); + } + if(msg == WM_KEYUP || msg == WM_SYSKEYUP) { + window->doKeyRelease(code); + } + } + if(window->state.dismissable && msg == WM_KEYDOWN && wparam == VK_ESCAPE) { + self->onClose(); } } } diff --git a/hiro/windows/window.cpp b/hiro/windows/window.cpp index 98f88174..e0f28ebc 100644 --- a/hiro/windows/window.cpp +++ b/hiro/windows/window.cpp @@ -67,6 +67,9 @@ auto pWindow::setBackgroundColor(Color color) -> void { if(color) hbrush = CreateSolidBrush(hbrushColor); } +auto pWindow::setDismissable(bool dismissable) -> void { +} + auto pWindow::setDroppable(bool droppable) -> void { DragAcceptFiles(hwnd, droppable); } diff --git a/hiro/windows/window.hpp b/hiro/windows/window.hpp index e42397ad..9b130b23 100644 --- a/hiro/windows/window.hpp +++ b/hiro/windows/window.hpp @@ -14,6 +14,7 @@ struct pWindow : pObject { auto remove(sMenuBar menuBar) -> void; auto remove(sStatusBar statusBar) -> void; auto setBackgroundColor(Color color) -> void; + auto setDismissable(bool dismissable) -> void; auto setDroppable(bool droppable) -> void; auto setEnabled(bool enabled) -> void; auto setFocused() -> void; diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index fe45f1f0..7871cc44 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -94,14 +94,14 @@ auto slice(string_view self, int offset, int length) -> string { template auto fromInteger(char* result, T value) -> char* { bool negative = value < 0; - if(negative) value = -value; + if(!negative) value = -value; //negate positive integers to support eg INT_MIN char buffer[1 + sizeof(T) * 3]; uint size = 0; do { - uint n = value % 10; - buffer[size++] = '0' + n; + int n = value % 10; //-0 to -9 + buffer[size++] = '0' - n; //'0' to '9' value /= 10; } while(value); if(negative) buffer[size++] = '-';