瀏覽代碼

Add fullscreen mode for selected monitors

The user might not always want to use all monitors when in fullscreen
mode, but instead only a few. This commit adds support for configuring
selected monitors from command line, in the config file and graphically
in the options menu.

Because it might be hard to guarantee the consistency of monitor
identifiers coming from third-parties (for example FLTK), it has been
decided to use our own numerical identifier. This identifier is based on
the monitor's positions. The mapping between this identifier and the
indices used by FLTK is done by MonitorIndicesParameter.
tags/v1.11.90
Hugo Lundin 2 年之前
父節點
當前提交
0d43b96d1c

+ 2
- 0
vncviewer/CMakeLists.txt 查看文件

@@ -17,6 +17,8 @@ set(VNCVIEWER_SOURCES
parameters.cxx
keysym2ucs.c
touch.cxx
MonitorArrangement.cxx
MonitorIndicesParameter.cxx
vncviewer.cxx)

if(WIN32)

+ 37
- 9
vncviewer/DesktopWindow.cxx 查看文件

@@ -883,8 +883,9 @@ int DesktopWindow::fltkHandle(int event, Fl_Window *win)
void DesktopWindow::fullscreen_on()
{
bool all_monitors = !strcasecmp(fullScreenMode, "all");
bool selected_monitors = !strcasecmp(fullScreenMode, "selected");

if (not all_monitors)
if (not selected_monitors and not all_monitors)
fullscreen_screens(-1, -1, -1, -1);
else {
int top, bottom, left, right;
@@ -892,30 +893,57 @@ void DesktopWindow::fullscreen_on()

int sx, sy, sw, sh;

top = bottom = left = right = 0;
std::set<int> monitors;

Fl::screen_xywh(sx, sy, sw, sh, 0);
if (selected_monitors and not all_monitors) {
std::set<int> selected = fullScreenSelectedMonitors.getParam();
monitors.insert(selected.begin(), selected.end());
} else {
for (int i = 0; i < Fl::screen_count(); i++) {
monitors.insert(i);
}
}

// If no monitors were found in the selected monitors case, we want
// to explicitly use the window's current monitor.
if (monitors.size() == 0) {
monitors.insert(Fl::screen_num(x(), y(), w(), h()));
}

// If there are monitors selected, calculate the dimensions
// of the frame buffer, expressed in the monitor indices that
// limits it.
std::set<int>::iterator it = monitors.begin();

// Get first monitor dimensions.
Fl::screen_xywh(sx, sy, sw, sh, *it);
top = bottom = left = right = *it;
top_y = sy;
bottom_y = sy + sh;
left_x = sx;
right_x = sx + sw;

for (int i = 1;i < Fl::screen_count();i++) {
Fl::screen_xywh(sx, sy, sw, sh, i);
// Keep going through the rest of the monitors.
for (; it != monitors.end(); it++) {
Fl::screen_xywh(sx, sy, sw, sh, *it);

if (sy < top_y) {
top = i;
top = *it;
top_y = sy;
}

if ((sy + sh) > bottom_y) {
bottom = i;
bottom = *it;
bottom_y = sy + sh;
}

if (sx < left_x) {
left = i;
left = *it;
left_x = sx;
}

if ((sx + sw) > right_x) {
right = i;
right = *it;
right_x = sx + sw;
}
}

+ 303
- 0
vncviewer/MonitorArrangement.cxx 查看文件

@@ -0,0 +1,303 @@
/* Copyright 2021 Hugo Lundin <huglu@cendio.se> 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#include <set>
#include <vector>
#include <string>
#include <utility>
#include <sstream>
#include <assert.h>
#include <algorithm>

#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Button.H>

#include <rfb/Rect.h>

#include "MonitorArrangement.h"

static const Fl_Boxtype FL_CHECKERED_BOX = FL_FREE_BOXTYPE;

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)))),
m_monitors()
{
// Used for required monitors.
Fl::set_boxtype(FL_CHECKERED_BOX, checkered_pattern_draw, 0, 0, 0, 0);

box(FL_DOWN_BOX);
color(fl_lighter(FL_BACKGROUND_COLOR));
layout();
end();
}

MonitorArrangement::~MonitorArrangement()
{

}

std::set<int> MonitorArrangement::get()
{
std::set<int> indices;

for (int i = 0; i < (int) m_monitors.size(); i++) {
if (m_monitors[i]->value() == 1)
indices.insert(i);
}

return indices;
}

void MonitorArrangement::set(std::set<int> indices)
{
for (int i = 0; i < (int) m_monitors.size(); i++) {
bool selected = std::find(indices.begin(), indices.end(), i) != indices.end();
m_monitors[i]->value(selected ? 1 : 0);
}
}

void MonitorArrangement::draw()
{
for (int i = 0; i < (int) m_monitors.size(); i++) {
Fl_Button * monitor = m_monitors[i];

if (is_required(i)) {
monitor->box(FL_CHECKERED_BOX);
monitor->color(SELECTION_COLOR);
} else {
monitor->box(FL_BORDER_BOX);
monitor->color(AVAILABLE_COLOR);
monitor->selection_color(SELECTION_COLOR);
}
}

Fl_Group::draw();
}

void MonitorArrangement::layout()
{
int x, y, w, h;
double scale = this->scale();
const double MARGIN_SCALE_FACTOR = 0.99;
std::pair<int, int> offset = this->offset();

for (int i = 0; i < Fl::screen_count(); i++) {
Fl::screen_xywh(x, y, w, h, i);

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,
/* w = */ w*scale*MARGIN_SCALE_FACTOR,
/* h = */ h*scale*MARGIN_SCALE_FACTOR
);

monitor->clear_visible_focus();
monitor->callback(monitor_pressed, this);
monitor->type(FL_TOGGLE_BUTTON);
monitor->when(FL_WHEN_CHANGED);
m_monitors.push_back(monitor);
}
}

