@@ -180,6 +180,45 @@ namespace portal {
180180 int pos_x;
181181 int pos_y;
182182 std::string monitor_name;
183+
184+ std::string to_display_name () {
185+ if (monitor_name.length () > 0 ) {
186+ return std::format (" n{}" , monitor_name);
187+ }
188+ return std::format (" p{},{},{},{}" , pos_x, pos_y, width, height);
189+ }
190+ bool match_display_name (const std::string &display_name) const {
191+ // Empty display_name never matches
192+ if (display_name.empty ()) {
193+ return false ;
194+ }
195+ // Method 1: Display_name starts with 'n' match by monitor_name starting from pos 1
196+ if (display_name[0 ] == ' n' ) {
197+ return display_name.substr (1 ) == monitor_name;
198+ }
199+ // Method 2: Display_name starts with 'p' match by position+resolution starting from pos 1
200+ if (display_name[0 ] == ' p' ) {
201+ auto stringstream = std::stringstream (display_name.substr (1 ));
202+ std::string stringvalue;
203+ std::vector<int > values;
204+ constexpr char display_name_delimiter = ' ,' ;
205+ while (std::getline (stringstream, stringvalue, display_name_delimiter)) {
206+ if (std::ranges::all_of (stringvalue, ::isdigit)) {
207+ values.emplace_back (std::stoi (stringvalue));
208+ } else {
209+ BOOST_LOG (debug) << " [portalgrab] Failed to parse int value: '" sv << stringvalue << " '" ;
210+ }
211+ }
212+ // Check if the vector has 4 values (pos_x, pos_y, width, height) from display_names formatting
213+ if (values.size () != 4 ) {
214+ BOOST_LOG (debug) << " [portalgrab] Display name does not match expected format 'x,y,w,h': '" sv << display_name << " '" ;
215+ return false ;
216+ }
217+ return pos_x == values[0 ] && pos_y == values[1 ] && width == values[2 ] && height == values[3 ];
218+ }
219+ // All matching methods have failed. No match!
220+ return false ;
221+ }
183222 };
184223
185224 class dbus_t {
@@ -1316,9 +1355,17 @@ namespace portal {
13161355 return -1 ;
13171356 }
13181357 // Match display_name to a stream from the pipewire_streams vector
1319- pipewire_streaminfo_t stream = match_display_name_to_stream (pipewire_streams, display_name);
1358+ bool use_fallback = true ;
1359+ pipewire_streaminfo_t stream;
1360+ for (const auto &stream_ : pipewire_streams) {
1361+ if (stream_.match_display_name (display_name)) {
1362+ stream = stream_;
1363+ use_fallback = false ;
1364+ break ;
1365+ }
1366+ }
13201367 // Fall back to first stream if we cannot match the given display_name to a stream in currently available streams.
1321- if (stream. width < 0 || stream. height < 0 ) {
1368+ if (use_fallback ) {
13221369 BOOST_LOG (info) << " [portalgrab] Using first available stream as no matching stream was found for: '" sv << display_name << " '" ;
13231370 stream = pipewire_streams[0 ];
13241371 }
@@ -1681,50 +1728,6 @@ namespace portal {
16811728 return 0 ;
16821729 }
16831730
1684- static pipewire_streaminfo_t match_display_name_to_stream (const std::vector<pipewire_streaminfo_t > &pipewire_streams, const std::string &display_name) {
1685- const auto invalid_stream = pipewire_streaminfo_t {-1 , -1 , -1 , -1 , -1 };
1686- // Empty display_names cannot be mapped to a valid stream
1687- if (display_name.empty ()) {
1688- return invalid_stream;
1689- }
1690- // Display_name starts with 'n' match by monitor_name starting from pos 1
1691- if (!display_name.empty () && display_name[0 ] == ' n' ) {
1692- auto monitor_name = display_name.substr (1 );
1693- for (const auto &stream : pipewire_streams) {
1694- if (stream.monitor_name == monitor_name) {
1695- return stream;
1696- }
1697- }
1698- }
1699- // Display_name starts with 'p' match by position+resolution starting from pos 1
1700- if (!display_name.empty () && display_name[0 ] == ' p' ) {
1701- auto stringstream = std::stringstream (display_name.substr (1 ));
1702- std::string stringvalue;
1703- std::vector<int > values;
1704- constexpr char display_name_delimiter = ' ,' ;
1705- while (std::getline (stringstream, stringvalue, display_name_delimiter)) {
1706- if (std::ranges::all_of (stringvalue, ::isdigit)) {
1707- values.emplace_back (std::stoi (stringvalue));
1708- } else {
1709- BOOST_LOG (warning) << " [portalgrab] Failed to parse int value: '" sv << stringvalue << " '" ;
1710- }
1711- }
1712- // Check if the vector has 4 values (pos_x, pos_y, width, height) from display_names formatting
1713- if (values.size () != 4 ) {
1714- BOOST_LOG (warning) << " [portalgrab] Display name does not match expected format 'x,y,w,h': '" sv << display_name << " '" ;
1715- return invalid_stream;
1716- }
1717- // Determine correct pipewire_node by iterating pipewire_streams and matching position and resolution
1718- for (const auto &stream : pipewire_streams) {
1719- if (stream.pos_x == values[0 ] && stream.pos_y == values[1 ] && stream.width == values[2 ] && stream.height == values[3 ]) {
1720- return stream;
1721- }
1722- }
1723- }
1724- // If we reach this point, no matching stream was found.
1725- return invalid_stream;
1726- }
1727-
17281731 platf::mem_type_e mem_type;
17291732 wl::display_t wl_display;
17301733 pipewire_t pipewire;
@@ -1758,21 +1761,6 @@ namespace platf {
17581761 return portal;
17591762 }
17601763
1761- std::vector<std::string> portal_streams_to_display_names (const std::vector<portal::pipewire_streaminfo_t > &pipewire_streams, const bool log) {
1762- std::vector<std::string> display_names;
1763- for (auto stream : pipewire_streams) {
1764- if (log) {
1765- BOOST_LOG (info) << " [portalgrab] Found stream for display: '" sv << stream.monitor_name << " ' position: " sv << stream.pos_x << " x" sv << stream.pos_y << " resolution: " sv << stream.width << " x" sv << stream.height ;
1766- }
1767- if (stream.monitor_name .length () > 0 ) {
1768- display_names.emplace_back (std::format (" n{}" , stream.monitor_name ));
1769- } else {
1770- display_names.emplace_back (std::format (" p{},{},{},{}" , stream.pos_x , stream.pos_y , stream.width , stream.height ));
1771- }
1772- }
1773- return display_names;
1774- }
1775-
17761764 std::vector<std::string> portal_display_names () {
17771765 auto dbus = std::make_shared<portal::dbus_t >();
17781766
@@ -1787,14 +1775,21 @@ namespace platf {
17871775 BOOST_LOG (warning) << " [portalgrab] Failed to connect to portal. Cannot enumerate displays, returning empty list." ;
17881776 return {};
17891777 }
1790- std::vector<std::string> dbus_display_names = portal_streams_to_display_names (dbus->pipewire_streams , true );
1778+ std::vector<std::string> dbus_display_names;
1779+ for (auto stream_ : dbus->pipewire_streams ) {
1780+ BOOST_LOG (info) << " [portalgrab] Found stream for display: '" sv << stream_.monitor_name << " ' position: " sv << stream_.pos_x << " x" sv << stream_.pos_y << " resolution: " sv << stream_.width << " x" sv << stream_.height ;
1781+ dbus_display_names.emplace_back (stream_.to_display_name ());
1782+ }
17911783 // Release the new portal as soon as possible to properly release related resources early.
17921784 dbus.reset ();
17931785 // Get all display_names from cache
17941786 int cache_pipewire_fd;
17951787 std::vector<portal::pipewire_streaminfo_t > cache_pipewire_streams;
17961788 portal::session_cache_t::instance ().get_or_create_session (cache_pipewire_fd, cache_pipewire_streams);
1797- std::vector<std::string> cache_display_names = portal_streams_to_display_names (cache_pipewire_streams, false );
1789+ std::vector<std::string> cache_display_names;
1790+ for (auto stream_ : cache_pipewire_streams) {
1791+ cache_display_names.emplace_back (stream_.to_display_name ());
1792+ }
17981793 // Close the unused duplicated pipewire_fd from get_or_create_session
17991794 close (cache_pipewire_fd);
18001795 // Compare dbus with cache display names and invalidate the cache if things differ
0 commit comments