1 /*
2  * RClientMetrics.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include "RClientMetrics.hpp"
17 
18 #include <iostream>
19 
20 #include <core/Settings.hpp>
21 
22 #include <r/ROptions.hpp>
23 #include <r/session/RSession.hpp>
24 
25 #include "graphics/RGraphicsDevice.hpp"
26 
27 using namespace rstudio::core;
28 
29 namespace rstudio {
30 namespace r {
31 namespace session {
32 namespace client_metrics {
33 
34 namespace {
35 const char * const kConsoleWidth = "r.session.client_metrics.console-width";
36 const char * const kBuildConsoleWidth = "r.session.client_metrics.build-console-width";
37 const char * const kGraphicsWidth = "r.session.client_metrics.graphics-width";
38 const char * const kGraphicsHeight = "r.session.client_metrics.graphics-height";
39 const char * const kDevicePixelRatio = "r.session.client_metrics.device-pixel-ratio";
40 
41 }
42 
get()43 RClientMetrics get()
44 {
45    RClientMetrics metrics;
46    metrics.consoleWidth = r::options::getOptionWidth();
47    metrics.buildConsoleWidth = r::options::getBuildOptionWidth();
48    metrics.graphicsWidth = graphics::device::getWidth();
49    metrics.graphicsHeight = graphics::device::getHeight();
50    metrics.devicePixelRatio = graphics::device::devicePixelRatio();
51    return metrics;
52 }
53 
set(const RClientMetrics & metrics)54 void set(const RClientMetrics& metrics)
55 {
56    // set console width (if it's within the valid range -- if it's not
57    // then an error will be thrown)
58    if (metrics.consoleWidth >= 10 && metrics.consoleWidth <= 10000)
59       r::options::setOptionWidth(metrics.consoleWidth);
60    if (metrics.buildConsoleWidth >= 10 && metrics.buildConsoleWidth <= 10000)
61       r::options::setBuildOptionWidth(metrics.buildConsoleWidth);
62 
63    // set graphics size, however don't do anything if width or height is less
64    // than or equal to 0)
65    // (means the graphics window is minimized)
66    if (metrics.graphicsWidth > 0 && metrics.graphicsHeight > 0)
67    {
68       // enforce a minimum graphics size so we don't get display
69       // list redraw errors -- note that setting the device to a size
70       // which diverges from the actual client size will break locator
71       // so we need to set the size small enough that there is no way
72       // it can reasonably be used for locator
73       int width = std::max(metrics.graphicsWidth, 100);
74       int height = std::max(metrics.graphicsHeight, 100);
75 
76       // enforce a maximum graphics size so we don't create a device
77       // that is so large that it exhausts available memory
78       width = std::min(width, 10000);
79       height = std::min(height, 10000);
80 
81       // set device size
82       graphics::device::setSize(width, height, metrics.devicePixelRatio);
83    }
84 }
85 
save(Settings * pSettings)86 void save(Settings* pSettings)
87 {
88    // get the client metrics
89    RClientMetrics metrics = client_metrics::get();
90 
91    // save them
92    pSettings->beginUpdate();
93    pSettings->set(kConsoleWidth, metrics.consoleWidth);
94    pSettings->set(kBuildConsoleWidth, metrics.buildConsoleWidth);
95    pSettings->set(kGraphicsWidth, metrics.graphicsWidth);
96    pSettings->set(kGraphicsHeight, metrics.graphicsHeight);
97    pSettings->set(kDevicePixelRatio, metrics.devicePixelRatio);
98    pSettings->endUpdate();
99 }
100 
restore(const Settings & settings)101 void restore(const Settings& settings)
102 {
103    // read the client metrics (specify defaults to be defensive)
104    RClientMetrics metrics;
105    metrics.consoleWidth = settings.getInt(kConsoleWidth,
106                                           r::options::kDefaultWidth);
107    metrics.buildConsoleWidth = settings.getInt(kBuildConsoleWidth,
108                                           r::options::kDefaultWidth);
109    metrics.graphicsWidth = settings.getInt(kGraphicsWidth,
110                                            graphics::device::kDefaultWidth);
111 
112    metrics.graphicsHeight = settings.getInt(kGraphicsHeight,
113                                             graphics::device::kDefaultHeight);
114    metrics.devicePixelRatio = settings.getDouble(kDevicePixelRatio,
115                                        graphics::device::kDefaultDevicePixelRatio);
116 
117    // set them
118    set(metrics);
119 }
120 
121 
122 } // namespace client_metrics
123 } // namespace session
124 } // namespace r
125 } // namespace rstudio
126 
127 
128 
129