diff --git a/higan/GNUmakefile b/higan/GNUmakefile index 7c082d6d..aa2e88e9 100644 --- a/higan/GNUmakefile +++ b/higan/GNUmakefile @@ -1,4 +1,4 @@ -build := release +build := optimize include ../nall/GNUmakefile target := tomoko diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 23d8304c..6ced2cc6 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 = "104.12"; + static const string Version = "104.13"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/hiro/cocoa/monitor.cpp b/hiro/cocoa/monitor.cpp index f6799db5..e230604b 100644 --- a/hiro/cocoa/monitor.cpp +++ b/hiro/cocoa/monitor.cpp @@ -8,6 +8,15 @@ auto pMonitor::count() -> uint { } } +auto pMonitor::dpi(uint monitor) -> Position { + @autoreleasepool { + NSScreen* screen = [[NSScreen screens] objectAtIndex:monitor]; + NSDistionary* dictionary = [screen deviceDescription]; + NSSize dpi = [[dictionary objectForKey:NSDeviceSize] sizeValue]; + return {dpi.width, dpi.height}; + } +} + auto pMonitor::geometry(uint monitor) -> Geometry { @autoreleasepool { NSRect rectangle = [[[NSScreen screens] objectAtIndex:monitor] frame]; diff --git a/hiro/cocoa/monitor.hpp b/hiro/cocoa/monitor.hpp index b41ab72a..70cf8a1d 100644 --- a/hiro/cocoa/monitor.hpp +++ b/hiro/cocoa/monitor.hpp @@ -4,6 +4,7 @@ namespace hiro { struct pMonitor { static auto count() -> uint; + static auto dpi(uint monitor) -> Position; static auto geometry(uint monitor) -> Geometry; static auto primary() -> uint; }; diff --git a/hiro/core/alignment.cpp b/hiro/core/alignment.cpp index 210a0aa6..bbc626d2 100644 --- a/hiro/core/alignment.cpp +++ b/hiro/core/alignment.cpp @@ -4,7 +4,7 @@ Alignment::Alignment() { setAlignment(-1.0, -1.0); } -Alignment::Alignment(double horizontal, double vertical) { +Alignment::Alignment(float horizontal, float vertical) { setAlignment(horizontal, vertical); } @@ -13,7 +13,7 @@ Alignment::operator bool() const { && state.vertical >= 0.0 && state.vertical <= 1.0; } -auto Alignment::horizontal() const -> double { +auto Alignment::horizontal() const -> float { return state.horizontal; } @@ -21,23 +21,23 @@ auto Alignment::reset() -> type& { return setAlignment(-1.0, -1.0); } -auto Alignment::setAlignment(double horizontal, double vertical) -> type& { +auto Alignment::setAlignment(float horizontal, float vertical) -> type& { state.horizontal = horizontal; state.vertical = vertical; return *this; } -auto Alignment::setHorizontal(double horizontal) -> type& { +auto Alignment::setHorizontal(float horizontal) -> type& { state.horizontal = horizontal; return *this; } -auto Alignment::setVertical(double vertical) -> type& { +auto Alignment::setVertical(float vertical) -> type& { state.vertical = vertical; return *this; } -auto Alignment::vertical() const -> double { +auto Alignment::vertical() const -> float { return state.vertical; } diff --git a/hiro/core/application.cpp b/hiro/core/application.cpp index 949f5d3f..a8f02b68 100644 --- a/hiro/core/application.cpp +++ b/hiro/core/application.cpp @@ -35,6 +35,14 @@ auto Application::quit() -> void { return pApplication::quit(); } +auto Application::scale() -> float { + return state.scale; +} + +auto Application::scale(float value) -> float { + return value * state.scale; +} + auto Application::setFont(const Font& font) -> void { state.font = font; } @@ -43,6 +51,10 @@ auto Application::setName(const string& name) -> void { state.name = name; } +auto Application::setScale(float scale) -> void { + state.scale = scale; +} + //Windows //======= diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index ae84e196..c8a5e635 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -90,8 +90,8 @@ Declare(Viewport) #undef Declare -enum class Orientation : unsigned { Horizontal, Vertical }; -enum class Navigation : unsigned { Top, Bottom, Left, Right }; +enum class Orientation : uint { Horizontal, Vertical }; +enum class Navigation : uint { Top, Bottom, Left, Right }; #if defined(Hiro_Color) struct Color { @@ -153,18 +153,18 @@ struct Alignment { using type = Alignment; Alignment(); - Alignment(double horizontal, double vertical = 0.5); + Alignment(float horizontal, float vertical = 0.5); explicit operator bool() const; auto operator==(const Alignment& source) const -> bool; auto operator!=(const Alignment& source) const -> bool; - auto horizontal() const -> double; + auto horizontal() const -> float; auto reset() -> type&; - auto setAlignment(double horizontal = -1.0, double vertical = 0.5) -> type&; - auto setHorizontal(double horizontal) -> type&; - auto setVertical(double vertical) -> type&; - auto vertical() const -> double; + auto setAlignment(float horizontal = -1.0, float vertical = 0.5) -> type&; + auto setHorizontal(float horizontal) -> type&; + auto setVertical(float vertical) -> type&; + auto vertical() const -> float; //private: struct State { @@ -203,9 +203,9 @@ struct Position { using type = Position; Position(); - Position(signed x, signed y); + Position(float x, float y); template - Position(X x, Y y) : Position((signed)x, (signed)y) {} + Position(X x, Y y) : Position((float)x, (float)y) {} explicit operator bool() const; auto operator==(const Position& source) const -> bool; @@ -213,16 +213,16 @@ struct Position { auto reset() -> type&; auto setPosition(Position position = {}) -> type&; - auto setPosition(signed x, signed y) -> type&; - auto setX(signed x) -> type&; - auto setY(signed y) -> type&; - auto x() const -> signed; - auto y() const -> signed; + auto setPosition(float x, float y) -> type&; + auto setX(float x) -> type&; + auto setY(float y) -> type&; + auto x() const -> float; + auto y() const -> float; //private: struct State { - signed x; - signed y; + float x; + float y; } state; }; #endif @@ -232,29 +232,29 @@ struct Size { using type = Size; Size(); - Size(signed width, signed height); + Size(float width, float height); template - Size(W width, H height) : Size((signed)width, (signed)height) {} + Size(W width, H height) : Size((float)width, (float)height) {} explicit operator bool() const; auto operator==(const Size& source) const -> bool; auto operator!=(const Size& source) const -> bool; - auto height() const -> signed; + auto height() const -> float; auto reset() -> type&; - auto setHeight(signed height) -> type&; + auto setHeight(float height) -> type&; auto setSize(Size source = {}) -> type&; - auto setSize(signed width, signed height) -> type&; - auto setWidth(signed width) -> type&; - auto width() const -> signed; + auto setSize(float width, float height) -> type&; + auto setWidth(float width) -> type&; + auto width() const -> float; - static const signed Maximum = ~0; //~0 == -1 - static const signed Minimum = 0; + static constexpr float Maximum = -1.0; + static constexpr float Minimum = +0.0; //private: struct State { - signed width; - signed height; + float width; + float height; } state; }; #endif @@ -265,39 +265,39 @@ struct Geometry { Geometry(); Geometry(Position position, Size size); - Geometry(signed x, signed y, signed width, signed height); + Geometry(float x, float y, float width, float height); template - Geometry(X x, Y y, W width, H height) : Geometry((signed)x, (signed)y, (signed)width, (signed)height) {} + Geometry(X x, Y y, W width, H height) : Geometry((float)x, (float)y, (float)width, (float)height) {} explicit operator bool() const; auto operator==(const Geometry& source) const -> bool; auto operator!=(const Geometry& source) const -> bool; - auto height() const -> signed; + auto height() const -> float; auto position() const -> Position; auto reset() -> type&; auto setGeometry(Geometry geometry = {}) -> type&; auto setGeometry(Position position, Size size) -> type&; - auto setGeometry(signed x, signed y, signed width, signed height) -> type&; - auto setHeight(signed height) -> type&; + auto setGeometry(float x, float y, float width, float height) -> type&; + auto setHeight(float height) -> type&; auto setPosition(Position position = {}) -> type&; - auto setPosition(signed x, signed y) -> type&; + auto setPosition(float x, float y) -> type&; auto setSize(Size size = {}) -> type&; - auto setSize(signed width, signed height) -> type&; - auto setWidth(signed width) -> type&; - auto setX(signed x) -> type&; - auto setY(signed y) -> type&; + auto setSize(float width, float height) -> type&; + auto setWidth(float width) -> type&; + auto setX(float x) -> type&; + auto setY(float y) -> type&; auto size() const -> Size; - auto width() const -> signed; - auto x() const -> signed; - auto y() const -> signed; + auto width() const -> float; + auto x() const -> float; + auto y() const -> float; //private: struct State { - signed x; - signed y; - signed width; - signed height; + float x; + float y; + float width; + float height; } state; }; #endif @@ -306,7 +306,7 @@ struct Geometry { struct Font { using type = Font; - Font(const string& family = "", unsigned size = 0); + Font(const string& family = "", float size = 0); explicit operator bool() const; auto operator==(const Font& source) const -> bool; @@ -319,8 +319,8 @@ struct Font { auto setBold(bool bold = true) -> type&; auto setFamily(const string& family = "") -> type&; auto setItalic(bool italic = true) -> type&; - auto setSize(unsigned size = 0) -> type&; - auto size() const -> unsigned; + auto setSize(float size = 0) -> type&; + auto size() const -> float; auto size(const string& text) const -> Size; static const string Sans; @@ -330,7 +330,7 @@ struct Font { //private: struct State { string family; - unsigned size; + float size; bool bold; bool italic; } state; @@ -377,11 +377,14 @@ struct Application { static auto name() -> string; static auto onMain(const function& callback = {}) -> void; static auto run() -> void; + static auto scale() -> float; + static auto scale(float value) -> float; static auto pendingEvents() -> bool; static auto processEvents() -> void; static auto quit() -> void; static auto setFont(const Font& font = {}) -> void; static auto setName(const string& name = "") -> void; + static auto setScale(float scale = 1.0) -> void; struct Windows { static auto doModalChange(bool modal) -> void; @@ -405,6 +408,7 @@ struct Application { string name; function onMain; bool quit = false; + float scale = 1.0; struct Windows { function onModalChange; @@ -435,9 +439,10 @@ struct Desktop { struct Monitor { Monitor() = delete; - static auto count() -> unsigned; - static auto geometry(unsigned monitor) -> Geometry; - static auto primary() -> unsigned; + static auto count() -> uint; + static auto dpi(uint monitor) -> Position; + static auto geometry(uint monitor) -> Geometry; + static auto primary() -> uint; }; #endif @@ -1680,7 +1685,7 @@ struct mTableViewColumn : mObject { auto editable() const -> bool; auto expandable() const -> bool; auto foregroundColor() const -> Color; - auto horizontalAlignment() const -> double; + auto horizontalAlignment() const -> float; auto icon() const -> image; auto remove() -> type& override; auto resizable() const -> bool; @@ -1690,18 +1695,18 @@ struct mTableViewColumn : mObject { auto setEditable(bool editable = true) -> type&; auto setExpandable(bool expandable = true) -> type&; auto setForegroundColor(Color color = {}) -> type&; - auto setHorizontalAlignment(double alignment = 0.0) -> type&; + auto setHorizontalAlignment(float alignment = 0.0) -> type&; auto setIcon(const image& icon = {}) -> type&; auto setResizable(bool resizable = true) -> type&; auto setSortable(bool sortable = true) -> type&; auto setText(const string& text = "") -> type&; - auto setVerticalAlignment(double alignment = 0.5) -> type&; + auto setVerticalAlignment(float alignment = 0.5) -> type&; auto setVisible(bool visible = true) -> type&; - auto setWidth(signed width = 0) -> type&; + auto setWidth(float width = 0) -> type&; auto sortable() const -> bool; auto text() const -> string; - auto verticalAlignment() const -> double; - auto width() const -> signed; + auto verticalAlignment() const -> float; + auto width() const -> float; //private: struct State { @@ -1710,14 +1715,14 @@ struct mTableViewColumn : mObject { bool editable = false; bool expandable = false; Color foregroundColor; - double horizontalAlignment = 0.0; + float horizontalAlignment = 0.0; image icon; bool resizable = true; bool sortable = false; string text; - double verticalAlignment = 0.5; + float verticalAlignment = 0.5; bool visible = true; - signed width = 0; + float width = 0; } state; }; #endif diff --git a/hiro/core/font.cpp b/hiro/core/font.cpp index d082c9c1..d17e007b 100644 --- a/hiro/core/font.cpp +++ b/hiro/core/font.cpp @@ -4,7 +4,7 @@ const string Font::Sans = "{sans}"; const string Font::Serif = "{serif}"; const string Font::Mono = "{mono}"; -Font::Font(const string& family, unsigned size) { +Font::Font(const string& family, float size) { setFamily(family); setSize(size); state.bold = false; @@ -58,12 +58,12 @@ auto Font::setItalic(bool italic) -> type& { return *this; } -auto Font::setSize(unsigned size) -> type& { +auto Font::setSize(float size) -> type& { state.size = size; return *this; } -auto Font::size() const -> unsigned { +auto Font::size() const -> float { return state.size; } diff --git a/hiro/core/geometry.cpp b/hiro/core/geometry.cpp index fe901414..b5a2242f 100644 --- a/hiro/core/geometry.cpp +++ b/hiro/core/geometry.cpp @@ -8,7 +8,7 @@ Geometry::Geometry(Position position, Size size) { setGeometry(position, size); } -Geometry::Geometry(signed x, signed y, signed width, signed height) { +Geometry::Geometry(float x, float y, float width, float height) { setGeometry(x, y, width, height); } @@ -24,7 +24,7 @@ auto Geometry::operator!=(const Geometry& source) const -> bool { return !operator==(source); } -auto Geometry::height() const -> signed { +auto Geometry::height() const -> float { return state.height; } @@ -36,7 +36,7 @@ auto Geometry::reset() -> type& { return setGeometry(0, 0, 0, 0); } -auto Geometry::setHeight(signed height) -> type& { +auto Geometry::setHeight(float height) -> type& { state.height = height; return *this; } @@ -50,7 +50,7 @@ auto Geometry::setGeometry(Position position, Size size) -> type& { return *this; } -auto Geometry::setGeometry(signed x, signed y, signed width, signed height) -> type& { +auto Geometry::setGeometry(float x, float y, float width, float height) -> type& { state.x = x; state.y = y; state.width = width; @@ -62,7 +62,7 @@ auto Geometry::setPosition(Position position) -> type& { return setPosition(position.x(), position.y()); } -auto Geometry::setPosition(signed x, signed y) -> type& { +auto Geometry::setPosition(float x, float y) -> type& { state.x = x; state.y = y; return *this; @@ -72,23 +72,23 @@ auto Geometry::setSize(Size size) -> type& { return setSize(size.width(), size.height()); } -auto Geometry::setSize(signed width, signed height) -> type& { +auto Geometry::setSize(float width, float height) -> type& { state.width = width; state.height = height; return *this; } -auto Geometry::setWidth(signed width) -> type& { +auto Geometry::setWidth(float width) -> type& { state.width = width; return *this; } -auto Geometry::setX(signed x) -> type& { +auto Geometry::setX(float x) -> type& { state.x = x; return *this; } -auto Geometry::setY(signed y) -> type& { +auto Geometry::setY(float y) -> type& { state.y = y; return *this; } @@ -97,15 +97,15 @@ auto Geometry::size() const -> Size { return {state.width, state.height}; } -auto Geometry::width() const -> signed { +auto Geometry::width() const -> float { return state.width; } -auto Geometry::x() const -> signed { +auto Geometry::x() const -> float { return state.x; } -auto Geometry::y() const -> signed { +auto Geometry::y() const -> float { return state.y; } diff --git a/hiro/core/monitor.cpp b/hiro/core/monitor.cpp index e4f07694..a8058c72 100644 --- a/hiro/core/monitor.cpp +++ b/hiro/core/monitor.cpp @@ -1,14 +1,18 @@ #if defined(Hiro_Monitor) -auto Monitor::count() -> unsigned { +auto Monitor::count() -> uint { return pMonitor::count(); } -auto Monitor::geometry(unsigned monitor) -> Geometry { +auto Monitor::dpi(uint monitor) -> Position { + return pMonitor::dpi(monitor); +} + +auto Monitor::geometry(uint monitor) -> Geometry { return pMonitor::geometry(monitor); } -auto Monitor::primary() -> unsigned { +auto Monitor::primary() -> uint { return pMonitor::primary(); } diff --git a/hiro/core/position.cpp b/hiro/core/position.cpp index 0bab72ed..79c45657 100644 --- a/hiro/core/position.cpp +++ b/hiro/core/position.cpp @@ -4,7 +4,7 @@ Position::Position() { setPosition(0, 0); } -Position::Position(signed x, signed y) { +Position::Position(float x, float y) { setPosition(x, y); } @@ -28,27 +28,27 @@ auto Position::setPosition(Position position) -> type& { return setPosition(position.x(), position.y()); } -auto Position::setPosition(signed x, signed y) -> type& { +auto Position::setPosition(float x, float y) -> type& { state.x = x; state.y = y; return *this; } -auto Position::setX(signed x) -> type& { +auto Position::setX(float x) -> type& { state.x = x; return *this; } -auto Position::setY(signed y) -> type& { +auto Position::setY(float y) -> type& { state.y = y; return *this; } -auto Position::x() const -> signed { +auto Position::x() const -> float { return state.x; } -auto Position::y() const -> signed { +auto Position::y() const -> float { return state.y; } diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp index 2d3a398d..2dcec6f1 100644 --- a/hiro/core/shared.hpp +++ b/hiro/core/shared.hpp @@ -648,11 +648,13 @@ struct TableViewColumn : sTableViewColumn { auto setEditable(bool editable = true) { return self().setEditable(editable), *this; } auto setExpandable(bool expandable = true) { return self().setExpandable(expandable), *this; } auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; } + auto setHorizontalAlignment(float alignment = 0.0) { return self().setHorizontalAlignment(alignment), *this; } auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; } auto setResizable(bool resizable = true) { return self().setResizable(resizable), *this; } auto setSortable(bool sortable = true) { return self().setSortable(sortable), *this; } auto setText(const string& text = "") { return self().setText(text), *this; } - auto setWidth(signed width = 0) { return self().setWidth(width), *this; } + auto setVerticalAlignment(float alignment = 0.5) { return self().setVerticalAlignment(alignment), *this; } + auto setWidth(float width = 0) { return self().setWidth(width), *this; } auto sortable() const { return self().sortable(); } auto text() const { return self().text(); } auto verticalAlignment() const { return self().verticalAlignment(); } diff --git a/hiro/core/size.cpp b/hiro/core/size.cpp index 26cd3168..86818d30 100644 --- a/hiro/core/size.cpp +++ b/hiro/core/size.cpp @@ -4,7 +4,7 @@ Size::Size() { setSize(0, 0); } -Size::Size(signed width, signed height) { +Size::Size(float width, float height) { setSize(width, height); } @@ -20,7 +20,7 @@ auto Size::operator!=(const Size& source) const -> bool { return !operator==(source); } -auto Size::height() const -> signed { +auto Size::height() const -> float { return state.height; } @@ -28,7 +28,7 @@ auto Size::reset() -> type& { return setSize(0, 0); } -auto Size::setHeight(signed height) -> type& { +auto Size::setHeight(float height) -> type& { state.height = height; return *this; } @@ -37,18 +37,18 @@ auto Size::setSize(Size size) -> type& { return setSize(size.width(), size.height()); } -auto Size::setSize(signed width, signed height) -> type& { +auto Size::setSize(float width, float height) -> type& { state.width = width; state.height = height; return *this; } -auto Size::setWidth(signed width) -> type& { +auto Size::setWidth(float width) -> type& { state.width = width; return *this; } -auto Size::width() const -> signed { +auto Size::width() const -> float { return state.width; } diff --git a/hiro/core/widget/table-view-column.cpp b/hiro/core/widget/table-view-column.cpp index cee2f8ad..f3f81966 100644 --- a/hiro/core/widget/table-view-column.cpp +++ b/hiro/core/widget/table-view-column.cpp @@ -31,7 +31,7 @@ auto mTableViewColumn::foregroundColor() const -> Color { return state.foregroundColor; } -auto mTableViewColumn::horizontalAlignment() const -> double { +auto mTableViewColumn::horizontalAlignment() const -> float { return state.horizontalAlignment; } @@ -84,7 +84,7 @@ auto mTableViewColumn::setForegroundColor(Color color) -> type& { return *this; } -auto mTableViewColumn::setHorizontalAlignment(double alignment) -> type& { +auto mTableViewColumn::setHorizontalAlignment(float alignment) -> type& { alignment = max(0.0, min(1.0, alignment)); state.horizontalAlignment = alignment; signal(setHorizontalAlignment, alignment); @@ -115,7 +115,7 @@ auto mTableViewColumn::setText(const string& text) -> type& { return *this; } -auto mTableViewColumn::setVerticalAlignment(double alignment) -> type& { +auto mTableViewColumn::setVerticalAlignment(float alignment) -> type& { alignment = max(0.0, min(1.0, alignment)); state.verticalAlignment = alignment; signal(setVerticalAlignment, alignment); @@ -128,7 +128,7 @@ auto mTableViewColumn::setVisible(bool visible) -> type& { return *this; } -auto mTableViewColumn::setWidth(signed width) -> type& { +auto mTableViewColumn::setWidth(float width) -> type& { state.width = max(0, width); signal(setWidth, width); return *this; @@ -142,11 +142,11 @@ auto mTableViewColumn::text() const -> string { return state.text; } -auto mTableViewColumn::verticalAlignment() const -> double { +auto mTableViewColumn::verticalAlignment() const -> float { return state.verticalAlignment; } -auto mTableViewColumn::width() const -> signed { +auto mTableViewColumn::width() const -> float { return state.width; } diff --git a/hiro/extension/fixed-layout.cpp b/hiro/extension/fixed-layout.cpp index 8fe302f9..e2be026e 100644 --- a/hiro/extension/fixed-layout.cpp +++ b/hiro/extension/fixed-layout.cpp @@ -16,7 +16,7 @@ auto mFixedLayout::modify(sSizable sizable, Geometry geometry) -> type& { } auto mFixedLayout::minimumSize() const -> Size { - signed width = Size::Minimum, height = Size::Minimum; + float width = Size::Minimum, height = Size::Minimum; for(auto n : range(sizableCount())) { width = max(width, sizable(n)->minimumSize().width()); height = max(height, sizable(n)->minimumSize().height()); diff --git a/hiro/extension/fixed-layout.hpp b/hiro/extension/fixed-layout.hpp index bcfb2e6c..dbcf350f 100644 --- a/hiro/extension/fixed-layout.hpp +++ b/hiro/extension/fixed-layout.hpp @@ -14,10 +14,10 @@ struct mFixedLayout : mLayout { auto setFont(const Font& font = {}) -> type& override; auto setVisible(bool visible = true) ->type& override; - struct Properties { + struct Property { Geometry geometry; }; - vector properties; + vector properties; }; #endif diff --git a/hiro/extension/horizontal-layout.cpp b/hiro/extension/horizontal-layout.cpp index c17f8429..8b82e5af 100644 --- a/hiro/extension/horizontal-layout.cpp +++ b/hiro/extension/horizontal-layout.cpp @@ -1,41 +1,41 @@ #if defined(Hiro_HorizontalLayout) -auto mHorizontalLayout::append(sSizable sizable, Size size, signed spacing) -> type& { +auto mHorizontalLayout::append(sSizable sizable, Size size, float spacing) -> type& { properties.append({size.width(), size.height(), spacing < 0 ? settings.spacing : spacing}); mLayout::append(sizable); return *this; } -auto mHorizontalLayout::modify(sSizable sizable, Size size, signed spacing) -> type& { +auto mHorizontalLayout::modify(sSizable sizable, Size size, float spacing) -> type& { if(sizable && this->sizable(sizable->offset()) == sizable) { auto& properties = this->properties[sizable->offset()]; - properties.width = size.width(); - properties.height = size.height(); - properties.spacing = spacing; + properties.setWidth(size.width()); + properties.setHeight(size.height()); + properties.setSpacing(spacing); } return *this; } auto mHorizontalLayout::minimumSize() const -> Size { - signed width = 0, height = 0; + float width = 0, height = 0; for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.width == Size::Minimum || child.width == Size::Maximum) { + if(child.width() == Size::Minimum || child.width() == Size::Maximum) { width += sizable(n)->minimumSize().width(); } else { - width += child.width; + width += child.width(); } - if(&child != &properties.right()) width += child.spacing; + if(&child != &properties.right()) width += child.spacing(); } for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.height == Size::Minimum || child.height == Size::Maximum) { + if(child.height() == Size::Minimum || child.height() == Size::Maximum) { height = max(height, sizable(n)->minimumSize().height()); continue; } - height = max(height, child.height); + height = max(height, child.height()); } return {settings.margin * 2 + width, settings.margin * 2 + height}; @@ -53,7 +53,7 @@ auto mHorizontalLayout::reset() -> type& { return *this; } -auto mHorizontalLayout::setAlignment(double alignment) -> type& { +auto mHorizontalLayout::setAlignment(float alignment) -> type& { settings.alignment = max(0.0, min(1.0, alignment)); return *this; } @@ -80,8 +80,8 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& { auto properties = this->properties; for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width(); - if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height(); + if(child.width() == Size::Minimum) child.setWidth(sizable(n)->minimumSize().width()); + if(child.height() == Size::Minimum) child.setHeight(sizable(n)->minimumSize().height()); } Geometry geometry = containerGeometry; @@ -90,42 +90,42 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& { geometry.setWidth (geometry.width() - settings.margin * 2); geometry.setHeight(geometry.height() - settings.margin * 2); - signed minimumWidth = 0, maximumWidthCounter = 0; + float minimumWidth = 0, maximumWidthCounter = 0; for(auto& child : properties) { - if(child.width == Size::Maximum) maximumWidthCounter++; - if(child.width != Size::Maximum) minimumWidth += child.width; - if(&child != &properties.right()) minimumWidth += child.spacing; + if(child.width() == Size::Maximum) maximumWidthCounter++; + if(child.width() != Size::Maximum) minimumWidth += child.width(); + if(&child != &properties.right()) minimumWidth += child.spacing(); } for(auto& child : properties) { - if(child.width == Size::Maximum) child.width = (geometry.width() - minimumWidth) / maximumWidthCounter; - if(child.height == Size::Maximum) child.height = geometry.height(); + if(child.width() == Size::Maximum) child.setWidth((geometry.width() - minimumWidth) / maximumWidthCounter); + if(child.height() == Size::Maximum) child.setHeight(geometry.height()); } - signed maximumHeight = 0; - for(auto& child : properties) maximumHeight = max(maximumHeight, child.height); + float maximumHeight = 0; + for(auto& child : properties) maximumHeight = max(maximumHeight, child.height()); for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - signed pivot = (maximumHeight - child.height) * settings.alignment; - Geometry childGeometry = {geometry.x(), geometry.y() + pivot, child.width, child.height}; + float pivot = (maximumHeight - child.height()) * settings.alignment; + Geometry childGeometry = {geometry.x(), geometry.y() + pivot, child.width(), child.height()}; if(childGeometry.width() < 1) childGeometry.setWidth (1); if(childGeometry.height() < 1) childGeometry.setHeight(1); sizable(n)->setGeometry(childGeometry); - geometry.setX (geometry.x() + child.width + child.spacing); - geometry.setWidth(geometry.width() - child.width + child.spacing); + geometry.setX (geometry.x() + child.width() + child.spacing()); + geometry.setWidth(geometry.width() - child.width() + child.spacing()); } return *this; } -auto mHorizontalLayout::setMargin(signed margin) -> type& { +auto mHorizontalLayout::setMargin(float margin) -> type& { settings.margin = margin; return *this; } -auto mHorizontalLayout::setSpacing(signed spacing) -> type& { +auto mHorizontalLayout::setSpacing(float spacing) -> type& { settings.spacing = spacing; return *this; } diff --git a/hiro/extension/horizontal-layout.hpp b/hiro/extension/horizontal-layout.hpp index 13a4d95a..e44ad219 100644 --- a/hiro/extension/horizontal-layout.hpp +++ b/hiro/extension/horizontal-layout.hpp @@ -5,29 +5,31 @@ struct mHorizontalLayout : mLayout { using mLayout::append; using mLayout::remove; - auto append(sSizable sizable, Size size, signed spacing = 5) -> type&; + auto append(sSizable sizable, Size size, float spacing = 5) -> type&; auto minimumSize() const -> Size override; - auto modify(sSizable sizable, Size size, signed spacing = 5) -> type&; + auto modify(sSizable sizable, Size size, float spacing = 5) -> type&; auto remove(sSizable sizable) -> type& override; auto reset() -> type& override; - auto setAlignment(double alignment = 0.5) -> type&; + auto setAlignment(float alignment = 0.5) -> type&; auto setEnabled(bool enabled = true) -> type& override; auto setFont(const Font& font = {}) -> type& override; auto setGeometry(Geometry geometry) -> type& override; - auto setMargin(signed margin = 0) -> type&; - auto setSpacing(signed spacing = 5) -> type&; + auto setMargin(float margin = 0) -> type&; + auto setSpacing(float spacing = 5) -> type&; auto setVisible(bool visible = true) -> type&; struct Settings { - double alignment = 0.5; - signed margin = 0; - signed spacing = 5; + float alignment = 0.5; + float margin = 0; + float spacing = 5; } settings; - struct Property { - signed width; - signed height; - signed spacing; + struct Property : Size { + Property() = default; + Property(float width, float height, float spacing) : Size(width, height), _spacing(spacing) {} + auto setSpacing(float spacing) -> Property& { return _spacing = spacing, *this; } + auto spacing() const -> float { return _spacing; } + float _spacing = 0; }; vector properties; }; diff --git a/hiro/extension/vertical-layout.cpp b/hiro/extension/vertical-layout.cpp index 601fe582..cc2de580 100644 --- a/hiro/extension/vertical-layout.cpp +++ b/hiro/extension/vertical-layout.cpp @@ -1,41 +1,41 @@ #if defined(Hiro_VerticalLayout) -auto mVerticalLayout::append(sSizable sizable, Size size, signed spacing) -> type& { +auto mVerticalLayout::append(sSizable sizable, Size size, float spacing) -> type& { properties.append({size.width(), size.height(), spacing < 0 ? settings.spacing : spacing}); mLayout::append(sizable); return *this; } -auto mVerticalLayout::modify(sSizable sizable, Size size, signed spacing) -> type& { +auto mVerticalLayout::modify(sSizable sizable, Size size, float spacing) -> type& { if(sizable && this->sizable(sizable->offset()) == sizable) { auto& properties = this->properties[sizable->offset()]; - properties.width = size.width(); - properties.height = size.height(); - properties.spacing = spacing; + properties.setWidth(size.width()); + properties.setHeight(size.height()); + properties.setSpacing(spacing); } return *this; } auto mVerticalLayout::minimumSize() const -> Size { - signed width = 0, height = 0; + float width = 0, height = 0; for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.width == Size::Minimum || child.width == Size::Maximum) { + if(child.width() == Size::Minimum || child.width() == Size::Maximum) { width = max(width, sizable(n)->minimumSize().width()); continue; } - width = max(width, child.width); + width = max(width, child.width()); } for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.height == Size::Minimum || child.height == Size::Maximum) { + if(child.height() == Size::Minimum || child.height() == Size::Maximum) { height += sizable(n)->minimumSize().height(); } else { - height += child.height; + height += child.height(); } - if(&child != &properties.right()) height += child.spacing; + if(&child != &properties.right()) height += child.spacing(); } return {settings.margin * 2 + width, settings.margin * 2 + height}; @@ -53,7 +53,7 @@ auto mVerticalLayout::reset() -> type& { return *this; } -auto mVerticalLayout::setAlignment(double alignment) -> type& { +auto mVerticalLayout::setAlignment(float alignment) -> type& { settings.alignment = max(0.0, min(1.0, alignment)); return *this; } @@ -80,8 +80,8 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& { auto properties = this->properties; for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width(); - if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height(); + if(child.width() == Size::Minimum) child.setWidth(sizable(n)->minimumSize().width()); + if(child.height() == Size::Minimum) child.setHeight(sizable(n)->minimumSize().height()); } Geometry geometry = containerGeometry; @@ -90,42 +90,42 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& { geometry.setWidth (geometry.width() - settings.margin * 2); geometry.setHeight(geometry.height() - settings.margin * 2); - signed minimumHeight = 0, maximumHeightCounter = 0; + float minimumHeight = 0, maximumHeightCounter = 0; for(auto& child : properties) { - if(child.height == Size::Maximum) maximumHeightCounter++; - if(child.height != Size::Maximum) minimumHeight += child.height; - if(&child != &properties.right()) minimumHeight += child.spacing; + if(child.height() == Size::Maximum) maximumHeightCounter++; + if(child.height() != Size::Maximum) minimumHeight += child.height(); + if(&child != &properties.right()) minimumHeight += child.spacing(); } for(auto& child : properties) { - if(child.width == Size::Maximum) child.width = geometry.width(); - if(child.height == Size::Maximum) child.height = (geometry.height() - minimumHeight) / maximumHeightCounter; + if(child.width() == Size::Maximum) child.setWidth(geometry.width()); + if(child.height() == Size::Maximum) child.setHeight((geometry.height() - minimumHeight) / maximumHeightCounter); } - signed maximumWidth = 0; - for(auto& child : properties) maximumWidth = max(maximumWidth, child.width); + float maximumWidth = 0; + for(auto& child : properties) maximumWidth = max(maximumWidth, child.width()); for(auto n : range(sizableCount())) { auto& child = properties[sizable(n)->offset()]; - signed pivot = (maximumWidth - child.width) * settings.alignment; - Geometry childGeometry = {geometry.x() + pivot, geometry.y(), child.width, child.height}; + float pivot = (maximumWidth - child.width()) * settings.alignment; + Geometry childGeometry = {geometry.x() + pivot, geometry.y(), child.width(), child.height()}; if(childGeometry.width() < 1) childGeometry.setWidth (1); if(childGeometry.height() < 1) childGeometry.setHeight(1); sizable(n)->setGeometry(childGeometry); - geometry.setY (geometry.y() + child.height + child.spacing); - geometry.setHeight(geometry.height() - child.height + child.spacing); + geometry.setY (geometry.y() + child.height() + child.spacing()); + geometry.setHeight(geometry.height() - child.height() + child.spacing()); } return *this; } -auto mVerticalLayout::setMargin(signed margin) -> type& { +auto mVerticalLayout::setMargin(float margin) -> type& { settings.margin = margin; return *this; } -auto mVerticalLayout::setSpacing(signed spacing) -> type& { +auto mVerticalLayout::setSpacing(float spacing) -> type& { settings.spacing = spacing; return *this; } diff --git a/hiro/extension/vertical-layout.hpp b/hiro/extension/vertical-layout.hpp index c208fc23..870a5a51 100644 --- a/hiro/extension/vertical-layout.hpp +++ b/hiro/extension/vertical-layout.hpp @@ -5,31 +5,33 @@ struct mVerticalLayout : mLayout { using mLayout::append; using mLayout::remove; - auto append(sSizable sizable, Size size, signed spacing = 5) -> type&; - auto modify(sSizable sizable, Size size, signed spacing = 5) -> type&; + auto append(sSizable sizable, Size size, float spacing = 5) -> type&; + auto modify(sSizable sizable, Size size, float spacing = 5) -> type&; auto minimumSize() const -> Size override; auto remove(sSizable sizable) -> type& override; auto reset() -> type& override; - auto setAlignment(double alignment = 0.0) -> type&; + auto setAlignment(float alignment = 0.0) -> type&; auto setEnabled(bool enabled = true) -> type& override; auto setFont(const Font& font = {}) -> type& override; auto setGeometry(Geometry geometry) -> type& override; - auto setMargin(signed margin = 0) -> type&; - auto setSpacing(signed spacing = 5) -> type&; + auto setMargin(float margin = 0) -> type&; + auto setSpacing(float spacing = 5) -> type&; auto setVisible(bool visible = true) -> type& override; struct Settings { - double alignment = 0.0; - signed margin = 0; - signed spacing = 5; + float alignment = 0.0; + float margin = 0; + float spacing = 5; } settings; - struct Properties { - signed width; - signed height; - signed spacing; + struct Property : Size { + Property() = default; + Property(float width, float height, float spacing) : Size(width, height), _spacing(spacing) {} + auto setSpacing(float spacing) -> Property& { return _spacing = spacing, *this; } + auto spacing() const -> float { return _spacing; } + float _spacing = 0; }; - vector properties; + vector properties; }; #endif diff --git a/hiro/gtk/monitor.cpp b/hiro/gtk/monitor.cpp index 498ea8b6..8e75c2b9 100644 --- a/hiro/gtk/monitor.cpp +++ b/hiro/gtk/monitor.cpp @@ -6,6 +6,12 @@ auto pMonitor::count() -> uint { return gdk_screen_get_n_monitors(gdk_screen_get_default()); } +auto pMonitor::dpi(uint monitor) -> Position { + //GTK+ does not support either per-monitor or per-axis DPI reporting + float dpi = round(gdk_screen_get_resolution(gdk_screen_get_default())); + return {dpi, dpi}; +} + auto pMonitor::geometry(uint monitor) -> Geometry { GdkRectangle rectangle = {0}; gdk_screen_get_monitor_geometry(gdk_screen_get_default(), monitor, &rectangle); diff --git a/hiro/gtk/monitor.hpp b/hiro/gtk/monitor.hpp index 53df3c93..70cf8a1d 100644 --- a/hiro/gtk/monitor.hpp +++ b/hiro/gtk/monitor.hpp @@ -4,7 +4,8 @@ namespace hiro { struct pMonitor { static auto count() -> uint; - static auto geometry(unsigned monitor) -> Geometry; + static auto dpi(uint monitor) -> Position; + static auto geometry(uint monitor) -> Geometry; static auto primary() -> uint; }; diff --git a/hiro/qt/monitor.cpp b/hiro/qt/monitor.cpp index a2774187..1e0e8db1 100644 --- a/hiro/qt/monitor.cpp +++ b/hiro/qt/monitor.cpp @@ -2,16 +2,24 @@ namespace hiro { -auto pMonitor::count() -> unsigned { +auto pMonitor::count() -> uint { return QApplication::desktop()->screenCount(); } -auto pMonitor::geometry(unsigned monitor) -> Geometry { +auto pMonitor::dpi(uint monitor) -> Position { + //Qt does not support per-monitor DPI retrieval + return { + QApplication::desktop()->logicalDpiX(), + QApplication::desktop()->logicalDpiY() + }; +} + +auto pMonitor::geometry(uint monitor) -> Geometry { QRect rectangle = QApplication::desktop()->screenGeometry(monitor); return {rectangle.x(), rectangle.y(), rectangle.width(), rectangle.height()}; } -auto pMonitor::primary() -> unsigned { +auto pMonitor::primary() -> uint { return QApplication::desktop()->primaryScreen(); } diff --git a/hiro/qt/monitor.hpp b/hiro/qt/monitor.hpp index 2ec76265..70cf8a1d 100644 --- a/hiro/qt/monitor.hpp +++ b/hiro/qt/monitor.hpp @@ -3,9 +3,10 @@ namespace hiro { struct pMonitor { - static auto count() -> unsigned; - static auto geometry(unsigned monitor) -> Geometry; - static auto primary() -> unsigned; + static auto count() -> uint; + static auto dpi(uint monitor) -> Position; + static auto geometry(uint monitor) -> Geometry; + static auto primary() -> uint; }; } diff --git a/hiro/windows/monitor.cpp b/hiro/windows/monitor.cpp index 84a90c53..a3049e7f 100644 --- a/hiro/windows/monitor.cpp +++ b/hiro/windows/monitor.cpp @@ -3,42 +3,53 @@ namespace hiro { struct MonitorInfo { - unsigned monitor = 0; - unsigned primary = 0; - unsigned index = 0; + uint monitor = 0; + uint primary = 0; + float dpiX = 0; + float dpiY = 0; Geometry geometry; + uint index = 0; }; static auto CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { MonitorInfo& info = *(MonitorInfo*)dwData; - MONITORINFOEX mi; - memset(&mi, 0, sizeof(MONITORINFOEX)); - mi.cbSize = sizeof(MONITORINFOEX); + MONITORINFOEX mi{sizeof(MONITORINFOEX)}; GetMonitorInfo(hMonitor, &mi); string displayName = (const char*)utf8_t(mi.szDevice); - if(displayName.beginsWith(R"(\\.\DISPLAYV)")) return TRUE; //ignore pseudo-monitors + if(displayName.beginsWith(R"(\\.\DISPLAYV)")) return true; //ignore pseudo-monitors if(mi.dwFlags & MONITORINFOF_PRIMARY) info.primary = info.index; if(info.monitor == info.index) { + UINT dpiX = 0, dpiY = 0; + GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + info.dpiX = dpiX; + info.dpiY = dpiY; info.geometry = {lprcMonitor->left, lprcMonitor->top, lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top}; } info.index++; - return TRUE; + return true; } -auto pMonitor::count() -> unsigned { +auto pMonitor::count() -> uint { return GetSystemMetrics(SM_CMONITORS); } -auto pMonitor::geometry(unsigned monitor) -> Geometry { +auto pMonitor::dpi(uint monitor) -> Position { MonitorInfo info; info.monitor = monitor; - EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&info); + EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, (LPARAM)&info); + return {info.dpiX, info.dpiY}; +} + +auto pMonitor::geometry(uint monitor) -> Geometry { + MonitorInfo info; + info.monitor = monitor; + EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, (LPARAM)&info); return info.geometry; } -auto pMonitor::primary() -> unsigned { +auto pMonitor::primary() -> uint { MonitorInfo info; - EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&info); + EnumDisplayMonitors(nullptr, nullptr, MonitorEnumProc, (LPARAM)&info); return info.primary; } diff --git a/hiro/windows/monitor.hpp b/hiro/windows/monitor.hpp index 2ec76265..70cf8a1d 100644 --- a/hiro/windows/monitor.hpp +++ b/hiro/windows/monitor.hpp @@ -3,9 +3,10 @@ namespace hiro { struct pMonitor { - static auto count() -> unsigned; - static auto geometry(unsigned monitor) -> Geometry; - static auto primary() -> unsigned; + static auto count() -> uint; + static auto dpi(uint monitor) -> Position; + static auto geometry(uint monitor) -> Geometry; + static auto primary() -> uint; }; } diff --git a/icarus/GNUmakefile b/icarus/GNUmakefile index 694dbe6b..1b9b70a9 100644 --- a/icarus/GNUmakefile +++ b/icarus/GNUmakefile @@ -1,4 +1,4 @@ -build := release +build := optimize include ../nall/GNUmakefile include ../hiro/GNUmakefile diff --git a/icarus/icarus.plist b/icarus/icarus.plist deleted file mode 100644 index 67833d77..00000000 --- a/icarus/icarus.plist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - CFBundleIdentifier - org.byuu.icarus - CFBundleDisplayName - icarus - CFBundleExecutable - icarus - - NSHighResolutionCapable - - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/nall/GNUmakefile b/nall/GNUmakefile index 18b7b214..e8c4df41 100644 --- a/nall/GNUmakefile +++ b/nall/GNUmakefile @@ -60,8 +60,10 @@ ifeq ($(compiler),) endif # build settings -ifeq ($(build),release) +ifeq ($(build),optimize) flags += -O3 +else ifeq ($(build),release) + flags += -O2 else ifeq ($(build),stable) flags += -O1 else ifeq ($(build),debug)