diff --git a/src/kcmodule/calibrationdialog.cpp b/src/kcmodule/calibrationdialog.cpp
index 70a0591..de8adb2 100644
--- a/src/kcmodule/calibrationdialog.cpp
+++ b/src/kcmodule/calibrationdialog.cpp
@@ -1,155 +1,165 @@
/*
* This file is part of the KDE wacomtablet project. For copyright
* information and license terms see the AUTHORS and COPYING files
* in the top-level directory of this distribution.
*
* This program 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 program 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 program. If not, see .
*/
#include "calibrationdialog.h"
#include "logging.h"
#include "x11wacom.h"
+#include "x11info.h"
//KDE includes
#include
//Qt includes
#include
#include
#include
#include
#include
using namespace Wacom;
const int frameGap = 10;
const int boxwidth = 100;
-CalibrationDialog::CalibrationDialog( const QString &toolname ) :
- QDialog( )
+CalibrationDialog::CalibrationDialog(const QString &toolname, const QString &targetScreen)
+ : QDialog()
+ , m_drawCross(0)
+ , m_toolName(toolname)
{
- setWindowState( Qt::WindowFullScreen );
+ auto screenList = X11Info::getScreenGeometries();
+ if (screenList.count() > 1) {
+ if (screenList.contains(targetScreen)) {
+ move(screenList.value(targetScreen).topLeft());
+ } else {
+ qCWarning(KCM) << "Calibration requested for unknown screen" << targetScreen;
+ }
+ }
+
+ setWindowState(Qt::WindowFullScreen);
- m_toolName = toolname;
- m_drawCross = 0;
m_shiftLeft = frameGap;
m_shiftTop = frameGap;
m_originaltabletArea = X11Wacom::getMaximumTabletArea(m_toolName);
QLabel *showInfo = new QLabel();
showInfo->setText( i18n( "Please tap into all four corners to calibrate the tablet.\nPress escape to cancel the process." ) );
showInfo->setAlignment( Qt::AlignCenter );
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget( showInfo );
setLayout(mainLayout);
}
QRect CalibrationDialog::calibratedArea()
{
return m_newtabletArea.toRect();
}
void CalibrationDialog::paintEvent( QPaintEvent *event )
{
Q_UNUSED( event );
QPainter painter( this );
painter.setPen(palette().color(QPalette::WindowText));
// vertical line
painter.drawLine( m_shiftLeft + boxwidth / 2,
m_shiftTop,
m_shiftLeft + boxwidth / 2,
m_shiftTop + boxwidth );
// horizontal line
painter.drawLine( m_shiftLeft,
m_shiftTop + boxwidth / 2,
m_shiftLeft + boxwidth,
m_shiftTop + boxwidth / 2 );
// draw circle around center
painter.drawEllipse( QPoint( m_shiftLeft + boxwidth / 2,
m_shiftTop + boxwidth / 2 ),
10, 10 );
}
void CalibrationDialog::mousePressEvent( QMouseEvent *event )
{
if( event->pos().x() > m_shiftLeft
&& event->pos().x() < m_shiftLeft + boxwidth
&& event->pos().y() > m_shiftTop
&& event->pos().y() < m_shiftTop + boxwidth ) {
m_drawCross++;
switch( m_drawCross ) {
case 1:
m_topLeft = event->windowPos();
m_shiftLeft = frameGap;
m_shiftTop = size().height() - frameGap - boxwidth;
break;
case 2:
m_bottomLeft = event->windowPos();
m_shiftLeft = size().width() - frameGap - boxwidth;
m_shiftTop = size().height() - frameGap - boxwidth;
break;
case 3:
m_bottomRight = event->windowPos();
m_shiftLeft = size().width() - frameGap - boxwidth;
m_shiftTop = frameGap;
break;
case 4:
m_topRight = event->windowPos();
calculateNewArea();
close();
break;
}
update();
}
}
void CalibrationDialog::calculateNewArea()
{
qreal frameoffset = frameGeometry().height() - size().height();
qreal tabletScreenRatioWidth = m_originaltabletArea.width() / size().width();
qreal tabletScreenRatioHeight = m_originaltabletArea.height() / size().height();
const qreal clickedX = ( m_topLeft.x() + m_bottomLeft.x() ) / 2;
const qreal clickedXadjusted = clickedX - frameGap - boxwidth / 2;
const qreal newX = m_originaltabletArea.x() + clickedXadjusted * tabletScreenRatioWidth;
const qreal clickedY = ( m_topLeft.y() + m_topRight.y() ) / 2;
const qreal clickedYadjusted = clickedY - frameGap - boxwidth / 2;
const qreal newY = m_originaltabletArea.y() + clickedYadjusted * tabletScreenRatioHeight;
const qreal clickedXright = ( m_topRight.x() + m_bottomRight.x() ) / 2;
const qreal newWidth = ( clickedXright + frameGap + boxwidth / 2 ) * tabletScreenRatioWidth;
const qreal clickedYbottom = ( m_bottomRight.y() + m_bottomLeft.y() ) / 2;
const qreal newHeight = ( clickedYbottom + frameGap + boxwidth / 2 + frameoffset ) * tabletScreenRatioHeight;
m_newtabletArea.setX( newX );
m_newtabletArea.setY( newY );
m_newtabletArea.setRight( newWidth );
m_newtabletArea.setBottom( newHeight );
qCDebug(KCM) << "Calibration debug:" << frameGeometry() << size() << m_originaltabletArea << m_topLeft << m_bottomLeft << m_topRight << m_bottomRight;
qCDebug(KCM) << "Calibration debug:" << frameoffset << tabletScreenRatioWidth << tabletScreenRatioHeight << clickedX << clickedY << clickedXright << clickedYbottom;
qCDebug(KCM) << "Calibration debug:" << m_newtabletArea;
}
diff --git a/src/kcmodule/calibrationdialog.h b/src/kcmodule/calibrationdialog.h
index 82c4144..08399a4 100644
--- a/src/kcmodule/calibrationdialog.h
+++ b/src/kcmodule/calibrationdialog.h
@@ -1,86 +1,87 @@
/*
* This file is part of the KDE wacomtablet project. For copyright
* information and license terms see the AUTHORS and COPYING files
* in the top-level directory of this distribution.
*
* This program 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 program 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 program. If not, see .
*/
#ifndef CALIBRATIONDIALOG_H
#define CALIBRATIONDIALOG_H
#include
namespace Wacom {
/**
* @brief
*
*/
class CalibrationDialog : public QDialog {
Q_OBJECT
public:
/**
* @brief Constructs the fullscreen window for the calibration process
*
* @param toolname name of the tool to calibrate (stylus or touch name)
+ * @param targetScreen screen which is going to be used for calibration
*/
- explicit CalibrationDialog( const QString &toolname );
+ CalibrationDialog(const QString &toolname, const QString &targetScreen);
/**
* @brief Returns the new tablet area
*
* @return Tablet area after calibration
*/
QRect calibratedArea();
protected:
/**
* @brief Draws the cross for the calibration
*
* The user has to hit the center of the cross for the calibration
*
* @param event some additional event details
*/
void paintEvent( QPaintEvent *event );
/**
* @brief Catch mousepress events
*
* Only events inside the calibration cross are recognized. All other are ignored.
*
* @param event mouse press details
*/
void mousePressEvent( QMouseEvent *event );
private:
/**
* @brief calculates the new tablet area from all 4 calibration points
*/
void calculateNewArea();
int m_drawCross; /**< Which cross should be drawn? 0=topleft, 1=bottomleft, and so on */
int m_shiftLeft; /**< Where to start the cross from the left */
int m_shiftTop; /**< Where to start the cross from the top */
QString m_toolName; /**< Name of the tool to calibrate (stylus name or touch name) */
QRectF m_originaltabletArea; /**< Original tablet area before calibration */
QRectF m_newtabletArea; /**< Calibrated tablet area */
QPointF m_topLeft; /**< Top left clicked point for calibration */
QPointF m_bottomLeft; /**< Bottom left clicked point for calibration */
QPointF m_topRight; /**< Top right clicked point for calibration */
QPointF m_bottomRight; /**< Bottom right clicked point for calibration */
};
}
#endif // CALIBRATIONDIALOG_H
diff --git a/src/kcmodule/tabletareaselectioncontroller.cpp b/src/kcmodule/tabletareaselectioncontroller.cpp
index 1f36182..695d943 100644
--- a/src/kcmodule/tabletareaselectioncontroller.cpp
+++ b/src/kcmodule/tabletareaselectioncontroller.cpp
@@ -1,360 +1,360 @@
/*
* This file is part of the KDE wacomtablet project. For copyright
* information and license terms see the AUTHORS and COPYING files
* in the top-level directory of this distribution.
*
* This program 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 program 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 program. If not, see .
*/
#include "tabletareaselectioncontroller.h"
#include "logging.h"
#include "tabletareaselectionview.h"
#include "calibrationdialog.h"
#include "screenmap.h"
#include "stringutils.h"
#include "x11info.h"
#include "x11wacom.h"
using namespace Wacom;
namespace Wacom {
class TabletAreaSelectionControllerPrivate
{
public:
TabletAreaSelectionView *view = nullptr;
TabletArea tabletGeometry; // the original tablet geometry
TabletArea tabletGeometryRotated; // the rotated tablet geometry if rotation is active
QMap screenGeometries; // the geometries of all screens which form the desktop
ScreenSpace currentScreen;
QString deviceName; // the device this instance is handling
ScreenMap screenMap; // the current screen mappings
ScreenRotation tabletRotation = ScreenRotation::NONE; // the tablet rotation
};
}
TabletAreaSelectionController::TabletAreaSelectionController()
: QObject(), d_ptr(new TabletAreaSelectionControllerPrivate)
{
// nothing to do except for initializing our private class
}
TabletAreaSelectionController::~TabletAreaSelectionController()
{
delete this->d_ptr;
}
const ScreenMap& TabletAreaSelectionController::getScreenMap()
{
Q_D(const TabletAreaSelectionController);
// make sure the current mapping is included
setMapping(d->currentScreen, d->view->getSelection());
// return mapping
return d->screenMap;
}
const ScreenSpace TabletAreaSelectionController::getScreenSpace() const
{
Q_D(const TabletAreaSelectionController);
return d->currentScreen;
}
void TabletAreaSelectionController::select(const ScreenSpace& screenSpace)
{
Q_D(TabletAreaSelectionController);
if (!hasView()) {
return;
}
setMapping(d->currentScreen, d->view->getSelection());
d->currentScreen = screenSpace;
d->view->select(screenSpace.toString(), screenSpace.isDesktop(), getMapping(d->currentScreen));
}
void TabletAreaSelectionController::setView(TabletAreaSelectionView* view)
{
Q_D(TabletAreaSelectionController);
// cleanup signal/slot connections if we already have a view
if (d->view) {
disconnect(d->view, SIGNAL(signalCalibrateClicked()), this, SLOT(onCalibrateClicked()));
disconnect(d->view, SIGNAL(signalFullTabletSelection()), this, SLOT(onFullTabletSelected()));
disconnect(d->view, SIGNAL(signalScreenToggle()), this, SLOT(onScreenToggle()));
disconnect(d->view, SIGNAL(signalSetScreenProportions()), this, SLOT(onSetScreenProportions()));
disconnect(d->view, SIGNAL(signalTabletAreaSelection()), this, SLOT(onTabletAreaSelected()));
}
// save view and connect signals
d->view = view;
if (view) {
connect(view, SIGNAL(signalCalibrateClicked()), this, SLOT(onCalibrateClicked()));
connect(view, SIGNAL(signalFullTabletSelection()), this, SLOT(onFullTabletSelected()));
connect(view, SIGNAL(signalScreenToggle()), this, SLOT(onScreenToggle()));
connect(view, SIGNAL(signalSetScreenProportions()), this, SLOT(onSetScreenProportions()));
connect(view, SIGNAL(signalTabletAreaSelection()), this, SLOT(onTabletAreaSelected()));
}
}
void TabletAreaSelectionController::setupController(const ScreenMap& mappings,
const QString& deviceName,
const ScreenRotation& rotation)
{
Q_D(TabletAreaSelectionController);
if (!hasView()) {
return;
}
d->deviceName = deviceName;
d->tabletGeometry = X11Wacom::getMaximumTabletArea(deviceName);
d->screenGeometries = X11Info::getScreenGeometries();
d->screenMap = mappings;
if (rotation == ScreenRotation::AUTO) {
// TODO
d->tabletRotation = X11Info::getScreenRotation();
// we have a tablet (not a canvas) viewpoint here, so we need to invert the screen rotation
d->tabletRotation = d->tabletRotation.invert();
} else if (rotation == ScreenRotation::AUTO_INVERTED) {
// TODO
d->tabletRotation = X11Info::getScreenRotation();
} else {
d->tabletRotation = rotation;
}
d->tabletGeometryRotated = d->tabletGeometry;
if (d->tabletRotation == ScreenRotation::CW || d->tabletRotation == ScreenRotation::CCW) {
d->tabletGeometryRotated.setWidth(d->tabletGeometry.height());
d->tabletGeometryRotated.setHeight(d->tabletGeometry.width());
}
qCDebug(KCM) << "Calling setupScreens and setupTablet from setupController. ScreenGeometries: " << d->screenGeometries;
d->view->setupScreens(d->screenGeometries, QSize(200,200));
d->view->setupTablet(d->tabletGeometryRotated, QSize(400,400));
// make sure we have valid data set
d->view->select(d->currentScreen.toString(), d->currentScreen.isDesktop(), getMapping(d->currentScreen));
}
void TabletAreaSelectionController::onCalibrateClicked()
{
Q_D(TabletAreaSelectionController);
- CalibrationDialog calibDialog(d->deviceName);
+ CalibrationDialog calibDialog(d->deviceName, d->currentScreen.toString());
calibDialog.exec();
setSelection(TabletArea(calibDialog.calibratedArea()));
}
void TabletAreaSelectionController::onFullTabletSelected()
{
checkConfigurationForTrackingModeProblems();
}
void TabletAreaSelectionController::onScreenToggle()
{
Q_D(TabletAreaSelectionController);
select(d->currentScreen.next());
}
void TabletAreaSelectionController::onSetScreenProportions()
{
Q_D(TabletAreaSelectionController);
QRect tabletGeometry = d->tabletGeometryRotated;
QRect screenSelection = getScreenGeometry(d->currentScreen.toString());
if (screenSelection.isEmpty()) {
return;
}
// calculate new height and width of the selection
qreal screenAreaSelectionRatio = (float)screenSelection.width() / screenSelection.height();
qreal newWidth, newHeight;
if (screenSelection.width() > screenSelection.height()) {
newWidth = tabletGeometry.width();
newHeight = newWidth / screenAreaSelectionRatio;
if (newHeight > tabletGeometry.height()) {
newHeight = tabletGeometry.height();
newWidth = newHeight * screenAreaSelectionRatio;
}
} else {
newHeight = tabletGeometry.height();
newWidth = newHeight * screenAreaSelectionRatio;
if (newWidth > tabletGeometry.width()) {
newWidth = tabletGeometry.width();
newHeight = newWidth / screenAreaSelectionRatio;
}
}
// calculate x and y to center the selection
int newX = tabletGeometry.x() + (int)((tabletGeometry.width() - newWidth) / 2.);
int newY = tabletGeometry.y() + (int)((tabletGeometry.height() - newHeight) / 2.);
setSelection(TabletArea(QRect(newX, newY, qRound(newWidth), qRound(newHeight))));
}
void TabletAreaSelectionController::onTabletAreaSelected()
{
checkConfigurationForTrackingModeProblems();
}
bool TabletAreaSelectionController::hasView() const
{
Q_D(const TabletAreaSelectionController);
return (d->view != nullptr);
}
void TabletAreaSelectionController::checkConfigurationForTrackingModeProblems()
{
Q_D(TabletAreaSelectionController);
// a device can not be mapped to a single screen in relative mode
if (d->currentScreen.isMonitor()) {
d->view->setTrackingModeWarning(true);
} else {
d->view->setTrackingModeWarning(false);
}
}
const TabletArea TabletAreaSelectionController::convertAreaFromRotation(const TabletArea &tablet, const TabletArea &area, const ScreenRotation &rotation) const
{
TabletArea result = area;
if (rotation == ScreenRotation::CW) {
result.setX(area.y());
result.setY(tablet.height() - area.x() - area.width());
result.setWidth(area.height());
result.setHeight(area.width());
} else if (rotation == ScreenRotation::CCW) {
result.setX(tablet.width() - area.y() - area.height());
result.setY(area.x());
result.setWidth(area.height());
result.setHeight(area.width());
} else if (rotation == ScreenRotation::HALF) {
result.setX(tablet.width() - area.width() - area.x());
result.setY(tablet.height() - area.height() - area.y());
result.setWidth(area.width());
result.setHeight(area.height());
}
return result;
}
const TabletArea TabletAreaSelectionController::convertAreaToRotation(const TabletArea &tablet, const TabletArea &area, const ScreenRotation &rotation) const
{
TabletArea result = area;
if (rotation == ScreenRotation::CW) {
result.setX(tablet.height() - area.height() - area.y());
result.setY(area.x());
result.setWidth(area.height());
result.setHeight(area.width());
} else if (rotation == ScreenRotation::CCW) {
result.setX(area.y());
result.setY(tablet.width() - area.width() - area.x());
result.setWidth(area.height());
result.setHeight(area.width());
} else if (rotation == ScreenRotation::HALF) {
result.setX(tablet.width() - area.width() - area.x());
result.setY(tablet.height() - area.height() - area.y());
result.setWidth(area.width());
result.setHeight(area.height());
}
return result;
}
const QRect TabletAreaSelectionController::getScreenGeometry(QString output) const
{
Q_D(const TabletAreaSelectionController);
return d->screenGeometries.value(output, X11Info::getDisplayGeometry());
}
const TabletArea TabletAreaSelectionController::getMapping(ScreenSpace screenSpace) const
{
Q_D(const TabletAreaSelectionController);
return convertAreaToRotation(d->tabletGeometry, d->screenMap.getMapping(screenSpace), d->tabletRotation);
}
void TabletAreaSelectionController::setMapping(ScreenSpace screenSpace, const TabletArea &mapping)
{
Q_D(TabletAreaSelectionController);
TabletArea area = convertAreaFromRotation(d->tabletGeometry, mapping, d->tabletRotation);
d->screenMap.setMapping(screenSpace, area);
}
void TabletAreaSelectionController::setSelection(const TabletArea &selection)
{
Q_D(TabletAreaSelectionController);
if (!hasView()) {
return;
}
if (selection.isEmpty() || selection == d->tabletGeometryRotated) {
d->view->selectFullTablet();
} else {
d->view->selectPartOfTablet(selection);
}
}