mirror of
https://github.com/labwc/labwc.git
synced 2026-06-17 14:33:30 -04:00
Compare commits
146 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
529fc382da | ||
|
|
4dab6994dc | ||
|
|
07e1053a8d | ||
|
|
2135fb0d35 | ||
|
|
bbfa6bbddb | ||
|
|
a814dd1e38 | ||
|
|
28d03b0893 | ||
|
|
f4b9bdab65 | ||
|
|
78227f1724 | ||
|
|
579e532908 | ||
|
|
d5b5b765c7 | ||
|
|
37434e3ea5 | ||
|
|
52487547ca | ||
|
|
7e74b82874 | ||
|
|
151acae28a | ||
|
|
bce14a5ad7 | ||
|
|
d5eb227c77 | ||
|
|
80ff89c640 | ||
|
|
4af693a7fd | ||
|
|
cd7be59d5f | ||
|
|
0a9bd41df0 | ||
|
|
df6dde131f | ||
|
|
7a53f294a8 | ||
|
|
8473ea4b72 | ||
|
|
4b61a8a879 | ||
|
|
bc287686ea | ||
|
|
477b3b1ddb | ||
|
|
e1fdbb0611 | ||
|
|
90b87cb882 | ||
|
|
e2f3c03287 | ||
|
|
d86b2cfd0d | ||
|
|
38f80d7167 | ||
|
|
c1b11c7821 | ||
|
|
2189b2be1e | ||
|
|
2480a23b19 | ||
|
|
0f5e4f8dd0 | ||
|
|
949e9ffe42 | ||
|
|
ff2f243eb1 | ||
|
|
f42e1895d4 | ||
|
|
3632c6703a | ||
|
|
07a0a4e59b | ||
|
|
0caefa6a9e | ||
|
|
0ff9af4ae0 | ||
|
|
6ce25978e7 | ||
|
|
bc7498dc6f | ||
|
|
df9537c809 | ||
|
|
def6ff22d3 | ||
|
|
998fd80737 | ||
|
|
7ec7a322d2 | ||
|
|
ccdef5e854 | ||
|
|
e209de3eb1 | ||
|
|
91d89f71ce | ||
|
|
de3870246a | ||
|
|
e61d58e54d | ||
|
|
6237e26a1d | ||
|
|
9661ed4285 | ||
|
|
ecc5565686 | ||
|
|
28908adfbe | ||
|
|
fe6ea66b82 | ||
|
|
7b3f37725f | ||
|
|
70e3173f99 | ||
|
|
af277b09ed | ||
|
|
d8119cb354 | ||
|
|
5c7bfe3c67 | ||
|
|
7d264c907f | ||
|
|
20540d76f9 | ||
|
|
5f668a82ee | ||
|
|
5c582bda09 | ||
|
|
6df6a092ba | ||
|
|
c5ea41e876 | ||
|
|
4c7a9960a4 | ||
|
|
da37e97a45 | ||
|
|
8b32422b93 | ||
|
|
c8bb3381a4 | ||
|
|
c4fd916fd3 | ||
|
|
3ec20044b5 | ||
|
|
afaed4af63 | ||
|
|
90c38e2681 | ||
|
|
a893b1ab50 | ||
|
|
c9b4da2ce2 | ||
|
|
e45548077e | ||
|
|
7be58fbaba | ||
|
|
3df8fcda3a | ||
|
|
8c6faa010f | ||
|
|
dfbea3e156 | ||
|
|
046d055ac0 | ||
|
|
fe1955fb27 | ||
|
|
b3f3fc9084 | ||
|
|
674238caa9 | ||
|
|
0d049552bc | ||
|
|
9209f611d5 | ||
|
|
46d687ab54 | ||
|
|
9a8154836c | ||
|
|
862d230ff9 | ||
|
|
3128f50a25 | ||
|
|
cdee4ba5f1 | ||
|
|
cee5712877 | ||
|
|
647e9b7658 | ||
|
|
c3fc78286a | ||
|
|
76f166ae42 | ||
|
|
863863fc7c | ||
|
|
5f8a6395a1 | ||
|
|
511ed69c53 | ||
|
|
0c24252c85 | ||
|
|
48bcccddc3 | ||
|
|
ea4e7e9a02 | ||
|
|
3ce6328f6d | ||
|
|
fee38bceca | ||
|
|
4e25347791 | ||
|
|
9903331995 | ||
|
|
d4ad27e636 | ||
|
|
9550bccef2 | ||
|
|
a2e0de7676 | ||
|
|
4f72e6775e | ||
|
|
8d46da9db1 | ||
|
|
cb49bddf63 | ||
|
|
60ac8f07bb | ||
|
|
50bb882cf0 | ||
|
|
17d6c29037 | ||
|
|
3b6fe26301 | ||
|
|
16c5373be5 | ||
|
|
c4effef0ec | ||
|
|
5a9ae66332 | ||
|
|
7c39ee30e9 | ||
|
|
4faab834f9 | ||
|
|
a3646721bc | ||
|
|
ab60379c7f | ||
|
|
93029ca583 | ||
|
|
89574772d0 | ||
|
|
b36b4ab816 | ||
|
|
f0589810ad | ||
|
|
3bb4ccd22d | ||
|
|
1f776466a8 | ||
|
|
9de35d7b4f | ||
|
|
8d8654db02 | ||
|
|
d6dab9139f | ||
|
|
00f63622b5 | ||
|
|
df73a97efa | ||
|
|
3f223fe5b0 | ||
|
|
658df83280 | ||
|
|
1211c43a47 | ||
|
|
5238dcaa08 | ||
|
|
6a9e6dcae1 | ||
|
|
04cd38f251 | ||
|
|
7be407c8e4 | ||
|
|
d4ca1dfb69 |
150 changed files with 4676 additions and 5634 deletions
34
.github/workflows/build.yml
vendored
34
.github/workflows/build.yml
vendored
|
|
@ -20,6 +20,7 @@ on:
|
|||
- 'clients/**'
|
||||
- 't/**'
|
||||
- 'scripts/**'
|
||||
- 'docs/**'
|
||||
- '.github/workflows/**'
|
||||
|
||||
jobs:
|
||||
|
|
@ -82,7 +83,7 @@ jobs:
|
|||
run: |
|
||||
pacman-key --init
|
||||
pacman -Syu --noconfirm
|
||||
pacman -S --noconfirm git meson clang wlroots0.19 libdrm libinput \
|
||||
pacman -S --noconfirm git meson clang wlroots0.20 libdrm libinput \
|
||||
wayland-protocols cairo pango libxml2 xorg-xwayland librsvg \
|
||||
libdisplay-info gdb ttf-dejavu foot libsfdo cmocka
|
||||
|
||||
|
|
@ -92,9 +93,15 @@ jobs:
|
|||
sed -i '/^Types/ s/deb/& deb-src/' /etc/apt/sources.list.d/debian.sources
|
||||
apt-get update
|
||||
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.19-dev
|
||||
apt-get install -y git gcc clang gdb xwayland meson pkgconf
|
||||
apt-get build-dep -y libwlroots-0.20-dev
|
||||
# Debian Testing temporarily removed labwc due to wlroots 0.20 transition
|
||||
#apt-get build-dep -y labwc
|
||||
# Install the deps manually
|
||||
apt-get install -y libxml2-dev liblzma-dev libglib2.0-dev \
|
||||
libcairo2-dev libpango1.0-dev libinput-dev libpng-dev \
|
||||
librsvg2-dev wayland-protocols libxkbcommon-dev libdrm-dev \
|
||||
scdoc gettext libwlroots-0.20-dev libsfdo-dev
|
||||
|
||||
- name: Install FreeBSD dependencies
|
||||
if: matrix.name == 'FreeBSD'
|
||||
|
|
@ -106,7 +113,7 @@ jobs:
|
|||
pkg set -yn pkg:mesa-dri # hack to skip llvm dependency
|
||||
pkg install -y git pcre2 meson gcc pkgconf cairo pango evdev-proto \
|
||||
hwdata wayland-protocols libdisplay-info libepoll-shim \
|
||||
wlroots019
|
||||
wlroots020
|
||||
run: echo "setup done"
|
||||
|
||||
- name: Install Void Linux dependencies
|
||||
|
|
@ -120,8 +127,8 @@ jobs:
|
|||
xbps-install -Syu
|
||||
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
|
||||
pango-devel wlroots0.20-devel gdb bash xorg-server-xwayland \
|
||||
dejavu-fonts-ttf libsfdo-devel foot hwids
|
||||
|
||||
# These builds are executed on all runners
|
||||
- name: Build with gcc
|
||||
|
|
@ -209,6 +216,19 @@ jobs:
|
|||
meson compile -C build-gcc-no-feature
|
||||
' | $TARGET
|
||||
|
||||
# No backend build, run on Arch only
|
||||
- name: Build with gcc - no-backends test
|
||||
if: matrix.name == 'Arch'
|
||||
run: |
|
||||
echo '
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
export CC=gcc
|
||||
meson setup build-gcc-no-backends \
|
||||
-Dwlroots:backends= -Dwlroots:session=disabled --werror \
|
||||
--force-fallback-for=wlroots
|
||||
meson compile -C build-gcc-no-backends
|
||||
' | $TARGET
|
||||
|
||||
# Unit tests, run on Arch only
|
||||
- name: Build with gcc - unit test
|
||||
if: matrix.name == 'Arch'
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
- [6. Unit Tests](#unit-tests)
|
||||
- [7. Submitting Patches](#submitting-patches)
|
||||
- [8. Native Language Support](#native-language-support)
|
||||
- [9. Upversion](#upversion)
|
||||
- [9. Tools](#tools)
|
||||
- [10. Upversion](#upversion)
|
||||
|
||||
# How to Contribute
|
||||
|
||||
|
|
@ -472,6 +473,29 @@ This generates a new pot file at `po/labwc.pot`
|
|||
3. Copy the header from the original `labwc.pot` to the new one, keeping
|
||||
the newly generated dates, check for sanity and commit.
|
||||
|
||||
# Tools
|
||||
|
||||
We permit LLM and AI-assisted tooling, but only on the basis that humans remain
|
||||
fully accountable. Contributors must use an `Assisted-by:` tag in the commit
|
||||
logs if AI tools generated or significantly assisted with any part of the code
|
||||
or documentation. Humans retain full legal and technical responsibility for the
|
||||
resulting work, including any defects.
|
||||
|
||||
We have received Pull Requests where the submitter clearly did not understand
|
||||
the code, could not reason about it, and would be unable to maintain it. This
|
||||
is not acceptable.
|
||||
|
||||
Any AI-generated code contribution must be compatible with the GPL-2.0-only
|
||||
license.
|
||||
|
||||
While LLMs can be useful for triage, review, clean-up, API refactoring and
|
||||
similar tasks, we strongly discourage AI slop. Code review effort is usually the
|
||||
project's primary bottleneck, and submitting unreviewed, AI-generated garbage
|
||||
wastes reviewer time, slows development, and harms the overall health of the
|
||||
project. Likewise, AI-generated commit messages and AI-written text in issues
|
||||
and discussions are strongly discouraged and may be treated as sabotage on this
|
||||
basis.
|
||||
|
||||
# Upversion
|
||||
|
||||
It is generally only the lead-maintainer who will upversion, but in order
|
||||
|
|
|
|||
341
NEWS.md
341
NEWS.md
|
|
@ -9,6 +9,11 @@ The format is based on [Keep a Changelog]
|
|||
|
||||
| Date | All Changes | wlroots version | lines-of-code |
|
||||
|------------|---------------|-----------------|---------------|
|
||||
| 2026-06-15 | [0.20.1] | 0.20.1 | 28337 |
|
||||
| 2026-05-25 | [0.20.0] | 0.20.1 | 28313 |
|
||||
| 2026-06-11 | [0.9.8] | 0.19.3 | 29284 |
|
||||
| 2026-04-17 | [0.9.7] | 0.19.2 | 29277 |
|
||||
| 2026-03-15 | [0.9.6] | 0.19.2 | 29271 |
|
||||
| 2026-03-04 | [0.9.5] | 0.19.2 | 29251 |
|
||||
| 2026-02-27 | [0.9.4] | 0.19.2 | 29225 |
|
||||
| 2025-12-19 | [0.9.3] | 0.19.2 | 28968 |
|
||||
|
|
@ -42,6 +47,11 @@ The format is based on [Keep a Changelog]
|
|||
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
|
||||
|
||||
[unreleased]: NEWS.md#unreleased
|
||||
[0.20.1]: NEWS.md#0201---2026-06-15
|
||||
[0.20.0]: NEWS.md#0200---2026-05-25
|
||||
[0.9.8]: NEWS.md#098---2026-06-11
|
||||
[0.9.7]: NEWS.md#097---2026-04-17
|
||||
[0.9.6]: NEWS.md#096---2026-03-15
|
||||
[0.9.5]: NEWS.md#095---2026-03-04
|
||||
[0.9.4]: NEWS.md#094---2026-02-27
|
||||
[0.9.3]: NEWS.md#093---2025-12-19
|
||||
|
|
@ -74,6 +84,138 @@ The format is based on [Keep a Changelog]
|
|||
[0.2.0]: NEWS.md#020---2021-04-15
|
||||
[0.1.0]: NEWS.md#010---2021-03-05
|
||||
|
||||
## unreleased
|
||||
|
||||
[unreleased-commits]
|
||||
|
||||
## Notes on wlroots-0.20
|
||||
|
||||
There are some regression warnings worth noting for the switch to wlroots 0.20:
|
||||
|
||||
- lxqt-panel auto-hiding does not work with a panel size greater than 40 [#3600]
|
||||
[wlroots-5392]
|
||||
- Some Wine game windows disappear after alt-tab. It is not yet clear where the
|
||||
bug is, but the issue manifests itself when running wlroots-0.20 [#3615]
|
||||
[wlroots-4103]
|
||||
|
||||
[wlroots-5392]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5392
|
||||
[wlroots-4103]: https://gitlab.freedesktop.org/wlroots/wlroots/-/work_items/4103
|
||||
|
||||
## 0.20.1 - 2026-06-15
|
||||
|
||||
[0.20.1-commits]
|
||||
|
||||
This is a small bug fix release.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle titles with no visible characters, for example the left-to-right mark
|
||||
(‎) @Consolatis [#3630]
|
||||
- Protect against SIGABRT when TTY switching in unusual circumstances by
|
||||
ensuring that xdg-shell windows have sensible width and height before trying
|
||||
to set size on configure. This protects against an edge case experienced when
|
||||
switching between labwc on one TTY and Xfce on XOrg on another TTY.
|
||||
@johanmalm @Tamaranch [#3617]
|
||||
|
||||
## 0.20.0 - 2026-05-25
|
||||
|
||||
[0.20.0-commits]
|
||||
|
||||
This is the first release using wlroots-0.20 and therefore has an increased risk
|
||||
of teething issues. Many thanks to @Consolatis for leading the effort to port
|
||||
across [#2956].
|
||||
|
||||
In terms of new features, the most noteworthy ones include: (i) the frequently
|
||||
requested show-desktop action; (ii) initial toplevel capture support to
|
||||
screenshot specific windows; (iii) menu accelerators/shortcuts; and (iv) HDR10
|
||||
support when running with the Vulkan renderer option.
|
||||
|
||||
The eagle-eyed amongst you will have noticed the sudden jump from labwc `0.9.7`
|
||||
to `0.20.0`. The reason for this is to align the minor number to that of the
|
||||
wlroots version against which the compositor is linked.
|
||||
|
||||
The 0.9.x series has turned into a maintenance branch named v0.9 with bug fixes
|
||||
only, for anyone preferring to build with wlroots-0.19.
|
||||
|
||||
Note to maintainers:
|
||||
|
||||
- libinput >=1.26 is required in support of tablet tool pressure range
|
||||
configuration.
|
||||
- wlroots >=0.20.1 is required to avoid some bugs that we do not want labwc to
|
||||
ship with. For details, see:
|
||||
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5325
|
||||
|
||||
### Added
|
||||
|
||||
- Partially support toplevel-capture. Note that the following are not yet
|
||||
implemented: (i) XWayland child windows; (ii) XWayland unmanaged windows
|
||||
(e.g. popups); (iii) xdg child window positioning; (iv) xdg subsurfaces;
|
||||
and (v) xdg popup positioning. [#2968] @Consolatis
|
||||
- Add command line option -t|--title to set the labwc window title when running
|
||||
nested [#3577] @mdsib
|
||||
- Add support for HDR10 output @kode54 @Consolatis [#3424]
|
||||
- Include wlroots version in --version string @Consolatis [#3567] [#3581]
|
||||
- Implement menu accelerators (one-letter mnemonics to quickly select/exec
|
||||
items from the current menu) @ch3rn1ka [#3505]
|
||||
- Add Next/PreviousWindowImmediate actions @elviosak @johanmalm [#3547]
|
||||
- Add labnag options `--details-border-color` and `--details-margin`
|
||||
@st0rm-shad0w [#3527]
|
||||
- Add config option `<focus><raiseOnFocusDelay>` to defer raise-on-focus by a
|
||||
small amount when `raiseOnFocus` is enabled @joske [#3513]
|
||||
- Install `labwc-session.target` systemd user unit when the systemd dependency
|
||||
is available @joske [#3534]
|
||||
- Add `onbutton` to config option `<libinput><device><scrollMethod>`. Also add
|
||||
associated option `<libinput><device><scrollButton>`. @diniamo [#3540]
|
||||
- Add `overrideInhibition` option to `<keybind>` [#3507] @drougas
|
||||
- Add action `ToggleShowDesktop` to hide/unhide windows, and default keybind
|
||||
`Super-d` to trigger this action [#3500] [#3595] @johanmalm
|
||||
- Add `<privilegedInterfaces>` config option so that privileged protocols can be
|
||||
restricted [#3493] @xi
|
||||
- Add action `DebugToggleKeyStateIndicator` to show a key-state on-screen
|
||||
display (OSD) for debugging. [#3499] @johanmalm @tokyo4j
|
||||
- Add support for `color-management-v1` and `color-representation-manager-v1`
|
||||
protocols [#3469] @ManuLinares
|
||||
- Add configuration option `<tabletTool minPressure="0.0" maxPressure="1.0" />`
|
||||
to enable tablet tool pressure range libinput settings [#2916] @jp7677
|
||||
- Add `wl_fixes` interface [#2956] @kode54
|
||||
|
||||
### Fixed
|
||||
|
||||
- Enable labnag long option --exclusive-zone [#3576] @st0rm-shad0w
|
||||
- Position chromium popup correctly when a window is maximized on a multi-
|
||||
output setup @elviosak [#3547]
|
||||
- Run session activation environment update synchronously to avoid a race
|
||||
condition with the autostart script [#3543] @joske
|
||||
- Allow interactive resize on fully maximized windows so that a resize
|
||||
initiated by modifier plus right-mouse-button-drag is not ignored [#3525]
|
||||
@bjorn
|
||||
- Gracefully handle missing XWayland packages, so that a labwc compositor which
|
||||
has been built with XWayland support (which is optional) can be run even if
|
||||
XWayland is not installed. [#3401] @quite
|
||||
- Rework how XWayland window initial geometry is set to ensure that the natural
|
||||
geometry does not exceed the usable output area when handling initial
|
||||
maximize/fullscreen requests. [#3439] @jlindgren90.
|
||||
- For XWayland windows, sync always-on-top state back to X.Org Server. This
|
||||
makes `wmctrl -b toggle,above` work. [#3446] @jlindgren90
|
||||
- Fix missing title and icon with XWayland client override-redirect toggle.
|
||||
There are no known issues with clients, so this is purely for preventative
|
||||
purposes. [#3450] @jlindgren90
|
||||
- Update titlebar title when set to empty and fix an associated issue causing
|
||||
the title to be misplaced outside of the titlebar when the window is resized.
|
||||
[#3443] @tokyo4j
|
||||
- When running nested, exit compositor when last output is destroyed because
|
||||
in this situation, each output corresponds to a window in the parent
|
||||
compositor and, unlike DRM outputs, these cannot be reconnected after being
|
||||
destroyed. [#3440] @marler8997
|
||||
- Allow policy-based placement to apply when an initially-maximized/fullscreen
|
||||
view is restored to floating geometry. [#3387] [#3502] @jlindgren90
|
||||
|
||||
### Changed
|
||||
|
||||
- Change the default keybinds for XF86Audio{LowerVolume,RaiseVolume,Mute} to use
|
||||
pactl instead of amixer [#3484] @danielrrrr
|
||||
- Drop cosmic-workspace protocol [#3031] @tokyo4j
|
||||
|
||||
## Notes on wlroots-0.19
|
||||
|
||||
There are some regression warnings worth noting for the switch to wlroots 0.19:
|
||||
|
|
@ -108,9 +250,73 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
|||
[wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
|
||||
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
|
||||
|
||||
## unreleased
|
||||
## 0.9.8 - 2026-06-11
|
||||
|
||||
[unreleased-commits]
|
||||
[0.9.8-commits]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle titles with no visible characters @Consolatis [#3631]
|
||||
- Save window position on initial placement to fix Raspberry Pi pygame SDL
|
||||
XWayland window starting off-screen. @tokyo4j [#3433] [#3625] [#3616]
|
||||
|
||||
## 0.9.7 - 2026-04-17
|
||||
|
||||
[0.9.7-commits]
|
||||
|
||||
This is a small bug fix release.
|
||||
|
||||
```
|
||||
0.9.6--------0.9.7 <--- v0.9 branch with bug-fixes only
|
||||
/
|
||||
/
|
||||
0.9.4--------0.9.5-------- <-- master (built with wlroots-0.20)
|
||||
```
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fix intermittent failed-to-get-texture issue with some clients (e.g. foot)
|
||||
when using the window-switcher in the thumbnail mode. [#3511] @yuiiio
|
||||
- Fix tablet tool tilt motion. [#3494] @jp7677
|
||||
- Handle window-switcher buffer allocation failure when in 'thumbnail' mode.
|
||||
This is believed to be very unlikely to happen, but has been reported by one
|
||||
user and is believed to be GPU driver related. [#3490] @Consolatis
|
||||
|
||||
## 0.9.6 - 2026-03-15
|
||||
|
||||
[0.9.6-commits]
|
||||
|
||||
This is an earlier-than-usual release containing bug fixes only. It has been
|
||||
done on a separate branch (v0.9) to avoid the inclusion of refactoring and new
|
||||
features.
|
||||
|
||||
```
|
||||
0.9.6 <--- bug-fixes only
|
||||
/
|
||||
/
|
||||
0.9.4--------0.9.5-------- <-- master
|
||||
```
|
||||
|
||||
### Fixed
|
||||
|
||||
- Disable outputs where all modes fail [#3428] [#3429] @Consolatis @kode54
|
||||
- Fix regression in `0.9.4` that causes `NextWindow` action to segfault when
|
||||
no outputs are connected. [#3425] [#3430] @Consolatis
|
||||
- Fix typo to allow `xdg-dialog-v1` global [#3426] @xi
|
||||
|
||||
### Changed
|
||||
|
||||
- Disallow X11 window always-on-top requests by default to fix an issue whereby
|
||||
Alt+Tab cannot be used to switch to other windows when using some XWayland
|
||||
Wine games [#3441]. Add window-rule property `allowAlwaysOnTop` to optionally
|
||||
allow this always-on-top requests. Add the snippet below to the `rc.xml` file
|
||||
to restore the previous behaviour. [#3445] @Consolatis
|
||||
|
||||
```
|
||||
<windowRules>
|
||||
<windowRule identifier="*" allowAlwaysOnTop="yes" />
|
||||
</windowRules>
|
||||
```
|
||||
|
||||
## 0.9.5 - 2026-03-04
|
||||
|
||||
|
|
@ -139,9 +345,9 @@ Note to package maintainers: This release requires wayland version >=1.22.90
|
|||
- Add theme option window.button.hover.bg.color [#3365] @johanmalm
|
||||
- Implement scrollable window-switcher OSD [#3291] @tokyo4j
|
||||
- Support the `NextWindow` options listed below [#3271] @tokyo4j
|
||||
- `<action name="NextWindow" workspace="current|all"/>`
|
||||
- `<action name="NextWindow" output="all|focused|cursor"/>`
|
||||
- `<action name="NextWindow" identifier="all|current"/>`
|
||||
- `<action name="NextWindow" workspace="current|all" />`
|
||||
- `<action name="NextWindow" output="all|focused|cursor" />`
|
||||
- `<action name="NextWindow" identifier="all|current" />`
|
||||
- Add config option `*<desktops><initial>` for setting the active workspace on
|
||||
startup. [#3265] @5trixs0f
|
||||
|
||||
|
|
@ -189,7 +395,7 @@ Note to package maintainers: This release requires wayland version >=1.22.90
|
|||
and get keyboard focus so that they can be operated with the keyboard.
|
||||
An example use-case is the xfce4-panel applications-menu being opened by
|
||||
the command xfce4-popup-applicationsmenu. [#3165] @johanmalm
|
||||
- On popup destory, return focus to whoever had it before the popop [#3165]
|
||||
- On popup destroy, return focus to whoever had it before the popop [#3165]
|
||||
@johanmalm @tokyo4j
|
||||
- Unshade window if selected from client-list-combined-menu [#3345] @Amodio
|
||||
- Show non-dialog child windows in window-switcher [#3339] @tokyo4j
|
||||
|
|
@ -223,7 +429,7 @@ A big thank you to all involved in this release.
|
|||
|
||||
### Added
|
||||
|
||||
- Add `<windowSwitcher order="focus|age"/>` to optionally order windows by age
|
||||
- Add `<windowSwitcher order="focus|age" />` to optionally order windows by age
|
||||
rather than most recent focus. @mbroemme [#3229]
|
||||
- Replace `<snapping><range>` with `<snapping><range inner="" outer="">` to
|
||||
provide more granular control when configuring the size of snapping areas
|
||||
|
|
@ -254,7 +460,7 @@ A big thank you to all involved in this release.
|
|||
[#3134]
|
||||
- labnag: add --keyboard-focus option @tokyo4j [#3120]
|
||||
- Allow window switcher to temporarily unshade windows using config option
|
||||
`<windowSwitcher unshade="yes|no"/>` @Amodio @Consolatis [#3124]
|
||||
`<windowSwitcher unshade="yes|no" />` @Amodio @Consolatis [#3124]
|
||||
- For the 'classic' style window-switcher, add the following theme options:
|
||||
- `osd.window-switcher.style-classic.item.active.border.color`
|
||||
- `osd.window-switcher.style-classic.item.active.bg.color`
|
||||
|
|
@ -284,7 +490,7 @@ A big thank you to all involved in this release.
|
|||
client surface. Fixes a regression in 885919f. @tokyo4j [#3211]
|
||||
- Set all foreign-toplevel initial states correctly. This is not believed to fix
|
||||
any particular user-issue, but just feels safer. @jlindgren90 [#3217]
|
||||
- Update layer-shell client top layer visiblity on unmap instead of destroy
|
||||
- Update layer-shell client top layer visibility on unmap instead of destroy
|
||||
because it is possible for fullscreen xwayland windows to be unmapped without
|
||||
being destroyed, and in this case the top layer visibility needs to be updated
|
||||
to unhide other layer-shell clients like panels. @jlindgren90 [#3199]
|
||||
|
|
@ -296,7 +502,7 @@ A big thank you to all involved in this release.
|
|||
@elviosak [#3146] [#3168]
|
||||
- Work around client-side rounding issues at right/bottom pixel. This fixes an
|
||||
issue with some clients (notably Qt ones) where cursor coordinates in the
|
||||
rightmost or bottom fixel are incorrectly rounded up putting them outside the
|
||||
rightmost or bottom pixel are incorrectly rounded up putting them outside the
|
||||
surface bounds. The issue has been particularly noticeable with layer-shell
|
||||
clients like lxqt-panel. @jlindgren90 [#3157] [#2379] [#3099]
|
||||
Note: This also avoids a similar server-side rounding issue with some
|
||||
|
|
@ -344,7 +550,7 @@ A big thank you to all involved in this release.
|
|||
when a window is using fullscreen mode. @johanmalm [#3158]
|
||||
- Call labnag with on-demand keyboard interactivity by default @tokyo4j [#3120]
|
||||
- Temporarily unshade windows when switching windows. Restore old behaviour with
|
||||
`<windowSwitcher unshade="no"/>` @Amodio @Consolatis [#3124]
|
||||
`<windowSwitcher unshade="no" />` @Amodio @Consolatis [#3124]
|
||||
- In the classic style window-switcher, the default color of the selected window
|
||||
item has been changed to inherit the border color but with 15% opacity
|
||||
@tokyo4j [#3118]
|
||||
|
|
@ -363,7 +569,7 @@ A big thank you to all involved in this release.
|
|||
`<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 `<theme maximizedDecoration="titlebar|none"/>` to allow hiding titlebar
|
||||
- Add `<theme 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
|
||||
@johanmalm [#2995]
|
||||
|
|
@ -414,7 +620,7 @@ A big thank you to all involved in this release.
|
|||
- Change default keybind `W-<arrow>` to combine cardinal directions to support
|
||||
resizing of windows to fill a quarter of an output. This only affects users
|
||||
who do not use an `rc.xml` (thereby using default keybinds) or use the
|
||||
`<keyboard><default/>` option. Previous behavior can be restored by setting
|
||||
`<keyboard><default />` option. Previous behavior can be restored by setting
|
||||
`combine="no"` as shown below. [#3081] @tokyo4j
|
||||
|
||||
```
|
||||
|
|
@ -513,7 +719,7 @@ window.*.title.bg.colorTo.splitTo:
|
|||
window rule to enable this. @Consolatis @tokyo4j [#2840]
|
||||
- Add config option `<core><primarySelection>`. This enables autoscroll
|
||||
(middle-click to scroll up/down) in Chromium and electron based clients
|
||||
without inadvertantly pasting the primary clipboard. @johanmalm [#2832]
|
||||
without inadvertently pasting the primary clipboard. @johanmalm [#2832]
|
||||
- Bump `xdg_shell` version from 3 to 6 @tokyo4j [#2814]
|
||||
- Bump `wl_compositor` version from 5 to 6 @tokyo4j [#2812]
|
||||
- Support tablet tool mouse buttons @jp7677 [#2778]
|
||||
|
|
@ -590,7 +796,7 @@ window.*.title.bg.colorTo.splitTo:
|
|||
agnostic on choice of launcher.
|
||||
- `A-<arrow>` for `MoveToEdge` because `Alt-` keybinds should be for clients
|
||||
to use and this one results in frequent user complaints because it prevents
|
||||
some common usage patterns like alt-left/right in web browers.
|
||||
some common usage patterns like alt-left/right in web browsers.
|
||||
- Change default titlebar menu button from a dot to an arrow @johanmalm [#2844]
|
||||
- When `dragLock` is set to `yes`, the drag no longer expires after a short
|
||||
delay (known as `Sticky` mode) as recommended by libinput [#2803]. The timeout
|
||||
|
|
@ -625,7 +831,7 @@ release.
|
|||
- Localize desktop-entry application names used by the window switcher via
|
||||
`desktop_entry_name` or the `%n` specifier @tokyo4j [#2653]
|
||||
- Add `HideCursor` action @jp7677 [#2633]
|
||||
- Support application icons in window-switcher using `<field content="icon"/>`
|
||||
- Support application icons in window-switcher using `<field content="icon" />`
|
||||
and use this by default. @tokyo4j [#2621]
|
||||
- Support application icons in client-list-combined-menu @tokyo4j [#2617]
|
||||
- Support the use of the keypad-enter key when using menu. @zeusgoose [#2610]
|
||||
|
|
@ -762,7 +968,7 @@ Notes to package maintainers:
|
|||
closing a popup did not move the pointer focus to the main toplevel until the
|
||||
cursor was moved. [#2443]
|
||||
- Improve algorithm for menu placement with xdg-positioner [#2408]
|
||||
- Do not forward IME key-release without correspinding key-press to avoid stuck
|
||||
- Do not forward IME key-release without corresponding key-press to avoid stuck
|
||||
keys [#2437]
|
||||
|
||||
### Changed
|
||||
|
|
@ -824,7 +1030,7 @@ Notes to package maintainers:
|
|||
|
||||
```xml
|
||||
<windowRules>
|
||||
<windowRule identifier="blender" wantAbsorbedModifierReleaseEvents="yes"/>
|
||||
<windowRule identifier="blender" wantAbsorbedModifierReleaseEvents="yes" />
|
||||
</windowRules>
|
||||
```
|
||||
|
||||
|
|
@ -841,8 +1047,8 @@ menu.border.color: #aaaaaa
|
|||
```xml
|
||||
<windowSwitcher>
|
||||
<fields>
|
||||
<field content="custom" format="%n" width="25%"/>
|
||||
<field content="title" width="75%"/>
|
||||
<field content="custom" format="%n" width="25%" />
|
||||
<field content="title" width="75%" />
|
||||
</fields>
|
||||
</windowSwitcher>
|
||||
```
|
||||
|
|
@ -972,7 +1178,7 @@ Notes to package maintainers:
|
|||
- Support the openbox style menus listed below. Written-by: @droc12345
|
||||
1. `client-list-combined-menu` shows windows across all workspaces. This can
|
||||
be used with a mouse/key bind using:
|
||||
`<action name="ShowMenu" menu="client-list-combined-menu"/>` [#2101]
|
||||
`<action name="ShowMenu" menu="client-list-combined-menu" />` [#2101]
|
||||
2. `client-send-to` shows all workspaces that the current window can be sent
|
||||
to. This can additional be used within a client menu using:
|
||||
`<menu id="client-send-to-menu" label="Send to Workspace..." />` [#2152]
|
||||
|
|
@ -1131,14 +1337,14 @@ have been attributed with a 'Written-by' against each relevant log entry.
|
|||
```xml
|
||||
<placement>
|
||||
<policy>cascade</policy>
|
||||
<cascadeOffset x="40" y="30"/>
|
||||
<cascadeOffset x="40" y="30" />
|
||||
</placement>
|
||||
```
|
||||
|
||||
- Support relative tablet motion. Written-by: @jp7677 [#1962]
|
||||
|
||||
```xml
|
||||
<tabletTool motion="absolute|relative" relativeMotionSensitivity="1.0"/>
|
||||
<tabletTool motion="absolute|relative" relativeMotionSensitivity="1.0" />
|
||||
```
|
||||
|
||||
### Fixed
|
||||
|
|
@ -1222,7 +1428,7 @@ joint effort by @spl237 and @Consolatis.
|
|||
- Respect `menu.overlap.x` when using pipemenus. [#1940]
|
||||
- Do not try to restore windows to very small width/height on unmaximize.
|
||||
This fixes a bug with Thonny (Python IDE made with Tk). [#1938]
|
||||
- Conditially set squared server-side decoration (SSD) corners when a view is
|
||||
- Conditionally set squared server-side decoration (SSD) corners when a view is
|
||||
tiled. Written-by: @jp7677 [#1926]
|
||||
- Remember initial direction when starting window-cycling with `PreviousView`.
|
||||
Also make the toggling of direction when shift is pressed relative to the
|
||||
|
|
@ -1246,7 +1452,7 @@ joint effort by @spl237 and @Consolatis.
|
|||
Chromium and Steam. [#1861]
|
||||
- Session-lock: fix flashing & update cursor shape. [#1858]
|
||||
- Remove tearing-controller listeners on destroy. [#1853]
|
||||
- Handle invalid `ForEach` and `If` action cofigs. [#1838]
|
||||
- Handle invalid `ForEach` and `If` action configs. [#1838]
|
||||
- Delay startup of applications until event loop is ready. This avoids race
|
||||
conditions when using autostart scripts that trigger a labwc SIGHUP. [#1588]
|
||||
- With `SendToDesktop` action follow=no option, ensure the topmost window is
|
||||
|
|
@ -1263,7 +1469,7 @@ joint effort by @spl237 and @Consolatis.
|
|||
|
||||
- Remove subprojects/seatd.wrap as no longer needed
|
||||
- Action `MoveToCursor` is deprecated in favour of:
|
||||
`<action name="AutoPlace" policy="cursor"/>`.
|
||||
`<action name="AutoPlace" policy="cursor" />`.
|
||||
|
||||
## 0.7.2 - 2024-05-10
|
||||
|
||||
|
|
@ -1280,7 +1486,7 @@ contributions from others as noted in the log.
|
|||
### Added
|
||||
|
||||
- Add `<menu><ignoreButtonReleasePeriod>` to prevent clicks with small movements
|
||||
from inadvertantly closing a menu or selecting a menu item. This is the
|
||||
from inadvertently closing a menu or selecting a menu item. This is the
|
||||
equivalent of `<menu><hideDelay>` on Openbox. [#1760]
|
||||
- Support drop-shadows (disabled by default) for windows using server-side
|
||||
decorations. Written-by: @cillian64
|
||||
|
|
@ -1308,7 +1514,7 @@ window.inactive.shadow.color: #00000040
|
|||
|
||||
```xml
|
||||
<action name="ForEach">
|
||||
<query identifier="foo"/>
|
||||
<query identifier="foo" />
|
||||
<then>
|
||||
<!-- carry out some action on match -->
|
||||
</then>
|
||||
|
|
@ -1350,7 +1556,7 @@ osd.window-switcher.width: 75%
|
|||
<snapping>
|
||||
<overlay>
|
||||
<enabled>yes|no</enabled>
|
||||
<delay inner="500" outer="500"/>
|
||||
<delay inner="500" outer="500" />
|
||||
</overlay>
|
||||
</snapping>
|
||||
```
|
||||
|
|
@ -1513,7 +1719,7 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff
|
|||
|
||||
```xml
|
||||
<keybind key="A-Space">
|
||||
<action name="ShowMenu" menu="client-menu" atCursor="No"/>
|
||||
<action name="ShowMenu" menu="client-menu" atCursor="No" />
|
||||
</keybind>
|
||||
```
|
||||
|
||||
|
|
@ -1521,7 +1727,7 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff
|
|||
is already used by the action itself). [#1589]
|
||||
|
||||
```xml
|
||||
<action name="MoveToOutput" output="HDMI-A-1"/>
|
||||
<action name="MoveToOutput" output="HDMI-A-1" />
|
||||
```
|
||||
|
||||
- Do not deactivate window when giving keyboard focus to a non-view
|
||||
|
|
@ -1586,8 +1792,8 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff
|
|||
Written-by: @jp7677
|
||||
|
||||
```xml
|
||||
<touch mapToOutput=""/>
|
||||
<touch deviceName="" mapToOutput=""/>
|
||||
<touch mapToOutput="" />
|
||||
<touch deviceName="" mapToOutput="" />
|
||||
```
|
||||
|
||||
- Add tablet support including:
|
||||
|
|
@ -1800,7 +2006,7 @@ relating to surface focus and keyboard issues, amongst others.
|
|||
- Allow referencing the current workspace in actions, for example:
|
||||
|
||||
```xml
|
||||
<action name="SendToDesktop" to="current"/>
|
||||
<action name="SendToDesktop" to="current" />
|
||||
```
|
||||
|
||||
### Fixed
|
||||
|
|
@ -1956,7 +2162,7 @@ relating to surface focus and keyboard issues, amongst others.
|
|||
```xml
|
||||
<windowSwitcher>
|
||||
<fields>
|
||||
<field content="identifier" width="25%"/>
|
||||
<field content="identifier" width="25%" />
|
||||
</fields>
|
||||
</windowSwithcer>
|
||||
```
|
||||
|
|
@ -2023,9 +2229,9 @@ relating to surface focus and keyboard issues, amongst others.
|
|||
```xml
|
||||
<windowRules>
|
||||
<windowRule identifier="some-application">
|
||||
<action name="Maximize"/>
|
||||
<action name="Maximize" />
|
||||
</windowRule>
|
||||
<windowRule identifier="foo*" serverDecoration="yes|no"/>
|
||||
<windowRule identifier="foo*" serverDecoration="yes|no" />
|
||||
</windowRules>
|
||||
```
|
||||
|
||||
|
|
@ -2110,7 +2316,7 @@ Unless otherwise stated all contributions are by the core-devs
|
|||
|
||||
```xml
|
||||
<keyboard>
|
||||
<default/>
|
||||
<default />
|
||||
<keybind key="A-Left"><action name="None" /></keybind>
|
||||
<keybind key="A-Right"><action name="None" /></keybind>
|
||||
</keyboard>
|
||||
|
|
@ -2374,7 +2580,7 @@ reported, tested and fixed issues. Particular mentions go to @bi4k8,
|
|||
actions to be de-coupled from buttons. As a result, "Drag" and
|
||||
"DoubleClick" actions previously defined against "TitleBar" should now
|
||||
come under the "Title" context, for example:
|
||||
`<mousebind button="Left" action="Drag"><action name="Move"/></mousebind>`
|
||||
`<mousebind button="Left" action="Drag"><action name="Move" /></mousebind>`
|
||||
- Remove default alt-escape keybind for Exit because too many people have
|
||||
exited the compositor by mistake trying to get out of alt-tab cycling
|
||||
or similar.
|
||||
|
|
@ -2607,7 +2813,12 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
ShowMenu
|
||||
|
||||
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
|
||||
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.9.5...HEAD
|
||||
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.20.1...HEAD
|
||||
[0.20.1-commits]: https://github.com/labwc/labwc/compare/0.20.0..0.20.1
|
||||
[0.20.0-commits]: https://github.com/labwc/labwc/compare/0.9.5..0.20.0
|
||||
[0.9.8-commits]: https://github.com/labwc/labwc/compare/0.9.7...0.9.8
|
||||
[0.9.7-commits]: https://github.com/labwc/labwc/compare/0.9.6...0.9.7
|
||||
[0.9.6-commits]: https://github.com/labwc/labwc/compare/0.9.5...0.9.6
|
||||
[0.9.5-commits]: https://github.com/labwc/labwc/compare/0.9.4...0.9.5
|
||||
[0.9.4-commits]: https://github.com/labwc/labwc/compare/0.9.3...0.9.4
|
||||
[0.9.3-commits]: https://github.com/labwc/labwc/compare/0.9.2...0.9.3
|
||||
|
|
@ -3046,6 +3257,7 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
[#2909]: https://github.com/labwc/labwc/pull/2909
|
||||
[#2910]: https://github.com/labwc/labwc/pull/2910
|
||||
[#2914]: https://github.com/labwc/labwc/pull/2914
|
||||
[#2916]: https://github.com/labwc/labwc/pull/2916
|
||||
[#2933]: https://github.com/labwc/labwc/pull/2933
|
||||
[#2937]: https://github.com/labwc/labwc/pull/2937
|
||||
[#2939]: https://github.com/labwc/labwc/pull/2939
|
||||
|
|
@ -3053,8 +3265,10 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
[#2943]: https://github.com/labwc/labwc/pull/2943
|
||||
[#2944]: https://github.com/labwc/labwc/pull/2944
|
||||
[#2948]: https://github.com/labwc/labwc/pull/2948
|
||||
[#2956]: https://github.com/labwc/labwc/pull/2956
|
||||
[#2965]: https://github.com/labwc/labwc/pull/2965
|
||||
[#2967]: https://github.com/labwc/labwc/pull/2967
|
||||
[#2968]: https://github.com/labwc/labwc/pull/2968
|
||||
[#2970]: https://github.com/labwc/labwc/pull/2970
|
||||
[#2971]: https://github.com/labwc/labwc/pull/2971
|
||||
[#2972]: https://github.com/labwc/labwc/pull/2972
|
||||
|
|
@ -3070,6 +3284,7 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
[#3020]: https://github.com/labwc/labwc/pull/3020
|
||||
[#3024]: https://github.com/labwc/labwc/pull/3024
|
||||
[#3028]: https://github.com/labwc/labwc/pull/3028
|
||||
[#3031]: https://github.com/labwc/labwc/pull/3031
|
||||
[#3033]: https://github.com/labwc/labwc/pull/3033
|
||||
[#3039]: https://github.com/labwc/labwc/pull/3039
|
||||
[#3042]: https://github.com/labwc/labwc/pull/3042
|
||||
|
|
@ -3135,8 +3350,54 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
|||
[#3365]: https://github.com/labwc/labwc/pull/3365
|
||||
[#3372]: https://github.com/labwc/labwc/pull/3372
|
||||
[#3373]: https://github.com/labwc/labwc/pull/3373
|
||||
[#3387]: https://github.com/labwc/labwc/pull/3387
|
||||
[#3400]: https://github.com/labwc/labwc/pull/3400
|
||||
[#3401]: https://github.com/labwc/labwc/pull/3401
|
||||
[#3406]: https://github.com/labwc/labwc/pull/3406
|
||||
[#3410]: https://github.com/labwc/labwc/pull/3410
|
||||
[#3411]: https://github.com/labwc/labwc/pull/3411
|
||||
[#3412]: https://github.com/labwc/labwc/pull/3412
|
||||
[#3424]: https://github.com/labwc/labwc/pull/3424
|
||||
[#3425]: https://github.com/labwc/labwc/pull/3425
|
||||
[#3426]: https://github.com/labwc/labwc/pull/3426
|
||||
[#3428]: https://github.com/labwc/labwc/pull/3428
|
||||
[#3429]: https://github.com/labwc/labwc/pull/3429
|
||||
[#3430]: https://github.com/labwc/labwc/pull/3430
|
||||
[#3433]: https://github.com/labwc/labwc/pull/3433
|
||||
[#3439]: https://github.com/labwc/labwc/pull/3439
|
||||
[#3440]: https://github.com/labwc/labwc/pull/3440
|
||||
[#3441]: https://github.com/labwc/labwc/pull/3441
|
||||
[#3443]: https://github.com/labwc/labwc/pull/3443
|
||||
[#3445]: https://github.com/labwc/labwc/pull/3445
|
||||
[#3446]: https://github.com/labwc/labwc/pull/3446
|
||||
[#3450]: https://github.com/labwc/labwc/pull/3450
|
||||
[#3469]: https://github.com/labwc/labwc/pull/3469
|
||||
[#3484]: https://github.com/labwc/labwc/pull/3484
|
||||
[#3490]: https://github.com/labwc/labwc/pull/3490
|
||||
[#3493]: https://github.com/labwc/labwc/pull/3493
|
||||
[#3494]: https://github.com/labwc/labwc/pull/3494
|
||||
[#3499]: https://github.com/labwc/labwc/pull/3499
|
||||
[#3500]: https://github.com/labwc/labwc/pull/3500
|
||||
[#3502]: https://github.com/labwc/labwc/pull/3502
|
||||
[#3505]: https://github.com/labwc/labwc/pull/3505
|
||||
[#3507]: https://github.com/labwc/labwc/pull/3507
|
||||
[#3511]: https://github.com/labwc/labwc/pull/3511
|
||||
[#3513]: https://github.com/labwc/labwc/pull/3513
|
||||
[#3525]: https://github.com/labwc/labwc/pull/3525
|
||||
[#3527]: https://github.com/labwc/labwc/pull/3527
|
||||
[#3534]: https://github.com/labwc/labwc/pull/3534
|
||||
[#3540]: https://github.com/labwc/labwc/pull/3540
|
||||
[#3543]: https://github.com/labwc/labwc/pull/3543
|
||||
[#3547]: https://github.com/labwc/labwc/pull/3547
|
||||
[#3567]: https://github.com/labwc/labwc/pull/3567
|
||||
[#3576]: https://github.com/labwc/labwc/pull/3576
|
||||
[#3577]: https://github.com/labwc/labwc/pull/3577
|
||||
[#3581]: https://github.com/labwc/labwc/pull/3581
|
||||
[#3595]: https://github.com/labwc/labwc/pull/3595
|
||||
[#3600]: https://github.com/labwc/labwc/pull/3600
|
||||
[#3615]: https://github.com/labwc/labwc/pull/3615
|
||||
[#3616]: https://github.com/labwc/labwc/pull/3616
|
||||
[#3617]: https://github.com/labwc/labwc/pull/3617
|
||||
[#3625]: https://github.com/labwc/labwc/pull/3625
|
||||
[#3630]: https://github.com/labwc/labwc/pull/3630
|
||||
[#3631]: https://github.com/labwc/labwc/pull/3631
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -153,7 +153,7 @@ Build dependencies include:
|
|||
- meson, ninja, gcc/clang
|
||||
- wayland-protocols
|
||||
|
||||
Disable xwayland with `meson -Dxwayland=disabled build/`
|
||||
Disable xwayland with `meson setup -Dxwayland=disabled build/`
|
||||
|
||||
For OS/distribution specific details see [wiki].
|
||||
|
||||
|
|
@ -213,15 +213,16 @@ If you have not created an rc.xml config file, default bindings will be:
|
|||
| `super`-`return` | lab-sensible-terminal
|
||||
| `alt`-`F4` | close window
|
||||
| `super`-`a` | toggle maximize
|
||||
| `super`-`d` | toggle show-desktop
|
||||
| `super`-`mouse-left` | move window
|
||||
| `super`-`mouse-right` | resize window
|
||||
| `super`-`arrow` | resize window to fill half the output
|
||||
| `alt`-`space` | show the window menu
|
||||
| `XF86_AudioLowerVolume` | amixer sset Master 5%-
|
||||
| `XF86_AudioRaiseVolume` | amixer sset Master 5%+
|
||||
| `XF86_AudioMute` | amixer sset Master toggle
|
||||
| `XF86_MonBrightnessUp` | brightnessctl set +10%
|
||||
| `XF86_MonBrightnessDown` | brightnessctl set 10%-
|
||||
| `XF86AudioLowerVolume` | pactl set-sink-volume @DEFAULT_SINK@ -5%
|
||||
| `XF86AudioRaiseVolume` | pactl set-sink-volume @DEFAULT_SINK@ +5%
|
||||
| `XF86AudioMute` | pactl set-sink-mute @DEFAULT_SINK@ toggle
|
||||
| `XF86MonBrightnessUp` | brightnessctl set +10%
|
||||
| `XF86MonBrightnessDown` | brightnessctl set 10%-
|
||||
|
||||
A root-menu can be opened by clicking on the desktop.
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ struct conf {
|
|||
uint32_t button_text;
|
||||
uint32_t button_background;
|
||||
uint32_t details_background;
|
||||
uint32_t details_border_color;
|
||||
uint32_t background;
|
||||
uint32_t text;
|
||||
uint32_t button_border;
|
||||
|
|
@ -60,6 +61,7 @@ struct conf {
|
|||
ssize_t button_gap_close;
|
||||
ssize_t button_margin_right;
|
||||
ssize_t button_padding;
|
||||
ssize_t details_margin;
|
||||
};
|
||||
|
||||
struct pointer {
|
||||
|
|
@ -206,6 +208,16 @@ static void
|
|||
get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height,
|
||||
int *baseline, double scale, bool markup, const char *fmt, ...)
|
||||
{
|
||||
if (width) {
|
||||
*width = 0;
|
||||
}
|
||||
if (height) {
|
||||
*height = 0;
|
||||
}
|
||||
if (baseline) {
|
||||
*baseline = 0;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
gchar *buf = g_strdup_vprintf(fmt, args);
|
||||
|
|
@ -290,10 +302,10 @@ render_details_scroll_button(cairo_t *cairo, struct nag *nag,
|
|||
get_text_size(cairo, nag->conf->font_description, &text_width,
|
||||
&text_height, NULL, 1, true, "%s", button->text);
|
||||
|
||||
int border = nag->conf->button_border_thickness;
|
||||
int padding = nag->conf->button_padding;
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int padding = (nag->conf->button_padding / 3) + 2;
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_background);
|
||||
cairo_set_source_u32(cairo, nag->conf->details_border_color);
|
||||
cairo_rectangle(cairo, button->x, button->y,
|
||||
button->width, button->height);
|
||||
cairo_fill(cairo);
|
||||
|
|
@ -306,7 +318,7 @@ render_details_scroll_button(cairo_t *cairo, struct nag *nag,
|
|||
|
||||
cairo_set_source_u32(cairo, nag->conf->button_text);
|
||||
cairo_move_to(cairo, button->x + border + padding,
|
||||
button->y + border + (button->height - text_height) / 2);
|
||||
button->y + (button->height - text_height) / 2);
|
||||
render_text(cairo, nag->conf->font_description, 1, true,
|
||||
"%s", button->text);
|
||||
}
|
||||
|
|
@ -321,8 +333,8 @@ get_detailed_scroll_button_width(cairo_t *cairo, struct nag *nag)
|
|||
NULL, 1, true, "%s", nag->details.button_down.text);
|
||||
|
||||
int text_width = up_width > down_width ? up_width : down_width;
|
||||
int border = nag->conf->button_border_thickness;
|
||||
int padding = nag->conf->button_padding;
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int padding = (nag->conf->button_padding / 3) + 2;
|
||||
|
||||
return text_width + border * 2 + padding * 2;
|
||||
}
|
||||
|
|
@ -333,8 +345,9 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
uint32_t width = nag->width;
|
||||
|
||||
int border = nag->conf->details_border_thickness;
|
||||
int margin = nag->conf->details_margin;
|
||||
int padding = nag->conf->message_padding;
|
||||
int decor = padding + border;
|
||||
int decor = margin + border;
|
||||
|
||||
nag->details.x = decor;
|
||||
nag->details.y = y + decor;
|
||||
|
|
@ -362,7 +375,7 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
bool show_buttons = nag->details.offset > 0;
|
||||
int button_width = get_detailed_scroll_button_width(cairo, nag);
|
||||
if (show_buttons) {
|
||||
nag->details.width -= button_width;
|
||||
nag->details.width += border - button_width;
|
||||
pango_layout_set_width(layout,
|
||||
(nag->details.width - padding * 2) * PANGO_SCALE);
|
||||
}
|
||||
|
|
@ -375,7 +388,7 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
|
||||
if (!show_buttons) {
|
||||
show_buttons = true;
|
||||
nag->details.width -= button_width;
|
||||
nag->details.width += border - button_width;
|
||||
pango_layout_set_width(layout,
|
||||
(nag->details.width - padding * 2) * PANGO_SCALE);
|
||||
}
|
||||
|
|
@ -391,21 +404,29 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
|||
|
||||
nag->details.visible_lines = pango_layout_get_line_count(layout);
|
||||
|
||||
int border_rect_height = nag->details.height + 2 * border;
|
||||
|
||||
if (show_buttons) {
|
||||
nag->details.button_up.x = nag->details.x + nag->details.width;
|
||||
nag->details.button_up.y = nag->details.y;
|
||||
nag->details.button_up.y = nag->details.y - border;
|
||||
nag->details.button_up.width = button_width;
|
||||
nag->details.button_up.height = nag->details.height / 2;
|
||||
nag->details.button_up.height = (border_rect_height + border) / 2;
|
||||
render_details_scroll_button(cairo, nag, &nag->details.button_up);
|
||||
|
||||
nag->details.button_down.x = nag->details.x + nag->details.width;
|
||||
nag->details.button_down.y =
|
||||
nag->details.button_up.y + nag->details.button_up.height;
|
||||
nag->details.button_up.y + nag->details.button_up.height - border;
|
||||
nag->details.button_down.width = button_width;
|
||||
nag->details.button_down.height = nag->details.height / 2;
|
||||
nag->details.button_down.height =
|
||||
border_rect_height - nag->details.button_up.height + border;
|
||||
render_details_scroll_button(cairo, nag, &nag->details.button_down);
|
||||
}
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_border_color);
|
||||
cairo_rectangle(cairo, margin, nag->details.y - border,
|
||||
nag->details.width + 2 * border, border_rect_height);
|
||||
cairo_fill(cairo);
|
||||
|
||||
cairo_set_source_u32(cairo, nag->conf->details_background);
|
||||
cairo_rectangle(cairo, nag->details.x, nag->details.y,
|
||||
nag->details.width, nag->details.height);
|
||||
|
|
@ -437,7 +458,7 @@ render_button(cairo_t *cairo, struct nag *nag, struct button *button,
|
|||
}
|
||||
|
||||
button->x = *x - border - text_width - padding * 2 + 1;
|
||||
button->y = (int)(ideal_height - text_height) / 2 - padding + 1;
|
||||
button->y = (int)(ideal_height - text_height) / 2 - padding;
|
||||
button->width = text_width + padding * 2;
|
||||
button->height = text_height + padding * 2;
|
||||
|
||||
|
|
@ -1388,6 +1409,7 @@ nag_setup(struct nag *nag)
|
|||
}
|
||||
|
||||
sigset_t mask;
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
|
@ -1453,14 +1475,16 @@ conf_init(struct conf *conf)
|
|||
conf->keyboard_focus = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||
conf->bar_border_thickness = 2;
|
||||
conf->message_padding = 8;
|
||||
conf->details_border_thickness = 3;
|
||||
conf->button_border_thickness = 3;
|
||||
conf->button_gap = 20;
|
||||
conf->button_gap_close = 15;
|
||||
conf->button_margin_right = 2;
|
||||
conf->button_padding = 3;
|
||||
conf->button_background = 0x680A0AFF;
|
||||
conf->details_margin = 11;
|
||||
conf->details_border_thickness = 3;
|
||||
conf->details_background = 0x680A0AFF;
|
||||
conf->details_border_color = 0x680A0AFF;
|
||||
conf->background = 0x900000FF;
|
||||
conf->text = 0xFFFFFFFF;
|
||||
conf->button_text = 0xFFFFFFFF;
|
||||
|
|
@ -1540,16 +1564,18 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
TO_COLOR_BORDER_BOTTOM,
|
||||
TO_COLOR_BUTTON_BG,
|
||||
TO_COLOR_DETAILS,
|
||||
TO_COLOR_DETAILS_BORDER,
|
||||
TO_COLOR_TEXT,
|
||||
TO_COLOR_BUTTON_TEXT,
|
||||
TO_THICK_BAR_BORDER,
|
||||
TO_PADDING_MESSAGE,
|
||||
TO_THICK_DET_BORDER,
|
||||
TO_THICK_DETAILS_BORDER,
|
||||
TO_THICK_BTN_BORDER,
|
||||
TO_GAP_BTN,
|
||||
TO_GAP_BTN_DISMISS,
|
||||
TO_MARGIN_BTN_RIGHT,
|
||||
TO_PADDING_BTN,
|
||||
TO_MARGIN_DETAILS,
|
||||
};
|
||||
|
||||
static const struct option opts[] = {
|
||||
|
|
@ -1566,6 +1592,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
{"message", required_argument, NULL, 'm'},
|
||||
{"output", required_argument, NULL, 'o'},
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"exclusive-zone", no_argument, NULL, 'x'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
|
||||
{"background-color", required_argument, NULL, TO_COLOR_BACKGROUND},
|
||||
|
|
@ -1576,8 +1603,10 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
{"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-border-size", required_argument, NULL, TO_THICK_DETAILS_BORDER},
|
||||
{"details-background-color", required_argument, NULL, TO_COLOR_DETAILS},
|
||||
{"details-border-color", required_argument, NULL, TO_COLOR_DETAILS_BORDER},
|
||||
{"details-margin", required_argument, NULL, TO_MARGIN_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},
|
||||
|
|
@ -1622,6 +1651,9 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
" --details-border-size size Thickness for the details border.\n"
|
||||
" --details-background-color RRGGBB[AA]\n"
|
||||
" Details background color.\n"
|
||||
" --details-border-color RRGGBB[AA]\n"
|
||||
" Details border color.\n"
|
||||
" --details-margin margin Margin for the details.\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"
|
||||
|
|
@ -1758,6 +1790,11 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
fprintf(stderr, "Invalid details background color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_DETAILS_BORDER:
|
||||
if (!parse_color(optarg, &conf->details_border_color)) {
|
||||
fprintf(stderr, "Invalid details border color: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case TO_COLOR_TEXT: /* Text color */
|
||||
if (!parse_color(optarg, &conf->text)) {
|
||||
fprintf(stderr, "Invalid text color: %s\n", optarg);
|
||||
|
|
@ -1774,7 +1811,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
case TO_PADDING_MESSAGE: /* Message padding */
|
||||
conf->message_padding = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_THICK_DET_BORDER: /* Details border thickness */
|
||||
case TO_THICK_DETAILS_BORDER: /* Details border thickness */
|
||||
conf->details_border_thickness = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_THICK_BTN_BORDER: /* Button border thickness */
|
||||
|
|
@ -1792,6 +1829,9 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
|||
case TO_PADDING_BTN: /* Padding for the button text */
|
||||
conf->button_padding = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case TO_MARGIN_DETAILS:
|
||||
conf->details_margin = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
default: /* Help or unknown flag */
|
||||
fprintf(c == 'h' ? stdout : stderr, "%s", usage);
|
||||
return LAB_EXIT_FAILURE;
|
||||
|
|
|
|||
|
|
@ -1,59 +1,61 @@
|
|||
wayland_client = dependency('wayland-client')
|
||||
wayland_cursor = dependency('wayland-cursor')
|
||||
if get_option('labnag').allowed()
|
||||
wayland_client = dependency('wayland-client')
|
||||
wayland_cursor = dependency('wayland-cursor')
|
||||
|
||||
nag_sources = files(
|
||||
'labnag.c',
|
||||
'pool-buffer.c',
|
||||
)
|
||||
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
|
||||
protocols = [
|
||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
'../protocols/wlr-layer-shell-unstable-v1.xml',
|
||||
]
|
||||
|
||||
foreach xml : protocols
|
||||
nag_sources += custom_target(
|
||||
xml.underscorify() + '_c',
|
||||
input: xml,
|
||||
output: '@BASENAME@-protocol.c',
|
||||
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||
nag_sources = files(
|
||||
'labnag.c',
|
||||
'pool-buffer.c',
|
||||
)
|
||||
nag_sources += custom_target(
|
||||
xml.underscorify() + '_client_h',
|
||||
input: xml,
|
||||
output: '@BASENAME@-client-protocol.h',
|
||||
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
if host_machine.system() in ['freebsd', 'openbsd']
|
||||
# For signalfd()
|
||||
epoll_dep = dependency('epoll-shim')
|
||||
else
|
||||
epoll_dep = []
|
||||
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
||||
|
||||
protocols = [
|
||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
'../protocols/wlr-layer-shell-unstable-v1.xml',
|
||||
]
|
||||
|
||||
foreach xml : protocols
|
||||
nag_sources += custom_target(
|
||||
xml.underscorify() + '_c',
|
||||
input: xml,
|
||||
output: '@BASENAME@-protocol.c',
|
||||
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
nag_sources += custom_target(
|
||||
xml.underscorify() + '_client_h',
|
||||
input: xml,
|
||||
output: '@BASENAME@-client-protocol.h',
|
||||
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
endforeach
|
||||
|
||||
if host_machine.system() in ['freebsd', 'openbsd']
|
||||
# For signalfd()
|
||||
epoll_dep = dependency('epoll-shim')
|
||||
else
|
||||
epoll_dep = []
|
||||
endif
|
||||
|
||||
executable(
|
||||
'labnag',
|
||||
nag_sources,
|
||||
dependencies: [
|
||||
cairo,
|
||||
pangocairo,
|
||||
glib,
|
||||
wayland_client,
|
||||
wayland_cursor,
|
||||
wlroots,
|
||||
server_protos,
|
||||
epoll_dep,
|
||||
xkbcommon,
|
||||
],
|
||||
include_directories: [labwc_inc],
|
||||
install: true,
|
||||
)
|
||||
endif
|
||||
|
||||
executable(
|
||||
'labnag',
|
||||
nag_sources,
|
||||
dependencies: [
|
||||
cairo,
|
||||
pangocairo,
|
||||
glib,
|
||||
wayland_client,
|
||||
wayland_cursor,
|
||||
wlroots,
|
||||
server_protos,
|
||||
epoll_dep,
|
||||
xkbcommon,
|
||||
],
|
||||
include_directories: [labwc_inc],
|
||||
install: true,
|
||||
)
|
||||
|
||||
clients = files('lab-sensible-terminal')
|
||||
install_data(clients, install_dir: get_option('bindir'))
|
||||
|
|
|
|||
6
data/labwc-session.target
Normal file
6
data/labwc-session.target
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[Unit]
|
||||
Description=labwc session
|
||||
Documentation=man:labwc(1) man:systemd.special(7)
|
||||
BindsTo=graphical-session.target
|
||||
Wants=graphical-session-pre.target
|
||||
After=graphical-session-pre.target
|
||||
|
|
@ -1,10 +1,18 @@
|
|||
# Example autostart file
|
||||
|
||||
# When running under systemd, uncomment the systemctl line below to pull in
|
||||
# graphical-session.target via labwc-session.target. This lets systemd user
|
||||
# services declaring WantedBy=graphical-session.target (panels, portals,
|
||||
# notification daemons, etc.) start in sync with the labwc session. Enable
|
||||
# individual services with: systemctl --user enable <unit>
|
||||
#
|
||||
# systemctl --user --no-block start labwc-session.target
|
||||
|
||||
# Set background color.
|
||||
swaybg -c '#113344' >/dev/null 2>&1 &
|
||||
|
||||
# Configure output directives such as mode, position, scale and transform.
|
||||
# Use wlr-randr to get your output names
|
||||
# Use wlr-randr to get your output names.
|
||||
# Example ~/.config/kanshi/config below:
|
||||
# profile {
|
||||
# output HDMI-A-1 position 1366,0
|
||||
|
|
|
|||
|
|
@ -95,6 +95,12 @@ _labnag_ [options...]
|
|||
*--details-border-size* <size>
|
||||
Set the thickness for the details border.
|
||||
|
||||
*--details-border-color* <RRGGBB[AA]>
|
||||
Set the color of the details border.
|
||||
|
||||
*--details-margin* <margin>
|
||||
Set the margin for the details.
|
||||
|
||||
*--button-border-size* <size>
|
||||
Set the thickness for the button border.
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
SIGTERM signal.
|
||||
|
||||
*<action name="Execute" command="value" />*
|
||||
Execute command. Note that in the interest of backward compatibility,
|
||||
Execute command. Note that in the interest of backward compatibility,
|
||||
labwc supports <execute> as an alternative to <command> even though
|
||||
openbox documentation states that it is deprecated.
|
||||
Note: Tilde (~) is expanded in the command before passing to execvp().
|
||||
|
|
@ -126,30 +126,34 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
position if it had been maximized or tiled to a direction or region.
|
||||
|
||||
*<action name="NextWindow" workspace="current" output="all" identifier="all" />*++
|
||||
*<action name="PreviousWindow" workspace="current" output="all" identifier="all" />*
|
||||
*<action name="PreviousWindow" workspace="current" output="all" identifier="all" />*++
|
||||
*<action name="NextWindowImmediate" workspace="current" output="all" identifier="all" />*++
|
||||
*<action name="PreviousWindowImmediate" workspace="current" output="all" identifier="all" />*++
|
||||
Cycle focus to next/previous window, respectively.
|
||||
|
||||
Default keybinds for NextWindow and PreviousWindow are Alt-Tab and
|
||||
Shift-Alt-Tab. While cycling through windows, the arrow keys move the
|
||||
selected window forwards/backwards and the escape key halts the cycling.
|
||||
|
||||
NextWindowImmediate and PreviousWindowImmediate skip the Window Switcher
|
||||
and OSD, useful for binding to keys without modifiers.
|
||||
|
||||
*workspace* [all|current]
|
||||
This determines whether to cycle through windows on all workspaces or the
|
||||
current workspace. Default is "current".
|
||||
This determines whether to cycle through windows on all workspaces or
|
||||
the current workspace. Default is "current".
|
||||
|
||||
*output* [all|focused|cursor]
|
||||
This determines whether to cycle through windows on all outputs, the focused
|
||||
output, or the output under the cursor. Default is "all".
|
||||
This determines whether to cycle through windows on all outputs, the
|
||||
focused output, or the output under the cursor. Default is "all".
|
||||
|
||||
*identifier* [all|current]
|
||||
This determines whether to cycle through all windows or only windows of the
|
||||
same application as the currently focused window. Default is "all".
|
||||
This determines whether to cycle through all windows or only windows of
|
||||
the same application as the currently focused window. Default is "all".
|
||||
|
||||
*<action name="Reconfigure" />*
|
||||
Re-load configuration and theme files.
|
||||
|
||||
*<action name="ShowMenu" menu="root-menu"/>*
|
||||
|
||||
*<action name="ShowMenu" menu="root-menu" />*
|
||||
Show a menu.
|
||||
|
||||
```
|
||||
|
|
@ -295,7 +299,7 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
(if one exists).
|
||||
|
||||
*wrap* [yes|no] When using the direction attribute, wrap around from
|
||||
right-to-left or top-to-bottom, and vice versa. Default no.
|
||||
right-to-left or top-to-bottom, and vice versa. Default is no.
|
||||
|
||||
*<action name="FitToOutput" />*
|
||||
Resizes active window size to width and height of the output when the
|
||||
|
|
@ -309,10 +313,10 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
workspace or its index (starting at 1) as configured in rc.xml.
|
||||
|
||||
*wrap* [yes|no] Wrap around from last desktop to first, and vice
|
||||
versa. Default yes.
|
||||
versa. Default is yes.
|
||||
|
||||
*toggle* [yes|no] Toggle to “last” if already on the workspace that
|
||||
would be the actual destination. Default no.
|
||||
would be the actual destination. Default is no.
|
||||
|
||||
*<action name="SendToDesktop" to="value" follow="yes" wrap="yes" />*
|
||||
Send active window to workspace.
|
||||
|
|
@ -320,10 +324,11 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
*to* The workspace to send the window to. Supported values are the same
|
||||
as for GoToDesktop.
|
||||
|
||||
*follow* [yes|no] Also switch to the specified workspace. Default yes.
|
||||
*follow* [yes|no] Also switch to the specified workspace.
|
||||
Default is yes.
|
||||
|
||||
*wrap* [yes|no] Wrap around from last desktop to first, and vice
|
||||
versa. Default yes.
|
||||
versa. Default is yes.
|
||||
|
||||
*<action name="VirtualOutputAdd" output_name="value" />*
|
||||
Add virtual output (headless backend).
|
||||
|
|
@ -341,11 +346,11 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
|
||||
```
|
||||
<keybind key="W-v">
|
||||
<action name="VirtualOutputAdd" output_name="ScreenCasting"/>
|
||||
<action name="Execute" command='sh -c "wlr-randr --output ScreenCasting --pos 0,0 --scale 2 --custom-mode 3840x2110; wlr-randr --output eDP-1 --pos 0,0 --scale 2 --mode 3840x2160"'/>
|
||||
<action name="VirtualOutputAdd" output_name="ScreenCasting" />
|
||||
<action name="Execute" command='sh -c "wlr-randr --output ScreenCasting --pos 0,0 --scale 2 --custom-mode 3840x2110; wlr-randr --output eDP-1 --pos 0,0 --scale 2 --mode 3840x2160"' />
|
||||
</keybind>
|
||||
<keybind key="W-c">
|
||||
<action name="VirtualOutputRemove"/>
|
||||
<action name="VirtualOutputRemove" />
|
||||
</keybind>
|
||||
```
|
||||
|
||||
|
|
@ -366,7 +371,7 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
*output_name* The name of virtual output. If not supplied, will remove
|
||||
the last virtual output added.
|
||||
|
||||
*<action name="AutoPlace" policy="value"/>*
|
||||
*<action name="AutoPlace" policy="value" />*
|
||||
Reposition the window according to the desired placement policy.
|
||||
|
||||
*policy* [automatic|cursor|center|cascade] Use the specified policy,
|
||||
|
|
@ -424,6 +429,13 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
Toggle the screen magnifier on or off at the last magnification level
|
||||
used.
|
||||
|
||||
*<action name="ToggleShowDesktop" />*
|
||||
Minimize all windows in the current workspace so that the desktop
|
||||
becomes visible. On calling the action again the hidden windows are
|
||||
unminimized, provided that - since the initial `ShowDesktop` - (a) no
|
||||
windows have been unminimized; (b) workspaces have not been switched;
|
||||
and (c) no new applications have been started.
|
||||
|
||||
*<action name="ZoomIn">*++
|
||||
*<action name="ZoomOut">*
|
||||
Increase or decrease the magnification level for the screen magnifier.
|
||||
|
|
@ -436,6 +448,10 @@ Actions are used in menus and keyboard/mouse bindings.
|
|||
If used as the only action for a binding: clear an earlier defined
|
||||
binding.
|
||||
|
||||
*<action name="DebugToggleKeyStateIndicator" />*
|
||||
Toggle visibility of key-state on-screen display (OSD). Note: This is
|
||||
for debugging purposes only.
|
||||
|
||||
# CONDITIONAL ACTIONS
|
||||
|
||||
Actions that execute other actions. Used in keyboard/mouse bindings.
|
||||
|
|
@ -448,10 +464,10 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
|
|||
|
||||
```
|
||||
<action name="If">
|
||||
<query/>
|
||||
<prompt message=""/>
|
||||
<then><action/></then>
|
||||
<else><action/></else>
|
||||
<query />
|
||||
<prompt message="" />
|
||||
<then><action /></then>
|
||||
<else><action /></else>
|
||||
</action>
|
||||
```
|
||||
|
||||
|
|
@ -503,7 +519,7 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
|
|||
"right-occupied" directions will not wrap.
|
||||
|
||||
*tiled* [up|right|down|left|up-left|up-right|down-left|down-right|center|any]
|
||||
Whether the client is tiled (snapped) along the the
|
||||
Whether the client is tiled (snapped) along the
|
||||
indicated screen edge.
|
||||
|
||||
*tiled_region*
|
||||
|
|
@ -533,9 +549,9 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
|
|||
```
|
||||
<keybind key="W-q">
|
||||
<action name="If">
|
||||
<prompt message="Quit?"/>
|
||||
<prompt message="Quit?" />
|
||||
<then>
|
||||
<action name="Exit"/>
|
||||
<action name="Exit" />
|
||||
</then>
|
||||
</action>
|
||||
</keybind>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ The XDG Base Directory Specification does not specify whether or not programs
|
|||
should (a) allow the first-identified configuration file to supersede any
|
||||
others, or (b) define rules for merging the information from more than one file.
|
||||
|
||||
By default, labwc uses option (a), reading only the first file identified. With
|
||||
By default, labwc uses option (a), reading only the first file identified. With
|
||||
the --merge-config option, the search order is reversed, but every configuration
|
||||
file encountered is processed in turn. Thus, user-specific files will augment
|
||||
system-wide configurations, with conflicts favoring the user-specific
|
||||
|
|
@ -175,6 +175,7 @@ this is for compatibility with Openbox.
|
|||
<adaptiveSync>no</adaptiveSync>
|
||||
<allowTearing>no</allowTearing>
|
||||
<autoEnableOutputs>yes</autoEnableOutputs>
|
||||
<hdr>no</hdr>
|
||||
<reuseOutputMode>no</reuseOutputMode>
|
||||
<xwaylandPersistence>no</xwaylandPersistence>
|
||||
<primarySelection>yes</primarySelection>
|
||||
|
|
@ -240,6 +241,12 @@ this is for compatibility with Openbox.
|
|||
'pkill kanshi ; wlopm --off \*' resume 'kanshi & wlopm --on \*'
|
||||
```
|
||||
|
||||
*<core><hdr>* [yes|no]
|
||||
Automatically enable HDR support on outputs when configuring them,
|
||||
where supported by the particular output device and display. Default
|
||||
is no. Additionally requires the Vulkan backend. Can be set
|
||||
via `WLR_RENDERER=vulkan` in `~/.config/labwc/environment`.
|
||||
|
||||
*<core><reuseOutputMode>* [yes|no]
|
||||
Try to re-use the existing output mode (resolution / refresh rate).
|
||||
This may prevent unnecessary screenblank delays when starting labwc
|
||||
|
|
@ -493,6 +500,13 @@ this is for compatibility with Openbox.
|
|||
*<focus><raiseOnFocus>* [yes|no]
|
||||
Raise window to top when focused. Default is no.
|
||||
|
||||
*<focus><raiseOnFocusDelay>* [milliseconds]
|
||||
When raiseOnFocus is enabled, delay the actual raise by this many
|
||||
milliseconds. Default is 0 (raise immediately). A subsequent focus
|
||||
change before the timer elapses restarts or cancels the pending raise.
|
||||
Useful together with followMouse to avoid brief passes of the cursor
|
||||
stacking up z-order changes.
|
||||
|
||||
## WINDOW SNAPPING
|
||||
|
||||
Windows may be "snapped" to an edge or user-defined region of an output when
|
||||
|
|
@ -512,7 +526,8 @@ extending outward from the snapped edge.
|
|||
*<range><inner>* and *<range><outer>*, and 50 for *<cornerRange>*.
|
||||
|
||||
*<snapping><overlay><enabled>* [yes|no]
|
||||
Show an overlay when snapping a window to an output edge. Default is yes.
|
||||
Show an overlay when snapping a window to an output edge.
|
||||
Default is yes.
|
||||
|
||||
*<snapping><overlay><delay><inner>*++
|
||||
*<snapping><overlay><delay><outer>*
|
||||
|
|
@ -581,7 +596,7 @@ extending outward from the snapped edge.
|
|||
A setting of 0 disables the OSD. Default is 1000 ms.
|
||||
|
||||
*<desktops><prefix>*
|
||||
Set the prefix to use when using "number" above. Default is "Workspace"
|
||||
Set the prefix to use when using "number" above. Default is "Workspace".
|
||||
|
||||
## THEME
|
||||
|
||||
|
|
@ -735,7 +750,7 @@ generate gesture events, like swipe and pinch. There are some related settings
|
|||
(e.g. *threeFingerDrag* and *twoFingerScroll*) in the *<libinput>* section.
|
||||
|
||||
In the Wayland Compositor domain, events associated with touchscreens are
|
||||
sometimes simply referred to as *touch* events. Touchscreens can be configured
|
||||
sometimes simply referred to as *touch* events. Touchscreens can be configured
|
||||
in both the *<touch>* and *<libinput>* sections. Note that touchscreen gestures
|
||||
are not interpreted by libinput, nor labwc. Any touch point is passed to the
|
||||
client (application) for any interpretation of gestures.
|
||||
|
|
@ -760,7 +775,8 @@ References:
|
|||
Stores the keyboard layout either globally or per window and restores
|
||||
it when switching back to the window. Default is global.
|
||||
|
||||
*<keyboard><keybind key="" layoutDependent="" onRelease="" allowWhenLocked="">*
|
||||
*<keyboard><keybind key="" layoutDependent="" onRelease="" allowWhenLocked=""
|
||||
overrideInhibition="">*
|
||||
Define a *key* binding in the format *modifier-key*, where supported
|
||||
modifiers are:
|
||||
- S (shift)
|
||||
|
|
@ -808,6 +824,12 @@ References:
|
|||
*allowWhenLocked* [yes|no]
|
||||
Make this keybind work even if the screen is locked. Default is no.
|
||||
|
||||
*overrideInhibition* [yes|no]
|
||||
Make this keybind work even if the view inhibits keybinds.
|
||||
This can be used to prevent W-Tab and similar keybinds from being
|
||||
delivered to Virtual Machines, VNC clients or nested compositors.
|
||||
Default is no.
|
||||
|
||||
*onRelease* [yes|no]
|
||||
When yes, fires the keybind action when the key or key
|
||||
combination is released, rather than first pressed. This is useful to
|
||||
|
|
@ -820,7 +842,7 @@ References:
|
|||
|
||||
```
|
||||
<keybind key="Super_L" onRelease="yes">
|
||||
<action name="Execute" command="rofi -show drun"/>
|
||||
<action name="Execute" command="rofi -show drun" />
|
||||
</keybind>
|
||||
```
|
||||
|
||||
|
|
@ -841,11 +863,12 @@ References:
|
|||
W-Return - lab-sensible-terminal
|
||||
A-F4 - close window
|
||||
W-a - toggle maximize
|
||||
W-d - toggle show-desktop
|
||||
W-<arrow> - resize window to fill half or quarter of the output
|
||||
A-Space - show window menu
|
||||
```
|
||||
|
||||
Audio and MonBrightness keys are also bound to amixer and
|
||||
Audio and MonBrightness keys are also bound to pactl and
|
||||
brightnessctl, respectively.
|
||||
|
||||
*<keyboard><repeatRate>*
|
||||
|
|
@ -880,7 +903,7 @@ input-devices by the Wayland protocol.
|
|||
- Shade: A button that, by default, toggles window shading.
|
||||
- AllDesktops: A button that, by default, toggles omnipresence of a
|
||||
window.
|
||||
- Close: A button that, by default, closses a window.
|
||||
- Close: A button that, by default, closes a window.
|
||||
- Border: The window's border including Top...BRCorner below.
|
||||
- Top: The top edge of the window's border.
|
||||
- Bottom: The bottom edge of the window's border.
|
||||
|
|
@ -954,10 +977,10 @@ input-devices by the Wayland protocol.
|
|||
|
||||
```
|
||||
<mouse>
|
||||
<default/>
|
||||
<default />
|
||||
<context name="Frame">
|
||||
<mousebind button="W-Left" action="Press"/>
|
||||
<mousebind button="W-Left" action="Drag"/>
|
||||
<mousebind button="W-Left" action="Press" />
|
||||
<mousebind button="W-Left" action="Drag" />
|
||||
</context>
|
||||
</mouse>
|
||||
```
|
||||
|
|
@ -965,7 +988,7 @@ input-devices by the Wayland protocol.
|
|||
*<mouse><default />*
|
||||
Load default mousebinds. This is an addition to the openbox
|
||||
specification and provides a way to keep config files simpler whilst
|
||||
allowing user specific binds. Note that if no rc.xml is found, or if no
|
||||
allowing user specific binds. Note that if no rc.xml is found, or if no
|
||||
<mouse><mousebind> entries exist, the same default mousebinds will be
|
||||
loaded even if the <default /> element is not provided.
|
||||
|
||||
|
|
@ -977,7 +1000,7 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
*calibrationMatrix* setting.
|
||||
|
||||
```
|
||||
<touch deviceName="" mapToOutput="" mouseEmulation="no"/>
|
||||
<touch deviceName="" mapToOutput="" mouseEmulation="no" />
|
||||
```
|
||||
|
||||
*<touch deviceName="" />*
|
||||
|
|
@ -1090,7 +1113,8 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
## TABLET TOOL
|
||||
|
||||
```
|
||||
<tabletTool motion="absolute" relativeMotionSensitivity="1" />
|
||||
<tabletTool motion="absolute" relativeMotionSensitivity="1.0"
|
||||
minPressure="0.0" maxPressure="1.0" />
|
||||
```
|
||||
|
||||
*<tabletTool motion="">* [absolute|relative]
|
||||
|
|
@ -1105,6 +1129,16 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
speed, using a value greater than 1.0 increases the speed of the
|
||||
cursor. The default is "1.0".
|
||||
|
||||
*<tabletTool minPressure="">*
|
||||
*<tabletTool maxPressure="">*
|
||||
The pressure range of a tablet tool can be controlled by adjusting
|
||||
*minPressure* and *maxPressure*. Setting the minimum pressure to
|
||||
a value greater than zero requires more pressure for the tip
|
||||
threshold, setting the maximum pressure to a value less than 1.0
|
||||
requires less pressure for the user before the maximum is reached.
|
||||
The default is 0 for the minimum pressure and 1.0 for the maximum
|
||||
pressure.
|
||||
|
||||
## LIBINPUT
|
||||
|
||||
```
|
||||
|
|
@ -1123,6 +1157,7 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
<disableWhileTyping></disableWhileTyping>
|
||||
<clickMethod></clickMethod>
|
||||
<scrollMethod></scrollMethod>
|
||||
<scrollButton></scrollButton>
|
||||
<sendEventsMode></sendEventsMode>
|
||||
<calibrationMatrix></calibrationMatrix>
|
||||
<scrollFactor>1.0</scrollFactor>
|
||||
|
|
@ -1227,19 +1262,26 @@ Note: To rotate touch events with output rotation, use the libinput
|
|||
|
||||
The default method depends on the touchpad hardware.
|
||||
|
||||
*<libinput><device><scrollMethod>* [none|twofinger|edge]
|
||||
Configure the method by which physical movements on a touchpad are
|
||||
mapped to scroll events.
|
||||
*<libinput><device><scrollMethod>* [none|twofinger|edge|onbutton]
|
||||
Configure the method by which physical movements are mapped to scroll
|
||||
events.
|
||||
|
||||
The scroll methods available are:
|
||||
- *twofinger* - Scroll by two fingers being placed on the surface of the
|
||||
touchpad, then moving those fingers vertically or horizontally.
|
||||
- *edge* - Scroll by moving a single finger along the right edge
|
||||
(vertical scroll) or bottom edge (horizontal scroll).
|
||||
- *onbutton* - Scroll by pressing a button.
|
||||
- *none* - No scroll events will be produced.
|
||||
|
||||
The default method depends on the touchpad hardware.
|
||||
|
||||
*<libinput><device><scrollButton>* [button]
|
||||
Set the button used for the *onbutton* scroll method.
|
||||
|
||||
*button* is the decimal form of a value
|
||||
from `linux/input-event-codes.h`.
|
||||
|
||||
*<libinput><device><sendEventsMode>* [yes|no|disabledOnExternalMouse]
|
||||
Optionally enable or disable sending any device events.
|
||||
|
||||
|
|
@ -1287,7 +1329,7 @@ defined as shown below.
|
|||
|
||||
<!-- Action -->
|
||||
<windowRule identifier="" title="" type="">
|
||||
<action name=""/>
|
||||
<action name="" />
|
||||
</windowRule>
|
||||
|
||||
<!-- Property -->
|
||||
|
|
@ -1354,6 +1396,13 @@ situation.
|
|||
*ignoreConfigureRequest* prevents a X11 window to position and size
|
||||
itself.
|
||||
|
||||
*<windowRules><windowRule allowAlwaysOnTop="">* [yes|no|default]
|
||||
*allowAlwaysOnTop* allows a X11 window to control its always-on-top
|
||||
state ('above' in X11 terms).
|
||||
|
||||
Note: X11 window always-on-top requests are disallowed by default.
|
||||
This window rule offers a means of allowing it.
|
||||
|
||||
*<windowRules><windowRule fixedPosition="">* [yes|no|default]
|
||||
*fixedPosition* disallows interactive move/resize and prevents
|
||||
re-positioning in response to changes in reserved output space, which
|
||||
|
|
@ -1427,11 +1476,73 @@ situation.
|
|||
Whether to apply a bilinear filter to the magnified image, or
|
||||
just to use nearest-neighbour. Default is true - bilinear filtered.
|
||||
|
||||
## PRIVILEGED INTERFACES
|
||||
|
||||
Labwc supports a small set of privileged wayland interfaces. All of these
|
||||
interfaces are enabled by default for applications unless they are running
|
||||
via a sandbox environment supporting the security-context-v1 protocol.
|
||||
|
||||
Security conscious users are suggested to use a sandbox framework to run
|
||||
potentially untrusted applications as it additionally limits access to the
|
||||
filesystem (including labwc configuration) and other services like dbus.
|
||||
|
||||
In addition to that, privileged protocols can be restricted for non-sandboxed
|
||||
clients by defining a `<privilegedInterfaces>` block:
|
||||
|
||||
```
|
||||
<privilegedInterfaces>
|
||||
<allow>zwlr_layer_shell_v1</allow>
|
||||
<allow>zwlr_virtual_pointer_manager_v1</allow>
|
||||
</privilegedInterfaces>
|
||||
```
|
||||
|
||||
*<privilegedInterfaces><allow>*
|
||||
Name of the interface that should be allowed.
|
||||
|
||||
This is the full list of interfaces that can be controlled with this mechanism:
|
||||
|
||||
- `wp_drm_lease_device_v1`
|
||||
- `zwlr_gamma_control_manager_v1`
|
||||
- `zwlr_output_manager_v1`
|
||||
- `zwlr_output_power_manager_v1`
|
||||
- `zwp_input_method_manager_v2`
|
||||
- `zwlr_virtual_pointer_manager_v1`
|
||||
- `zwp_virtual_keyboard_manager_v1`
|
||||
- `zwlr_export_dmabuf_manager_v1`
|
||||
- `zwlr_screencopy_manager_v1`
|
||||
- `ext_data_control_manager_v1`
|
||||
- `zwlr_data_control_manager_v1`
|
||||
- `wp_security_context_manager_v1`
|
||||
- `ext_idle_notifier_v1`
|
||||
- `zwlr_foreign_toplevel_manager_v1`
|
||||
- `ext_foreign_toplevel_list_v1`
|
||||
- `ext_session_lock_manager_v1`
|
||||
- `zwlr_layer_shell_v1`
|
||||
- `ext_workspace_manager_v1`
|
||||
- `ext_image_copy_capture_manager_v1`
|
||||
- `ext_output_image_capture_source_manager_v1`
|
||||
|
||||
## ENVIRONMENT VARIABLES
|
||||
|
||||
*XCURSOR_THEME* and *XCURSOR_SIZE* are supported to set cursor theme
|
||||
and size respectively. The default size is 24. System cursor themes can
|
||||
typically be found with a command such as:
|
||||
*XCURSOR_PATH*
|
||||
Specify a colon-separated list of paths to look for mouse cursors in.
|
||||
Default is
|
||||
~/.local/share/icons:
|
||||
~/.icons:
|
||||
/usr/share/icons:
|
||||
/usr/share/pixmaps:
|
||||
~/.cursors:
|
||||
/usr/share/cursors/xorg-x11:
|
||||
/usr/X11R6/lib/X11/icons:
|
||||
|
||||
*XCURSOR_SIZE*
|
||||
Specify an alternative mouse cursor size in pixels. Requires
|
||||
XCURSOR_THEME to be set also. Default is 24.
|
||||
|
||||
*XCURSOR_THEME*
|
||||
Specify a mouse cursor theme within XCURSOR_PATH.
|
||||
|
||||
System cursor themes can typically be found with a command such as:
|
||||
|
||||
```
|
||||
find /usr/share/icons/ -type d -name "cursors"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Static menus are built based on the menu.xml file located at
|
|||
# SYNTAX
|
||||
|
||||
The menu file must be entirely enclosed within <openbox_menu> and
|
||||
</openbox_menu> tags. Inside these tags, menus are specified as follows:
|
||||
</openbox_menu> tags. Inside these tags, menus are specified as follows:
|
||||
|
||||
```
|
||||
<!-- A toplevel menu -->
|
||||
|
|
@ -111,7 +111,7 @@ Pipe menus are menus generated dynamically based on output of scripts or
|
|||
binaries. They are so-called because the output of the executable is piped to
|
||||
the labwc menu.
|
||||
|
||||
For any *<menu id="" label="" execute="COMMAND"/>* entry in menu.xml, the
|
||||
For any *<menu id="" label="" execute="COMMAND" />* entry in menu.xml, the
|
||||
COMMAND will be executed the first time the item is selected (for example by
|
||||
cursor or keyboard input). The XML output of the command will be parsed and
|
||||
shown as a submenu. The content of pipemenus is cached until the whole menu
|
||||
|
|
@ -124,7 +124,7 @@ menus, for example:
|
|||
```
|
||||
<openbox_pipe_menu>
|
||||
<item label="Terminal">
|
||||
<action name="Execute" command="xterm"/>
|
||||
<action name="Execute" command="xterm" />
|
||||
</item>
|
||||
</openbox_pipe_menu>
|
||||
```
|
||||
|
|
@ -144,10 +144,25 @@ obmenu-generator with the menu generator of your choice):
|
|||
```
|
||||
<?xml version="1.0"?>
|
||||
<openbox_menu>
|
||||
<menu id="root-menu" label="" execute="obmenu-generator"/>
|
||||
<menu id="root-menu" label="" execute="obmenu-generator" />
|
||||
</openbox_menu>
|
||||
```
|
||||
|
||||
# ACCELERATORS / MNEMONICS
|
||||
|
||||
Menu accelerators are one-letter mnemonics to quickly select/exec items from
|
||||
the current menu. For each menu item, the accelerator is defined as the first
|
||||
character of the item label, converted to lowercase. A different accelerator
|
||||
can be explicitly defined in menu.xml with the special '\_' character before the
|
||||
target letter. Accelerators can be any unicode character and are not limited to
|
||||
ASCII. A usual underscore can be shown by duplicating it.
|
||||
|
||||
If the menu only contains a single instance of the pressed accelerator the item
|
||||
will be executed directly. Otherwise, all matching items are cycled through.
|
||||
|
||||
Example:
|
||||
The accelerator for an item with the label "e_Macs" is 'm'.
|
||||
|
||||
# LOCALISATION
|
||||
|
||||
Available localisation for the default "client-menu" is only shown if no
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ window.*.title.bg.colorTo.splitTo: #557485
|
|||
|
||||
*window.active.title.bg*
|
||||
Texture for the focused window's titlebar. See texture section above.
|
||||
Default is *Solid*
|
||||
Default is *Solid*.
|
||||
|
||||
*window.active.title.bg.color*
|
||||
Background color for the focused window's titlebar. See texture section
|
||||
|
|
@ -144,7 +144,7 @@ window.*.title.bg.colorTo.splitTo: #557485
|
|||
|
||||
*window.inactive.title.bg*
|
||||
Texture for non-focused windows' titlebars. See texture section above.
|
||||
Default is *Solid*
|
||||
Default is *Solid*.
|
||||
|
||||
*window.inactive.title.bg.color*
|
||||
Background color for non-focused windows' titlebars. See texture section
|
||||
|
|
@ -470,7 +470,7 @@ all are supported.
|
|||
Width of magnifier window border in pixels. Default is 1.
|
||||
|
||||
*magnifier.border.color*
|
||||
Color of the magnfier window border. Default is #ff0000 (red).
|
||||
Color of the magnifier window border. Default is #ff0000 (red).
|
||||
|
||||
# BUTTONS
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,18 @@ the `--exit` and `--reconfigure` options use.
|
|||
Manager, or the Window Manager can be launched independently first. On
|
||||
Wayland, the Compositor is both Display Server and Window Manager, so
|
||||
the described session management mechanisms do not work because the
|
||||
Compositor needs to be running before the session can function. As some
|
||||
Compositor needs to be running before the session can function. As some
|
||||
session clients support both X11 and Wayland, this command line option
|
||||
avoids re-writes and fragmentation.
|
||||
|
||||
*-t, --title* <fmtstr>
|
||||
Set the window title for labwc to use when it is running in a window
|
||||
(i.e. nested in a compositor). <fmtstr> is a format string to be used as
|
||||
the window title, replacing `%o` with the name of the output
|
||||
region. This is useful when simulating multiple screens, such as with
|
||||
running labwc with the environment variable `WLR_WL_OUTPUTS=2`. In this
|
||||
case, `%o` will be unique per simulated screen.
|
||||
|
||||
*-v, --version*
|
||||
Show the version number and quit
|
||||
|
||||
|
|
@ -118,6 +126,25 @@ this is accomplished by setting the session variables to empty strings. For
|
|||
systemd, the command `systemctl --user unset-environment` will be invoked to
|
||||
actually remove the variables from the activation environment.
|
||||
|
||||
A systemd user unit named `labwc-session.target` is also shipped alongside
|
||||
the compositor for users who want to integrate labwc with systemd. It binds
|
||||
to the standard `graphical-session.target`, so systemd user services can
|
||||
start and stop in sync with the labwc session when they declare a WantedBy
|
||||
or PartOf relationship to that target. Labwc does not activate the target
|
||||
itself; users opt in by adding lines like the following to their
|
||||
*autostart* and *shutdown* files:
|
||||
|
||||
```
|
||||
systemctl --user --no-block start labwc-session.target
|
||||
systemctl --user stop graphical-session.target
|
||||
```
|
||||
|
||||
The example *autostart* and *shutdown* files shipped with labwc include
|
||||
these commented out. To have a user service automatically started with
|
||||
the session, enable it so the corresponding symlink under the
|
||||
graphical-session.target.wants directory exists, for example by running
|
||||
"systemctl --user enable dms.service".
|
||||
|
||||
# ENVIRONMENT VARIABLES
|
||||
|
||||
Set the environment variables listed below to enable specific debug options.
|
||||
|
|
@ -141,7 +168,7 @@ example: *LABWC_DEBUG_FOO=1 labwc*.
|
|||
|
||||
*LABWC_DEBUG_KEY_STATE*
|
||||
Enable logging of press and release events for bound keys (generally
|
||||
key-combinations like *Ctrl-Alt-t*)
|
||||
key-combinations like *Ctrl-Alt-t*).
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
Any menu with the id "workspaces" will be hidden
|
||||
if there is only a single workspace available.
|
||||
-->
|
||||
<menu id="client-send-to-menu"/>
|
||||
<menu id="client-send-to-menu" />
|
||||
<!--
|
||||
openbox default workspace selector
|
||||
to use replace above workspace menu with the example below
|
||||
|
|
@ -56,9 +56,9 @@
|
|||
# A prompt can be used as follows:
|
||||
<item label="Exit">
|
||||
<action name="If">
|
||||
<prompt message="Do you really want to exit the compositor?"/>
|
||||
<prompt message="Do you really want to exit the compositor?" />
|
||||
<then>
|
||||
<action name="Exit"/>
|
||||
<action name="Exit" />
|
||||
</then>
|
||||
</action>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<adaptiveSync>no</adaptiveSync>
|
||||
<allowTearing>no</allowTearing>
|
||||
<autoEnableOutputs>yes</autoEnableOutputs>
|
||||
<hdr>no</hdr>
|
||||
<reuseOutputMode>no</reuseOutputMode>
|
||||
<xwaylandPersistence>no</xwaylandPersistence>
|
||||
<primarySelection>yes</primarySelection>
|
||||
|
|
@ -158,6 +159,8 @@
|
|||
<followMouse>no</followMouse>
|
||||
<followMouseRequiresMovement>yes</followMouseRequiresMovement>
|
||||
<raiseOnFocus>no</raiseOnFocus>
|
||||
<!-- Delay (ms) before applying raise-on-focus. 0 = immediate. -->
|
||||
<raiseOnFocusDelay>0</raiseOnFocusDelay>
|
||||
</focus>
|
||||
|
||||
<snapping>
|
||||
|
|
@ -276,6 +279,9 @@
|
|||
<keybind key="W-a">
|
||||
<action name="ToggleMaximize" />
|
||||
</keybind>
|
||||
<keybind key="W-d">
|
||||
<action name="ToggleShowDesktop" />
|
||||
</keybind>
|
||||
<keybind key="W-Left">
|
||||
<action name="SnapToEdge" direction="left" combine="yes" />
|
||||
</keybind>
|
||||
|
|
@ -291,19 +297,19 @@
|
|||
<keybind key="A-Space">
|
||||
<action name="ShowMenu" menu="client-menu" atCursor="no" />
|
||||
</keybind>
|
||||
<keybind key="XF86_AudioLowerVolume">
|
||||
<action name="Execute" command="amixer sset Master 5%-" />
|
||||
<keybind key="XF86AudioLowerVolume">
|
||||
<action name="Execute" command="pactl set-sink-volume @DEFAULT_SINK@ -5%" />
|
||||
</keybind>
|
||||
<keybind key="XF86_AudioRaiseVolume">
|
||||
<action name="Execute" command="amixer sset Master 5%+" />
|
||||
<keybind key="XF86AudioRaiseVolume">
|
||||
<action name="Execute" command="pactl set-sink-volume @DEFAULT_SINK@ +5%" />
|
||||
</keybind>
|
||||
<keybind key="XF86_AudioMute">
|
||||
<action name="Execute" command="amixer sset Master toggle" />
|
||||
<keybind key="XF86AudioMute">
|
||||
<action name="Execute" command="pactl set-sink-mute @DEFAULT_SINK@ toggle" />
|
||||
</keybind>
|
||||
<keybind key="XF86_MonBrightnessUp">
|
||||
<keybind key="XF86MonBrightnessUp">
|
||||
<action name="Execute" command="brightnessctl set +10%" />
|
||||
</keybind>
|
||||
<keybind key="XF86_MonBrightnessDown">
|
||||
<keybind key="XF86MonBrightnessDown">
|
||||
<action name="Execute" command="brightnessctl set 10%-" />
|
||||
</keybind>
|
||||
<!-- SnapToRegion via W-Numpad -->
|
||||
|
|
@ -573,8 +579,11 @@
|
|||
*relativeMotionSensitivity* controls the speed of the cursor. Using
|
||||
a value lower than 1.0 decreases the speed, using a value greater than
|
||||
1.0 increases the speed of the cursor.
|
||||
The pressure range of a tablet tool can be controlled by adjusting
|
||||
*minPressure* and *maxPressure*.
|
||||
-->
|
||||
<tabletTool motion="absolute" relativeMotionSensitivity="1.0" />
|
||||
<tabletTool motion="absolute" relativeMotionSensitivity="1.0"
|
||||
minPressure="0.0" maxPressure="1.0" />
|
||||
|
||||
<!--
|
||||
The *category* attribute is optional and can be set to touch, touchpad,
|
||||
|
|
@ -589,7 +598,7 @@
|
|||
- accelProfile [flat|adaptive]
|
||||
- tapButtonMap [lrm|lmr]
|
||||
- clickMethod [none|buttonAreas|clickfinger]
|
||||
- scrollMethod [twoFinger|edge|none]
|
||||
- scrollMethod [twoFinger|edge|onbutton|none]
|
||||
- sendEventsMode [yes|no|disabledOnExternalMouse]
|
||||
- calibrationMatrix [six float values split by space]
|
||||
- scrollFactor [float]
|
||||
|
|
@ -615,6 +624,7 @@
|
|||
<!-- <disableWhileTyping>yes</disableWhileTyping> -->
|
||||
<!-- <clickMethod>buttonAreas</clickMethod> -->
|
||||
<!-- <scrollMethod>twofinger</scrollMethod> -->
|
||||
<!-- <scrollButton>274</scrollButton> -->
|
||||
<!-- <sendEventsMode>yes</sendEventsMode> -->
|
||||
<!-- <calibrationMatrix>1 0 0 0 1 0</calibrationMatrix> -->
|
||||
<scrollFactor>1.0</scrollFactor>
|
||||
|
|
@ -635,10 +645,10 @@
|
|||
# string and '?' matches any single character.
|
||||
|
||||
<windowRules>
|
||||
<windowRule identifier="*"><action name="Maximize"/></windowRule>
|
||||
<windowRule identifier="foo" serverDecoration="yes"/>
|
||||
<windowRule title="bar" serverDecoration="yes"/>
|
||||
<windowRule identifier="baz" title="quax" serverDecoration="yes"/>
|
||||
<windowRule identifier="*"><action name="Maximize" /></windowRule>
|
||||
<windowRule identifier="foo" serverDecoration="yes" />
|
||||
<windowRule title="bar" serverDecoration="yes" />
|
||||
<windowRule identifier="baz" title="quax" serverDecoration="yes" />
|
||||
</windowRules>
|
||||
|
||||
# Example below for `lxqt-panel` and `pcmanfm-qt \-\-desktop`
|
||||
|
|
@ -649,18 +659,18 @@
|
|||
<windowRule identifier="lxqt-panel" matchOnce="true">
|
||||
<skipTaskbar>yes</skipTaskbar>
|
||||
<action name="MoveTo" x="0" y="0" />
|
||||
<action name="ToggleAlwaysOnTop"/>
|
||||
<action name="ToggleAlwaysOnTop" />
|
||||
</windowRule>
|
||||
<windowRule title="pcmanfm-desktop*">
|
||||
<skipTaskbar>yes</skipTaskbar>
|
||||
<skipWindowSwitcher>yes</skipWindowSwitcher>
|
||||
<fixedPosition>yes</fixedPosition>
|
||||
<action name="MoveTo" x="0" y="0" />
|
||||
<action name="ToggleAlwaysOnBottom"/>
|
||||
<action name="ToggleAlwaysOnBottom" />
|
||||
</windowRule>
|
||||
<windowRule identifier="org.qutebrowser.qutebrowser">
|
||||
<action name="ResizeTo" width="1024" height="800" />
|
||||
<action name="AutoPlace"/>
|
||||
<action name="AutoPlace" />
|
||||
</windowRule>
|
||||
</windowRules>
|
||||
-->
|
||||
|
|
|
|||
|
|
@ -3,3 +3,11 @@
|
|||
# This file is executed as a shell script when labwc is preparing to terminate
|
||||
# itself.
|
||||
# For further details see labwc-config(5).
|
||||
|
||||
# When running under systemd, uncomment the systemctl line below to tear down
|
||||
# graphical-session.target (which cascades to labwc-session.target via
|
||||
# BindsTo, and to any service declaring PartOf=graphical-session.target).
|
||||
# Running synchronously here ensures those services are stopped before the
|
||||
# Wayland socket goes away, avoiding "Broken pipe" failures on teardown.
|
||||
#
|
||||
# systemctl --user stop graphical-session.target
|
||||
|
|
|
|||
|
|
@ -47,8 +47,7 @@ bool actions_contain_toggle_keybinds(struct wl_list *action_list);
|
|||
* direction of resize or the position of the window menu button for ShowMenu
|
||||
* action.
|
||||
*/
|
||||
void actions_run(struct view *activator, struct server *server,
|
||||
struct wl_list *actions, struct cursor_context *ctx);
|
||||
void actions_run(struct view *activator, struct wl_list *actions, struct cursor_context *ctx);
|
||||
|
||||
void action_prompts_destroy(void);
|
||||
bool action_check_prompt_result(pid_t pid, int exit_code);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <cairo.h>
|
||||
#include <pango/pango-font.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct lab_data_buffer;
|
||||
|
||||
|
|
@ -43,10 +44,11 @@ void font_get_buffer_size(int max_width, const char *text, struct font *font,
|
|||
* @font: font description
|
||||
* @color: foreground color in rgba format
|
||||
* @bg_pattern: background pattern
|
||||
* @use_markup: flag to render pango markup
|
||||
*/
|
||||
void font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
||||
int height, const char *text, struct font *font, const float *color,
|
||||
cairo_pattern_t *bg_pattern, double scale);
|
||||
cairo_pattern_t *bg_pattern, double scale, bool use_markup);
|
||||
|
||||
/**
|
||||
* font_finish - free some font related resources
|
||||
|
|
|
|||
|
|
@ -62,7 +62,11 @@
|
|||
#define BOUNDED_INT(a) ((a) < INT_MAX && (a) > INT_MIN)
|
||||
#endif
|
||||
|
||||
#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) \
|
||||
(WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro)))
|
||||
#define _LAB_CALC_WLR_VERSION_NUM(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro))
|
||||
|
||||
#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) ( \
|
||||
server.wlr_version >= _LAB_CALC_WLR_VERSION_NUM(major, minor, micro))
|
||||
|
||||
#define LAB_WLR_VERSION_LOWER(major, minor, micro) (!LAB_WLR_VERSION_AT_LEAST(major, minor, micro))
|
||||
|
||||
#endif /* LABWC_MACROS_H */
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct wlr_buffer;
|
||||
struct wlr_scene_node;
|
||||
struct wlr_surface;
|
||||
struct wlr_scene_output;
|
||||
|
|
@ -11,6 +12,13 @@ struct wlr_output_state;
|
|||
|
||||
struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node);
|
||||
|
||||
/* variants of wlr_scene_*_create() functions that don't return NULL */
|
||||
struct wlr_scene_tree *lab_wlr_scene_tree_create(struct wlr_scene_tree *parent);
|
||||
struct wlr_scene_rect *lab_wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
||||
int width, int height, const float color[static 4]);
|
||||
struct wlr_scene_buffer *lab_wlr_scene_buffer_create(
|
||||
struct wlr_scene_tree *parent, struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* lab_get_prev_node - return previous (sibling) node
|
||||
* @node: node to find the previous node from
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ pid_t spawn_primary_client(const char *command);
|
|||
*/
|
||||
void spawn_async_no_shell(char const *command);
|
||||
|
||||
/**
|
||||
* spawn_sync_no_shell - execute synchronously
|
||||
* @command: command to be executed
|
||||
*/
|
||||
void spawn_sync_no_shell(char const *command);
|
||||
|
||||
/**
|
||||
* spawn_piped - execute asynchronously
|
||||
* @command: command to be executed
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ static struct key_combos {
|
|||
}, {
|
||||
.binding = "W-a",
|
||||
.action = "ToggleMaximize",
|
||||
}, {
|
||||
.binding = "W-d",
|
||||
.action = "ToggleShowDesktop",
|
||||
}, {
|
||||
.binding = "W-Left",
|
||||
.action = "SnapToEdge",
|
||||
|
|
@ -84,35 +87,35 @@ static struct key_combos {
|
|||
.value = "no",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86_AudioLowerVolume",
|
||||
.binding = "XF86AudioLowerVolume",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master 5%-",
|
||||
.value = "pactl set-sink-volume @DEFAULT_SINK@ -5%",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86_AudioRaiseVolume",
|
||||
.binding = "XF86AudioRaiseVolume",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master 5%+",
|
||||
.value = "pactl set-sink-volume @DEFAULT_SINK@ +5%",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86_AudioMute",
|
||||
.binding = "XF86AudioMute",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "amixer sset Master toggle",
|
||||
.value = "pactl set-sink-mute @DEFAULT_SINK@ toggle",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86_MonBrightnessUp",
|
||||
.binding = "XF86MonBrightnessUp",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
.value = "brightnessctl set +10%",
|
||||
},
|
||||
}, {
|
||||
.binding = "XF86_MonBrightnessDown",
|
||||
.binding = "XF86MonBrightnessDown",
|
||||
.action = "Execute",
|
||||
.attributes[0] = {
|
||||
.name = "command",
|
||||
|
|
@ -141,14 +144,14 @@ static struct key_combos {
|
|||
* <mouse>
|
||||
* <context name="Maximize">
|
||||
* <mousebind button="Left" action="Click">
|
||||
* <action name="Focus"/>
|
||||
* <action name="Raise"/>
|
||||
* <action name="ToggleMaximize"/>
|
||||
* <action name="Focus" />
|
||||
* <action name="Raise" />
|
||||
* <action name="ToggleMaximize" />
|
||||
* </mousebind>
|
||||
* </context>
|
||||
* <context name="Root">
|
||||
* <mousebind direction="Up" action="Scroll">
|
||||
* <action name="GoToDesktop" to="left" wrap="yes"/>
|
||||
* <action name="GoToDesktop" to="left" wrap="yes" />
|
||||
* </mousebind>
|
||||
* </context>
|
||||
* </mouse>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ struct keybind {
|
|||
struct wl_list actions; /* struct action.link */
|
||||
struct wl_list link; /* struct rcxml.keybinds */
|
||||
bool on_release;
|
||||
bool override_inhibition;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -45,5 +46,5 @@ bool keybind_the_same(struct keybind *a, struct keybind *b);
|
|||
bool keybind_contains_keycode(struct keybind *keybind, xkb_keycode_t keycode);
|
||||
bool keybind_contains_keysym(struct keybind *keybind, xkb_keysym_t keysym);
|
||||
|
||||
void keybind_update_keycodes(struct server *server);
|
||||
void keybind_update_keycodes(void);
|
||||
#endif /* LABWC_KEYBIND_H */
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct libinput_category {
|
|||
int dwt; /* -1 or libinput_config_dwt_state */
|
||||
int click_method; /* -1 or libinput_config_click_method */
|
||||
int scroll_method; /* -1 or libinput_config_scroll_method */
|
||||
int scroll_button; /* -1 or a button from linux/input_event_codes.h */
|
||||
int send_events_mode; /* -1 or libinput_config_send_events_mode */
|
||||
bool have_calibration_matrix;
|
||||
double scroll_factor;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@ enum tearing_mode {
|
|||
LAB_TEARING_FULLSCREEN_FORCED,
|
||||
};
|
||||
|
||||
enum render_bit_depth {
|
||||
LAB_RENDER_BIT_DEPTH_DEFAULT = 0,
|
||||
LAB_RENDER_BIT_DEPTH_8,
|
||||
LAB_RENDER_BIT_DEPTH_10,
|
||||
};
|
||||
|
||||
enum tiling_events_mode {
|
||||
LAB_TILING_EVENTS_NEVER = 0,
|
||||
LAB_TILING_EVENTS_REGION = 1 << 0,
|
||||
|
|
@ -74,8 +80,10 @@ struct rcxml {
|
|||
int gap;
|
||||
enum adaptive_sync_mode adaptive_sync;
|
||||
enum tearing_mode allow_tearing;
|
||||
enum render_bit_depth target_render_depth;
|
||||
bool auto_enable_outputs;
|
||||
bool reuse_output_mode;
|
||||
uint32_t allowed_interfaces;
|
||||
bool xwayland_persistence;
|
||||
bool primary_selection;
|
||||
char *prompt_command;
|
||||
|
|
@ -89,6 +97,7 @@ struct rcxml {
|
|||
bool focus_follow_mouse;
|
||||
bool focus_follow_mouse_requires_movement;
|
||||
bool raise_on_focus;
|
||||
uint32_t raise_on_focus_delay_ms;
|
||||
|
||||
/* theme */
|
||||
char *theme_name;
|
||||
|
|
@ -144,6 +153,8 @@ struct rcxml {
|
|||
struct tablet_tool_config {
|
||||
enum lab_motion motion;
|
||||
double relative_motion_sensitivity;
|
||||
double min_pressure;
|
||||
double max_pressure;
|
||||
} tablet_tool;
|
||||
|
||||
/* libinput */
|
||||
|
|
@ -211,6 +222,7 @@ struct rcxml {
|
|||
bool mag_filter;
|
||||
};
|
||||
|
||||
/* defined in main.c */
|
||||
extern struct rcxml rc;
|
||||
|
||||
void rcxml_read(const char *filename);
|
||||
|
|
@ -222,4 +234,6 @@ void rcxml_finish(void);
|
|||
*/
|
||||
void append_parsed_actions(xmlNode *node, struct wl_list *list);
|
||||
|
||||
uint32_t parse_privileged_interface(const char *name);
|
||||
|
||||
#endif /* LABWC_RCXML_H */
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ void session_environment_init(void);
|
|||
* session_autostart_init - run autostart file as shell script
|
||||
* Note: Same as `sh ~/.config/labwc/autostart` (or equivalent XDG config dir)
|
||||
*/
|
||||
void session_autostart_init(struct server *server);
|
||||
void session_autostart_init(void);
|
||||
|
||||
/**
|
||||
* session_shutdown - run session shutdown file as shell script
|
||||
* Note: Same as `sh ~/.config/labwc/shutdown` (or equivalent XDG config dir)
|
||||
*/
|
||||
void session_shutdown(struct server *server);
|
||||
void session_shutdown(void);
|
||||
|
||||
#endif /* LABWC_SESSION_H */
|
||||
|
|
|
|||
|
|
@ -91,20 +91,24 @@ struct server;
|
|||
struct wlr_scene_node;
|
||||
|
||||
/* Begin window switcher */
|
||||
void cycle_begin(struct server *server, enum lab_cycle_dir direction,
|
||||
void cycle_begin(enum lab_cycle_dir direction,
|
||||
struct cycle_filter filter);
|
||||
|
||||
/* Cycle the selected view in the window switcher */
|
||||
void cycle_step(struct server *server, enum lab_cycle_dir direction);
|
||||
void cycle_step(enum lab_cycle_dir direction);
|
||||
|
||||
/* Closes the OSD */
|
||||
void cycle_finish(struct server *server, bool switch_focus);
|
||||
void cycle_finish(bool switch_focus);
|
||||
|
||||
/* Re-initialize the window switcher */
|
||||
void cycle_reinitialize(struct server *server);
|
||||
void cycle_reinitialize(void);
|
||||
|
||||
/* Immediately cycle to next/previous window */
|
||||
void cycle_immediate(enum lab_cycle_dir direction,
|
||||
struct cycle_filter filter);
|
||||
|
||||
/* Focus the clicked window and close OSD */
|
||||
void cycle_on_cursor_release(struct server *server, struct wlr_scene_node *node);
|
||||
void cycle_on_cursor_release(struct wlr_scene_node *node);
|
||||
|
||||
/* Used by osd.c internally to render window switcher fields */
|
||||
void cycle_osd_field_get_content(struct cycle_osd_field *field,
|
||||
|
|
@ -133,7 +137,7 @@ struct cycle_osd_impl {
|
|||
*/
|
||||
void (*init)(struct cycle_osd_output *osd_output);
|
||||
/*
|
||||
* Update the OSD to highlight server->cycle.selected_view.
|
||||
* Update the OSD to highlight server.cycle.selected_view.
|
||||
*/
|
||||
void (*update)(struct cycle_osd_output *osd_output);
|
||||
};
|
||||
|
|
@ -157,7 +161,7 @@ void cycle_osd_scroll_init(struct cycle_osd_output *osd_output,
|
|||
int nr_cols, int nr_rows, int nr_visible_rows,
|
||||
float *border_color, float *bg_color);
|
||||
|
||||
/* Scroll the OSD to show server->cycle.selected_view if needed */
|
||||
/* Scroll the OSD to show server.cycle.selected_view if needed */
|
||||
void cycle_osd_scroll_update(struct cycle_osd_output *osd_output);
|
||||
|
||||
extern struct cycle_osd_impl cycle_osd_classic_impl;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
|
||||
struct server;
|
||||
|
||||
void debug_dump_scene(struct server *server);
|
||||
void debug_dump_scene(void);
|
||||
|
||||
#endif /* LABWC_DEBUG_H */
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ struct server;
|
|||
struct view;
|
||||
struct wlr_surface;
|
||||
|
||||
void kde_server_decoration_init(struct server *server);
|
||||
void xdg_server_decoration_init(struct server *server);
|
||||
void kde_server_decoration_init(void);
|
||||
void xdg_server_decoration_init(void);
|
||||
|
||||
void kde_server_decoration_update_default(void);
|
||||
void kde_server_decoration_set_view(struct view *view, struct wlr_surface *surface);
|
||||
|
||||
void kde_server_decoration_finish(struct server *server);
|
||||
void xdg_server_decoration_finish(struct server *server);
|
||||
void kde_server_decoration_finish(void);
|
||||
void xdg_server_decoration_finish(void);
|
||||
|
||||
#endif /* LABWC_DECORATIONS_H */
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@
|
|||
|
||||
struct server;
|
||||
|
||||
void desktop_entry_init(struct server *server);
|
||||
void desktop_entry_finish(struct server *server);
|
||||
void desktop_entry_init(void);
|
||||
void desktop_entry_finish(void);
|
||||
|
||||
struct lab_img *desktop_entry_load_icon_from_app_id(
|
||||
struct server *server, const char *app_id, int size, float scale);
|
||||
struct lab_img *desktop_entry_load_icon_from_app_id(const char *app_id, int size, float scale);
|
||||
|
||||
struct lab_img *desktop_entry_load_icon(
|
||||
struct server *server, const char *icon_name, int size, float scale);
|
||||
struct lab_img *desktop_entry_load_icon(const char *icon_name, int size, float scale);
|
||||
|
||||
/**
|
||||
* desktop_entry_name_lookup() - return the application name
|
||||
|
|
@ -22,8 +20,7 @@ struct lab_img *desktop_entry_load_icon(
|
|||
* The lifetime of the returned value is the same as that
|
||||
* of sfdo_desktop_db (from `struct sfdo.desktop_db`)
|
||||
*/
|
||||
const char *desktop_entry_name_lookup(struct server *server,
|
||||
const char *app_id);
|
||||
const char *desktop_entry_name_lookup(const char *app_id);
|
||||
|
||||
#endif /* HAVE_LIBSFDO */
|
||||
#endif /* LABWC_DESKTOP_ENTRY_H */
|
||||
|
|
|
|||
|
|
@ -117,6 +117,6 @@ void edges_adjust_resize_geom(struct view *view, struct border edges,
|
|||
|
||||
bool edges_traverse_edge(struct edge current, struct edge target, struct edge edge);
|
||||
|
||||
void edges_calculate_visibility(struct server *server, struct view *ignored_view);
|
||||
void edges_calculate_visibility(struct view *ignored_view);
|
||||
|
||||
#endif /* LABWC_EDGES_H */
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ struct wl_display;
|
|||
struct wlr_seat;
|
||||
|
||||
void idle_manager_create(struct wl_display *display);
|
||||
void idle_manager_notify_activity(struct wlr_seat *seat);
|
||||
void idle_manager_notify_activity(struct wlr_seat *wlr_seat);
|
||||
|
||||
#endif /* LABWC_IDLE_H */
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct cursor_context_saved {
|
|||
*
|
||||
* If no node is found at cursor, ctx.type is set to ROOT.
|
||||
*/
|
||||
struct cursor_context get_cursor_context(struct server *server);
|
||||
struct cursor_context get_cursor_context(void);
|
||||
|
||||
/**
|
||||
* cursor_set - set cursor icon
|
||||
|
|
@ -82,7 +82,7 @@ void cursor_context_save(struct cursor_context_saved *saved_ctx,
|
|||
|
||||
/**
|
||||
* cursor_get_resize_edges - calculate resize edge based on cursor position
|
||||
* @cursor - the current cursor (usually server->seat.cursor)
|
||||
* @cursor - the current cursor (usually server.seat.cursor)
|
||||
* @cursor_context - result of get_cursor_context()
|
||||
*
|
||||
* Calculates the resize edge combination that is most appropriate based
|
||||
|
|
@ -92,7 +92,7 @@ void cursor_context_save(struct cursor_context_saved *saved_ctx,
|
|||
* keyboard modifier or when using the Resize action from a keybind.
|
||||
*/
|
||||
enum lab_edge cursor_get_resize_edges(struct wlr_cursor *cursor,
|
||||
struct cursor_context *ctx);
|
||||
const struct cursor_context *ctx);
|
||||
|
||||
/**
|
||||
* cursor_get_from_edge - translate lab_edge enum to lab_cursor enum
|
||||
|
|
@ -113,7 +113,7 @@ enum lab_cursors cursor_get_from_edge(enum lab_edge resize_edges);
|
|||
* or to force an update of the cursor icon by sending an exit and enter
|
||||
* event to an already focused surface.
|
||||
*/
|
||||
void cursor_update_focus(struct server *server);
|
||||
void cursor_update_focus(void);
|
||||
|
||||
/**
|
||||
* cursor_update_image - re-set the labwc cursor image
|
||||
|
|
@ -130,7 +130,7 @@ void cursor_update_image(struct seat *seat);
|
|||
* should be notified. Parameters sx, sy holds the surface coordinates
|
||||
* in that case.
|
||||
*/
|
||||
bool cursor_process_motion(struct server *server, uint32_t time, double *sx, double *sy);
|
||||
bool cursor_process_motion(uint32_t time, double *sx, double *sy);
|
||||
|
||||
/**
|
||||
* Processes cursor button press. The return value indicates if a client
|
||||
|
|
|
|||
|
|
@ -5,12 +5,17 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct seat;
|
||||
|
||||
/*
|
||||
* All keycodes in these functions are (Linux) libinput evdev scancodes which is
|
||||
* what 'wlr_keyboard' uses (e.g. 'seat->keyboard_group->keyboard->keycodes').
|
||||
* Note: These keycodes are different to XKB scancodes by a value of 8.
|
||||
*/
|
||||
|
||||
void key_state_indicator_update(struct seat *seat);
|
||||
void key_state_indicator_toggle(void);
|
||||
|
||||
/**
|
||||
* key_state_pressed_sent_keycodes - generate array of pressed+sent keys
|
||||
* Note: The array is generated by subtracting any bound keys from _all_ pressed
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ enum input_mode {
|
|||
};
|
||||
|
||||
struct seat {
|
||||
struct wlr_seat *seat;
|
||||
struct server *server;
|
||||
struct wlr_seat *wlr_seat;
|
||||
struct wlr_keyboard_group *keyboard_group;
|
||||
|
||||
struct wl_list touch_points; /* struct touch_point.link */
|
||||
|
|
@ -149,8 +148,15 @@ struct seat {
|
|||
};
|
||||
|
||||
struct server {
|
||||
uint32_t wlr_version;
|
||||
|
||||
struct wl_display *wl_display;
|
||||
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
|
||||
|
||||
/* Pending auto-raise timer (used when rc.raise_on_focus_delay_ms > 0) */
|
||||
struct view *pending_auto_raise_view;
|
||||
struct wl_event_source *pending_auto_raise_timer;
|
||||
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_allocator *allocator;
|
||||
struct wlr_backend *backend;
|
||||
|
|
@ -188,6 +194,13 @@ struct server {
|
|||
struct wlr_xdg_toplevel_icon_manager_v1 *xdg_toplevel_icon_manager;
|
||||
struct wl_listener xdg_toplevel_icon_set_icon;
|
||||
|
||||
struct {
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *manager;
|
||||
struct {
|
||||
struct wl_listener new_request;
|
||||
} on;
|
||||
} toplevel_capture;
|
||||
|
||||
/* front to back order */
|
||||
struct wl_list views;
|
||||
uint64_t next_view_creation_id;
|
||||
|
|
@ -244,13 +257,14 @@ struct server {
|
|||
struct wl_list all; /* struct workspace.link */
|
||||
struct workspace *current;
|
||||
struct workspace *last;
|
||||
struct lab_cosmic_workspace_manager *cosmic_manager;
|
||||
struct lab_cosmic_workspace_group *cosmic_group;
|
||||
struct lab_ext_workspace_manager *ext_manager;
|
||||
struct lab_ext_workspace_group *ext_group;
|
||||
struct wlr_ext_workspace_manager_v1 *ext_manager;
|
||||
struct wlr_ext_workspace_group_handle_v1 *ext_group;
|
||||
struct {
|
||||
struct wl_listener layout_output_added;
|
||||
} on;
|
||||
struct {
|
||||
struct wl_listener commit;
|
||||
} on_ext_manager;
|
||||
} workspaces;
|
||||
|
||||
struct wl_list outputs;
|
||||
|
|
@ -274,7 +288,6 @@ struct server {
|
|||
struct wl_listener renderer_lost;
|
||||
|
||||
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
||||
struct wl_listener gamma_control_set_gamma;
|
||||
|
||||
struct session_lock_manager *session_lock_manager;
|
||||
|
||||
|
|
@ -303,19 +316,22 @@ struct server {
|
|||
/* Set when in cycle (alt-tab) mode */
|
||||
struct cycle_state cycle;
|
||||
|
||||
struct theme *theme;
|
||||
|
||||
struct menu *menu_current;
|
||||
struct wl_list menus;
|
||||
|
||||
struct sfdo *sfdo;
|
||||
|
||||
pid_t primary_client_pid;
|
||||
|
||||
char *title_fmt;
|
||||
};
|
||||
|
||||
/* defined in main.c */
|
||||
extern struct server server;
|
||||
|
||||
void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
|
||||
void xdg_shell_init(struct server *server);
|
||||
void xdg_shell_finish(struct server *server);
|
||||
void xdg_shell_init(void);
|
||||
void xdg_shell_finish(void);
|
||||
|
||||
/*
|
||||
* desktop.c routines deal with a collection of views
|
||||
|
|
@ -343,6 +359,13 @@ void xdg_shell_finish(struct server *server);
|
|||
*/
|
||||
void desktop_focus_view(struct view *view, bool raise);
|
||||
|
||||
/**
|
||||
* desktop_cancel_pending_auto_raise() - cancel any pending delayed auto-raise
|
||||
* (from raiseOnFocusDelay). Called when a view is being destroyed, on config
|
||||
* reload, or when a new focus change with raise=false supersedes the pending.
|
||||
*/
|
||||
void desktop_cancel_pending_auto_raise(void);
|
||||
|
||||
/**
|
||||
* desktop_focus_view_or_surface() - like desktop_focus_view() but can
|
||||
* also focus other (e.g. xwayland-unmanaged) surfaces
|
||||
|
|
@ -350,14 +373,14 @@ void desktop_focus_view(struct view *view, bool raise);
|
|||
void desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
||||
struct wlr_surface *surface, bool raise);
|
||||
|
||||
void desktop_arrange_all_views(struct server *server);
|
||||
void desktop_arrange_all_views(void);
|
||||
void desktop_focus_output(struct output *output);
|
||||
|
||||
/**
|
||||
* Toggles the (output local) visibility of the layershell top layer
|
||||
* based on the existence of a fullscreen window on the current workspace.
|
||||
*/
|
||||
void desktop_update_top_layer_visibility(struct server *server);
|
||||
void desktop_update_top_layer_visibility(void);
|
||||
|
||||
/**
|
||||
* desktop_focus_topmost_view() - focus the topmost view on the current
|
||||
|
|
@ -367,11 +390,11 @@ void desktop_update_top_layer_visibility(struct server *server);
|
|||
* This function is typically called when the focused view is hidden
|
||||
* (closes, is minimized, etc.) to focus the "next" view underneath.
|
||||
*/
|
||||
void desktop_focus_topmost_view(struct server *server);
|
||||
void desktop_focus_topmost_view(void);
|
||||
|
||||
void seat_init(struct server *server);
|
||||
void seat_finish(struct server *server);
|
||||
void seat_reconfigure(struct server *server);
|
||||
void seat_init(void);
|
||||
void seat_finish(void);
|
||||
void seat_reconfigure(void);
|
||||
void seat_force_focus_surface(struct seat *seat, struct wlr_surface *surface);
|
||||
void seat_focus_surface(struct seat *seat, struct wlr_surface *surface);
|
||||
|
||||
|
|
@ -403,15 +426,15 @@ void seat_focus_override_end(struct seat *seat, bool restore_focus);
|
|||
/**
|
||||
* interactive_anchor_to_cursor() - repositions the geometry to remain
|
||||
* underneath the cursor when its size changes during interactive move.
|
||||
* This function also resizes server->grab_box and repositions it to remain
|
||||
* underneath server->grab_{x,y}.
|
||||
* This function also resizes server.grab_box and repositions it to remain
|
||||
* underneath server.grab_{x,y}.
|
||||
*
|
||||
* geo->{width,height} are provided by the caller.
|
||||
* geo->{x,y} are computed by this function.
|
||||
*/
|
||||
void interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo);
|
||||
void interactive_anchor_to_cursor(struct wlr_box *geo);
|
||||
|
||||
void interactive_set_grab_context(struct cursor_context *ctx);
|
||||
void interactive_set_grab_context(const struct cursor_context *ctx);
|
||||
void interactive_begin(struct view *view, enum input_mode mode,
|
||||
enum lab_edge edges);
|
||||
void interactive_finish(struct view *view);
|
||||
|
|
@ -429,12 +452,12 @@ bool edge_from_cursor(struct seat *seat, struct output **dest_output,
|
|||
|
||||
void handle_tearing_new_object(struct wl_listener *listener, void *data);
|
||||
|
||||
void server_init(struct server *server);
|
||||
void server_start(struct server *server);
|
||||
void server_finish(struct server *server);
|
||||
void server_init(void);
|
||||
void server_start(void);
|
||||
void server_finish(void);
|
||||
|
||||
void create_constraint(struct wl_listener *listener, void *data);
|
||||
void constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
|
||||
void constrain_cursor(struct wlr_pointer_constraint_v1
|
||||
*constraint);
|
||||
|
||||
#endif /* LABWC_H */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ struct seat;
|
|||
struct lab_layer_surface {
|
||||
struct wlr_layer_surface_v1 *layer_surface;
|
||||
struct wlr_scene_layer_surface_v1 *scene_layer_surface;
|
||||
struct server *server;
|
||||
|
||||
bool mapped;
|
||||
/* true only inside handle_unmap() */
|
||||
|
|
@ -29,7 +28,6 @@ struct lab_layer_surface {
|
|||
struct lab_layer_popup {
|
||||
struct wlr_xdg_popup *wlr_popup;
|
||||
struct wlr_scene_tree *scene_tree;
|
||||
struct server *server;
|
||||
bool parent_was_focused;
|
||||
|
||||
/* To simplify moving popup nodes from the bottom to the top layer */
|
||||
|
|
@ -41,8 +39,8 @@ struct lab_layer_popup {
|
|||
struct wl_listener reposition;
|
||||
};
|
||||
|
||||
void layers_init(struct server *server);
|
||||
void layers_finish(struct server *server);
|
||||
void layers_init(void);
|
||||
void layers_finish(void);
|
||||
|
||||
void layers_arrange(struct output *output);
|
||||
void layer_try_set_focus(struct seat *seat,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ enum magnify_dir {
|
|||
MAGNIFY_DECREASE
|
||||
};
|
||||
|
||||
void magnifier_toggle(struct server *server);
|
||||
void magnifier_set_scale(struct server *server, enum magnify_dir dir);
|
||||
void magnifier_toggle(void);
|
||||
void magnifier_set_scale(enum magnify_dir dir);
|
||||
bool output_wants_magnification(struct output *output);
|
||||
void magnifier_draw(struct output *output, struct wlr_buffer *output_buffer,
|
||||
struct wlr_box *damage);
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@ struct menuitem {
|
|||
char *text;
|
||||
char *icon_name;
|
||||
const char *arrow;
|
||||
uint32_t accelerator;
|
||||
struct menu *parent;
|
||||
struct menu *submenu;
|
||||
bool selectable;
|
||||
bool use_markup;
|
||||
enum menuitem_type type;
|
||||
int native_width;
|
||||
struct wlr_scene_tree *tree;
|
||||
|
|
@ -49,7 +51,6 @@ struct menu {
|
|||
int height;
|
||||
} size;
|
||||
struct wl_list menuitems;
|
||||
struct server *server;
|
||||
struct {
|
||||
struct menu *menu;
|
||||
struct menuitem *item;
|
||||
|
|
@ -65,14 +66,27 @@ struct menu {
|
|||
};
|
||||
|
||||
/* For keyboard support */
|
||||
void menu_item_select_next(struct server *server);
|
||||
void menu_item_select_previous(struct server *server);
|
||||
void menu_submenu_enter(struct server *server);
|
||||
void menu_submenu_leave(struct server *server);
|
||||
bool menu_call_selected_actions(struct server *server);
|
||||
void menu_item_select_next(void);
|
||||
void menu_item_select_previous(void);
|
||||
|
||||
void menu_init(struct server *server);
|
||||
void menu_finish(struct server *server);
|
||||
/**
|
||||
* menu_item_select_by_accelerator - selects the next menu item with
|
||||
* a matching accelerator, starting after the current selection
|
||||
*
|
||||
* @accelerator a shortcut to quickly select/open an item, defined in menu.xml
|
||||
* with an underscore in the item label before the target letter.
|
||||
*
|
||||
* Return: a boolean value that represents whether the newly selected item
|
||||
* needs to be executed.
|
||||
*/
|
||||
bool menu_item_select_by_accelerator(uint32_t accelerator);
|
||||
|
||||
void menu_submenu_enter(void);
|
||||
void menu_submenu_leave(void);
|
||||
bool menu_call_selected_actions(void);
|
||||
|
||||
void menu_init(void);
|
||||
void menu_finish(void);
|
||||
void menu_on_view_destroy(struct view *view);
|
||||
|
||||
/**
|
||||
|
|
@ -80,15 +94,15 @@ void menu_on_view_destroy(struct view *view);
|
|||
*
|
||||
* @id id string defined in menu.xml like "root-menu"
|
||||
*/
|
||||
struct menu *menu_get_by_id(struct server *server, const char *id);
|
||||
struct menu *menu_get_by_id(const char *id);
|
||||
|
||||
/**
|
||||
* menu_open_root - open menu on position (x, y)
|
||||
*
|
||||
* This function will close server->menu_current, open the
|
||||
* new menu and assign @menu to server->menu_current.
|
||||
* This function will close server.menu_current, open the
|
||||
* new menu and assign @menu to server.menu_current.
|
||||
*
|
||||
* Additionally, server->input_mode will be set to LAB_INPUT_STATE_MENU.
|
||||
* Additionally, server.input_mode will be set to LAB_INPUT_STATE_MENU.
|
||||
*/
|
||||
void menu_open_root(struct menu *menu, int x, int y);
|
||||
|
||||
|
|
@ -101,16 +115,16 @@ void menu_open_root(struct menu *menu, int x, int y);
|
|||
void menu_process_cursor_motion(struct wlr_scene_node *node);
|
||||
|
||||
/**
|
||||
* menu_close_root- close root menu
|
||||
* menu_close_root - close root menu
|
||||
*
|
||||
* This function will close server->menu_current and set it to NULL.
|
||||
* Asserts that server->input_mode is set to LAB_INPUT_STATE_MENU.
|
||||
* This function will close server.menu_current and set it to NULL.
|
||||
* Asserts that server.input_mode is set to LAB_INPUT_STATE_MENU.
|
||||
*
|
||||
* Additionally, server->input_mode will be set to LAB_INPUT_STATE_PASSTHROUGH.
|
||||
* Additionally, server.input_mode will be set to LAB_INPUT_STATE_PASSTHROUGH.
|
||||
*/
|
||||
void menu_close_root(struct server *server);
|
||||
void menu_close_root(void);
|
||||
|
||||
/* menu_reconfigure - reload theme and content */
|
||||
void menu_reconfigure(struct server *server);
|
||||
void menu_reconfigure(void);
|
||||
|
||||
#endif /* LABWC_MENU_H */
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
struct server;
|
||||
struct wlr_output;
|
||||
|
||||
void output_virtual_add(struct server *server, const char *output_name,
|
||||
void output_virtual_add(const char *output_name,
|
||||
struct wlr_output **store_wlr_output);
|
||||
void output_virtual_remove(struct server *server, const char *output_name);
|
||||
void output_virtual_update_fallback(struct server *server);
|
||||
void output_virtual_remove(const char *output_name);
|
||||
void output_virtual_update_fallback(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
struct output {
|
||||
struct wl_list link; /* server.outputs */
|
||||
struct server *server;
|
||||
struct wlr_output *wlr_output;
|
||||
struct wlr_output_state pending;
|
||||
struct wlr_scene_output *scene_output;
|
||||
|
|
@ -39,19 +38,16 @@ struct output {
|
|||
* disconnected and connected again.
|
||||
*/
|
||||
uint64_t id_bit;
|
||||
|
||||
bool gamma_lut_changed;
|
||||
};
|
||||
|
||||
#undef LAB_NR_LAYERS
|
||||
|
||||
void output_init(struct server *server);
|
||||
void output_finish(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);
|
||||
struct output *output_nearest_to(struct server *server, int lx, int ly);
|
||||
struct output *output_nearest_to_cursor(struct server *server);
|
||||
void output_init(void);
|
||||
void output_finish(void);
|
||||
struct output *output_from_wlr_output(struct wlr_output *wlr_output);
|
||||
struct output *output_from_name(const char *name);
|
||||
struct output *output_nearest_to(int lx, int ly);
|
||||
struct output *output_nearest_to_cursor(void);
|
||||
|
||||
/**
|
||||
* output_get_adjacent() - get next output, in a given direction,
|
||||
|
|
@ -69,12 +65,15 @@ struct output *output_get_adjacent(struct output *output,
|
|||
|
||||
bool output_is_usable(struct output *output);
|
||||
void output_update_usable_area(struct output *output);
|
||||
void output_update_all_usable_areas(struct server *server, bool layout_changed);
|
||||
void output_update_all_usable_areas(bool layout_changed);
|
||||
bool output_get_tearing_allowance(struct output *output);
|
||||
struct wlr_box output_usable_area_in_layout_coords(struct output *output);
|
||||
void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
||||
void *data);
|
||||
void output_enable_adaptive_sync(struct output *output, bool enabled);
|
||||
void output_enable_hdr(struct output *output, struct wlr_output_state *os,
|
||||
bool enabled, bool silent);
|
||||
void output_state_setup_hdr(struct output *output, bool silent);
|
||||
|
||||
/**
|
||||
* Notifies whether a fullscreen view is displayed on the given output.
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H
|
||||
#define LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H
|
||||
|
||||
struct lab_cosmic_workspace;
|
||||
struct lab_cosmic_workspace_group;
|
||||
struct lab_cosmic_workspace_manager;
|
||||
|
||||
enum pending_change {
|
||||
/* group events */
|
||||
CW_PENDING_WS_CREATE = 1 << 0,
|
||||
|
||||
/* ws events*/
|
||||
CW_PENDING_WS_ACTIVATE = 1 << 1,
|
||||
CW_PENDING_WS_DEACTIVATE = 1 << 2,
|
||||
CW_PENDING_WS_REMOVE = 1 << 3,
|
||||
};
|
||||
|
||||
void cosmic_group_output_send_initial_state(struct lab_cosmic_workspace_group *group,
|
||||
struct wl_resource *group_resource);
|
||||
|
||||
void cosmic_manager_schedule_done_event(struct lab_cosmic_workspace_manager *manager);
|
||||
|
||||
#endif /* LABWC_PROTOCOLS_COSMIC_WORKSPACES_INTERNAL_H */
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_PROTOCOLS_COSMIC_WORKSPACES_H
|
||||
#define LABWC_PROTOCOLS_COSMIC_WORKSPACES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_output;
|
||||
|
||||
struct lab_cosmic_workspace_manager {
|
||||
struct wl_global *global;
|
||||
struct wl_list groups;
|
||||
uint32_t caps;
|
||||
struct wl_event_source *idle_source;
|
||||
struct wl_event_loop *event_loop;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} on;
|
||||
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
struct lab_cosmic_workspace_group {
|
||||
struct lab_cosmic_workspace_manager *manager;
|
||||
struct wl_list workspaces;
|
||||
struct wl_array capabilities;
|
||||
struct {
|
||||
struct wl_signal create_workspace;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link;
|
||||
struct wl_list outputs;
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
struct lab_cosmic_workspace {
|
||||
struct lab_cosmic_workspace_group *group;
|
||||
char *name;
|
||||
struct wl_array coordinates;
|
||||
struct wl_array capabilities;
|
||||
uint32_t state; /* enum lab_cosmic_workspace_state */
|
||||
uint32_t state_pending; /* enum lab_cosmic_workspace_state */
|
||||
|
||||
struct {
|
||||
struct wl_signal activate;
|
||||
struct wl_signal deactivate;
|
||||
struct wl_signal remove;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link;
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
enum lab_cosmic_workspace_caps {
|
||||
CW_CAP_NONE = 0,
|
||||
CW_CAP_GRP_ALL = 0x000000ff,
|
||||
CW_CAP_WS_ALL = 0x0000ff00,
|
||||
|
||||
/* group caps */
|
||||
CW_CAP_GRP_WS_CREATE = 1 << 0,
|
||||
|
||||
/* workspace caps */
|
||||
CW_CAP_WS_ACTIVATE = 1 << 8,
|
||||
CW_CAP_WS_DEACTIVATE = 1 << 9,
|
||||
CW_CAP_WS_REMOVE = 1 << 10,
|
||||
};
|
||||
|
||||
struct lab_cosmic_workspace_manager *lab_cosmic_workspace_manager_create(
|
||||
struct wl_display *display, uint32_t caps, uint32_t version);
|
||||
|
||||
struct lab_cosmic_workspace_group *lab_cosmic_workspace_group_create(
|
||||
struct lab_cosmic_workspace_manager *manager);
|
||||
|
||||
void lab_cosmic_workspace_group_output_enter(
|
||||
struct lab_cosmic_workspace_group *group, struct wlr_output *output);
|
||||
|
||||
void lab_cosmic_workspace_group_output_leave(
|
||||
|
||||
struct lab_cosmic_workspace_group *group, struct wlr_output *output);
|
||||
void lab_cosmic_workspace_group_destroy(struct lab_cosmic_workspace_group *group);
|
||||
|
||||
struct lab_cosmic_workspace *lab_cosmic_workspace_create(struct lab_cosmic_workspace_group *group);
|
||||
void lab_cosmic_workspace_set_name(struct lab_cosmic_workspace *workspace, const char *name);
|
||||
void lab_cosmic_workspace_set_active(struct lab_cosmic_workspace *workspace, bool enabled);
|
||||
void lab_cosmic_workspace_set_urgent(struct lab_cosmic_workspace *workspace, bool enabled);
|
||||
void lab_cosmic_workspace_set_hidden(struct lab_cosmic_workspace *workspace, bool enabled);
|
||||
void lab_cosmic_workspace_set_coordinates(struct lab_cosmic_workspace *workspace,
|
||||
struct wl_array *coordinates);
|
||||
void lab_cosmic_workspace_destroy(struct lab_cosmic_workspace *workspace);
|
||||
|
||||
#endif /* LABWC_PROTOCOLS_COSMIC_WORKSPACES_H */
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H
|
||||
#define LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H
|
||||
|
||||
struct wl_resource;
|
||||
struct lab_ext_workspace_group;
|
||||
struct lab_ext_workspace_manager;
|
||||
|
||||
enum pending_ext_workspaces_change {
|
||||
/* group events */
|
||||
WS_PENDING_WS_CREATE = 1 << 0,
|
||||
|
||||
/* ws events*/
|
||||
WS_PENDING_WS_ACTIVATE = 1 << 1,
|
||||
WS_PENDING_WS_DEACTIVATE = 1 << 2,
|
||||
WS_PENDING_WS_REMOVE = 1 << 3,
|
||||
WS_PENDING_WS_ASSIGN = 1 << 4,
|
||||
};
|
||||
|
||||
void ext_group_output_send_initial_state(struct lab_ext_workspace_group *group,
|
||||
struct wl_resource *group_resource);
|
||||
|
||||
void ext_manager_schedule_done_event(struct lab_ext_workspace_manager *manager);
|
||||
|
||||
#endif /* LABWC_PROTOCOLS_EXT_WORKSPACES_INTERNAL_H */
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_PROTOCOLS_EXT_WORKSPACES_H
|
||||
#define LABWC_PROTOCOLS_EXT_WORKSPACES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct wlr_output;
|
||||
|
||||
struct lab_ext_workspace_manager {
|
||||
struct wl_global *global;
|
||||
struct wl_list groups;
|
||||
struct wl_list workspaces;
|
||||
uint32_t caps;
|
||||
struct wl_event_source *idle_source;
|
||||
struct wl_event_loop *event_loop;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} on;
|
||||
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
struct lab_ext_workspace_group {
|
||||
struct lab_ext_workspace_manager *manager;
|
||||
uint32_t capabilities;
|
||||
struct {
|
||||
struct wl_signal create_workspace;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link;
|
||||
struct wl_list outputs;
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
struct lab_ext_workspace {
|
||||
struct lab_ext_workspace_manager *manager;
|
||||
struct lab_ext_workspace_group *group;
|
||||
char *id;
|
||||
char *name;
|
||||
struct wl_array coordinates;
|
||||
uint32_t capabilities;
|
||||
uint32_t state; /* enum lab_ext_workspace_state */
|
||||
uint32_t state_pending; /* enum lab_ext_workspace_state */
|
||||
|
||||
struct {
|
||||
struct wl_signal activate;
|
||||
struct wl_signal deactivate;
|
||||
struct wl_signal remove;
|
||||
struct wl_signal assign;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct wl_list link;
|
||||
struct wl_list resources;
|
||||
};
|
||||
|
||||
enum lab_ext_workspace_caps {
|
||||
WS_CAP_NONE = 0,
|
||||
WS_CAP_GRP_ALL = 0x0000ffff,
|
||||
WS_CAP_WS_ALL = 0xffff0000,
|
||||
|
||||
/* group caps */
|
||||
WS_CAP_GRP_WS_CREATE = 1 << 0,
|
||||
|
||||
/* workspace caps */
|
||||
WS_CAP_WS_ACTIVATE = 1 << 16,
|
||||
WS_CAP_WS_DEACTIVATE = 1 << 17,
|
||||
WS_CAP_WS_REMOVE = 1 << 18,
|
||||
WS_CAP_WS_ASSIGN = 1 << 19,
|
||||
};
|
||||
|
||||
struct lab_ext_workspace_manager *lab_ext_workspace_manager_create(
|
||||
struct wl_display *display, uint32_t caps, uint32_t version);
|
||||
|
||||
struct lab_ext_workspace_group *lab_ext_workspace_group_create(
|
||||
struct lab_ext_workspace_manager *manager);
|
||||
|
||||
void lab_ext_workspace_group_output_enter(
|
||||
struct lab_ext_workspace_group *group, struct wlr_output *output);
|
||||
|
||||
void lab_ext_workspace_group_output_leave(
|
||||
struct lab_ext_workspace_group *group, struct wlr_output *output);
|
||||
|
||||
void lab_ext_workspace_group_destroy(struct lab_ext_workspace_group *group);
|
||||
|
||||
/* Create a new workspace, id may be NULL */
|
||||
struct lab_ext_workspace *lab_ext_workspace_create(
|
||||
struct lab_ext_workspace_manager *manager, const char *id);
|
||||
|
||||
void lab_ext_workspace_assign_to_group(struct lab_ext_workspace *workspace,
|
||||
struct lab_ext_workspace_group *group);
|
||||
|
||||
void lab_ext_workspace_set_name(struct lab_ext_workspace *workspace, const char *name);
|
||||
|
||||
void lab_ext_workspace_set_active(struct lab_ext_workspace *workspace, bool enabled);
|
||||
|
||||
void lab_ext_workspace_set_urgent(struct lab_ext_workspace *workspace, bool enabled);
|
||||
|
||||
void lab_ext_workspace_set_hidden(struct lab_ext_workspace *workspace, bool enabled);
|
||||
|
||||
void lab_ext_workspace_set_coordinates(struct lab_ext_workspace *workspace,
|
||||
struct wl_array *coordinates);
|
||||
|
||||
void lab_ext_workspace_destroy(struct lab_ext_workspace *workspace);
|
||||
|
||||
#endif /* LABWC_PROTOCOLS_EXT_WORKSPACES_H */
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_PROTOCOLS_TRANSACTION_ADDON_H
|
||||
#define LABWC_PROTOCOLS_TRANSACTION_ADDON_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
struct lab_transaction_op {
|
||||
uint32_t change;
|
||||
void *src;
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
// Private
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct lab_transaction_session_context {
|
||||
int ref_count;
|
||||
struct wl_list transaction_ops;
|
||||
};
|
||||
|
||||
struct lab_wl_resource_addon {
|
||||
struct lab_transaction_session_context *ctx;
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a new addon which can be attached to a wl_resource via
|
||||
* wl_resource_set_user_data() and retrieved via wl_resource_get_user_data().
|
||||
*
|
||||
* Usually the ctx argument should be addon->ctx of the parent wl_resource.
|
||||
* If it is NULL it will be created automatically which can be used for top
|
||||
* level wl_resources (when a client binds a wl_global from the registry).
|
||||
*
|
||||
* The context refcount is increased by one after this call.
|
||||
*/
|
||||
struct lab_wl_resource_addon *lab_resource_addon_create(
|
||||
struct lab_transaction_session_context *ctx);
|
||||
|
||||
/*
|
||||
* A generic transaction operation attached to
|
||||
* a session context transaction operation list.
|
||||
*
|
||||
* All arguments other than the context are user defined.
|
||||
* Use of an enum for pending_change is suggested.
|
||||
*
|
||||
* The client is responsible for eventually freeing the data
|
||||
* passed in the void *src and *data arguments by listening
|
||||
* to the events.destroy signal. The transaction operations can be
|
||||
* looped through by using lab_transaction_for_each(trans_op, ctx).
|
||||
*/
|
||||
struct lab_transaction_op *lab_transaction_op_add(
|
||||
struct lab_transaction_session_context *ctx,
|
||||
uint32_t pending_change, void *src, void *data);
|
||||
|
||||
/*
|
||||
* Removes the transaction operation from the ctx list and frees it.
|
||||
*
|
||||
* Does *not* free any passed in src or data arguments.
|
||||
* Use the events.destroy signal for that if necessary.
|
||||
*/
|
||||
void lab_transaction_op_destroy(struct lab_transaction_op *transaction_op);
|
||||
|
||||
/*
|
||||
* Destroys the addon.
|
||||
*
|
||||
* The context refcount is decreased by one. If it reaches
|
||||
* zero the context will be free'd alongside the addon itself.
|
||||
* If the context is destroyed all pending transaction operations
|
||||
* are destroyed as well.
|
||||
*/
|
||||
void lab_resource_addon_destroy(struct lab_wl_resource_addon *addon);
|
||||
|
||||
/* Convenience wrappers for looping through the pending transaction ops of a ctx */
|
||||
#define lab_transaction_for_each(transaction_op, ctx) \
|
||||
wl_list_for_each(transaction_op, &(ctx)->transaction_ops, link)
|
||||
|
||||
#define lab_transaction_for_each_safe(trans_op, trans_op_tmp, ctx) \
|
||||
wl_list_for_each_safe(trans_op, trans_op_tmp, &(ctx)->transaction_ops, link)
|
||||
|
||||
#endif /* LABWC_PROTOCOLS_TRANSACTIONS_ADDON_H */
|
||||
|
|
@ -26,7 +26,7 @@ struct region {
|
|||
};
|
||||
|
||||
/* Returns true if we should show the region overlay or snap to region */
|
||||
bool regions_should_snap(struct server *server);
|
||||
bool regions_should_snap(void);
|
||||
|
||||
/**
|
||||
* regions_reconfigure*() - re-initializes all regions from struct rc.
|
||||
|
|
@ -36,7 +36,7 @@ bool regions_should_snap(struct server *server);
|
|||
* - new output local regions are created from struct rc
|
||||
* - the region geometry is re-calculated
|
||||
*/
|
||||
void regions_reconfigure(struct server *server);
|
||||
void regions_reconfigure(void);
|
||||
void regions_reconfigure_output(struct output *output);
|
||||
|
||||
/* re-calculate the geometry based on usable area */
|
||||
|
|
@ -62,7 +62,7 @@ void regions_evacuate_output(struct output *output);
|
|||
void regions_destroy(struct seat *seat, struct wl_list *regions);
|
||||
|
||||
/* Get output local region from cursor or name, may be NULL */
|
||||
struct region *regions_from_cursor(struct server *server);
|
||||
struct region *regions_from_cursor(void);
|
||||
struct region *regions_from_name(const char *region_name, struct output *output);
|
||||
|
||||
#endif /* LABWC_REGIONS_H */
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
struct server;
|
||||
struct view;
|
||||
|
||||
void resize_indicator_reconfigure(struct server *server);
|
||||
void resize_indicator_reconfigure(void);
|
||||
void resize_indicator_show(struct view *view);
|
||||
void resize_indicator_update(struct view *view);
|
||||
void resize_indicator_hide(struct view *view);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ void scaled_buffer_request_update(struct scaled_buffer *self,
|
|||
|
||||
/**
|
||||
* scaled_buffer_invalidate_sharing - clear the list of entire cached
|
||||
* scaled_buffers used to share visually dupliated buffers. This should
|
||||
* scaled_buffers used to share visually duplicated buffers. This should
|
||||
* be called on Reconfigure to force updates of newly created
|
||||
* scaled_buffers rather than reusing ones created before Reconfigure.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ struct scaled_font_buffer {
|
|||
|
||||
/* Private */
|
||||
char *text;
|
||||
bool use_markup;
|
||||
int max_width;
|
||||
float color[4];
|
||||
float bg_color[4];
|
||||
|
|
@ -69,8 +70,18 @@ scaled_font_buffer_create_for_titlebar(struct wlr_scene_tree *parent,
|
|||
* bg_color is ignored for font buffers created with
|
||||
* scaled_font_buffer_create_for_titlebar().
|
||||
*/
|
||||
void scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text,
|
||||
int max_width, struct font *font, const float *color,
|
||||
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 an existing auto scaling font buffer allowing the use of pango markup.
|
||||
*
|
||||
* Behaves identically to scaled_font_buffer_update(), but allows customization
|
||||
* of the `use_markup` field of the @self struct via @use_markup.
|
||||
*/
|
||||
void scaled_font_buffer_update_markup(struct scaled_font_buffer *self,
|
||||
const char *text, int max_width, struct font *font, const float *color,
|
||||
const float *bg_color, bool use_markup);
|
||||
|
||||
#endif /* LABWC_SCALED_FONT_BUFFER_H */
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ struct wlr_scene_buffer;
|
|||
struct scaled_icon_buffer {
|
||||
struct scaled_buffer *scaled_buffer;
|
||||
struct wlr_scene_buffer *scene_buffer;
|
||||
struct server *server;
|
||||
/* for window icon */
|
||||
struct view *view;
|
||||
char *view_app_id;
|
||||
|
|
@ -39,8 +38,7 @@ struct scaled_icon_buffer {
|
|||
* wlr_scene_buffer (or one of its parents) is being destroyed.
|
||||
*/
|
||||
struct scaled_icon_buffer *scaled_icon_buffer_create(
|
||||
struct wlr_scene_tree *parent, struct server *server,
|
||||
int width, int height);
|
||||
struct wlr_scene_tree *parent, int width, int height);
|
||||
|
||||
void scaled_icon_buffer_set_view(struct scaled_icon_buffer *self,
|
||||
struct view *view);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ struct output;
|
|||
struct server;
|
||||
|
||||
struct session_lock_manager {
|
||||
struct server *server;
|
||||
struct wlr_session_lock_manager_v1 *wlr_manager;
|
||||
/* View re-focused on unlock */
|
||||
struct view *last_active_view;
|
||||
|
|
@ -31,8 +30,8 @@ struct session_lock_manager {
|
|||
struct wl_listener lock_destroy;
|
||||
};
|
||||
|
||||
void session_lock_init(struct server *server);
|
||||
void session_lock_init(void);
|
||||
void session_lock_output_create(struct session_lock_manager *manager, struct output *output);
|
||||
void session_lock_update_for_layout_change(struct server *server);
|
||||
void session_lock_update_for_layout_change(void);
|
||||
|
||||
#endif /* LABWC_SESSION_LOCK_H */
|
||||
|
|
|
|||
8
include/show-desktop.h
Normal file
8
include/show-desktop.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef LABWC_SHOW_DESKTOP_H
|
||||
#define LABWC_SHOW_DESKTOP_H
|
||||
|
||||
void show_desktop_toggle(void);
|
||||
void show_desktop_reset(void);
|
||||
|
||||
#endif /* LABWC_SHOW_DESKTOP_H */
|
||||
|
|
@ -51,8 +51,7 @@ void ssd_set_titlebar(struct ssd *ssd, bool enabled);
|
|||
void ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable);
|
||||
void ssd_enable_shade(struct ssd *ssd, bool enable);
|
||||
|
||||
void ssd_update_hovered_button(struct server *server,
|
||||
struct wlr_scene_node *node);
|
||||
void ssd_update_hovered_button(struct wlr_scene_node *node);
|
||||
|
||||
void ssd_button_free(struct ssd_button *button);
|
||||
|
||||
|
|
|
|||
|
|
@ -213,16 +213,13 @@ struct theme {
|
|||
int mag_border_width;
|
||||
};
|
||||
|
||||
struct server;
|
||||
|
||||
/**
|
||||
* theme_init - read openbox theme and generate button textures
|
||||
* @theme: theme data
|
||||
* @server: server
|
||||
* @theme_name: theme-name in <theme-dir>/<theme-name>/labwc/themerc
|
||||
* Note <theme-dir> is obtained in theme-dir.c
|
||||
*/
|
||||
void theme_init(struct theme *theme, struct server *server, const char *theme_name);
|
||||
void theme_init(struct theme *theme, const char *theme_name);
|
||||
|
||||
/**
|
||||
* theme_finish - free button textures
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ struct view_impl {
|
|||
};
|
||||
|
||||
struct view {
|
||||
struct server *server;
|
||||
enum view_type type;
|
||||
const struct view_impl *impl;
|
||||
struct wl_list link;
|
||||
|
|
@ -178,6 +177,12 @@ struct view {
|
|||
char *title;
|
||||
char *app_id; /* WM_CLASS for xwayland windows */
|
||||
|
||||
struct {
|
||||
struct wlr_scene *scene;
|
||||
struct wlr_ext_image_capture_source_v1 *source;
|
||||
struct wl_listener on_capture_source_destroy;
|
||||
} capture;
|
||||
|
||||
bool mapped;
|
||||
bool been_mapped;
|
||||
uint64_t creation_id;
|
||||
|
|
@ -185,6 +190,7 @@ struct view {
|
|||
enum ssd_preference ssd_preference;
|
||||
bool shaded;
|
||||
bool minimized;
|
||||
bool was_minimized_by_show_desktop_action;
|
||||
enum view_axis maximized;
|
||||
bool fullscreen;
|
||||
bool tearing_hint;
|
||||
|
|
@ -280,6 +286,7 @@ struct view {
|
|||
struct wl_signal minimized;
|
||||
struct wl_signal fullscreened;
|
||||
struct wl_signal activated; /* bool *activated */
|
||||
struct wl_signal always_on_top;
|
||||
/*
|
||||
* This is emitted when app_id, or icon set via xdg_toplevel_icon
|
||||
* is updated. This is listened by scaled_icon_buffer.
|
||||
|
|
@ -318,6 +325,7 @@ struct xdg_toplevel_view {
|
|||
/* Events unique to xdg-toplevel views */
|
||||
struct wl_listener set_app_id;
|
||||
struct wl_listener request_show_window_menu;
|
||||
struct wl_listener set_parent;
|
||||
struct wl_listener new_popup;
|
||||
};
|
||||
|
||||
|
|
@ -357,7 +365,7 @@ bool view_matches_query(struct view *view, struct view_query *query);
|
|||
* @criteria: Criteria to match against.
|
||||
* Example:
|
||||
* struct view *view;
|
||||
* for_each_view(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
|
||||
* for_each_view(view, &server.views, LAB_VIEW_CRITERIA_NONE) {
|
||||
* printf("%s\n", view_get_string_prop(view, "app_id"));
|
||||
* }
|
||||
*/
|
||||
|
|
@ -373,7 +381,7 @@ bool view_matches_query(struct view *view, struct view_query *query);
|
|||
* @criteria: Criteria to match against.
|
||||
* Example:
|
||||
* struct view *view;
|
||||
* for_each_view_reverse(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
|
||||
* for_each_view_reverse(view, &server.views, LAB_VIEW_CRITERIA_NONE) {
|
||||
* printf("%s\n", view_get_string_prop(view, "app_id"));
|
||||
* }
|
||||
*/
|
||||
|
|
@ -423,13 +431,13 @@ struct view *view_prev(struct wl_list *head, struct view *view,
|
|||
* struct view **view;
|
||||
* struct wl_array views;
|
||||
* wl_array_init(&views);
|
||||
* view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE);
|
||||
* view_array_append(&views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE);
|
||||
* wl_array_for_each(view, &views) {
|
||||
* // Do something with *view
|
||||
* }
|
||||
* wl_array_release(&views);
|
||||
*/
|
||||
void view_array_append(struct server *server, struct wl_array *views,
|
||||
void view_array_append(struct wl_array *views,
|
||||
enum lab_view_criteria criteria);
|
||||
|
||||
enum view_wants_focus view_wants_focus(struct view *view);
|
||||
|
|
@ -486,7 +494,6 @@ void view_resize_relative(struct view *view,
|
|||
int left, int right, int top, int bottom);
|
||||
void view_move_relative(struct view *view, int x, int y);
|
||||
void view_move(struct view *view, int x, int y);
|
||||
void view_move_to_cursor(struct view *view);
|
||||
void view_moved(struct view *view);
|
||||
void view_minimize(struct view *view, bool minimized);
|
||||
bool view_compute_centered_position(struct view *view,
|
||||
|
|
@ -515,11 +522,30 @@ int view_effective_height(struct view *view, bool use_pending);
|
|||
*/
|
||||
void view_center(struct view *view, const struct wlr_box *ref);
|
||||
|
||||
/**
|
||||
* view_compute_position_by_policy() - compute view placement
|
||||
* @view: view to be placed
|
||||
* @geom: floating view geometry to update (in/out)
|
||||
* @allow_cursor: set to false to ignore center-on-cursor policy
|
||||
* @policy: placement policy to apply
|
||||
*
|
||||
* Computes floating view placement according to configured strategy.
|
||||
* Unlike view_place_by_policy(), this function doesn't actually move
|
||||
* the view. It returns false if position could not be computed (e.g.
|
||||
* if no outputs are connected). In that case, @geom is not modified.
|
||||
*/
|
||||
bool view_compute_position_by_policy(struct view *view, struct wlr_box *geom,
|
||||
bool allow_cursor, enum lab_placement_policy policy);
|
||||
|
||||
/**
|
||||
* view_place_by_policy - apply placement strategy to view
|
||||
* @view: view to be placed
|
||||
* @allow_cursor: set to false to ignore center-on-cursor policy
|
||||
* @policy: placement policy to apply
|
||||
*
|
||||
* Places a floating view according to configured placement strategy.
|
||||
* Clears any maximized/fullscreen/tiled state and restores natural
|
||||
* geometry of the view before positioning.
|
||||
*/
|
||||
void view_place_by_policy(struct view *view, bool allow_cursor,
|
||||
enum lab_placement_policy policy);
|
||||
|
|
@ -546,7 +572,15 @@ bool view_titlebar_visible(struct view *view);
|
|||
void view_set_ssd_mode(struct view *view, enum lab_ssd_mode mode);
|
||||
void view_set_decorations(struct view *view, enum lab_ssd_mode mode, bool force_ssd);
|
||||
void view_toggle_fullscreen(struct view *view);
|
||||
|
||||
/*
|
||||
* Saves the window position in view->last_placement. This should be called
|
||||
* when a view is first mapped or manually moved by the user.
|
||||
*/
|
||||
void view_save_last_placement(struct view *view);
|
||||
/* Restores and adjusts the view's position from the view->last_placement */
|
||||
void view_adjust_for_layout_change(struct view *view);
|
||||
|
||||
void view_move_to_edge(struct view *view, enum lab_edge direction, bool snap_to_windows);
|
||||
void view_grow_to_edge(struct view *view, enum lab_edge direction);
|
||||
void view_shrink_to_edge(struct view *view, enum lab_edge direction);
|
||||
|
|
@ -603,4 +637,6 @@ enum lab_placement_policy view_placement_parse(const char *policy);
|
|||
/* xdg.c */
|
||||
struct wlr_xdg_surface *xdg_surface_from_view(struct view *view);
|
||||
|
||||
bool view_matches_criteria(struct view *view, enum lab_view_criteria criteria);
|
||||
|
||||
#endif /* LABWC_VIEW_H */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ struct window_rule {
|
|||
enum property ignore_configure_request;
|
||||
enum property fixed_position;
|
||||
enum property icon_prefer_client;
|
||||
enum property allow_always_on_top;
|
||||
|
||||
struct wl_list link; /* struct rcxml.window_rules */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,34 +12,20 @@ struct wlr_scene_tree;
|
|||
|
||||
struct workspace {
|
||||
struct wl_list link; /* struct server.workspaces */
|
||||
struct server *server;
|
||||
|
||||
char *name;
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_scene_tree *view_trees[3];
|
||||
|
||||
struct lab_cosmic_workspace *cosmic_workspace;
|
||||
struct {
|
||||
struct wl_listener activate;
|
||||
struct wl_listener deactivate;
|
||||
struct wl_listener remove;
|
||||
} on_cosmic;
|
||||
|
||||
struct lab_ext_workspace *ext_workspace;
|
||||
struct {
|
||||
struct wl_listener activate;
|
||||
struct wl_listener deactivate;
|
||||
struct wl_listener assign;
|
||||
struct wl_listener remove;
|
||||
} on_ext;
|
||||
struct wlr_ext_workspace_handle_v1 *ext_workspace;
|
||||
};
|
||||
|
||||
void workspaces_init(struct server *server);
|
||||
void workspaces_init(void);
|
||||
void workspaces_switch_to(struct workspace *target, bool update_focus);
|
||||
void workspaces_destroy(struct server *server);
|
||||
void workspaces_destroy(void);
|
||||
void workspaces_osd_hide(struct seat *seat);
|
||||
struct workspace *workspaces_find(struct workspace *anchor, const char *name,
|
||||
bool wrap);
|
||||
void workspaces_reconfigure(struct server *server);
|
||||
void workspaces_reconfigure(void);
|
||||
|
||||
#endif /* LABWC_WORKSPACES_H */
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ struct wlr_output;
|
|||
struct wlr_output_layout;
|
||||
|
||||
struct xwayland_unmanaged {
|
||||
struct server *server;
|
||||
struct wlr_xwayland_surface *xwayland_surface;
|
||||
struct wlr_scene_node *node;
|
||||
struct wl_list link;
|
||||
|
|
@ -40,6 +39,7 @@ struct xwayland_view {
|
|||
struct view base;
|
||||
struct wlr_xwayland_surface *xwayland_surface;
|
||||
bool focused_before_map;
|
||||
bool initial_geometry_set;
|
||||
|
||||
/* Events unique to XWayland views */
|
||||
struct wl_listener associate;
|
||||
|
|
@ -53,33 +53,34 @@ struct xwayland_view {
|
|||
struct wl_listener set_override_redirect;
|
||||
struct wl_listener set_strut_partial;
|
||||
struct wl_listener set_window_type;
|
||||
struct wl_listener set_icon;
|
||||
struct wl_listener focus_in;
|
||||
struct wl_listener map_request;
|
||||
|
||||
/* Not (yet) implemented */
|
||||
/* struct wl_listener set_role; */
|
||||
/* struct wl_listener set_hints; */
|
||||
|
||||
/* Events coming in from the view itself */
|
||||
struct {
|
||||
struct wl_listener always_on_top;
|
||||
} on_view;
|
||||
|
||||
};
|
||||
|
||||
void xwayland_unmanaged_create(struct server *server,
|
||||
struct wlr_xwayland_surface *xsurface, bool mapped);
|
||||
void xwayland_unmanaged_create(struct wlr_xwayland_surface *xsurface, bool mapped);
|
||||
|
||||
void xwayland_view_create(struct server *server,
|
||||
struct wlr_xwayland_surface *xsurface, bool mapped);
|
||||
void xwayland_view_create(struct wlr_xwayland_surface *xsurface, bool mapped);
|
||||
|
||||
void xwayland_server_init(struct server *server,
|
||||
struct wlr_compositor *compositor);
|
||||
void xwayland_server_finish(struct server *server);
|
||||
void xwayland_server_init(struct wlr_compositor *compositor);
|
||||
void xwayland_server_finish(void);
|
||||
|
||||
void xwayland_adjust_usable_area(struct view *view,
|
||||
struct wlr_output_layout *layout, struct wlr_output *output,
|
||||
struct wlr_box *usable);
|
||||
|
||||
void xwayland_update_workarea(struct server *server);
|
||||
void xwayland_update_workarea(void);
|
||||
|
||||
void xwayland_reset_cursor(struct server *server);
|
||||
|
||||
void xwayland_flush(struct server *server);
|
||||
void xwayland_flush(void);
|
||||
|
||||
#endif /* HAVE_XWAYLAND */
|
||||
#endif /* LABWC_XWAYLAND_H */
|
||||
|
|
|
|||
21
meson.build
21
meson.build
|
|
@ -1,7 +1,7 @@
|
|||
project(
|
||||
'labwc',
|
||||
'c',
|
||||
version: '0.9.5',
|
||||
version: '0.20.1',
|
||||
license: 'GPL-2.0-only',
|
||||
meson_version: '>=0.59.0',
|
||||
default_options: [
|
||||
|
|
@ -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.1', '<0.21.0'],
|
||||
)
|
||||
|
||||
wlroots_has_xwayland = wlroots.get_variable('have_xwayland') == 'true'
|
||||
|
|
@ -65,13 +65,13 @@ xkbcommon = dependency('xkbcommon')
|
|||
xcb = dependency('xcb', required: get_option('xwayland'))
|
||||
xcb_ewmh = dependency('xcb-ewmh', required: get_option('xwayland'))
|
||||
xcb_icccm = dependency('xcb-icccm', required: get_option('xwayland'))
|
||||
drm_full = dependency('libdrm')
|
||||
drm_full = dependency('libdrm', required: wlroots.get_variable('have_drm_backend') == 'true')
|
||||
drm = drm_full.partial_dependency(compile_args: true, includes: true)
|
||||
xml2 = dependency('libxml-2.0')
|
||||
glib = dependency('glib-2.0')
|
||||
cairo = dependency('cairo')
|
||||
pangocairo = dependency('pangocairo')
|
||||
input = dependency('libinput', version: '>=1.14')
|
||||
input = dependency('libinput', version: '>=1.26', required: wlroots.get_variable('have_libinput_backend') == 'true')
|
||||
pixman = dependency('pixman-1')
|
||||
math = cc.find_library('m')
|
||||
png = dependency('libpng')
|
||||
|
|
@ -211,6 +211,17 @@ install_data('data/labwc.desktop', install_dir: get_option('datadir') / 'wayland
|
|||
|
||||
install_data('data/labwc-portals.conf', install_dir: get_option('datadir') / 'xdg-desktop-portal')
|
||||
|
||||
# Install labwc-session.target so that systemd user services with
|
||||
# WantedBy=graphical-session.target can be started and stopped in sync
|
||||
# with a labwc session (see labwc(1) SESSION MANAGEMENT for the opt-in
|
||||
# autostart/shutdown snippet).
|
||||
systemd_feat = get_option('systemd-session')
|
||||
systemd = dependency('systemd', required: systemd_feat)
|
||||
if systemd.found()
|
||||
install_data('data/labwc-session.target',
|
||||
install_dir: systemd.get_variable('systemduserunitdir'))
|
||||
endif
|
||||
|
||||
icons = ['labwc-symbolic.svg', 'labwc.svg']
|
||||
foreach icon : icons
|
||||
icon_path = join_paths('data', icon)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ option('man-pages', type: 'feature', value: 'auto', description: 'Generate and i
|
|||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
||||
option('svg', type: 'feature', value: 'enabled', description: 'Enable svg window buttons')
|
||||
option('icon', type: 'feature', value: 'enabled', description: 'Enable window icons')
|
||||
option('labnag', type: 'feature', value: 'auto', description: 'Build labnag notification daemon')
|
||||
option('nls', type: 'feature', value: 'auto', description: 'Enable native language support')
|
||||
option('systemd-session', type: 'feature', value: 'auto', description: 'Install labwc-session.target systemd user unit')
|
||||
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')
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
ar ca cs da de el es et eu fa fi fr gl he hr hu id it ja ka kk ko lt ms nl pa pl pt pt_BR ru sk sv tr uk vi zh_CN zh_TW
|
||||
ar ca cs da de el es et eu fa fi fr gl he hr hu id it ja ka kab kk ko lt ms nl pa pl pt pt_BR ru sk sr_Latn sv tr uk vi zh_CN zh_TW
|
||||
|
|
|
|||
10
po/de.po
10
po/de.po
|
|
@ -8,8 +8,8 @@ msgstr ""
|
|||
"Project-Id-Version: labwc\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
|
||||
"PO-Revision-Date: 2025-08-15 20:01+0000\n"
|
||||
"Last-Translator: Ettore Atalan <atalanttore@googlemail.com>\n"
|
||||
"PO-Revision-Date: 2026-05-18 18:28+0000\n"
|
||||
"Last-Translator: Demian <Demian@gmx.co.uk>\n"
|
||||
"Language-Team: German <https://translate.lxqt-project.org/projects/labwc/"
|
||||
"labwc/de/>\n"
|
||||
"Language: de\n"
|
||||
|
|
@ -21,7 +21,7 @@ msgstr ""
|
|||
|
||||
#: src/menu/menu.c:1016
|
||||
msgid "Go there..."
|
||||
msgstr "Dorthin gehen..."
|
||||
msgstr "Dorthin wechseln ..."
|
||||
|
||||
#: src/menu/menu.c:1034
|
||||
msgid "Terminal"
|
||||
|
|
@ -61,11 +61,11 @@ msgstr "Immer im Vordergrund"
|
|||
|
||||
#: src/menu/menu.c:1071
|
||||
msgid "Move Left"
|
||||
msgstr "nach links"
|
||||
msgstr "Nach links"
|
||||
|
||||
#: src/menu/menu.c:1078
|
||||
msgid "Move Right"
|
||||
msgstr "nach rechts"
|
||||
msgstr "Nach rechts"
|
||||
|
||||
#: src/menu/menu.c:1083
|
||||
msgid "Always on Visible Workspace"
|
||||
|
|
|
|||
80
po/kab.po
Normal file
80
po/kab.po
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# Labwc pot file
|
||||
# Copyright (C) 2024
|
||||
# This file is distributed under the same license as the labwc package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: labwc\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
|
||||
"PO-Revision-Date: 2026-03-31 08:01+0000\n"
|
||||
"Last-Translator: ButterflyOfFire <butterflyoffire@protonmail.com>\n"
|
||||
"Language-Team: Kabyle <https://translate.lxqt-project.org/projects/labwc/"
|
||||
"labwc/kab/>\n"
|
||||
"Language: kab\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.2.1\n"
|
||||
|
||||
#: src/menu/menu.c:1016
|
||||
msgid "Go there..."
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1034
|
||||
msgid "Terminal"
|
||||
msgstr "Ixf"
|
||||
|
||||
#: src/menu/menu.c:1040
|
||||
msgid "Reconfigure"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1042
|
||||
msgid "Exit"
|
||||
msgstr "Ffeɣ"
|
||||
|
||||
#: src/menu/menu.c:1056
|
||||
msgid "Minimize"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1058
|
||||
msgid "Maximize"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1060
|
||||
msgid "Fullscreen"
|
||||
msgstr "Agdil aččuran"
|
||||
|
||||
#: src/menu/menu.c:1062
|
||||
msgid "Roll Up/Down"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1064
|
||||
msgid "Decorations"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1066
|
||||
msgid "Always on Top"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1071
|
||||
msgid "Move Left"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1078
|
||||
msgid "Move Right"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1083
|
||||
msgid "Always on Visible Workspace"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1086
|
||||
msgid "Workspace"
|
||||
msgstr ""
|
||||
|
||||
#: src/menu/menu.c:1089
|
||||
msgid "Close"
|
||||
msgstr "Mdel"
|
||||
81
po/sr_Latn.po
Normal file
81
po/sr_Latn.po
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Labwc pot file
|
||||
# Copyright (C) 2024
|
||||
# This file is distributed under the same license as the labwc package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: labwc\n"
|
||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
|
||||
"PO-Revision-Date: 2026-05-05 08:28+0000\n"
|
||||
"Last-Translator: Tobias Si <dragoslav123@protonmail.com>\n"
|
||||
"Language-Team: Serbian (latin) <https://translate.lxqt-project.org/projects/"
|
||||
"labwc/labwc/sr_Latn/>\n"
|
||||
"Language: sr_Latn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 4.2.1\n"
|
||||
|
||||
#: src/menu/menu.c:1016
|
||||
msgid "Go there..."
|
||||
msgstr "Idi tamo..."
|
||||
|
||||
#: src/menu/menu.c:1034
|
||||
msgid "Terminal"
|
||||
msgstr "Terminal"
|
||||
|
||||
#: src/menu/menu.c:1040
|
||||
msgid "Reconfigure"
|
||||
msgstr "Podesi"
|
||||
|
||||
#: src/menu/menu.c:1042
|
||||
msgid "Exit"
|
||||
msgstr "Izlaz"
|
||||
|
||||
#: src/menu/menu.c:1056
|
||||
msgid "Minimize"
|
||||
msgstr "Minimiziraj"
|
||||
|
||||
#: src/menu/menu.c:1058
|
||||
msgid "Maximize"
|
||||
msgstr "Maksimiziraj"
|
||||
|
||||
#: src/menu/menu.c:1060
|
||||
msgid "Fullscreen"
|
||||
msgstr "Prikaz preko celog ekrana"
|
||||
|
||||
#: src/menu/menu.c:1062
|
||||
msgid "Roll Up/Down"
|
||||
msgstr "Prevuci Gore/Dole"
|
||||
|
||||
#: src/menu/menu.c:1064
|
||||
msgid "Decorations"
|
||||
msgstr "Dekoracije"
|
||||
|
||||
#: src/menu/menu.c:1066
|
||||
msgid "Always on Top"
|
||||
msgstr "Uvek na vrhu"
|
||||
|
||||
#: src/menu/menu.c:1071
|
||||
msgid "Move Left"
|
||||
msgstr "Pomeri levo"
|
||||
|
||||
#: src/menu/menu.c:1078
|
||||
msgid "Move Right"
|
||||
msgstr "Pomeri desno"
|
||||
|
||||
#: src/menu/menu.c:1083
|
||||
msgid "Always on Visible Workspace"
|
||||
msgstr "Uvek na vidljivom radnom prostoru"
|
||||
|
||||
#: src/menu/menu.c:1086
|
||||
msgid "Workspace"
|
||||
msgstr "Radni prostor"
|
||||
|
||||
#: src/menu/menu.c:1089
|
||||
msgid "Close"
|
||||
msgstr "Zatvori"
|
||||
|
|
@ -1,364 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="cosmic_workspace_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2019 Christopher Billington
|
||||
Copyright © 2020 Ilia Bozhinov
|
||||
Copyright © 2022 Victoria Brekenfeld
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zcosmic_workspace_manager_v1" version="1">
|
||||
<description summary="list and control workspaces">
|
||||
Workspaces, also called virtual desktops, are groups of surfaces. A
|
||||
compositor with a concept of workspaces may only show some such groups of
|
||||
surfaces (those of 'active' workspaces) at a time. 'Activating' a
|
||||
workspace is a request for the compositor to display that workspace's
|
||||
surfaces as normal, whereas the compositor may hide or otherwise
|
||||
de-emphasise surfaces that are associated only with 'inactive' workspaces.
|
||||
Workspaces are grouped by which sets of outputs they correspond to, and
|
||||
may contain surfaces only from those outputs. In this way, it is possible
|
||||
for each output to have its own set of workspaces, or for all outputs (or
|
||||
any other arbitrary grouping) to share workspaces. Compositors may
|
||||
optionally conceptually arrange each group of workspaces in an
|
||||
N-dimensional grid.
|
||||
|
||||
The purpose of this protocol is to enable the creation of taskbars and
|
||||
docks by providing them with a list of workspaces and their properties,
|
||||
and allowing them to activate and deactivate workspaces.
|
||||
|
||||
After a client binds the zcosmic_workspace_manager_v1, each workspace will be
|
||||
sent via the workspace event.
|
||||
</description>
|
||||
|
||||
<event name="workspace_group">
|
||||
<description summary="a workspace group has been created">
|
||||
This event is emitted whenever a new workspace group has been created.
|
||||
|
||||
All initial details of the workspace group (workspaces, outputs) will be
|
||||
sent immediately after this event via the corresponding events in
|
||||
zcosmic_workspace_group_handle_v1.
|
||||
</description>
|
||||
<arg name="workspace_group" type="new_id" interface="zcosmic_workspace_group_handle_v1"/>
|
||||
</event>
|
||||
|
||||
<request name="commit">
|
||||
<description summary="all requests about the workspaces have been sent">
|
||||
The client must send this request after it has finished sending other
|
||||
requests. The compositor must process a series of requests preceding a
|
||||
commit request atomically.
|
||||
|
||||
This allows changes to the workspace properties to be seen as atomic,
|
||||
even if they happen via multiple events, and even if they involve
|
||||
multiple zcosmic_workspace_handle_v1 objects, for example, deactivating one
|
||||
workspace and activating another.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="done">
|
||||
<description summary="all information about the workspace groups has been sent">
|
||||
This event is sent after all changes in all workspace groups have been
|
||||
sent.
|
||||
|
||||
This allows changes to one or more zcosmic_workspace_group_handle_v1
|
||||
properties and zcosmic_workspace_handle_v1 properties to be seen as atomic,
|
||||
even if they happen via multiple events.
|
||||
In particular, an output moving from one workspace group to
|
||||
another sends an output_enter event and an output_leave event to the two
|
||||
zcosmic_workspace_group_handle_v1 objects in question. The compositor sends
|
||||
the done event only after updating the output information in both
|
||||
workspace groups.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<event name="finished">
|
||||
<description summary="the compositor has finished with the workspace_manager">
|
||||
This event indicates that the compositor is done sending events to the
|
||||
zcosmic_workspace_manager_v1. The server will destroy the object
|
||||
immediately after sending this request, so it will become invalid and
|
||||
the client should free any resources associated with it.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="stop">
|
||||
<description summary="stop sending events">
|
||||
Indicates the client no longer wishes to receive events for new
|
||||
workspace groups. However the compositor may emit further workspace
|
||||
events, until the finished event is emitted.
|
||||
|
||||
The client must not send any more requests after this one.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zcosmic_workspace_group_handle_v1" version="1">
|
||||
<description summary="a workspace group assigned to a set of outputs">
|
||||
A zcosmic_workspace_group_handle_v1 object represents a a workspace group
|
||||
that is assigned a set of outputs and contains a number of workspaces.
|
||||
|
||||
The set of outputs assigned to the workspace group is conveyed to the client via
|
||||
output_enter and output_leave events, and its workspaces are conveyed with
|
||||
workspace events.
|
||||
|
||||
For example, a compositor which has a set of workspaces for each output may
|
||||
advertise a workspace group (and its workspaces) per output, whereas a compositor
|
||||
where a workspace spans all outputs may advertise a single workspace group for all
|
||||
outputs.
|
||||
</description>
|
||||
|
||||
<enum name="zcosmic_workspace_group_capabilities_v1">
|
||||
<entry name="create_workspace" value="1" summary="create_workspace request is available"/>
|
||||
</enum>
|
||||
|
||||
<event name="capabilities">
|
||||
<description summary="compositor capabilities">
|
||||
This event advertises the capabilities supported by the compositor. If
|
||||
a capability isn't supported, clients should hide or disable the UI
|
||||
elements that expose this functionality. For instance, if the
|
||||
compositor doesn't advertise support for creating workspaces, a button
|
||||
triggering the create_workspace request should not be displayed.
|
||||
|
||||
The compositor will ignore requests it doesn't support. For instance,
|
||||
a compositor which doesn't advertise support for creating workspaces will ignore
|
||||
create_workspace requests.
|
||||
|
||||
Compositors must send this event once after creation of an
|
||||
zcosmic_workspace_group_handle_v1 . When the capabilities change, compositors
|
||||
must send this event again.
|
||||
|
||||
The capabilities are sent as an array of 32-bit unsigned integers in
|
||||
native endianness.
|
||||
</description>
|
||||
<arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
|
||||
</event>
|
||||
|
||||
<event name="output_enter">
|
||||
<description summary="output assigned to workspace group">
|
||||
This event is emitted whenever an output is assigned to the workspace
|
||||
group.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<event name="output_leave">
|
||||
<description summary="output removed from workspace group">
|
||||
This event is emitted whenever an output is removed from the workspace
|
||||
group.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<event name="workspace">
|
||||
<description summary="workspace added to workspace group">
|
||||
This event is emitted whenever a new workspace has been created.
|
||||
A workspace can only be a member of a single workspace group and cannot
|
||||
be re-assigned.
|
||||
|
||||
All initial details of the workspace (name, coordinates, state) will
|
||||
be sent immediately after this event via the corresponding events in
|
||||
zcosmic_workspace_handle_v1.
|
||||
</description>
|
||||
<arg name="workspace" type="new_id" interface="zcosmic_workspace_handle_v1"/>
|
||||
</event>
|
||||
|
||||
<event name="remove">
|
||||
<description summary="this workspace group has been destroyed">
|
||||
This event means the zcosmic_workspace_group_handle_v1 has been destroyed.
|
||||
It is guaranteed there won't be any more events for this
|
||||
zcosmic_workspace_group_handle_v1. The zext_workspace_group_handle_v1 becomes
|
||||
inert so any requests will be ignored except the destroy request.
|
||||
|
||||
The compositor must remove all workspaces belonging to a workspace group
|
||||
before removing the workspace group.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="create_workspace">
|
||||
<description summary="create a new workspace">
|
||||
Request that the compositor create a new workspace with the given name.
|
||||
|
||||
There is no guarantee that the compositor will create a new workspace,
|
||||
or that the created workspace will have the provided name.
|
||||
</description>
|
||||
<arg name="workspace" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the zcosmic_workspace_group_handle_v1 object">
|
||||
Destroys the zcosmic_workspace_group_handle_v1 object.
|
||||
|
||||
This request should be called either when the client does not want to
|
||||
use the workspace object any more or after the remove event to finalize
|
||||
the destruction of the object.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zcosmic_workspace_handle_v1" version="1">
|
||||
<description summary="a workspace handing a group of surfaces">
|
||||
A zcosmic_workspace_handle_v1 object represents a a workspace that handles a
|
||||
group of surfaces.
|
||||
|
||||
Each workspace has a name, conveyed to the client with the name event; a
|
||||
list of states, conveyed to the client with the state event; and
|
||||
optionally a set of coordinates, conveyed to the client with the
|
||||
coordinates event. The client may request that the compositor activate or
|
||||
deactivate the workspace.
|
||||
|
||||
Each workspace can belong to only a single workspace group.
|
||||
Depepending on the compositor policy, there might be workspaces with
|
||||
the same name in different workspace groups, but these workspaces are still
|
||||
separate (e.g. one of them might be active while the other is not).
|
||||
</description>
|
||||
|
||||
<event name="name">
|
||||
<description summary="workspace name changed">
|
||||
This event is emitted immediately after the zcosmic_workspace_handle_v1 is
|
||||
created and whenever the name of the workspace changes.
|
||||
</description>
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="coordinates">
|
||||
<description summary="workspace coordinates changed">
|
||||
This event is used to organize workspaces into an N-dimensional grid
|
||||
within a workspace group, and if supported, is emitted immediately after
|
||||
the zcosmic_workspace_handle_v1 is created and whenever the coordinates of
|
||||
the workspace change. Compositors may not send this event if they do not
|
||||
conceptually arrange workspaces in this way. If compositors simply
|
||||
number workspaces, without any geometric interpretation, they may send
|
||||
1D coordinates, which clients should not interpret as implying any
|
||||
geometry. Sending an empty array means that the compositor no longer
|
||||
orders the workspace geometrically.
|
||||
|
||||
Coordinates have an arbitrary number of dimensions N with an uint32
|
||||
position along each dimension. By convention if N > 1, the first
|
||||
dimension is X, the second Y, the third Z, and so on. The compositor may
|
||||
chose to utilize these events for a more novel workspace layout
|
||||
convention, however. No guarantee is made about the grid being filled or
|
||||
bounded; there may be a workspace at coordinate 1 and another at
|
||||
coordinate 1000 and none in between. Within a workspace group, however,
|
||||
workspaces must have unique coordinates of equal dimensionality.
|
||||
</description>
|
||||
<arg name="coordinates" type="array"/>
|
||||
</event>
|
||||
|
||||
<event name="state">
|
||||
<description summary="the state of the workspace changed">
|
||||
This event is emitted immediately after the zcosmic_workspace_handle_v1 is
|
||||
created and each time the workspace state changes, either because of a
|
||||
compositor action or because of a request in this protocol.
|
||||
</description>
|
||||
<arg name="state" type="array"/>
|
||||
</event>
|
||||
|
||||
<enum name="state">
|
||||
<description summary="types of states on the workspace">
|
||||
The different states that a workspace can have.
|
||||
</description>
|
||||
|
||||
<entry name="active" value="0" summary="the workspace is active"/>
|
||||
<entry name="urgent" value="1" summary="the workspace requests attention"/>
|
||||
<entry name="hidden" value="2">
|
||||
<description summary="the workspace is not visible">
|
||||
The workspace is not visible in its workspace group, and clients
|
||||
attempting to visualize the compositor workspace state should not
|
||||
display such workspaces.
|
||||
</description>
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<enum name="zcosmic_workspace_capabilities_v1">
|
||||
<entry name="activate" value="1" summary="activate request is available"/>
|
||||
<entry name="deactivate" value="2" summary="deactivate request is available"/>
|
||||
<entry name="remove" value="3" summary="remove request is available"/>
|
||||
</enum>
|
||||
|
||||
<event name="capabilities">
|
||||
<description summary="compositor capabilities">
|
||||
This event advertises the capabilities supported by the compositor. If
|
||||
a capability isn't supported, clients should hide or disable the UI
|
||||
elements that expose this functionality. For instance, if the
|
||||
compositor doesn't advertise support for removing workspaces, a button
|
||||
triggering the remove request should not be displayed.
|
||||
|
||||
The compositor will ignore requests it doesn't support. For instance,
|
||||
a compositor which doesn't advertise support for remove will ignore
|
||||
remove requests.
|
||||
|
||||
Compositors must send this event once after creation of an
|
||||
zcosmic_workspace_handle_v1 . When the capabilities change, compositors
|
||||
must send this event again.
|
||||
|
||||
The capabilities are sent as an array of 32-bit unsigned integers in
|
||||
native endianness.
|
||||
</description>
|
||||
<arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
|
||||
</event>
|
||||
|
||||
<event name="remove">
|
||||
<description summary="this workspace has been destroyed">
|
||||
This event means the zcosmic_workspace_handle_v1 has been destroyed. It is
|
||||
guaranteed there won't be any more events for this
|
||||
zcosmic_workspace_handle_v1. The zext_workspace_handle_v1 becomes inert so
|
||||
any requests will be ignored except the destroy request.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the zcosmic_workspace_handle_v1 object">
|
||||
Destroys the zcosmic_workspace_handle_v1 object.
|
||||
|
||||
This request should be called either when the client does not want to
|
||||
use the workspace object any more or after the remove event to finalize
|
||||
the destruction of the object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="activate">
|
||||
<description summary="activate the workspace">
|
||||
Request that this workspace be activated.
|
||||
|
||||
There is no guarantee the workspace will be actually activated, and
|
||||
behaviour may be compositor-dependent. For example, activating a
|
||||
workspace may or may not deactivate all other workspaces in the same
|
||||
group.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="deactivate">
|
||||
<description summary="activate the workspace">
|
||||
Request that this workspace be deactivated.
|
||||
|
||||
There is no guarantee the workspace will be actually deactivated.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="remove">
|
||||
<description summary="remove the workspace">
|
||||
Request that this workspace be removed.
|
||||
|
||||
There is no guarantee the workspace will be actually removed.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
|
|
@ -14,18 +14,6 @@ wayland_scanner_server = generator(
|
|||
)
|
||||
|
||||
server_protocols = [
|
||||
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
|
||||
wl_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
|
||||
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
|
||||
wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
|
||||
'cosmic-workspace-unstable-v1.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
]
|
||||
|
|
|
|||
409
src/action.c
409
src/action.c
|
|
@ -21,12 +21,14 @@
|
|||
#include "cycle.h"
|
||||
#include "debug.h"
|
||||
#include "input/keyboard.h"
|
||||
#include "input/key-state.h"
|
||||
#include "labwc.h"
|
||||
#include "magnifier.h"
|
||||
#include "menu/menu.h"
|
||||
#include "output.h"
|
||||
#include "output-virtual.h"
|
||||
#include "regions.h"
|
||||
#include "show-desktop.h"
|
||||
#include "ssd.h"
|
||||
#include "theme.h"
|
||||
#include "translate.h"
|
||||
|
|
@ -68,145 +70,114 @@ struct action_arg_list {
|
|||
struct wl_list value;
|
||||
};
|
||||
|
||||
#define ACTION_TYPE_LIST(X) \
|
||||
X(NONE, "None") \
|
||||
X(CLOSE, "Close") \
|
||||
X(KILL, "Kill") \
|
||||
X(DEBUG, "Debug") \
|
||||
X(EXECUTE, "Execute") \
|
||||
X(EXIT, "Exit") \
|
||||
X(MOVE_TO_EDGE, "MoveToEdge") \
|
||||
X(TOGGLE_SNAP_TO_EDGE, "ToggleSnapToEdge") \
|
||||
X(SNAP_TO_EDGE, "SnapToEdge") \
|
||||
X(GROW_TO_EDGE, "GrowToEdge") \
|
||||
X(SHRINK_TO_EDGE, "ShrinkToEdge") \
|
||||
X(NEXT_WINDOW, "NextWindow") \
|
||||
X(PREVIOUS_WINDOW, "PreviousWindow") \
|
||||
X(NEXT_WINDOW_IMMEDIATE, "NextWindowImmediate") \
|
||||
X(PREVIOUS_WINDOW_IMMEDIATE, "PreviousWindowImmediate") \
|
||||
X(RECONFIGURE, "Reconfigure") \
|
||||
X(SHOW_MENU, "ShowMenu") \
|
||||
X(TOGGLE_MAXIMIZE, "ToggleMaximize") \
|
||||
X(MAXIMIZE, "Maximize") \
|
||||
X(UNMAXIMIZE, "UnMaximize") \
|
||||
X(TOGGLE_FULLSCREEN, "ToggleFullscreen") \
|
||||
X(SET_DECORATIONS, "SetDecorations") \
|
||||
X(TOGGLE_DECORATIONS, "ToggleDecorations") \
|
||||
X(TOGGLE_ALWAYS_ON_TOP, "ToggleAlwaysOnTop") \
|
||||
X(TOGGLE_ALWAYS_ON_BOTTOM, "ToggleAlwaysOnBottom") \
|
||||
X(TOGGLE_OMNIPRESENT, "ToggleOmnipresent") \
|
||||
X(FOCUS, "Focus") \
|
||||
X(UNFOCUS, "Unfocus") \
|
||||
X(ICONIFY, "Iconify") \
|
||||
X(RAISE, "Raise") \
|
||||
X(LOWER, "Lower") \
|
||||
X(MOVE, "Move") \
|
||||
X(RESIZE, "Resize") \
|
||||
X(RESIZE_RELATIVE, "ResizeRelative") \
|
||||
X(MOVETO, "MoveTo") \
|
||||
X(RESIZETO, "ResizeTo") \
|
||||
X(MOVETO_CURSOR, "MoveToCursor") \
|
||||
X(MOVE_RELATIVE, "MoveRelative") \
|
||||
X(SEND_TO_DESKTOP, "SendToDesktop") \
|
||||
X(GO_TO_DESKTOP, "GoToDesktop") \
|
||||
X(TOGGLE_SNAP_TO_REGION, "ToggleSnapToRegion") \
|
||||
X(SNAP_TO_REGION, "SnapToRegion") \
|
||||
X(UNSNAP, "UnSnap") \
|
||||
X(TOGGLE_KEYBINDS, "ToggleKeybinds") \
|
||||
X(FOCUS_OUTPUT, "FocusOutput") \
|
||||
X(MOVE_TO_OUTPUT, "MoveToOutput") \
|
||||
X(FIT_TO_OUTPUT, "FitToOutput") \
|
||||
X(IF, "If") \
|
||||
X(FOR_EACH, "ForEach") \
|
||||
X(VIRTUAL_OUTPUT_ADD, "VirtualOutputAdd") \
|
||||
X(VIRTUAL_OUTPUT_REMOVE, "VirtualOutputRemove") \
|
||||
X(AUTO_PLACE, "AutoPlace") \
|
||||
X(TOGGLE_TEARING, "ToggleTearing") \
|
||||
X(SHADE, "Shade") \
|
||||
X(UNSHADE, "Unshade") \
|
||||
X(TOGGLE_SHADE, "ToggleShade") \
|
||||
X(ENABLE_SCROLL_WHEEL_EMULATION, "EnableScrollWheelEmulation") \
|
||||
X(DISABLE_SCROLL_WHEEL_EMULATION, "DisableScrollWheelEmulation") \
|
||||
X(TOGGLE_SCROLL_WHEEL_EMULATION, "ToggleScrollWheelEmulation") \
|
||||
X(ENABLE_TABLET_MOUSE_EMULATION, "EnableTabletMouseEmulation") \
|
||||
X(DISABLE_TABLET_MOUSE_EMULATION, "DisableTabletMouseEmulation") \
|
||||
X(TOGGLE_TABLET_MOUSE_EMULATION, "ToggleTabletMouseEmulation") \
|
||||
X(TOGGLE_MAGNIFY, "ToggleMagnify") \
|
||||
X(ZOOM_IN, "ZoomIn") \
|
||||
X(ZOOM_OUT, "ZoomOut") \
|
||||
X(TOGGLE_SHOW_DESKTOP, "ToggleShowDesktop") \
|
||||
X(WARP_CURSOR, "WarpCursor") \
|
||||
X(HIDE_CURSOR, "HideCursor") \
|
||||
X(DEBUG_TOGGLE_KEY_STATE_INDICATOR, "DebugToggleKeyStateIndicator")
|
||||
|
||||
/*
|
||||
* Will expand to:
|
||||
*
|
||||
* enum action_type {
|
||||
* ACTION_TYPE_INVALID = 0,
|
||||
* ACTION_TYPE_NONE,
|
||||
* ACTION_TYPE_CLOSE,
|
||||
* ACTION_TYPE_KILL,
|
||||
* etc...
|
||||
*/
|
||||
enum action_type {
|
||||
ACTION_TYPE_INVALID = 0,
|
||||
ACTION_TYPE_NONE,
|
||||
ACTION_TYPE_CLOSE,
|
||||
ACTION_TYPE_KILL,
|
||||
ACTION_TYPE_DEBUG,
|
||||
ACTION_TYPE_EXECUTE,
|
||||
ACTION_TYPE_EXIT,
|
||||
ACTION_TYPE_MOVE_TO_EDGE,
|
||||
ACTION_TYPE_TOGGLE_SNAP_TO_EDGE,
|
||||
ACTION_TYPE_SNAP_TO_EDGE,
|
||||
ACTION_TYPE_GROW_TO_EDGE,
|
||||
ACTION_TYPE_SHRINK_TO_EDGE,
|
||||
ACTION_TYPE_NEXT_WINDOW,
|
||||
ACTION_TYPE_PREVIOUS_WINDOW,
|
||||
ACTION_TYPE_RECONFIGURE,
|
||||
ACTION_TYPE_SHOW_MENU,
|
||||
ACTION_TYPE_TOGGLE_MAXIMIZE,
|
||||
ACTION_TYPE_MAXIMIZE,
|
||||
ACTION_TYPE_UNMAXIMIZE,
|
||||
ACTION_TYPE_TOGGLE_FULLSCREEN,
|
||||
ACTION_TYPE_SET_DECORATIONS,
|
||||
ACTION_TYPE_TOGGLE_DECORATIONS,
|
||||
ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP,
|
||||
ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM,
|
||||
ACTION_TYPE_TOGGLE_OMNIPRESENT,
|
||||
ACTION_TYPE_FOCUS,
|
||||
ACTION_TYPE_UNFOCUS,
|
||||
ACTION_TYPE_ICONIFY,
|
||||
ACTION_TYPE_MOVE,
|
||||
ACTION_TYPE_RAISE,
|
||||
ACTION_TYPE_LOWER,
|
||||
ACTION_TYPE_RESIZE,
|
||||
ACTION_TYPE_RESIZE_RELATIVE,
|
||||
ACTION_TYPE_MOVETO,
|
||||
ACTION_TYPE_RESIZETO,
|
||||
ACTION_TYPE_MOVETO_CURSOR,
|
||||
ACTION_TYPE_MOVE_RELATIVE,
|
||||
ACTION_TYPE_SEND_TO_DESKTOP,
|
||||
ACTION_TYPE_GO_TO_DESKTOP,
|
||||
ACTION_TYPE_TOGGLE_SNAP_TO_REGION,
|
||||
ACTION_TYPE_SNAP_TO_REGION,
|
||||
ACTION_TYPE_UNSNAP,
|
||||
ACTION_TYPE_TOGGLE_KEYBINDS,
|
||||
ACTION_TYPE_FOCUS_OUTPUT,
|
||||
ACTION_TYPE_MOVE_TO_OUTPUT,
|
||||
ACTION_TYPE_FIT_TO_OUTPUT,
|
||||
ACTION_TYPE_IF,
|
||||
ACTION_TYPE_FOR_EACH,
|
||||
ACTION_TYPE_VIRTUAL_OUTPUT_ADD,
|
||||
ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE,
|
||||
ACTION_TYPE_AUTO_PLACE,
|
||||
ACTION_TYPE_TOGGLE_TEARING,
|
||||
ACTION_TYPE_SHADE,
|
||||
ACTION_TYPE_UNSHADE,
|
||||
ACTION_TYPE_TOGGLE_SHADE,
|
||||
ACTION_TYPE_ENABLE_SCROLL_WHEEL_EMULATION,
|
||||
ACTION_TYPE_DISABLE_SCROLL_WHEEL_EMULATION,
|
||||
ACTION_TYPE_TOGGLE_SCROLL_WHEEL_EMULATION,
|
||||
ACTION_TYPE_ENABLE_TABLET_MOUSE_EMULATION,
|
||||
ACTION_TYPE_DISABLE_TABLET_MOUSE_EMULATION,
|
||||
ACTION_TYPE_TOGGLE_TABLET_MOUSE_EMULATION,
|
||||
ACTION_TYPE_TOGGLE_MAGNIFY,
|
||||
ACTION_TYPE_ZOOM_IN,
|
||||
ACTION_TYPE_ZOOM_OUT,
|
||||
ACTION_TYPE_WARP_CURSOR,
|
||||
ACTION_TYPE_HIDE_CURSOR,
|
||||
#define X(name, str) ACTION_TYPE_##name,
|
||||
ACTION_TYPE_LIST(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
/*
|
||||
* Will expand to:
|
||||
*
|
||||
* const char *action_names[] = {
|
||||
* [ACTION_TYPE_INVALID] = "INVALID",
|
||||
* [ACTION_TYPE_NONE] = "None",
|
||||
* [ACTION_TYPE_CLOSE] = "Close",
|
||||
* [ACTION_TYPE_KILL] = "Kill",
|
||||
* etc...
|
||||
*/
|
||||
const char *action_names[] = {
|
||||
"INVALID",
|
||||
"None",
|
||||
"Close",
|
||||
"Kill",
|
||||
"Debug",
|
||||
"Execute",
|
||||
"Exit",
|
||||
"MoveToEdge",
|
||||
"ToggleSnapToEdge",
|
||||
"SnapToEdge",
|
||||
"GrowToEdge",
|
||||
"ShrinkToEdge",
|
||||
"NextWindow",
|
||||
"PreviousWindow",
|
||||
"Reconfigure",
|
||||
"ShowMenu",
|
||||
"ToggleMaximize",
|
||||
"Maximize",
|
||||
"UnMaximize",
|
||||
"ToggleFullscreen",
|
||||
"SetDecorations",
|
||||
"ToggleDecorations",
|
||||
"ToggleAlwaysOnTop",
|
||||
"ToggleAlwaysOnBottom",
|
||||
"ToggleOmnipresent",
|
||||
"Focus",
|
||||
"Unfocus",
|
||||
"Iconify",
|
||||
"Move",
|
||||
"Raise",
|
||||
"Lower",
|
||||
"Resize",
|
||||
"ResizeRelative",
|
||||
"MoveTo",
|
||||
"ResizeTo",
|
||||
"MoveToCursor",
|
||||
"MoveRelative",
|
||||
"SendToDesktop",
|
||||
"GoToDesktop",
|
||||
"ToggleSnapToRegion",
|
||||
"SnapToRegion",
|
||||
"UnSnap",
|
||||
"ToggleKeybinds",
|
||||
"FocusOutput",
|
||||
"MoveToOutput",
|
||||
"FitToOutput",
|
||||
"If",
|
||||
"ForEach",
|
||||
"VirtualOutputAdd",
|
||||
"VirtualOutputRemove",
|
||||
"AutoPlace",
|
||||
"ToggleTearing",
|
||||
"Shade",
|
||||
"Unshade",
|
||||
"ToggleShade",
|
||||
"EnableScrollWheelEmulation",
|
||||
"DisableScrollWheelEmulation",
|
||||
"ToggleScrollWheelEmulation",
|
||||
"EnableTabletMouseEmulation",
|
||||
"DisableTabletMouseEmulation",
|
||||
"ToggleTabletMouseEmulation",
|
||||
"ToggleMagnify",
|
||||
"ZoomIn",
|
||||
"ZoomOut",
|
||||
"WarpCursor",
|
||||
"HideCursor",
|
||||
[ACTION_TYPE_INVALID] = "INVALID",
|
||||
#define X(name, str)[ACTION_TYPE_##name] = str,
|
||||
ACTION_TYPE_LIST(X)
|
||||
#undef X
|
||||
NULL
|
||||
};
|
||||
|
||||
#undef ACTION_TYPE_LIST
|
||||
|
||||
void
|
||||
action_arg_add_str(struct action *action, const char *key, const char *value)
|
||||
{
|
||||
|
|
@ -368,6 +339,8 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
|||
break;
|
||||
case ACTION_TYPE_NEXT_WINDOW:
|
||||
case ACTION_TYPE_PREVIOUS_WINDOW:
|
||||
case ACTION_TYPE_NEXT_WINDOW_IMMEDIATE:
|
||||
case ACTION_TYPE_PREVIOUS_WINDOW_IMMEDIATE:
|
||||
if (!strcasecmp(argument, "workspace")) {
|
||||
if (!strcasecmp(content, "all")) {
|
||||
action_arg_add_int(action, argument, CYCLE_WORKSPACE_ALL);
|
||||
|
|
@ -739,23 +712,23 @@ action_list_free(struct wl_list *action_list)
|
|||
}
|
||||
|
||||
static void
|
||||
show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
|
||||
show_menu(struct view *view, struct cursor_context *ctx,
|
||||
const char *menu_name, bool at_cursor,
|
||||
const char *pos_x, const char *pos_y)
|
||||
{
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH
|
||||
&& server->input_mode != LAB_INPUT_STATE_MENU) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH
|
||||
&& server.input_mode != LAB_INPUT_STATE_MENU) {
|
||||
/* Prevent opening a menu while resizing / moving a view */
|
||||
return;
|
||||
}
|
||||
|
||||
struct menu *menu = menu_get_by_id(server, menu_name);
|
||||
struct menu *menu = menu_get_by_id(menu_name);
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x = server->seat.cursor->x;
|
||||
int y = server->seat.cursor->y;
|
||||
int x = server.seat.cursor->x;
|
||||
int y = server.seat.cursor->y;
|
||||
|
||||
/* The client menu needs an active client */
|
||||
bool is_client_menu = !strcasecmp(menu_name, "client-menu");
|
||||
|
|
@ -774,7 +747,7 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
|
|||
int lx, ly;
|
||||
wlr_scene_node_coords(ctx->node, &lx, &ly);
|
||||
/* MAX() prevents negative x when the window is maximized */
|
||||
x = MAX(x, lx - server->theme->menu_border_width);
|
||||
x = MAX(x, lx - rc.theme->menu_border_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -783,8 +756,8 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
|
|||
* x/y can be number, "center" or a %percent of screen dimensions
|
||||
*/
|
||||
if (pos_x && pos_y) {
|
||||
struct output *output = output_nearest_to(server,
|
||||
server->seat.cursor->x, server->seat.cursor->y);
|
||||
struct output *output = output_nearest_to(
|
||||
server.seat.cursor->x, server.seat.cursor->y);
|
||||
struct wlr_box usable = output_usable_area_in_layout_coords(output);
|
||||
|
||||
if (!strcasecmp(pos_x, "center")) {
|
||||
|
|
@ -828,8 +801,7 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
|
|||
}
|
||||
|
||||
static struct view *
|
||||
view_for_action(struct view *activator, struct server *server,
|
||||
struct action *action, struct cursor_context *ctx)
|
||||
view_for_action(struct view *activator, struct action *action, struct cursor_context *ctx)
|
||||
{
|
||||
/* View is explicitly specified for mousebinds */
|
||||
if (activator) {
|
||||
|
|
@ -841,17 +813,16 @@ view_for_action(struct view *activator, struct server *server,
|
|||
case ACTION_TYPE_FOCUS:
|
||||
case ACTION_TYPE_MOVE:
|
||||
case ACTION_TYPE_RESIZE: {
|
||||
*ctx = get_cursor_context(server);
|
||||
*ctx = get_cursor_context();
|
||||
return ctx->view;
|
||||
}
|
||||
default:
|
||||
return server->active_view;
|
||||
return server.active_view;
|
||||
}
|
||||
}
|
||||
|
||||
struct action_prompt {
|
||||
/* Set when created */
|
||||
struct server *server;
|
||||
struct action *action;
|
||||
struct view *view;
|
||||
|
||||
|
|
@ -928,7 +899,7 @@ print_prompt_command(struct buf *buf, const char *format,
|
|||
}
|
||||
|
||||
static void
|
||||
action_prompt_create(struct view *view, struct server *server, struct action *action)
|
||||
action_prompt_create(struct view *view, struct action *action)
|
||||
{
|
||||
struct buf command = BUF_INIT;
|
||||
print_prompt_command(&command, rc.prompt_command, action, rc.theme);
|
||||
|
|
@ -945,7 +916,6 @@ action_prompt_create(struct view *view, struct server *server, struct action *ac
|
|||
close(pipe_fd);
|
||||
|
||||
struct action_prompt *prompt = znew(*prompt);
|
||||
prompt->server = server;
|
||||
prompt->action = action;
|
||||
prompt->view = view;
|
||||
prompt->pid = prompt_pid;
|
||||
|
|
@ -994,8 +964,7 @@ action_check_prompt_result(pid_t pid, int exit_code)
|
|||
}
|
||||
if (actions) {
|
||||
wlr_log(WLR_INFO, "Running actions");
|
||||
actions_run(prompt->view, prompt->server,
|
||||
actions, /*cursor_ctx*/ NULL);
|
||||
actions_run(prompt->view, actions, /*cursor_ctx*/ NULL);
|
||||
} else {
|
||||
wlr_log(WLR_INFO, "No actions for selected branch");
|
||||
}
|
||||
|
|
@ -1026,14 +995,13 @@ match_queries(struct view *view, struct action *action)
|
|||
}
|
||||
|
||||
static struct output *
|
||||
get_target_output(struct output *output, struct server *server,
|
||||
struct action *action)
|
||||
get_target_output(struct output *output, struct action *action)
|
||||
{
|
||||
const char *output_name = action_get_str(action, "output", NULL);
|
||||
struct output *target = NULL;
|
||||
|
||||
if (output_name) {
|
||||
target = output_from_name(server, output_name);
|
||||
target = output_from_name(output_name);
|
||||
} else {
|
||||
enum lab_edge edge =
|
||||
action_get_int(action, "direction", LAB_EDGE_NONE);
|
||||
|
|
@ -1049,9 +1017,9 @@ get_target_output(struct output *output, struct server *server,
|
|||
}
|
||||
|
||||
static void
|
||||
warp_cursor(struct server *server, struct view *view, const char *to, const char *x, const char *y)
|
||||
warp_cursor(struct view *view, const char *to, const char *x, const char *y)
|
||||
{
|
||||
struct output *output = output_nearest_to_cursor(server);
|
||||
struct output *output = output_nearest_to_cursor();
|
||||
struct wlr_box target_area = {0};
|
||||
int goto_x;
|
||||
int goto_y;
|
||||
|
|
@ -1082,12 +1050,12 @@ warp_cursor(struct server *server, struct view *view, const char *to, const char
|
|||
target_area.y + target_area.height + offset_y;
|
||||
}
|
||||
|
||||
wlr_cursor_warp(server->seat.cursor, NULL, goto_x, goto_y);
|
||||
cursor_update_focus(server);
|
||||
wlr_cursor_warp(server.seat.cursor, NULL, goto_x, goto_y);
|
||||
cursor_update_focus();
|
||||
}
|
||||
|
||||
static void
|
||||
run_action(struct view *view, struct server *server, struct action *action,
|
||||
run_action(struct view *view, struct action *action,
|
||||
struct cursor_context *ctx)
|
||||
{
|
||||
switch (action->type) {
|
||||
|
|
@ -1109,7 +1077,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_DEBUG:
|
||||
debug_dump_scene(server);
|
||||
debug_dump_scene();
|
||||
break;
|
||||
case ACTION_TYPE_EXECUTE: {
|
||||
struct buf cmd = BUF_INIT;
|
||||
|
|
@ -1120,7 +1088,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
break;
|
||||
}
|
||||
case ACTION_TYPE_EXIT:
|
||||
wl_display_terminate(server->wl_display);
|
||||
wl_display_terminate(server.wl_display);
|
||||
break;
|
||||
case ACTION_TYPE_MOVE_TO_EDGE:
|
||||
if (view) {
|
||||
|
|
@ -1175,18 +1143,33 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
.app_id = action_get_int(action, "identifier",
|
||||
CYCLE_APP_ID_ALL),
|
||||
};
|
||||
if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
cycle_step(server, dir);
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
cycle_step(dir);
|
||||
} else {
|
||||
cycle_begin(server, dir, filter);
|
||||
cycle_begin(dir, filter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_NEXT_WINDOW_IMMEDIATE:
|
||||
case ACTION_TYPE_PREVIOUS_WINDOW_IMMEDIATE: {
|
||||
enum lab_cycle_dir dir = (action->type == ACTION_TYPE_NEXT_WINDOW_IMMEDIATE) ?
|
||||
LAB_CYCLE_DIR_FORWARD : LAB_CYCLE_DIR_BACKWARD;
|
||||
struct cycle_filter filter = {
|
||||
.workspace = action_get_int(action, "workspace",
|
||||
rc.window_switcher.workspace_filter),
|
||||
.output = action_get_int(action, "output",
|
||||
CYCLE_OUTPUT_ALL),
|
||||
.app_id = action_get_int(action, "identifier",
|
||||
CYCLE_APP_ID_ALL),
|
||||
};
|
||||
cycle_immediate(dir, filter);
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_RECONFIGURE:
|
||||
kill(getpid(), SIGHUP);
|
||||
break;
|
||||
case ACTION_TYPE_SHOW_MENU:
|
||||
show_menu(server, view, ctx,
|
||||
show_menu(view, ctx,
|
||||
action_get_str(action, "menu", NULL),
|
||||
action_get_bool(action, "atCursor", true),
|
||||
action_get_str(action, "x.position", NULL),
|
||||
|
|
@ -1253,27 +1236,13 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_UNFOCUS:
|
||||
seat_focus_surface(&server->seat, NULL);
|
||||
seat_focus_surface(&server.seat, NULL);
|
||||
break;
|
||||
case ACTION_TYPE_ICONIFY:
|
||||
if (view) {
|
||||
view_minimize(view, true);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_MOVE:
|
||||
if (view) {
|
||||
/*
|
||||
* If triggered by mousebind, grab context was already
|
||||
* set by button press handling. For keybind-triggered
|
||||
* Move, set it now from current cursor position.
|
||||
*/
|
||||
if (view != server->seat.pressed.ctx.view) {
|
||||
interactive_set_grab_context(ctx);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE,
|
||||
LAB_EDGE_NONE);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_RAISE:
|
||||
if (view) {
|
||||
view_move_to_front(view);
|
||||
|
|
@ -1284,6 +1253,20 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
view_move_to_back(view);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_MOVE:
|
||||
if (view) {
|
||||
/*
|
||||
* If triggered by mousebind, grab context was already
|
||||
* set by button press handling. For keybind-triggered
|
||||
* Move, set it now from current cursor position.
|
||||
*/
|
||||
if (view != server.seat.pressed.ctx.view) {
|
||||
interactive_set_grab_context(ctx);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_MOVE,
|
||||
LAB_EDGE_NONE);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_RESIZE:
|
||||
if (view) {
|
||||
/*
|
||||
|
|
@ -1298,7 +1281,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
* set by button press handling. For keybind-triggered
|
||||
* Resize, set it now from current cursor position.
|
||||
*/
|
||||
if (view != server->seat.pressed.ctx.view) {
|
||||
if (view != server.seat.pressed.ctx.view) {
|
||||
interactive_set_grab_context(ctx);
|
||||
}
|
||||
interactive_begin(view, LAB_INPUT_STATE_RESIZE,
|
||||
|
|
@ -1329,7 +1312,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
|
||||
/*
|
||||
* To support only setting one of width/height
|
||||
* in <action name="ResizeTo" width="" height=""/>
|
||||
* in <action name="ResizeTo" width="" height="" />
|
||||
* we fall back to current dimension when unset.
|
||||
*/
|
||||
struct wlr_box box = {
|
||||
|
|
@ -1354,7 +1337,8 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
"Action MoveToCursor is deprecated. To ensure your config works in future labwc "
|
||||
"releases, please use <action name=\"AutoPlace\" policy=\"cursor\">");
|
||||
if (view) {
|
||||
view_move_to_cursor(view);
|
||||
view_place_by_policy(view, /* allow_cursor */ true,
|
||||
LAB_PLACE_CURSOR);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SEND_TO_DESKTOP:
|
||||
|
|
@ -1372,12 +1356,12 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
* a required argument for both SendToDesktop and GoToDesktop.
|
||||
*/
|
||||
struct workspace *target_workspace = workspaces_find(
|
||||
server->workspaces.current, to, wrap);
|
||||
server.workspaces.current, to, wrap);
|
||||
if (action->type == ACTION_TYPE_GO_TO_DESKTOP) {
|
||||
bool toggle = action_get_bool(action, "toggle", false);
|
||||
if (target_workspace == server->workspaces.current
|
||||
if (target_workspace == server.workspaces.current
|
||||
&& toggle) {
|
||||
target_workspace = server->workspaces.last;
|
||||
target_workspace = server.workspaces.last;
|
||||
}
|
||||
}
|
||||
if (!target_workspace) {
|
||||
|
|
@ -1388,8 +1372,8 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
follow = action_get_bool(action, "follow", true);
|
||||
|
||||
/* Ensure that the focus is not on another desktop */
|
||||
if (!follow && server->active_view == view) {
|
||||
desktop_focus_topmost_view(server);
|
||||
if (!follow && server.active_view == view) {
|
||||
desktop_focus_topmost_view();
|
||||
}
|
||||
}
|
||||
if (follow) {
|
||||
|
|
@ -1403,7 +1387,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
break;
|
||||
}
|
||||
struct output *target_output =
|
||||
get_target_output(view->output, server, action);
|
||||
get_target_output(view->output, action);
|
||||
if (target_output) {
|
||||
view_move_to_output(view, target_output);
|
||||
}
|
||||
|
|
@ -1455,9 +1439,9 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_FOCUS_OUTPUT: {
|
||||
struct output *output = output_nearest_to_cursor(server);
|
||||
struct output *output = output_nearest_to_cursor();
|
||||
struct output *target_output =
|
||||
get_target_output(output, server, action);
|
||||
get_target_output(output, action);
|
||||
if (target_output) {
|
||||
desktop_focus_output(target_output);
|
||||
}
|
||||
|
|
@ -1470,7 +1454,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
* We delay the selection and execution of the
|
||||
* branch until we get a response from the user.
|
||||
*/
|
||||
action_prompt_create(view, server, action);
|
||||
action_prompt_create(view, action);
|
||||
} else if (view) {
|
||||
struct wl_list *actions;
|
||||
if (match_queries(view, action)) {
|
||||
|
|
@ -1479,7 +1463,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
actions = action_get_actionlist(action, "else");
|
||||
}
|
||||
if (actions) {
|
||||
actions_run(view, server, actions, ctx);
|
||||
actions_run(view, actions, ctx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1490,7 +1474,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
|
||||
struct wl_array views;
|
||||
wl_array_init(&views);
|
||||
view_array_append(server, &views, LAB_VIEW_CRITERIA_NONE);
|
||||
view_array_append(&views, LAB_VIEW_CRITERIA_NONE);
|
||||
|
||||
struct view **item;
|
||||
wl_array_for_each(item, &views) {
|
||||
|
|
@ -1501,14 +1485,14 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
actions = action_get_actionlist(action, "else");
|
||||
}
|
||||
if (actions) {
|
||||
actions_run(*item, server, actions, ctx);
|
||||
actions_run(*item, actions, ctx);
|
||||
}
|
||||
}
|
||||
wl_array_release(&views);
|
||||
if (!matches) {
|
||||
actions = action_get_actionlist(action, "none");
|
||||
if (actions) {
|
||||
actions_run(view, server, actions, NULL);
|
||||
actions_run(view, actions, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1517,7 +1501,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
/* TODO: rename this argument to "outputName" */
|
||||
const char *output_name =
|
||||
action_get_str(action, "output_name", NULL);
|
||||
output_virtual_add(server, output_name,
|
||||
output_virtual_add(output_name,
|
||||
/*store_wlr_output*/ NULL);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1525,7 +1509,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
/* TODO: rename this argument to "outputName" */
|
||||
const char *output_name =
|
||||
action_get_str(action, "output_name", NULL);
|
||||
output_virtual_remove(server, output_name);
|
||||
output_virtual_remove(output_name);
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_AUTO_PLACE:
|
||||
|
|
@ -1572,14 +1556,14 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_ENABLE_SCROLL_WHEEL_EMULATION:
|
||||
server->seat.cursor_scroll_wheel_emulation = true;
|
||||
server.seat.cursor_scroll_wheel_emulation = true;
|
||||
break;
|
||||
case ACTION_TYPE_DISABLE_SCROLL_WHEEL_EMULATION:
|
||||
server->seat.cursor_scroll_wheel_emulation = false;
|
||||
server.seat.cursor_scroll_wheel_emulation = false;
|
||||
break;
|
||||
case ACTION_TYPE_TOGGLE_SCROLL_WHEEL_EMULATION:
|
||||
server->seat.cursor_scroll_wheel_emulation =
|
||||
!server->seat.cursor_scroll_wheel_emulation;
|
||||
server.seat.cursor_scroll_wheel_emulation =
|
||||
!server.seat.cursor_scroll_wheel_emulation;
|
||||
break;
|
||||
case ACTION_TYPE_ENABLE_TABLET_MOUSE_EMULATION:
|
||||
rc.tablet.force_mouse_emulation = true;
|
||||
|
|
@ -1591,23 +1575,29 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
rc.tablet.force_mouse_emulation = !rc.tablet.force_mouse_emulation;
|
||||
break;
|
||||
case ACTION_TYPE_TOGGLE_MAGNIFY:
|
||||
magnifier_toggle(server);
|
||||
magnifier_toggle();
|
||||
break;
|
||||
case ACTION_TYPE_ZOOM_IN:
|
||||
magnifier_set_scale(server, MAGNIFY_INCREASE);
|
||||
magnifier_set_scale(MAGNIFY_INCREASE);
|
||||
break;
|
||||
case ACTION_TYPE_ZOOM_OUT:
|
||||
magnifier_set_scale(server, MAGNIFY_DECREASE);
|
||||
magnifier_set_scale(MAGNIFY_DECREASE);
|
||||
break;
|
||||
case ACTION_TYPE_TOGGLE_SHOW_DESKTOP:
|
||||
show_desktop_toggle();
|
||||
break;
|
||||
case ACTION_TYPE_WARP_CURSOR: {
|
||||
const char *to = action_get_str(action, "to", "output");
|
||||
const char *x = action_get_str(action, "x", "center");
|
||||
const char *y = action_get_str(action, "y", "center");
|
||||
warp_cursor(server, view, to, x, y);
|
||||
warp_cursor(view, to, x, y);
|
||||
break;
|
||||
}
|
||||
case ACTION_TYPE_HIDE_CURSOR:
|
||||
cursor_set_visible(&server->seat, false);
|
||||
cursor_set_visible(&server.seat, false);
|
||||
break;
|
||||
case ACTION_TYPE_DEBUG_TOGGLE_KEY_STATE_INDICATOR:
|
||||
key_state_indicator_toggle();
|
||||
break;
|
||||
case ACTION_TYPE_INVALID:
|
||||
wlr_log(WLR_ERROR, "Not executing unknown action");
|
||||
|
|
@ -1625,8 +1615,7 @@ run_action(struct view *view, struct server *server, struct action *action,
|
|||
}
|
||||
|
||||
void
|
||||
actions_run(struct view *activator, struct server *server,
|
||||
struct wl_list *actions, struct cursor_context *cursor_ctx)
|
||||
actions_run(struct view *activator, struct wl_list *actions, struct cursor_context *cursor_ctx)
|
||||
{
|
||||
if (!actions) {
|
||||
wlr_log(WLR_ERROR, "empty actions");
|
||||
|
|
@ -1643,7 +1632,7 @@ actions_run(struct view *activator, struct server *server,
|
|||
|
||||
struct action *action;
|
||||
wl_list_for_each(action, actions, link) {
|
||||
if (server->input_mode == LAB_INPUT_STATE_CYCLE
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE
|
||||
&& action->type != ACTION_TYPE_NEXT_WINDOW
|
||||
&& action->type != ACTION_TYPE_PREVIOUS_WINDOW) {
|
||||
wlr_log(WLR_INFO, "Only NextWindow or PreviousWindow "
|
||||
|
|
@ -1658,8 +1647,8 @@ actions_run(struct view *activator, struct server *server,
|
|||
* Refetch view because it may have been changed due to the
|
||||
* previous action
|
||||
*/
|
||||
struct view *view = view_for_action(activator, server, action, &ctx);
|
||||
struct view *view = view_for_action(activator, action, &ctx);
|
||||
|
||||
run_action(view, server, action, &ctx);
|
||||
run_action(view, action, &ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/buffer.c
12
src/buffer.c
|
|
@ -95,6 +95,7 @@ buffer_adopt_cairo_surface(cairo_surface_t *surface)
|
|||
|
||||
buffer->surface = surface;
|
||||
buffer->data = cairo_image_surface_get_data(buffer->surface);
|
||||
assert(buffer->data);
|
||||
buffer->format = DRM_FORMAT_ARGB8888;
|
||||
buffer->stride = cairo_image_surface_get_stride(buffer->surface);
|
||||
buffer->logical_width = width;
|
||||
|
|
@ -107,6 +108,12 @@ buffer_adopt_cairo_surface(cairo_surface_t *surface)
|
|||
struct lab_data_buffer *
|
||||
buffer_create_cairo(uint32_t logical_width, uint32_t logical_height, float scale)
|
||||
{
|
||||
if (!logical_width || !logical_height) {
|
||||
wlr_log(WLR_ERROR, "Failed to create cairo buffer of %ux%u: dimensions must be > 0",
|
||||
logical_width, logical_height);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create an image surface with the scaled size */
|
||||
cairo_surface_t *surface =
|
||||
cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
|
||||
|
|
@ -142,6 +149,7 @@ buffer_create_from_data(void *pixel_data, uint32_t width, uint32_t height,
|
|||
buffer->logical_width = width;
|
||||
buffer->logical_height = height;
|
||||
buffer->data = pixel_data;
|
||||
assert(buffer->data);
|
||||
buffer->format = DRM_FORMAT_ARGB8888;
|
||||
buffer->stride = stride;
|
||||
buffer->surface = cairo_image_surface_create_for_data(
|
||||
|
|
@ -188,6 +196,10 @@ buffer_resize(struct lab_data_buffer *src_buffer, int width, int height,
|
|||
|
||||
struct lab_data_buffer *buffer =
|
||||
buffer_create_cairo(width, height, scale);
|
||||
if (!buffer) {
|
||||
wlr_log(WLR_INFO, "Failed to resize buffer to %dx%d", width, height);
|
||||
return NULL;
|
||||
}
|
||||
cairo_t *cairo = cairo_create(buffer->surface);
|
||||
|
||||
struct wlr_box container = {
|
||||
|
|
|
|||
|
|
@ -53,15 +53,14 @@ buf_expand_shell_variables(struct buf *s)
|
|||
if (s->data[i] == '$' && isvalid(s->data[i+1])) {
|
||||
/* expand environment variable */
|
||||
buf_clear(&environment_variable);
|
||||
buf_add(&environment_variable, s->data + i + 1);
|
||||
char *p = environment_variable.data;
|
||||
while (isvalid(*p)) {
|
||||
++p;
|
||||
int len = 0;
|
||||
while (isvalid(s->data[i + 1 + len])) {
|
||||
buf_add_char(&environment_variable, s->data[i + 1 + len]);
|
||||
++len;
|
||||
}
|
||||
*p = '\0';
|
||||
i += strlen(environment_variable.data);
|
||||
i += len;
|
||||
strip_curly_braces(environment_variable.data);
|
||||
p = getenv(environment_variable.data);
|
||||
char *p = getenv(environment_variable.data);
|
||||
if (p) {
|
||||
buf_add(&tmp, p);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,9 +79,10 @@ font_get_buffer_size(int max_width, const char *text, struct font *font,
|
|||
void
|
||||
font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
||||
int height, const char *text, struct font *font, const float *color,
|
||||
cairo_pattern_t *bg_pattern, double scale)
|
||||
cairo_pattern_t *bg_pattern, double scale, bool use_markup)
|
||||
{
|
||||
if (string_null_or_empty(text)) {
|
||||
*buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +92,13 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
|||
height = computed_height;
|
||||
}
|
||||
|
||||
if (height <= 0 || width <= 0) {
|
||||
wlr_log(WLR_INFO, "Refusing to create invisible font buffer of %dx%d",
|
||||
width, height);
|
||||
*buffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*buffer = buffer_create_cairo(width, height, scale);
|
||||
if (!*buffer) {
|
||||
wlr_log(WLR_ERROR, "Failed to create font buffer");
|
||||
|
|
@ -123,7 +131,13 @@ font_buffer_create(struct lab_data_buffer **buffer, int max_width,
|
|||
PangoLayout *layout = pango_cairo_create_layout(cairo);
|
||||
pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
|
||||
pango_layout_set_width(layout, width * PANGO_SCALE);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
|
||||
if (use_markup) {
|
||||
pango_layout_set_markup(layout, text, -1);
|
||||
} else {
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
}
|
||||
|
||||
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
|
||||
|
||||
if (!opaque_bg) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <assert.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
|
||||
struct border_scene {
|
||||
struct wlr_scene_tree *tree;
|
||||
|
|
@ -26,20 +27,20 @@ lab_scene_rect_create(struct wlr_scene_tree *parent,
|
|||
rect->border_width = opts->border_width;
|
||||
rect->nr_borders = opts->nr_borders;
|
||||
rect->borders = znew_n(rect->borders[0], opts->nr_borders);
|
||||
rect->tree = wlr_scene_tree_create(parent);
|
||||
rect->tree = lab_wlr_scene_tree_create(parent);
|
||||
|
||||
if (opts->bg_color) {
|
||||
rect->fill = wlr_scene_rect_create(rect->tree, 0, 0, opts->bg_color);
|
||||
rect->fill = lab_wlr_scene_rect_create(rect->tree, 0, 0, opts->bg_color);
|
||||
}
|
||||
|
||||
for (int i = 0; i < rect->nr_borders; i++) {
|
||||
struct border_scene *border = &rect->borders[i];
|
||||
float *color = opts->border_colors[i];
|
||||
border->tree = wlr_scene_tree_create(rect->tree);
|
||||
border->top = wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->right = wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->bottom = wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->left = wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->tree = lab_wlr_scene_tree_create(rect->tree);
|
||||
border->top = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->right = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->bottom = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
border->left = lab_wlr_scene_rect_create(border->tree, 0, 0, color);
|
||||
}
|
||||
|
||||
rect->node_destroy.notify = handle_node_destroy;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/mem.h"
|
||||
#include "magnifier.h"
|
||||
#include "output.h"
|
||||
|
||||
|
|
@ -24,6 +25,34 @@ lab_wlr_surface_from_node(struct wlr_scene_node *node)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_scene_tree *
|
||||
lab_wlr_scene_tree_create(struct wlr_scene_tree *parent)
|
||||
{
|
||||
struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
|
||||
die_if_null(tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
struct wlr_scene_rect *
|
||||
lab_wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
||||
int width, int height, const float color[static 4])
|
||||
{
|
||||
struct wlr_scene_rect *rect =
|
||||
wlr_scene_rect_create(parent, width, height, color);
|
||||
die_if_null(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
struct wlr_scene_buffer *
|
||||
lab_wlr_scene_buffer_create(struct wlr_scene_tree *parent,
|
||||
struct wlr_buffer *buffer)
|
||||
{
|
||||
struct wlr_scene_buffer *scene_buffer =
|
||||
wlr_scene_buffer_create(parent, buffer);
|
||||
die_if_null(scene_buffer);
|
||||
return scene_buffer;
|
||||
}
|
||||
|
||||
struct wlr_scene_node *
|
||||
lab_wlr_scene_get_prev_node(struct wlr_scene_node *node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -89,6 +89,37 @@ out:
|
|||
g_strfreev(argv);
|
||||
}
|
||||
|
||||
void
|
||||
spawn_sync_no_shell(char const *command)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar **argv = NULL;
|
||||
|
||||
assert(command);
|
||||
|
||||
g_shell_parse_argv((gchar *)command, NULL, &argv, &err);
|
||||
if (err) {
|
||||
g_message("%s", err->message);
|
||||
g_error_free(err);
|
||||
return;
|
||||
}
|
||||
|
||||
pid_t child = fork();
|
||||
switch (child) {
|
||||
case -1:
|
||||
wlr_log(WLR_ERROR, "unable to fork()");
|
||||
break;
|
||||
case 0:
|
||||
reset_signals_and_limits();
|
||||
execvp(argv[0], argv);
|
||||
_exit(1);
|
||||
default:
|
||||
waitpid(child, NULL, 0);
|
||||
break;
|
||||
}
|
||||
g_strfreev(argv);
|
||||
}
|
||||
|
||||
pid_t
|
||||
spawn_primary_client(const char *command)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,9 +121,9 @@ update_keycodes_iter(struct xkb_keymap *keymap, xkb_keycode_t key, void *data)
|
|||
}
|
||||
|
||||
void
|
||||
keybind_update_keycodes(struct server *server)
|
||||
keybind_update_keycodes(void)
|
||||
{
|
||||
struct xkb_state *state = server->seat.keyboard_group->keyboard.xkb_state;
|
||||
struct xkb_state *state = server.seat.keyboard_group->keyboard.xkb_state;
|
||||
struct xkb_keymap *keymap = xkb_state_get_keymap(state);
|
||||
|
||||
struct keybind *keybind;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ libinput_category_init(struct libinput_category *l)
|
|||
l->dwt = -1;
|
||||
l->click_method = -1;
|
||||
l->scroll_method = -1;
|
||||
l->scroll_button = -1;
|
||||
l->send_events_mode = -1;
|
||||
l->have_calibration_matrix = false;
|
||||
l->scroll_factor = 1.0;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,43 @@ parse_window_type(const char *type)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
parse_privileged_interface(const char *name)
|
||||
{
|
||||
static const char * const ifaces[] = {
|
||||
"wp_drm_lease_device_v1",
|
||||
"zwlr_gamma_control_manager_v1",
|
||||
"zwlr_output_manager_v1",
|
||||
"zwlr_output_power_manager_v1",
|
||||
"zwp_input_method_manager_v2",
|
||||
"zwlr_virtual_pointer_manager_v1",
|
||||
"zwp_virtual_keyboard_manager_v1",
|
||||
"zwlr_export_dmabuf_manager_v1",
|
||||
"zwlr_screencopy_manager_v1",
|
||||
"ext_data_control_manager_v1",
|
||||
"zwlr_data_control_manager_v1",
|
||||
"wp_security_context_manager_v1",
|
||||
"ext_idle_notifier_v1",
|
||||
"zwlr_foreign_toplevel_manager_v1",
|
||||
"ext_foreign_toplevel_list_v1",
|
||||
"ext_session_lock_manager_v1",
|
||||
"zwlr_layer_shell_v1",
|
||||
"ext_workspace_manager_v1",
|
||||
"ext_image_copy_capture_manager_v1",
|
||||
"ext_output_image_capture_source_manager_v1",
|
||||
};
|
||||
|
||||
static_assert(ARRAY_SIZE(ifaces) <= 32,
|
||||
"return type too small for amount of privileged protocols");
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(ifaces); i++) {
|
||||
if (!strcmp(name, ifaces[i])) {
|
||||
return 1 << i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Openbox/labwc comparison
|
||||
*
|
||||
|
|
@ -300,6 +337,8 @@ fill_window_rule(xmlNode *node)
|
|||
set_property(content, &window_rule->ignore_configure_request);
|
||||
} else if (!strcasecmp(key, "fixedPosition")) {
|
||||
set_property(content, &window_rule->fixed_position);
|
||||
} else if (!strcasecmp(key, "allowAlwaysOnTop")) {
|
||||
set_property(content, &window_rule->allow_always_on_top);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -563,6 +602,7 @@ fill_keybind(xmlNode *node)
|
|||
lab_xml_get_bool(node, "onRelease", &keybind->on_release);
|
||||
lab_xml_get_bool(node, "layoutDependent", &keybind->use_syms_only);
|
||||
lab_xml_get_bool(node, "allowWhenLocked", &keybind->allow_when_locked);
|
||||
lab_xml_get_bool(node, "overrideInhibition", &keybind->override_inhibition);
|
||||
|
||||
append_parsed_actions(node, &keybind->actions);
|
||||
}
|
||||
|
|
@ -573,9 +613,9 @@ fill_mousebind(xmlNode *node, const char *context)
|
|||
/*
|
||||
* Example of what we are parsing:
|
||||
* <mousebind button="Left" action="DoubleClick">
|
||||
* <action name="Focus"/>
|
||||
* <action name="Raise"/>
|
||||
* <action name="ToggleMaximize"/>
|
||||
* <action name="Focus" />
|
||||
* <action name="Raise" />
|
||||
* <action name="ToggleMaximize" />
|
||||
* </mousebind>
|
||||
*/
|
||||
|
||||
|
|
@ -851,9 +891,19 @@ fill_libinput_category(xmlNode *node)
|
|||
} else if (!strcasecmp(content, "twofinger")) {
|
||||
category->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
} else if (!strcasecmp(content, "onbutton")) {
|
||||
category->scroll_method =
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "invalid scrollMethod");
|
||||
}
|
||||
} else if (!strcasecmp(key, "scrollButton")) {
|
||||
int button = atoi(content);
|
||||
if (button != 0) {
|
||||
category->scroll_button = button;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "invalid scrollButton");
|
||||
}
|
||||
} else if (!strcasecmp(key, "sendEventsMode")) {
|
||||
category->send_events_mode =
|
||||
get_send_events_mode(content);
|
||||
|
|
@ -1030,6 +1080,16 @@ set_tearing_mode(const char *str, enum tearing_mode *variable)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_hdr_mode(const char *str, enum render_bit_depth *variable)
|
||||
{
|
||||
if (parse_bool(str, -1) == 1) {
|
||||
*variable = LAB_RENDER_BIT_DEPTH_10;
|
||||
} else {
|
||||
*variable = LAB_RENDER_BIT_DEPTH_8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if the node's children should also be traversed */
|
||||
static bool
|
||||
entry(xmlNode *node, char *nodename, char *content)
|
||||
|
|
@ -1094,6 +1154,8 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
set_adaptive_sync_mode(content, &rc.adaptive_sync);
|
||||
} else if (!strcasecmp(nodename, "allowTearing.core")) {
|
||||
set_tearing_mode(content, &rc.allow_tearing);
|
||||
} else if (!strcasecmp(nodename, "Hdr.core")) {
|
||||
set_hdr_mode(content, &rc.target_render_depth);
|
||||
} else if (!strcasecmp(nodename, "autoEnableOutputs.core")) {
|
||||
set_bool(content, &rc.auto_enable_outputs);
|
||||
} else if (!strcasecmp(nodename, "reuseOutputMode.core")) {
|
||||
|
|
@ -1145,6 +1207,9 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
set_bool(content, &rc.focus_follow_mouse_requires_movement);
|
||||
} else if (!strcasecmp(nodename, "raiseOnFocus.focus")) {
|
||||
set_bool(content, &rc.raise_on_focus);
|
||||
} else if (!strcasecmp(nodename, "raiseOnFocusDelay.focus")) {
|
||||
long val = strtol(content, NULL, 10);
|
||||
rc.raise_on_focus_delay_ms = val > 0 ? (uint32_t)val : 0;
|
||||
} else if (!strcasecmp(nodename, "doubleClickTime.mouse")) {
|
||||
long doubleclick_time_parsed = strtol(content, NULL, 10);
|
||||
if (doubleclick_time_parsed > 0) {
|
||||
|
|
@ -1353,6 +1418,12 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
} else if (!strcasecmp(nodename, "relativeMotionSensitivity.tabletTool")) {
|
||||
rc.tablet_tool.relative_motion_sensitivity =
|
||||
tablet_get_dbl_if_positive(content, "relativeMotionSensitivity");
|
||||
} else if (!strcasecmp(nodename, "minPressure.tabletTool")) {
|
||||
rc.tablet_tool.min_pressure =
|
||||
tablet_get_dbl_if_positive(content, "minPressure");
|
||||
} else if (!strcasecmp(nodename, "maxPressure.tabletTool")) {
|
||||
rc.tablet_tool.max_pressure =
|
||||
tablet_get_dbl_if_positive(content, "maxPressure");
|
||||
} else if (!strcasecmp(nodename, "ignoreButtonReleasePeriod.menu")) {
|
||||
rc.menu_ignore_button_release_period = atoi(content);
|
||||
} else if (!strcasecmp(nodename, "showIcons.menu")) {
|
||||
|
|
@ -1369,6 +1440,16 @@ entry(xmlNode *node, char *nodename, char *content)
|
|||
rc.mag_increment = MAX(0, rc.mag_increment);
|
||||
} else if (!strcasecmp(nodename, "useFilter.magnifier")) {
|
||||
set_bool(content, &rc.mag_filter);
|
||||
} else if (!strcasecmp(nodename, "privilegedInterfaces")) {
|
||||
rc.allowed_interfaces = 0;
|
||||
} else if (!strcasecmp(nodename, "allow.privilegedInterfaces")) {
|
||||
uint32_t iface_id = parse_privileged_interface(content);
|
||||
if (iface_id) {
|
||||
rc.allowed_interfaces |= iface_id;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "invalid value for "
|
||||
"<privilegedInterfaces><allow>");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -1449,8 +1530,10 @@ rcxml_init(void)
|
|||
rc.gap = 0;
|
||||
rc.adaptive_sync = LAB_ADAPTIVE_SYNC_DISABLED;
|
||||
rc.allow_tearing = LAB_TEARING_DISABLED;
|
||||
rc.target_render_depth = LAB_RENDER_BIT_DEPTH_DEFAULT;
|
||||
rc.auto_enable_outputs = true;
|
||||
rc.reuse_output_mode = false;
|
||||
rc.allowed_interfaces = UINT32_MAX;
|
||||
rc.xwayland_persistence = false;
|
||||
rc.primary_selection = true;
|
||||
|
||||
|
|
@ -1463,6 +1546,7 @@ rcxml_init(void)
|
|||
rc.focus_follow_mouse = false;
|
||||
rc.focus_follow_mouse_requires_movement = true;
|
||||
rc.raise_on_focus = false;
|
||||
rc.raise_on_focus_delay_ms = 0;
|
||||
|
||||
rc.doubleclick_time = 500;
|
||||
|
||||
|
|
@ -1473,6 +1557,8 @@ rcxml_init(void)
|
|||
tablet_load_default_button_mappings();
|
||||
rc.tablet_tool.motion = LAB_MOTION_ABSOLUTE;
|
||||
rc.tablet_tool.relative_motion_sensitivity = 1.0;
|
||||
rc.tablet_tool.min_pressure = 0.0;
|
||||
rc.tablet_tool.max_pressure = 1.0;
|
||||
|
||||
rc.repeat_rate = 25;
|
||||
rc.repeat_delay = 600;
|
||||
|
|
@ -1648,6 +1734,8 @@ deduplicate_key_bindings(void)
|
|||
wl_list_remove(¤t->link);
|
||||
keybind_destroy(current);
|
||||
cleared++;
|
||||
} else if (actions_contain_toggle_keybinds(¤t->actions)) {
|
||||
current->override_inhibition = true;
|
||||
}
|
||||
}
|
||||
if (replaced) {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <wlr/backend/drm.h>
|
||||
#include <wlr/backend/multi.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/buf.h"
|
||||
#include "common/dir.h"
|
||||
|
|
@ -20,8 +20,13 @@
|
|||
#include "config/rcxml.h"
|
||||
#include "labwc.h"
|
||||
|
||||
#if WLR_HAS_DRM_BACKEND
|
||||
#include <wlr/backend/drm.h>
|
||||
#else
|
||||
#define wlr_backend_is_drm(backend) (false)
|
||||
#endif
|
||||
|
||||
static const char *const env_vars[] = {
|
||||
"DISPLAY",
|
||||
"WAYLAND_DISPLAY",
|
||||
"XDG_CURRENT_DESKTOP",
|
||||
"XCURSOR_SIZE",
|
||||
|
|
@ -185,10 +190,8 @@ backend_check_drm(struct wlr_backend *backend, void *is_drm)
|
|||
}
|
||||
|
||||
static bool
|
||||
should_update_activation(struct server *server)
|
||||
should_update_activation(void)
|
||||
{
|
||||
assert(server);
|
||||
|
||||
static const char *act_env = "LABWC_UPDATE_ACTIVATION_ENV";
|
||||
char *env = getenv(act_env);
|
||||
if (env) {
|
||||
|
|
@ -206,14 +209,29 @@ should_update_activation(struct server *server)
|
|||
|
||||
/* With no valid preference, update when a DRM backend is in use */
|
||||
bool have_drm = false;
|
||||
wlr_multi_for_each_backend(server->backend, backend_check_drm, &have_drm);
|
||||
wlr_multi_for_each_backend(server.backend, backend_check_drm, &have_drm);
|
||||
return have_drm;
|
||||
}
|
||||
|
||||
static void
|
||||
update_activation_env(struct server *server, bool initialize)
|
||||
execute_update(const char *env_keys, const char *env_unset_keys, bool initialize)
|
||||
{
|
||||
if (!should_update_activation(server)) {
|
||||
char *cmd =
|
||||
strdup_printf("dbus-update-activation-environment %s",
|
||||
initialize ? env_keys : env_unset_keys);
|
||||
spawn_sync_no_shell(cmd);
|
||||
free(cmd);
|
||||
|
||||
cmd = strdup_printf("systemctl --user %s %s",
|
||||
initialize ? "import-environment" : "unset-environment", env_keys);
|
||||
spawn_sync_no_shell(cmd);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
update_activation_env(bool initialize)
|
||||
{
|
||||
if (!should_update_activation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -229,19 +247,18 @@ update_activation_env(struct server *server, bool initialize)
|
|||
char *env_keys = str_join(env_vars, "%s", " ");
|
||||
char *env_unset_keys = initialize ? NULL : str_join(env_vars, "%s=", " ");
|
||||
|
||||
char *cmd =
|
||||
strdup_printf("dbus-update-activation-environment %s",
|
||||
initialize ? env_keys : env_unset_keys);
|
||||
spawn_async_no_shell(cmd);
|
||||
free(cmd);
|
||||
|
||||
cmd = strdup_printf("systemctl --user %s %s",
|
||||
initialize ? "import-environment" : "unset-environment", env_keys);
|
||||
spawn_async_no_shell(cmd);
|
||||
free(cmd);
|
||||
execute_update(env_keys, env_unset_keys, initialize);
|
||||
|
||||
free(env_keys);
|
||||
free(env_unset_keys);
|
||||
|
||||
#if HAVE_XWAYLAND
|
||||
if (server.xwayland) {
|
||||
// DISPLAY is only set if xwayland was initialized successfully,
|
||||
// so we only update the env in that case
|
||||
execute_update("DISPLAY", "DISPLAY=", initialize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -314,18 +331,18 @@ session_run_script(const char *script)
|
|||
}
|
||||
|
||||
void
|
||||
session_autostart_init(struct server *server)
|
||||
session_autostart_init(void)
|
||||
{
|
||||
/* Update dbus and systemd user environment, each may fail gracefully */
|
||||
update_activation_env(server, /* initialize */ true);
|
||||
update_activation_env(/* initialize */ true);
|
||||
session_run_script("autostart");
|
||||
}
|
||||
|
||||
void
|
||||
session_shutdown(struct server *server)
|
||||
session_shutdown(void)
|
||||
{
|
||||
session_run_script("shutdown");
|
||||
|
||||
/* Clear the dbus and systemd user environment, each may fail gracefully */
|
||||
update_activation_env(server, /* initialize */ false);
|
||||
update_activation_env(/* initialize */ false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "config/types.h"
|
||||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
#include "output.h"
|
||||
|
|
@ -18,17 +19,16 @@
|
|||
#include "theme.h"
|
||||
#include "view.h"
|
||||
|
||||
static bool init_cycle(struct server *server, struct cycle_filter filter);
|
||||
static void update_cycle(struct server *server);
|
||||
static void destroy_cycle(struct server *server);
|
||||
static bool init_cycle(struct cycle_filter filter);
|
||||
static void update_cycle(void);
|
||||
static void destroy_cycle(void);
|
||||
|
||||
static void
|
||||
update_preview_outlines(struct view *view)
|
||||
{
|
||||
/* Create / Update preview outline tree */
|
||||
struct server *server = view->server;
|
||||
struct theme *theme = server->theme;
|
||||
struct lab_scene_rect *rect = view->server->cycle.preview_outline;
|
||||
struct theme *theme = rc.theme;
|
||||
struct lab_scene_rect *rect = server.cycle.preview_outline;
|
||||
if (!rect) {
|
||||
struct lab_scene_rect_options opts = {
|
||||
.border_colors = (float *[3]) {
|
||||
|
|
@ -39,10 +39,10 @@ update_preview_outlines(struct view *view)
|
|||
.nr_borders = 3,
|
||||
.border_width = theme->osd_window_switcher_preview_border_width,
|
||||
};
|
||||
rect = lab_scene_rect_create(&server->scene->tree, &opts);
|
||||
rect = lab_scene_rect_create(&server.scene->tree, &opts);
|
||||
wlr_scene_node_place_above(&rect->tree->node,
|
||||
&server->cycle_preview_tree->node);
|
||||
server->cycle.preview_outline = rect;
|
||||
&server.cycle_preview_tree->node);
|
||||
server.cycle.preview_outline = rect;
|
||||
}
|
||||
|
||||
struct wlr_box geo = ssd_max_extents(view);
|
||||
|
|
@ -52,21 +52,21 @@ update_preview_outlines(struct view *view)
|
|||
|
||||
/* Returns the view to select next in the window switcher. */
|
||||
static struct view *
|
||||
get_next_selected_view(struct server *server, enum lab_cycle_dir dir)
|
||||
get_next_selected_view(enum lab_cycle_dir dir)
|
||||
{
|
||||
struct cycle_state *cycle = &server->cycle;
|
||||
struct cycle_state *cycle = &server.cycle;
|
||||
assert(cycle->selected_view);
|
||||
assert(!wl_list_empty(&server->cycle.views));
|
||||
assert(!wl_list_empty(&server.cycle.views));
|
||||
|
||||
struct wl_list *link;
|
||||
if (dir == LAB_CYCLE_DIR_FORWARD) {
|
||||
link = cycle->selected_view->cycle_link.next;
|
||||
if (link == &server->cycle.views) {
|
||||
if (link == &server.cycle.views) {
|
||||
link = link->next;
|
||||
}
|
||||
} else {
|
||||
link = cycle->selected_view->cycle_link.prev;
|
||||
if (link == &server->cycle.views) {
|
||||
if (link == &server.cycle.views) {
|
||||
link = link->prev;
|
||||
}
|
||||
}
|
||||
|
|
@ -83,22 +83,22 @@ get_first_view(struct wl_list *views)
|
|||
}
|
||||
|
||||
void
|
||||
cycle_reinitialize(struct server *server)
|
||||
cycle_reinitialize(void)
|
||||
{
|
||||
struct cycle_state *cycle = &server->cycle;
|
||||
struct cycle_state *cycle = &server.cycle;
|
||||
|
||||
if (server->input_mode != LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_CYCLE) {
|
||||
/* OSD not active, no need for clean up */
|
||||
return;
|
||||
}
|
||||
|
||||
struct view *selected_view = cycle->selected_view;
|
||||
struct view *selected_view_prev =
|
||||
get_next_selected_view(server, LAB_CYCLE_DIR_BACKWARD);
|
||||
get_next_selected_view(LAB_CYCLE_DIR_BACKWARD);
|
||||
struct cycle_filter filter = cycle->filter;
|
||||
|
||||
destroy_cycle(server);
|
||||
if (init_cycle(server, filter)) {
|
||||
destroy_cycle();
|
||||
if (init_cycle(filter)) {
|
||||
/*
|
||||
* Preserve the selected view (or its previous view) if it's
|
||||
* still in the cycle list
|
||||
|
|
@ -110,104 +110,104 @@ cycle_reinitialize(struct server *server)
|
|||
} else {
|
||||
/* should be unreachable */
|
||||
wlr_log(WLR_ERROR, "could not find view to select");
|
||||
cycle->selected_view = get_first_view(&server->cycle.views);
|
||||
cycle->selected_view = get_first_view(&server.cycle.views);
|
||||
}
|
||||
update_cycle(server);
|
||||
update_cycle();
|
||||
} else {
|
||||
/* Failed to re-init window switcher, exit */
|
||||
cycle_finish(server, /*switch_focus*/ false);
|
||||
cycle_finish(/*switch_focus*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cycle_on_cursor_release(struct server *server, struct wlr_scene_node *node)
|
||||
cycle_on_cursor_release(struct wlr_scene_node *node)
|
||||
{
|
||||
assert(server->input_mode == LAB_INPUT_STATE_CYCLE);
|
||||
assert(server.input_mode == LAB_INPUT_STATE_CYCLE);
|
||||
|
||||
struct cycle_osd_item *item = node_cycle_osd_item_from_node(node);
|
||||
server->cycle.selected_view = item->view;
|
||||
cycle_finish(server, /*switch_focus*/ true);
|
||||
server.cycle.selected_view = item->view;
|
||||
cycle_finish(/*switch_focus*/ true);
|
||||
}
|
||||
|
||||
static void
|
||||
restore_preview_node(struct server *server)
|
||||
restore_preview_node(void)
|
||||
{
|
||||
if (server->cycle.preview_node) {
|
||||
wlr_scene_node_reparent(server->cycle.preview_node,
|
||||
server->cycle.preview_dummy->parent);
|
||||
wlr_scene_node_place_above(server->cycle.preview_node,
|
||||
server->cycle.preview_dummy);
|
||||
wlr_scene_node_destroy(server->cycle.preview_dummy);
|
||||
if (server.cycle.preview_node) {
|
||||
wlr_scene_node_reparent(server.cycle.preview_node,
|
||||
server.cycle.preview_dummy->parent);
|
||||
wlr_scene_node_place_above(server.cycle.preview_node,
|
||||
server.cycle.preview_dummy);
|
||||
wlr_scene_node_destroy(server.cycle.preview_dummy);
|
||||
|
||||
/* Node was disabled / minimized before, disable again */
|
||||
if (!server->cycle.preview_was_enabled) {
|
||||
wlr_scene_node_set_enabled(server->cycle.preview_node, false);
|
||||
if (!server.cycle.preview_was_enabled) {
|
||||
wlr_scene_node_set_enabled(server.cycle.preview_node, false);
|
||||
}
|
||||
if (server->cycle.preview_was_shaded) {
|
||||
struct view *view = node_view_from_node(server->cycle.preview_node);
|
||||
if (server.cycle.preview_was_shaded) {
|
||||
struct view *view = node_view_from_node(server.cycle.preview_node);
|
||||
view_set_shade(view, true);
|
||||
}
|
||||
server->cycle.preview_node = NULL;
|
||||
server->cycle.preview_dummy = NULL;
|
||||
server->cycle.preview_was_enabled = false;
|
||||
server->cycle.preview_was_shaded = false;
|
||||
server.cycle.preview_node = NULL;
|
||||
server.cycle.preview_dummy = NULL;
|
||||
server.cycle.preview_was_enabled = false;
|
||||
server.cycle.preview_was_shaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cycle_begin(struct server *server, enum lab_cycle_dir direction,
|
||||
cycle_begin(enum lab_cycle_dir direction,
|
||||
struct cycle_filter filter)
|
||||
{
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!init_cycle(server, filter)) {
|
||||
if (!init_cycle(filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct view *active_view = server->active_view;
|
||||
struct view *active_view = server.active_view;
|
||||
if (active_view && active_view->cycle_link.next) {
|
||||
/* Select the active view it's in the cycle list */
|
||||
server->cycle.selected_view = active_view;
|
||||
/* Select the active view if it's in the cycle list */
|
||||
server.cycle.selected_view = active_view;
|
||||
} else {
|
||||
/* Otherwise, select the first view in the cycle list */
|
||||
server->cycle.selected_view = get_first_view(&server->cycle.views);
|
||||
server.cycle.selected_view = get_first_view(&server.cycle.views);
|
||||
}
|
||||
/* Pre-select the next view in the given direction */
|
||||
server->cycle.selected_view = get_next_selected_view(server, direction);
|
||||
server.cycle.selected_view = get_next_selected_view(direction);
|
||||
|
||||
seat_focus_override_begin(&server->seat,
|
||||
seat_focus_override_begin(&server.seat,
|
||||
LAB_INPUT_STATE_CYCLE, LAB_CURSOR_DEFAULT);
|
||||
update_cycle(server);
|
||||
update_cycle();
|
||||
|
||||
/* Update cursor, in case it is within the area covered by OSD */
|
||||
cursor_update_focus(server);
|
||||
cursor_update_focus();
|
||||
}
|
||||
|
||||
void
|
||||
cycle_step(struct server *server, enum lab_cycle_dir direction)
|
||||
cycle_step(enum lab_cycle_dir direction)
|
||||
{
|
||||
assert(server->input_mode == LAB_INPUT_STATE_CYCLE);
|
||||
assert(server.input_mode == LAB_INPUT_STATE_CYCLE);
|
||||
|
||||
server->cycle.selected_view = get_next_selected_view(server, direction);
|
||||
update_cycle(server);
|
||||
server.cycle.selected_view = get_next_selected_view(direction);
|
||||
update_cycle();
|
||||
}
|
||||
|
||||
void
|
||||
cycle_finish(struct server *server, bool switch_focus)
|
||||
cycle_finish(bool switch_focus)
|
||||
{
|
||||
if (server->input_mode != LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_CYCLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct view *selected_view = server->cycle.selected_view;
|
||||
destroy_cycle(server);
|
||||
struct view *selected_view = server.cycle.selected_view;
|
||||
destroy_cycle();
|
||||
|
||||
seat_focus_override_end(&server->seat, /*restore_focus*/ false);
|
||||
seat_focus_override_end(&server.seat, /*restore_focus*/ false);
|
||||
|
||||
/* Hiding OSD may need a cursor change */
|
||||
cursor_update_focus(server);
|
||||
cursor_update_focus();
|
||||
|
||||
if (switch_focus && selected_view) {
|
||||
if (rc.window_switcher.unshade) {
|
||||
|
|
@ -222,16 +222,15 @@ preview_selected_view(struct view *view)
|
|||
{
|
||||
assert(view);
|
||||
assert(view->scene_tree);
|
||||
struct server *server = view->server;
|
||||
struct cycle_state *cycle = &server->cycle;
|
||||
struct cycle_state *cycle = &server.cycle;
|
||||
|
||||
/* Move previous selected node back to its original place */
|
||||
restore_preview_node(server);
|
||||
restore_preview_node();
|
||||
|
||||
cycle->preview_node = &view->scene_tree->node;
|
||||
|
||||
/* Create a dummy node at the original place of the previewed window */
|
||||
struct wlr_scene_rect *dummy_rect = wlr_scene_rect_create(
|
||||
struct wlr_scene_rect *dummy_rect = lab_wlr_scene_rect_create(
|
||||
cycle->preview_node->parent, 0, 0, (float [4]) {0});
|
||||
wlr_scene_node_place_below(&dummy_rect->node, cycle->preview_node);
|
||||
wlr_scene_node_set_enabled(&dummy_rect->node, false);
|
||||
|
|
@ -246,7 +245,7 @@ preview_selected_view(struct view *view)
|
|||
}
|
||||
|
||||
wlr_scene_node_reparent(cycle->preview_node,
|
||||
view->server->cycle_preview_tree);
|
||||
server.cycle_preview_tree);
|
||||
|
||||
/* Finally raise selected node to the top */
|
||||
wlr_scene_node_raise_to_top(cycle->preview_node);
|
||||
|
|
@ -265,8 +264,7 @@ get_osd_impl(void)
|
|||
}
|
||||
|
||||
static uint64_t
|
||||
get_outputs_by_filter(struct server *server,
|
||||
enum cycle_output_filter output_filter)
|
||||
get_outputs_by_filter(enum cycle_output_filter output_filter)
|
||||
{
|
||||
struct output *output = NULL;
|
||||
|
||||
|
|
@ -274,15 +272,15 @@ get_outputs_by_filter(struct server *server,
|
|||
case CYCLE_OUTPUT_ALL:
|
||||
break;
|
||||
case CYCLE_OUTPUT_CURSOR:
|
||||
output = output_nearest_to_cursor(server);
|
||||
output = output_nearest_to_cursor();
|
||||
break;
|
||||
case CYCLE_OUTPUT_FOCUSED: {
|
||||
struct view *view = server->active_view;
|
||||
struct view *view = server.active_view;
|
||||
if (view && output_is_usable(view->output)) {
|
||||
output = view->output;
|
||||
} else {
|
||||
/* Fallback to pointer */
|
||||
output = output_nearest_to_cursor(server);
|
||||
output = output_nearest_to_cursor();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -325,52 +323,111 @@ handle_osd_tree_destroy(struct wl_listener *listener, void *data)
|
|||
free(osd_output);
|
||||
}
|
||||
|
||||
/* Return false on failure */
|
||||
static bool
|
||||
init_cycle(struct server *server, struct cycle_filter filter)
|
||||
static enum lab_view_criteria
|
||||
get_view_criteria(struct cycle_filter *filter)
|
||||
{
|
||||
enum lab_view_criteria criteria =
|
||||
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER
|
||||
| LAB_VIEW_CRITERIA_NO_DIALOG;
|
||||
if (filter.workspace == CYCLE_WORKSPACE_CURRENT) {
|
||||
if (filter->workspace == CYCLE_WORKSPACE_CURRENT) {
|
||||
criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
|
||||
}
|
||||
return criteria;
|
||||
}
|
||||
|
||||
uint64_t cycle_outputs =
|
||||
get_outputs_by_filter(server, filter.output);
|
||||
static const char *
|
||||
get_cycle_app_id(struct cycle_filter *filter)
|
||||
{
|
||||
if (filter->app_id == CYCLE_APP_ID_CURRENT && server.active_view) {
|
||||
return server.active_view->app_id;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *cycle_app_id = NULL;
|
||||
if (filter.app_id == CYCLE_APP_ID_CURRENT && server->active_view) {
|
||||
cycle_app_id = server->active_view->app_id;
|
||||
static struct wl_list *prev(struct wl_list *elm) { return elm->prev; }
|
||||
static struct wl_list *next(struct wl_list *elm) { return elm->next; }
|
||||
|
||||
void
|
||||
cycle_immediate(enum lab_cycle_dir direction, struct cycle_filter filter)
|
||||
{
|
||||
if (wl_list_empty(&server.views)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct view *view;
|
||||
for_each_view(view, &server->views, criteria) {
|
||||
if (!(cycle_outputs & view->output->id_bit)) {
|
||||
enum lab_view_criteria criteria = get_view_criteria(&filter);
|
||||
uint64_t cycle_outputs = get_outputs_by_filter(filter.output);
|
||||
const char *cycle_app_id = get_cycle_app_id(&filter);
|
||||
|
||||
struct wl_list *head = &server.views;
|
||||
struct wl_list *(*iter)(struct wl_list *list);
|
||||
iter = direction == LAB_CYCLE_DIR_FORWARD ? next : prev;
|
||||
|
||||
struct wl_list *from = (direction == LAB_CYCLE_DIR_FORWARD) && server.active_view
|
||||
? &server.active_view->link : head;
|
||||
|
||||
for (struct wl_list *elm = iter(from); elm != head; elm = iter(elm)) {
|
||||
struct view *view = wl_container_of(elm, view, link);
|
||||
if (!view_matches_criteria(view, criteria)) {
|
||||
continue;
|
||||
}
|
||||
if (filter.output != CYCLE_OUTPUT_ALL) {
|
||||
if (!view->output || !(cycle_outputs & view->output->id_bit)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cycle_app_id && strcmp(view->app_id, cycle_app_id) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (server.active_view && direction == LAB_CYCLE_DIR_FORWARD) {
|
||||
/*
|
||||
* When cycling forward, the current active view needs to be
|
||||
* sent to back to keep the same sequence and avoid getting
|
||||
* stuck in the 2 topmost views.
|
||||
*/
|
||||
view_move_to_back(server.active_view);
|
||||
}
|
||||
desktop_focus_view(view, true);
|
||||
break;
|
||||
}
|
||||
cursor_update_focus();
|
||||
}
|
||||
|
||||
/* Return false on failure */
|
||||
static bool
|
||||
init_cycle(struct cycle_filter filter)
|
||||
{
|
||||
enum lab_view_criteria criteria = get_view_criteria(&filter);
|
||||
uint64_t cycle_outputs = get_outputs_by_filter(filter.output);
|
||||
const char *cycle_app_id = get_cycle_app_id(&filter);
|
||||
|
||||
struct view *view;
|
||||
for_each_view(view, &server.views, criteria) {
|
||||
if (filter.output != CYCLE_OUTPUT_ALL) {
|
||||
if (!view->output || !(cycle_outputs & view->output->id_bit)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cycle_app_id && strcmp(view->app_id, cycle_app_id) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rc.window_switcher.order == WINDOW_SWITCHER_ORDER_AGE) {
|
||||
insert_view_ordered_by_age(&server->cycle.views, view);
|
||||
insert_view_ordered_by_age(&server.cycle.views, view);
|
||||
} else {
|
||||
wl_list_append(&server->cycle.views, &view->cycle_link);
|
||||
wl_list_append(&server.cycle.views, &view->cycle_link);
|
||||
}
|
||||
}
|
||||
if (wl_list_empty(&server->cycle.views)) {
|
||||
if (wl_list_empty(&server.cycle.views)) {
|
||||
wlr_log(WLR_DEBUG, "no views to switch between");
|
||||
return false;
|
||||
}
|
||||
server->cycle.filter = filter;
|
||||
server.cycle.filter = filter;
|
||||
|
||||
if (rc.window_switcher.osd.show) {
|
||||
/* Create OSD */
|
||||
uint64_t osd_outputs = get_outputs_by_filter(server,
|
||||
rc.window_switcher.osd.output_filter);
|
||||
uint64_t osd_outputs = get_outputs_by_filter(rc.window_switcher.osd.output_filter);
|
||||
struct output *output;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
if (!(osd_outputs & output->id_bit)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -379,7 +436,7 @@ init_cycle(struct server *server, struct cycle_filter filter)
|
|||
}
|
||||
|
||||
struct cycle_osd_output *osd_output = znew(*osd_output);
|
||||
wl_list_append(&server->cycle.osd_outputs, &osd_output->link);
|
||||
wl_list_append(&server.cycle.osd_outputs, &osd_output->link);
|
||||
osd_output->output = output;
|
||||
wl_list_init(&osd_output->items);
|
||||
|
||||
|
|
@ -395,9 +452,9 @@ init_cycle(struct server *server, struct cycle_filter filter)
|
|||
}
|
||||
|
||||
static void
|
||||
update_cycle(struct server *server)
|
||||
update_cycle(void)
|
||||
{
|
||||
struct cycle_state *cycle = &server->cycle;
|
||||
struct cycle_state *cycle = &server.cycle;
|
||||
|
||||
if (rc.window_switcher.osd.show) {
|
||||
struct cycle_osd_output *osd_output;
|
||||
|
|
@ -418,29 +475,29 @@ update_cycle(struct server *server)
|
|||
}
|
||||
}
|
||||
|
||||
/* Resets all the states in server->cycle */
|
||||
/* Resets all the states in server.cycle */
|
||||
static void
|
||||
destroy_cycle(struct server *server)
|
||||
destroy_cycle(void)
|
||||
{
|
||||
struct cycle_osd_output *osd_output, *tmp;
|
||||
wl_list_for_each_safe(osd_output, tmp, &server->cycle.osd_outputs, link) {
|
||||
wl_list_for_each_safe(osd_output, tmp, &server.cycle.osd_outputs, link) {
|
||||
/* calls handle_osd_tree_destroy() */
|
||||
wlr_scene_node_destroy(&osd_output->tree->node);
|
||||
}
|
||||
|
||||
restore_preview_node(server);
|
||||
restore_preview_node();
|
||||
|
||||
if (server->cycle.preview_outline) {
|
||||
wlr_scene_node_destroy(&server->cycle.preview_outline->tree->node);
|
||||
if (server.cycle.preview_outline) {
|
||||
wlr_scene_node_destroy(&server.cycle.preview_outline->tree->node);
|
||||
}
|
||||
|
||||
struct view *view, *tmp2;
|
||||
wl_list_for_each_safe(view, tmp2, &server->cycle.views, cycle_link) {
|
||||
wl_list_for_each_safe(view, tmp2, &server.cycle.views, cycle_link) {
|
||||
wl_list_remove(&view->cycle_link);
|
||||
view->cycle_link = (struct wl_list){0};
|
||||
}
|
||||
|
||||
server->cycle = (struct cycle_state){0};
|
||||
wl_list_init(&server->cycle.views);
|
||||
wl_list_init(&server->cycle.osd_outputs);
|
||||
server.cycle = (struct cycle_state){0};
|
||||
wl_list_init(&server.cycle.views);
|
||||
wl_list_init(&server.cycle.osd_outputs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "common/lab-scene-rect.h"
|
||||
#include "common/list.h"
|
||||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "common/string-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "cycle.h"
|
||||
|
|
@ -27,11 +28,11 @@ struct cycle_osd_classic_item {
|
|||
};
|
||||
|
||||
static void
|
||||
create_fields_scene(struct server *server, struct view *view,
|
||||
create_fields_scene(struct view *view,
|
||||
struct wlr_scene_tree *parent, const float *text_color,
|
||||
const float *bg_color, int field_widths_sum, int x, int y)
|
||||
{
|
||||
struct theme *theme = server->theme;
|
||||
struct theme *theme = rc.theme;
|
||||
struct window_switcher_classic_theme *switcher_theme =
|
||||
&theme->osd_window_switcher_classic;
|
||||
|
||||
|
|
@ -45,8 +46,7 @@ create_fields_scene(struct server *server, struct view *view,
|
|||
int icon_size = MIN(field_width,
|
||||
switcher_theme->item_icon_size);
|
||||
struct scaled_icon_buffer *icon_buffer =
|
||||
scaled_icon_buffer_create(parent,
|
||||
server, icon_size, icon_size);
|
||||
scaled_icon_buffer_create(parent, icon_size, icon_size);
|
||||
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||
node = &icon_buffer->scene_buffer->node;
|
||||
height = icon_size;
|
||||
|
|
@ -80,17 +80,16 @@ static void
|
|||
cycle_osd_classic_init(struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct output *output = osd_output->output;
|
||||
struct server *server = output->server;
|
||||
struct theme *theme = server->theme;
|
||||
struct theme *theme = rc.theme;
|
||||
struct window_switcher_classic_theme *switcher_theme =
|
||||
&theme->osd_window_switcher_classic;
|
||||
int padding = theme->osd_border_width + switcher_theme->padding;
|
||||
bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1;
|
||||
const char *workspace_name = server->workspaces.current->name;
|
||||
int nr_views = wl_list_length(&server->cycle.views);
|
||||
const char *workspace_name = server.workspaces.current->name;
|
||||
int nr_views = wl_list_length(&server.cycle.views);
|
||||
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(server->output_layout, output->wlr_output,
|
||||
wlr_output_layout_get_box(server.output_layout, output->wlr_output,
|
||||
&output_box);
|
||||
|
||||
int w = switcher_theme->width;
|
||||
|
|
@ -108,7 +107,7 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output)
|
|||
int h = workspace_name_h + nr_visible_views * switcher_theme->item_height
|
||||
+ 2 * padding;
|
||||
|
||||
osd_output->tree = wlr_scene_tree_create(output->cycle_osd_tree);
|
||||
osd_output->tree = lab_wlr_scene_tree_create(output->cycle_osd_tree);
|
||||
|
||||
float *text_color = theme->osd_label_text_color;
|
||||
float *bg_color = theme->osd_bg_color;
|
||||
|
|
@ -161,15 +160,15 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output)
|
|||
|
||||
float *active_bg_color = switcher_theme->item_active_bg_color;
|
||||
float *active_border_color = switcher_theme->item_active_border_color;
|
||||
osd_output->items_tree = wlr_scene_tree_create(osd_output->tree);
|
||||
osd_output->items_tree = lab_wlr_scene_tree_create(osd_output->tree);
|
||||
|
||||
/* Draw text for each node */
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->cycle.views, cycle_link) {
|
||||
wl_list_for_each(view, &server.cycle.views, cycle_link) {
|
||||
struct cycle_osd_classic_item *item = znew(*item);
|
||||
wl_list_append(&osd_output->items, &item->base.link);
|
||||
item->base.view = view;
|
||||
item->base.tree = wlr_scene_tree_create(osd_output->items_tree);
|
||||
item->base.tree = lab_wlr_scene_tree_create(osd_output->items_tree);
|
||||
node_descriptor_create(&item->base.tree->node,
|
||||
LAB_NODE_CYCLE_OSD_ITEM, NULL, item);
|
||||
/*
|
||||
|
|
@ -191,8 +190,8 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output)
|
|||
int x = padding
|
||||
+ switcher_theme->item_active_border_width
|
||||
+ switcher_theme->item_padding_x;
|
||||
item->normal_tree = wlr_scene_tree_create(item->base.tree);
|
||||
item->active_tree = wlr_scene_tree_create(item->base.tree);
|
||||
item->normal_tree = lab_wlr_scene_tree_create(item->base.tree);
|
||||
item->active_tree = lab_wlr_scene_tree_create(item->base.tree);
|
||||
wlr_scene_node_set_enabled(&item->active_tree->node, false);
|
||||
|
||||
/* Highlight around selected window's item */
|
||||
|
|
@ -209,13 +208,13 @@ cycle_osd_classic_init(struct cycle_osd_output *osd_output)
|
|||
wlr_scene_node_set_position(&highlight_rect->tree->node, padding, y);
|
||||
|
||||
/* hitbox for mouse clicks */
|
||||
struct wlr_scene_rect *hitbox = wlr_scene_rect_create(item->base.tree,
|
||||
struct wlr_scene_rect *hitbox = lab_wlr_scene_rect_create(item->base.tree,
|
||||
w - 2 * padding, switcher_theme->item_height, (float[4]) {0});
|
||||
wlr_scene_node_set_position(&hitbox->node, padding, y);
|
||||
|
||||
create_fields_scene(server, view, item->normal_tree,
|
||||
create_fields_scene(view, item->normal_tree,
|
||||
text_color, bg_color, field_widths_sum, x, y);
|
||||
create_fields_scene(server, view, item->active_tree,
|
||||
create_fields_scene(view, item->active_tree,
|
||||
text_color, active_bg_color, field_widths_sum, x, y);
|
||||
|
||||
y += switcher_theme->item_height;
|
||||
|
|
@ -242,12 +241,11 @@ error:;
|
|||
static void
|
||||
cycle_osd_classic_update(struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct server *server = osd_output->output->server;
|
||||
cycle_osd_scroll_update(osd_output);
|
||||
|
||||
struct cycle_osd_classic_item *item;
|
||||
wl_list_for_each(item, &osd_output->items, base.link) {
|
||||
bool active = item->base.view == server->cycle.selected_view;
|
||||
bool active = item->base.view == server.cycle.selected_view;
|
||||
wlr_scene_node_set_enabled(&item->normal_tree->node, !active);
|
||||
wlr_scene_node_set_enabled(&item->active_tree->node, active);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ static const char *
|
|||
get_desktop_name(struct view *view)
|
||||
{
|
||||
#if HAVE_LIBSFDO
|
||||
const char *name = desktop_entry_name_lookup(view->server, view->app_id);
|
||||
const char *name = desktop_entry_name_lookup(view->app_id);
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ static void
|
|||
field_set_output_short(struct buf *buf, struct view *view, const char *format)
|
||||
{
|
||||
/* custom type conversion-specifier: o */
|
||||
if (wl_list_length(&view->server->outputs) > 1 &&
|
||||
if (wl_list_length(&server.outputs) > 1 &&
|
||||
output_is_usable(view->output)) {
|
||||
buf_add(buf, view->output->wlr_output->name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <assert.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include "common/lab-scene-rect.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "labwc.h"
|
||||
#include "cycle.h"
|
||||
#include "output.h"
|
||||
|
|
@ -23,7 +24,7 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar
|
|||
scroll->top_row_idx = 0;
|
||||
scroll->bar_area = bar_area;
|
||||
scroll->delta_y = delta_y;
|
||||
scroll->bar_tree = wlr_scene_tree_create(osd_output->tree);
|
||||
scroll->bar_tree = lab_wlr_scene_tree_create(osd_output->tree);
|
||||
wlr_scene_node_set_position(&scroll->bar_tree->node,
|
||||
bar_area.x, bar_area.y);
|
||||
|
||||
|
|
@ -41,12 +42,10 @@ cycle_osd_scroll_init(struct cycle_osd_output *osd_output, struct wlr_box bar_ar
|
|||
static int
|
||||
get_cycle_idx(struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct server *server = osd_output->output->server;
|
||||
|
||||
int idx = 0;
|
||||
struct cycle_osd_item *item;
|
||||
wl_list_for_each(item, &osd_output->items, link) {
|
||||
if (item->view == server->cycle.selected_view) {
|
||||
if (item->view == server.cycle.selected_view) {
|
||||
return idx;
|
||||
}
|
||||
idx++;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <assert.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include "config/rcxml.h"
|
||||
|
|
@ -10,6 +11,7 @@
|
|||
#include "common/lab-scene-rect.h"
|
||||
#include "common/list.h"
|
||||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "cycle.h"
|
||||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
|
|
@ -27,7 +29,7 @@ struct cycle_osd_thumbnail_item {
|
|||
};
|
||||
|
||||
static void
|
||||
render_node(struct server *server, struct wlr_render_pass *pass,
|
||||
render_node(struct wlr_render_pass *pass,
|
||||
struct wlr_scene_node *node, int x, int y)
|
||||
{
|
||||
switch (node->type) {
|
||||
|
|
@ -35,7 +37,7 @@ render_node(struct server *server, struct wlr_render_pass *pass,
|
|||
struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
|
||||
struct wlr_scene_node *child;
|
||||
wl_list_for_each(child, &tree->children, link) {
|
||||
render_node(server, pass, child, x + node->x, y + node->y);
|
||||
render_node(pass, child, x + node->x, y + node->y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -45,8 +47,12 @@ render_node(struct server *server, struct wlr_render_pass *pass,
|
|||
if (!scene_buffer->buffer) {
|
||||
break;
|
||||
}
|
||||
struct wlr_texture *texture = wlr_texture_from_buffer(
|
||||
server->renderer, scene_buffer->buffer);
|
||||
struct wlr_texture *texture = NULL;
|
||||
struct wlr_client_buffer *client_buffer =
|
||||
wlr_client_buffer_get(scene_buffer->buffer);
|
||||
if (client_buffer) {
|
||||
texture = client_buffer->texture;
|
||||
}
|
||||
if (!texture) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -61,7 +67,6 @@ render_node(struct server *server, struct wlr_render_pass *pass,
|
|||
},
|
||||
.transform = scene_buffer->transform,
|
||||
});
|
||||
wlr_texture_destroy(texture);
|
||||
break;
|
||||
}
|
||||
case WLR_SCENE_NODE_RECT:
|
||||
|
|
@ -81,13 +86,16 @@ render_thumb(struct output *output, struct view *view)
|
|||
*/
|
||||
return NULL;
|
||||
}
|
||||
struct server *server = output->server;
|
||||
struct wlr_buffer *buffer = wlr_allocator_create_buffer(server->allocator,
|
||||
struct wlr_buffer *buffer = wlr_allocator_create_buffer(server.allocator,
|
||||
view->current.width, view->current.height,
|
||||
&output->wlr_output->swapchain->format);
|
||||
if (!buffer) {
|
||||
wlr_log(WLR_ERROR, "failed to allocate buffer for thumbnail");
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(
|
||||
server->renderer, buffer, NULL);
|
||||
render_node(server, pass, &view->content_tree->node, 0, 0);
|
||||
server.renderer, buffer, NULL);
|
||||
render_node(pass, &view->content_tree->node, 0, 0);
|
||||
if (!wlr_render_pass_submit(pass)) {
|
||||
wlr_log(WLR_ERROR, "failed to submit render pass");
|
||||
wlr_buffer_drop(buffer);
|
||||
|
|
@ -119,8 +127,7 @@ static struct cycle_osd_thumbnail_item *
|
|||
create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
||||
struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct server *server = osd_output->output->server;
|
||||
struct theme *theme = server->theme;
|
||||
struct theme *theme = rc.theme;
|
||||
struct window_switcher_thumbnail_theme *switcher_theme =
|
||||
&theme->osd_window_switcher_thumbnail;
|
||||
int padding = theme->border_width + switcher_theme->item_padding;
|
||||
|
|
@ -138,7 +145,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
|||
|
||||
struct cycle_osd_thumbnail_item *item = znew(*item);
|
||||
wl_list_append(&osd_output->items, &item->base.link);
|
||||
struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
|
||||
struct wlr_scene_tree *tree = lab_wlr_scene_tree_create(parent);
|
||||
node_descriptor_create(&tree->node, LAB_NODE_CYCLE_OSD_ITEM, NULL, item);
|
||||
item->base.tree = tree;
|
||||
item->base.view = view;
|
||||
|
|
@ -155,14 +162,14 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
|||
item->active_bg = lab_scene_rect_create(tree, &opts);
|
||||
|
||||
/* hitbox for mouse clicks */
|
||||
wlr_scene_rect_create(tree, switcher_theme->item_width,
|
||||
lab_wlr_scene_rect_create(tree, switcher_theme->item_width,
|
||||
switcher_theme->item_height, (float[4]) {0});
|
||||
|
||||
/* thumbnail */
|
||||
struct wlr_buffer *thumb_buffer = render_thumb(osd_output->output, view);
|
||||
if (thumb_buffer) {
|
||||
struct wlr_scene_buffer *thumb_scene_buffer =
|
||||
wlr_scene_buffer_create(tree, thumb_buffer);
|
||||
lab_wlr_scene_buffer_create(tree, thumb_buffer);
|
||||
wlr_buffer_drop(thumb_buffer);
|
||||
struct wlr_box thumb_box = box_fit_within(
|
||||
thumb_buffer->width, thumb_buffer->height,
|
||||
|
|
@ -184,7 +191,7 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
|||
/* icon */
|
||||
int icon_size = switcher_theme->item_icon_size;
|
||||
struct scaled_icon_buffer *icon_buffer =
|
||||
scaled_icon_buffer_create(tree, server, icon_size, icon_size);
|
||||
scaled_icon_buffer_create(tree, icon_size, icon_size);
|
||||
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||
int x = (switcher_theme->item_width - icon_size) / 2;
|
||||
int y = title_y - padding - icon_size + 10; /* slide by 10px */
|
||||
|
|
@ -197,7 +204,7 @@ static void
|
|||
get_items_geometry(struct output *output, int nr_thumbs,
|
||||
int *nr_cols, int *nr_rows, int *nr_visible_rows)
|
||||
{
|
||||
struct theme *theme = output->server->theme;
|
||||
struct theme *theme = rc.theme;
|
||||
struct window_switcher_thumbnail_theme *switcher_theme =
|
||||
&theme->osd_window_switcher_thumbnail;
|
||||
int output_width, output_height;
|
||||
|
|
@ -233,16 +240,15 @@ static void
|
|||
cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct output *output = osd_output->output;
|
||||
struct server *server = output->server;
|
||||
struct theme *theme = server->theme;
|
||||
struct theme *theme = rc.theme;
|
||||
struct window_switcher_thumbnail_theme *switcher_theme =
|
||||
&theme->osd_window_switcher_thumbnail;
|
||||
int padding = theme->osd_border_width + switcher_theme->padding;
|
||||
|
||||
osd_output->tree = wlr_scene_tree_create(output->cycle_osd_tree);
|
||||
osd_output->items_tree = wlr_scene_tree_create(osd_output->tree);
|
||||
osd_output->tree = lab_wlr_scene_tree_create(output->cycle_osd_tree);
|
||||
osd_output->items_tree = lab_wlr_scene_tree_create(osd_output->tree);
|
||||
|
||||
int nr_views = wl_list_length(&server->cycle.views);
|
||||
int nr_views = wl_list_length(&server.cycle.views);
|
||||
assert(nr_views > 0);
|
||||
int nr_cols, nr_rows, nr_visible_rows;
|
||||
get_items_geometry(output, nr_views, &nr_cols, &nr_rows, &nr_visible_rows);
|
||||
|
|
@ -250,7 +256,7 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output)
|
|||
/* items */
|
||||
struct view *view;
|
||||
int index = 0;
|
||||
wl_list_for_each(view, &server->cycle.views, cycle_link) {
|
||||
wl_list_for_each(view, &server.cycle.views, cycle_link) {
|
||||
struct cycle_osd_thumbnail_item *item = create_item_scene(
|
||||
osd_output->items_tree, view, osd_output);
|
||||
if (!item) {
|
||||
|
|
@ -291,7 +297,7 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output)
|
|||
|
||||
/* center */
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(server->output_layout, output->wlr_output,
|
||||
wlr_output_layout_get_box(server.output_layout, output->wlr_output,
|
||||
&output_box);
|
||||
int lx = output_box.x + (output_box.width - bg_opts.width) / 2;
|
||||
int ly = output_box.y + (output_box.height - bg_opts.height) / 2;
|
||||
|
|
@ -301,12 +307,11 @@ cycle_osd_thumbnail_init(struct cycle_osd_output *osd_output)
|
|||
static void
|
||||
cycle_osd_thumbnail_update(struct cycle_osd_output *osd_output)
|
||||
{
|
||||
struct server *server = osd_output->output->server;
|
||||
cycle_osd_scroll_update(osd_output);
|
||||
|
||||
struct cycle_osd_thumbnail_item *item;
|
||||
wl_list_for_each(item, &osd_output->items, base.link) {
|
||||
bool active = (item->base.view == server->cycle.selected_view);
|
||||
bool active = (item->base.view == server.cycle.selected_view);
|
||||
wlr_scene_node_set_enabled(&item->active_bg->tree->node, active);
|
||||
wlr_scene_node_set_enabled(
|
||||
&item->active_label->scene_buffer->node, active);
|
||||
|
|
|
|||
74
src/debug.c
74
src/debug.c
|
|
@ -89,10 +89,10 @@ get_view_part(struct view *view, struct wlr_scene_node *node)
|
|||
}
|
||||
|
||||
static struct workspace *
|
||||
get_workspace_from_node(struct server *server, struct wlr_scene_node *node)
|
||||
get_workspace_from_node(struct wlr_scene_node *node)
|
||||
{
|
||||
struct workspace *workspace;
|
||||
wl_list_for_each(workspace, &server->workspaces.all, link) {
|
||||
wl_list_for_each(workspace, &server.workspaces.all, link) {
|
||||
if (&workspace->tree->node == node) {
|
||||
return workspace;
|
||||
}
|
||||
|
|
@ -101,31 +101,31 @@ get_workspace_from_node(struct server *server, struct wlr_scene_node *node)
|
|||
}
|
||||
|
||||
static const char *
|
||||
get_special(struct server *server, struct wlr_scene_node *node)
|
||||
get_special(struct wlr_scene_node *node)
|
||||
{
|
||||
struct wlr_scene_tree *grand_parent =
|
||||
node->parent ? node->parent->node.parent : NULL;
|
||||
struct wlr_scene_tree *grand_grand_parent =
|
||||
grand_parent ? grand_parent->node.parent : NULL;
|
||||
if (node == &server->scene->tree.node) {
|
||||
return "server->scene";
|
||||
if (node == &server.scene->tree.node) {
|
||||
return "server.scene";
|
||||
}
|
||||
if (node == &server->menu_tree->node) {
|
||||
return "server->menu_tree";
|
||||
if (node == &server.menu_tree->node) {
|
||||
return "server.menu_tree";
|
||||
}
|
||||
if (node == &server->workspace_tree->node) {
|
||||
return "server->workspace_tree";
|
||||
if (node == &server.workspace_tree->node) {
|
||||
return "server.workspace_tree";
|
||||
}
|
||||
if (node->parent == server->workspace_tree) {
|
||||
struct workspace *workspace = get_workspace_from_node(server, node);
|
||||
if (node->parent == server.workspace_tree) {
|
||||
struct workspace *workspace = get_workspace_from_node(node);
|
||||
if (workspace) {
|
||||
return workspace->name;
|
||||
}
|
||||
return "unknown workspace";
|
||||
}
|
||||
if (grand_parent == server->workspace_tree) {
|
||||
if (grand_parent == server.workspace_tree) {
|
||||
struct workspace *workspace =
|
||||
get_workspace_from_node(server, &node->parent->node);
|
||||
get_workspace_from_node(&node->parent->node);
|
||||
if (workspace) {
|
||||
struct wlr_scene_tree **trees = workspace->view_trees;
|
||||
if (node == &trees[VIEW_LAYER_NORMAL]->node) {
|
||||
|
|
@ -138,9 +138,9 @@ get_special(struct server *server, struct wlr_scene_node *node)
|
|||
}
|
||||
return "unknown tree";
|
||||
}
|
||||
if (node->parent == &server->scene->tree) {
|
||||
if (node->parent == &server.scene->tree) {
|
||||
struct output *output;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
if (node == &output->cycle_osd_tree->node) {
|
||||
return "output->osd_tree";
|
||||
}
|
||||
|
|
@ -157,33 +157,33 @@ get_special(struct server *server, struct wlr_scene_node *node)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (node == &server->xdg_popup_tree->node) {
|
||||
return "server->xdg_popup_tree";
|
||||
if (node == &server.xdg_popup_tree->node) {
|
||||
return "server.xdg_popup_tree";
|
||||
}
|
||||
if (node == &server->seat.drag.icons->node) {
|
||||
if (node == &server.seat.drag.icons->node) {
|
||||
return "seat->drag.icons";
|
||||
}
|
||||
if (server->seat.overlay.rect
|
||||
&& node == &server->seat.overlay.rect->tree->node) {
|
||||
if (server.seat.overlay.rect
|
||||
&& node == &server.seat.overlay.rect->tree->node) {
|
||||
/* Created on-demand */
|
||||
return "seat->overlay.rect";
|
||||
}
|
||||
if (server->seat.input_method_relay->popup_tree
|
||||
&& node == &server->seat.input_method_relay->popup_tree->node) {
|
||||
if (server.seat.input_method_relay->popup_tree
|
||||
&& node == &server.seat.input_method_relay->popup_tree->node) {
|
||||
/* Created on-demand */
|
||||
return "seat->im_relay->popup_tree";
|
||||
}
|
||||
if (server->cycle.preview_outline
|
||||
&& node == &server->cycle.preview_outline->tree->node) {
|
||||
if (server.cycle.preview_outline
|
||||
&& node == &server.cycle.preview_outline->tree->node) {
|
||||
/* Created on-demand */
|
||||
return "cycle_state->preview_outline";
|
||||
}
|
||||
#if HAVE_XWAYLAND
|
||||
if (node == &server->unmanaged_tree->node) {
|
||||
return "server->unmanaged_tree";
|
||||
if (node == &server.unmanaged_tree->node) {
|
||||
return "server.unmanaged_tree";
|
||||
}
|
||||
#endif
|
||||
if (grand_grand_parent == server->workspace_tree && node->data) {
|
||||
if (grand_grand_parent == server.workspace_tree && node->data) {
|
||||
last_view = node_view_from_node(node);
|
||||
}
|
||||
const char *view_part = get_view_part(last_view, node);
|
||||
|
|
@ -209,10 +209,10 @@ get_center_padding(const char *text, uint8_t max_width)
|
|||
}
|
||||
|
||||
static void
|
||||
dump_tree(struct server *server, struct wlr_scene_node *node,
|
||||
dump_tree(struct wlr_scene_node *node,
|
||||
int pos, int x, int y)
|
||||
{
|
||||
const char *type = get_special(server, node);
|
||||
const char *type = get_special(node);
|
||||
|
||||
if (pos) {
|
||||
printf("%*c+-- ", pos, ' ');
|
||||
|
|
@ -234,13 +234,13 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
|
|||
}
|
||||
printf("%.*s %*c %4d %4d [%p]\n", max_width - 1, type, padding, ' ', x, y, node);
|
||||
|
||||
if ((IGNORE_MENU && node == &server->menu_tree->node)
|
||||
if ((IGNORE_MENU && node == &server.menu_tree->node)
|
||||
|| (IGNORE_SSD && last_view
|
||||
&& ssd_debug_is_root_node(last_view->ssd, node))
|
||||
|| (IGNORE_CYCLE_PREVIEW_OUTLINE && server->cycle.preview_outline
|
||||
&& node == &server->cycle.preview_outline->tree->node)
|
||||
|| (IGNORE_SNAPPING_OVERLAY && server->seat.overlay.rect
|
||||
&& node == &server->seat.overlay.rect->tree->node)) {
|
||||
|| (IGNORE_CYCLE_PREVIEW_OUTLINE && server.cycle.preview_outline
|
||||
&& node == &server.cycle.preview_outline->tree->node)
|
||||
|| (IGNORE_SNAPPING_OVERLAY && server.seat.overlay.rect
|
||||
&& node == &server.seat.overlay.rect->tree->node)) {
|
||||
printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
|
||||
return;
|
||||
}
|
||||
|
|
@ -249,17 +249,17 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
|
|||
struct wlr_scene_node *child;
|
||||
struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
|
||||
wl_list_for_each(child, &tree->children, link) {
|
||||
dump_tree(server, child, pos + INDENT_SIZE,
|
||||
dump_tree(child, pos + INDENT_SIZE,
|
||||
x + child->x, y + child->y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_scene(struct server *server)
|
||||
debug_dump_scene(void)
|
||||
{
|
||||
printf("\n");
|
||||
dump_tree(server, &server->scene->tree.node, 0, 0, 0);
|
||||
dump_tree(&server.scene->tree.node, 0, 0, 0);
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -119,10 +119,10 @@ kde_server_decoration_update_default(void)
|
|||
}
|
||||
|
||||
void
|
||||
kde_server_decoration_init(struct server *server)
|
||||
kde_server_decoration_init(void)
|
||||
{
|
||||
assert(!kde_deco_mgr);
|
||||
kde_deco_mgr = wlr_server_decoration_manager_create(server->wl_display);
|
||||
kde_deco_mgr = wlr_server_decoration_manager_create(server.wl_display);
|
||||
if (!kde_deco_mgr) {
|
||||
wlr_log(WLR_ERROR, "unable to create the kde server deco manager");
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -131,12 +131,12 @@ kde_server_decoration_init(struct server *server)
|
|||
wl_list_init(&decorations);
|
||||
kde_server_decoration_update_default();
|
||||
|
||||
wl_signal_add(&kde_deco_mgr->events.new_decoration, &server->kde_server_decoration);
|
||||
server->kde_server_decoration.notify = handle_new_server_decoration;
|
||||
wl_signal_add(&kde_deco_mgr->events.new_decoration, &server.kde_server_decoration);
|
||||
server.kde_server_decoration.notify = handle_new_server_decoration;
|
||||
}
|
||||
|
||||
void
|
||||
kde_server_decoration_finish(struct server *server)
|
||||
kde_server_decoration_finish(void)
|
||||
{
|
||||
wl_list_remove(&server->kde_server_decoration.link);
|
||||
wl_list_remove(&server.kde_server_decoration.link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,22 +115,22 @@ xdg_toplevel_decoration(struct wl_listener *listener, void *data)
|
|||
}
|
||||
|
||||
void
|
||||
xdg_server_decoration_init(struct server *server)
|
||||
xdg_server_decoration_init(void)
|
||||
{
|
||||
struct wlr_xdg_decoration_manager_v1 *xdg_deco_mgr = NULL;
|
||||
xdg_deco_mgr = wlr_xdg_decoration_manager_v1_create(server->wl_display);
|
||||
xdg_deco_mgr = wlr_xdg_decoration_manager_v1_create(server.wl_display);
|
||||
if (!xdg_deco_mgr) {
|
||||
wlr_log(WLR_ERROR, "unable to create the XDG deco manager");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
wl_signal_add(&xdg_deco_mgr->events.new_toplevel_decoration,
|
||||
&server->xdg_toplevel_decoration);
|
||||
server->xdg_toplevel_decoration.notify = xdg_toplevel_decoration;
|
||||
&server.xdg_toplevel_decoration);
|
||||
server.xdg_toplevel_decoration.notify = xdg_toplevel_decoration;
|
||||
}
|
||||
|
||||
void
|
||||
xdg_server_decoration_finish(struct server *server)
|
||||
xdg_server_decoration_finish(void)
|
||||
{
|
||||
wl_list_remove(&server->xdg_toplevel_decoration.link);
|
||||
wl_list_remove(&server.xdg_toplevel_decoration.link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ log_handler(enum sfdo_log_level level, const char *fmt, va_list args, void *tag)
|
|||
}
|
||||
|
||||
void
|
||||
desktop_entry_init(struct server *server)
|
||||
desktop_entry_init(void)
|
||||
{
|
||||
struct sfdo *sfdo = znew(*sfdo);
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ desktop_entry_init(struct server *server)
|
|||
/* basedir_ctx is not referenced by other objects */
|
||||
sfdo_basedir_ctx_destroy(basedir_ctx);
|
||||
|
||||
server->sfdo = sfdo;
|
||||
server.sfdo = sfdo;
|
||||
return;
|
||||
|
||||
err_icon_theme:
|
||||
|
|
@ -155,9 +155,9 @@ err_basedir_ctx:
|
|||
}
|
||||
|
||||
void
|
||||
desktop_entry_finish(struct server *server)
|
||||
desktop_entry_finish(void)
|
||||
{
|
||||
struct sfdo *sfdo = server->sfdo;
|
||||
struct sfdo *sfdo = server.sfdo;
|
||||
if (!sfdo) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ desktop_entry_finish(struct server *server)
|
|||
sfdo_icon_ctx_destroy(sfdo->icon_ctx);
|
||||
sfdo_desktop_ctx_destroy(sfdo->desktop_ctx);
|
||||
free(sfdo);
|
||||
server->sfdo = NULL;
|
||||
server.sfdo = NULL;
|
||||
}
|
||||
|
||||
struct icon_ctx {
|
||||
|
|
@ -348,14 +348,14 @@ convert_img_type(enum sfdo_icon_file_format fmt)
|
|||
}
|
||||
|
||||
struct lab_img *
|
||||
desktop_entry_load_icon(struct server *server, const char *icon_name, int size, float scale)
|
||||
desktop_entry_load_icon(const char *icon_name, int size, float scale)
|
||||
{
|
||||
/* static analyzer isn't able to detect the NULL check in string_null_or_empty() */
|
||||
if (string_null_or_empty(icon_name) || !icon_name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sfdo *sfdo = server->sfdo;
|
||||
struct sfdo *sfdo = server.sfdo;
|
||||
if (!sfdo) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -387,14 +387,13 @@ desktop_entry_load_icon(struct server *server, const char *icon_name, int size,
|
|||
}
|
||||
|
||||
struct lab_img *
|
||||
desktop_entry_load_icon_from_app_id(struct server *server,
|
||||
const char *app_id, int size, float scale)
|
||||
desktop_entry_load_icon_from_app_id(const char *app_id, int size, float scale)
|
||||
{
|
||||
if (string_null_or_empty(app_id)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sfdo *sfdo = server->sfdo;
|
||||
struct sfdo *sfdo = server.sfdo;
|
||||
if (!sfdo) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -405,22 +404,22 @@ desktop_entry_load_icon_from_app_id(struct server *server,
|
|||
icon_name = sfdo_desktop_entry_get_icon(entry, NULL);
|
||||
}
|
||||
|
||||
struct lab_img *img = desktop_entry_load_icon(server, icon_name, size, scale);
|
||||
struct lab_img *img = desktop_entry_load_icon(icon_name, size, scale);
|
||||
if (!img) {
|
||||
/* Icon not defined in .desktop file or could not be loaded */
|
||||
img = desktop_entry_load_icon(server, app_id, size, scale);
|
||||
img = desktop_entry_load_icon(app_id, size, scale);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
const char *
|
||||
desktop_entry_name_lookup(struct server *server, const char *app_id)
|
||||
desktop_entry_name_lookup(const char *app_id)
|
||||
{
|
||||
if (string_null_or_empty(app_id)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sfdo *sfdo = server->sfdo;
|
||||
struct sfdo *sfdo = server.sfdo;
|
||||
if (!sfdo) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
128
src/desktop.c
128
src/desktop.c
|
|
@ -9,11 +9,13 @@
|
|||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include "common/scene-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "dnd.h"
|
||||
#include "labwc.h"
|
||||
#include "layers.h"
|
||||
#include "node.h"
|
||||
#include "output.h"
|
||||
#include "show-desktop.h"
|
||||
#include "ssd.h"
|
||||
#include "view.h"
|
||||
#include "workspaces.h"
|
||||
|
|
@ -23,7 +25,7 @@
|
|||
#endif
|
||||
|
||||
void
|
||||
desktop_arrange_all_views(struct server *server)
|
||||
desktop_arrange_all_views(void)
|
||||
{
|
||||
/*
|
||||
* Adjust window positions/sizes. Skip views with no size since
|
||||
|
|
@ -36,7 +38,7 @@ desktop_arrange_all_views(struct server *server)
|
|||
* views.
|
||||
*/
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
wl_list_for_each(view, &server.views, link) {
|
||||
if (!wlr_box_empty(&view->pending)) {
|
||||
view_adjust_for_layout_change(view);
|
||||
}
|
||||
|
|
@ -46,16 +48,16 @@ desktop_arrange_all_views(struct server *server)
|
|||
static void
|
||||
set_or_offer_focus(struct view *view)
|
||||
{
|
||||
struct seat *seat = &view->server->seat;
|
||||
struct seat *seat = &server.seat;
|
||||
switch (view_wants_focus(view)) {
|
||||
case VIEW_WANTS_FOCUS_ALWAYS:
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
if (view->surface != seat->wlr_seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
}
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_LIKELY:
|
||||
case VIEW_WANTS_FOCUS_UNLIKELY:
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
if (view->surface != seat->wlr_seat->keyboard_state.focused_surface) {
|
||||
view_offer_focus(view);
|
||||
}
|
||||
break;
|
||||
|
|
@ -64,8 +66,51 @@ set_or_offer_focus(struct view *view)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
handle_auto_raise_timer(void *data)
|
||||
{
|
||||
(void)data;
|
||||
struct view *view = server.pending_auto_raise_view;
|
||||
server.pending_auto_raise_view = NULL;
|
||||
|
||||
if (view && view->mapped) {
|
||||
view_move_to_front(view);
|
||||
}
|
||||
return 0; /* ignored per wl_event_loop docs */
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_view(struct view *view, bool raise)
|
||||
desktop_cancel_pending_auto_raise(void)
|
||||
{
|
||||
server.pending_auto_raise_view = NULL;
|
||||
if (server.pending_auto_raise_timer) {
|
||||
/* Disarm by setting to 0 ms */
|
||||
wl_event_source_timer_update(server.pending_auto_raise_timer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_delayed_auto_raise(struct view *view)
|
||||
{
|
||||
server.pending_auto_raise_view = view;
|
||||
if (!server.pending_auto_raise_timer) {
|
||||
server.pending_auto_raise_timer =
|
||||
wl_event_loop_add_timer(server.wl_event_loop,
|
||||
handle_auto_raise_timer, NULL);
|
||||
}
|
||||
wl_event_source_timer_update(server.pending_auto_raise_timer,
|
||||
rc.raise_on_focus_delay_ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* The raise_on_focus_delay is only meant to dampen z-order churn from
|
||||
* focus-follows-mouse cursor passes. Explicit focus changes (alt-tab,
|
||||
* Focus action, xdg/xwayland activation, etc.) should raise immediately.
|
||||
* allow_delay is therefore only set when the caller is the sloppy-focus
|
||||
* path in desktop_focus_view_or_surface().
|
||||
*/
|
||||
static void
|
||||
desktop_focus_view_internal(struct view *view, bool raise, bool allow_delay)
|
||||
{
|
||||
assert(view);
|
||||
/*
|
||||
|
|
@ -76,7 +121,7 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
return;
|
||||
}
|
||||
|
||||
if (view->server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
wlr_log(WLR_DEBUG, "not focusing window while window switching");
|
||||
return;
|
||||
}
|
||||
|
|
@ -102,8 +147,17 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
||||
}
|
||||
|
||||
/*
|
||||
* A new focus change supersedes any pending auto-raise from a
|
||||
* previous focus event, regardless of whether we raise now.
|
||||
*/
|
||||
desktop_cancel_pending_auto_raise();
|
||||
if (raise) {
|
||||
view_move_to_front(view);
|
||||
if (allow_delay && rc.raise_on_focus_delay_ms > 0) {
|
||||
schedule_delayed_auto_raise(view);
|
||||
} else {
|
||||
view_move_to_front(view);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -113,6 +167,14 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
*/
|
||||
struct view *dialog = view_get_modal_dialog(view);
|
||||
set_or_offer_focus(dialog ? dialog : view);
|
||||
|
||||
show_desktop_reset();
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_view(struct view *view, bool raise)
|
||||
{
|
||||
desktop_focus_view_internal(view, raise, /*allow_delay*/ false);
|
||||
}
|
||||
|
||||
/* TODO: focus layer-shell surfaces also? */
|
||||
|
|
@ -122,7 +184,7 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|||
{
|
||||
assert(view || surface);
|
||||
if (view) {
|
||||
desktop_focus_view(view, raise);
|
||||
desktop_focus_view_internal(view, raise, /*allow_delay*/ true);
|
||||
#if HAVE_XWAYLAND
|
||||
} else {
|
||||
struct wlr_xwayland_surface *xsurface =
|
||||
|
|
@ -135,10 +197,10 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
|
|||
}
|
||||
|
||||
static struct view *
|
||||
desktop_topmost_focusable_view(struct server *server)
|
||||
desktop_topmost_focusable_view(void)
|
||||
{
|
||||
struct view *view;
|
||||
for_each_view(view, &server->views,
|
||||
for_each_view(view, &server.views,
|
||||
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
if (!view->minimized) {
|
||||
return view;
|
||||
|
|
@ -148,9 +210,9 @@ desktop_topmost_focusable_view(struct server *server)
|
|||
}
|
||||
|
||||
void
|
||||
desktop_focus_topmost_view(struct server *server)
|
||||
desktop_focus_topmost_view(void)
|
||||
{
|
||||
struct view *view = desktop_topmost_focusable_view(server);
|
||||
struct view *view = desktop_topmost_focusable_view();
|
||||
if (view) {
|
||||
desktop_focus_view(view, /*raise*/ true);
|
||||
} else {
|
||||
|
|
@ -158,49 +220,47 @@ desktop_focus_topmost_view(struct server *server)
|
|||
* Defocus previous focused surface/view if no longer
|
||||
* focusable (e.g. unmapped or on a different workspace).
|
||||
*/
|
||||
seat_focus_surface(&server->seat, NULL);
|
||||
seat_focus_surface(&server.seat, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_output(struct output *output)
|
||||
{
|
||||
struct server *server = output->server;
|
||||
|
||||
if (!output_is_usable(output) || server->input_mode
|
||||
if (!output_is_usable(output) || server.input_mode
|
||||
!= LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
return;
|
||||
}
|
||||
struct view *view;
|
||||
for_each_view(view, &server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
for_each_view(view, &server.views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
if (view->outputs & output->id_bit) {
|
||||
desktop_focus_view(view, /*raise*/ false);
|
||||
wlr_cursor_warp(server->seat.cursor, NULL,
|
||||
wlr_cursor_warp(server.seat.cursor, NULL,
|
||||
view->current.x + view->current.width / 2,
|
||||
view->current.y + view->current.height / 2);
|
||||
cursor_update_focus(server);
|
||||
cursor_update_focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* No view found on desired output */
|
||||
struct wlr_box layout_box;
|
||||
wlr_output_layout_get_box(server->output_layout,
|
||||
wlr_output_layout_get_box(server.output_layout,
|
||||
output->wlr_output, &layout_box);
|
||||
wlr_cursor_warp(server->seat.cursor, NULL,
|
||||
wlr_cursor_warp(server.seat.cursor, NULL,
|
||||
layout_box.x + output->usable_area.x + output->usable_area.width / 2,
|
||||
layout_box.y + output->usable_area.y + output->usable_area.height / 2);
|
||||
cursor_update_focus(server);
|
||||
cursor_update_focus();
|
||||
}
|
||||
|
||||
void
|
||||
desktop_update_top_layer_visibility(struct server *server)
|
||||
desktop_update_top_layer_visibility(void)
|
||||
{
|
||||
struct view *view;
|
||||
struct output *output;
|
||||
uint32_t top = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
|
||||
|
||||
/* Enable all top layers */
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
if (!output_is_usable(output)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -212,7 +272,7 @@ desktop_update_top_layer_visibility(struct server *server)
|
|||
* any views above it
|
||||
*/
|
||||
uint64_t outputs_covered = 0;
|
||||
for_each_view(view, &server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
for_each_view(view, &server.views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
if (view->minimized) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -262,22 +322,22 @@ avoid_edge_rounding_issues(struct cursor_context *ctx)
|
|||
|
||||
/* TODO: make this less big and scary */
|
||||
struct cursor_context
|
||||
get_cursor_context(struct server *server)
|
||||
get_cursor_context(void)
|
||||
{
|
||||
struct cursor_context ret = {.type = LAB_NODE_NONE};
|
||||
struct wlr_cursor *cursor = server->seat.cursor;
|
||||
struct wlr_cursor *cursor = server.seat.cursor;
|
||||
|
||||
/* Prevent drag icons to be on top of the hitbox detection */
|
||||
if (server->seat.drag.active) {
|
||||
dnd_icons_show(&server->seat, false);
|
||||
if (server.seat.drag.active) {
|
||||
dnd_icons_show(&server.seat, false);
|
||||
}
|
||||
|
||||
struct wlr_scene_node *node =
|
||||
wlr_scene_node_at(&server->scene->tree.node,
|
||||
wlr_scene_node_at(&server.scene->tree.node,
|
||||
cursor->x, cursor->y, &ret.sx, &ret.sy);
|
||||
|
||||
if (server->seat.drag.active) {
|
||||
dnd_icons_show(&server->seat, true);
|
||||
if (server.seat.drag.active) {
|
||||
dnd_icons_show(&server.seat, true);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
|
|
@ -292,7 +352,7 @@ get_cursor_context(struct server *server)
|
|||
#if HAVE_XWAYLAND
|
||||
/* TODO: attach LAB_NODE_UNMANAGED node-descriptor to unmanaged surfaces */
|
||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||
if (node->parent == server->unmanaged_tree) {
|
||||
if (node->parent == server.unmanaged_tree) {
|
||||
ret.type = LAB_NODE_UNMANAGED;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
13
src/dnd.c
13
src/dnd.c
|
|
@ -4,6 +4,7 @@
|
|||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/scene-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "input/cursor.h"
|
||||
#include "labwc.h" /* for struct seat */
|
||||
|
|
@ -17,8 +18,8 @@ handle_drag_request(struct wl_listener *listener, void *data)
|
|||
struct wlr_seat_request_start_drag_event *event = data;
|
||||
|
||||
if (wlr_seat_validate_pointer_grab_serial(
|
||||
seat->seat, event->origin, event->serial)) {
|
||||
wlr_seat_start_pointer_drag(seat->seat, event->drag,
|
||||
seat->wlr_seat, event->origin, event->serial)) {
|
||||
wlr_seat_start_pointer_drag(seat->wlr_seat, event->drag,
|
||||
event->serial);
|
||||
} else {
|
||||
wlr_data_source_destroy(event->drag->source);
|
||||
|
|
@ -67,7 +68,7 @@ handle_drag_destroy(struct wl_listener *listener, void *data)
|
|||
return;
|
||||
}
|
||||
|
||||
struct cursor_context ctx = get_cursor_context(seat->server);
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
if (!ctx.surface) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -83,16 +84,16 @@ handle_drag_destroy(struct wl_listener *listener, void *data)
|
|||
void
|
||||
dnd_init(struct seat *seat)
|
||||
{
|
||||
seat->drag.icons = wlr_scene_tree_create(&seat->server->scene->tree);
|
||||
seat->drag.icons = lab_wlr_scene_tree_create(&server.scene->tree);
|
||||
wlr_scene_node_set_enabled(&seat->drag.icons->node, false);
|
||||
|
||||
seat->drag.events.request.notify = handle_drag_request;
|
||||
seat->drag.events.start.notify = handle_drag_start;
|
||||
seat->drag.events.destroy.notify = handle_drag_destroy;
|
||||
|
||||
wl_signal_add(&seat->seat->events.request_start_drag,
|
||||
wl_signal_add(&seat->wlr_seat->events.request_start_drag,
|
||||
&seat->drag.events.request);
|
||||
wl_signal_add(&seat->seat->events.start_drag, &seat->drag.events.start);
|
||||
wl_signal_add(&seat->wlr_seat->events.start_drag, &seat->drag.events.start);
|
||||
/*
|
||||
* destroy.notify is listened to in handle_drag_start() and reset in
|
||||
* handle_drag_destroy()
|
||||
|
|
|
|||
12
src/edges.c
12
src/edges.c
|
|
@ -328,7 +328,7 @@ subtract_node_tree(struct wlr_scene_tree *tree, pixman_region32_t *available,
|
|||
}
|
||||
|
||||
void
|
||||
edges_calculate_visibility(struct server *server, struct view *ignored_view)
|
||||
edges_calculate_visibility(struct view *ignored_view)
|
||||
{
|
||||
/*
|
||||
* The region stores the available output layout space
|
||||
|
|
@ -353,17 +353,17 @@ edges_calculate_visibility(struct server *server, struct view *ignored_view)
|
|||
*/
|
||||
struct output *output;
|
||||
struct wlr_box layout_box;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
if (!output_is_usable(output)) {
|
||||
continue;
|
||||
}
|
||||
wlr_output_layout_get_box(server->output_layout,
|
||||
wlr_output_layout_get_box(server.output_layout,
|
||||
output->wlr_output, &layout_box);
|
||||
pixman_region32_union_rect(®ion, ®ion,
|
||||
layout_box.x, layout_box.y, layout_box.width, layout_box.height);
|
||||
}
|
||||
|
||||
subtract_node_tree(&server->scene->tree, ®ion, ignored_view);
|
||||
subtract_node_tree(&server.scene->tree, ®ion, ignored_view);
|
||||
|
||||
pixman_region32_fini(®ion);
|
||||
}
|
||||
|
|
@ -389,7 +389,7 @@ edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
|||
edges_for_target_geometry(&target_edges, view, target);
|
||||
|
||||
struct view *v;
|
||||
for_each_view(v, &view->server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
for_each_view(v, &server.views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
if (v == view || v->minimized || !output_is_usable(v->output)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -447,7 +447,7 @@ edges_find_outputs(struct border *nearest_edges, struct view *view,
|
|||
edges_for_target_geometry(&target_edges, view, target);
|
||||
|
||||
struct output *o;
|
||||
wl_list_for_each(o, &view->server->outputs, link) {
|
||||
wl_list_for_each(o, &server.outputs, link) {
|
||||
if (!output_is_usable(o)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void
|
|||
ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
||||
struct view *view)
|
||||
{
|
||||
assert(view->server->foreign_toplevel_list);
|
||||
assert(server.foreign_toplevel_list);
|
||||
ext_toplevel->view = view;
|
||||
|
||||
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
||||
|
|
@ -67,7 +67,7 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
|||
.app_id = view->app_id,
|
||||
};
|
||||
ext_toplevel->handle = wlr_ext_foreign_toplevel_handle_v1_create(
|
||||
view->server->foreign_toplevel_list, &state);
|
||||
server.foreign_toplevel_list, &state);
|
||||
|
||||
if (!ext_toplevel->handle) {
|
||||
wlr_log(WLR_ERROR, "cannot create ext toplevel handle for (%s)",
|
||||
|
|
@ -75,6 +75,9 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
|||
return;
|
||||
}
|
||||
|
||||
/* In support for ext-toplevel-capture */
|
||||
ext_toplevel->handle->data = view;
|
||||
|
||||
/* Client side requests */
|
||||
ext_toplevel->on.handle_destroy.notify = handle_handle_destroy;
|
||||
wl_signal_add(&ext_toplevel->handle->events.destroy, &ext_toplevel->on.handle_destroy);
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ handle_new_outputs(struct wl_listener *listener, void *data)
|
|||
* wlr_foreign_toplevel handle the rest.
|
||||
*/
|
||||
struct output *output;
|
||||
wl_list_for_each(output, &wlr_toplevel->view->server->outputs, link) {
|
||||
wl_list_for_each(output, &server.outputs, link) {
|
||||
if (view_on_output(wlr_toplevel->view, output)) {
|
||||
wlr_foreign_toplevel_handle_v1_output_enter(
|
||||
wlr_toplevel->handle, output->wlr_output);
|
||||
|
|
@ -184,11 +184,11 @@ void
|
|||
wlr_foreign_toplevel_init(struct wlr_foreign_toplevel *wlr_toplevel,
|
||||
struct view *view)
|
||||
{
|
||||
assert(view->server->foreign_toplevel_manager);
|
||||
assert(server.foreign_toplevel_manager);
|
||||
wlr_toplevel->view = view;
|
||||
|
||||
wlr_toplevel->handle = wlr_foreign_toplevel_handle_v1_create(
|
||||
view->server->foreign_toplevel_manager);
|
||||
server.foreign_toplevel_manager);
|
||||
if (!wlr_toplevel->handle) {
|
||||
wlr_log(WLR_ERROR, "cannot create wlr foreign toplevel handle for (%s)",
|
||||
view->title);
|
||||
|
|
@ -203,7 +203,7 @@ wlr_foreign_toplevel_init(struct wlr_foreign_toplevel *wlr_toplevel,
|
|||
handle_minimized(&wlr_toplevel->on_view.minimized, NULL);
|
||||
handle_fullscreened(&wlr_toplevel->on_view.fullscreened, NULL);
|
||||
handle_activated(&wlr_toplevel->on_view.activated,
|
||||
&(bool){view == view->server->active_view});
|
||||
&(bool){view == server.active_view});
|
||||
|
||||
/* Client side requests */
|
||||
CONNECT_SIGNAL(wlr_toplevel->handle, &wlr_toplevel->on, request_maximize);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ idle_manager_create(struct wl_display *display)
|
|||
}
|
||||
|
||||
void
|
||||
idle_manager_notify_activity(struct wlr_seat *seat)
|
||||
idle_manager_notify_activity(struct wlr_seat *wlr_seat)
|
||||
{
|
||||
/*
|
||||
* The display destroy event might have been triggered
|
||||
|
|
@ -96,5 +96,5 @@ idle_manager_notify_activity(struct wlr_seat *seat)
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_idle_notifier_v1_notify_activity(manager->ext, seat);
|
||||
wlr_idle_notifier_v1_notify_activity(manager->ext, wlr_seat);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ out:
|
|||
|
||||
/*
|
||||
* Openbox built-in icons are not bigger than 8x8, so have only written this
|
||||
* function to cope wit that max size
|
||||
* function to cope with that max size
|
||||
*/
|
||||
#define LABWC_BUILTIN_ICON_MAX_SIZE (8)
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ xpm_load_to_surface(struct file_handle *handle)
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (int n = 0, xcnt = 0; n < wbytes; n += cpp, xcnt++) {
|
||||
for (int n = 0; n < wbytes; n += cpp) {
|
||||
g_strlcpy(pixel_str, &buffer[n], cpp + 1);
|
||||
|
||||
struct xpm_color *color =
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "input/cursor.h"
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <wlr/backend/libinput.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
|
|
@ -38,6 +38,10 @@
|
|||
#include "view.h"
|
||||
#include "xwayland.h"
|
||||
|
||||
#if WLR_HAS_LIBINPUT_BACKEND
|
||||
#include <wlr/backend/libinput.h>
|
||||
#endif
|
||||
|
||||
#define LAB_CURSOR_SHAPE_V1_VERSION 1
|
||||
|
||||
struct constraint {
|
||||
|
|
@ -148,7 +152,7 @@ handle_request_set_cursor(struct wl_listener *listener, void *data)
|
|||
{
|
||||
struct seat *seat = wl_container_of(listener, seat, request_set_cursor);
|
||||
|
||||
if (seat->server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
/* Prevent setting a cursor image when moving or resizing */
|
||||
return;
|
||||
}
|
||||
|
|
@ -180,7 +184,7 @@ handle_request_set_cursor(struct wl_listener *listener, void *data)
|
|||
*/
|
||||
struct wlr_seat_pointer_request_set_cursor_event *event = data;
|
||||
struct wlr_seat_client *focused_client =
|
||||
seat->seat->pointer_state.focused_client;
|
||||
seat->wlr_seat->pointer_state.focused_client;
|
||||
|
||||
/*
|
||||
* This can be sent by any client, so we check to make sure this one
|
||||
|
|
@ -205,10 +209,10 @@ handle_request_set_shape(struct wl_listener *listener, void *data)
|
|||
struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
|
||||
const char *shape_name = wlr_cursor_shape_v1_name(event->shape);
|
||||
struct seat *seat = wl_container_of(listener, seat, request_set_shape);
|
||||
struct wlr_seat_client *focused_client = seat->seat->pointer_state.focused_client;
|
||||
struct wlr_seat_client *focused_client = seat->wlr_seat->pointer_state.focused_client;
|
||||
|
||||
/* Prevent setting a cursor image when moving or resizing */
|
||||
if (seat->server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +254,7 @@ handle_request_set_selection(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(
|
||||
listener, seat, request_set_selection);
|
||||
struct wlr_seat_request_set_selection_event *event = data;
|
||||
wlr_seat_set_selection(seat->seat, event->source,
|
||||
wlr_seat_set_selection(seat->wlr_seat, event->source,
|
||||
event->serial);
|
||||
}
|
||||
|
||||
|
|
@ -260,17 +264,17 @@ handle_request_set_primary_selection(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(
|
||||
listener, seat, request_set_primary_selection);
|
||||
struct wlr_seat_request_set_primary_selection_event *event = data;
|
||||
wlr_seat_set_primary_selection(seat->seat, event->source,
|
||||
wlr_seat_set_primary_selection(seat->wlr_seat, event->source,
|
||||
event->serial);
|
||||
}
|
||||
|
||||
static void
|
||||
process_cursor_move(struct server *server, uint32_t time)
|
||||
process_cursor_move(uint32_t time)
|
||||
{
|
||||
struct view *view = server->grabbed_view;
|
||||
struct view *view = server.grabbed_view;
|
||||
|
||||
int x = server->grab_box.x + (server->seat.cursor->x - server->grab_x);
|
||||
int y = server->grab_box.y + (server->seat.cursor->y - server->grab_y);
|
||||
int x = server.grab_box.x + (server.seat.cursor->x - server.grab_x);
|
||||
int y = server.grab_box.y + (server.seat.cursor->y - server.grab_y);
|
||||
|
||||
/* Apply resistance for maximized/tiled view */
|
||||
bool needs_untile = resistance_unsnap_apply(view, &x, &y);
|
||||
|
|
@ -286,7 +290,7 @@ process_cursor_move(struct server *server, uint32_t time)
|
|||
.width = view->natural_geometry.width,
|
||||
.height = view->natural_geometry.height,
|
||||
};
|
||||
interactive_anchor_to_cursor(server, &new_geo);
|
||||
interactive_anchor_to_cursor(&new_geo);
|
||||
/* Shaded clients will not process resize events until unshaded */
|
||||
view_set_shade(view, false);
|
||||
view_set_maximized(view, VIEW_AXIS_NONE);
|
||||
|
|
@ -300,18 +304,18 @@ process_cursor_move(struct server *server, uint32_t time)
|
|||
resistance_move_apply(view, &x, &y);
|
||||
|
||||
view_move(view, x, y);
|
||||
overlay_update(&server->seat);
|
||||
overlay_update(&server.seat);
|
||||
}
|
||||
|
||||
static void
|
||||
process_cursor_resize(struct server *server, uint32_t time)
|
||||
process_cursor_resize(uint32_t time)
|
||||
{
|
||||
/* Rate-limit resize events respecting monitor refresh rate */
|
||||
static uint32_t last_resize_time = 0;
|
||||
static struct view *last_resize_view = NULL;
|
||||
|
||||
assert(server->grabbed_view);
|
||||
if (server->grabbed_view == last_resize_view) {
|
||||
assert(server.grabbed_view);
|
||||
if (server.grabbed_view == last_resize_view) {
|
||||
int32_t refresh = 0;
|
||||
if (output_is_usable(last_resize_view->output)) {
|
||||
refresh = last_resize_view->output->wlr_output->refresh;
|
||||
|
|
@ -327,43 +331,43 @@ process_cursor_resize(struct server *server, uint32_t time)
|
|||
}
|
||||
|
||||
last_resize_time = time;
|
||||
last_resize_view = server->grabbed_view;
|
||||
last_resize_view = server.grabbed_view;
|
||||
|
||||
double dx = server->seat.cursor->x - server->grab_x;
|
||||
double dy = server->seat.cursor->y - server->grab_y;
|
||||
double dx = server.seat.cursor->x - server.grab_x;
|
||||
double dy = server.seat.cursor->y - server.grab_y;
|
||||
|
||||
struct view *view = server->grabbed_view;
|
||||
struct view *view = server.grabbed_view;
|
||||
struct wlr_box new_view_geo = view->current;
|
||||
|
||||
if (server->resize_edges & LAB_EDGE_TOP) {
|
||||
if (server.resize_edges & LAB_EDGE_TOP) {
|
||||
/* Shift y to anchor bottom edge when resizing top */
|
||||
new_view_geo.y = server->grab_box.y + dy;
|
||||
new_view_geo.height = server->grab_box.height - dy;
|
||||
} else if (server->resize_edges & LAB_EDGE_BOTTOM) {
|
||||
new_view_geo.height = server->grab_box.height + dy;
|
||||
new_view_geo.y = server.grab_box.y + dy;
|
||||
new_view_geo.height = server.grab_box.height - dy;
|
||||
} else if (server.resize_edges & LAB_EDGE_BOTTOM) {
|
||||
new_view_geo.height = server.grab_box.height + dy;
|
||||
}
|
||||
|
||||
if (server->resize_edges & LAB_EDGE_LEFT) {
|
||||
if (server.resize_edges & LAB_EDGE_LEFT) {
|
||||
/* Shift x to anchor right edge when resizing left */
|
||||
new_view_geo.x = server->grab_box.x + dx;
|
||||
new_view_geo.width = server->grab_box.width - dx;
|
||||
} else if (server->resize_edges & LAB_EDGE_RIGHT) {
|
||||
new_view_geo.width = server->grab_box.width + dx;
|
||||
new_view_geo.x = server.grab_box.x + dx;
|
||||
new_view_geo.width = server.grab_box.width - dx;
|
||||
} else if (server.resize_edges & LAB_EDGE_RIGHT) {
|
||||
new_view_geo.width = server.grab_box.width + dx;
|
||||
}
|
||||
|
||||
resistance_resize_apply(view, &new_view_geo);
|
||||
view_adjust_size(view, &new_view_geo.width, &new_view_geo.height);
|
||||
|
||||
if (server->resize_edges & LAB_EDGE_TOP) {
|
||||
if (server.resize_edges & LAB_EDGE_TOP) {
|
||||
/* After size adjustments, make sure to anchor bottom edge */
|
||||
new_view_geo.y = server->grab_box.y +
|
||||
server->grab_box.height - new_view_geo.height;
|
||||
new_view_geo.y = server.grab_box.y +
|
||||
server.grab_box.height - new_view_geo.height;
|
||||
}
|
||||
|
||||
if (server->resize_edges & LAB_EDGE_LEFT) {
|
||||
if (server.resize_edges & LAB_EDGE_LEFT) {
|
||||
/* After size adjustments, make sure to anchor bottom right */
|
||||
new_view_geo.x = server->grab_box.x +
|
||||
server->grab_box.width - new_view_geo.width;
|
||||
new_view_geo.x = server.grab_box.x +
|
||||
server.grab_box.width - new_view_geo.width;
|
||||
}
|
||||
|
||||
if (rc.resize_draw_contents) {
|
||||
|
|
@ -418,11 +422,11 @@ cursor_update_image(struct seat *seat)
|
|||
* a new output instance), we have to force a re-enter of
|
||||
* the surface so the client sets its own cursor again.
|
||||
*/
|
||||
if (seat->seat->pointer_state.focused_surface) {
|
||||
if (seat->wlr_seat->pointer_state.focused_surface) {
|
||||
seat->server_cursor = LAB_CURSOR_DEFAULT;
|
||||
wlr_cursor_set_xcursor(seat->cursor, seat->xcursor_manager, "");
|
||||
wlr_seat_pointer_clear_focus(seat->seat);
|
||||
cursor_update_focus(seat->server);
|
||||
wlr_seat_pointer_clear_focus(seat->wlr_seat);
|
||||
cursor_update_focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -515,7 +519,7 @@ update_pressed_surface(struct seat *seat, const struct cursor_context *ctx)
|
|||
* context menus (in contrast) do not use an XDG popup grab and
|
||||
* do not work properly if we send leave/enter events.
|
||||
*/
|
||||
if (!wlr_seat_pointer_has_grab(seat->seat)) {
|
||||
if (!wlr_seat_pointer_has_grab(seat->wlr_seat)) {
|
||||
return false;
|
||||
}
|
||||
if (seat->pressed.ctx.surface && ctx->surface != seat->pressed.ctx.surface) {
|
||||
|
|
@ -533,15 +537,15 @@ update_pressed_surface(struct seat *seat, const struct cursor_context *ctx)
|
|||
* and process_cursor_axis()
|
||||
*/
|
||||
static void
|
||||
cursor_update_common(struct server *server, const struct cursor_context *ctx,
|
||||
cursor_update_common(const struct cursor_context *ctx,
|
||||
struct cursor_context *notified_ctx)
|
||||
{
|
||||
struct seat *seat = &server->seat;
|
||||
struct wlr_seat *wlr_seat = seat->seat;
|
||||
struct seat *seat = &server.seat;
|
||||
struct wlr_seat *wlr_seat = seat->wlr_seat;
|
||||
|
||||
ssd_update_hovered_button(server, ctx->node);
|
||||
ssd_update_hovered_button(ctx->node);
|
||||
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
/*
|
||||
* Prevent updating focus/cursor image during
|
||||
* interactive move/resize, window switcher and
|
||||
|
|
@ -565,8 +569,8 @@ cursor_update_common(struct server *server, const struct cursor_context *ctx,
|
|||
int lx, ly;
|
||||
wlr_scene_node_coords(seat->pressed.ctx.node, &lx, &ly);
|
||||
*notified_ctx = seat->pressed.ctx;
|
||||
notified_ctx->sx = server->seat.cursor->x - lx;
|
||||
notified_ctx->sy = server->seat.cursor->y - ly;
|
||||
notified_ctx->sx = server.seat.cursor->x - lx;
|
||||
notified_ctx->sy = server.seat.cursor->y - ly;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -604,7 +608,7 @@ cursor_update_common(struct server *server, const struct cursor_context *ctx,
|
|||
}
|
||||
|
||||
enum lab_edge
|
||||
cursor_get_resize_edges(struct wlr_cursor *cursor, struct cursor_context *ctx)
|
||||
cursor_get_resize_edges(struct wlr_cursor *cursor, const struct cursor_context *ctx)
|
||||
{
|
||||
enum lab_edge resize_edges = node_type_to_edges(ctx->type);
|
||||
if (ctx->view && !resize_edges) {
|
||||
|
|
@ -620,24 +624,24 @@ cursor_get_resize_edges(struct wlr_cursor *cursor, struct cursor_context *ctx)
|
|||
}
|
||||
|
||||
bool
|
||||
cursor_process_motion(struct server *server, uint32_t time, double *sx, double *sy)
|
||||
cursor_process_motion(uint32_t time, double *sx, double *sy)
|
||||
{
|
||||
/* If the mode is non-passthrough, delegate to those functions. */
|
||||
if (server->input_mode == LAB_INPUT_STATE_MOVE) {
|
||||
process_cursor_move(server, time);
|
||||
if (server.input_mode == LAB_INPUT_STATE_MOVE) {
|
||||
process_cursor_move(time);
|
||||
return false;
|
||||
} else if (server->input_mode == LAB_INPUT_STATE_RESIZE) {
|
||||
process_cursor_resize(server, time);
|
||||
} else if (server.input_mode == LAB_INPUT_STATE_RESIZE) {
|
||||
process_cursor_resize(time);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Otherwise, find view under the pointer and send the event along */
|
||||
struct cursor_context ctx = get_cursor_context(server);
|
||||
struct seat *seat = &server->seat;
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
struct seat *seat = &server.seat;
|
||||
|
||||
if (ctx.type == LAB_NODE_MENUITEM) {
|
||||
menu_process_cursor_motion(ctx.node);
|
||||
cursor_set(&server->seat, LAB_CURSOR_DEFAULT);
|
||||
cursor_set(&server.seat, LAB_CURSOR_DEFAULT);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -659,7 +663,7 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
|
|||
* moving/resizing the wrong view
|
||||
*/
|
||||
mousebind->pressed_in_context = false;
|
||||
actions_run(seat->pressed.ctx.view, server,
|
||||
actions_run(seat->pressed.ctx.view,
|
||||
&mousebind->actions, &seat->pressed.ctx);
|
||||
}
|
||||
}
|
||||
|
|
@ -670,7 +674,7 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
|
|||
* and the pressed view is set while out-of-surface dragging.
|
||||
*/
|
||||
struct cursor_context notified_ctx = {0};
|
||||
cursor_update_common(server, &ctx, ¬ified_ctx);
|
||||
cursor_update_common(&ctx, ¬ified_ctx);
|
||||
|
||||
if (rc.focus_follow_mouse) {
|
||||
/*
|
||||
|
|
@ -701,10 +705,10 @@ cursor_process_motion(struct server *server, uint32_t time, double *sx, double *
|
|||
}
|
||||
|
||||
static void
|
||||
_cursor_update_focus(struct server *server)
|
||||
_cursor_update_focus(void)
|
||||
{
|
||||
/* Focus surface under cursor if it isn't already focused */
|
||||
struct cursor_context ctx = get_cursor_context(server);
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
|
||||
if ((ctx.view || ctx.surface) && rc.focus_follow_mouse
|
||||
&& !rc.focus_follow_mouse_requires_movement) {
|
||||
|
|
@ -712,21 +716,21 @@ _cursor_update_focus(struct server *server)
|
|||
* Always focus the surface below the cursor when
|
||||
* followMouse=yes and followMouseRequiresMovement=no.
|
||||
*/
|
||||
desktop_focus_view_or_surface(&server->seat, ctx.view,
|
||||
desktop_focus_view_or_surface(&server.seat, ctx.view,
|
||||
ctx.surface, rc.raise_on_focus);
|
||||
}
|
||||
|
||||
cursor_update_common(server, &ctx, NULL);
|
||||
cursor_update_common(&ctx, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
cursor_update_focus(struct server *server)
|
||||
cursor_update_focus(void)
|
||||
{
|
||||
/* Prevent recursion via view_move_to_front() */
|
||||
static bool updating_focus = false;
|
||||
if (!updating_focus) {
|
||||
updating_focus = true;
|
||||
_cursor_update_focus(server);
|
||||
_cursor_update_focus();
|
||||
updating_focus = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -735,7 +739,7 @@ static void
|
|||
warp_cursor_to_constraint_hint(struct seat *seat,
|
||||
struct wlr_pointer_constraint_v1 *constraint)
|
||||
{
|
||||
if (!seat->server->active_view) {
|
||||
if (!server.active_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -744,11 +748,11 @@ warp_cursor_to_constraint_hint(struct seat *seat,
|
|||
double sx = constraint->current.cursor_hint.x;
|
||||
double sy = constraint->current.cursor_hint.y;
|
||||
wlr_cursor_warp(seat->cursor, NULL,
|
||||
seat->server->active_view->current.x + sx,
|
||||
seat->server->active_view->current.y + sy);
|
||||
server.active_view->current.x + sx,
|
||||
server.active_view->current.y + sy);
|
||||
|
||||
/* Make sure we are not sending unnecessary surface movements */
|
||||
wlr_seat_pointer_warp(seat->seat, sx, sy);
|
||||
wlr_seat_pointer_warp(seat->wlr_seat, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -788,26 +792,24 @@ void
|
|||
create_constraint(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct wlr_pointer_constraint_v1 *wlr_constraint = data;
|
||||
struct server *server = wl_container_of(listener, server,
|
||||
new_constraint);
|
||||
struct constraint *constraint = znew(*constraint);
|
||||
|
||||
constraint->constraint = wlr_constraint;
|
||||
constraint->seat = &server->seat;
|
||||
constraint->seat = &server.seat;
|
||||
constraint->destroy.notify = handle_constraint_destroy;
|
||||
wl_signal_add(&wlr_constraint->events.destroy, &constraint->destroy);
|
||||
|
||||
struct view *view = server->active_view;
|
||||
struct view *view = server.active_view;
|
||||
if (view && view->surface == wlr_constraint->surface) {
|
||||
constrain_cursor(server, wlr_constraint);
|
||||
constrain_cursor(wlr_constraint);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
|
||||
constrain_cursor(struct wlr_pointer_constraint_v1
|
||||
*constraint)
|
||||
{
|
||||
struct seat *seat = &server->seat;
|
||||
struct seat *seat = &server.seat;
|
||||
if (seat->current_constraint == constraint) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -837,7 +839,7 @@ constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
|
|||
static void
|
||||
apply_constraint(struct seat *seat, struct wlr_pointer *pointer, double *x, double *y)
|
||||
{
|
||||
if (!seat->server->active_view) {
|
||||
if (!server.active_view) {
|
||||
return;
|
||||
}
|
||||
if (!seat->current_constraint
|
||||
|
|
@ -850,8 +852,8 @@ apply_constraint(struct seat *seat, struct wlr_pointer *pointer, double *x, doub
|
|||
double sx = seat->cursor->x;
|
||||
double sy = seat->cursor->y;
|
||||
|
||||
sx -= seat->server->active_view->current.x;
|
||||
sy -= seat->server->active_view->current.y;
|
||||
sx -= server.active_view->current.x;
|
||||
sy -= server.active_view->current.y;
|
||||
|
||||
double sx_confined, sy_confined;
|
||||
if (!wlr_region_confine(&seat->current_constraint->region, sx, sy,
|
||||
|
|
@ -870,7 +872,7 @@ cursor_locked(struct seat *seat, struct wlr_pointer *pointer)
|
|||
&& pointer->base.type == WLR_INPUT_DEVICE_POINTER
|
||||
&& seat->current_constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED
|
||||
&& seat->current_constraint->surface
|
||||
== seat->seat->pointer_state.focused_surface;
|
||||
== seat->wlr_seat->pointer_state.focused_surface;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -892,14 +894,15 @@ preprocess_cursor_motion(struct seat *seat, struct wlr_pointer *pointer,
|
|||
*/
|
||||
wlr_cursor_move(seat->cursor, &pointer->base, dx, dy);
|
||||
double sx, sy;
|
||||
bool notify = cursor_process_motion(seat->server, time_msec, &sx, &sy);
|
||||
bool notify = cursor_process_motion(time_msec, &sx, &sy);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy);
|
||||
wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
|
||||
}
|
||||
}
|
||||
|
||||
static double get_natural_scroll_factor(struct wlr_input_device *wlr_input_device)
|
||||
{
|
||||
#if WLR_HAS_LIBINPUT_BACKEND
|
||||
if (wlr_input_device_is_libinput(wlr_input_device)) {
|
||||
struct libinput_device *libinput_device =
|
||||
wlr_libinput_get_device_handle(wlr_input_device);
|
||||
|
|
@ -907,7 +910,7 @@ static double get_natural_scroll_factor(struct wlr_input_device *wlr_input_devic
|
|||
return -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
|
@ -919,9 +922,8 @@ handle_motion(struct wl_listener *listener, void *data)
|
|||
* _relative_ pointer motion event (i.e. a delta)
|
||||
*/
|
||||
struct seat *seat = wl_container_of(listener, seat, on_cursor.motion);
|
||||
struct server *server = seat->server;
|
||||
struct wlr_pointer_motion_event *event = data;
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
if (seat->cursor_scroll_wheel_emulation) {
|
||||
|
|
@ -952,8 +954,8 @@ handle_motion(struct wl_listener *listener, void *data)
|
|||
WL_POINTER_AXIS_SOURCE_CONTINUOUS, event->time_msec);
|
||||
} else {
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(
|
||||
server->relative_pointer_manager,
|
||||
seat->seat, (uint64_t)event->time_msec * 1000,
|
||||
server.relative_pointer_manager,
|
||||
seat->wlr_seat, (uint64_t)event->time_msec * 1000,
|
||||
event->delta_x, event->delta_y, event->unaccel_dx,
|
||||
event->unaccel_dy);
|
||||
|
||||
|
|
@ -975,7 +977,7 @@ handle_motion_absolute(struct wl_listener *listener, void *data)
|
|||
*/
|
||||
struct seat *seat = wl_container_of(listener, seat, on_cursor.motion_absolute);
|
||||
struct wlr_pointer_motion_absolute_event *event = data;
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
double lx, ly;
|
||||
|
|
@ -990,15 +992,14 @@ handle_motion_absolute(struct wl_listener *listener, void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
process_release_mousebinding(struct server *server,
|
||||
struct cursor_context *ctx, uint32_t button)
|
||||
process_release_mousebinding(struct cursor_context *ctx, uint32_t button)
|
||||
{
|
||||
if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct mousebind *mousebind;
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server.seat);
|
||||
|
||||
wl_list_for_each(mousebind, &rc.mousebinds, link) {
|
||||
if (ctx->type == LAB_NODE_CLIENT
|
||||
|
|
@ -1019,7 +1020,7 @@ process_release_mousebinding(struct server *server,
|
|||
default:
|
||||
continue;
|
||||
}
|
||||
actions_run(ctx->view, server, &mousebind->actions, ctx);
|
||||
actions_run(ctx->view, &mousebind->actions, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1059,17 +1060,17 @@ is_double_click(long double_click_speed, uint32_t button,
|
|||
}
|
||||
|
||||
static bool
|
||||
process_press_mousebinding(struct server *server, struct cursor_context *ctx,
|
||||
process_press_mousebinding(struct cursor_context *ctx,
|
||||
uint32_t button)
|
||||
{
|
||||
if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct mousebind *mousebind;
|
||||
bool double_click = is_double_click(rc.doubleclick_time, button, ctx);
|
||||
bool consumed_by_frame_context = false;
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server.seat);
|
||||
|
||||
wl_list_for_each(mousebind, &rc.mousebinds, link) {
|
||||
if (ctx->type == LAB_NODE_CLIENT
|
||||
|
|
@ -1108,7 +1109,7 @@ process_press_mousebinding(struct server *server, struct cursor_context *ctx,
|
|||
}
|
||||
consumed_by_frame_context |= mousebind->context == LAB_NODE_FRAME;
|
||||
consumed_by_frame_context |= mousebind->context == LAB_NODE_ALL;
|
||||
actions_run(ctx->view, server, &mousebind->actions, ctx);
|
||||
actions_run(ctx->view, &mousebind->actions, ctx);
|
||||
}
|
||||
}
|
||||
return consumed_by_frame_context;
|
||||
|
|
@ -1138,8 +1139,7 @@ static uint32_t press_msec;
|
|||
bool
|
||||
cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_msec)
|
||||
{
|
||||
struct server *server = seat->server;
|
||||
struct cursor_context ctx = get_cursor_context(server);
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
|
||||
/* Used on next button release to check if it can close menu or select menu item */
|
||||
press_msec = time_msec;
|
||||
|
|
@ -1150,7 +1150,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
|||
interactive_set_grab_context(&ctx);
|
||||
}
|
||||
|
||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_MENU) {
|
||||
/*
|
||||
* If menu was already opened on press, set a very small value
|
||||
* so subsequent release always closes menu or selects menu item.
|
||||
|
|
@ -1171,7 +1171,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
|||
if (layer && layer->current.keyboard_interactive) {
|
||||
layer_try_set_focus(seat, layer);
|
||||
}
|
||||
#ifdef HAVE_XWAYLAND
|
||||
#if HAVE_XWAYLAND
|
||||
} else if (ctx.type == LAB_NODE_UNMANAGED) {
|
||||
desktop_focus_view_or_surface(seat, NULL, ctx.surface,
|
||||
/*raise*/ false);
|
||||
|
|
@ -1179,7 +1179,7 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
|||
}
|
||||
|
||||
if (ctx.type != LAB_NODE_CLIENT && ctx.type != LAB_NODE_LAYER_SURFACE
|
||||
&& wlr_seat_pointer_has_grab(seat->seat)) {
|
||||
&& wlr_seat_pointer_has_grab(seat->wlr_seat)) {
|
||||
/*
|
||||
* If we have an active popup grab (an open popup) we want to
|
||||
* cancel that grab whenever the user presses on anything that
|
||||
|
|
@ -1188,14 +1188,14 @@ cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_ms
|
|||
*
|
||||
* Note: This does not work for XWayland clients
|
||||
*/
|
||||
wlr_seat_pointer_end_grab(seat->seat);
|
||||
wlr_seat_pointer_end_grab(seat->wlr_seat);
|
||||
lab_set_add(&seat->bound_buttons, button);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Bindings to the Frame context swallow mouse events if activated */
|
||||
bool consumed_by_frame_context =
|
||||
process_press_mousebinding(server, &ctx, button);
|
||||
process_press_mousebinding(&ctx, button);
|
||||
|
||||
if (ctx.surface && !consumed_by_frame_context) {
|
||||
/* Notify client with pointer focus of button press */
|
||||
|
|
@ -1210,8 +1210,7 @@ bool
|
|||
cursor_process_button_release(struct seat *seat, uint32_t button,
|
||||
uint32_t time_msec)
|
||||
{
|
||||
struct server *server = seat->server;
|
||||
struct cursor_context ctx = get_cursor_context(server);
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
struct wlr_surface *pressed_surface = seat->pressed.ctx.surface;
|
||||
|
||||
/* Always notify button release event when it's not bound */
|
||||
|
|
@ -1219,26 +1218,26 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
|
|||
|
||||
cursor_context_save(&seat->pressed, NULL);
|
||||
|
||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_MENU) {
|
||||
/* TODO: take into account overflow of time_msec */
|
||||
if (time_msec - press_msec > rc.menu_ignore_button_release_period) {
|
||||
if (ctx.type == LAB_NODE_MENUITEM) {
|
||||
menu_call_selected_actions(server);
|
||||
menu_call_selected_actions();
|
||||
} else {
|
||||
menu_close_root(server);
|
||||
cursor_update_focus(server);
|
||||
menu_close_root();
|
||||
cursor_update_focus();
|
||||
}
|
||||
}
|
||||
return notify;
|
||||
}
|
||||
if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (ctx.type == LAB_NODE_CYCLE_OSD_ITEM) {
|
||||
cycle_on_cursor_release(server, ctx.node);
|
||||
cycle_on_cursor_release(ctx.node);
|
||||
}
|
||||
return notify;
|
||||
}
|
||||
|
||||
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
if (server.input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
|
||||
return notify;
|
||||
}
|
||||
|
||||
|
|
@ -1250,7 +1249,7 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
|
|||
return notify;
|
||||
}
|
||||
|
||||
process_release_mousebinding(server, &ctx, button);
|
||||
process_release_mousebinding(&ctx, button);
|
||||
|
||||
return notify;
|
||||
}
|
||||
|
|
@ -1258,8 +1257,6 @@ cursor_process_button_release(struct seat *seat, uint32_t button,
|
|||
bool
|
||||
cursor_finish_button_release(struct seat *seat, uint32_t button)
|
||||
{
|
||||
struct server *server = seat->server;
|
||||
|
||||
/* Clear "pressed" status for all bindings of this mouse button */
|
||||
struct mousebind *mousebind;
|
||||
wl_list_for_each(mousebind, &rc.mousebinds, link) {
|
||||
|
|
@ -1270,17 +1267,17 @@ cursor_finish_button_release(struct seat *seat, uint32_t button)
|
|||
|
||||
lab_set_remove(&seat->bound_buttons, button);
|
||||
|
||||
if (server->input_mode == LAB_INPUT_STATE_MOVE
|
||||
|| server->input_mode == LAB_INPUT_STATE_RESIZE) {
|
||||
if (resize_outlines_enabled(server->grabbed_view)) {
|
||||
resize_outlines_finish(server->grabbed_view);
|
||||
if (server.input_mode == LAB_INPUT_STATE_MOVE
|
||||
|| server.input_mode == LAB_INPUT_STATE_RESIZE) {
|
||||
if (resize_outlines_enabled(server.grabbed_view)) {
|
||||
resize_outlines_finish(server.grabbed_view);
|
||||
}
|
||||
/* Exit interactive move/resize mode */
|
||||
interactive_finish(server->grabbed_view);
|
||||
interactive_finish(server.grabbed_view);
|
||||
return true;
|
||||
} else if (server->grabbed_view) {
|
||||
} else if (server.grabbed_view) {
|
||||
/* Button was released without starting move/resize */
|
||||
interactive_cancel(server->grabbed_view);
|
||||
interactive_cancel(server.grabbed_view);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -1295,7 +1292,7 @@ handle_button(struct wl_listener *listener, void *data)
|
|||
*/
|
||||
struct seat *seat = wl_container_of(listener, seat, on_cursor.button);
|
||||
struct wlr_pointer_button_event *event = data;
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
bool notify;
|
||||
|
|
@ -1304,7 +1301,7 @@ handle_button(struct wl_listener *listener, void *data)
|
|||
notify = cursor_process_button_press(seat, event->button,
|
||||
event->time_msec);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
|
||||
wlr_seat_pointer_notify_button(seat->wlr_seat, event->time_msec,
|
||||
event->button, event->state);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1312,7 +1309,7 @@ handle_button(struct wl_listener *listener, void *data)
|
|||
notify = cursor_process_button_release(seat, event->button,
|
||||
event->time_msec);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
|
||||
wlr_seat_pointer_notify_button(seat->wlr_seat, event->time_msec,
|
||||
event->button, event->state);
|
||||
}
|
||||
cursor_finish_button_release(seat, event->button);
|
||||
|
|
@ -1370,15 +1367,15 @@ compare_delta(double delta, double delta_discrete, struct accumulated_scroll *ac
|
|||
}
|
||||
|
||||
static bool
|
||||
process_cursor_axis(struct server *server, enum wl_pointer_axis orientation,
|
||||
process_cursor_axis(enum wl_pointer_axis orientation,
|
||||
double delta, double delta_discrete)
|
||||
{
|
||||
struct cursor_context ctx = get_cursor_context(server);
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server->seat);
|
||||
struct cursor_context ctx = get_cursor_context();
|
||||
uint32_t modifiers = keyboard_get_all_modifiers(&server.seat);
|
||||
|
||||
enum direction direction = LAB_DIRECTION_INVALID;
|
||||
struct scroll_info info = compare_delta(delta, delta_discrete,
|
||||
&server->seat.accumulated_scrolls[orientation]);
|
||||
&server.seat.accumulated_scrolls[orientation]);
|
||||
|
||||
if (orientation == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
|
||||
if (info.direction < 0) {
|
||||
|
|
@ -1415,7 +1412,7 @@ process_cursor_axis(struct server *server, enum wl_pointer_axis orientation,
|
|||
* on touchpads or hi-res mice doesn't exceed the threshold
|
||||
*/
|
||||
if (info.run_action) {
|
||||
actions_run(ctx.view, server, &mousebind->actions, &ctx);
|
||||
actions_run(ctx.view, &mousebind->actions, &ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1424,7 +1421,7 @@ process_cursor_axis(struct server *server, enum wl_pointer_axis orientation,
|
|||
/* Bindings swallow mouse events if activated */
|
||||
if (ctx.surface && !consumed) {
|
||||
/* Make sure we are sending the events to the surface under the cursor */
|
||||
cursor_update_common(server, &ctx, NULL);
|
||||
cursor_update_common(&ctx, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1440,9 +1437,8 @@ handle_axis(struct wl_listener *listener, void *data)
|
|||
* event, for example when you move the scroll wheel.
|
||||
*/
|
||||
struct seat *seat = wl_container_of(listener, seat, on_cursor.axis);
|
||||
struct server *server = seat->server;
|
||||
struct wlr_pointer_axis_event *event = data;
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
/* input->scroll_factor is set for pointer/touch devices */
|
||||
|
|
@ -1451,12 +1447,12 @@ handle_axis(struct wl_listener *listener, void *data)
|
|||
struct input *input = event->pointer->base.data;
|
||||
double scroll_factor = input->scroll_factor;
|
||||
|
||||
bool notify = process_cursor_axis(server, event->orientation,
|
||||
bool notify = process_cursor_axis(event->orientation,
|
||||
event->delta, event->delta_discrete);
|
||||
|
||||
if (notify) {
|
||||
/* Notify the client with pointer focus of the axis event. */
|
||||
wlr_seat_pointer_notify_axis(seat->seat, event->time_msec,
|
||||
wlr_seat_pointer_notify_axis(seat->wlr_seat, event->time_msec,
|
||||
event->orientation, scroll_factor * event->delta,
|
||||
round(scroll_factor * event->delta_discrete),
|
||||
event->source, event->relative_direction);
|
||||
|
|
@ -1475,7 +1471,7 @@ handle_frame(struct wl_listener *listener, void *data)
|
|||
*/
|
||||
struct seat *seat = wl_container_of(listener, seat, on_cursor.frame);
|
||||
/* Notify the client with pointer focus of the frame event. */
|
||||
wlr_seat_pointer_notify_frame(seat->seat);
|
||||
wlr_seat_pointer_notify_frame(seat->wlr_seat);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1483,7 +1479,6 @@ cursor_emulate_axis(struct seat *seat, struct wlr_input_device *device,
|
|||
enum wl_pointer_axis orientation, double delta, double delta_discrete,
|
||||
enum wl_pointer_axis_source source, uint32_t time_msec)
|
||||
{
|
||||
struct server *server = seat->server;
|
||||
struct input *input = device->data;
|
||||
|
||||
double scroll_factor = 1.0;
|
||||
|
|
@ -1493,15 +1488,15 @@ cursor_emulate_axis(struct seat *seat, struct wlr_input_device *device,
|
|||
scroll_factor = input->scroll_factor;
|
||||
}
|
||||
|
||||
bool notify = process_cursor_axis(server, orientation, delta, delta_discrete);
|
||||
bool notify = process_cursor_axis(orientation, delta, delta_discrete);
|
||||
if (notify) {
|
||||
/* Notify the client with pointer focus of the axis event. */
|
||||
wlr_seat_pointer_notify_axis(seat->seat, time_msec,
|
||||
wlr_seat_pointer_notify_axis(seat->wlr_seat, time_msec,
|
||||
orientation, scroll_factor * delta,
|
||||
round(scroll_factor * delta_discrete),
|
||||
source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);
|
||||
}
|
||||
wlr_seat_pointer_notify_frame(seat->seat);
|
||||
wlr_seat_pointer_notify_frame(seat->wlr_seat);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1514,17 +1509,17 @@ cursor_emulate_move(struct seat *seat, struct wlr_input_device *device,
|
|||
}
|
||||
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(
|
||||
seat->server->relative_pointer_manager,
|
||||
seat->seat, (uint64_t)time_msec * 1000,
|
||||
server.relative_pointer_manager,
|
||||
seat->wlr_seat, (uint64_t)time_msec * 1000,
|
||||
dx, dy, dx, dy);
|
||||
|
||||
wlr_cursor_move(seat->cursor, device, dx, dy);
|
||||
double sx, sy;
|
||||
bool notify = cursor_process_motion(seat->server, time_msec, &sx, &sy);
|
||||
bool notify = cursor_process_motion(time_msec, &sx, &sy);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy);
|
||||
wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
|
||||
}
|
||||
wlr_seat_pointer_notify_frame(seat->seat);
|
||||
wlr_seat_pointer_notify_frame(seat->wlr_seat);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1550,18 +1545,18 @@ cursor_emulate_button(struct seat *seat, uint32_t button,
|
|||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||
notify = cursor_process_button_press(seat, button, time_msec);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_button(seat->seat, time_msec, button, state);
|
||||
wlr_seat_pointer_notify_button(seat->wlr_seat, time_msec, button, state);
|
||||
}
|
||||
break;
|
||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||
notify = cursor_process_button_release(seat, button, time_msec);
|
||||
if (notify) {
|
||||
wlr_seat_pointer_notify_button(seat->seat, time_msec, button, state);
|
||||
wlr_seat_pointer_notify_button(seat->wlr_seat, time_msec, button, state);
|
||||
}
|
||||
cursor_finish_button_release(seat, button);
|
||||
break;
|
||||
}
|
||||
wlr_seat_pointer_notify_frame(seat->seat);
|
||||
wlr_seat_pointer_notify_frame(seat->wlr_seat);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1614,9 +1609,6 @@ void
|
|||
cursor_reload(struct seat *seat)
|
||||
{
|
||||
cursor_load(seat);
|
||||
#if HAVE_XWAYLAND
|
||||
xwayland_reset_cursor(seat->server);
|
||||
#endif
|
||||
cursor_update_image(seat);
|
||||
}
|
||||
|
||||
|
|
@ -1640,10 +1632,10 @@ cursor_init(struct seat *seat)
|
|||
touch_init(seat);
|
||||
tablet_init(seat);
|
||||
|
||||
CONNECT_SIGNAL(seat->seat, seat, request_set_cursor);
|
||||
CONNECT_SIGNAL(seat->wlr_seat, seat, request_set_cursor);
|
||||
|
||||
struct wlr_cursor_shape_manager_v1 *cursor_shape_manager =
|
||||
wlr_cursor_shape_manager_v1_create(seat->server->wl_display,
|
||||
wlr_cursor_shape_manager_v1_create(server.wl_display,
|
||||
LAB_CURSOR_SHAPE_V1_VERSION);
|
||||
if (!cursor_shape_manager) {
|
||||
wlr_log(WLR_ERROR, "unable to create cursor_shape interface");
|
||||
|
|
@ -1651,8 +1643,8 @@ cursor_init(struct seat *seat)
|
|||
}
|
||||
|
||||
CONNECT_SIGNAL(cursor_shape_manager, seat, request_set_shape);
|
||||
CONNECT_SIGNAL(seat->seat, seat, request_set_selection);
|
||||
CONNECT_SIGNAL(seat->seat, seat, request_set_primary_selection);
|
||||
CONNECT_SIGNAL(seat->wlr_seat, seat, request_set_selection);
|
||||
CONNECT_SIGNAL(seat->wlr_seat, seat, request_set_primary_selection);
|
||||
}
|
||||
|
||||
void cursor_finish(struct seat *seat)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ handle_pinch_begin(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, pinch_begin);
|
||||
struct wlr_pointer_pinch_begin_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_pinch_begin(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->fingers);
|
||||
seat->wlr_seat, event->time_msec, event->fingers);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -25,11 +25,11 @@ handle_pinch_update(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, pinch_update);
|
||||
struct wlr_pointer_pinch_update_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_pinch_update(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->dx, event->dy,
|
||||
seat->wlr_seat, event->time_msec, event->dx, event->dy,
|
||||
event->scale, event->rotation);
|
||||
}
|
||||
|
||||
|
|
@ -39,11 +39,11 @@ handle_pinch_end(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, pinch_end);
|
||||
struct wlr_pointer_pinch_end_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_pinch_end(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->cancelled);
|
||||
seat->wlr_seat, event->time_msec, event->cancelled);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -52,11 +52,11 @@ handle_swipe_begin(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, swipe_begin);
|
||||
struct wlr_pointer_swipe_begin_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_swipe_begin(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->fingers);
|
||||
seat->wlr_seat, event->time_msec, event->fingers);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -65,11 +65,11 @@ handle_swipe_update(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, swipe_update);
|
||||
struct wlr_pointer_swipe_update_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_swipe_update(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->dx, event->dy);
|
||||
seat->wlr_seat, event->time_msec, event->dx, event->dy);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -78,11 +78,11 @@ handle_swipe_end(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, swipe_end);
|
||||
struct wlr_pointer_swipe_end_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_swipe_end(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->cancelled);
|
||||
seat->wlr_seat, event->time_msec, event->cancelled);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -91,11 +91,11 @@ handle_hold_begin(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, hold_begin);
|
||||
struct wlr_pointer_hold_begin_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_hold_begin(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->fingers);
|
||||
seat->wlr_seat, event->time_msec, event->fingers);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -104,17 +104,17 @@ handle_hold_end(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, hold_end);
|
||||
struct wlr_pointer_hold_end_event *event = data;
|
||||
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
cursor_set_visible(seat, /* visible */ true);
|
||||
|
||||
wlr_pointer_gestures_v1_send_hold_end(seat->pointer_gestures,
|
||||
seat->seat, event->time_msec, event->cancelled);
|
||||
seat->wlr_seat, event->time_msec, event->cancelled);
|
||||
}
|
||||
|
||||
void
|
||||
gestures_init(struct seat *seat)
|
||||
{
|
||||
seat->pointer_gestures = wlr_pointer_gestures_v1_create(seat->server->wl_display);
|
||||
seat->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display);
|
||||
|
||||
CONNECT_SIGNAL(seat->cursor, seat, pinch_begin);
|
||||
CONNECT_SIGNAL(seat->cursor, seat, pinch_update);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "input/keyboard.h"
|
||||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
|
|
@ -178,7 +179,6 @@ static void
|
|||
update_popup_position(struct input_method_popup *popup)
|
||||
{
|
||||
struct input_method_relay *relay = popup->relay;
|
||||
struct server *server = relay->seat->server;
|
||||
struct text_input *text_input = relay->active_text_input;
|
||||
|
||||
if (!text_input || !relay->focused_surface
|
||||
|
|
@ -219,7 +219,7 @@ update_popup_position(struct input_method_popup *popup)
|
|||
}
|
||||
|
||||
struct output *output =
|
||||
output_nearest_to(server, cursor_rect.x, cursor_rect.y);
|
||||
output_nearest_to(cursor_rect.x, cursor_rect.y);
|
||||
if (!output_is_usable(output)) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"Cannot position IME popup (unusable output)");
|
||||
|
|
@ -227,7 +227,7 @@ update_popup_position(struct input_method_popup *popup)
|
|||
}
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(
|
||||
server->output_layout, output->wlr_output, &output_box);
|
||||
server.output_layout, output->wlr_output, &output_box);
|
||||
|
||||
/* Use xdg-positioner utilities to position popup */
|
||||
struct wlr_xdg_positioner_rules rules = {
|
||||
|
|
@ -309,7 +309,8 @@ handle_keyboard_grab_destroy(struct wl_listener *listener, void *data)
|
|||
{
|
||||
struct input_method_relay *relay =
|
||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||
relay->input_method->keyboard_grab;
|
||||
assert(keyboard_grab);
|
||||
|
||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||
|
|
@ -330,7 +331,7 @@ handle_input_method_grab_keyboard(struct wl_listener *listener, void *data)
|
|||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
||||
|
||||
struct wlr_keyboard *active_keyboard =
|
||||
wlr_seat_get_keyboard(relay->seat->seat);
|
||||
wlr_seat_get_keyboard(relay->seat->wlr_seat);
|
||||
|
||||
if (!is_keyboard_emulated_by_input_method(
|
||||
active_keyboard, relay->input_method)) {
|
||||
|
|
@ -398,6 +399,8 @@ handle_input_method_new_popup_surface(struct wl_listener *listener, void *data)
|
|||
|
||||
popup->tree = wlr_scene_subsurface_tree_create(
|
||||
relay->popup_tree, popup->popup_surface->surface);
|
||||
die_if_null(popup->tree);
|
||||
|
||||
node_descriptor_create(&popup->tree->node, LAB_NODE_IME_POPUP,
|
||||
/*view*/ NULL, /*data*/ NULL);
|
||||
|
||||
|
|
@ -412,7 +415,7 @@ handle_new_input_method(struct wl_listener *listener, void *data)
|
|||
struct input_method_relay *relay =
|
||||
wl_container_of(listener, relay, new_input_method);
|
||||
struct wlr_input_method_v2 *input_method = data;
|
||||
if (relay->seat->seat != input_method->seat) {
|
||||
if (relay->seat->wlr_seat != input_method->seat) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +537,7 @@ handle_new_text_input(struct wl_listener *listener, void *data)
|
|||
struct input_method_relay *relay =
|
||||
wl_container_of(listener, relay, new_text_input);
|
||||
struct wlr_text_input_v3 *wlr_text_input = data;
|
||||
if (relay->seat->seat != wlr_text_input->seat) {
|
||||
if (relay->seat->wlr_seat != wlr_text_input->seat) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -580,14 +583,14 @@ input_method_relay_create(struct seat *seat)
|
|||
relay->seat = seat;
|
||||
wl_list_init(&relay->text_inputs);
|
||||
wl_list_init(&relay->popups);
|
||||
relay->popup_tree = wlr_scene_tree_create(&seat->server->scene->tree);
|
||||
relay->popup_tree = lab_wlr_scene_tree_create(&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(&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(&server.input_method_manager->events.new_input_method,
|
||||
&relay->new_input_method);
|
||||
|
||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,171 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include "config/rcxml.h"
|
||||
#include "common/buf.h"
|
||||
#include "common/set.h"
|
||||
#include "input/keyboard.h"
|
||||
#include "labwc.h"
|
||||
#include "scaled-buffer/scaled-font-buffer.h"
|
||||
|
||||
static struct lab_set pressed, bound, pressed_sent;
|
||||
|
||||
static bool show_debug_indicator;
|
||||
static struct indicator_state {
|
||||
struct wlr_scene_tree *tree;
|
||||
struct scaled_font_buffer *sfb_pressed;
|
||||
struct scaled_font_buffer *sfb_bound;
|
||||
struct scaled_font_buffer *sfb_pressed_sent;
|
||||
struct scaled_font_buffer *sfb_modifiers;
|
||||
struct xkb_keymap *keymap;
|
||||
} indicator_state;
|
||||
|
||||
static const char *
|
||||
keycode_to_keyname(struct xkb_keymap *keymap, uint32_t keycode)
|
||||
{
|
||||
const xkb_keysym_t *syms;
|
||||
int syms_len = xkb_keymap_key_get_syms_by_level(keymap, keycode + 8, 0, 0, &syms);
|
||||
if (!syms_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char buf[256];
|
||||
if (!xkb_keysym_get_name(syms[0], buf, sizeof(buf))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *
|
||||
modifier_to_name(uint32_t modifier)
|
||||
{
|
||||
switch (modifier) {
|
||||
case WLR_MODIFIER_SHIFT:
|
||||
return "S";
|
||||
case WLR_MODIFIER_CAPS:
|
||||
return "caps";
|
||||
case WLR_MODIFIER_CTRL:
|
||||
return "C";
|
||||
case WLR_MODIFIER_ALT:
|
||||
return "A";
|
||||
case WLR_MODIFIER_MOD2:
|
||||
return "numlock";
|
||||
case WLR_MODIFIER_MOD3:
|
||||
return "H";
|
||||
case WLR_MODIFIER_LOGO:
|
||||
return "W";
|
||||
case WLR_MODIFIER_MOD5:
|
||||
return "M";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_indicator(struct indicator_state *state)
|
||||
{
|
||||
state->tree = wlr_scene_tree_create(&server.scene->tree);
|
||||
wlr_scene_node_set_enabled(&state->tree->node, false);
|
||||
|
||||
state->sfb_pressed = scaled_font_buffer_create(state->tree);
|
||||
wlr_scene_node_set_position(&state->sfb_pressed->scene_buffer->node, 0, 0);
|
||||
state->sfb_bound = scaled_font_buffer_create(state->tree);
|
||||
wlr_scene_node_set_position(&state->sfb_bound->scene_buffer->node, 0, 20);
|
||||
state->sfb_pressed_sent = scaled_font_buffer_create(state->tree);
|
||||
wlr_scene_node_set_position(&state->sfb_pressed_sent->scene_buffer->node, 0, 40);
|
||||
state->sfb_modifiers = scaled_font_buffer_create(state->tree);
|
||||
wlr_scene_node_set_position(&state->sfb_modifiers->scene_buffer->node, 0, 60);
|
||||
|
||||
struct xkb_rule_names rules = { 0 };
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
state->keymap = xkb_map_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
static void
|
||||
update_key_indicator_callback(void *data)
|
||||
{
|
||||
struct seat *seat = data;
|
||||
uint32_t all_modifiers = keyboard_get_all_modifiers(seat);
|
||||
float black[4] = {0, 0, 0, 1};
|
||||
float white[4] = {1, 1, 1, 1};
|
||||
|
||||
if (!indicator_state.tree) {
|
||||
init_indicator(&indicator_state);
|
||||
}
|
||||
|
||||
if (show_debug_indicator) {
|
||||
wlr_scene_node_set_enabled(&indicator_state.tree->node, true);
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&indicator_state.tree->node, false);
|
||||
return;
|
||||
}
|
||||
|
||||
struct buf buf = BUF_INIT;
|
||||
|
||||
buf_add(&buf, "pressed=");
|
||||
for (int i = 0; i < pressed.size; i++) {
|
||||
const char *keyname = keycode_to_keyname(indicator_state.keymap,
|
||||
pressed.values[i]);
|
||||
buf_add_fmt(&buf, "%s (%d), ", keyname, pressed.values[i]);
|
||||
}
|
||||
scaled_font_buffer_update(indicator_state.sfb_pressed, buf.data,
|
||||
-1, &rc.font_osd, black, white);
|
||||
|
||||
buf_clear(&buf);
|
||||
buf_add(&buf, "bound=");
|
||||
for (int i = 0; i < bound.size; i++) {
|
||||
const char *keyname = keycode_to_keyname(indicator_state.keymap,
|
||||
bound.values[i]);
|
||||
buf_add_fmt(&buf, "%s (%d), ", keyname, bound.values[i]);
|
||||
}
|
||||
scaled_font_buffer_update(indicator_state.sfb_bound, buf.data,
|
||||
-1, &rc.font_osd, black, white);
|
||||
|
||||
buf_clear(&buf);
|
||||
buf_add(&buf, "pressed_sent=");
|
||||
for (int i = 0; i < pressed_sent.size; i++) {
|
||||
const char *keyname = keycode_to_keyname(indicator_state.keymap,
|
||||
pressed_sent.values[i]);
|
||||
buf_add_fmt(&buf, "%s (%d), ", keyname, pressed_sent.values[i]);
|
||||
}
|
||||
scaled_font_buffer_update(indicator_state.sfb_pressed_sent, buf.data, -1,
|
||||
&rc.font_osd, black, white);
|
||||
|
||||
buf_clear(&buf);
|
||||
buf_add(&buf, "modifiers=");
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
uint32_t mod = 1 << i;
|
||||
if (all_modifiers & mod) {
|
||||
buf_add_fmt(&buf, "%s, ", modifier_to_name(mod));
|
||||
}
|
||||
}
|
||||
buf_add_fmt(&buf, "(%d)", all_modifiers);
|
||||
scaled_font_buffer_update(indicator_state.sfb_modifiers, buf.data, -1,
|
||||
&rc.font_osd, black, white);
|
||||
|
||||
buf_reset(&buf);
|
||||
}
|
||||
|
||||
void
|
||||
key_state_indicator_update(struct seat *seat)
|
||||
{
|
||||
if (!show_debug_indicator) {
|
||||
return;
|
||||
}
|
||||
wl_event_loop_add_idle(server.wl_event_loop,
|
||||
update_key_indicator_callback, seat);
|
||||
}
|
||||
|
||||
void
|
||||
key_state_indicator_toggle(void)
|
||||
{
|
||||
show_debug_indicator = !show_debug_indicator;
|
||||
}
|
||||
|
||||
static void
|
||||
report(struct lab_set *key_set, const char *msg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "input/keyboard.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
|
|
@ -21,6 +21,10 @@
|
|||
#include "view.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
#if WLR_HAS_SESSION
|
||||
#include <wlr/backend/session.h>
|
||||
#endif
|
||||
|
||||
enum lab_key_handled {
|
||||
LAB_KEY_HANDLED_FALSE = 0,
|
||||
LAB_KEY_HANDLED_TRUE = 1,
|
||||
|
|
@ -52,9 +56,11 @@ keyboard_reset_current_keybind(void)
|
|||
}
|
||||
|
||||
static void
|
||||
change_vt(struct server *server, unsigned int vt)
|
||||
change_vt(unsigned int vt)
|
||||
{
|
||||
wlr_session_change_vt(server->session, vt);
|
||||
#if WLR_HAS_SESSION
|
||||
wlr_session_change_vt(server.session, vt);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
@ -90,7 +96,7 @@ seat_client_from_keyboard_resource(struct wl_resource *resource)
|
|||
}
|
||||
|
||||
static void
|
||||
broadcast_modifiers_to_unfocused_clients(struct wlr_seat *seat,
|
||||
broadcast_modifiers_to_unfocused_clients(struct wlr_seat *wlr_seat,
|
||||
const struct keyboard *keyboard,
|
||||
const struct wlr_keyboard_modifiers *modifiers)
|
||||
{
|
||||
|
|
@ -100,8 +106,8 @@ broadcast_modifiers_to_unfocused_clients(struct wlr_seat *seat,
|
|||
}
|
||||
|
||||
struct wlr_seat_client *client;
|
||||
wl_list_for_each(client, &seat->clients, link) {
|
||||
if (client == seat->keyboard_state.focused_client) {
|
||||
wl_list_for_each(client, &wlr_seat->clients, link) {
|
||||
if (client == wlr_seat->keyboard_state.focused_client) {
|
||||
/*
|
||||
* We've already notified the focused client by calling
|
||||
* wlr_seat_keyboard_notify_modifiers()
|
||||
|
|
@ -131,17 +137,18 @@ handle_modifiers(struct wl_listener *listener, void *data)
|
|||
{
|
||||
struct keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
|
||||
struct seat *seat = keyboard->base.seat;
|
||||
struct server *server = seat->server;
|
||||
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
|
||||
|
||||
if (server->input_mode == LAB_INPUT_STATE_MOVE) {
|
||||
key_state_indicator_update(seat);
|
||||
|
||||
if (server.input_mode == LAB_INPUT_STATE_MOVE) {
|
||||
/* Any change to the modifier state re-enable region snap */
|
||||
seat->region_prevent_snap = false;
|
||||
/* Pressing/releasing modifier key may show/hide region overlay */
|
||||
overlay_update(seat);
|
||||
}
|
||||
|
||||
bool cycling = server->input_mode == LAB_INPUT_STATE_CYCLE;
|
||||
bool cycling = server.input_mode == LAB_INPUT_STATE_CYCLE;
|
||||
|
||||
if ((cycling || seat->workspace_osd_shown_by_modifier)
|
||||
&& !keyboard_get_all_modifiers(seat)) {
|
||||
|
|
@ -150,7 +157,7 @@ handle_modifiers(struct wl_listener *listener, void *data)
|
|||
should_cancel_cycling_on_next_key_release = true;
|
||||
} else {
|
||||
should_cancel_cycling_on_next_key_release = false;
|
||||
cycle_finish(server, /*switch_focus*/ true);
|
||||
cycle_finish(/*switch_focus*/ true);
|
||||
}
|
||||
}
|
||||
if (seat->workspace_osd_shown_by_modifier) {
|
||||
|
|
@ -160,7 +167,7 @@ handle_modifiers(struct wl_listener *listener, void *data)
|
|||
|
||||
if (!input_method_keyboard_grab_forward_modifiers(keyboard)) {
|
||||
/* Send modifiers to focused client */
|
||||
wlr_seat_keyboard_notify_modifiers(seat->seat,
|
||||
wlr_seat_keyboard_notify_modifiers(seat->wlr_seat,
|
||||
&wlr_keyboard->modifiers);
|
||||
|
||||
/*
|
||||
|
|
@ -182,13 +189,13 @@ handle_modifiers(struct wl_listener *listener, void *data)
|
|||
* consequences. If so, modifiers ought to still be passed to
|
||||
* clients with pointer-focus (see issue #2271)
|
||||
*/
|
||||
broadcast_modifiers_to_unfocused_clients(seat->seat,
|
||||
broadcast_modifiers_to_unfocused_clients(seat->wlr_seat,
|
||||
keyboard, &wlr_keyboard->modifiers);
|
||||
}
|
||||
}
|
||||
|
||||
static struct keybind *
|
||||
match_keybinding_for_sym(struct server *server, uint32_t modifiers,
|
||||
match_keybinding_for_sym(uint32_t modifiers,
|
||||
xkb_keysym_t sym, xkb_keycode_t xkb_keycode)
|
||||
{
|
||||
struct keybind *keybind;
|
||||
|
|
@ -196,8 +203,10 @@ match_keybinding_for_sym(struct server *server, uint32_t modifiers,
|
|||
if (modifiers ^ keybind->modifiers) {
|
||||
continue;
|
||||
}
|
||||
if (view_inhibits_actions(server->active_view, &keybind->actions)) {
|
||||
continue;
|
||||
if (!(keybind->override_inhibition)) {
|
||||
if (view_inhibits_actions(server.active_view, &keybind->actions)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (sym == XKB_KEY_NoSymbol) {
|
||||
/* Use keycodes */
|
||||
|
|
@ -241,12 +250,12 @@ match_keybinding_for_sym(struct server *server, uint32_t modifiers,
|
|||
* the raw keysym fallback.
|
||||
*/
|
||||
static struct keybind *
|
||||
match_keybinding(struct server *server, struct keyinfo *keyinfo,
|
||||
match_keybinding(struct keyinfo *keyinfo,
|
||||
bool is_virtual)
|
||||
{
|
||||
if (!is_virtual) {
|
||||
/* First try keycodes */
|
||||
struct keybind *keybind = match_keybinding_for_sym(server,
|
||||
struct keybind *keybind = match_keybinding_for_sym(
|
||||
keyinfo->modifiers, XKB_KEY_NoSymbol, keyinfo->xkb_keycode);
|
||||
if (keybind) {
|
||||
wlr_log(WLR_DEBUG, "keycode matched");
|
||||
|
|
@ -257,7 +266,7 @@ match_keybinding(struct server *server, struct keyinfo *keyinfo,
|
|||
/* Then fall back to keysyms */
|
||||
for (int i = 0; i < keyinfo->translated.nr_syms; i++) {
|
||||
struct keybind *keybind =
|
||||
match_keybinding_for_sym(server, keyinfo->modifiers,
|
||||
match_keybinding_for_sym(keyinfo->modifiers,
|
||||
keyinfo->translated.syms[i], keyinfo->xkb_keycode);
|
||||
if (keybind) {
|
||||
wlr_log(WLR_DEBUG, "translated keysym matched");
|
||||
|
|
@ -268,7 +277,7 @@ match_keybinding(struct server *server, struct keyinfo *keyinfo,
|
|||
/* And finally test for keysyms without modifier */
|
||||
for (int i = 0; i < keyinfo->raw.nr_syms; i++) {
|
||||
struct keybind *keybind =
|
||||
match_keybinding_for_sym(server, keyinfo->modifiers,
|
||||
match_keybinding_for_sym(keyinfo->modifiers,
|
||||
keyinfo->raw.syms[i], keyinfo->xkb_keycode);
|
||||
if (keybind) {
|
||||
wlr_log(WLR_DEBUG, "raw keysym matched");
|
||||
|
|
@ -366,7 +375,7 @@ get_keyinfo(struct wlr_keyboard *wlr_keyboard, uint32_t evdev_keycode)
|
|||
}
|
||||
|
||||
static enum lab_key_handled
|
||||
handle_key_release(struct server *server, uint32_t evdev_keycode)
|
||||
handle_key_release(uint32_t evdev_keycode)
|
||||
{
|
||||
/*
|
||||
* Release events for keys that were not bound should always be
|
||||
|
|
@ -387,7 +396,7 @@ handle_key_release(struct server *server, uint32_t evdev_keycode)
|
|||
*/
|
||||
if (should_cancel_cycling_on_next_key_release) {
|
||||
should_cancel_cycling_on_next_key_release = false;
|
||||
cycle_finish(server, /*switch_focus*/ true);
|
||||
cycle_finish(/*switch_focus*/ true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -399,7 +408,7 @@ handle_key_release(struct server *server, uint32_t evdev_keycode)
|
|||
}
|
||||
|
||||
static bool
|
||||
handle_change_vt_key(struct server *server, struct keyboard *keyboard,
|
||||
handle_change_vt_key(struct keyboard *keyboard,
|
||||
struct keysyms *translated)
|
||||
{
|
||||
for (int i = 0; i < translated->nr_syms; i++) {
|
||||
|
|
@ -407,7 +416,7 @@ handle_change_vt_key(struct server *server, struct keyboard *keyboard,
|
|||
translated->syms[i] - XKB_KEY_XF86Switch_VT_1 + 1;
|
||||
if (vt >= 1 && vt <= 12) {
|
||||
keyboard_cancel_keybind_repeat(keyboard);
|
||||
change_vt(server, vt);
|
||||
change_vt(vt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -415,42 +424,51 @@ handle_change_vt_key(struct server *server, struct keyboard *keyboard,
|
|||
}
|
||||
|
||||
static void
|
||||
handle_menu_keys(struct server *server, struct keysyms *syms)
|
||||
handle_menu_keys(struct keysyms *syms)
|
||||
{
|
||||
assert(server->input_mode == LAB_INPUT_STATE_MENU);
|
||||
assert(server.input_mode == LAB_INPUT_STATE_MENU);
|
||||
|
||||
for (int i = 0; i < syms->nr_syms; i++) {
|
||||
switch (syms->syms[i]) {
|
||||
case XKB_KEY_Down:
|
||||
menu_item_select_next(server);
|
||||
menu_item_select_next();
|
||||
break;
|
||||
case XKB_KEY_Up:
|
||||
menu_item_select_previous(server);
|
||||
menu_item_select_previous();
|
||||
break;
|
||||
case XKB_KEY_Right:
|
||||
menu_submenu_enter(server);
|
||||
menu_submenu_enter();
|
||||
break;
|
||||
case XKB_KEY_Left:
|
||||
menu_submenu_leave(server);
|
||||
menu_submenu_leave();
|
||||
break;
|
||||
case XKB_KEY_Return:
|
||||
case XKB_KEY_KP_Enter:
|
||||
menu_call_selected_actions(server);
|
||||
if (!menu_call_selected_actions()) {
|
||||
menu_submenu_enter();
|
||||
};
|
||||
break;
|
||||
case XKB_KEY_Escape:
|
||||
menu_close_root(server);
|
||||
cursor_update_focus(server);
|
||||
menu_close_root();
|
||||
cursor_update_focus();
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
default: {
|
||||
uint32_t accelerator = xkb_keysym_to_utf32(syms->syms[i]);
|
||||
if (accelerator == 0) {
|
||||
continue;
|
||||
}
|
||||
if (menu_item_select_by_accelerator(accelerator)) {
|
||||
menu_call_selected_actions();
|
||||
}
|
||||
break;
|
||||
}}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if the keystroke is consumed */
|
||||
static bool
|
||||
handle_cycle_view_key(struct server *server, struct keyinfo *keyinfo)
|
||||
handle_cycle_view_key(struct keyinfo *keyinfo)
|
||||
{
|
||||
if (keyinfo->is_modifier) {
|
||||
return false;
|
||||
|
|
@ -460,19 +478,19 @@ handle_cycle_view_key(struct server *server, struct keyinfo *keyinfo)
|
|||
for (int i = 0; i < keyinfo->translated.nr_syms; i++) {
|
||||
if (keyinfo->translated.syms[i] == XKB_KEY_Escape) {
|
||||
/* Esc deactivates window switcher */
|
||||
cycle_finish(server, /*switch_focus*/ false);
|
||||
cycle_finish(/*switch_focus*/ false);
|
||||
return true;
|
||||
}
|
||||
if (keyinfo->translated.syms[i] == XKB_KEY_Up
|
||||
|| keyinfo->translated.syms[i] == XKB_KEY_Left) {
|
||||
/* Up/Left cycles the window backward */
|
||||
cycle_step(server, LAB_CYCLE_DIR_BACKWARD);
|
||||
cycle_step(LAB_CYCLE_DIR_BACKWARD);
|
||||
return true;
|
||||
}
|
||||
if (keyinfo->translated.syms[i] == XKB_KEY_Down
|
||||
|| keyinfo->translated.syms[i] == XKB_KEY_Right) {
|
||||
/* Down/Right cycles the window forward */
|
||||
cycle_step(server, LAB_CYCLE_DIR_FORWARD);
|
||||
cycle_step(LAB_CYCLE_DIR_FORWARD);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -483,11 +501,9 @@ static enum lab_key_handled
|
|||
handle_compositor_keybindings(struct keyboard *keyboard,
|
||||
struct wlr_keyboard_key_event *event)
|
||||
{
|
||||
struct seat *seat = keyboard->base.seat;
|
||||
struct server *server = seat->server;
|
||||
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
|
||||
struct keyinfo keyinfo = get_keyinfo(wlr_keyboard, event->keycode);
|
||||
bool locked = seat->server->session_lock_manager->locked;
|
||||
bool locked = server.session_lock_manager->locked;
|
||||
|
||||
key_state_set_pressed(event->keycode,
|
||||
event->state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
|
|
@ -499,15 +515,15 @@ handle_compositor_keybindings(struct keyboard *keyboard,
|
|||
cur_keybind = NULL;
|
||||
return LAB_KEY_HANDLED_TRUE;
|
||||
}
|
||||
actions_run(NULL, server, &cur_keybind->actions, NULL);
|
||||
actions_run(NULL, &cur_keybind->actions, NULL);
|
||||
return LAB_KEY_HANDLED_TRUE;
|
||||
} else {
|
||||
return handle_key_release(server, event->keycode);
|
||||
return handle_key_release(event->keycode);
|
||||
}
|
||||
}
|
||||
|
||||
/* Catch C-A-F1 to C-A-F12 to change tty */
|
||||
if (handle_change_vt_key(server, keyboard, &keyinfo.translated)) {
|
||||
if (handle_change_vt_key(keyboard, &keyinfo.translated)) {
|
||||
key_state_store_pressed_key_as_bound(event->keycode);
|
||||
return LAB_KEY_HANDLED_TRUE_AND_VT_CHANGED;
|
||||
}
|
||||
|
|
@ -518,12 +534,12 @@ handle_compositor_keybindings(struct keyboard *keyboard,
|
|||
* _all_ key press/releases are registered
|
||||
*/
|
||||
if (!locked) {
|
||||
if (server->input_mode == LAB_INPUT_STATE_MENU) {
|
||||
if (server.input_mode == LAB_INPUT_STATE_MENU) {
|
||||
key_state_store_pressed_key_as_bound(event->keycode);
|
||||
handle_menu_keys(server, &keyinfo.translated);
|
||||
handle_menu_keys(&keyinfo.translated);
|
||||
return LAB_KEY_HANDLED_TRUE;
|
||||
} else if (server->input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (handle_cycle_view_key(server, &keyinfo)) {
|
||||
} else if (server.input_mode == LAB_INPUT_STATE_CYCLE) {
|
||||
if (handle_cycle_view_key(&keyinfo)) {
|
||||
key_state_store_pressed_key_as_bound(event->keycode);
|
||||
return LAB_KEY_HANDLED_TRUE;
|
||||
}
|
||||
|
|
@ -533,7 +549,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
|
|||
/*
|
||||
* Handle compositor keybinds
|
||||
*/
|
||||
cur_keybind = match_keybinding(server, &keyinfo, keyboard->is_virtual);
|
||||
cur_keybind = match_keybinding(&keyinfo, keyboard->is_virtual);
|
||||
if (cur_keybind && (!locked || cur_keybind->allow_when_locked)) {
|
||||
/*
|
||||
* Update key-state before action_run() because the action
|
||||
|
|
@ -542,7 +558,7 @@ handle_compositor_keybindings(struct keyboard *keyboard,
|
|||
*/
|
||||
key_state_store_pressed_key_as_bound(event->keycode);
|
||||
if (!cur_keybind->on_release) {
|
||||
actions_run(NULL, server, &cur_keybind->actions, NULL);
|
||||
actions_run(NULL, &cur_keybind->actions, NULL);
|
||||
}
|
||||
return LAB_KEY_HANDLED_TRUE;
|
||||
}
|
||||
|
|
@ -572,7 +588,7 @@ handle_keybind_repeat(void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
start_keybind_repeat(struct server *server, struct keyboard *keyboard,
|
||||
start_keybind_repeat(struct keyboard *keyboard,
|
||||
struct wlr_keyboard_key_event *event)
|
||||
{
|
||||
struct wlr_keyboard *wlr_keyboard = keyboard->wlr_keyboard;
|
||||
|
|
@ -583,7 +599,7 @@ start_keybind_repeat(struct server *server, struct keyboard *keyboard,
|
|||
keyboard->keybind_repeat_keycode = event->keycode;
|
||||
keyboard->keybind_repeat_rate = wlr_keyboard->repeat_info.rate;
|
||||
keyboard->keybind_repeat = wl_event_loop_add_timer(
|
||||
server->wl_event_loop, handle_keybind_repeat, keyboard);
|
||||
server.wl_event_loop, handle_keybind_repeat, keyboard);
|
||||
wl_event_source_timer_update(keyboard->keybind_repeat,
|
||||
wlr_keyboard->repeat_info.delay);
|
||||
}
|
||||
|
|
@ -618,8 +634,11 @@ handle_key(struct wl_listener *listener, void *data)
|
|||
struct keyboard *keyboard = wl_container_of(listener, keyboard, key);
|
||||
struct seat *seat = keyboard->base.seat;
|
||||
struct wlr_keyboard_key_event *event = data;
|
||||
struct wlr_seat *wlr_seat = seat->seat;
|
||||
idle_manager_notify_activity(seat->seat);
|
||||
struct wlr_seat *wlr_seat = seat->wlr_seat;
|
||||
|
||||
key_state_indicator_update(seat);
|
||||
|
||||
idle_manager_notify_activity(seat->wlr_seat);
|
||||
|
||||
/* any new press/release cancels current keybind repeat */
|
||||
keyboard_cancel_keybind_repeat(keyboard);
|
||||
|
|
@ -639,7 +658,7 @@ handle_key(struct wl_listener *listener, void *data)
|
|||
*/
|
||||
if (!is_modifier(keyboard->wlr_keyboard, event->keycode)
|
||||
&& event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
start_keybind_repeat(seat->server, keyboard, event);
|
||||
start_keybind_repeat(keyboard, event);
|
||||
}
|
||||
} else if (!input_method_keyboard_grab_forward_key(keyboard, event)) {
|
||||
wlr_seat_set_keyboard(wlr_seat, keyboard->wlr_keyboard);
|
||||
|
|
@ -715,7 +734,7 @@ keyboard_update_layout(struct seat *seat, xkb_layout_index_t layout)
|
|||
}
|
||||
|
||||
static void
|
||||
reset_window_keyboard_layout_groups(struct server *server)
|
||||
reset_window_keyboard_layout_groups(void)
|
||||
{
|
||||
if (!rc.kb_layout_per_window) {
|
||||
return;
|
||||
|
|
@ -727,15 +746,15 @@ reset_window_keyboard_layout_groups(struct server *server)
|
|||
* but let's keep it simple for now and just reset them all.
|
||||
*/
|
||||
struct view *view;
|
||||
for_each_view(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
|
||||
for_each_view(view, &server.views, LAB_VIEW_CRITERIA_NONE) {
|
||||
view->keyboard_layout = 0;
|
||||
}
|
||||
|
||||
struct view *active_view = server->active_view;
|
||||
struct view *active_view = server.active_view;
|
||||
if (!active_view) {
|
||||
return;
|
||||
}
|
||||
keyboard_update_layout(&server->seat, active_view->keyboard_layout);
|
||||
keyboard_update_layout(&server.seat, active_view->keyboard_layout);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -743,12 +762,23 @@ reset_window_keyboard_layout_groups(struct server *server)
|
|||
* XKB_DEFAULT_OPTIONS, and friends.
|
||||
*/
|
||||
static void
|
||||
set_layout(struct server *server, struct wlr_keyboard *kb)
|
||||
set_layout(struct wlr_keyboard *kb)
|
||||
{
|
||||
static bool fallback_mode;
|
||||
|
||||
struct xkb_rule_names rules = { 0 };
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_FLAGS;
|
||||
#ifdef __ANDROID__
|
||||
/*
|
||||
* Android's bionic libc implements secure_getenv() as a function
|
||||
* that always returns NULL (the app process has no AT_SECURE).
|
||||
* This prevents xkbcommon from reading XKB_DEFAULT_LAYOUT and
|
||||
* friends via secure_getenv(). Use the flag to fall back to
|
||||
* regular getenv() which works fine on Android.
|
||||
*/
|
||||
ctx_flags |= XKB_CONTEXT_NO_SECURE_GETENV;
|
||||
#endif
|
||||
struct xkb_context *context = xkb_context_new(ctx_flags);
|
||||
struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
|
|
@ -762,7 +792,7 @@ set_layout(struct server *server, struct wlr_keyboard *kb)
|
|||
if (keymap && !layout_empty) {
|
||||
if (!wlr_keyboard_keymaps_match(kb->keymap, keymap)) {
|
||||
wlr_keyboard_set_keymap(kb, keymap);
|
||||
reset_window_keyboard_layout_groups(server);
|
||||
reset_window_keyboard_layout_groups();
|
||||
}
|
||||
xkb_keymap_unref(keymap);
|
||||
} else {
|
||||
|
|
@ -772,7 +802,7 @@ set_layout(struct server *server, struct wlr_keyboard *kb)
|
|||
wlr_log(WLR_ERROR, "entering fallback mode with layout 'us'");
|
||||
fallback_mode = true;
|
||||
setenv("XKB_DEFAULT_LAYOUT", "us", 1);
|
||||
set_layout(server, kb);
|
||||
set_layout(kb);
|
||||
}
|
||||
}
|
||||
xkb_context_unref(context);
|
||||
|
|
@ -782,10 +812,10 @@ void
|
|||
keyboard_configure(struct seat *seat, struct wlr_keyboard *kb, bool is_virtual)
|
||||
{
|
||||
if (!is_virtual) {
|
||||
set_layout(seat->server, kb);
|
||||
set_layout(kb);
|
||||
}
|
||||
wlr_keyboard_set_repeat_info(kb, rc.repeat_rate, rc.repeat_delay);
|
||||
keybind_update_keycodes(seat->server);
|
||||
keybind_update_keycodes();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue