1 /*
2  *  Copyright (c) 2019 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "KisDlgCustomTabletResolution.h"
20 #include "ui_KisDlgCustomTabletResolution.h"
21 
22 #include <QSettings>
23 #include "kis_debug.h"
24 
25 #include <QGuiApplication>
26 #include <QScreen>
27 #include <QStandardPaths>
28 #include <qpa/qplatformscreen.h>
29 
30 namespace {
rectToString(const QRect & rc)31 QString rectToString(const QRect &rc) {
32     return QString("%1, %2 %3 x %4")
33             .arg(rc.x())
34             .arg(rc.y())
35             .arg(rc.width())
36             .arg(rc.height());
37 }
38 }
39 
KisDlgCustomTabletResolution(QWidget * parent)40 KisDlgCustomTabletResolution::KisDlgCustomTabletResolution(QWidget *parent) :
41     QDialog(parent),
42     ui(new Ui::KisDlgCustomTabletResolution)
43 {
44     ui->setupUi(this);
45     connect(ui->btnBox, SIGNAL(rejected()), this, SLOT(reject()));
46     connect(ui->btnBox, SIGNAL(accepted()), this, SLOT(accept()));
47 
48     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->lblXOffset, SLOT(setEnabled(bool)));
49     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->lblYOffset, SLOT(setEnabled(bool)));
50     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->lblWidth, SLOT(setEnabled(bool)));
51     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->lblHeight, SLOT(setEnabled(bool)));
52 
53     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->intXOffset, SLOT(setEnabled(bool)));
54     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->intYOffset, SLOT(setEnabled(bool)));
55     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->intWidth, SLOT(setEnabled(bool)));
56     connect(ui->radioCustomMapping, SIGNAL(toggled(bool)), ui->intHeight, SLOT(setEnabled(bool)));
57 
58     const QRect virtualScreenRect = calcNativeScreenRect();
59 
60     ui->radioMapToEntireScreen->setText(i18nc("@option:radio", "Map to entire virtual screen (%1)", rectToString(virtualScreenRect)));
61 
62     QRect nativeScreenRect;
63     QPlatformScreen *screen = qGuiApp->primaryScreen()->handle();
64     Q_FOREACH (QPlatformScreen *scr, screen->virtualSiblings()) {
65         nativeScreenRect |= scr->geometry();
66     }
67 
68     QRect customScreenRect = virtualScreenRect;
69     Mode mode = getTabletMode(&customScreenRect);
70 
71     if (mode == USE_CUSTOM) {
72         ui->radioCustomMapping->setChecked(true);
73     } else if (mode == USE_VIRTUAL_SCREEN) {
74         ui->radioMapToEntireScreen->setChecked(true);
75     } else {
76         ui->radioMapAsWintab->setChecked(true);
77     }
78 
79     ui->intXOffset->setValue(customScreenRect.x());
80     ui->intYOffset->setValue(customScreenRect.y());
81     ui->intWidth->setValue(customScreenRect.width());
82     ui->intHeight->setValue(customScreenRect.height());
83 }
84 
accept()85 void KisDlgCustomTabletResolution::accept()
86 {
87     const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
88     QSettings cfg(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
89 
90     if (ui->radioMapAsWintab->isChecked()) {
91         cfg.setValue("wintabResolutionMode", "wintab");
92     } else if (ui->radioMapToEntireScreen->isChecked()) {
93         cfg.setValue("wintabResolutionMode", "virtual-screen");
94     } else if (ui->radioCustomMapping->isChecked()) {
95         cfg.setValue("wintabResolutionMode", "custom");
96 
97         cfg.setValue("wintabCustomResolutionX", ui->intXOffset->value());
98         cfg.setValue("wintabCustomResolutionY", ui->intYOffset->value());
99         cfg.setValue("wintabCustomResolutionWidth", ui->intWidth->value());
100         cfg.setValue("wintabCustomResolutionHeight", ui->intHeight->value());
101     }
102 
103     // apply the mode right now
104     {
105         QRect customTabletRect;
106         const Mode tabletMode = getTabletMode(&customTabletRect);
107         applyConfiguration(tabletMode, customTabletRect);
108     }
109 
110     QDialog::accept();
111 }
112 
~KisDlgCustomTabletResolution()113 KisDlgCustomTabletResolution::~KisDlgCustomTabletResolution()
114 {
115     delete ui;
116 }
117 
calcNativeScreenRect()118 QRect KisDlgCustomTabletResolution::calcNativeScreenRect()
119 {
120     QRect nativeScreenRect;
121     QPlatformScreen *screen = qGuiApp->primaryScreen()->handle();
122     Q_FOREACH (QPlatformScreen *scr, screen->virtualSiblings()) {
123         nativeScreenRect |= scr->geometry();
124     }
125     return nativeScreenRect;
126 }
127 
getTabletMode(QRect * customRect)128 KisDlgCustomTabletResolution::Mode KisDlgCustomTabletResolution::getTabletMode(QRect *customRect)
129 {
130     const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
131     QSettings cfg(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
132 
133     const QString mode = cfg.value("wintabResolutionMode", QString("wintab")).toString();
134     Mode modeValue = USE_WINTAB;
135 
136     if (mode == "custom") {
137         modeValue = USE_CUSTOM;
138     } else if (mode == "virtual-screen") {
139         modeValue = USE_VIRTUAL_SCREEN;
140     } else {
141         modeValue = USE_WINTAB;
142     }
143 
144     if (mode == "custom") {
145         customRect->setX(cfg.value("wintabCustomResolutionX", customRect->x()).toInt());
146         customRect->setY(cfg.value("wintabCustomResolutionY", customRect->y()).toInt());
147         customRect->setWidth(cfg.value("wintabCustomResolutionWidth", customRect->width()).toInt());
148         customRect->setHeight(cfg.value("wintabCustomResolutionHeight", customRect->height()).toInt());
149     }
150 
151     return modeValue;
152 }
153 
applyConfiguration(KisDlgCustomTabletResolution::Mode tabletMode,const QRect & customTabletRect)154 void KisDlgCustomTabletResolution::applyConfiguration(KisDlgCustomTabletResolution::Mode tabletMode, const QRect &customTabletRect)
155 {
156     if (tabletMode == KisDlgCustomTabletResolution::USE_CUSTOM) {
157         qputenv("QT_WINTAB_DESKTOP_RECT",
158                 QString("%1;%2;%3;%4")
159                 .arg(customTabletRect.x())
160                 .arg(customTabletRect.y())
161                 .arg(customTabletRect.width())
162                 .arg(customTabletRect.height()).toLatin1());
163         qunsetenv("QT_IGNORE_WINTAB_MAPPING");
164     } else if (tabletMode == KisDlgCustomTabletResolution::USE_VIRTUAL_SCREEN) {
165         qputenv("QT_IGNORE_WINTAB_MAPPING", "1");
166         qunsetenv("QT_WINTAB_DESKTOP_RECT");
167     } else {
168         qunsetenv("QT_WINTAB_DESKTOP_RECT");
169         qunsetenv("QT_IGNORE_WINTAB_MAPPING");
170     }
171 }
172