diff --git a/meson.build b/meson.build
index da74da51..eda15dcf 100644
--- a/meson.build
+++ b/meson.build
@@ -33,8 +33,8 @@ dbusmenu_gtk = dependency('dbusmenu-glib-0.4')
xkbregistry = dependency('xkbregistry')
json = subproject('wf-json').get_variable('wfjson')
openssl = dependency('openssl')
-gbm = dependency('gbm', required: get_option('live-previews-dmabuf'))
-drm = dependency('libdrm', required: get_option('live-previews-dmabuf'))
+gbm = dependency('gbm', required: false)
+drm = dependency('libdrm', required: false)
if get_option('wayland-logout') == true
wayland_logout = subproject('wayland-logout')
@@ -45,8 +45,8 @@ if get_option('weather') == true
add_project_arguments('-DHAVE_WEATHER=1', language: 'cpp')
endif
-if gbm.found() and drm.found() and not get_option('live-previews-dmabuf').disabled()
- add_project_arguments('-DHAVE_DMABUF=1', language: 'cpp')
+if not gbm.found() or not drm.found()
+ message('Live window previews require gbm and libdrm dependencies')
endif
if libpulse.found()
diff --git a/meson_options.txt b/meson_options.txt
index 12b64c52..3c50471b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -28,9 +28,3 @@ option(
value: false,
description: 'Install weather widgets and open-weather-fetch systemd service',
)
-option(
- 'live-previews-dmabuf',
- type: 'feature',
- value: 'auto',
- description: 'Enable live window preview tooltips when hovering over window-list buttons in wf-panel'
-)
diff --git a/proto/meson.build b/proto/meson.build
index 28d4037a..de6234c9 100644
--- a/proto/meson.build
+++ b/proto/meson.build
@@ -20,7 +20,6 @@ client_protocols = [
[wl_protocol_dir, 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml'],
[wl_protocol_dir, 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml'],
'wlr-foreign-toplevel-management-unstable-v1.xml',
- 'wlr-screencopy.xml',
wayfire.get_pkgconfig_variable('pkgdatadir') / 'unstable' / 'wayfire-shell-unstable-v2.xml',
]
diff --git a/proto/wlr-screencopy.xml b/proto/wlr-screencopy.xml
deleted file mode 100644
index 85b57d7e..00000000
--- a/proto/wlr-screencopy.xml
+++ /dev/null
@@ -1,231 +0,0 @@
-
-
-
- Copyright © 2018 Simon Ser
- Copyright © 2019 Andri Yngvason
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice (including the next
- paragraph) shall be included in all copies or substantial portions of the
- Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
-
-
- This protocol allows clients to ask the compositor to copy part of the
- screen content to a client buffer.
-
- Warning! The protocol described in this file is experimental and
- backward incompatible changes may be made. Backward compatible changes
- may be added together with the corresponding interface version bump.
- Backward incompatible changes are done by bumping the version number in
- the protocol and interface names and resetting the interface version.
- Once the protocol is to be declared stable, the 'z' prefix and the
- version number in the protocol and interface names are removed and the
- interface version number is reset.
-
-
-
-
- This object is a manager which offers requests to start capturing from a
- source.
-
-
-
-
- Capture the next frame of an entire output.
-
-
-
-
-
-
-
-
- Capture the next frame of an output's region.
-
- The region is given in output logical coordinates, see
- xdg_output.logical_size. The region will be clipped to the output's
- extents.
-
-
-
-
-
-
-
-
-
-
-
-
- All objects created by the manager will still remain valid, until their
- appropriate destroy request has been called.
-
-
-
-
-
-
- This object represents a single frame.
-
- When created, a series of buffer events will be sent, each representing a
- supported buffer type. The "buffer_done" event is sent afterwards to
- indicate that all supported buffer types have been enumerated. The client
- will then be able to send a "copy" request. If the capture is successful,
- the compositor will send a "flags" event followed by a "ready" event.
-
- For objects version 2 or lower, wl_shm buffers are always supported, ie.
- the "buffer" event is guaranteed to be sent.
-
- If the capture failed, the "failed" event is sent. This can happen anytime
- before the "ready" event.
-
- Once either a "ready" or a "failed" event is received, the client should
- destroy the frame.
-
-
-
-
- Provides information about wl_shm buffer parameters that need to be
- used for this frame. This event is sent once after the frame is created
- if wl_shm buffers are supported.
-
-
-
-
-
-
-
-
-
- Copy the frame to the supplied buffer. The buffer must have the
- correct size, see zwlr_screencopy_frame_v1.buffer and
- zwlr_screencopy_frame_v1.linux_dmabuf. The buffer needs to have a
- supported format.
-
- If the frame is successfully copied, "flags" and "ready" events are
- sent. Otherwise, a "failed" event is sent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Provides flags about the frame. This event is sent once before the
- "ready" event.
-
-
-
-
-
-
- Called as soon as the frame is copied, indicating it is available
- for reading. This event includes the time at which the presentation took place.
-
- The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
- each component being an unsigned 32-bit value. Whole seconds are in
- tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
- and the additional fractional part in tv_nsec as nanoseconds. Hence,
- for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part
- may have an arbitrary offset at start.
-
- After receiving this event, the client should destroy the object.
-
-
-
-
-
-
-
-
- This event indicates that the attempted frame copy has failed.
-
- After receiving this event, the client should destroy the object.
-
-
-
-
-
- Destroys the frame. This request can be sent at any time by the client.
-
-
-
-
-
-
- Same as copy, except it waits until there is damage to copy.
-
-
-
-
-
-
- This event is sent right before the ready event when copy_with_damage is
- requested. It may be generated multiple times for each copy_with_damage
- request.
-
- The arguments describe a box around an area that has changed since the
- last copy request that was derived from the current screencopy manager
- instance.
-
- The union of all regions received between the call to copy_with_damage
- and a ready event is the total damage since the prior ready event.
-
-
-
-
-
-
-
-
-
-
- Provides information about linux-dmabuf buffer parameters that need to
- be used for this frame. This event is sent once after the frame is
- created if linux-dmabuf buffers are supported.
-
-
-
-
-
-
-
-
- This event is sent once after all buffer events have been sent.
-
- The client should proceed to create a buffer of one of the supported
- types, and send a "copy" request.
-
-
-
-
diff --git a/src/panel/meson.build b/src/panel/meson.build
index 02e861a9..2f4fde16 100644
--- a/src/panel/meson.build
+++ b/src/panel/meson.build
@@ -72,10 +72,10 @@ else
message('Weather disabled, weather widgets and owf service not included.')
endif
-if gbm.found() and drm.found() and not get_option('live-previews-dmabuf').disabled()
+if gbm.found() and drm.found()
deps += [gbm, drm]
else
- message('Development packages for gbm and drm are required to enable live window preview tooltips in wf-panel.')
+ message('Development packages for gbm and libdrm are required to enable live window preview tooltips in wf-panel.')
endif
executable(
diff --git a/src/panel/widgets/window-list/toplevel.cpp b/src/panel/widgets/window-list/toplevel.cpp
index 1b182434..e952cd83 100644
--- a/src/panel/widgets/window-list/toplevel.cpp
+++ b/src/panel/widgets/window-list/toplevel.cpp
@@ -18,174 +18,135 @@ namespace
extern zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_v1_impl;
}
-static int create_anon_file(off_t size)
+static void session_handle_buffer_size(void *data,
+ struct ext_image_copy_capture_session_v1*,
+ uint32_t width, uint32_t height)
{
- int fd = memfd_create("wf-live-preview", MFD_CLOEXEC);
+ TooltipMedia *toplevel = (TooltipMedia*)data;
+ toplevel->current_buffer_width = width;
+ toplevel->current_buffer_height = height;
+}
- if (fd == -1)
- {
- perror("memfd_create");
- return 1;
- }
+static void session_handle_shm_format(void *data,
+ struct ext_image_copy_capture_session_v1*,
+ uint32_t format)
+{}
- if (ftruncate(fd, size) == -1)
- {
- perror("ftruncate");
- close(fd);
- return 1;
- }
+static void session_handle_dmabuf_device(void*,
+ struct ext_image_copy_capture_session_v1*,
+ struct wl_array*)
+{}
- return fd;
+static void session_handle_dmabuf_format(void *data,
+ struct ext_image_copy_capture_session_v1*,
+ uint32_t format,
+ struct wl_array*)
+{
+ TooltipMedia *toplevel = (TooltipMedia*)data;
+ toplevel->current_buffer_format = format;
}
-#ifdef HAVE_DMABUF
+static void session_handle_done(void *data,
+ struct ext_image_copy_capture_session_v1*)
+{}
+
+static void session_handle_stopped(void*,
+ struct ext_image_copy_capture_session_v1 *session)
+{}
+
+static const struct ext_image_copy_capture_session_v1_listener recording_session_listener = {
+ .buffer_size = session_handle_buffer_size,
+ .shm_format = session_handle_shm_format,
+ .dmabuf_device = session_handle_dmabuf_device,
+ .dmabuf_format = session_handle_dmabuf_format,
+ .done = session_handle_done,
+ .stopped = session_handle_stopped,
+};
+
static void dmabuf_created(void *data, struct zwp_linux_buffer_params_v1*,
struct wl_buffer *wl_buffer)
{
TooltipMedia *tooltip_media = (TooltipMedia*)data;
tooltip_media->buffer = wl_buffer;
- zwlr_screencopy_frame_v1_copy(tooltip_media->frame, tooltip_media->buffer);
}
static void dmabuf_failed(void *data, struct zwp_linux_buffer_params_v1*)
-{
- TooltipMedia *tooltip_media = (TooltipMedia*)data;
-
- std::cerr << "Failed to create dmabuf, trying shm" << std::endl;
- tooltip_media->window_list->live_previews_dmabuf = false;
-}
+{}
static const struct zwp_linux_buffer_params_v1_listener params_listener =
{
.created = dmabuf_created,
.failed = dmabuf_failed,
};
-#endif // HAVE_DMABUF
-void handle_frame_buffer(void *data,
- struct zwlr_screencopy_frame_v1 *zwlr_screencopy_frame_v1,
- uint32_t format,
- uint32_t width,
- uint32_t height,
- uint32_t stride)
-{
- TooltipMedia *tooltip_media = (TooltipMedia*)data;
+/* Copy Capture Callbacks */
- if (tooltip_media->window_list->live_previews_dmabuf)
- {
- tooltip_media->shm_data = nullptr;
- return;
- }
-
- size_t size = width * height * int(stride / width);
-
- if (tooltip_media->size != size)
- {
- if (tooltip_media->shm_data && tooltip_media->size)
- {
- if (munmap(tooltip_media->shm_data, tooltip_media->size) < 0)
- {
- perror("munmap failed");
- }
- }
-
- tooltip_media->size = size;
- auto anon_file = create_anon_file(size);
- if (anon_file < 0)
- {
- perror("anon_file < 0");
- return;
- }
-
- void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, anon_file, 0);
- if (data == MAP_FAILED)
- {
- perror("data == MAP_FAILED");
- close(anon_file);
- return;
- }
-
- wl_shm_pool *pool = wl_shm_create_pool(tooltip_media->window_list->shm, anon_file, size);
- tooltip_media->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format);
- wl_shm_pool_destroy(pool);
- close(anon_file);
- tooltip_media->buffer_width = width;
- tooltip_media->buffer_height = height;
- tooltip_media->buffer_stride = stride;
- tooltip_media->shm_data = data;
- }
+static void frame_handle_transform(void*,
+ struct ext_image_copy_capture_frame_v1*,
+ uint32_t)
+{}
- zwlr_screencopy_frame_v1_copy(tooltip_media->frame, tooltip_media->buffer);
-}
+static void frame_handle_damage(void*,
+ struct ext_image_copy_capture_frame_v1*,
+ int32_t, int32_t, int32_t, int32_t)
+{}
-void handle_frame_flags(void*,
- struct zwlr_screencopy_frame_v1*,
- uint32_t)
+static void frame_handle_presentation_time(void*,
+ struct ext_image_copy_capture_frame_v1*,
+ uint32_t, uint32_t, uint32_t)
{}
-void handle_frame_ready(void *data,
- struct zwlr_screencopy_frame_v1 *zwlr_screencopy_frame_v1,
- uint32_t tv_sec_hi,
- uint32_t tv_sec_lo,
- uint32_t tv_nsec)
+static void frame_handle_ready(void *data,
+ struct ext_image_copy_capture_frame_v1*)
{
TooltipMedia *tooltip_media = (TooltipMedia*)data;
- tooltip_media->request_next_frame();
+ tooltip_media->frame_in_flight = false;
-#ifdef HAVE_DMABUF
- if (tooltip_media->window_list->live_previews_dmabuf && tooltip_media->bo)
+ if (tooltip_media->buffer == nullptr)
{
- uint32_t stride = 0;
- tooltip_media->map_data = nullptr;
- tooltip_media->dmabuf_data = gbm_bo_map(tooltip_media->bo,
- 0, 0, tooltip_media->buffer_width, tooltip_media->buffer_height,
- GBM_BO_TRANSFER_READ, &stride, &tooltip_media->map_data);
-
- if (!tooltip_media->dmabuf_data)
- {
- perror("Failed to map bo");
- std::cerr << "Trying shm" << std::endl;
- tooltip_media->window_list->live_previews_dmabuf = false;
- return;
- }
+ printf("%s buffer null\n", __func__);
- if (tooltip_media->bo && tooltip_media->map_data)
- {
- gbm_bo_unmap(tooltip_media->bo, tooltip_media->map_data);
- tooltip_media->map_data = nullptr;
- }
-
- tooltip_media->buffer_stride = stride;
- tooltip_media->size = tooltip_media->buffer_height * tooltip_media->buffer_stride;
+ return;
}
-#endif // HAVE_DMABUF
-
- if ((!tooltip_media->shm_data
-#ifdef HAVE_DMABUF
- && !tooltip_media->dmabuf_data
-#endif // HAVE_DMABUF
- ) || !tooltip_media->size)
+ uint32_t stride = 0;
+ void *map_data = NULL;
+ void *pixel_data = gbm_bo_map(tooltip_media->bo, 0, 0, tooltip_media->width, tooltip_media->height,
+ GBM_BO_TRANSFER_READ, &stride, &map_data);
+ if (!pixel_data)
{
+ perror("failed to map bo");
return;
}
- std::shared_ptr bytes = 0;
- size_t size = tooltip_media->buffer_height * tooltip_media->buffer_stride;
- if (tooltip_media->shm_data)
- {
- bytes = Glib::Bytes::create(tooltip_media->shm_data, size);
- }
+ /* Scale */
+ auto pixbuf = Gdk::Pixbuf::create_from_data(
+ (const guint8*)pixel_data,
+ Gdk::Colorspace::RGB,
+ true,
+ 8,
+ tooltip_media->width,
+ tooltip_media->height,
+ stride);
-#ifdef HAVE_DMABUF
- else if (tooltip_media->dmabuf_data)
- {
- bytes = Glib::Bytes::create(tooltip_media->dmabuf_data, size);
- tooltip_media->dmabuf_data = nullptr;
- }
-#endif // HAVE_DMABUF
+ gbm_bo_unmap(tooltip_media->bo, map_data);
+
+ uint32_t w = 500;
+ uint32_t h = tooltip_media->height * (500.0f / tooltip_media->width);
+
+ auto scaled_pixbuf = pixbuf->scale_simple(
+ w, h, Gdk::InterpType::BILINEAR);
+
+ w = scaled_pixbuf->get_width();
+ h = scaled_pixbuf->get_height();
+ uint32_t s = scaled_pixbuf->get_rowstride();
+
+ /* Swap red and blue channels */
+ size_t size = s * h;
+ pixel_data = scaled_pixbuf->get_pixels();
+ std::shared_ptr bytes = Glib::Bytes::create((unsigned char*)pixel_data, size);
if (!bytes)
{
@@ -194,170 +155,191 @@ void handle_frame_ready(void *data,
auto builder = Gdk::MemoryTextureBuilder::create();
builder->set_bytes(bytes);
- builder->set_width(tooltip_media->buffer_width);
- builder->set_height(tooltip_media->buffer_height);
- builder->set_stride(tooltip_media->buffer_stride);
- builder->set_format(Gdk::MemoryFormat::R8G8B8A8);
+ builder->set_width(w);
+ builder->set_height(h);
+ builder->set_stride(s);
+ builder->set_format(Gdk::MemoryFormat::B8G8R8A8);
auto texture = builder->build();
tooltip_media->set_paintable(texture);
+ tooltip_media->frame_in_flight = false;
}
-void handle_frame_failed(void*, struct zwlr_screencopy_frame_v1*)
-{}
+static void frame_handle_failed(void *data,
+ struct ext_image_copy_capture_frame_v1 *handle,
+ uint32_t reason)
+{
+ TooltipMedia *tooltip_media = (TooltipMedia*)data;
-void handle_frame_damage(void*,
- struct zwlr_screencopy_frame_v1*,
- uint32_t,
- uint32_t,
- uint32_t,
- uint32_t)
-{}
+ ext_image_copy_capture_frame_v1_destroy(handle);
+ tooltip_media->frame = nullptr;
+ tooltip_media->frame_in_flight = false;
+}
-void handle_frame_linux_dmabuf(void *data,
- struct zwlr_screencopy_frame_v1 *frame,
- uint32_t format,
- uint32_t width,
- uint32_t height)
+static const struct ext_image_copy_capture_frame_v1_listener frame_listener = {
+ .transform = frame_handle_transform,
+ .damage = frame_handle_damage,
+ .presentation_time = frame_handle_presentation_time,
+ .ready = frame_handle_ready,
+ .failed = frame_handle_failed,
+};
+
+static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, TooltipMedia *tooltip_media)
{
-#ifdef HAVE_DMABUF
- TooltipMedia *tooltip_media = (TooltipMedia*)data;
+ auto format = (tooltip_media->current_buffer_format == WL_SHM_FORMAT_XRGB8888) ?
+ GBM_FORMAT_XRGB8888 : GBM_FORMAT_ARGB8888;
- if (!tooltip_media->window_list->live_previews_dmabuf)
+ if (tooltip_media->bo)
{
- return;
+ gbm_bo_destroy(tooltip_media->bo);
+ tooltip_media->bo = nullptr;
}
- tooltip_media->buffer_width = width;
- tooltip_media->buffer_height = height;
-
- if (!tooltip_media->buffer)
+ if (tooltip_media->params)
{
- if (tooltip_media->bo)
- {
- if (tooltip_media->buffer)
- {
- wl_buffer_destroy(tooltip_media->buffer);
- tooltip_media->buffer = nullptr;
- }
+ zwp_linux_buffer_params_v1_destroy(tooltip_media->params);
+ tooltip_media->params = nullptr;
+ }
- if (tooltip_media->params)
- {
- zwp_linux_buffer_params_v1_destroy(tooltip_media->params);
- tooltip_media->params = nullptr;
- }
+ auto w = width;
+ auto h = height;
- if (tooltip_media->bo)
- {
- gbm_bo_destroy(tooltip_media->bo);
- tooltip_media->bo = nullptr;
- }
- }
+ const uint64_t modifier = 0; // DRM_FORMAT_MOD_LINEAR
+ tooltip_media->bo = gbm_bo_create_with_modifiers(tooltip_media->window_list->dmabuf_device, w, h,
+ format, &modifier, 1);
+ if (tooltip_media->bo == NULL)
+ {
+ tooltip_media->bo = gbm_bo_create(tooltip_media->window_list->dmabuf_device, w, h,
+ format, GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING);
+ }
- const uint64_t modifier = 0; // DRM_FORMAT_MOD_LINEAR
- tooltip_media->bo = gbm_bo_create_with_modifiers(tooltip_media->window_list->dmabuf_device,
- tooltip_media->buffer_width,
- tooltip_media->buffer_height, format, &modifier, 1);
- if (!tooltip_media->bo)
- {
- tooltip_media->bo = gbm_bo_create(tooltip_media->window_list->dmabuf_device,
- tooltip_media->buffer_width,
- tooltip_media->buffer_height, format, GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING);
- }
+ if (tooltip_media->bo == NULL)
+ {
+ perror("failed to create gbm bo");
+ return;
+ }
- if (!tooltip_media->bo)
- {
- perror("Failed to create gbm bo");
- std::cerr << "Trying shm" << std::endl;
- tooltip_media->window_list->live_previews_dmabuf = false;
- return;
- }
+ tooltip_media->width = gbm_bo_get_width(tooltip_media->bo);
+ tooltip_media->height = gbm_bo_get_height(tooltip_media->bo);
+ tooltip_media->stride = gbm_bo_get_stride(tooltip_media->bo);
+ tooltip_media->params = zwp_linux_dmabuf_v1_create_params(tooltip_media->window_list->dmabuf);
- tooltip_media->buffer_stride = gbm_bo_get_stride(tooltip_media->bo);
+ uint64_t mod = gbm_bo_get_modifier(tooltip_media->bo);
+ zwp_linux_buffer_params_v1_add(tooltip_media->params,
+ gbm_bo_get_fd(tooltip_media->bo), 0,
+ gbm_bo_get_offset(tooltip_media->bo, 0),
+ gbm_bo_get_stride(tooltip_media->bo),
+ mod >> 32, mod & 0xffffffff);
- tooltip_media->params = zwp_linux_dmabuf_v1_create_params(tooltip_media->window_list->dmabuf);
+ zwp_linux_buffer_params_v1_add_listener(tooltip_media->params, ¶ms_listener, tooltip_media);
+ zwp_linux_buffer_params_v1_create(tooltip_media->params, w, h, format, 0);
+}
- uint64_t mod = gbm_bo_get_modifier(tooltip_media->bo);
- zwp_linux_buffer_params_v1_add(tooltip_media->params,
- gbm_bo_get_fd(tooltip_media->bo), 0,
- gbm_bo_get_offset(tooltip_media->bo, 0),
- gbm_bo_get_stride(tooltip_media->bo),
- mod >> 32, mod & 0xffffffff);
+void TooltipMedia::request_next_frame()
+{
+ if ((current_buffer_width <= 0) || (current_buffer_height <= 0))
+ {
+ return;
+ }
- zwp_linux_buffer_params_v1_add_listener(tooltip_media->params, ¶ms_listener, tooltip_media);
- zwp_linux_buffer_params_v1_create(tooltip_media->params, tooltip_media->buffer_width,
- tooltip_media->buffer_height, format, 0);
- } else
+ if (!recording_session)
{
- zwlr_screencopy_frame_v1_copy(frame, tooltip_media->buffer);
+ return;
}
-#endif // HAVE_DMABUF
-}
+ bool dirty = (width != current_buffer_width) || (height != current_buffer_height) ||
+ !buffer;
-void handle_frame_buffer_done(void*, struct zwlr_screencopy_frame_v1*)
-{}
+ width = current_buffer_width;
+ height = current_buffer_height;
-static struct zwlr_screencopy_frame_v1_listener screencopy_frame_listener =
-{
- handle_frame_buffer,
- handle_frame_flags,
- handle_frame_ready,
- handle_frame_failed,
- handle_frame_damage,
- handle_frame_linux_dmabuf,
- handle_frame_buffer_done,
-};
+ if (dirty)
+ {
+ frame_handle_linux_dmabuf(width, height, this);
+ }
-bool TooltipMedia::request_next_frame()
-{
- if (this->frame)
+ if (!buffer)
{
- zwlr_screencopy_frame_v1_destroy(this->frame);
- this->frame = nullptr;
+ return;
}
- if (!WayfireShellApp::get().live_preview_output)
+ if (frame_in_flight)
{
- return false;
+ return;
+ }
+
+ if (frame)
+ {
+ ext_image_copy_capture_frame_v1_destroy(frame);
+ frame = NULL;
}
- this->frame = zwlr_screencopy_manager_v1_capture_output(this->window_list->screencopy_manager, 0,
- WayfireShellApp::get().live_preview_output);
- zwlr_screencopy_frame_v1_add_listener(this->frame, &screencopy_frame_listener, this);
+ frame = ext_image_copy_capture_session_v1_create_frame(recording_session);
+ frame = frame;
+
+ ext_image_copy_capture_frame_v1_add_listener(frame, &frame_listener, this);
+ ext_image_copy_capture_frame_v1_attach_buffer(frame, buffer);
+ ext_image_copy_capture_frame_v1_damage_buffer(frame, 0, 0, width, height);
+ ext_image_copy_capture_frame_v1_capture(frame);
+ frame_in_flight = true;
+}
- return true;
+void TooltipMedia::start_toplevel_source_session()
+{
+ copy_capture_source = ext_foreign_toplevel_image_capture_source_manager_v1_create_source(
+ this->window_list->toplevel_capture_manager,
+ this->ext_handle);
+ recording_session = ext_image_copy_capture_manager_v1_create_session(
+ this->window_list->copy_capture_manager,
+ copy_capture_source, 0);
+ ext_image_copy_capture_session_v1_add_listener(recording_session, &recording_session_listener, this);
}
-TooltipMedia::TooltipMedia(WayfireWindowList *window_list)
+TooltipMedia::TooltipMedia(WayfireWindowList *window_list, ext_foreign_toplevel_handle_v1 *ext_handle)
{
this->window_list = window_list;
- this->shm = window_list->shm;
+ this->ext_handle = ext_handle;
+ set_can_shrink(true);
+ set_content_fit(Gtk::ContentFit::CONTAIN);
+ set_vexpand(false);
+ set_hexpand(false);
+ set_size_request(200, -1);
+
+ start_toplevel_source_session();
- this->add_tick_callback([=] (const Glib::RefPtr& clock)
+ timer_connection = Glib::signal_timeout().connect(
+ [this] ()
{
- return !this->request_next_frame();
- });
+ if (!timer_continue)
+ {
+ return false;
+ }
+
+ this->request_next_frame();
+
+ return true;
+ }, 20);
}
TooltipMedia::~TooltipMedia()
{
- if (this->frame)
+ timer_connection.disconnect();
+ timer_continue = false;
+
+ if (frame)
{
- zwlr_screencopy_frame_v1_destroy(this->frame);
+ ext_image_copy_capture_frame_v1_destroy(frame);
}
- if (
-#ifdef HAVE_DMABUF
- !this->window_list->live_previews_dmabuf &&
-#endif // HAVE_DMABUF
- this->shm_data && this->size)
+ if (copy_capture_source)
{
- if (munmap(this->shm_data, this->size) < 0)
- {
- perror("munmap failed");
- }
+ ext_image_capture_source_v1_destroy(copy_capture_source);
+ }
+
+ if (recording_session)
+ {
+ ext_image_copy_capture_session_v1_destroy(recording_session);
}
if (this->buffer)
@@ -365,7 +347,6 @@ TooltipMedia::~TooltipMedia()
wl_buffer_destroy(this->buffer);
}
-#ifdef HAVE_DMABUF
if (this->params)
{
zwp_linux_buffer_params_v1_destroy(this->params);
@@ -380,13 +361,12 @@ TooltipMedia::~TooltipMedia()
{
gbm_bo_destroy(this->bo);
}
-
-#endif // HAVE_DMABUF
}
class WayfireToplevel::impl
{
zwlr_foreign_toplevel_handle_v1 *handle, *parent;
+ ext_foreign_toplevel_handle_v1 *ext_handle = NULL;
std::vector children;
uint32_t state;
uint64_t view_id;
@@ -511,56 +491,13 @@ class WayfireToplevel::impl
auto motion_controller = Gtk::EventControllerMotion::create();
button_leave_signal = motion_controller->signal_leave().connect([=] ()
{
- wf::json_t live_window_release_output_request;
- live_window_release_output_request["method"] = "live_previews/release_output";
- this->window_list->ipc_client->send(live_window_release_output_request.serialize(),
- [=] (wf::json_t data)
- {
- unset_tooltip_media();
- this->window_list->live_window_preview_view_id = 0;
- if (data.serialize().find("error") != std::string::npos)
- {
- if (this->window_list->live_window_preview_tooltips)
- {
- std::cerr <<
- "Error releasing output for live preview stream! (is live-previews plugin disabled?)"
- <<
- std::endl;
- }
-
- this->window_list->enable_normal_tooltips_flag(true);
- return;
- }
- });
+ unset_tooltip_media();
});
button.add_controller(motion_controller);
motion_controller = Gtk::EventControllerMotion::create();
signals.push_back(motion_controller->signal_enter().connect([=] (double x, double y)
{
- wf::json_t live_window_preview_stream_request;
- live_window_preview_stream_request["method"] = "live_previews/request_stream";
- wf::json_t view_id_int;
- view_id_int["id"] = this->view_id;
- live_window_preview_stream_request["data"] = view_id_int;
- this->window_list->ipc_client->send(live_window_preview_stream_request.serialize(),
- [=] (wf::json_t data)
- {
- if ((data.serialize().find("error") != std::string::npos) &&
- this->window_list->live_window_preview_tooltips)
- {
- std::cerr << data.serialize() << std::endl;
- std::cerr <<
- "Error acquiring live preview stream. (is live-previews wayfire plugin enabled?)" <<
- std::endl;
- this->window_list->enable_normal_tooltips_flag(true);
- button.set_tooltip_text(title);
-
- return;
- }
-
- set_tooltip_media();
- update_tooltip();
- });
+ set_tooltip_media();
}));
button.add_controller(motion_controller);
button.set_tooltip_text("none");
@@ -572,7 +509,6 @@ class WayfireToplevel::impl
return query_tooltip(x, y, keyboard_mode, tooltip);
}, false));
button.set_has_tooltip(true);
- update_tooltip();
send_rectangle_hints();
set_state(0); // will set the appropriate button style
@@ -580,12 +516,13 @@ class WayfireToplevel::impl
void set_tooltip_media()
{
- if (this->tooltip_media)
+ if (this->tooltip_media || !this->window_list->toplevel_capture_manager ||
+ !(bool)window_list->live_window_previews || !this->ext_handle)
{
return;
}
- this->tooltip_media = Gtk::make_managed(this->window_list);
+ this->tooltip_media = Gtk::make_managed(this->window_list, this->ext_handle);
this->custom_tooltip_content.append(*this->tooltip_media);
}
@@ -600,68 +537,14 @@ class WayfireToplevel::impl
this->tooltip_media = nullptr;
}
- void update_tooltip()
+ ext_foreign_toplevel_handle_v1 *get_ext_handle()
{
- wf::json_t ipc_methods_request;
- ipc_methods_request["method"] = "list-methods";
- this->window_list->ipc_client->send(ipc_methods_request.serialize(), [=] (wf::json_t data)
- {
- if (data.serialize().find("error") != std::string::npos)
- {
- std::cerr << "Error getting ipc methods list!" << std::endl;
- this->window_list->enable_normal_tooltips_flag(true);
- return;
- }
+ return this->ext_handle;
+ }
- if ((data.serialize().find("live_previews/request_stream") == std::string::npos) ||
- (data.serialize().find("live_previews/release_output") == std::string::npos))
- {
- unset_tooltip_media();
- if (this->window_list->live_window_preview_tooltips)
- {
- if (this->window_list->live_window_previews_opt)
- {
- std::cout << "wf-shell configuration [panel] option 'live_window_previews' is set to 'true' but live-previews wayfire plugin is disabled." << std::endl;
- this->window_list->enable_normal_tooltips_flag(true);
- }
-
- for (const auto& toplevel_button : this->window_list->toplevels)
- {
- if (toplevel_button.second && toplevel_button.second->pimpl)
- {
- toplevel_button.second->unset_tooltip_media();
- }
- }
- }
- } else
- {
- set_tooltip_media();
- if (!this->window_list->live_window_preview_tooltips)
- {
- if (!this->window_list->live_window_previews_opt)
- {
- std::cout << "Detected live-previews plugin is enabled but wf-shell configuration [panel] option 'live_window_previews' is set to 'false'." << std::endl;
- } else
- {
- std::cout << "Enabling live window preview tooltips." << std::endl;
- }
-
- this->window_list->enable_normal_tooltips_flag(false);
- for (const auto& toplevel_button : this->window_list->toplevels)
- {
- if (toplevel_button.second && toplevel_button.second->pimpl)
- {
- toplevel_button.second->set_tooltip_media();
- }
- }
- }
- }
- });
- if (!this->window_list->live_window_previews_enabled())
- {
- this->window_list->normal_title_tooltips = true;
- button.set_tooltip_text(title);
- }
+ void set_ext_handle(ext_foreign_toplevel_handle_v1 *handle)
+ {
+ this->ext_handle = handle;
}
int grab_off_x;
@@ -832,60 +715,23 @@ class WayfireToplevel::impl
return false;
}
- if (!this->window_list->live_window_previews_enabled())
+ if (this->window_list->list_toplevels.empty() || !this->window_list->toplevel_capture_manager ||
+ !(bool)window_list->live_window_previews || !this->ext_handle)
{
- if (!this->window_list->normal_title_tooltips)
- {
- std::cerr <<
- "Normal title tooltips enabled. To enable live window preview tooltips, make sure to set [panel] option 'live_window_previews = true' in wf-shell configuration and enable wayfire plugin live-previews"
- <<
- std::endl;
- this->window_list->enable_normal_tooltips_flag(true);
- }
-
tooltip->set_text(title);
- return true;
}
- this->window_list->live_window_preview_view_id = this->view_id;
tooltip->set_custom(this->custom_tooltip_content);
return true;
}
- uint64_t get_view_id_from_full_app_id(const std::string& app_id)
- {
- const std::string sub_str = "wf-ipc-";
- size_t pos = app_id.find(sub_str);
-
- if (pos != std::string::npos)
- {
- size_t suffix_start_index = pos + sub_str.length();
- if (suffix_start_index < app_id.length())
- {
- try {
- uint64_t view_id = std::stoi(app_id.substr(suffix_start_index, std::string::npos));
- return view_id;
- } catch (...)
- {
- return 0;
- }
- } else
- {
- return 0;
- }
- } else
- {
- return 0;
- }
- }
-
void set_app_id(std::string app_id)
{
WfOption minimal_panel_height{"panel/minimal_height"};
this->app_id = app_id;
IconProvider::image_set_icon(image, app_id);
- this->view_id = get_view_id_from_full_app_id(app_id);
+ this->view_id = this->window_list->get_view_id_from_full_app_id(app_id);
if (this->view_id == 0)
{
std::cerr << "Failed to get view id from app_id. " <<
@@ -895,6 +741,11 @@ class WayfireToplevel::impl
}
}
+ std::string get_app_id()
+ {
+ return this->app_id;
+ }
+
void send_rectangle_hints()
{
for (const auto& toplevel_button : window_list->toplevels)
@@ -923,10 +774,6 @@ class WayfireToplevel::impl
void set_title(std::string title)
{
this->title = title;
- if (!this->window_list->live_window_previews_enabled())
- {
- button.set_tooltip_text(title);
- }
label.set_text(title);
}
@@ -1104,6 +951,21 @@ void WayfireToplevel::unset_tooltip_media()
pimpl->unset_tooltip_media();
}
+ext_foreign_toplevel_handle_v1*WayfireToplevel::get_ext_handle()
+{
+ return pimpl->get_ext_handle();
+}
+
+void WayfireToplevel::set_ext_handle(ext_foreign_toplevel_handle_v1 *handle)
+{
+ pimpl->set_ext_handle(handle);
+}
+
+std::string WayfireToplevel::get_app_id()
+{
+ return pimpl->get_app_id();
+}
+
/* wl_array_for_each isn't supported in C++, so we have to manually
* get the data from wl_array, see:
*
@@ -1144,7 +1006,21 @@ static void handle_toplevel_state(void *data, toplevel_t, wl_array *state)
}
static void handle_toplevel_done(void *data, toplevel_t)
-{}
+{
+ auto impl = static_cast(data);
+ auto window_list = impl->window_list;
+
+ auto wf_id = window_list->get_view_id_from_full_app_id(impl->get_app_id());
+ for (auto & list_toplevel : window_list->list_toplevels)
+ {
+ auto id = window_list->get_view_id_from_full_app_id(list_toplevel.second->app_id);
+ if (wf_id == id)
+ {
+ impl->set_ext_handle(list_toplevel.first);
+ break;
+ }
+ }
+}
static void remove_child_from_parent(WayfireToplevel::impl *impl, toplevel_t child)
{
diff --git a/src/panel/widgets/window-list/toplevel.hpp b/src/panel/widgets/window-list/toplevel.hpp
index fc544a33..8baa92ef 100644
--- a/src/panel/widgets/window-list/toplevel.hpp
+++ b/src/panel/widgets/window-list/toplevel.hpp
@@ -1,23 +1,22 @@
#pragma once
+#include
+#include
#include
#include
#include
#include
#include
#include
-#include
+#include
+#include
+#include
+#include
#include
#include
#include "wf-shell-app.hpp"
#include "panel.hpp"
-#ifdef HAVE_DMABUF
- #include
- #include
- #include
-#endif // HAVE_DMABUF
-
class WayfireWindowList;
class WayfireWindowListBox;
@@ -32,26 +31,29 @@ class TooltipMedia : public Gtk::Picture
{
public:
WayfireWindowList *window_list = nullptr;
- wl_shm *shm = nullptr;
wl_buffer *buffer = nullptr;
- void *shm_data = nullptr;
- zwlr_screencopy_frame_v1 *frame = nullptr;
- uint32_t buffer_width;
- uint32_t buffer_height;
- uint32_t buffer_stride;
- size_t size = 0;
+ ext_foreign_toplevel_handle_v1 *ext_handle = NULL;
+ ext_image_copy_capture_frame_v1 *frame = NULL;
+ ext_image_capture_source_v1 *copy_capture_source = NULL;
+ ext_image_copy_capture_session_v1 *recording_session = NULL;
+ sigc::connection timer_connection;
+ bool frame_in_flight = false;
+ bool timer_continue = true;
+ uint32_t current_buffer_format = GBM_FORMAT_ARGB8888;
+ uint32_t current_buffer_width = 0, width = -1;
+ uint32_t current_buffer_height = 0, height = -1;
+ uint32_t stride;
-#ifdef HAVE_DMABUF
gbm_bo *bo = nullptr;
zwp_linux_buffer_params_v1 *params = nullptr;
void *dmabuf_data = nullptr;
- void *map_data = nullptr;
-#endif // HAVE_DMABUF
+ void *map_data = nullptr;
- TooltipMedia(WayfireWindowList *window_list);
+ TooltipMedia(WayfireWindowList *window_list, ext_foreign_toplevel_handle_v1 *ext_handle);
~TooltipMedia();
- bool request_next_frame();
+ void start_toplevel_source_session();
+ void request_next_frame();
};
/* Represents a single opened toplevel window.
@@ -62,12 +64,15 @@ class WayfireToplevel
WayfireToplevel(WayfireWindowList *window_list, zwlr_foreign_toplevel_handle_v1 *handle);
uint32_t get_state();
+ std::string get_app_id();
void send_rectangle_hint();
std::vector& get_children();
~WayfireToplevel();
void set_hide_text(bool hide_text);
void set_tooltip_media();
void unset_tooltip_media();
+ void set_ext_handle(ext_foreign_toplevel_handle_v1 *handle);
+ ext_foreign_toplevel_handle_v1 *get_ext_handle();
class impl;
diff --git a/src/panel/widgets/window-list/window-list.cpp b/src/panel/widgets/window-list/window-list.cpp
index 3fa0b958..9d38a7d1 100644
--- a/src/panel/widgets/window-list/window-list.cpp
+++ b/src/panel/widgets/window-list/window-list.cpp
@@ -4,9 +4,7 @@
#include "window-list.hpp"
-#ifdef HAVE_DMABUF
- #include
-#endif // HAVE_DMABUF
+#include
#define DEFAULT_SIZE_PC 0.1
@@ -28,7 +26,115 @@ zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_v1_impl = {
.finished = handle_manager_finished,
};
-#ifdef HAVE_DMABUF
+/* Toplevel Callbacks */
+
+static void toplevel_handle_closed(void *data,
+ struct ext_foreign_toplevel_handle_v1 *handle)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+ for (auto & toplevel : window_list->toplevels)
+ {
+ if (!toplevel.second)
+ {
+ continue;
+ }
+
+ if (toplevel.second->get_ext_handle() == handle)
+ {
+ toplevel.second->set_ext_handle(NULL);
+ break;
+ }
+ }
+
+ ext_foreign_toplevel_handle_v1_destroy(handle);
+ window_list->list_toplevels.erase(handle);
+}
+
+static void toplevel_handle_done(void *data,
+ struct ext_foreign_toplevel_handle_v1 *handle)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+
+ for (auto & toplevel : window_list->toplevels)
+ {
+ if (!toplevel.second)
+ {
+ continue;
+ }
+
+ auto wf_id = window_list->get_view_id_from_full_app_id(toplevel.second->get_app_id());
+ for (auto & list_toplevel : window_list->list_toplevels)
+ {
+ if (!list_toplevel.second)
+ {
+ continue;
+ }
+
+ auto id = window_list->get_view_id_from_full_app_id(list_toplevel.second->app_id);
+ if (wf_id == id)
+ {
+ toplevel.second->set_ext_handle(list_toplevel.first);
+ break;
+ }
+ }
+ }
+}
+
+static void toplevel_handle_title(void *data,
+ struct ext_foreign_toplevel_handle_v1 *handle,
+ const char *title)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+ window_list->list_toplevels[handle]->title = title;
+}
+
+static void toplevel_handle_app_id(void *data,
+ struct ext_foreign_toplevel_handle_v1 *handle,
+ const char *app_id)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+ window_list->list_toplevels[handle]->app_id = app_id;
+}
+
+static void toplevel_handle_identifier(void *data,
+ struct ext_foreign_toplevel_handle_v1 *handle,
+ const char *identifier)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+ window_list->list_toplevels[handle]->identifier = identifier;
+}
+
+ext_foreign_toplevel_handle_v1_listener toplevels_listener =
+{
+ .closed = toplevel_handle_closed,
+ .done = toplevel_handle_done,
+ .title = toplevel_handle_title,
+ .app_id = toplevel_handle_app_id,
+ .identifier = toplevel_handle_identifier,
+};
+
+/* Static callbacks for toplevel list object */
+static void handle_toplevel(void *data,
+ struct ext_foreign_toplevel_list_v1 *list,
+ struct ext_foreign_toplevel_handle_v1 *handle)
+{
+ WayfireWindowList *window_list = (WayfireWindowList*)data;
+ window_list->list_toplevels[handle] = std::make_unique();
+ ext_foreign_toplevel_handle_v1_add_listener(handle, &toplevels_listener, window_list);
+}
+
+static void handle_finished(void *data,
+ struct ext_foreign_toplevel_list_v1 *list)
+{
+ ext_foreign_toplevel_list_v1_stop(list);
+ ext_foreign_toplevel_list_v1_destroy(list);
+}
+
+ext_foreign_toplevel_list_v1_listener toplevel_list_v1_impl = {
+ .toplevel = handle_toplevel,
+ .finished = handle_finished,
+};
+
static void dmabuf_feedback_done(void *data, struct zwp_linux_dmabuf_feedback_v1 *feedback)
{
WayfireWindowList *window_list = (WayfireWindowList*)data;
@@ -58,7 +164,6 @@ static void dmabuf_feedback_main_device(void *data, struct zwp_linux_dmabuf_feed
{
perror("Failed to get DRM device from dev id");
std::cerr << "Trying shm" << std::endl;
- window_list->live_previews_dmabuf = false;
return;
}
@@ -75,7 +180,6 @@ static void dmabuf_feedback_main_device(void *data, struct zwp_linux_dmabuf_feed
{
perror("Failed to open drm device");
std::cerr << "Trying shm" << std::endl;
- window_list->live_previews_dmabuf = false;
return;
}
@@ -85,7 +189,6 @@ static void dmabuf_feedback_main_device(void *data, struct zwp_linux_dmabuf_feed
close(drm_fd);
perror("Failed to create gbm device");
std::cerr << "Trying shm" << std::endl;
- window_list->live_previews_dmabuf = false;
return;
}
@@ -119,17 +222,13 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_feedback_listen
.tranche_formats = dmabuf_feedback_tranche_formats,
.tranche_flags = dmabuf_feedback_tranche_flags,
};
-#endif // HAVE_DMABUF
static void registry_add_object(void *data, wl_registry *registry, uint32_t name,
const char *interface, uint32_t version)
{
WayfireWindowList *window_list = (WayfireWindowList*)data;
- if (strcmp(interface, wl_shm_interface.name) == 0)
- {
- window_list->shm = (wl_shm*)wl_registry_bind(registry, name, &wl_shm_interface, version);
- } else if (strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0)
+ if (strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0)
{
auto zwlr_toplevel_manager = (zwlr_foreign_toplevel_manager_v1*)
wl_registry_bind(registry, name,
@@ -138,16 +237,28 @@ static void registry_add_object(void *data, wl_registry *registry, uint32_t name
window_list->handle_toplevel_manager(zwlr_toplevel_manager);
zwlr_foreign_toplevel_manager_v1_add_listener(window_list->manager,
&toplevel_manager_v1_impl, window_list);
- wl_display_roundtrip(window_list->display);
- } else if (strcmp(interface, zwlr_screencopy_manager_v1_interface.name) == 0)
+ } else if (strcmp(interface, ext_foreign_toplevel_list_v1_interface.name) == 0)
{
- window_list->screencopy_manager = (zwlr_screencopy_manager_v1*)wl_registry_bind(registry, name,
- &zwlr_screencopy_manager_v1_interface,
+ auto foreign_toplevel_list = (ext_foreign_toplevel_list_v1*)
+ wl_registry_bind(registry, name,
+ &ext_foreign_toplevel_list_v1_interface,
version);
- }
-
-#ifdef HAVE_DMABUF
- else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0)
+ window_list->foreign_toplevel_list = foreign_toplevel_list;
+ ext_foreign_toplevel_list_v1_add_listener(foreign_toplevel_list,
+ &toplevel_list_v1_impl, window_list);
+ } else if (strcmp(interface, ext_image_copy_capture_manager_v1_interface.name) == 0)
+ {
+ auto copy_capture_manager = (ext_image_copy_capture_manager_v1*)wl_registry_bind(registry, name,
+ &ext_image_copy_capture_manager_v1_interface, version);
+ window_list->copy_capture_manager = copy_capture_manager;
+ } else if (strcmp(interface, ext_foreign_toplevel_image_capture_source_manager_v1_interface.name) == 0)
+ {
+ auto toplevel_capture_manager =
+ (ext_foreign_toplevel_image_capture_source_manager_v1*)wl_registry_bind(registry, name,
+ &ext_foreign_toplevel_image_capture_source_manager_v1_interface, version);
+ window_list->toplevel_capture_manager = toplevel_capture_manager;
+ printf("set toplevel_capture_manager: %p\n", toplevel_capture_manager);
+ } else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0)
{
window_list->dmabuf = (zwp_linux_dmabuf_v1*)wl_registry_bind(registry, name,
&zwp_linux_dmabuf_v1_interface, version);
@@ -158,7 +269,6 @@ static void registry_add_object(void *data, wl_registry *registry, uint32_t name
window_list);
}
}
-#endif // HAVE_DMABUF
}
static void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name)
@@ -170,107 +280,65 @@ static struct wl_registry_listener registry_listener =
®istry_remove_object
};
-void WayfireWindowList::live_window_previews_plugin_check()
+uint64_t WayfireWindowList::get_view_id_from_full_app_id(const std::string& app_id)
{
- wf::json_t ipc_methods_request;
- ipc_methods_request["method"] = "list-methods";
- this->ipc_client->send(ipc_methods_request.serialize(), [=] (wf::json_t data)
- {
- if (data.serialize().find(
- "error") != std::string::npos)
- {
- std::cerr << "Error getting ipc methods list! (are ipc and ipc-rules plugins loaded?)" << std::endl;
- this->enable_normal_tooltips_flag(true);
- return;
- }
+ const std::string sub_str = "wf-ipc-";
+ size_t pos = app_id.find(sub_str);
- if ((data.serialize().find("live_previews/request_stream") == std::string::npos) ||
- (data.serialize().find(
- "live_previews/release_output") == std::string::npos))
- {
- std::cerr << "Did not find live-previews ipc methods in methods list. Disabling live window preview tooltips. (is the live-previews plugin enabled?)" << std::endl;
- this->enable_normal_tooltips_flag(
- true);
- } else
+ if (pos != std::string::npos)
+ {
+ size_t suffix_start_index = pos + sub_str.length();
+ if (suffix_start_index < app_id.length())
{
- if (!this->live_window_previews_opt)
- {
- std::cout << "Detected live-previews plugin is enabled but wf-shell configuration [panel] option 'live_window_previews' is set to 'false'." << std::endl;
- this->enable_normal_tooltips_flag(
- true);
- } else
+ try {
+ uint64_t view_id = std::stoi(app_id.substr(suffix_start_index, std::string::npos));
+ return view_id;
+ } catch (...)
{
- std::cout << "Enabling live window preview tooltips using " <<
- std::string(live_previews_dmabuf ? "dmabuf" : "shm") <<
- " transfers on output " << this->output->monitor->get_connector() <<
- std::endl;
- this->enable_normal_tooltips_flag(false);
+ return 0;
}
+ } else
+ {
+ return 0;
}
- });
-}
-
-void WayfireWindowList::enable_ipc(bool enable)
-{
- if (!this->ipc_client)
- {
- this->ipc_client = WayfirePanelApp::get().get_ipc_server_instance()->create_client();
- }
-
- if (!this->ipc_client)
+ } else
{
- std::cerr <<
- "Failed to connect to ipc. Live window previews will not be available. (are ipc and ipc-rules plugins loaded?)";
+ return 0;
}
}
-void WayfireWindowList::enable_normal_tooltips_flag(bool enable)
-{
- this->normal_title_tooltips = enable;
- this->live_window_preview_tooltips = !enable;
-}
-
-bool WayfireWindowList::live_window_previews_enabled()
-{
- return this->live_window_previews_opt && this->live_window_preview_tooltips && this->ipc_client;
-}
-
void WayfireWindowList::init(Gtk::Box *container)
{
- enable_ipc(this->live_window_previews_opt);
- live_window_previews_plugin_check();
-
- this->live_window_previews_opt.set_callback([=] ()
- {
- enable_ipc(this->live_window_previews_opt);
- live_window_previews_plugin_check();
- });
-
auto gdk_display = gdk_display_get_default();
auto display = gdk_wayland_display_get_wl_display(gdk_display);
this->display = display;
- wl_registry *registry = wl_display_get_registry(display);
+ registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, ®istry_listener, this);
wl_display_roundtrip(display);
- wl_registry_destroy(registry);
-
if (!this->manager)
{
std::cerr << "Compositor doesn't support" <<
- " wlr-foreign-toplevel-management." <<
+ " ext-image-copy-capture-v1." <<
"The window-list widget will not be initialized." << std::endl;
- wl_registry_destroy(registry);
return;
}
-#ifdef HAVE_DMABUF
- this->live_previews_dmabuf = this->dmabuf ? true : false;
-#else
- this->live_previews_dmabuf = false;
-#endif // HAVE_DMABUF
+ if (!this->foreign_toplevel_list)
+ {
+ std::cerr << "Compositor doesn't support" <<
+ " ext-foreign-toplevel-list-v1." <<
+ "Live window previews cannot be enabled." << std::endl;
+ }
+
+ if (!this->toplevel_capture_manager)
+ {
+ std::cerr << "Compositor doesn't support" <<
+ " ext-foreign-toplevel-image-copy-capture-v1." <<
+ "Live window previews cannot be enabled." << std::endl;
+ }
scrolled_window.add_css_class("window-list");
@@ -386,19 +454,16 @@ void WayfireWindowList::handle_toplevel_manager(zwlr_foreign_toplevel_manager_v1
this->manager = manager;
}
-void WayfireWindowList::handle_new_toplevel(zwlr_foreign_toplevel_handle_v1 *handle)
+void WayfireWindowList::handle_new_toplevel(zwlr_foreign_toplevel_handle_v1 *toplevel)
{
- toplevels[handle] = std::unique_ptr(new WayfireToplevel(this, handle));
+ toplevels[toplevel] = std::make_unique(this, toplevel);
}
-void WayfireWindowList::handle_toplevel_closed(zwlr_foreign_toplevel_handle_v1 *handle)
+void WayfireWindowList::handle_toplevel_closed(zwlr_foreign_toplevel_handle_v1 *toplevel)
{
- toplevels.erase(handle);
+ toplevels.erase(toplevel);
}
-void WayfireWindowList::on_event(wf::json_t data)
-{}
-
WayfireWindowList::WayfireWindowList(WayfireOutput *output)
{
this->output = output;
@@ -418,10 +483,35 @@ WayfireWindowList::~WayfireWindowList()
* when the window-list widget is unloaded. */
toplevels.clear();
- wl_shm_destroy(this->shm);
- zwlr_foreign_toplevel_manager_v1_destroy(this->manager);
- zwlr_screencopy_manager_v1_destroy(this->screencopy_manager);
-#ifdef HAVE_DMABUF
+ for (auto & list_toplevel : list_toplevels)
+ {
+ ext_foreign_toplevel_handle_v1_destroy(list_toplevel.first);
+ }
+
+ list_toplevels.clear();
+
+ wl_registry_destroy(registry);
+
+ if (this->manager)
+ {
+ zwlr_foreign_toplevel_manager_v1_destroy(this->manager);
+ }
+
+ if (this->foreign_toplevel_list)
+ {
+ ext_foreign_toplevel_list_v1_destroy(this->foreign_toplevel_list);
+ }
+
+ if (this->copy_capture_manager)
+ {
+ ext_image_copy_capture_manager_v1_destroy(this->copy_capture_manager);
+ }
+
+ if (this->toplevel_capture_manager)
+ {
+ ext_foreign_toplevel_image_capture_source_manager_v1_destroy(this->toplevel_capture_manager);
+ }
+
if (this->dmabuf)
{
zwp_linux_dmabuf_v1_destroy(this->dmabuf);
@@ -436,6 +526,4 @@ WayfireWindowList::~WayfireWindowList()
{
gbm_device_destroy(this->dmabuf_device);
}
-
-#endif
}
diff --git a/src/panel/widgets/window-list/window-list.hpp b/src/panel/widgets/window-list/window-list.hpp
index 5958bc34..daf31022 100644
--- a/src/panel/widgets/window-list/window-list.hpp
+++ b/src/panel/widgets/window-list/window-list.hpp
@@ -5,27 +5,37 @@
#include "../../widget.hpp"
#include "toplevel.hpp"
#include "layout.hpp"
-#include "wf-ipc.hpp"
#ifdef HAVE_DMABUF
#include
#endif // HAVE_DMABUF
+struct WayfireListToplevel
+{
+ std::string title;
+ std::string app_id;
+ std::string identifier;
+};
+
class WayfireToplevel;
-class WayfireWindowList : public Gtk::Box, public WayfireWidget, public IIPCSubscriber
+class WayfireWindowList : public Gtk::Box, public WayfireWidget
{
+ wl_display *display;
+ wl_registry *registry;
WfOption user_size{"panel/window_list_size"};
std::shared_ptr layout;
public:
std::map> toplevels;
+ std::map> list_toplevels;
- wl_display *display;
- wl_shm *shm = nullptr;
- zwlr_foreign_toplevel_manager_v1 *manager = nullptr;
- zwlr_screencopy_manager_v1 *screencopy_manager = nullptr;
+ zwlr_foreign_toplevel_manager_v1 *manager = NULL;
+ ext_foreign_toplevel_list_v1 *foreign_toplevel_list = NULL;
+ ext_image_copy_capture_manager_v1 *copy_capture_manager = NULL;
+ ext_foreign_toplevel_image_capture_source_manager_v1 *toplevel_capture_manager = NULL;
WayfireOutput *output;
Gtk::ScrolledWindow scrolled_window;
@@ -33,8 +43,10 @@ class WayfireWindowList : public Gtk::Box, public WayfireWidget, public IIPCSubs
virtual ~WayfireWindowList();
void handle_toplevel_manager(zwlr_foreign_toplevel_manager_v1 *manager);
+ void handle_new_toplevel(zwlr_foreign_toplevel_handle_v1 *toplevel);
void handle_toplevel_closed(zwlr_foreign_toplevel_handle_v1 *handle);
- void handle_new_toplevel(zwlr_foreign_toplevel_handle_v1 *handle);
+
+ uint64_t get_view_id_from_full_app_id(const std::string& app_id);
wayfire_config *get_config();
@@ -72,24 +84,12 @@ class WayfireWindowList : public Gtk::Box, public WayfireWidget, public IIPCSubs
*/
Gtk::Widget *get_widget_before(int x);
- WfOption live_window_previews_opt{"panel/live_window_previews"};
+ WfOption live_window_previews{"panel/live_window_previews"};
void handle_new_wl_output(wl_output *output);
- void on_event(wf::json_t data) override;
- std::shared_ptr ipc_client;
- bool live_window_preview_tooltips = false;
- bool normal_title_tooltips = false;
- void enable_normal_tooltips_flag(bool enable);
- uint64_t live_window_preview_view_id = 0;
- void live_window_previews_plugin_check();
- void enable_ipc(bool enable);
- bool live_window_previews_enabled();
- bool live_previews_dmabuf = true;
-#ifdef HAVE_DMABUF
zwp_linux_dmabuf_feedback_v1 *feedback = nullptr;
zwp_linux_dmabuf_v1 *dmabuf = nullptr;
gbm_device *dmabuf_device = nullptr;
-#endif // HAVE_DMABUF
private:
int get_default_button_width();