bool MonitorArrangement::is_required(int m)
{
// A selected monitor is never required.
if (m_monitors[m]->value() == 1)
return false;

// If no monitors are selected, none are required.
std::set<int> selected = get();
if (selected.size() <= 0)
return false;


// Go through all selected monitors and find the monitor
// indices that bounds the fullscreen frame buffer. If
// the given monitor's coordinates are inside the bounds,
// while not being selected, it is instead required.

int x, y, w, h;
int top_y, bottom_y, left_x, right_x;
std::set<int>::iterator it = selected.begin();

// Base the rest of the calculations on the dimensions
// obtained for the first monitor.
Fl::screen_xywh(x, y, w, h, *it);
top_y = y;
bottom_y = y + h;
left_x = x;
right_x = x + w;

// Go through the rest of the monitors,
// exhausting the rest of the iterator.
for (; it != selected.end(); it++) {
Fl::screen_xywh(x, y, w, h, *it);

if (y < top_y) {
top_y = y;
}

if ((y + h) > bottom_y) {
bottom_y = y + h;
}

if (x < left_x) {
left_x = x;
}

if ((x + w) > right_x) {
right_x = x + w;
}
}

rfb::Rect viewport, monitor;
viewport.setXYWH(left_x, top_y, right_x - left_x, bottom_y - top_y);

Fl::screen_xywh(x, y, w, h, m);
monitor.setXYWH(x, y, w, h);

return monitor.enclosed_by(viewport);
}

double MonitorArrangement::scale()
{
const int MARGIN = 20;
std::pair<int, int> size = this->size();

double s_w = static_cast<double>(this->w()-MARGIN) / static_cast<double>(size.first);
double s_h = static_cast<double>(this->h()-MARGIN) / static_cast<double>(size.second);

// Choose the one that scales the least, in order to
// maximize our use of the given bounding area.
if (s_w > s_h)
return s_h;
else
return s_w;
}

std::pair<int, int> MonitorArrangement::size()
{
int x, y, w, h;
int top, bottom, left, right;
int x_min, x_max, y_min, y_max;
x_min = x_max = y_min = y_max = 0;

for (int i = 0; i < Fl::screen_count(); i++) {
Fl::screen_xywh(x, y, w, h, i);

top = y;
bottom = y + h;
left = x;
right = x + w;

if (top < y_min)
y_min = top;

if (bottom > y_max)
y_max = bottom;

if (left < x_min)
x_min = left;

if (right > x_max)
x_max = right;
}

return std::make_pair(x_max - x_min, y_max - y_min);
}

