Update os-gui to 0.6.0
parent
91a6466a5d
commit
d7e66471de
|
@ -84,10 +84,16 @@ $Window.Z_INDEX = 5;
|
|||
|
||||
var minimize_slots = []; // for if there's no taskbar
|
||||
|
||||
// @TODO: make this a class,
|
||||
// instead of a weird pseudo-class
|
||||
function $Window(options) {
|
||||
options = options || {};
|
||||
// @TODO: handle all option defaults here
|
||||
// and validate options.
|
||||
|
||||
var $w = $(E("div")).addClass("window os-window").appendTo("body");
|
||||
$w[0].$window = $w;
|
||||
$w.element = $w[0];
|
||||
$w[0].id = `os-window-${Math.random().toString(36).substr(2, 9)}`;
|
||||
$w.$titlebar = $(E("div")).addClass("window-titlebar").appendTo($w);
|
||||
$w.$title_area = $(E("div")).addClass("window-title-area").appendTo($w.$titlebar);
|
||||
|
@ -99,14 +105,20 @@ function $Window(options) {
|
|||
if (options.minimizeButton !== false) {
|
||||
$w.$minimize = $(E("button")).addClass("window-minimize-button window-action-minimize window-button").appendTo($w.$titlebar);
|
||||
$w.$minimize.attr("aria-label", "Minimize window"); // @TODO: for taskbarless minimized windows, "restore"
|
||||
$w.$minimize.append("<span class='window-button-icon'></span>");
|
||||
}
|
||||
if (options.maximizeButton !== false) {
|
||||
$w.$maximize = $(E("button")).addClass("window-maximize-button window-action-maximize window-button").appendTo($w.$titlebar);
|
||||
$w.$maximize.attr("aria-label", "Maximize or restore window"); // @TODO: specific text for the state
|
||||
if (!options.resizable) {
|
||||
$w.$maximize.attr("disabled", true);
|
||||
}
|
||||
$w.$maximize.append("<span class='window-button-icon'></span>");
|
||||
}
|
||||
if (options.closeButton !== false) {
|
||||
$w.$x = $(E("button")).addClass("window-close-button window-action-close window-button").appendTo($w.$titlebar);
|
||||
$w.$x.attr("aria-label", "Close window");
|
||||
$w.$x.append("<span class='window-button-icon'></span>");
|
||||
}
|
||||
$w.$content = $(E("div")).addClass("window-content").appendTo($w);
|
||||
$w.$content.attr("tabIndex", "-1");
|
||||
|
@ -146,6 +158,7 @@ function $Window(options) {
|
|||
$w.$icon.prependTo($w.$titlebar);
|
||||
}
|
||||
iconSize = target_icon_size;
|
||||
$w.trigger("icon-change");
|
||||
};
|
||||
$w.getTitlebarIconSize = function () {
|
||||
return iconSize;
|
||||
|
@ -203,12 +216,14 @@ function $Window(options) {
|
|||
old_$icon.replaceWith($w.$icon);
|
||||
$w.icon_name = icon_name;
|
||||
$w.task?.updateIcon();
|
||||
$w.trigger("icon-change");
|
||||
return $w;
|
||||
};
|
||||
$w.setIcons = (icons) => {
|
||||
$w.icons = icons;
|
||||
$w.setTitlebarIconSize(iconSize);
|
||||
$w.task?.updateIcon();
|
||||
// icon-change already sent by setTitlebarIconSize
|
||||
};
|
||||
|
||||
if ($component) {
|
||||
|
@ -552,19 +567,33 @@ function $Window(options) {
|
|||
|
||||
$w.css("touch-action", "none");
|
||||
|
||||
let minimize_target_el = null; // taskbar button (optional)
|
||||
$w.setMinimizeTarget = function (new_taskbar_button_el) {
|
||||
minimize_target_el = new_taskbar_button_el;
|
||||
};
|
||||
|
||||
let task;
|
||||
Object.defineProperty($w, "task", {
|
||||
get() {
|
||||
return task;
|
||||
},
|
||||
set(new_task) {
|
||||
console.warn("DEPRECATED: use $w.setMinimizeTarget(taskbar_button_el) instead of setting $window.task object");
|
||||
task = new_task;
|
||||
},
|
||||
});
|
||||
|
||||
let before_minimize;
|
||||
$w.minimize = () => {
|
||||
minimize_target_el = minimize_target_el || task?.$task[0];
|
||||
if (animating_titlebar) {
|
||||
when_done_animating_titlebar.push($w.minimize);
|
||||
return;
|
||||
}
|
||||
if ($w.is(":visible")) {
|
||||
if ($w.task) {
|
||||
// @TODO: API like $w.setMinimizeTarget(taskbarItemElement)
|
||||
// instead of this hacky way you have to set `task` on the window
|
||||
const $task = $w.task.$task;
|
||||
if (minimize_target_el && !$w.hasClass("minimized-without-taskbar")) {
|
||||
const before_rect = $w.$titlebar[0].getBoundingClientRect();
|
||||
const after_rect = $task[0].getBoundingClientRect();
|
||||
const after_rect = minimize_target_el.getBoundingClientRect();
|
||||
$w.animateTitlebar(before_rect, after_rect, () => {
|
||||
$w.hide();
|
||||
$w.blur();
|
||||
|
@ -693,8 +722,7 @@ function $Window(options) {
|
|||
return;
|
||||
}
|
||||
if ($w.is(":hidden")) {
|
||||
const $task = $w.task.$task;
|
||||
const before_rect = $task[0].getBoundingClientRect();
|
||||
const before_rect = minimize_target_el.getBoundingClientRect();
|
||||
$w.show();
|
||||
const after_rect = $w.$titlebar[0].getBoundingClientRect();
|
||||
$w.hide();
|
||||
|
@ -708,6 +736,9 @@ function $Window(options) {
|
|||
|
||||
let before_maximize;
|
||||
$w.maximize = () => {
|
||||
if (!options.resizable) {
|
||||
return;
|
||||
}
|
||||
if (animating_titlebar) {
|
||||
when_done_animating_titlebar.push($w.maximize);
|
||||
return;
|
||||
|
@ -1150,7 +1181,7 @@ You can also disable this warning by passing {iframes: {ignoreCrossOrigin: true}
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 27: // Esc
|
||||
case 27: // Escape
|
||||
// @TODO: make this optional, and probably default false
|
||||
$w.close();
|
||||
break;
|
||||
|
@ -1221,6 +1252,9 @@ You can also disable this warning by passing {iframes: {ignoreCrossOrigin: true}
|
|||
refocus();
|
||||
// Emulate :enabled:active:hover state with .pressing class
|
||||
const button = e.currentTarget;
|
||||
if (!$(button).is(":enabled")) {
|
||||
return;
|
||||
}
|
||||
button.classList.add("pressing");
|
||||
const release = (event) => {
|
||||
// blur is just to handle the edge case of alt+tabbing/ctrl+tabbing away
|
||||
|
@ -1445,6 +1479,7 @@ You can also disable this warning by passing {iframes: {ignoreCrossOrigin: true}
|
|||
$w.title = title => {
|
||||
if (title) {
|
||||
$w.$title.text(title);
|
||||
$w.trigger("title-change");
|
||||
if ($w.task) {
|
||||
$w.task.updateTitle();
|
||||
}
|
||||
|
@ -1536,6 +1571,22 @@ You can also disable this warning by passing {iframes: {ignoreCrossOrigin: true}
|
|||
};
|
||||
$w.closed = false;
|
||||
|
||||
let current_menu_bar;
|
||||
// @TODO: should this be like setMenus(menu_definitions)?
|
||||
// It seems like setMenuBar(menu_bar) might be prone to bugs
|
||||
// trying to set the same menu bar on multiple windows.
|
||||
$w.setMenuBar = (menu_bar) => {
|
||||
// $w.find(".menus").remove(); // ugly, if only because of the class name haha
|
||||
if (current_menu_bar) {
|
||||
current_menu_bar.element.remove();
|
||||
}
|
||||
if (menu_bar) {
|
||||
$w.$titlebar.after(menu_bar.element);
|
||||
menu_bar.setKeyboardScope($w[0]);
|
||||
current_menu_bar = menu_bar;
|
||||
}
|
||||
};
|
||||
|
||||
if (options.title) {
|
||||
$w.title(options.title);
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ function MenuBar(menus) {
|
|||
}
|
||||
top_level_highlight(-1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
const is_disabled = item => {
|
||||
if (typeof item.enabled === "function") {
|
||||
|
@ -334,20 +334,34 @@ function MenuBar(menus) {
|
|||
default:
|
||||
// handle accelerators and first-letter navigation
|
||||
const key = String.fromCharCode(e.keyCode).toLowerCase();
|
||||
const item_els = [...menu_popup_el.querySelectorAll(".menu-item")];
|
||||
const item_els = active_menu_popup ?
|
||||
[...menu_popup_el.querySelectorAll(".menu-item")] :
|
||||
top_level_menus.map(top_level_menu => top_level_menu.menu_button_el);
|
||||
const item_els_by_accelerator = {};
|
||||
for (const item_el of item_els) {
|
||||
const accelerator = item_el.querySelector(".menu-hotkey");
|
||||
const accelerator_key = (accelerator ? accelerator.textContent : item_el.querySelector(".menu-item-label").textContent[0]).toLowerCase();
|
||||
const accelerator_key = (accelerator ?
|
||||
accelerator.textContent :
|
||||
(item_el.querySelector(".menu-item-label") ?? item_el).textContent[0]
|
||||
).toLowerCase();
|
||||
item_els_by_accelerator[accelerator_key] = item_els_by_accelerator[accelerator_key] || [];
|
||||
item_els_by_accelerator[accelerator_key].push(item_el);
|
||||
}
|
||||
const matching_item_els = item_els_by_accelerator[key] || [];
|
||||
// console.log({ key, item_els, item_els_by_accelerator, matching_item_els });
|
||||
if (matching_item_els.length) {
|
||||
if (matching_item_els.length === 1) {
|
||||
// it's unambiguous, go ahead and activate it
|
||||
const menu_item_el = matching_item_els[0];
|
||||
menu_item_el.click();
|
||||
// click() doesn't work for menu buttons at the moment,
|
||||
// and also we want to highlight the first item in the menu
|
||||
// in that case, which doesn't happen with the mouse
|
||||
if (menu_item_el.classList.contains("menu-button")) {
|
||||
const top_level_menu = top_level_menus.find(top_level_menu => top_level_menu.menu_button_el === menu_item_el);
|
||||
top_level_menu.open_top_level_menu("keydown");
|
||||
} else {
|
||||
menu_item_el.click();
|
||||
}
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// cycle the menu items that match the key
|
||||
|
@ -814,28 +828,14 @@ function MenuBar(menus) {
|
|||
menu_button_el.setAttribute("aria-haspopup", "true");
|
||||
menu_button_el.setAttribute("aria-controls", menu_popup_el.id);
|
||||
|
||||
// @TODO: allow setting scope for alt shortcuts, like menuBar.setHotkeyScope(windowElement||window)
|
||||
// and add a helper to $Window to set up a menu bar, like $window.setMenuBar(menuBar||null)
|
||||
window.addEventListener("keydown", e => {
|
||||
if (e.ctrlKey || e.metaKey) { // Ctrl or Command held
|
||||
if (e.keyCode !== 17 && e.keyCode !== 91 && e.keyCode !== 93 && e.keyCode !== 224) { // anything but Ctrl or Command pressed
|
||||
close_menus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { // Alt held
|
||||
if (String.fromCharCode(e.keyCode) === get_hotkey(menus_key)) {
|
||||
e.preventDefault();
|
||||
open_top_level_menu("keydown");
|
||||
}
|
||||
}
|
||||
});
|
||||
menu_button_el.addEventListener("focus", () => {
|
||||
top_level_highlight(menus_key);
|
||||
});
|
||||
menu_button_el.addEventListener("pointerdown", e => {
|
||||
if (menu_button_el.classList.contains("active")) {
|
||||
menu_button_el.dispatchEvent(new CustomEvent("release", {}));
|
||||
refocus_window();
|
||||
e.preventDefault(); // needed for refocus_window() to work
|
||||
} else {
|
||||
open_top_level_menu(e.type);
|
||||
}
|
||||
|
@ -863,7 +863,7 @@ function MenuBar(menus) {
|
|||
// console.log("pointerdown (possibly simulated) — menu_popup_el.style.zIndex", menu_popup_el.style.zIndex, "$Window.Z_INDEX", $Window.Z_INDEX, "menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex);
|
||||
// setTimeout(() => { console.log("after timeout, menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex); }, 0);
|
||||
top_level_highlight(menus_key);
|
||||
|
||||
|
||||
menu_popup_el.dispatchEvent(new CustomEvent("update"), {});
|
||||
|
||||
selecting_menus = true;
|
||||
|
@ -894,6 +894,7 @@ function MenuBar(menus) {
|
|||
menu_button_el,
|
||||
menu_popup_el,
|
||||
menus_key,
|
||||
hotkey: get_hotkey(menus_key),
|
||||
open_top_level_menu,
|
||||
});
|
||||
};
|
||||
|
@ -918,7 +919,15 @@ function MenuBar(menus) {
|
|||
}
|
||||
}
|
||||
});
|
||||
window.addEventListener("blur", close_menus);
|
||||
// window.addEventListener("blur", close_menus);
|
||||
window.addEventListener("blur", (event) => {
|
||||
// hack for Pinball (in 98.js.org) where it triggers fake blur events
|
||||
// in order to pause the game
|
||||
if (!event.isTrusted) {
|
||||
return;
|
||||
}
|
||||
close_menus();
|
||||
});
|
||||
function close_menus_on_click_outside(event) {
|
||||
if (event.target?.closest?.(".menus, .menu-popup")) {
|
||||
return;
|
||||
|
@ -929,7 +938,51 @@ function MenuBar(menus) {
|
|||
window.addEventListener("pointerdown", close_menus_on_click_outside);
|
||||
window.addEventListener("pointerup", close_menus_on_click_outside);
|
||||
|
||||
let keyboard_scope_elements = [];
|
||||
function set_keyboard_scope(...elements) {
|
||||
for (const el of keyboard_scope_elements) {
|
||||
el.removeEventListener("keydown", keyboard_scope_keydown);
|
||||
}
|
||||
keyboard_scope_elements = elements;
|
||||
for (const el of keyboard_scope_elements) {
|
||||
el.addEventListener("keydown", keyboard_scope_keydown);
|
||||
}
|
||||
}
|
||||
function keyboard_scope_keydown(e) {
|
||||
// Close menus if the user presses almost any key combination
|
||||
// e.g. if you look in the menu to remember a shortcut,
|
||||
// and then use the shortcut.
|
||||
if (
|
||||
(e.ctrlKey || e.metaKey) && // Ctrl or Command held down
|
||||
// and anything then pressed other than Ctrl or Command
|
||||
e.keyCode !== 17 &&
|
||||
e.keyCode !== 91 &&
|
||||
e.keyCode !== 93 &&
|
||||
e.keyCode !== 224
|
||||
) {
|
||||
close_menus();
|
||||
return;
|
||||
}
|
||||
if (e.defaultPrevented) {
|
||||
return; // closing menus above is meant to be done when activating unrelated shortcuts
|
||||
// but stuff after this is should not be handled at the same time as something else
|
||||
}
|
||||
if (e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { // Alt held
|
||||
const menu = top_level_menus.find((menu) =>
|
||||
menu.hotkey.toLowerCase() === String.fromCharCode(e.keyCode).toLowerCase()
|
||||
);
|
||||
if (menu) {
|
||||
e.preventDefault();
|
||||
menu.open_top_level_menu("keydown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_keyboard_scope(window);
|
||||
|
||||
this.element = menus_el;
|
||||
this.closeMenus = close_menus;
|
||||
this.setKeyboardScope = set_keyboard_scope;
|
||||
}
|
||||
|
||||
exports.MenuBar = MenuBar;
|
||||
|
|
|
@ -276,3 +276,42 @@ function makeThemeCSSFile(cssProperties) {
|
|||
`;
|
||||
return css;
|
||||
}
|
||||
|
||||
// @TODO: should this be part of theme graphics generation?
|
||||
// I want to figure out a better way to do dynamic theme features,
|
||||
// where it works with the CSS cascade as much as possible
|
||||
function makeBlackToInsetFilter() {
|
||||
if (document.getElementById("os-gui-black-to-inset-filter")) {
|
||||
return;
|
||||
}
|
||||
const svg_xml = `
|
||||
<svg style="position: absolute; pointer-events: none; bottom: 100%;">
|
||||
<defs>
|
||||
<filter id="os-gui-black-to-inset-filter" x="0" y="0" width="1px" height="1px">
|
||||
<feColorMatrix
|
||||
in="SourceGraphic"
|
||||
type="matrix"
|
||||
values="
|
||||
1 0 0 0 0
|
||||
0 1 0 0 0
|
||||
0 0 1 0 0
|
||||
-1000 -1000 -1000 1 0
|
||||
"
|
||||
result="black-parts-isolated"
|
||||
/>
|
||||
<feFlood result="shadow-color" flood-color="var(--ButtonShadow)"/>
|
||||
<feFlood result="hilight-color" flood-color="var(--ButtonHilight)"/>
|
||||
<feOffset in="black-parts-isolated" dx="1" dy="1" result="offset"/>
|
||||
<feComposite in="hilight-color" in2="offset" operator="in" result="hilight-colored-offset"/>
|
||||
<feComposite in="shadow-color" in2="black-parts-isolated" operator="in" result="shadow-colored"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="hilight-colored-offset"/>
|
||||
<feMergeNode in="shadow-colored"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
const $svg = $(svg_xml);
|
||||
$svg.appendTo("body");
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ button:not(.lightweight).default:enabled:hover:active {
|
|||
}
|
||||
*/
|
||||
/* also, this is more complicated; see Paint; the tool buttons translate when being pushed and when depressed, and these add together */
|
||||
/* omg, a thought... what if I used feDisplacementMap SVG filter... */
|
||||
|
||||
button:not(.lightweight):focus::before {
|
||||
content: "";
|
||||
|
@ -316,9 +317,77 @@ body > .window-titlebar {
|
|||
border-width: 2px 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.window-button {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
padding: 0;
|
||||
margin: 2px 0;
|
||||
}
|
||||
.window-button-icon {
|
||||
display: block;
|
||||
/* background-image: url("images/titlebar-buttons.png"); */
|
||||
--sprite-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAKCAYAAADo3z3CAAAAoUlEQVRIS9VVWw7AIAib9z/0FpZgCOFRgpluf9MClhYdV++7gfDhYLxYDw+UyiHd5F8S5lr6zNa6Xpv/KwhHOahQpLB1+CwfycgYrwmE0WK8MTsIR1aOGsR+NYkkYzN5/pGwVA9xA/diq8LeHCKuQxQ+aoYt2yJWtpSNZth0edRpGVC5eGQcSg4hXLml3fdpBeHs8evWyPKX9ruXVqnYCeAHA8IyC9K2kmkAAAAASUVORK5CYII=");
|
||||
--sprite-y: 0;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
width: 12px;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
}
|
||||
.os-window .window-button:enabled:hover:active .window-button-icon,
|
||||
.os-window .window-button.pressing .window-button-icon {
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
.window-button:disabled .window-button-icon {
|
||||
/* filter: saturate(0%) opacity(50%); fallback */
|
||||
/* filter: url("#os-gui-black-to-inset-filter"); */
|
||||
}
|
||||
.window-button .window-button-icon::before,
|
||||
.window-button .window-button-icon::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-mask-image: var(--sprite-image);
|
||||
mask-image: var(--sprite-image);
|
||||
-webkit-mask-position: var(--sprite-x) var(--sprite-y);
|
||||
mask-position: var(--sprite-x) var(--sprite-y);
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-color: var(--ButtonText);
|
||||
}
|
||||
.window-button:disabled .window-button-icon::before {
|
||||
background-color: rgb(255, 255, 255);
|
||||
background-color: var(--ButtonHilight);
|
||||
left: 1px;
|
||||
top: 1px;
|
||||
}
|
||||
.window-button:enabled .window-button-icon::after {
|
||||
display: none;
|
||||
}
|
||||
.window-button:disabled .window-button-icon::after {
|
||||
background-color: rgb(128, 128, 128);
|
||||
background-color: var(--GrayText);
|
||||
}
|
||||
.window-action-close .window-button-icon {
|
||||
--sprite-x: calc(-3 * 13px - 1px);
|
||||
}
|
||||
.window-action-maximize .window-button-icon {
|
||||
--sprite-x: calc(-1 * 13px - 1px);
|
||||
}
|
||||
.window-action-restore .window-button-icon {
|
||||
--sprite-x: calc(-2 * 13px - 1px);
|
||||
}
|
||||
.window-action-minimize .window-button-icon {
|
||||
--sprite-x: calc(-0 * 13px - 1px);
|
||||
}
|
||||
.window-close-button {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
|
@ -326,11 +395,11 @@ body > .window-titlebar {
|
|||
.os-window.tool-window .window-close-button {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background-position: 7px 0;
|
||||
}
|
||||
.os-window.tool-window .window-close-button:enabled:hover:active,
|
||||
.os-window.tool-window .window-close-button.pressing {
|
||||
background-position: 8px 1px;
|
||||
.os-window.tool-window .window-close-button .window-button-icon {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
--sprite-x: 7px;
|
||||
}
|
||||
.os-window .window-title-area {
|
||||
height: 16px;
|
||||
|
@ -358,55 +427,6 @@ body > .window-titlebar {
|
|||
white-space: nowrap;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.window-close-button {
|
||||
/* display: block !important; */
|
||||
/* float: right; */
|
||||
/* width: 13px;
|
||||
height: 11px; */
|
||||
}
|
||||
.window-close-button,
|
||||
.window-maximize-button,
|
||||
.window-minimize-button {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAKCAYAAADo3z3CAAAAoUlEQVRIS9VVWw7AIAib9z/0FpZgCOFRgpluf9MClhYdV++7gfDhYLxYDw+UyiHd5F8S5lr6zNa6Xpv/KwhHOahQpLB1+CwfycgYrwmE0WK8MTsIR1aOGsR+NYkkYzN5/pGwVA9xA/diq8LeHCKuQxQ+aoYt2yJWtpSNZth0edRpGVC5eGQcSg4hXLml3fdpBeHs8evWyPKX9ruXVqnYCeAHA8IyC9K2kmkAAAAASUVORK5CYII=");
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.window-action-close {
|
||||
background-position: calc(-3 * 13px - 1px) 0px;
|
||||
}
|
||||
.window-action-maximize {
|
||||
background-position: calc(-1 * 13px - 1px) 0px;
|
||||
}
|
||||
.window-action-restore {
|
||||
background-position: calc(-2 * 13px - 1px) 0px;
|
||||
}
|
||||
.window-action-minimize {
|
||||
background-position: calc(-0 * 13px - 1px) 0px;
|
||||
}
|
||||
|
||||
.window-action-close:enabled:hover:active,
|
||||
.window-action-close.pressing {
|
||||
background-position: calc(-3 * 13px - 0px) 1px;
|
||||
}
|
||||
.window-action-maximize:enabled:hover:active,
|
||||
.window-action-maximize.pressing {
|
||||
background-position: calc(-1 * 13px - 0px) 1px;
|
||||
}
|
||||
.window-action-restore:enabled:hover:active,
|
||||
.window-action-restore.pressing {
|
||||
background-position: calc(-2 * 13px - 0px) 1px;
|
||||
}
|
||||
.window-action-minimize:enabled:hover:active,
|
||||
.window-action-minimize.pressing {
|
||||
background-position: calc(-0 * 13px - 0px) 1px;
|
||||
}
|
||||
|
||||
|
||||
.menus {
|
||||
background: rgb(192, 192, 192);
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue