Compare commits

...

17 Commits

Author SHA1 Message Date
blank X c5e3ca6249 wlroots 0.15.1
Alexander Orzechowski (1):
       xdg-foreign: Fix crash on destroy of degenerate surface
 
 Isaac Freund (3):
       wlr_texture: remove wlr_texture_from_wl_drm() from header
       foreign-toplevel: send enter if needed on output bind
       tinywl: fix check whether client is focused or not
 
 Kirill Primak (3):
       scene/subsurface_tree: fix handling subsurface destruction
       compositor: damage the whole buffer on viewport src change
       subsurface: unlock cached state on commit if desynced
 
 Simon Ser (4):
       backend: error out in autocreate without libinput support
       scene: schedule an output frame on wl_surface.frame
       scene: try to import buffers as textures before rendering
       build: bump version to 0.15.1
 
 Tadeo Kondrak (1):
       input_method_v2: improve mapping detection
 
 Thomas Hebb (1):
       render/gles2: don't constrain shm formats to ones that support reading
 
 nyorain (1):
       vulkan: Fix imported image layout
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEENP+VJs/vDpejQOLkD9574OiPXkgFAmH8RzEACgkQD9574OiP
 XkjPGw/+KdgxXeVJ1Typ8fp9ZfhGTW3sJVREpMpnLra/1lA4LQ1jUDFfvXEPAveI
 UjgGiyoBpBWcWgj0jS0GgcTE2ExnGlkd9Y6pImM0zUTQ1mQF8hPxyThQiJNDpBix
 42lqWtIqYPQObJnXa19SpebNCw/TbHoF/0sHR8I/a0o2PgVT9LGIsqI1nAYH7H/e
 lUR5paZU5G60lQdePhTIOv7MuXNt7fgtpizw/WNMqz0Cl+1weoIAtXv2UWZM39wW
 hhK2e02n8GncLYQn459xqf5UfkCnie9u6BCL4PMuEm+sOsYH5sQzsUFfQjBsNCqL
 ztgFssPwW6v/vImvWclvD0DAOgPK0kMEg0RWlBOKfTTxBewloKp4MIY/udKX9+5S
 b8ALOizzS0vL/lTFc+o4XBELE/X9f0S0Sv+mtWXD4xuOMREPUaijJ5LyOmDf6gG5
 K/CB5T2pdQqNC9UdTGMPlauSFVqliBO7hyQSHl3tr5/ZjQZ3tGFL+szp7b62Rb5r
 ChQCUC6NvDhcKzZaPwL9py005yk0LT5oEXVxRJId6ipWuGn+XBnBoWWckpy/3Zpu
 cnacvsxyKaQS3Uts13UlVW4ojr3wolDzBqDPQGU8xsqQcbgcbjGLxkPFDIWT++3D
 XzBx6bRBTKr1EJRoEROuSl0xDEaWJlZt1XUGPLP1Uxew4DSrXOg=
 =mFoc
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+M9eMyy2C5F27kiEzBX8gix/YfUFAmIphlUACgkQzBX8gix/
 YfVWfA/8C+GEw9/P2s+eKBdK6jIB9H0as/yjLCDQDmAX2iAIGdnJ+4ojd2C6xDMK
 mUDRU1UOufafXMdaFa7DXeWYGkHII62K3qxdVD737bCRApkBGLVC9h11QuWgcYYC
 BxeduZouZ1npRtTxINBCC5TXKDWkt0cvQDrD7pnL+AH+ny5WvOnRO1CaPXCgnc7v
 hqdrVAtHRdAkYBBHuu9WgMpvVzkS3KXr7NaWLpRdGa7nWpkKX9aoa0tNjCL86TPq
 QHDMhQnPxghxJl6xc9rhDWJYcYCUxJ4W4ABbyqkkP64wBtjnDJVh7LWRx4qnFNIO
 ky0E3JM6A5YZ/N0fdOIsxvJ2YOpqYYXhKS8NJa2a+Wnsw+QEHe8hnST4UWGcQERf
 qX0hghKhuYNxpm4vrB3rOPwbcQIdjGo2jlEH4GG3gENduekvvdGAr5qcXDH+5pol
 7iwrbARI3T6kTplx/iDvHk5wYGKwj5oatXy4AKwbBt+DNDakF6Vf9RGLKOtC2cty
 YS607osq9kUUX47RCSP11W3zb84cAtJNw5eHmQzVPJ+hAlGsaMdDVUbUGgJiruVe
 pyYeSKxKyFTao3SYSizZwJB0mwYXWsDsVdf4c6mbdr3w5MBWslrliCof9vzSQSq3
 KAiGawPiT+ar87kyQMaCaMl0ZLaXG7g/MXKNsRp/Ss437nhknqg=
 =6/3L
 -----END PGP SIGNATURE-----

Merge tag '0.15.1' into dkondor-upstream-pr-2551

wlroots 0.15.1

Alexander Orzechowski (1):
      xdg-foreign: Fix crash on destroy of degenerate surface

Isaac Freund (3):
      wlr_texture: remove wlr_texture_from_wl_drm() from header
      foreign-toplevel: send enter if needed on output bind
      tinywl: fix check whether client is focused or not

Kirill Primak (3):
      scene/subsurface_tree: fix handling subsurface destruction
      compositor: damage the whole buffer on viewport src change
      subsurface: unlock cached state on commit if desynced

Simon Ser (4):
      backend: error out in autocreate without libinput support
      scene: schedule an output frame on wl_surface.frame
      scene: try to import buffers as textures before rendering
      build: bump version to 0.15.1

Tadeo Kondrak (1):
      input_method_v2: improve mapping detection

Thomas Hebb (1):
      render/gles2: don't constrain shm formats to ones that support reading

nyorain (1):
      vulkan: Fix imported image layout
2022-03-10 12:02:12 +07:00
Simon Ser 29938b7425 build: bump version to 0.15.1 2022-02-03 22:19:54 +01:00
Isaac Freund eb1a451803 tinywl: fix check whether client is focused or not
Currently this check is too strict and denies the move/resize request
if a subsurface of the client has pointer focus.

(cherry picked from commit 89dc9a44968fbd3fe8a08a41858d1537ee145668)
2022-02-03 22:15:51 +01:00
Isaac Freund a819c512ec foreign-toplevel: send enter if needed on output bind
Currently the output enter event is never sent if the client has not
yet bound the output, which happens every time the compositor creates a
new output.

To fix this, listen for the output bind event and inform clients as
if needed.

(cherry picked from commit 1bd0ea3a809bdba092ef051120bb6d32f79c0ffb)
2022-02-03 22:15:39 +01:00
Alexander Orzechowski c4824b680a xdg-foreign: Fix crash on destroy of degenerate surface
I am running a custom compiled version of chromium with a patch to get
it up and running on sway git at the moment, and in that development
build I compiled there is a bug where the browser will crash if you
try to open a file select dialog. When this crash happens, chromium will
not close, but instead will remain open and impossible to close unless
you send a SIGKILL signal to the process. However, sway will crash to
tty when you send the SIGKILL.

I have a hunch that when chromium is opening the file select dialog
it is creating some sort of a xdg toplevel surface. But it freezes
before it fully initializes the surface. When the SIGKILL signal is
given, sway/wlroots will try to free the xdg_toplevel surface but
because it hasn't fully initialized due to the frozen window, it
segfaults.

Don't be fooled by the assert, the assert is not firing, the surface
pointer is indeed NULL here.

* thread #1, name = 'sway', stop reason = signal SIGSEGV: invalid address (fault address: 0x28)
    frame #0: 0x00007ffff78b9041 libwlroots.so.11`wlr_xdg_toplevel_set_parent(surface=0x0000000000000000, parent=0x0000000000000000) at wlr_xdg_toplevel.c:159:37
   156
   157 	void wlr_xdg_toplevel_set_parent(struct wlr_xdg_surface *surface,
   158 			struct wlr_xdg_surface *parent) {
-> 159 		assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
   160 		assert(!parent || parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
   161
   162 		if (surface->toplevel->parent) {
(lldb) up
error: sway {0x0003442a}: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x67) attribute, but range extraction failed (invalid range list offset 0x67), please file a bug and attach the file at the start of this error message
error: sway {0x0003442a}: DIE has DW_AT_ranges(DW_FORM_sec_offset 0x67) attribute, but range extraction failed (invalid range list offset 0x67), please file a bug and attach the file at the start of this error message
frame #1: 0x00007ffff78e176e libwlroots.so.11`destroy_imported(imported=0x000055555626d570) at wlr_xdg_foreign_v1.c:154:3
   151 		wl_list_for_each_safe(child, child_tmp, &imported->children, link) {
   152 			struct wlr_xdg_surface *xdg_child =
   153 				wlr_xdg_surface_from_wlr_surface(child->surface);
-> 154 			wlr_xdg_toplevel_set_parent(xdg_child, NULL);
   155 		}
   156
   157 		wl_list_remove(&imported->exported_destroyed.link);
(lldb) up
frame #2: 0x00007ffff78e1b9d libwlroots.so.11`xdg_imported_handle_resource_destroy(resource=0x00005555562555a0) at wlr_xdg_foreign_v1.c:280:2
   277 			struct wl_resource *resource) {
   278 		struct wlr_xdg_imported_v1 *imported = xdg_imported_from_resource(resource);
   279 		if (!imported) {
-> 280 			return;
   281 		}
   282
   283 		destroy_imported(imported);
(lldb) up
frame #3: 0x00007ffff794989a libwayland-server.so.0`___lldb_unnamed_symbol211 + 154
libwayland-server.so.0`___lldb_unnamed_symbol211:
->  0x7ffff794989a <+154>: andl   $0x1, %r13d
    0x7ffff794989e <+158>: je     0x7ffff79498b0            ; <+176>
    0x7ffff79498a0 <+160>: addq   $0x8, %rsp
    0x7ffff79498a4 <+164>: movl   $0x1, %eax
(lldb) up
frame #4: 0x00007ffff794fec0 libwayland-server.so.0`___lldb_unnamed_symbol290 + 64
libwayland-server.so.0`___lldb_unnamed_symbol290:
->  0x7ffff794fec0 <+64>: cmpl   $0x1, %eax
    0x7ffff794fec3 <+67>: jne    0x7ffff794fed3            ; <+83>
    0x7ffff794fec5 <+69>: addq   $0x8, %rbx
    0x7ffff794fec9 <+73>: cmpq   %rbx, %r13
(lldb) up
frame #5: 0x00007ffff79503e0 libwayland-server.so.0`___lldb_unnamed_symbol300 + 32
libwayland-server.so.0`___lldb_unnamed_symbol300:
->  0x7ffff79503e0 <+32>: cmpl   $0x1, %eax
    0x7ffff79503e3 <+35>: je     0x7ffff79503f0            ; <+48>
    0x7ffff79503e5 <+37>: popq   %rbx
    0x7ffff79503e6 <+38>: popq   %r12
(lldb) up
frame #6: 0x00007ffff794a30e libwayland-server.so.0`wl_client_destroy + 126
libwayland-server.so.0`wl_client_destroy:
->  0x7ffff794a30e <+126>: movq   %r12, %rdi
    0x7ffff794a311 <+129>: callq  0x7ffff7950150            ; ___lldb_unnamed_symbol293
    0x7ffff794a317 <+135>: movq   0x8(%rbp), %rdi
    0x7ffff794a31b <+139>: callq  *0xdc77(%rip)
(lldb) up
frame #7: 0x00007ffff794a3f7 libwayland-server.so.0`___lldb_unnamed_symbol214 + 119
libwayland-server.so.0`___lldb_unnamed_symbol214:
->  0x7ffff794a3f7 <+119>: movq   0x28(%rsp), %rax
    0x7ffff794a3fc <+124>: subq   %fs:0x28, %rax
    0x7ffff794a405 <+133>: jne    0x7ffff794a727            ; <+935>
    0x7ffff794a40b <+139>: addq   $0x38, %rsp
(lldb) up
frame #8: 0x00007ffff794d1ca libwayland-server.so.0`wl_event_loop_dispatch + 202
libwayland-server.so.0`wl_event_loop_dispatch:
->  0x7ffff794d1ca <+202>: addq   $0xc, %r15
    0x7ffff794d1ce <+206>: cmpq   %r15, %rbp
    0x7ffff794d1d1 <+209>: jne    0x7ffff794d1b8            ; <+184>
    0x7ffff794d1d3 <+211>: movq   0x8(%rsp), %rcx
(lldb) up
frame #9: 0x00007ffff794ad37 libwayland-server.so.0`wl_display_run + 39
libwayland-server.so.0`wl_display_run:
->  0x7ffff794ad37 <+39>: movl   0x8(%rbx), %eax
    0x7ffff794ad3a <+42>: testl  %eax, %eax
    0x7ffff794ad3c <+44>: jne    0x7ffff794ad20            ; <+16>
    0x7ffff794ad3e <+46>: popq   %rbx
(lldb) up
frame #10: 0x000055555557689a sway`server_run(server=0x00005555555f26c0) at server.c:307:2
   304 			wlr_backend_destroy(server->backend);
   305 			return false;
   306 		}
-> 307
   308 		return true;
   309 	}
   310
(lldb) up
frame #11: 0x0000555555575a93 sway`main(argc=3, argv=0x00007fffffffe978) at main.c:431:2
   428 			swaynag_show(&config->swaynag_config_errors);
   429 		}
   430
-> 431 		server_run(&server);
   432
   433 	shutdown:
   434 		sway_log(SWAY_INFO, "Shutting down sway");

(cherry picked from commit cddc1c1bd9f796709c50f4bbb300788edd42fd4f)
2022-02-02 20:29:44 +01:00
Simon Ser ec3780e6ea scene: try to import buffers as textures before rendering
The wlroots APIs currently don't allow importing/uploading a buffer
during rendering operations. Scene-graph buffer nodes need to turn
their wlr_buffer into a wlr_texture at some point. It's not always
possible to do so at wlr_scene_buffer creation time because the
scene-graph may have zero outputs at this point, thus no way to
grab a wlr_renderer.

Instead, add scene-graph buffers to a pending list and try to import
them in wlr_scene_output_commit.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3354
(cherry picked from commit 3db1bcbe641b407b9f5c9e5d0a012b45aa2c6cb7)
2022-02-02 20:28:27 +01:00
Kirill Primak 68c5fa340d subsurface: unlock cached state on commit if desynced
wl_subsurface::set_desync description states: "If cached state exists when
wl_surface.commit is called in desynchronized mode, the pending state is
added to the cached state, and applied as a whole."

This commit reintroduces an implementation of said behavior, previously
removed in 7daf6da9ac05be2cb74c0983e3caee0b21db75d4.

Strictly speaking, this logic isn't fully correct, as the cached state
and the pending state are applied individually instead, if the cached
state isn't locked by anything else. However, the end result is still
the same.

This commit fixes the issue with Firefox permission popups.

(cherry picked from commit 77951968dc9df7214c04c33f4905a9a7aa92f60c)
2022-02-02 20:27:49 +01:00
Kirill Primak 304c61307a compositor: damage the whole buffer on viewport src change
wp_viewporter protocol doesn't seem to say anything about damage, but
Firefox assumes that wp_viewport::set_source alone is enough to damage
the whole surface, and that assumption kinda makes sense, so let's do
that.

(cherry picked from commit da2491d4163e1d8e627d00c8ae594c7f8003472e)
2022-02-02 20:25:28 +01:00
Tadeo Kondrak b0fee56974 input_method_v2: improve mapping detection
Detect NULL commits before the surface is actually committed, allowing
the surface to be properly damaged on unmap.

(cherry picked from commit 5091118bed82394de5a151d658e895bb44059b61)
2022-02-02 20:25:24 +01:00
Kirill Primak 7dde2b66d6 scene/subsurface_tree: fix handling subsurface destruction
This commit renames map/unmap listeners to clarify that they handle
subsurface events, and ensures the node is always destroyed before
the subsurface.

Without this patch, wl_list_remove() would operate on listener links in
already freed memory. glibc is usually lenient to bugs like this, but
musl isn't.

(cherry picked from commit 83ab5055fd36bd0f8a0106257e45d8ed303636d8)
2022-02-02 20:08:20 +01:00
Thomas Hebb ea77cc5cb2 render/gles2: don't constrain shm formats to ones that support reading
commit 44e8451cd9 ("render/gles2: hide shm formats without GL
support") added the is_gles2_pixel_format_supported() function to
render/gles2/pixel_format.c, whose stated purpose is to "check whether
the renderer has the needed GL extensions to read a given pixel format."
It then used that function to filter the pixel formats returned by
get_gles2_shm_formats().

The result of this change is that RGB formats are no longer reported for
GL drivers that don't implement EXT_read_format_bgra, even when those
formats are supported for rendering (which they have to be for
wlr_gles2_renderer_create() to succeed). This is a pretty clear
regression, since wlr_renderer_init_wl_shm() fails when either of
WL_SHM_FORMAT_ARGB8888 or WL_SHM_FORMAT_XRGB8888 are missing.

To fix the regression, change is_gles2_pixel_format_supported() to
accept all pixel formats that support rendering, regardless of whether
we can read them or not, and move the check for EXT_read_format_bgra
back into gles2_read_pixels(). (There's already a check for this
extension in gles2_preferred_read_format(), so we're not breaking any
abstraction that wasn't already broken.)

Tested on the NVIDIA 495.46 proprietary driver, which doesn't support
EXT_read_format_bgra.

Fixes: 44e8451cd9 ("render/gles2: hide shm formats without GL support")
(cherry picked from commit 59b9518f072527ac59593e51df7f5d5331a34f0e)
2022-02-02 20:08:17 +01:00
nyorain a59a957f2b vulkan: Fix imported image layout
(cherry picked from commit 9988eb3378dbc3301059aa9b5e1ff476354cb92b)
2022-02-02 20:08:01 +01:00
Simon Ser df945b665c scene: schedule an output frame on wl_surface.frame
Some clients (e.g. mpv, Firefox) request a new wl_surface.frame
callback without damaging their surface. When this happens,
schedule a new output frame.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3350
(cherry picked from commit 812951f5bc47f502429406e49f4e24f377b7799b)
2022-02-02 20:07:39 +01:00
Isaac Freund 4b358c2f91 wlr_texture: remove wlr_texture_from_wl_drm() from header
This function was already removed in e5b5592a but it was forgotten to
remove it from the header.

(cherry picked from commit 823476e76ed166762095330a8f51eabc825febff)
2022-02-02 20:07:21 +01:00
Simon Ser 7864f26d73 backend: error out in autocreate without libinput support
The libinput backend is now optional. However, this means that a
user building wlroots without the correct libinput dependencies
will end up with a compositor which doesn't respond to input events.

wlr_backend_autocreate is supposed to return a sensible setup, so in
this case let's just error out and explain what happened. Users can
suppress the check by setting WLR_LIBINPUT_NO_DEVICES=1 (already used
to suppress the zero input device case inside the libinput backend).

Compositors which really want to create a bare DRM backend can easily
create it manually instead of using wlr_backend_autocreate.

(cherry picked from commit ec2845750862cc0b175bef59de4305f6da91960a)
2022-02-02 20:07:07 +01:00
blank X b309e8fc39
Update README.md 2021-12-18 19:47:06 +07:00
Daniel Kondor 80d10b9c98 Alternative fix for #2543
No need for an additional enum value
2021-12-18 19:46:53 +07:00
19 changed files with 181 additions and 64 deletions

View File

@ -1,3 +1,9 @@
# blankie/wlroots - dkondor-upstream-pr-2551
This branch "frontports" https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/2551,
should be updated when there's a new wlroots version and be unmaintained
when the pull request above is merged
# wlroots
Pluggable, composable, unopinionated modules for building a [Wayland]

View File

@ -364,6 +364,19 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) {
return NULL;
}
wlr_multi_backend_add(backend, libinput);
#else
const char *no_devs = getenv("WLR_LIBINPUT_NO_DEVICES");
if (no_devs && strcmp(no_devs, "1") == 0) {
wlr_log(WLR_INFO, "WLR_LIBINPUT_NO_DEVICES is set, "
"starting without libinput backend");
} else {
wlr_log(WLR_ERROR, "libinput support is not compiled in, "
"refusing to start");
wlr_log(WLR_ERROR, "Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check");
wlr_session_destroy(multi->session);
wlr_backend_destroy(backend);
return NULL;
}
#endif
#if WLR_HAS_DRM_BACKEND

View File

@ -33,16 +33,6 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer,
uint32_t fmt, uint32_t stride, uint32_t width, uint32_t height,
const void *data);
/**
* Create a new texture from a wl_drm resource. The returned texture is
* immutable.
*
* Should not be called in a rendering block like renderer_begin()/end() or
* between attaching a renderer to an output and committing it.
*/
struct wlr_texture *wlr_texture_from_wl_drm(struct wlr_renderer *renderer,
struct wl_resource *data);
/**
* Create a new texture from a DMA-BUF. The returned texture is immutable.
*

View File

@ -36,10 +36,13 @@ enum wlr_foreign_toplevel_handle_v1_state {
struct wlr_foreign_toplevel_handle_v1_output {
struct wl_list link; // wlr_foreign_toplevel_handle_v1::outputs
struct wl_listener output_destroy;
struct wlr_output *output;
struct wlr_foreign_toplevel_handle_v1 *toplevel;
// private state
struct wl_listener output_bind;
struct wl_listener output_destroy;
};
struct wlr_foreign_toplevel_handle_v1 {

View File

@ -68,6 +68,9 @@ struct wlr_scene {
// May be NULL
struct wlr_presentation *presentation;
struct wl_listener presentation_destroy;
// List of buffers which need to be imported as textures
struct wl_list pending_buffers; // wlr_scene_buffer.pending_link
};
/** A sub-tree in the scene-graph. */
@ -114,6 +117,7 @@ struct wlr_scene_buffer {
struct wlr_fbox src_box;
int dst_width, dst_height;
enum wl_output_transform transform;
struct wl_list pending_link; // wlr_scene.pending_buffers
};
/** A viewport for an output in the scene-graph */

View File

@ -1,7 +1,7 @@
project(
'wlroots',
'c',
version: '0.15.0',
version: '0.15.1',
license: 'MIT',
meson_version: '>=0.58.1',
default_options: [

View File

@ -98,6 +98,10 @@ static const struct wlr_gles2_pixel_format formats[] = {
// TODO: more pixel formats
/*
* Return true if supported for texturing, even if other operations like
* reading aren't supported.
*/
bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer,
const struct wlr_gles2_pixel_format *format) {
if (format->gl_type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT
@ -108,10 +112,12 @@ bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer,
&& !renderer->exts.OES_texture_half_float_linear) {
return false;
}
if (format->gl_format == GL_BGRA_EXT
&& !renderer->exts.EXT_read_format_bgra) {
return false;
}
/*
* Note that we don't need to check for GL_EXT_texture_format_BGRA8888
* here, since we've already checked if we have it at renderer creation
* time and bailed out if not. We do the check there because Wayland
* requires all compositors to support SHM buffers in that format.
*/
return true;
}

View File

@ -441,6 +441,12 @@ static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer,
return false;
}
if (fmt->gl_format == GL_BGRA_EXT && !renderer->exts.EXT_read_format_bgra) {
wlr_log(WLR_ERROR,
"Cannot read pixels: missing GL_EXT_read_format_bgra extension");
return false;
}
const struct wlr_pixel_format_info *drm_fmt =
drm_get_pixel_format_info(fmt->drm_format);
assert(drm_fmt);

View File

@ -598,7 +598,7 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
wl_list_for_each_safe(texture, tmp_tex, &renderer->foreign_textures, foreign_link) {
VkImageLayout src_layout = VK_IMAGE_LAYOUT_GENERAL;
if (!texture->transitioned) {
src_layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
src_layout = VK_IMAGE_LAYOUT_UNDEFINED;
texture->transitioned = true;
}

View File

@ -438,7 +438,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
img_info.arrayLayers = 1;
img_info.samples = VK_SAMPLE_COUNT_1_BIT;
img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
img_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
img_info.extent = (VkExtent3D) { attribs->width, attribs->height, 1 };
img_info.usage = for_render ?
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT :

View File

@ -611,7 +611,8 @@ static void begin_interactive(struct tinywl_view *view,
struct tinywl_server *server = view->server;
struct wlr_surface *focused_surface =
server->seat->pointer_state.focused_surface;
if (view->xdg_surface->surface != focused_surface) {
if (view->xdg_surface->surface !=
wlr_surface_get_root_surface(focused_surface)) {
/* Deny move/resize requests from unfocused clients. */
return;
}

View File

@ -13,15 +13,20 @@ struct wlr_scene_subsurface_tree {
struct wlr_surface *surface;
struct wlr_scene_surface *scene_surface;
struct wlr_scene_subsurface_tree *parent; // NULL for the top-level surface
struct wlr_addon surface_addon; // only set if there's a parent
struct wl_listener tree_destroy;
struct wl_listener surface_destroy;
struct wl_listener surface_commit;
struct wl_listener surface_map;
struct wl_listener surface_unmap;
struct wl_listener surface_new_subsurface;
struct wlr_scene_subsurface_tree *parent; // NULL for the top-level surface
// Only valid if the surface is a sub-surface
struct wlr_addon surface_addon;
struct wl_listener subsurface_destroy;
struct wl_listener subsurface_map;
struct wl_listener subsurface_unmap;
};
static void subsurface_tree_handle_tree_destroy(struct wl_listener *listener,
@ -31,23 +36,17 @@ static void subsurface_tree_handle_tree_destroy(struct wl_listener *listener,
// tree and scene_surface will be cleaned up by scene_node_finish
if (subsurface_tree->parent) {
wlr_addon_finish(&subsurface_tree->surface_addon);
wl_list_remove(&subsurface_tree->subsurface_destroy.link);
wl_list_remove(&subsurface_tree->subsurface_map.link);
wl_list_remove(&subsurface_tree->subsurface_unmap.link);
}
wl_list_remove(&subsurface_tree->tree_destroy.link);
wl_list_remove(&subsurface_tree->surface_destroy.link);
wl_list_remove(&subsurface_tree->surface_commit.link);
wl_list_remove(&subsurface_tree->surface_map.link);
wl_list_remove(&subsurface_tree->surface_unmap.link);
wl_list_remove(&subsurface_tree->surface_new_subsurface.link);
free(subsurface_tree);
}
static void subsurface_tree_handle_surface_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
wl_container_of(listener, subsurface_tree, surface_destroy);
wlr_scene_node_destroy(&subsurface_tree->tree->node);
}
static const struct wlr_addon_interface subsurface_tree_addon_impl;
static struct wlr_scene_subsurface_tree *subsurface_tree_from_subsurface(
@ -97,6 +96,13 @@ static void subsurface_tree_reconfigure(
}
}
static void subsurface_tree_handle_surface_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
wl_container_of(listener, subsurface_tree, surface_destroy);
wlr_scene_node_destroy(&subsurface_tree->tree->node);
}
static void subsurface_tree_handle_surface_commit(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
@ -106,18 +112,25 @@ static void subsurface_tree_handle_surface_commit(struct wl_listener *listener,
subsurface_tree_reconfigure(subsurface_tree);
}
static void subsurface_tree_handle_surface_map(struct wl_listener *listener,
static void subsurface_tree_handle_subsurface_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
wl_container_of(listener, subsurface_tree, surface_map);
wl_container_of(listener, subsurface_tree, subsurface_destroy);
wlr_scene_node_destroy(&subsurface_tree->tree->node);
}
static void subsurface_tree_handle_subsurface_map(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
wl_container_of(listener, subsurface_tree, subsurface_map);
wlr_scene_node_set_enabled(&subsurface_tree->tree->node, true);
}
static void subsurface_tree_handle_surface_unmap(struct wl_listener *listener,
static void subsurface_tree_handle_subsurface_unmap(struct wl_listener *listener,
void *data) {
struct wlr_scene_subsurface_tree *subsurface_tree =
wl_container_of(listener, subsurface_tree, surface_unmap);
wl_container_of(listener, subsurface_tree, subsurface_unmap);
wlr_scene_node_set_enabled(&subsurface_tree->tree->node, false);
}
@ -151,8 +164,14 @@ static bool subsurface_tree_create_subsurface(
wlr_addon_init(&child->surface_addon, &subsurface->surface->addons,
parent, &subsurface_tree_addon_impl);
wl_signal_add(&subsurface->events.map, &child->surface_map);
wl_signal_add(&subsurface->events.unmap, &child->surface_unmap);
child->subsurface_destroy.notify = subsurface_tree_handle_subsurface_destroy;
wl_signal_add(&subsurface->events.destroy, &child->subsurface_destroy);
child->subsurface_map.notify = subsurface_tree_handle_subsurface_map;
wl_signal_add(&subsurface->events.map, &child->subsurface_map);
child->subsurface_unmap.notify = subsurface_tree_handle_subsurface_unmap;
wl_signal_add(&subsurface->events.unmap, &child->subsurface_unmap);
return true;
}
@ -214,12 +233,6 @@ static struct wlr_scene_subsurface_tree *scene_surface_tree_create(
subsurface_tree->surface_commit.notify = subsurface_tree_handle_surface_commit;
wl_signal_add(&surface->events.commit, &subsurface_tree->surface_commit);
subsurface_tree->surface_map.notify = subsurface_tree_handle_surface_map;
wl_list_init(&subsurface_tree->surface_map.link);
subsurface_tree->surface_unmap.notify = subsurface_tree_handle_surface_unmap;
wl_list_init(&subsurface_tree->surface_unmap.link);
subsurface_tree->surface_new_subsurface.notify =
subsurface_tree_handle_surface_new_subsurface;
wl_signal_add(&surface->events.new_subsurface,

View File

@ -130,6 +130,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
break;
case WLR_SCENE_NODE_BUFFER:;
struct wlr_scene_buffer *scene_buffer = scene_buffer_from_node(node);
wl_list_remove(&scene_buffer->pending_link);
wlr_texture_destroy(scene_buffer->texture);
wlr_buffer_unlock(scene_buffer->buffer);
free(scene_buffer);
@ -145,6 +146,7 @@ struct wlr_scene *wlr_scene_create(void) {
scene_node_init(&scene->node, WLR_SCENE_NODE_ROOT, NULL);
wl_list_init(&scene->outputs);
wl_list_init(&scene->presentation_destroy.link);
wl_list_init(&scene->pending_buffers);
return scene;
}
@ -236,10 +238,6 @@ static void scene_surface_handle_surface_commit(struct wl_listener *listener,
wl_container_of(listener, scene_surface, surface_commit);
struct wlr_surface *surface = scene_surface->surface;
if (!pixman_region32_not_empty(&surface->buffer_damage)) {
return;
}
struct wlr_scene *scene = scene_node_get_root(&scene_surface->node);
int lx, ly;
@ -256,6 +254,17 @@ static void scene_surface_handle_surface_commit(struct wl_listener *listener,
return;
}
// Even if the surface hasn't submitted damage, schedule a new frame if
// the client has requested a wl_surface.frame callback.
if (!wl_list_empty(&surface->current.frame_callback_list) &&
scene_surface->primary_output != NULL) {
wlr_output_schedule_frame(scene_surface->primary_output);
}
if (!pixman_region32_not_empty(&surface->buffer_damage)) {
return;
}
struct wlr_scene_output *scene_output;
wl_list_for_each(scene_output, &scene->outputs, link) {
struct wlr_output *output = scene_output->output;
@ -353,6 +362,9 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_node *parent,
scene_node_damage_whole(&scene_buffer->node);
struct wlr_scene *scene = scene_node_get_root(parent);
wl_list_insert(&scene->pending_buffers, &scene_buffer->pending_link);
return scene_buffer;
}
@ -1106,6 +1118,15 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) {
return true;
}
// Try to import new buffers as textures
struct wlr_scene_buffer *scene_buffer, *scene_buffer_tmp;
wl_list_for_each_safe(scene_buffer, scene_buffer_tmp,
&scene_output->scene->pending_buffers, pending_link) {
scene_buffer_get_texture(scene_buffer, renderer);
wl_list_remove(&scene_buffer->pending_link);
wl_list_init(&scene_buffer->pending_link);
}
wlr_renderer_begin(renderer, output->width, output->height);
int nrects;

View File

@ -256,6 +256,23 @@ static void toplevel_send_output(struct wlr_foreign_toplevel_handle_v1 *toplevel
toplevel_update_idle_source(toplevel);
}
static void toplevel_handle_output_bind(struct wl_listener *listener,
void *data) {
struct wlr_foreign_toplevel_handle_v1_output *toplevel_output =
wl_container_of(listener, toplevel_output, output_bind);
struct wlr_output_event_bind *event = data;
struct wl_client *client = wl_resource_get_client(event->resource);
struct wl_resource *resource;
wl_resource_for_each(resource, &toplevel_output->toplevel->resources) {
if (wl_resource_get_client(resource) == client) {
send_output_to_resource(resource, toplevel_output->output, true);
}
}
toplevel_update_idle_source(toplevel_output->toplevel);
}
static void toplevel_handle_output_destroy(struct wl_listener *listener,
void *data) {
struct wlr_foreign_toplevel_handle_v1_output *toplevel_output =
@ -285,6 +302,9 @@ void wlr_foreign_toplevel_handle_v1_output_enter(
toplevel_output->toplevel = toplevel;
wl_list_insert(&toplevel->outputs, &toplevel_output->link);
toplevel_output->output_bind.notify = toplevel_handle_output_bind;
wl_signal_add(&output->events.bind, &toplevel_output->output_bind);
toplevel_output->output_destroy.notify = toplevel_handle_output_destroy;
wl_signal_add(&output->events.destroy, &toplevel_output->output_destroy);
@ -294,6 +314,7 @@ void wlr_foreign_toplevel_handle_v1_output_enter(
static void toplevel_output_destroy(
struct wlr_foreign_toplevel_handle_v1_output *toplevel_output) {
wl_list_remove(&toplevel_output->link);
wl_list_remove(&toplevel_output->output_bind.link);
wl_list_remove(&toplevel_output->output_destroy.link);
free(toplevel_output);
}

View File

@ -157,9 +157,22 @@ static void popup_surface_surface_role_commit(struct wlr_surface *surface) {
&& popup_surface->input_method->client_active);
}
static void popup_surface_surface_role_precommit(struct wlr_surface *surface) {
struct wlr_input_popup_surface_v2 *popup_surface = surface->role_data;
if (popup_surface == NULL) {
return;
}
if (surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
surface->pending.buffer == NULL) {
// This is a NULL commit
popup_surface_set_mapped(popup_surface, false);
}
}
static const struct wlr_surface_role input_popup_surface_v2_role = {
.name = "zwp_input_popup_surface_v2",
.commit = popup_surface_surface_role_commit,
.precommit = popup_surface_surface_role_precommit,
};
bool wlr_surface_is_input_popup_surface_v2(struct wlr_surface *surface) {

View File

@ -207,8 +207,12 @@ static void surface_update_damage(pixman_region32_t *buffer_damage,
pixman_region32_clear(buffer_damage);
if (pending->width != current->width ||
pending->height != current->height) {
// Damage the whole buffer on resize
pending->height != current->height ||
pending->viewport.src.x != current->viewport.src.x ||
pending->viewport.src.y != current->viewport.src.y ||
pending->viewport.src.width != current->viewport.src.width ||
pending->viewport.src.height != current->viewport.src.height) {
// Damage the whole buffer on resize or viewport source box change
pixman_region32_union_rect(buffer_damage, buffer_damage, 0, 0,
pending->buffer_width, pending->buffer_height);
} else {
@ -491,7 +495,7 @@ static void collect_subsurface_damage_iter(struct wlr_surface *surface,
static void subsurface_parent_commit(struct wlr_subsurface *subsurface) {
struct wlr_surface *surface = subsurface->surface;
bool moved = subsurface->current.x != subsurface->pending.x ||
subsurface->current.y != subsurface->pending.y;
if (subsurface->mapped && moved) {
@ -530,6 +534,9 @@ static void subsurface_commit(struct wlr_subsurface *subsurface) {
}
subsurface->has_cache = true;
subsurface->cached_seq = wlr_surface_lock_pending(surface);
} else if (subsurface->has_cache) {
wlr_surface_unlock_cached(surface, subsurface->cached_seq);
subsurface->has_cache = false;
}
}

View File

@ -33,7 +33,7 @@ static bool verify_is_toplevel(struct wl_resource *client_resource,
if (wlr_surface_is_xdg_surface(surface)) {
struct wlr_xdg_surface *xdg_surface =
wlr_xdg_surface_from_wlr_surface(surface);
if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
if (xdg_surface == NULL || xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wl_resource_post_error(client_resource, -1,
"surface must be an xdg_toplevel");
return false;
@ -151,7 +151,10 @@ static void destroy_imported(struct wlr_xdg_imported_v1 *imported) {
wl_list_for_each_safe(child, child_tmp, &imported->children, link) {
struct wlr_xdg_surface *xdg_child =
wlr_xdg_surface_from_wlr_surface(child->surface);
wlr_xdg_toplevel_set_parent(xdg_child, NULL);
if (xdg_child != NULL) {
wlr_xdg_toplevel_set_parent(xdg_child, NULL);
}
}
wl_list_remove(&imported->exported_destroyed.link);

View File

@ -42,7 +42,7 @@ static bool verify_is_toplevel(struct wl_resource *client_resource,
struct wlr_xdg_surface *xdg_surface =
wlr_xdg_surface_from_wlr_surface(surface);
if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
if (xdg_surface == NULL || xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wl_resource_post_error(client_resource,
ZXDG_EXPORTER_V2_ERROR_INVALID_SURFACE,
"surface must be an xdg_toplevel");
@ -157,7 +157,10 @@ static void destroy_imported(struct wlr_xdg_imported_v2 *imported) {
wl_list_for_each_safe(child, child_tmp, &imported->children, link) {
struct wlr_xdg_surface *xdg_child =
wlr_xdg_surface_from_wlr_surface(child->surface);
wlr_xdg_toplevel_set_parent(xdg_child, NULL);
if (xdg_child != NULL) {
wlr_xdg_toplevel_set_parent(xdg_child, NULL);
}
}
wl_list_remove(&imported->exported_destroyed.link);

View File

@ -11,6 +11,11 @@ bool wlr_surface_is_xdg_surface(struct wlr_surface *surface) {
surface->role == &xdg_popup_surface_role;
}
static bool xdg_surface_is_inert_popup(struct wlr_xdg_surface* surface) {
return surface->role == WLR_XDG_SURFACE_ROLE_NONE &&
surface->surface->role == &xdg_popup_surface_role;
}
struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface(
struct wlr_surface *surface) {
assert(wlr_surface_is_xdg_surface(surface));
@ -90,7 +95,7 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) {
static void xdg_surface_handle_ack_configure(struct wl_client *client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_surface *surface = wlr_xdg_surface_from_resource(resource);
if (surface == NULL) {
if (surface == NULL || xdg_surface_is_inert_popup(surface)) {
return;
}
@ -227,7 +232,7 @@ static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_surface *surface = wlr_xdg_surface_from_resource(resource);
if (surface == NULL) {
if (surface == NULL || xdg_surface_is_inert_popup(surface)) {
return;
}
@ -288,6 +293,8 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
struct wlr_xdg_surface *surface =
wl_container_of(listener, surface, surface_commit);
if (xdg_surface_is_inert_popup(surface)) return;
if (wlr_surface_has_buffer(surface->surface) && !surface->configured) {
wl_resource_post_error(surface->resource,
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER,
@ -295,9 +302,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
return;
}
// surface->role might be NONE for inert popups
// So we check surface->surface->role
if (surface->surface->role == NULL) {
if (surface->role == WLR_XDG_SURFACE_ROLE_NONE) {
wl_resource_post_error(surface->resource,
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
"xdg_surface must have a role");
@ -308,7 +313,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_wlr_surface(wlr_surface);
if (surface == NULL) {
if (surface == NULL || xdg_surface_is_inert_popup(surface)) {
return;
}
@ -316,7 +321,9 @@ void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_NONE:
// inert toplevel or popup
wl_resource_post_error(surface->resource,
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
"xdg_surface must have a role");
return;
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
handle_xdg_surface_toplevel_committed(surface);