diff --git a/data/default_config b/data/default_config
index 15667e5..711d884 100644
--- a/data/default_config
+++ b/data/default_config
@@ -1,4 +1,5 @@
active-at-startup
+# emulate-im-popups
global-bindings {
Ctrl+Shift+Backspace toggle
diff --git a/doc/anthywl.5.scd b/doc/anthywl.5.scd
index f6aba50..c0aa3e3 100644
--- a/doc/anthywl.5.scd
+++ b/doc/anthywl.5.scd
@@ -38,6 +38,12 @@ See https://git.sr.ht/~emersion/scfg for details.
}
```
+ *emulate-im-popups*:
+
+ When enabled, anthywl will mirror the contents of input method popups to a
+ layer-shell (overlay) window. This is useful for compositors that do not
+ yet support input method popups.
+
# ACTIONS
*enable*:
diff --git a/include/anthywl.h b/include/anthywl.h
index 6f34f12..7fe9d74 100644
--- a/include/anthywl.h
+++ b/include/anthywl.h
@@ -9,6 +9,7 @@
#include "input-method-unstable-v2-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
#include "virtual-keyboard-unstable-v1-client-protocol.h"
+#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "actions.h"
#include "buffer.h"
@@ -48,6 +49,7 @@ struct anthywl_state {
struct wl_registry *wl_registry;
struct wl_compositor *wl_compositor;
struct wl_shm *wl_shm;
+ struct zwlr_layer_shell_v1 *zwlr_layer_shell_v1;
struct zwp_input_method_manager_v2 *zwp_input_method_manager_v2;
struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1;
struct wl_cursor_theme *wl_cursor_theme;
@@ -144,8 +146,10 @@ struct anthywl_seat {
anthy_context_t anthy_context;
// popup
- struct wl_surface *wl_surface;
+ struct wl_surface *popup_wl_surface;
+ struct wl_surface *layer_wl_surface;
struct zwp_input_popup_surface_v2 *zwp_input_popup_surface_v2;
+ struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1;
};
struct anthywl_binding {
@@ -164,6 +168,12 @@ void zwp_input_popup_surface_v2_text_input_rectangle(void *data,
struct zwp_input_popup_surface_v2 *zwp_input_popup_surface_v2,
int32_t x, int32_t y, int32_t width, int32_t height);
+void zwlr_layer_surface_v1_configure(void *data,
+ struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1, uint32_t serial,
+ uint32_t width, uint32_t height);
+void zwlr_layer_surface_v1_closed(void *data,
+ struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1);
+
void wl_surface_enter(void *data, struct wl_surface *wl_surface,
struct wl_output *wl_output);
void wl_surface_leave(void *data, struct wl_surface *wl_surface,
@@ -277,6 +287,8 @@ void anthywl_state_finish(struct anthywl_state *state);
extern struct zwp_input_popup_surface_v2_listener const
zwp_input_popup_surface_v2_listener;
+extern struct zwlr_layer_surface_v1_listener const
+ zwlr_layer_surface_v1_listener;
extern struct wl_seat_listener const wl_seat_listener;
extern struct wl_surface_listener const wl_surface_listener;
extern struct zwp_input_method_keyboard_grab_v2_listener const
diff --git a/include/config.h b/include/config.h
index fce05e5..8e0e720 100644
--- a/include/config.h
+++ b/include/config.h
@@ -5,6 +5,7 @@
struct anthywl_config {
bool active_at_startup;
+ bool emulate_im_popups;
struct wl_array global_bindings;
struct wl_array composing_bindings;
struct wl_array selecting_bindings;
diff --git a/protocol/meson.build b/protocol/meson.build
index 1146220..46866bf 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -7,9 +7,11 @@ wayland_scanner_bin = find_program(
)
protocols = {
+ 'xdg-shell': wayland_protocols_dir / 'stable/xdg-shell/xdg-shell.xml',
'text-input-v3': wayland_protocols_dir / 'unstable/text-input/text-input-unstable-v3.xml',
'zwp-input-method-unstable-v2': 'input-method-unstable-v2.xml',
'zwp-virtual-keyboard-unstable-v1': 'virtual-keyboard-unstable-v1.xml',
+ 'wlr-layer-shell-unstable-v1': 'wlr-layer-shell-unstable-v1.xml',
}
protocols_src = []
diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml
new file mode 100644
index 0000000..e9f27e4
--- /dev/null
+++ b/protocol/wlr-layer-shell-unstable-v1.xml
@@ -0,0 +1,407 @@
+
+
+
+ Copyright © 2017 Drew DeVault
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+
+
+
+
+ Clients can use this interface to assign the surface_layer role to
+ wl_surfaces. Such surfaces are assigned to a "layer" of the output and
+ rendered with a defined z-depth respective to each other. They may also be
+ anchored to the edges and corners of a screen and specify input handling
+ semantics. This interface should be suitable for the implementation of
+ many desktop shell components, and a broad number of other applications
+ that interact with the desktop.
+
+
+
+
+ Create a layer surface for an existing surface. This assigns the role of
+ layer_surface, or raises a protocol error if another role is already
+ assigned.
+
+ Creating a layer surface from a wl_surface which has a buffer attached
+ or committed is a client error, and any attempts by a client to attach
+ or manipulate a buffer prior to the first layer_surface.configure call
+ must also be treated as errors.
+
+ After creating a layer_surface object and setting it up, the client
+ must perform an initial commit without any buffer attached.
+ The compositor will reply with a layer_surface.configure event.
+ The client must acknowledge it and is then allowed to attach a buffer
+ to map the surface.
+
+ You may pass NULL for output to allow the compositor to decide which
+ output to use. Generally this will be the one that the user most
+ recently interacted with.
+
+ Clients can specify a namespace that defines the purpose of the layer
+ surface.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ These values indicate which layers a surface can be rendered in. They
+ are ordered by z depth, bottom-most first. Traditional shell surfaces
+ will typically be rendered between the bottom and top layers.
+ Fullscreen shell surfaces are typically rendered at the top layer.
+ Multiple surfaces can share a single layer, and ordering within a
+ single layer is undefined.
+
+
+
+
+
+
+
+
+
+
+
+
+ This request indicates that the client will not use the layer_shell
+ object any more. Objects that have been created through this instance
+ are not affected.
+
+
+
+
+
+
+ An interface that may be implemented by a wl_surface, for surfaces that
+ are designed to be rendered as a layer of a stacked desktop-like
+ environment.
+
+ Layer surface state (layer, size, anchor, exclusive zone,
+ margin, interactivity) is double-buffered, and will be applied at the
+ time wl_surface.commit of the corresponding wl_surface is called.
+
+ Attaching a null buffer to a layer surface unmaps it.
+
+ Unmapping a layer_surface means that the surface cannot be shown by the
+ compositor until it is explicitly mapped again. The layer_surface
+ returns to the state it had right after layer_shell.get_layer_surface.
+ The client can re-map the surface by performing a commit without any
+ buffer attached, waiting for a configure event and handling it as usual.
+
+
+
+
+ Sets the size of the surface in surface-local coordinates. The
+ compositor will display the surface centered with respect to its
+ anchors.
+
+ If you pass 0 for either value, the compositor will assign it and
+ inform you of the assignment in the configure event. You must set your
+ anchor to opposite edges in the dimensions you omit; not doing so is a
+ protocol error. Both values are 0 by default.
+
+ Size is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+
+ Requests that the compositor anchor the surface to the specified edges
+ and corners. If two orthogonal edges are specified (e.g. 'top' and
+ 'left'), then the anchor point will be the intersection of the edges
+ (e.g. the top left corner of the output); otherwise the anchor point
+ will be centered on that edge, or in the center if none is specified.
+
+ Anchor is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+ Requests that the compositor avoids occluding an area with other
+ surfaces. The compositor's use of this information is
+ implementation-dependent - do not assume that this region will not
+ actually be occluded.
+
+ A positive value is only meaningful if the surface is anchored to one
+ edge or an edge and both perpendicular edges. If the surface is not
+ anchored, anchored to only two perpendicular edges (a corner), anchored
+ to only two parallel edges or anchored to all edges, a positive value
+ will be treated the same as zero.
+
+ A positive zone is the distance from the edge in surface-local
+ coordinates to consider exclusive.
+
+ Surfaces that do not wish to have an exclusive zone may instead specify
+ how they should interact with surfaces that do. If set to zero, the
+ surface indicates that it would like to be moved to avoid occluding
+ surfaces with a positive exclusive zone. If set to -1, the surface
+ indicates that it would not like to be moved to accommodate for other
+ surfaces, and the compositor should extend it all the way to the edges
+ it is anchored to.
+
+ For example, a panel might set its exclusive zone to 10, so that
+ maximized shell surfaces are not shown on top of it. A notification
+ might set its exclusive zone to 0, so that it is moved to avoid
+ occluding the panel, but shell surfaces are shown underneath it. A
+ wallpaper or lock screen might set their exclusive zone to -1, so that
+ they stretch below or over the panel.
+
+ The default value is 0.
+
+ Exclusive zone is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+ Requests that the surface be placed some distance away from the anchor
+ point on the output, in surface-local coordinates. Setting this value
+ for edges you are not anchored to has no effect.
+
+ The exclusive zone includes the margin.
+
+ Margin is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+
+
+
+ Types of keyboard interaction possible for layer shell surfaces. The
+ rationale for this is twofold: (1) some applications are not interested
+ in keyboard events and not allowing them to be focused can improve the
+ desktop experience; (2) some applications will want to take exclusive
+ keyboard focus.
+
+
+
+
+ This value indicates that this surface is not interested in keyboard
+ events and the compositor should never assign it the keyboard focus.
+
+ This is the default value, set for newly created layer shell surfaces.
+
+ This is useful for e.g. desktop widgets that display information or
+ only have interaction with non-keyboard input devices.
+
+
+
+
+ Request exclusive keyboard focus if this surface is above the shell surface layer.
+
+ For the top and overlay layers, the seat will always give
+ exclusive keyboard focus to the top-most layer which has keyboard
+ interactivity set to exclusive. If this layer contains multiple
+ surfaces with keyboard interactivity set to exclusive, the compositor
+ determines the one receiving keyboard events in an implementation-
+ defined manner. In this case, no guarantee is made when this surface
+ will receive keyboard focus (if ever).
+
+ For the bottom and background layers, the compositor is allowed to use
+ normal focus semantics.
+
+ This setting is mainly intended for applications that need to ensure
+ they receive all keyboard events, such as a lock screen or a password
+ prompt.
+
+
+
+
+ This requests the compositor to allow this surface to be focused and
+ unfocused by the user in an implementation-defined manner. The user
+ should be able to unfocus this surface even regardless of the layer
+ it is on.
+
+ Typically, the compositor will want to use its normal mechanism to
+ manage keyboard focus between layer shell surfaces with this setting
+ and regular toplevels on the desktop layer (e.g. click to focus).
+ Nevertheless, it is possible for a compositor to require a special
+ interaction to focus or unfocus layer shell surfaces (e.g. requiring
+ a click even if focus follows the mouse normally, or providing a
+ keybinding to switch focus between layers).
+
+ This setting is mainly intended for desktop shell components (e.g.
+ panels) that allow keyboard interaction. Using this option can allow
+ implementing a desktop shell that can be fully usable without the
+ mouse.
+
+
+
+
+
+
+ Set how keyboard events are delivered to this surface. By default,
+ layer shell surfaces do not receive keyboard events; this request can
+ be used to change this.
+
+ This setting is inherited by child surfaces set by the get_popup
+ request.
+
+ Layer surfaces receive pointer, touch, and tablet events normally. If
+ you do not want to receive them, set the input region on your surface
+ to an empty region.
+
+ Keyboard interactivity is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+ This assigns an xdg_popup's parent to this layer_surface. This popup
+ should have been created via xdg_surface::get_popup with the parent set
+ to NULL, and this request must be invoked before committing the popup's
+ initial state.
+
+ See the documentation of xdg_popup for more details about what an
+ xdg_popup is and how it is used.
+
+
+
+
+
+
+ When a configure event is received, if a client commits the
+ surface in response to the configure event, then the client
+ must make an ack_configure request sometime before the commit
+ request, passing along the serial of the configure event.
+
+ If the client receives multiple configure events before it
+ can respond to one, it only has to ack the last configure event.
+
+ A client is not required to commit immediately after sending
+ an ack_configure request - it may even ack_configure several times
+ before its next surface commit.
+
+ A client may send multiple ack_configure requests before committing, but
+ only the last request sent before a commit indicates which configure
+ event the client really is responding to.
+
+
+
+
+
+
+ This request destroys the layer surface.
+
+
+
+
+
+ The configure event asks the client to resize its surface.
+
+ Clients should arrange their surface for the new states, and then send
+ an ack_configure request with the serial sent in this configure event at
+ some point before committing the new surface.
+
+ The client is free to dismiss all but the last configure event it
+ received.
+
+ The width and height arguments specify the size of the window in
+ surface-local coordinates.
+
+ The size is a hint, in the sense that the client is free to ignore it if
+ it doesn't resize, pick a smaller size (to satisfy aspect ratio or
+ resize in steps of NxM pixels). If the client picks a smaller size and
+ is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
+ surface will be centered on this axis.
+
+ If the width or height arguments are zero, it means the client should
+ decide its own window dimension.
+
+
+
+
+
+
+
+
+ The closed event is sent by the compositor when the surface will no
+ longer be shown. The output may have been destroyed or the user may
+ have asked for it to be removed. Further changes to the surface will be
+ ignored. The client should destroy the resource after receiving this
+ event, and create a new surface if they so choose.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Change the layer that the surface is rendered on.
+
+ Layer is double-buffered, see wl_surface.commit.
+
+
+
+
+
+
+
+
+ Requests an edge for the exclusive zone to apply. The exclusive
+ edge will be automatically deduced from anchor points when possible,
+ but when the surface is anchored to a corner, it will be necessary
+ to set it explicitly to disambiguate, as it is not possible to deduce
+ which one of the two corner edges should be used.
+
+ The edge must be one the surface is anchored to, otherwise the
+ invalid_exclusive_edge protocol error will be raised.
+
+
+
+
+
diff --git a/src/anthywl.c b/src/anthywl.c
index 0262ce3..b33089b 100644
--- a/src/anthywl.c
+++ b/src/anthywl.c
@@ -30,6 +30,7 @@
#include "buffer.h"
#include "graphics_buffer.h"
#include "keymap.h"
+#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#ifdef ANTHYWL_IPC_SUPPORT
#include
@@ -58,6 +59,19 @@ void zwp_input_popup_surface_v2_text_input_rectangle(void *data,
{
}
+void zwlr_layer_surface_v1_configure(void *data,
+ struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1, uint32_t serial,
+ uint32_t width, uint32_t height)
+{
+ zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial);
+ anthywl_seat_draw_popup(data);
+}
+
+void zwlr_layer_surface_v1_closed(void *data,
+ struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1)
+{
+}
+
#define BORDER (1.0)
#define PADDING (5.0)
@@ -260,15 +274,43 @@ void anthywl_seat_draw_popup(struct anthywl_seat *seat) {
}
if (buffer) {
- wl_surface_attach(seat->wl_surface, buffer->wl_buffer, 0, 0);
- wl_surface_damage_buffer(seat->wl_surface, 0, 0,
+ wl_surface_attach(seat->popup_wl_surface, buffer->wl_buffer, 0, 0);
+ wl_surface_damage_buffer(seat->popup_wl_surface, 0, 0,
buffer->width, buffer->height);
- wl_surface_set_buffer_scale(seat->wl_surface, scale);
+ wl_surface_set_buffer_scale(seat->popup_wl_surface, scale);
+
+ if (seat->state->config.emulate_im_popups) {
+ assert(seat->zwlr_layer_surface_v1);
+ zwlr_layer_surface_v1_set_anchor(seat->zwlr_layer_surface_v1,
+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
+ | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
+ zwlr_layer_surface_v1_set_size(
+ seat->zwlr_layer_surface_v1, buffer->width, buffer->height);
+ zwlr_layer_surface_v1_set_margin(seat->zwlr_layer_surface_v1,
+ 5 * scale, 5 * scale, 5 * scale, 5 * scale);
+ wl_surface_attach(seat->layer_wl_surface, buffer->wl_buffer, 0, 0);
+ wl_surface_damage_buffer(seat->layer_wl_surface, 0, 0,
+ buffer->width, buffer->height);
+ wl_surface_set_buffer_scale(seat->layer_wl_surface, scale);
+ }
} else {
- wl_surface_attach(seat->wl_surface, NULL, 0, 0);
+ wl_surface_attach(seat->popup_wl_surface, NULL, 0, 0);
+ if (seat->state->config.emulate_im_popups) {
+ zwlr_layer_surface_v1_set_anchor(seat->zwlr_layer_surface_v1,
+ ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
+ | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
+ | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
+ | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
+ zwlr_layer_surface_v1_set_size(
+ seat->zwlr_layer_surface_v1, 0, 0);
+ wl_surface_attach(seat->layer_wl_surface, NULL, 0, 0);
+ }
}
- wl_surface_commit(seat->wl_surface);
+ wl_surface_commit(seat->popup_wl_surface);
+ if (seat->state->config.emulate_im_popups) {
+ wl_surface_commit(seat->layer_wl_surface);
+ }
}
void anthywl_seat_init(struct anthywl_seat *seat,
@@ -287,6 +329,7 @@ void anthywl_seat_init(struct anthywl_seat *seat,
anthy_context_set_encoding(seat->anthy_context, ANTHY_UTF8_ENCODING);
seat->repeat_timer.callback = anthywl_seat_repeat_timer_callback;
seat->is_composing = state->config.active_at_startup;
+ seat->is_composing_popup_visible = true;
}
void wl_surface_enter(void *data, struct wl_surface *wl_surface,
@@ -347,14 +390,23 @@ void anthywl_seat_init_protocols(struct anthywl_seat *seat) {
zwp_input_method_keyboard_grab_v2_add_listener(
seat->zwp_input_method_keyboard_grab_v2,
&zwp_input_method_keyboard_grab_v2_listener, seat);
- seat->wl_surface = wl_compositor_create_surface(seat->state->wl_compositor);
- wl_surface_add_listener(seat->wl_surface, &wl_surface_listener, seat);
- anthywl_seat_draw_popup(seat);
+ seat->popup_wl_surface = wl_compositor_create_surface(seat->state->wl_compositor);
+ wl_surface_add_listener(seat->popup_wl_surface, &wl_surface_listener, seat);
seat->zwp_input_popup_surface_v2 =
zwp_input_method_v2_get_input_popup_surface(
- seat->zwp_input_method_v2, seat->wl_surface);
+ seat->zwp_input_method_v2, seat->popup_wl_surface);
zwp_input_popup_surface_v2_add_listener(seat->zwp_input_popup_surface_v2,
&zwp_input_popup_surface_v2_listener, seat);
+ if (seat->state->config.emulate_im_popups) {
+ seat->layer_wl_surface = wl_compositor_create_surface(seat->state->wl_compositor);
+ wl_surface_add_listener(seat->layer_wl_surface, &wl_surface_listener, seat);
+ seat->zwlr_layer_surface_v1 = zwlr_layer_shell_v1_get_layer_surface(
+ seat->state->zwlr_layer_shell_v1, seat->layer_wl_surface, NULL,
+ ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "anthywl");
+ zwlr_layer_surface_v1_add_listener(seat->zwlr_layer_surface_v1,
+ &zwlr_layer_surface_v1_listener, seat);
+ }
+ anthywl_seat_draw_popup(seat);
seat->wl_surface_cursor =
wl_compositor_create_surface(seat->state->wl_compositor);
wl_surface_add_listener(
@@ -374,8 +426,12 @@ void anthywl_seat_destroy(struct anthywl_seat *seat) {
xkb_context_unref(seat->xkb_context);
free(seat->xkb_keymap_string);
if (seat->are_protocols_initted) {
+ if (seat->state->config.emulate_im_popups) {
+ zwlr_layer_surface_v1_destroy(seat->zwlr_layer_surface_v1);
+ wl_surface_destroy(seat->layer_wl_surface);
+ }
zwp_input_popup_surface_v2_destroy(seat->zwp_input_popup_surface_v2);
- wl_surface_destroy(seat->wl_surface);
+ wl_surface_destroy(seat->popup_wl_surface);
zwp_virtual_keyboard_v1_destroy(seat->zwp_virtual_keyboard_v1_backup_input);
zwp_virtual_keyboard_v1_destroy(seat->zwp_virtual_keyboard_v1_passthrough);
zwp_input_method_keyboard_grab_v2_destroy(
@@ -859,6 +915,7 @@ void zwp_input_method_v2_deactivate(
{
struct anthywl_seat *seat = data;
seat->pending_activate = false;
+ seat->is_composing_popup_visible = true;
}
void zwp_input_method_v2_surrounding_text(
@@ -903,10 +960,10 @@ void zwp_input_method_v2_done(
seat->text_change_cause = seat->pending_text_change_cause;
seat->content_type_hint = seat->pending_content_type_hint;
seat->content_type_purpose = seat->pending_content_type_purpose;
+ seat->is_composing_popup_visible = !seat->active;
seat->done_events_received++;
if (!was_active && seat->active) {
seat->is_selecting = false;
- seat->is_composing_popup_visible = false;
anthywl_buffer_clear(&seat->buffer);
anthywl_seat_draw_popup(seat);
}
@@ -1084,6 +1141,7 @@ struct anthywl_global {
struct wl_interface const *interface;
int version;
bool is_singleton;
+ bool is_optional;
union {
ptrdiff_t offset;
void (*callback)(struct anthywl_state *state, void *data);
@@ -1125,6 +1183,14 @@ static struct anthywl_global const globals[] = {
.is_singleton = true,
.offset = offsetof(struct anthywl_state, wl_shm),
},
+ {
+ .name = "zwlr_layer_shell_v1",
+ .interface = &zwlr_layer_shell_v1_interface,
+ .version = 1,
+ .is_singleton = true,
+ .is_optional = true,
+ .offset = offsetof(struct anthywl_state, zwlr_layer_shell_v1),
+ },
{
.name = "zwp_input_method_manager_v2",
.interface = &zwp_input_method_manager_v2_interface,
@@ -1218,7 +1284,7 @@ bool anthywl_state_init(struct anthywl_state *state) {
continue;
struct wl_proxy **location =
(struct wl_proxy **)((uintptr_t)state + global->offset);
- if (*location == NULL) {
+ if (*location == NULL && !global->is_optional) {
fprintf(
stderr, "required interface unsupported by compositor: %s\n",
global->name);
@@ -1226,6 +1292,11 @@ bool anthywl_state_init(struct anthywl_state *state) {
}
}
+ if (state->config.emulate_im_popups && state->zwlr_layer_shell_v1 == NULL) {
+ fprintf(stderr, "warning: input method popup emulation requested "
+ "but layer-shell-v1 unsupported by compositor\n");
+ }
+
anthywl_reload_cursor_theme(state);
struct anthywl_seat *seat;
@@ -1383,6 +1454,11 @@ struct zwp_input_popup_surface_v2_listener const
.text_input_rectangle = zwp_input_popup_surface_v2_text_input_rectangle,
};
+struct zwlr_layer_surface_v1_listener const zwlr_layer_surface_v1_listener = {
+ .configure = zwlr_layer_surface_v1_configure,
+ .closed = zwlr_layer_surface_v1_closed,
+};
+
struct wl_seat_listener const wl_seat_listener = {
.capabilities = wl_seat_capabilities,
.name = wl_seat_name,
diff --git a/src/config.c b/src/config.c
index 400dc34..5df2d8c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -74,6 +74,13 @@ static void anthywl_config_load_root(struct anthywl_config *config,
directive->lineno);
else
config->active_at_startup = true;
+ } else if (strcmp(directive->name, "emulate-im-popups") == 0) {
+ if (directive->params_len != 0)
+ fprintf(stderr,
+ "line %d: too many arguments to emulate-im-popups\n",
+ directive->lineno);
+ else
+ config->emulate_im_popups = true;
} else if (strcmp(directive->name, "global-bindings") == 0) {
anthywl_config_load_bindings(
config, &directive->children, &config->global_bindings);