std::pair<int, int> MonitorArrangement::offset()
{
double scale = this->scale();
std::pair<int, int> size = this->size();
std::pair<int, int> origin = this->origin();

int offset_x = (this->w()/2) - (size.first/2 * scale);
int offset_y = (this->h()/2) - (size.second/2 * scale);

return std::make_pair(offset_x + abs(origin.first)*scale, offset_y + abs(origin.second)*scale);
}

std::pair<int, int> MonitorArrangement::origin()
{
int x, y, w, h, ox, oy;
ox = oy = 0;

for (int i = 0; i < Fl::screen_count(); i++) {
Fl::screen_xywh(x, y, w, h, i);

if (x < ox)
ox = x;

if (y < oy)
oy = y;
}

return std::make_pair(ox, oy);
}

void MonitorArrangement::monitor_pressed(Fl_Widget *widget, void *user_data)
{
MonitorArrangement *self = (MonitorArrangement *) user_data;

// When a monitor is selected, FLTK changes the state of it for us.
// However, selecting a monitor might implicitly change the state of
// others (if they become required). FLTK only redraws the selected
// monitor. Therefore, we must trigger a redraw of the whole widget
// manually.
self->redraw();
}

void MonitorArrangement::checkered_pattern_draw(
int x, int y, int width, int height, Fl_Color color)
{
bool draw_checker = false;
const int CHECKER_SIZE = 8;

fl_color(fl_lighter(fl_lighter(fl_lighter(color))));
fl_rectf(x, y, width, height);

fl_color(Fl::draw_box_active() ? color : fl_inactive(color));

// Round up the square count. Later on, we remove square area that are
// outside the given bounding area.
const int count = (width + CHECKER_SIZE - 1) / CHECKER_SIZE;

for (int i = 0; i < count; i++) {
for (int j = 0; j < count; j++) {

draw_checker = (i + j) % 2 == 0;

if (draw_checker) {
fl_rectf(
/* x = */ x + i * CHECKER_SIZE,
/* y = */ y + j * CHECKER_SIZE,
/* w = */ CHECKER_SIZE - std::max(0, ((i + 1) * CHECKER_SIZE) - width),
/* h = */ CHECKER_SIZE - std::max(0, ((j + 1) * CHECKER_SIZE) - height)
);
}
}
}

fl_color(Fl::draw_box_active() ? FL_BLACK : fl_inactive(FL_BLACK));
fl_rect(x, y, width, height);
}

+ 72
- 0
vncviewer/MonitorArrangement.h 查看文件

