diff --git a/.gitignore b/.gitignore index 2c9ea2b..96fffaf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -.kdev4 build -ScreenRotator.kdev4 +aur/src/** +aur/pkg/** +aur/screenrotator-modified-git/** +aur/*.tar.zst diff --git a/README.md b/README.md index 18ed198..ea180ca 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,15 @@ Similar to the current solution implemented in Gnome, but works on all other des - Qt5 (with modules x11extras, sensors) - xrandr - XInput (Xi) - + On ubuntu, run the following command to install dependencies: ``` -sudo apt install -y git cmake build-essential qtbase5-dev libxrandr-dev libxi-dev libqt5x11extras5-dev libqt5sensors5-dev +sudo apt install -y git cmake build-essential qtbase5-dev libxrandr-dev libxi-dev libqt5x11extras5-dev libqt5sensors5-dev ``` ## Building ``` -git clone https://github.com/GuLinux/ScreenRotator +git clone https://github.com/pakro/ScreenRotator mkdir ScreenRotator/build cd ScreenRotator/build cmake .. @@ -31,5 +31,4 @@ sudo make install ## Links -Main icon: https://www.iconfinder.com/icons/326583/orientation_rotation_screen_icon#size=256 - +Main icon from https://www.onlinewebfonts.com/icon/310563 diff --git a/aur/.gitignore b/aur/.gitignore deleted file mode 100644 index 699fc4e..0000000 --- a/aur/.gitignore +++ /dev/null @@ -1 +0,0 @@ -screenrotator-git diff --git a/aur/PKGBUILD b/aur/PKGBUILD index 0e8a8a9..5181175 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -1,12 +1,10 @@ -# Maintainer: Marco Gulino - -pkgname=screenrotator-git -pkgver=r23.1a78a4b +pkgname=screenrotator-modified-git +pkgver=r45.767fa46 pkgrel=1 epoch=1 pkgdesc='Automatic screen rotation daemon for X11' arch=('i686' 'x86_64') -url='https://github.com/GuLinux/ScreenRotator' +url='https://github.com/pakro/ScreenRotator' license=('GPL3') depends=('qt5-base' 'qt5-x11extras' 'libxi' 'libxrandr' 'qt5-sensors') makedepends=('git' 'cmake' 'qt5-tools') @@ -14,24 +12,24 @@ source=("${pkgname}::git+${url}") sha256sums=('SKIP') pkgver() { - cd "$pkgname" - printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" + cd "$pkgname" + printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" } prepare() { - cd "$srcdir/$pkgname" - install -d build + cd "$srcdir/$pkgname" + install -d build } build() { - cd "$srcdir/$pkgname/build" - cmake ..\ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=Release - make + cd "$srcdir/$pkgname/build" + cmake ..\ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_BUILD_TYPE=Release + make } package() { - cd "$srcdir/$pkgname/build" - make DESTDIR="$pkgdir" install + cd "$srcdir/$pkgname/build" + make DESTDIR="$pkgdir" install } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8835a5b..7333c65 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,8 @@ set(screenrotator_SRCS displaymanager.cpp orientationsensor.cpp trayicon.cpp rotateinput.cpp) add_executable(screenrotator main.cpp ${screenrotator_SRCS}) -configure_file(screenrotator-autostart.desktop.in screenrotator-autostart.desktop) target_link_libraries(screenrotator Qt5::Gui Qt5::X11Extras Qt5::Sensors Qt5::Widgets Qt5::DBus Xrandr Xi X11) install(TARGETS screenrotator RUNTIME DESTINATION bin) install(FILES screenrotator.desktop DESTINATION share/applications) file(GLOB ICON_DIRECTORIES resources/*x*) install(DIRECTORY ${ICON_DIRECTORIES} resources/scalable DESTINATION share/icons/hicolor/) -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/screenrotator-autostart.desktop DESTINATION /etc/xdg/autostart/) diff --git a/src/displaymanager.cpp b/src/displaymanager.cpp index f5e6519..d428362 100644 --- a/src/displaymanager.cpp +++ b/src/displaymanager.cpp @@ -30,7 +30,7 @@ struct DisplayManagerX11Mediator { XRRScreenConfiguration *screenConfiguration; Rotation rotation; SizeID configurationId; - + DisplayManagerX11Mediator(); ~DisplayManagerX11Mediator(); bool setRotation(Rotation rotation); @@ -75,7 +75,7 @@ Orientation DisplayManager::Private::to_orientation(Rotation rotation) if(orientation2rotation[key] == rotation) return key; // TODO: fallback value? - return Orientation::LeftUp; + return Orientation::TopUp; } @@ -84,7 +84,6 @@ DisplayManager::DisplayManager(QObject* parent) : QObject{parent}, d{new Private { DisplayManagerX11Mediator mediator; d->currentOrientation = d->to_orientation(mediator.rotation); - qDebug() << "Current orientation: " << d->currentOrientation << ", rotation: " << mediator.rotation; } DisplayManager::~DisplayManager() @@ -95,8 +94,7 @@ void DisplayManager::setOrientation(Orientation orientation) { DisplayManagerX11Mediator mediator; auto rotation = orientation2rotation[orientation]; - if(mediator.rotation == rotation) - return; mediator.setRotation(rotation); d->currentOrientation = orientation; + qDebug() << "Current orientation: " << d->currentOrientation << ", rotation: " << mediator.rotation; } diff --git a/src/main.cpp b/src/main.cpp index 8447d9e..dfb53f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,9 @@ int main(int argc, char *argv[]) TrayIcon tray; OrientationSensor sensor; RotateInput rotateInput; - QObject::connect(&sensor, &OrientationSensor::reading, &displayManager, &DisplayManager::setOrientation); - QObject::connect(&sensor, &OrientationSensor::reading, &rotateInput, &RotateInput::rotate); + QObject::connect(&sensor, &OrientationSensor::reading, &tray, &TrayIcon::orientationUpdated); + QObject::connect(&tray, &TrayIcon::emitRotation, &displayManager, &DisplayManager::setOrientation); + QObject::connect(&tray, &TrayIcon::emitRotation, &rotateInput, &RotateInput::rotate); + return app.exec(); } diff --git a/src/resources/1024x1024/apps/screenrotator.png b/src/resources/1024x1024/apps/screenrotator.png new file mode 100644 index 0000000..9d4b3ac Binary files /dev/null and b/src/resources/1024x1024/apps/screenrotator.png differ diff --git a/src/resources/128x128/apps/screenrotator.png b/src/resources/128x128/apps/screenrotator.png index 370260b..873d4ac 100644 Binary files a/src/resources/128x128/apps/screenrotator.png and b/src/resources/128x128/apps/screenrotator.png differ diff --git a/src/resources/16x16/apps/screenrotator.png b/src/resources/16x16/apps/screenrotator.png index 555c76d..bbfb1bd 100644 Binary files a/src/resources/16x16/apps/screenrotator.png and b/src/resources/16x16/apps/screenrotator.png differ diff --git a/src/resources/192x192/apps/screenrotator.png b/src/resources/192x192/apps/screenrotator.png index ae28bad..de5eff1 100644 Binary files a/src/resources/192x192/apps/screenrotator.png and b/src/resources/192x192/apps/screenrotator.png differ diff --git a/src/resources/20x20/apps/screenrotator.png b/src/resources/20x20/apps/screenrotator.png index 22959cf..7f14a53 100644 Binary files a/src/resources/20x20/apps/screenrotator.png and b/src/resources/20x20/apps/screenrotator.png differ diff --git a/src/resources/22x22/apps/screenrotator.png b/src/resources/22x22/apps/screenrotator.png index 4f3000e..d5b8c9b 100644 Binary files a/src/resources/22x22/apps/screenrotator.png and b/src/resources/22x22/apps/screenrotator.png differ diff --git a/src/resources/24x24/apps/screenrotator.png b/src/resources/24x24/apps/screenrotator.png index 898233a..49327eb 100644 Binary files a/src/resources/24x24/apps/screenrotator.png and b/src/resources/24x24/apps/screenrotator.png differ diff --git a/src/resources/256x256/apps/screenrotator.png b/src/resources/256x256/apps/screenrotator.png index e972403..8c6ad30 100644 Binary files a/src/resources/256x256/apps/screenrotator.png and b/src/resources/256x256/apps/screenrotator.png differ diff --git a/src/resources/28x28/apps/screenrotator.png b/src/resources/28x28/apps/screenrotator.png new file mode 100644 index 0000000..84c0f39 Binary files /dev/null and b/src/resources/28x28/apps/screenrotator.png differ diff --git a/src/resources/32x32/apps/screenrotator.png b/src/resources/32x32/apps/screenrotator.png index ff2ca23..74fc18f 100644 Binary files a/src/resources/32x32/apps/screenrotator.png and b/src/resources/32x32/apps/screenrotator.png differ diff --git a/src/resources/36x36/apps/screenrotator.png b/src/resources/36x36/apps/screenrotator.png index dcfe1b7..e5015cf 100644 Binary files a/src/resources/36x36/apps/screenrotator.png and b/src/resources/36x36/apps/screenrotator.png differ diff --git a/src/resources/384x384/apps/screenrotator.png b/src/resources/384x384/apps/screenrotator.png index 166989f..76f0eb1 100644 Binary files a/src/resources/384x384/apps/screenrotator.png and b/src/resources/384x384/apps/screenrotator.png differ diff --git a/src/resources/40x40/apps/screenrotator.png b/src/resources/40x40/apps/screenrotator.png index 05c45d5..04c7a8e 100644 Binary files a/src/resources/40x40/apps/screenrotator.png and b/src/resources/40x40/apps/screenrotator.png differ diff --git a/src/resources/48x48/apps/screenrotator.png b/src/resources/48x48/apps/screenrotator.png index b270c1c..60716cb 100644 Binary files a/src/resources/48x48/apps/screenrotator.png and b/src/resources/48x48/apps/screenrotator.png differ diff --git a/src/resources/512x512/apps/screenrotator.png b/src/resources/512x512/apps/screenrotator.png index e731098..71538e5 100644 Binary files a/src/resources/512x512/apps/screenrotator.png and b/src/resources/512x512/apps/screenrotator.png differ diff --git a/src/resources/64x64/apps/screenrotator.png b/src/resources/64x64/apps/screenrotator.png index b2b1f85..919aa34 100644 Binary files a/src/resources/64x64/apps/screenrotator.png and b/src/resources/64x64/apps/screenrotator.png differ diff --git a/src/resources/72x72/apps/screenrotator.png b/src/resources/72x72/apps/screenrotator.png index 07f599c..49e49db 100644 Binary files a/src/resources/72x72/apps/screenrotator.png and b/src/resources/72x72/apps/screenrotator.png differ diff --git a/src/resources/80x80/apps/screenrotator.png b/src/resources/80x80/apps/screenrotator.png index f2877a9..6fdaa7c 100644 Binary files a/src/resources/80x80/apps/screenrotator.png and b/src/resources/80x80/apps/screenrotator.png differ diff --git a/src/resources/8x8/apps/screenrotator.png b/src/resources/8x8/apps/screenrotator.png index 23b79fd..61b10da 100644 Binary files a/src/resources/8x8/apps/screenrotator.png and b/src/resources/8x8/apps/screenrotator.png differ diff --git a/src/resources/96x96/apps/screenrotator.png b/src/resources/96x96/apps/screenrotator.png index 25a0dde..854c1fe 100644 Binary files a/src/resources/96x96/apps/screenrotator.png and b/src/resources/96x96/apps/screenrotator.png differ diff --git a/src/resources/create_icons b/src/resources/create_icons index 8a24e2d..0d0bae3 100755 --- a/src/resources/create_icons +++ b/src/resources/create_icons @@ -3,5 +3,5 @@ for size in $( ls /usr/share/icons/hicolor | grep x | grep -v index ); do size_x="${size%%x*}" size_y="${size##*x}" mkdir -p "$size"/apps - inkscape -z -e "$size/apps/screenrotator.png" -w $size_x -h "$size_y" scalable/apps/screenrotator.svg + inkscape --export-filename="$size/apps/screenrotator.png" -w $size_x -h "$size_y" scalable/apps/screenrotator.svg done diff --git a/src/resources/scalable/apps/screenrotator.svg b/src/resources/scalable/apps/screenrotator.svg index c65a318..fd1feb8 100644 --- a/src/resources/scalable/apps/screenrotator.svg +++ b/src/resources/scalable/apps/screenrotator.svg @@ -1 +1,49 @@ - \ No newline at end of file + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon image/svg+xml + + diff --git a/src/rotateinput.cpp b/src/rotateinput.cpp index 926a969..38ef44a 100644 --- a/src/rotateinput.cpp +++ b/src/rotateinput.cpp @@ -33,7 +33,7 @@ struct InputProperty { Atom type; int format; QString name; - + bool isRotationMatrix() const; void setRotationMatrix(const vector &matrix); }; @@ -56,7 +56,7 @@ InputDevice::InputDevice(XIDeviceInfo* info, Display *display) : display{display id = info->deviceid; for(int j=0; jnum_classes; j++) { if(info->classes[j]->type == XITouchClass) { - qDebug() << "Device" << info->name << "seems to be a touchscreen device"; + qDebug() << "Device" << info->name << "has touchscreen functionality"; isTouchScreen = true; } } @@ -90,7 +90,7 @@ InputProperty::InputProperty(int deviceId, Display* display, Atom atom) : device if(XIGetProperty(display, deviceId, atom, 0, 0, False, AnyPropertyType, &property_type, &property_format, &items_count, &bytes_after, &data) == Success) { type = property_type; format = property_format; - qDebug() << "Property name=" << name << ", atom=" << atom << ", format=" << format << ", type=" << type; + //qDebug() << "Property name=" << name << ", atom=" << atom << ", format=" << format << ", type=" << type; XFree(data); } else { qDebug() << "Unable to get data for property " << name; @@ -128,27 +128,34 @@ class RotateInput::Private { RotateInput::RotateInput(QObject* parent) : QObject{parent}, d{new Private} { d->display = QX11Info::display(); + this->scanForTouchDevices(); + //for(auto device: d->devices) { + // for(auto property: device.properties()) { + // qDebug() << "Device" << device.name << ", property:" << property.name << ", atom=" << property.atom << ", type: " << property.type; + // } + //} +} +RotateInput::~RotateInput() +{ +} + +void RotateInput::scanForTouchDevices() +{ + d->devices.clear(); int devices; XIDeviceInfo *deviceInfo = XIQueryDevice(d->display, XIAllDevices, &devices); for(int i=0; idisplay}; if(device.hasRotationMatrix) - d->devices.push_back(device); + if(device.name.startsWith("Wacom Pen") || device.name.startsWith("Goodix Capacitive")) + d->devices.push_back(device); } XIFreeDeviceInfo(deviceInfo); - - for(auto device: d->devices) { - for(auto property: device.properties()) { - qDebug() << "Device" << device.name << ", property:" << property.name << ", atom=" << property.atom << ", type: " << property.type; - } - } -} -RotateInput::~RotateInput() -{ } void RotateInput::rotate(Orientation orientation) { + this->scanForTouchDevices(); #ifdef USE_XINPUT static QHash orientation_matrix_map { {TopUp, {"1", "0", "0", "0", "1", "0", "0", "0", "1"}}, @@ -168,11 +175,10 @@ void RotateInput::rotate(Orientation orientation) {RightUp, {0, 1, 0, -1, 0, 1, 0, 0, 1}}, }; auto orientation_matrix = orientation_matrix_map[orientation]; - qDebug() << "Setting rotation matrix: " << orientation_matrix; for(auto device: d->devices) { for(auto property: device.properties()) { if(property.isRotationMatrix()) { - qDebug() << "Changing orientation matrix for device " << device.name << ", property " << property.name; + qDebug() << "Changing orientation matrix for device" << device.name << "using matrix" << orientation_matrix; property.setRotationMatrix(orientation_matrix); } } diff --git a/src/rotateinput.h b/src/rotateinput.h index 10e1066..17b7638 100644 --- a/src/rotateinput.h +++ b/src/rotateinput.h @@ -34,6 +34,7 @@ public slots: private: class Private; std::unique_ptr d; + void scanForTouchDevices(); }; #endif // ROTATEINPUT_H diff --git a/src/screenrotator-autostart.desktop.in b/src/screenrotator-autostart.desktop.in deleted file mode 100644 index ed906b2..0000000 --- a/src/screenrotator-autostart.desktop.in +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Type=Application -Name=Screen Rotator -Exec=@CMAKE_INSTALL_PREFIX@/bin/screenrotator -NoDisplay=true -X-KDE-StartupNotify=false diff --git a/src/trayicon.cpp b/src/trayicon.cpp index 00071a7..f6270cb 100644 --- a/src/trayicon.cpp +++ b/src/trayicon.cpp @@ -21,25 +21,88 @@ #include #include #include +#include +#include using namespace std; class TrayIcon::Private { public: QSystemTrayIcon tray; unique_ptr menu; + Orientation lastOrientation; + bool hasLastOrientation; + bool autoRotating; }; +#define APP_NAME tr("Screen Rotator") +#define APP_ICON QIcon::fromTheme("screenrotator") + TrayIcon::TrayIcon(QObject* parent) : QObject{parent}, d{new Private} { - d->tray.setIcon(QIcon::fromTheme("screenrotator")); + d->tray.setIcon(APP_ICON); d->menu.reset(new QMenu()); - d->tray.setToolTip(tr("Screen Rotator")); + d->tray.setToolTip(APP_NAME); + + connect(&d->tray, &QSystemTrayIcon::activated, this, &TrayIcon::activated); + connect(&d->tray, &QSystemTrayIcon::messageClicked, this, &TrayIcon::messageClicked); d->tray.setContextMenu(d->menu.get()); + d->menu->addAction(tr("Rotate"), this, &TrayIcon::emitRotationIfHas); + d->menu->addAction(tr("Toggle auto-rotation"), this, &TrayIcon::toggleAutoRotating); d->menu->addAction(tr("Quit"), qApp, &QApplication::quit); + d->hasLastOrientation = false; + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + d->autoRotating = !env.contains("DEFAULT_AUTO_ROTATION_OFF"); QTimer::singleShot(100, &d->tray, &QSystemTrayIcon::show); } TrayIcon::~TrayIcon() { } + +void TrayIcon::setAutoRotating(bool autoRotating) +{ + d->autoRotating = autoRotating; + if (d->autoRotating) { + d->tray.showMessage(APP_NAME, tr("Auto-rotation enabled"), APP_ICON, 3000); + } else { + d->tray.showMessage(APP_NAME, tr("Auto-rotation disabled"), APP_ICON, 3000); + } +} + +void TrayIcon::toggleAutoRotating() +{ + this->setAutoRotating(!d->autoRotating); +} + +void TrayIcon::orientationUpdated(Orientation orientation) +{ + d->lastOrientation = orientation; + d->hasLastOrientation = true; + if (d->autoRotating) { + this->emitRotationIfHas(); + } else { + d->tray.showMessage(APP_NAME, tr("Orientaion change detected, click tray icon to rotate"), APP_ICON, 3000); + qApp->processEvents(); + } +} + +void TrayIcon::activated(QSystemTrayIcon::ActivationReason reason) +{ + this->emitRotationIfHas(); +} + +void TrayIcon::messageClicked() +{ + this->emitRotationIfHas(); +} + +void TrayIcon::emitRotationIfHas() +{ + if (d->hasLastOrientation) { + emit this->emitRotation(d->lastOrientation); + } else { + d->tray.showMessage(APP_NAME, tr("No orientaion change detected, try rotate the devise again"), APP_ICON, 5000); + } +} diff --git a/src/trayicon.h b/src/trayicon.h index 92e7bb0..746f319 100644 --- a/src/trayicon.h +++ b/src/trayicon.h @@ -20,6 +20,8 @@ #define TRAYICON_H #include +#include +#include "orientation.h" #include class TrayIcon : public QObject { @@ -27,9 +29,18 @@ class TrayIcon : public QObject public: TrayIcon(QObject* parent = nullptr); ~TrayIcon(); +public slots: + void setAutoRotating(bool autoRotating); + void toggleAutoRotating(); + void orientationUpdated(Orientation orientation); + void activated(QSystemTrayIcon::ActivationReason reason); + void messageClicked(); private: class Private; std::unique_ptr d; + void emitRotationIfHas(); +signals: + void emitRotation(Orientation orientation); }; #endif // TRAYICON_H