allow adjusting mouse for each screen

This commit is contained in:
galister
2025-12-20 16:42:04 +09:00
parent b4b641371a
commit 9381ebc700
19 changed files with 524 additions and 54 deletions

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="flip180.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="18.3125"
inkscape:cy="14.46875"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 m 0,-2 c 2.233333,0 4.125,-0.775 5.675,-2.325 C 19.225,16.125 20,14.233333 20,12 20,9.9778321 19.418096,8.0680972 17.675,6.325 15.931904,4.5819028 14.232703,3.7451172 12.00586,3.7451172 c 0,3.1215572 -0.0031,8.2546878 -0.0031,8.2546878 C 12.002734,11.999805 12,20 12,20"
id="path1"
sodipodi:nodetypes="csssssssssssssssccsszccc" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="flip270.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="18.3125"
inkscape:cy="14.46875"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 m 0,-2 c 2.233333,0 4.125,-0.775 5.675,-2.325 C 19.225,16.125 20,14.233333 20,12 20,9.9778321 19.418096,8.0680972 17.675,6.325 15.931904,4.5819028 14.232703,3.7451172 12.00586,3.7451172 c 0,3.1215572 -0.0031,8.2546878 -0.0031,8.2546878 C 12.002734,11.999805 6.7304687,12 4,12 4,14.233333 4.775,16.125 6.325,17.675 7.875,19.225 9.7666667,20 12,20"
id="path1"
sodipodi:nodetypes="csssssssssssssssccsszcccsc" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="flip90.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="18.3125"
inkscape:cy="14.46875"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 M 20,12 C 20,9.9778321 19.418096,8.0680972 17.675,6.325 15.931904,4.5819028 14.232703,3.7451172 12.00586,3.7451172 c 0,3.1215572 -0.0031,8.2546878 -0.0031,8.2546878"
id="path1"
sodipodi:nodetypes="cssssssssssssssscczcc" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="flipped.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="18.3125"
inkscape:cy="14.46875"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22"
id="path1"
sodipodi:nodetypes="csssssssssssssssc" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="m2.1 2.075l19.8 19.8l-1.425 1.425l-1.1-1.1q-.5.375-1.1.588T17 23h-6.95q-.75 0-1.4-.337T7.575 21.7L1.2 12.375l.6-.575q.475-.475 1.125-.55t1.175.3L7 13.575v-3.75L.675 3.5zM21 18.15l-6-5.975V3q0-.425.288-.712T16 2t.713.288T17 3v9.175h2V5q0-.425.288-.712T20 4t.713.288T21 5zm-8-8l-2-2V2q0-.425.288-.712T12 1t.713.288T13 2zm-4-4l-2-2V4q0-.425.288-.712T8 3t.713.288T9 4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="white" d="m2.1 2.075l19.8 19.8l-1.425 1.425l-1.1-1.1q-.5.375-1.1.588T17 23h-6.95q-.75 0-1.4-.337T7.575 21.7L1.2 12.375l.6-.575q.475-.475 1.125-.55t1.175.3L7 13.575v-3.75L.675 3.5zM21 18.15l-6-5.975V3q0-.425.288-.712T16 2t.713.288T17 3v9.175h2V5q0-.425.288-.712T20 4t.713.288T21 5zm-8-8l-2-2V2q0-.425.288-.712T12 1t.713.288T13 2zm-4-4l-2-2V4q0-.425.288-.712T8 3t.713.288T9 4z"/></svg>

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="normal.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="18.3125"
inkscape:cy="14.46875"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 m 0,-2 c 2.233333,0 4.125,-0.775 5.675,-2.325 C 19.225,16.125 20,14.233333 20,12 20,9.9778321 19.418096,8.0680972 17.675,6.325 15.931904,4.5819028 14.226843,4 12,4 9.7731573,4 7.875,4.775 6.325,6.325 4.775,7.875 4,9.7666667 4,12 4,14.233333 4.775,16.125 6.325,17.675 7.875,19.225 9.7666667,20 12,20"
id="path1"
sodipodi:nodetypes="csssssssssssssssccsszzzssc" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="rotate180.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="22.5"
inkscape:cy="19.09375"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 m 0,-2 c 0,-4.40625 0,-3.449573 0,-8 V 4 C 9.7666667,4 7.875,4.775 6.325,6.325 4.775,7.875 4,9.7666667 4,12 4,14.233333 4.775,16.125 6.325,17.675 7.875,19.225 9.7666667,20 12,20"
id="path1"
sodipodi:nodetypes="csssssssssssssssccccsssc" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="rotate270.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="22.5"
inkscape:cy="19.09375"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 M 12,12 V 4 C 9.7666667,4 7.875,4.775 6.325,6.325 4.775,7.875 4,9.7666667 4,12"
id="path1"
sodipodi:nodetypes="cssssssssssssssscccsc" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="32"
height="32"
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="rotate90.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="32"
inkscape:cx="22.5"
inkscape:cy="19.09375"
inkscape:window-width="2560"
inkscape:window-height="1402"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE -->
<path
fill="white"
d="M 12,22 C 10.616667,22 9.3166667,21.737333 8.1,21.212 6.8833333,20.686667 5.825,19.974333 4.925,19.075 4.025,18.175667 3.3126667,17.117333 2.788,15.9 2.2633333,14.682667 2.0006667,13.382667 2,12 1.9993333,10.617333 2.262,9.3173333 2.788,8.1 3.314,6.8826667 4.0263333,5.8243333 4.925,4.925 5.8236667,4.0256667 6.882,3.3133333 8.1,2.788 9.318,2.2626667 10.618,2 12,2 c 1.382,0 2.682,0.2626667 3.9,0.788 1.218,0.5253333 2.276333,1.2376667 3.175,2.137 0.898667,0.8993333 1.611333,1.9576667 2.138,3.175 0.526667,1.2173333 0.789,2.517333 0.787,3.9 -0.002,1.382667 -0.264667,2.682667 -0.788,3.9 -0.523333,1.217333 -1.235667,2.275667 -2.137,3.175 -0.901333,0.899333 -1.959667,1.612 -3.175,2.138 C 14.684667,21.739 13.384667,22.001333 12,22 m 0,-2 c 2.233333,0 4.125,-0.775 5.675,-2.325 C 19.225,16.125 20,14.233333 20,12 16.205587,12 14.579192,11.9944 12,12 V 4 C 9.7666667,4 7.875,4.775 6.325,6.325 4.775,7.875 4,9.7666667 4,12 4,14.233333 4.775,16.125 6.325,17.675 7.875,19.225 9.7666667,20 12,20"
id="path1"
sodipodi:nodetypes="csssssssssssssssccscccsssc" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -45,6 +45,7 @@
<TopButton sticky="0" id="top_alpha" src="edit/fade.svg" tooltip="EDIT_MODE.OPACITY" press="::EditModeTab alpha" />
<TopButton sticky="0" id="top_curve" src="edit/curve.svg" tooltip="EDIT_MODE.ADJUST_CURVATURE" press="::EditModeTab curve" />
<TopButton sticky="0" id="top_stereo" src="edit/3d.svg" tooltip="EDIT_MODE.STEREO_3D_MODE.TITLE" press="::EditModeTab stereo" />
<TopButton sticky="0" id="top_mouse" src="edit/normal.svg" tooltip="EDIT_MODE.MOUSE.TITLE" press="::EditModeTab mouse" />
<!-- TopButton sticky="0" id="top_move" src="edit/move-all.svg" tooltip="EDIT_MODE.MOVE_PRESS_AND_DRAG" / -->
<!-- TopButton sticky="0" id="top_resize" src="edit/resize.svg" tooltip="EDIT_MODE.RESIZE_PRESS_AND_DRAG" / -->
<TopButtonDanger src="edit/delete.svg" tooltip="EDIT_MODE.DELETE" press="::EditModeDeletePress" release="::EditModeDeleteRelease" />
@@ -77,6 +78,19 @@
<PosButton id="stereo_bottomtop" src="edit/3d_bottomtop.svg" tooltip="EDIT_MODE.STEREO_3D_MODE.SPLIT_BOTTOM_TOP" press="::EditModeSetStereo bottomtop" />
</div>
</div>
<div id="tab_mouse" display="none" height="100" flex_direction="column">
<div padding="8" gap="8" justify_content="center" align_items="center">
<PosButton id="mouse_default" src="edit/close.svg" tooltip="DEFAULT" press="::EditModeSetMouse default" />
<PosButton id="mouse_normal" src="edit/normal.svg" tooltip="EDIT_MODE.MOUSE.NORMAL" press="::EditModeSetMouse normal" />
<PosButton id="mouse_rotate90" src="edit/rotate90.svg" tooltip="EDIT_MODE.MOUSE.ROTATE90" press="::EditModeSetMouse rotate90" />
<PosButton id="mouse_rotate180" src="edit/rotate180.svg" tooltip="EDIT_MODE.MOUSE.ROTATE180" press="::EditModeSetMouse rotate180" />
<PosButton id="mouse_rotate270" src="edit/rotate270.svg" tooltip="EDIT_MODE.MOUSE.ROTATE270" press="::EditModeSetMouse rotate270" />
<PosButton id="mouse_flipped" src="edit/flipped.svg" tooltip="EDIT_MODE.MOUSE.FLIPPED" press="::EditModeSetMouse flipped" />
<PosButton id="mouse_flip90" src="edit/flip90.svg" tooltip="EDIT_MODE.MOUSE.FLIP90" press="::EditModeSetMouse flip90" />
<PosButton id="mouse_flip180" src="edit/flip180.svg" tooltip="EDIT_MODE.MOUSE.FLIP180" press="::EditModeSetMouse flip180" />
<PosButton id="mouse_flip270" src="edit/flip270.svg" tooltip="EDIT_MODE.MOUSE.FLIP270" press="::EditModeSetMouse flip270" />
</div>
</div>
<div id="tab_alpha" display="none" height="100" padding="8" gap="8" justify_content="center" align_items="center">
<div width="100%" padding="8" gap="8" justify_content="center" align_items="center">
<label translation="EDIT_MODE.OPACITY" />
@@ -98,4 +112,4 @@
</rectangle>
</div>
</elements>
</layout>
</layout>

