mirror of
https://github.com/labwc/labwc.git
synced 2026-04-16 08:21:26 -04:00
Merge branch 'master' into headerbar_touch
This commit is contained in:
commit
861c0de99f
43 changed files with 1128 additions and 181 deletions
|
|
@ -98,7 +98,7 @@ Some distributions carry labwc in their repositories or user repositories.
|
||||||
- @adcdam (Slackware)
|
- @adcdam (Slackware)
|
||||||
- @bdantas (Tiny Core Linux)
|
- @bdantas (Tiny Core Linux)
|
||||||
- @Visone-Selektah (Venom Linux)
|
- @Visone-Selektah (Venom Linux)
|
||||||
- @tranzystorek-io (Void Linux)
|
- @tranzystorekk (Void Linux)
|
||||||
|
|
||||||
kindly maintain the packages in their respective distro.
|
kindly maintain the packages in their respective distro.
|
||||||
|
|
||||||
|
|
@ -350,19 +350,32 @@ Base both bugfixes and new features on `master`.
|
||||||
|
|
||||||
# Native Language Support
|
# Native Language Support
|
||||||
|
|
||||||
|
## Translators
|
||||||
|
|
||||||
|
### Weblate Instance
|
||||||
|
|
||||||
|
Translators can create an account at [LXQt Weblate](https://translate.lxqt-project.org/projects/labwc/labwc/)
|
||||||
|
and use the web interface. Adding new languages should work, otherwise the
|
||||||
|
administrators can be contacted. Suggestions for improving existing translations
|
||||||
|
can be added without account.
|
||||||
|
|
||||||
|
### Github Pull Request
|
||||||
|
|
||||||
Translators can add their `MY_LOCALE.po` files to the `po` directory
|
Translators can add their `MY_LOCALE.po` files to the `po` directory
|
||||||
based on `po/labwc.pot` and issue a pull request. To do this they can
|
based on `po/labwc.pot` and issue a pull request. To do this they can
|
||||||
generate their `MY_LOCALE.po` file in a few steps:
|
generate their `MY_LOCALE.po` file in a few steps:
|
||||||
|
|
||||||
1. Edit the `po/LINGUAS` file to add their locale name by adding a space
|
1. Edit the `po/LINGUAS` file to add their locale code in English
|
||||||
to the end of the field and typing the locale code.
|
alphabetical order to the field of locale codes.
|
||||||
2. Copy the po/labwc.pot to po/MY_LOCALE.po
|
2. Copy the `po/labwc.pot` to `po/MY_LOCALE.po`
|
||||||
3. Edit the newly generated MY_LOCALE.po file with some of their
|
3. Edit the newly generated `MY_LOCALE.po` file with some of their
|
||||||
contact and locale details in the header of the file then add the
|
contact and locale details in the header of the file then add the
|
||||||
translation strings under each English string.
|
translation strings under each English string.
|
||||||
|
|
||||||
[See this tutorial for further guidance](https://www.labri.fr/perso/fleury/posts/programming/a-quick-gettext-tutorial.html)
|
[See this tutorial for further guidance](https://www.labri.fr/perso/fleury/posts/programming/a-quick-gettext-tutorial.html)
|
||||||
|
|
||||||
|
## Coders
|
||||||
|
|
||||||
Code contributors may need to update relevant files if their additions
|
Code contributors may need to update relevant files if their additions
|
||||||
affect UI elements (at the moment only `src/menu/menu.c`). In this case
|
affect UI elements (at the moment only `src/menu/menu.c`). In this case
|
||||||
the `po/labwc.pot` file needs to be updated so that translators can
|
the `po/labwc.pot` file needs to be updated so that translators can
|
||||||
|
|
|
||||||
40
NEWS.md
40
NEWS.md
|
|
@ -9,7 +9,7 @@ The format is based on [Keep a Changelog]
|
||||||
|
|
||||||
| Date | All Changes | wlroots version | lines-of-code |
|
| Date | All Changes | wlroots version | lines-of-code |
|
||||||
|------------|---------------|-----------------|---------------|
|
|------------|---------------|-----------------|---------------|
|
||||||
| 2024-01-23 | [unreleased] | 0.17.1 | |
|
| 2024-03-01 | [0.7.1] | 0.17.1 | 18624 |
|
||||||
| 2023-12-22 | [0.7.0] | 0.17.1 | 16576 |
|
| 2023-12-22 | [0.7.0] | 0.17.1 | 16576 |
|
||||||
| 2023-11-25 | [0.6.6] | 0.16.2 | 15796 |
|
| 2023-11-25 | [0.6.6] | 0.16.2 | 15796 |
|
||||||
| 2023-09-23 | [0.6.5] | 0.16.2 | 14809 |
|
| 2023-09-23 | [0.6.5] | 0.16.2 | 14809 |
|
||||||
|
|
@ -28,10 +28,33 @@ The format is based on [Keep a Changelog]
|
||||||
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
|
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
|
||||||
|
|
||||||
|
|
||||||
## [unreleased]
|
## [0.7.1]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Support libinput option sendEventsMode to allow enabling/disabling devices.
|
||||||
|
Co-Authored-By: @Sachin-Bhat
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<libinput>
|
||||||
|
<device>
|
||||||
|
<sendEventsMode>yes|no|disabledOnExternalMouse</sendEventsMode>
|
||||||
|
</device>
|
||||||
|
</libinput>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Add click method libinput option. Written-by: @datMaffin
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<libinput>
|
||||||
|
<device>
|
||||||
|
<clickMethod>none|buttonAreas|clickfinger</clickMethod>
|
||||||
|
</device>
|
||||||
|
</libinput>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Add `data/labwc.svg` & `data/labwc-symbolic.svg`, and specify icon name
|
||||||
|
in labwc.desktop to enable Display Managers to show an icons for labwc.
|
||||||
- Expose output configuration test to clients. For example, this enables
|
- Expose output configuration test to clients. For example, this enables
|
||||||
`wlr-randr --dryrun`
|
`wlr-randr --dryrun`
|
||||||
- Add window-edge resistance for interactive moves/resizes and support negative
|
- Add window-edge resistance for interactive moves/resizes and support negative
|
||||||
|
|
@ -90,6 +113,7 @@ The format is based on [Keep a Changelog]
|
||||||
- Add config option `<placement><policy>` with supported values `center`,
|
- Add config option `<placement><policy>` with supported values `center`,
|
||||||
`cursor` and `automatic`. The latter minimizes overlap with other windows
|
`cursor` and `automatic`. The latter minimizes overlap with other windows
|
||||||
already on screen and is similar to Openbox's smart window placement.
|
already on screen and is similar to Openbox's smart window placement.
|
||||||
|
The placement policies honour `<core><gap>`.
|
||||||
Written-by: @ahesford #1312
|
Written-by: @ahesford #1312
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
|
|
@ -100,6 +124,13 @@ The format is based on [Keep a Changelog]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Delay popup-unconstrain until after first commit in response to a changed
|
||||||
|
wlroots 0.17 interface and to get rid of the error message below. Issue #1372
|
||||||
|
|
||||||
|
[types/xdg_shell/wlr_xdg_surface.c:169] A configure is scheduled for an uninitialized xdg_surface
|
||||||
|
|
||||||
|
- Notify clients about configuration errors when changing output settings.
|
||||||
|
Issue #1528.
|
||||||
- Fix output configuration bug causing compositor crash when refresh rate is
|
- Fix output configuration bug causing compositor crash when refresh rate is
|
||||||
zero. Issue #1458
|
zero. Issue #1458
|
||||||
- Fix disappearing cursor bug on view destruction. Issue #1393
|
- Fix disappearing cursor bug on view destruction. Issue #1393
|
||||||
|
|
@ -124,6 +155,8 @@ The format is based on [Keep a Changelog]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Make `MoveToCursor` honour `<core><gap>`. Issue #1494
|
||||||
|
- Add `Roll Up/Down` client-menu entry for `ToggleShade`
|
||||||
- When a Wayland-native window is snapped to a screen edges or user-defined
|
- When a Wayland-native window is snapped to a screen edges or user-defined
|
||||||
region, labwc will notify the application that it is "tiled", allowing the
|
region, labwc will notify the application that it is "tiled", allowing the
|
||||||
application to better adapt its rendering to constrained layouts. Windows
|
application to better adapt its rendering to constrained layouts. Windows
|
||||||
|
|
@ -1043,7 +1076,8 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
||||||
ShowMenu
|
ShowMenu
|
||||||
|
|
||||||
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
|
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
|
||||||
[unreleased]: https://github.com/labwc/labwc/compare/0.7.0...HEAD
|
[unreleased]: https://github.com/labwc/labwc/compare/0.7.1...HEAD
|
||||||
|
[0.7.1]: https://github.com/labwc/labwc/compare/0.7.0...0.7.1
|
||||||
[0.7.0]: https://github.com/labwc/labwc/compare/0.6.6...0.7.0
|
[0.7.0]: https://github.com/labwc/labwc/compare/0.6.6...0.7.0
|
||||||
[0.6.6]: https://github.com/labwc/labwc/compare/0.6.5...0.6.6
|
[0.6.6]: https://github.com/labwc/labwc/compare/0.6.5...0.6.6
|
||||||
[0.6.5]: https://github.com/labwc/labwc/compare/0.6.4...0.6.5
|
[0.6.5]: https://github.com/labwc/labwc/compare/0.6.4...0.6.5
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,11 @@ High-level summary of items that Labwc supports:
|
||||||
|
|
||||||
The obligatory screenshot:
|
The obligatory screenshot:
|
||||||
|
|
||||||
<a href="https://i.imgur.com/vOelinT.png">
|
<a href="https://labwc.github.io/img/scrot1.png">
|
||||||
<img src="https://i.imgur.com/vOelinTl.png">
|
<img src="https://labwc.github.io/img/scrot1-small.png">
|
||||||
|
</a><br />
|
||||||
|
<a href="https://labwc.github.io/obligatory-screenshot.html">
|
||||||
|
<small>Screenshot description</small>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
## 2. Build and Installation
|
## 2. Build and Installation
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ Actions are used in menus and keyboard/mouse bindings.
|
||||||
to the center of the window. If the given output does not contain
|
to the center of the window. If the given output does not contain
|
||||||
any windows, the cursor is centered on the given output.
|
any windows, the cursor is centered on the given output.
|
||||||
|
|
||||||
*<action name="MoveToOutput" name="HDMI-A-1" direction="value" />*
|
*<action name="MoveToOutput" name="HDMI-A-1" direction="value" wrap="no" />*
|
||||||
Moves active window to other output, unless the window state is
|
Moves active window to other output, unless the window state is
|
||||||
fullscreen.
|
fullscreen.
|
||||||
|
|
||||||
|
|
@ -172,6 +172,9 @@ Actions are used in menus and keyboard/mouse bindings.
|
||||||
be one of "left", "right", "up" or "down" to indicate that the window
|
be one of "left", "right", "up" or "down" to indicate that the window
|
||||||
should be moved to the next output in that direction (if one exists).
|
should be moved to the next output in that direction (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.
|
||||||
|
|
||||||
*<action name="FitToOutput" />*
|
*<action name="FitToOutput" />*
|
||||||
Resizes active window size to width and height of the output when the
|
Resizes active window size to width and height of the output when the
|
||||||
window size exceeds the output size.
|
window size exceeds the output size.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ labwc - configuration files
|
||||||
|
|
||||||
Labwc uses openbox-3.6 specification for configuration and theming, but does not
|
Labwc uses openbox-3.6 specification for configuration and theming, but does not
|
||||||
support all options. The following files form the basis of the labwc
|
support all options. The following files form the basis of the labwc
|
||||||
configuration: rc.xml, menu.xml, autostart and environment.
|
configuration: rc.xml, menu.xml, autostart, shutdown and environment.
|
||||||
|
|
||||||
No configuration files are needed to start and run labwc.
|
No configuration files are needed to start and run labwc.
|
||||||
|
|
||||||
|
|
@ -34,11 +34,8 @@ alternative.
|
||||||
The configuration directory location can be override with the -C command line
|
The configuration directory location can be override with the -C command line
|
||||||
option.
|
option.
|
||||||
|
|
||||||
All configuration and theme files except autostart are re-loaded on receiving
|
All configuration and theme files except autostart and shutdown are re-loaded on
|
||||||
signal SIGHUP.
|
receiving signal SIGHUP.
|
||||||
|
|
||||||
The *autostart* file is executed as a shell script. This is the place for
|
|
||||||
executing clients for handling background images, panels and similar.
|
|
||||||
|
|
||||||
The *environment* file is parsed as *variable=value* and sets environment
|
The *environment* file is parsed as *variable=value* and sets environment
|
||||||
variables accordingly. It is recommended to specify keyboard layout settings and
|
variables accordingly. It is recommended to specify keyboard layout settings and
|
||||||
|
|
@ -48,6 +45,20 @@ sourced prior to running openbox.
|
||||||
Note: Tilde (~) and environment variables in the value are expanded, but
|
Note: Tilde (~) and environment variables in the value are expanded, but
|
||||||
subshell syntax and apostrophes are ignored.
|
subshell syntax and apostrophes are ignored.
|
||||||
|
|
||||||
|
The *autostart* file is executed as a shell script after labwc has read its
|
||||||
|
configuration and set variables defined in the environment file. Additionally,
|
||||||
|
the environment variables WAYLAND_DISPLAY and (when labwc is built with Xwayland
|
||||||
|
support) DISPLAY will be defined. This is the place for executing clients for
|
||||||
|
handling background images, panels and other tasks that should run automatically
|
||||||
|
when labwc launches.
|
||||||
|
|
||||||
|
The *shutdown* file is executed as a shell script when labwc is preparing to
|
||||||
|
terminate itself. All environment variables, including WAYLAND_DISPLAY and
|
||||||
|
DISPLAY, will be available to the script. However, because the script runs
|
||||||
|
asynchronously with other termination tasks, the shutdown file should not assume
|
||||||
|
that the display will be usable. This file is useful to perform any custom
|
||||||
|
operations necessary to finalize a labwc session.
|
||||||
|
|
||||||
The *menu.xml* file defines the context/root-menus and is described in
|
The *menu.xml* file defines the context/root-menus and is described in
|
||||||
labwc-menu(5).
|
labwc-menu(5).
|
||||||
|
|
||||||
|
|
@ -511,7 +522,7 @@ extending outward from the snapped edge.
|
||||||
```
|
```
|
||||||
|
|
||||||
*<touch deviceName="" />*
|
*<touch deviceName="" />*
|
||||||
A touch configuration can be bound to a specifc device. If device
|
A touch configuration can be bound to a specific device. If device
|
||||||
name is left empty, the touch configuration applies to all touch
|
name is left empty, the touch configuration applies to all touch
|
||||||
devices or functions as a fallback. Multiple touch configurations
|
devices or functions as a fallback. Multiple touch configurations
|
||||||
can exist.
|
can exist.
|
||||||
|
|
@ -592,6 +603,8 @@ extending outward from the snapped edge.
|
||||||
<dragLock></dragLock>
|
<dragLock></dragLock>
|
||||||
<middleEmulation></middleEmulation>
|
<middleEmulation></middleEmulation>
|
||||||
<disableWhileTyping></disableWhileTyping>
|
<disableWhileTyping></disableWhileTyping>
|
||||||
|
<clickMethod></clickMethod>
|
||||||
|
<sendEventsMode></sendEventsMode>
|
||||||
</device>
|
</device>
|
||||||
</libinput>
|
</libinput>
|
||||||
```
|
```
|
||||||
|
|
@ -667,6 +680,36 @@ extending outward from the snapped edge.
|
||||||
any motion events while a keyboard is typing, and for a short while
|
any motion events while a keyboard is typing, and for a short while
|
||||||
after as well.
|
after as well.
|
||||||
|
|
||||||
|
*<libinput><device><clickMethod>* [none|buttonAreas|clickfinger]
|
||||||
|
Configure the method by which physical clicks on a touchpad are mapped to
|
||||||
|
mouse-button events.
|
||||||
|
|
||||||
|
The click methods available are:
|
||||||
|
- *buttonAreas* - The bottom of the touchpad is divided into distinct
|
||||||
|
regions corresponding to left, middle and right buttons; clicking within
|
||||||
|
the region will trigger the corresponding event. Clicking the main area
|
||||||
|
further up produces a left button event.
|
||||||
|
- *clickfinger* - Clicking with one, two or three finger(s) will produce
|
||||||
|
left, right or middle button event without regard to the location of a
|
||||||
|
click.
|
||||||
|
- *none* - Physical clicks will not produce button events.
|
||||||
|
|
||||||
|
The default method depends on the touchpad hardware.
|
||||||
|
|
||||||
|
*<libinput><device><sendEventsMode>* [yes|no|disabledOnExternalMouse]
|
||||||
|
Optionally enable or disable sending any device events.
|
||||||
|
|
||||||
|
The options available are:
|
||||||
|
- *yes* - Events are sent as usual
|
||||||
|
- *no* - No events are sent from this device
|
||||||
|
- *disabledOnExternalMouse* - This device does not send events if an
|
||||||
|
external mouse has been detected.
|
||||||
|
|
||||||
|
It is possible to prevent events from a device in the config and then do
|
||||||
|
a Reconfigure to temporarily enable / disable specific devices.
|
||||||
|
|
||||||
|
By default, this setting is not configured.
|
||||||
|
|
||||||
## WINDOW RULES
|
## WINDOW RULES
|
||||||
|
|
||||||
Two types of window rules are supported, actions and properties. They are
|
Two types of window rules are supported, actions and properties. They are
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ labwc(1)
|
||||||
|
|
||||||
# NAME
|
# NAME
|
||||||
|
|
||||||
labwc - a wayland stacking compositor
|
labwc - a Wayland stacking compositor
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
|
|
@ -16,8 +16,10 @@ It is light-weight and independent with a focus on simply stacking windows
|
||||||
well and rendering some window decorations. Where practicable it uses clients
|
well and rendering some window decorations. Where practicable it uses clients
|
||||||
for wall-paper, panels, screenshots and so on.
|
for wall-paper, panels, screenshots and so on.
|
||||||
|
|
||||||
|
# SIGNALS
|
||||||
|
|
||||||
The compositor will exit or reload its configuration upon receiving SIGTERM
|
The compositor will exit or reload its configuration upon receiving SIGTERM
|
||||||
and SIGHUP respectively. For example:
|
and SIGHUP respectively. For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
kill -s <signal> $LABWC_PID
|
kill -s <signal> $LABWC_PID
|
||||||
|
|
@ -40,7 +42,7 @@ the `--exit` and `--reconfigure` options use.
|
||||||
Enable full logging, including debug information
|
Enable full logging, including debug information
|
||||||
|
|
||||||
*-e, --exit*
|
*-e, --exit*
|
||||||
Exit the compositor
|
Exit the compositor by sending SIGTERM to `$LABWC_PID`
|
||||||
|
|
||||||
*-h, --help*
|
*-h, --help*
|
||||||
Show help message and quit
|
Show help message and quit
|
||||||
|
|
@ -49,7 +51,7 @@ the `--exit` and `--reconfigure` options use.
|
||||||
Merge user config/theme files in all XDG Base Directories
|
Merge user config/theme files in all XDG Base Directories
|
||||||
|
|
||||||
*-r, --reconfigure*
|
*-r, --reconfigure*
|
||||||
Reload the compositor configuration
|
Reload the compositor configuration by sending SIGHUP to `$LABWC_PID`
|
||||||
|
|
||||||
*-s, --startup* <command>
|
*-s, --startup* <command>
|
||||||
Run command on startup
|
Run command on startup
|
||||||
|
|
@ -60,6 +62,48 @@ the `--exit` and `--reconfigure` options use.
|
||||||
*-V, --verbose*
|
*-V, --verbose*
|
||||||
Enable more verbose logging
|
Enable more verbose logging
|
||||||
|
|
||||||
|
# SESSION MANAGEMENT
|
||||||
|
|
||||||
|
To enable the use of graphical clients launched via D-Bus or systemd servie
|
||||||
|
activation, labwc can update both activation environments on launch. Provided
|
||||||
|
that labwc is aware of an active D-Bus user session (*i.e.*, the environment
|
||||||
|
variable `DBUS_SESSION_BUS_ADDRESS` is defined), the compositor will invoke the
|
||||||
|
commands
|
||||||
|
|
||||||
|
```
|
||||||
|
dbus-update-activation-environment
|
||||||
|
systemctl --user import-environment
|
||||||
|
```
|
||||||
|
|
||||||
|
(when available) to notify D-Bus and systemd with the values of the following
|
||||||
|
environment variables:
|
||||||
|
|
||||||
|
```
|
||||||
|
WAYLAND_DISPLAY
|
||||||
|
DISPLAY
|
||||||
|
XDG_CURRENT_DESKTOP
|
||||||
|
XDG_SESSION_TYPE
|
||||||
|
XCURSOR_SIZE
|
||||||
|
XCURSOR_THEME
|
||||||
|
LABWC_PWD
|
||||||
|
```
|
||||||
|
|
||||||
|
This behavior is enabled by default whenever labwc uses the "DRM" wlroots
|
||||||
|
backend (which implies that labwc is the primary compositor on the console).
|
||||||
|
When other backends are employed (for example, when labwc runs nested in another
|
||||||
|
Wayland compositor or an X11 server), updates to the activation environment are
|
||||||
|
disabled by default. Updates to the activation environment can be forced by
|
||||||
|
setting the environment variable `LABWC_UPDATE_ACTIVATION_ENV` to one of the
|
||||||
|
truthy values `1`, `true`, `yes` or `on`; or suppressed by setting the variable
|
||||||
|
to one of the falsy values `0`, `false`, `no` or `off`.
|
||||||
|
|
||||||
|
Whenever labwc updates the activation environment on launch, it will also
|
||||||
|
attempt to clear the activation environment on exit. For D-Bus, which does not
|
||||||
|
provide a means for properly un-setting variables in the activation environment,
|
||||||
|
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.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
labwc-config(5), labwc-theme(5), labwc-actions(5)
|
labwc-actions(5), labwc-config(5), labwc-menu(5), labwc-theme(5)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,6 @@
|
||||||
|
|
||||||
<labwc_config>
|
<labwc_config>
|
||||||
|
|
||||||
<core>
|
|
||||||
<gap>10</gap>
|
|
||||||
</core>
|
|
||||||
|
|
||||||
<theme>
|
<theme>
|
||||||
<name></name>
|
<name></name>
|
||||||
<cornerRadius>8</cornerRadius>
|
<cornerRadius>8</cornerRadius>
|
||||||
|
|
|
||||||
|
|
@ -465,13 +465,15 @@
|
||||||
non-touch, default or the name of a device. You can obtain device names by
|
non-touch, default or the name of a device. You can obtain device names by
|
||||||
running *libinput list-devices* as root or member of the input group.
|
running *libinput list-devices* as root or member of the input group.
|
||||||
|
|
||||||
Tap is set to *yes* be default. All others are left blank in order to use
|
Tap is set to *yes* by default. All others are left blank in order to use
|
||||||
device defaults.
|
device defaults.
|
||||||
|
|
||||||
All values are [yes|no] except for:
|
All values are [yes|no] except for:
|
||||||
- pointerSpeed [-1.0 to 1.0]
|
- pointerSpeed [-1.0 to 1.0]
|
||||||
- accelProfile [flat|adaptive]
|
- accelProfile [flat|adaptive]
|
||||||
- tapButtonMap [lrm|lmr]
|
- tapButtonMap [lrm|lmr]
|
||||||
|
- clickMethod [none|buttonAreas|clickfinger]
|
||||||
|
- sendEventsMode [yes|no|disabledOnExternalMouse]
|
||||||
-->
|
-->
|
||||||
<libinput>
|
<libinput>
|
||||||
<device category="default">
|
<device category="default">
|
||||||
|
|
@ -485,6 +487,8 @@
|
||||||
<dragLock></dragLock>
|
<dragLock></dragLock>
|
||||||
<middleEmulation></middleEmulation>
|
<middleEmulation></middleEmulation>
|
||||||
<disableWhileTyping></disableWhileTyping>
|
<disableWhileTyping></disableWhileTyping>
|
||||||
|
<clickMethod></clickMethod>
|
||||||
|
<sendEventsMode></sendEventsMode>
|
||||||
</device>
|
</device>
|
||||||
</libinput>
|
</libinput>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,23 @@ void string_truncate_at_pattern(char *buf, const char *pattern);
|
||||||
*/
|
*/
|
||||||
char *strdup_printf(const char *fmt, ...);
|
char *strdup_printf(const char *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* str_join - format and join an array of strings with a separator
|
||||||
|
* @parts: NULL-terminated array of string parts to be joined
|
||||||
|
* @fmt: printf-style format string applied to each part
|
||||||
|
* @sep: separator inserted between parts when joining
|
||||||
|
*
|
||||||
|
* A new string is allocated to hold the joined result. The user must free the
|
||||||
|
* returned string. Returns NULL on error.
|
||||||
|
*
|
||||||
|
* Each part of the array is converted via the equivalent of sprintf(output,
|
||||||
|
* fmt, part), so fmt should include a single "%s" format specification. If fmt
|
||||||
|
* is NULL, a default "%s" will be used to copy each part verbatim.
|
||||||
|
*
|
||||||
|
* The separator is arbitrary. When the separator is NULL, a single space will
|
||||||
|
* be used.
|
||||||
|
*/
|
||||||
|
char *str_join(const char * const parts[],
|
||||||
|
const char *restrict fmt, const char *restrict sep);
|
||||||
|
|
||||||
#endif /* LABWC_STRING_HELPERS_H */
|
#endif /* LABWC_STRING_HELPERS_H */
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,13 @@ struct libinput_category {
|
||||||
int left_handed;
|
int left_handed;
|
||||||
enum libinput_config_tap_state tap;
|
enum libinput_config_tap_state tap;
|
||||||
enum libinput_config_tap_button_map tap_button_map;
|
enum libinput_config_tap_button_map tap_button_map;
|
||||||
int tap_and_drag; /* -1 or libinput_config_drag_state */
|
int tap_and_drag; /* -1 or libinput_config_drag_state */
|
||||||
int drag_lock; /* -1 or libinput_config_drag_lock_state */
|
int drag_lock; /* -1 or libinput_config_drag_lock_state */
|
||||||
int accel_profile; /* -1 or libinput_config_accel_profile */
|
int accel_profile; /* -1 or libinput_config_accel_profile */
|
||||||
int middle_emu; /* -1 or libinput_config_middle_emulation_state */
|
int middle_emu; /* -1 or libinput_config_middle_emulation_state */
|
||||||
int dwt; /* -1 or libinput_config_dwt_state */
|
int dwt; /* -1 or libinput_config_dwt_state */
|
||||||
|
int click_method; /* -1 or libinput_config_click_method */
|
||||||
|
int send_events_mode; /* -1 or libinput_config_send_events_mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lab_libinput_device_type get_device_type(const char *s);
|
enum lab_libinput_device_type get_device_type(const char *s);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#ifndef LABWC_SESSION_H
|
#ifndef LABWC_SESSION_H
|
||||||
#define LABWC_SESSION_H
|
#define LABWC_SESSION_H
|
||||||
|
|
||||||
|
struct server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* session_environment_init - set enrivonment variables based on <key>=<value>
|
* session_environment_init - set enrivonment variables based on <key>=<value>
|
||||||
* pairs in `${XDG_CONFIG_DIRS:-/etc/xdg}/lawbc/environment` with user override
|
* pairs in `${XDG_CONFIG_DIRS:-/etc/xdg}/lawbc/environment` with user override
|
||||||
|
|
@ -13,6 +15,12 @@ void session_environment_init(void);
|
||||||
* session_autostart_init - run autostart file as shell script
|
* session_autostart_init - run autostart file as shell script
|
||||||
* Note: Same as `sh ~/.config/labwc/autostart` (or equivalent XDG config dir)
|
* Note: Same as `sh ~/.config/labwc/autostart` (or equivalent XDG config dir)
|
||||||
*/
|
*/
|
||||||
void session_autostart_init(void);
|
void session_autostart_init(struct server *server);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
#endif /* LABWC_SESSION_H */
|
#endif /* LABWC_SESSION_H */
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,15 @@
|
||||||
#define LABWC_EDGES_H
|
#define LABWC_EDGES_H
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
|
|
||||||
struct border;
|
struct border;
|
||||||
struct output;
|
struct output;
|
||||||
|
struct server;
|
||||||
struct view;
|
struct view;
|
||||||
|
struct wlr_box;
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
clipped_add(int a, int b)
|
clipped_add(int a, int b)
|
||||||
|
|
@ -102,7 +106,7 @@ void edges_adjust_geom(struct view *view, struct border edges,
|
||||||
|
|
||||||
void edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
void edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
||||||
struct wlr_box target, struct output *output,
|
struct wlr_box target, struct output *output,
|
||||||
edge_validator_t validator, bool use_pending);
|
edge_validator_t validator, bool use_pending, bool ignore_hidden);
|
||||||
|
|
||||||
void edges_find_outputs(struct border *nearest_edges, struct view *view,
|
void edges_find_outputs(struct border *nearest_edges, struct view *view,
|
||||||
struct wlr_box target, struct output *output,
|
struct wlr_box target, struct output *output,
|
||||||
|
|
@ -116,4 +120,5 @@ void edges_adjust_resize_geom(struct view *view, struct border edges,
|
||||||
|
|
||||||
bool edges_traverse_edge(struct edge current, struct edge target, struct edge edge);
|
bool edges_traverse_edge(struct edge current, struct edge target, struct edge edge);
|
||||||
|
|
||||||
|
void edges_calculate_visibility(struct server *server, struct view *ignored_view);
|
||||||
#endif /* LABWC_EDGES_H */
|
#endif /* LABWC_EDGES_H */
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ struct lab_layer_popup {
|
||||||
/* To simplify moving popup nodes from the bottom to the top layer */
|
/* To simplify moving popup nodes from the bottom to the top layer */
|
||||||
struct wlr_box output_toplevel_sx_box;
|
struct wlr_box output_toplevel_sx_box;
|
||||||
|
|
||||||
|
struct wl_listener commit;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener new_popup;
|
struct wl_listener new_popup;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ struct view {
|
||||||
bool tearing_hint;
|
bool tearing_hint;
|
||||||
bool visible_on_all_workspaces;
|
bool visible_on_all_workspaces;
|
||||||
enum view_edge tiled;
|
enum view_edge tiled;
|
||||||
|
uint32_t edges_visible; /* enum wlr_edges bitset */
|
||||||
bool inhibits_keybinds;
|
bool inhibits_keybinds;
|
||||||
xkb_layout_index_t keyboard_layout;
|
xkb_layout_index_t keyboard_layout;
|
||||||
|
|
||||||
|
|
@ -502,7 +503,8 @@ void view_on_output_destroy(struct view *view);
|
||||||
void view_connect_map(struct view *view, struct wlr_surface *surface);
|
void view_connect_map(struct view *view, struct wlr_surface *surface);
|
||||||
void view_destroy(struct view *view);
|
void view_destroy(struct view *view);
|
||||||
|
|
||||||
struct output *view_get_adjacent_output(struct view *view, enum view_edge edge);
|
struct output *view_get_adjacent_output(struct view *view, enum view_edge edge,
|
||||||
|
bool wrap);
|
||||||
enum view_axis view_axis_parse(const char *direction);
|
enum view_axis view_axis_parse(const char *direction);
|
||||||
enum view_edge view_edge_parse(const char *direction);
|
enum view_edge view_edge_parse(const char *direction);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'labwc',
|
'labwc',
|
||||||
'c',
|
'c',
|
||||||
version: '0.7.0',
|
version: '0.7.1',
|
||||||
license: 'GPL-2.0-only',
|
license: 'GPL-2.0-only',
|
||||||
meson_version: '>=0.59.0',
|
meson_version: '>=0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
de es et eu fi gl id it ja ka lt nl pa pl pt ru sv tr uk zh_CN
|
cs de es et eu fi gl hu id it ja ka lt nl pa pl pt ru sv tr uk zh_CN
|
||||||
|
|
|
||||||
69
po/cs.po
Normal file
69
po/cs.po
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Labwc pot file
|
||||||
|
# Copyright (C) 2024
|
||||||
|
# This file is distributed under the same license as the labwc package.
|
||||||
|
# zenobit <zenobit@disroot.org>, 2024.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: labwc\n"
|
||||||
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
|
"PO-Revision-Date: 2024-03-02 02:00+0100\n"
|
||||||
|
"Last-Translator: zenobit <zenobit@disroot.org>\n"
|
||||||
|
"Language-Team: Czech <zenobit@disroot.org>\n"
|
||||||
|
"Language: cs\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:697
|
||||||
|
msgid "Reconfigure"
|
||||||
|
msgstr "Překonfigurovat"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:699
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Odejít"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:715
|
||||||
|
msgid "Minimize"
|
||||||
|
msgstr "Minimalizovat"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:717
|
||||||
|
msgid "Maximize"
|
||||||
|
msgstr "Maximalizovat"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:719
|
||||||
|
msgid "Fullscreen"
|
||||||
|
msgstr "Na celou obrazovku"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:721
|
||||||
|
msgid "Roll up/down"
|
||||||
|
msgstr "Rolovat nahoru/dolů"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:723
|
||||||
|
msgid "Decorations"
|
||||||
|
msgstr "Dekorace"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:725
|
||||||
|
msgid "Always on Top"
|
||||||
|
msgstr "Vždy nahoře"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:730
|
||||||
|
msgid "Move left"
|
||||||
|
msgstr "Posunout doleva"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:737
|
||||||
|
msgid "Move right"
|
||||||
|
msgstr "Posunout doprava"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:742
|
||||||
|
msgid "Always on Visible Workspace"
|
||||||
|
msgstr "Vždy na viditelné Pracovní Ploše"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:745
|
||||||
|
msgid "Workspace"
|
||||||
|
msgstr "Pracovní Plocha"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:748
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Zavřít"
|
||||||
11
po/fi.po
11
po/fi.po
|
|
@ -8,13 +8,16 @@ msgstr ""
|
||||||
"Project-Id-Version: labwc\n"
|
"Project-Id-Version: labwc\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2024-02-29 14:23+0000\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Jouni Järvinen <jounijarvis@gmail.com>\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: Finnish <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/fi/>\n"
|
||||||
"Language: fi\n"
|
"Language: fi\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\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:697
|
#: src/menu/menu.c:697
|
||||||
msgid "Reconfigure"
|
msgid "Reconfigure"
|
||||||
|
|
@ -22,7 +25,7 @@ msgstr ""
|
||||||
|
|
||||||
#: src/menu/menu.c:699
|
#: src/menu/menu.c:699
|
||||||
msgid "Exit"
|
msgid "Exit"
|
||||||
msgstr ""
|
msgstr "Poistu"
|
||||||
|
|
||||||
#: src/menu/menu.c:715
|
#: src/menu/menu.c:715
|
||||||
msgid "Minimize"
|
msgid "Minimize"
|
||||||
|
|
|
||||||
72
po/hu.po
Normal file
72
po/hu.po
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
# 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-01-15 16:00-0500\n"
|
||||||
|
"PO-Revision-Date: 2024-02-19 21:23+0000\n"
|
||||||
|
"Last-Translator: winerysearch <david.fitala@gmail.com>\n"
|
||||||
|
"Language-Team: Hungarian <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/hu/>\n"
|
||||||
|
"Language: hu\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:697
|
||||||
|
msgid "Reconfigure"
|
||||||
|
msgstr "Rekonfigurál"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:699
|
||||||
|
msgid "Exit"
|
||||||
|
msgstr "Kilépés"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:715
|
||||||
|
msgid "Minimize"
|
||||||
|
msgstr "Kis méret"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:717
|
||||||
|
msgid "Maximize"
|
||||||
|
msgstr "Teljes méret"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:719
|
||||||
|
msgid "Fullscreen"
|
||||||
|
msgstr "Teljes képernyő"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:721
|
||||||
|
msgid "Roll up/down"
|
||||||
|
msgstr "Felhúz / Legördül"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:723
|
||||||
|
msgid "Decorations"
|
||||||
|
msgstr "Dekorációk"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:725
|
||||||
|
msgid "Always on Top"
|
||||||
|
msgstr "Mindig felül"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:730
|
||||||
|
msgid "Move left"
|
||||||
|
msgstr "Balra dokkol"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:737
|
||||||
|
msgid "Move right"
|
||||||
|
msgstr "Jobbra dokkol"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:742
|
||||||
|
msgid "Always on Visible Workspace"
|
||||||
|
msgstr "Kitűz"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:745
|
||||||
|
msgid "Workspace"
|
||||||
|
msgstr "Munkaasztal"
|
||||||
|
|
||||||
|
#: src/menu/menu.c:748
|
||||||
|
msgid "Close"
|
||||||
|
msgstr "Bezárás"
|
||||||
11
po/lt.po
11
po/lt.po
|
|
@ -8,14 +8,17 @@ msgstr ""
|
||||||
"Project-Id-Version: labwc\n"
|
"Project-Id-Version: labwc\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
"PO-Revision-Date: 2024-01-04 15:23+0000\n"
|
"PO-Revision-Date: 2024-02-29 14:23+0000\n"
|
||||||
"Last-Translator: Moo <hazap@hotmail.com>\n"
|
"Last-Translator: Moo <hazap@hotmail.com>\n"
|
||||||
"Language-Team: Lithuanian <https://translate.lxqt-project.org/projects/labwc/labwc/lt/>\n"
|
"Language-Team: Lithuanian <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/lt/>\n"
|
||||||
"Language: lt\n"
|
"Language: lt\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? 1 : 2);\n"
|
"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > "
|
||||||
|
"19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? "
|
||||||
|
"1 : 2);\n"
|
||||||
"X-Generator: Weblate 4.2.1\n"
|
"X-Generator: Weblate 4.2.1\n"
|
||||||
|
|
||||||
#: src/menu/menu.c:697
|
#: src/menu/menu.c:697
|
||||||
|
|
@ -40,7 +43,7 @@ msgstr "Visas ekranas"
|
||||||
|
|
||||||
#: src/menu/menu.c:721
|
#: src/menu/menu.c:721
|
||||||
msgid "Roll up/down"
|
msgid "Roll up/down"
|
||||||
msgstr ""
|
msgstr "Užraityti/atraityti"
|
||||||
|
|
||||||
#: src/menu/menu.c:723
|
#: src/menu/menu.c:723
|
||||||
msgid "Decorations"
|
msgid "Decorations"
|
||||||
|
|
|
||||||
7
po/pa.po
7
po/pa.po
|
|
@ -8,9 +8,10 @@ msgstr ""
|
||||||
"Project-Id-Version: labwc\n"
|
"Project-Id-Version: labwc\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
"PO-Revision-Date: 2023-12-26 07:23+0000\n"
|
"PO-Revision-Date: 2024-02-21 14:23+0000\n"
|
||||||
"Last-Translator: A S Alam <amanpreet.alam@gmail.com>\n"
|
"Last-Translator: A S Alam <amanpreet.alam@gmail.com>\n"
|
||||||
"Language-Team: Punjabi <https://translate.lxqt-project.org/projects/labwc/labwc/pa/>\n"
|
"Language-Team: Punjabi <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/pa/>\n"
|
||||||
"Language: pa\n"
|
"Language: pa\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
|
@ -40,7 +41,7 @@ msgstr "ਪੂਰੀ ਸਕਰੀਨ"
|
||||||
|
|
||||||
#: src/menu/menu.c:721
|
#: src/menu/menu.c:721
|
||||||
msgid "Roll up/down"
|
msgid "Roll up/down"
|
||||||
msgstr ""
|
msgstr "ਉੱਤੇ/ਹੇਠਾਂ ਸਕਰਾਓ"
|
||||||
|
|
||||||
#: src/menu/menu.c:723
|
#: src/menu/menu.c:723
|
||||||
msgid "Decorations"
|
msgid "Decorations"
|
||||||
|
|
|
||||||
5
po/ru.po
5
po/ru.po
|
|
@ -8,8 +8,8 @@ msgstr ""
|
||||||
"Project-Id-Version: labwc\n"
|
"Project-Id-Version: labwc\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
"PO-Revision-Date: 2024-01-30 08:23+0000\n"
|
"PO-Revision-Date: 2024-02-26 12:23+0000\n"
|
||||||
"Last-Translator: pixis1 <vaninpixel89@gmail.com>\n"
|
"Last-Translator: Alice Ventus <zolkin.ag@phystech.edu>\n"
|
||||||
"Language-Team: Russian <https://translate.lxqt-project.org/projects/labwc/"
|
"Language-Team: Russian <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
"labwc/ru/>\n"
|
"labwc/ru/>\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
|
|
@ -41,7 +41,6 @@ msgid "Fullscreen"
|
||||||
msgstr "На весь экран"
|
msgstr "На весь экран"
|
||||||
|
|
||||||
#: src/menu/menu.c:721
|
#: src/menu/menu.c:721
|
||||||
#, fuzzy
|
|
||||||
msgid "Roll up/down"
|
msgid "Roll up/down"
|
||||||
msgstr "Свернуть/развернуть в заголовок"
|
msgstr "Свернуть/развернуть в заголовок"
|
||||||
|
|
||||||
|
|
|
||||||
7
po/tr.po
7
po/tr.po
|
|
@ -8,9 +8,10 @@ msgstr ""
|
||||||
"Project-Id-Version: labwc\n"
|
"Project-Id-Version: labwc\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
|
||||||
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
|
||||||
"PO-Revision-Date: 2023-12-26 09:00+0000\n"
|
"PO-Revision-Date: 2024-02-24 22:23+0000\n"
|
||||||
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
|
"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n"
|
||||||
"Language-Team: Turkish <https://translate.lxqt-project.org/projects/labwc/labwc/tr/>\n"
|
"Language-Team: Turkish <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/tr/>\n"
|
||||||
"Language: tr\n"
|
"Language: tr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
|
@ -40,7 +41,7 @@ msgstr "Tam Ekran"
|
||||||
|
|
||||||
#: src/menu/menu.c:721
|
#: src/menu/menu.c:721
|
||||||
msgid "Roll up/down"
|
msgid "Roll up/down"
|
||||||
msgstr ""
|
msgstr "Yukarı/aşağı katla"
|
||||||
|
|
||||||
#: src/menu/menu.c:723
|
#: src/menu/menu.c:723
|
||||||
msgid "Decorations"
|
msgid "Decorations"
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ server_protocols = [
|
||||||
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.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/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/tearing-control/tearing-control-v1.xml',
|
||||||
'wlr-layer-shell-unstable-v1.xml',
|
'wlr-layer-shell-unstable-v1.xml',
|
||||||
'wlr-input-inhibitor-unstable-v1.xml',
|
'wlr-input-inhibitor-unstable-v1.xml',
|
||||||
|
|
|
||||||
13
src/action.c
13
src/action.c
|
|
@ -397,6 +397,10 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
|
||||||
}
|
}
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(argument, "wrap")) {
|
||||||
|
action_arg_add_bool(action, argument, parse_bool(content, false));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_TYPE_VIRTUAL_OUTPUT_ADD:
|
case ACTION_TYPE_VIRTUAL_OUTPUT_ADD:
|
||||||
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
|
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
|
||||||
|
|
@ -924,10 +928,15 @@ actions_run(struct view *activator, struct server *server,
|
||||||
} else {
|
} else {
|
||||||
/* Config parsing makes sure that direction is a valid direction */
|
/* Config parsing makes sure that direction is a valid direction */
|
||||||
enum view_edge edge = action_get_int(action, "direction", 0);
|
enum view_edge edge = action_get_int(action, "direction", 0);
|
||||||
target = view_get_adjacent_output(view, edge);
|
bool wrap = action_get_bool(action, "wrap", false);
|
||||||
|
target = view_get_adjacent_output(view, edge, wrap);
|
||||||
}
|
}
|
||||||
if (!target) {
|
if (!target) {
|
||||||
wlr_log(WLR_ERROR, "Invalid output.");
|
/*
|
||||||
|
* Most likely because we're already on the
|
||||||
|
* output furthest in the requested direction.
|
||||||
|
*/
|
||||||
|
wlr_log(WLR_DEBUG, "Invalid output");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
view_move_to_output(view, target);
|
view_move_to_output(view, target);
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,16 @@ parse_bool(const char *str, int default_value)
|
||||||
return true;
|
return true;
|
||||||
} else if (!strcasecmp(str, "on")) {
|
} else if (!strcasecmp(str, "on")) {
|
||||||
return true;
|
return true;
|
||||||
|
} else if (!strcmp(str, "1")) {
|
||||||
|
return true;
|
||||||
} else if (!strcasecmp(str, "no")) {
|
} else if (!strcasecmp(str, "no")) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!strcasecmp(str, "false")) {
|
} else if (!strcasecmp(str, "false")) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!strcasecmp(str, "off")) {
|
} else if (!strcasecmp(str, "off")) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (!strcmp(str, "0")) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
error_not_a_boolean:
|
error_not_a_boolean:
|
||||||
wlr_log(WLR_ERROR, "(%s) is not a boolean value", str);
|
wlr_log(WLR_ERROR, "(%s) is not a boolean value", str);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -83,3 +84,73 @@ strdup_printf(const char *fmt, ...)
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
str_join(const char * const parts[],
|
||||||
|
const char *restrict fmt, const char *restrict sep)
|
||||||
|
{
|
||||||
|
assert(parts);
|
||||||
|
|
||||||
|
if (!fmt) {
|
||||||
|
fmt = "%s";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sep) {
|
||||||
|
sep = " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = 0;
|
||||||
|
size_t n_parts = 0;
|
||||||
|
|
||||||
|
size_t sep_len = strlen(sep);
|
||||||
|
|
||||||
|
/* Count the length of each formatted string */
|
||||||
|
for (const char *const *s = parts; *s; ++s) {
|
||||||
|
int n = snprintf(NULL, 0, fmt, *s);
|
||||||
|
if (n < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size += (size_t)n;
|
||||||
|
++n_parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_parts < 1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need (n_parts - 1) separators, plus one NULL terminator */
|
||||||
|
size += (n_parts - 1) * sep_len + 1;
|
||||||
|
|
||||||
|
/* Concatenate the strings and separators */
|
||||||
|
char *buf = xzalloc(size);
|
||||||
|
char *p = buf;
|
||||||
|
for (const char *const *s = parts; *s; ++s) {
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (p != buf) {
|
||||||
|
n = snprintf(p, size, "%s", sep);
|
||||||
|
if (n < 0 || (size_t)n >= size) {
|
||||||
|
p = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size -= (size_t)n;
|
||||||
|
p += (size_t)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = snprintf(p, size, fmt, *s);
|
||||||
|
if (n < 0 || (size_t)n >= size) {
|
||||||
|
p = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size -= (size_t)n;
|
||||||
|
p += (size_t)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p) {
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ libinput_category_init(struct libinput_category *l)
|
||||||
l->accel_profile = -1;
|
l->accel_profile = -1;
|
||||||
l->middle_emu = -1;
|
l->middle_emu = -1;
|
||||||
l->dwt = -1;
|
l->dwt = -1;
|
||||||
|
l->click_method = -1;
|
||||||
|
l->send_events_mode = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum lab_libinput_device_type
|
enum lab_libinput_device_type
|
||||||
|
|
|
||||||
|
|
@ -461,6 +461,29 @@ get_accel_profile(const char *s)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_send_events_mode(const char *s)
|
||||||
|
{
|
||||||
|
if (!s) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = parse_bool(s, -1);
|
||||||
|
if (ret >= 0) {
|
||||||
|
return ret
|
||||||
|
? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||||
|
: LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(s, "disabledOnExternalMouse")) {
|
||||||
|
return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
wlr_log(WLR_INFO, "Not a recognised send events mode");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_libinput_category(char *nodename, char *content)
|
fill_libinput_category(char *nodename, char *content)
|
||||||
{
|
{
|
||||||
|
|
@ -563,6 +586,22 @@ fill_libinput_category(char *nodename, char *content)
|
||||||
current_libinput_category->dwt = ret
|
current_libinput_category->dwt = ret
|
||||||
? LIBINPUT_CONFIG_DWT_ENABLED
|
? LIBINPUT_CONFIG_DWT_ENABLED
|
||||||
: LIBINPUT_CONFIG_DWT_DISABLED;
|
: LIBINPUT_CONFIG_DWT_DISABLED;
|
||||||
|
} else if (!strcasecmp(nodename, "clickMethod")) {
|
||||||
|
if (!strcasecmp(content, "none")) {
|
||||||
|
current_libinput_category->click_method =
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_NONE;
|
||||||
|
} else if (!strcasecmp(content, "clickfinger")) {
|
||||||
|
current_libinput_category->click_method =
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
|
||||||
|
} else if (!strcasecmp(content, "buttonAreas")) {
|
||||||
|
current_libinput_category->click_method =
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "invalid clickMethod");
|
||||||
|
}
|
||||||
|
} else if (!strcasecmp(nodename, "sendEventsMode")) {
|
||||||
|
current_libinput_category->send_events_mode =
|
||||||
|
get_send_events_mode(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,35 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <wlr/backend/drm.h>
|
||||||
|
#include <wlr/backend/multi.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "common/buf.h"
|
#include "common/buf.h"
|
||||||
#include "common/dir.h"
|
#include "common/dir.h"
|
||||||
#include "common/file-helpers.h"
|
#include "common/file-helpers.h"
|
||||||
|
#include "common/mem.h"
|
||||||
|
#include "common/parse-bool.h"
|
||||||
#include "common/spawn.h"
|
#include "common/spawn.h"
|
||||||
#include "common/string-helpers.h"
|
#include "common/string-helpers.h"
|
||||||
#include "config/session.h"
|
#include "config/session.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
|
|
||||||
|
static const char *const env_vars[] = {
|
||||||
|
"DISPLAY",
|
||||||
|
"WAYLAND_DISPLAY",
|
||||||
|
"XDG_CURRENT_DESKTOP",
|
||||||
|
"XCURSOR_SIZE",
|
||||||
|
"XCURSOR_THEME",
|
||||||
|
"XDG_SESSION_TYPE",
|
||||||
|
"LABWC_PID",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_line(char *line)
|
process_line(char *line)
|
||||||
{
|
{
|
||||||
|
|
@ -65,23 +81,71 @@ read_environment_file(const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_activation_env(const char *env_keys)
|
backend_check_drm(struct wlr_backend *backend, void *is_drm)
|
||||||
{
|
{
|
||||||
|
if (wlr_backend_is_drm(backend)) {
|
||||||
|
*(bool *)is_drm = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
should_update_activation(struct server *server)
|
||||||
|
{
|
||||||
|
assert(server);
|
||||||
|
|
||||||
|
static const char *act_env = "LABWC_UPDATE_ACTIVATION_ENV";
|
||||||
|
char *env = getenv(act_env);
|
||||||
|
if (env) {
|
||||||
|
/* Respect any valid preference from the environment */
|
||||||
|
int enabled = parse_bool(env, -1);
|
||||||
|
|
||||||
|
if (enabled == -1) {
|
||||||
|
wlr_log(WLR_ERROR, "ignoring non-Boolean variable %s", act_env);
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_DEBUG, "%s is %s",
|
||||||
|
act_env, enabled ? "true" : "false");
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
return have_drm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_activation_env(struct server *server, bool initialize)
|
||||||
|
{
|
||||||
|
if (!should_update_activation(server)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!getenv("DBUS_SESSION_BUS_ADDRESS")) {
|
if (!getenv("DBUS_SESSION_BUS_ADDRESS")) {
|
||||||
/* Prevent accidentally auto-launching a dbus session */
|
/* Prevent accidentally auto-launching a dbus session */
|
||||||
wlr_log(WLR_INFO, "Not updating dbus execution environment: "
|
wlr_log(WLR_INFO, "Not updating dbus execution environment: "
|
||||||
"DBUS_SESSION_BUS_ADDRESS not set");
|
"DBUS_SESSION_BUS_ADDRESS not set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_log(WLR_INFO, "Updating dbus execution environment");
|
wlr_log(WLR_INFO, "Updating dbus execution environment");
|
||||||
|
|
||||||
char *cmd = strdup_printf("dbus-update-activation-environment %s", env_keys);
|
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);
|
spawn_async_no_shell(cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
||||||
cmd = strdup_printf("systemctl --user import-environment %s", env_keys);
|
cmd = strdup_printf("systemctl --user %s %s",
|
||||||
|
initialize ? "import-environment" : "unset-environment", env_keys);
|
||||||
spawn_async_no_shell(cmd);
|
spawn_async_no_shell(cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
||||||
|
free(env_keys);
|
||||||
|
free(env_unset_keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -120,14 +184,11 @@ session_environment_init(void)
|
||||||
paths_destroy(&paths);
|
paths_destroy(&paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
session_autostart_init(void)
|
run_session_script(const char *script)
|
||||||
{
|
{
|
||||||
/* Update dbus and systemd user environment, each may fail gracefully */
|
|
||||||
update_activation_env("DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP");
|
|
||||||
|
|
||||||
struct wl_list paths;
|
struct wl_list paths;
|
||||||
paths_config_create(&paths, "autostart");
|
paths_config_create(&paths, script);
|
||||||
|
|
||||||
bool should_merge_config = rc.merge_config;
|
bool should_merge_config = rc.merge_config;
|
||||||
struct wl_list *(*iter)(struct wl_list *list);
|
struct wl_list *(*iter)(struct wl_list *list);
|
||||||
|
|
@ -138,7 +199,7 @@ session_autostart_init(void)
|
||||||
if (!file_exists(path->string)) {
|
if (!file_exists(path->string)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
wlr_log(WLR_INFO, "run autostart file %s", path->string);
|
wlr_log(WLR_INFO, "run session script %s", path->string);
|
||||||
char *cmd = strdup_printf("sh %s", path->string);
|
char *cmd = strdup_printf("sh %s", path->string);
|
||||||
spawn_async_no_shell(cmd);
|
spawn_async_no_shell(cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
@ -149,3 +210,20 @@ session_autostart_init(void)
|
||||||
}
|
}
|
||||||
paths_destroy(&paths);
|
paths_destroy(&paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
session_autostart_init(struct server *server)
|
||||||
|
{
|
||||||
|
/* Update dbus and systemd user environment, each may fail gracefully */
|
||||||
|
update_activation_env(server, /* initialize */ true);
|
||||||
|
run_session_script("autostart");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
session_shutdown(struct server *server)
|
||||||
|
{
|
||||||
|
run_session_script("shutdown");
|
||||||
|
|
||||||
|
/* Clear the dbus and systemd user environment, each may fail gracefully */
|
||||||
|
update_activation_env(server, /* initialize */ false);
|
||||||
|
}
|
||||||
|
|
|
||||||
84
src/debug.c
84
src/debug.c
|
|
@ -1,19 +1,23 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include "common/graphic-helpers.h"
|
||||||
#include "common/scene-helpers.h"
|
#include "common/scene-helpers.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "ssd.h"
|
#include "ssd.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "workspaces.h"
|
||||||
|
|
||||||
#define HEADER_CHARS "------------------------------"
|
#define HEADER_CHARS "------------------------------"
|
||||||
|
|
||||||
#define INDENT_SIZE 3
|
#define INDENT_SIZE 3
|
||||||
|
#define LEFT_COL_SPACE 35
|
||||||
|
|
||||||
#define IGNORE_SSD true
|
#define IGNORE_SSD true
|
||||||
#define IGNORE_MENU true
|
#define IGNORE_MENU true
|
||||||
#define LEFT_COL_SPACE 35
|
#define IGNORE_OSD_PREVIEW_OUTLINE true
|
||||||
|
|
||||||
static struct view *last_view;
|
static struct view *last_view;
|
||||||
|
|
||||||
|
|
@ -42,13 +46,13 @@ get_layer_name(uint32_t layer)
|
||||||
{
|
{
|
||||||
switch (layer) {
|
switch (layer) {
|
||||||
case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
|
case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
|
||||||
return "layer-background";
|
return "output->layer-background";
|
||||||
case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
|
case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
|
||||||
return "layer-bottom";
|
return "output->layer-bottom";
|
||||||
case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
|
case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
|
||||||
return "layer-top";
|
return "output->layer-top";
|
||||||
case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
|
case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
|
||||||
return "layer-overlay";
|
return "output->layer-overlay";
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
@ -57,16 +61,27 @@ get_layer_name(uint32_t layer)
|
||||||
static const char *
|
static const char *
|
||||||
get_view_part(struct view *view, struct wlr_scene_node *node)
|
get_view_part(struct view *view, struct wlr_scene_node *node)
|
||||||
{
|
{
|
||||||
if (view && node == &view->scene_tree->node) {
|
static char view_name[LEFT_COL_SPACE];
|
||||||
return "view";
|
if (!view) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (view && node == view->scene_node) {
|
if (node == &view->scene_tree->node) {
|
||||||
|
const char *app_id = view_get_string_prop(view, "app_id");
|
||||||
|
if (!app_id) {
|
||||||
|
return "view";
|
||||||
|
}
|
||||||
|
snprintf(view_name, sizeof(view_name), "view (%s)", app_id);
|
||||||
|
return view_name;
|
||||||
|
}
|
||||||
|
if (node == view->scene_node) {
|
||||||
return "view->scene_node";
|
return "view->scene_node";
|
||||||
}
|
}
|
||||||
if (view) {
|
if (view->resize_indicator.tree
|
||||||
return ssd_debug_get_node_name(view->ssd, node);
|
&& node == &view->resize_indicator.tree->node) {
|
||||||
|
/* Created on-demand */
|
||||||
|
return "view->resize_indicator";
|
||||||
}
|
}
|
||||||
return NULL;
|
return ssd_debug_get_node_name(view->ssd, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -81,12 +96,20 @@ get_special(struct server *server, struct wlr_scene_node *node)
|
||||||
if (node == &server->view_tree->node) {
|
if (node == &server->view_tree->node) {
|
||||||
return "server->view_tree";
|
return "server->view_tree";
|
||||||
}
|
}
|
||||||
|
if (node == &server->view_tree_always_on_bottom->node) {
|
||||||
|
return "server->always_on_bottom";
|
||||||
|
}
|
||||||
if (node == &server->view_tree_always_on_top->node) {
|
if (node == &server->view_tree_always_on_top->node) {
|
||||||
return "server->view_tree_always_on_top";
|
return "server->always_on_top";
|
||||||
}
|
}
|
||||||
if (node->parent == server->view_tree) {
|
if (node->parent == server->view_tree) {
|
||||||
/* Add node_descriptor just to get the name here? */
|
struct workspace *workspace;
|
||||||
return "workspace";
|
wl_list_for_each(workspace, &server->workspaces, link) {
|
||||||
|
if (&workspace->tree->node == node) {
|
||||||
|
return workspace->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "unknown workspace";
|
||||||
}
|
}
|
||||||
if (node->parent == &server->scene->tree) {
|
if (node->parent == &server->scene->tree) {
|
||||||
struct output *output;
|
struct output *output;
|
||||||
|
|
@ -95,15 +118,34 @@ get_special(struct server *server, struct wlr_scene_node *node)
|
||||||
return "output->osd_tree";
|
return "output->osd_tree";
|
||||||
}
|
}
|
||||||
if (node == &output->layer_popup_tree->node) {
|
if (node == &output->layer_popup_tree->node) {
|
||||||
return "output->popup_tree";
|
return "output->layer_popup_tree";
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (node == &output->layer_tree[i]->node) {
|
if (node == &output->layer_tree[i]->node) {
|
||||||
return get_layer_name(i);
|
return get_layer_name(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node == &output->session_lock_tree->node) {
|
||||||
|
return "output->session_lock_tree";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node == &server->xdg_popup_tree->node) {
|
||||||
|
return "server->xdg_popup_tree";
|
||||||
|
}
|
||||||
|
if (node == &server->seat.drag.icons->node) {
|
||||||
|
return "seat->drag.icons";
|
||||||
|
}
|
||||||
|
if (server->seat.region_overlay.tree
|
||||||
|
&& node == &server->seat.region_overlay.tree->node) {
|
||||||
|
/* Created on-demand */
|
||||||
|
return "seat->region_overlay";
|
||||||
|
}
|
||||||
|
if (server->osd_state.preview_outline
|
||||||
|
&& node == &server->osd_state.preview_outline->tree->node) {
|
||||||
|
/* Created on-demand */
|
||||||
|
return "osd_state->preview_outline";
|
||||||
|
}
|
||||||
#if HAVE_XWAYLAND
|
#if HAVE_XWAYLAND
|
||||||
if (node == &server->unmanaged_tree->node) {
|
if (node == &server->unmanaged_tree->node) {
|
||||||
return "server->unmanaged_tree";
|
return "server->unmanaged_tree";
|
||||||
|
|
@ -155,15 +197,21 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
|
||||||
HEADER_CHARS, HEADER_CHARS, HEADER_CHARS);
|
HEADER_CHARS, HEADER_CHARS, HEADER_CHARS);
|
||||||
printf(" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
int padding = LEFT_COL_SPACE - pos - strlen(type);
|
int max_width = LEFT_COL_SPACE - pos;
|
||||||
|
int padding = max_width - strlen(type);
|
||||||
|
if (padding < 0) {
|
||||||
|
padding = 0;
|
||||||
|
}
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
padding += 3;
|
padding += 3;
|
||||||
}
|
}
|
||||||
printf("%s %*c %4d %4d [%p]\n", type, padding, ' ', x, y, 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
|
|| (IGNORE_SSD && last_view
|
||||||
&& ssd_debug_is_root_node(last_view->ssd, node))) {
|
&& ssd_debug_is_root_node(last_view->ssd, node))
|
||||||
|
|| (IGNORE_OSD_PREVIEW_OUTLINE && server->osd_state.preview_outline
|
||||||
|
&& node == &server->osd_state.preview_outline->tree->node)) {
|
||||||
printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
|
printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
261
src/edges.c
261
src/edges.c
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <wlr/util/edges.h>
|
||||||
#include <wlr/util/box.h>
|
#include <wlr/util/box.h>
|
||||||
#include "common/border.h"
|
#include "common/border.h"
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
|
|
@ -8,6 +10,7 @@
|
||||||
#include "edges.h"
|
#include "edges.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
edges_for_target_geometry(struct border *edges, struct view *view,
|
edges_for_target_geometry(struct border *edges, struct view *view,
|
||||||
|
|
@ -35,34 +38,54 @@ edges_initialize(struct border *edges)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct edge
|
static inline struct edge
|
||||||
build_edge(struct border region, enum view_edge direction, int pad)
|
build_edge(struct border region, enum wlr_edges direction, int pad)
|
||||||
{
|
{
|
||||||
struct edge edge = { 0 };
|
struct edge edge = { 0 };
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case VIEW_EDGE_LEFT:
|
case WLR_EDGE_LEFT:
|
||||||
edge.offset = clipped_sub(region.left, pad);
|
edge.offset = clipped_sub(region.left, pad);
|
||||||
edge.min = region.top;
|
edge.min = region.top;
|
||||||
edge.max = region.bottom;
|
edge.max = region.bottom;
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_RIGHT:
|
case WLR_EDGE_RIGHT:
|
||||||
edge.offset = clipped_add(region.right, pad);
|
edge.offset = clipped_add(region.right, pad);
|
||||||
edge.min = region.top;
|
edge.min = region.top;
|
||||||
edge.max = region.bottom;
|
edge.max = region.bottom;
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_UP:
|
case WLR_EDGE_TOP:
|
||||||
edge.offset = clipped_sub(region.top, pad);
|
edge.offset = clipped_sub(region.top, pad);
|
||||||
edge.min = region.left;
|
edge.min = region.left;
|
||||||
edge.max = region.right;
|
edge.max = region.right;
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_DOWN:
|
case WLR_EDGE_BOTTOM:
|
||||||
edge.offset = clipped_add(region.bottom, pad);
|
edge.offset = clipped_add(region.bottom, pad);
|
||||||
edge.min = region.left;
|
edge.min = region.left;
|
||||||
edge.max = region.right;
|
edge.max = region.right;
|
||||||
break;
|
break;
|
||||||
default:
|
case WLR_EDGE_NONE:
|
||||||
/* Should never be reached */
|
/* Should never be reached */
|
||||||
assert(false);
|
wlr_log(WLR_ERROR, "invalid direction");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_lesser(enum wlr_edges direction)
|
||||||
|
{
|
||||||
|
return direction == WLR_EDGE_LEFT || direction == WLR_EDGE_TOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct edge
|
||||||
|
build_visible_edge(struct border region, enum wlr_edges direction,
|
||||||
|
int pad, uint32_t edges_visible)
|
||||||
|
{
|
||||||
|
struct edge edge = build_edge(region, direction, pad);
|
||||||
|
|
||||||
|
if (!(edges_visible & direction)) {
|
||||||
|
edge.offset = is_lesser(direction) ? INT_MIN : INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
return edge;
|
return edge;
|
||||||
|
|
@ -72,7 +95,7 @@ static void
|
||||||
validate_single_region_edge(int *valid_edge,
|
validate_single_region_edge(int *valid_edge,
|
||||||
struct border view, struct border target,
|
struct border view, struct border target,
|
||||||
struct border region, edge_validator_t validator,
|
struct border region, edge_validator_t validator,
|
||||||
enum view_edge direction)
|
enum wlr_edges direction, uint32_t edges_visible)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* When a view snaps to another while moving to its target, it can do
|
* When a view snaps to another while moving to its target, it can do
|
||||||
|
|
@ -90,42 +113,63 @@ validate_single_region_edge(int *valid_edge,
|
||||||
* the region borders for aligned edges only.
|
* the region borders for aligned edges only.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool lesser = direction == VIEW_EDGE_LEFT || direction == VIEW_EDGE_UP;
|
enum wlr_edges opposing = WLR_EDGE_NONE;
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case WLR_EDGE_TOP:
|
||||||
|
opposing = WLR_EDGE_BOTTOM;
|
||||||
|
break;
|
||||||
|
case WLR_EDGE_BOTTOM:
|
||||||
|
opposing = WLR_EDGE_TOP;
|
||||||
|
break;
|
||||||
|
case WLR_EDGE_LEFT:
|
||||||
|
opposing = WLR_EDGE_RIGHT;
|
||||||
|
break;
|
||||||
|
case WLR_EDGE_RIGHT:
|
||||||
|
opposing = WLR_EDGE_LEFT;
|
||||||
|
break;
|
||||||
|
case WLR_EDGE_NONE:
|
||||||
|
/* Should never be reached */
|
||||||
|
assert(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
validator(valid_edge,
|
validator(valid_edge,
|
||||||
build_edge(view, direction, 0),
|
build_edge(view, direction, 0),
|
||||||
build_edge(target, direction, 0),
|
build_edge(target, direction, 0),
|
||||||
build_edge(region, view_edge_invert(direction), 0),
|
build_visible_edge(region, opposing, 0, edges_visible),
|
||||||
build_edge(region, direction, rc.gap), lesser);
|
build_visible_edge(region, direction, rc.gap, edges_visible),
|
||||||
|
is_lesser(direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
validate_edges(struct border *valid_edges,
|
validate_edges(struct border *valid_edges,
|
||||||
struct border view, struct border target,
|
struct border view, struct border target,
|
||||||
struct border region, edge_validator_t validator)
|
struct border region, uint32_t edges_visible,
|
||||||
|
edge_validator_t validator)
|
||||||
{
|
{
|
||||||
/* Check for edges encountered during movement of left edge */
|
/* Check for edges encountered during movement of left edge */
|
||||||
validate_single_region_edge(&valid_edges->left,
|
validate_single_region_edge(&valid_edges->left,
|
||||||
view, target, region, validator, VIEW_EDGE_LEFT);
|
view, target, region, validator, WLR_EDGE_LEFT, edges_visible);
|
||||||
|
|
||||||
/* Check for edges encountered during movement of right edge */
|
/* Check for edges encountered during movement of right edge */
|
||||||
validate_single_region_edge(&valid_edges->right,
|
validate_single_region_edge(&valid_edges->right,
|
||||||
view, target, region, validator, VIEW_EDGE_RIGHT);
|
view, target, region, validator, WLR_EDGE_RIGHT, edges_visible);
|
||||||
|
|
||||||
/* Check for edges encountered during movement of top edge */
|
/* Check for edges encountered during movement of top edge */
|
||||||
validate_single_region_edge(&valid_edges->top,
|
validate_single_region_edge(&valid_edges->top,
|
||||||
view, target, region, validator, VIEW_EDGE_UP);
|
view, target, region, validator, WLR_EDGE_TOP, edges_visible);
|
||||||
|
|
||||||
/* Check for edges encountered during movement of bottom edge */
|
/* Check for edges encountered during movement of bottom edge */
|
||||||
validate_single_region_edge(&valid_edges->bottom,
|
validate_single_region_edge(&valid_edges->bottom,
|
||||||
view, target, region, validator, VIEW_EDGE_DOWN);
|
view, target, region, validator, WLR_EDGE_BOTTOM, edges_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
validate_single_output_edge(int *valid_edge,
|
validate_single_output_edge(int *valid_edge,
|
||||||
struct border view, struct border target,
|
struct border view, struct border target,
|
||||||
struct border region, edge_validator_t validator,
|
struct border region, edge_validator_t validator,
|
||||||
enum view_edge direction)
|
enum wlr_edges direction)
|
||||||
{
|
{
|
||||||
static struct border unbounded = {
|
static struct border unbounded = {
|
||||||
.top = INT_MIN,
|
.top = INT_MIN,
|
||||||
|
|
@ -134,13 +178,11 @@ validate_single_output_edge(int *valid_edge,
|
||||||
.left = INT_MIN,
|
.left = INT_MIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool lesser = direction == VIEW_EDGE_LEFT || direction == VIEW_EDGE_UP;
|
|
||||||
|
|
||||||
validator(valid_edge,
|
validator(valid_edge,
|
||||||
build_edge(view, direction, 0),
|
build_edge(view, direction, 0),
|
||||||
build_edge(target, direction, 0),
|
build_edge(target, direction, 0),
|
||||||
build_edge(region, direction, 0),
|
build_edge(region, direction, 0),
|
||||||
build_edge(unbounded, direction, 0), lesser);
|
build_edge(unbounded, direction, 0), is_lesser(direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -182,32 +224,170 @@ validate_output_edges(struct border *valid_edges,
|
||||||
/* Left edge encounters a half-infinite region to the left of the output */
|
/* Left edge encounters a half-infinite region to the left of the output */
|
||||||
|
|
||||||
validate_single_output_edge(&valid_edges->left,
|
validate_single_output_edge(&valid_edges->left,
|
||||||
view, target, output, validator, VIEW_EDGE_LEFT);
|
view, target, output, validator, WLR_EDGE_LEFT);
|
||||||
|
|
||||||
/* Right edge encounters a half-infinite region to the right of the output */
|
/* Right edge encounters a half-infinite region to the right of the output */
|
||||||
|
|
||||||
validate_single_output_edge(&valid_edges->right,
|
validate_single_output_edge(&valid_edges->right,
|
||||||
view, target, output, validator, VIEW_EDGE_RIGHT);
|
view, target, output, validator, WLR_EDGE_RIGHT);
|
||||||
|
|
||||||
/* Top edge encounters a half-infinite region above the output */
|
/* Top edge encounters a half-infinite region above the output */
|
||||||
|
|
||||||
validate_single_output_edge(&valid_edges->top,
|
validate_single_output_edge(&valid_edges->top,
|
||||||
view, target, output, validator, VIEW_EDGE_UP);
|
view, target, output, validator, WLR_EDGE_TOP);
|
||||||
|
|
||||||
/* Bottom edge encounters a half-infinite region below the output */
|
/* Bottom edge encounters a half-infinite region below the output */
|
||||||
validate_single_output_edge(&valid_edges->bottom,
|
validate_single_output_edge(&valid_edges->bottom,
|
||||||
view, target, output, validator, VIEW_EDGE_DOWN);
|
view, target, output, validator, WLR_EDGE_BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test if parts of the current view is covered by the remaining space in the region */
|
||||||
|
static void
|
||||||
|
subtract_view_from_space(struct view *view, pixman_region32_t *available)
|
||||||
|
{
|
||||||
|
struct wlr_box view_size = ssd_max_extents(view);
|
||||||
|
pixman_box32_t view_rect = {
|
||||||
|
.x1 = view_size.x,
|
||||||
|
.x2 = view_size.x + view_size.width,
|
||||||
|
.y1 = view_size.y,
|
||||||
|
.y2 = view_size.y + view_size.height
|
||||||
|
};
|
||||||
|
|
||||||
|
pixman_region_overlap_t overlap =
|
||||||
|
pixman_region32_contains_rectangle(available, &view_rect);
|
||||||
|
|
||||||
|
switch (overlap) {
|
||||||
|
case PIXMAN_REGION_IN:
|
||||||
|
view->edges_visible = WLR_EDGE_TOP | WLR_EDGE_RIGHT
|
||||||
|
| WLR_EDGE_BOTTOM | WLR_EDGE_LEFT;
|
||||||
|
break;
|
||||||
|
case PIXMAN_REGION_OUT:
|
||||||
|
view->edges_visible = 0;
|
||||||
|
return;
|
||||||
|
case PIXMAN_REGION_PART:
|
||||||
|
; /* works around "a label can only be part of a statement" */
|
||||||
|
pixman_region32_t intersection;
|
||||||
|
pixman_region32_init(&intersection);
|
||||||
|
pixman_region32_intersect_rect(&intersection, available,
|
||||||
|
view_size.x, view_size.y,
|
||||||
|
view_size.width, view_size.height);
|
||||||
|
|
||||||
|
int nrects;
|
||||||
|
const pixman_box32_t *rects =
|
||||||
|
pixman_region32_rectangles(&intersection, &nrects);
|
||||||
|
|
||||||
|
view->edges_visible = 0;
|
||||||
|
for (int i = 0; i < nrects; i++) {
|
||||||
|
if (rects[i].x1 == view_rect.x1) {
|
||||||
|
view->edges_visible |= WLR_EDGE_LEFT;
|
||||||
|
}
|
||||||
|
if (rects[i].y1 == view_rect.y1) {
|
||||||
|
view->edges_visible |= WLR_EDGE_TOP;
|
||||||
|
}
|
||||||
|
if (rects[i].x2 == view_rect.x2) {
|
||||||
|
view->edges_visible |= WLR_EDGE_RIGHT;
|
||||||
|
}
|
||||||
|
if (rects[i].y2 == view_rect.y2) {
|
||||||
|
view->edges_visible |= WLR_EDGE_BOTTOM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pixman_region32_fini(&intersection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Subtract the view geometry from the available region for the next check */
|
||||||
|
pixman_region32_t view_region;
|
||||||
|
pixman_region32_init_rects(&view_region, &view_rect, 1);
|
||||||
|
pixman_region32_subtract(available, available, &view_region);
|
||||||
|
pixman_region32_fini(&view_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
subtract_node_tree(struct wlr_scene_tree *tree, pixman_region32_t *available,
|
||||||
|
struct view *ignored_view)
|
||||||
|
{
|
||||||
|
struct view *view;
|
||||||
|
struct wlr_scene_node *node;
|
||||||
|
struct node_descriptor *node_desc;
|
||||||
|
wl_list_for_each_reverse(node, &tree->children, link) {
|
||||||
|
if (!node->enabled) {
|
||||||
|
/*
|
||||||
|
* This skips everything that is not being
|
||||||
|
* rendered, including minimized / unmapped
|
||||||
|
* windows and workspaces other than the
|
||||||
|
* current one.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_desc = node->data;
|
||||||
|
if (node_desc && node_desc->type == LAB_NODE_DESC_VIEW) {
|
||||||
|
view = node_view_from_node(node);
|
||||||
|
if (view != ignored_view) {
|
||||||
|
subtract_view_from_space(view, available);
|
||||||
|
}
|
||||||
|
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||||
|
subtract_node_tree(wlr_scene_tree_from_node(node),
|
||||||
|
available, ignored_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
edges_calculate_visibility(struct server *server, struct view *ignored_view)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The region stores the available output layout space
|
||||||
|
* and subtracts the window geometries in reverse rendering
|
||||||
|
* order, e.g. a window rendered on top is subtracted first.
|
||||||
|
*
|
||||||
|
* This allows to detect if a window is actually visible.
|
||||||
|
* If there is no overlap of its geometry and the remaining
|
||||||
|
* region it must be completely covered by other windows.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
pixman_region32_t region;
|
||||||
|
pixman_region32_init(®ion);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the region with each individual output.
|
||||||
|
*
|
||||||
|
* If we were to use NULL for the reference output we
|
||||||
|
* would get a single combined wlr_box of the whole
|
||||||
|
* layout which could cover actual invisible areas
|
||||||
|
* in case the output resolutions differ.
|
||||||
|
*/
|
||||||
|
struct output *output;
|
||||||
|
struct wlr_box layout_box;
|
||||||
|
wl_list_for_each(output, &server->outputs, link) {
|
||||||
|
if (!output_is_usable(output)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
pixman_region32_fini(®ion);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
||||||
struct wlr_box target, struct output *output,
|
struct wlr_box target, struct output *output,
|
||||||
edge_validator_t validator, bool use_pending)
|
edge_validator_t validator, bool use_pending, bool ignore_hidden)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
assert(validator);
|
assert(validator);
|
||||||
assert(nearest_edges);
|
assert(nearest_edges);
|
||||||
|
|
||||||
|
if (!output_is_usable(view->output)) {
|
||||||
|
wlr_log(WLR_DEBUG, "ignoring edge search for view on unsable output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct border view_edges = { 0 };
|
struct border view_edges = { 0 };
|
||||||
struct border target_edges = { 0 };
|
struct border target_edges = { 0 };
|
||||||
|
|
||||||
|
|
@ -223,22 +403,21 @@ edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output && v->output != output) {
|
uint32_t edges_visible = ignore_hidden ? v->edges_visible :
|
||||||
|
WLR_EDGE_TOP | WLR_EDGE_LEFT
|
||||||
|
| WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT;
|
||||||
|
|
||||||
|
if (edges_visible == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (output && output != v->output && !view_on_output(v, output)) {
|
||||||
* If view and v are on different outputs, make sure part of
|
continue;
|
||||||
* view is actually in the usable area of the output of v.
|
}
|
||||||
*/
|
|
||||||
if (view->output != v->output) {
|
|
||||||
struct wlr_box usable =
|
|
||||||
output_usable_area_in_layout_coords(v->output);
|
|
||||||
|
|
||||||
struct wlr_box ol;
|
/* Both view and v must share a common output */
|
||||||
if (!wlr_box_intersection(&ol, view_geom, &usable)) {
|
if (view->output != v->output && !(view->outputs & v->outputs)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct border border = ssd_get_margin(v->ssd);
|
struct border border = ssd_get_margin(v->ssd);
|
||||||
|
|
@ -252,7 +431,7 @@ edges_find_neighbors(struct border *nearest_edges, struct view *view,
|
||||||
};
|
};
|
||||||
|
|
||||||
validate_edges(nearest_edges, view_edges,
|
validate_edges(nearest_edges, view_edges,
|
||||||
target_edges, win_edges, validator);
|
target_edges, win_edges, edges_visible, validator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,6 +444,12 @@ edges_find_outputs(struct border *nearest_edges, struct view *view,
|
||||||
assert(validator);
|
assert(validator);
|
||||||
assert(nearest_edges);
|
assert(nearest_edges);
|
||||||
|
|
||||||
|
if (!output_is_usable(view->output)) {
|
||||||
|
wlr_log(WLR_DEBUG,
|
||||||
|
"ignoring edge search for view on unsable output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct border view_edges = { 0 };
|
struct border view_edges = { 0 };
|
||||||
struct border target_edges = { 0 };
|
struct border target_edges = { 0 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,7 @@ key_state_pressed_sent_keycodes(void)
|
||||||
report(&bound, "before - bound:");
|
report(&bound, "before - bound:");
|
||||||
|
|
||||||
/* pressed_sent = pressed - bound */
|
/* pressed_sent = pressed - bound */
|
||||||
memcpy(pressed_sent.keys, pressed.keys,
|
pressed_sent = pressed;
|
||||||
MAX_PRESSED_KEYS * sizeof(uint32_t));
|
|
||||||
pressed_sent.nr_keys = pressed.nr_keys;
|
|
||||||
for (int i = 0; i < bound.nr_keys; ++i) {
|
for (int i = 0; i < bound.nr_keys; ++i) {
|
||||||
remove_key(&pressed_sent, bound.keys[i]);
|
remove_key(&pressed_sent, bound.keys[i]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#include "edges.h"
|
||||||
#include "input/keyboard.h"
|
#include "input/keyboard.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
|
|
@ -123,6 +124,9 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
if (rc.resize_indicator) {
|
if (rc.resize_indicator) {
|
||||||
resize_indicator_show(view);
|
resize_indicator_show(view);
|
||||||
}
|
}
|
||||||
|
if (rc.window_edge_strength) {
|
||||||
|
edges_calculate_visibility(server, view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if view was snapped to any edge */
|
/* Returns true if view was snapped to any edge */
|
||||||
|
|
|
||||||
36
src/layers.c
36
src/layers.c
|
|
@ -260,14 +260,35 @@ popup_handle_destroy(struct wl_listener *listener, void *data)
|
||||||
wl_container_of(listener, popup, destroy);
|
wl_container_of(listener, popup, destroy);
|
||||||
wl_list_remove(&popup->destroy.link);
|
wl_list_remove(&popup->destroy.link);
|
||||||
wl_list_remove(&popup->new_popup.link);
|
wl_list_remove(&popup->new_popup.link);
|
||||||
|
|
||||||
|
/* Usually already removed unless there was no commit at all */
|
||||||
|
if (popup->commit.notify) {
|
||||||
|
wl_list_remove(&popup->commit.link);
|
||||||
|
}
|
||||||
|
|
||||||
free(popup);
|
free(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
popup_handle_commit(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct lab_layer_popup *popup =
|
||||||
|
wl_container_of(listener, popup, commit);
|
||||||
|
|
||||||
|
if (popup->wlr_popup->base->initial_commit) {
|
||||||
|
wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup,
|
||||||
|
&popup->output_toplevel_sx_box);
|
||||||
|
|
||||||
|
/* Prevent getting called over and over again */
|
||||||
|
wl_list_remove(&popup->commit.link);
|
||||||
|
popup->commit.notify = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void popup_handle_new_popup(struct wl_listener *listener, void *data);
|
static void popup_handle_new_popup(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
static struct lab_layer_popup *
|
static struct lab_layer_popup *
|
||||||
create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent,
|
create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent)
|
||||||
struct wlr_box *output_toplevel_sx_box)
|
|
||||||
{
|
{
|
||||||
struct lab_layer_popup *popup = znew(*popup);
|
struct lab_layer_popup *popup = znew(*popup);
|
||||||
popup->wlr_popup = wlr_popup;
|
popup->wlr_popup = wlr_popup;
|
||||||
|
|
@ -282,10 +303,13 @@ create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent,
|
||||||
|
|
||||||
popup->destroy.notify = popup_handle_destroy;
|
popup->destroy.notify = popup_handle_destroy;
|
||||||
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
|
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
|
||||||
|
|
||||||
popup->new_popup.notify = popup_handle_new_popup;
|
popup->new_popup.notify = popup_handle_new_popup;
|
||||||
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
||||||
|
|
||||||
wlr_xdg_popup_unconstrain_from_box(wlr_popup, output_toplevel_sx_box);
|
popup->commit.notify = popup_handle_commit;
|
||||||
|
wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
|
||||||
|
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,8 +321,7 @@ popup_handle_new_popup(struct wl_listener *listener, void *data)
|
||||||
wl_container_of(listener, lab_layer_popup, new_popup);
|
wl_container_of(listener, lab_layer_popup, new_popup);
|
||||||
struct wlr_xdg_popup *wlr_popup = data;
|
struct wlr_xdg_popup *wlr_popup = data;
|
||||||
struct lab_layer_popup *new_popup = create_popup(wlr_popup,
|
struct lab_layer_popup *new_popup = create_popup(wlr_popup,
|
||||||
lab_layer_popup->scene_tree,
|
lab_layer_popup->scene_tree);
|
||||||
&lab_layer_popup->output_toplevel_sx_box);
|
|
||||||
new_popup->output_toplevel_sx_box =
|
new_popup->output_toplevel_sx_box =
|
||||||
lab_layer_popup->output_toplevel_sx_box;
|
lab_layer_popup->output_toplevel_sx_box;
|
||||||
}
|
}
|
||||||
|
|
@ -357,8 +380,7 @@ handle_new_popup(struct wl_listener *listener, void *data)
|
||||||
.width = output_box.width,
|
.width = output_box.width,
|
||||||
.height = output_box.height,
|
.height = output_box.height,
|
||||||
};
|
};
|
||||||
struct lab_layer_popup *popup = create_popup(wlr_popup,
|
struct lab_layer_popup *popup = create_popup(wlr_popup, surface->tree);
|
||||||
surface->tree, &output_toplevel_sx_box);
|
|
||||||
popup->output_toplevel_sx_box = output_toplevel_sx_box;
|
popup->output_toplevel_sx_box = output_toplevel_sx_box;
|
||||||
|
|
||||||
if (surface->layer_surface->current.layer
|
if (surface->layer_surface->current.layer
|
||||||
|
|
|
||||||
|
|
@ -171,13 +171,15 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
menu_init(&server);
|
menu_init(&server);
|
||||||
|
|
||||||
session_autostart_init();
|
session_autostart_init(&server);
|
||||||
if (startup_cmd) {
|
if (startup_cmd) {
|
||||||
spawn_async_no_shell(startup_cmd);
|
spawn_async_no_shell(startup_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_display_run(server.wl_display);
|
wl_display_run(server.wl_display);
|
||||||
|
|
||||||
|
session_shutdown(&server);
|
||||||
|
|
||||||
server_finish(&server);
|
server_finish(&server);
|
||||||
|
|
||||||
menu_finish(&server);
|
menu_finish(&server);
|
||||||
|
|
|
||||||
52
src/output.c
52
src/output.c
|
|
@ -150,6 +150,32 @@ output_request_state_notify(struct wl_listener *listener, void *data)
|
||||||
struct output *output = wl_container_of(listener, output, request_state);
|
struct output *output = wl_container_of(listener, output, request_state);
|
||||||
const struct wlr_output_event_request_state *event = data;
|
const struct wlr_output_event_request_state *event = data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If wlroots ever requests other state changes here we could
|
||||||
|
* restore more of ddc9047a67cd53b2948f71fde1bbe9118000dd3f.
|
||||||
|
*/
|
||||||
|
if (event->state->committed == WLR_OUTPUT_STATE_MODE) {
|
||||||
|
/* Only the mode has changed */
|
||||||
|
switch (event->state->mode_type) {
|
||||||
|
case WLR_OUTPUT_STATE_MODE_FIXED:
|
||||||
|
wlr_output_set_mode(output->wlr_output, event->state->mode);
|
||||||
|
break;
|
||||||
|
case WLR_OUTPUT_STATE_MODE_CUSTOM:
|
||||||
|
wlr_output_set_custom_mode(output->wlr_output,
|
||||||
|
event->state->custom_mode.width,
|
||||||
|
event->state->custom_mode.height,
|
||||||
|
event->state->custom_mode.refresh);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wlr_output_schedule_frame(output->wlr_output);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fallback path for everything that we didn't handle above.
|
||||||
|
* The commit will cause a black frame injection so this
|
||||||
|
* path causes flickering during resize of nested outputs.
|
||||||
|
*/
|
||||||
if (!wlr_output_commit_state(output->wlr_output, event->state)) {
|
if (!wlr_output_commit_state(output->wlr_output, event->state)) {
|
||||||
wlr_log(WLR_ERROR, "Backend requested a new state that could not be applied");
|
wlr_log(WLR_ERROR, "Backend requested a new state that could not be applied");
|
||||||
}
|
}
|
||||||
|
|
@ -405,10 +431,11 @@ output_update_for_layout_change(struct server *server)
|
||||||
cursor_update_image(&server->seat);
|
cursor_update_image(&server->seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
output_config_apply(struct server *server,
|
output_config_apply(struct server *server,
|
||||||
struct wlr_output_configuration_v1 *config)
|
struct wlr_output_configuration_v1 *config)
|
||||||
{
|
{
|
||||||
|
bool success = true;
|
||||||
server->pending_output_layout_change++;
|
server->pending_output_layout_change++;
|
||||||
|
|
||||||
struct wlr_output_configuration_head_v1 *head;
|
struct wlr_output_configuration_head_v1 *head;
|
||||||
|
|
@ -436,8 +463,15 @@ output_config_apply(struct server *server,
|
||||||
output_enable_adaptive_sync(o, head->state.adaptive_sync_enabled);
|
output_enable_adaptive_sync(o, head->state.adaptive_sync_enabled);
|
||||||
}
|
}
|
||||||
if (!wlr_output_commit(o)) {
|
if (!wlr_output_commit(o)) {
|
||||||
wlr_log(WLR_ERROR, "Output config commit failed");
|
/*
|
||||||
continue;
|
* FIXME: This is only part of the story, we should revert
|
||||||
|
* all previously commited outputs as well here.
|
||||||
|
*
|
||||||
|
* See https://github.com/labwc/labwc/pull/1528
|
||||||
|
*/
|
||||||
|
wlr_log(WLR_INFO, "Output config commit failed: %s", o->name);
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only do Layout specific actions if the commit went trough */
|
/* Only do Layout specific actions if the commit went trough */
|
||||||
|
|
@ -477,6 +511,7 @@ output_config_apply(struct server *server,
|
||||||
|
|
||||||
server->pending_output_layout_change--;
|
server->pending_output_layout_change--;
|
||||||
do_output_layout_change(server);
|
do_output_layout_change(server);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -509,11 +544,17 @@ verify_output_config_v1(const struct wlr_output_configuration_v1 *config)
|
||||||
|
|
||||||
if (wlr_output_is_wl(head->state.output) && refresh != 0) {
|
if (wlr_output_is_wl(head->state.output) && refresh != 0) {
|
||||||
/* Wayland backend does not support refresh rates */
|
/* Wayland backend does not support refresh rates */
|
||||||
err_msg = "Wayland backend refresh rate unsupported";
|
err_msg = "Wayland backend refresh rates unsupported";
|
||||||
goto custom_mode_failed;
|
goto custom_mode_failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlr_output_is_wl(head->state.output)
|
||||||
|
&& !head->state.adaptive_sync_enabled) {
|
||||||
|
err_msg = "Wayland backend requires adaptive sync";
|
||||||
|
goto custom_mode_failed;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure the new output state can be applied on
|
* Ensure the new output state can be applied on
|
||||||
* its own and inform the client when it can not.
|
* its own and inform the client when it can not.
|
||||||
|
|
@ -569,8 +610,7 @@ handle_output_manager_apply(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
bool config_is_good = verify_output_config_v1(config);
|
bool config_is_good = verify_output_config_v1(config);
|
||||||
|
|
||||||
if (config_is_good) {
|
if (config_is_good && output_config_apply(server, config)) {
|
||||||
output_config_apply(server, config);
|
|
||||||
wlr_output_configuration_v1_send_succeeded(config);
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
} else {
|
} else {
|
||||||
wlr_output_configuration_v1_send_failed(config);
|
wlr_output_configuration_v1_send_failed(config);
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,9 @@ resistance_move_apply(struct view *view, double *x, double *y)
|
||||||
|
|
||||||
if (rc.window_edge_strength != 0) {
|
if (rc.window_edge_strength != 0) {
|
||||||
/* Find any relevant window edges encountered by this move */
|
/* Find any relevant window edges encountered by this move */
|
||||||
edges_find_neighbors(&next_edges, view, target, NULL,
|
edges_find_neighbors(&next_edges,
|
||||||
check_edge_window, /* use_pending */ false);
|
view, target, NULL, check_edge_window,
|
||||||
|
/* use_pending */ false, /* ignore_hidden */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If any "best" edges were encountered during this move, snap motion */
|
/* If any "best" edges were encountered during this move, snap motion */
|
||||||
|
|
@ -143,8 +144,9 @@ resistance_resize_apply(struct view *view, struct wlr_box *new_geom)
|
||||||
|
|
||||||
if (rc.window_edge_strength != 0) {
|
if (rc.window_edge_strength != 0) {
|
||||||
/* Find any relevant window edges encountered by this move */
|
/* Find any relevant window edges encountered by this move */
|
||||||
edges_find_neighbors(&next_edges, view, *new_geom, NULL,
|
edges_find_neighbors(&next_edges,
|
||||||
check_edge_window, /* use_pending */ false);
|
view, *new_geom, NULL, check_edge_window,
|
||||||
|
/* use_pending */ false, /* ignore_hidden */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If any "best" edges were encountered during this move, snap motion */
|
/* If any "best" edges were encountered during this move, snap motion */
|
||||||
|
|
|
||||||
48
src/seat.c
48
src/seat.c
|
|
@ -91,6 +91,24 @@ get_category(struct wlr_input_device *device)
|
||||||
static void
|
static void
|
||||||
configure_libinput(struct wlr_input_device *wlr_input_device)
|
configure_libinput(struct wlr_input_device *wlr_input_device)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* TODO: We do not check any return values for the various
|
||||||
|
* libinput_device_config_*_set_*() calls. It would
|
||||||
|
* be nice if we could inform the users via log file
|
||||||
|
* that some libinput setting could not be applied.
|
||||||
|
*
|
||||||
|
* TODO: We are currently using int32_t with -1 as default
|
||||||
|
* to desribe the not-configured state. This is not
|
||||||
|
* really optimal as we can't properly deal with
|
||||||
|
* enum values that are 0. After some discussion via
|
||||||
|
* IRC the best way forward seem to be to use a
|
||||||
|
* uint32_t instead and UINT32_MAX as indicator for
|
||||||
|
* a not-configured state. This allows to properly
|
||||||
|
* test the enum being a member of a bitset via
|
||||||
|
* mask & value == value. All libinput enums are
|
||||||
|
* way below UINT32_MAX.
|
||||||
|
*/
|
||||||
|
|
||||||
if (!wlr_input_device) {
|
if (!wlr_input_device) {
|
||||||
wlr_log(WLR_ERROR, "no wlr_input_device");
|
wlr_log(WLR_ERROR, "no wlr_input_device");
|
||||||
return;
|
return;
|
||||||
|
|
@ -189,6 +207,36 @@ configure_libinput(struct wlr_input_device *wlr_input_device)
|
||||||
wlr_log(WLR_INFO, "dwt configured");
|
wlr_log(WLR_INFO, "dwt configured");
|
||||||
libinput_device_config_dwt_set_enabled(libinput_dev, dc->dwt);
|
libinput_device_config_dwt_set_enabled(libinput_dev, dc->dwt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((dc->click_method != LIBINPUT_CONFIG_CLICK_METHOD_NONE
|
||||||
|
&& (libinput_device_config_click_get_methods(libinput_dev)
|
||||||
|
& dc->click_method) == 0)
|
||||||
|
|| dc->click_method < 0) {
|
||||||
|
wlr_log(WLR_INFO, "click method not configured");
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_INFO, "click method configured");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note, the documentation claims that:
|
||||||
|
* > [...] The device may require changing to a neutral state
|
||||||
|
* > first before activating the new method.
|
||||||
|
*
|
||||||
|
* However, just setting the method seems to work without
|
||||||
|
* issues.
|
||||||
|
*/
|
||||||
|
|
||||||
|
libinput_device_config_click_set_method(libinput_dev, dc->click_method);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dc->send_events_mode != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||||
|
&& (libinput_device_config_send_events_get_modes(libinput_dev)
|
||||||
|
& dc->send_events_mode) == 0)
|
||||||
|
|| dc->send_events_mode < 0) {
|
||||||
|
wlr_log(WLR_INFO, "send events mode not configured");
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_INFO, "send events mode configured");
|
||||||
|
libinput_device_config_send_events_set_mode(libinput_dev, dc->send_events_mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_output *
|
static struct wlr_output *
|
||||||
|
|
|
||||||
12
src/server.c
12
src/server.c
|
|
@ -17,6 +17,7 @@
|
||||||
#include <wlr/types/wlr_viewporter.h>
|
#include <wlr/types/wlr_viewporter.h>
|
||||||
#if HAVE_XWAYLAND
|
#if HAVE_XWAYLAND
|
||||||
#include <wlr/xwayland.h>
|
#include <wlr/xwayland.h>
|
||||||
|
#include "xwayland-shell-v1-protocol.h"
|
||||||
#endif
|
#endif
|
||||||
#include "drm-lease-v1-protocol.h"
|
#include "drm-lease-v1-protocol.h"
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
|
|
@ -172,9 +173,11 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo
|
||||||
(void)iface; (void)server;
|
(void)iface; (void)server;
|
||||||
|
|
||||||
#if HAVE_XWAYLAND
|
#if HAVE_XWAYLAND
|
||||||
struct wl_client *xwayland_client =
|
struct wl_client *xwayland_client = (server->xwayland && server->xwayland->server)
|
||||||
server->xwayland ? server->xwayland->server->client : NULL;
|
? server->xwayland->server->client
|
||||||
if (xwayland_client && client == xwayland_client) {
|
: NULL;
|
||||||
|
|
||||||
|
if (client == xwayland_client) {
|
||||||
/*
|
/*
|
||||||
* Filter out wp_drm_lease_device_v1 for now as it is resulting in
|
* Filter out wp_drm_lease_device_v1 for now as it is resulting in
|
||||||
* issues with Xwayland applications lagging over time.
|
* issues with Xwayland applications lagging over time.
|
||||||
|
|
@ -184,6 +187,9 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo
|
||||||
if (!strcmp(iface->name, wp_drm_lease_device_v1_interface.name)) {
|
if (!strcmp(iface->name, wp_drm_lease_device_v1_interface.name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(iface->name, xwayland_shell_v1_interface.name)) {
|
||||||
|
/* Filter out the xwayland shell for usual clients */
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
15
src/snap.c
15
src/snap.c
|
|
@ -121,8 +121,9 @@ snap_move_to_edge(struct view *view, enum view_edge direction,
|
||||||
struct border next_edges;
|
struct border next_edges;
|
||||||
edges_initialize(&next_edges);
|
edges_initialize(&next_edges);
|
||||||
|
|
||||||
edges_find_neighbors(&next_edges, view, target,
|
edges_find_neighbors(&next_edges,
|
||||||
output, check_edge, /* use_pending */ true);
|
view, target, output, check_edge,
|
||||||
|
/* use_pending */ true, /* ignore_hidden */ false);
|
||||||
|
|
||||||
/* If any "best" edges were encountered, limit motion */
|
/* If any "best" edges were encountered, limit motion */
|
||||||
edges_adjust_move_coords(view, next_edges,
|
edges_adjust_move_coords(view, next_edges,
|
||||||
|
|
@ -196,8 +197,9 @@ snap_grow_to_next_edge(struct view *view, enum view_edge direction,
|
||||||
edges_initialize(&next_edges);
|
edges_initialize(&next_edges);
|
||||||
|
|
||||||
/* Limit motion to any intervening edge of other views on this output */
|
/* Limit motion to any intervening edge of other views on this output */
|
||||||
edges_find_neighbors(&next_edges, view, *geo,
|
edges_find_neighbors(&next_edges,
|
||||||
output, check_edge, /* use_pending */ true);
|
view, *geo, output, check_edge,
|
||||||
|
/* use_pending */ true, /* ignore_hidden */ false);
|
||||||
edges_adjust_resize_geom(view, next_edges,
|
edges_adjust_resize_geom(view, next_edges,
|
||||||
resize_edges, geo, /* use_pending */ true);
|
resize_edges, geo, /* use_pending */ true);
|
||||||
}
|
}
|
||||||
|
|
@ -255,8 +257,9 @@ snap_shrink_to_next_edge(struct view *view, enum view_edge direction,
|
||||||
view->output, check_edge, /* use_pending */ true);
|
view->output, check_edge, /* use_pending */ true);
|
||||||
|
|
||||||
/* Limit motion to any intervening edge of ther views on this output */
|
/* Limit motion to any intervening edge of ther views on this output */
|
||||||
edges_find_neighbors(&next_edges, view, *geo,
|
edges_find_neighbors(&next_edges,
|
||||||
view->output, check_edge, /* use_pending */ true);
|
view, *geo, view->output, check_edge,
|
||||||
|
/* use_pending */ true, /* ignore_hidden */ false);
|
||||||
|
|
||||||
edges_adjust_resize_geom(view, next_edges,
|
edges_adjust_resize_geom(view, next_edges,
|
||||||
resize_edges, geo, /* use_pending */ true);
|
resize_edges, geo, /* use_pending */ true);
|
||||||
|
|
|
||||||
83
src/view.c
83
src/view.c
|
|
@ -2,6 +2,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
#include "common/match.h"
|
#include "common/match.h"
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
|
|
@ -1519,8 +1520,44 @@ view_on_output_destroy(struct view *view)
|
||||||
view->output = NULL;
|
view->output = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum wlr_direction
|
||||||
|
opposite_direction(enum wlr_direction direction)
|
||||||
|
{
|
||||||
|
switch (direction) {
|
||||||
|
case WLR_DIRECTION_RIGHT:
|
||||||
|
return WLR_DIRECTION_LEFT;
|
||||||
|
case WLR_DIRECTION_LEFT:
|
||||||
|
return WLR_DIRECTION_RIGHT;
|
||||||
|
case WLR_DIRECTION_DOWN:
|
||||||
|
return WLR_DIRECTION_UP;
|
||||||
|
case WLR_DIRECTION_UP:
|
||||||
|
return WLR_DIRECTION_DOWN;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum wlr_direction
|
||||||
|
get_wlr_direction(enum view_edge edge)
|
||||||
|
{
|
||||||
|
switch (edge) {
|
||||||
|
case VIEW_EDGE_LEFT:
|
||||||
|
return WLR_DIRECTION_LEFT;
|
||||||
|
case VIEW_EDGE_RIGHT:
|
||||||
|
return WLR_DIRECTION_RIGHT;
|
||||||
|
case VIEW_EDGE_UP:
|
||||||
|
return WLR_DIRECTION_UP;
|
||||||
|
case VIEW_EDGE_DOWN:
|
||||||
|
return WLR_DIRECTION_DOWN;
|
||||||
|
case VIEW_EDGE_CENTER:
|
||||||
|
case VIEW_EDGE_INVALID:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct output *
|
struct output *
|
||||||
view_get_adjacent_output(struct view *view, enum view_edge edge)
|
view_get_adjacent_output(struct view *view, enum view_edge edge, bool wrap)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
struct output *output = view->output;
|
struct output *output = view->output;
|
||||||
|
|
@ -1530,32 +1567,31 @@ view_get_adjacent_output(struct view *view, enum view_edge edge)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wlr_box box = output_usable_area_in_layout_coords(output);
|
||||||
|
int lx = box.x + box.width / 2;
|
||||||
|
int ly = box.y + box.height / 2;
|
||||||
|
|
||||||
/* Determine any adjacent output in the appropriate direction */
|
/* Determine any adjacent output in the appropriate direction */
|
||||||
struct wlr_output *new_output = NULL;
|
struct wlr_output *new_output = NULL;
|
||||||
struct wlr_output *current_output = output->wlr_output;
|
struct wlr_output *current_output = output->wlr_output;
|
||||||
struct wlr_output_layout *layout = view->server->output_layout;
|
struct wlr_output_layout *layout = view->server->output_layout;
|
||||||
switch (edge) {
|
enum wlr_direction direction = get_wlr_direction(edge);
|
||||||
case VIEW_EDGE_LEFT:
|
new_output = wlr_output_layout_adjacent_output(layout, direction,
|
||||||
new_output = wlr_output_layout_adjacent_output(
|
current_output, lx, ly);
|
||||||
layout, WLR_DIRECTION_LEFT, current_output, 1, 0);
|
|
||||||
break;
|
/*
|
||||||
case VIEW_EDGE_RIGHT:
|
* Optionally wrap around from top-to-bottom or left-to-right, and vice
|
||||||
new_output = wlr_output_layout_adjacent_output(
|
* versa.
|
||||||
layout, WLR_DIRECTION_RIGHT, current_output, 1, 0);
|
*/
|
||||||
break;
|
if (wrap && !new_output) {
|
||||||
case VIEW_EDGE_UP:
|
new_output = wlr_output_layout_farthest_output(layout,
|
||||||
new_output = wlr_output_layout_adjacent_output(
|
opposite_direction(direction), current_output, lx, ly);
|
||||||
layout, WLR_DIRECTION_UP, current_output, 0, 1);
|
|
||||||
break;
|
|
||||||
case VIEW_EDGE_DOWN:
|
|
||||||
new_output = wlr_output_layout_adjacent_output(
|
|
||||||
layout, WLR_DIRECTION_DOWN, current_output, 0, 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When "adjacent" output is the same as the original, there is no adjacent */
|
/*
|
||||||
|
* When "adjacent" output is the same as the original, there is no
|
||||||
|
* adjacent
|
||||||
|
*/
|
||||||
if (!new_output || new_output == current_output) {
|
if (!new_output || new_output == current_output) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1629,7 +1665,8 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, move to edge of next adjacent display, if possible */
|
/* Otherwise, move to edge of next adjacent display, if possible */
|
||||||
struct output *output = view_get_adjacent_output(view, direction);
|
struct output *output =
|
||||||
|
view_get_adjacent_output(view, direction, /* wrap */ false);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1788,7 +1825,7 @@ view_snap_to_edge(struct view *view, enum view_edge edge,
|
||||||
|
|
||||||
if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) {
|
if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) {
|
||||||
/* We are already tiled for this edge; try to switch outputs */
|
/* We are already tiled for this edge; try to switch outputs */
|
||||||
output = view_get_adjacent_output(view, edge);
|
output = view_get_adjacent_output(view, edge, /* wrap */ false);
|
||||||
|
|
||||||
if (!output) {
|
if (!output) {
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,17 @@ struct xdg_popup {
|
||||||
struct view *parent_view;
|
struct view *parent_view;
|
||||||
struct wlr_xdg_popup *wlr_popup;
|
struct wlr_xdg_popup *wlr_popup;
|
||||||
|
|
||||||
|
struct wl_listener commit;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener new_popup;
|
struct wl_listener new_popup;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
popup_unconstrain(struct view *view, struct wlr_xdg_popup *popup)
|
popup_unconstrain(struct xdg_popup *popup)
|
||||||
{
|
{
|
||||||
|
struct view *view = popup->parent_view;
|
||||||
struct server *server = view->server;
|
struct server *server = view->server;
|
||||||
struct wlr_box *popup_box = &popup->current.geometry;
|
struct wlr_box *popup_box = &popup->wlr_popup->current.geometry;
|
||||||
struct wlr_output_layout *output_layout = server->output_layout;
|
struct wlr_output_layout *output_layout = server->output_layout;
|
||||||
struct wlr_output *wlr_output = wlr_output_layout_output_at(
|
struct wlr_output *wlr_output = wlr_output_layout_output_at(
|
||||||
output_layout, view->current.x + popup_box->x,
|
output_layout, view->current.x + popup_box->x,
|
||||||
|
|
@ -39,7 +41,7 @@ popup_unconstrain(struct view *view, struct wlr_xdg_popup *popup)
|
||||||
.width = output_box.width,
|
.width = output_box.width,
|
||||||
.height = output_box.height,
|
.height = output_box.height,
|
||||||
};
|
};
|
||||||
wlr_xdg_popup_unconstrain_from_box(popup, &output_toplevel_box);
|
wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -48,9 +50,28 @@ handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
|
||||||
struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
|
struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
|
||||||
wl_list_remove(&popup->destroy.link);
|
wl_list_remove(&popup->destroy.link);
|
||||||
wl_list_remove(&popup->new_popup.link);
|
wl_list_remove(&popup->new_popup.link);
|
||||||
|
|
||||||
|
/* Usually already removed unless there was no commit at all */
|
||||||
|
if (popup->commit.notify) {
|
||||||
|
wl_list_remove(&popup->commit.link);
|
||||||
|
}
|
||||||
free(popup);
|
free(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_xdg_popup_commit(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct xdg_popup *popup = wl_container_of(listener, popup, commit);
|
||||||
|
|
||||||
|
if (popup->wlr_popup->base->initial_commit) {
|
||||||
|
popup_unconstrain(popup);
|
||||||
|
|
||||||
|
/* Prevent getting called over and over again */
|
||||||
|
wl_list_remove(&popup->commit.link);
|
||||||
|
popup->commit.notify = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
|
popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -75,9 +96,13 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
|
||||||
|
|
||||||
popup->destroy.notify = handle_xdg_popup_destroy;
|
popup->destroy.notify = handle_xdg_popup_destroy;
|
||||||
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
|
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
|
||||||
|
|
||||||
popup->new_popup.notify = popup_handle_new_xdg_popup;
|
popup->new_popup.notify = popup_handle_new_xdg_popup;
|
||||||
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
||||||
|
|
||||||
|
popup->commit.notify = handle_xdg_popup_commit;
|
||||||
|
wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must add xdg popups to the scene graph so they get rendered. The
|
* We must add xdg popups to the scene graph so they get rendered. The
|
||||||
* wlroots scene graph provides a helper for this, but to use it we must
|
* wlroots scene graph provides a helper for this, but to use it we must
|
||||||
|
|
@ -100,6 +125,4 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
|
||||||
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
|
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
|
||||||
node_descriptor_create(wlr_popup->base->surface->data,
|
node_descriptor_create(wlr_popup->base->surface->data,
|
||||||
LAB_NODE_DESC_XDG_POPUP, view);
|
LAB_NODE_DESC_XDG_POPUP, view);
|
||||||
|
|
||||||
popup_unconstrain(view, wlr_popup);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue