Skip to content
This repository was archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
vm_tools: sommelier: Attach xshape to window
Browse files Browse the repository at this point in the history
This patch adds the ability to listens to incoming shape events to
Sommelier. This data is then attached the appropriate window.

This is added to support subsequent patches which will perform
the necessary image manipulations in order to display the shaped
window correctly.

BUG=b:223232234
TEST=Ensured no crashes when using both regular and shaped applications

Change-Id: I86d5a9df940677c0782a5915fff6db053846b5f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3880723
Tested-by: Isaac Bosompem <[email protected]>
Reviewed-by: Nic Hollingum <[email protected]>
Commit-Queue: Isaac Bosompem <[email protected]>
  • Loading branch information
Isaac Bosompem authored and Chromeos LUCI committed Oct 6, 2022
1 parent 93e3af9 commit 836c972
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 1 deletion.
11 changes: 10 additions & 1 deletion BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ sommelier_defines = [
static_library("libgaming") {
sources = [ "sommelier-gaming.cc" ]
defines = gaming_defines
pkg_deps = [ "libevdev" ]
pkg_deps = [
"libevdev",
"pixman-1",
]
deps = [ ":sommelier-protocol" ]
}

Expand Down Expand Up @@ -104,6 +107,7 @@ static_library("libsommelier") {
"sommelier-viewporter.cc",
"sommelier-window.cc",
"sommelier-xdg-shell.cc",
"sommelier-xshape.cc",
"sommelier.cc",
"virtualization/virtgpu_channel.cc",
"virtualization/virtwl_channel.cc",
Expand Down Expand Up @@ -138,10 +142,13 @@ if (use.test) {
executable("sommelier_test") {
sources = [ "sommelier_test.cc" ]

pkg_deps = [ "pixman-1" ]

# gnlint: disable=GnLintCommonTesting
libs = [
"gmock",
"gtest",
"pixman-1",
]
defines = sommelier_defines
deps = [ ":libsommelier" ]
Expand All @@ -151,6 +158,8 @@ if (use.test) {
if (use.fuzzer) {
executable("sommelier_wayland_fuzzer") {
sources = [ "sommelier-wayland-fuzzer.cc" ]
pkg_deps = [ "pixman-1" ]
libs = [ "pixman-1" ]

configs += [ "//common-mk/common_fuzzer" ]

Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ libsommelier = static_library('sommelier',
'sommelier-util.cc',
'sommelier-viewporter.cc',
'sommelier-xdg-shell.cc',
'sommelier-xshape.cc',
'sommelier.cc',
'sommelier-window.cc',
'virtualization/virtwl_channel.cc',
Expand Down Expand Up @@ -180,6 +181,7 @@ if get_option('with_tests')
dependencies: [
dependency('gtest'),
dependency('gmock'),
dependency('pixman-1')
],
cpp_args: cpp_args + sommelier_defines,
include_directories: includes,
Expand Down
2 changes: 2 additions & 0 deletions sommelier-window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ sl_window::sl_window(struct sl_context* ctx,
height(height),
border_width(border_width) {
wl_list_insert(&ctx->unpaired_windows, &link);
pixman_region32_init(&shape_rectangles);
}

sl_window::~sl_window() {
Expand All @@ -49,6 +50,7 @@ sl_window::~sl_window() {
free(clazz);
free(startup_id);
wl_list_remove(&link);
pixman_region32_fini(&shape_rectangles);
}

void sl_configure_window(struct sl_window* window) {
Expand Down
3 changes: 3 additions & 0 deletions sommelier-window.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef VM_TOOLS_SOMMELIER_SOMMELIER_WINDOW_H_
#define VM_TOOLS_SOMMELIER_SOMMELIER_WINDOW_H_

#include <pixman.h>
#include <wayland-server-core.h>
#include <string>
#include <xcb/xcb.h>
Expand Down Expand Up @@ -45,6 +46,7 @@ struct sl_window {
xcb_window_t frame_id = XCB_WINDOW_NONE;
uint32_t host_surface_id = 0;
int unpaired = 1;
bool shaped = false;
int x = 0;
int y = 0;
int width = 0;
Expand Down Expand Up @@ -81,6 +83,7 @@ struct sl_window {
struct xdg_popup* xdg_popup = nullptr;
struct zaura_surface* aura_surface = nullptr;
struct sl_host_surface* paired_surface = nullptr;
struct pixman_region32 shape_rectangles;
struct wl_list link = {};
};

Expand Down
100 changes: 100 additions & 0 deletions sommelier-xshape.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <assert.h>
#include <pixman.h>

#include "sommelier.h" // NOLINT(build/include_directory)
#include "sommelier-tracing.h" // NOLINT(build/include_directory)
#include "sommelier-xshape.h" // NOLINT(build/include_directory)

static void sl_clear_shape_region(sl_window* window) {
window->shaped = false;
pixman_region32_fini(&window->shape_rectangles);
}

static void sl_attach_shape_region(struct sl_context* ctx,
xcb_window_t window) {
sl_window* sl_window = nullptr;
xcb_shape_get_rectangles_reply_t* reply;
int i;

sl_window = sl_lookup_window(ctx, window);
if (!sl_window)
return;

reply = xcb_shape_get_rectangles_reply(
ctx->connection,
xcb_shape_get_rectangles(ctx->connection, window, XCB_SHAPE_SK_BOUNDING),
NULL);

if (!reply)
return;

int nrects = xcb_shape_get_rectangles_rectangles_length(reply);
xcb_rectangle_t* rects = xcb_shape_get_rectangles_rectangles(reply);

if (!rects || nrects <= 0)
return;

pixman_box32_t* boxes =
static_cast<pixman_box32_t*>(calloc(sizeof(pixman_box32_t), nrects));

if (!boxes) {
free(reply);
return;
}

for (i = 0; i < nrects; i++) {
boxes[i].x1 = rects[i].x;
boxes[i].y1 = rects[i].y;

boxes[i].x2 = rects[i].x + rects[i].width;
boxes[i].y2 = rects[i].y + rects[i].height;
}

pixman_region32_init_rects(&sl_window->shape_rectangles, boxes, nrects);
free(boxes);
free(reply);

sl_window->shaped = true;
}

void sl_handle_shape_notify(struct sl_context* ctx,
struct xcb_shape_notify_event_t* event) {
sl_window* window = nullptr;

window = sl_lookup_window(ctx, event->affected_window);

if (!window)
return;

sl_clear_shape_region(window);

if (event->shaped)
sl_attach_shape_region(ctx, event->affected_window);

return;
}

void sl_shape_query(struct sl_context* ctx, xcb_window_t xwindow) {
xcb_shape_query_extents_reply_t* reply;
sl_window* sl_window = nullptr;

sl_window = sl_lookup_window(ctx, xwindow);
if (!sl_window)
return;

reply = xcb_shape_query_extents_reply(
ctx->connection, xcb_shape_query_extents(ctx->connection, xwindow), NULL);

if (!reply)
return;

sl_clear_shape_region(sl_window);

if (reply->bounding_shaped) {
sl_attach_shape_region(ctx, xwindow);
}
}
17 changes: 17 additions & 0 deletions sommelier-xshape.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef VM_TOOLS_SOMMELIER_SOMMELIER_XSHAPE_H_
#define VM_TOOLS_SOMMELIER_SOMMELIER_XSHAPE_H_

#include <xcb/shape.h>
#include <xcb/xcb.h>
#include "sommelier-ctx.h" // NOLINT(build/include_directory)

void sl_handle_shape_notify(struct sl_context* ctx,
struct xcb_shape_notify_event_t* event);

void sl_shape_query(struct sl_context* ctx, xcb_window_t xwindow);

#endif // VM_TOOLS_SOMMELIER_SOMMELIER_XSHAPE_H_
21 changes: 21 additions & 0 deletions sommelier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "sommelier.h" // NOLINT(build/include_directory)
#include "sommelier-tracing.h" // NOLINT(build/include_directory)
#include "sommelier-transform.h" // NOLINT(build/include_directory)
#include "sommelier-xshape.h" // NOLINT(build/include_directory)

#include <assert.h>
#include <errno.h>
Expand Down Expand Up @@ -876,6 +877,11 @@ void sl_create_window(struct sl_context* ctx,
values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE;
xcb_change_window_attributes(ctx->connection, window->id, XCB_CW_EVENT_MASK,
values);

// Also enable shape events for this window to come in if the xshape
// flag has been enabled
if (ctx->enable_xshape)
xcb_shape_select_input(ctx->connection, id, 1);
}

static void sl_destroy_window(struct sl_window* window) {
Expand Down Expand Up @@ -2661,6 +2667,21 @@ static int sl_handle_x_connection_event(int fd, uint32_t mask, void* data) {
break;
}

// Xshape specific events extend the normal event numbers
// The first event id is retrieved when querying for xshape
// extension information. This can be used to determine
// if the event that is received is Xshape specific.
if (ctx->enable_xshape) {
uint8_t xshape_event_id =
event->response_type - ctx->xshape_extension->first_event;
switch (xshape_event_id) {
case XCB_SHAPE_NOTIFY:
sl_handle_shape_notify(
ctx, reinterpret_cast<xcb_shape_notify_event_t*>(event));
break;
}
}

free(event);
++count;
}
Expand Down

0 comments on commit 836c972

Please sign in to comment.