mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
Compare commits
37 commits
b94416cad5
...
259803178e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
259803178e | ||
|
|
e764fc4964 | ||
|
|
a71723f1ba | ||
|
|
92c92ae28d | ||
|
|
c9b9c3d227 | ||
|
|
a9f1145802 | ||
|
|
8583637331 | ||
|
|
7f67b9c866 | ||
|
|
eebf5b3e4e | ||
|
|
89fab2d449 | ||
|
|
c78a0fe1b4 | ||
|
|
77a11568a7 | ||
|
|
953249249c | ||
|
|
ef73431367 | ||
|
|
03c70e8a5e | ||
|
|
2b3aadb6af | ||
|
|
364a1d5207 | ||
|
|
babd7af8f8 | ||
|
|
27cc738985 | ||
|
|
da96513e70 | ||
|
|
40eed3915a | ||
|
|
e6f54a0fc8 | ||
|
|
5e8df27f84 | ||
|
|
5f981226c2 | ||
|
|
2f96664670 | ||
|
|
70e5beb5ec | ||
|
|
d94e5da815 | ||
|
|
e44a489530 | ||
|
|
6cdfe32af0 | ||
|
|
e1820adcd3 | ||
|
|
474c513ed6 | ||
|
|
c27d4955a4 | ||
|
|
7166efe7bf | ||
|
|
017152da52 | ||
|
|
814af0ae4d | ||
|
|
cb0a4b875e | ||
|
|
998ff9e7b5 |
51 changed files with 840 additions and 604 deletions
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
|
@ -17,6 +17,7 @@ on:
|
||||||
- 'src/**'
|
- 'src/**'
|
||||||
- 'include/**'
|
- 'include/**'
|
||||||
- 'protocols/**'
|
- 'protocols/**'
|
||||||
|
- 'clients/**'
|
||||||
- 'scripts/**'
|
- 'scripts/**'
|
||||||
- '.github/workflows/**'
|
- '.github/workflows/**'
|
||||||
|
|
||||||
|
|
@ -93,6 +94,7 @@ jobs:
|
||||||
apt-get install -y git gcc clang gdb xwayland
|
apt-get install -y git gcc clang gdb xwayland
|
||||||
apt-get build-dep -y labwc
|
apt-get build-dep -y labwc
|
||||||
apt-get build-dep -y libwlroots-0.19-dev
|
apt-get build-dep -y libwlroots-0.19-dev
|
||||||
|
apt-get build-dep -y libxkbcommon-dev
|
||||||
|
|
||||||
- name: Install FreeBSD dependencies
|
- name: Install FreeBSD dependencies
|
||||||
if: matrix.name == 'FreeBSD'
|
if: matrix.name == 'FreeBSD'
|
||||||
|
|
@ -119,7 +121,7 @@ jobs:
|
||||||
xbps-install -y git meson gcc clang pkg-config scdoc \
|
xbps-install -y git meson gcc clang pkg-config scdoc \
|
||||||
cairo-devel glib-devel libpng-devel librsvg-devel libxml2-devel \
|
cairo-devel glib-devel libpng-devel librsvg-devel libxml2-devel \
|
||||||
pango-devel wlroots0.19-devel gdb bash xorg-server-xwayland \
|
pango-devel wlroots0.19-devel gdb bash xorg-server-xwayland \
|
||||||
dejavu-fonts-ttf libsfdo-devel foot
|
dejavu-fonts-ttf libsfdo-devel foot hwids
|
||||||
|
|
||||||
# These builds are executed on all runners
|
# These builds are executed on all runners
|
||||||
- name: Build with gcc
|
- name: Build with gcc
|
||||||
|
|
|
||||||
47
NEWS.md
47
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 |
|
||||||
|------------|---------------|-----------------|---------------|
|
|------------|---------------|-----------------|---------------|
|
||||||
| 2025-09-15 | [unreleased] | 0.19.0 | 28686 |
|
| 2025-10-10 | [0.9.2] | 0.19.1 | 28818 |
|
||||||
| 2025-08-02 | [0.9.1] | 0.19.0 | 28605 |
|
| 2025-08-02 | [0.9.1] | 0.19.0 | 28605 |
|
||||||
| 2025-07-11 | [0.9.0] | 0.19.0 | 28586 |
|
| 2025-07-11 | [0.9.0] | 0.19.0 | 28586 |
|
||||||
| 2025-05-02 | [0.8.4] | 0.18.2 | 27679 |
|
| 2025-05-02 | [0.8.4] | 0.18.2 | 27679 |
|
||||||
|
|
@ -39,6 +39,7 @@ 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]: NEWS.md#unreleased
|
[unreleased]: NEWS.md#unreleased
|
||||||
|
[0.9.2]: NEWS.md#092---2025-10-10
|
||||||
[0.9.1]: NEWS.md#091---2025-08-02
|
[0.9.1]: NEWS.md#091---2025-08-02
|
||||||
[0.9.0]: NEWS.md#090---2025-07-11
|
[0.9.0]: NEWS.md#090---2025-07-11
|
||||||
[0.8.4]: NEWS.md#084---2025-05-02
|
[0.8.4]: NEWS.md#084---2025-05-02
|
||||||
|
|
@ -100,23 +101,35 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
||||||
around a bug on the wlroots side which is expected to be fixed in wlroots
|
around a bug on the wlroots side which is expected to be fixed in wlroots
|
||||||
`0.19.1` [#2887]
|
`0.19.1` [#2887]
|
||||||
|
|
||||||
|
With wlroots compiled with libwayland (>= 1.24.0), there is an invisible margin
|
||||||
|
preventing pointer focus on some layer-shell surfaces including those created by
|
||||||
|
Gtk. In simple words, this is because libwayland now rounds floats a bit
|
||||||
|
differently [#3099]. There is a pending fix [wlroots-5159].
|
||||||
|
|
||||||
[wlroots-4878]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4878
|
[wlroots-4878]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4878
|
||||||
[wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
|
[wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
|
||||||
|
[wlroots-5159]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5159
|
||||||
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
|
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
|
||||||
|
|
||||||
## unreleased
|
## unreleased
|
||||||
|
|
||||||
[unreleased-commits]
|
[unreleased-commits]
|
||||||
|
|
||||||
|
## 0.9.2 - 2025-10-10
|
||||||
|
|
||||||
|
[0.9.2-commits]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Allow `SnapToEdge` and `ToggleSnapToEdge` to combine two cardinal directions
|
||||||
|
with the config option `combine="yes|no"`. [#3081] @tokyo4j
|
||||||
- Support `Border` context for mousebinds as an alias for `Top`...`BRCorner` to
|
- Support `Border` context for mousebinds as an alias for `Top`...`BRCorner` to
|
||||||
make configuration easier. @tokyo4j [#3047]
|
make configuration easier. @tokyo4j [#3047]
|
||||||
- Add window-switcher mode with thumbnails. This can be enabled with:
|
- Add window-switcher mode with thumbnails. This can be enabled with:
|
||||||
`<windowSwitcher style="thumbnail">`. @tokyo4j [#2981]
|
`<windowSwitcher style="thumbnail">`. @tokyo4j [#2981]
|
||||||
- Add `toggle` option to `GoToDesktop` action. This has the effect of going back
|
- Add `toggle` option to `GoToDesktop` action. This has the effect of going back
|
||||||
to the last desktop if already on the target. @RainerKuemmerle [#3024]
|
to the last desktop if already on the target. @RainerKuemmerle [#3024]
|
||||||
- Add `<core maximizedDecoration="titlebar|none"/>` to allow hiding titlebar
|
- Add `<theme maximizedDecoration="titlebar|none"/>` to allow hiding titlebar
|
||||||
when window is maximized. @CosmicFusion @tokyo4j [#3015]
|
when window is maximized. @CosmicFusion @tokyo4j [#3015]
|
||||||
- Use client-send-to-menu as 'Workspace' submenu in built-in client-menu
|
- Use client-send-to-menu as 'Workspace' submenu in built-in client-menu
|
||||||
@johanmalm [#2995]
|
@johanmalm [#2995]
|
||||||
|
|
@ -126,6 +139,7 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
||||||
[#2994]
|
[#2994]
|
||||||
- Add `labnag` (a dialog client with message and buttons) and associated
|
- Add `labnag` (a dialog client with message and buttons) and associated
|
||||||
`<prompt>` option in 'If' actions. @johanmalm @Consolatis @tokyo4j [#2699]
|
`<prompt>` option in 'If' actions. @johanmalm @Consolatis @tokyo4j [#2699]
|
||||||
|
- Support config option `<core><promptCommand>` @johanmalm [#3097]
|
||||||
- Allow snapping to corner edges during interactive move with associated config
|
- Allow snapping to corner edges during interactive move with associated config
|
||||||
options `<snapping><cornerRange>`. @tokyo4j [#2885]
|
options `<snapping><cornerRange>`. @tokyo4j [#2885]
|
||||||
- Support new values "up-left", "up-right", "down-left" and "down-right" with
|
- Support new values "up-left", "up-right", "down-left" and "down-right" with
|
||||||
|
|
@ -147,6 +161,7 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- On detecting broken icon theme, fall back on 'hicolor' @Consolatis [#3126]
|
||||||
- Restore initially-maximized window position after unplug/plug @tokyo4j [#3042]
|
- Restore initially-maximized window position after unplug/plug @tokyo4j [#3042]
|
||||||
- Fix large client-side icon not being loaded when the rendered icon size is
|
- Fix large client-side icon not being loaded when the rendered icon size is
|
||||||
larger than icon sizes from the client. @tokyo4j [#3033]
|
larger than icon sizes from the client. @tokyo4j [#3033]
|
||||||
|
|
@ -162,6 +177,27 @@ There are some regression warnings worth noting for the switch to wlroots 0.19:
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Change default keybind `W-<arrow>` to combine cardinal directions to support
|
||||||
|
resizing of windows to fill a quarter of an output. This only affects users
|
||||||
|
who do not use an `rc.xml` (thereby using default keybinds) or use the
|
||||||
|
`<keyboard><default/>` option. Previous behavior can be restored by setting
|
||||||
|
`combine="no"` as shown below. [#3081] @tokyo4j
|
||||||
|
|
||||||
|
```
|
||||||
|
<keybind key="W-Left">
|
||||||
|
<action name="SnapToEdge" direction="left" combine="no" />
|
||||||
|
</keybind>
|
||||||
|
<keybind key="W-Right">
|
||||||
|
<action name="SnapToEdge" direction="right" combine="no" />
|
||||||
|
</keybind>
|
||||||
|
<keybind key="W-Up">
|
||||||
|
<action name="SnapToEdge" direction="up" combine="no" />
|
||||||
|
</keybind>
|
||||||
|
<keybind key="W-Down">
|
||||||
|
<action name="SnapToEdge" direction="down" combine="no" />
|
||||||
|
</keybind>
|
||||||
|
```
|
||||||
|
|
||||||
- `Focus` and `Raise` on window border press because it is probably what most
|
- `Focus` and `Raise` on window border press because it is probably what most
|
||||||
people expect and it makes the behavior consistent with that of Openbox.
|
people expect and it makes the behavior consistent with that of Openbox.
|
||||||
@johanmalm [#3039] [#3049]
|
@johanmalm [#3039] [#3049]
|
||||||
|
|
@ -2337,7 +2373,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-commits]: https://github.com/labwc/labwc/compare/0.9.0...HEAD
|
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.9.2...HEAD
|
||||||
|
[0.9.2-commits]: https://github.com/labwc/labwc/compare/0.9.1...0.9.2
|
||||||
[0.9.1-commits]: https://github.com/labwc/labwc/compare/0.9.0...0.9.1
|
[0.9.1-commits]: https://github.com/labwc/labwc/compare/0.9.0...0.9.1
|
||||||
[0.9.0-commits]: https://github.com/labwc/labwc/compare/0.8.4...0.9.0
|
[0.9.0-commits]: https://github.com/labwc/labwc/compare/0.8.4...0.9.0
|
||||||
[0.8.4-commits]: https://github.com/labwc/labwc/compare/0.8.3...0.8.4
|
[0.8.4-commits]: https://github.com/labwc/labwc/compare/0.8.3...0.8.4
|
||||||
|
|
@ -2800,3 +2837,7 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
|
||||||
[#3043]: https://github.com/labwc/labwc/pull/3043
|
[#3043]: https://github.com/labwc/labwc/pull/3043
|
||||||
[#3047]: https://github.com/labwc/labwc/pull/3047
|
[#3047]: https://github.com/labwc/labwc/pull/3047
|
||||||
[#3049]: https://github.com/labwc/labwc/pull/3049
|
[#3049]: https://github.com/labwc/labwc/pull/3049
|
||||||
|
[#3081]: https://github.com/labwc/labwc/pull/3081
|
||||||
|
[#3097]: https://github.com/labwc/labwc/pull/3097
|
||||||
|
[#3099]: https://github.com/labwc/labwc/pull/3099
|
||||||
|
[#3126]: https://github.com/labwc/labwc/pull/3126
|
||||||
|
|
|
||||||
246
clients/labnag.c
246
clients/labnag.c
|
|
@ -19,6 +19,7 @@
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
#include <sys/event.h> /* For signalfd() */
|
#include <sys/event.h> /* For signalfd() */
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include "action-prompt-codes.h"
|
#include "action-prompt-codes.h"
|
||||||
#include "pool-buffer.h"
|
#include "pool-buffer.h"
|
||||||
#include "cursor-shape-v1-client-protocol.h"
|
#include "cursor-shape-v1-client-protocol.h"
|
||||||
|
|
@ -38,6 +40,7 @@ struct conf {
|
||||||
char *output;
|
char *output;
|
||||||
uint32_t anchors;
|
uint32_t anchors;
|
||||||
int32_t layer; /* enum zwlr_layer_shell_v1_layer or -1 if unset */
|
int32_t layer; /* enum zwlr_layer_shell_v1_layer or -1 if unset */
|
||||||
|
enum zwlr_layer_surface_v1_keyboard_interactivity keyboard_focus;
|
||||||
|
|
||||||
/* Colors */
|
/* Colors */
|
||||||
uint32_t button_text;
|
uint32_t button_text;
|
||||||
|
|
@ -69,11 +72,18 @@ struct pointer {
|
||||||
int y;
|
int y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct keyboard {
|
||||||
|
struct wl_keyboard *keyboard;
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_state *state;
|
||||||
|
};
|
||||||
|
|
||||||
struct seat {
|
struct seat {
|
||||||
struct wl_seat *wl_seat;
|
struct wl_seat *wl_seat;
|
||||||
uint32_t wl_name;
|
uint32_t wl_name;
|
||||||
struct nag *nag;
|
struct nag *nag;
|
||||||
struct pointer pointer;
|
struct pointer pointer;
|
||||||
|
struct keyboard keyboard;
|
||||||
struct wl_list link; /* nag.seats */
|
struct wl_list link; /* nag.seats */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -130,6 +140,7 @@ struct nag {
|
||||||
struct conf *conf;
|
struct conf *conf;
|
||||||
char *message;
|
char *message;
|
||||||
struct wl_list buttons;
|
struct wl_list buttons;
|
||||||
|
int selected_button;
|
||||||
struct pollfd pollfds[NR_FDS];
|
struct pollfd pollfds[NR_FDS];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -409,7 +420,8 @@ render_detailed(cairo_t *cairo, struct nag *nag, uint32_t y)
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
render_button(cairo_t *cairo, struct nag *nag, struct button *button, int *x)
|
render_button(cairo_t *cairo, struct nag *nag, struct button *button,
|
||||||
|
bool selected, int *x)
|
||||||
{
|
{
|
||||||
int text_width, text_height;
|
int text_width, text_height;
|
||||||
get_text_size(cairo, nag->conf->font_description, &text_width,
|
get_text_size(cairo, nag->conf->font_description, &text_width,
|
||||||
|
|
@ -439,6 +451,14 @@ render_button(cairo_t *cairo, struct nag *nag, struct button *button, int *x)
|
||||||
button->width, button->height);
|
button->width, button->height);
|
||||||
cairo_fill(cairo);
|
cairo_fill(cairo);
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
cairo_set_source_u32(cairo, nag->conf->button_border);
|
||||||
|
cairo_set_line_width(cairo, 1);
|
||||||
|
cairo_rectangle(cairo, button->x + 1.5, button->y + 1.5,
|
||||||
|
button->width - 3, button->height - 3);
|
||||||
|
cairo_stroke(cairo);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_set_source_u32(cairo, nag->conf->button_text);
|
cairo_set_source_u32(cairo, nag->conf->button_text);
|
||||||
cairo_move_to(cairo, button->x + padding, button->y + padding);
|
cairo_move_to(cairo, button->x + padding, button->y + padding);
|
||||||
render_text(cairo, nag->conf->font_description, 1, true,
|
render_text(cairo, nag->conf->font_description, 1, true,
|
||||||
|
|
@ -464,11 +484,13 @@ render_to_cairo(cairo_t *cairo, struct nag *nag)
|
||||||
int x = nag->width - nag->conf->button_margin_right;
|
int x = nag->width - nag->conf->button_margin_right;
|
||||||
x -= nag->conf->button_gap_close;
|
x -= nag->conf->button_gap_close;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
struct button *button;
|
struct button *button;
|
||||||
wl_list_for_each(button, &nag->buttons, link) {
|
wl_list_for_each(button, &nag->buttons, link) {
|
||||||
h = render_button(cairo, nag, button, &x);
|
h = render_button(cairo, nag, button, idx == nag->selected_button, &x);
|
||||||
max_height = h > max_height ? h : max_height;
|
max_height = h > max_height ? h : max_height;
|
||||||
x -= nag->conf->button_gap;
|
x -= nag->conf->button_gap;
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nag->details.visible) {
|
if (nag->details.visible) {
|
||||||
|
|
@ -555,6 +577,15 @@ seat_destroy(struct seat *seat)
|
||||||
if (seat->pointer.pointer) {
|
if (seat->pointer.pointer) {
|
||||||
wl_pointer_destroy(seat->pointer.pointer);
|
wl_pointer_destroy(seat->pointer.pointer);
|
||||||
}
|
}
|
||||||
|
if (seat->keyboard.keyboard) {
|
||||||
|
wl_keyboard_destroy(seat->keyboard.keyboard);
|
||||||
|
}
|
||||||
|
if (seat->keyboard.keymap) {
|
||||||
|
xkb_keymap_unref(seat->keyboard.keymap);
|
||||||
|
}
|
||||||
|
if (seat->keyboard.state) {
|
||||||
|
xkb_state_unref(seat->keyboard.state);
|
||||||
|
}
|
||||||
wl_seat_destroy(seat->wl_seat);
|
wl_seat_destroy(seat->wl_seat);
|
||||||
wl_list_remove(&seat->link);
|
wl_list_remove(&seat->link);
|
||||||
free(seat);
|
free(seat);
|
||||||
|
|
@ -939,12 +970,170 @@ static const struct wl_pointer_listener pointer_listener = {
|
||||||
.axis_discrete = wl_pointer_axis_discrete,
|
.axis_discrete = wl_pointer_axis_discrete,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
|
uint32_t format, int32_t fd, uint32_t size)
|
||||||
|
{
|
||||||
|
struct seat *seat = data;
|
||||||
|
|
||||||
|
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||||
|
wlr_log(WLR_ERROR, "unreconizable keymap format: %d", format);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *map_shm = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (map_shm == MAP_FAILED) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "mmap()");
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seat->keyboard.keymap) {
|
||||||
|
xkb_keymap_unref(seat->keyboard.keymap);
|
||||||
|
seat->keyboard.keymap = NULL;
|
||||||
|
}
|
||||||
|
if (seat->keyboard.state) {
|
||||||
|
xkb_state_unref(seat->keyboard.state);
|
||||||
|
seat->keyboard.state = NULL;
|
||||||
|
}
|
||||||
|
struct xkb_context *xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
seat->keyboard.keymap = xkb_keymap_new_from_string(xkb, map_shm,
|
||||||
|
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
if (seat->keyboard.keymap) {
|
||||||
|
seat->keyboard.state = xkb_state_new(seat->keyboard.keymap);
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "failed to compile keymap");
|
||||||
|
}
|
||||||
|
xkb_context_unref(xkb);
|
||||||
|
|
||||||
|
munmap(map_shm, size);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
|
struct wl_surface *surface, struct wl_array *keys)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
|
struct wl_surface *surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
|
uint32_t time, uint32_t key, uint32_t state)
|
||||||
|
{
|
||||||
|
struct seat *seat = data;
|
||||||
|
struct nag *nag = seat->nag;
|
||||||
|
|
||||||
|
if (!seat->keyboard.keymap || !seat->keyboard.state) {
|
||||||
|
wlr_log(WLR_ERROR, "keymap/state unavailable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
key += 8;
|
||||||
|
const xkb_keysym_t *syms;
|
||||||
|
if (!xkb_keymap_key_get_syms_by_level(seat->keyboard.keymap,
|
||||||
|
key, 0, 0, &syms)) {
|
||||||
|
wlr_log(WLR_ERROR, "failed to translate key: %d", key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xkb_mod_mask_t mods = xkb_state_serialize_mods(seat->keyboard.state,
|
||||||
|
XKB_STATE_MODS_EFFECTIVE);
|
||||||
|
xkb_mod_index_t shift_idx = xkb_keymap_mod_get_index(
|
||||||
|
seat->keyboard.keymap, XKB_MOD_NAME_SHIFT);
|
||||||
|
bool shift = shift_idx != XKB_MOD_INVALID && (mods & (1 << shift_idx));
|
||||||
|
|
||||||
|
int nr_buttons = wl_list_length(&nag->buttons);
|
||||||
|
|
||||||
|
switch (syms[0]) {
|
||||||
|
case XKB_KEY_Left:
|
||||||
|
case XKB_KEY_Right:
|
||||||
|
case XKB_KEY_Tab: {
|
||||||
|
if (nr_buttons <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int direction;
|
||||||
|
if (syms[0] == XKB_KEY_Left || (syms[0] == XKB_KEY_Tab && shift)) {
|
||||||
|
direction = 1;
|
||||||
|
} else {
|
||||||
|
direction = -1;
|
||||||
|
}
|
||||||
|
nag->selected_button += nr_buttons + direction;
|
||||||
|
nag->selected_button %= nr_buttons;
|
||||||
|
render_frame(nag);
|
||||||
|
close_pollfd(&nag->pollfds[FD_TIMER]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XKB_KEY_Escape:
|
||||||
|
exit_status = LAB_EXIT_CANCELLED;
|
||||||
|
nag->run_display = false;
|
||||||
|
break;
|
||||||
|
case XKB_KEY_Return:
|
||||||
|
case XKB_KEY_KP_Enter: {
|
||||||
|
int idx = 0;
|
||||||
|
struct button *button;
|
||||||
|
wl_list_for_each(button, &nag->buttons, link) {
|
||||||
|
if (idx == nag->selected_button) {
|
||||||
|
button_execute(nag, button);
|
||||||
|
close_pollfd(&nag->pollfds[FD_TIMER]);
|
||||||
|
exit_status = idx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
|
uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
|
||||||
|
uint32_t mods_locked, uint32_t group)
|
||||||
|
{
|
||||||
|
struct seat *seat = data;
|
||||||
|
|
||||||
|
if (!seat->keyboard.state) {
|
||||||
|
wlr_log(WLR_ERROR, "xkb state unavailable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_state_update_mask(seat->keyboard.state, mods_depressed,
|
||||||
|
mods_latched, mods_locked, 0, 0, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
|
int32_t rate, int32_t delay)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wl_keyboard_listener keyboard_listener = {
|
||||||
|
.keymap = wl_keyboard_keymap,
|
||||||
|
.enter = wl_keyboard_enter,
|
||||||
|
.leave = wl_keyboard_leave,
|
||||||
|
.key = wl_keyboard_key,
|
||||||
|
.modifiers = wl_keyboard_modifiers,
|
||||||
|
.repeat_info = wl_keyboard_repeat_info,
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
||||||
enum wl_seat_capability caps)
|
enum wl_seat_capability caps)
|
||||||
{
|
{
|
||||||
struct seat *seat = data;
|
struct seat *seat = data;
|
||||||
bool cap_pointer = caps & WL_SEAT_CAPABILITY_POINTER;
|
bool cap_pointer = caps & WL_SEAT_CAPABILITY_POINTER;
|
||||||
|
bool cap_keyboard = caps & WL_SEAT_CAPABILITY_KEYBOARD;
|
||||||
|
|
||||||
if (cap_pointer && !seat->pointer.pointer) {
|
if (cap_pointer && !seat->pointer.pointer) {
|
||||||
seat->pointer.pointer = wl_seat_get_pointer(wl_seat);
|
seat->pointer.pointer = wl_seat_get_pointer(wl_seat);
|
||||||
wl_pointer_add_listener(seat->pointer.pointer,
|
wl_pointer_add_listener(seat->pointer.pointer,
|
||||||
|
|
@ -953,6 +1142,15 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
||||||
wl_pointer_destroy(seat->pointer.pointer);
|
wl_pointer_destroy(seat->pointer.pointer);
|
||||||
seat->pointer.pointer = NULL;
|
seat->pointer.pointer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cap_keyboard && !seat->keyboard.keyboard) {
|
||||||
|
seat->keyboard.keyboard = wl_seat_get_keyboard(wl_seat);
|
||||||
|
wl_keyboard_add_listener(seat->keyboard.keyboard,
|
||||||
|
&keyboard_listener, seat);
|
||||||
|
} else if (!cap_keyboard && seat->keyboard.keyboard) {
|
||||||
|
wl_keyboard_destroy(seat->keyboard.keyboard);
|
||||||
|
seat->keyboard.keyboard = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1075,7 +1273,7 @@ handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
}
|
}
|
||||||
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
|
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
|
||||||
nag->layer_shell = wl_registry_bind(
|
nag->layer_shell = wl_registry_bind(
|
||||||
registry, name, &zwlr_layer_shell_v1_interface, 1);
|
registry, name, &zwlr_layer_shell_v1_interface, 4);
|
||||||
} else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
|
} else if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) {
|
||||||
nag->cursor_shape_manager = wl_registry_bind(
|
nag->cursor_shape_manager = wl_registry_bind(
|
||||||
registry, name, &wp_cursor_shape_manager_v1_interface, 1);
|
registry, name, &wp_cursor_shape_manager_v1_interface, 1);
|
||||||
|
|
@ -1170,6 +1368,8 @@ nag_setup(struct nag *nag)
|
||||||
&layer_surface_listener, nag);
|
&layer_surface_listener, nag);
|
||||||
zwlr_layer_surface_v1_set_anchor(nag->layer_surface,
|
zwlr_layer_surface_v1_set_anchor(nag->layer_surface,
|
||||||
nag->conf->anchors);
|
nag->conf->anchors);
|
||||||
|
zwlr_layer_surface_v1_set_keyboard_interactivity(nag->layer_surface,
|
||||||
|
nag->conf->keyboard_focus);
|
||||||
|
|
||||||
wl_registry_destroy(registry);
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
|
|
@ -1233,7 +1433,7 @@ nag_run(struct nag *nag)
|
||||||
wl_display_cancel_read(nag->display);
|
wl_display_cancel_read(nag->display);
|
||||||
}
|
}
|
||||||
if (nag->pollfds[FD_TIMER].revents & POLLIN) {
|
if (nag->pollfds[FD_TIMER].revents & POLLIN) {
|
||||||
exit_status = LAB_EXIT_TIMEOUT;
|
exit_status = LAB_EXIT_CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nag->pollfds[FD_SIGNAL].revents & POLLIN) {
|
if (nag->pollfds[FD_SIGNAL].revents & POLLIN) {
|
||||||
|
|
@ -1250,13 +1450,7 @@ conf_init(struct conf *conf)
|
||||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
|
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
|
||||||
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||||
conf->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
|
conf->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
|
||||||
conf->button_background = 0x333333FF;
|
conf->keyboard_focus = ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||||
conf->details_background = 0x333333FF;
|
|
||||||
conf->background = 0x323232FF;
|
|
||||||
conf->text = 0xFFFFFFFF;
|
|
||||||
conf->button_text = 0xFFFFFFFF;
|
|
||||||
conf->button_border = 0x222222FF;
|
|
||||||
conf->border_bottom = 0x444444FF;
|
|
||||||
conf->bar_border_thickness = 2;
|
conf->bar_border_thickness = 2;
|
||||||
conf->message_padding = 8;
|
conf->message_padding = 8;
|
||||||
conf->details_border_thickness = 3;
|
conf->details_border_thickness = 3;
|
||||||
|
|
@ -1364,6 +1558,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
||||||
{"debug", no_argument, NULL, 'd'},
|
{"debug", no_argument, NULL, 'd'},
|
||||||
{"edge", required_argument, NULL, 'e'},
|
{"edge", required_argument, NULL, 'e'},
|
||||||
{"layer", required_argument, NULL, 'y'},
|
{"layer", required_argument, NULL, 'y'},
|
||||||
|
{"keyboard-focus", required_argument, NULL, 'k'},
|
||||||
{"font", required_argument, NULL, 'f'},
|
{"font", required_argument, NULL, 'f'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{"detailed-message", no_argument, NULL, 'l'},
|
{"detailed-message", no_argument, NULL, 'l'},
|
||||||
|
|
@ -1402,6 +1597,8 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
||||||
" -e, --edge top|bottom Set the edge to use.\n"
|
" -e, --edge top|bottom Set the edge to use.\n"
|
||||||
" -y, --layer overlay|top|bottom|background\n"
|
" -y, --layer overlay|top|bottom|background\n"
|
||||||
" Set the layer to use.\n"
|
" Set the layer to use.\n"
|
||||||
|
" -k, --keyboard-focus none|exclusive|on-demand|\n"
|
||||||
|
" Set the policy for keyboard focus.\n"
|
||||||
" -f, --font <font> Set the font to use.\n"
|
" -f, --font <font> Set the font to use.\n"
|
||||||
" -h, --help Show help message and quit.\n"
|
" -h, --help Show help message and quit.\n"
|
||||||
" -l, --detailed-message Read a detailed message from stdin.\n"
|
" -l, --detailed-message Read a detailed message from stdin.\n"
|
||||||
|
|
@ -1433,7 +1630,7 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
||||||
|
|
||||||
optind = 1;
|
optind = 1;
|
||||||
while (1) {
|
while (1) {
|
||||||
int c = getopt_long(argc, argv, "B:Z:c:de:y:f:hlL:m:o:s:t:vx", opts, NULL);
|
int c = getopt_long(argc, argv, "B:Z:c:de:y:k:f:hlL:m:o:s:t:vx", opts, NULL);
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1487,6 +1684,23 @@ nag_parse_options(int argc, char **argv, struct nag *nag,
|
||||||
return LAB_EXIT_FAILURE;
|
return LAB_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'k':
|
||||||
|
if (strcmp(optarg, "none") == 0) {
|
||||||
|
conf->keyboard_focus =
|
||||||
|
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE;
|
||||||
|
} else if (strcmp(optarg, "exclusive") == 0) {
|
||||||
|
conf->keyboard_focus =
|
||||||
|
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
|
||||||
|
} else if (strcmp(optarg, "on-demand") == 0) {
|
||||||
|
conf->keyboard_focus =
|
||||||
|
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid keyboard focus: %s\n"
|
||||||
|
"Usage: --keyboard-focus none|exclusive|on-demand\n",
|
||||||
|
optarg);
|
||||||
|
return LAB_EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'f': /* Font */
|
case 'f': /* Font */
|
||||||
pango_font_description_free(conf->font_description);
|
pango_font_description_free(conf->font_description);
|
||||||
conf->font_description = pango_font_description_from_string(optarg);
|
conf->font_description = pango_font_description_from_string(optarg);
|
||||||
|
|
@ -1629,6 +1843,14 @@ main(int argc, char **argv)
|
||||||
wl_list_insert(nag.buttons.prev, &nag.details.button_details->link);
|
wl_list_insert(nag.buttons.prev, &nag.details.button_details->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nr_buttons = wl_list_length(&nag.buttons);
|
||||||
|
if (conf.keyboard_focus && nr_buttons > 0) {
|
||||||
|
/* select the leftmost button */
|
||||||
|
nag.selected_button = nr_buttons - 1;
|
||||||
|
} else {
|
||||||
|
nag.selected_button = -1;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "Output: %s", nag.conf->output);
|
wlr_log(WLR_DEBUG, "Output: %s", nag.conf->output);
|
||||||
wlr_log(WLR_DEBUG, "Anchors: %lu", (unsigned long)nag.conf->anchors);
|
wlr_log(WLR_DEBUG, "Anchors: %lu", (unsigned long)nag.conf->anchors);
|
||||||
wlr_log(WLR_DEBUG, "Message: %s", nag.message);
|
wlr_log(WLR_DEBUG, "Message: %s", nag.message);
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,10 @@ executable(
|
||||||
wlroots,
|
wlroots,
|
||||||
server_protos,
|
server_protos,
|
||||||
epoll_dep,
|
epoll_dep,
|
||||||
|
xkbcommon,
|
||||||
],
|
],
|
||||||
include_directories: [labwc_inc],
|
include_directories: [labwc_inc],
|
||||||
install: true
|
install: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
clients = files('lab-sensible-terminal')
|
clients = files('lab-sensible-terminal')
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ _labnag_ [options...]
|
||||||
*-y, --layer* overlay|top|bottom|background
|
*-y, --layer* overlay|top|bottom|background
|
||||||
Set the layer to use.
|
Set the layer to use.
|
||||||
|
|
||||||
|
*-k, --keyboard-focus none|exclusive|on-demand*
|
||||||
|
Set the policy for keyboard focus.
|
||||||
|
|
||||||
*-f, --font* <font>
|
*-f, --font* <font>
|
||||||
Set the font to use.
|
Set the font to use.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,6 @@ this is for compatibility with Openbox.
|
||||||
```
|
```
|
||||||
<core>
|
<core>
|
||||||
<decoration>server</decoration>
|
<decoration>server</decoration>
|
||||||
<maximizedDecoration>titlebar</maximizedDecoration>
|
|
||||||
<gap>0</gap>
|
<gap>0</gap>
|
||||||
<adaptiveSync>no</adaptiveSync>
|
<adaptiveSync>no</adaptiveSync>
|
||||||
<allowTearing>no</allowTearing>
|
<allowTearing>no</allowTearing>
|
||||||
|
|
@ -188,11 +187,6 @@ this is for compatibility with Openbox.
|
||||||
that it is not always possible to turn off client side decorations.
|
that it is not always possible to turn off client side decorations.
|
||||||
Default is server.
|
Default is server.
|
||||||
|
|
||||||
*<core><maximizedDecoration>* [titlebar|none]
|
|
||||||
Specify how server side decorations are shown for maximized windows.
|
|
||||||
*titlebar* shows titlebar above a maximized window. *none* shows no server
|
|
||||||
side decorations around a maximized window. Default is titlebar.
|
|
||||||
|
|
||||||
*<core><gap>*
|
*<core><gap>*
|
||||||
The distance in pixels between windows and output edges when using
|
The distance in pixels between windows and output edges when using
|
||||||
movement actions, for example MoveToEdge. Default is 0.
|
movement actions, for example MoveToEdge. Default is 0.
|
||||||
|
|
@ -291,6 +285,7 @@ this is for compatibility with Openbox.
|
||||||
--button-text-color '%t' \\
|
--button-text-color '%t' \\
|
||||||
--border-bottom-size 1 \\
|
--border-bottom-size 1 \\
|
||||||
--button-border-size 3 \\
|
--button-border-size 3 \\
|
||||||
|
--keyboard-focus on-demand \\
|
||||||
--timeout 0
|
--timeout 0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -352,7 +347,7 @@ this is for compatibility with Openbox.
|
||||||
</windowSwitcher>
|
</windowSwitcher>
|
||||||
```
|
```
|
||||||
|
|
||||||
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="">*
|
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="" unshade="">*
|
||||||
*show* [yes|no] Draw the OnScreenDisplay when switching between
|
*show* [yes|no] Draw the OnScreenDisplay when switching between
|
||||||
windows. Default is yes.
|
windows. Default is yes.
|
||||||
|
|
||||||
|
|
@ -370,6 +365,9 @@ this is for compatibility with Openbox.
|
||||||
they are on. Default no (that is only windows on the current workspace
|
they are on. Default no (that is only windows on the current workspace
|
||||||
are shown).
|
are shown).
|
||||||
|
|
||||||
|
*unshade* [yes|no] Temporarily unshade windows when switching between
|
||||||
|
them and permanently unshade on the final selection. Default is yes.
|
||||||
|
|
||||||
*<windowSwitcher><fields><field content="" width="%">*
|
*<windowSwitcher><fields><field content="" width="%">*
|
||||||
Define window switcher fields when using *<windowSwitcher style="classic" />*.
|
Define window switcher fields when using *<windowSwitcher style="classic" />*.
|
||||||
|
|
||||||
|
|
@ -403,9 +401,9 @@ this is for compatibility with Openbox.
|
||||||
fields are:
|
fields are:
|
||||||
- 'B' - shell type, values [xwayland|xdg-shell]
|
- 'B' - shell type, values [xwayland|xdg-shell]
|
||||||
- 'b' - shell type (short form), values [X|W]
|
- 'b' - shell type (short form), values [X|W]
|
||||||
- 'S' - state of window, values [M|m|F] (3 spaces allocated)
|
- 'S' - state of window, values [m|s|M|F] (4 spaces allocated)
|
||||||
(maximized, minimized, fullscreen)
|
(minimized, shaded, maximized, fullscreen)
|
||||||
- 's' - state of window (short form), values [M|m|F] (1 space)
|
- 's' - state of window (short form), values [m|s|M|F] (1 space)
|
||||||
- 'I' - wm-class/app-id
|
- 'I' - wm-class/app-id
|
||||||
- 'i' - wm-class/app-id trimmed, remove "org." if available
|
- 'i' - wm-class/app-id trimmed, remove "org." if available
|
||||||
- 'n' - desktop entry/file application name, falls back to
|
- 'n' - desktop entry/file application name, falls back to
|
||||||
|
|
@ -603,6 +601,11 @@ extending outward from the snapped edge.
|
||||||
Even when disabling server side decorations via ToggleDecorations,
|
Even when disabling server side decorations via ToggleDecorations,
|
||||||
keep a small border (and resize area) around the window. Default is yes.
|
keep a small border (and resize area) around the window. Default is yes.
|
||||||
|
|
||||||
|
*<theme><maximizedDecoration>* [titlebar|none]
|
||||||
|
Specify how server side decorations are shown for maximized windows.
|
||||||
|
*titlebar* shows titlebar above a maximized window. *none* shows no server
|
||||||
|
side decorations around a maximized window. Default is titlebar.
|
||||||
|
|
||||||
*<theme><dropShadows>* [yes|no]
|
*<theme><dropShadows>* [yes|no]
|
||||||
Should drop-shadows be rendered behind windows. Default is no.
|
Should drop-shadows be rendered behind windows. Default is no.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,14 @@ all are supported.
|
||||||
Border width of the selection box in the window switcher in pixels.
|
Border width of the selection box in the window switcher in pixels.
|
||||||
Default is 2.
|
Default is 2.
|
||||||
|
|
||||||
|
*osd.window-switcher.style-classic.item.active.border.color*
|
||||||
|
Border color around the selected window switcher item.
|
||||||
|
Default is *osd.label.text.color* with 50% opacity.
|
||||||
|
|
||||||
|
*osd.window-switcher.style-classic.item.active.bg.color*
|
||||||
|
Background color of the selected window switcher item.
|
||||||
|
Default is *osd.label.text.color* with 15% opacity.
|
||||||
|
|
||||||
*osd.window-switcher.style-classic.item.icon.size*
|
*osd.window-switcher.style-classic.item.icon.size*
|
||||||
Size of the icon in window switcher, in pixels.
|
Size of the icon in window switcher, in pixels.
|
||||||
If not set, the font size derived from <theme><font place="OnScreenDisplay">
|
If not set, the font size derived from <theme><font place="OnScreenDisplay">
|
||||||
|
|
@ -358,10 +366,12 @@ all are supported.
|
||||||
Border width of selected window switcher items in pixels. Default is 2.
|
Border width of selected window switcher items in pixels. Default is 2.
|
||||||
|
|
||||||
*osd.window-switcher.style-thumbnail.item.active.border.color*
|
*osd.window-switcher.style-thumbnail.item.active.border.color*
|
||||||
Color of border around selected window switcher items. Default is #589bda.
|
Color of border around selected window switcher items.
|
||||||
|
Default is *osd.label.text.color* with 50% opacity.
|
||||||
|
|
||||||
*osd.window-switcher.style-thumbnail.item.active.bg.color*
|
*osd.window-switcher.style-thumbnail.item.active.bg.color*
|
||||||
Color of selected window switcher items. Default is #c7e2fc.
|
Color of selected window switcher items.
|
||||||
|
Default is *osd.label.text.color* with 15% opacity.
|
||||||
|
|
||||||
*osd.window-switcher.style-thumbnail.item.icon.size*
|
*osd.window-switcher.style-thumbnail.item.icon.size*
|
||||||
Size of window icons in window switcher items in pixels. Default is 60.
|
Size of window icons in window switcher items in pixels. Default is 60.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
<core>
|
<core>
|
||||||
<decoration>server</decoration>
|
<decoration>server</decoration>
|
||||||
<maximizedDecoration>titlebar</maximizedDecoration>
|
|
||||||
<gap>0</gap>
|
<gap>0</gap>
|
||||||
<adaptiveSync>no</adaptiveSync>
|
<adaptiveSync>no</adaptiveSync>
|
||||||
<allowTearing>no</allowTearing>
|
<allowTearing>no</allowTearing>
|
||||||
|
|
@ -45,6 +44,7 @@
|
||||||
</titlebar>
|
</titlebar>
|
||||||
<cornerRadius>8</cornerRadius>
|
<cornerRadius>8</cornerRadius>
|
||||||
<keepBorder>yes</keepBorder>
|
<keepBorder>yes</keepBorder>
|
||||||
|
<maximizedDecoration>titlebar</maximizedDecoration>
|
||||||
<dropShadows>no</dropShadows>
|
<dropShadows>no</dropShadows>
|
||||||
<dropShadowsOnTiled>no</dropShadowsOnTiled>
|
<dropShadowsOnTiled>no</dropShadowsOnTiled>
|
||||||
<font place="ActiveWindow">
|
<font place="ActiveWindow">
|
||||||
|
|
@ -79,7 +79,8 @@
|
||||||
</font>
|
</font>
|
||||||
</theme>
|
</theme>
|
||||||
|
|
||||||
<windowSwitcher show="yes" style="classic" preview="yes" outlines="yes" allWorkspaces="no">
|
<windowSwitcher show="yes" style="classic" preview="yes"
|
||||||
|
outlines="yes" allWorkspaces="no" unshade="yes">
|
||||||
<fields>
|
<fields>
|
||||||
<field content="icon" width="5%" />
|
<field content="icon" width="5%" />
|
||||||
<field content="desktop_entry_name" width="30%" />
|
<field content="desktop_entry_name" width="30%" />
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,8 @@ osd.window-switcher.style-classic.padding: 4
|
||||||
osd.window-switcher.style-classic.item.padding.x: 10
|
osd.window-switcher.style-classic.item.padding.x: 10
|
||||||
osd.window-switcher.style-classic.item.padding.y: 1
|
osd.window-switcher.style-classic.item.padding.y: 1
|
||||||
osd.window-switcher.style-classic.item.active.border.width: 2
|
osd.window-switcher.style-classic.item.active.border.width: 2
|
||||||
|
osd.window-switcher.style-classic.item.active.border.color: #706f6d
|
||||||
|
osd.window-switcher.style-classic.item.active.bg.color: #bfbcba
|
||||||
# The icon size the same as the font size by default
|
# The icon size the same as the font size by default
|
||||||
# osd.window-switcher.style-classic.item.icon.size: 50
|
# osd.window-switcher.style-classic.item.icon.size: 50
|
||||||
|
|
||||||
|
|
@ -106,8 +108,8 @@ osd.window-switcher.style-thumbnail.item.width: 300
|
||||||
osd.window-switcher.style-thumbnail.item.height: 250
|
osd.window-switcher.style-thumbnail.item.height: 250
|
||||||
osd.window-switcher.style-thumbnail.item.padding: 10
|
osd.window-switcher.style-thumbnail.item.padding: 10
|
||||||
osd.window-switcher.style-thumbnail.item.active.border.width: 2
|
osd.window-switcher.style-thumbnail.item.active.border.width: 2
|
||||||
osd.window-switcher.style-thumbnail.item.active.border.color: #589bda
|
osd.window-switcher.style-thumbnail.item.active.border.color: #706f6d
|
||||||
osd.window-switcher.style-thumbnail.item.active.bg.color: #c7e2fc
|
osd.window-switcher.style-thumbnail.item.active.bg.color: #bfbcba
|
||||||
osd.window-switcher.style-thumbnail.item.icon.size: 60
|
osd.window-switcher.style-thumbnail.item.icon.size: 60
|
||||||
|
|
||||||
osd.window-switcher.preview.border.width: 1
|
osd.window-switcher.preview.border.width: 1
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#define LABWC_ACTION_PROMPT_CODES_H
|
#define LABWC_ACTION_PROMPT_CODES_H
|
||||||
|
|
||||||
#define LAB_EXIT_FAILURE 255
|
#define LAB_EXIT_FAILURE 255
|
||||||
#define LAB_EXIT_TIMEOUT 254
|
#define LAB_EXIT_CANCELLED 254
|
||||||
#define LAB_EXIT_SUCCESS 0
|
#define LAB_EXIT_SUCCESS 0
|
||||||
|
|
||||||
#endif /* LABWC_ACTION_PROMPT_CODES_H */
|
#endif /* LABWC_ACTION_PROMPT_CODES_H */
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
#ifndef LABWC_ACTION_PROMPT_COMMAND_H
|
|
||||||
#define LABWC_ACTION_PROMPT_COMMAND_H
|
|
||||||
|
|
||||||
struct buf;
|
|
||||||
struct action;
|
|
||||||
struct theme;
|
|
||||||
|
|
||||||
void action_prompt_command(struct buf *buf, const char *format,
|
|
||||||
struct action *action, struct theme *theme);
|
|
||||||
|
|
||||||
#endif /* LABWC_ACTION_PROMPT_COMMAND_H */
|
|
||||||
|
|
@ -109,4 +109,11 @@ void buf_reset(struct buf *s);
|
||||||
*/
|
*/
|
||||||
void buf_move(struct buf *dst, struct buf *src);
|
void buf_move(struct buf *dst, struct buf *src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buf_from_file - read file into memory buffer
|
||||||
|
* @filename: file to read
|
||||||
|
* Free returned buffer with buf_reset().
|
||||||
|
*/
|
||||||
|
struct buf buf_from_file(const char *filename);
|
||||||
|
|
||||||
#endif /* LABWC_BUF_H */
|
#endif /* LABWC_BUF_H */
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
/*
|
|
||||||
* Read file into memory
|
|
||||||
*
|
|
||||||
* Copyright Johan Malm 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LABWC_GRAB_FILE_H
|
|
||||||
#define LABWC_GRAB_FILE_H
|
|
||||||
|
|
||||||
#include "common/buf.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* grab_file - read file into memory buffer
|
|
||||||
* @filename: file to read
|
|
||||||
* Free returned buffer with buf_reset().
|
|
||||||
*/
|
|
||||||
struct buf grab_file(const char *filename);
|
|
||||||
|
|
||||||
#endif /* LABWC_GRAB_FILE_H */
|
|
||||||
|
|
@ -179,6 +179,7 @@ struct rcxml {
|
||||||
bool show;
|
bool show;
|
||||||
bool preview;
|
bool preview;
|
||||||
bool outlines;
|
bool outlines;
|
||||||
|
bool unshade;
|
||||||
enum lab_view_criteria criteria;
|
enum lab_view_criteria criteria;
|
||||||
struct wl_list fields; /* struct window_switcher_field.link */
|
struct wl_list fields; /* struct window_switcher_field.link */
|
||||||
enum window_switcher_style style;
|
enum window_switcher_style style;
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ struct server {
|
||||||
/* Set when in cycle (alt-tab) mode */
|
/* Set when in cycle (alt-tab) mode */
|
||||||
struct osd_state {
|
struct osd_state {
|
||||||
struct view *cycle_view;
|
struct view *cycle_view;
|
||||||
|
bool preview_was_shaded;
|
||||||
bool preview_was_enabled;
|
bool preview_was_enabled;
|
||||||
struct wlr_scene_node *preview_node;
|
struct wlr_scene_node *preview_node;
|
||||||
struct wlr_scene_tree *preview_parent;
|
struct wlr_scene_tree *preview_parent;
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ struct theme {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Themes/textures for each active/inactive window. Indexed by
|
* Themes/textures for each active/inactive window. Indexed by
|
||||||
* THEME_INACTIVE and THEME_ACTIVE.
|
* ssd_active_state.
|
||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
/* title background pattern (solid or gradient) */
|
/* title background pattern (solid or gradient) */
|
||||||
|
|
@ -170,6 +170,8 @@ struct theme {
|
||||||
int item_padding_x;
|
int item_padding_x;
|
||||||
int item_padding_y;
|
int item_padding_y;
|
||||||
int item_active_border_width;
|
int item_active_border_width;
|
||||||
|
float item_active_border_color[4];
|
||||||
|
float item_active_bg_color[4];
|
||||||
int item_icon_size;
|
int item_icon_size;
|
||||||
bool width_is_percent;
|
bool width_is_percent;
|
||||||
|
|
||||||
|
|
@ -210,10 +212,6 @@ struct theme {
|
||||||
int mag_border_width;
|
int mag_border_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: replace with enum ssd_active_state */
|
|
||||||
#define THEME_INACTIVE 0
|
|
||||||
#define THEME_ACTIVE 1
|
|
||||||
|
|
||||||
struct server;
|
struct server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,6 @@ struct view_size_hints {
|
||||||
struct view_impl {
|
struct view_impl {
|
||||||
void (*configure)(struct view *view, struct wlr_box geo);
|
void (*configure)(struct view *view, struct wlr_box geo);
|
||||||
void (*close)(struct view *view);
|
void (*close)(struct view *view);
|
||||||
const char *(*get_string_prop)(struct view *view, const char *prop);
|
|
||||||
void (*map)(struct view *view);
|
void (*map)(struct view *view);
|
||||||
void (*set_activated)(struct view *view, bool activated);
|
void (*set_activated)(struct view *view, bool activated);
|
||||||
void (*set_fullscreen)(struct view *view, bool fullscreen);
|
void (*set_fullscreen)(struct view *view, bool fullscreen);
|
||||||
|
|
@ -173,6 +172,10 @@ struct view {
|
||||||
struct wlr_scene_tree *scene_tree;
|
struct wlr_scene_tree *scene_tree;
|
||||||
struct wlr_scene_tree *content_tree;
|
struct wlr_scene_tree *content_tree;
|
||||||
|
|
||||||
|
/* These are never NULL and an empty string is set instead. */
|
||||||
|
char *title;
|
||||||
|
char *app_id; /* WM_CLASS for xwayland windows */
|
||||||
|
|
||||||
bool mapped;
|
bool mapped;
|
||||||
bool been_mapped;
|
bool been_mapped;
|
||||||
enum lab_ssd_mode ssd_mode;
|
enum lab_ssd_mode ssd_mode;
|
||||||
|
|
@ -571,9 +574,8 @@ bool view_on_output(struct view *view, struct output *output);
|
||||||
*/
|
*/
|
||||||
bool view_has_strut_partial(struct view *view);
|
bool view_has_strut_partial(struct view *view);
|
||||||
|
|
||||||
const char *view_get_string_prop(struct view *view, const char *prop);
|
void view_set_title(struct view *view, const char *title);
|
||||||
void view_update_title(struct view *view);
|
void view_set_app_id(struct view *view, const char *app_id);
|
||||||
void view_update_app_id(struct view *view);
|
|
||||||
void view_reload_ssd(struct view *view);
|
void view_reload_ssd(struct view *view);
|
||||||
|
|
||||||
void view_set_shade(struct view *view, bool shaded);
|
void view_set_shade(struct view *view, bool shaded);
|
||||||
|
|
|
||||||
10
meson.build
10
meson.build
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'labwc',
|
'labwc',
|
||||||
'c',
|
'c',
|
||||||
version: '0.9.0',
|
version: '0.9.2',
|
||||||
license: 'GPL-2.0-only',
|
license: 'GPL-2.0-only',
|
||||||
meson_version: '>=0.59.0',
|
meson_version: '>=0.59.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
@ -51,9 +51,9 @@ endif
|
||||||
add_project_arguments('-DLABWC_VERSION=@0@'.format(version), language: 'c')
|
add_project_arguments('-DLABWC_VERSION=@0@'.format(version), language: 'c')
|
||||||
|
|
||||||
wlroots = dependency(
|
wlroots = dependency(
|
||||||
'wlroots-0.19',
|
'wlroots-0.20',
|
||||||
default_options: ['default_library=static', 'examples=false'],
|
default_options: ['default_library=static', 'examples=false'],
|
||||||
version: ['>=0.19.0', '<0.20.0'],
|
version: ['>=0.20.0', '<0.21.0'],
|
||||||
)
|
)
|
||||||
|
|
||||||
wlroots_has_xwayland = wlroots.get_variable('have_xwayland') == 'true'
|
wlroots_has_xwayland = wlroots.get_variable('have_xwayland') == 'true'
|
||||||
|
|
@ -127,7 +127,9 @@ conf_data.set10('HAVE_RSVG', have_rsvg)
|
||||||
conf_data.set10('HAVE_LIBSFDO', have_libsfdo)
|
conf_data.set10('HAVE_LIBSFDO', have_libsfdo)
|
||||||
|
|
||||||
foreach sym : ['LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY', 'LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG']
|
foreach sym : ['LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY', 'LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG']
|
||||||
conf_data.set10('HAVE_' + sym, cc.has_header_symbol('libinput.h', sym, dependencies: input))
|
has_sym = input.type_name() != 'internal' \
|
||||||
|
and cc.has_header_symbol('libinput.h', sym, dependencies: input)
|
||||||
|
conf_data.set10('HAVE_' + sym, has_sym)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
if get_option('static_analyzer').enabled()
|
if get_option('static_analyzer').enabled()
|
||||||
|
|
|
||||||
9
po/ca.po
9
po/ca.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-09-19 21:09+1000\n"
|
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
|
||||||
"PO-Revision-Date: 2025-03-29 11:25+0000\n"
|
"PO-Revision-Date: 2025-10-11 20:01+0000\n"
|
||||||
"Last-Translator: Davidmp <opensusecatala@gmail.com>\n"
|
"Last-Translator: alvaroelpob <alvaropobladoresteban9@gmail.com>\n"
|
||||||
"Language-Team: Catalan <https://translate.lxqt-project.org/projects/labwc/labwc/ca/>\n"
|
"Language-Team: Catalan <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/ca/>\n"
|
||||||
"Language: ca\n"
|
"Language: ca\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"
|
||||||
|
|
@ -24,7 +25,7 @@ msgstr "Ves-hi..."
|
||||||
|
|
||||||
#: src/menu/menu.c:1034
|
#: src/menu/menu.c:1034
|
||||||
msgid "Terminal"
|
msgid "Terminal"
|
||||||
msgstr ""
|
msgstr "Terminal"
|
||||||
|
|
||||||
#: src/menu/menu.c:1040
|
#: src/menu/menu.c:1040
|
||||||
msgid "Reconfigure"
|
msgid "Reconfigure"
|
||||||
|
|
|
||||||
23
po/cs.po
23
po/cs.po
|
|
@ -8,29 +8,32 @@ 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-09-19 21:09+1000\n"
|
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
|
||||||
"PO-Revision-Date: 2024-03-02 02:00+0100\n"
|
"PO-Revision-Date: 2025-10-11 20:01+0000\n"
|
||||||
"Last-Translator: zenobit <zenobit@disroot.org>\n"
|
"Last-Translator: p-bo <pavel.borecki@gmail.com>\n"
|
||||||
"Language-Team: Czech <zenobit@disroot.org>\n"
|
"Language-Team: Czech <https://translate.lxqt-project.org/projects/labwc/"
|
||||||
|
"labwc/cs/>\n"
|
||||||
"Language: cs\n"
|
"Language: cs\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==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||||
|
"X-Generator: Weblate 4.2.1\n"
|
||||||
|
|
||||||
#: src/menu/menu.c:1016
|
#: src/menu/menu.c:1016
|
||||||
msgid "Go there..."
|
msgid "Go there..."
|
||||||
msgstr ""
|
msgstr "Přejít tam..."
|
||||||
|
|
||||||
#: src/menu/menu.c:1034
|
#: src/menu/menu.c:1034
|
||||||
msgid "Terminal"
|
msgid "Terminal"
|
||||||
msgstr ""
|
msgstr "Terminál"
|
||||||
|
|
||||||
#: src/menu/menu.c:1040
|
#: src/menu/menu.c:1040
|
||||||
msgid "Reconfigure"
|
msgid "Reconfigure"
|
||||||
msgstr "Překonfigurovat"
|
msgstr "Přenastavit"
|
||||||
|
|
||||||
#: src/menu/menu.c:1042
|
#: src/menu/menu.c:1042
|
||||||
msgid "Exit"
|
msgid "Exit"
|
||||||
msgstr "Odejít"
|
msgstr "Ukončit"
|
||||||
|
|
||||||
#: src/menu/menu.c:1056
|
#: src/menu/menu.c:1056
|
||||||
msgid "Minimize"
|
msgid "Minimize"
|
||||||
|
|
@ -46,7 +49,7 @@ msgstr "Na celou obrazovku"
|
||||||
|
|
||||||
#: src/menu/menu.c:1062
|
#: src/menu/menu.c:1062
|
||||||
msgid "Roll Up/Down"
|
msgid "Roll Up/Down"
|
||||||
msgstr "Rolovat nahoru/dolů"
|
msgstr "Posouvat nahoru/dolů"
|
||||||
|
|
||||||
#: src/menu/menu.c:1064
|
#: src/menu/menu.c:1064
|
||||||
msgid "Decorations"
|
msgid "Decorations"
|
||||||
|
|
@ -66,11 +69,11 @@ msgstr "Posunout doprava"
|
||||||
|
|
||||||
#: src/menu/menu.c:1083
|
#: src/menu/menu.c:1083
|
||||||
msgid "Always on Visible Workspace"
|
msgid "Always on Visible Workspace"
|
||||||
msgstr "Vždy na viditelné Pracovní Ploše"
|
msgstr "Vždy na viditelné Pracovní ploše"
|
||||||
|
|
||||||
#: src/menu/menu.c:1086
|
#: src/menu/menu.c:1086
|
||||||
msgid "Workspace"
|
msgid "Workspace"
|
||||||
msgstr "Pracovní Plocha"
|
msgstr "Pracovní plocha"
|
||||||
|
|
||||||
#: src/menu/menu.c:1089
|
#: src/menu/menu.c:1089
|
||||||
msgid "Close"
|
msgid "Close"
|
||||||
|
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
#include "action-prompt-command.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <wlr/util/log.h>
|
|
||||||
#include "action.h"
|
|
||||||
#include "common/buf.h"
|
|
||||||
#include "theme.h"
|
|
||||||
#include "translate.h"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
LAB_PROMPT_NONE = 0,
|
|
||||||
LAB_PROMPT_MESSAGE,
|
|
||||||
LAB_PROMPT_NO,
|
|
||||||
LAB_PROMPT_YES,
|
|
||||||
LAB_PROMPT_BG_COL,
|
|
||||||
LAB_PROMPT_TEXT_COL,
|
|
||||||
|
|
||||||
LAB_PROMPT_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void field_conversion_type(struct buf *buf, struct action *action,
|
|
||||||
struct theme *theme);
|
|
||||||
|
|
||||||
struct field_converter {
|
|
||||||
const char fmt_char;
|
|
||||||
field_conversion_type *fn;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* %m */
|
|
||||||
static void
|
|
||||||
set_message(struct buf *buf, struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
buf_add(buf, action_get_str(action, "message.prompt", "Choose wisely"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* %n */
|
|
||||||
static void
|
|
||||||
set_no(struct buf *buf, struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
buf_add(buf, _("No"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* %y */
|
|
||||||
static void
|
|
||||||
set_yes(struct buf *buf, struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
buf_add(buf, _("Yes"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* %b */
|
|
||||||
static void
|
|
||||||
set_bg_col(struct buf *buf, struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
buf_add_hex_color(buf, theme->osd_bg_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* %t */
|
|
||||||
static void
|
|
||||||
set_text_col(struct buf *buf, struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
buf_add_hex_color(buf, theme->osd_label_text_color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct field_converter field_converter[LAB_PROMPT_COUNT] = {
|
|
||||||
[LAB_PROMPT_MESSAGE] = { 'm', set_message },
|
|
||||||
[LAB_PROMPT_NO] = { 'n', set_no },
|
|
||||||
[LAB_PROMPT_YES] = { 'y', set_yes },
|
|
||||||
[LAB_PROMPT_BG_COL] = { 'b', set_bg_col },
|
|
||||||
[LAB_PROMPT_TEXT_COL] = { 't', set_text_col },
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
action_prompt_command(struct buf *buf, const char *format,
|
|
||||||
struct action *action, struct theme *theme)
|
|
||||||
{
|
|
||||||
if (!format) {
|
|
||||||
wlr_log(WLR_ERROR, "missing format");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const char *p = format; *p; p++) {
|
|
||||||
/*
|
|
||||||
* If we're not on a conversion specifier (like %m) then just
|
|
||||||
* keep adding it to the buffer
|
|
||||||
*/
|
|
||||||
if (*p != '%') {
|
|
||||||
buf_add_char(buf, *p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process the %* conversion specifier */
|
|
||||||
++p;
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
for (unsigned char i = 0; i < LAB_PROMPT_COUNT; i++) {
|
|
||||||
if (*p == field_converter[i].fmt_char) {
|
|
||||||
field_converter[i].fn(buf, action, theme);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"invalid prompt command conversion specifier '%c'", *p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
50
src/action.c
50
src/action.c
|
|
@ -10,7 +10,6 @@
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include <wlr/types/wlr_scene.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include "action-prompt-codes.h"
|
#include "action-prompt-codes.h"
|
||||||
#include "action-prompt-command.h"
|
|
||||||
#include "common/buf.h"
|
#include "common/buf.h"
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
|
|
@ -30,6 +29,7 @@
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
#include "ssd.h"
|
#include "ssd.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
#include "translate.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
|
|
||||||
|
|
@ -831,11 +831,55 @@ handle_view_destroy(struct wl_listener *listener, void *data)
|
||||||
prompt->view = NULL;
|
prompt->view = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_prompt_command(struct buf *buf, const char *format,
|
||||||
|
struct action *action, struct theme *theme)
|
||||||
|
{
|
||||||
|
assert(format);
|
||||||
|
|
||||||
|
for (const char *p = format; *p; p++) {
|
||||||
|
/*
|
||||||
|
* If we're not on a conversion specifier (like %m) then just
|
||||||
|
* keep adding it to the buffer
|
||||||
|
*/
|
||||||
|
if (*p != '%') {
|
||||||
|
buf_add_char(buf, *p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the %* conversion specifier */
|
||||||
|
++p;
|
||||||
|
|
||||||
|
switch (*p) {
|
||||||
|
case 'm':
|
||||||
|
buf_add(buf, action_get_str(action,
|
||||||
|
"message.prompt", "Choose wisely"));
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
buf_add(buf, _("No"));
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
buf_add(buf, _("Yes"));
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
buf_add_hex_color(buf, theme->osd_bg_color);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
buf_add_hex_color(buf, theme->osd_label_text_color);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wlr_log(WLR_ERROR,
|
||||||
|
"invalid prompt command conversion specifier '%c'", *p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
action_prompt_create(struct view *view, struct server *server, struct action *action)
|
action_prompt_create(struct view *view, struct server *server, struct action *action)
|
||||||
{
|
{
|
||||||
struct buf command = BUF_INIT;
|
struct buf command = BUF_INIT;
|
||||||
action_prompt_command(&command, rc.prompt_command, action, rc.theme);
|
print_prompt_command(&command, rc.prompt_command, action, rc.theme);
|
||||||
|
|
||||||
wlr_log(WLR_INFO, "prompt command: '%s'", command.data);
|
wlr_log(WLR_INFO, "prompt command: '%s'", command.data);
|
||||||
|
|
||||||
|
|
@ -890,7 +934,7 @@ action_check_prompt_result(pid_t pid, int exit_code)
|
||||||
if (exit_code == LAB_EXIT_SUCCESS) {
|
if (exit_code == LAB_EXIT_SUCCESS) {
|
||||||
wlr_log(WLR_INFO, "Selected the 'then' branch");
|
wlr_log(WLR_INFO, "Selected the 'then' branch");
|
||||||
actions = action_get_actionlist(prompt->action, "then");
|
actions = action_get_actionlist(prompt->action, "then");
|
||||||
} else if (exit_code == LAB_EXIT_TIMEOUT) {
|
} else if (exit_code == LAB_EXIT_CANCELLED) {
|
||||||
/* no-op */
|
/* no-op */
|
||||||
} else {
|
} else {
|
||||||
wlr_log(WLR_INFO, "Selected the 'else' branch");
|
wlr_log(WLR_INFO, "Selected the 'else' branch");
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
#include "common/macros.h"
|
#include "common/macros.h"
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
#include "common/string-helpers.h"
|
#include "common/string-helpers.h"
|
||||||
|
|
@ -203,3 +204,37 @@ buf_move(struct buf *dst, struct buf *src)
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
*src = BUF_INIT;
|
*src = BUF_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct buf
|
||||||
|
buf_from_file(const char *filename)
|
||||||
|
{
|
||||||
|
struct buf buf = BUF_INIT;
|
||||||
|
FILE *stream = fopen(filename, "r");
|
||||||
|
if (!stream) {
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fseek(stream, 0, SEEK_END) == -1) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "fseek(%s)", filename);
|
||||||
|
fclose(stream);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
long size = ftell(stream);
|
||||||
|
if (size == -1) {
|
||||||
|
wlr_log_errno(WLR_ERROR, "ftell(%s)", filename);
|
||||||
|
fclose(stream);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
rewind(stream);
|
||||||
|
|
||||||
|
buf_expand(&buf, size + 1);
|
||||||
|
if (fread(buf.data, 1, size, stream) == (size_t)size) {
|
||||||
|
buf.len = size;
|
||||||
|
buf.data[size] = '\0';
|
||||||
|
} else {
|
||||||
|
wlr_log_errno(WLR_ERROR, "fread(%s)", filename);
|
||||||
|
buf_reset(&buf);
|
||||||
|
}
|
||||||
|
fclose(stream);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
/*
|
|
||||||
* Read file into memory
|
|
||||||
*
|
|
||||||
* Copyright Johan Malm 2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
#include "common/grab-file.h"
|
|
||||||
#include "common/buf.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct buf
|
|
||||||
grab_file(const char *filename)
|
|
||||||
{
|
|
||||||
char *line = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
FILE *stream = fopen(filename, "r");
|
|
||||||
if (!stream) {
|
|
||||||
return BUF_INIT;
|
|
||||||
}
|
|
||||||
struct buf buffer = BUF_INIT;
|
|
||||||
while ((getline(&line, &len, stream) != -1)) {
|
|
||||||
char *p = strrchr(line, '\n');
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
}
|
|
||||||
buf_add(&buffer, line);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
fclose(stream);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,6 @@ labwc_sources += files(
|
||||||
'fd-util.c',
|
'fd-util.c',
|
||||||
'file-helpers.c',
|
'file-helpers.c',
|
||||||
'font.c',
|
'font.c',
|
||||||
'grab-file.c',
|
|
||||||
'graphic-helpers.c',
|
'graphic-helpers.c',
|
||||||
'lab-scene-rect.c',
|
'lab-scene-rect.c',
|
||||||
'match.c',
|
'match.c',
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ create_attribute_tree(const xmlAttr *attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Consider <keybind name.action="ShowMenu" x.position.action="1" y.position="2" />.
|
* Consider <keybind name.action="ShowMenu" x.position.action="1" y.position.action="2" />.
|
||||||
* These three attributes are represented by following trees.
|
* These three attributes are represented by following trees.
|
||||||
* action(dst)---name
|
* action(dst)---name
|
||||||
* action(src)---position---x
|
* action(src)---position---x
|
||||||
|
|
@ -79,7 +79,8 @@ merge_two_trees(xmlNode *dst, xmlNode *src)
|
||||||
&& !strcasecmp((char *)dst->name, (char *)src->name)) {
|
&& !strcasecmp((char *)dst->name, (char *)src->name)) {
|
||||||
xmlNode *next_dst = dst->last;
|
xmlNode *next_dst = dst->last;
|
||||||
xmlNode *next_src = src->children;
|
xmlNode *next_src = src->children;
|
||||||
xmlAddChild(dst, src->children);
|
xmlUnlinkNode(next_src);
|
||||||
|
xmlAddChild(dst, next_src);
|
||||||
xmlUnlinkNode(src);
|
xmlUnlinkNode(src);
|
||||||
xmlFreeNode(src);
|
xmlFreeNode(src);
|
||||||
src = next_src;
|
src = next_src;
|
||||||
|
|
|
||||||
|
|
@ -1083,12 +1083,6 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
} else {
|
} else {
|
||||||
rc.xdg_shell_server_side_deco = true;
|
rc.xdg_shell_server_side_deco = true;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp(nodename, "maximizedDecoration.core")) {
|
|
||||||
if (!strcasecmp(content, "titlebar")) {
|
|
||||||
rc.hide_maximized_window_titlebar = false;
|
|
||||||
} else if (!strcasecmp(content, "none")) {
|
|
||||||
rc.hide_maximized_window_titlebar = true;
|
|
||||||
}
|
|
||||||
} else if (!strcmp(nodename, "gap.core")) {
|
} else if (!strcmp(nodename, "gap.core")) {
|
||||||
rc.gap = atoi(content);
|
rc.gap = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "adaptiveSync.core")) {
|
} else if (!strcasecmp(nodename, "adaptiveSync.core")) {
|
||||||
|
|
@ -1130,6 +1124,12 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
rc.corner_radius = atoi(content);
|
rc.corner_radius = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "keepBorder.theme")) {
|
} else if (!strcasecmp(nodename, "keepBorder.theme")) {
|
||||||
set_bool(content, &rc.ssd_keep_border);
|
set_bool(content, &rc.ssd_keep_border);
|
||||||
|
} else if (!strcasecmp(nodename, "maximizedDecoration.theme")) {
|
||||||
|
if (!strcasecmp(content, "titlebar")) {
|
||||||
|
rc.hide_maximized_window_titlebar = false;
|
||||||
|
} else if (!strcasecmp(content, "none")) {
|
||||||
|
rc.hide_maximized_window_titlebar = true;
|
||||||
|
}
|
||||||
} else if (!strcasecmp(nodename, "dropShadows.theme")) {
|
} else if (!strcasecmp(nodename, "dropShadows.theme")) {
|
||||||
set_bool(content, &rc.shadows_enabled);
|
set_bool(content, &rc.shadows_enabled);
|
||||||
} else if (!strcasecmp(nodename, "dropShadowsOnTiled.theme")) {
|
} else if (!strcasecmp(nodename, "dropShadowsOnTiled.theme")) {
|
||||||
|
|
@ -1217,6 +1217,8 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
rc.window_switcher.criteria &=
|
rc.window_switcher.criteria &=
|
||||||
~LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
|
~LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
|
||||||
}
|
}
|
||||||
|
} else if (!strcasecmp(nodename, "unshade.windowSwitcher")) {
|
||||||
|
set_bool(content, &rc.window_switcher.unshade);
|
||||||
|
|
||||||
/* Remove this long term - just a friendly warning for now */
|
/* Remove this long term - just a friendly warning for now */
|
||||||
} else if (strstr(nodename, "windowswitcher.core")) {
|
} else if (strstr(nodename, "windowswitcher.core")) {
|
||||||
|
|
@ -1429,6 +1431,7 @@ rcxml_init(void)
|
||||||
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
rc.window_switcher.style = WINDOW_SWITCHER_CLASSIC;
|
||||||
rc.window_switcher.preview = true;
|
rc.window_switcher.preview = true;
|
||||||
rc.window_switcher.outlines = true;
|
rc.window_switcher.outlines = true;
|
||||||
|
rc.window_switcher.unshade = true;
|
||||||
rc.window_switcher.criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
|
rc.window_switcher.criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
|
||||||
| LAB_VIEW_CRITERIA_ROOT_TOPLEVEL
|
| LAB_VIEW_CRITERIA_ROOT_TOPLEVEL
|
||||||
| LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;
|
| LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;
|
||||||
|
|
@ -1642,6 +1645,7 @@ post_processing(void)
|
||||||
"--button-text-color '%t' "
|
"--button-text-color '%t' "
|
||||||
"--border-bottom-size 1 "
|
"--border-bottom-size 1 "
|
||||||
"--button-border-size 3 "
|
"--button-border-size 3 "
|
||||||
|
"--keyboard-focus on-demand "
|
||||||
"--timeout 0");
|
"--timeout 0");
|
||||||
}
|
}
|
||||||
if (!rc.fallback_app_icon_name) {
|
if (!rc.fallback_app_icon_name) {
|
||||||
|
|
@ -1868,25 +1872,13 @@ rcxml_read(const char *filename)
|
||||||
*/
|
*/
|
||||||
for (struct wl_list *elm = iter(&paths); elm != &paths; elm = iter(elm)) {
|
for (struct wl_list *elm = iter(&paths); elm != &paths; elm = iter(elm)) {
|
||||||
struct path *path = wl_container_of(elm, path, link);
|
struct path *path = wl_container_of(elm, path, link);
|
||||||
FILE *stream = fopen(path->string, "r");
|
struct buf b = buf_from_file(path->string);
|
||||||
if (!stream) {
|
if (!b.len) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_log(WLR_INFO, "read config file %s", path->string);
|
wlr_log(WLR_INFO, "read config file %s", path->string);
|
||||||
|
|
||||||
struct buf b = BUF_INIT;
|
|
||||||
char *line = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
while (getline(&line, &len, stream) != -1) {
|
|
||||||
char *p = strrchr(line, '\n');
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
}
|
|
||||||
buf_add(&b, line);
|
|
||||||
}
|
|
||||||
zfree(line);
|
|
||||||
fclose(stream);
|
|
||||||
rcxml_parse_xml(&b);
|
rcxml_parse_xml(&b);
|
||||||
buf_reset(&b);
|
buf_reset(&b);
|
||||||
if (!should_merge_config) {
|
if (!should_merge_config) {
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,10 @@ get_view_part(struct view *view, struct wlr_scene_node *node)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (node == &view->scene_tree->node) {
|
if (node == &view->scene_tree->node) {
|
||||||
const char *app_id = view_get_string_prop(view, "app_id");
|
if (string_null_or_empty(view->app_id)) {
|
||||||
if (string_null_or_empty(app_id)) {
|
|
||||||
return "view";
|
return "view";
|
||||||
}
|
}
|
||||||
snprintf(view_name, sizeof(view_name), "view (%s)", app_id);
|
snprintf(view_name, sizeof(view_name), "view (%s)", view->app_id);
|
||||||
return view_name;
|
return view_name;
|
||||||
}
|
}
|
||||||
if (node == &view->content_tree->node) {
|
if (node == &view->content_tree->node) {
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,10 @@ log_handler(enum sfdo_log_level level, const char *fmt, va_list args, void *tag)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To avoid logging issues with .desktop files as errors, all libsfdo
|
* To avoid logging issues with .desktop files as errors, all libsfdo
|
||||||
* error-logging is demoted to info level.
|
* error-logging is demoted to info level unless running with
|
||||||
|
* LABWC_DEBUG_LIBSFDO.
|
||||||
*/
|
*/
|
||||||
if (level == SFDO_LOG_LEVEL_ERROR) {
|
if (!debug_libsfdo && level == SFDO_LOG_LEVEL_ERROR) {
|
||||||
level = SFDO_LOG_LEVEL_INFO;
|
level = SFDO_LOG_LEVEL_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,19 +96,37 @@ desktop_entry_init(struct server *server)
|
||||||
* We set some relaxed load options to accommodate delinquent themes in
|
* We set some relaxed load options to accommodate delinquent themes in
|
||||||
* the wild, namely:
|
* the wild, namely:
|
||||||
*
|
*
|
||||||
* - SFDO_ICON_THEME_LOAD_OPTION_ALLOW_MISSING to "impose less
|
* - SFDO_ICON_THEME_LOAD_OPTION_RELAXED to "impose less restrictions
|
||||||
* restrictions on the format of icon theme files"
|
* on the format of icon theme files"
|
||||||
*
|
*
|
||||||
* - SFDO_ICON_THEME_LOAD_OPTION_RELAXED to "continue loading even if it
|
* - SFDO_ICON_THEME_LOAD_OPTION_ALLOW_MISSING to "continue loading
|
||||||
* fails to find a theme or one of its dependencies."
|
* even if it fails to find a theme or one of its dependencies."
|
||||||
*/
|
*/
|
||||||
int load_options = SFDO_ICON_THEME_LOAD_OPTIONS_DEFAULT
|
int load_options = SFDO_ICON_THEME_LOAD_OPTIONS_DEFAULT
|
||||||
| SFDO_ICON_THEME_LOAD_OPTION_ALLOW_MISSING
|
| SFDO_ICON_THEME_LOAD_OPTION_RELAXED
|
||||||
| SFDO_ICON_THEME_LOAD_OPTION_RELAXED;
|
| SFDO_ICON_THEME_LOAD_OPTION_ALLOW_MISSING;
|
||||||
|
|
||||||
sfdo->icon_theme = sfdo_icon_theme_load(
|
sfdo->icon_theme = sfdo_icon_theme_load(
|
||||||
sfdo->icon_ctx,
|
sfdo->icon_ctx,
|
||||||
rc.icon_theme_name, load_options);
|
rc.icon_theme_name, load_options);
|
||||||
|
if (!sfdo->icon_theme) {
|
||||||
|
/*
|
||||||
|
* sfdo_icon_theme_load() falls back to hicolor theme with
|
||||||
|
* _ALLOW_MISSING flag when the theme is missing, but just
|
||||||
|
* fails when the theme is invalid.
|
||||||
|
* So manually call sfdo_icon_theme_load() again here.
|
||||||
|
*/
|
||||||
|
wlr_log(WLR_ERROR, "Failed to load icon theme %s, falling back to 'hicolor'",
|
||||||
|
rc.icon_theme_name);
|
||||||
|
|
||||||
|
if (!debug_libsfdo) {
|
||||||
|
wlr_log(WLR_ERROR, "Further information is available by setting "
|
||||||
|
"the LABWC_DEBUG_LIBSFDO=1 env var before starting labwc");
|
||||||
|
}
|
||||||
|
|
||||||
|
sfdo->icon_theme = sfdo_icon_theme_load(
|
||||||
|
sfdo->icon_ctx, "hicolor", load_options);
|
||||||
|
}
|
||||||
if (!sfdo->icon_theme) {
|
if (!sfdo->icon_theme) {
|
||||||
goto err_icon_theme;
|
goto err_icon_theme;
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +148,10 @@ err_desktop_ctx:
|
||||||
err_basedir_ctx:
|
err_basedir_ctx:
|
||||||
free(sfdo);
|
free(sfdo);
|
||||||
wlr_log(WLR_ERROR, "Failed to initialize icon loader");
|
wlr_log(WLR_ERROR, "Failed to initialize icon loader");
|
||||||
|
if (!debug_libsfdo) {
|
||||||
|
wlr_log(WLR_ERROR, "Further information is available by setting "
|
||||||
|
"the LABWC_DEBUG_LIBSFDO=1 env var before starting labwc");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ handle_new_app_id(struct wl_listener *listener, void *data)
|
||||||
assert(ext_toplevel->handle);
|
assert(ext_toplevel->handle);
|
||||||
|
|
||||||
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
||||||
.title = view_get_string_prop(ext_toplevel->view, "title"),
|
.title = ext_toplevel->view->title,
|
||||||
.app_id = view_get_string_prop(ext_toplevel->view, "app_id")
|
.app_id = ext_toplevel->view->app_id,
|
||||||
};
|
};
|
||||||
wlr_ext_foreign_toplevel_handle_v1_update_state(ext_toplevel->handle,
|
wlr_ext_foreign_toplevel_handle_v1_update_state(ext_toplevel->handle,
|
||||||
&state);
|
&state);
|
||||||
|
|
@ -47,8 +47,8 @@ handle_new_title(struct wl_listener *listener, void *data)
|
||||||
assert(ext_toplevel->handle);
|
assert(ext_toplevel->handle);
|
||||||
|
|
||||||
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
||||||
.title = view_get_string_prop(ext_toplevel->view, "title"),
|
.title = ext_toplevel->view->title,
|
||||||
.app_id = view_get_string_prop(ext_toplevel->view, "app_id")
|
.app_id = ext_toplevel->view->app_id,
|
||||||
};
|
};
|
||||||
wlr_ext_foreign_toplevel_handle_v1_update_state(ext_toplevel->handle,
|
wlr_ext_foreign_toplevel_handle_v1_update_state(ext_toplevel->handle,
|
||||||
&state);
|
&state);
|
||||||
|
|
@ -63,15 +63,15 @@ ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
|
||||||
ext_toplevel->view = view;
|
ext_toplevel->view = view;
|
||||||
|
|
||||||
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
struct wlr_ext_foreign_toplevel_handle_v1_state state = {
|
||||||
.title = view_get_string_prop(view, "title"),
|
.title = view->title,
|
||||||
.app_id = view_get_string_prop(view, "app_id")
|
.app_id = view->app_id,
|
||||||
};
|
};
|
||||||
ext_toplevel->handle = wlr_ext_foreign_toplevel_handle_v1_create(
|
ext_toplevel->handle = wlr_ext_foreign_toplevel_handle_v1_create(
|
||||||
view->server->foreign_toplevel_list, &state);
|
view->server->foreign_toplevel_list, &state);
|
||||||
|
|
||||||
if (!ext_toplevel->handle) {
|
if (!ext_toplevel->handle) {
|
||||||
wlr_log(WLR_ERROR, "cannot create ext toplevel handle for (%s)",
|
wlr_log(WLR_ERROR, "cannot create ext toplevel handle for (%s)",
|
||||||
view_get_string_prop(view, "title"));
|
view->title);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,13 +94,8 @@ handle_new_app_id(struct wl_listener *listener, void *data)
|
||||||
wl_container_of(listener, wlr_toplevel, on_view.new_app_id);
|
wl_container_of(listener, wlr_toplevel, on_view.new_app_id);
|
||||||
assert(wlr_toplevel->handle);
|
assert(wlr_toplevel->handle);
|
||||||
|
|
||||||
const char *app_id = view_get_string_prop(wlr_toplevel->view, "app_id");
|
wlr_foreign_toplevel_handle_v1_set_app_id(wlr_toplevel->handle,
|
||||||
const char *wlr_app_id = wlr_toplevel->handle->app_id;
|
wlr_toplevel->view->app_id);
|
||||||
if (app_id && wlr_app_id && !strcmp(app_id, wlr_app_id)) {
|
|
||||||
/* Don't send app_id if they are the same */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wlr_foreign_toplevel_handle_v1_set_app_id(wlr_toplevel->handle, app_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -110,13 +105,8 @@ handle_new_title(struct wl_listener *listener, void *data)
|
||||||
wl_container_of(listener, wlr_toplevel, on_view.new_title);
|
wl_container_of(listener, wlr_toplevel, on_view.new_title);
|
||||||
assert(wlr_toplevel->handle);
|
assert(wlr_toplevel->handle);
|
||||||
|
|
||||||
const char *title = view_get_string_prop(wlr_toplevel->view, "title");
|
wlr_foreign_toplevel_handle_v1_set_title(wlr_toplevel->handle,
|
||||||
const char *wlr_title = wlr_toplevel->handle->title;
|
wlr_toplevel->view->title);
|
||||||
if (title && wlr_title && !strcmp(title, wlr_title)) {
|
|
||||||
/* Don't send title if they are the same */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wlr_foreign_toplevel_handle_v1_set_title(wlr_toplevel->handle, title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -202,7 +192,7 @@ wlr_foreign_toplevel_init(struct wlr_foreign_toplevel *wlr_toplevel,
|
||||||
view->server->foreign_toplevel_manager);
|
view->server->foreign_toplevel_manager);
|
||||||
if (!wlr_toplevel->handle) {
|
if (!wlr_toplevel->handle) {
|
||||||
wlr_log(WLR_ERROR, "cannot create wlr foreign toplevel handle for (%s)",
|
wlr_log(WLR_ERROR, "cannot create wlr foreign toplevel handle for (%s)",
|
||||||
view_get_string_prop(view, "title"));
|
view->title);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "common/grab-file.h"
|
#include "common/buf.h"
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
#include "common/string-helpers.h"
|
#include "common/string-helpers.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
@ -273,7 +273,7 @@ img_xbm_load(const char *filename, float *rgba)
|
||||||
uint32_t color = argb32(rgba);
|
uint32_t color = argb32(rgba);
|
||||||
|
|
||||||
/* Read file into memory as it's easier to tokenize that way */
|
/* Read file into memory as it's easier to tokenize that way */
|
||||||
struct buf token_buf = grab_file(filename);
|
struct buf token_buf = buf_from_file(filename);
|
||||||
if (token_buf.len) {
|
if (token_buf.len) {
|
||||||
struct token *tokens = tokenize_xbm(token_buf.data);
|
struct token *tokens = tokenize_xbm(token_buf.data);
|
||||||
pixmap = parse_xbm_tokens(tokens, color);
|
pixmap = parse_xbm_tokens(tokens, color);
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,8 @@ handle_keyboard_grab_destroy(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct input_method_relay *relay =
|
struct input_method_relay *relay =
|
||||||
wl_container_of(listener, relay, keyboard_grab_destroy);
|
wl_container_of(listener, relay, keyboard_grab_destroy);
|
||||||
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
|
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab =
|
||||||
|
relay->input_method->keyboard_grab;
|
||||||
assert(keyboard_grab);
|
assert(keyboard_grab);
|
||||||
|
|
||||||
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
wl_list_remove(&relay->keyboard_grab_destroy.link);
|
||||||
|
|
@ -583,11 +584,11 @@ input_method_relay_create(struct seat *seat)
|
||||||
relay->popup_tree = wlr_scene_tree_create(&seat->server->scene->tree);
|
relay->popup_tree = wlr_scene_tree_create(&seat->server->scene->tree);
|
||||||
|
|
||||||
relay->new_text_input.notify = handle_new_text_input;
|
relay->new_text_input.notify = handle_new_text_input;
|
||||||
wl_signal_add(&seat->server->text_input_manager->events.text_input,
|
wl_signal_add(&seat->server->text_input_manager->events.new_text_input,
|
||||||
&relay->new_text_input);
|
&relay->new_text_input);
|
||||||
|
|
||||||
relay->new_input_method.notify = handle_new_input_method;
|
relay->new_input_method.notify = handle_new_input_method;
|
||||||
wl_signal_add(&seat->server->input_method_manager->events.input_method,
|
wl_signal_add(&seat->server->input_method_manager->events.new_input_method,
|
||||||
&relay->new_input_method);
|
&relay->new_input_method);
|
||||||
|
|
||||||
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
relay->focused_surface_destroy.notify = handle_focused_surface_destroy;
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,9 @@ end_cycling(struct server *server)
|
||||||
/* FIXME: osd_finish() transiently sets focus to the old surface */
|
/* FIXME: osd_finish() transiently sets focus to the old surface */
|
||||||
osd_finish(server);
|
osd_finish(server);
|
||||||
/* Note that server->osd_state.cycle_view is cleared at this point */
|
/* Note that server->osd_state.cycle_view is cleared at this point */
|
||||||
|
if (rc.window_switcher.unshade) {
|
||||||
|
view_set_shade(cycle_view, false);
|
||||||
|
}
|
||||||
desktop_focus_view(cycle_view, /*raise*/ true);
|
desktop_focus_view(cycle_view, /*raise*/ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -482,13 +482,13 @@ fill_item(struct menu *menu, xmlNode *node)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct menuitem *item = item_create(menu, (char *)label, icon_name, false);
|
struct menuitem *item = item_create(menu, label, icon_name, false);
|
||||||
lab_xml_expand_dotted_attributes(node);
|
lab_xml_expand_dotted_attributes(node);
|
||||||
append_parsed_actions(node, &item->actions);
|
append_parsed_actions(node, &item->actions);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(label);
|
xmlFree(label);
|
||||||
free(icon_name);
|
xmlFree(icon_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -619,10 +619,10 @@ fill_menu(struct server *server, struct menu *parent, xmlNode *n)
|
||||||
item->submenu = menu;
|
item->submenu = menu;
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
free(label);
|
xmlFree(label);
|
||||||
free(icon_name);
|
xmlFree(icon_name);
|
||||||
free(execute);
|
xmlFree(execute);
|
||||||
free(id);
|
xmlFree(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This can be one of <separator> and <separator label=""> */
|
/* This can be one of <separator> and <separator label=""> */
|
||||||
|
|
@ -631,7 +631,7 @@ fill_separator(struct menu *menu, xmlNode *n)
|
||||||
{
|
{
|
||||||
char *label = (char *)xmlGetProp(n, (const xmlChar *)"label");
|
char *label = (char *)xmlGetProp(n, (const xmlChar *)"label");
|
||||||
separator_create(menu, label);
|
separator_create(menu, label);
|
||||||
free(label);
|
xmlFree(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parent==NULL when processing toplevel menus in menu.xml */
|
/* parent==NULL when processing toplevel menus in menu.xml */
|
||||||
|
|
@ -679,30 +679,6 @@ parse_buf(struct server *server, struct menu *parent, struct buf *buf)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @stream can come from either of the following:
|
|
||||||
* - fopen() in the case of reading a file such as menu.xml
|
|
||||||
* - popen() when processing pipemenus
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
parse_stream(struct server *server, FILE *stream)
|
|
||||||
{
|
|
||||||
char *line = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
struct buf b = BUF_INIT;
|
|
||||||
|
|
||||||
while (getline(&line, &len, stream) != -1) {
|
|
||||||
char *p = strrchr(line, '\n');
|
|
||||||
if (p) {
|
|
||||||
*p = '\0';
|
|
||||||
}
|
|
||||||
buf_add(&b, line);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
parse_buf(server, NULL, &b);
|
|
||||||
buf_reset(&b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_xml(const char *filename, struct server *server)
|
parse_xml(const char *filename, struct server *server)
|
||||||
{
|
{
|
||||||
|
|
@ -715,13 +691,13 @@ parse_xml(const char *filename, struct server *server)
|
||||||
|
|
||||||
for (struct wl_list *elm = iter(&paths); elm != &paths; elm = iter(elm)) {
|
for (struct wl_list *elm = iter(&paths); elm != &paths; elm = iter(elm)) {
|
||||||
struct path *path = wl_container_of(elm, path, link);
|
struct path *path = wl_container_of(elm, path, link);
|
||||||
FILE *stream = fopen(path->string, "r");
|
struct buf buf = buf_from_file(path->string);
|
||||||
if (!stream) {
|
if (!buf.len) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
wlr_log(WLR_INFO, "read menu file %s", path->string);
|
wlr_log(WLR_INFO, "read menu file %s", path->string);
|
||||||
parse_stream(server, stream);
|
parse_buf(server, /*parent*/ NULL, &buf);
|
||||||
fclose(stream);
|
buf_reset(&buf);
|
||||||
if (!should_merge_config) {
|
if (!should_merge_config) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -900,8 +876,8 @@ update_client_list_combined_menu(struct server *server)
|
||||||
|
|
||||||
wl_list_for_each(view, &server->views, link) {
|
wl_list_for_each(view, &server->views, link) {
|
||||||
if (view->workspace == workspace) {
|
if (view->workspace == workspace) {
|
||||||
const char *title = view_get_string_prop(view, "title");
|
if (!view->foreign_toplevel
|
||||||
if (!view->foreign_toplevel || string_null_or_empty(title)) {
|
|| string_null_or_empty(view->title)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -909,9 +885,9 @@ update_client_list_combined_menu(struct server *server)
|
||||||
buf_add(&buffer, "*");
|
buf_add(&buffer, "*");
|
||||||
}
|
}
|
||||||
if (view->minimized) {
|
if (view->minimized) {
|
||||||
buf_add_fmt(&buffer, "(%s)", title);
|
buf_add_fmt(&buffer, "(%s)", view->title);
|
||||||
} else {
|
} else {
|
||||||
buf_add(&buffer, title);
|
buf_add(&buffer, view->title);
|
||||||
}
|
}
|
||||||
item = item_create(menu, buffer.data, NULL,
|
item = item_create(menu, buffer.data, NULL,
|
||||||
/*show arrow*/ false);
|
/*show arrow*/ false);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
labwc_sources = files(
|
labwc_sources = files(
|
||||||
'action.c',
|
'action.c',
|
||||||
'action-prompt-command.c',
|
|
||||||
'buffer.c',
|
'buffer.c',
|
||||||
'debug.c',
|
'debug.c',
|
||||||
'desktop.c',
|
'desktop.c',
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,59 @@
|
||||||
|
|
||||||
struct osd_classic_scene_item {
|
struct osd_classic_scene_item {
|
||||||
struct view *view;
|
struct view *view;
|
||||||
struct wlr_scene_node *highlight_outline;
|
struct wlr_scene_tree *normal_tree, *active_tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_fields_scene(struct server *server, struct view *view,
|
||||||
|
struct wlr_scene_tree *parent, const float *text_color,
|
||||||
|
const float *bg_color, int field_widths_sum, int x, int y)
|
||||||
|
{
|
||||||
|
struct theme *theme = server->theme;
|
||||||
|
struct window_switcher_classic_theme *switcher_theme =
|
||||||
|
&theme->osd_window_switcher_classic;
|
||||||
|
|
||||||
|
struct window_switcher_field *field;
|
||||||
|
wl_list_for_each(field, &rc.window_switcher.fields, link) {
|
||||||
|
int field_width = field_widths_sum * field->width / 100.0;
|
||||||
|
struct wlr_scene_node *node = NULL;
|
||||||
|
int height = -1;
|
||||||
|
|
||||||
|
if (field->content == LAB_FIELD_ICON) {
|
||||||
|
int icon_size = MIN(field_width,
|
||||||
|
switcher_theme->item_icon_size);
|
||||||
|
struct scaled_icon_buffer *icon_buffer =
|
||||||
|
scaled_icon_buffer_create(parent,
|
||||||
|
server, icon_size, icon_size);
|
||||||
|
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||||
|
node = &icon_buffer->scene_buffer->node;
|
||||||
|
height = icon_size;
|
||||||
|
} else {
|
||||||
|
struct buf buf = BUF_INIT;
|
||||||
|
osd_field_get_content(field, &buf, view);
|
||||||
|
|
||||||
|
if (!string_null_or_empty(buf.data)) {
|
||||||
|
struct scaled_font_buffer *font_buffer =
|
||||||
|
scaled_font_buffer_create(parent);
|
||||||
|
scaled_font_buffer_update(font_buffer,
|
||||||
|
buf.data, field_width,
|
||||||
|
&rc.font_osd, text_color, bg_color);
|
||||||
|
node = &font_buffer->scene_buffer->node;
|
||||||
|
height = font_height(&rc.font_osd);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf_reset(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
int item_height = switcher_theme->item_height;
|
||||||
|
wlr_scene_node_set_position(node,
|
||||||
|
x, y + (item_height - height) / 2);
|
||||||
|
}
|
||||||
|
x += field_width + switcher_theme->item_padding_x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
osd_classic_create(struct output *output, struct wl_array *views)
|
osd_classic_create(struct output *output, struct wl_array *views)
|
||||||
{
|
{
|
||||||
|
|
@ -126,62 +176,33 @@ osd_classic_create(struct output *output, struct wl_array *views)
|
||||||
+ switcher_theme->item_padding_x;
|
+ switcher_theme->item_padding_x;
|
||||||
struct wlr_scene_tree *item_root =
|
struct wlr_scene_tree *item_root =
|
||||||
wlr_scene_tree_create(output->osd_scene.tree);
|
wlr_scene_tree_create(output->osd_scene.tree);
|
||||||
|
item->normal_tree = wlr_scene_tree_create(item_root);
|
||||||
|
item->active_tree = wlr_scene_tree_create(item_root);
|
||||||
|
wlr_scene_node_set_enabled(&item->active_tree->node, false);
|
||||||
|
|
||||||
struct window_switcher_field *field;
|
float *active_bg_color = switcher_theme->item_active_bg_color;
|
||||||
wl_list_for_each(field, &rc.window_switcher.fields, link) {
|
float *active_border_color = switcher_theme->item_active_border_color;
|
||||||
int field_width = field_widths_sum * field->width / 100.0;
|
|
||||||
struct wlr_scene_node *node = NULL;
|
|
||||||
int height = -1;
|
|
||||||
|
|
||||||
if (field->content == LAB_FIELD_ICON) {
|
|
||||||
int icon_size = MIN(field_width,
|
|
||||||
switcher_theme->item_icon_size);
|
|
||||||
struct scaled_icon_buffer *icon_buffer =
|
|
||||||
scaled_icon_buffer_create(item_root,
|
|
||||||
server, icon_size, icon_size);
|
|
||||||
scaled_icon_buffer_set_view(icon_buffer, *view);
|
|
||||||
node = &icon_buffer->scene_buffer->node;
|
|
||||||
height = icon_size;
|
|
||||||
} else {
|
|
||||||
buf_clear(&buf);
|
|
||||||
osd_field_get_content(field, &buf, *view);
|
|
||||||
|
|
||||||
if (!string_null_or_empty(buf.data)) {
|
|
||||||
struct scaled_font_buffer *font_buffer =
|
|
||||||
scaled_font_buffer_create(item_root);
|
|
||||||
scaled_font_buffer_update(font_buffer,
|
|
||||||
buf.data, field_width,
|
|
||||||
&rc.font_osd, text_color, bg_color);
|
|
||||||
node = &font_buffer->scene_buffer->node;
|
|
||||||
height = font_height(&rc.font_osd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node) {
|
|
||||||
int item_height = switcher_theme->item_height;
|
|
||||||
wlr_scene_node_set_position(node,
|
|
||||||
x, y + (item_height - height) / 2);
|
|
||||||
}
|
|
||||||
x += field_width + switcher_theme->item_padding_x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Highlight around selected window's item */
|
/* Highlight around selected window's item */
|
||||||
int highlight_x = theme->osd_border_width
|
int highlight_x = theme->osd_border_width
|
||||||
+ switcher_theme->padding;
|
+ switcher_theme->padding;
|
||||||
struct lab_scene_rect_options highlight_opts = {
|
struct lab_scene_rect_options highlight_opts = {
|
||||||
.border_colors = (float *[1]) {text_color},
|
.border_colors = (float *[1]) {active_border_color},
|
||||||
|
.bg_color = active_bg_color,
|
||||||
.nr_borders = 1,
|
.nr_borders = 1,
|
||||||
.border_width = switcher_theme->item_active_border_width,
|
.border_width = switcher_theme->item_active_border_width,
|
||||||
.width = w - 2 * theme->osd_border_width
|
.width = w - 2 * theme->osd_border_width
|
||||||
- 2 * switcher_theme->padding,
|
- 2 * switcher_theme->padding,
|
||||||
.height = switcher_theme->item_height,
|
.height = switcher_theme->item_height,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lab_scene_rect *highlight_rect = lab_scene_rect_create(
|
struct lab_scene_rect *highlight_rect = lab_scene_rect_create(
|
||||||
output->osd_scene.tree, &highlight_opts);
|
item->active_tree, &highlight_opts);
|
||||||
item->highlight_outline = &highlight_rect->tree->node;
|
wlr_scene_node_set_position(&highlight_rect->tree->node, highlight_x, y);
|
||||||
wlr_scene_node_set_position(item->highlight_outline, highlight_x, y);
|
|
||||||
wlr_scene_node_set_enabled(item->highlight_outline, false);
|
create_fields_scene(server, *view, item->normal_tree,
|
||||||
|
text_color, bg_color, field_widths_sum, x, y);
|
||||||
|
create_fields_scene(server, *view, item->active_tree,
|
||||||
|
text_color, active_bg_color, field_widths_sum, x, y);
|
||||||
|
|
||||||
y += switcher_theme->item_height;
|
y += switcher_theme->item_height;
|
||||||
}
|
}
|
||||||
|
|
@ -200,8 +221,9 @@ osd_classic_update(struct output *output)
|
||||||
{
|
{
|
||||||
struct osd_classic_scene_item *item;
|
struct osd_classic_scene_item *item;
|
||||||
wl_array_for_each(item, &output->osd_scene.items) {
|
wl_array_for_each(item, &output->osd_scene.items) {
|
||||||
wlr_scene_node_set_enabled(item->highlight_outline,
|
bool active = item->view == output->server->osd_state.cycle_view;
|
||||||
item->view == output->server->osd_state.cycle_view);
|
wlr_scene_node_set_enabled(&item->normal_tree->node, !active);
|
||||||
|
wlr_scene_node_set_enabled(&item->active_tree->node, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,13 @@ struct field_converter {
|
||||||
/* Internal helpers */
|
/* Internal helpers */
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_app_id_or_class(struct view *view, bool trim)
|
get_identifier(struct view *view, bool trim)
|
||||||
{
|
{
|
||||||
/*
|
const char *identifier = view->app_id;
|
||||||
* XWayland clients return WM_CLASS for 'app_id' so we don't need a
|
|
||||||
* special case for that here.
|
|
||||||
*/
|
|
||||||
const char *identifier = view_get_string_prop(view, "app_id");
|
|
||||||
|
|
||||||
/* remove the first two nodes of 'org.' strings */
|
/* remove the first two nodes of 'org.' strings */
|
||||||
if (trim && !strncmp(identifier, "org.", 4)) {
|
if (trim && !strncmp(identifier, "org.", 4)) {
|
||||||
char *p = (char *)identifier + 4;
|
const char *p = identifier + 4;
|
||||||
p = strchr(p, '.');
|
p = strchr(p, '.');
|
||||||
if (p) {
|
if (p) {
|
||||||
return ++p;
|
return ++p;
|
||||||
|
|
@ -49,14 +45,13 @@ static const char *
|
||||||
get_desktop_name(struct view *view)
|
get_desktop_name(struct view *view)
|
||||||
{
|
{
|
||||||
#if HAVE_LIBSFDO
|
#if HAVE_LIBSFDO
|
||||||
const char *app_id = view_get_string_prop(view, "app_id");
|
const char *name = desktop_entry_name_lookup(view->server, view->app_id);
|
||||||
const char *name = desktop_entry_name_lookup(view->server, app_id);
|
|
||||||
if (name) {
|
if (name) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return get_app_id_or_class(view, /* trim */ true);
|
return get_identifier(view, /* trim */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
@ -73,21 +68,12 @@ get_type(struct view *view, bool short_form)
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
get_title(struct view *view)
|
|
||||||
{
|
|
||||||
return view_get_string_prop(view, "title");
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
get_title_if_different(struct view *view)
|
get_title_if_different(struct view *view)
|
||||||
{
|
{
|
||||||
const char *identifier = get_app_id_or_class(view, /*trim*/ false);
|
const char *identifier = get_identifier(view, /*trim*/ false);
|
||||||
const char *title = get_title(view);
|
const char *title = view->title;
|
||||||
if (!identifier) {
|
return !strcmp(identifier, title) ? NULL : title;
|
||||||
return title;
|
|
||||||
}
|
|
||||||
return (!title || !strcmp(identifier, title)) ? NULL : title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Field handlers */
|
/* Field handlers */
|
||||||
|
|
@ -125,10 +111,12 @@ static void
|
||||||
field_set_win_state(struct buf *buf, struct view *view, const char *format)
|
field_set_win_state(struct buf *buf, struct view *view, const char *format)
|
||||||
{
|
{
|
||||||
/* custom type conversion-specifier: s */
|
/* custom type conversion-specifier: s */
|
||||||
if (view->maximized) {
|
if (view->minimized) {
|
||||||
buf_add(buf, "M");
|
|
||||||
} else if (view->minimized) {
|
|
||||||
buf_add(buf, "m");
|
buf_add(buf, "m");
|
||||||
|
} else if (view->shaded) {
|
||||||
|
buf_add(buf, "s");
|
||||||
|
} else if (view->maximized) {
|
||||||
|
buf_add(buf, "M");
|
||||||
} else if (view->fullscreen) {
|
} else if (view->fullscreen) {
|
||||||
buf_add(buf, "F");
|
buf_add(buf, "F");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -141,6 +129,7 @@ field_set_win_state_all(struct buf *buf, struct view *view, const char *format)
|
||||||
{
|
{
|
||||||
/* custom type conversion-specifier: S */
|
/* custom type conversion-specifier: S */
|
||||||
buf_add(buf, view->minimized ? "m" : " ");
|
buf_add(buf, view->minimized ? "m" : " ");
|
||||||
|
buf_add(buf, view->shaded ? "s" : " ");
|
||||||
buf_add(buf, view->maximized ? "M" : " ");
|
buf_add(buf, view->maximized ? "M" : " ");
|
||||||
buf_add(buf, view->fullscreen ? "F" : " ");
|
buf_add(buf, view->fullscreen ? "F" : " ");
|
||||||
/* TODO: add always-on-top and omnipresent ? */
|
/* TODO: add always-on-top and omnipresent ? */
|
||||||
|
|
@ -169,14 +158,14 @@ static void
|
||||||
field_set_identifier(struct buf *buf, struct view *view, const char *format)
|
field_set_identifier(struct buf *buf, struct view *view, const char *format)
|
||||||
{
|
{
|
||||||
/* custom type conversion-specifier: I */
|
/* custom type conversion-specifier: I */
|
||||||
buf_add(buf, get_app_id_or_class(view, /*trim*/ false));
|
buf_add(buf, get_identifier(view, /*trim*/ false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
field_set_identifier_trimmed(struct buf *buf, struct view *view, const char *format)
|
field_set_identifier_trimmed(struct buf *buf, struct view *view, const char *format)
|
||||||
{
|
{
|
||||||
/* custom type conversion-specifier: i */
|
/* custom type conversion-specifier: i */
|
||||||
buf_add(buf, get_app_id_or_class(view, /*trim*/ true));
|
buf_add(buf, get_identifier(view, /*trim*/ true));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -190,7 +179,7 @@ static void
|
||||||
field_set_title(struct buf *buf, struct view *view, const char *format)
|
field_set_title(struct buf *buf, struct view *view, const char *format)
|
||||||
{
|
{
|
||||||
/* custom type conversion-specifier: T */
|
/* custom type conversion-specifier: T */
|
||||||
buf_add(buf, get_title(view));
|
buf_add(buf, view->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -155,15 +155,12 @@ create_item_scene(struct wlr_scene_tree *parent, struct view *view,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* title */
|
/* title */
|
||||||
const char *title = view_get_string_prop(view, "title");
|
|
||||||
if (title) {
|
|
||||||
item->normal_title = create_title(item->tree, switcher_theme,
|
item->normal_title = create_title(item->tree, switcher_theme,
|
||||||
title, theme->osd_label_text_color,
|
view->title, theme->osd_label_text_color,
|
||||||
theme->osd_bg_color, title_y);
|
theme->osd_bg_color, title_y);
|
||||||
item->active_title = create_title(item->tree, switcher_theme,
|
item->active_title = create_title(item->tree, switcher_theme,
|
||||||
title, theme->osd_label_text_color,
|
view->title, theme->osd_label_text_color,
|
||||||
switcher_theme->item_active_bg_color, title_y);
|
switcher_theme->item_active_bg_color, title_y);
|
||||||
}
|
|
||||||
|
|
||||||
/* icon */
|
/* icon */
|
||||||
int icon_size = switcher_theme->item_icon_size;
|
int icon_size = switcher_theme->item_icon_size;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common/scene-helpers.h"
|
#include "common/scene-helpers.h"
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
|
#include "node.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "scaled-buffer/scaled-font-buffer.h"
|
#include "scaled-buffer/scaled-font-buffer.h"
|
||||||
#include "scaled-buffer/scaled-icon-buffer.h"
|
#include "scaled-buffer/scaled-icon-buffer.h"
|
||||||
|
|
@ -160,9 +161,14 @@ restore_preview_node(struct server *server)
|
||||||
if (!osd_state->preview_was_enabled) {
|
if (!osd_state->preview_was_enabled) {
|
||||||
wlr_scene_node_set_enabled(osd_state->preview_node, false);
|
wlr_scene_node_set_enabled(osd_state->preview_node, false);
|
||||||
}
|
}
|
||||||
|
if (osd_state->preview_was_shaded) {
|
||||||
|
struct view *view = node_view_from_node(osd_state->preview_node);
|
||||||
|
view_set_shade(view, true);
|
||||||
|
}
|
||||||
osd_state->preview_node = NULL;
|
osd_state->preview_node = NULL;
|
||||||
osd_state->preview_parent = NULL;
|
osd_state->preview_parent = NULL;
|
||||||
osd_state->preview_anchor = NULL;
|
osd_state->preview_anchor = NULL;
|
||||||
|
osd_state->preview_was_shaded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,6 +209,7 @@ osd_finish(struct server *server)
|
||||||
server->osd_state.preview_node = NULL;
|
server->osd_state.preview_node = NULL;
|
||||||
server->osd_state.preview_anchor = NULL;
|
server->osd_state.preview_anchor = NULL;
|
||||||
server->osd_state.cycle_view = NULL;
|
server->osd_state.cycle_view = NULL;
|
||||||
|
server->osd_state.preview_was_shaded = false;
|
||||||
|
|
||||||
destroy_osd_scenes(server);
|
destroy_osd_scenes(server);
|
||||||
|
|
||||||
|
|
@ -244,6 +251,10 @@ preview_cycled_view(struct view *view)
|
||||||
if (!osd_state->preview_was_enabled) {
|
if (!osd_state->preview_was_enabled) {
|
||||||
wlr_scene_node_set_enabled(osd_state->preview_node, true);
|
wlr_scene_node_set_enabled(osd_state->preview_node, true);
|
||||||
}
|
}
|
||||||
|
if (rc.window_switcher.unshade && view->shaded) {
|
||||||
|
view_set_shade(view, false);
|
||||||
|
osd_state->preview_was_shaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: This abuses an implementation detail of the always-on-top tree.
|
* FIXME: This abuses an implementation detail of the always-on-top tree.
|
||||||
|
|
@ -294,6 +305,10 @@ update_osd(struct server *server)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc.window_switcher.preview) {
|
||||||
|
preview_cycled_view(server->osd_state.cycle_view);
|
||||||
|
}
|
||||||
|
|
||||||
/* Outline current window */
|
/* Outline current window */
|
||||||
if (rc.window_switcher.outlines) {
|
if (rc.window_switcher.outlines) {
|
||||||
if (view_is_focusable(server->osd_state.cycle_view)) {
|
if (view_is_focusable(server->osd_state.cycle_view)) {
|
||||||
|
|
@ -301,9 +316,6 @@ update_osd(struct server *server)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc.window_switcher.preview) {
|
|
||||||
preview_cycled_view(server->osd_state.cycle_view);
|
|
||||||
}
|
|
||||||
out:
|
out:
|
||||||
wl_array_release(&views);
|
wl_array_release(&views);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ handle_view_new_app_id(struct wl_listener *listener, void *data)
|
||||||
struct scaled_icon_buffer *self =
|
struct scaled_icon_buffer *self =
|
||||||
wl_container_of(listener, self, on_view.new_app_id);
|
wl_container_of(listener, self, on_view.new_app_id);
|
||||||
|
|
||||||
const char *app_id = view_get_string_prop(self->view, "app_id");
|
const char *app_id = self->view->app_id;
|
||||||
if (str_equal(app_id, self->view_app_id)) {
|
if (str_equal(app_id, self->view_app_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||||
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||||
|
#include <wlr/types/wlr_fixes.h>
|
||||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||||
#include <wlr/types/wlr_input_method_v2.h>
|
#include <wlr/types/wlr_input_method_v2.h>
|
||||||
|
|
@ -255,6 +256,7 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
|
||||||
"wl_data_device_manager", /* would be great if we could drop this one */
|
"wl_data_device_manager", /* would be great if we could drop this one */
|
||||||
"wl_seat",
|
"wl_seat",
|
||||||
"xdg_wm_base",
|
"xdg_wm_base",
|
||||||
|
"wl_fixes",
|
||||||
/* enhanced */
|
/* enhanced */
|
||||||
"wl_output",
|
"wl_output",
|
||||||
"wl_drm",
|
"wl_drm",
|
||||||
|
|
@ -276,6 +278,7 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
|
||||||
"zxdg_importer_v1",
|
"zxdg_importer_v1",
|
||||||
"zxdg_importer_v2",
|
"zxdg_importer_v2",
|
||||||
"xdg_toplevel_icon_manager_v1",
|
"xdg_toplevel_icon_manager_v1",
|
||||||
|
"xdg_dialog_v1",
|
||||||
/* plus */
|
/* plus */
|
||||||
"wp_alpha_modifier_v1",
|
"wp_alpha_modifier_v1",
|
||||||
"wp_linux_drm_syncobj_manager_v1",
|
"wp_linux_drm_syncobj_manager_v1",
|
||||||
|
|
@ -434,6 +437,8 @@ server_init(struct server *server)
|
||||||
|
|
||||||
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
||||||
|
|
||||||
|
wlr_fixes_create(server->wl_display, 1);
|
||||||
|
|
||||||
/* Catch signals */
|
/* Catch signals */
|
||||||
server->sighup_source = wl_event_loop_add_signal(
|
server->sighup_source = wl_event_loop_add_signal(
|
||||||
server->wl_event_loop, SIGHUP, handle_sighup, server);
|
server->wl_event_loop, SIGHUP, handle_sighup, server);
|
||||||
|
|
|
||||||
|
|
@ -259,8 +259,8 @@ ssd_shadow_update(struct ssd *ssd)
|
||||||
bool maximized = view->maximized == VIEW_AXIS_BOTH;
|
bool maximized = view->maximized == VIEW_AXIS_BOTH;
|
||||||
bool tiled_shadows = false;
|
bool tiled_shadows = false;
|
||||||
if (rc.shadows_on_tiled) {
|
if (rc.shadows_on_tiled) {
|
||||||
if (rc.gap >= theme->window[THEME_ACTIVE].shadow_size
|
if (rc.gap >= theme->window[SSD_ACTIVE].shadow_size
|
||||||
&& rc.gap >= theme->window[THEME_INACTIVE].shadow_size) {
|
&& rc.gap >= theme->window[SSD_INACTIVE].shadow_size) {
|
||||||
tiled_shadows = true;
|
tiled_shadows = true;
|
||||||
} else {
|
} else {
|
||||||
wlr_log(WLR_INFO, "gap size < shadow_size, ignore rc.shadows_ontiled");
|
wlr_log(WLR_INFO, "gap size < shadow_size, ignore rc.shadows_ontiled");
|
||||||
|
|
|
||||||
|
|
@ -440,14 +440,13 @@ ssd_update_title(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct view *view = ssd->view;
|
struct view *view = ssd->view;
|
||||||
char *title = (char *)view_get_string_prop(view, "title");
|
if (string_null_or_empty(view->title)) {
|
||||||
if (string_null_or_empty(title)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
struct ssd_state_title *state = &ssd->state.title;
|
struct ssd_state_title *state = &ssd->state.title;
|
||||||
bool title_unchanged = state->text && !strcmp(title, state->text);
|
bool title_unchanged = state->text && !strcmp(view->title, state->text);
|
||||||
|
|
||||||
int offset_left, offset_right;
|
int offset_left, offset_right;
|
||||||
get_title_offsets(ssd, &offset_left, &offset_right);
|
get_title_offsets(ssd, &offset_left, &offset_right);
|
||||||
|
|
@ -473,7 +472,7 @@ ssd_update_title(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
|
|
||||||
const float bg_color[4] = {0, 0, 0, 0}; /* ignored */
|
const float bg_color[4] = {0, 0, 0, 0}; /* ignored */
|
||||||
scaled_font_buffer_update(subtree->title, title,
|
scaled_font_buffer_update(subtree->title, view->title,
|
||||||
title_bg_width, font,
|
title_bg_width, font,
|
||||||
text_color, bg_color);
|
text_color, bg_color);
|
||||||
|
|
||||||
|
|
@ -483,10 +482,7 @@ ssd_update_title(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!title_unchanged) {
|
if (!title_unchanged) {
|
||||||
if (state->text) {
|
xstrdup_replace(state->text, view->title);
|
||||||
free(state->text);
|
|
||||||
}
|
|
||||||
state->text = xstrdup(title);
|
|
||||||
}
|
}
|
||||||
ssd_update_title_positions(ssd, offset_left, offset_right);
|
ssd_update_title_positions(ssd, offset_left, offset_right);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
|
||||||
|
|
||||||
float *color = enable
|
float *color = enable
|
||||||
? rc.theme->window_toggled_keybinds_color
|
? rc.theme->window_toggled_keybinds_color
|
||||||
: rc.theme->window[THEME_ACTIVE].border_color;
|
: rc.theme->window[SSD_ACTIVE].border_color;
|
||||||
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
|
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
200
src/theme.c
200
src/theme.c
|
|
@ -162,7 +162,7 @@ get_button_filename(char *buf, size_t len, const char *name, const char *postfix
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_button(struct theme *theme, struct button *b, int active)
|
load_button(struct theme *theme, struct button *b, enum ssd_active_state active)
|
||||||
{
|
{
|
||||||
struct lab_img *(*button_imgs)[LAB_BS_ALL + 1] =
|
struct lab_img *(*button_imgs)[LAB_BS_ALL + 1] =
|
||||||
theme->window[active].button_imgs;
|
theme->window[active].button_imgs;
|
||||||
|
|
@ -374,8 +374,8 @@ load_buttons(struct theme *theme)
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) {
|
for (size_t i = 0; i < ARRAY_SIZE(buttons); ++i) {
|
||||||
struct button *b = &buttons[i];
|
struct button *b = &buttons[i];
|
||||||
load_button(theme, b, THEME_INACTIVE);
|
load_button(theme, b, SSD_INACTIVE);
|
||||||
load_button(theme, b, THEME_ACTIVE);
|
load_button(theme, b, SSD_ACTIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -537,24 +537,24 @@ theme_builtin(struct theme *theme, struct server *server)
|
||||||
theme->window_titlebar_padding_height = 0;
|
theme->window_titlebar_padding_height = 0;
|
||||||
theme->window_titlebar_padding_width = 0;
|
theme->window_titlebar_padding_width = 0;
|
||||||
|
|
||||||
parse_hexstr("#aaaaaa", theme->window[THEME_ACTIVE].border_color);
|
parse_hexstr("#aaaaaa", theme->window[SSD_ACTIVE].border_color);
|
||||||
parse_hexstr("#aaaaaa", theme->window[THEME_INACTIVE].border_color);
|
parse_hexstr("#aaaaaa", theme->window[SSD_INACTIVE].border_color);
|
||||||
|
|
||||||
parse_hexstr("#ff0000", theme->window_toggled_keybinds_color);
|
parse_hexstr("#ff0000", theme->window_toggled_keybinds_color);
|
||||||
|
|
||||||
theme->window[THEME_ACTIVE].title_bg.gradient = LAB_GRADIENT_NONE;
|
theme->window[SSD_ACTIVE].title_bg.gradient = LAB_GRADIENT_NONE;
|
||||||
theme->window[THEME_INACTIVE].title_bg.gradient = LAB_GRADIENT_NONE;
|
theme->window[SSD_INACTIVE].title_bg.gradient = LAB_GRADIENT_NONE;
|
||||||
parse_hexstr("#e1dedb", theme->window[THEME_ACTIVE].title_bg.color);
|
parse_hexstr("#e1dedb", theme->window[SSD_ACTIVE].title_bg.color);
|
||||||
parse_hexstr("#f6f5f4", theme->window[THEME_INACTIVE].title_bg.color);
|
parse_hexstr("#f6f5f4", theme->window[SSD_INACTIVE].title_bg.color);
|
||||||
theme->window[THEME_ACTIVE].title_bg.color_split_to[0] = FLT_MIN;
|
theme->window[SSD_ACTIVE].title_bg.color_split_to[0] = FLT_MIN;
|
||||||
theme->window[THEME_INACTIVE].title_bg.color_split_to[0] = FLT_MIN;
|
theme->window[SSD_INACTIVE].title_bg.color_split_to[0] = FLT_MIN;
|
||||||
theme->window[THEME_ACTIVE].title_bg.color_to[0] = FLT_MIN;
|
theme->window[SSD_ACTIVE].title_bg.color_to[0] = FLT_MIN;
|
||||||
theme->window[THEME_INACTIVE].title_bg.color_to[0] = FLT_MIN;
|
theme->window[SSD_INACTIVE].title_bg.color_to[0] = FLT_MIN;
|
||||||
theme->window[THEME_ACTIVE].title_bg.color_to_split_to[0] = FLT_MIN;
|
theme->window[SSD_ACTIVE].title_bg.color_to_split_to[0] = FLT_MIN;
|
||||||
theme->window[THEME_INACTIVE].title_bg.color_to_split_to[0] = FLT_MIN;
|
theme->window[SSD_INACTIVE].title_bg.color_to_split_to[0] = FLT_MIN;
|
||||||
|
|
||||||
parse_hexstr("#000000", theme->window[THEME_ACTIVE].label_text_color);
|
parse_hexstr("#000000", theme->window[SSD_ACTIVE].label_text_color);
|
||||||
parse_hexstr("#000000", theme->window[THEME_INACTIVE].label_text_color);
|
parse_hexstr("#000000", theme->window[SSD_INACTIVE].label_text_color);
|
||||||
theme->window_label_text_justify = parse_justification("Center");
|
theme->window_label_text_justify = parse_justification("Center");
|
||||||
|
|
||||||
theme->window_button_width = 26;
|
theme->window_button_width = 26;
|
||||||
|
|
@ -565,15 +565,15 @@ theme_builtin(struct theme *theme, struct server *server)
|
||||||
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
||||||
type <= LAB_NODE_BUTTON_LAST; type++) {
|
type <= LAB_NODE_BUTTON_LAST; type++) {
|
||||||
parse_hexstr("#000000",
|
parse_hexstr("#000000",
|
||||||
theme->window[THEME_INACTIVE].button_colors[type]);
|
theme->window[SSD_INACTIVE].button_colors[type]);
|
||||||
parse_hexstr("#000000",
|
parse_hexstr("#000000",
|
||||||
theme->window[THEME_ACTIVE].button_colors[type]);
|
theme->window[SSD_ACTIVE].button_colors[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
theme->window[THEME_ACTIVE].shadow_size = 60;
|
theme->window[SSD_ACTIVE].shadow_size = 60;
|
||||||
theme->window[THEME_INACTIVE].shadow_size = 40;
|
theme->window[SSD_INACTIVE].shadow_size = 40;
|
||||||
parse_hexstr("#00000060", theme->window[THEME_ACTIVE].shadow_color);
|
parse_hexstr("#00000060", theme->window[SSD_ACTIVE].shadow_color);
|
||||||
parse_hexstr("#00000040", theme->window[THEME_INACTIVE].shadow_color);
|
parse_hexstr("#00000040", theme->window[SSD_INACTIVE].shadow_color);
|
||||||
|
|
||||||
theme->menu_overlap_x = 0;
|
theme->menu_overlap_x = 0;
|
||||||
theme->menu_overlap_y = 0;
|
theme->menu_overlap_y = 0;
|
||||||
|
|
@ -604,6 +604,8 @@ theme_builtin(struct theme *theme, struct server *server)
|
||||||
theme->osd_window_switcher_classic.item_padding_x = 10;
|
theme->osd_window_switcher_classic.item_padding_x = 10;
|
||||||
theme->osd_window_switcher_classic.item_padding_y = 1;
|
theme->osd_window_switcher_classic.item_padding_y = 1;
|
||||||
theme->osd_window_switcher_classic.item_active_border_width = 2;
|
theme->osd_window_switcher_classic.item_active_border_width = 2;
|
||||||
|
theme->osd_window_switcher_classic.item_active_border_color[0] = FLT_MIN;
|
||||||
|
theme->osd_window_switcher_classic.item_active_bg_color[0] = FLT_MIN;
|
||||||
theme->osd_window_switcher_classic.item_icon_size = -1;
|
theme->osd_window_switcher_classic.item_icon_size = -1;
|
||||||
|
|
||||||
theme->osd_window_switcher_thumbnail.max_width = 80;
|
theme->osd_window_switcher_thumbnail.max_width = 80;
|
||||||
|
|
@ -613,8 +615,8 @@ theme_builtin(struct theme *theme, struct server *server)
|
||||||
theme->osd_window_switcher_thumbnail.item_height = 250;
|
theme->osd_window_switcher_thumbnail.item_height = 250;
|
||||||
theme->osd_window_switcher_thumbnail.item_padding = 10;
|
theme->osd_window_switcher_thumbnail.item_padding = 10;
|
||||||
theme->osd_window_switcher_thumbnail.item_active_border_width = 2;
|
theme->osd_window_switcher_thumbnail.item_active_border_width = 2;
|
||||||
parse_color("#589bda", theme->osd_window_switcher_thumbnail.item_active_border_color);
|
theme->osd_window_switcher_thumbnail.item_active_border_color[0] = FLT_MIN;
|
||||||
parse_color("#c7e2fc", theme->osd_window_switcher_thumbnail.item_active_bg_color);
|
theme->osd_window_switcher_thumbnail.item_active_bg_color[0] = FLT_MIN;
|
||||||
theme->osd_window_switcher_thumbnail.item_icon_size = 60;
|
theme->osd_window_switcher_thumbnail.item_icon_size = 60;
|
||||||
|
|
||||||
/* inherit settings in post_processing() if not set elsewhere */
|
/* inherit settings in post_processing() if not set elsewhere */
|
||||||
|
|
@ -709,15 +711,15 @@ entry(struct theme *theme, const char *key, const char *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_glob(key, "window.active.border.color")) {
|
if (match_glob(key, "window.active.border.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].border_color);
|
parse_color(value, theme->window[SSD_ACTIVE].border_color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.border.color")) {
|
if (match_glob(key, "window.inactive.border.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].border_color);
|
parse_color(value, theme->window[SSD_INACTIVE].border_color);
|
||||||
}
|
}
|
||||||
/* border.color is obsolete, but handled for backward compatibility */
|
/* border.color is obsolete, but handled for backward compatibility */
|
||||||
if (match_glob(key, "border.color")) {
|
if (match_glob(key, "border.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].border_color);
|
parse_color(value, theme->window[SSD_ACTIVE].border_color);
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].border_color);
|
parse_color(value, theme->window[SSD_INACTIVE].border_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_glob(key, "window.active.indicator.toggled-keybind.color")) {
|
if (match_glob(key, "window.active.indicator.toggled-keybind.color")) {
|
||||||
|
|
@ -725,41 +727,41 @@ entry(struct theme *theme, const char *key, const char *value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_glob(key, "window.active.title.bg")) {
|
if (match_glob(key, "window.active.title.bg")) {
|
||||||
theme->window[THEME_ACTIVE].title_bg.gradient = parse_gradient(value);
|
theme->window[SSD_ACTIVE].title_bg.gradient = parse_gradient(value);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.title.bg")) {
|
if (match_glob(key, "window.inactive.title.bg")) {
|
||||||
theme->window[THEME_INACTIVE].title_bg.gradient = parse_gradient(value);
|
theme->window[SSD_INACTIVE].title_bg.gradient = parse_gradient(value);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.title.bg.color")) {
|
if (match_glob(key, "window.active.title.bg.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].title_bg.color);
|
parse_color(value, theme->window[SSD_ACTIVE].title_bg.color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.title.bg.color")) {
|
if (match_glob(key, "window.inactive.title.bg.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].title_bg.color);
|
parse_color(value, theme->window[SSD_INACTIVE].title_bg.color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.title.bg.color.splitTo")) {
|
if (match_glob(key, "window.active.title.bg.color.splitTo")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].title_bg.color_split_to);
|
parse_color(value, theme->window[SSD_ACTIVE].title_bg.color_split_to);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.title.bg.color.splitTo")) {
|
if (match_glob(key, "window.inactive.title.bg.color.splitTo")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].title_bg.color_split_to);
|
parse_color(value, theme->window[SSD_INACTIVE].title_bg.color_split_to);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.title.bg.colorTo")) {
|
if (match_glob(key, "window.active.title.bg.colorTo")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].title_bg.color_to);
|
parse_color(value, theme->window[SSD_ACTIVE].title_bg.color_to);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.title.bg.colorTo")) {
|
if (match_glob(key, "window.inactive.title.bg.colorTo")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].title_bg.color_to);
|
parse_color(value, theme->window[SSD_INACTIVE].title_bg.color_to);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.title.bg.colorTo.splitTo")) {
|
if (match_glob(key, "window.active.title.bg.colorTo.splitTo")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].title_bg.color_to_split_to);
|
parse_color(value, theme->window[SSD_ACTIVE].title_bg.color_to_split_to);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.title.bg.colorTo.splitTo")) {
|
if (match_glob(key, "window.inactive.title.bg.colorTo.splitTo")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].title_bg.color_to_split_to);
|
parse_color(value, theme->window[SSD_INACTIVE].title_bg.color_to_split_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_glob(key, "window.active.label.text.color")) {
|
if (match_glob(key, "window.active.label.text.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].label_text_color);
|
parse_color(value, theme->window[SSD_ACTIVE].label_text_color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.label.text.color")) {
|
if (match_glob(key, "window.inactive.label.text.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].label_text_color);
|
parse_color(value, theme->window[SSD_INACTIVE].label_text_color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.label.text.justify")) {
|
if (match_glob(key, "window.label.text.justify")) {
|
||||||
theme->window_label_text_justify = parse_justification(value);
|
theme->window_label_text_justify = parse_justification(value);
|
||||||
|
|
@ -795,85 +797,85 @@ entry(struct theme *theme, const char *key, const char *value)
|
||||||
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
||||||
type <= LAB_NODE_BUTTON_LAST; type++) {
|
type <= LAB_NODE_BUTTON_LAST; type++) {
|
||||||
parse_color(value,
|
parse_color(value,
|
||||||
theme->window[THEME_ACTIVE].button_colors[type]);
|
theme->window[SSD_ACTIVE].button_colors[type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.unpressed.image.color")) {
|
||||||
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
for (enum lab_node_type type = LAB_NODE_BUTTON_FIRST;
|
||||||
type <= LAB_NODE_BUTTON_LAST; type++) {
|
type <= LAB_NODE_BUTTON_LAST; type++) {
|
||||||
parse_color(value,
|
parse_color(value,
|
||||||
theme->window[THEME_INACTIVE].button_colors[type]);
|
theme->window[SSD_INACTIVE].button_colors[type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* individual buttons */
|
/* individual buttons */
|
||||||
if (match_glob(key, "window.active.button.menu.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.menu.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_WINDOW_MENU]);
|
.button_colors[LAB_NODE_BUTTON_WINDOW_MENU]);
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_WINDOW_ICON]);
|
.button_colors[LAB_NODE_BUTTON_WINDOW_ICON]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.button.iconify.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.iconify.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_ICONIFY]);
|
.button_colors[LAB_NODE_BUTTON_ICONIFY]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.button.max.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.max.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_MAXIMIZE]);
|
.button_colors[LAB_NODE_BUTTON_MAXIMIZE]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.button.shade.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.shade.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_SHADE]);
|
.button_colors[LAB_NODE_BUTTON_SHADE]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.button.desk.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.desk.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_OMNIPRESENT]);
|
.button_colors[LAB_NODE_BUTTON_OMNIPRESENT]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.button.close.unpressed.image.color")) {
|
if (match_glob(key, "window.active.button.close.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE]
|
parse_color(value, theme->window[SSD_ACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_CLOSE]);
|
.button_colors[LAB_NODE_BUTTON_CLOSE]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.menu.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.menu.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_WINDOW_MENU]);
|
.button_colors[LAB_NODE_BUTTON_WINDOW_MENU]);
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_WINDOW_ICON]);
|
.button_colors[LAB_NODE_BUTTON_WINDOW_ICON]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.iconify.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.iconify.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_ICONIFY]);
|
.button_colors[LAB_NODE_BUTTON_ICONIFY]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.max.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.max.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_MAXIMIZE]);
|
.button_colors[LAB_NODE_BUTTON_MAXIMIZE]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.shade.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.shade.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_SHADE]);
|
.button_colors[LAB_NODE_BUTTON_SHADE]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.desk.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.desk.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_OMNIPRESENT]);
|
.button_colors[LAB_NODE_BUTTON_OMNIPRESENT]);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.button.close.unpressed.image.color")) {
|
if (match_glob(key, "window.inactive.button.close.unpressed.image.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE]
|
parse_color(value, theme->window[SSD_INACTIVE]
|
||||||
.button_colors[LAB_NODE_BUTTON_CLOSE]);
|
.button_colors[LAB_NODE_BUTTON_CLOSE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* window drop-shadows */
|
/* window drop-shadows */
|
||||||
if (match_glob(key, "window.active.shadow.size")) {
|
if (match_glob(key, "window.active.shadow.size")) {
|
||||||
theme->window[THEME_ACTIVE].shadow_size = get_int_if_positive(
|
theme->window[SSD_ACTIVE].shadow_size = get_int_if_positive(
|
||||||
value, "window.active.shadow.size");
|
value, "window.active.shadow.size");
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.shadow.size")) {
|
if (match_glob(key, "window.inactive.shadow.size")) {
|
||||||
theme->window[THEME_INACTIVE].shadow_size = get_int_if_positive(
|
theme->window[SSD_INACTIVE].shadow_size = get_int_if_positive(
|
||||||
value, "window.inactive.shadow.size");
|
value, "window.inactive.shadow.size");
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.active.shadow.color")) {
|
if (match_glob(key, "window.active.shadow.color")) {
|
||||||
parse_color(value, theme->window[THEME_ACTIVE].shadow_color);
|
parse_color(value, theme->window[SSD_ACTIVE].shadow_color);
|
||||||
}
|
}
|
||||||
if (match_glob(key, "window.inactive.shadow.color")) {
|
if (match_glob(key, "window.inactive.shadow.color")) {
|
||||||
parse_color(value, theme->window[THEME_INACTIVE].shadow_color);
|
parse_color(value, theme->window[SSD_INACTIVE].shadow_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_glob(key, "menu.overlap.x")) {
|
if (match_glob(key, "menu.overlap.x")) {
|
||||||
|
|
@ -989,6 +991,12 @@ entry(struct theme *theme, const char *key, const char *value)
|
||||||
get_int_if_positive(value,
|
get_int_if_positive(value,
|
||||||
"osd.window-switcher.style-classic.item.active.border.width");
|
"osd.window-switcher.style-classic.item.active.border.width");
|
||||||
}
|
}
|
||||||
|
if (match_glob(key, "osd.window-switcher.style-classic.item.active.border.color")) {
|
||||||
|
parse_color(value, switcher_classic_theme->item_active_border_color);
|
||||||
|
}
|
||||||
|
if (match_glob(key, "osd.window-switcher.style-classic.item.active.bg.color")) {
|
||||||
|
parse_color(value, switcher_classic_theme->item_active_bg_color);
|
||||||
|
}
|
||||||
if (match_glob(key, "osd.window-switcher.style-classic.item.icon.size")
|
if (match_glob(key, "osd.window-switcher.style-classic.item.icon.size")
|
||||||
|| match_glob(key, "osd.window-switcher.item.icon.size")) {
|
|| match_glob(key, "osd.window-switcher.item.icon.size")) {
|
||||||
switcher_classic_theme->item_icon_size =
|
switcher_classic_theme->item_icon_size =
|
||||||
|
|
@ -1388,7 +1396,8 @@ create_titlebar_fill(cairo_pattern_t *pattern, int height)
|
||||||
static void
|
static void
|
||||||
create_backgrounds(struct theme *theme)
|
create_backgrounds(struct theme *theme)
|
||||||
{
|
{
|
||||||
for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) {
|
enum ssd_active_state active;
|
||||||
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
theme->window[active].titlebar_pattern = create_titlebar_pattern(
|
theme->window[active].titlebar_pattern = create_titlebar_pattern(
|
||||||
&theme->window[active].title_bg,
|
&theme->window[active].title_bg,
|
||||||
theme->titlebar_height);
|
theme->titlebar_height);
|
||||||
|
|
@ -1410,7 +1419,8 @@ create_corners(struct theme *theme)
|
||||||
.height = theme->titlebar_height + theme->border_width,
|
.height = theme->titlebar_height + theme->border_width,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) {
|
enum ssd_active_state active;
|
||||||
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
struct rounded_corner_ctx ctx = {
|
struct rounded_corner_ctx ctx = {
|
||||||
.box = &box,
|
.box = &box,
|
||||||
.radius = rc.corner_radius,
|
.radius = rc.corner_radius,
|
||||||
|
|
@ -1540,7 +1550,7 @@ shadow_corner_gradient(struct lab_data_buffer *buffer, int visible_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_shadow(struct theme *theme, int active)
|
create_shadow(struct theme *theme, enum ssd_active_state active)
|
||||||
{
|
{
|
||||||
/* Size of shadow visible extending beyond the window */
|
/* Size of shadow visible extending beyond the window */
|
||||||
int visible_size = theme->window[active].shadow_size;
|
int visible_size = theme->window[active].shadow_size;
|
||||||
|
|
@ -1582,8 +1592,8 @@ create_shadow(struct theme *theme, int active)
|
||||||
static void
|
static void
|
||||||
create_shadows(struct theme *theme)
|
create_shadows(struct theme *theme)
|
||||||
{
|
{
|
||||||
create_shadow(theme, THEME_INACTIVE);
|
create_shadow(theme, SSD_INACTIVE);
|
||||||
create_shadow(theme, THEME_ACTIVE);
|
create_shadow(theme, SSD_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1633,6 +1643,31 @@ get_titlebar_height(struct theme *theme)
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Blend foreground color (with new alpha) with background color */
|
||||||
|
static void
|
||||||
|
blend_color_with_bg(float *dst, float *fg, float fg_a, float *bg)
|
||||||
|
{
|
||||||
|
/* Guard against zero division */
|
||||||
|
if (fg[3] <= 0.0f) {
|
||||||
|
memset(dst, 0, sizeof(float) * 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Redo premultiplication to update foreground alpha */
|
||||||
|
float new_fg[4] = {
|
||||||
|
fg[0] / fg[3] * fg_a,
|
||||||
|
fg[1] / fg[3] * fg_a,
|
||||||
|
fg[2] / fg[3] * fg_a,
|
||||||
|
fg_a,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Blend colors */
|
||||||
|
dst[0] = new_fg[0] + bg[0] * (1.0f - new_fg[3]);
|
||||||
|
dst[1] = new_fg[1] + bg[1] * (1.0f - new_fg[3]);
|
||||||
|
dst[2] = new_fg[2] + bg[2] * (1.0f - new_fg[3]);
|
||||||
|
dst[3] = new_fg[3] + bg[3] * (1.0f - new_fg[3]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
post_processing(struct theme *theme)
|
post_processing(struct theme *theme)
|
||||||
{
|
{
|
||||||
|
|
@ -1643,8 +1678,8 @@ post_processing(struct theme *theme)
|
||||||
|
|
||||||
theme->titlebar_height = get_titlebar_height(theme);
|
theme->titlebar_height = get_titlebar_height(theme);
|
||||||
|
|
||||||
fill_background_colors(&theme->window[THEME_INACTIVE].title_bg);
|
fill_background_colors(&theme->window[SSD_INACTIVE].title_bg);
|
||||||
fill_background_colors(&theme->window[THEME_ACTIVE].title_bg);
|
fill_background_colors(&theme->window[SSD_ACTIVE].title_bg);
|
||||||
|
|
||||||
theme->menu_item_height = font_height(&rc.font_menuitem)
|
theme->menu_item_height = font_height(&rc.font_menuitem)
|
||||||
+ 2 * theme->menu_items_padding_y;
|
+ 2 * theme->menu_items_padding_y;
|
||||||
|
|
@ -1689,14 +1724,14 @@ post_processing(struct theme *theme)
|
||||||
}
|
}
|
||||||
if (theme->menu_border_color[0] == FLT_MIN) {
|
if (theme->menu_border_color[0] == FLT_MIN) {
|
||||||
memcpy(theme->menu_border_color,
|
memcpy(theme->menu_border_color,
|
||||||
theme->window[THEME_ACTIVE].border_color,
|
theme->window[SSD_ACTIVE].border_color,
|
||||||
sizeof(theme->menu_border_color));
|
sizeof(theme->menu_border_color));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inherit OSD settings if not set */
|
/* Inherit OSD settings if not set */
|
||||||
if (theme->osd_bg_color[0] == FLT_MIN) {
|
if (theme->osd_bg_color[0] == FLT_MIN) {
|
||||||
memcpy(theme->osd_bg_color,
|
memcpy(theme->osd_bg_color,
|
||||||
theme->window[THEME_ACTIVE].title_bg.color,
|
theme->window[SSD_ACTIVE].title_bg.color,
|
||||||
sizeof(theme->osd_bg_color));
|
sizeof(theme->osd_bg_color));
|
||||||
}
|
}
|
||||||
if (theme->osd_border_width == INT_MIN) {
|
if (theme->osd_border_width == INT_MIN) {
|
||||||
|
|
@ -1704,7 +1739,7 @@ post_processing(struct theme *theme)
|
||||||
}
|
}
|
||||||
if (theme->osd_label_text_color[0] == FLT_MIN) {
|
if (theme->osd_label_text_color[0] == FLT_MIN) {
|
||||||
memcpy(theme->osd_label_text_color,
|
memcpy(theme->osd_label_text_color,
|
||||||
theme->window[THEME_ACTIVE].label_text_color,
|
theme->window[SSD_ACTIVE].label_text_color,
|
||||||
sizeof(theme->osd_label_text_color));
|
sizeof(theme->osd_label_text_color));
|
||||||
}
|
}
|
||||||
if (theme->osd_border_color[0] == FLT_MIN) {
|
if (theme->osd_border_color[0] == FLT_MIN) {
|
||||||
|
|
@ -1721,6 +1756,22 @@ post_processing(struct theme *theme)
|
||||||
memcpy(theme->osd_border_color, theme->osd_label_text_color,
|
memcpy(theme->osd_border_color, theme->osd_label_text_color,
|
||||||
sizeof(theme->osd_border_color));
|
sizeof(theme->osd_border_color));
|
||||||
}
|
}
|
||||||
|
if (switcher_classic_theme->item_active_border_color[0] == FLT_MIN) {
|
||||||
|
blend_color_with_bg(switcher_classic_theme->item_active_border_color,
|
||||||
|
theme->osd_label_text_color, 0.50, theme->osd_bg_color);
|
||||||
|
}
|
||||||
|
if (switcher_classic_theme->item_active_bg_color[0] == FLT_MIN) {
|
||||||
|
blend_color_with_bg(switcher_classic_theme->item_active_bg_color,
|
||||||
|
theme->osd_label_text_color, 0.15, theme->osd_bg_color);
|
||||||
|
}
|
||||||
|
if (switcher_thumb_theme->item_active_border_color[0] == FLT_MIN) {
|
||||||
|
blend_color_with_bg(switcher_thumb_theme->item_active_border_color,
|
||||||
|
theme->osd_label_text_color, 0.50, theme->osd_bg_color);
|
||||||
|
}
|
||||||
|
if (switcher_thumb_theme->item_active_bg_color[0] == FLT_MIN) {
|
||||||
|
blend_color_with_bg(switcher_thumb_theme->item_active_bg_color,
|
||||||
|
theme->osd_label_text_color, 0.15, theme->osd_bg_color);
|
||||||
|
}
|
||||||
if (theme->osd_workspace_switcher_boxes_width == 0) {
|
if (theme->osd_workspace_switcher_boxes_width == 0) {
|
||||||
theme->osd_workspace_switcher_boxes_height = 0;
|
theme->osd_workspace_switcher_boxes_height = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1805,14 +1856,15 @@ theme_finish(struct theme *theme)
|
||||||
type <= LAB_NODE_BUTTON_LAST; type++) {
|
type <= LAB_NODE_BUTTON_LAST; type++) {
|
||||||
for (uint8_t state_set = LAB_BS_DEFAULT;
|
for (uint8_t state_set = LAB_BS_DEFAULT;
|
||||||
state_set <= LAB_BS_ALL; state_set++) {
|
state_set <= LAB_BS_ALL; state_set++) {
|
||||||
destroy_img(&theme->window[THEME_INACTIVE]
|
destroy_img(&theme->window[SSD_INACTIVE]
|
||||||
.button_imgs[type][state_set]);
|
.button_imgs[type][state_set]);
|
||||||
destroy_img(&theme->window[THEME_ACTIVE]
|
destroy_img(&theme->window[SSD_ACTIVE]
|
||||||
.button_imgs[type][state_set]);
|
.button_imgs[type][state_set]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int active = THEME_INACTIVE; active <= THEME_ACTIVE; active++) {
|
enum ssd_active_state active;
|
||||||
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
zfree_pattern(theme->window[active].titlebar_pattern);
|
zfree_pattern(theme->window[active].titlebar_pattern);
|
||||||
zdrop(&theme->window[active].titlebar_fill);
|
zdrop(&theme->window[active].titlebar_fill);
|
||||||
zdrop(&theme->window[active].corner_top_left_normal);
|
zdrop(&theme->window[active].corner_top_left_normal);
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ void
|
||||||
view_impl_map(struct view *view)
|
view_impl_map(struct view *view)
|
||||||
{
|
{
|
||||||
desktop_focus_view(view, /*raise*/ true);
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
view_update_title(view);
|
|
||||||
view_update_app_id(view);
|
|
||||||
if (!view->been_mapped) {
|
if (!view->been_mapped) {
|
||||||
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
|
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
|
||||||
}
|
}
|
||||||
|
|
@ -36,8 +34,7 @@ view_impl_map(struct view *view)
|
||||||
desktop_update_top_layer_visibility(view->server);
|
desktop_update_top_layer_visibility(view->server);
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "[map] identifier=%s, title=%s",
|
wlr_log(WLR_DEBUG, "[map] identifier=%s, title=%s",
|
||||||
view_get_string_prop(view, "app_id"),
|
view->app_id, view->title);
|
||||||
view_get_string_prop(view, "title"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
48
src/view.c
48
src/view.c
|
|
@ -133,11 +133,11 @@ view_contains_window_type(struct view *view, enum lab_window_type window_type)
|
||||||
bool
|
bool
|
||||||
view_matches_query(struct view *view, struct view_query *query)
|
view_matches_query(struct view *view, struct view_query *query)
|
||||||
{
|
{
|
||||||
if (!query_str_match(query->identifier, view_get_string_prop(view, "app_id"))) {
|
if (!query_str_match(query->identifier, view->app_id)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!query_str_match(query->title, view_get_string_prop(view, "title"))) {
|
if (!query_str_match(query->title, view->title)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2161,7 +2161,8 @@ view_snap_to_edge(struct view *view, enum lab_edge edge,
|
||||||
|
|
||||||
view_set_shade(view, false);
|
view_set_shade(view, false);
|
||||||
|
|
||||||
if (lab_edge_is_cardinal(edge) && view->maximized == VIEW_AXIS_NONE) {
|
if (lab_edge_is_cardinal(edge) && view->maximized == VIEW_AXIS_NONE
|
||||||
|
&& view->tiled != LAB_EDGE_CENTER) {
|
||||||
enum lab_edge invert_edge = lab_edge_invert(edge);
|
enum lab_edge invert_edge = lab_edge_invert(edge);
|
||||||
/* Represents axis of snapping direction */
|
/* Represents axis of snapping direction */
|
||||||
enum lab_edge parallel_mask = edge | invert_edge;
|
enum lab_edge parallel_mask = edge | invert_edge;
|
||||||
|
|
@ -2384,31 +2385,36 @@ view_has_strut_partial(struct view *view)
|
||||||
view->impl->has_strut_partial(view);
|
view->impl->has_strut_partial(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: It is safe to assume that this function never returns NULL */
|
|
||||||
const char *
|
|
||||||
view_get_string_prop(struct view *view, const char *prop)
|
|
||||||
{
|
|
||||||
assert(view);
|
|
||||||
assert(prop);
|
|
||||||
if (view->impl->get_string_prop) {
|
|
||||||
const char *ret = view->impl->get_string_prop(view, prop);
|
|
||||||
return ret ? ret : "";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
view_update_title(struct view *view)
|
view_set_title(struct view *view, const char *title)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
|
if (!title) {
|
||||||
|
title = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(view->title, title)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xstrdup_replace(view->title, title);
|
||||||
|
|
||||||
ssd_update_title(view->ssd);
|
ssd_update_title(view->ssd);
|
||||||
wl_signal_emit_mutable(&view->events.new_title, NULL);
|
wl_signal_emit_mutable(&view->events.new_title, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
view_update_app_id(struct view *view)
|
view_set_app_id(struct view *view, const char *app_id)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
|
if (!app_id) {
|
||||||
|
app_id = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(view->app_id, app_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xstrdup_replace(view->app_id, app_id);
|
||||||
|
|
||||||
wl_signal_emit_mutable(&view->events.new_app_id, NULL);
|
wl_signal_emit_mutable(&view->events.new_app_id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2561,6 +2567,9 @@ view_init(struct view *view)
|
||||||
wl_signal_init(&view->events.activated);
|
wl_signal_init(&view->events.activated);
|
||||||
wl_signal_init(&view->events.set_icon);
|
wl_signal_init(&view->events.set_icon);
|
||||||
wl_signal_init(&view->events.destroy);
|
wl_signal_init(&view->events.destroy);
|
||||||
|
|
||||||
|
view->title = xstrdup("");
|
||||||
|
view->app_id = xstrdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2584,6 +2593,9 @@ view_destroy(struct view *view)
|
||||||
wl_list_remove(&view->set_title.link);
|
wl_list_remove(&view->set_title.link);
|
||||||
wl_list_remove(&view->destroy.link);
|
wl_list_remove(&view->destroy.link);
|
||||||
|
|
||||||
|
zfree(view->title);
|
||||||
|
zfree(view->app_id);
|
||||||
|
|
||||||
if (view->foreign_toplevel) {
|
if (view->foreign_toplevel) {
|
||||||
foreign_toplevel_destroy(view->foreign_toplevel);
|
foreign_toplevel_destroy(view->foreign_toplevel);
|
||||||
view->foreign_toplevel = NULL;
|
view->foreign_toplevel = NULL;
|
||||||
|
|
|
||||||
55
src/xdg.c
55
src/xdg.c
|
|
@ -5,6 +5,7 @@
|
||||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include <wlr/types/wlr_scene.h>
|
||||||
#include <wlr/types/wlr_xdg_activation_v1.h>
|
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_dialog_v1.h>
|
||||||
#include <wlr/types/wlr_xdg_shell.h>
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
#include <wlr/types/wlr_xdg_toplevel_icon_v1.h>
|
#include <wlr/types/wlr_xdg_toplevel_icon_v1.h>
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
@ -216,7 +217,7 @@ handle_commit(struct wl_listener *listener, void *data)
|
||||||
&& extent.height == view->pending.height) {
|
&& extent.height == view->pending.height) {
|
||||||
wlr_log(WLR_DEBUG, "window geometry for client (%s) "
|
wlr_log(WLR_DEBUG, "window geometry for client (%s) "
|
||||||
"appears to be incorrect - ignoring",
|
"appears to be incorrect - ignoring",
|
||||||
view_get_string_prop(view, "app_id"));
|
view->app_id);
|
||||||
size = extent; /* Use surface extent instead */
|
size = extent; /* Use surface extent instead */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -283,9 +284,8 @@ handle_configure_timeout(void *data)
|
||||||
assert(view->pending_configure_serial > 0);
|
assert(view->pending_configure_serial > 0);
|
||||||
assert(view->pending_configure_timeout);
|
assert(view->pending_configure_timeout);
|
||||||
|
|
||||||
const char *app_id = view_get_string_prop(view, "app_id");
|
|
||||||
wlr_log(WLR_INFO, "client (%s) did not respond to configure request "
|
wlr_log(WLR_INFO, "client (%s) did not respond to configure request "
|
||||||
"in %d ms", app_id, CONFIGURE_TIMEOUT_MS);
|
"in %d ms", view->app_id, CONFIGURE_TIMEOUT_MS);
|
||||||
|
|
||||||
wl_event_source_remove(view->pending_configure_timeout);
|
wl_event_source_remove(view->pending_configure_timeout);
|
||||||
view->pending_configure_serial = 0;
|
view->pending_configure_serial = 0;
|
||||||
|
|
@ -492,7 +492,9 @@ static void
|
||||||
handle_set_title(struct wl_listener *listener, void *data)
|
handle_set_title(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct view *view = wl_container_of(listener, view, set_title);
|
struct view *view = wl_container_of(listener, view, set_title);
|
||||||
view_update_title(view);
|
struct wlr_xdg_toplevel *toplevel = xdg_toplevel_from_view(view);
|
||||||
|
|
||||||
|
view_set_title(view, toplevel->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -501,7 +503,9 @@ handle_set_app_id(struct wl_listener *listener, void *data)
|
||||||
struct xdg_toplevel_view *xdg_toplevel_view =
|
struct xdg_toplevel_view *xdg_toplevel_view =
|
||||||
wl_container_of(listener, xdg_toplevel_view, set_app_id);
|
wl_container_of(listener, xdg_toplevel_view, set_app_id);
|
||||||
struct view *view = &xdg_toplevel_view->base;
|
struct view *view = &xdg_toplevel_view->base;
|
||||||
view_update_app_id(view);
|
struct wlr_xdg_toplevel *toplevel = xdg_toplevel_from_view(view);
|
||||||
|
|
||||||
|
view_set_app_id(view, toplevel->app_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -614,6 +618,18 @@ xdg_toplevel_view_append_children(struct view *self, struct wl_array *children)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
xdg_toplevel_view_is_modal_dialog(struct view *view)
|
||||||
|
{
|
||||||
|
struct wlr_xdg_toplevel *toplevel = xdg_toplevel_from_view(view);
|
||||||
|
struct wlr_xdg_dialog_v1 *dialog =
|
||||||
|
wlr_xdg_dialog_v1_try_from_wlr_xdg_toplevel(toplevel);
|
||||||
|
if (!dialog) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return dialog->modal;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xdg_toplevel_view_set_activated(struct view *view, bool activated)
|
xdg_toplevel_view_set_activated(struct view *view, bool activated)
|
||||||
{
|
{
|
||||||
|
|
@ -740,31 +756,6 @@ set_initial_position(struct view *view)
|
||||||
view_place_by_policy(view, /* allow_cursor */ true, rc.placement_policy);
|
view_place_by_policy(view, /* allow_cursor */ true, rc.placement_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
xdg_toplevel_view_get_string_prop(struct view *view, const char *prop)
|
|
||||||
{
|
|
||||||
struct xdg_toplevel_view *xdg_view = xdg_toplevel_view_from_view(view);
|
|
||||||
struct wlr_xdg_toplevel *xdg_toplevel = xdg_view->xdg_surface
|
|
||||||
? xdg_view->xdg_surface->toplevel
|
|
||||||
: NULL;
|
|
||||||
if (!xdg_toplevel) {
|
|
||||||
/*
|
|
||||||
* This may happen due to a matchOnce rule when
|
|
||||||
* a view is destroyed while A-Tab is open. See
|
|
||||||
* https://github.com/labwc/labwc/issues/1082#issuecomment-1716137180
|
|
||||||
*/
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(prop, "title")) {
|
|
||||||
return xdg_toplevel->title ? xdg_toplevel->title : "";
|
|
||||||
}
|
|
||||||
if (!strcmp(prop, "app_id")) {
|
|
||||||
return xdg_toplevel->app_id ? xdg_toplevel->app_id : "";
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_foreign_toplevel(struct view *view)
|
init_foreign_toplevel(struct view *view)
|
||||||
{
|
{
|
||||||
|
|
@ -884,7 +875,6 @@ xdg_view_get_pid(struct view *view)
|
||||||
static const struct view_impl xdg_toplevel_view_impl = {
|
static const struct view_impl xdg_toplevel_view_impl = {
|
||||||
.configure = xdg_toplevel_view_configure,
|
.configure = xdg_toplevel_view_configure,
|
||||||
.close = xdg_toplevel_view_close,
|
.close = xdg_toplevel_view_close,
|
||||||
.get_string_prop = xdg_toplevel_view_get_string_prop,
|
|
||||||
.map = xdg_toplevel_view_map,
|
.map = xdg_toplevel_view_map,
|
||||||
.set_activated = xdg_toplevel_view_set_activated,
|
.set_activated = xdg_toplevel_view_set_activated,
|
||||||
.set_fullscreen = xdg_toplevel_view_set_fullscreen,
|
.set_fullscreen = xdg_toplevel_view_set_fullscreen,
|
||||||
|
|
@ -894,6 +884,7 @@ static const struct view_impl xdg_toplevel_view_impl = {
|
||||||
.minimize = xdg_toplevel_view_minimize,
|
.minimize = xdg_toplevel_view_minimize,
|
||||||
.get_root = xdg_toplevel_view_get_root,
|
.get_root = xdg_toplevel_view_get_root,
|
||||||
.append_children = xdg_toplevel_view_append_children,
|
.append_children = xdg_toplevel_view_append_children,
|
||||||
|
.is_modal_dialog = xdg_toplevel_view_is_modal_dialog,
|
||||||
.get_size_hints = xdg_toplevel_view_get_size_hints,
|
.get_size_hints = xdg_toplevel_view_get_size_hints,
|
||||||
.contains_window_type = xdg_toplevel_view_contains_window_type,
|
.contains_window_type = xdg_toplevel_view_contains_window_type,
|
||||||
.get_pid = xdg_view_get_pid,
|
.get_pid = xdg_view_get_pid,
|
||||||
|
|
@ -1139,6 +1130,8 @@ xdg_shell_init(struct server *server)
|
||||||
server->xdg_toplevel_icon_set_icon.notify = handle_xdg_toplevel_icon_set_icon;
|
server->xdg_toplevel_icon_set_icon.notify = handle_xdg_toplevel_icon_set_icon;
|
||||||
wl_signal_add(&server->xdg_toplevel_icon_manager->events.set_icon,
|
wl_signal_add(&server->xdg_toplevel_icon_manager->events.set_icon,
|
||||||
&server->xdg_toplevel_icon_set_icon);
|
&server->xdg_toplevel_icon_set_icon);
|
||||||
|
|
||||||
|
wlr_xdg_wm_dialog_v1_create(server->wl_display, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -498,7 +498,8 @@ static void
|
||||||
handle_set_title(struct wl_listener *listener, void *data)
|
handle_set_title(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct view *view = wl_container_of(listener, view, set_title);
|
struct view *view = wl_container_of(listener, view, set_title);
|
||||||
view_update_title(view);
|
struct xwayland_view *xwayland_view = xwayland_view_from_view(view);
|
||||||
|
view_set_title(view, xwayland_view->xwayland_surface->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -507,35 +508,7 @@ handle_set_class(struct wl_listener *listener, void *data)
|
||||||
struct xwayland_view *xwayland_view =
|
struct xwayland_view *xwayland_view =
|
||||||
wl_container_of(listener, xwayland_view, set_class);
|
wl_container_of(listener, xwayland_view, set_class);
|
||||||
struct view *view = &xwayland_view->base;
|
struct view *view = &xwayland_view->base;
|
||||||
view_update_app_id(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xwayland_view_close(struct view *view)
|
|
||||||
{
|
|
||||||
wlr_xwayland_surface_close(xwayland_surface_from_view(view));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
xwayland_view_get_string_prop(struct view *view, const char *prop)
|
|
||||||
{
|
|
||||||
struct xwayland_view *xwayland_view = xwayland_view_from_view(view);
|
|
||||||
struct wlr_xwayland_surface *xwayland_surface = xwayland_view->xwayland_surface;
|
|
||||||
if (!xwayland_surface) {
|
|
||||||
/*
|
|
||||||
* This may happen due to a matchOnce rule when
|
|
||||||
* a view is destroyed while A-Tab is open. See
|
|
||||||
* https://github.com/labwc/labwc/issues/1082#issuecomment-1716137180
|
|
||||||
*/
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(prop, "title")) {
|
|
||||||
return xwayland_surface->title ? xwayland_surface->title : "";
|
|
||||||
}
|
|
||||||
if (!strcmp(prop, "class")) {
|
|
||||||
return xwayland_surface->class ? xwayland_surface->class : "";
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Use the WM_CLASS 'instance' (1st string) for the app_id. Per
|
* Use the WM_CLASS 'instance' (1st string) for the app_id. Per
|
||||||
* ICCCM, this is usually "the trailing part of the name used to
|
* ICCCM, this is usually "the trailing part of the name used to
|
||||||
|
|
@ -545,10 +518,13 @@ xwayland_view_get_string_prop(struct view *view, const char *prop)
|
||||||
* 'instance' except for being capitalized. We want lowercase
|
* 'instance' except for being capitalized. We want lowercase
|
||||||
* here since we use the app_id for icon lookups.
|
* here since we use the app_id for icon lookups.
|
||||||
*/
|
*/
|
||||||
if (!strcmp(prop, "app_id")) {
|
view_set_app_id(view, xwayland_view->xwayland_surface->instance);
|
||||||
return xwayland_surface->instance ? xwayland_surface->instance : "";
|
}
|
||||||
}
|
|
||||||
return "";
|
static void
|
||||||
|
xwayland_view_close(struct view *view)
|
||||||
|
{
|
||||||
|
wlr_xwayland_surface_close(xwayland_surface_from_view(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1050,7 +1026,6 @@ xwayland_view_get_pid(struct view *view)
|
||||||
static const struct view_impl xwayland_view_impl = {
|
static const struct view_impl xwayland_view_impl = {
|
||||||
.configure = xwayland_view_configure,
|
.configure = xwayland_view_configure,
|
||||||
.close = xwayland_view_close,
|
.close = xwayland_view_close,
|
||||||
.get_string_prop = xwayland_view_get_string_prop,
|
|
||||||
.map = xwayland_view_map,
|
.map = xwayland_view_map,
|
||||||
.set_activated = xwayland_view_set_activated,
|
.set_activated = xwayland_view_set_activated,
|
||||||
.set_fullscreen = xwayland_view_set_fullscreen,
|
.set_fullscreen = xwayland_view_set_fullscreen,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[wrap-git]
|
[wrap-git]
|
||||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||||
revision = 0.19
|
revision = master
|
||||||
|
|
||||||
[provide]
|
[provide]
|
||||||
dependency_names = wlroots-0.19
|
dependency_names = wlroots-0.20
|
||||||
wlroots-0.19=wlroots
|
wlroots-0.20=wlroots
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue