Sfoglia il codice sorgente

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.
tags/v1.12.90
Pierre Ossman 2 anni fa
parent
commit
fb561eb321

+ 38
- 16
vncviewer/MonitorArrangement.cxx Vedi File

/* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB. /* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB.
* Copyright 2021 Pierre Ossman for Cendio AB
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
int x, int y, int w, int h) int x, int y, int w, int h)
: Fl_Group(x, y, w, h), : Fl_Group(x, y, w, h),
SELECTION_COLOR(fl_lighter(FL_BLUE)), 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. // Used for required monitors.
Fl::set_boxtype(FL_CHECKERED_BOX, checkered_pattern_draw, 0, 0, 0, 0); Fl::set_boxtype(FL_CHECKERED_BOX, checkered_pattern_draw, 0, 0, 0, 0);
std::set<int> MonitorArrangement::get() std::set<int> MonitorArrangement::get()
{ {
std::set<int> indices; std::set<int> 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; return indices;


void MonitorArrangement::set(std::set<int> indices) void MonitorArrangement::set(std::set<int> 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() 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->box(FL_CHECKERED_BOX);
monitor->color(SELECTION_COLOR); monitor->color(SELECTION_COLOR);
} else { } else {
std::pair<int, int> offset = this->offset(); std::pair<int, int> offset = this->offset();


for (int i = 0; i < Fl::screen_count(); i++) { for (int i = 0; i < Fl::screen_count(); i++) {
bool match;

Fl::screen_xywh(x, y, w, h, i); 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( Fl_Button *monitor = new Fl_Button(
/* x = */ this->x() + offset.first + x*scale + (1 - MARGIN_SCALE_FACTOR)*x*scale, /* 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, /* y = */ this->y() + offset.second + y*scale + (1 - MARGIN_SCALE_FACTOR)*y*scale,
monitor->callback(monitor_pressed, this); monitor->callback(monitor_pressed, this);
monitor->type(FL_TOGGLE_BUTTON); monitor->type(FL_TOGGLE_BUTTON);
monitor->when(FL_WHEN_CHANGED); 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() void MonitorArrangement::refresh()


std::string MonitorArrangement::description(int m) std::string MonitorArrangement::description(int m)
{ {
assert(m < (int) monitors.size());
assert(m < Fl::screen_count());
const size_t name_len = 1024; const size_t name_len = 1024;
char name[name_len] = {}; char name[name_len] = {};
int bytes_written = get_monitor_name(m, name, name_len); int bytes_written = get_monitor_name(m, name, name_len);

+ 5
- 1
vncviewer/MonitorArrangement.h Vedi File

/* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB. /* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB.
* Copyright 2021 Pierre Ossman for Cendio AB
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
#define __MONITOR_ARRANGEMENT_H__ #define __MONITOR_ARRANGEMENT_H__


#include <string> #include <string>
#include <map>
#include <set>


class Fl_Group; class Fl_Group;
class Fl_Button; class Fl_Button;
private: private:
const Fl_Color SELECTION_COLOR; const Fl_Color SELECTION_COLOR;
const Fl_Color AVAILABLE_COLOR; const Fl_Color AVAILABLE_COLOR;
std::vector<Fl_Button *> monitors;
typedef std::map<int, Fl_Button *> MonitorMap;
MonitorMap monitors;


// Layout the monitor arrangement. // Layout the monitor arrangement.
void layout(); void layout();

+ 20
- 0
vncviewer/MonitorIndicesParameter.cxx Vedi File

/* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB. /* Copyright 2021 Hugo Lundin <huglu@cendio.se> for Cendio AB.
* Copyright 2021 Pierre Ossman for Cendio AB
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
// Start by creating a struct for every monitor. // Start by creating a struct for every monitor.
for (int i = 0; i < Fl::screen_count(); i++) { for (int i = 0; i < Fl::screen_count(); i++) {
Monitor monitor = {0}; Monitor monitor = {0};
bool match;


// Get the properties of the monitor at the current index; // Get the properties of the monitor at the current index;
Fl::screen_xywh( Fl::screen_xywh(
i 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; monitor.fltkIndex = i;
monitors.push_back(monitor); monitors.push_back(monitor);
} }

Loading…
Annulla
Salva