diff --git a/src/common/screenspace.cpp b/src/common/screenspace.cpp index f1c2160..e543ca1 100644 --- a/src/common/screenspace.cpp +++ b/src/common/screenspace.cpp @@ -1,168 +1,186 @@ /* * 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 "screenspace.h" #include "logging.h" #include "x11info.h" using namespace Wacom; namespace Wacom { static const QString DESKTOP_STRING = QLatin1String("desktop"); static const QString AREA_STRING = QLatin1String("area"); static const QString SPEED_STRING = QLatin1String("speed"); } ScreenSpace::ScreenSpace() { } ScreenSpace::ScreenSpace(const QString &screenSpaceString) { if (screenSpaceString == DESKTOP_STRING) { _type = ScreenSpaceType::Desktop; return; } QStringList tokens = screenSpaceString.split(QChar::fromLatin1('x')); if (tokens.size() == 5 && tokens.at(0) == AREA_STRING) { _type = ScreenSpaceType::Area; _area = QRect( tokens.at(1).toInt(), tokens.at(2).toInt(), tokens.at(3).toInt(), tokens.at(4).toInt() ); return; } if (tokens.size() == 3 && tokens.at(0) == SPEED_STRING) { _type = ScreenSpaceType::ArbitraryTranslationMatrix; _speed = QPointF( tokens.at(1).toDouble(), tokens.at(2).toDouble() ); return; } _type = ScreenSpaceType::Output; _output = screenSpaceString; } ScreenSpace::~ScreenSpace() { } bool ScreenSpace::operator==(const ScreenSpace& screenSpace) const { if (getType() != screenSpace.getType()) return false; switch (getType()) { case Wacom::ScreenSpace::ScreenSpaceType::Output: return _output == screenSpace._output; case Wacom::ScreenSpace::ScreenSpaceType::Area: return _area == screenSpace._area; case Wacom::ScreenSpace::ScreenSpaceType::ArbitraryTranslationMatrix: return _speed == screenSpace._speed; case Wacom::ScreenSpace::ScreenSpaceType::Desktop: default: return true; } } const ScreenSpace ScreenSpace::desktop() { return ScreenSpace(DESKTOP_STRING); } bool ScreenSpace::isDesktop() const { return _type == ScreenSpaceType::Desktop; } bool ScreenSpace::isMonitor() const { return _type == ScreenSpaceType::Output; } const ScreenSpace ScreenSpace::monitor(QString output) { return ScreenSpace(output); } const QString ScreenSpace::toString() const { switch (getType()) { case ScreenSpaceType::Desktop: return DESKTOP_STRING; case ScreenSpaceType::Output: return _output; case ScreenSpaceType::Area: return QString::fromLatin1("%1x%2x%3x%4x%5") .arg(AREA_STRING).arg(_area.left()).arg(_area.top()).arg(_area.width()).arg(_area.height()); case ScreenSpaceType::ArbitraryTranslationMatrix: return QString::fromLatin1("%1x%2x%3") .arg(SPEED_STRING).arg(_speed.x()).arg(_speed.y()); default: qCDebug(COMMON) << "Broken ScreenSpace serialized"; return DESKTOP_STRING; } } +QRect ScreenSpace::toScreenGeometry() const +{ + switch (getType()) { + case ScreenSpaceType::Output: + { + const auto screenList = X11Info::getScreenGeometries(); + return screenList.contains(toString()) ? screenList.value(toString()) : QRect(); + } + case ScreenSpaceType::Area: + return getArea(); + case ScreenSpaceType::Desktop: + return X11Info::getDisplayGeometry(); + case ScreenSpaceType::ArbitraryTranslationMatrix: + default: + return QRect(); + } +} + ScreenSpace ScreenSpace::next() const { ScreenSpace nextScreen = ScreenSpace::desktop(); if (getType() != ScreenSpaceType::Output) { nextScreen = ScreenSpace::monitor(X11Info::getPrimaryScreenName()); } else { auto nextScreenName = X11Info::getNextScreenName(toString()); if (nextScreenName == X11Info::getPrimaryScreenName()) { nextScreen = ScreenSpace::desktop(); } else { nextScreen = ScreenSpace::monitor(nextScreenName); } } return nextScreen; } ScreenSpace::ScreenSpaceType ScreenSpace::getType() const { return _type; } QPointF ScreenSpace::getSpeed() const { return _speed; } QRect ScreenSpace::getArea() const { return _area; } diff --git a/src/common/screenspace.h b/src/common/screenspace.h index c5fa1c3..6ecc32f 100644 --- a/src/common/screenspace.h +++ b/src/common/screenspace.h @@ -1,85 +1,95 @@ /* * 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 SCREENSPACE_H #define SCREENSPACE_H #include #include namespace Wacom { /** * @brief Specifies screen area that is used for mapping * * Stores either "desktop", specific output, arbitrary area * or translation matrix (for relative mode). * When set as a device property, is converted into translation matrix. */ class ScreenSpace { public: enum class ScreenSpaceType { Desktop, Output, Area, ArbitraryTranslationMatrix, }; ScreenSpace(); ScreenSpace(const QString& screenSpaceString); virtual ~ScreenSpace(); bool operator== (const ScreenSpace& screenSpace) const; static const ScreenSpace desktop(); bool isDesktop() const; bool isMonitor() const; static const ScreenSpace monitor(QString output); const QString toString() const; + /** + * @brief Converts ScreenSpace to corresponding geometry + * + * For example, if it's set to output DVI-1, returns geometry of the screen + * connected to DVI-1 + * + * Returns empty rectangle on error + */ + QRect toScreenGeometry() const; + /** * This function allows to cycle through all existing screen spaces in a loop, * which means every individual connected screen and "desktop" (whole screen) * * @return Next ScreenSpace after this */ ScreenSpace next() const; ScreenSpaceType getType() const; QPointF getSpeed() const; QRect getArea() const; private: ScreenSpaceType _type = ScreenSpaceType::Desktop; QString _output; QRect _area; QPointF _speed; }; // CLASS } // NAMESPACE #endif // HEADER PROTECTION diff --git a/src/kcmodule/kcmwacomtabletwidget.ui b/src/kcmodule/kcmwacomtabletwidget.ui index 8c252ab..f51a6d0 100644 --- a/src/kcmodule/kcmwacomtabletwidget.ui +++ b/src/kcmodule/kcmwacomtabletwidget.ui @@ -1,130 +1,118 @@ KCMWacomTabletWidget 0 0 646 522 Graphic Tablet Settings - - 0 - - - 0 - - - 0 - - - 0 - - - + + &Select Tablet: tabletListSelector - + 0 0 - - - - - + Select &Profile: profileSelector - - - - - 0 - 0 - - - - - - - - Creates a new default profile - - - - - - Qt::ToolButtonIconOnly - - - document-new - - - - - - - Deletes the current profile - - - edit-delete-page - - + + + + + + + 0 + 0 + + + + + + + + Creates a new default profile + + + + + + Qt::ToolButtonIconOnly + + + document-new + + + + + + + Deletes the current profile + + + edit-delete-page + + + + true KAnimatedButton QToolButton
kanimatedbutton.h
profileSelector addProfileButton delProfileButton deviceTabWidget
diff --git a/src/kded/xsetwacomadaptor.cpp b/src/kded/xsetwacomadaptor.cpp index 6b0a645..4389739 100644 --- a/src/kded/xsetwacomadaptor.cpp +++ b/src/kded/xsetwacomadaptor.cpp @@ -1,273 +1,273 @@ /* * 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 "xsetwacomadaptor.h" #include "logging.h" #include "xsetwacomproperty.h" #include "stringutils.h" #include "buttonshortcut.h" #include "screenrotation.h" #include "tabletarea.h" #include #include using namespace Wacom; namespace Wacom { class XsetwacomAdaptorPrivate { public: QMap buttonMap; QString device; }; // CLASS } // NAMESPACE XsetwacomAdaptor::XsetwacomAdaptor(const QString& deviceName) : PropertyAdaptor(nullptr), d_ptr(new XsetwacomAdaptorPrivate) { Q_D( XsetwacomAdaptor ); d->device = deviceName; } XsetwacomAdaptor::XsetwacomAdaptor(const QString& deviceName, const QMap< QString, QString >& buttonMap) : PropertyAdaptor(nullptr), d_ptr(new XsetwacomAdaptorPrivate) { Q_D( XsetwacomAdaptor ); d->buttonMap = buttonMap; d->device = deviceName; } XsetwacomAdaptor::~XsetwacomAdaptor() { delete this->d_ptr; } const QList< Property > XsetwacomAdaptor::getProperties() const { return XsetwacomProperty::ids(); } const QString XsetwacomAdaptor::getProperty(const Property& property) const { Q_D( const XsetwacomAdaptor ); const XsetwacomProperty *xsetproperty = XsetwacomProperty::map(property); if (!xsetproperty) { qCWarning(KDED) << QString::fromLatin1("Can not get unsupported property '%1' using xsetwacom!").arg(property.key()); return QString(); } // TODO: get invert scroll parameter QString convertedParam = convertParameter (*xsetproperty); QString xsetwacomValue = getParameter (d->device, convertedParam); // convert value to a unified format convertFromXsetwacomValue (*xsetproperty, xsetwacomValue); qCDebug(KDED) << QString::fromLatin1("Reading property '%1' from device '%2' -> '%3'.").arg(property.key()).arg(d->device).arg(xsetwacomValue); return xsetwacomValue; } bool XsetwacomAdaptor::setProperty(const Property& property, const QString& value) { Q_D( const XsetwacomAdaptor ); qCDebug(KDED) << QString::fromLatin1("Setting property '%1' to '%2' on device '%3'.").arg(property.key()).arg(value).arg(d->device); const XsetwacomProperty *xsetproperty = XsetwacomProperty::map(property); if (!xsetproperty) { qCWarning(KDED) << QString::fromLatin1("Can not set unsupported property '%1' to '%2' on device '%3' using xsetwacom!").arg(property.key()).arg(value).arg(d->device); return false; } // check for properties which need special handling if (property == Property::Area) { return setArea(value); }else if (property == Property::Rotate) { return setRotation(value); } else { // normal property QString convertedParam = convertParameter(*xsetproperty); QString convertedValue = value; convertToXsetwacomValue(*xsetproperty, convertedValue); return setParameter(d->device, convertedParam, convertedValue); } return false; } bool XsetwacomAdaptor::supportsProperty(const Property& property) const { return (XsetwacomProperty::map(property) != nullptr); } const QString XsetwacomAdaptor::convertParameter(const XsetwacomProperty& param) const { Q_D( const XsetwacomAdaptor ); QString modifiedParam = param.key(); // convert tablet button number to hardware button number QRegExp rx(QLatin1String("^Button\\s*([0-9]+)$"), Qt::CaseInsensitive); if (rx.indexIn(modifiedParam, 0) != -1) { QString hwButtonNumber = rx.cap(1); QString kernelButtonNumber; if (!d->buttonMap.isEmpty()) { kernelButtonNumber = d->buttonMap.value(hwButtonNumber); } if (kernelButtonNumber.isEmpty()) { kernelButtonNumber = hwButtonNumber; } - //qCDebug(KDED) << QString::fromLatin1("Mapping tablet button %1 to X11 button %2.").arg(hwButtonNumber).arg(kernelButtonNumber); + qCDebug(KDED) << QString::fromLatin1("Mapping tablet button %1 to X11 button %2.").arg(hwButtonNumber).arg(kernelButtonNumber); modifiedParam = QString(QLatin1String("Button %1")).arg(kernelButtonNumber); } return modifiedParam; } void XsetwacomAdaptor::convertButtonShortcut (const XsetwacomProperty& property, QString& value) const { QRegExp rx (QLatin1String("^Button\\s*[0-9]+$"), Qt::CaseInsensitive); if (rx.indexIn(property.key(), 0) != -1) { ButtonShortcut buttonshortcut(value); value = buttonshortcut.toString(); } } void XsetwacomAdaptor::convertFromXsetwacomValue(const XsetwacomProperty& property, QString& value) const { // convert button shortcuts to a unified format convertButtonShortcut(property, value); } void XsetwacomAdaptor::convertToXsetwacomValue(const XsetwacomProperty& property, QString& value) const { // convert button shortcuts to a unified format convertButtonShortcut(property, value); } const QString XsetwacomAdaptor::getParameter(const QString& device, const QString& param) const { QString cmd = QString::fromLatin1( "xsetwacom get \"%1\" %2" ).arg( device ).arg( param ); QProcess getConf; getConf.start( cmd ); if( !getConf.waitForStarted() || !getConf.waitForFinished() ) { return QString(); } QString result = QLatin1String( getConf.readAll() ); return result.remove( QLatin1Char( '\n' ) ); } bool XsetwacomAdaptor::setArea(const QString& value) { Q_D( const XsetwacomAdaptor ); TabletArea area(value); if ( area.isEmpty() ) { return setParameter(d->device, XsetwacomProperty::ResetArea.key(), QString()); } return setParameter(d->device, XsetwacomProperty::Area.key(), area.toString()); } bool XsetwacomAdaptor::setRotation(const QString& value) { Q_D( const XsetwacomAdaptor ); const ScreenRotation* lookup = ScreenRotation::find(value); ScreenRotation rotation = lookup ? *lookup : ScreenRotation::NONE; // only accept real rotations if (rotation == ScreenRotation::NONE || rotation == ScreenRotation::CW || rotation == ScreenRotation::CCW || rotation == ScreenRotation::HALF) { setParameter(d->device, XsetwacomProperty::Rotate.key(), rotation.key()); return true; } // do not set this value as it is not a real screen rotation // probably some auto-mode. return false; } bool XsetwacomAdaptor::setParameter(const QString& device, const QString& param, const QString& value) const { QString cmd; if (value.isEmpty()) { cmd = QString::fromLatin1( "xsetwacom set \"%1\" %2" ).arg( device ).arg( param ); } else { cmd = QString::fromLatin1( "xsetwacom set \"%1\" %2 \"%3\"" ).arg( device ).arg( param ).arg( value ); } QProcess setConf; setConf.start( cmd ); if( !setConf.waitForStarted() || !setConf.waitForFinished()) { return false; } QByteArray errorOutput = setConf.readAll(); if( !errorOutput.isEmpty() ) { qCDebug(KDED) << cmd << " : " << errorOutput; return false; } return true; }