@@ -0,0 +1,72 @@
/* Copyright 2021 Hugo Lundin <huglu@cendio.se> 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#ifndef __MONITOR_ARRANGEMENT_H__
#define __MONITOR_ARRANGEMENT_H__

#include <string>

class Fl_Group;
class Fl_Button;

class MonitorArrangement: public Fl_Group {
public:
MonitorArrangement(int x, int y, int w, int h);
~MonitorArrangement();

// Get selected indices.
std::set<int> get();

// Set selected indices.
void set(std::set<int> indices);

protected:
virtual void draw();

private:
const Fl_Color SELECTION_COLOR;
const Fl_Color AVAILABLE_COLOR;
std::vector<Fl_Button *> m_monitors;

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

// Return true if the given monitor is required to be part of the configuration
// for it to be valid. A configuration is only valid if the framebuffer created
// from is rectangular.
bool is_required(int m);

// Calculate the scale of the monitor arrangement.
double scale();

// Return the size of the monitor arrangement.
std::pair<int, int> size();

// Return the offset required for centering the monitor
// arrangement in the given bounding area.
std::pair<int, int> offset();

// Return the origin of the monitor arrangement (top left corner).
std::pair<int, int> origin();

static void monitor_pressed(Fl_Widget *widget, void *user_data);
static void checkered_pattern_draw(
int x, int y, int width, int height, Fl_Color color);
};

#endif

+ 229
- 0
vncviewer/MonitorIndicesParameter.cxx 查看文件

@@ -0,0 +1,229 @@
/* Copyright 2021 Hugo Lundin <huglu@cendio.se> 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#include <algorithm>
#include <vector>
#include <string>
#include <limits>
#include <set>
#include <stdlib.h>
#include <stdexcept>

#include "i18n.h"
#include <FL/Fl.H>
#include <rfb/LogWriter.h>

#include "MonitorIndicesParameter.h"

using namespace rfb;
static LogWriter vlog("MonitorIndicesParameter");

MonitorIndicesParameter::MonitorIndicesParameter(const char* name_, const char* desc_, const char* v)
: StringParameter(name_, desc_, v) {}

std::set<int> MonitorIndicesParameter::getParam()
{
bool valid = false;
std::set<int> indices;
std::set<int> config_indices;
std::vector<MonitorIndicesParameter::Monitor> monitors = this->monitors();

if (monitors.size() <= 0) {
vlog.error(_("Failed to get monitors."));
return indices;
}

valid = parse_indices(value, &config_indices);
if (!valid) {
return indices;
}

if (config_indices.size() <= 0) {
return indices;
}

// Go through the monitors and see what indices are present in the config.
for (int i = 0; i < ((int) monitors.size()); i++) {
if (std::find(config_indices.begin(), config_indices.end(), i) != config_indices.end())
indices.insert(monitors[i].fltk_index);
}

return indices;
}

bool MonitorIndicesParameter::setParam(const char* value)
{
int index;
std::set<int> indices;

if (strlen(value) < 0)
return false;

if (!parse_indices(value, &indices)) {
vlog.error(_("Invalid FullScreenSelectedMonitors configuration."));
return false;
}

for (std::set<int>::iterator it = indices.begin(); it != indices.end(); it++) {
index = *it + 1;

if (index <= 0 || index > Fl::screen_count())
vlog.error(_("Monitor index %d does not exist."), index);
}

return StringParameter::setParam(value);
}

bool MonitorIndicesParameter::setParam(std::set<int> indices)
{
static const int BUF_MAX_LEN = 1024;
char buf[BUF_MAX_LEN] = {0};
std::set<int> config_indices;
std::vector<MonitorIndicesParameter::Monitor> monitors = this->monitors();

if (monitors.size() <= 0) {
vlog.error(_("Failed to get monitors."));
// Don't return, store the configuration anyways.
}

for (int i = 0; i < ((int) monitors.size()); i++) {
if (std::find(indices.begin(), indices.end(), monitors[i].fltk_index) != indices.end())
config_indices.insert(i);
}

int bytes_written = 0;
char const * separator = "";

for (std::set<int>::iterator index = config_indices.begin();
index != config_indices.end();
index++)
{
bytes_written += snprintf(
buf+bytes_written,
BUF_MAX_LEN-bytes_written,
"%s%u",
separator,
(*index)+1
);

separator = ",";
}

return setParam(buf);
}

static bool parse_number(std::string number, std::set<int> *indices)
{
if (number.size() <= 0)
return false;

int v = strtol(number.c_str(), NULL, 0);

if (v <= 0) {
vlog.error(_("The given monitor index(%s) is too small to be valid."), number.c_str());
return false;
}

if (v > INT_MAX) {
vlog.error(_("The given monitor index (%s) is too large to be valid."), number.c_str());
return false;
}

indices->insert(v-1);
return true;
}

bool MonitorIndicesParameter::parse_indices(const char* value, std::set<int> *indices)
{
char d;
std::string current;

for (size_t i = 0; i < strlen(value); i++) {
d = value[i];

if (d == ' ')
continue;
else if (d >= '0' && d <= '9')
current.push_back(d);
else if (d == ',') {
if (!parse_number(current, indices)) {
vlog.error(_("Invalid monitor index '%s' in FullScreenSelectedMonitors"), current.c_str());
return false;
}

current.clear();
} else {
vlog.error(_("Unexpected character '%c' in FullScreenSelectedMonitors"), d);
return false;
}
}

// If we have nothing left to parse we are in a valid state.
if (current.size() == 0)
return true;

// Parsing anything we have left.
if (!parse_number(current, indices))
return false;

return true;
}

std::vector<MonitorIndicesParameter::Monitor> MonitorIndicesParameter::monitors()
{
std::vector<Monitor> monitors;

// Start by creating a struct for every monitor.
for (int i = 0; i < Fl::screen_count(); i++) {
Monitor monitor = {0};

// Get the properties of the monitor at the current index;
Fl::screen_xywh(
monitor.x,
monitor.y,
monitor.w,
monitor.h,
i
);

monitor.fltk_index = i;
monitors.push_back(monitor);
}

// Sort the monitors according to the specification in the vncviewer manual.
qsort(&monitors[0], monitors.size(), sizeof(*(&monitors[0])), sort_cb);
return monitors;
}

int MonitorIndicesParameter::sort_cb(const void *a, const void *b)
{
MonitorIndicesParameter::Monitor * monitor1 = (MonitorIndicesParameter::Monitor *) a;
MonitorIndicesParameter::Monitor * monitor2 = (MonitorIndicesParameter::Monitor *) b;

if (monitor1->x < monitor2->x)
return -1;

if (monitor1->y < monitor2->y)
return -1;

if (monitor1->x == monitor2->x)
if (monitor1->y == monitor2->y)
return 0;

return 1;
}

+ 44
- 0
vncviewer/MonitorIndicesParameter.h 查看文件

@@ -0,0 +1,44 @@
/* Copyright 2021 Hugo Lundin <huglu@cendio.se> 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#ifndef __MONITOR_INDEX_PARAMETER_H
#define __MONITOR_INDEX_PARAMETER_H

#include <set>
#include <vector>

#include <rfb/Configuration.h>

class MonitorIndicesParameter: public rfb::StringParameter {
public:
MonitorIndicesParameter(const char* name_, const char* desc_, const char* v);
std::set<int> getParam();
bool setParam(std::set<int> indices);
bool setParam(const char* value);
private:
typedef struct {
int x, y, w, h;
int fltk_index;
} Monitor;

bool parse_indices(const char* value, std::set<int> *indices);
std::vector<MonitorIndicesParameter::Monitor> monitors();
static int sort_cb(const void*, const void*);
};

#endif // __MONITOR_INDEX_PARAMETER_H

+ 44
- 0
vncviewer/OptionsDialog.cxx 查看文件

@@ -38,6 +38,7 @@
#include "i18n.h"
#include "menukey.h"
#include "parameters.h"
#include "MonitorArrangement.h"

#include <FL/Fl_Tabs.H>
#include <FL/Fl_Button.H>
@@ -300,11 +301,16 @@ void OptionsDialog::loadOptions(void)

if (!strcasecmp(fullScreenMode, "all")) {
allMonitorsButton->setonly();
} else if (!strcasecmp(fullScreenMode, "selected")) {
selectedMonitorsButton->setonly();
} else {
currentMonitorButton->setonly();
}

monitorArrangement->set(fullScreenSelectedMonitors.getParam());

handleDesktopSize(desktopSizeCheckbox, this);
handleFullScreenMode(selectedMonitorsButton, this);

/* Misc. */
sharedCheckbox->value(shared);
@@ -415,10 +421,14 @@ void OptionsDialog::storeOptions(void)

