Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 56 additions & 17 deletions src/platform/linux/pipewire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,46 @@ namespace pipewire {
}
}

virtual int configure_stream(const std::string &display_name, int &out_pipewire_fd, int &out_pipewire_node, int &out_pos_x, int &out_pos_y, int &out_width, int &out_height) = 0;
/**
* @brief Configure the pipewire stream
* @param display_name provide a stream for this display_name
* @param out_pipewire_fd set to the pipewire fd for the stream in during function call (or -1 for using the local context)
* @param out_pipewire_node set to the pipewire node of the stream in during function call
* @returns 0 if the stream successfully configured
*/
virtual int configure_stream(const std::string &display_name, int &out_pipewire_fd, int &out_pipewire_node) = 0;

/**
* @brief Verify and update display parameters for logical dimensions, desktop dimensions and logical desktop dimensions (default is adapted from wlgrab)
*/
virtual void verify_and_update_display_parameters() {
// Set environment dimensions to stream dimensions (unless we find something better to report here)
if (env_height <= 0 || env_width <= 0) {
this->env_width = width;
this->env_height = height;
BOOST_LOG(debug) << "[pipewire] Desktop Resolution: "sv << env_width << 'x' << env_height;
}
// Query logical sizes directly using wayland wl::monitors() and match current screen based on offset/dimensions
if (logical_height <= 0 || logical_width <= 0 || env_logical_height <= 0 || env_logical_width <= 0) {
int desktop_logical_width = 0;
int desktop_logical_height = 0;
for (const auto &monitor : wl::monitors()) {
// If logical_width and logical_height are not valid try to update them to correct values by matching to monitor position/dimension or position/logical dimensions
// since we're iterating for maximum environment size anyway
if ((logical_width <= 0 || logical_height <= 0) && monitor->viewport.offset_x == offset_x && monitor->viewport.offset_y == offset_y && ((monitor->viewport.width == width && monitor->viewport.height == height) || (monitor->viewport.logical_width == width && monitor->viewport.logical_height == height))) {
this->logical_width = monitor->viewport.logical_width;
this->logical_height = monitor->viewport.logical_height;
BOOST_LOG(debug) << "[pipewire] Logical Resolution: "sv << logical_width << 'x' << logical_height;
}
// Update logical dimensions to setup maximum environment size over all screens
desktop_logical_width = std::max(desktop_logical_width, monitor->viewport.offset_x + monitor->viewport.logical_width);
desktop_logical_height = std::max(desktop_logical_height, monitor->viewport.offset_y + monitor->viewport.logical_height);
}
this->env_logical_width = std::max(env_logical_width, desktop_logical_width);
this->env_logical_height = std::max(env_logical_height, desktop_logical_height);
BOOST_LOG(debug) << "[pipewire] Logical Desktop Resolution: "sv << env_logical_width << 'x' << env_logical_height;
}
}

int init(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
// calculate frame interval we should capture at
Expand All @@ -638,14 +677,15 @@ namespace pipewire {

int pipewire_fd = -1;
int pipewire_node = -1;
int pos_x = -1;
int pos_y = -1;
// Fetch stream info
if (configure_stream(display_name, pipewire_fd, pipewire_node, pos_x, pos_y, width, height) < 0) {
if (configure_stream(display_name, pipewire_fd, pipewire_node) < 0 || pipewire_node < 0) {
BOOST_LOG(error) << "[pipewire] Could not find display with name: '"sv << display_name << "'";
return -1;
}
BOOST_LOG(info) << "[pipewire] Streaming display '"sv << display_name << "' from position: "sv << pos_x << "x"sv << pos_y << " resolution: "sv << width << "x"sv << height;
BOOST_LOG(info) << "[pipewire] Streaming display '"sv << display_name << "' from position: "sv << offset_x << "x"sv << offset_y << " resolution: "sv << width << "x"sv << height;

// Verify or update display parameters for streaming to ensure absolute touch inputs work as expected
verify_and_update_display_parameters();

framerate = config.framerate;

Expand All @@ -668,10 +708,10 @@ namespace pipewire {
return -1;
}

// Wait for pipewire negotiation to finish so we have the proper negotiated dimensions
int timeout_ms = 1500;
int negotiated_w = 0;
int negotiated_h = 0;

while (timeout_ms > 0) {
negotiated_w = shared_state->negotiated_width.load();
negotiated_h = shared_state->negotiated_height.load();
Expand All @@ -681,23 +721,22 @@ namespace pipewire {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
timeout_ms -= 10;
}

// Set width and height to the values negotiated by pipewire
if (negotiated_w > 0 && negotiated_h > 0 && (negotiated_w != width || negotiated_h != height)) {
BOOST_LOG(info) << "[pipewire] Using negotiated resolution "sv
<< negotiated_w << "x" << negotiated_h;

width = negotiated_w;
height = negotiated_h;
BOOST_LOG(info) << "[pipewire] Using negotiated Resolution: "sv << width << "x" << height;

// Reset and update display parameters for negotiated resolution
env_width = 0;
env_height = 0;
logical_height = 0;
logical_width = 0;
env_logical_height = 0;
env_logical_width = 0;
verify_and_update_display_parameters();
}

// Set env dimensions to match the captured display.
// Portal captures a single display, so the environment size equals the capture size.
// Without this, touch input is silently dropped because touch_port_t::operator bool()
// checks env_width and env_height are non-zero.
env_width = width;
env_height = height;

return 0;
}

Expand Down
15 changes: 9 additions & 6 deletions src/platform/linux/portalgrab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ namespace portal {

class portal_t: public pipewire::pipewire_display_t {
public:
int configure_stream(const std::string &display_name, int &out_pipewire_fd, int &out_pipewire_node, int &out_pos_x, int &out_pos_y, int &out_width, int &out_height) override {
int configure_stream(const std::string &display_name, int &out_pipewire_fd, int &out_pipewire_node) override {
// Connect DBus portal session
if (dbus.init() < 0) {
BOOST_LOG(error) << "[portalgrab] Failed to connect to dbus. portal_t setup failed.";
Expand Down Expand Up @@ -759,13 +759,16 @@ namespace portal {
// Restore global maxframerate negotiation state
pipewire.set_negotiate_maxframerate(negotiate_maxframerate.load());

// Return values
// Return values for pipewire init
out_pipewire_fd = dbus.pipewire_fd;
out_pipewire_node = stream.pipewire_node;
out_pos_x = stream.pos_x;
out_pos_y = stream.pos_y;
out_width = stream.width;
out_height = stream.height;
// Set/update basic stream parameters on display_t
this->offset_x = stream.pos_x;
this->offset_y = stream.pos_y;
this->width = stream.width;
this->height = stream.height;
this->logical_width = 0; // Explicitly mark for pipewire_display_t to try to figure this out.
this->logical_height = 0; // Explicitly Mark for pipewire_display_t to try to figure this out.
// Flag successful setup
return 0;
}
Expand Down
Loading