From 9e5e2def61f518a5f4ae7ccaf4a2b6db7634d3be Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 9 Sep 2021 11:01:47 +0200 Subject: [PATCH] Handle mirrored monitors on X11 macOS and Windows present mirrored monitors as a single virtual monitor, but X11 exposes this scenario as two distinct monitors with identical coordinates. This messes up our logic, and is likely confusing for the user. So instead we'll ignore any monitors that have identical coordinates to any already seen monitors. (cherry picked from commit fb561eb321b36dcf13932c903047ce08e55d67d5) --- vncviewer/MonitorArrangement.cxx | 54 +++++++++++++++++++-------- vncviewer/MonitorArrangement.h | 6 ++- vncviewer/MonitorIndicesParameter.cxx | 20 ++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/vncviewer/MonitorArrangement.cxx b/vncviewer/MonitorArrangement.cxx index b1d30128..735177ba 100644 --- a/vncviewer/MonitorArrangement.cxx +++ b/vncviewer/MonitorArrangement.cxx @@ -1,4 +1,5 @@ /* Copyright 2021 Hugo Lundin for Cendio AB. + * Copyright 2021 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,8 +61,7 @@ MonitorArrangement::MonitorArrangement( int x, int y, int w, int h) : Fl_Group(x, y, w, h), SELECTION_COLOR(fl_lighter(FL_BLUE)), - AVAILABLE_COLOR(fl_lighter(fl_lighter(fl_lighter(FL_BACKGROUND_COLOR)))), - monitors() + AVAILABLE_COLOR(fl_lighter(fl_lighter(fl_lighter(FL_BACKGROUND_COLOR)))) { // Used for required monitors. Fl::set_boxtype(FL_CHECKERED_BOX, checkered_pattern_draw, 0, 0, 0, 0); @@ -87,10 +87,11 @@ MonitorArrangement::~MonitorArrangement() std::set MonitorArrangement::get() { std::set indices; + MonitorMap::const_iterator iter; - for (int i = 0; i < (int) monitors.size(); i++) { - if (monitors[i]->value() == 1) - indices.insert(i); + for (iter = monitors.begin(); iter != monitors.end(); ++iter) { + if (iter->second->value() == 1) + indices.insert(iter->first); } return indices; @@ -98,18 +99,23 @@ std::set MonitorArrangement::get() void MonitorArrangement::set(std::set indices) { - for (int i = 0; i < (int) monitors.size(); i++) { - bool selected = std::find(indices.begin(), indices.end(), i) != indices.end(); - monitors[i]->value(selected ? 1 : 0); + MonitorMap::const_iterator iter; + + for (iter = monitors.begin(); iter != monitors.end(); ++iter) { + bool selected = std::find(indices.begin(), indices.end(), + iter->first) != indices.end(); + iter->second->value(selected ? 1 : 0); } } void MonitorArrangement::draw() { - for (int i = 0; i < (int) monitors.size(); i++) { - Fl_Button * monitor = monitors[i]; + MonitorMap::const_iterator iter; + + for (iter = monitors.begin(); iter != monitors.end(); ++iter) { + Fl_Button * monitor = iter->second; - if (is_required(i)) { + if (is_required(iter->first)) { monitor->box(FL_CHECKERED_BOX); monitor->color(SELECTION_COLOR); } else { @@ -130,8 +136,26 @@ void MonitorArrangement::layout() std::pair offset = this->offset(); for (int i = 0; i < Fl::screen_count(); i++) { + bool match; + Fl::screen_xywh(x, y, w, h, i); + // Only keep a single entry for mirrored screens + match = false; + for (int j = 0; j < i; j++) { + int x2, y2, w2, h2; + + Fl::screen_xywh(x2, y2, w2, h2, j); + + if ((x != x2) || (y != y2) || (w != w2) || (h != h2)) + continue; + + match = true; + break; + } + if (match) + continue; + Fl_Button *monitor = new Fl_Button( /* x = */ this->x() + offset.first + x*scale + (1 - MARGIN_SCALE_FACTOR)*x*scale, /* y = */ this->y() + offset.second + y*scale + (1 - MARGIN_SCALE_FACTOR)*y*scale, @@ -143,11 +167,9 @@ void MonitorArrangement::layout() monitor->callback(monitor_pressed, this); monitor->type(FL_TOGGLE_BUTTON); monitor->when(FL_WHEN_CHANGED); - monitors.push_back(monitor); + monitor->copy_tooltip(description(i).c_str()); + monitors[i] = monitor; } - - for (int i = 0; i < (int) monitors.size(); i++) - monitors[i]->copy_tooltip(description(i).c_str()); } void MonitorArrangement::refresh() @@ -308,7 +330,7 @@ std::pair MonitorArrangement::origin() std::string MonitorArrangement::description(int m) { - assert(m < (int) monitors.size()); + assert(m < Fl::screen_count()); const size_t name_len = 1024; char name[name_len] = {}; int bytes_written = get_monitor_name(m, name, name_len); diff --git a/vncviewer/MonitorArrangement.h b/vncviewer/MonitorArrangement.h index 3a71e5b0..e69198b6 100644 --- a/vncviewer/MonitorArrangement.h +++ b/vncviewer/MonitorArrangement.h @@ -1,4 +1,5 @@ /* Copyright 2021 Hugo Lundin for Cendio AB. + * Copyright 2021 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,8 @@ #define __MONITOR_ARRANGEMENT_H__ #include +#include +#include class Fl_Group; class Fl_Button; @@ -41,7 +44,8 @@ protected: private: const Fl_Color SELECTION_COLOR; const Fl_Color AVAILABLE_COLOR; - std::vector monitors; + typedef std::map MonitorMap; + MonitorMap monitors; // Layout the monitor arrangement. void layout(); diff --git a/vncviewer/MonitorIndicesParameter.cxx b/vncviewer/MonitorIndicesParameter.cxx index 827687dc..ad791504 100644 --- a/vncviewer/MonitorIndicesParameter.cxx +++ b/vncviewer/MonitorIndicesParameter.cxx @@ -1,4 +1,5 @@ /* Copyright 2021 Hugo Lundin for Cendio AB. + * Copyright 2021 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -196,6 +197,7 @@ std::vector MonitorIndicesParameter::fetchMoni // Start by creating a struct for every monitor. for (int i = 0; i < Fl::screen_count(); i++) { Monitor monitor = {0}; + bool match; // Get the properties of the monitor at the current index; Fl::screen_xywh( @@ -206,6 +208,24 @@ std::vector MonitorIndicesParameter::fetchMoni i ); + // Only keep a single entry for mirrored screens + match = false; + for (int j = 0; j < ((int) monitors.size()); j++) { + if (monitors[i].x != monitor.x) + continue; + if (monitors[i].y != monitor.y) + continue; + if (monitors[i].w != monitor.w) + continue; + if (monitors[i].h != monitor.h) + continue; + + match = true; + break; + } + if (match) + continue; + monitor.fltkIndex = i; monitors.push_back(monitor); } -- 2.39.5