diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index e760609..c59f063 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -339,6 +339,7 @@ MwInline int wayland_load_funcs() { #include "Wayland/pointer-constraints-client-protocol.h" #include "Wayland/relative-pointer-client-protocol.h" #include "Wayland/xdg-toplevel-icon-client-protocol.h" +#include "Wayland/wlr-layer-shell-client-protocol.h" #endif typedef struct wayland_protocol { @@ -387,6 +388,10 @@ struct _MwLLWaylandPopup { MwLL topmost_parent; }; +struct _MwLLWaylandLayerSurface { + struct zwlr_layer_surface_v1* surface; +}; + /* Shared set of anything needed for a shm buffer. */ struct _MwLLWaylandShmBuffer { struct wl_shm* shm; @@ -410,6 +415,7 @@ enum _MwLLWaylandType { MwLL_WAYLAND_TOPLEVEL, MwLL_WAYLAND_SUBLEVEL, MwLL_WAYLAND_POPUP, + MwLL_WAYLAND_LAYER_SURFACE, }; typedef struct wl_clipboard_device_context { @@ -436,6 +442,8 @@ struct _MwLLWayland { struct _MwLLWaylandSublevel* sublevel; /* Pointer for data that's only loaded if the widget is a popup */ struct _MwLLWaylandPopup* popup; + /* Pointer for data that's only loaded if the widget is a layer surface */ + struct _MwLLWaylandLayerSurface* layer_surface; }; enum _MwLLWaylandType type; diff --git a/pl/rules.pl b/pl/rules.pl index 52f3c2a..2c8ea1b 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -65,6 +65,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1"); scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1"); + scan_wayland_protocol_from_file("wlr-layer-shell", "wlr-layer-shell-unstable-v1.xml"); $gl_libs = "-lGL -lGLU"; } diff --git a/pl/utils.pl b/pl/utils.pl index a86cbbe..23e16f0 100644 --- a/pl/utils.pl +++ b/pl/utils.pl @@ -125,6 +125,38 @@ sub scan_wayland_protocol { } } + +sub scan_wayland_protocol_from_file { + my $proto = $_[0]; + my $file = $_[1]; + my $proto_c = "src/backend/wayland/wayland-${proto}-protocol.c"; + + if ( + system( +"wayland-scanner private-code ./resource/wayland/${file} ${proto_c}" + ) != 0 + ) + { + print( +"^ Error on getting private code for ./resource/wayland/${file}\n" + ); + } + else { + new_object($proto_c); + } + if ( + system( +"wayland-scanner client-header ./resource/wayland/${file} include/Mw/LowLevel/Wayland/${proto}-client-protocol.h" + ) + ) + { + print( +"^ Error on getting client header for ./resource/wayland/${file}\n" + ); + } +} + + our %params = (); sub param_set { diff --git a/resource/wayland/wlr-layer-shell-unstable-v1.xml b/resource/wayland/wlr-layer-shell-unstable-v1.xml new file mode 100644 index 0000000..f9ee0ff --- /dev/null +++ b/resource/wayland/wlr-layer-shell-unstable-v1.xml @@ -0,0 +1,451 @@ + + + + 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. + + + + + diff --git a/src/backend/wayland/interfaces.c b/src/backend/wayland/interfaces.c index 2de4e67..0d9f6d6 100644 --- a/src/backend/wayland/interfaces.c +++ b/src/backend/wayland/interfaces.c @@ -655,7 +655,7 @@ static void keyboard_keymap(void* data, MwLL self = data; (void)wl_keyboard; - if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL) { + if(self->wayland.type == MwLL_WAYLAND_TOPLEVEL || self->wayland.type == MwLL_WAYLAND_LAYER_SURFACE) { assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1); char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); @@ -1133,6 +1133,21 @@ static void xdg_toplevel_icon_manager_v1_interface_destroy(struct _MwLLWayland* free(data->listener); } +static wayland_protocol_t* zwlr_layer_shell_v1_setup(MwU32 name, struct _MwLLWayland* wayland, wayland_protocol_t* data) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + + proto->context = wl_registry_bind(wayland->registry, name, &zwlr_layer_shell_v1_interface, 1); + proto->listener = NULL; + + return proto; +} + +static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) { + (void)wayland; + + // free(data); +} + /* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { /* Convience macro for adding the interface functions to the setup map */ @@ -1161,12 +1176,16 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) { WL_INTERFACE(zwp_pointer_constraints_v1); WL_INTERFACE(zwp_relative_pointer_manager_v1); WL_INTERFACE(xdg_wm_base); + WL_INTERFACE(zwlr_layer_shell_v1); /* Only used for layer surface, but we use it always if it's turned into a tool window */ if(wayland->type == MwLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(wp_viewporter); WL_INTERFACE(zxdg_decoration_manager_v1); WL_INTERFACE(xdg_toplevel_icon_manager_v1); WL_INTERFACE(wl_subcompositor); } else if(wayland->type == MwLL_WAYLAND_POPUP) { + } else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) { + WL_INTERFACE(wp_viewporter); + WL_INTERFACE(wl_subcompositor); } else { WL_INTERFACE(wl_subcompositor); } diff --git a/src/backend/wayland/wayland.c b/src/backend/wayland/wayland.c index d438ac6..0eb3caf 100644 --- a/src/backend/wayland/wayland.c +++ b/src/backend/wayland/wayland.c @@ -329,14 +329,14 @@ static void destroy_toplevel(MwLL r) { zxdg_decoration_manager_v1_destroy(dec->manager); } - wl_surface_destroy(r->wayland.framebuffer.surface); - - wl_compositor_destroy(r->wayland.compositor); - xdg_surface_destroy(r->wayland.toplevel->xdg_surface); xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level); + wl_surface_destroy(r->wayland.framebuffer.surface); + + wl_compositor_destroy(r->wayland.compositor); + xkb_keymap_unref(r->wayland.xkb_keymap); xkb_state_unref(r->wayland.xkb_state); @@ -345,7 +345,7 @@ static void destroy_toplevel(MwLL r) { free(r->wayland.toplevel); - wl_registry_destroy(r->wayland.registry); + // wl_registry_destroy(r->wayland.registry); // wl_display_disconnect(r->wayland.display); @@ -451,7 +451,6 @@ struct xdg_popup_listener popup_listener = { static void setup_popup(MwLL r, int x, int y, MwLL parent) { struct xdg_surface* xdg_surface; MwLL topmost_parent = r->wayland.parent; - MwU32 ver; r->wayland.type = MwLL_WAYLAND_POPUP; r->wayland.x = x; @@ -510,8 +509,6 @@ static void setup_popup(MwLL r, int x, int y, MwLL parent) { xdg_surface, r->wayland.popup->xdg_positioner); - ver = wl_proxy_get_version((struct wl_proxy*)r->wayland.popup->xdg_popup); - xdg_popup_add_listener(r->wayland.popup->xdg_popup, &popup_listener, r); r->wayland.popup->xdg_surface_listener.configure = xdg_surface_configure; @@ -533,6 +530,120 @@ static void destroy_popup(MwLL r) { r->wayland.configured = MwFALSE; } +static void layer_shell_configure(void* data, + struct zwlr_layer_surface_v1* surface, + uint32_t serial, + uint32_t width, + uint32_t height) { + MwLL self = data; + zwlr_layer_surface_v1_ack_configure(surface, serial); + + self->wayland.x = 0; + self->wayland.y = 0; + self->wayland.ww = width; + self->wayland.wh = height; + + wl_surface_commit(self->wayland.framebuffer.surface); + + self->wayland.configured = MwTRUE; +}; + +static void layer_shell_done(void* data, + struct zwlr_layer_surface_v1* zwlr_layer_surface_v1) { + (void)data; + (void)zwlr_layer_surface_v1; + + printf("closed\n"); +}; + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_shell_configure, + .closed = layer_shell_done, +}; + +/* Layer surface setup function */ +static void setup_layer_surface(MwLL r, int x, int y, int width, int height) { + wayland_protocol_t* layer_shell_protocol; + struct zwlr_layer_shell_v1* layer_shell; + r->wayland.type = MwLL_WAYLAND_LAYER_SURFACE; + r->wayland.layer_surface = malloc(sizeof(struct _MwLLWaylandLayerSurface)); + r->wayland.x = x; + r->wayland.y = y; + + MwLLWaylandSetupCallbacks(&r->wayland); + + /* Connect to the Wayland compositor */ + if(!r->wayland.display) { + r->wayland.display = wl_display_connect(NULL); + if(r->wayland.display == NULL) { + printf("wayland: failed to create display\n"); + raise(SIGTRAP); + return; + } + } + + /* Do a roundtrip to ensure all interfaces are setup. */ + r->wayland.registry = wl_display_get_registry(r->wayland.display); + wl_registry_add_listener(r->wayland.registry, &r->wayland.registry_listener, r); + if(wl_display_roundtrip(r->wayland.display) == -1) { + printf("roundtrip failed\n"); + raise(SIGTRAP); + return; + } + + layer_shell_protocol = WAYLAND_GET_INTERFACE(r->wayland, zwlr_layer_shell_v1); + assert(layer_shell_protocol); + + layer_shell = layer_shell_protocol->context; + + r->wayland.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + r->wayland.framebuffer.surface = wl_compositor_create_surface(r->wayland.compositor); + + r->wayland.layer_surface->surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, r->wayland.framebuffer.surface, NULL, 1, "milsko-surfaces"); + + zwlr_layer_surface_v1_set_size(r->wayland.layer_surface->surface, width, height); + + zwlr_layer_surface_v1_set_anchor(r->wayland.layer_surface->surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP); + zwlr_layer_surface_v1_set_margin(r->wayland.layer_surface->surface, + y, 0, 0, x); + + zwlr_layer_surface_v1_add_listener(r->wayland.layer_surface->surface, &layer_surface_listener, r); + + zwlr_layer_surface_v1_set_keyboard_interactivity(r->wayland.layer_surface->surface, MwTRUE); + + /* Perform the initial commit and wait for the first configure event */ + wl_surface_commit(r->wayland.framebuffer.surface); + while(!r->wayland.configured) { + event_loop(r); + } +} + +/* Toplevel destroy function */ +static void destroy_layer_surface(MwLL r) { + if(shget(r->wayland.wl_protocol_map, zxdg_decoration_manager_v1_interface.name) != NULL) { + zxdg_decoration_manager_v1_context_t* dec = WAYLAND_GET_INTERFACE(r->wayland, zxdg_decoration_manager_v1)->context; + zxdg_decoration_manager_v1_destroy(dec->manager); + } + + wl_surface_destroy(r->wayland.framebuffer.surface); + + wl_compositor_destroy(r->wayland.compositor); + + xkb_keymap_unref(r->wayland.xkb_keymap); + + xkb_state_unref(r->wayland.xkb_state); + + xkb_context_unref(r->wayland.xkb_context); + + wl_registry_destroy(r->wayland.registry); + + r->wayland.configured = MwFALSE; +} + static void clip(MwLL handle) { int i; int x, y, cx, cy, mx, my; @@ -613,7 +724,7 @@ static void wl_logger(const char* fmt, va_list args) { raise(SIGTRAP); } -static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int height, enum _MwLLWaylandType ty) { +static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int height, enum _MwLLWaylandType ty, MwBool can_do_layer_surface) { /* Wayland does not report global coordinates ever. Compositors are not even expected to have knowledge of this. */ r->common.coordinate_type = MwCOORDINATE_LOCAL; @@ -664,12 +775,19 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh } else { /* * We can't actually have a popup without a parent but this needs to be valid behavior. - * So we do a few things to "fake" a toplevel that looks like a popup. + * So we either make a wlr layer surface at this point, or just fake it with a borderless window. */ - setup_toplevel(r, x, y); - MwLLMakeBorderless(r, MwTRUE); + if(can_do_layer_surface) { + setup_layer_surface(r, x, y, width, height); + } else { + setup_toplevel(r, x, y); + MwLLMakeBorderless(r, MwTRUE); + } } break; + case MwLL_WAYLAND_LAYER_SURFACE: + setup_layer_surface(r, x, y, width, height); + break; } } @@ -729,7 +847,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.is_toplevel = parent == NULL; r->wayland.is_clipping = 0; - widget_setup(r, parent, x, y, width, height, MwLL_WAYLAND_UNKNOWN); + widget_setup(r, parent, x, y, width, height, MwLL_WAYLAND_UNKNOWN, MwFALSE); #ifdef USE_DBUS if(!parent && wl_call_tbl.has_dbus) { @@ -1627,14 +1745,18 @@ static void MwLLBeginStateChangeImpl(MwLL handle) { } static void MwLLEndStateChangeImpl(MwLL handle) { - MwLL topmost_parent; + MwLL topmost_parent; + MwBool can_do_layer_surface = MwFALSE; WIDGET_CHECK(handle); - topmost_parent = handle->wayland.parent; + topmost_parent = handle->wayland.parent; + can_do_layer_surface = (WAYLAND_GET_INTERFACE(handle->wayland, zwlr_layer_shell_v1) != NULL); - if(topmost_parent) { - while(topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { + while(topmost_parent) { + if(topmost_parent->wayland.type != MwLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; + } else { + break; } } @@ -1650,11 +1772,14 @@ static void MwLLEndStateChangeImpl(MwLL handle) { case MwLL_WAYLAND_POPUP: destroy_popup(handle); break; + case MwLL_WAYLAND_LAYER_SURFACE: + destroy_layer_surface(handle); + break; } MwLLWaylandFlush(handle); - widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be); + widget_setup(handle, handle->wayland.parent, handle->wayland.detach_point.x, handle->wayland.detach_point.y, handle->wayland.ww, handle->wayland.wh, handle->wayland.type_to_be, can_do_layer_surface); handle->wayland.is_toplevel = MwTRUE; @@ -1666,8 +1791,7 @@ static void MwLLEndStateChangeImpl(MwLL handle) { int i; for(i = 0; i < arrlen(w->children); i++) { if(w->children[i]->lowlevel->wayland.type == MwLL_WAYLAND_SUBLEVEL) { - MwLL child = w->children[i]->lowlevel; - printf("%p\n", child->wayland.sublevel->subcompositor); + MwLL child = w->children[i]->lowlevel; child->wayland.sublevel->xdg_surface = handle->wayland.popup->xdg_surface; wl_subsurface_destroy(child->wayland.sublevel->subsurface); MwLLWaylandFlush(handle);