diff --git a/.github/workflows/coding-style-pr.yml b/.github/workflows/coding-style-pr.yml index 5b9125f51b..37876ce0b1 100644 --- a/.github/workflows/coding-style-pr.yml +++ b/.github/workflows/coding-style-pr.yml @@ -8,6 +8,6 @@ jobs: steps: - uses: actions/checkout@v4 - run: git fetch --depth=1 origin ${{ github.event.pull_request.base.sha }} - - uses: yshui/git-clang-format-lint@v1.15 + - uses: yshui/git-clang-format-lint@v1.16 with: base: ${{ github.event.pull_request.base.sha }} diff --git a/.github/workflows/coding-style.yml b/.github/workflows/coding-style.yml index 96cc6965f3..c09ef5671b 100644 --- a/.github/workflows/coding-style.yml +++ b/.github/workflows/coding-style.yml @@ -9,6 +9,6 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 2 - - uses: yshui/git-clang-format-lint@v1.15 + - uses: yshui/git-clang-format-lint@v1.16 with: base: ${{ github.event.ref }}~1 diff --git a/.github/workflows/page.yml b/.github/workflows/page.yml new file mode 100644 index 0000000000..c55a5de940 --- /dev/null +++ b/.github/workflows/page.yml @@ -0,0 +1,53 @@ + +name: GitHub Pages + +on: + push: + pull_request: + + +permissions: + contents: read + pages: write + id-token: write +concurrency: + group: "pages" + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: false + fetch-depth: 0 + + - name: Setup Pages + id: pages + uses: actions/configure-pages@v5 + - name: Install asciidoctor + run: sudo apt install -y asciidoctor + + - name: Build + run: | + asciidoctor -a doctype=article -a stylesheet=../assets/next.css -b html man/picom.1.adoc -D _site + asciidoctor -a doctype=article -a stylesheet=../assets/next.css -b html man/picom-inspect.1.adoc -D _site + asciidoctor -a doctype=article -a stylesheet=../assets/next.css -b html man/picom-trans.1.adoc -D _site + cp _site/picom.1.html _site/index.html + + - name: Upload + uses: actions/upload-pages-artifact@v3 + + deploy: + if: github.ref == 'refs/heads/next' + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + diff --git a/CHANGELOG.md b/CHANGELOG.md index 7038b3e51b..6638910f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ * `libconfig` is now a mandatory dependency, with a minimal supported version of 1.7. * `xcb-dpms` is not needed anymore. * `libXext` is not needed anymore. +* man pages are now built with asciidoctor, instead of asciidoc. ## Behind the scene changes diff --git a/assets/next.css b/assets/next.css new file mode 100644 index 0000000000..a8ffc58777 --- /dev/null +++ b/assets/next.css @@ -0,0 +1,1234 @@ +html { + line-height: 1.15; + -webkit-text-size-adjust: 100%; } + +body { + margin: 0; } + +main { + display: block; } + +h1 { + font-size: 2em; + margin: 0.67em 0; } + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; } + +pre { + font-family: monospace, monospace; + font-size: 1em; } + +a { + background-color: transparent; } + +abbr[title] { + border-bottom: none; + text-decoration: underline; + text-decoration: underline dotted; } + +b, +strong { + font-weight: bolder; } + +code, +kbd, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +small { + font-size: 80%; } + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sub { + bottom: -0.25em; } + +sup { + top: -0.5em; } + +img { + border-style: none; } + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + font-size: 100%; + line-height: 1.15; + margin: 0; } + +button, +input { + overflow: visible; } + +button, +select { + text-transform: none; } + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; } + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; } + +fieldset { + padding: 0.35em 0.75em 0.625em; } + +legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; } + +progress { + vertical-align: baseline; } + +textarea { + overflow: auto; } + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + padding: 0; } + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; } + +details { + display: block; } + +summary { + display: list-item; } + +template { + display: none; } + +[hidden] { + display: none; } + +:root { + --font-family-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, + "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Noto Color Emoji"; + --font-family-serif: Georgia, Cambria, "Times New Roman", Times, serif; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", + monospace; + --font-body: var(--font-family-sans); + --font-heading: var(--font-family-sans); + --font-subheading: var(--font-family-serif); + --font-heading-weight: 300; + --background: #fff; + --background-panel: #fafafa; + --text: rgba(0, 0, 0, 0.87); + --text-secondary: rgba(0, 0, 0, 0.54); + --text-disabled: rgba(0, 0, 0, 0.38); + --link: #3f51b5; + --link-hover: #3f51b5; + --border: rgba(0, 0, 0, 0.06); + --divider: rgba(0, 0, 0, 0.12); + --h1-font-size: 2.5em; + --h2-font-size: 2em; + --h3-font-size: 1.75em; + --h4-font-size: 1.5em; + --h5-font-size: 1.25em; + --h6-font-size: 1em; + --code-text: var(--text); + --code-background: rgba(255, 230, 102, 0.2); + --tip: rgb(76, 174, 79); + --tip-border: rgba(76, 174, 79, 0.4); + --tip-background: rgba(76, 174, 79, 0.1); + --note: rgb(32, 148, 243); + --note-border: rgba(32, 148, 243, 0.4); + --note-background: rgba(32, 148, 243, 0.1); + --caution: rgb(211, 49, 49); + --caution-border: rgba(211, 49, 49, 0.4); + --caution-background: rgba(211, 49, 49, 0.1); + --important: rgb(244, 64, 52); + --important-border: rgba(244, 64, 52, 0.4); + --important-background: rgba(244, 64, 52, 0.1); + --warning: rgb(255, 153, 0); + --warning-border: rgba(255, 153, 0, 0.4); + --warning-background: rgba(255, 153, 0, 0.1); + --hljs-color: #383a42; + --hljs-background: #fafafa; + --hljs-comment: #a0a1a7; + --hljs-keyword: #a626a4; + --hljs-section: #e45649; + --hljs-literal: #0184bb; + --hljs-string: #50a14f; + --hljs-built-in: #c18401; + --hljs-variable: #986801; + --hljs-symbol: #4078f2; } + +html[data-theme="dark"] { + --link: #f48fb1; + --link-hover: #f48fb1; + --text: #fff; + --text-secondary: rgba(255, 255, 255, 0.7); + --background: #303030; + --background-panel: rgba(0, 0, 0, 0.2); + --border: rgba(255, 255, 255, 0.12); + --divider: rgba(255, 255, 255, 0.12); + --code-text: var(--text); + --code-background: rgba(255, 229, 100, 0.2); + --tip-background: rgba(76, 174, 79, 0.05); + --note-background: rgba(32, 148, 243, 0.05); + --caution-background: rgba(211, 49, 49, 0.05); + --important-background: rgba(244, 64, 52, 0.05); + --warning-background: rgba(255, 153, 0, 0.05); + --hljs-color: #abb2bf; + --hljs-background: #282c34; + --hljs-background: var(--background-panel); + --hljs-comment: #5c6370; + --hljs-keyword: #c678dd; + --hljs-section: #e06c75; + --hljs-literal: #56b6c2; + --hljs-string: #98c379; + --hljs-built-in: #e6c07b; + --hljs-variable: #d19a66; + --hljs-symbol: #61aeee; } + +body { + font-family: var(--font-body); + font-size: 1rem; + line-height: 1.5; + background-color: var(--background); + color: var(--text); } + +@media screen and (min-width: 768px) { + body.toc2 { + padding-left: 15em; + padding-right: 0; } + + #toc.toc2 { + position: fixed; + top: 0; + left: 0; + width: 15em; + height: 100%; + overflow: auto; + border-top: none !important; + border-right: 1px solid var(--divider); + background-color: var(--background-panel); + padding: 1em 1em 0 1em; + box-sizing: border-box; } + + body.toc2.toc-right { + padding-left: 0; + padding-right: 15em; } + body.toc2.toc-right #toc.toc2 { + border-right: none !important; + border-left: 1px solid var(--divider); + left: auto; + right: 0; } } +@media screen and (min-width: 1280px) { + body.toc2 { + padding-left: 20em; + padding-right: 0; } + + #toc.toc2 { + width: 20em; } + + body.toc2.toc-right { + padding-left: 0; + padding-right: 20em; } } +h1, +h2, +h3, +h4, +#toctitle, +h5, +h6 { + font-family: var(--font-heading); + font-weight: var(--font-heading-weight); } + +h1 { + font-size: var(--h1-font-size); } + +h2 { + font-size: var(--h2-font-size); } + +h3 { + font-size: var(--h3-font-size); } + +h4, #toctitle { + font-size: var(--h4-font-size); } + +h5 { + font-size: var(--h5-font-size); } + +h6 { + font-size: var(--h6-font-size); } + +hr { + border: 0; + border-bottom: 1px solid var(--divider); + margin: 1em 0; } + +pre, +code { + font-family: var(--font-family-monospace); } + +img, +object, +svg { + display: inline-block; + vertical-align: middle; } + +em em { + font-style: normal; } + +strong strong { + font-weight: normal; } + +a { + color: var(--link); + text-decoration: none; } + a:hover { + color: var(--link-hover); + text-decoration: underline; } + +#header, +#content, +#footnotes { + max-width: 100%; + margin-left: auto; + margin-right: auto; } + +@media screen and (min-width: 768px) { + #header, + #content, + #footnotes { + max-width: 60em; } } +#header { + border-bottom: 1px solid var(--border); } + #header > h1:first-child { + color: var(--text); + margin-bottom: 0; } + #header #toc { + border-top: 1px solid var(--border); + padding-top: 1em; } + #header #toc ul { + list-style: none; + padding-left: 1.25em; } + #header #toc > ul { + margin-left: 0; + padding-left: 0; } + #header #toc a { + text-decoration: none; } + #header #toc a:active { + text-decoration: underline; } + #header .details { + display: flex; + flex-flow: row wrap; + padding-bottom: 0.25em; + color: var(--text-secondary); } + #header .details span.email a { + color: var(--text); } + #header .details br { + display: none; } + #header .details br + span:before { + content: "\00a0\2013\00a0"; } + #header .details br + span.author:before { + content: "\00a0\22c5\00a0"; + color: var(--text-secondary); } + #header .details br + span#revremark:before { + content: "\00a0|\00a0"; } + #header #revnumber { + text-transform: capitalize; } + #header #revnumber:after { + content: "\00a0"; } + +#content #toc { + background: var(--background-panel); + border: 1px solid var(--border); + border-radius: 4px; + margin-bottom: 1.25em; + padding: 1.25em; } + #content #toc > :first-child { + margin-top: 0; } + #content #toc > :last-child { + margin-bottom: 0; } + +#footnotes hr { + width: 7em; + margin-bottom: 0.5em; } +#footnotes .footnote { + font-size: 0.9em; } + +#footer { + max-width: 100%; + background: rgba(0, 0, 0, 0.8); + padding: 1em; + margin-top: 1em; } + +#footer-text { + color: rgba(255, 255, 255, 0.8); } + +.sect1 > h2 { + border-bottom: 1px solid var(--divider); + padding-bottom: 0.3rem; } + +h1 > a.anchor, +h2 > a.anchor, +h3 > a.anchor, +h5 > a.anchor, +h6 > a.anchor, +#toctitle > a.anchor, +.content > .title > a.anchor { + position: absolute; + display: inline-block; + width: 2ex; + margin-left: -2ex; + text-decoration: none !important; + visibility: hidden; + text-align: center; + font-weight: normal; + font-size: 0.85em; + margin-top: 0.15em; } + h1 > a.anchor:before, + h2 > a.anchor:before, + h3 > a.anchor:before, + h5 > a.anchor:before, + h6 > a.anchor:before, + #toctitle > a.anchor:before, + .content > .title > a.anchor:before { + content: "#"; + display: block; } +h1:hover > a.anchor, +h1 > a.anchor:hover, +h2:hover > a.anchor, +h2 > a.anchor:hover, +h3:hover > a.anchor, +h3 > a.anchor:hover, +h5:hover > a.anchor, +h5 > a.anchor:hover, +h6:hover > a.anchor, +h6 > a.anchor:hover, +#toctitle:hover > a.anchor, +#toctitle > a.anchor:hover, +.content > .title:hover > a.anchor, +.content > .title > a.anchor:hover { + visibility: visible; } +h1 > a.link, +h2 > a.link, +h3 > a.link, +h5 > a.link, +h6 > a.link, +#toctitle > a.link, +.content > .title > a.link { + text-decoration: none; } + +:not(pre) > code { + font-size: 0.93em; + font-style: normal !important; + letter-spacing: 0; + padding: 0.2em 0.5ex 0.1em 0.5ex; + word-spacing: -0.15em; + border-radius: 4px; + line-height: 1.4; + text-rendering: optimizeSpeed; + word-wrap: break-word; + background-color: var(--code-background); + color: var(--code-text); + background-color: var(--code-background); + color: var(--code-text); } + :not(pre) > code.nobreak { + word-wrap: normal; } + :not(pre) > code.nowrap { + white-space: nowrap; } + +pre { + line-height: 1.4; } + pre > code { + display: block; } + pre .nowrap, + pre .nowrap pre { + white-space: pre; + word-wrap: normal; } + +table { + background: var(--background); + margin-bottom: 1.25em; + border: 1px solid var(--border); + border-spacing: 0; } + table thead, + table tfoot { + background: var(--background); + font-weight: var(--font-weight-medium, 500); } + table thead tr th, + table thead tr td, + table tfoot tr th, + table tfoot tr td { + padding: 0.5em 0.625em 0.625em; + font-size: inherit; + color: var(--text-secondary); + text-align: left; } + table tr th, + table tr td { + padding: 0.5625em 0.625em; + font-size: inherit; + color: var(--text); } + table tr.even, table tr.alt { + background: rgba(0, 0, 0, 0.04); } + table thead tr th, + table tfoot tr th, + table tbody tr td, + table tr td, + table tfoot tr td { + display: table-cell; + line-height: 1.6; } + +table.tableblock { + max-width: 100%; + border-collapse: separate; } + +p.tableblock { + margin-top: 0; } + +p.tableblock:last-child { + margin-bottom: 0; } + +td.tableblock > .content { + margin-bottom: 1.25em; } + td.tableblock > .content > :last-child { + margin-bottom: -1.25em; } + +table.tableblock, +th.tableblock, +td.tableblock { + border: 0 solid var(--border); } + +table.grid-all > thead > tr > .tableblock, +table.grid-all > tbody > tr > .tableblock { + border-width: 0 1px 1px 0; } + +table.grid-all > tfoot > tr > .tableblock { + border-width: 1px 1px 0 0; } + +table.grid-cols > * > tr > .tableblock { + border-width: 0 1px 0 0; } + +table.grid-rows > thead > tr > .tableblock, +table.grid-rows > tbody > tr > .tableblock { + border-width: 0 0 1px 0; } + +table.grid-rows > tfoot > tr > .tableblock { + border-width: 1px 0 0 0; } + +table.grid-all > * > tr > .tableblock:last-child, +table.grid-cols > * > tr > .tableblock:last-child { + border-right-width: 0; } + +table.grid-all > tbody > tr:last-child > .tableblock, +table.grid-all > thead:last-child > tr > .tableblock, +table.grid-rows > tbody > tr:last-child > .tableblock, +table.grid-rows > thead:last-child > tr > .tableblock { + border-bottom-width: 0; } + +table.frame-all { + border-width: 1px; } + +table.frame-sides { + border-width: 0 1px; } + +table.frame-topbot, +table.frame-ends { + border-width: 1px 0; } + +table.stripes-all tr, +table.stripes-odd tr:nth-of-type(odd), +table.stripes-even tr:nth-of-type(even), +table.stripes-hover tr:hover { + background: rgba(0, 0, 0, 0.04); } + +th.halign-left, +td.halign-left { + text-align: left; } + +th.halign-right, +td.halign-right { + text-align: right; } + +th.halign-center, +td.halign-center { + text-align: center; } + +th.valign-top, +td.valign-top { + vertical-align: top; } + +th.valign-bottom, +td.valign-bottom { + vertical-align: bottom; } + +th.valign-middle, +td.valign-middle { + vertical-align: middle; } + +table thead th, +table tfoot th { + font-weight: var(--font-weight-medium); } + +tbody tr th { + display: table-cell; + line-height: 1.6; + background: var(--background); } + +tbody tr th, +tbody tr th p, +tfoot tr th, +tfoot tr th p { + color: var(--text-secondary); + font-weight: var(--font-weight-medium); } + +p.tableblock > code:only-child { + background: none; + padding: 0; } + +p.tableblock { + font-size: 1em; } + +details, +.audioblock, +.imageblock, +.literalblock, +.listingblock, +.stemblock, +.videoblock { + margin-bottom: 1em; } + +.admonitionblock td.content > .title, +.audioblock > .title, +.exampleblock > .title, +.imageblock > .title, +.listingblock > .title, +.literalblock > .title, +.stemblock > .title, +.openblock > .title, +.paragraph > .title, +.quoteblock > .title, +table.tableblock > .title, +.verseblock > .title, +.videoblock > .title, +.dlist > .title, +.olist > .title, +.ulist > .title, +.qlist > .title, +.hdlist > .title { + color: var(--text-secondary); + text-align: left; + font-family: var(--font-subheading); + font-weight: var(--font-heading-weight); + font-size: 1rem; + font-style: italic; } + +.paragraph.lead > p, +#preamble > .sectionbody > [class="paragraph"]:first-of-type p { + font-size: 1.2rem; + line-height: 1.6; + color: var(--text); } + +.exampleblock > .content { + background: var(--background-panel); + border: 1px solid var(--border); + border-radius: 4px; + margin-bottom: 1.25em; + padding: 1.25em; } + .exampleblock > .content > :first-child { + margin-top: 0; } + .exampleblock > .content > :last-child { + margin-bottom: 0; } + +.sidebarblock { + background: var(--background-panel); + border: 1px solid var(--border); + border-radius: 4px; + margin-bottom: 1.25em; + padding: 1.25em; } + .sidebarblock > :first-child { + margin-top: 0; } + .sidebarblock > :last-child { + margin-bottom: 0; } + .sidebarblock > .content > .title { + font-size: 1rem; + font-weight: bold; + text-transform: uppercase; + text-align: left; + color: var(--text-secondary); + margin-top: 0; + margin-bottom: 1rem; } + +:not(.openblock) > .content .paragraph:first-child > p:first-child { + margin-top: 0; } +:not(.openblock) > .content .paragraph:last-child > p:last-child { + margin-bottom: 0; } + +.literalblock pre, +.listingblock > .content > pre { + border: 1px solid var(--border); + border-radius: 4px; + word-wrap: break-word; + overflow-x: auto; + padding: 1rem; + font-size: 0.9rem; } + +.literalblock pre, +.listingblock > .content > pre:not(.highlight), +.listingblock > .content > pre[class="highlight"], +.listingblock > .content > pre[class^="highlight "] { + background: var(--background-panel); } + +.listingblock > .content { + position: relative; } +.listingblock code[data-lang]:before { + display: none; + content: attr(data-lang); + position: absolute; + font-size: 0.8rem; + top: 0.425rem; + right: 0.5rem; + line-height: 1; + text-transform: uppercase; + color: inherit; + opacity: 0.5; } +.listingblock:hover code[data-lang]:before { + display: block; } + +.quoteblock, +.verseblock { + margin: 1.25em 0; + padding-left: 1.25em; + border-left: 6px solid var(--divider); } + .quoteblock .attribution, + .verseblock .attribution { + font-size: 0.9rem; + line-height: 1.45; + font-style: italic; } + .quoteblock .attribution br, + .verseblock .attribution br { + display: none; } + .quoteblock .attribution cite, + .verseblock .attribution cite { + display: block; + letter-spacing: -0.025em; + color: var(--text-secondary); } + +.quoteblock blockquote { + margin: 1em 0; + padding: 0; + border: none; } +.quoteblock blockquote, +.quoteblock p { + font-style: italic; } + +.verseblock pre { + font-family: var(--font-body); + font-style: italic; + font-weight: 300; } + .verseblock pre strong { + font-weight: 400; } + +.admonitionblock { + border-left: 6px solid var(--divider); + border-radius: 4px; + background-color: var(--background-panel); } + .admonitionblock table { + border: 0; + border-collapse: collapse; + background: transparent; } + .admonitionblock td.icon { + position: absolute; + font-weight: bold; + text-transform: uppercase; + padding: 1rem; } + .admonitionblock td.icon i::after { + content: attr(title); + font-family: var(--font-body); + font-weight: bold; + font-size: 1rem; } + .admonitionblock td.content { + padding: 3rem 1rem 1rem; } + .admonitionblock.note { + border-color: var(--note-border); + background-color: var(--note-background); } + .admonitionblock.note td.icon { + color: var(--note); } + .admonitionblock.tip { + border-color: var(--tip-border); + background-color: var(--tip-background); } + .admonitionblock.tip td.icon { + color: var(--tip); } + .admonitionblock.warning { + border-color: var(--warning-border); + background-color: var(--warning-background); } + .admonitionblock.warning td.icon { + color: var(--warning); } + .admonitionblock.caution { + border-color: var(--caution-border); + background-color: var(--caution-background); } + .admonitionblock.caution td.icon { + color: var(--caution); } + .admonitionblock.important { + border-color: var(--important-border); + background-color: var(--important-background); } + .admonitionblock.important td.icon { + color: var(--important); } + +ol, +ul { + padding-left: 1.25em; } + +dl dt { + font-weight: bold; } + +dl dd { + margin-left: 1.25em; } + dl dd > :first-child { + margin-top: 0.5em; } + +ul.checklist { + list-style-type: none; + padding-left: 0; + margin-left: 0.625em; } + +ul.checklist li > p:first-child > .fa-square-o:first-child, +ul.checklist li > p:first-child > .fa-check-square-o:first-child { + width: 1.25em; + font-size: 0.8em; + position: relative; + bottom: 0.125em; } + +ul.checklist li > p:first-child > input[type="checkbox"]:first-child { + margin-right: 0.25em; } + +.hdlist > table, +.colist > table { + border: 0; + background: none; } + .hdlist > table > tbody > tr, + .colist > table > tbody > tr { + background: none; } + +td.hdlist1, +td.hdlist2 { + vertical-align: top; } + +td.hdlist1 { + font-weight: bold; } + +td.hdlist2 :first-child { + margin-top: 0; } +td.hdlist2 :last-child { + margin-bottom: 0; } + +.literalblock + .colist, +.listingblock + .colist { + margin-top: -0.5em; } + +.colist td:not([class]):first-child { + padding: 0.4em 0.75em 0 0.75em; + line-height: 1; + vertical-align: top; } + .colist td:not([class]):first-child img { + max-width: none; } +.colist td:not([class]):last-child { + padding: 0.25em 0; } + +.keyseq, +.menuseq, +.menuref { + color: var(--text-secondary); } + +kbd { + display: inline-block; + font-family: var(--font-family-monospace); + font-size: 0.75em; + line-height: 1.45; + margin: 0 0.15em; + padding: 0.2em 0.5em; + color: var(--text-secondary); + background-color: var(--background-panel); + border: 1px solid var(--border); + border-radius: 4px; + box-shadow: 0 1px 0 var(--border), 0 0 0 0.1em var(--background-panel) inset; + vertical-align: middle; + position: relative; + top: -0.1em; + white-space: nowrap; } + +.keyseq kbd:first-child { + margin-left: 0; } + +.keyseq kbd:last-child { + margin-right: 0; } + +.menuseq b:not(.caret), +.menuref { + font-weight: inherit; } + +.menuseq { + word-spacing: -0.02em; } + .menuseq b.caret { + font-size: 1.25em; + line-height: 0.8; } + .menuseq i.caret { + font-weight: bold; + text-align: center; + width: 0.45em; } + +b.button:before, +b.button:after { + position: relative; + top: -1px; + font-weight: normal; } + +b.button:before { + content: "["; + padding: 0 3px 0 2px; } + +b.button:after { + content: "]"; + padding: 0 2px 0 3px; } + +.left { + float: left !important; } + +.right { + float: right !important; } + +.text-left { + text-align: left !important; } + +.text-right { + text-align: right !important; } + +.text-center { + text-align: center !important; } + +.text-justify { + text-align: justify !important; } + +.hide { + display: none; } + +.center { + margin-left: auto; + margin-right: auto; } + +.stretch { + width: 100%; } + +.unbreakable { + page-break-inside: avoid; } + +.big { + font-size: larger; } + +.small { + font-size: smaller; } + +.underline { + text-decoration: underline; } + +.overline { + text-decoration: overline; } + +.line-through { + text-decoration: line-through; } + +.aqua { + color: var(--aqua, #00bfbf); } + +.aqua-background { + background-color: var(--aqua-background, #00fafa); } + +.black { + color: var(--black, black); } + +.black-background { + background-color: var(--black-background, black); } + +.blue { + color: var(--blue, #0000bf); } + +.blue-background { + background-color: var(--blue-background, #0000fa); } + +.fuchsia { + color: var(--fuchsia, #bf00bf); } + +.fuchsia-background { + background-color: var(--fuchsia-background, #fa00fa); } + +.gray { + color: var(--gray, #606060); } + +.gray-background { + background-color: var(--gray-background, #7d7d7d); } + +.green { + color: var(--green, #006000); } + +.green-background { + background-color: var(--green-background, #007d00); } + +.lime { + color: var(--lime, #00bf00); } + +.lime-background { + background-color: var(--lime-background, #00fa00); } + +.maroon { + color: var(--maroon, #600000); } + +.maroon-background { + background-color: var(--maroon-background, #7d0000); } + +.navy { + color: var(--navy, #000060); } + +.navy-background { + background-color: var(--navy-background, #00007d); } + +.olive { + color: var(--olive, #606000); } + +.olive-background { + background-color: var(--olive-background, #7d7d00); } + +.purple { + color: var(--purple, #600060); } + +.purple-background { + background-color: var(--purple-background, #7d007d); } + +.red { + color: var(--red, #bf0000); } + +.red-background { + background-color: var(--red-background, #fa0000); } + +.silver { + color: var(--silver, #909090); } + +.silver-background { + background-color: var(--silver-background, #bcbcbc); } + +.teal { + color: var(--teal, #006060); } + +.teal-background { + background-color: var(--teal-background, #007d7d); } + +.white { + color: var(--white, #bfbfbf); } + +.white-background { + background-color: var(--white-background, #fafafa); } + +.yellow { + color: var(--yellow, #bfbf00); } + +.yellow-background { + background-color: var(--yellow-background, #fafa00); } + +span.icon > .fa { + cursor: default; } + a span.icon > .fa { + cursor: inherit; } + +.conum[data-value] { + display: inline-block; + color: var(--background) !important; + background-color: var(--text); + border-radius: 50%; + text-align: center; + font-size: 0.75em; + width: 1.67em; + height: 1.67em; + line-height: 1.67em; + font-family: var(--font-body); + font-style: normal; + font-weight: 500; } + .conum[data-value] * { + color: var(--text) !important; } + .conum[data-value] + b { + display: none; } + .conum[data-value]:after { + content: attr(data-value); } + pre .conum[data-value] { + position: relative; + top: -0.125em; } + +b.conum * { + color: inherit !important; } + +.conum:not([data-value]):empty { + display: none; } + +.hljs { + display: block; + overflow-x: auto; + color: var(--hljs-color); + background: var(--hljs-background); } + +.hljs-comment, +.hljs-quote { + color: var(--hljs-comment); + font-style: italic; } + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: var(--hljs-keyword); } + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: var(--hljs-section); } + +.hljs-literal { + color: var(--hljs-literal); } + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: var(--hljs-string); } + +.hljs-built_in, +.hljs-class .hljs-title { + color: var(--hljs-built-in); } + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-type, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: var(--hljs-variable); } + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id, +.hljs-title { + color: var(--hljs-symbol); } + +.hljs-emphasis { + font-style: italic; } + +.hljs-strong { + font-weight: bold; } + +.hljs-link { + text-decoration: underline; } + +.print-only { + display: none !important; } + +@media print { + * { + box-shadow: none; + text-shadow: none !important; } + + html { + font-size: 80%; } + + a { + color: inherit !important; + text-decoration: underline !important; } + + abbr[title]:after { + content: " (" attr(title) ")"; } + + pre, + blockquote, + tr, + img, + object, + svg { + page-break-inside: avoid; } + + thead { + display: table-header-group; } + + image, + object, + embed, + svg { + max-width: 100%; } + + p, + blockquote, + dt, + td.content { + font-size: 1em; + orphans: 3; + widows: 3; } + + h2, + h3, + #toctitle, + .sidebarblock > .content > .title { + page-break-after: avoid; } + + #toc, + .sidebarblock, + .exampleblock > .content { + background: none !important; } + + .admonitionblock, + .quoteblock, + .verseblock { + page-break-inside: avoid; } + + #header, + #content, + #footnotes { + padding: 0 1.5rem; } } diff --git a/flake.nix b/flake.nix index c305f9bfa2..ff89646e6f 100644 --- a/flake.nix +++ b/flake.nix @@ -21,6 +21,10 @@ picom = super.picom.overrideAttrs (oldAttrs: rec { version = "11"; pname = "picom"; + nativeBuildInputs = (removeFromList [ self.asciidoc ] oldAttrs.nativeBuildInputs) ++ + [ + self.asciidoctor + ]; buildInputs = [ self.pcre2 @@ -61,6 +65,7 @@ nativeBuildInputs = o.nativeBuildInputs ++ (with pkgs; [ clang-tools_18 llvmPackages_18.clang-unwrapped.python + llvmPackages_18.libllvm python ]); hardeningDisable = ["fortify"]; @@ -79,7 +84,6 @@ ; packages = { default = pkgs.picom; - llvm = profilePkgs.llvm_18; }; devShells.default = mkDevShell packages.default; devShells.useClang = devShells.default.override { diff --git a/man/meson.build b/man/meson.build index c3b3eed9bd..a14e7608d8 100644 --- a/man/meson.build +++ b/man/meson.build @@ -1,13 +1,19 @@ mans = ['picom.1', 'picom-inspect.1', 'picom-trans.1'] if get_option('with_docs') - a2x = find_program('a2x') + a2x = find_program('asciidoctor') foreach m : mans - custom_target(m, output: [m], input: [m+'.asciidoc'], + custom_target(m, output: [m], input: [m+'.adoc'], command: [a2x, '-a', 'picom-version='+version, - '--format', 'manpage', '@INPUT@', '-D', + '--backend', 'manpage', '@INPUT@', '-D', meson.current_build_dir()], install: true, install_dir: join_paths(get_option('mandir'), 'man1')) + custom_target(m+'.html', output: [m+'.html'], input: [m+'.adoc'], + command: [a2x, '-a', + 'picom-version='+version, + '--backend', 'html', '@INPUT@', '-D', + meson.current_build_dir()], + install_dir: get_option('datadir') / 'doc' / 'picom') endforeach endif diff --git a/man/picom-inspect.1.asciidoc b/man/picom-inspect.1.adoc similarity index 82% rename from man/picom-inspect.1.asciidoc rename to man/picom-inspect.1.adoc index 95d031fe45..f27fa8408b 100644 --- a/man/picom-inspect.1.asciidoc +++ b/man/picom-inspect.1.adoc @@ -1,9 +1,9 @@ -picom-inspect(1) -================ += picom-inspect(1) +Yuxuan Shui :doctype: manpage -:man source: picom-inspect -:man version: {picom-version} -:man manual: User Commands +:mansource: picom-inspect +:manversion: {picom-version} +:manmanual: User Commands NAME ---- @@ -11,7 +11,7 @@ picom-inspect - easily test your picom rules SYNOPSIS -------- -*picom-inspect* ['OPTIONS'] +*picom-inspect* [_OPTIONS_] DESCRIPTION ----------- @@ -37,4 +37,4 @@ Homepage: SEE ALSO -------- -*xcompmgr*(1), link:picom.html[*picom*(1)] +*xcompmgr*(1), xref:picom.1.adoc[*picom*(1)] diff --git a/man/picom-trans.1.asciidoc b/man/picom-trans.1.adoc similarity index 81% rename from man/picom-trans.1.asciidoc rename to man/picom-trans.1.adoc index 22b1dd2bcb..a59af9d837 100644 --- a/man/picom-trans.1.asciidoc +++ b/man/picom-trans.1.adoc @@ -1,9 +1,9 @@ -picom-trans(1) -================ -:doctype: manpage -:man source: picom -:man version: {picom-version} -:man manual: User Commands += picom-trans(1) +Yuxuan Shui +:doctype: manpage +:mansource: picom +:manversion: {picom-version} +:manmanual: User Commands NAME ---- @@ -12,19 +12,19 @@ picom-trans - an opacity setter tool SYNOPSIS -------- -*picom-trans* [-w 'WINDOW_ID'] [-n 'WINDOW_NAME'] [-c] [-s] 'OPACITY' +*picom-trans* [-w _WINDOW_ID_] [-n _WINDOW_NAME_] [-c] [-s] _OPACITY_ DESCRIPTION ----------- -*picom-trans* is a bash script that sets '_NET_WM_WINDOW_OPACITY' attribute of a window using standard X11 command-line utilities, including *xprop*(1) and *xwininfo*(1). It is similar to *transset*(1) or *transset-df*(1). +*picom-trans* is a bash script that sets __NET_WM_WINDOW_OPACITY_ attribute of a window using standard X11 command-line utilities, including *xprop*(1) and *xwininfo*(1). It is similar to *transset*(1) or *transset-df*(1). OPTIONS ------- -*-w*, *--window*='WINDOW_ID':: +*-w*, *--window*=_WINDOW_ID_:: Specify the window id of the target window. -*-n*, *--name*='WINDOW_NAME':: +*-n*, *--name*=_WINDOW_NAME_:: Specify and try to match a window name. *-c*, *--current*:: @@ -33,7 +33,7 @@ Specify the currently active window as target. Only works if EWMH '_NET_ACTIVE_W *-s*, *--select*:: Select target window with mouse cursor. This is the default if no window has been specified. -*-o*, *--opacity*='OPACITY':: +*-o*, *--opacity*=_OPACITY_:: Specify the new opacity value for the window. This value can be anywhere from 1-100. If it is prefixed with a plus or minus (+/-), this will increment or decrement from the target window's current opacity instead. *-g*, *--get*:: @@ -111,4 +111,4 @@ Please submit bug reports to . SEE ALSO -------- -link:picom.1.html[*picom*(1)], *xprop*(1), *xwininfo*(1) +xref:picom.1.adoc[*picom*(1)], *xprop*(1), *xwininfo*(1) diff --git a/man/picom.1.asciidoc b/man/picom.1.adoc similarity index 84% rename from man/picom.1.asciidoc rename to man/picom.1.adoc index 2387ce222a..d9f55416d7 100644 --- a/man/picom.1.asciidoc +++ b/man/picom.1.adoc @@ -1,9 +1,12 @@ -picom(1) -======== -:doctype: manpage -:man source: picom -:man version: {picom-version} -:man manual: User Commands += picom(1) +Yuxuan Shui +:doctype: manpage +:mansource: picom +:manversion: {picom-version} +:manmanual: User Commands +:source-highlighter: highlight.js +:highlightjs-languages: glsl +:toc: right NAME ---- @@ -11,7 +14,7 @@ picom - a compositor for X11 SYNOPSIS -------- -*picom* ['OPTIONS'] +*picom* [_OPTIONS_] DESCRIPTION ----------- @@ -22,37 +25,37 @@ OPTIONS *-h*, *--help*:: Get the usage text embedded in program code, which may be more up-to-date than this man page. -*-r*, *--shadow-radius*='RADIUS':: +*-r*, *--shadow-radius*=_RADIUS_:: The blur radius for shadows, in pixels. (defaults to 12) -*-o*, *--shadow-opacity*='OPACITY':: +*-o*, *--shadow-opacity*=_OPACITY_:: The opacity of shadows. (0.0 - 1.0, defaults to 0.75) -*-l*, *--shadow-offset-x*='OFFSET':: +*-l*, *--shadow-offset-x*=_OFFSET_:: The left offset for shadows, in pixels. (defaults to -15) -*-t*, *--shadow-offset-y*='OFFSET':: +*-t*, *--shadow-offset-y*=_OFFSET_:: The top offset for shadows, in pixels. (defaults to -15) -*-I*, *--fade-in-step*='OPACITY_STEP':: +*-I*, *--fade-in-step*=_OPACITY_STEP_:: Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) -*-O*, *--fade-out-step*='OPACITY_STEP':: +*-O*, *--fade-out-step*=_OPACITY_STEP_:: Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) -*-D*, *--fade-delta*='MILLISECONDS':: +*-D*, *--fade-delta*=_MILLISECONDS_:: The time between steps in fade step, in milliseconds. (> 0, defaults to 10) *-c*, *--shadow*:: - Enabled client-side shadows on windows. Note desktop windows (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, unless explicitly requested using the wintypes option. + Enabled client-side shadows on windows. Note desktop windows (windows with __NET_WM_WINDOW_TYPE_DESKTOP_) never get shadow, unless explicitly requested using the wintypes option. *-f*, *--fading*:: Fade windows in/out when opening/closing and when opacity changes, unless *--no-fading-openclose* is used. -*-i*, *--inactive-opacity*='OPACITY':: +*-i*, *--inactive-opacity*=_OPACITY_:: Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) -*-e*, *--frame-opacity*='OPACITY':: +*-e*, *--frame-opacity*=_OPACITY_:: Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) *-b*, *--daemon*:: @@ -70,53 +73,53 @@ OPTIONS *--show-all-xerrors*:: Show all X errors (for debugging). -*--config* 'PATH':: +*--config* _PATH_:: Look for configuration file at the path. See *CONFIGURATION FILES* section below for where picom looks for a configuration file by default. Use `/dev/null` to avoid loading configuration file. -*--write-pid-path* 'PATH':: +*--write-pid-path* _PATH_:: Write process ID to a file. it is recommended to use an absolute path. -*--plugins* 'PATH':: +*--plugins* _PATH_:: Specify plugins to load. Plugins will first be searched in current working directory (unless specified in the config file, in which case this step is skipped), then in `$XDG_CONFIG_HOME/picom/plugins`, then in `$XDG_CONFIG_DIRS/picom/plugins`. If all of the above fail, the plugin name is passed directly to the dynamic loader. Can be specified multiple times to load more than one plugins. -*--shadow-color* 'STRING':: - Color of shadow, as a hex string ('#000000') +*--shadow-color* _STRING_:: + Color of shadow, as a hex string (e.g. _#000000_) -*--shadow-red* 'VALUE':: +*--shadow-red* _VALUE_:: Red color value of shadow (0.0 - 1.0, defaults to 0). -*--shadow-green* 'VALUE':: +*--shadow-green* _VALUE_:: Green color value of shadow (0.0 - 1.0, defaults to 0). -*--shadow-blue* 'VALUE':: +*--shadow-blue* _VALUE_:: Blue color value of shadow (0.0 - 1.0, defaults to 0). *--inactive-opacity-override*:: - Let inactive opacity set by *-i* override the '_NET_WM_WINDOW_OPACITY' values of windows. + Let inactive opacity set by *-i* override the __NET_WM_WINDOW_OPACITY_ values of windows. -*--active-opacity* 'OPACITY':: +*--active-opacity* _OPACITY_:: Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) -*--inactive-dim* 'VALUE':: +*--inactive-dim* _VALUE_:: Dim inactive windows. (0.0 - 1.0, defaults to 0.0) -*--corner-radius* 'VALUE':: +*--corner-radius* _VALUE_:: Sets the radius of rounded window corners. When > 0, the compositor will round the corners of windows. Does not interact well with *--transparent-clipping*. (defaults to 0). -*--corner-radius-rules* 'RADIUS':'CONDITION':: +*--corner-radius-rules* _RADIUS_:_CONDITION_:: Specify a list of corner radius rules. Overrides the corner radii of matching windows. This option takes precedence over the *--rounded-corners-exclude* option, and also overrides the default exclusion of fullscreen windows. The condition has the same format as *--opacity-rule*. -*--rounded-corners-exclude* 'CONDITION':: +*--rounded-corners-exclude* _CONDITION_:: Exclude conditions for rounded corners. *--no-frame-pacing*:: Disable vsync-aware frame pacing. By default, the compositor tries to make sure it only renders once per vblank interval, and also the render happens as late as possible to minimize the latency from updates to the screen. However this can sometimes cause stuttering, or even lowered frame rate. This option can be used to disable frame pacing. *--mark-wmwin-focused*:: - Try to detect WM windows (a non-override-redirect window with no child that has 'WM_STATE') and mark them as active. + Try to detect WM windows (a non-override-redirect window with no child that has _WM_STATE_) and mark them as active. *--mark-ovredir-focused*:: - Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. + Mark override-redirect windows that doesn't have a child window with _WM_STATE_ focused. *--no-fading-openclose*:: Do not fade on window open/close. @@ -131,49 +134,49 @@ OPTIONS Try to detect windows with rounded corners and don't consider them shaped windows. The accuracy is not very high, unfortunately. *--detect-client-opacity*:: - Detect '_NET_WM_WINDOW_OPACITY' on client windows, useful for window managers not passing '_NET_WM_WINDOW_OPACITY' of client windows to frame windows. + Detect _pass:[_]NET_WM_WINDOW_OPACITY_ on client windows, useful for window managers not passing _pass:[_]NET_WM_WINDOW_OPACITY_ of client windows to frame windows. *--vsync*, *--no-vsync*:: Enable/disable VSync. *--use-ewmh-active-win*:: - Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, provided that the WM supports it. + Use EWMH __NET_ACTIVE_WINDOW_ to determine currently focused window, rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, provided that the WM supports it. *--unredir-if-possible*:: Unredirect all windows in some cases. Known to cause flickering when redirecting/unredirecting windows. Currently, unredirecting is triggered by following conditions: * If the top level window is taking up the entire screen. In multi-monitor setup, this means ALL monitors. * If there is no window. * If a window is fullscreen according to its WM hints. (can be disabled with *--no-ewmh-fullscreen*). - * If a window requests to bypass the compositor ('_NET_WM_BYPASS_COMPOSITOR'). + * If a window requests to bypass the compositor (__NET_WM_BYPASS_COMPOSITOR_). Windows are also unredirected unconditionally when monitors are powered off, regardless if *--unredir-if-possible* is set. -*--unredir-if-possible-delay* 'MILLISECONDS':: +*--unredir-if-possible-delay* _MILLISECONDS_:: Delay before unredirecting the window, in milliseconds. Defaults to 0. -*--unredir-if-possible-exclude* 'CONDITION':: +*--unredir-if-possible-exclude* _CONDITION_:: Conditions of windows that shouldn't be considered full-screen for unredirecting screen. -*--shadow-exclude* 'CONDITION':: +*--shadow-exclude* _CONDITION_:: Specify a list of conditions of windows that should have no shadow. -*--clip-shadow-above* 'CONDITION':: +*--clip-shadow-above* _CONDITION_:: Specify a list of conditions of windows that should have no shadow painted over, such as a dock window. -*--fade-exclude* 'CONDITION':: +*--fade-exclude* _CONDITION_:: Specify a list of conditions of windows that should not be faded. -*--focus-exclude* 'CONDITION':: +*--focus-exclude* _CONDITION_:: Specify a list of conditions of windows that should always be considered focused. *--inactive-dim-fixed*:: Use fixed inactive dim value, instead of adjusting according to window opacity. *--detect-transient*:: - Use 'WM_TRANSIENT_FOR' to group windows, and consider windows in the same group focused at the same time. + Use _WM_TRANSIENT_FOR_ to group windows, and consider windows in the same group focused at the same time. *--detect-client-leader*:: - Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same group focused at the same time. This usually means windows from the same application will be considered focused or unfocused at the same time.'WM_TRANSIENT_FOR' has higher priority if *--detect-transient* is enabled, too. + Use _WM_CLIENT_LEADER_ to group windows, and consider windows in the same group focused at the same time. This usually means windows from the same application will be considered focused or unfocused at the same time._WM_TRANSIENT_FOR_ has higher priority if *--detect-transient* is enabled, too. *--blur-method*, *--blur-size*, *--blur-deviation*, *--blur-strength*:: Parameters for background blurring, see the *BLUR* section for more information. @@ -187,16 +190,16 @@ OPTIONS *--blur-background-fixed*:: Use fixed blur strength rather than adjusting according to window opacity. -*--blur-kern* 'MATRIX':: +*--blur-kern* _MATRIX_:: Specify the blur convolution kernel, with the following format: + ---- WIDTH,HEIGHT,ELE1,ELE2,ELE3,ELE4,ELE5... ---- + -In other words, the matrix is formatted as a list of comma separated numbers. The first two numbers must be integers, which specify the width and height of the matrix. They must be odd numbers. Then, the following 'width * height - 1' numbers specifies the numbers in the matrix, row by row, excluding the center element. +In other words, the matrix is formatted as a list of comma separated numbers. The first two numbers must be integers, which specify the width and height of the matrix. They must be odd numbers. Then, the following `width * height - 1` numbers specifies the numbers in the matrix, row by row, excluding the center element. + -The elements are finite floating point numbers. The decimal pointer has to be '.' (a period), scientific notation is not supported. +The elements are finite floating point numbers. The decimal pointer has to be _._ (a period), scientific notation is not supported. + The element in the center will either be 1.0 or varying based on opacity, depending on whether you have *--blur-background-fixed*. Yet the automatic adjustment of blur factor may not work well with a custom blur kernel. + @@ -208,22 +211,22 @@ A 7x7 Gaussian blur kernel (sigma = 0.84089642) looks like: + May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box`, `3x3gaussian`, `5x5gaussian`, `7x7gaussian`, `9x9gaussian`, `11x11gaussian`. All Gaussian kernels are generated with sigma = 0.84089642 . If you find yourself needing to generate custom blur kernels, you might want to try the new blur configuration (See *BLUR*). -*--blur-background-exclude* 'CONDITION':: +*--blur-background-exclude* _CONDITION_:: Exclude conditions for background blur. -*--resize-damage* 'INTEGER':: - Resize damaged region by a specific number of pixels. A positive value enlarges it while a negative one shrinks it. If the value is positive, those additional pixels will not be actually painted to screen, only used in blur calculation, and such. (Due to technical limitations, with *--use-damage*, those pixels will still be incorrectly painted to screen.) Primarily used to fix the line corruption issues of blur, in which case you should use the blur radius value here (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, with a 5x5 one you use `--resize-damage 2`, and so on). May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. +*--resize-damage* _INTEGER_:: + Resize damaged region by a specific number of pixels. A positive value enlarges it while a negative one shrinks it. If the value is positive, those additional pixels will not be actually painted to screen, only used in blur calculation, and such. (Due to technical limitations, with *--use-damage*, those pixels will still be incorrectly painted to screen.) Primarily used to fix the line corruption issues of blur, in which case you should use the blur radius value here (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, with a 5x5 one you use `--resize-damage 2`, and so on). May or may not work with *--glx-no-stencil*. Only works with *--legacy-backends*. Shrinking doesn't function correctly. -*--invert-color-include* 'CONDITION':: +*--invert-color-include* _CONDITION_:: Specify a list of conditions of windows that should be painted with inverted color. Resource-hogging, and is not well tested. -*--opacity-rule* 'OPACITY':'CONDITION':: - Specify a list of opacity rules, in the format `PERCENT:PATTERN`, like `50:name *= "Firefox"`. picom-trans is recommended over this. Note we don't make any guarantee about possible conflicts with other programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. +*--opacity-rule* _OPACITY_:_CONDITION_:: + Specify a list of opacity rules, in the format `PERCENT:PATTERN`, like `50:name *= "Firefox"`. picom-trans is recommended over this. Note we don't make any guarantee about possible conflicts with other programs that set __NET_WM_WINDOW_OPACITY_ on frame or client windows. *--crop-shadow-to-monitor*:: Crop shadow of a window fully on a particular monitor to that monitor. This is currently implemented using the X RandR extension. -*--backend* 'BACKEND':: +*--backend* _BACKEND_:: Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. `xrender` is the default one. + -- @@ -244,7 +247,7 @@ May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box *--xrender-sync-fence*:: Use X Sync fence to sync clients' draw calls, to make sure all draw calls are finished before picom starts drawing. Needed on nvidia-drivers with GLX backend for some users. -*--glx-fshader-win* 'SHADER':: +*--glx-fshader-win* _SHADER_:: GLX backend: Use specified GLSL fragment shader for rendering window contents. See `compton-default-fshader-win.glsl` and `compton-fake-transparency-fshader-win.glsl` in the source tree for examples. Only works with *--legacy-backends* enabled. *--force-win-blend*:: @@ -253,10 +256,10 @@ May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box *--dbus*:: Enable remote control via D-Bus. See the *D-BUS API* section below for more details. -*--benchmark* 'CYCLES':: +*--benchmark* _CYCLES_:: Benchmark mode. Repeatedly paint until reaching the specified cycles. -*--benchmark-wid* 'WINDOW_ID':: +*--benchmark-wid* _WINDOW_ID_:: Specify window ID to repaint in benchmark mode. If omitted or is 0, the whole screen is repainted. *--no-ewmh-fullscreen*:: @@ -268,14 +271,14 @@ May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box *--transparent-clipping*:: Make transparent windows clip other windows like non-transparent windows do, instead of blending on top of them. -*--transparent-clipping-exclude* 'CONDITION':: +*--transparent-clipping-exclude* _CONDITION_:: Specify a list of conditions of windows that should never have transparent clipping applied. Useful for screenshot tools, where you need to be able to see through transparent parts of the window. -*--window-shader-fg* 'SHADER':: +*--window-shader-fg* _SHADER_:: Specify GLSL fragment shader path for rendering window contents. Does not work when *--legacy-backends* is enabled. Shader is searched first relative to the directory the configuration file is in, then in the usual places for a configuration file. See section *SHADER INTERFACE* below for more details on the interface. -*--window-shader-fg-rule* 'SHADER':'CONDITION':: - Specify GLSL fragment shader path for rendering window contents using patterns. Similar to *--opacity-rule*, arguments should be in the format of 'SHADER:CONDITION', e.g. "shader.frag:name = \'window\'". Leading and trailing whitespaces in 'SHADER' will be trimmed. If 'SHADER' is "default", then the default shader will be used for the matching windows. (This also unfortunately means you can't use a shader file named "default"). Does not work when *--legacy-backends* is enabled. +*--window-shader-fg-rule* _SHADER_:_CONDITION_:: + Specify GLSL fragment shader path for rendering window contents using patterns. Similar to *--opacity-rule*, arguments should be in the format of _SHADER:CONDITION_, e.g. "shader.frag:name = 'window'". Leading and trailing whitespaces in _SHADER_ will be trimmed. If _SHADER_ is "default", then the default shader will be used for the matching windows. (This also unfortunately means you can't use a shader file named "default"). Does not work when *--legacy-backends* is enabled. *--dithered-present* Use higher precision during rendering, and apply dither when presenting the rendered screen. Reduces banding artifacts, but might cause performance degradation. Only works with OpenGL. @@ -296,21 +299,21 @@ With greater-than/less-than operators it looks like: [] -'NEGATION' (optional) is one or more exclamation marks; +_NEGATION_ (optional) is one or more exclamation marks; -'TARGET' is either a predefined target name, or the name of a window property to match. Supported predefined targets are `id`, `x`, `y`, `x2` (`x` + `widthb`), `y2` (like `x2`), `width`, `height`, `widthb` (`width` + 2 * `border_width`), `heightb` (like `widthb`), `border_width`, `fullscreen`, `override_redirect`, `argb` (whether the window has an ARGB visual), `focused`, `wmwin` (whether the window looks like a WM window, i.e. has no child window with `WM_STATE` and is not override-redirected), `bounding_shaped`, `rounded_corners` (requires *--detect-rounded-corners*), `client` (ID of client window), `window_type` (window type in string), `leader` (ID of window leader), `name`, `class_g` (= `WM_CLASS[1]`), `class_i` (= `WM_CLASS[0]`), and `role`. +_TARGET_ is either a predefined target name, or the name of a window property to match. Supported predefined targets are `id`, `x`, `y`, `x2` (`x` + `widthb`), `y2` (like `x2`), `width`, `height`, `widthb` (`width` + 2 * `border_width`), `heightb` (like `widthb`), `border_width`, `fullscreen`, `override_redirect`, `argb` (whether the window has an ARGB visual), `focused`, `wmwin` (whether the window looks like a WM window, i.e. has no child window with `WM_STATE` and is not override-redirected), `bounding_shaped`, `rounded_corners` (requires *--detect-rounded-corners*), `client` (ID of client window), `window_type` (window type in string), `leader` (ID of window leader), `name`, `class_g` (= `WM_CLASS[1]`), `class_i` (= `WM_CLASS[0]`), and `role`. -'CLIENT/FRAME' is a single `@` if the window attribute should be be looked up on client window, nothing if on frame window; +_CLIENT/FRAME_ is a single `@` if the window attribute should be be looked up on client window, nothing if on frame window; -'INDEX' (optional) is the index number of the property to look up. For example, `[2]` means look at the third value in the property. If not specified, the first value (index `[0]`) is used implicitly. Use the special value `[*]` to perform matching against all available property values using logical OR. Do not specify it for predefined targets. +_INDEX_ (optional) is the index number of the property to look up. For example, `[2]` means look at the third value in the property. If not specified, the first value (index `[0]`) is used implicitly. Use the special value `[*]` to perform matching against all available property values using logical OR. Do not specify it for predefined targets. 'OP QUALIFIER' (optional), applicable only for equals operator, could be `?` (ignore-case). 'MATCH TYPE' (optional), applicable only for equals operator, could be nothing (exact match), `*` (match anywhere), `^` (match from start), `%` (wildcard), or `~` (PCRE regular expression). -'OPERATOR' is one of `=` (equals), `<`, `>`, `<=`, `=>`, or nothing (exists). Exists operator checks whether a property exists on a window (but for predefined targets, exists means != 0 then). +_OPERATOR_ is one of `=` (equals), `<`, `>`, `<=`, `=>`, or nothing (exists). Exists operator checks whether a property exists on a window (but for predefined targets, exists means != 0 then). -'PATTERN' is either an integer or a string enclosed by single or double quotes. Python-3-style escape sequences are supported in the string format. +_PATTERN_ is either an integer or a string enclosed by single or double quotes. Python-3-style escape sequences are supported in the string format. Supported logical operators are `&&` (and) and `||` (or). `&&` has higher precedence than `||`, left-to-right associativity. Use parentheses to change precedence. @@ -355,13 +358,13 @@ This is the old condition format we once used. Support of this format might be r condition = TARGET:TYPE[FLAGS]:PATTERN -'TARGET' is one of "n" (window name), "i" (window class instance), "g" (window general class), and "r" (window role). +_TARGET_ is one of "n" (window name), "i" (window class instance), "g" (window general class), and "r" (window role). -'TYPE' is one of "e" (exact match), "a" (match anywhere), "s" (match from start), "w" (wildcard), and "p" (PCRE regular expressions, if compiled with the support). +_TYPE_ is one of "e" (exact match), "a" (match anywhere), "s" (match from start), "w" (wildcard), and "p" (PCRE regular expressions, if compiled with the support). -'FLAGS' could be a series of flags. Currently the only defined flag is "i" (ignore case). +_FLAGS_ could be a series of flags. Currently the only defined flag is "i" (ignore case). -'PATTERN' is the actual pattern string. +_PATTERN_ is the actual pattern string. SHADER INTERFACE ---------------- @@ -372,7 +375,7 @@ A custom shader is a GLSL fragment shader program, which can be used to override The interface between picom and a custom shader is dependent on which backend is being used. The xrender backend doesn't support shader at all. Here we descibe the interface provided by the glx backend. -The shader must define a function, 'vec4 window_shader()', which would be the entry point of the shader. The returned 'vec4' will be used to set 'gl_FragColor'. A function, 'vec4 default_post_processing(vec4 c)', is provided for applying the default picom effects to input color 'c'. +The shader must define a function, _vec4 window_shader()_, which would be the entry point of the shader. The returned _vec4_ will be used to set __gl_FragColor__. A function, _vec4 default_post_processing(vec4 c)_, is provided for applying the default picom effects to input color 'c'. The following uniform/input variables are made available to the shader: @@ -437,7 +440,7 @@ wintypes: }; ------------ -'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: "unknown", "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal", "dropdown_menu", "popup_menu", "tooltip", "notification", "combo", and "dnd". +_WINDOW_TYPE_ is one of the 15 window types defined in EWMH standard: "unknown", "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal", "dropdown_menu", "popup_menu", "tooltip", "notification", "combo", and "dnd". Following per window-type options are available: :: @@ -475,25 +478,25 @@ blur: }; -------- -Available options of the 'blur' section are: :: +Available options of the _blur_ section are: :: *method*::: A string. Controls the blur method. Corresponds to the *--blur-method* command line option. Available choices are: - 'none' to disable blurring; 'gaussian' for gaussian blur; 'box' for box blur; 'kernel' for convolution blur with a custom kernel; 'dual_kawase' for dual-filter kawase blur. - Note: 'gaussian', 'box' and 'dual_kawase' blur methods are not supported by the legacy backends. + _none_ to disable blurring; _gaussian_ for gaussian blur; _box_ for box blur; _kernel_ for convolution blur with a custom kernel; _dual_kawase_ for dual-filter kawase blur. + Note: _gaussian_, _box_ and _dual_kawase_ blur methods are not supported by the legacy backends. (default: none) *size*::: - An integer. The size of the blur kernel, required by 'gaussian' and 'box' blur methods. For the 'kernel' method, the size is included in the kernel. Corresponds to the *--blur-size* command line option (default: 3). + An integer. The size of the blur kernel, required by _gaussian_ and _box_ blur methods. For the _kernel_ method, the size is included in the kernel. Corresponds to the *--blur-size* command line option (default: 3). *deviation*::: - A floating point number. The standard deviation for the 'gaussian' blur method. Corresponds to the *--blur-deviation* command line option (default: 0.84089642). + A floating point number. The standard deviation for the _gaussian_ blur method. Corresponds to the *--blur-deviation* command line option (default: 0.84089642). *strength*::: - An integer in the range 0-20. The strength of the 'dual_kawase' blur method. Corresponds to the *--blur-strength* command line option. If set to zero, the value requested by *--blur-size* is approximated (default: 5). + An integer in the range 0-20. The strength of the _dual_kawase_ blur method. Corresponds to the *--blur-strength* command line option. If set to zero, the value requested by *--blur-size* is approximated (default: 5). *kernel*::: - A string. The kernel to use for the 'kernel' blur method, specified in the same format as the *--blur-kern* option. Corresponds to the *--blur-kern* command line option. + A string. The kernel to use for the _kernel_ blur method, specified in the same format as the *--blur-kern* option. Corresponds to the *--blur-kern* command line option. SIGNALS ------- @@ -558,4 +561,4 @@ Homepage: SEE ALSO -------- -*xcompmgr*(1), link:picom-inspect.html[*picom-inspect*(1)], link:picom-trans.html[*picom-trans*(1)] +*xcompmgr*(1), xref:picom-inspect.1.adoc[*picom-inspect*(1)], xref:picom-trans.1.adoc[*picom-trans*(1)] diff --git a/src/backend/gl/egl.c b/src/backend/gl/egl.c index 13d30b7876..960d5d94a6 100644 --- a/src/backend/gl/egl.c +++ b/src/backend/gl/egl.c @@ -165,15 +165,13 @@ static backend_t *egl_init(session_t *ps, xcb_window_t target) { // clang-format off if (eglChooseConfig(gd->display, (EGLint[]){ - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_RED_SIZE, visual_info.red_size, - EGL_GREEN_SIZE, visual_info.green_size, - EGL_BLUE_SIZE, visual_info.blue_size, - EGL_ALPHA_SIZE, visual_info.alpha_size, - EGL_STENCIL_SIZE, 1, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_NONE, + EGL_RED_SIZE, visual_info.red_size, + EGL_GREEN_SIZE, visual_info.green_size, + EGL_BLUE_SIZE, visual_info.blue_size, + EGL_ALPHA_SIZE, visual_info.alpha_size, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE, }, &config, nconfigs, &nconfigs) != EGL_TRUE) { log_error("Failed to choose EGL config for the root window."); goto end; diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index 629f49f3c9..b15f5c96c6 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -66,20 +66,14 @@ bool glx_find_fbconfig(struct x_connection *c, struct xvisual_info m, // clang-format off GLXFBConfig *cfg = glXChooseFBConfig(c->dpy, c->screen, (int[]){ - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_X_RENDERABLE, true, - GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, (GLint)GLX_DONT_CARE, - GLX_BUFFER_SIZE, m.red_size + m.green_size + - m.blue_size + m.alpha_size, GLX_RED_SIZE, m.red_size, - GLX_BLUE_SIZE, m.blue_size, GLX_GREEN_SIZE, m.green_size, + GLX_BLUE_SIZE, m.blue_size, GLX_ALPHA_SIZE, m.alpha_size, - GLX_STENCIL_SIZE, 0, - GLX_DEPTH_SIZE, 0, - 0 + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_X_RENDERABLE, True, + GLX_CONFIG_CAVEAT, GLX_NONE, + None, }, &ncfg); // clang-format on @@ -260,11 +254,6 @@ static backend_t *glx_init(session_t *ps, xcb_window_t target) { goto end; } - if (glXGetConfig(ps->c.dpy, pvis, GLX_STENCIL_SIZE, &value) || !value) { - log_error("Root visual lacks stencil buffer."); - goto end; - } - if (glXGetConfig(ps->c.dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) { log_error("Root visual is not a double buffered GL visual."); goto end; diff --git a/src/c2.c b/src/c2.c index 08733c1454..84dae05e7f 100644 --- a/src/c2.c +++ b/src/c2.c @@ -102,7 +102,10 @@ struct c2_property_value { /// Initializer for c2_ptr_t. #define C2_PTR_INIT \ - { .isbranch = false, .l = NULL, } + { \ + .isbranch = false, \ + .l = NULL, \ + } static const c2_ptr_t C2_PTR_NULL = C2_PTR_INIT; @@ -124,7 +127,7 @@ struct _c2_b { /// Initializer for c2_b_t. #define C2_B_INIT \ - { .neg = false, .op = C2_B_OUNDEFINED, .opr1 = C2_PTR_INIT, .opr2 = C2_PTR_INIT, } + {.neg = false, .op = C2_B_OUNDEFINED, .opr1 = C2_PTR_INIT, .opr2 = C2_PTR_INIT} /// Structure for leaf element in a window condition struct _c2_l { @@ -197,10 +200,18 @@ struct _c2_l { /// Initializer for c2_l_t. #define C2_L_INIT \ { \ - .neg = false, .op = C2_L_OEXISTS, .match = C2_L_MEXACT, \ - .match_ignorecase = false, .tgt = NULL, .tgtatom = 0, \ - .target_on_client = false, .predef = C2_L_PUNDEFINED, .index = 0, \ - .ptntype = C2_L_PTUNDEFINED, .ptnstr = NULL, .ptnint = 0, \ + .neg = false, \ + .op = C2_L_OEXISTS, \ + .match = C2_L_MEXACT, \ + .match_ignorecase = false, \ + .tgt = NULL, \ + .tgtatom = 0, \ + .target_on_client = false, \ + .predef = C2_L_PUNDEFINED, \ + .index = 0, \ + .ptntype = C2_L_PTUNDEFINED, \ + .ptnstr = NULL, \ + .ptnint = 0, \ } static const c2_l_t leaf_def = C2_L_INIT; @@ -212,10 +223,6 @@ struct _c2_lptr { struct _c2_lptr *next; }; -/// Initializer for c2_lptr_t. -#define C2_LPTR_INIT \ - { .ptr = C2_PTR_INIT, .data = NULL, .next = NULL, } - /// Structure representing a predefined target. typedef struct { const char *name; @@ -387,11 +394,12 @@ c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) { // Insert to pcondlst { - static const c2_lptr_t lptr_def = C2_LPTR_INIT; auto plptr = cmalloc(c2_lptr_t); - memcpy(plptr, &lptr_def, sizeof(c2_lptr_t)); - plptr->ptr = result; - plptr->data = data; + *plptr = (c2_lptr_t){ + .ptr = result, + .data = data, + .next = NULL, + }; if (pcondlst) { plptr->next = *pcondlst; *pcondlst = plptr; diff --git a/src/event.c b/src/event.c index 2a8bb56e3c..7d431db0fe 100644 --- a/src/event.c +++ b/src/event.c @@ -380,44 +380,14 @@ static void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { return; } - add_damage_from_win(ps, w); - - // We check against pending_g here, because there might have been multiple - // configure notifies in this cycle, or the window could receive multiple updates - // while it's unmapped. - bool position_changed = w->pending_g.x != ce->x || w->pending_g.y != ce->y; - bool size_changed = w->pending_g.width != ce->width || - w->pending_g.height != ce->height || - w->pending_g.border_width != ce->border_width; - if (position_changed || size_changed) { - // Queue pending updates - win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED); - // TODO(yshui) don't set pending_updates if the window is not - // visible/mapped - ps->pending_updates = true; - - // At least one of the following if's is true - if (position_changed) { - log_trace("Window position changed, %dx%d -> %dx%d", w->g.x, - w->g.y, ce->x, ce->y); - w->pending_g.x = ce->x; - w->pending_g.y = ce->y; - win_set_flags(w, WIN_FLAGS_POSITION_STALE); - } + bool changed = win_set_pending_geometry(w, win_geometry_from_configure_notify(ce)) | + (w->a.override_redirect != ce->override_redirect); + w->a.override_redirect = ce->override_redirect; - if (size_changed) { - log_trace("Window size changed, %dx%d -> %dx%d", w->g.width, - w->g.height, ce->width, ce->height); - w->pending_g.width = ce->width; - w->pending_g.height = ce->height; - w->pending_g.border_width = ce->border_width; - win_set_flags(w, WIN_FLAGS_SIZE_STALE); - } + if (w->state == WSTATE_MAPPED) { + add_damage_from_win(ps, w); + ps->pending_updates |= changed; } - - // override_redirect flag cannot be changed after window creation, as far - // as I know, so there's no point to re-match windows here. - w->a.override_redirect = ce->override_redirect; } static inline void ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) { diff --git a/src/meson.build b/src/meson.build index d05ee95e98..ed8784306d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -103,8 +103,13 @@ subdir('renderer') subdir('transition') subdir('utils') +dl_dep = [] +if not cc.has_function('dlopen') + dl_dep = [ cc.find_library('dl', required: true) ] +endif + picom = executable('picom', srcs, c_args: cflags, - dependencies: [ base_deps, deps, test_h_dep ], + dependencies: [ base_deps, deps, test_h_dep ] + dl_dep, install: true, include_directories: picom_inc, export_dynamic: true, gnu_symbol_visibility: 'hidden') diff --git a/src/picom.c b/src/picom.c index e1e78f7d87..3f847366df 100644 --- a/src/picom.c +++ b/src/picom.c @@ -1543,7 +1543,7 @@ static void handle_new_window_attributes_reply(struct x_connection * /*c*/, auto w = win_maybe_allocate(ps, toplevel, (xcb_get_window_attributes_reply_t *)reply_or_error); if (w != NULL && w->a.map_state == XCB_MAP_STATE_VIEWABLE) { - win_map_start(w); + win_map_start(ps, w); ps->pending_updates = true; } } diff --git a/src/wm/win.c b/src/wm/win.c index 2679db402a..c08ac88caa 100644 --- a/src/wm/win.c +++ b/src/wm/win.c @@ -443,7 +443,7 @@ void win_process_primary_flags(session_t *ps, struct win *w) { win_id(w), w->name, w->to_paint, w->flags); if (win_check_flags_all(w, WIN_FLAGS_MAPPED)) { - win_map_start(w); + win_map_start(ps, w); win_clear_flags(w, WIN_FLAGS_MAPPED); } @@ -1296,8 +1296,6 @@ bool win_update_wintype(struct x_connection *c, struct atom *atoms, struct win * * @param w struct _win of the parent window */ void win_on_client_update(session_t *ps, struct win *w) { - auto client_win = wm_ref_client_of(w->tree_ref); - // If the window isn't mapped yet, stop here, as the function will be // called in map_win() if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) { @@ -1306,7 +1304,7 @@ void win_on_client_update(session_t *ps, struct win *w) { win_update_wintype(&ps->c, ps->atoms, w); - xcb_window_t client_win_id = client_win ? wm_ref_win_id(client_win) : XCB_NONE; + xcb_window_t client_win_id = win_client_id(w, /*fallback_to_self=*/true); // Get frame widths. The window is in damaged area already. win_update_frame_extents(&ps->c, ps->atoms, w, client_win_id, ps->o.frame_opacity); @@ -2188,9 +2186,83 @@ int win_find_monitor(const struct x_monitors *monitors, const struct win *mw) { return ret; } +bool win_set_pending_geometry(struct win *w, struct win_geometry g) { + // We check against pending_g here, because there might have been multiple + // configure notifies in this cycle, or the window could receive multiple updates + // while it's unmapped. `pending_g` should be equal to `g` otherwise. + bool position_changed = w->pending_g.x != g.x || w->pending_g.y != g.y; + bool size_changed = w->pending_g.width != g.width || w->pending_g.height != g.height || + w->pending_g.border_width != g.border_width; + if (position_changed || size_changed) { + // Queue pending updates + win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED); + + // At least one of the following if's is true + if (position_changed) { + log_trace("Window %#010x position changed, %dx%d -> %dx%d", + win_id(w), w->g.x, w->g.y, g.x, g.y); + w->pending_g.x = g.x; + w->pending_g.y = g.y; + win_set_flags(w, WIN_FLAGS_POSITION_STALE); + } + + if (size_changed) { + log_trace("Window %#010x size changed, %dx%d -> %dx%d", win_id(w), + w->g.width, w->g.height, g.width, g.height); + w->pending_g.width = g.width; + w->pending_g.height = g.height; + w->pending_g.border_width = g.border_width; + win_set_flags(w, WIN_FLAGS_SIZE_STALE); + } + } + return position_changed || size_changed; +} + +struct win_get_geometry_request { + struct x_async_request_base base; + struct session *ps; + xcb_window_t wid; +}; + +static void win_handle_get_geometry_reply(struct x_connection * /*c*/, + struct x_async_request_base *req_base, + xcb_raw_generic_event_t *reply_or_error) { + auto req = (struct win_get_geometry_request *)req_base; + auto wid = req->wid; + auto ps = req->ps; + free(req); + + if (reply_or_error->response_type == 0) { + log_debug("Failed to get geometry of window %#010x: %s", wid, + x_strerror((xcb_generic_error_t *)reply_or_error)); + return; + } + + auto cursor = wm_find(ps->wm, wid); + if (cursor == NULL) { + // Rare, window is destroyed then its ID is reused + if (wm_is_consistent(ps->wm)) { + log_error("Successfully fetched geometry of a non-existent " + "window %#010x", + wid); + assert(false); + } + return; + } + + auto w = wm_ref_deref(cursor); + if (w == NULL) { + // Not yet managed. Rare, window is destroyed then its ID is reused + return; + } + + auto r = (xcb_get_geometry_reply_t *)reply_or_error; + ps->pending_updates |= win_set_pending_geometry(w, win_geometry_from_get_geometry(r)); +} + /// Start the mapping of a window. We cannot map immediately since we might need to fade /// the window in. -void win_map_start(struct win *w) { +void win_map_start(struct session *ps, struct win *w) { assert(w); // Don't care about window mapping if it's an InputOnly window @@ -2223,6 +2295,15 @@ void win_map_start(struct win *w) { w->state = WSTATE_MAPPED; win_set_flags(w, WIN_FLAGS_PIXMAP_STALE | WIN_FLAGS_CLIENT_STALE); + + auto req = ccalloc(1, struct win_get_geometry_request); + req->base = (struct x_async_request_base){ + .callback = win_handle_get_geometry_reply, + .sequence = xcb_get_geometry(ps->c.c, win_id(w)).sequence, + }; + req->wid = win_id(w); + req->ps = ps; + x_await_request(&ps->c, &req->base); } /// Set flags on a window. Some sanity checks are performed diff --git a/src/wm/win.h b/src/wm/win.h index c5ff0af070..4aa8e6249f 100644 --- a/src/wm/win.h +++ b/src/wm/win.h @@ -357,7 +357,7 @@ void unmap_win_finish(session_t *ps, struct win *w); /// Start the destroying of a window. Windows cannot always be destroyed immediately /// because of fading and such. void win_destroy_start(session_t *ps, struct win *w); -void win_map_start(struct win *w); +void win_map_start(struct session *ps, struct win *w); /// Release images bound with a window, set the *_NONE flags on the window. Only to be /// used when de-initializing the backend outside of win.c void win_release_images(struct backend_base *backend, struct win *w); @@ -474,6 +474,30 @@ bool win_check_flags_all(struct win *w, uint64_t flags); /// Mark properties as stale for a window void win_set_properties_stale(struct win *w, const xcb_atom_t *prop, int nprops); +static inline struct win_geometry +win_geometry_from_configure_notify(const xcb_configure_notify_event_t *ce) { + return (struct win_geometry){ + .x = ce->x, + .y = ce->y, + .width = ce->width, + .height = ce->height, + .border_width = ce->border_width, + }; +} +static inline struct win_geometry +win_geometry_from_get_geometry(const xcb_get_geometry_reply_t *g) { + return (struct win_geometry){ + .x = g->x, + .y = g->y, + .width = g->width, + .height = g->height, + .border_width = g->border_width, + }; +} +/// Set the pending geometry of a window. And set appropriate flags when the geometry +/// changes. +/// Returns true if the geometry has changed, false otherwise. +bool win_set_pending_geometry(struct win *w, struct win_geometry g); bool win_update_wintype(struct x_connection *c, struct atom *atoms, struct win *w); /** * Retrieve frame extents from a window.