if (allMonitorsButton->value()) {
fullScreenMode.setParam("All");
} else if (selectedMonitorsButton->value()) {
fullScreenMode.setParam("Selected");
} else {
fullScreenMode.setParam("Current");
}

fullScreenSelectedMonitors.setParam(monitorArrangement->get());

/* Misc. */
shared.setParam(sharedCheckbox->value());
dotWhenNoCursor.setParam(dotCursorCheckbox->value());
@@ -812,6 +822,7 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
RADIO_HEIGHT,
_("Use current monitor")));
currentMonitorButton->type(FL_RADIO_BUTTON);
currentMonitorButton->callback(handleFullScreenMode, this);
ty += RADIO_HEIGHT + TIGHT_MARGIN;

allMonitorsButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
@@ -819,7 +830,29 @@ void OptionsDialog::createScreenPage(int tx, int ty, int tw, int th)
RADIO_HEIGHT,
_("Use all monitors")));
allMonitorsButton->type(FL_RADIO_BUTTON);
allMonitorsButton->callback(handleFullScreenMode, this);
ty += RADIO_HEIGHT + TIGHT_MARGIN;

selectedMonitorsButton = new Fl_Round_Button(LBLRIGHT(tx, ty,
RADIO_MIN_WIDTH,
RADIO_HEIGHT,
_("Use selected monitor(s)")));
selectedMonitorsButton->type(FL_RADIO_BUTTON);
selectedMonitorsButton->callback(handleFullScreenMode, this);
ty += RADIO_HEIGHT + TIGHT_MARGIN;

int full_width = tw - OUTER_MARGIN * 2;
int margin_width = full_width - INDENT - INNER_MARGIN*2;
int full_height = th;
int margin_height = full_height - ty + INNER_MARGIN*3;

monitorArrangement = new MonitorArrangement(
tx + INDENT,
ty,
margin_width,
margin_height);

