diff options
author | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2020-03-29 21:13:35 -0300 |
---|---|---|
committer | Georges Basile Stavracas Neto <georges.stavracas@gmail.com> | 2021-08-13 18:17:36 +0000 |
commit | 0f0845172fff169c33f28ae3eccfc89cb022c9b2 (patch) | |
tree | b376dc72a22008dae6a3d6894ffd43d7551a97e6 | |
parent | b7ff6aa2d543252e261d5cb564c68f1c2c73a761 (diff) | |
download | gnome-control-center-0f0845172fff169c33f28ae3eccfc89cb022c9b2.tar.gz |
Introduce the Multitasking panel
The Multitasking panel brings some additional settings
from Tweaks that are relevant to the general platform.
Related: https://gitlab.gnome.org/GNOME/gnome-control-center/issues/558
21 files changed, 2251 insertions, 1 deletions
diff --git a/gnome-control-center.doap b/gnome-control-center.doap index 600fd66c8..7986d9150 100644 --- a/gnome-control-center.doap +++ b/gnome-control-center.doap @@ -13,7 +13,7 @@ <category rdf:resource="http://api.gnome.org/doap-extensions#core" /> <programming-language>C</programming-language> - <!-- General --> + <!-- General, Multitasking --> <maintainer> <foaf:Person> <foaf:name>Georges Basile Stavracas Neto</foaf:name> diff --git a/panels/meson.build b/panels/meson.build index 2f4fdc5e3..1318904ae 100644 --- a/panels/meson.build +++ b/panels/meson.build @@ -15,6 +15,7 @@ panels = [ 'lock', 'microphone', 'mouse', + 'multitasking', 'notifications', 'online-accounts', 'power', diff --git a/panels/multitasking/assets/active-screen-edges.svg b/panels/multitasking/assets/active-screen-edges.svg new file mode 100644 index 000000000..34dc67b4e --- /dev/null +++ b/panels/multitasking/assets/active-screen-edges.svg @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="160" + height="94" + viewBox="0 0 42.333332 24.870834" + version="1.1" + id="svg1555" + inkscape:version="1.1 (c68e22c387, 2021-05-23)" + sodipodi:docname="active-screen-edges.svg" + 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"> + <sodipodi:namedview + id="namedview1557" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + width="160mm" + units="px" + inkscape:zoom="0.64" + inkscape:cx="-25.78125" + inkscape:cy="240.625" + inkscape:window-width="1920" + inkscape:window-height="1011" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1552"> + <clipPath + id="clipPath9252" + clipPathUnits="userSpaceOnUse"> + <rect + y="-4731.0068" + x="316" + height="95" + width="162" + id="rect9254" + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + </clipPath> + <clipPath + id="clipPath9252-2" + clipPathUnits="userSpaceOnUse"> + <rect + y="-4731.0068" + x="316" + height="95" + width="162" + id="rect9254-9" + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + </clipPath> + </defs> + <g + inkscape:label="Camada 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="display:inline;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#3584e4;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1114" + width="41.80423" + height="24.341667" + x="0.2645835" + y="0.2645835" /> + <rect + y="1.3696841" + x="0.51395404" + height="23.198996" + width="20.486208" + id="rect9256" + style="display:inline;opacity:0.287;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:#3584e4;stroke-width:0.79375;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + <g + transform="matrix(0.26458333,0,0,0.26458333,-400.05167,1156.7601)" + id="g9263" + style="display:inline"> + <rect + ry="2.9999998" + rx="2.9999998" + y="-4353.0068" + x="1520.0065" + height="58.000057" + width="76" + id="rect1158" + style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" /> + <path + id="path1160" + overflow="visible" + font-weight="400" + style="color:#bebebe;font-weight:400;line-height:normal;font-family:'Andale Mono';-inkscape-font-specification:'Andale Mono';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-transform:none;overflow:visible;fill:#3584e4;fill-opacity:1;marker:none" + d="m 1583,-4348.0058 h 1.031 c 0.255,0.011 0.51,0.129 0.688,0.313 l 2.281,2.279 2.312,-2.28 c 0.266,-0.231 0.447,-0.306 0.688,-0.313 h 1 v 1 c 0,0.286 -0.034,0.55 -0.25,0.75 l -2.281,2.282 2.25,2.25 c 0.188,0.188 0.281,0.454 0.281,0.719 v 1 h -1 c -0.265,0 -0.53,-0.093 -0.719,-0.281 l -2.281,-2.281 -2.281,2.28 a 1.015,1.015 0 0 1 -0.719,0.282 h -1 v -1 c 0,-0.265 0.093,-0.53 0.281,-0.719 l 2.281,-2.25 -2.28,-2.281 a 0.909,0.909 0 0 1 -0.282,-0.75 z" /> + <g + style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#3584e4;stroke-opacity:1" + id="g1276" + transform="matrix(1.6306074,0,0,1.6324898,1484.124,-4348.5411)"> + <path + id="path1272" + d="M 26.604893,2.3179921 V 18.758225 l 3.712311,-3.623922 2.12132,4.331029 c 0.519598,1.171377 3.220861,0.229524 2.452777,-1.336875 l -2.099224,-4.496756 h 4.684582 z" + style="color:#000000;display:block;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" /> + <path + style="color:#000000;display:block;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="M 26.604893,2.3179921 V 18.758225 l 3.712311,-3.623922 2.12132,4.331029 c 0.519598,1.171377 3.220861,0.229524 2.452777,-1.336875 l -2.099224,-4.496756 h 4.684582 z" + id="path1274" /> + </g> + </g> + <path + id="rect1179-7" + d="M 1.1938423e-4,2.750539e-4 V 0.26485805 2.6482511 H 0.52772538 c 0,-0.397748 0.395737,-0.793829 0.79330002,-0.793829 H 40.995507 c 0.444474,0 0.807217,0.424021 0.807217,0.793829 l 0.509508,-0.0026 0.02117,-2.645595046096 z" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + </g> +</svg> diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg new file mode 100644 index 000000000..0a1732c0e --- /dev/null +++ b/panels/multitasking/assets/hot-corner.svg @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="160" + height="94" + viewBox="0 0 42.333332 24.870834" + version="1.1" + id="svg1555" + inkscape:version="1.1 (c68e22c387, 2021-05-23)" + sodipodi:docname="hot-corner.svg" + 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"> + <sodipodi:namedview + id="namedview1557" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + width="160mm" + units="px" + inkscape:zoom="3.6203867" + inkscape:cx="87.697814" + inkscape:cy="96.950969" + inkscape:window-width="1920" + inkscape:window-height="1011" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1552"> + <clipPath + id="clipPath9252" + clipPathUnits="userSpaceOnUse"> + <rect + y="-4731.0068" + x="316" + height="95" + width="162" + id="rect9254" + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + </clipPath> + </defs> + <g + inkscape:label="Camada 1" + inkscape:groupmode="layer" + id="layer1"> + <g + transform="matrix(0.26458333,0,0,0.26458333,-396.87656,960.96898)" + id="g1185" + style="display:inline"> + <rect + style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1173" + width="158.00024" + height="92" + x="1501.0063" + y="-3631.0071" /> + <path + id="rect1179" + d="m 1500.0059,-3632.0078 v 1 9.0081 H 1502 c 0,-1.5033 1.4957,-3.0003 2.9983,-3.0003 h 149.9508 c 1.6799,0 3.0509,1.6026 3.0509,3.0003 l 1.9257,-0.01 0.08,-9.9991 z" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + </g> + <g + clip-path="url(#clipPath9252)" + transform="matrix(0.26458333,0,0,0.26458333,-83.608226,1251.7459)" + id="g9250" + style="display:inline"> + <circle + style="opacity:0.249;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" + id="path9238" + cx="316.00006" + cy="-4731.0068" + r="78.260803" /> + <circle + r="47.991684" + cy="-4731.0068" + cx="316" + id="circle9240" + style="opacity:0.474;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + <circle + style="opacity:0.705;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" + id="circle9242" + cx="316" + cy="-4731.0068" + r="26.859203" /> + <circle + r="16.567965" + cy="-4731.0068" + cx="316" + id="circle9244" + style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" /> + </g> + <g + id="g3562" + transform="matrix(0.42866156,0,0,0.42915644,-106.13477,-107.60043)" + style="display:inline"> + <path + style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0.95;stroke-opacity:1;marker:none;enable-background:accumulate" + d="m 275.61943,271.74975 -3.12986,-3.21358 4.94975,-4.94975 -18.38478,-1.41422 1.41422,18.38478 4.94975,-4.94975 7.67189,7.67189" + id="path3548" /> + <g + style="display:inline" + id="g3554" + transform="translate(251.65245,268.27952)"> + <path + style="color:#000000;display:block;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1.22583, 0.612915;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" + d="M 29.691048,6.6336286 V 23.073865 l 3.712311,-3.623922 2.12132,4.331029 c 0.519598,1.171377 3.220861,0.229524 2.452777,-1.336875 l -2.099224,-4.496756 h 4.684582 z" + id="path3552" /> + </g> + <g + style="display:inline" + id="g3560" + transform="translate(281.65245,298.27952)" /> + </g> + </g> +</svg> diff --git a/panels/multitasking/assets/workspaces-primary-display.svg b/panels/multitasking/assets/workspaces-primary-display.svg new file mode 100644 index 000000000..56e05c4bb --- /dev/null +++ b/panels/multitasking/assets/workspaces-primary-display.svg @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="300" + height="100" + viewBox="0 0 79.374998 26.458334" + version="1.1" + id="svg1869" + sodipodi:docname="workspaces-primary-display.svg" + inkscape:version="1.1 (c68e22c387, 2021-05-23)" + 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"> + <sodipodi:namedview + id="namedview1871" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + units="px" + inkscape:zoom="2.56" + inkscape:cx="411.13281" + inkscape:cy="273.04688" + inkscape:window-width="3840" + inkscape:window-height="2091" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1866"> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath1386"> + <rect + style="opacity:1;vector-effect:none;fill:#ed333b;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1388" + width="127" + height="73" + x="1448" + y="-3870.0144" /> + </clipPath> + </defs> + <g + inkscape:label="Camada 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="vector-effect:none;fill:none;fill-opacity:1;stroke:#98c1f1;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.5875, 1.5875;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect9297" + width="41.539581" + height="25.929115" + x="0.2645835" + y="0.2645835" /> + <g + id="g1336" + style="display:inline" + transform="matrix(0.26458333,0,0,0.26458333,-378.97118,1027.377)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect9299" + width="127" + height="73" + x="1605" + y="-3870.0144" /> + <rect + style="fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stop-color:#000000" + id="rect1332" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + <g + id="g1384" + clip-path="url(#clipPath1386)" + transform="matrix(0.26458333,0,0,0.26458333,-378.97118,1027.377)"> + <g + id="g1370" + style="display:inline" + transform="translate(-96.931677)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1366" + width="132.98438" + height="73" + x="1599.0156" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1368" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + <g + id="g1376" + style="display:inline" + transform="translate(-224.02007)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1372" + width="127" + height="73" + x="1605" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1374" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + </g> + </g> +</svg> diff --git a/panels/multitasking/assets/workspaces-span-displays.svg b/panels/multitasking/assets/workspaces-span-displays.svg new file mode 100644 index 000000000..7b3655df9 --- /dev/null +++ b/panels/multitasking/assets/workspaces-span-displays.svg @@ -0,0 +1,178 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="313" + height="100" + viewBox="0 0 82.814582 26.458334" + version="1.1" + id="svg1869" + inkscape:version="1.1 (c68e22c387, 2021-05-23)" + sodipodi:docname="workspaces-all-displays.svg" + 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"> + <sodipodi:namedview + id="namedview1871" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + units="px" + inkscape:zoom="2.56" + inkscape:cx="411.13281" + inkscape:cy="273.04688" + inkscape:window-width="3840" + inkscape:window-height="2091" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" /> + <defs + id="defs1866"> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath1386"> + <rect + style="opacity:1;vector-effect:none;fill:#ed333b;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1388" + width="127" + height="73" + x="1448" + y="-3870.0144" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath1386-9"> + <rect + style="opacity:1;vector-effect:none;fill:#ed333b;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1388-4" + width="127" + height="73" + x="1448" + y="-3870.0144" /> + </clipPath> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath2112"> + <rect + style="opacity:1;vector-effect:none;fill:#ed333b;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect2110" + width="127" + height="73" + x="1448" + y="-3870.0144" /> + </clipPath> + </defs> + <g + inkscape:label="Camada 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="font-variation-settings:normal;display:inline;vector-effect:none;fill:none;fill-opacity:1;stroke:#98c1f1;stroke-width:0.529025;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.58707, 1.58707;stroke-dashoffset:0;stroke-opacity:1;marker:none;stop-color:#000000" + id="rect1390" + width="82.285698" + height="25.716372" + x="0.26444107" + y="0.2645835" /> + <g + id="g1490" + clip-path="url(#clipPath1386-9)" + transform="matrix(0.26444091,0,0,0.26458333,-378.87348,1027.8037)"> + <g + id="g1482" + style="display:inline" + transform="translate(-96.931677)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1478" + width="132.98438" + height="73" + x="1599.0156" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1480" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + <g + id="g1488" + style="display:inline" + transform="translate(-224.02007)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1484" + width="127" + height="73" + x="1605" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1486" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + </g> + <g + id="g1505" + clip-path="url(#clipPath1386-9)" + transform="matrix(0.26444091,0,0,0.26458333,-337.35626,1027.8037)"> + <g + id="g1496" + style="display:inline" + transform="translate(-96.931677)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1492" + width="132.98438" + height="73" + x="1599.0156" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1494" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + <g + id="g1503" + style="display:inline" + transform="translate(-224.02007)"> + <rect + style="opacity:1;vector-effect:none;fill:#3584e4;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" + id="rect1499" + width="127" + height="73" + x="1605" + y="-3870.0144" /> + <rect + style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#c5dcf7;fill-opacity:1;stroke:none;stroke-width:1.03357;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1" + id="rect1501" + width="117" + height="63.000103" + x="1610" + y="-3865.0144" + rx="5.0263672" + ry="5.0263672" /> + </g> + </g> + </g> +</svg> diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c new file mode 100644 index 000000000..6a3177fe9 --- /dev/null +++ b/panels/multitasking/cc-multitasking-panel.c @@ -0,0 +1,150 @@ +/* cc-multitasking-panel.h + * + * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "cc-multitasking-panel.h" + +#include "cc-multitasking-resources.h" +#include "cc-multitasking-row.h" +#include "list-box-helper.h" + +struct _CcMultitaskingPanel +{ + CcPanel parent_instance; + + GSettings *interface_settings; + GSettings *mutter_settings; + GSettings *overrides_settings; + GSettings *shell_settings; + GSettings *wm_settings; + + GtkSwitch *active_screen_edges_switch; + GtkToggleButton *current_workspace_radio; + GtkToggleButton *dynamic_workspaces_radio; + GtkToggleButton *fixed_workspaces_radio; + GtkSwitch *hot_corner_switch; + GtkSpinButton *number_of_workspaces_spin; + GtkToggleButton *workspaces_primary_display_radio; + GtkToggleButton *workspaces_span_displays_radio; +}; + +CC_PANEL_REGISTER (CcMultitaskingPanel, cc_multitasking_panel) + +/* GObject overrides */ + +static void +cc_multitasking_panel_finalize (GObject *object) +{ + CcMultitaskingPanel *self = (CcMultitaskingPanel *)object; + + g_clear_object (&self->interface_settings); + g_clear_object (&self->mutter_settings); + g_clear_object (&self->overrides_settings); + g_clear_object (&self->shell_settings); + g_clear_object (&self->wm_settings); + + G_OBJECT_CLASS (cc_multitasking_panel_parent_class)->finalize (object); +} + +static void +cc_multitasking_panel_class_init (CcMultitaskingPanelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + g_type_ensure (CC_TYPE_MULTITASKING_ROW); + + object_class->finalize = cc_multitasking_panel_finalize; + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-panel.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_switch); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, current_workspace_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, dynamic_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, fixed_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_switch); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, number_of_workspaces_spin); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_primary_display_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_span_displays_radio); +} + +static void +cc_multitasking_panel_init (CcMultitaskingPanel *self) +{ + g_resources_register (cc_multitasking_get_resource ()); + + gtk_widget_init_template (GTK_WIDGET (self)); + + self->interface_settings = g_settings_new ("org.gnome.desktop.interface"); + g_settings_bind (self->interface_settings, + "enable-hot-corners", + self->hot_corner_switch, + "active", + G_SETTINGS_BIND_DEFAULT); + + self->mutter_settings = g_settings_new ("org.gnome.mutter"); + + if (g_settings_get_boolean (self->mutter_settings, "workspaces-only-on-primary")) + gtk_toggle_button_set_active (self->workspaces_primary_display_radio, TRUE); + else + gtk_toggle_button_set_active (self->workspaces_span_displays_radio, TRUE); + + g_settings_bind (self->mutter_settings, + "workspaces-only-on-primary", + self->workspaces_primary_display_radio, + "active", + G_SETTINGS_BIND_DEFAULT); + g_settings_bind (self->mutter_settings, + "edge-tiling", + self->active_screen_edges_switch, + "active", + G_SETTINGS_BIND_DEFAULT); + + self->overrides_settings = g_settings_new ("org.gnome.shell.overrides"); + + if (g_settings_get_boolean (self->overrides_settings, "dynamic-workspaces")) + gtk_toggle_button_set_active (self->dynamic_workspaces_radio, TRUE); + else + gtk_toggle_button_set_active (self->fixed_workspaces_radio, TRUE); + + g_settings_bind (self->overrides_settings, + "dynamic-workspaces", + self->dynamic_workspaces_radio, + "active", + G_SETTINGS_BIND_DEFAULT); + + self->wm_settings = g_settings_new ("org.gnome.desktop.wm.preferences"); + g_settings_bind (self->wm_settings, + "num-workspaces", + self->number_of_workspaces_spin, + "value", + G_SETTINGS_BIND_DEFAULT); + + self->shell_settings = g_settings_new ("org.gnome.shell.app-switcher"); + + if (g_settings_get_boolean (self->shell_settings, "current-workspace-only")) + gtk_toggle_button_set_active (self->current_workspace_radio, TRUE); + + g_settings_bind (self->shell_settings, + "current-workspace-only", + self->current_workspace_radio, + "active", + G_SETTINGS_BIND_DEFAULT); +} diff --git a/panels/multitasking/cc-multitasking-panel.h b/panels/multitasking/cc-multitasking-panel.h new file mode 100644 index 000000000..81e78f071 --- /dev/null +++ b/panels/multitasking/cc-multitasking-panel.h @@ -0,0 +1,30 @@ +/* cc-multitasking-panel.h + * + * Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include <shell/cc-panel.h> + +G_BEGIN_DECLS + +#define CC_TYPE_MULTITASKING_PANEL (cc_multitasking_panel_get_type()) +G_DECLARE_FINAL_TYPE (CcMultitaskingPanel, cc_multitasking_panel, CC, MULTITASKING_PANEL, CcPanel) + +G_END_DECLS diff --git a/panels/multitasking/cc-multitasking-panel.ui b/panels/multitasking/cc-multitasking-panel.ui new file mode 100644 index 000000000..5b5725038 --- /dev/null +++ b/panels/multitasking/cc-multitasking-panel.ui @@ -0,0 +1,357 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <template class="CcMultitaskingPanel" parent="CcPanel"> + <property name="visible">True</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">true</property> + <property name="hscrollbar-policy">never</property> + <child> + <object class="HdyClamp"> + <property name="visible">True</property> + <property name="maximum-size">600</property> + <property name="tightening-threshold">400</property> + <property name="margin_top">32</property> + <property name="margin_bottom">32</property> + <property name="margin_start">12</property> + <property name="margin_end">12</property> + + <child> + <object class="GtkBox"> + <property name="visible">true</property> + <property name="can-focus">false</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + + <!-- General --> + <child> + <object class="GtkLabel"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="label" translatable="yes">General</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold" /> + </attributes> + </object> + </child> + + <child> + <object class="GtkListBox"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="selection-mode">none</property> + <property name="margin-bottom">24</property> + + <style> + <class name="content"/> + </style> + + <!-- Hot Corner --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">hot_corner_switch</property> + <property name="title" translatable="yes">_Hot Corner</property> + <property name="subtitle" translatable="yes">Touch the top-left corner to open the Activities Overview.</property> + <property name="use_underline">True</property> + <child> + <object class="GtkSwitch" id="hot_corner_switch"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + </object> + </child> + <child type="artwork"> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">center</property> + <property name="margin">18</property> + <property name="resource">/org/gnome/control-center/multitasking/assets/hot-corner.svg</property> + </object> + </child> + </object> + </child> + + <!-- Active Screen Edges --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">active_screen_edges_switch</property> + <property name="title" translatable="yes">_Active Screen Edges</property> + <property name="subtitle" translatable="yes">Drag windows against the top, left, and right screen edges to resize them.</property> + <property name="use_underline">True</property> + <child> + <object class="GtkSwitch" id="active_screen_edges_switch"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + </object> + </child> + <child type="artwork"> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">center</property> + <property name="margin">18</property> + <property name="resource">/org/gnome/control-center/multitasking/assets/active-screen-edges.svg</property> + </object> + </child> + </object> + </child> + + </object> + </child> + + <!-- Workspaces --> + <child> + <object class="GtkLabel"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="label" translatable="yes">Workspaces</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold" /> + </attributes> + </object> + </child> + + <child> + <object class="GtkListBox"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="selection-mode">none</property> + <property name="margin-bottom">18</property> + + <style> + <class name="content"/> + </style> + + <!-- Dynamic Workspaces --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">dynamic_workspaces_radio</property> + <property name="title" translatable="yes">_Dynamic workspaces</property> + <property name="subtitle" translatable="yes">Automatically removes empty workspaces.</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="dynamic_workspaces_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + </object> + </child> + </object> + </child> + + <!-- Fixed Number of Workspaces --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">fixed_workspaces_radio</property> + <property name="title" translatable="yes">_Fixed number of workspaces</property> + <property name="subtitle" translatable="yes">Specify a number of permanent workspaces.</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="fixed_workspaces_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + <property name="group">dynamic_workspaces_radio</property> + </object> + </child> + </object> + </child> + + <!-- Number of Workspaces --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="sensitive" bind-source="fixed_workspaces_radio" bind-property="active" bind-flags="default|sync-create" /> + <property name="activatable-widget">number_of_workspaces_spin</property> + <property name="title" translatable="yes">_Number of Workspaces</property> + <property name="use_underline">True</property> + <child> + <object class="GtkSpinButton" id="number_of_workspaces_spin"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + <property name="adjustment">workspaces_adjustment</property> + </object> + </child> + </object> + </child> + + </object> + </child> + + <!-- Multi-Monitor --> + <child> + <object class="GtkLabel"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="label" translatable="yes">Multi-Monitor</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold" /> + </attributes> + </object> + </child> + + <child> + <object class="GtkListBox"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="selection-mode">none</property> + <property name="margin-bottom">18</property> + + <style> + <class name="content"/> + </style> + + <!-- Primary Display --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">workspaces_primary_display_radio</property> + <property name="title" translatable="yes">Workspaces on _primary display only</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="workspaces_primary_display_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + </object> + </child> + <child type="artwork"> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">center</property> + <property name="margin">18</property> + <property name="resource">/org/gnome/control-center/multitasking/assets/workspaces-primary-display.svg</property> + </object> + </child> + </object> + </child> + + <!-- Span Displays --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">workspaces_span_displays_radio</property> + <property name="title" translatable="yes">Workspaces on all d_isplays</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="workspaces_span_displays_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + <property name="group">workspaces_primary_display_radio</property> + </object> + </child> + <child type="artwork"> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="hexpand">True</property> + <property name="halign">center</property> + <property name="margin">18</property> + <property name="resource">/org/gnome/control-center/multitasking/assets/workspaces-span-displays.svg</property> + </object> + </child> + </object> + </child> + + </object> + </child> + + <!-- Application Switching --> + <child> + <object class="GtkLabel"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="label" translatable="yes">Application Switching</property> + <property name="xalign">0.0</property> + <attributes> + <attribute name="weight" value="bold" /> + </attributes> + </object> + </child> + + <child> + <object class="GtkListBox"> + <property name="visible">true</property> + <property name="can-focus">true</property> + <property name="selection-mode">none</property> + <property name="margin-bottom">18</property> + + <style> + <class name="content"/> + </style> + + <!-- All Workspaces --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">all_workspaces_radio</property> + <property name="title" translatable="yes">Include applications from all _workspaces</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="all_workspaces_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + </object> + </child> + </object> + </child> + + <!-- Current Workspace --> + <child> + <object class="CcMultitaskingRow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="activatable-widget">current_workspace_radio</property> + <property name="title" translatable="yes">Include applications from the _current workspace only</property> + <property name="use_underline">True</property> + <child type="prefix"> + <object class="GtkRadioButton" id="current_workspace_radio"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="valign">center</property> + <property name="group">all_workspaces_radio</property> + </object> + </child> + </object> + </child> + + </object> + </child> + + </object> + </child> + + </object> + </child> + </object> + </child> + </template> + + <object class="GtkAdjustment" id="workspaces_adjustment"> + <property name="lower">1.0</property> + <property name="step-increment">1.0</property> + <property name="value">4.0</property> + <!-- 36 is the maximum value allowed by Mutter --> + <property name="upper">36.0</property> + </object> +</interface> diff --git a/panels/multitasking/cc-multitasking-row.c b/panels/multitasking/cc-multitasking-row.c new file mode 100644 index 000000000..608e4c48f --- /dev/null +++ b/panels/multitasking/cc-multitasking-row.c @@ -0,0 +1,684 @@ +/* cc-multitasking-row.c + * + * Copyright 2018 Purism SPC + * 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "cc-multitasking-row.h" + +struct _CcMultitaskingRow +{ + HdyPreferencesRow parent; + + GtkBox *artwork_box; + GtkBox *header; + GtkImage *image; + GtkBox *prefixes; + GtkLabel *subtitle; + GtkBox *suffixes; + GtkLabel *title; + GtkBox *title_box; + + GtkWidget *previous_parent; + + gboolean use_underline; + gint title_lines; + gint subtitle_lines; + GtkWidget *activatable_widget; +}; + +static void cc_multitasking_row_buildable_init (GtkBuildableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (CcMultitaskingRow, cc_multitasking_row, HDY_TYPE_PREFERENCES_ROW, + G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_multitasking_row_buildable_init)) + +enum +{ + PROP_0, + PROP_ICON_NAME, + PROP_ACTIVATABLE_WIDGET, + PROP_SUBTITLE, + PROP_USE_UNDERLINE, + PROP_TITLE_LINES, + PROP_SUBTITLE_LINES, + N_PROPS, +}; + +enum +{ + SIGNAL_ACTIVATED, + SIGNAL_LAST_SIGNAL, +}; + +static GParamSpec *props[N_PROPS] = { NULL, }; +static guint signals[SIGNAL_LAST_SIGNAL] = { 0, }; + +static void +row_activated_cb (CcMultitaskingRow *self, + GtkListBoxRow *row) +{ + /* No need to use GTK_LIST_BOX_ROW() for a pointer comparison. */ + if ((GtkListBoxRow *) self == row) + cc_multitasking_row_activate (self); +} + +static void +parent_cb (CcMultitaskingRow *self) +{ + GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self)); + + if (self->previous_parent != NULL) + { + g_signal_handlers_disconnect_by_func (self->previous_parent, + G_CALLBACK (row_activated_cb), + self); + self->previous_parent = NULL; + } + + if (parent == NULL || !GTK_IS_LIST_BOX (parent)) + return; + + self->previous_parent = parent; + g_signal_connect_swapped (parent, "row-activated", G_CALLBACK (row_activated_cb), self); +} + +static void +update_subtitle_visibility (CcMultitaskingRow *self) +{ + gtk_widget_set_visible (GTK_WIDGET (self->subtitle), + gtk_label_get_text (self->subtitle) != NULL && + g_strcmp0 (gtk_label_get_text (self->subtitle), "") != 0); +} + +static void +cc_multitasking_row_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); + + switch (prop_id) + { + case PROP_ICON_NAME: + g_value_set_string (value, cc_multitasking_row_get_icon_name (self)); + break; + case PROP_ACTIVATABLE_WIDGET: + g_value_set_object (value, (GObject *) cc_multitasking_row_get_activatable_widget (self)); + break; + case PROP_SUBTITLE: + g_value_set_string (value, cc_multitasking_row_get_subtitle (self)); + break; + case PROP_SUBTITLE_LINES: + g_value_set_int (value, cc_multitasking_row_get_subtitle_lines (self)); + break; + case PROP_TITLE_LINES: + g_value_set_int (value, cc_multitasking_row_get_title_lines (self)); + break; + case PROP_USE_UNDERLINE: + g_value_set_boolean (value, cc_multitasking_row_get_use_underline (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_multitasking_row_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); + + switch (prop_id) + { + case PROP_ICON_NAME: + cc_multitasking_row_set_icon_name (self, g_value_get_string (value)); + break; + case PROP_ACTIVATABLE_WIDGET: + cc_multitasking_row_set_activatable_widget (self, (GtkWidget*) g_value_get_object (value)); + break; + case PROP_SUBTITLE: + cc_multitasking_row_set_subtitle (self, g_value_get_string (value)); + break; + case PROP_SUBTITLE_LINES: + cc_multitasking_row_set_subtitle_lines (self, g_value_get_int (value)); + break; + case PROP_TITLE_LINES: + cc_multitasking_row_set_title_lines (self, g_value_get_int (value)); + break; + case PROP_USE_UNDERLINE: + cc_multitasking_row_set_use_underline (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_multitasking_row_dispose (GObject *object) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); + + if (self->previous_parent != NULL) { + g_signal_handlers_disconnect_by_func (self->previous_parent, G_CALLBACK (row_activated_cb), self); + self->previous_parent = NULL; + } + + G_OBJECT_CLASS (cc_multitasking_row_parent_class)->dispose (object); +} + +static void +cc_multitasking_row_show_all (GtkWidget *widget) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (widget); + + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + + gtk_container_foreach (GTK_CONTAINER (self->prefixes), + (GtkCallback) gtk_widget_show_all, + NULL); + + gtk_container_foreach (GTK_CONTAINER (self->suffixes), + (GtkCallback) gtk_widget_show_all, + NULL); + + GTK_WIDGET_CLASS (cc_multitasking_row_parent_class)->show_all (widget); +} + +static void +cc_multitasking_row_destroy (GtkWidget *widget) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (widget); + + if (self->header) + { + gtk_widget_destroy (GTK_WIDGET (self->header)); + self->header = NULL; + } + + cc_multitasking_row_set_activatable_widget (self, NULL); + + self->prefixes = NULL; + self->suffixes = NULL; + + GTK_WIDGET_CLASS (cc_multitasking_row_parent_class)->destroy (widget); +} + +static void +cc_multitasking_row_add (GtkContainer *container, + GtkWidget *child) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); + + /* When constructing the widget, we want the box to be added as the child of + * the GtkListBoxRow, as an implementation detail. + */ + if (!self->header) + { + GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->add (container, child); + } + else + { + gtk_container_add (GTK_CONTAINER (self->suffixes), child); + gtk_widget_show (GTK_WIDGET (self->suffixes)); + } +} + +static void +cc_multitasking_row_remove (GtkContainer *container, + GtkWidget *child) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); + + if (child == GTK_WIDGET (self->header)) + GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->remove (container, child); + else if (gtk_widget_get_parent (child) == GTK_WIDGET (self->prefixes)) + gtk_container_remove (GTK_CONTAINER (self->prefixes), child); + else + gtk_container_remove (GTK_CONTAINER (self->suffixes), child); +} + +typedef struct { + CcMultitaskingRow *row; + GtkCallback callback; + gpointer callback_data; +} ForallData; + +static void +for_non_internal_child (GtkWidget *widget, + gpointer callback_data) +{ + ForallData *data = callback_data; + CcMultitaskingRow *self = data->row; + + if (widget != (GtkWidget *) self->image && + widget != (GtkWidget *) self->prefixes && + widget != (GtkWidget *) self->suffixes && + widget != (GtkWidget *) self->title_box) + { + data->callback (widget, data->callback_data); + } +} + +static void +cc_multitasking_row_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); + ForallData data; + + if (include_internals) + { + GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->forall (GTK_CONTAINER (self), + include_internals, + callback, + callback_data); + return; + } + + data.row = self; + data.callback = callback; + data.callback_data = callback_data; + + if (self->prefixes) + { + GTK_CONTAINER_GET_CLASS (self->prefixes)->forall (GTK_CONTAINER (self->prefixes), + include_internals, + for_non_internal_child, + &data); + } + if (self->suffixes) + { + GTK_CONTAINER_GET_CLASS (self->suffixes)->forall (GTK_CONTAINER (self->suffixes), + include_internals, + for_non_internal_child, + &data); + } + if (self->header) + { + GTK_CONTAINER_GET_CLASS (self->header)->forall (GTK_CONTAINER (self->header), + include_internals, + for_non_internal_child, + &data); + } +} + +static void +cc_multitasking_row_class_init (CcMultitaskingRowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); + + object_class->get_property = cc_multitasking_row_get_property; + object_class->set_property = cc_multitasking_row_set_property; + object_class->dispose = cc_multitasking_row_dispose; + + widget_class->destroy = cc_multitasking_row_destroy; + widget_class->show_all = cc_multitasking_row_show_all; + + container_class->add = cc_multitasking_row_add; + container_class->remove = cc_multitasking_row_remove; + container_class->forall = cc_multitasking_row_forall; + + props[PROP_ICON_NAME] = + g_param_spec_string ("icon-name", + "Icon name", + "Icon name", + "", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + props[PROP_ACTIVATABLE_WIDGET] = + g_param_spec_object ("activatable-widget", + "Activatable widget", + "The widget to be activated when the row is activated", + GTK_TYPE_WIDGET, + G_PARAM_READWRITE); + + props[PROP_SUBTITLE] = + g_param_spec_string ("subtitle", + "Subtitle", + "Subtitle", + "", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + props[PROP_USE_UNDERLINE] = + g_param_spec_boolean ("use-underline", + "Use underline", + "If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key", + FALSE, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + + props[PROP_TITLE_LINES] = + g_param_spec_int ("title-lines", + "Number of title lines", + "The desired number of title lines", + 0, G_MAXINT, + 1, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + + props[PROP_SUBTITLE_LINES] = + g_param_spec_int ("subtitle-lines", + "Number of subtitle lines", + "The desired number of subtitle lines", + 0, G_MAXINT, + 1, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, N_PROPS, props); + + signals[SIGNAL_ACTIVATED] = + g_signal_new ("activated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, + 0); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, artwork_box); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, header); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, image); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, prefixes); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, subtitle); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, suffixes); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title_box); +} + +static gboolean +string_is_not_empty (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + const gchar *string = g_value_get_string (from_value); + + g_value_set_boolean (to_value, string != NULL && g_strcmp0 (string, "") != 0); + + return TRUE; +} + +static void +cc_multitasking_row_init (CcMultitaskingRow *self) +{ + self->title_lines = 1; + self->subtitle_lines = 1; + + gtk_widget_init_template (GTK_WIDGET (self)); + + g_object_bind_property_full (self, "title", + self->title, "visible", + G_BINDING_SYNC_CREATE, + string_is_not_empty, + NULL, NULL, NULL); + + update_subtitle_visibility (self); + + g_signal_connect (self, "notify::parent", G_CALLBACK (parent_cb), NULL); +} + +static void +cc_multitasking_row_buildable_add_child (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *type) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (buildable); + + if (self->header == NULL || !type) + gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (child)); + else if (type && strcmp (type, "prefix") == 0) + cc_multitasking_row_add_prefix (self, GTK_WIDGET (child)); + else if (type && strcmp (type, "artwork") == 0) + cc_multitasking_row_add_artwork(self, GTK_WIDGET (child)); + else + GTK_BUILDER_WARN_INVALID_CHILD_TYPE (self, type); +} + +static void +cc_multitasking_row_buildable_init (GtkBuildableIface *iface) +{ + iface->add_child = cc_multitasking_row_buildable_add_child; +} + +const gchar * +cc_multitasking_row_get_subtitle (CcMultitaskingRow *self) +{ + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); + + return gtk_label_get_text (self->subtitle); +} + +void +cc_multitasking_row_set_subtitle (CcMultitaskingRow *self, + const gchar *subtitle) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + + if (g_strcmp0 (gtk_label_get_text (self->subtitle), subtitle) == 0) + return; + + gtk_label_set_text (self->subtitle, subtitle); + gtk_widget_set_visible (GTK_WIDGET (self->subtitle), + subtitle != NULL && g_strcmp0 (subtitle, "") != 0); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE]); +} + +const gchar * +cc_multitasking_row_get_icon_name (CcMultitaskingRow *self) +{ + const gchar *icon_name; + + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); + + gtk_image_get_icon_name (self->image, &icon_name, NULL); + + return icon_name; +} + +void +cc_multitasking_row_set_icon_name (CcMultitaskingRow *self, + const gchar *icon_name) +{ + const gchar *old_icon_name; + + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + + gtk_image_get_icon_name (self->image, &old_icon_name, NULL); + if (g_strcmp0 (old_icon_name, icon_name) == 0) + return; + + gtk_image_set_from_icon_name (self->image, icon_name, GTK_ICON_SIZE_INVALID); + gtk_widget_set_visible (GTK_WIDGET (self->image), + icon_name != NULL && g_strcmp0 (icon_name, "") != 0); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]); +} + +GtkWidget * +cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self) +{ + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); + + return self->activatable_widget; +} + +static void +activatable_widget_weak_notify (gpointer data, + GObject *where_the_object_was) +{ + CcMultitaskingRow *self = CC_MULTITASKING_ROW (data); + + self->activatable_widget = NULL; + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]); +} + +void +cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self, + GtkWidget *widget) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); + + if (self->activatable_widget == widget) + return; + + if (self->activatable_widget) + g_object_weak_unref (G_OBJECT (self->activatable_widget), + activatable_widget_weak_notify, + self); + + self->activatable_widget = widget; + + if (self->activatable_widget != NULL) { + g_object_weak_ref (G_OBJECT (self->activatable_widget), + activatable_widget_weak_notify, + self); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE); + } + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]); +} + +gboolean +cc_multitasking_row_get_use_underline (CcMultitaskingRow *self) +{ + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), FALSE); + + return self->use_underline; +} + +void +cc_multitasking_row_set_use_underline (CcMultitaskingRow *self, + gboolean use_underline) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + + use_underline = !!use_underline; + + if (self->use_underline == use_underline) + return; + + self->use_underline = use_underline; + hdy_preferences_row_set_use_underline (HDY_PREFERENCES_ROW (self), self->use_underline); + gtk_label_set_use_underline (self->title, self->use_underline); + gtk_label_set_use_underline (self->subtitle, self->use_underline); + gtk_label_set_mnemonic_widget (self->title, GTK_WIDGET (self)); + gtk_label_set_mnemonic_widget (self->subtitle, GTK_WIDGET (self)); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]); +} + +gint +cc_multitasking_row_get_title_lines (CcMultitaskingRow *self) +{ + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0); + + return self->title_lines; +} + +void +cc_multitasking_row_set_title_lines (CcMultitaskingRow *self, + gint title_lines) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + g_return_if_fail (title_lines >= 0); + + if (self->title_lines == title_lines) + return; + + self->title_lines = title_lines; + + gtk_label_set_lines (self->title, title_lines); + gtk_label_set_ellipsize (self->title, title_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE_LINES]); +} + +gint +cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self) +{ + g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0); + + return self->subtitle_lines; +} + +void +cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self, + gint subtitle_lines) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + g_return_if_fail (subtitle_lines >= 0); + + if (self->subtitle_lines == subtitle_lines) + return; + + self->subtitle_lines = subtitle_lines; + + gtk_label_set_lines (self->subtitle, subtitle_lines); + gtk_label_set_ellipsize (self->subtitle, subtitle_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END); + + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE_LINES]); +} + +void +cc_multitasking_row_add_prefix (CcMultitaskingRow *self, + GtkWidget *widget) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + g_return_if_fail (GTK_IS_WIDGET (self)); + + gtk_box_pack_start (self->prefixes, widget, FALSE, TRUE, 0); + gtk_widget_show (GTK_WIDGET (self->prefixes)); +} + +void +cc_multitasking_row_add_artwork (CcMultitaskingRow *self, + GtkWidget *widget) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + g_return_if_fail (GTK_IS_WIDGET (self)); + + /* HACK: the artwork box pushes the title too much to the top, so we + * need to compensate this here. + */ + gtk_widget_set_margin_top (GTK_WIDGET (self->header), 12); + + gtk_box_pack_start (self->artwork_box, widget, FALSE, TRUE, 0); + gtk_widget_show (GTK_WIDGET (self->artwork_box)); +} + +void +cc_multitasking_row_activate (CcMultitaskingRow *self) +{ + g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); + + if (self->activatable_widget) + gtk_widget_mnemonic_activate (self->activatable_widget, FALSE); + + g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0); +} diff --git a/panels/multitasking/cc-multitasking-row.h b/panels/multitasking/cc-multitasking-row.h new file mode 100644 index 000000000..c35d9d688 --- /dev/null +++ b/panels/multitasking/cc-multitasking-row.h @@ -0,0 +1,63 @@ +/* cc-multitasking-row.h + * + * Copyright 2018 Purism SPC + * 2021 Georges Basile Stavracas Neto <georges.stavracas@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include <handy.h> + +G_BEGIN_DECLS + +#define CC_TYPE_MULTITASKING_ROW (cc_multitasking_row_get_type()) +G_DECLARE_FINAL_TYPE (CcMultitaskingRow, cc_multitasking_row, CC, MULTITASKING_ROW, HdyPreferencesRow) + +const gchar *cc_multitasking_row_get_subtitle (CcMultitaskingRow *self); +void cc_multitasking_row_set_subtitle (CcMultitaskingRow *self, + const gchar *subtitle); + +const gchar *cc_multitasking_row_get_icon_name (CcMultitaskingRow *self); +void cc_multitasking_row_set_icon_name (CcMultitaskingRow *self, + const gchar *icon_name); + +GtkWidget *cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self); +void cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self, + GtkWidget *widget); + +gboolean cc_multitasking_row_get_use_underline (CcMultitaskingRow *self); +void cc_multitasking_row_set_use_underline (CcMultitaskingRow *self, + gboolean use_underline); + +gint cc_multitasking_row_get_title_lines (CcMultitaskingRow *self); +void cc_multitasking_row_set_title_lines (CcMultitaskingRow *self, + gint title_lines); + +gint cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self); +void cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self, + gint subtitle_lines); + +void cc_multitasking_row_add_prefix (CcMultitaskingRow *self, + GtkWidget *widget); + +void cc_multitasking_row_add_artwork (CcMultitaskingRow *self, + GtkWidget *widget); + +void cc_multitasking_row_activate (CcMultitaskingRow *self); + +G_END_DECLS diff --git a/panels/multitasking/cc-multitasking-row.ui b/panels/multitasking/cc-multitasking-row.ui new file mode 100644 index 000000000..a3377229f --- /dev/null +++ b/panels/multitasking/cc-multitasking-row.ui @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <template class="CcMultitaskingRow" parent="HdyPreferencesRow"> + <property name="activatable">False</property> + <accessibility> + <relation target="title" type="labelled-by"/> + </accessibility> + <child> + <object class="GtkBox" id="header"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="valign">center</property> + <property name="visible">True</property> + <style> + <class name="header"/> + </style> + + <child> + <object class="GtkBox"> + <property name="can_focus">False</property> + <property name="spacing">12</property> + <property name="valign">center</property> + <property name="vexpand">True</property> + <property name="visible">True</property> + + <child> + <object class="GtkBox" id="prefixes"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="spacing">12</property> + <property name="visible">False</property> + </object> + </child> + <child> + <object class="GtkImage" id="image"> + <property name="no_show_all">True</property> + <property name="pixel_size">32</property> + <property name="valign">center</property> + </object> + </child> + <child> + <object class="GtkBox" id="title_box"> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="no_show_all">True</property> + <property name="orientation">vertical</property> + <property name="valign">center</property> + <property name="visible">True</property> + <style> + <class name="title"/> + </style> + <child> + <object class="GtkLabel" id="title"> + <property name="can_focus">False</property> + <property name="ellipsize">end</property> + <property name="halign">start</property> + <property name="hexpand">True</property> + <property name="label" bind-source="CcMultitaskingRow" bind-property="title" bind-flags="sync-create"/> + <property name="lines">1</property> + <property name="visible">True</property> + <property name="wrap">True</property> + <property name="wrap-mode">word-char</property> + <property name="xalign">0</property> + <style> + <class name="title"/> + </style> + <accessibility> + <relation target="CcMultitaskingRow" type="label-for"/> + </accessibility> + </object> + </child> + <child> + <object class="GtkLabel" id="subtitle"> + <property name="can_focus">False</property> + <property name="ellipsize">end</property> + <property name="halign">start</property> + <property name="hexpand">True</property> + <property name="lines">1</property> + <property name="wrap">True</property> + <property name="wrap-mode">word-char</property> + <property name="xalign">0</property> + <style> + <class name="subtitle"/> + </style> + </object> + </child> + </object> + </child> + <child> + <object class="GtkBox" id="suffixes"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="spacing">12</property> + <property name="visible">False</property> + </object> + <packing> + <property name="pack-type">end</property> + </packing> + </child> + + </object> + </child> + + <child> + <object class="GtkBox" id="artwork_box"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="visible">False</property> + <property name="hexpand">True</property> + <property name="margin-top">12</property> + <property name="margin-bottom">12</property> + <style> + <class name="frame" /> + <class name="background" /> + </style> + </object> + </child> + + </object> + </child> + </template> +</interface> diff --git a/panels/multitasking/gnome-multitasking-panel.desktop.in.in b/panels/multitasking/gnome-multitasking-panel.desktop.in.in new file mode 100644 index 000000000..675879bc2 --- /dev/null +++ b/panels/multitasking/gnome-multitasking-panel.desktop.in.in @@ -0,0 +1,14 @@ +[Desktop Entry] +Name=Multitasking +Comment=Manage preferences for productivity and multitasking +Exec=gnome-control-center multitasking +# Translators: Do NOT translate or transliterate this text (this is an icon file name)! +Icon=org.gnome.Settings-multitasking-symbolic +Terminal=false +Type=Application +NoDisplay=true +StartupNotify=true +Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings; +OnlyShowIn=GNOME; +# Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +Keywords=Multitasking;Multitask;Productivity;Customize;Desktop; diff --git a/panels/multitasking/icons/meson.build b/panels/multitasking/icons/meson.build new file mode 100644 index 000000000..b274dd102 --- /dev/null +++ b/panels/multitasking/icons/meson.build @@ -0,0 +1,4 @@ +install_data( + 'scalable/org.gnome.Settings-multitasking-symbolic.svg', + install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps') +) diff --git a/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg new file mode 100644 index 000000000..0e09bbcd5 --- /dev/null +++ b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <filter id="a" height="100%" width="100%" x="0%" y="0%"> + <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/> + </filter> + <mask id="b"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/> + </g> + </mask> + <clipPath id="c"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="d"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="e"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="f"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="g"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="h"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="i"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="j"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="k"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="l"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="m"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="n"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/> + </g> + </mask> + <clipPath id="o"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="p"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/> + </g> + </mask> + <clipPath id="q"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <mask id="r"> + <g filter="url(#a)"> + <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/> + </g> + </mask> + <clipPath id="s"> + <path d="m 0 0 h 1024 v 800 h -1024 z"/> + </clipPath> + <path d="m 3 1 v 2 h -3 v 10 h 3 v 2 h 10 v -2 h 3 v -10 h -3 v -2 z m 2 2 h 6 v 10 h -6 z m -3 2 h 1 v 6 h -1 z m 11 0 h 1 v 6 h -1 z m 0 0" fill="#2e3436"/> + <g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 562.460938 212.058594 h 10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="#2e3436"/> + </g> + <g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 16 632 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 17 631 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 18 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 16 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 17 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#o)" mask="url(#n)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 19 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/> + </g> + <g clip-path="url(#q)" mask="url(#p)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 136 660 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/> + </g> + <g clip-path="url(#s)" mask="url(#r)" transform="matrix(1 0 0 1 -700 -664)"> + <path d="m 219 642 h 3 v 12 h -3 z m 0 0" fill="#2e3436"/> + </g> +</svg> diff --git a/panels/multitasking/meson.build b/panels/multitasking/meson.build new file mode 100644 index 000000000..772b63813 --- /dev/null +++ b/panels/multitasking/meson.build @@ -0,0 +1,49 @@ +panels_list += cappletname +desktop = 'gnome-@0@-panel.desktop'.format(cappletname) + +desktop_in = configure_file( + input: desktop + '.in.in', + output: desktop + '.in', + configuration: desktop_conf +) + +i18n.merge_file( + desktop, + type: 'desktop', + input: desktop_in, + output: desktop, + po_dir: po_dir, + install: true, + install_dir: control_center_desktopdir +) + +sources = files( + 'cc-multitasking-panel.c', + 'cc-multitasking-row.c', +) + +resource_data = files( + 'cc-multitasking-panel.ui', +) + +sources += gnome.compile_resources( + 'cc-' + cappletname + '-resources', + cappletname + '.gresource.xml', + c_name: 'cc_' + cappletname, + dependencies: resource_data, + export: true +) + +cflags += [ + '-DDATADIR="@0@"'.format(control_center_datadir) +] + +panels_libs += static_library( + cappletname, + sources: sources, + include_directories: [ top_inc, common_inc ], + dependencies: common_deps, + c_args: cflags +) + +subdir('icons') diff --git a/panels/multitasking/multitasking.gresource.xml b/panels/multitasking/multitasking.gresource.xml new file mode 100644 index 000000000..db8365f68 --- /dev/null +++ b/panels/multitasking/multitasking.gresource.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/org/gnome/control-center/multitasking"> + <file preprocess="xml-stripblanks">cc-multitasking-panel.ui</file> + <file preprocess="xml-stripblanks">cc-multitasking-row.ui</file> + + <!-- Assets --> + <file>assets/active-screen-edges.svg</file> + <file>assets/hot-corner.svg</file> + <file>assets/workspaces-primary-display.svg</file> + <file>assets/workspaces-span-displays.svg</file> + </gresource> +</gresources> diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c index a8eb279d7..fe536dbd9 100644 --- a/shell/cc-panel-list.c +++ b/shell/cc-panel-list.c @@ -386,6 +386,7 @@ static const gchar * const panel_order[] = { "background", "notifications", "search", + "multitasking", "applications", "privacy", "online-accounts", diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c index f20384394..fcbf398ca 100644 --- a/shell/cc-panel-loader.c +++ b/shell/cc-panel-loader.c @@ -43,6 +43,7 @@ extern GType cc_display_panel_get_type (void); extern GType cc_info_overview_panel_get_type (void); extern GType cc_keyboard_panel_get_type (void); extern GType cc_mouse_panel_get_type (void); +extern GType cc_multitasking_panel_get_type (void); #ifdef BUILD_NETWORK extern GType cc_network_panel_get_type (void); extern GType cc_wifi_panel_get_type (void); @@ -107,6 +108,7 @@ static CcPanelLoaderVtable default_panels[] = PANEL_TYPE("lock", cc_lock_panel_get_type, NULL), PANEL_TYPE("microphone", cc_microphone_panel_get_type, NULL), PANEL_TYPE("mouse", cc_mouse_panel_get_type, NULL), + PANEL_TYPE("multitasking", cc_multitasking_panel_get_type, NULL), #ifdef BUILD_NETWORK PANEL_TYPE("network", cc_network_panel_get_type, NULL), PANEL_TYPE("wifi", cc_wifi_panel_get_type, cc_wifi_panel_static_init_func), diff --git a/shell/gnome-control-center.gresource.xml b/shell/gnome-control-center.gresource.xml index 9be077ec9..5550440e1 100644 --- a/shell/gnome-control-center.gresource.xml +++ b/shell/gnome-control-center.gresource.xml @@ -6,4 +6,10 @@ <file preprocess="xml-stripblanks">help-overlay.ui</file> <file>style.css</file> </gresource> + + <!-- Panel icons --> + <gresource prefix="/org/gnome/ControlCenter"> + <file preprocess="xml-stripblanks">icons/multitasking-symbolic.svg</file> + <file>style.css</file> + </gresource> </gresources> diff --git a/shell/icons/multitasking-symbolic.svg b/shell/icons/multitasking-symbolic.svg new file mode 100644 index 000000000..7959ddbfc --- /dev/null +++ b/shell/icons/multitasking-symbolic.svg @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:osb="http://www.openswatchbook.org/uri/2009/osb" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + width="16.00004" + viewBox="0 0 16.00004 16" + version="1.1" + id="svg7384" + height="16"> + <metadata + id="metadata90"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title>Gnome Symbolic Icon Theme</dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <title + id="title9167">Gnome Symbolic Icon Theme</title> + <defs + id="defs7386"> + <linearGradient + osb:paint="solid" + id="linearGradient7212"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop7214" /> + </linearGradient> + </defs> + <g + transform="translate(-699.99996,-400.00765)" + style="display:inline" + id="layer1"> + <path + d="m 703,401 v 1 1 h -3 v 1 9 h 3 v 2 h 10 v -2 h 3 v -10 h -3 v -2 z m 2,2 h 6 v 1 9 h -6 z m -3,2 h 1 v 6 h -1 z m 11,0 h 1 v 6 h -1 z" + id="rect8510" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2e3436;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + </g> + <g + transform="translate(-699.99996,-600.00765)" + id="layer21" /> + <g + transform="translate(-941.00016,-33.00765)" + style="display:inline" + id="layer9" /> + <g + transform="translate(-941.00016,-33.00765)" + style="display:inline" + id="g7628" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer19" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer13" /> + <g + transform="translate(-699.99996,-400.00765)" + style="display:inline" + id="layer11" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer14" /> + <g + transform="translate(-699.99996,-400.00765)" + style="display:inline" + id="g6387" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer18" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer17" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer16" /> + <g + transform="translate(-699.99996,-400.00765)" + style="display:inline" + id="layer10" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer15" /> + <g + transform="translate(-699.99996,-400.00765)" + id="layer12" /> + <g + transform="translate(-699.99996,-600.00765)" + id="layer20" /> +</svg> |