mirror of
https://github.com/catppuccin/catppuccin
synced 2024-11-21 19:13:05 +00:00
feat: added palettes generator script, some rust samples and wcag-compliace tests
This commit is contained in:
parent
86248b77f1
commit
4285b456a5
9 changed files with 1827 additions and 2 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules/
|
263
resources/palettes_gen.sh
Executable file
263
resources/palettes_gen.sh
Executable file
|
@ -0,0 +1,263 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ---- sys
|
||||
NC=" \033[0m"
|
||||
coerce=false
|
||||
lowercase=false
|
||||
file=""
|
||||
prefix=""
|
||||
original_palette="storm"
|
||||
verbosity=0
|
||||
|
||||
script_help=$(
|
||||
cat <<EOF
|
||||
Generate missing Catppuccin palettes from a base file (e.g. generate a dawn.conf & a dusk.conf from a storm.conf file)
|
||||
|
||||
Usages:
|
||||
#0: $(basename "$0") <flag> [arg]
|
||||
|
||||
Flags:
|
||||
-f, --file specify file (mandatory)
|
||||
-v, --verbose increase verbosity by 1
|
||||
-o, --original-palette the palette used in the based file (given by --file)
|
||||
-l, --lowercase replaces with lowercased hex codes
|
||||
-c, --coerce force the creation of new palette files (useful when those files already exist)
|
||||
-p, --prefix specify which prefix to use for the hex codes. Surround it with double quotes if needed.
|
||||
-h, --help see this message
|
||||
EOF
|
||||
)
|
||||
|
||||
palette_names=(
|
||||
storm
|
||||
dusk
|
||||
dawn
|
||||
)
|
||||
|
||||
declare -A dusk=(
|
||||
[white]='C6D0F5'
|
||||
[peach]='FAB387'
|
||||
[gray2]='ADB5D8'
|
||||
[black0]='101019'
|
||||
[black1]='181825'
|
||||
[gray1]='959BBA'
|
||||
[blue]='90C1FB'
|
||||
[green]='A6E3A1'
|
||||
[sapphire]='74C7EC'
|
||||
[black3]='323044'
|
||||
[black4]='4B4B62'
|
||||
[black5]='63657F'
|
||||
[teal]='94E2D5'
|
||||
[gray0]='7C809D'
|
||||
[rosewater]='F5E0DC'
|
||||
[maroon]='EBA0AC'
|
||||
[lavender]='C9CBFF'
|
||||
[yellow]='F9E2AF'
|
||||
[flamingo]='F2CDCD'
|
||||
[sky]='89DCEB'
|
||||
[mauve]='CBA6F7'
|
||||
[black2]='1E1E2E'
|
||||
[pink]='F5C2E7'
|
||||
[red]='F38BA8'
|
||||
)
|
||||
|
||||
declare -A storm=(
|
||||
[white]='C5CFF5'
|
||||
[sapphire]='34C3DC'
|
||||
[pink]='F5BFE7'
|
||||
[rosewater]='F5DFDA'
|
||||
[black2]='24273A'
|
||||
[flamingo]='F2CBCB'
|
||||
[red]='F67E98'
|
||||
[maroon]='F1949B'
|
||||
[peach]='FEA571'
|
||||
[black1]='1F2233'
|
||||
[sky]='89DCFD'
|
||||
[gray1]='8289AA'
|
||||
[lavender]='C2CBFE'
|
||||
[black3]='2B3045'
|
||||
[green]='A1DF8E'
|
||||
[black4]='3E435E'
|
||||
[yellow]='F1D8A4'
|
||||
[gray2]='A6AFD2'
|
||||
[blue]='83ABF9'
|
||||
[black0]='1A1B26'
|
||||
[gray0]='5F6587'
|
||||
[teal]='85E0D1'
|
||||
[black5]='4F5473'
|
||||
[mauve]='C59FF6'
|
||||
)
|
||||
|
||||
declare -A dawn=(
|
||||
[black4]='CCC9D1'
|
||||
[peach]='FE6811'
|
||||
[black3]='E6E3E5'
|
||||
[pink]='EC83D0'
|
||||
[black0]='D3D0D2'
|
||||
[black1]='EDEDED'
|
||||
[blue]='1D65F5'
|
||||
[lavender]='7287FD'
|
||||
[mauve]='8F46EF'
|
||||
[black5]='B5B1BF'
|
||||
[maroon]='E63B4A'
|
||||
[rosewater]='E5AC9F'
|
||||
[green]='509E31'
|
||||
[gray1]='86819C'
|
||||
[black2]='FBF8F4'
|
||||
[white]='575279'
|
||||
[gray2]='6E6A8B'
|
||||
[sky]='04A5E5'
|
||||
[sapphire]='209FB5'
|
||||
[red]='D20F39'
|
||||
[teal]='289886'
|
||||
[gray0]='9D99AE'
|
||||
[flamingo]='DF7F7F'
|
||||
[yellow]='E49320'
|
||||
)
|
||||
|
||||
function prompt() {
|
||||
local type=${1} # error, success, warning, info
|
||||
local message=${2}
|
||||
local modifiers=${3}
|
||||
|
||||
if [[ $1 == "-i" || $1 == "--info" ]]; then
|
||||
type=""
|
||||
fi
|
||||
|
||||
case ${type} in
|
||||
"-e" | "--error")
|
||||
printf "\033[0;31m${modifiers}ERROR: %s${NC}\n" "${message}"
|
||||
;;
|
||||
"-s" | "--success")
|
||||
printf "\033[0;32m${modifiers}SUCCESS: %s${NC}\n" "${message}"
|
||||
;;
|
||||
"-w" | "--warning")
|
||||
printf "\033[0;33m${modifiers}WARNING: %s${NC}\n" "${message}"
|
||||
;;
|
||||
*)
|
||||
printf "\033[0;34m${modifiers}INFO: %s${NC}\n" "${message}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function verbose_print() {
|
||||
# $1 = message
|
||||
# $2 = modifiers
|
||||
if [[ $verbosity -gt 0 ]]; then
|
||||
printf "\033[3;29m${2}%s${NC}\n" "${1}"
|
||||
fi
|
||||
}
|
||||
|
||||
function generate_palettes() {
|
||||
capitalization_char='\U' # uppercase
|
||||
[[ $lowercase == true ]] && {
|
||||
capitalization_char='\L' # lowercase
|
||||
}
|
||||
|
||||
new_array=()
|
||||
for val in "${palette_names[@]}"; do
|
||||
[[ "$val" != "$original_palette" ]] && new_array+=("$val")
|
||||
done
|
||||
palette_names=("${new_array[@]}")
|
||||
unset new_array
|
||||
|
||||
for palette in "${palette_names[@]}"; do
|
||||
printf " GENERATING: \033[3;32m%s${NC}\n" "$palette"
|
||||
|
||||
local dest_file="${palette}.${file##*.}"
|
||||
prompt -w "creating $dest_file..." "\t• "
|
||||
|
||||
if [[ -f $dest_file ]]; then
|
||||
if [[ ! $coerce == true ]]; then
|
||||
prompt -e "file '$dest_file' already exists. Use --coerce to force it's replacement" "\t• "
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cp "$file" "$dest_file"
|
||||
prompt -i "replacing colors..." "\t• "
|
||||
|
||||
for clr in "${!storm[@]}"; do
|
||||
local curr_color=$(eval "echo \${${original_palette}[$clr]}")
|
||||
local dest_color=$(eval "echo \${${palette}[${clr}]}")
|
||||
verbose_print "modifying ${clr}" "\t + "
|
||||
sed -i "s/${curr_color}/${prefix}${capitalization_char}${dest_color}/gI" "$dest_file"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
function detect_original_palette() {
|
||||
prompt -w "detecting palette..."
|
||||
original_palette=""
|
||||
for palette in "${palette_names[@]}"; do
|
||||
for clr in "${!storm[@]}"; do
|
||||
if grep -q $(eval "echo \${${palette}[${clr}]}") "$file"; then
|
||||
original_palette=$palette
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ $original_palette == "" ]]; then
|
||||
prompt -e "couldn't detect the original palette"
|
||||
exit 1
|
||||
else
|
||||
prompt -s "detected '$original_palette'"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
if [[ ! "$#" -gt 0 ]]; then
|
||||
prompt -e "you must provide at least the file you want to generate the missing palettes from"
|
||||
else
|
||||
local help_used=false
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-v | --verbose)
|
||||
verbosity=$((verbosity + 1))
|
||||
;;
|
||||
-f | --file)
|
||||
file=$2
|
||||
shift
|
||||
;;
|
||||
-o | --original-palette)
|
||||
origianl_palette=$2
|
||||
shift
|
||||
;;
|
||||
-l | --lowercase)
|
||||
lowercase=true
|
||||
;;
|
||||
-c | --coerce)
|
||||
coerce=true
|
||||
;;
|
||||
-p | --prefix)
|
||||
prefix=$2
|
||||
shift
|
||||
;;
|
||||
-h | --help)
|
||||
help_used=true
|
||||
echo "$script_help"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: command ($1) not recognized"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ $help_used != "true" ]]; then
|
||||
if [[ $file != "" ]]; then
|
||||
[[ -f $file ]] && {
|
||||
prompt "updating colors..."
|
||||
if [[ original_palette != "storm" || original_palette != "dusk" || original_palette != "dawn" ]]; then
|
||||
detect_original_palette
|
||||
fi
|
||||
generate_palettes
|
||||
} || prompt -e "file ${1} does not exist"
|
||||
else
|
||||
prompt -e "please profive a file to use a base using the --file flag"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
131
samples/header.h
Normal file
131
samples/header.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* appearance */
|
||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||
static const unsigned int snap = 32; /* snap pixel */
|
||||
static const int showbar = 1; /* 0 means no bar */
|
||||
static const int topbar = 1; /* 0 means bottom bar */
|
||||
static const char *fonts[] = { "monospace:size=10" };
|
||||
static const char dmenufont[] = "monospace:size=10";
|
||||
static const char col_gray1[] = "#5F6587";
|
||||
static const char col_gray2[] = "#8289AA";
|
||||
static const char col_gray3[] = "#A6AFD2";
|
||||
static const char col_gray4[] = "#C5CFF5";
|
||||
static const char col_teal[] = "#78DCCC";
|
||||
static const char *colors[][3] = {
|
||||
/* fg bg border */
|
||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
|
||||
[SchemeSel] = { col_gray4, col_teal, col_teal },
|
||||
};
|
||||
|
||||
/* tagging */
|
||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
|
||||
static const Rule rules[] = {
|
||||
/* xprop(1):
|
||||
* WM_CLASS(STRING) = instance, class
|
||||
* WM_NAME(STRING) = title
|
||||
*/
|
||||
/* class instance title tags mask isfloating monitor */
|
||||
{ "Gimp", NULL, NULL, 0, 1, -1 },
|
||||
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
||||
};
|
||||
static const int ruleperiod = 5; /* number of seconds before rules are ignored */
|
||||
|
||||
/* layout(s) */
|
||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
|
||||
static const int nmaster = 1; /* number of clients in master area */
|
||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
|
||||
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
|
||||
|
||||
static const LayoutMonitorRule lm_rules[] = {
|
||||
/* >=w, >=h, req'd layout, new nmaster, new mfact */
|
||||
{ 3000, 0, 0, 2, 0.66 },
|
||||
};
|
||||
|
||||
static const Layout layouts[] = {
|
||||
/* symbol arrange function */
|
||||
{ "[]=", tile }, /* first entry is default */
|
||||
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||
{ "[M]", monocle },
|
||||
{ "TTT", bstack },
|
||||
{ "===", bstackhoriz },
|
||||
};
|
||||
|
||||
/* key definitions */
|
||||
#define MODKEY Mod1Mask
|
||||
#define TAGKEYS(KEY,TAG) \
|
||||
{ KeyPress, MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||
{ KeyPress, MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||
{ KeyPress, MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
|
||||
{ KeyPress, MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
|
||||
|
||||
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
|
||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||
|
||||
/* commands */
|
||||
static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
|
||||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_teal, "-sf", col_gray4, NULL };
|
||||
static const char *termcmd[] = { "st", NULL };
|
||||
|
||||
#include "movestack.c"
|
||||
static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
||||
{ MODKEY, XK_b, togglebar, {0} },
|
||||
{ MODKEY, XK_j, focusstack, {.i = +1 } },
|
||||
{ MODKEY, XK_k, focusstack, {.i = -1 } },
|
||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
|
||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
|
||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
|
||||
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
|
||||
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
|
||||
{ MODKEY, XK_Return, zoom, {0} },
|
||||
{ MODKEY, XK_Tab, view, {0} },
|
||||
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
|
||||
{ MODKEY|ShiftMask, XK_x, killunsel, {0} },
|
||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
|
||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
|
||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
|
||||
{ MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
|
||||
{ MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
|
||||
{ MODKEY, XK_space, setlayout, {0} },
|
||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
|
||||
{ MODKEY, XK_0, view, {.ui = ~0 } },
|
||||
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
|
||||
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
|
||||
{ MODKEY, XK_period, focusmon, {.i = +1 } },
|
||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
|
||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
|
||||
{ MODKEY|ControlMask, XK_comma, tagallmon, {.i = -1 } },
|
||||
{ MODKEY|ControlMask, XK_period, tagallmon, {.i = +1 } },
|
||||
TAGKEYS( XK_1, 0)
|
||||
TAGKEYS( XK_2, 1)
|
||||
TAGKEYS( XK_3, 2)
|
||||
TAGKEYS( XK_4, 3)
|
||||
TAGKEYS( XK_5, 4)
|
||||
TAGKEYS( XK_6, 5)
|
||||
TAGKEYS( XK_7, 6)
|
||||
TAGKEYS( XK_8, 7)
|
||||
TAGKEYS( XK_9, 8)
|
||||
{ KeyPress, MODKEY|ShiftMask, XK_q, quit, {0} },
|
||||
};
|
||||
|
||||
/* button definitions */
|
||||
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
|
||||
static Button buttons[] = {
|
||||
/* click event mask button function argument */
|
||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
|
||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
|
||||
{ ClkWinTitle, 0, Button2, zoom, {0} },
|
||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
|
||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
|
||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
|
||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
|
||||
{ ClkTagBar, 0, Button1, view, {0} },
|
||||
{ ClkTagBar, 0, Button3, toggleview, {0} },
|
||||
{ ClkTagBar, MODKEY, Button1, tag, {0} },
|
||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
|
||||
};
|
|
@ -1,5 +1,3 @@
|
|||
// Simple program made by a simple programmer
|
||||
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![allow(elided_lifetimes_in_paths)]
|
||||
|
961
samples/rust/1.rs
Normal file
961
samples/rust/1.rs
Normal file
|
@ -0,0 +1,961 @@
|
|||
use crate::context::DrawContext;
|
||||
use crate::controller::Controller;
|
||||
use crate::font::FontCache;
|
||||
use crate::scene::*;
|
||||
use crate::wayland::*;
|
||||
use crate::*;
|
||||
use smithay_client_toolkit::reexports::calloop::{EventLoop, LoopHandle, RegistrationToken};
|
||||
use smithay_client_toolkit::seat::keyboard::ModifiersState;
|
||||
use smithay_client_toolkit::shm::AutoMemPool;
|
||||
use smithay_client_toolkit::WaylandSource;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use smithay_client_toolkit::reexports::client::{
|
||||
global_filter,
|
||||
protocol::wl_buffer::WlBuffer,
|
||||
protocol::wl_callback,
|
||||
protocol::wl_compositor::WlCompositor,
|
||||
protocol::wl_output::{self, WlOutput},
|
||||
protocol::wl_pointer::{self, WlPointer},
|
||||
protocol::wl_region::WlRegion,
|
||||
protocol::wl_seat::{self, Capability, WlSeat},
|
||||
protocol::wl_shm::WlShm,
|
||||
protocol::wl_surface::WlSurface,
|
||||
Attached, Display, GlobalError, GlobalManager, Interface, Main, Proxy,
|
||||
};
|
||||
use smithay_client_toolkit::reexports::protocols::wlr::unstable::layer_shell::v1::client::{
|
||||
zwlr_layer_shell_v1::ZwlrLayerShellV1, zwlr_layer_surface_v1,
|
||||
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||
};
|
||||
|
||||
pub struct Application<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
display: Display,
|
||||
globals: Rc<RefCell<Globals>>,
|
||||
global_manager: GlobalManager,
|
||||
pub inner: Vec<InnerApplication<M, C>>,
|
||||
token: RegistrationToken,
|
||||
}
|
||||
|
||||
struct Context {
|
||||
pending_cb: bool,
|
||||
time: Option<u32>,
|
||||
render_node: Option<RenderNode>,
|
||||
font_cache: FontCache,
|
||||
}
|
||||
|
||||
pub struct CoreApplication<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone,
|
||||
{
|
||||
pub controller: C,
|
||||
ctx: Context,
|
||||
globals: Rc<RefCell<Globals>>,
|
||||
mempool: AutoMemPool,
|
||||
widget: Box<dyn Widget<M>>,
|
||||
surface: Option<Surface>,
|
||||
}
|
||||
|
||||
pub struct InnerApplication<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone,
|
||||
{
|
||||
core: CoreApplication<M, C>,
|
||||
cb: Box<dyn FnMut(&mut CoreApplication<M, C>, Event<M>)>,
|
||||
}
|
||||
|
||||
impl Surface {
|
||||
fn new(
|
||||
surface: Main<WlSurface>,
|
||||
shell: Shell,
|
||||
region: Main<WlRegion>,
|
||||
previous: Option<Surface>,
|
||||
) -> Self {
|
||||
Surface {
|
||||
alive: true,
|
||||
surface,
|
||||
shell,
|
||||
region,
|
||||
previous: if let Some(surface) = previous {
|
||||
Some(Box::new(surface))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
buffer: None,
|
||||
}
|
||||
}
|
||||
fn commit(&mut self) {
|
||||
self.surface.commit();
|
||||
std::mem::drop(&mut self.previous);
|
||||
self.previous = None;
|
||||
}
|
||||
fn destroy(&mut self) {
|
||||
self.alive = false;
|
||||
self.surface.destroy();
|
||||
self.region.destroy();
|
||||
self.shell.destroy();
|
||||
if let Some(buffer) = self.buffer.as_ref() {
|
||||
buffer.destroy();
|
||||
}
|
||||
self.buffer = None;
|
||||
}
|
||||
fn destroy_previous(&mut self) {
|
||||
if let Some(surface) = self.previous.as_mut() {
|
||||
surface.destroy();
|
||||
}
|
||||
self.previous = None;
|
||||
}
|
||||
fn set_size(&self, width: u32, height: u32) {
|
||||
self.shell.set_size(width, height);
|
||||
}
|
||||
fn damage(&self, report: &[Region]) {
|
||||
self.surface.attach(self.buffer.as_ref(), 0, 0);
|
||||
for d in report {
|
||||
self.surface
|
||||
.damage(d.x as i32, d.y as i32, d.width as i32, d.height as i32);
|
||||
}
|
||||
}
|
||||
fn attach_buffer(&mut self, buffer: WlBuffer) {
|
||||
self.buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
impl Globals {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
outputs: Vec::new(),
|
||||
seats: Vec::new(),
|
||||
shm: None,
|
||||
compositor: None,
|
||||
shell: None,
|
||||
}
|
||||
}
|
||||
pub fn create_shell_surface_from<M, C>(
|
||||
&self,
|
||||
geometry: &dyn Widget<M>,
|
||||
config: ShellConfig,
|
||||
previous: Option<Surface>,
|
||||
) -> Option<Surface>
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
if self.compositor.is_some() {
|
||||
match config {
|
||||
ShellConfig::LayerShell(config) => {
|
||||
if let Some(layer_shell) = self.shell.as_ref() {
|
||||
let region = self.compositor.as_ref().unwrap().create_region();
|
||||
let wl_surface = self.compositor.as_ref().unwrap().create_surface();
|
||||
let layer_surface = layer_shell.get_layer_surface(
|
||||
&wl_surface,
|
||||
config.output.as_ref(),
|
||||
config.layer,
|
||||
config.namespace.clone(),
|
||||
);
|
||||
if let Some(anchor) = &config.anchor {
|
||||
layer_surface.set_anchor(*anchor);
|
||||
}
|
||||
wl_surface.quick_assign(|_, _, _| {});
|
||||
layer_surface.set_exclusive_zone(config.exclusive);
|
||||
layer_surface.set_keyboard_interactivity(config.interactivity);
|
||||
layer_surface.set_size(geometry.width() as u32, geometry.height() as u32);
|
||||
layer_surface.set_margin(
|
||||
config.margin[0],
|
||||
config.margin[1],
|
||||
config.margin[2],
|
||||
config.margin[3],
|
||||
);
|
||||
wl_surface.commit();
|
||||
assign_surface::<M, C>(&layer_surface);
|
||||
return Some(Surface::new(
|
||||
wl_surface,
|
||||
Shell::LayerShell {
|
||||
surface: layer_surface,
|
||||
config,
|
||||
},
|
||||
region,
|
||||
previous,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn create_mempool(&self) -> AutoMemPool {
|
||||
let attached = Attached::from(self.shm.clone().unwrap());
|
||||
AutoMemPool::new(attached).unwrap()
|
||||
}
|
||||
pub fn get_outputs(&self) -> Vec<Output> {
|
||||
self.outputs.clone()
|
||||
}
|
||||
pub fn get_seats(&self) -> &[Seat] {
|
||||
&self.seats
|
||||
}
|
||||
}
|
||||
|
||||
impl Output {
|
||||
fn new(output: Main<WlOutput>) -> Self {
|
||||
Output {
|
||||
width: 0,
|
||||
height: 0,
|
||||
scale: 1,
|
||||
name: String::new(),
|
||||
output,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> Application<M, C>
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
pub fn new(pointer: bool) -> (Self, EventLoop<'static, Self>) {
|
||||
let display = Display::connect_to_env().unwrap();
|
||||
let event_queue = display.create_event_queue();
|
||||
let attached_display = (*display).clone().attach(event_queue.token());
|
||||
|
||||
let display_handle = display.clone();
|
||||
|
||||
let globals = Globals::new();
|
||||
|
||||
let global_manager = GlobalManager::new_with_cb(
|
||||
&attached_display,
|
||||
global_filter!(
|
||||
[
|
||||
ZwlrLayerShellV1,
|
||||
1,
|
||||
|layer_shell: Main<ZwlrLayerShellV1>, mut application: DispatchData| {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
globals.shell = Some(layer_shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
WlShm,
|
||||
1,
|
||||
|shm: Main<WlShm>, mut application: DispatchData| {
|
||||
shm.quick_assign(|_, _, _| {});
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
globals.shm = Some(shm);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
WlCompositor,
|
||||
4,
|
||||
|compositor: Main<WlCompositor>, mut application: DispatchData| {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
globals.compositor = Some(compositor);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[WlSeat, 7, move |seat: Main<WlSeat>, _: DispatchData| {
|
||||
seat.quick_assign(move |wl_seat, event, mut application| match event {
|
||||
wl_seat::Event::Capabilities { capabilities } => {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if pointer
|
||||
&& capabilities & Capability::Pointer == Capability::Pointer
|
||||
{
|
||||
let pointer = wl_seat.get_pointer();
|
||||
assign_pointer::<M, C>(&pointer);
|
||||
}
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
let mut found = None;
|
||||
for seat in &mut globals.seats {
|
||||
if wl_seat.eq(&seat.seat) {
|
||||
found = Some(());
|
||||
seat.capabilities = capabilities;
|
||||
}
|
||||
}
|
||||
if found.is_none() {
|
||||
globals.seats.push(Seat {
|
||||
capabilities,
|
||||
seat: wl_seat,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}],
|
||||
[
|
||||
WlOutput,
|
||||
3,
|
||||
|output: Main<WlOutput>, _application: DispatchData| {
|
||||
output.quick_assign(move |wl_output, event, mut application| match event {
|
||||
wl_output::Event::Geometry {
|
||||
x: _,
|
||||
y: _,
|
||||
physical_width: _,
|
||||
physical_height: _,
|
||||
subpixel: _,
|
||||
make,
|
||||
model: _,
|
||||
transform: _,
|
||||
} => {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
let mut found = None;
|
||||
for output in &mut globals.outputs {
|
||||
if wl_output.eq(&output.output) {
|
||||
found = Some(());
|
||||
output.name = make.clone();
|
||||
}
|
||||
}
|
||||
if found.is_none() {
|
||||
let mut output = Output::new(wl_output);
|
||||
output.name = make;
|
||||
globals.outputs.push(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_output::Event::Mode {
|
||||
flags: _,
|
||||
width,
|
||||
height,
|
||||
refresh: _,
|
||||
} => {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
let mut found = None;
|
||||
for output in &mut globals.outputs {
|
||||
if wl_output.eq(&output.output) {
|
||||
found = Some(());
|
||||
output.width = width;
|
||||
output.height = height;
|
||||
}
|
||||
}
|
||||
if found.is_none() {
|
||||
let mut output = Output::new(wl_output);
|
||||
output.width = width;
|
||||
output.height = height;
|
||||
globals.outputs.push(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_output::Event::Scale { factor } => {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Ok(mut globals) = application.globals.try_borrow_mut() {
|
||||
let mut found = None;
|
||||
for output in &mut globals.outputs {
|
||||
if wl_output.eq(&output.output) {
|
||||
found = Some(());
|
||||
output.scale = factor;
|
||||
}
|
||||
}
|
||||
if found.is_none() {
|
||||
let mut output = Output::new(wl_output);
|
||||
output.scale = factor;
|
||||
globals.outputs.push(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_output::Event::Done => {}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
]
|
||||
),
|
||||
);
|
||||
|
||||
let event_loop = EventLoop::try_new().expect("Failed to initialize the event loop!");
|
||||
let token = WaylandSource::new(event_queue)
|
||||
.quick_insert(event_loop.handle())
|
||||
.unwrap();
|
||||
|
||||
let (mut application, mut event_loop) = (
|
||||
Application {
|
||||
display,
|
||||
globals: Rc::new(RefCell::new(globals)),
|
||||
global_manager,
|
||||
inner: Vec::new(),
|
||||
token,
|
||||
},
|
||||
event_loop,
|
||||
);
|
||||
|
||||
for _ in 0..2 {
|
||||
display_handle.flush().unwrap();
|
||||
event_loop.dispatch(None, &mut application).unwrap();
|
||||
}
|
||||
|
||||
(application, event_loop)
|
||||
}
|
||||
fn get_index(&self, surface: &WlSurface) -> usize {
|
||||
for i in 0..self.inner.len() {
|
||||
if self.inner[i].eq(surface) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
||||
fn get_application(&mut self, surface: &WlSurface) -> Option<&mut InnerApplication<M, C>> {
|
||||
for inner in &mut self.inner {
|
||||
if inner.eq(surface) {
|
||||
return Some(inner);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
pub fn get_global<I>(&self) -> Result<Main<I>, GlobalError>
|
||||
where
|
||||
I: Interface + AsRef<Proxy<I>> + From<Proxy<I>>,
|
||||
{
|
||||
self.global_manager.instantiate_range::<I>(0, 1 << 8)
|
||||
}
|
||||
pub fn create_empty_inner_application<Data: 'static>(
|
||||
&mut self,
|
||||
controller: C,
|
||||
widget: impl Widget<M> + 'static,
|
||||
handle: LoopHandle<'_, Data>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) {
|
||||
let inner_application =
|
||||
InnerApplication::empty(controller, widget, self.globals.clone(), cb);
|
||||
self.inner.push(inner_application);
|
||||
handle.update(&self.token).unwrap();
|
||||
}
|
||||
pub fn create_inner_application_from<Data: 'static>(
|
||||
&mut self,
|
||||
controller: C,
|
||||
config: ShellConfig,
|
||||
widget: impl Widget<M> + 'static,
|
||||
handle: LoopHandle<'_, Data>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) {
|
||||
let inner_application =
|
||||
InnerApplication::new(controller, widget, config, self.globals.clone(), cb);
|
||||
self.inner.push(inner_application);
|
||||
handle.update(&self.token).unwrap();
|
||||
}
|
||||
pub fn create_inner_application<Data: 'static>(
|
||||
&mut self,
|
||||
controller: C,
|
||||
widget: impl Widget<M> + 'static,
|
||||
handle: LoopHandle<'_, Data>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) {
|
||||
let inner_application =
|
||||
InnerApplication::normal(controller, widget, self.globals.clone(), cb);
|
||||
self.inner.push(inner_application);
|
||||
handle.update(&self.token).unwrap();
|
||||
}
|
||||
pub fn run(mut self, event_loop: &mut EventLoop<'static, Self>) {
|
||||
loop {
|
||||
self.display.flush().unwrap();
|
||||
event_loop.dispatch(None, &mut self).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> Deref for InnerApplication<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
type Target = CoreApplication<M, C>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.core
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> DerefMut for InnerApplication<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.core
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> CoreApplication<M, C>
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
pub fn poll(&mut self, ev: Event<M>) -> C {
|
||||
let mut ctl = self.controller.clone();
|
||||
let mut sync_ctx = SyncContext::new(&mut ctl, &mut self.ctx.font_cache);
|
||||
self.widget.sync(&mut sync_ctx, ev);
|
||||
ctl
|
||||
}
|
||||
pub fn sync(&mut self, ev: Event<M>) -> bool {
|
||||
let mut sync_ctx = SyncContext::new(&mut self.controller, &mut self.ctx.font_cache);
|
||||
let mut damage = self.widget.sync(&mut sync_ctx, ev);
|
||||
while let Ok(msg) = sync_ctx.sync() {
|
||||
damage = damage.max(self.widget.sync(&mut sync_ctx, Event::Message(&msg)));
|
||||
}
|
||||
if damage == Damage::Frame {
|
||||
if self.ctx.time.is_none() {
|
||||
self.ctx.time = Some(0);
|
||||
}
|
||||
}
|
||||
damage.is_some() && !self.ctx.pending_cb
|
||||
}
|
||||
pub fn destroy(&mut self) {
|
||||
if let Some(surface) = self.surface.as_mut() {
|
||||
surface.destroy();
|
||||
}
|
||||
}
|
||||
pub fn get_layer_surface(&self) -> ZwlrLayerSurfaceV1 {
|
||||
match &self.surface.as_ref().unwrap().shell {
|
||||
Shell::LayerShell { config: _, surface } => surface.detach(),
|
||||
}
|
||||
}
|
||||
pub fn is_hidden(&self) -> bool {
|
||||
if let Some(surface) = self.surface.as_ref() {
|
||||
return !surface.alive;
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
pub fn replace_surface(&mut self) {
|
||||
if let Some(surface) = self.surface.as_mut() {
|
||||
surface.destroy();
|
||||
surface.alive = true;
|
||||
match &surface.shell {
|
||||
Shell::LayerShell { config, surface: _ } => {
|
||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
||||
self.widget.deref(),
|
||||
ShellConfig::LayerShell(config.clone()),
|
||||
Some(surface.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
||||
self.widget.deref(),
|
||||
ShellConfig::LayerShell(LayerShellConfig::default()),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn replace_surface_by(&mut self, config: ShellConfig) {
|
||||
if let Some(surface) = self.surface.as_mut() {
|
||||
surface.destroy();
|
||||
surface.alive = true;
|
||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
||||
self.widget.deref(),
|
||||
config,
|
||||
Some(surface.clone()),
|
||||
);
|
||||
} else {
|
||||
self.surface = self.globals.borrow().create_shell_surface_from::<M, C>(
|
||||
self.widget.deref(),
|
||||
config,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> Geometry for InnerApplication<M, C>
|
||||
where
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
fn width(&self) -> f32 {
|
||||
self.widget.width()
|
||||
}
|
||||
fn height(&self) -> f32 {
|
||||
self.widget.height()
|
||||
}
|
||||
fn set_size(&mut self, width: f32, height: f32) -> Result<(), (f32, f32)> {
|
||||
if let Some(surface) = self.surface.as_ref() {
|
||||
surface.set_size(width as u32, height as u32);
|
||||
surface.surface.commit();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, C> InnerApplication<M, C>
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
pub fn empty(
|
||||
controller: C,
|
||||
widget: impl Widget<M> + 'static,
|
||||
globals: Rc<RefCell<Globals>>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) -> Self {
|
||||
let mempool = globals.borrow().create_mempool();
|
||||
let mut default = InnerApplication {
|
||||
core: CoreApplication {
|
||||
controller,
|
||||
ctx: Context {
|
||||
pending_cb: false,
|
||||
time: None,
|
||||
font_cache: FontCache::new(),
|
||||
render_node: None,
|
||||
},
|
||||
surface: None,
|
||||
widget: Box::new(widget),
|
||||
mempool,
|
||||
globals,
|
||||
},
|
||||
cb: Box::new(cb),
|
||||
};
|
||||
default.sync(Event::Prepare);
|
||||
default
|
||||
}
|
||||
pub fn normal(
|
||||
controller: C,
|
||||
widget: impl Widget<M> + 'static,
|
||||
globals: Rc<RefCell<Globals>>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) -> Self {
|
||||
let mempool = globals.borrow().create_mempool();
|
||||
let mut default = InnerApplication {
|
||||
core: CoreApplication {
|
||||
controller,
|
||||
ctx: Context {
|
||||
pending_cb: false,
|
||||
time: None,
|
||||
font_cache: FontCache::new(),
|
||||
render_node: None,
|
||||
},
|
||||
surface: None,
|
||||
widget: Box::new(widget),
|
||||
mempool,
|
||||
globals,
|
||||
},
|
||||
cb: Box::new(cb),
|
||||
};
|
||||
default.sync(Event::Prepare);
|
||||
default.replace_surface();
|
||||
default
|
||||
}
|
||||
pub fn new(
|
||||
controller: C,
|
||||
widget: impl Widget<M> + 'static,
|
||||
config: ShellConfig,
|
||||
globals: Rc<RefCell<Globals>>,
|
||||
cb: impl FnMut(&mut CoreApplication<M, C>, Event<M>) + 'static,
|
||||
) -> Self {
|
||||
let mempool = globals.borrow().create_mempool();
|
||||
let mut new = InnerApplication {
|
||||
core: CoreApplication {
|
||||
controller,
|
||||
ctx: Context {
|
||||
pending_cb: false,
|
||||
time: None,
|
||||
font_cache: FontCache::new(),
|
||||
render_node: None,
|
||||
},
|
||||
surface: None,
|
||||
widget: Box::new(widget),
|
||||
mempool,
|
||||
globals,
|
||||
},
|
||||
cb: Box::new(cb),
|
||||
};
|
||||
new.sync(Event::Prepare);
|
||||
new.replace_surface_by(config);
|
||||
new
|
||||
}
|
||||
fn eq(&self, wl_surface: &WlSurface) -> bool {
|
||||
if let Some(surface) = &self.surface {
|
||||
return surface.surface.detach().eq(wl_surface);
|
||||
}
|
||||
false
|
||||
}
|
||||
pub fn roundtrip(&mut self, ev: Event<M>) -> Result<RenderNode, ()> {
|
||||
let width = self.width();
|
||||
let height = self.height();
|
||||
|
||||
// Sending the event to the widget tree
|
||||
if self.sync(ev) || ev.is_frame() {
|
||||
// Calling the application´s closure
|
||||
(self.cb)(&mut self.core, ev);
|
||||
|
||||
if !self.is_hidden() {
|
||||
let current_width = self.width();
|
||||
let current_height = self.height();
|
||||
|
||||
// Resizing the surface in case the widget changed size
|
||||
if ev.is_frame() {
|
||||
self.ctx.render_node = None;
|
||||
} else if width != current_width || height != current_height {
|
||||
let _ = self.set_size(current_width, current_height);
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// Creating the render node
|
||||
let render_node = self.core.widget.create_node(0., 0.);
|
||||
|
||||
self.ctx.pending_cb = true;
|
||||
|
||||
return Ok(render_node);
|
||||
}
|
||||
} else {
|
||||
// Calling the application´s closure
|
||||
(self.cb)(&mut self.core, ev);
|
||||
}
|
||||
|
||||
Err(())
|
||||
}
|
||||
fn render(&mut self, time: u32, recent_node: RenderNode) {
|
||||
let width = recent_node.width();
|
||||
let height = recent_node.height();
|
||||
if Some(time).ne(&self.core.ctx.time) || time == 0 {
|
||||
if let Ok((buffer, wl_buffer)) =
|
||||
Buffer::new(&mut self.core.mempool, width as i32, height as i32)
|
||||
{
|
||||
let mut v = Vec::new();
|
||||
let mut ctx =
|
||||
DrawContext::new(buffer.backend, &mut self.core.ctx.font_cache, &mut v);
|
||||
if let Some(render_node) = self.core.ctx.render_node.as_mut() {
|
||||
if let Err(region) = render_node.draw_merge(
|
||||
recent_node,
|
||||
&mut ctx,
|
||||
&Instruction::empty(0., 0., width, height),
|
||||
None,
|
||||
) {
|
||||
ctx.damage_region(&Background::Transparent, region, false);
|
||||
}
|
||||
} else {
|
||||
ctx.damage_region(
|
||||
&Background::Transparent,
|
||||
Region::new(0., 0., width, height),
|
||||
false,
|
||||
);
|
||||
recent_node.render(&mut ctx, None);
|
||||
self.core.ctx.render_node = Some(recent_node);
|
||||
}
|
||||
self.core.ctx.pending_cb = false;
|
||||
if let Some(surface) = self.core.surface.as_mut() {
|
||||
surface.attach_buffer(wl_buffer);
|
||||
surface.damage(&v);
|
||||
surface.commit();
|
||||
if let Some(_) = self.core.ctx.time {
|
||||
self.core.ctx.time = Some(time);
|
||||
frame_callback::<M, C>(time, surface.surface.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn callback(&mut self, ev: Event<M>) {
|
||||
if self.ctx.time.is_none() || ev.is_cb() {
|
||||
if let Ok(render_node) = self.roundtrip(ev) {
|
||||
if let Some(surface) = self.surface.as_ref() {
|
||||
draw_callback::<M, C>(&surface.surface, render_node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let width = self.width();
|
||||
let height = self.height();
|
||||
|
||||
self.sync(ev);
|
||||
|
||||
let current_width = self.width();
|
||||
let current_height = self.height();
|
||||
|
||||
// Resizing the surface in case the widget changed size
|
||||
if width != current_width || height != current_height {
|
||||
let _ = self.set_size(current_width, current_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn frame_callback<M, C>(time: u32, surface: Main<WlSurface>)
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
let h = surface.detach();
|
||||
surface
|
||||
.frame()
|
||||
.quick_assign(move |_, event, mut application| match event {
|
||||
wl_callback::Event::Done { callback_data } => {
|
||||
let timeout = (callback_data - time).min(50);
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
if let Some(inner_application) = application.get_application(&h) {
|
||||
inner_application.ctx.time = None;
|
||||
inner_application.callback(Event::Callback(timeout));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
surface.commit();
|
||||
}
|
||||
|
||||
fn draw_callback<M, C>(surface: &Main<WlSurface>, mut recent_node: RenderNode)
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
let h = surface.detach();
|
||||
surface
|
||||
.frame()
|
||||
.quick_assign(move |_, event, mut application| match event {
|
||||
wl_callback::Event::Done { callback_data } => {
|
||||
if let Some(application) = application.get::<Application<M, C>>() {
|
||||
let inner_application = application.get_application(&h).unwrap();
|
||||
inner_application.render(callback_data, std::mem::take(&mut recent_node));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
surface.commit();
|
||||
}
|
||||
|
||||
impl From<ModifiersState> for Modifiers {
|
||||
fn from(modifer_state: ModifiersState) -> Modifiers {
|
||||
Modifiers {
|
||||
ctrl: modifer_state.ctrl,
|
||||
alt: modifer_state.alt,
|
||||
shift: modifer_state.shift,
|
||||
caps_lock: modifer_state.caps_lock,
|
||||
logo: modifer_state.logo,
|
||||
num_lock: modifer_state.num_lock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_pointer<M, C>(pointer: &Main<WlPointer>)
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
let mut index = 0;
|
||||
let mut input = Pointer::Enter;
|
||||
let (mut x, mut y) = (0., 0.);
|
||||
pointer.quick_assign(move |_, event, mut inner| match event {
|
||||
wl_pointer::Event::Leave { serial: _, surface } => {
|
||||
input = Pointer::Leave;
|
||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
||||
if let Some(inner_application) = application.get_application(&surface) {
|
||||
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
|
||||
}
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::Button {
|
||||
serial: _,
|
||||
time,
|
||||
button,
|
||||
state,
|
||||
} => {
|
||||
input = Pointer::MouseClick {
|
||||
time,
|
||||
button: MouseButton::new(button),
|
||||
pressed: state == wl_pointer::ButtonState::Pressed,
|
||||
};
|
||||
}
|
||||
wl_pointer::Event::Frame => {
|
||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
||||
let inner_application = application.inner.get_mut(index).unwrap();
|
||||
inner_application.callback(Event::Pointer(x as f32, y as f32, input));
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::Axis {
|
||||
time: _,
|
||||
axis,
|
||||
value,
|
||||
} => {
|
||||
input = Pointer::Scroll {
|
||||
orientation: match axis {
|
||||
wl_pointer::Axis::VerticalScroll => Orientation::Vertical,
|
||||
wl_pointer::Axis::HorizontalScroll => Orientation::Horizontal,
|
||||
_ => Orientation::Vertical,
|
||||
},
|
||||
value: value as f32,
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::Enter {
|
||||
serial: _,
|
||||
surface,
|
||||
surface_x,
|
||||
surface_y,
|
||||
} => {
|
||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
||||
x = surface_x;
|
||||
y = surface_y;
|
||||
index = application.get_index(&surface);
|
||||
}
|
||||
}
|
||||
wl_pointer::Event::Motion {
|
||||
time: _,
|
||||
surface_x,
|
||||
surface_y,
|
||||
} => {
|
||||
x = surface_x;
|
||||
y = surface_y;
|
||||
input = Pointer::Hover;
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
|
||||
fn assign_surface<M, C>(shell: &Main<ZwlrLayerSurfaceV1>)
|
||||
where
|
||||
M: 'static,
|
||||
C: Controller<M> + Clone + 'static,
|
||||
{
|
||||
shell.quick_assign(move |shell, event, mut inner| match event {
|
||||
zwlr_layer_surface_v1::Event::Configure {
|
||||
serial,
|
||||
width,
|
||||
height,
|
||||
} => {
|
||||
shell.ack_configure(serial);
|
||||
println!("\nCONFIGURE - {} : {} X {}\n", serial, width, height);
|
||||
if let Some(application) = inner.get::<Application<M, C>>() {
|
||||
for inner_application in &mut application.inner {
|
||||
if let Some(app_surface) = inner_application.surface.as_mut() {
|
||||
match &app_surface.shell {
|
||||
Shell::LayerShell { config: _, surface } => {
|
||||
if shell.eq(surface) {
|
||||
app_surface.destroy_previous();
|
||||
let _ = inner_application
|
||||
.widget
|
||||
.set_size(width as f32, height as f32);
|
||||
if inner_application.ctx.pending_cb {
|
||||
if let Ok(render_node) =
|
||||
inner_application.roundtrip(Event::Frame)
|
||||
{
|
||||
draw_callback::<M, C>(
|
||||
&inner_application
|
||||
.surface
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.surface,
|
||||
render_node,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if let Ok(render_node) =
|
||||
inner_application.roundtrip(Event::Frame)
|
||||
{
|
||||
inner_application.render(0, render_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
});
|
||||
}
|
326
tests/wcag-compliance/package-lock.json
generated
Normal file
326
tests/wcag-compliance/package-lock.json
generated
Normal file
|
@ -0,0 +1,326 @@
|
|||
{
|
||||
"name": "wcag-compliance",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wcag-compliance",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-contrast-checker": "^2.1.0",
|
||||
"execa": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-contrast-checker": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-2.1.0.tgz",
|
||||
"integrity": "sha512-6Y0aIEej3pwZTVlicIqVzhO6T4izDWouaIXnYoDdTuFFAMQ9nnN0dgHNP9J94jRnH6asjPq1/wzUKxwoNbWtRQ=="
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
|
||||
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.1",
|
||||
"human-signals": "^3.0.1",
|
||||
"is-stream": "^3.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^5.1.0",
|
||||
"onetime": "^6.0.0",
|
||||
"signal-exit": "^3.0.7",
|
||||
"strip-final-newline": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
|
||||
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==",
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
|
||||
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
},
|
||||
"node_modules/mimic-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
|
||||
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
|
||||
"dependencies": {
|
||||
"path-key": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-path/node_modules/path-key": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/strip-final-newline": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
|
||||
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"color-contrast-checker": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-2.1.0.tgz",
|
||||
"integrity": "sha512-6Y0aIEej3pwZTVlicIqVzhO6T4izDWouaIXnYoDdTuFFAMQ9nnN0dgHNP9J94jRnH6asjPq1/wzUKxwoNbWtRQ=="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"requires": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
|
||||
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
|
||||
"requires": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^6.0.1",
|
||||
"human-signals": "^3.0.1",
|
||||
"is-stream": "^3.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^5.1.0",
|
||||
"onetime": "^6.0.0",
|
||||
"signal-exit": "^3.0.7",
|
||||
"strip-final-newline": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
|
||||
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
|
||||
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ=="
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
|
||||
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
|
||||
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
|
||||
"requires": {
|
||||
"path-key": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"path-key": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"onetime": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"requires": {
|
||||
"mimic-fn": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"requires": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"strip-final-newline": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
|
||||
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
tests/wcag-compliance/package.json
Normal file
32
tests/wcag-compliance/package.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "wcag-compliance",
|
||||
"version": "0.1.0",
|
||||
"description": "An accessibility checker tool for validating the color contrast of Catppuccin's palettes based on WCAG 2.0 and WCAG 2.1 standards",
|
||||
"main": "./src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/catppuccin/catppuccin.git"
|
||||
},
|
||||
"keywords": [
|
||||
"wcag",
|
||||
"wcag-aa",
|
||||
"color",
|
||||
"contrast",
|
||||
"verifier",
|
||||
"accessibility",
|
||||
"standard"
|
||||
],
|
||||
"author": "Pocco81",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/catppuccin/catppuccin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/catppuccin/catppuccin#readme",
|
||||
"dependencies": {
|
||||
"color-contrast-checker": "^2.1.0",
|
||||
"execa": "^6.1.0"
|
||||
}
|
||||
}
|
110
tests/wcag-compliance/src/index.js
Normal file
110
tests/wcag-compliance/src/index.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
// import { platform } from 'os';
|
||||
|
||||
const os = require('os')
|
||||
const execa = require("execa")
|
||||
const ColorContrastChecker = require('color-contrast-checker')
|
||||
|
||||
const {stdout} = execa('echo', ['unicorns']);
|
||||
console.log(stdout);
|
||||
|
||||
|
||||
function get_git_root() {
|
||||
try {
|
||||
let cmd = ''
|
||||
|
||||
if (platform() === 'win32') {
|
||||
cmd = `git rev-parse --show-toplevel `
|
||||
} else {
|
||||
cmd = `(git rev-parse --show-toplevel )`
|
||||
}
|
||||
|
||||
const { stdout } = execa.shellSync(cmd)
|
||||
|
||||
return stdout
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(execa.shellSync("echo 'hello'"))
|
||||
|
||||
// /* File System Object */
|
||||
// var fs = require('fs');
|
||||
//
|
||||
// pr
|
||||
|
||||
/* Read File */
|
||||
// fs.readFile(get_git_root() + "palettes.json", bar)
|
||||
|
||||
function bar (err, data)
|
||||
{
|
||||
/* If an error exists, show it, otherwise show the file */
|
||||
err ? Function("error","throw error")(err) : console.log(JSON.stringify(data) );
|
||||
};
|
||||
|
||||
// const fs = require("fs")
|
||||
//
|
||||
|
||||
// var ccc = new ColorContrastChecker();
|
||||
// var palettes = fs.readFileSync('../../palettes.json', 'utf8');
|
||||
// var palettes = fs.readFile('test.json', 'utf8');
|
||||
|
||||
// fs.readFile("../../../palettes.json", function(text){
|
||||
// palettes = text.split("\n")
|
||||
// });
|
||||
|
||||
// for (var key in palettes) {
|
||||
// console.log(key)
|
||||
// if (ccc.isLevelAA(background, rainbow[key], 14)) {
|
||||
// console.log(" •" + key + ": ✅");
|
||||
// } else {
|
||||
// console.log(" •" + key + ": ❌");
|
||||
// }
|
||||
// }
|
||||
|
||||
// const background = "#1E1D2F"
|
||||
// var rainbow = {
|
||||
// rosewater: "#F5E0DC",
|
||||
// flamingo: "#F2CDCD",
|
||||
// mauve: "#DDB6F2",
|
||||
// pink: "#F5C2E7",
|
||||
// red: "#F28FAD",
|
||||
// maroon: "#E8A2AF",
|
||||
// peach: "#F8BD96",
|
||||
// yellow: "#FAE3B0",
|
||||
// green: "#ABE9B3",
|
||||
// blue: "#96CDFB",
|
||||
// sky: "#89DCEB",
|
||||
// teal: "#B5E8E0",
|
||||
// lavender: "#C9CBFF",
|
||||
// white: "#D9E0EE",
|
||||
// gray2: "#C3BAC6",
|
||||
// gray1: "#988BA2",
|
||||
// gray0: "#6E6C7E",
|
||||
// black4: "#575268",
|
||||
// black3: "#302D41",
|
||||
// black2: "#1E1D2F",
|
||||
// black1: "#1A1823",
|
||||
// black0: "#131020",
|
||||
// }
|
||||
//
|
||||
// console.log("\t---- WCAG conformance level AA on Catppuccin ----\n")
|
||||
//
|
||||
// for (var key in rainbow) {
|
||||
// if (ccc.isLevelAA(background, rainbow[key], 14)) {
|
||||
// console.log(" •" + key + ": ✅");
|
||||
// } else {
|
||||
// console.log(" •" + key + ": ❌");
|
||||
// }
|
||||
// }
|
||||
|
||||
// var color1 = "#FFFFFF";
|
||||
// var color2 = "#000000";
|
||||
//
|
||||
// if (ccc.isLevelAA(color1, color2, 14)) {
|
||||
// console.log("Valid Level AA");
|
||||
// } else {
|
||||
// console.log("Invalid Contrast");
|
||||
// }
|
||||
//
|
||||
// console.log("Hello world!")
|
3
tests/wcag-compliance/test.json
Normal file
3
tests/wcag-compliance/test.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"hello": "world"
|
||||
}
|
Loading…
Reference in a new issue