ty += CHECK_HEIGHT + margin_height;
}

fullScreenModeGroup->end();
@@ -933,6 +966,17 @@ void OptionsDialog::handleClipboard(Fl_Widget *widget, void *data)
#endif
}

void OptionsDialog::handleFullScreenMode(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;

if (dialog->selectedMonitorsButton->value()) {
dialog->monitorArrangement->activate();
} else {
dialog->monitorArrangement->deactivate();
}
}

void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
{
OptionsDialog *dialog = (OptionsDialog*)data;

+ 5
- 0
vncviewer/OptionsDialog.h 查看文件

@@ -30,6 +30,7 @@ class Fl_Round_Button;
class Fl_Input;
class Fl_Int_Input;
class Fl_Choice;
class MonitorArrangement;

typedef void (OptionsCallback)(void*);

@@ -66,6 +67,8 @@ protected:

static void handleClipboard(Fl_Widget *widget, void *data);

static void handleFullScreenMode(Fl_Widget *widget, void *data);

static void handleCancel(Fl_Widget *widget, void *data);
static void handleOK(Fl_Widget *widget, void *data);

@@ -128,6 +131,8 @@ protected:

Fl_Round_Button *currentMonitorButton;
Fl_Round_Button *allMonitorsButton;
Fl_Round_Button *selectedMonitorsButton;
MonitorArrangement *monitorArrangement;

/* Misc. */
Fl_Check_Button *sharedCheckbox;

+ 6
- 1
vncviewer/parameters.cxx 查看文件

@@ -103,11 +103,15 @@ IntParameter qualityLevel("QualityLevel",
BoolParameter maximize("Maximize", "Maximize viewer window", false);
BoolParameter fullScreen("FullScreen", "Enable full screen", false);
StringParameter fullScreenMode("FullScreenMode", "Specify which monitors to use when in full screen. "
"Should be either Current or All",
"Should be either Current, Selected or All",
"Current");
BoolParameter fullScreenAllMonitors("FullScreenAllMonitors",
"[DEPRECATED] Enable full screen over all monitors",
false);
MonitorIndicesParameter fullScreenSelectedMonitors("FullScreenSelectedMonitors",
"Use the given list of monitors in full screen"
" when -FullScreenMode=Selected.",
"1");
StringParameter desktopSize("DesktopSize",
"Reconfigure desktop size on the server on "
"connect (if possible)", "");
@@ -179,6 +183,7 @@ static VoidParameter* parameterArray[] = {
&qualityLevel,
&fullScreen,
&fullScreenMode,
&fullScreenSelectedMonitors,
&desktopSize,
&remoteResize,
&viewOnly,

+ 2
- 0
vncviewer/parameters.h 查看文件

@@ -21,6 +21,7 @@
#define __PARAMETERS_H__

#include <rfb/Configuration.h>
#include "MonitorIndicesParameter.h"

#ifdef _WIN32
#include <vector>
@@ -51,6 +52,7 @@ extern rfb::BoolParameter maximize;
extern rfb::BoolParameter fullScreen;
extern rfb::StringParameter fullScreenMode;
extern rfb::BoolParameter fullScreenAllMonitors; // deprecated
extern MonitorIndicesParameter fullScreenSelectedMonitors;
extern rfb::StringParameter desktopSize;
extern rfb::StringParameter geometry;
extern rfb::BoolParameter remoteResize;

+ 9
- 1
vncviewer/vncviewer.man 查看文件

@@ -211,9 +211,17 @@ full-screen mode. Replaced by \fB-FullScreenMode=all\fP
.
.TP
.B \-FullScreenMode \fImode\fP
Specify which monitors to use when in full screen. It should be either "Current" or "All".
Specify which monitors to use when in full screen. It should be either "Current",
"Selected" (specified by \fB-FullScreenSelectedMonitors\fP) or "All".
The default is "Current".
.
.TP
.B \-FullScreenSelectedMonitors \fImonitors\fP
This option specifies the monitors to use with \fB-FullScreenMode=selected\fP.
Monitors are ordered according to the system configuration from left to right,
and in case of a conflict, from top to bottom. So, for example, "1,2,3" means
that the first, second and third monitor counting from the left should be used.
The default is "1".
.
.TP
.B \-FullscreenSystemKeys

Loading…
取消
儲存