View File

@@ -1,7 +1,7 @@
use regex::Regex;
use std::{
fs,
io::{BufRead, BufReader, Read},
io::{BufRead, BufReader},
process::Child,
sync::{
Arc, LazyLock,

View File

@@ -56,6 +56,7 @@ pub struct GuiPanel<S> {
context: WguiContext,
timestep: Timestep,
has_focus: [bool; 2],
last_content_size: Vec2,
}
pub type OnCustomIdFunc<S> = Box<
@@ -175,6 +176,7 @@ impl<S: 'static> GuiPanel<S> {
gui_scale: params.gui_scale,
initialized: false,
has_focus: [false, false],
last_content_size: Vec2::ZERO,
})
}
@@ -206,6 +208,7 @@ impl<S: 'static> GuiPanel<S> {
gui_scale: params.gui_scale,
initialized: false,
has_focus: [false, false],
last_content_size: Vec2::ZERO,
})
}
@@ -238,7 +241,6 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
if self.layout.content_size.x * self.layout.content_size.y != 0.0 {
self.update_layout()?;
self.interaction_transform = Some(ui_transform([
//TODO: dynamic
self.layout.content_size.x as _,
self.layout.content_size.y as _,
]));
@@ -275,6 +277,17 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
return Ok(ShouldRender::Unable);
}
if !self
.last_content_size
.abs_diff_eq(self.layout.content_size, 0.1 /* pixels */)
{
self.interaction_transform = Some(ui_transform([
self.layout.content_size.x as _,
self.layout.content_size.y as _,
]));
self.last_content_size = self.layout.content_size;
}
Ok(if self.layout.check_toggle_needs_redraw() {
ShouldRender::Should
} else {

View File

@@ -14,6 +14,7 @@ use wgui::{
parser::Fetchable,
widget::EventResult,
};
use wlx_capture::frame::Transform;
use crate::{
attrib_value,
@@ -24,6 +25,7 @@ use crate::{
gui::panel::{GuiPanel, NewGuiPanelParams, OnCustomAttribFunc, button::BUTTON_EVENTS},
overlays::edit::{
lock::InteractLockHandler,
mouse::new_mouse_tab_handler,
pos::{PosTabState, new_pos_tab_handler},
sprite_tab::SpriteTabHandler,
stereo::new_stereo_tab_handler,
@@ -42,6 +44,7 @@ use crate::{
};
mod lock;
mod mouse;
mod pos;
mod sprite_tab;
mod stereo;
@@ -66,6 +69,7 @@ struct EditModeState {
lock: InteractLockHandler,
pos: SpriteTabHandler<PosTabState>,
stereo: SpriteTabHandler<StereoMode>,
mouse: SpriteTabHandler<Transform>,
}
type EditModeWrapPanel = GuiPanel<EditModeState>;
@@ -264,6 +268,7 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
lock: InteractLockHandler::default(),
pos: SpriteTabHandler::default(),
stereo: SpriteTabHandler::default(),
mouse: SpriteTabHandler::default(),
};
let on_custom_attrib: OnCustomAttribFunc = Box::new(move |layout, attribs, _app| {
@@ -323,6 +328,16 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
Ok(EventResult::Consumed)
})
}
"::EditModeSetMouse" => {
let key = args.next().unwrap().to_owned();
Box::new(move |common, _data, app, state| {
let sel = OverlaySelector::Id(*state.id.borrow());
let task = state.mouse.button_clicked(common, &key);
app.tasks
.enqueue(TaskType::Overlay(OverlayTask::Modify(sel, task)));
Ok(EventResult::Consumed)
})
}
"::EditModeDeletePress" => Box::new(move |_common, _data, _app, state| {
state.delete.pressed = Instant::now();
// TODO: animate to light up button after 2s
@@ -361,9 +376,12 @@ fn make_edit_panel(app: &mut AppState) -> anyhow::Result<EditModeWrapPanel> {
panel.state.pos = new_pos_tab_handler(&mut panel)?;
panel.state.stereo = new_stereo_tab_handler(&mut panel)?;
panel.state.mouse = new_mouse_tab_handler(&mut panel)?;
panel.state.lock = InteractLockHandler::new(&mut panel)?;
panel.state.tabs =
ButtonPaneTabSwitcher::new(&mut panel, &["none", "pos", "alpha", "curve", "stereo"])?;
panel.state.tabs = ButtonPaneTabSwitcher::new(
&mut panel,
&["none", "pos", "alpha", "curve", "stereo", "mouse"],
)?;
set_up_checkbox(&mut panel, "additive_box", cb_assign_additive)?;
set_up_slider(&mut panel, "lerp_slider", cb_assign_lerp)?;
@@ -435,6 +453,19 @@ fn reset_panel(
.set_tab_visible(&mut common, "stereo", false);
}
if let Some(mouse) = attrib_value!(
owc.backend.get_attrib(BackendAttrib::MouseTransform),
BackendAttribValue::MouseTransform
) {
panel.state.tabs.set_tab_visible(&mut common, "mouse", true);
panel.state.mouse.reset(&mut common, &mouse);
} else {
panel
.state
.tabs
.set_tab_visible(&mut common, "mouse", false);
}
panel.layout.process_alterables(alterables)?;
Ok(())

View File

@@ -0,0 +1,72 @@
use wlx_capture::frame::Transform;
use crate::{
overlays::edit::{
EditModeWrapPanel,
sprite_tab::{SpriteTabHandler, SpriteTabKey},
},
windowing::backend::BackendAttribValue,
};
static MOUSE_NAMES: [&str; 9] = [
"default",
"normal",
"rotate90",
"rotate180",
"rotate270",
"flipped",
"flip90",
"flip180",
"flip270",
];
pub fn new_mouse_tab_handler(
panel: &mut EditModeWrapPanel,
) -> anyhow::Result<SpriteTabHandler<Transform>> {
SpriteTabHandler::new(
panel,
"mouse",
&MOUSE_NAMES,
Box::new(|_common, state| {
let mouse_transform = state.clone();
Box::new(move |app, owc| {
owc.backend
.set_attrib(app, BackendAttribValue::MouseTransform(mouse_transform));
})
}),
None,
)
}
impl SpriteTabKey for Transform {
fn to_tab_key(&self) -> &'static str {
match self {
Transform::Undefined => "default",
Transform::Normal => "normal",
Transform::Rotated90 => "rotate90",
Transform::Rotated180 => "rotate180",
Transform::Rotated270 => "rotate270",
Transform::Flipped => "flipped",
Transform::Flipped90 => "flip90",
Transform::Flipped180 => "flip180",
Transform::Flipped270 => "flip270",
}
}
fn from_tab_key(key: &str) -> Self {
match key {
"default" => Transform::Undefined,
"normal" => Transform::Normal,
"rotate90" => Transform::Rotated90,
"rotate180" => Transform::Rotated180,
"rotate270" => Transform::Rotated270,
"flipped" => Transform::Flipped,
"flip90" => Transform::Flipped90,
"flip180" => Transform::Flipped180,
"flip270" => Transform::Flipped270,
_ => {
panic!("cannot translate to mouse transform: {key}")
}
}
}
}

View File

@@ -45,7 +45,7 @@ impl SpriteTabKey for StereoMode {
"topbottom" => StereoMode::TopBottom,
"bottomtop" => StereoMode::BottomTop,
_ => {
panic!("cannot translate to positioning: {key}")
panic!("cannot translate to stereo mode: {key}")
}
}
}

View File

@@ -16,7 +16,7 @@ use crate::{
subsystem::hid::{MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, WheelDelta},
windowing::backend::{
BackendAttrib, BackendAttribValue, FrameMeta, OverlayBackend, OverlayEventData,
RenderResources, ShouldRender, StereoMode,
RenderResources, ShouldRender, StereoMode, ui_transform,
},
};
@@ -47,6 +47,10 @@ pub struct ScreenBackend {
mouse_transform: Affine2,
interaction_transform: Option<Affine2>,
stereo: Option<StereoMode>,
pub(super) logical_pos: Vec2,
pub(super) logical_size: Vec2,
pub(super) mouse_transform_original: Transform,
mouse_transform_override: Transform,
}
impl ScreenBackend {
@@ -63,49 +67,61 @@ impl ScreenBackend {
mouse_transform: Affine2::ZERO,
interaction_transform: None,
stereo: None,
logical_pos: Vec2::ZERO,
logical_size: Vec2::ZERO,
mouse_transform_original: Transform::Undefined,
mouse_transform_override: Transform::Undefined,
}
}
pub(super) fn set_mouse_transform(&mut self, pos: Vec2, size: Vec2, transform: Transform) {
pub(super) fn apply_mouse_transform_with_override(&mut self, override_transform: Transform) {
let size = self.logical_size;
let pos = self.logical_pos;
let transform = match override_transform {
Transform::Undefined => self.mouse_transform_original,
other => other,
};
self.mouse_transform = match transform {
Transform::Rotated90 | Transform::Flipped90 => Affine2::from_cols(
Transform::Normal | Transform::Undefined => {
Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos)
}
Transform::Rotated90 => Affine2::from_cols(
vec2(0., size.y),
vec2(-size.x, 0.),
vec2(pos.x + size.x, pos.y),
),
Transform::Rotated180 | Transform::Flipped180 => Affine2::from_cols(
Transform::Rotated180 => Affine2::from_cols(
vec2(-size.x, 0.),
vec2(0., -size.y),
vec2(pos.x + size.x, pos.y + size.y),
),
Transform::Rotated270 | Transform::Flipped270 => Affine2::from_cols(
Transform::Rotated270 => Affine2::from_cols(
vec2(0., -size.y),
vec2(size.x, 0.),
vec2(pos.x, pos.y + size.y),
),
_ => Affine2::from_cols(vec2(size.x, 0.), vec2(0., size.y), pos),
Transform::Flipped => Affine2::from_cols(
vec2(-size.x, 0.),
vec2(0., size.y),
vec2(pos.x + size.x, pos.y),
),
Transform::Flipped90 => {
Affine2::from_cols(vec2(0., size.y), vec2(size.x, 0.), vec2(pos.x, pos.y))
}
Transform::Flipped180 => Affine2::from_cols(
vec2(size.x, 0.),
vec2(0., -size.y),
vec2(pos.x, pos.y + size.y),
),
Transform::Flipped270 => Affine2::from_cols(
vec2(0., -size.y),
vec2(-size.x, 0.),
vec2(pos.x + size.x, pos.y + size.y),
),
};
}
pub(super) fn set_interaction_transform(&mut self, res: Vec2, transform: Transform) {
let center = Vec2 { x: 0.5, y: 0.5 };
self.interaction_transform = Some(match transform {
Transform::Rotated90 | Transform::Flipped90 => {
Affine2::from_cols(Vec2::NEG_Y * (res.x / res.y), Vec2::NEG_X, center)
}
Transform::Rotated180 | Transform::Flipped180 => {
Affine2::from_cols(Vec2::NEG_X, Vec2::NEG_Y * (-res.x / res.y), center)
}
Transform::Rotated270 | Transform::Flipped270 => {
Affine2::from_cols(Vec2::Y * (res.x / res.y), Vec2::X, center)
}
_ if res.y > res.x => {
// Xorg upright screens
Affine2::from_cols(Vec2::X * (res.y / res.x), Vec2::NEG_Y, center)
}
_ => Affine2::from_cols(Vec2::X, Vec2::NEG_Y * (res.x / res.y), center),
});
}
}
impl OverlayBackend for ScreenBackend {
@@ -175,17 +191,14 @@ impl OverlayBackend for ScreenBackend {
.is_some_and(|old| old.extent[..2] != meta.extent[..2])
{
pipeline.set_extent(app, [meta.extent[0] as _, meta.extent[1] as _])?;
self.set_interaction_transform(
meta.extent.extent_vec2(),
frame.get_transform(),
);
self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
}
} else {
let pipeline =
ScreenPipeline::new(&meta, app, self.stereo.unwrap_or(StereoMode::None))?;
meta.extent[2] = pipeline.get_depth();
self.pipeline = Some(pipeline);
self.set_interaction_transform(meta.extent.extent_vec2(), frame.get_transform());
self.interaction_transform = Some(ui_transform(meta.extent.extent_u32arr()));
}
self.meta = Some(meta);
@@ -281,6 +294,9 @@ impl OverlayBackend for ScreenBackend {
fn get_attrib(&self, attrib: BackendAttrib) -> Option<BackendAttribValue> {
match attrib {
BackendAttrib::Stereo => self.stereo.map(|s| BackendAttribValue::Stereo(s)),
BackendAttrib::MouseTransform => Some(BackendAttribValue::MouseTransform(
self.mouse_transform_override,
)),
_ => None,
}
}
@@ -299,6 +315,11 @@ impl OverlayBackend for ScreenBackend {
false
}
}
BackendAttribValue::MouseTransform(new) => {
self.mouse_transform_override = new;
self.apply_mouse_transform_with_override(new);
true
}
_ => false,
}
}

View File

@@ -1,6 +1,7 @@
use glam::vec2;
use wlx_capture::{
WlxCapture,
frame::Transform,
wayland::{WlxClient, WlxOutput},
wlr_dmabuf::WlrDmabufCapture,
wlr_screencopy::WlrScreencopyCapture,
@@ -124,15 +125,14 @@ pub fn create_screens_wayland(wl: &mut WlxClient, app: &mut AppState) -> ScreenC
&mut pw_tokens,
app,
) {
let logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
let logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
let transform = output.transform;
backend.set_mouse_transform(logical_pos, logical_size, transform);
backend.logical_pos = vec2(output.logical_pos.0 as f32, output.logical_pos.1 as f32);
backend.logical_size = vec2(output.logical_size.0 as f32, output.logical_size.1 as f32);
backend.mouse_transform_original = output.transform;
backend.apply_mouse_transform_with_override(Transform::Undefined);
let window_config = create_screen_from_backend(
output.name.clone(),
transform,
output.transform,
&app.session,
Box::new(backend),
);

View File

@@ -103,11 +103,9 @@ pub fn create_screens_x11pw(app: &mut AppState) -> anyhow::Result<ScreenCreateDa
),
);
backend.set_mouse_transform(
vec2(m.monitor.x() as f32, m.monitor.y() as f32),
vec2(m.monitor.width() as f32, m.monitor.height() as f32),
Transform::Normal,
);
backend.logical_pos = vec2(m.monitor.x() as f32, m.monitor.y() as f32);
backend.logical_size = vec2(m.monitor.width() as f32, m.monitor.height() as f32);
backend.apply_mouse_transform_with_override(Transform::Undefined);
let window_data = create_screen_from_backend(
m.name.clone(),
@@ -188,11 +186,9 @@ pub fn create_screens_xshm(app: &mut AppState) -> anyhow::Result<ScreenCreateDat
pos,
);
backend.set_mouse_transform(
vec2(s.monitor.x() as f32, s.monitor.y() as f32),
vec2(size.0 as f32, size.1 as f32),
Transform::Normal,
);
backend.logical_pos = vec2(s.monitor.x() as f32, s.monitor.y() as f32);
backend.logical_size = vec2(size.0 as f32, size.1 as f32);
backend.apply_mouse_transform_with_override(Transform::Undefined);
let window_data = create_screen_from_backend(
s.name.clone(),

View File

@@ -6,6 +6,7 @@ use wgui::gfx::{
WGfx,
cmd::{GfxCommandBuffer, WGfxClearMode},
};
use wlx_capture::frame::Transform;
use crate::{
backend::input::{HoverResult, PointerHit},
@@ -111,11 +112,13 @@ macro_rules! attrib_value {
#[derive(Clone, Copy)]
pub enum BackendAttrib {
Stereo,
MouseTransform,
}
#[derive(Debug, Clone)]
pub enum BackendAttribValue {
Stereo(StereoMode),
MouseTransform(Transform),
}
pub struct OverlayMeta {