mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
Compare commits
55 commits
0fc6c5e4fd
...
d6dcda73d6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6dcda73d6 | ||
|
|
19b8ad35f9 | ||
|
|
b7f46ac9ba | ||
|
|
13e838cd34 | ||
|
|
a0dacbf85d | ||
|
|
4cc00058e3 | ||
|
|
bed0be8a88 | ||
|
|
0d0d1075cc | ||
|
|
4c1e66f6c8 | ||
|
|
389cef9c3b | ||
|
|
e558d0d619 | ||
|
|
c8581b3fed | ||
|
|
60d536304b | ||
|
|
9ec49144ac | ||
|
|
eb41c6a3b0 | ||
|
|
2ea0f6fff4 | ||
|
|
950c634cea | ||
|
|
286005e121 | ||
|
|
040e25f38e | ||
|
|
27f3097f8f | ||
|
|
c5cd1f691d | ||
|
|
46bd1fef95 | ||
|
|
7e27f78662 | ||
|
|
1043a9becc | ||
|
|
94c980c6be | ||
|
|
c9030dcc5b | ||
|
|
26bd02d457 | ||
|
|
1692c47fa0 | ||
|
|
bdc8e1c546 | ||
|
|
ee87b4fc30 | ||
|
|
34e52a40c7 | ||
|
|
139a5f0383 | ||
|
|
0bf2678f9d | ||
|
|
6bbdc3c6dc | ||
|
|
7a5b7aa378 | ||
|
|
5fdebedcd9 | ||
|
|
5765586636 | ||
|
|
7028e65154 | ||
|
|
ebce406b11 | ||
|
|
141f932efa | ||
|
|
24f39e3a41 | ||
|
|
2ac48116e1 | ||
|
|
af6a0df231 | ||
|
|
0db3b9309b | ||
|
|
387e62d87b | ||
|
|
c6503e299f | ||
|
|
268ef857db | ||
|
|
f09ace51bf | ||
|
|
d54051d9c1 | ||
|
|
5ce20b2b95 | ||
|
|
072d45d4b2 | ||
|
|
0ce10f6afa | ||
|
|
bca0ec07ac | ||
|
|
e17ec0203c | ||
|
|
f2639226c7 |
60 changed files with 674 additions and 430 deletions
|
|
@ -12,14 +12,21 @@ UseTab: Always
|
|||
IndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignOperands: false
|
||||
AlwaysBreakAfterDefinitionReturnType: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Linux
|
||||
IndentCaseLabels: false
|
||||
PenaltyBreakOpenParenthesis: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 500
|
||||
SpaceBeforeParens: ControlStatementsExceptControlMacros
|
||||
ForEachMacros: ['for_each_view',
|
||||
'for_each_view_reverse',
|
||||
'wl_array_for_each',
|
||||
'wl_list_for_each',
|
||||
'wl_list_for_each_reverse',
|
||||
'wl_list_for_each_reverse_safe',
|
||||
'wl_list_for_each_safe']
|
||||
IncludeCategories:
|
||||
- Regex: '<.*>'
|
||||
- Regex: '.*'
|
||||
|
|
|
|||
21
.github/workflows/build.yml
vendored
21
.github/workflows/build.yml
vendored
|
|
@ -82,7 +82,7 @@ jobs:
|
|||
pacman -Syu --noconfirm
|
||||
pacman -S --noconfirm git meson clang wlroots0.19 libdrm libinput \
|
||||
wayland-protocols cairo pango libxml2 xorg-xwayland librsvg \
|
||||
libdisplay-info gdb ttf-dejavu foot libsfdo
|
||||
libdisplay-info gdb ttf-dejavu foot libsfdo cmocka
|
||||
|
||||
- name: Install Debian Testing dependencies
|
||||
if: matrix.name == 'Debian'
|
||||
|
|
@ -92,7 +92,8 @@ jobs:
|
|||
apt-get upgrade -y
|
||||
apt-get install -y git gcc clang gdb xwayland
|
||||
apt-get build-dep -y labwc
|
||||
apt-get build-dep -y libwlroots-0.18-dev
|
||||
apt-get build-dep -y libwlroots-0.19-dev
|
||||
apt-get build-dep -y libxkbcommon-dev
|
||||
|
||||
- name: Install FreeBSD dependencies
|
||||
if: matrix.name == 'FreeBSD'
|
||||
|
|
@ -119,7 +120,7 @@ jobs:
|
|||
xbps-install -y git meson gcc clang pkg-config scdoc \
|
||||
cairo-devel glib-devel libpng-devel librsvg-devel libxml2-devel \
|
||||
pango-devel wlroots0.19-devel gdb bash xorg-server-xwayland \
|
||||
dejavu-fonts-ttf libsfdo-devel foot
|
||||
dejavu-fonts-ttf libsfdo-devel foot hwids
|
||||
|
||||
# These builds are executed on all runners
|
||||
- name: Build with gcc
|
||||
|
|
@ -168,6 +169,7 @@ jobs:
|
|||
meson setup build-gcc-release -Dxwayland=enabled \
|
||||
-Dbuildtype=release -Db_ndebug=true --werror
|
||||
meson configure build-gcc-release -Dwlroots:b_ndebug=false || true
|
||||
meson configure build-gcc-release -Dlibsfdo:b_ndebug=false || true
|
||||
meson compile -C build-gcc-release
|
||||
' | $TARGET
|
||||
|
||||
|
|
@ -190,6 +192,7 @@ jobs:
|
|||
meson setup build-clang-release -Dxwayland=enabled \
|
||||
-Dbuildtype=release -Db_ndebug=true --werror
|
||||
meson configure build-clang-release -Dwlroots:b_ndebug=false || true
|
||||
meson configure build-clang-release -Dlibsfdo:b_ndebug=false || true
|
||||
meson compile -C build-clang-release
|
||||
' | $TARGET
|
||||
|
||||
|
|
@ -205,6 +208,18 @@ jobs:
|
|||
meson compile -C build-gcc-no-feature
|
||||
' | $TARGET
|
||||
|
||||
# Unit tests, run on Arch only
|
||||
- name: Build with gcc - unit test
|
||||
if: matrix.name == 'Arch'
|
||||
run: |
|
||||
echo '
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
export CC=gcc
|
||||
meson setup build-gcc-unit-test -Dtest=enabled --werror
|
||||
meson compile -C build-gcc-unit-test
|
||||
meson test -C build-gcc-unit-test --print-errorlogs
|
||||
' | $TARGET
|
||||
|
||||
# Runtime tests, these run on Arch and Void only (the later due to libmusl being used)
|
||||
- name: Build with gcc - runtime test
|
||||
if: matrix.name == 'Arch'
|
||||
|
|
|
|||
|
|
@ -23,14 +23,14 @@
|
|||
|
||||
# How to Contribute
|
||||
|
||||
1. Report bugs as github issues. We use a template prompting you to provide
|
||||
1. Report bugs as GitHub issues. We use a template prompting you to provide
|
||||
some sensible information such as what happened, what you expected to happen
|
||||
and steps to reproduce. If applicable try with default configuration. If
|
||||
you are able to, try to do some debugging (guidelines below).
|
||||
and steps to reproduce. If applicable try with default configuration. If
|
||||
you are able to, try debugging (guidelines below).
|
||||
|
||||
2. Submit patches as github pull-requests. If you wish to introduces significant
|
||||
2. Submit patches as GitHub pull requests. If you wish to introduce significant
|
||||
changes or new features, consult the [scope document], discuss on IRC or via
|
||||
a github issue first.
|
||||
a GitHub issue first.
|
||||
|
||||
# Debugging
|
||||
|
||||
|
|
@ -251,14 +251,14 @@ We try to keep the use of GLib pretty minimal for the following reasons:
|
|||
- The use of GLib has been known to make AddressSanitiser diagnose false
|
||||
positives and negatives.
|
||||
- Log messages coming from GLib functions look inconsistent.
|
||||
- The use of GLib functions, naming-conventions and iterators in a code base
|
||||
- The use of GLib functions, naming-conventions and iterators in a codebase
|
||||
that is predominantly ANSI C creates a clash which makes readability and
|
||||
maintainability harder.
|
||||
- Mixing gmalloc()/malloc() and respective free()s can create problems with
|
||||
memory pools [^1]
|
||||
|
||||
Having said that, with our use of cairo and pango we depend on glib-2.0 anyway
|
||||
so linking with it and making use of some of its helper functions comes for free
|
||||
Having said that, with our use of cairo and pango we depend on glib-2.0 anyway,
|
||||
so linking with it and making use of some of its helper functions comes for free,
|
||||
and can keep the code simpler.
|
||||
|
||||
For example, if we were going to carry out extensive string manipulation,
|
||||
|
|
@ -291,7 +291,7 @@ match(const gchar *pattern, const gchar *string)
|
|||
|
||||
### The Use of GNU Extensions
|
||||
|
||||
We avoid [GNU C extensions] because we want to fit into the eco-system
|
||||
We avoid [GNU C extensions] because we want to fit into the ecosystem
|
||||
(wayland and wlroots) we live in.
|
||||
|
||||
We do use `__typeof__` which strictly speaking is a GNU C extension (`typeof`)
|
||||
|
|
@ -300,18 +300,18 @@ but through the use of `__` is supported by gcc and clang without defining
|
|||
in the [`wl_container_of()`] macro which is needed in `wl_list*` and it
|
||||
does provide pretty big benefits in terms of type safety.
|
||||
|
||||
We compile with `-std=c11` because that's what 'wlroots' uses and we do not
|
||||
We compile with `-std=c11` because that's what 'wlroots' uses, and we do not
|
||||
want to increase the entry-level for OSs without good reason (and currently
|
||||
we can't think of one).
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
There are three types of coordinate systems: surface, output and layout - for
|
||||
There are three types of coordinate systems: surface, output, and layout — for
|
||||
which the variables (sx, sy), (ox, oy) and (lx, ly) are used respectively in
|
||||
line with wlroots.
|
||||
|
||||
With the introduction of the scene-graph API, some wlroots functions also use
|
||||
node coordinates (nx, ny) but we prefer (sx, sy) where possible.
|
||||
node coordinates (nx, ny), but we prefer (sx, sy) where possible.
|
||||
|
||||
We do not worry about namespace issues too much and we try to not make the code
|
||||
a pain to use just to uniquify names. If we were writing a library we would
|
||||
|
|
@ -361,11 +361,11 @@ In new files, please order `#include` lines as follows:
|
|||
compiles cleanly on its own, without implicit dependencies on other
|
||||
headers being included first.
|
||||
|
||||
- Then list any "system" headers (those not part of labwc) in alphebetical
|
||||
- Then list any "system" headers (those not part of labwc) in alphabetical
|
||||
order, using angle brackets. This includes 3rd-party library headers
|
||||
such as `<cairo.h>`, as well as wlroots headers.
|
||||
|
||||
- Then list any other labwc headers in alphetical order, using quotation
|
||||
- Then list any other labwc headers in alphabetical order, using quotation
|
||||
marks and relative to the `include/` folder. Subfolders below `include/`,
|
||||
such as `common/`, should be specified even when including one header
|
||||
from another in the same folder (for example, `#include "common/buf.h"`
|
||||
|
|
@ -388,11 +388,11 @@ This first line should:
|
|||
- In most cases be prefixed with "area: " where area refers to a filename
|
||||
or identifier for the general area of the code being modified.
|
||||
- Not capitalize the first word following the "area: " prefix, unless
|
||||
it's a name, acronym or similar.
|
||||
it's a name, acronym, or similar.
|
||||
- Skip the full stop
|
||||
|
||||
And please wrap the commit message at max 74 characters, otherwise `git log`
|
||||
and similar look so weird. URLs and other references are exempt.
|
||||
and similar look very weird. URLs and other references are exempt.
|
||||
|
||||
# Unit Tests
|
||||
|
||||
|
|
@ -404,9 +404,9 @@ In the bigger scheme of validating that the compositor meets users' needs, unit
|
|||
tests do not contribute a great deal. However, they have a role to play in
|
||||
providing some verification that stand-alone functions behave as expected.
|
||||
|
||||
On this project, writing unit-tests is not compulsory nor do we measure
|
||||
On this project, writing unit-tests is not compulsory, nor do we measure
|
||||
coverage. The inclusion of the t/ directory does not signify a move towards
|
||||
test-driven development. We intend to use unit tests sparingly and only when
|
||||
test-driven development. We intend to use unit tests sparingly, and only when
|
||||
devs find them useful.
|
||||
|
||||
## Usage
|
||||
|
|
@ -432,17 +432,17 @@ and use the web interface. Adding new languages should work, otherwise the
|
|||
administrators can be contacted. Suggestions for improving existing translations
|
||||
can be added without account.
|
||||
|
||||
### Github Pull Request
|
||||
### GitHub Pull Request
|
||||
|
||||
Translators can add their `MY_LOCALE.po` files to the `po` directory
|
||||
based on `po/labwc.pot` and issue a pull request. To do this they can
|
||||
based on `po/labwc.pot`, and issue a pull request. To do this they can
|
||||
generate their `MY_LOCALE.po` file in a few steps:
|
||||
|
||||
1. Edit the `po/LINGUAS` file to add their locale code in English
|
||||
alphabetical order to the field of locale codes.
|
||||
2. Copy the `po/labwc.pot` to `po/MY_LOCALE.po`
|
||||
3. Edit the newly generated `MY_LOCALE.po` file with some of their
|
||||
contact and locale details in the header of the file then add the
|
||||
contact and locale details in the header of the file. Then, add the
|
||||
translation strings under each English string.
|
||||
|
||||
[See this tutorial for further guidance](https://www.labri.fr/perso/fleury/posts/programming/a-quick-gettext-tutorial.html)
|
||||
|
|
@ -483,13 +483,13 @@ follow the steps to be taken:
|
|||
2. Update `NEWS.md` with the release details and run
|
||||
`git commit -m 'NEWS.md: update notes for X.Y.Z'`
|
||||
Note: If new dependencies are needed, make this clear.
|
||||
3. In `meson.build` update the version and (if required) the wlroots
|
||||
3. In `meson.build`, update the version, and (if required) the wlroots
|
||||
dependency version. Then run `git commit -m 'build: bump version to X.Y.Z'`
|
||||
4. Run `git tag -a X.Y.Z`. The first line of the commit message should be
|
||||
"labwc X.Y.Z" and the body should be the `NEWS.md` additions removing
|
||||
hash characters (#) from the headings as these will otherwise be
|
||||
ignored by git.
|
||||
5. On github, create a 'Release' as some distros use this as a trigger. Set it
|
||||
5. On GitHub, create a 'Release' as some distros use this as a trigger. Set it
|
||||
as 'latest release'.
|
||||
|
||||
[scope document]: https://github.com/labwc/labwc-scope#readme
|
||||
|
|
@ -510,4 +510,3 @@ follow the steps to be taken:
|
|||
different memory pools (and new/delete call constructors and
|
||||
destructors)."
|
||||
See: https://docs.gtk.org/glib/memory.html
|
||||
|
||||
|
|
|
|||
32
NEWS.md
32
NEWS.md
|
|
@ -9,7 +9,7 @@ The format is based on [Keep a Changelog]
|
|||
|
||||
| Date | All Changes | wlroots version | lines-of-code |
|
||||
|------------|---------------|-----------------|---------------|
|
||||
| 2025-08-25 | [unreleased] | 0.19.0 | |
|
||||
| 2025-09-15 | [unreleased] | 0.19.0 | 28686 |
|
||||
| 2025-08-02 | [0.9.1] | 0.19.0 | 28605 |
|
||||
| 2025-07-11 | [0.9.0] | 0.19.0 | 28586 |
|
||||
| 2025-05-02 | [0.8.4] | 0.18.2 | 27679 |
|
||||
|
|
@ -110,6 +110,12 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
|||
|
||||
### Added
|
||||
|
||||
- Support `Border` context for mousebinds as an alias for `Top`...`BRCorner` to
|
||||
make configuration easier. @tokyo4j [#3047]
|
||||
- Add window-switcher mode with thumbnails. This can be enabled with:
|
||||
`<windowSwitcher style="thumbnail">`. @tokyo4j [#2981]
|
||||
- Add `toggle` option to `GoToDesktop` action. This has the effect of going back
|
||||
to the last desktop if already on the target. @RainerKuemmerle [#3024]
|
||||
- Add `<core maximizedDecoration="titlebar|none"/>` to allow hiding titlebar
|
||||
when window is maximized. @CosmicFusion @tokyo4j [#3015]
|
||||
- Use client-send-to-menu as 'Workspace' submenu in built-in client-menu
|
||||
|
|
@ -141,6 +147,10 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
|||
|
||||
### Fixed
|
||||
|
||||
- Restore initially-maximized window position after unplug/plug @tokyo4j [#3042]
|
||||
- Fix large client-side icon not being loaded when the rendered icon size is
|
||||
larger than icon sizes from the client. @tokyo4j [#3033]
|
||||
- Improve debug logging for configuring input devices @jlindgren90 [#3028]
|
||||
- Fix false positives when matching desktop entries @datMaffin [#3004]
|
||||
- Prevent accidental downcasting of scale in scaled-icon-buffer to avoid blurry
|
||||
icons on non-integer scales and a cairo assert when using a output scale < 1.
|
||||
|
|
@ -152,6 +162,16 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
|||
|
||||
### Changed
|
||||
|
||||
- `Focus` and `Raise` on window border press because it is probably what most
|
||||
people expect and it makes the behavior consistent with that of Openbox.
|
||||
@johanmalm [#3039] [#3049]
|
||||
- On interactive resize, only un-maximize the axis/axes that are being resized.
|
||||
@jlindgren90 [#3043]
|
||||
- Change theme setting `osd.window-switcher.*` to
|
||||
`osd.window-switcher.style-classic.*`. Backward compatibility is preserved.
|
||||
@tokyo4j [#2981]
|
||||
- In client-list menu, add brackets around the titles of any minimised windows
|
||||
@davidphilipbarr [#3002]
|
||||
- Respect client-initiated window resize of non-maximized axis, for example
|
||||
remember the width of vertically-maximized window resizing itself
|
||||
horizontally. @jlindgren90 [#3020]
|
||||
|
|
@ -2763,10 +2783,20 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
[#2971]: https://github.com/labwc/labwc/pull/2971
|
||||
[#2972]: https://github.com/labwc/labwc/pull/2972
|
||||
[#2976]: https://github.com/labwc/labwc/pull/2976
|
||||
[#2981]: https://github.com/labwc/labwc/pull/2981
|
||||
[#2994]: https://github.com/labwc/labwc/pull/2994
|
||||
[#2995]: https://github.com/labwc/labwc/pull/2995
|
||||
[#2998]: https://github.com/labwc/labwc/pull/2998
|
||||
[#3002]: https://github.com/labwc/labwc/pull/3002
|
||||
[#3004]: https://github.com/labwc/labwc/pull/3004
|
||||
[#3011]: https://github.com/labwc/labwc/pull/3011
|
||||
[#3015]: https://github.com/labwc/labwc/pull/3015
|
||||
[#3020]: https://github.com/labwc/labwc/pull/3020
|
||||
[#3024]: https://github.com/labwc/labwc/pull/3024
|
||||
[#3028]: https://github.com/labwc/labwc/pull/3028
|
||||
[#3033]: https://github.com/labwc/labwc/pull/3033
|
||||
[#3039]: https://github.com/labwc/labwc/pull/3039
|
||||
[#3042]: https://github.com/labwc/labwc/pull/3042
|
||||
[#3043]: https://github.com/labwc/labwc/pull/3043
|
||||
[#3047]: https://github.com/labwc/labwc/pull/3047
|
||||
[#3049]: https://github.com/labwc/labwc/pull/3049
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -101,21 +101,8 @@ spend our effort.
|
|||
|
||||
A lot of emphasis is put on code simplicity when considering features.
|
||||
|
||||
The main development effort is focused on producing a solid foundation for a
|
||||
stacking compositor rather than adding configuration and theming options.
|
||||
|
||||
See [scope] for full details on implemented features.
|
||||
|
||||
High-level summary of items that Labwc supports:
|
||||
|
||||
- [x] Config files (rc.xml, autostart, shutdown, environment, menu.xml)
|
||||
- [x] Theme files and xbm/png/svg icons
|
||||
- [x] Basic desktop and client menus
|
||||
- [x] HiDPI
|
||||
- [x] wlroots protocols such as `output-management`, `layer-shell` and
|
||||
`foreign-toplevel`
|
||||
- [x] Optionally xwayland
|
||||
|
||||
### 1.5 Videos
|
||||
|
||||
| video link | date | duration
|
||||
|
|
@ -249,7 +236,7 @@ Suggested apps to use with Labwc:
|
|||
- Screen shooter: [grim]
|
||||
- Screen recorder: [wf-recorder]
|
||||
- Background image: [swaybg]
|
||||
- Panel: [waybar], [yambar], [lavalauncher], [sfwbar], [xfce4-panel]
|
||||
- Panel: [waybar], [lavalauncher], [sfwbar], [xfce4-panel]
|
||||
- Launchers: [bemenu], [fuzzel], [wofi]
|
||||
- Output managers: [wlopm], [kanshi], [wlr-randr]
|
||||
- Screen locker: [swaylock]
|
||||
|
|
@ -292,7 +279,6 @@ The default window bar menu can be translated on the [weblate platform](https://
|
|||
[wf-recorder]: https://github.com/ammen99/wf-recorder
|
||||
[swaybg]: https://github.com/swaywm/swaybg
|
||||
[waybar]: https://github.com/Alexays/Waybar
|
||||
[yambar]: https://codeberg.org/dnkl/yambar
|
||||
[lavalauncher]: https://sr.ht/~leon_plickat/LavaLauncher
|
||||
[sfwbar]: https://github.com/LBCrion/sfwbar
|
||||
[xfce4-panel]: https://gitlab.xfce.org/xfce/xfce4-panel
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ struct conf {
|
|||
uint32_t details_background;
|
||||
uint32_t background;
|
||||
uint32_t text;
|
||||
uint32_t border;
|
||||
uint32_t button_border;
|
||||
uint32_t border_bottom;
|
||||
|
||||
/* Sizing */
|
||||
|
|
@ -429,7 +429,7 @@ render_button(cairo_t *cairo, struct nag *nag, struct button *button, int *x)
|
|||
button->width = text_width + padding * 2;
|
||||
button->height = text_height + padding * 2;
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->border);
|
||||
cairo_set_source_u32(cairo, nag->conf->button_border);
|
||||
cairo_rectangle(cairo, button->x - border, button->y - border,
|
||||
button->width + border * 2, button->height + border * 2);
|
||||
cairo_fill(cairo);
|
||||
|
|
@ -1255,7 +1255,7 @@ conf_init(struct conf *conf)
|
|||
conf->background = 0x323232FF;
|
||||
conf->text = 0xFFFFFFFF;
|
||||
conf->button_text = 0xFFFFFFFF;
|
||||
conf->border = 0x222222FF;
|
||||
conf->button_border = 0x222222FF;
|
||||
conf->border_bottom = 0x444444FF;
|
||||
conf->bar_border_thickness = 2;
|
||||
conf->message_padding = 8;
|
||||
|
|
@ -1270,7 +1270,7 @@ conf_init(struct conf *conf)
|
|||
conf->background = 0x900000FF;
|
||||
conf->text = 0xFFFFFFFF;
|
||||
conf->button_text = 0xFFFFFFFF;
|
||||
conf->border = 0xD92424FF;
|
||||
conf->button_border = 0xD92424FF;
|
||||
conf->border_bottom = 0x470909FF;
|
||||
}
|
||||
|
||||
|
|
@ -1342,9 +1342,9 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
{
|
||||
enum type_options {
|
||||
TO_COLOR_BACKGROUND = 256,
|
||||
TO_COLOR_BORDER,
|
||||
TO_COLOR_BUTTON_BORDER,
|
||||
TO_COLOR_BORDER_BOTTOM,
|
||||
TO_COLOR_BUTTON,
|
||||
TO_COLOR_BUTTON_BG,
|
||||
TO_COLOR_DETAILS,
|
||||
TO_COLOR_TEXT,
|
||||
TO_COLOR_BUTTON_TEXT,
|
||||
|
|
@ -1370,19 +1370,19 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
{"detailed-button", required_argument, NULL, 'L'},
|
||||
{"message", required_argument, NULL, 'm'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"timeout", no_argument, NULL, 't'},
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
|
||||
{"background", required_argument, NULL, TO_COLOR_BACKGROUND},
|
||||
{"border", required_argument, NULL, TO_COLOR_BORDER},
|
||||
{"border-bottom", required_argument, NULL, TO_COLOR_BORDER_BOTTOM},
|
||||
{"button-background", required_argument, NULL, TO_COLOR_BUTTON},
|
||||
{"text", required_argument, NULL, TO_COLOR_TEXT},
|
||||
{"button-text", required_argument, NULL, TO_COLOR_BUTTON_TEXT},
|
||||
{"background-color", required_argument, NULL, TO_COLOR_BACKGROUND},
|
||||
{"button-border-color", required_argument, NULL, TO_COLOR_BUTTON_BORDER},
|
||||
{"border-bottom-color", required_argument, NULL, TO_COLOR_BORDER_BOTTOM},
|
||||
{"button-background-color", required_argument, NULL, TO_COLOR_BUTTON_BG},
|
||||
{"text-color", required_argument, NULL, TO_COLOR_TEXT},
|
||||
{"button-text-color", required_argument, NULL, TO_COLOR_BUTTON_TEXT},
|
||||
{"border-bottom-size", required_argument, NULL, TO_THICK_BAR_BORDER},
|
||||
{"message-padding", required_argument, NULL, TO_PADDING_MESSAGE},
|
||||
{"details-border-size", required_argument, NULL, TO_THICK_DET_BORDER},
|
||||
{"details-background", required_argument, NULL, TO_COLOR_DETAILS},
|
||||
{"details-background-color", required_argument, NULL, TO_COLOR_DETAILS},
|
||||
{"button-border-size", required_argument, NULL, TO_THICK_BTN_BORDER},
|
||||
{"button-gap", required_argument, NULL, TO_GAP_BTN},
|
||||
{"button-dismiss-gap", required_argument, NULL, TO_GAP_BTN_DISMISS},
|
||||
|
|
@ -1413,21 +1413,23 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
" -v, --version Show the version number and quit.\n"
|
||||
"\n"
|
||||
"The following appearance options can also be given:\n"
|
||||
" --background RRGGBB[AA] Background color.\n"
|
||||
" --border RRGGBB[AA] Border color.\n"
|
||||
" --border-bottom RRGGBB[AA] Bottom border color.\n"
|
||||
" --button-background RRGGBB[AA] Button background color.\n"
|
||||
" --text RRGGBB[AA] Text color.\n"
|
||||
" --button-text RRGGBB[AA] Button text color.\n"
|
||||
" --border-bottom-size size Thickness of the bar border.\n"
|
||||
" --message-padding padding Padding for the message.\n"
|
||||
" --details-border-size size Thickness for the details border.\n"
|
||||
" --details-background RRGGBB[AA] Details background color.\n"
|
||||
" --button-border-size size Thickness for the button border.\n"
|
||||
" --button-gap gap Size of the gap between buttons\n"
|
||||
" --button-dismiss-gap gap Size of the gap for dismiss button.\n"
|
||||
" --button-margin-right margin Margin from dismiss button to edge.\n"
|
||||
" --button-padding padding Padding for the button text.\n";
|
||||
" --background-color RRGGBB[AA] Background color.\n"
|
||||
" --button-border-color RRGGBB[AA] Button border color.\n"
|
||||
" --border-bottom-color RRGGBB[AA] Bottom border color.\n"
|
||||
" --button-background-color RRGGBB[AA]\n"
|
||||
" Button background color.\n"
|
||||
" --text-color RRGGBB[AA] Text color.\n"
|
||||
" --button-text-color RRGGBB[AA] Button text color.\n"
|
||||
" --border-bottom-size size Thickness of the bar border.\n"
|
||||
" --message-padding padding Padding for the message.\n"
|
||||
" --details-border-size size Thickness for the details border.\n"
|
||||
" --details-background-color RRGGBB[AA]\n"
|
||||
" Details background color.\n"
|
||||
" --button-border-size size Thickness for the button border.\n"
|
||||
" --button-gap gap Size of the gap between buttons\n"
|
||||
" --button-dismiss-gap gap Size of the gap for dismiss button.\n"
|
||||
" --button-margin-right margin Margin from dismiss button to edge.\n"
|
||||
" --button-padding padding Padding for the button text.\n";
|
||||
|
||||
optind = 1;
|
||||
while (1) {
|
||||
|
|
@ -1522,8 +1524,8 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
fprintf(stderr, "Invalid background color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_BORDER: /* Border color */
|
||||
if (!parse_color(optarg, &conf->border)) {
|
||||
case TO_COLOR_BUTTON_BORDER: /* Border color */
|
||||
if (!parse_color(optarg, &conf->button_border)) {
|
||||
fprintf(stderr, "Invalid border color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1532,7 +1534,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
fprintf(stderr, "Invalid border bottom color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_BUTTON: /* Button background color */
|
||||
case TO_COLOR_BUTTON_BG: /* Button background color */
|
||||
if (!parse_color(optarg, &conf->button_background)) {
|
||||
fprintf(stderr, "Invalid button background color: %s\n", optarg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,22 +62,22 @@ _labnag_ [options...]
|
|||
|
||||
# APPEARANCE OPTIONS
|
||||
|
||||
*--background* <RRGGBB[AA]>
|
||||
*--background-color* <RRGGBB[AA]>
|
||||
Set the color of the background.
|
||||
|
||||
*--border* <RRGGBB[AA]>
|
||||
Set the color of the border.
|
||||
*--button-border-color* <RRGGBB[AA]>
|
||||
Set the color of the button border.
|
||||
|
||||
*--border-bottom* <RRGGBB[AA]>
|
||||
*--border-bottom-color* <RRGGBB[AA]>
|
||||
Set the color of the bottom border.
|
||||
|
||||
*--button-background* <RRGGBB[AA]>
|
||||
*--button-background-color* <RRGGBB[AA]>
|
||||
Set the color for the background for buttons.
|
||||
|
||||
*--text* <RRGGBB[AA]>
|
||||
*--text-color* <RRGGBB[AA]>
|
||||
Set the text color.
|
||||
|
||||
*--button-text* <RRGGBB[AA]>
|
||||
*--button-text-color* <RRGGBB[AA]>
|
||||
Set the button text color.
|
||||
|
||||
*--border-bottom-size* <size>
|
||||
|
|
@ -86,7 +86,7 @@ _labnag_ [options...]
|
|||
*--message-padding* <padding>
|
||||
Set the padding for the message.
|
||||
|
||||
*--details-background* <RRGGBB[AA]>
|
||||
*--details-background-color* <RRGGBB[AA]>
|
||||
Set the color for the background for details.
|
||||
|
||||
*--details-border-size* <size>
|
||||
|
|
@ -126,11 +126,11 @@ labnag \\
|
|||
-Z "Hibernate" "systemctl hibernate"\\
|
||||
-Z " Suspend " "systemctl suspend"\\
|
||||
-Z " Cancel "\\
|
||||
--background 00ffff\\
|
||||
--button-background 00ffff\\
|
||||
--border 00ccccaa\\
|
||||
--text 000000\\
|
||||
--button-text 000000\\
|
||||
--background-color 00ffff\\
|
||||
--button-background-color 00ffff\\
|
||||
--button-border-color 00ccccaa\\
|
||||
--text-color 000000\\
|
||||
--button-text-color 000000\\
|
||||
--button-gap 8\\
|
||||
--button-margin-right 0\\
|
||||
--button-padding 5\\
|
||||
|
|
|
|||
|
|
@ -92,11 +92,18 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
Move window relative to its current position. Positive value of x moves
|
||||
it right, negative left. Positive value of y moves it down, negative up.
|
||||
|
||||
*<action name="ToggleSnapToEdge" direction="value" />*++
|
||||
*<action name="SnapToEdge" direction="value" />*
|
||||
Resize window to fill half the output in the given direction. Supports
|
||||
directions "left", "up", "right", "down", "up-left", "up-right", "down-left",
|
||||
"down-right" and "center".
|
||||
*<action name="ToggleSnapToEdge" direction="value" combine="value" />*++
|
||||
*<action name="SnapToEdge" direction="value" combine="value" />*
|
||||
Resize window to fill half or quarter the output in the given direction.
|
||||
|
||||
*direction* [up|down|left|right|up-left|up-right|down-left|down-right|center]
|
||||
Direction in which to snap the window.
|
||||
|
||||
*combine* [yes|no]
|
||||
Allows to snap a window to an output corner by combining two
|
||||
directions. For example, snapping a window to *right* and then
|
||||
to *up* places it in the *up-right* quarter of the output.
|
||||
Default is no.
|
||||
|
||||
ToggleSnapToEdge additionally toggles the active window between
|
||||
tiled to the given direction and its untiled position.
|
||||
|
|
@ -479,7 +486,7 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
|
|||
The "left" , "right", "left-occupied" and
|
||||
"right-occupied" directions will not wrap.
|
||||
|
||||
*tiled* [up|right|down|left|top-left|top-right|down-left|down-right|center|any]
|
||||
*tiled* [up|right|down|left|up-left|up-right|down-left|down-right|center|any]
|
||||
Whether the client is tiled (snapped) along the the
|
||||
indicated screen edge.
|
||||
|
||||
|
|
|
|||
|
|
@ -179,6 +179,7 @@ this is for compatibility with Openbox.
|
|||
<reuseOutputMode>no</reuseOutputMode>
|
||||
<xwaylandPersistence>no</xwaylandPersistence>
|
||||
<primarySelection>yes</primarySelection>
|
||||
<promptCommand>[see details below]</promptCommand>
|
||||
</core>
|
||||
```
|
||||
|
||||
|
|
@ -228,6 +229,23 @@ this is for compatibility with Openbox.
|
|||
unless an external tool such as `wlr-randr` or `kanshi` is used to
|
||||
manage outputs.
|
||||
|
||||
The reason for the existance of this option is that after losing signal
|
||||
from the PC (e.g. by `wlopm -off`), some monitors do an input detection
|
||||
that makes it appear (from the PC side) to disconnect and reconnect a
|
||||
few seconds later, causing the monitor to turn back on again (as labwc
|
||||
auto-enables newly connected outputs by default).
|
||||
|
||||
An example usage pattern to avoid the above behavior looks as follows:
|
||||
- Set *<core><autoEnableOutputs>* to *no*
|
||||
- Run kanshi (e.g. from autostart) and rely on it to enable new outputs
|
||||
- Have swayidle kill and restart kanshi when entering powersave as
|
||||
follows:
|
||||
|
||||
```
|
||||
swayidle -w timeout 600 \\
|
||||
'pkill kanshi ; wlopm --off \*' resume 'kanshi & wlopm --on \*'
|
||||
```
|
||||
|
||||
*<core><reuseOutputMode>* [yes|no]
|
||||
Try to re-use the existing output mode (resolution / refresh rate).
|
||||
This may prevent unnecessary screenblank delays when starting labwc
|
||||
|
|
@ -248,6 +266,53 @@ this is for compatibility with Openbox.
|
|||
up/down) in Chromium and electron based clients without inadvertantly
|
||||
pasting the primary clipboard. Default is yes.
|
||||
|
||||
*<core><promptCommand>*
|
||||
Set command to be invoked for an action prompt (*<action><prompt>*)
|
||||
|
||||
The following conversion specifiers are supported:
|
||||
- *%m*: the *<prompt>* message option
|
||||
- *%n*: "No" (in local language if translation is available)
|
||||
- *%y*: "Yes" (in local language if translation is available)
|
||||
- *%b*: osd.bg.color
|
||||
- *%t*: osd.label.text.color
|
||||
|
||||
The default prompt command is:
|
||||
|
||||
```
|
||||
labnag \\
|
||||
--message '%m' \\
|
||||
--button-dismiss '%n' \\
|
||||
--button-dismiss '%y' \\
|
||||
--background-color '%b' \\
|
||||
--text-color '%t' \\
|
||||
--button-border-color '%t' \\
|
||||
--border-bottom-color '%t' \\
|
||||
--button-background-color '%b' \\
|
||||
--button-text-color '%t' \\
|
||||
--border-bottom-size 1 \\
|
||||
--button-border-size 3 \\
|
||||
--timeout 0
|
||||
```
|
||||
|
||||
Example 1: The prompt can be configured to use a different dialog client
|
||||
|
||||
```
|
||||
<core>
|
||||
<promptCommand>zenity --question --text="%m"</promptCommand>
|
||||
</core>
|
||||
```
|
||||
|
||||
Example 2: A more complex zenity command could be used:
|
||||
|
||||
```
|
||||
zenity \\
|
||||
--question \\
|
||||
--title="" \\
|
||||
--text="%m" \\
|
||||
--ok-label="%y" \\
|
||||
--cancel-label="%n"
|
||||
```
|
||||
|
||||
## PLACEMENT
|
||||
|
||||
```
|
||||
|
|
@ -710,7 +775,7 @@ extending outward from the snapped edge.
|
|||
W-Return - lab-sensible-terminal
|
||||
A-F4 - close window
|
||||
W-a - toggle maximize
|
||||
W-<arrow> - resize window to fill half the output
|
||||
W-<arrow> - resize window to fill half or quarter of the output
|
||||
A-Space - show window menu
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
<reuseOutputMode>no</reuseOutputMode>
|
||||
<xwaylandPersistence>no</xwaylandPersistence>
|
||||
<primarySelection>yes</primarySelection>
|
||||
<!--
|
||||
# See labwc-config(5) for details
|
||||
<promptCommand></promptCommand>
|
||||
-->
|
||||
</core>
|
||||
|
||||
<placement>
|
||||
|
|
@ -271,16 +275,16 @@
|
|||
<action name="ToggleMaximize" />
|
||||
</keybind>
|
||||
<keybind key="W-Left">
|
||||
<action name="SnapToEdge" direction="left" />
|
||||
<action name="SnapToEdge" direction="left" combine="yes" />
|
||||
</keybind>
|
||||
<keybind key="W-Right">
|
||||
<action name="SnapToEdge" direction="right" />
|
||||
<action name="SnapToEdge" direction="right" combine="yes" />
|
||||
</keybind>
|
||||
<keybind key="W-Up">
|
||||
<action name="SnapToEdge" direction="up" />
|
||||
<action name="SnapToEdge" direction="up" combine="yes" />
|
||||
</keybind>
|
||||
<keybind key="W-Down">
|
||||
<action name="SnapToEdge" direction="down" />
|
||||
<action name="SnapToEdge" direction="down" combine="yes" />
|
||||
</keybind>
|
||||
<keybind key="A-Space">
|
||||
<action name="ShowMenu" menu="client-menu" atCursor="no" />
|
||||
|
|
|
|||
12
include/action-prompt-command.h
Normal file
12
include/action-prompt-command.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_ACTION_PROMPT_COMMAND_H
|
||||
#define LABWC_ACTION_PROMPT_COMMAND_H
|
||||
|
||||
struct buf;
|
||||
struct action;
|
||||
struct theme;
|
||||
|
||||
void action_prompt_command(struct buf *buf, const char *format,
|
||||
struct action *action, struct theme *theme);
|
||||
|
||||
#endif /* LABWC_ACTION_PROMPT_COMMAND_H */
|
||||
|
|
@ -23,6 +23,8 @@ struct action {
|
|||
|
||||
struct action *action_create(const char *action_name);
|
||||
|
||||
const char *action_get_str(struct action *action, const char *key,
|
||||
const char *default_value);
|
||||
bool action_is_valid(struct action *action);
|
||||
bool action_is_show_menu(struct action *action);
|
||||
|
||||
|
|
@ -48,6 +50,7 @@ bool actions_contain_toggle_keybinds(struct wl_list *action_list);
|
|||
void actions_run(struct view *activator, struct server *server,
|
||||
struct wl_list *actions, struct cursor_context *ctx);
|
||||
|
||||
void action_prompts_destroy(void);
|
||||
bool action_check_prompt_result(pid_t pid, int exit_code);
|
||||
|
||||
void action_free(struct action *action);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ void box_union(struct wlr_box *box_dest, struct wlr_box *box_a,
|
|||
* The returned x & y coordinates are the centered content position
|
||||
* relative to the top-left corner of the bounding box.
|
||||
*/
|
||||
struct wlr_box box_fit_within(int width, int height, struct wlr_box *bounding_box);
|
||||
struct wlr_box box_fit_within(int width, int height, struct wlr_box *bound);
|
||||
|
||||
struct wlr_fbox box_to_fbox(struct wlr_box *box);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,17 @@ void buf_expand_shell_variables(struct buf *s);
|
|||
*/
|
||||
void buf_add_fmt(struct buf *s, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* buf_add_hex_color - add rgb color as hex string to C string buffer
|
||||
* @s: buffer
|
||||
* @color: rgb color to be added
|
||||
*
|
||||
* For example:
|
||||
* - With the input 'red' (defined as red[4] = { 1.0f, 0.0f, 0.0f, 1.0f}) the
|
||||
* string "#ff0000ff" will be written to the buffer.
|
||||
*/
|
||||
void buf_add_hex_color(struct buf *s, float color[4]);
|
||||
|
||||
/**
|
||||
* buf_add - add data to C string buffer
|
||||
* @s: buffer
|
||||
|
|
@ -60,9 +71,9 @@ void buf_add(struct buf *s, const char *data);
|
|||
/**
|
||||
* buf_add_char - add single char to C string buffer
|
||||
* @s: buffer
|
||||
* @data: char to be added
|
||||
* @ch: char to be added
|
||||
*/
|
||||
void buf_add_char(struct buf *s, char data);
|
||||
void buf_add_char(struct buf *s, char ch);
|
||||
|
||||
/**
|
||||
* buf_clear - clear the buffer, internal allocations are preserved
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ struct wlr_scene_node *lab_wlr_scene_get_prev_node(struct wlr_scene_node *node);
|
|||
|
||||
/* A variant of wlr_scene_output_commit() that respects wlr_output->pending */
|
||||
bool lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||
struct wlr_output_state *output_state);
|
||||
struct wlr_output_state *state);
|
||||
|
||||
#endif /* LABWC_SCENE_HELPERS_H */
|
||||
|
|
|
|||
|
|
@ -15,15 +15,6 @@ bool string_null_or_empty(const char *s);
|
|||
*/
|
||||
bool str_space_only(const char *s);
|
||||
|
||||
/**
|
||||
* trim_last_field() - Trim last field of string splitting on provided delim
|
||||
* @buf: string to trim
|
||||
* @delim: delimitator
|
||||
*
|
||||
* Example: With delim='_' and buf="foo_bar_baz" the return value is "foo_bar"
|
||||
*/
|
||||
void trim_last_field(char *buf, char delim);
|
||||
|
||||
/**
|
||||
* string_strip - strip white space left and right
|
||||
* Note: this function does a left skip, so the returning pointer cannot be
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@
|
|||
* </action>
|
||||
* </keybind>
|
||||
*/
|
||||
void lab_xml_expand_dotted_attributes(xmlNode *root);
|
||||
void lab_xml_expand_dotted_attributes(xmlNode *parent);
|
||||
|
||||
/* Returns true if the node only contains a string or is empty */
|
||||
bool lab_xml_node_is_leaf(xmlNode *node);
|
||||
|
||||
bool lab_xml_get_node(xmlNode *node, const char *key, xmlNode **dst_node);
|
||||
bool lab_xml_get_string(xmlNode *node, const char *key, char *s, size_t len);
|
||||
bool lab_xml_get_int(xmlNode *node, const char *key, int *i);
|
||||
bool lab_xml_get_bool(xmlNode *node, const char *key, bool *b);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ static struct key_combos {
|
|||
.name = "direction",
|
||||
.value = "left",
|
||||
},
|
||||
.attributes[1] = {
|
||||
.name = "combine",
|
||||
.value = "yes",
|
||||
},
|
||||
}, {
|
||||
.binding = "W-Right",
|
||||
.action = "SnapToEdge",
|
||||
|
|
@ -42,6 +46,10 @@ static struct key_combos {
|
|||
.name = "direction",
|
||||
.value = "right",
|
||||
},
|
||||
.attributes[1] = {
|
||||
.name = "combine",
|
||||
.value = "yes",
|
||||
},
|
||||
}, {
|
||||
.binding = "W-Up",
|
||||
.action = "SnapToEdge",
|
||||
|
|
@ -49,6 +57,10 @@ static struct key_combos {
|
|||
.name = "direction",
|
||||
.value = "up",
|
||||
},
|
||||
.attributes[1] = {
|
||||
.name = "combine",
|
||||
.value = "yes",
|
||||
},
|
||||
}, {
|
||||
.binding = "W-Down",
|
||||
.action = "SnapToEdge",
|
||||
|
|
@ -56,6 +68,10 @@ static struct key_combos {
|
|||
.name = "direction",
|
||||
.value = "down",
|
||||
},
|
||||
.attributes[1] = {
|
||||
.name = "combine",
|
||||
.value = "yes",
|
||||
},
|
||||
}, {
|
||||
.binding = "A-Space",
|
||||
.action = "ShowMenu",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#define BUTTON_MAP_MAX 16
|
||||
|
||||
/* max of one button of each type (no repeats) */
|
||||
#define TITLE_BUTTONS_MAX ((LAB_NODE_BUTTON_LAST + 1) - LAB_NODE_BUTTON_FIRST)
|
||||
|
||||
enum adaptive_sync_mode {
|
||||
LAB_ADAPTIVE_SYNC_DISABLED,
|
||||
LAB_ADAPTIVE_SYNC_ENABLED,
|
||||
|
|
@ -48,11 +51,6 @@ struct button_map_entry {
|
|||
uint32_t to;
|
||||
};
|
||||
|
||||
struct title_button {
|
||||
enum lab_node_type type;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct usable_area_override {
|
||||
struct border margin;
|
||||
char *output;
|
||||
|
|
@ -73,9 +71,12 @@ struct rcxml {
|
|||
enum tearing_mode allow_tearing;
|
||||
bool auto_enable_outputs;
|
||||
bool reuse_output_mode;
|
||||
enum lab_placement_policy placement_policy;
|
||||
bool xwayland_persistence;
|
||||
bool primary_selection;
|
||||
char *prompt_command;
|
||||
|
||||
/* placement */
|
||||
enum lab_placement_policy placement_policy;
|
||||
int placement_cascade_offset_x;
|
||||
int placement_cascade_offset_y;
|
||||
|
||||
|
|
@ -88,8 +89,12 @@ struct rcxml {
|
|||
char *theme_name;
|
||||
char *icon_theme_name;
|
||||
char *fallback_app_icon_name;
|
||||
struct wl_list title_buttons_left;
|
||||
struct wl_list title_buttons_right;
|
||||
|
||||
enum lab_node_type title_buttons_left[TITLE_BUTTONS_MAX];
|
||||
int nr_title_buttons_left;
|
||||
enum lab_node_type title_buttons_right[TITLE_BUTTONS_MAX];
|
||||
int nr_title_buttons_right;
|
||||
|
||||
int corner_radius;
|
||||
bool show_title;
|
||||
bool title_layout_loaded;
|
||||
|
|
@ -195,7 +200,6 @@ struct rcxml {
|
|||
|
||||
extern struct rcxml rc;
|
||||
|
||||
void rcxml_parse_xml(struct buf *b);
|
||||
void rcxml_read(const char *filename);
|
||||
void rcxml_finish(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,5 @@ void key_state_store_pressed_key_as_bound(uint32_t keycode);
|
|||
bool key_state_corresponding_press_event_was_bound(uint32_t keycode);
|
||||
void key_state_bound_key_remove(uint32_t keycode);
|
||||
int key_state_nr_bound_keys(void);
|
||||
int key_state_nr_pressed_keys(void);
|
||||
|
||||
#endif /* LABWC_KEY_STATE_H */
|
||||
|
|
|
|||
|
|
@ -7,13 +7,6 @@
|
|||
#include "common/set.h"
|
||||
#include "input/cursor.h"
|
||||
#include "overlay.h"
|
||||
#if HAVE_NLS
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#define _ gettext
|
||||
#else
|
||||
#define _(s) (s)
|
||||
#endif
|
||||
|
||||
#define XCURSOR_DEFAULT "left_ptr"
|
||||
#define XCURSOR_SIZE 24
|
||||
|
|
@ -366,7 +359,6 @@ void desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|||
|
||||
void desktop_arrange_all_views(struct server *server);
|
||||
void desktop_focus_output(struct output *output);
|
||||
struct view *desktop_topmost_focusable_view(struct server *server);
|
||||
|
||||
/**
|
||||
* Toggles the (output local) visibility of the layershell top layer
|
||||
|
|
|
|||
|
|
@ -100,18 +100,6 @@ void menu_open_root(struct menu *menu, int x, int y);
|
|||
*/
|
||||
void menu_process_cursor_motion(struct wlr_scene_node *node);
|
||||
|
||||
/**
|
||||
* menu_call_actions - call actions associated with a menu node
|
||||
*
|
||||
* If menuitem connected to @node does not just open a submenu:
|
||||
* - associated actions will be called
|
||||
* - server->menu_current will be closed
|
||||
* - server->menu_current will be set to NULL
|
||||
*
|
||||
* Returns true if actions have actually been executed
|
||||
*/
|
||||
bool menu_call_actions(struct wlr_scene_node *node);
|
||||
|
||||
/**
|
||||
* menu_close_root- close root menu
|
||||
*
|
||||
|
|
|
|||
|
|
@ -45,13 +45,6 @@ struct view *node_view_from_node(struct wlr_scene_node *wlr_scene_node);
|
|||
struct lab_layer_surface *node_layer_surface_from_node(
|
||||
struct wlr_scene_node *wlr_scene_node);
|
||||
|
||||
/**
|
||||
* node_layer_popup_from_node - return lab_layer_popup struct from node
|
||||
* @wlr_scene_node: wlr_scene_node from which to return data
|
||||
*/
|
||||
struct lab_layer_popup *node_layer_popup_from_node(
|
||||
struct wlr_scene_node *wlr_scene_node);
|
||||
|
||||
/**
|
||||
* node_menuitem_from_node - return menuitem struct from node
|
||||
* @wlr_scene_node: wlr_scene_node from which to return data
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ struct output {
|
|||
|
||||
void output_init(struct server *server);
|
||||
void output_finish(struct server *server);
|
||||
void output_manager_init(struct server *server);
|
||||
struct output *output_from_wlr_output(struct server *server,
|
||||
struct wlr_output *wlr_output);
|
||||
struct output *output_from_name(struct server *server, const char *name);
|
||||
|
|
@ -70,11 +69,4 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
|||
void *data);
|
||||
void output_enable_adaptive_sync(struct output *output, bool enabled);
|
||||
|
||||
/**
|
||||
* output_max_scale() - get maximum scale factor of all usable outputs.
|
||||
* Used when loading/rendering resources (e.g. icons) that may be
|
||||
* displayed on any output.
|
||||
*/
|
||||
float output_max_scale(struct server *server);
|
||||
|
||||
#endif // LABWC_OUTPUT_H
|
||||
|
|
|
|||
|
|
@ -73,12 +73,4 @@ void scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text
|
|||
int max_width, struct font *font, const float *color,
|
||||
const float *bg_color);
|
||||
|
||||
/**
|
||||
* Update the max width of an existing auto scaling font buffer
|
||||
* and force a new render.
|
||||
*
|
||||
* No steps are taken to detect if its actually required to render a new buffer.
|
||||
*/
|
||||
void scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width);
|
||||
|
||||
#endif /* LABWC_SCALED_FONT_BUFFER_H */
|
||||
|
|
|
|||
14
include/translate.h
Normal file
14
include/translate.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_TRANSLATE_H
|
||||
#define LABWC_TRANSLATE_H
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_NLS
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#define _ gettext
|
||||
#else
|
||||
#define _(s) (s)
|
||||
#endif
|
||||
|
||||
#endif /* LABWC_TRANSLATE_H */
|
||||
|
|
@ -425,7 +425,6 @@ void view_array_append(struct server *server, struct wl_array *views,
|
|||
enum lab_view_criteria criteria);
|
||||
|
||||
enum view_wants_focus view_wants_focus(struct view *view);
|
||||
bool view_contains_window_type(struct view *view, enum lab_window_type window_type);
|
||||
|
||||
/* If view is NULL, the size of SSD is not considered */
|
||||
struct wlr_box view_get_edge_snap_box(struct view *view, struct output *output,
|
||||
|
|
@ -548,14 +547,12 @@ void view_move_to_edge(struct view *view, enum lab_edge direction, bool snap_to_
|
|||
void view_grow_to_edge(struct view *view, enum lab_edge direction);
|
||||
void view_shrink_to_edge(struct view *view, enum lab_edge direction);
|
||||
void view_snap_to_edge(struct view *view, enum lab_edge direction,
|
||||
bool across_outputs, bool store_natural_geometry);
|
||||
bool across_outputs, bool combine, bool store_natural_geometry);
|
||||
void view_snap_to_region(struct view *view, struct region *region, bool store_natural_geometry);
|
||||
void view_move_to_output(struct view *view, struct output *output);
|
||||
|
||||
void view_move_to_front(struct view *view);
|
||||
void view_move_to_back(struct view *view);
|
||||
struct view *view_get_root(struct view *view);
|
||||
void view_append_children(struct view *view, struct wl_array *children);
|
||||
|
||||
/**
|
||||
* view_get_modal_dialog() - returns any modal dialog found among this
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ void xwayland_unmanaged_create(struct server *server,
|
|||
void xwayland_view_create(struct server *server,
|
||||
struct wlr_xwayland_surface *xsurface, bool mapped);
|
||||
|
||||
struct wlr_xwayland_surface *xwayland_surface_from_view(struct view *view);
|
||||
|
||||
void xwayland_server_init(struct server *server,
|
||||
struct wlr_compositor *compositor);
|
||||
void xwayland_server_finish(struct server *server);
|
||||
|
|
|
|||
14
meson.build
14
meson.build
|
|
@ -51,9 +51,9 @@ endif
|
|||
add_project_arguments('-DLABWC_VERSION=@0@'.format(version), language: 'c')
|
||||
|
||||
wlroots = dependency(
|
||||
'wlroots-0.19',
|
||||
'wlroots-0.20',
|
||||
default_options: ['default_library=static', 'examples=false'],
|
||||
version: ['>=0.19.0', '<0.20.0'],
|
||||
version: ['>=0.20.0', '<0.21.0'],
|
||||
)
|
||||
|
||||
wlroots_has_xwayland = wlroots.get_variable('have_xwayland') == 'true'
|
||||
|
|
@ -134,6 +134,15 @@ if get_option('static_analyzer').enabled()
|
|||
add_project_arguments(['-fanalyzer'], language: 'c')
|
||||
endif
|
||||
|
||||
link_args = []
|
||||
if get_option('sections').enabled()
|
||||
add_project_arguments(['-ffunction-sections'], language: 'c')
|
||||
link_args += [
|
||||
'-Wl,--gc-sections',
|
||||
'-Wl,--print-gc-sections',
|
||||
]
|
||||
endif
|
||||
|
||||
msgfmt = find_program('msgfmt', required: get_option('nls'))
|
||||
if msgfmt.found()
|
||||
source_root = meson.current_source_dir()
|
||||
|
|
@ -193,6 +202,7 @@ executable(
|
|||
include_directories: [labwc_inc],
|
||||
dependencies: labwc_deps,
|
||||
install: true,
|
||||
link_args: link_args,
|
||||
)
|
||||
|
||||
install_data('data/labwc.desktop', install_dir: get_option('datadir') / 'wayland-sessions')
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@ option('icon', type: 'feature', value: 'enabled', description: 'Enable window ic
|
|||
option('nls', type: 'feature', value: 'auto', description: 'Enable native language support')
|
||||
option('static_analyzer', type: 'feature', value: 'disabled', description: 'Run gcc static analyzer')
|
||||
option('test', type: 'feature', value: 'disabled', description: 'Run tests')
|
||||
option('sections', type: 'feature', value: 'disabled', description: 'Show unused functions')
|
||||
|
|
|
|||
108
src/action-prompt-command.c
Normal file
108
src/action-prompt-command.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "action-prompt-command.h"
|
||||
#include <stdio.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "action.h"
|
||||
#include "common/buf.h"
|
||||
#include "theme.h"
|
||||
#include "translate.h"
|
||||
|
||||
enum {
|
||||
LAB_PROMPT_NONE = 0,
|
||||
LAB_PROMPT_MESSAGE,
|
||||
LAB_PROMPT_NO,
|
||||
LAB_PROMPT_YES,
|
||||
LAB_PROMPT_BG_COL,
|
||||
LAB_PROMPT_TEXT_COL,
|
||||
|
||||
LAB_PROMPT_COUNT
|
||||
};
|
||||
|
||||
typedef void field_conversion_type(struct buf *buf, struct action *action,
|
||||
struct theme *theme);
|
||||
|
||||
struct field_converter {
|
||||
const char fmt_char;
|
||||
field_conversion_type *fn;
|
||||
};
|
||||
|
||||
/* %m */
|
||||
static void
|
||||
set_message(struct buf *buf, struct action *action, struct theme *theme)
|
||||
{
|
||||
buf_add(buf, action_get_str(action, "message.prompt", "Choose wisely"));
|
||||
}
|
||||
|
||||
/* %n */
|
||||
static void
|
||||
set_no(struct buf *buf, struct action *action, struct theme *theme)
|
||||
{
|
||||
buf_add(buf, _("No"));
|
||||
}
|
||||
|
||||
/* %y */
|
||||
static void
|
||||
set_yes(struct buf *buf, struct action *action, struct theme *theme)
|
||||
{
|
||||
buf_add(buf, _("Yes"));
|
||||
}
|
||||
|
||||
/* %b */
|
||||
static void
|
||||
set_bg_col(struct buf *buf, struct action *action, struct theme *theme)
|
||||
{
|
||||
buf_add_hex_color(buf, theme->osd_bg_color);
|
||||
}
|
||||
|
||||
/* %t */
|
||||
static void
|
||||
set_text_col(struct buf *buf, struct action *action, struct theme *theme)
|
||||
{
|
||||
buf_add_hex_color(buf, theme->osd_label_text_color);
|
||||
}
|
||||
|
||||
static const struct field_converter field_converter[LAB_PROMPT_COUNT] = {
|
||||
[LAB_PROMPT_MESSAGE] = { 'm', set_message },
|
||||
[LAB_PROMPT_NO] = { 'n', set_no },
|
||||
[LAB_PROMPT_YES] = { 'y', set_yes },
|
||||
[LAB_PROMPT_BG_COL] = { 'b', set_bg_col },
|
||||
[LAB_PROMPT_TEXT_COL] = { 't', set_text_col },
|
||||
};
|
||||
|
||||
void
|
||||
action_prompt_command(struct buf *buf, const char *format,
|
||||
struct action *action, struct theme *theme)
|
||||
{
|
||||
if (!format) {
|
||||
wlr_log(WLR_ERROR, "missing format");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const char *p = format; *p; p++) {
|
||||
/*
|
||||
* If we're not on a conversion specifier (like %m) then just
|
||||
* keep adding it to the buffer
|
||||
*/
|
||||
if (*p != '%') {
|
||||
buf_add_char(buf, *p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Process the %* conversion specifier */
|
||||
++p;
|
||||
|
||||
bool found = false;
|
||||
for (unsigned char i = 0; i < LAB_PROMPT_COUNT; i++) {
|
||||
if (*p == field_converter[i].fmt_char) {
|
||||
field_converter[i].fn(buf, action, theme);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"invalid prompt command conversion specifier '%c'", *p);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/action.c
45
src/action.c
|
|
@ -10,6 +10,7 @@
|
|||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "action-prompt-codes.h"
|
||||
#include "action-prompt-command.h"
|
||||
#include "common/buf.h"
|
||||
#include "common/macros.h"
|
||||
#include "common/list.h"
|
||||
|
|
@ -281,7 +282,7 @@ action_get_arg(struct action *action, const char *key, enum action_arg_type type
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
const char *
|
||||
action_get_str(struct action *action, const char *key, const char *default_value)
|
||||
{
|
||||
struct action_arg_str *arg = action_get_arg(action, key, LAB_ACTION_ARG_STR);
|
||||
|
|
@ -337,11 +338,6 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_MOVE_TO_EDGE:
|
||||
if (!strcasecmp(argument, "snapWindows")) {
|
||||
action_arg_add_bool(action, argument, parse_bool(content, true));
|
||||
goto cleanup;
|
||||
}
|
||||
/* Falls through */
|
||||
case ACTION_TYPE_TOGGLE_SNAP_TO_EDGE:
|
||||
case ACTION_TYPE_SNAP_TO_EDGE:
|
||||
case ACTION_TYPE_GROW_TO_EDGE:
|
||||
|
|
@ -358,6 +354,17 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
}
|
||||
goto cleanup;
|
||||
}
|
||||
if (action->type == ACTION_TYPE_MOVE_TO_EDGE
|
||||
&& !strcasecmp(argument, "snapWindows")) {
|
||||
action_arg_add_bool(action, argument, parse_bool(content, true));
|
||||
goto cleanup;
|
||||
}
|
||||
if ((action->type == ACTION_TYPE_SNAP_TO_EDGE
|
||||
|| action->type == ACTION_TYPE_TOGGLE_SNAP_TO_EDGE)
|
||||
&& !strcasecmp(argument, "combine")) {
|
||||
action_arg_add_bool(action, argument, parse_bool(content, false));
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SHOW_MENU:
|
||||
if (!strcmp(argument, "menu")) {
|
||||
|
|
@ -827,12 +834,13 @@ handle_view_destroy(struct wl_listener *listener, void *data)
|
|||
static void
|
||||
action_prompt_create(struct view *view, struct server *server, struct action *action)
|
||||
{
|
||||
char *command = strdup_printf("labnag -m \"%s\" -Z \"%s\" -Z \"%s\"",
|
||||
action_get_str(action, "message.prompt", "Choose wisely"),
|
||||
_("No"), _("Yes"));
|
||||
struct buf command = BUF_INIT;
|
||||
action_prompt_command(&command, rc.prompt_command, action, rc.theme);
|
||||
|
||||
wlr_log(WLR_INFO, "prompt command: '%s'", command.data);
|
||||
|
||||
int pipe_fd;
|
||||
pid_t prompt_pid = spawn_piped(command, &pipe_fd);
|
||||
pid_t prompt_pid = spawn_piped(command.data, &pipe_fd);
|
||||
if (prompt_pid < 0) {
|
||||
wlr_log(WLR_ERROR, "Failed to create action prompt");
|
||||
goto cleanup;
|
||||
|
|
@ -856,7 +864,16 @@ action_prompt_create(struct view *view, struct server *server, struct action *ac
|
|||
wl_list_insert(&prompts, &prompt->link);
|
||||
|
||||
cleanup:
|
||||
free(command);
|
||||
buf_reset(&command);
|
||||
}
|
||||
|
||||
void
|
||||
action_prompts_destroy(void)
|
||||
{
|
||||
struct action_prompt *prompt, *tmp;
|
||||
wl_list_for_each_safe(prompt, tmp, &prompts, link) {
|
||||
action_prompt_destroy(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -1031,9 +1048,9 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
view_apply_natural_geometry(view);
|
||||
break;
|
||||
}
|
||||
view_snap_to_edge(view, edge,
|
||||
/*across_outputs*/ true,
|
||||
/*store_natural_geometry*/ true);
|
||||
bool combine = action_get_bool(action, "combine", false);
|
||||
view_snap_to_edge(view, edge, /*across_outputs*/ true,
|
||||
combine, /*store_natural_geometry*/ true);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_GROW_TO_EDGE:
|
||||
|
|
|
|||
|
|
@ -128,6 +128,30 @@ buf_add_fmt(struct buf *s, const char *fmt, ...)
|
|||
s->data[s->len] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
buf_add_hex_color(struct buf *s, float color[4])
|
||||
{
|
||||
/*
|
||||
* In theme.c parse_hexstr() colors are pre-multiplied (by alpha) as
|
||||
* expected by wlr_scene(). We therefore need to reverse that here.
|
||||
*
|
||||
* For details, see https://github.com/labwc/labwc/pull/1685
|
||||
*/
|
||||
float alpha = color[3];
|
||||
|
||||
/* Avoid division by zero */
|
||||
if (alpha == 0.0f) {
|
||||
buf_add(s, "#00000000");
|
||||
return;
|
||||
}
|
||||
|
||||
buf_add_fmt(s, "#%02x%02x%02x%02x",
|
||||
(int)(color[0] / alpha * 255),
|
||||
(int)(color[1] / alpha * 255),
|
||||
(int)(color[2] / alpha * 255),
|
||||
(int)(alpha * 255));
|
||||
}
|
||||
|
||||
void
|
||||
buf_add(struct buf *s, const char *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static PangoRectangle
|
|||
font_extents(struct font *font, const char *string)
|
||||
{
|
||||
PangoRectangle rect = { 0 };
|
||||
if (!string) {
|
||||
if (string_null_or_empty(string)) {
|
||||
return rect;
|
||||
}
|
||||
cairo_surface_t *surface;
|
||||
|
|
@ -43,10 +43,6 @@ font_extents(struct font *font, const char *string)
|
|||
pango_layout_get_extents(layout, NULL, &rect);
|
||||
pango_extents_to_pixels(&rect, NULL);
|
||||
|
||||
/* we put a 2 px edge on each side - because Openbox does it :) */
|
||||
/* TODO: remove the 4 pixel addition and always do the padding by the caller */
|
||||
rect.width += 4;
|
||||
|
||||
cairo_destroy(c);
|
||||
cairo_surface_destroy(surface);
|
||||
pango_font_description_free(desc);
|
||||
|
|
|
|||
|
|
@ -27,34 +27,34 @@ draw_cairo_border(cairo_t *cairo, struct wlr_fbox fbox, double line_width)
|
|||
|
||||
/* Sets the cairo color. Splits the single color channels */
|
||||
void
|
||||
set_cairo_color(cairo_t *cairo, const float *c)
|
||||
set_cairo_color(cairo_t *cairo, const float *color)
|
||||
{
|
||||
/*
|
||||
* We are dealing with pre-multiplied colors
|
||||
* but cairo expects unmultiplied colors here
|
||||
*/
|
||||
float alpha = c[3];
|
||||
float alpha = color[3];
|
||||
|
||||
if (alpha == 0.0f) {
|
||||
cairo_set_source_rgba(cairo, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_set_source_rgba(cairo, c[0] / alpha, c[1] / alpha,
|
||||
c[2] / alpha, alpha);
|
||||
cairo_set_source_rgba(cairo, color[0] / alpha, color[1] / alpha,
|
||||
color[2] / alpha, alpha);
|
||||
}
|
||||
|
||||
cairo_pattern_t *
|
||||
color_to_pattern(const float *c)
|
||||
color_to_pattern(const float *color)
|
||||
{
|
||||
float alpha = c[3];
|
||||
float alpha = color[3];
|
||||
|
||||
if (alpha == 0.0f) {
|
||||
return cairo_pattern_create_rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return cairo_pattern_create_rgba(
|
||||
c[0] / alpha, c[1] / alpha, c[2] / alpha, alpha);
|
||||
return cairo_pattern_create_rgba(color[0] / alpha, color[1] / alpha,
|
||||
color[2] / alpha, alpha);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -20,15 +20,6 @@ string_null_or_empty(const char *s)
|
|||
return !s || !*s;
|
||||
}
|
||||
|
||||
void
|
||||
trim_last_field(char *buf, char delim)
|
||||
{
|
||||
char *p = strrchr(buf, delim);
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtrim(char *s)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -164,12 +164,6 @@ get_node(xmlNode *node, const char *key, xmlNode **dst_node, bool leaf_only)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
lab_xml_get_node(xmlNode *node, const char *key, xmlNode **dst_node)
|
||||
{
|
||||
return get_node(node, key, dst_node, /* leaf_only */ false);
|
||||
}
|
||||
|
||||
bool
|
||||
lab_xml_get_string(xmlNode *node, const char *key, char *s, size_t len)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "osd.h"
|
||||
#include "regions.h"
|
||||
#include "ssd.h"
|
||||
#include "translate.h"
|
||||
#include "view.h"
|
||||
#include "window-rules.h"
|
||||
#include "workspaces.h"
|
||||
|
|
@ -116,7 +117,8 @@ parse_window_type(const char *type)
|
|||
* desk D All-desktops toggle (aka omnipresent)
|
||||
*/
|
||||
static void
|
||||
fill_section(const char *content, struct wl_list *list, uint32_t *found_buttons)
|
||||
fill_section(const char *content, enum lab_node_type *buttons, int *count,
|
||||
uint32_t *found_buttons /* bitmask */)
|
||||
{
|
||||
gchar **identifiers = g_strsplit(content, ",", -1);
|
||||
for (size_t i = 0; identifiers[i]; ++i) {
|
||||
|
|
@ -162,9 +164,8 @@ fill_section(const char *content, struct wl_list *list, uint32_t *found_buttons)
|
|||
|
||||
*found_buttons |= (1 << type);
|
||||
|
||||
struct title_button *item = znew(*item);
|
||||
item->type = type;
|
||||
wl_list_append(list, &item->link);
|
||||
assert(*count < TITLE_BUTTONS_MAX);
|
||||
buttons[(*count)++] = type;
|
||||
}
|
||||
g_strfreev(identifiers);
|
||||
}
|
||||
|
|
@ -172,28 +173,16 @@ fill_section(const char *content, struct wl_list *list, uint32_t *found_buttons)
|
|||
static void
|
||||
clear_title_layout(void)
|
||||
{
|
||||
struct title_button *button, *button_tmp;
|
||||
wl_list_for_each_safe(button, button_tmp, &rc.title_buttons_left, link) {
|
||||
wl_list_remove(&button->link);
|
||||
zfree(button);
|
||||
}
|
||||
wl_list_for_each_safe(button, button_tmp, &rc.title_buttons_right, link) {
|
||||
wl_list_remove(&button->link);
|
||||
zfree(button);
|
||||
}
|
||||
rc.nr_title_buttons_left = 0;
|
||||
rc.nr_title_buttons_right = 0;
|
||||
rc.title_layout_loaded = false;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_title_layout(char *content)
|
||||
fill_title_layout(const char *content)
|
||||
{
|
||||
clear_title_layout();
|
||||
|
||||
struct wl_list *sections[] = {
|
||||
&rc.title_buttons_left,
|
||||
&rc.title_buttons_right,
|
||||
};
|
||||
|
||||
gchar **parts = g_strsplit(content, ":", -1);
|
||||
|
||||
if (g_strv_length(parts) != 2) {
|
||||
|
|
@ -202,9 +191,10 @@ fill_title_layout(char *content)
|
|||
}
|
||||
|
||||
uint32_t found_buttons = 0;
|
||||
for (size_t i = 0; parts[i]; ++i) {
|
||||
fill_section(parts[i], sections[i], &found_buttons);
|
||||
}
|
||||
fill_section(parts[0], rc.title_buttons_left,
|
||||
&rc.nr_title_buttons_left, &found_buttons);
|
||||
fill_section(parts[1], rc.title_buttons_right,
|
||||
&rc.nr_title_buttons_right, &found_buttons);
|
||||
|
||||
rc.title_layout_loaded = true;
|
||||
err:
|
||||
|
|
@ -1113,6 +1103,10 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
set_bool(content, &rc.xwayland_persistence);
|
||||
} else if (!strcasecmp(nodename, "primarySelection.core")) {
|
||||
set_bool(content, &rc.primary_selection);
|
||||
|
||||
} else if (!strcasecmp(nodename, "promptCommand.core")) {
|
||||
xstrdup_replace(rc.prompt_command, content);
|
||||
|
||||
} else if (!strcmp(nodename, "policy.placement")) {
|
||||
enum lab_placement_policy policy = view_placement_parse(content);
|
||||
if (policy != LAB_PLACE_INVALID) {
|
||||
|
|
@ -1329,8 +1323,7 @@ traverse(xmlNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
/* Exposed in header file to allow unit tests to parse buffers */
|
||||
void
|
||||
static void
|
||||
rcxml_parse_xml(struct buf *b)
|
||||
{
|
||||
int options = 0;
|
||||
|
|
@ -1362,8 +1355,6 @@ rcxml_init(void)
|
|||
static bool has_run;
|
||||
|
||||
if (!has_run) {
|
||||
wl_list_init(&rc.title_buttons_left);
|
||||
wl_list_init(&rc.title_buttons_right);
|
||||
wl_list_init(&rc.usable_area_overrides);
|
||||
wl_list_init(&rc.keybinds);
|
||||
wl_list_init(&rc.mousebinds);
|
||||
|
|
@ -1637,6 +1628,22 @@ post_processing(void)
|
|||
load_default_mouse_bindings();
|
||||
}
|
||||
|
||||
if (!rc.prompt_command) {
|
||||
rc.prompt_command =
|
||||
xstrdup("labnag "
|
||||
"--message '%m' "
|
||||
"--button-dismiss '%n' "
|
||||
"--button-dismiss '%y' "
|
||||
"--background-color '%b' "
|
||||
"--text-color '%t' "
|
||||
"--button-border-color '%t' "
|
||||
"--border-bottom-color '%t' "
|
||||
"--button-background-color '%b' "
|
||||
"--button-text-color '%t' "
|
||||
"--border-bottom-size 1 "
|
||||
"--button-border-size 3 "
|
||||
"--timeout 0");
|
||||
}
|
||||
if (!rc.fallback_app_icon_name) {
|
||||
rc.fallback_app_icon_name = xstrdup("labwc");
|
||||
}
|
||||
|
|
@ -1899,6 +1906,7 @@ rcxml_finish(void)
|
|||
zfree(rc.font_menuheader.name);
|
||||
zfree(rc.font_menuitem.name);
|
||||
zfree(rc.font_osd.name);
|
||||
zfree(rc.prompt_command);
|
||||
zfree(rc.theme_name);
|
||||
zfree(rc.icon_theme_name);
|
||||
zfree(rc.fallback_app_icon_name);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include "desktop-entry.h"
|
||||
#include <locale.h>
|
||||
#include <sfdo-desktop.h>
|
||||
#include <sfdo-icon.h>
|
||||
#include <sfdo-basedir.h>
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|||
}
|
||||
}
|
||||
|
||||
struct view *
|
||||
static struct view *
|
||||
desktop_topmost_focusable_view(struct server *server)
|
||||
{
|
||||
struct view *view;
|
||||
|
|
|
|||
|
|
@ -583,11 +583,11 @@ input_method_relay_create(struct seat *seat)
|
|||
relay->popup_tree = wlr_scene_tree_create(&seat->server->scene->tree);
|
||||
|
||||
relay->new_text_input.notify = handle_new_text_input;
|
||||
wl_signal_add(&seat->server->text_input_manager->events.text_input,
|
||||
wl_signal_add(&seat->server->text_input_manager->events.new_text_input,
|
||||
&relay->new_text_input);
|
||||
|
||||
relay->new_input_method.notify = handle_new_input_method;
|
||||
wl_signal_add(&seat->server->input_method_manager->events.input_method,
|
||||
wl_signal_add(&seat->server->input_method_manager->events.new_input_method,
|
||||
&relay->new_input_method);
|
||||
|
||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||
|
|
|
|||
|
|
@ -84,9 +84,3 @@ key_state_nr_bound_keys(void)
|
|||
{
|
||||
return bound.size;
|
||||
}
|
||||
|
||||
int
|
||||
key_state_nr_pressed_keys(void)
|
||||
{
|
||||
return pressed.size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
|
||||
cursor_shape = LAB_CURSOR_GRAB;
|
||||
break;
|
||||
case LAB_INPUT_STATE_RESIZE:
|
||||
case LAB_INPUT_STATE_RESIZE: {
|
||||
if (view->shaded || view->fullscreen ||
|
||||
view->maximized == VIEW_AXIS_BOTH) {
|
||||
/*
|
||||
|
|
@ -133,6 +133,7 @@ interactive_begin(struct view *view, enum input_mode mode, enum lab_edge edges)
|
|||
view_set_untiled(view);
|
||||
cursor_shape = cursor_get_from_edge(edges);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Should not be reached */
|
||||
return;
|
||||
|
|
@ -259,9 +260,8 @@ snap_to_edge(struct view *view)
|
|||
view_maximize(view, VIEW_AXIS_BOTH,
|
||||
/*store_natural_geometry*/ false);
|
||||
} else {
|
||||
view_snap_to_edge(view, edge,
|
||||
/*across_outputs*/ false,
|
||||
/*store_natural_geometry*/ false);
|
||||
view_snap_to_edge(view, edge, /*across_outputs*/ false,
|
||||
/*combine*/ false, /*store_natural_geometry*/ false);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "config/session.h"
|
||||
#include "labwc.h"
|
||||
#include "theme.h"
|
||||
#include "translate.h"
|
||||
#include "menu/menu.h"
|
||||
|
||||
struct rcxml rc = { 0 };
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "scaled-buffer/scaled-font-buffer.h"
|
||||
#include "scaled-buffer/scaled-icon-buffer.h"
|
||||
#include "theme.h"
|
||||
#include "translate.h"
|
||||
#include "view.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
|
|
@ -135,6 +136,7 @@ item_create(struct menu *menu, const char *text, const char *icon_name, bool sho
|
|||
assert(menu);
|
||||
assert(text);
|
||||
|
||||
struct theme *theme = menu->server->theme;
|
||||
struct menuitem *menuitem = znew(*menuitem);
|
||||
menuitem->parent = menu;
|
||||
menuitem->selectable = true;
|
||||
|
|
@ -151,7 +153,8 @@ item_create(struct menu *menu, const char *text, const char *icon_name, bool sho
|
|||
|
||||
menuitem->native_width = font_width(&rc.font_menuitem, text);
|
||||
if (menuitem->arrow) {
|
||||
menuitem->native_width += font_width(&rc.font_menuitem, menuitem->arrow);
|
||||
menuitem->native_width += font_width(&rc.font_menuitem, menuitem->arrow)
|
||||
+ theme->menu_items_padding_x;
|
||||
}
|
||||
|
||||
wl_list_append(&menu->menuitems, &menuitem->link);
|
||||
|
|
@ -177,7 +180,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color,
|
|||
|
||||
int bg_width = menu->size.width - 2 * theme->menu_border_width;
|
||||
int arrow_width = item->arrow ?
|
||||
font_width(&rc.font_menuitem, item->arrow) : 0;
|
||||
font_width(&rc.font_menuitem, item->arrow) + theme->menu_items_padding_x : 0;
|
||||
int label_max_width = bg_width - 2 * theme->menu_items_padding_x
|
||||
- arrow_width - icon_width;
|
||||
|
||||
|
|
@ -227,7 +230,7 @@ item_create_scene_for_state(struct menuitem *item, float *text_color,
|
|||
scaled_font_buffer_update(arrow_buffer, item->arrow, -1,
|
||||
&rc.font_menuitem, text_color, bg_color);
|
||||
/* Vertically center and right-align arrow */
|
||||
x += label_max_width;
|
||||
x += label_max_width + theme->menu_items_padding_x;
|
||||
y = (theme->menu_item_height - label_buffer->height) / 2;
|
||||
wlr_scene_node_set_position(&arrow_buffer->scene_buffer->node, x, y);
|
||||
|
||||
|
|
@ -1542,15 +1545,6 @@ menu_process_cursor_motion(struct wlr_scene_node *node)
|
|||
menu_process_item_selection(item);
|
||||
}
|
||||
|
||||
bool
|
||||
menu_call_actions(struct wlr_scene_node *node)
|
||||
{
|
||||
assert(node && node->data);
|
||||
struct menuitem *item = node_menuitem_from_node(node);
|
||||
|
||||
return menu_execute_item(item);
|
||||
}
|
||||
|
||||
void
|
||||
menu_close_root(struct server *server)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
labwc_sources = files(
|
||||
'action.c',
|
||||
'action-prompt-command.c',
|
||||
'buffer.c',
|
||||
'debug.c',
|
||||
'desktop.c',
|
||||
|
|
|
|||
|
|
@ -50,15 +50,6 @@ node_layer_surface_from_node(struct wlr_scene_node *wlr_scene_node)
|
|||
return (struct lab_layer_surface *)node_descriptor->data;
|
||||
}
|
||||
|
||||
struct lab_layer_popup *
|
||||
node_layer_popup_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||
{
|
||||
assert(wlr_scene_node->data);
|
||||
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
||||
assert(node_descriptor->type == LAB_NODE_LAYER_POPUP);
|
||||
return (struct lab_layer_popup *)node_descriptor->data;
|
||||
}
|
||||
|
||||
struct menuitem *
|
||||
node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -130,12 +130,12 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
|||
|
||||
/* background for selected item */
|
||||
struct lab_scene_rect_options opts = {
|
||||
.border_colors = (float *[1]) { switcher_theme->item_active_border_color },
|
||||
.nr_borders = 1,
|
||||
.border_width = switcher_theme->item_active_border_width,
|
||||
.bg_color = switcher_theme->item_active_bg_color,
|
||||
.width = switcher_theme->item_width,
|
||||
.height = switcher_theme->item_height,
|
||||
.bg_color = switcher_theme->item_active_bg_color,
|
||||
.nr_borders = 1,
|
||||
.border_colors = (float *[1]) { switcher_theme->item_active_border_color },
|
||||
.border_width = switcher_theme->item_active_border_width,
|
||||
};
|
||||
item->active_bg = lab_scene_rect_create(item->tree, &opts);
|
||||
|
||||
|
|
@ -241,12 +241,12 @@ osd_thumbnail_create(struct output *output, struct wl_array *views)
|
|||
|
||||
/* background */
|
||||
struct lab_scene_rect_options bg_opts = {
|
||||
.width = nr_cols * switcher_theme->item_width + 2 * padding,
|
||||
.height = nr_rows * switcher_theme->item_height + 2 * padding,
|
||||
.bg_color = theme->osd_bg_color,
|
||||
.border_colors = (float *[1]) { theme->osd_border_color },
|
||||
.nr_borders = 1,
|
||||
.border_width = theme->osd_border_width,
|
||||
.border_colors = (float *[1]) { theme->osd_border_color },
|
||||
.bg_color = theme->osd_bg_color,
|
||||
.width = nr_cols * switcher_theme->item_width + 2 * padding,
|
||||
.height = nr_rows * switcher_theme->item_height + 2 * padding,
|
||||
};
|
||||
struct lab_scene_rect *bg =
|
||||
lab_scene_rect_create(output->osd_scene.tree, &bg_opts);
|
||||
|
|
|
|||
18
src/output.c
18
src/output.c
|
|
@ -551,6 +551,8 @@ handle_new_output(struct wl_listener *listener, void *data)
|
|||
do_output_layout_change(server);
|
||||
}
|
||||
|
||||
static void output_manager_init(struct server *server);
|
||||
|
||||
void
|
||||
output_init(struct server *server)
|
||||
{
|
||||
|
|
@ -890,7 +892,7 @@ handle_gamma_control_set_gamma(struct wl_listener *listener, void *data)
|
|||
wlr_output_schedule_frame(output->wlr_output);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
output_manager_init(struct server *server)
|
||||
{
|
||||
server->output_manager = wlr_output_manager_v1_create(server->wl_display);
|
||||
|
|
@ -1142,17 +1144,3 @@ output_enable_adaptive_sync(struct output *output, bool enabled)
|
|||
enabled ? "en" : "dis", output->wlr_output->name);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
output_max_scale(struct server *server)
|
||||
{
|
||||
/* Never return less than 1, in case outputs are disabled */
|
||||
float scale = 1;
|
||||
struct output *output;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
if (output_is_usable(output)) {
|
||||
scale = MAX(scale, output->wlr_output->scale);
|
||||
}
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,17 +139,3 @@ scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
|
|||
scaled_buffer_request_update(self->scaled_buffer,
|
||||
self->width, self->height);
|
||||
}
|
||||
|
||||
void
|
||||
scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width)
|
||||
{
|
||||
self->max_width = max_width;
|
||||
|
||||
int computed_height;
|
||||
font_get_buffer_size(self->max_width, self->text, &self->font,
|
||||
&self->width, &computed_height);
|
||||
self->height = (self->fixed_height > 0) ?
|
||||
self->fixed_height : computed_height;
|
||||
scaled_buffer_request_update(self->scaled_buffer,
|
||||
self->width, self->height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||
#include <wlr/types/wlr_fixes.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||
#include <wlr/types/wlr_input_method_v2.h>
|
||||
|
|
@ -78,6 +79,9 @@
|
|||
static void
|
||||
reload_config_and_theme(struct server *server)
|
||||
{
|
||||
/* Avoid UAF when dialog client is used during reconfigure */
|
||||
action_prompts_destroy();
|
||||
|
||||
scaled_buffer_invalidate_sharing();
|
||||
rcxml_finish();
|
||||
rcxml_read(rc.config_file);
|
||||
|
|
@ -252,6 +256,7 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
|
|||
"wl_data_device_manager", /* would be great if we could drop this one */
|
||||
"wl_seat",
|
||||
"xdg_wm_base",
|
||||
"wl_fixes",
|
||||
/* enhanced */
|
||||
"wl_output",
|
||||
"wl_drm",
|
||||
|
|
@ -431,6 +436,8 @@ server_init(struct server *server)
|
|||
|
||||
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
||||
|
||||
wlr_fixes_create(server->wl_display, 1);
|
||||
|
||||
/* Catch signals */
|
||||
server->sighup_source = wl_event_loop_add_signal(
|
||||
server->wl_event_loop, SIGHUP, handle_sighup, server);
|
||||
|
|
|
|||
|
|
@ -193,9 +193,6 @@ resize_indicator_update(struct view *view)
|
|||
/* Let the indicator change width as required by the content */
|
||||
int width = font_width(&rc.font_osd, text);
|
||||
|
||||
/* font_extents() adds 4 pixels to the calculated width */
|
||||
width -= 4;
|
||||
|
||||
resize_indicator_set_size(indicator, width);
|
||||
|
||||
/* Center the indicator in the window */
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ ssd_titlebar_create(struct ssd *ssd)
|
|||
LAB_NODE_TITLE, view, /*data*/ NULL);
|
||||
|
||||
/* Buttons */
|
||||
struct title_button *b;
|
||||
int x = theme->window_titlebar_padding_width;
|
||||
|
||||
/* Center vertically within titlebar */
|
||||
|
|
@ -90,20 +89,22 @@ ssd_titlebar_create(struct ssd *ssd)
|
|||
wl_list_init(&subtree->buttons_left);
|
||||
wl_list_init(&subtree->buttons_right);
|
||||
|
||||
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
||||
for (int b = 0; b < rc.nr_title_buttons_left; b++) {
|
||||
enum lab_node_type type = rc.title_buttons_left[b];
|
||||
struct lab_img **imgs =
|
||||
theme->window[active].button_imgs[b->type];
|
||||
attach_ssd_button(&subtree->buttons_left, b->type, parent,
|
||||
theme->window[active].button_imgs[type];
|
||||
attach_ssd_button(&subtree->buttons_left, type, parent,
|
||||
imgs, x, y, view);
|
||||
x += theme->window_button_width + theme->window_button_spacing;
|
||||
}
|
||||
|
||||
x = width - theme->window_titlebar_padding_width + theme->window_button_spacing;
|
||||
wl_list_for_each_reverse(b, &rc.title_buttons_right, link) {
|
||||
for (int b = rc.nr_title_buttons_right - 1; b >= 0; b--) {
|
||||
x -= theme->window_button_width + theme->window_button_spacing;
|
||||
enum lab_node_type type = rc.title_buttons_right[b];
|
||||
struct lab_img **imgs =
|
||||
theme->window[active].button_imgs[b->type];
|
||||
attach_ssd_button(&subtree->buttons_right, b->type, parent,
|
||||
theme->window[active].button_imgs[type];
|
||||
attach_ssd_button(&subtree->buttons_right, type, parent,
|
||||
imgs, x, y, view);
|
||||
}
|
||||
}
|
||||
|
|
@ -223,8 +224,8 @@ update_visible_buttons(struct ssd *ssd)
|
|||
int width = MAX(view->current.width - 2 * theme->window_titlebar_padding_width, 0);
|
||||
int button_width = theme->window_button_width;
|
||||
int button_spacing = theme->window_button_spacing;
|
||||
int button_count_left = wl_list_length(&rc.title_buttons_left);
|
||||
int button_count_right = wl_list_length(&rc.title_buttons_right);
|
||||
int button_count_left = rc.nr_title_buttons_left;
|
||||
int button_count_right = rc.nr_title_buttons_right;
|
||||
|
||||
/* Make sure infinite loop never occurs */
|
||||
assert(button_width > 0);
|
||||
|
|
|
|||
27
src/theme.c
27
src/theme.c
|
|
@ -231,25 +231,16 @@ load_button(struct theme *theme, struct button *b, int active)
|
|||
struct lab_img **rounded_img =
|
||||
&button_imgs[b->type][b->state_set | LAB_BS_ROUNDED];
|
||||
|
||||
struct title_button *leftmost_button;
|
||||
wl_list_for_each(leftmost_button,
|
||||
&rc.title_buttons_left, link) {
|
||||
if (leftmost_button->type == b->type) {
|
||||
*rounded_img = lab_img_copy(*img);
|
||||
lab_img_add_modifier(*rounded_img,
|
||||
round_left_corner_button);
|
||||
}
|
||||
break;
|
||||
if (rc.nr_title_buttons_left > 0
|
||||
&& b->type == rc.title_buttons_left[0]) {
|
||||
*rounded_img = lab_img_copy(*img);
|
||||
lab_img_add_modifier(*rounded_img, round_left_corner_button);
|
||||
}
|
||||
struct title_button *rightmost_button;
|
||||
wl_list_for_each_reverse(rightmost_button,
|
||||
&rc.title_buttons_right, link) {
|
||||
if (rightmost_button->type == b->type) {
|
||||
*rounded_img = lab_img_copy(*img);
|
||||
lab_img_add_modifier(*rounded_img,
|
||||
round_right_corner_button);
|
||||
}
|
||||
break;
|
||||
if (rc.nr_title_buttons_right > 0
|
||||
&& b->type == rc.title_buttons_right
|
||||
[rc.nr_title_buttons_right - 1]) {
|
||||
*rounded_img = lab_img_copy(*img);
|
||||
lab_img_add_modifier(*rounded_img, round_right_corner_button);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
143
src/view.c
143
src/view.c
|
|
@ -120,6 +120,16 @@ query_str_match(const char *condition, const char *value)
|
|||
return value && match_glob(condition, value);
|
||||
}
|
||||
|
||||
static bool
|
||||
view_contains_window_type(struct view *view, enum lab_window_type window_type)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->contains_window_type) {
|
||||
return view->impl->contains_window_type(view, window_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
view_matches_query(struct view *view, struct view_query *query)
|
||||
{
|
||||
|
|
@ -215,26 +225,41 @@ view_matches_query(struct view *view, struct view_query *query)
|
|||
|
||||
if (query->monitor) {
|
||||
struct output *current = output_nearest_to_cursor(view->server);
|
||||
|
||||
if (!strcasecmp(query->monitor, "current") && current != view->output) {
|
||||
return false;
|
||||
}
|
||||
if (!strcasecmp(query->monitor, "left") &&
|
||||
output_get_adjacent(current, LAB_EDGE_LEFT, false) != view->output) {
|
||||
return false;
|
||||
}
|
||||
if (!strcasecmp(query->monitor, "right") &&
|
||||
output_get_adjacent(current, LAB_EDGE_RIGHT, false) != view->output) {
|
||||
return false;
|
||||
}
|
||||
if (output_from_name(view->server, query->monitor) != view->output) {
|
||||
return false;
|
||||
if (!strcasecmp(query->monitor, "current")) {
|
||||
if (current != view->output) {
|
||||
return false;
|
||||
}
|
||||
} else if (!strcasecmp(query->monitor, "left")) {
|
||||
if (output_get_adjacent(current, LAB_EDGE_LEFT, false)
|
||||
!= view->output) {
|
||||
return false;
|
||||
}
|
||||
} else if (!strcasecmp(query->monitor, "right")) {
|
||||
if (output_get_adjacent(current, LAB_EDGE_RIGHT, false)
|
||||
!= view->output) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (output_from_name(view->server, query->monitor)
|
||||
!= view->output) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct view *
|
||||
view_get_root(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->get_root) {
|
||||
return view->impl->get_root(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
static bool
|
||||
matches_criteria(struct view *view, enum lab_view_criteria criteria)
|
||||
{
|
||||
|
|
@ -388,16 +413,6 @@ view_wants_focus(struct view *view)
|
|||
return VIEW_WANTS_FOCUS_ALWAYS;
|
||||
}
|
||||
|
||||
bool
|
||||
view_contains_window_type(struct view *view, enum lab_window_type window_type)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->contains_window_type) {
|
||||
return view->impl->contains_window_type(view, window_type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
view_is_focusable(struct view *view)
|
||||
{
|
||||
|
|
@ -793,6 +808,15 @@ _minimize(struct view *view, bool minimized)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_append_children(struct view *view, struct wl_array *children)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->append_children) {
|
||||
view->impl->append_children(view, children);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
minimize_sub_views(struct view *view, bool minimized)
|
||||
{
|
||||
|
|
@ -2121,7 +2145,7 @@ view_placement_parse(const char *policy)
|
|||
|
||||
void
|
||||
view_snap_to_edge(struct view *view, enum lab_edge edge,
|
||||
bool across_outputs, bool store_natural_geometry)
|
||||
bool across_outputs, bool combine, bool store_natural_geometry)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
|
|
@ -2137,25 +2161,45 @@ view_snap_to_edge(struct view *view, enum lab_edge edge,
|
|||
|
||||
view_set_shade(view, false);
|
||||
|
||||
if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) {
|
||||
/* We are already tiled for this edge; try to switch outputs */
|
||||
output = output_get_adjacent(view->output, edge, /* wrap */ false);
|
||||
if (lab_edge_is_cardinal(edge) && view->maximized == VIEW_AXIS_NONE) {
|
||||
enum lab_edge invert_edge = lab_edge_invert(edge);
|
||||
/* Represents axis of snapping direction */
|
||||
enum lab_edge parallel_mask = edge | invert_edge;
|
||||
/*
|
||||
* The vector view->tiled is split to components
|
||||
* parallel/orthogonal to snapping direction. For example,
|
||||
* view->tiled=TOP_LEFT is split to parallel_tiled=TOP and
|
||||
* orthogonal_tiled=LEFT when edge=TOP or edge=BOTTOM.
|
||||
*/
|
||||
enum lab_edge parallel_tiled = view->tiled & parallel_mask;
|
||||
enum lab_edge orthogonal_tiled = view->tiled & ~parallel_mask;
|
||||
|
||||
if (!output) {
|
||||
if (across_outputs && view->tiled == edge) {
|
||||
/*
|
||||
* No more output to move to
|
||||
*
|
||||
* We re-apply the tiled geometry without changing any
|
||||
* state because the window might have been moved away
|
||||
* (and thus got untiled) and then snapped back to the
|
||||
* original edge.
|
||||
* E.g. when window is tiled to up and being snapped
|
||||
* to up again, move it to the output above and tile
|
||||
* it to down.
|
||||
*/
|
||||
view_apply_tiled_geometry(view);
|
||||
return;
|
||||
output = output_get_adjacent(view->output, edge,
|
||||
/* wrap */ false);
|
||||
if (!output) {
|
||||
return;
|
||||
}
|
||||
edge = invert_edge;
|
||||
} else if (combine && parallel_tiled == invert_edge
|
||||
&& orthogonal_tiled != LAB_EDGE_NONE) {
|
||||
/*
|
||||
* E.g. when window is tiled to downleft/downright and
|
||||
* being snapped to up, tile it to left/right.
|
||||
*/
|
||||
edge = view->tiled & ~parallel_mask;
|
||||
} else if (combine && parallel_tiled == LAB_EDGE_NONE) {
|
||||
/*
|
||||
* E.g. when window is tiled to left/right and being
|
||||
* snapped to up, tile it to upleft/upright.
|
||||
*/
|
||||
edge = view->tiled | edge;
|
||||
}
|
||||
|
||||
/* When switching outputs, jump to the opposite edge */
|
||||
edge = lab_edge_invert(edge);
|
||||
}
|
||||
|
||||
if (view->maximized != VIEW_AXIS_NONE) {
|
||||
|
|
@ -2302,25 +2346,6 @@ view_move_to_back(struct view *view)
|
|||
desktop_update_top_layer_visibility(view->server);
|
||||
}
|
||||
|
||||
struct view *
|
||||
view_get_root(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->get_root) {
|
||||
return view->impl->get_root(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
void
|
||||
view_append_children(struct view *view, struct wl_array *children)
|
||||
{
|
||||
assert(view);
|
||||
if (view->impl->append_children) {
|
||||
view->impl->append_children(view, children);
|
||||
}
|
||||
}
|
||||
|
||||
struct view *
|
||||
view_get_modal_dialog(struct view *view)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,21 @@ static xcb_atom_t atoms[ATOM_COUNT] = {0};
|
|||
|
||||
static void xwayland_view_unmap(struct view *view, bool client_request);
|
||||
|
||||
static struct xwayland_view *
|
||||
xwayland_view_from_view(struct view *view)
|
||||
{
|
||||
assert(view->type == LAB_XWAYLAND_VIEW);
|
||||
return (struct xwayland_view *)view;
|
||||
}
|
||||
|
||||
static struct wlr_xwayland_surface *
|
||||
xwayland_surface_from_view(struct view *view)
|
||||
{
|
||||
struct xwayland_view *xwayland_view = xwayland_view_from_view(view);
|
||||
assert(xwayland_view->xwayland_surface);
|
||||
return xwayland_view->xwayland_surface;
|
||||
}
|
||||
|
||||
static bool
|
||||
xwayland_view_contains_window_type(struct view *view,
|
||||
enum lab_window_type window_type)
|
||||
|
|
@ -186,21 +201,6 @@ top_parent_of(struct view *view)
|
|||
return s;
|
||||
}
|
||||
|
||||
static struct xwayland_view *
|
||||
xwayland_view_from_view(struct view *view)
|
||||
{
|
||||
assert(view->type == LAB_XWAYLAND_VIEW);
|
||||
return (struct xwayland_view *)view;
|
||||
}
|
||||
|
||||
struct wlr_xwayland_surface *
|
||||
xwayland_surface_from_view(struct view *view)
|
||||
{
|
||||
struct xwayland_view *xwayland_view = xwayland_view_from_view(view);
|
||||
assert(xwayland_view->xwayland_surface);
|
||||
return xwayland_view->xwayland_surface;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_initial_geometry_and_output(struct view *view)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[wrap-git]
|
||||
url = https://gitlab.freedesktop.org/vyivel/libsfdo.git
|
||||
revision = v0.1.3
|
||||
revision = v0.1.4
|
||||
|
||||
[provide]
|
||||
dependency_names = libsfdo-basedir, libsfdo-desktop, libsfdo-icon
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[wrap-git]
|
||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
revision = 0.19
|
||||
revision = master
|
||||
|
||||
[provide]
|
||||
dependency_names = wlroots-0.19
|
||||
wlroots-0.19=wlroots
|
||||
dependency_names = wlroots-0.20
|
||||
wlroots-0.20=wlroots
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
test_deps = [
|
||||
dep_cmocka,
|
||||
glib,
|
||||
xml2,
|
||||
wlroots,
|
||||
]
|
||||
|
||||
test_lib = static_library(
|
||||
'test_lib',
|
||||
sources: files(
|
||||
|
|
@ -8,12 +15,7 @@ test_lib = static_library(
|
|||
'../src/common/parse-bool.c',
|
||||
),
|
||||
include_directories: [labwc_inc],
|
||||
dependencies: [
|
||||
dep_cmocka,
|
||||
glib,
|
||||
xml2,
|
||||
wlroots,
|
||||
],
|
||||
dependencies: test_deps,
|
||||
)
|
||||
|
||||
tests = [
|
||||
|
|
@ -30,7 +32,7 @@ foreach t : tests
|
|||
sources: '@0@.c'.format(t),
|
||||
include_directories: [labwc_inc],
|
||||
link_with: [test_lib],
|
||||
dependencies: [xml2],
|
||||
dependencies: test_deps,
|
||||
),
|
||||
is_parallel: false,
|
||||
)
|
||||
|
|
|
|||
2
t/xml.c
2
t/xml.c
|
|
@ -111,7 +111,7 @@ test_lab_xml_expand_dotted_attributes(void **state)
|
|||
|
||||
xmlBuffer *buf = xmlBufferCreate();
|
||||
xmlNodeDump(buf, root->doc, root, 0, 0);
|
||||
assert_string_equal(test_cases[i].after, (char *)buf->content);
|
||||
assert_string_equal(test_cases[i].after, (char *)xmlBufferContent(buf));
|
||||
xmlBufferFree(buf);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue