parent
d2f63e1308
commit
77ab6d7612
|
|
@ -1 +1 @@
|
|||
Subproject commit 1dc05d97e7b624548f29d8c4db7ea5433eef8a25
|
||||
Subproject commit 008571130310f2159286560205b2e31dea022846
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
html
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
body
|
||||
{
|
||||
flow: vertical;
|
||||
width: 100%%;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
.about-body
|
||||
{
|
||||
flow: vertical;
|
||||
width: 100%%;
|
||||
padding: 1em 1.25em 0.25em 1.25em;
|
||||
}
|
||||
|
||||
body>.footer
|
||||
{
|
||||
padding: 0.35em 1.25em 0.5em 1.25em;
|
||||
}
|
||||
|
||||
.about-row-top
|
||||
{
|
||||
flow: horizontal;
|
||||
vertical-align: middle;
|
||||
width: 100%%;
|
||||
margin-bottom: 0.85em;
|
||||
}
|
||||
|
||||
.about-logo-wrap
|
||||
{
|
||||
width: 40%%;
|
||||
margin-right: 1em;
|
||||
horizontal-align: center;
|
||||
}
|
||||
|
||||
.about-logo
|
||||
{
|
||||
display: block;
|
||||
width: 100%%;
|
||||
height: width(100%%);
|
||||
margin: 0 auto;
|
||||
image-rendering: auto;
|
||||
}
|
||||
|
||||
.about-product
|
||||
{
|
||||
width: *;
|
||||
flow: vertical;
|
||||
text-align: center;
|
||||
horizontal-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.about-name
|
||||
{
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-top: *;
|
||||
margin-bottom: 0.2em;
|
||||
color: var(--color-ui-text-primary);
|
||||
}
|
||||
|
||||
.about-version,
|
||||
.about-copyright
|
||||
{
|
||||
color: var(--color-ui-text-muted);
|
||||
}
|
||||
|
||||
.about-version
|
||||
{
|
||||
margin-bottom: 0.15em;
|
||||
}
|
||||
|
||||
.about-copyright
|
||||
{
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: *;
|
||||
}
|
||||
|
||||
.about-row-content
|
||||
{
|
||||
width: 100%%;
|
||||
}
|
||||
|
||||
.about-description
|
||||
{
|
||||
line-height: 1.45;
|
||||
margin-bottom: 0.85em;
|
||||
color: var(--color-ui-text-primary);
|
||||
}
|
||||
|
||||
.about-description p
|
||||
{
|
||||
margin: 0 0 0.65em 0;
|
||||
}
|
||||
|
||||
.about-disclaimer
|
||||
{
|
||||
color: var(--color-ui-text-muted);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.about-credits
|
||||
{
|
||||
margin-bottom: 0.85em;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.about-credits-title
|
||||
{
|
||||
color: var(--color-ui-text-primary);
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.about-credits-list
|
||||
{
|
||||
color: var(--color-ui-text-muted);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.about-links
|
||||
{
|
||||
margin-bottom: 0.75em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.about-link-sep
|
||||
{
|
||||
color: var(--color-ui-text-muted);
|
||||
}
|
||||
|
||||
a.about-link
|
||||
{
|
||||
color: #3cafe9;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.about-link:hover
|
||||
{
|
||||
color: #7ec8f7;
|
||||
}
|
||||
|
||||
.about-trademark
|
||||
{
|
||||
color: var(--color-ui-text-muted);
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
|
@ -139,274 +139,3 @@ html > header > window-buttons > window-button[role="window-minimize"]
|
|||
{
|
||||
foreground-image: url(icon:window-minimize);
|
||||
}
|
||||
|
||||
ul#menu-bar
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0 0.5em 0.3em 0.5em;
|
||||
background: var(--color-menubar-background);
|
||||
color: var(--color-ui-text-primary);
|
||||
font-family: var(--font-ui);
|
||||
font-size: 0.9em;
|
||||
font-weight: 100;
|
||||
behavior:menu-bar;
|
||||
flow: horizontal;
|
||||
}
|
||||
|
||||
ul#menu-bar > li
|
||||
{
|
||||
padding: 0.28em 0.55em;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
width: max-content;
|
||||
display: block;
|
||||
flow: horizontal;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
ul#menu-bar > li:hover
|
||||
{
|
||||
background: var(--color-menubar-background-hover);
|
||||
}
|
||||
|
||||
ul#menu-bar:focus > li:current,
|
||||
ul#menu-bar > li:owns-popup {
|
||||
background-color: var(--color-menubar-background-active);
|
||||
border-radius: 5px 5px 0;
|
||||
}
|
||||
|
||||
ul#menu-bar caption u,
|
||||
menu li .menu-item-label u
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
[data-menu-mnemonics="1"] ul#menu-bar caption u,
|
||||
[data-menu-mnemonics="1"] menu li .menu-item-label u,
|
||||
ul#menu-bar > li:owns-popup caption u,
|
||||
menu[window-state="shown"] li .menu-item-label u,
|
||||
menu[window-state="shown"] caption u
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
menu
|
||||
{
|
||||
behavior:menu;
|
||||
flow: vertical;
|
||||
display:none;
|
||||
margin:0;
|
||||
padding: 0.35em 0;
|
||||
min-width: 14em;
|
||||
max-width:max-content;
|
||||
background: var(--color-menu-popup-background);
|
||||
color: #f0f0f0;
|
||||
border: 1px solid var(--color-menu-popup-border);
|
||||
border-top: none;
|
||||
box-shadow: 0 0.25em 0.75em var(--color-menu-popup-shadow);
|
||||
}
|
||||
|
||||
@media (menu-animation-supported) {
|
||||
menu {
|
||||
popup-animation: popup-animation(type:blend,duration:100ms);
|
||||
}
|
||||
}
|
||||
|
||||
menu menu
|
||||
{
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
width:*;
|
||||
display:block;
|
||||
flow:horizontal;
|
||||
vertical-align:middle;
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: left 2px top 50%;
|
||||
padding: 0.4em 1.75em 0.4em 1.1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
menu li .menu-item-label
|
||||
{
|
||||
width: *;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu) caption
|
||||
{
|
||||
width: *;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
menu li:current caption,
|
||||
menu li:hover:owns-popup caption
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph
|
||||
{
|
||||
width: 1.15em;
|
||||
min-width: 1.15em;
|
||||
max-width: 1.15em;
|
||||
min-height: 1.15em;
|
||||
max-height: 1.15em;
|
||||
margin: 0 0.55em 0 0;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
flex-shrink: 0;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-glyph-spacer
|
||||
{
|
||||
border: 1.5px solid transparent;
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-checkbox
|
||||
{
|
||||
border: 1.5px solid var(--color-ui-text-muted, #8c8c8c);
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-checkbox.checked
|
||||
{
|
||||
border-color: var(--color-ui-text-primary, #f0f0f0);
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg
|
||||
{
|
||||
border: none;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
min-width: 1.15em;
|
||||
max-width: 1.15em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg svg
|
||||
{
|
||||
width: 1.05em;
|
||||
height: 1.05em;
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg path,
|
||||
menu li .menu-item-glyph.menu-item-icon-svg circle
|
||||
{
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg path[fill="none"],
|
||||
menu li .menu-item-glyph.menu-item-icon-svg circle[fill="none"]
|
||||
{
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph .menu-item-checkmark
|
||||
{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: *;
|
||||
height: *;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: 0.72em;
|
||||
line-height: 1.15em;
|
||||
color: var(--color-ui-text-primary, #f0f0f0);
|
||||
}
|
||||
|
||||
menu li:current .menu-item-glyph.menu-item-checkbox,
|
||||
menu li:hover:owns-popup .menu-item-glyph.menu-item-checkbox
|
||||
{
|
||||
border-color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li:current .menu-item-glyph .menu-item-checkmark,
|
||||
menu li:hover:owns-popup .menu-item-glyph .menu-item-checkmark
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li .menu-accelerator
|
||||
{
|
||||
width: max-content;
|
||||
margin-left: 2.5em;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
color: var(--color-menu-shortcut-text);
|
||||
}
|
||||
|
||||
menu li .menu-accelerator:empty
|
||||
{
|
||||
display: none;
|
||||
margin: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
menu li:hover
|
||||
{
|
||||
background: var(--color-menuitem-background-hover);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
menu li:current,
|
||||
menu li:hover:owns-popup
|
||||
{
|
||||
background-color: #094771;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
menu li:current .menu-item-label,
|
||||
menu li:current .menu-accelerator,
|
||||
menu li:hover:owns-popup .menu-item-label,
|
||||
menu li:hover:owns-popup .menu-accelerator
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li:disabled
|
||||
{
|
||||
color:graytext;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu)
|
||||
{
|
||||
foreground-image:url(stock:arrow-right);
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: top 50% right 2px;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu):rtl
|
||||
{
|
||||
foreground-image:url(stock:arrow-left);
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: top 50% left 2px;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0.2em 0;
|
||||
}
|
||||
|
||||
menu hr
|
||||
{
|
||||
display: block;
|
||||
height: 1px;
|
||||
margin: 0.4em 0.65em;
|
||||
border: none;
|
||||
background: var(--color-menu-separator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,11 @@
|
|||
:root {
|
||||
--color-config-background: #181818;
|
||||
--color-config-page: #31363B;
|
||||
--color-config-page-border: #505050;
|
||||
}
|
||||
|
||||
html
|
||||
{
|
||||
background: var(--color-config-background);
|
||||
}
|
||||
|
||||
button
|
||||
{
|
||||
color: #eff0f1;
|
||||
background: #232728;
|
||||
border: 1px solid #55575a;
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.2rem;
|
||||
min-width: 5rem;
|
||||
}
|
||||
|
||||
div.ConfigPage
|
||||
{
|
||||
background: var(--color-config-background);
|
||||
background: var(--color-dialog-background);
|
||||
flow: horizontal;
|
||||
width: 100%%;
|
||||
height: 100%%;
|
||||
|
|
@ -44,16 +27,6 @@ popup.tooltip
|
|||
margin: 0 0 0 0.3rem;
|
||||
}
|
||||
|
||||
button:hover
|
||||
{
|
||||
border: 1px solid #3cafe9;
|
||||
}
|
||||
|
||||
button:active
|
||||
{
|
||||
background: #3cafe9;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
font-size: 0;
|
||||
|
|
@ -147,12 +120,6 @@ button:active
|
|||
height: 1.4rem;
|
||||
}
|
||||
|
||||
.footer
|
||||
{
|
||||
padding: 0.5rem 0 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#ConfigContents {
|
||||
width: 100%%;
|
||||
height: 100%%;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
:root {
|
||||
--color-dialog-background: #181818;
|
||||
}
|
||||
|
||||
html {
|
||||
background: var(--color-dialog-background);
|
||||
}
|
||||
|
||||
button {
|
||||
color: #eff0f1;
|
||||
background: #232728;
|
||||
border: 1px solid #55575a;
|
||||
font-family: var(--font-ui);
|
||||
font-size: 0.8rem;
|
||||
padding: 0.2rem;
|
||||
min-width: 5rem;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border: 1px solid #3cafe9;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: #3cafe9;
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 0.5rem 0 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
|
@ -358,3 +358,268 @@ rombrowser .games-grid[data-size="4"] .rom-card
|
|||
{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
ul#menu-bar
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0 0.5em 0.3em 0.5em;
|
||||
background: var(--color-menubar-background);
|
||||
color: var(--color-ui-text-primary);
|
||||
font-family: var(--font-ui);
|
||||
font-size: 0.9em;
|
||||
font-weight: 100;
|
||||
behavior:menu-bar;
|
||||
flow: horizontal;
|
||||
}
|
||||
|
||||
ul#menu-bar > li
|
||||
{
|
||||
padding: 0.28em 0.55em;
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
width: max-content;
|
||||
display: block;
|
||||
flow: horizontal;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
ul#menu-bar > li:hover
|
||||
{
|
||||
background: var(--color-menubar-background-hover);
|
||||
}
|
||||
|
||||
ul#menu-bar:focus > li:current,
|
||||
ul#menu-bar > li:owns-popup {
|
||||
background-color: var(--color-menubar-background-active);
|
||||
border-radius: 5px 5px 0;
|
||||
}
|
||||
|
||||
ul#menu-bar caption u,
|
||||
menu li .menu-item-label u
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
[data-menu-mnemonics="1"] ul#menu-bar caption u,
|
||||
[data-menu-mnemonics="1"] menu li .menu-item-label u,
|
||||
ul#menu-bar > li:owns-popup caption u,
|
||||
menu[window-state="shown"] li .menu-item-label u,
|
||||
menu[window-state="shown"] caption u
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
menu
|
||||
{
|
||||
behavior:menu;
|
||||
flow: vertical;
|
||||
display:none;
|
||||
margin:0;
|
||||
padding: 0.35em 0;
|
||||
min-width: 14em;
|
||||
max-width:max-content;
|
||||
background: var(--color-menu-popup-background);
|
||||
color: #f0f0f0;
|
||||
border: 1px solid var(--color-menu-popup-border);
|
||||
border-top: none;
|
||||
box-shadow: 0 0.25em 0.75em var(--color-menu-popup-shadow);
|
||||
}
|
||||
|
||||
@media (menu-animation-supported) {
|
||||
menu {
|
||||
popup-animation: popup-animation(type:blend,duration:100ms);
|
||||
}
|
||||
}
|
||||
|
||||
menu menu
|
||||
{
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
menu li
|
||||
{
|
||||
width:*;
|
||||
display:block;
|
||||
flow:horizontal;
|
||||
vertical-align:middle;
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: left 2px top 50%;
|
||||
padding: 0.4em 1.75em 0.4em 1.1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
menu li .menu-item-label
|
||||
{
|
||||
width: *;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu) caption
|
||||
{
|
||||
width: *;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
menu li:current caption,
|
||||
menu li:hover:owns-popup caption
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph
|
||||
{
|
||||
width: 1.15em;
|
||||
min-width: 1.15em;
|
||||
max-width: 1.15em;
|
||||
min-height: 1.15em;
|
||||
max-height: 1.15em;
|
||||
margin: 0 0.55em 0 0;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
flex-shrink: 0;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-glyph-spacer
|
||||
{
|
||||
border: 1.5px solid transparent;
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-checkbox
|
||||
{
|
||||
border: 1.5px solid var(--color-ui-text-muted, #8c8c8c);
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-checkbox.checked
|
||||
{
|
||||
border-color: var(--color-ui-text-primary, #f0f0f0);
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg
|
||||
{
|
||||
border: none;
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
min-width: 1.15em;
|
||||
max-width: 1.15em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg svg
|
||||
{
|
||||
width: 1.05em;
|
||||
height: 1.05em;
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg path,
|
||||
menu li .menu-item-glyph.menu-item-icon-svg circle
|
||||
{
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph.menu-item-icon-svg path[fill="none"],
|
||||
menu li .menu-item-glyph.menu-item-icon-svg circle[fill="none"]
|
||||
{
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
menu li .menu-item-glyph .menu-item-checkmark
|
||||
{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: *;
|
||||
height: *;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: 0.72em;
|
||||
line-height: 1.15em;
|
||||
color: var(--color-ui-text-primary, #f0f0f0);
|
||||
}
|
||||
|
||||
menu li:current .menu-item-glyph.menu-item-checkbox,
|
||||
menu li:hover:owns-popup .menu-item-glyph.menu-item-checkbox
|
||||
{
|
||||
border-color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li:current .menu-item-glyph .menu-item-checkmark,
|
||||
menu li:hover:owns-popup .menu-item-glyph .menu-item-checkmark
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li .menu-accelerator
|
||||
{
|
||||
width: max-content;
|
||||
margin-left: 2.5em;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
color: var(--color-menu-shortcut-text);
|
||||
}
|
||||
|
||||
menu li .menu-accelerator:empty
|
||||
{
|
||||
display: none;
|
||||
margin: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
menu li:hover
|
||||
{
|
||||
background: var(--color-menuitem-background-hover);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
menu li:current,
|
||||
menu li:hover:owns-popup
|
||||
{
|
||||
background-color: #094771;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
menu li:current .menu-item-label,
|
||||
menu li:current .menu-accelerator,
|
||||
menu li:hover:owns-popup .menu-item-label,
|
||||
menu li:hover:owns-popup .menu-accelerator
|
||||
{
|
||||
color: #f0f0f0;
|
||||
}
|
||||
|
||||
menu li:disabled
|
||||
{
|
||||
color:graytext;
|
||||
foreground-image: none;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu)
|
||||
{
|
||||
foreground-image:url(stock:arrow-right);
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: top 50% right 2px;
|
||||
}
|
||||
|
||||
menu li:has-child-of-type(menu):rtl
|
||||
{
|
||||
foreground-image:url(stock:arrow-left);
|
||||
foreground-repeat: no-repeat;
|
||||
foreground-position: top 50% left 2px;
|
||||
}
|
||||
|
||||
menu hr
|
||||
{
|
||||
display: block;
|
||||
height: 1px;
|
||||
margin: 0.4em 0.65em;
|
||||
border: none;
|
||||
background: var(--color-menu-separator);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
<html window-frame="solid-with-shadow" window-icon="window-icon.png">
|
||||
<head>
|
||||
<link href="base.css" rel="stylesheet" type="text/css" />
|
||||
<link href="dialog.css" rel="stylesheet" type="text/css" />
|
||||
<link href="about_dialog.css" rel="stylesheet" type="text/css" />
|
||||
<title>About NXEmu</title>
|
||||
</head>
|
||||
<header>
|
||||
<window-caption role="window-caption"><img src="window-icon-32.png" /><span>About NXEmu</span></window-caption>
|
||||
<window-buttons>
|
||||
<window-button role="window-close"></window-button>
|
||||
</window-buttons>
|
||||
</header>
|
||||
<body>
|
||||
<div class="about-body">
|
||||
<div class="about-row-top">
|
||||
<div class="about-logo-wrap">
|
||||
<img class="about-logo" src="nxemu-logo.png" />
|
||||
</div>
|
||||
<div class="about-product">
|
||||
<div class="about-name">NXEmu</div>
|
||||
<div id="AboutVersion" class="about-version"></div>
|
||||
<div id="AboutCopyright" class="about-copyright"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="about-row-content">
|
||||
<div class="about-description">
|
||||
<p>NXEmu is an experimental open-source Nintendo Switch emulator.</p>
|
||||
<p class="about-disclaimer">You are responsible for ensuring your use of this software complies with the laws in your jurisdiction.</p>
|
||||
</div>
|
||||
<div class="about-credits">
|
||||
<div class="about-credits-title">With thanks to</div>
|
||||
<div class="about-credits-list">
|
||||
the yuzu project, Stardust, and NullVector
|
||||
</div>
|
||||
</div>
|
||||
<div class="about-links">
|
||||
<a id="AboutLinkWebsite" class="about-link" href="https://www.nxemu.com/">Website</a>
|
||||
<span class="about-link-sep"> | </span>
|
||||
<a id="AboutLinkSource" class="about-link" href="https://github.com/N3xoX1/nxemu">Source Code</a>
|
||||
<span class="about-link-sep"> | </span>
|
||||
<a id="AboutLinkDiscord" class="about-link" href="https://discord.gg/hEa4hNyFWU">Discord</a>
|
||||
</div>
|
||||
<div class="about-trademark">
|
||||
"Nintendo Switch" is a trademark of Nintendo. NXEmu is not affiliated with Nintendo in any way.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<button role="window-ok">OK</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<html window-frame="solid-with-shadow" window-icon="window-icon.png">
|
||||
<head>
|
||||
<link href="base.css" rel="stylesheet" type="text/css" />
|
||||
<link href="dialog.css" rel="stylesheet" type="text/css" />
|
||||
<link href="config.css" rel="stylesheet" type="text/css" />
|
||||
<title>Configure Input</title>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<html window-frame="solid-with-shadow" window-icon="window-icon.png">
|
||||
<head>
|
||||
<link href="base.css" rel="stylesheet" type="text/css" />
|
||||
<link href="dialog.css" rel="stylesheet" type="text/css" />
|
||||
<link href="config.css" rel="stylesheet" type="text/css" />
|
||||
<title>NxEmu Configuration</title>
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Z"/>
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16v-4M12 8h.01"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 384 B |
|
|
@ -0,0 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.59 34.173A49 49 0 0 1 14.68 38C7.3 37.79 4.5 33 4.5 33a44.8 44.8 0 0 1 4.81-19.52A16.47 16.47 0 0 1 18.69 10l1 2.31A33 33 0 0 1 24 12a33 33 0 0 1 4.33.3l1-2.31a16.47 16.47 0 0 1 9.38 3.51A44.8 44.8 0 0 1 43.5 33s-2.8 4.79-10.18 5a47 47 0 0 1-2.86-3.81m6.46-2.9c-3.84 1.945-7.555 3.89-12.92 3.89s-9.08-1.945-12.92-3.89"/>
|
||||
<circle fill="none" stroke="currentColor" stroke-width="2" cx="17.847" cy="26.23" r="3.35"/>
|
||||
<circle fill="none" stroke="currentColor" stroke-width="2" cx="30.153" cy="26.23" r="3.35"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 704 B |
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
|
|
@ -7,6 +7,7 @@ add_library(common STATIC
|
|||
path.cpp
|
||||
path_finder.cpp
|
||||
platform.cpp
|
||||
shell_open_url.cpp
|
||||
std_string.cpp
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
<ClInclude Include="path.h" />
|
||||
<ClInclude Include="path_finder.h" />
|
||||
<ClInclude Include="sha256.h" />
|
||||
<ClInclude Include="shell_open_url.h" />
|
||||
<ClInclude Include="std_string.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -46,6 +47,7 @@
|
|||
<ClCompile Include="path.cpp" />
|
||||
<ClCompile Include="path_finder.cpp" />
|
||||
<ClCompile Include="sha256.cpp" />
|
||||
<ClCompile Include="shell_open_url.cpp" />
|
||||
<ClCompile Include="std_string.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -48,6 +48,9 @@
|
|||
<ClInclude Include="path_finder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shell_open_url.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="file.cpp">
|
||||
|
|
@ -80,5 +83,8 @@
|
|||
<ClCompile Include="path_finder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shell_open_url.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include "shell_open_url.h"
|
||||
|
||||
#include <common/std_string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
bool ShellOpenUrl(const char * url_utf8, const void * owner_window)
|
||||
{
|
||||
if (url_utf8 == nullptr || url_utf8[0] == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
bool converted = false;
|
||||
const std::wstring wide_url = stdstr(url_utf8).ToUTF16(stdstr::CODEPAGE_UTF8, &converted);
|
||||
if (!converted || wide_url.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const HWND owner = (HWND)owner_window;
|
||||
const HINSTANCE result = ShellExecuteW(owner, L"open", wide_url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
return reinterpret_cast<INT_PTR>(result) > 32;
|
||||
#else
|
||||
(void)owner_window;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
// Opens a URL or file URI with the system default handler (browser, etc.).
|
||||
// owner_window is optional; on Windows this is an HWND passed to ShellExecuteW.
|
||||
bool ShellOpenUrl(const char * url_utf8, const void * owner_window = nullptr);
|
||||
|
|
@ -1,30 +1,13 @@
|
|||
#include "web_browser.h"
|
||||
|
||||
#include <common/shell_open_url.h>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::wstring Utf8ToWide(std::string_view utf8)
|
||||
{
|
||||
if (utf8.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
const int n = MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), nullptr, 0);
|
||||
if (n <= 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
std::wstring wide(static_cast<std::size_t>(n), L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8.data(), static_cast<int>(utf8.size()), wide.data(), n);
|
||||
return wide;
|
||||
}
|
||||
|
||||
std::string FileUriFromLocalPath(std::string_view local_url_utf8)
|
||||
{
|
||||
std::string uri{"file:///"};
|
||||
|
|
@ -52,17 +35,6 @@ void InvokeOpenResult(OpenWebPageFn callback, void * user_data, bool success, co
|
|||
callback(user_data, static_cast<uint32_t>(success ? WebExitReasonHost::EndButtonPressed : WebExitReasonHost::WindowClosed), last_url_utf8 != nullptr ? last_url_utf8 : "");
|
||||
}
|
||||
|
||||
bool ShellOpen(HWND owner, const std::string & url_utf8)
|
||||
{
|
||||
const std::wstring wide_url = Utf8ToWide(url_utf8);
|
||||
if (wide_url.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const HINSTANCE result = ShellExecuteW(owner, L"open", wide_url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
||||
return reinterpret_cast<INT_PTR>(result) > 32;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WebBrowserApplet::WebBrowserApplet() :
|
||||
|
|
@ -99,7 +71,7 @@ void WebBrowserApplet::OpenLocalWebPage(const char * local_url_utf8, void * extr
|
|||
}
|
||||
|
||||
const std::string file_uri = FileUriFromLocalPath(local_path);
|
||||
const bool success = ShellOpen(static_cast<HWND>(m_hwnd), file_uri);
|
||||
const bool success = ShellOpenUrl(file_uri.c_str(), m_hwnd);
|
||||
InvokeOpenResult(open_callback, open_user_data, success, success ? file_uri.c_str() : "");
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +84,6 @@ void WebBrowserApplet::OpenExternalWebPage(const char * external_url_utf8, void
|
|||
return;
|
||||
}
|
||||
|
||||
const bool success = ShellOpen(static_cast<HWND>(m_hwnd), external_url);
|
||||
const bool success = ShellOpenUrl(external_url.c_str(), m_hwnd);
|
||||
InvokeOpenResult(callback, user_data, success, success ? external_url.c_str() : "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
<ClCompile Include="user_interface\game_list_worker.cpp" />
|
||||
<ClCompile Include="user_interface\hotkey_map.cpp" />
|
||||
<ClCompile Include="user_interface\key_mappings.cpp" />
|
||||
<ClCompile Include="user_interface\about_dialog.cpp" />
|
||||
<ClCompile Include="user_interface\notification.cpp" />
|
||||
<ClCompile Include="user_interface\sciter_main_window.cpp" />
|
||||
<ClCompile Include="user_interface\settings\config_setting .cpp" />
|
||||
|
|
@ -65,10 +66,10 @@
|
|||
<ClInclude Include="settings\ui_settings.h" />
|
||||
<ClInclude Include="settings\ui_settings_identifiers.h" />
|
||||
<ClInclude Include="startup_checks.h" />
|
||||
<ClInclude Include="user_interface\dpi_scaling.h" />
|
||||
<ClInclude Include="user_interface\game_list_worker.h" />
|
||||
<ClInclude Include="user_interface\hotkey_map.h" />
|
||||
<ClInclude Include="user_interface\key_mappings.h" />
|
||||
<ClInclude Include="user_interface\about_dialog.h" />
|
||||
<ClInclude Include="user_interface\notification.h" />
|
||||
<ClInclude Include="user_interface\resource.h" />
|
||||
<ClInclude Include="user_interface\sciter_main_window.h" />
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@
|
|||
<ClCompile Include="settings\ui_settings.cpp">
|
||||
<Filter>Source Files\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="user_interface\about_dialog.cpp">
|
||||
<Filter>Source Files\user_interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="user_interface\notification.cpp">
|
||||
<Filter>Source Files\user_interface</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -116,6 +119,9 @@
|
|||
<ClInclude Include="settings\ui_settings.h">
|
||||
<Filter>Header Files\settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="user_interface\about_dialog.h">
|
||||
<Filter>Header Files\user_interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="user_interface\notification.h">
|
||||
<Filter>Header Files\user_interface</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -161,9 +167,6 @@
|
|||
<ClInclude Include="user_interface\game_list_worker.h">
|
||||
<Filter>Header Files\user_interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="user_interface\dpi_scaling.h">
|
||||
<Filter>Header Files\user_interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="user_interface\widgets\rom_browser.h">
|
||||
<Filter>Header Files\user_interface\widgets</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,107 @@
|
|||
#include "about_dialog.h"
|
||||
|
||||
#include <common/shell_open_url.h>
|
||||
#include <nxemu-core/version.h>
|
||||
#include <sciter_element.h>
|
||||
#include <sciter_handler.h>
|
||||
#include <sciter_ui.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void AttachClickHandler(ISciterUI & sciterUI, const SciterElement & element, IClickSink * sink)
|
||||
{
|
||||
if (element.IsValid())
|
||||
{
|
||||
sciterUI.AttachHandler(element, IID_ICLICKSINK, sink);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AboutDialog::AboutDialog(ISciterUI & sciterUI) :
|
||||
m_sciterUI(sciterUI),
|
||||
m_window(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog() = default;
|
||||
|
||||
void AboutDialog::Display(void * parentWindow)
|
||||
{
|
||||
enum
|
||||
{
|
||||
WINDOW_WIDTH = 480,
|
||||
};
|
||||
|
||||
m_window = nullptr;
|
||||
if (!m_sciterUI.WindowCreate(parentWindow, "about_dialog.html", 0, 0, WINDOW_WIDTH, 0, SUIW_CHILD, m_window))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_window->OnDestroySinkAdd(this);
|
||||
|
||||
SciterElement root(m_window->GetRootElement());
|
||||
if (root.IsValid())
|
||||
{
|
||||
SciterElement versionEl(root.GetElementByID("AboutVersion"));
|
||||
if (versionEl.IsValid())
|
||||
{
|
||||
versionEl.SetText(VER_FILE_VERSION_STR);
|
||||
}
|
||||
|
||||
SciterElement copyrightEl(root.GetElementByID("AboutCopyright"));
|
||||
if (copyrightEl.IsValid())
|
||||
{
|
||||
copyrightEl.SetText(VER_COPYRIGHT_STR);
|
||||
}
|
||||
|
||||
AttachClickHandler(m_sciterUI, root.FindFirst("button[role=\"window-ok\"]"), this);
|
||||
AttachClickHandler(m_sciterUI, root.FindFirst("window-button[role=\"window-close\"]"), this);
|
||||
AttachClickHandler(m_sciterUI, root.GetElementByID("AboutLinkWebsite"), this);
|
||||
AttachClickHandler(m_sciterUI, root.GetElementByID("AboutLinkSource"), this);
|
||||
AttachClickHandler(m_sciterUI, root.GetElementByID("AboutLinkDiscord"), this);
|
||||
}
|
||||
|
||||
m_window->FixMinSize();
|
||||
m_window->CenterWindow();
|
||||
}
|
||||
|
||||
void AboutDialog::Close()
|
||||
{
|
||||
if (m_window == nullptr || m_window->IsClosed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_window->Destroy();
|
||||
}
|
||||
|
||||
bool AboutDialog::OnClick(SCITER_ELEMENT element, SCITER_ELEMENT /*source*/, uint32_t /*reason*/)
|
||||
{
|
||||
SciterElement clickElem(element);
|
||||
const std::string role = clickElem.GetAttribute("role");
|
||||
|
||||
if (role == "window-ok" || role == "window-close")
|
||||
{
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string href = clickElem.GetAttribute("href");
|
||||
if (!href.empty() && (href.compare(0, 7, "http://") == 0 || href.compare(0, 8, "https://") == 0))
|
||||
{
|
||||
const void * owner = m_window != nullptr ? m_window->GetHandle() : nullptr;
|
||||
ShellOpenUrl(href.c_str(), owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AboutDialog::OnWindowDestroy(HWINDOW /*hWnd*/)
|
||||
{
|
||||
m_window = nullptr;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include <sciter_handler.h>
|
||||
|
||||
__interface ISciterUI;
|
||||
__interface ISciterWindow;
|
||||
|
||||
class AboutDialog :
|
||||
public IClickSink,
|
||||
public IWindowDestroySink
|
||||
{
|
||||
public:
|
||||
explicit AboutDialog(ISciterUI & sciterUI);
|
||||
~AboutDialog();
|
||||
|
||||
void Display(void * parentWindow);
|
||||
|
||||
bool OnClick(SCITER_ELEMENT element, SCITER_ELEMENT source, uint32_t reason) override;
|
||||
void OnWindowDestroy(HWINDOW hWnd) override;
|
||||
|
||||
private:
|
||||
AboutDialog(const AboutDialog &) = delete;
|
||||
AboutDialog & operator=(const AboutDialog &) = delete;
|
||||
|
||||
void Close();
|
||||
|
||||
ISciterUI & m_sciterUI;
|
||||
ISciterWindow * m_window;
|
||||
};
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
inline void ScaleWindowSizeForDpi(void * parentWindow, int & width, int & height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HWND parent = static_cast<HWND>(parentWindow);
|
||||
UINT dpi = USER_DEFAULT_SCREEN_DPI;
|
||||
|
||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
||||
typedef UINT (WINAPI * PFN_GetDpiForSystem)();
|
||||
static PFN_GetDpiForWindow pGetDpiForWindow = reinterpret_cast<PFN_GetDpiForWindow>(
|
||||
::GetProcAddress(::GetModuleHandleW(L"user32.dll"), "GetDpiForWindow"));
|
||||
static PFN_GetDpiForSystem pGetDpiForSystem = reinterpret_cast<PFN_GetDpiForSystem>(
|
||||
::GetProcAddress(::GetModuleHandleW(L"user32.dll"), "GetDpiForSystem"));
|
||||
|
||||
if (parent != nullptr && pGetDpiForWindow != nullptr)
|
||||
{
|
||||
UINT v = pGetDpiForWindow(parent);
|
||||
if (v != 0)
|
||||
{
|
||||
dpi = v;
|
||||
}
|
||||
}
|
||||
else if (pGetDpiForSystem != nullptr)
|
||||
{
|
||||
UINT v = pGetDpiForSystem();
|
||||
if (v != 0)
|
||||
{
|
||||
dpi = v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HDC hdc = ::GetDC(nullptr);
|
||||
if (hdc != nullptr)
|
||||
{
|
||||
int v = ::GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
if (v > 0)
|
||||
{
|
||||
dpi = static_cast<UINT>(v);
|
||||
}
|
||||
::ReleaseDC(nullptr, hdc);
|
||||
}
|
||||
}
|
||||
|
||||
width = ::MulDiv(width, static_cast<int>(dpi), USER_DEFAULT_SCREEN_DPI);
|
||||
height = ::MulDiv(height, static_cast<int>(dpi), USER_DEFAULT_SCREEN_DPI);
|
||||
|
||||
RECT workArea{};
|
||||
HMONITOR monitor = parent != nullptr
|
||||
? ::MonitorFromWindow(parent, MONITOR_DEFAULTTONEAREST)
|
||||
: ::MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY);
|
||||
MONITORINFO mi{sizeof(MONITORINFO)};
|
||||
if (monitor != nullptr && ::GetMonitorInfoW(monitor, &mi))
|
||||
{
|
||||
workArea = mi.rcWork;
|
||||
}
|
||||
else if (!::SystemParametersInfoW(SPI_GETWORKAREA, 0, &workArea, 0))
|
||||
{
|
||||
workArea.right = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
workArea.bottom = ::GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
const int maxWidth = std::max<int>(320, workArea.right - workArea.left);
|
||||
const int maxHeight = std::max<int>(240, workArea.bottom - workArea.top);
|
||||
if (width > maxWidth)
|
||||
{
|
||||
width = maxWidth;
|
||||
}
|
||||
if (height > maxHeight)
|
||||
{
|
||||
height = maxHeight;
|
||||
}
|
||||
#else
|
||||
(void)parentWindow;
|
||||
(void)width;
|
||||
(void)height;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
#include "sciter_main_window.h"
|
||||
#include "user_interface/about_dialog.h"
|
||||
#include "user_interface/notification.h"
|
||||
#include "settings/input_config.h"
|
||||
#include "settings/system_config.h"
|
||||
#include "settings/ui_settings.h"
|
||||
#include "user_interface/dpi_scaling.h"
|
||||
#include "user_interface/key_mappings.h"
|
||||
#include <common/base64.h>
|
||||
#include <common/shell_open_url.h>
|
||||
#include <common/std_string.h>
|
||||
#include <nxemu-core/notification.h>
|
||||
#include <nxemu-core/settings/identifiers.h>
|
||||
|
|
@ -30,6 +31,13 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr const char * kNxEmuDiscordUrl = "https://discord.gg/hEa4hNyFWU";
|
||||
|
||||
} // namespace
|
||||
|
||||
struct Win32FullscreenState
|
||||
{
|
||||
bool active = false;
|
||||
|
|
@ -272,6 +280,10 @@ const char * SciterMainWindow::MenuIconResource(GuiAction action) const
|
|||
case GuiAction::ResetWindowSize900p:
|
||||
case GuiAction::ResetWindowSize1080p:
|
||||
return "resize.svg";
|
||||
case GuiAction::OpenAboutDialog:
|
||||
return "about.svg";
|
||||
case GuiAction::OpenDiscord:
|
||||
return "discord.svg";
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -431,6 +443,12 @@ void SciterMainWindow::ResetMenu()
|
|||
}
|
||||
mainTitleMenu.push_back(MenuBarItem(MenuBarItem::SUB_MENU, "&Options", &optionsMenu));
|
||||
|
||||
MenuBarItemList helpMenu;
|
||||
helpMenu.push_back(MenuBarItem(static_cast<int32_t>(GuiAction::OpenDiscord), "&Discord", nullptr, nullptr, MenuBarItem::CheckState::None, MenuIconSvg(GuiAction::OpenDiscord)));
|
||||
helpMenu.push_back(MenuBarItem(MenuBarItem::SPLITER));
|
||||
helpMenu.push_back(MenuBarItem(static_cast<int32_t>(GuiAction::OpenAboutDialog), "&About NXEmu...", nullptr, nullptr, MenuBarItem::CheckState::None, MenuIconSvg(GuiAction::OpenAboutDialog)));
|
||||
mainTitleMenu.push_back(MenuBarItem(MenuBarItem::SUB_MENU, "&Help", &helpMenu));
|
||||
|
||||
m_menuBar->AddSink(this);
|
||||
m_menuBar->SetMenuContent(mainTitleMenu);
|
||||
}
|
||||
|
|
@ -443,10 +461,7 @@ bool SciterMainWindow::Show()
|
|||
WINDOW_WIDTH = 760,
|
||||
};
|
||||
|
||||
int width = WINDOW_WIDTH;
|
||||
int height = WINDOW_HEIGHT;
|
||||
ScaleWindowSizeForDpi(nullptr, width, height);
|
||||
if (!m_sciterUI.WindowCreate(nullptr, "main_window.html", 0, 0, width, height, SUIW_MAIN | SUIW_HIDDEN, m_window))
|
||||
if (!m_sciterUI.WindowCreate(nullptr, "main_window.html", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, SUIW_MAIN | SUIW_HIDDEN, m_window))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1137,6 +1152,17 @@ void SciterMainWindow::OnInputConfig()
|
|||
m_inputConfig->Display((void *)m_window->GetHandle());
|
||||
}
|
||||
|
||||
void SciterMainWindow::OnAbout()
|
||||
{
|
||||
m_aboutDialog.reset(new AboutDialog(m_sciterUI));
|
||||
m_aboutDialog->Display((void *)m_window->GetHandle());
|
||||
}
|
||||
|
||||
void SciterMainWindow::OnOpenDiscord()
|
||||
{
|
||||
ShellOpenUrl(kNxEmuDiscordUrl);
|
||||
}
|
||||
|
||||
void SciterMainWindow::UpdateEmulationStatusText()
|
||||
{
|
||||
SciterElement statusTextEl(m_rootElement.GetElementByID("StatusText"));
|
||||
|
|
@ -1352,6 +1378,12 @@ void SciterMainWindow::OnGuiAction(GuiAction action)
|
|||
case GuiAction::OpenSystemConfiguration:
|
||||
OnSystemConfig();
|
||||
break;
|
||||
case GuiAction::OpenAboutDialog:
|
||||
OnAbout();
|
||||
break;
|
||||
case GuiAction::OpenDiscord:
|
||||
OnOpenDiscord();
|
||||
break;
|
||||
case GuiAction::ToggleFullscreen:
|
||||
ToggleFullscreen();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ struct Win32FullscreenState;
|
|||
|
||||
class SystemConfig;
|
||||
class InputConfig;
|
||||
class AboutDialog;
|
||||
|
||||
class SciterMainWindow :
|
||||
public IWindowDestroySink,
|
||||
|
|
@ -51,6 +52,8 @@ class SciterMainWindow :
|
|||
ResetWindowSize720p,
|
||||
ResetWindowSize900p,
|
||||
ResetWindowSize1080p,
|
||||
OpenAboutDialog,
|
||||
OpenDiscord,
|
||||
RecentFileMenuFirst,
|
||||
RecentFileMenuLast = RecentFileMenuFirst + 20,
|
||||
};
|
||||
|
|
@ -121,6 +124,8 @@ private:
|
|||
void OnRecetGame(uint32_t fileIndex);
|
||||
void OnToggleDockedMode();
|
||||
void OnToggleStartGamesInFullscreen();
|
||||
void OnAbout();
|
||||
void OnOpenDiscord();
|
||||
void UpdateEmulationStatusText();
|
||||
const MenuBarAccelerator * HotkeyAccelerator(const char * name);
|
||||
const char * IsMenuBarAccelerator(uint32_t keyCode, uint32_t keyboardState);
|
||||
|
|
@ -187,6 +192,7 @@ private:
|
|||
std::string m_windowTitle;
|
||||
std::unique_ptr<SystemConfig> m_systemConfig;
|
||||
std::unique_ptr<InputConfig> m_inputConfig;
|
||||
std::unique_ptr<AboutDialog> m_aboutDialog;
|
||||
WebBrowserApplet m_WebBrowser;
|
||||
float m_resolutionUpFactor;
|
||||
bool m_useMultiCore;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include "system_config_general.h"
|
||||
#include "system_config_graphics.h"
|
||||
#include "system_config_system.h"
|
||||
#include "user_interface/dpi_scaling.h"
|
||||
#include <common/std_string.h>
|
||||
#include <nxemu-core/settings/identifiers.h>
|
||||
#include <nxemu-core/settings/settings.h>
|
||||
|
|
@ -48,10 +47,7 @@ void SystemConfig::Display(void * parentWindow, const char * startPage)
|
|||
subPage = initialPage.substr(separator + 1);
|
||||
initialPage = initialPage.substr(0, separator);
|
||||
}
|
||||
int width = WINDOW_WIDTH;
|
||||
int height = WINDOW_HEIGHT;
|
||||
ScaleWindowSizeForDpi(parentWindow, width, height);
|
||||
if (!m_sciterUI.WindowCreate(parentWindow, "system_config.html", 0, 0, width, height, SUIW_CHILD, m_window))
|
||||
if (!m_sciterUI.WindowCreate(parentWindow, "system_config.html", 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, SUIW_CHILD, m_window))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue