diff --git a/effects/trackmouse/trackmouse.cpp b/effects/trackmouse/trackmouse.cpp index c9fa60f3e..f92342104 100644 --- a/effects/trackmouse/trackmouse.cpp +++ b/effects/trackmouse/trackmouse.cpp @@ -1,286 +1,313 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak Copyright (C) 2010 Jorge Mata +Copyright (C) 2018 Vlad Zagorodniy 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 "trackmouse.h" // KConfigSkeleton #include "trackmouseconfig.h" #include #include #include #include #include #include #include #include #include #include namespace KWin { TrackMouseEffect::TrackMouseEffect() - : m_active(false) - , m_angle(0) + : m_angle(0) { initConfig(); m_texture[0] = m_texture[1] = 0; #ifdef KWIN_HAVE_XRENDER_COMPOSITING m_picture[0] = m_picture[1] = 0; if ( effects->compositingType() == XRenderCompositing) m_angleBase = 1.57079632679489661923; // Pi/2 #endif if ( effects->isOpenGLCompositing() || effects->compositingType() == QPainterCompositing) m_angleBase = 90.0; m_mousePolling = false; m_action = new QAction(this); m_action->setObjectName(QStringLiteral("TrackMouse")); m_action->setText(i18n("Track mouse")); KGlobalAccel::self()->setDefaultShortcut(m_action, QList()); KGlobalAccel::self()->setShortcut(m_action, QList()); effects->registerGlobalShortcut(QKeySequence(), m_action); connect(m_action, SIGNAL(triggered(bool)), this, SLOT(toggle())); connect(effects, SIGNAL(mouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers)), SLOT(slotMouseChanged(QPoint,QPoint,Qt::MouseButtons,Qt::MouseButtons,Qt::KeyboardModifiers,Qt::KeyboardModifiers))); reconfigure(ReconfigureAll); } TrackMouseEffect::~TrackMouseEffect() { if (m_mousePolling) effects->stopMousePolling(); for (int i = 0; i < 2; ++i) { delete m_texture[i]; m_texture[i] = 0; #ifdef KWIN_HAVE_XRENDER_COMPOSITING delete m_picture[i]; m_picture[i] = 0; #endif } } void TrackMouseEffect::reconfigure(ReconfigureFlags) { m_modifiers = 0; TrackMouseConfig::self()->read(); if (TrackMouseConfig::shift()) m_modifiers |= Qt::ShiftModifier; if (TrackMouseConfig::alt()) m_modifiers |= Qt::AltModifier; if (TrackMouseConfig::control()) m_modifiers |= Qt::ControlModifier; if (TrackMouseConfig::meta()) m_modifiers |= Qt::MetaModifier; if (m_modifiers) { if (!m_mousePolling) effects->startMousePolling(); m_mousePolling = true; } else if (m_mousePolling) { effects->stopMousePolling(); m_mousePolling = false; } } void TrackMouseEffect::prePaintScreen(ScreenPrePaintData& data, int time) { - if (m_active) { - QTime t = QTime::currentTime(); - m_angle = ((t.second() % 4) * m_angleBase) + (t.msec() / 1000.0 * m_angleBase); - m_lastRect[0].moveCenter(cursorPos()); - m_lastRect[1].moveCenter(cursorPos()); - data.paint |= m_lastRect[0].adjusted(-1,-1,1,1); - } + QTime t = QTime::currentTime(); + m_angle = ((t.second() % 4) * m_angleBase) + (t.msec() / 1000.0 * m_angleBase); + m_lastRect[0].moveCenter(cursorPos()); + m_lastRect[1].moveCenter(cursorPos()); + data.paint |= m_lastRect[0].adjusted(-1,-1,1,1); + effects->prePaintScreen(data, time); } void TrackMouseEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) { effects->paintScreen(mask, region, data); // paint normal screen - if (!m_active) - return; if ( effects->isOpenGLCompositing() && m_texture[0] && m_texture[1]) { ShaderBinder binder(ShaderTrait::MapTexture); GLShader *shader(binder.shader()); if (!shader) { return; } glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); QMatrix4x4 matrix(data.projectionMatrix()); const QPointF p = m_lastRect[0].topLeft() + QPoint(m_lastRect[0].width()/2.0, m_lastRect[0].height()/2.0); const float x = p.x()*data.xScale() + data.xTranslation(); const float y = p.y()*data.yScale() + data.yTranslation(); for (int i = 0; i < 2; ++i) { matrix.translate(x, y, 0.0); matrix.rotate(i ? -2*m_angle : m_angle, 0, 0, 1.0); matrix.translate(-x, -y, 0.0); QMatrix4x4 mvp(matrix); mvp.translate(m_lastRect[i].x(), m_lastRect[i].y()); shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); m_texture[i]->bind(); m_texture[i]->render(region, m_lastRect[i]); m_texture[i]->unbind(); } glDisable(GL_BLEND); } #ifdef KWIN_HAVE_XRENDER_COMPOSITING if ( effects->compositingType() == XRenderCompositing && m_picture[0] && m_picture[1]) { float sine = sin(m_angle); const float cosine = cos(m_angle); for (int i = 0; i < 2; ++i) { if (i) sine = -sine; const float dx = m_size[i].width()/2.0; const float dy = m_size[i].height()/2.0; const xcb_render_picture_t picture = *m_picture[i]; #define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536)) xcb_render_transform_t xform = { DOUBLE_TO_FIXED( cosine ), DOUBLE_TO_FIXED( -sine ), DOUBLE_TO_FIXED( dx - cosine*dx + sine*dy ), DOUBLE_TO_FIXED( sine ), DOUBLE_TO_FIXED( cosine ), DOUBLE_TO_FIXED( dy - sine*dx - cosine*dy ), DOUBLE_TO_FIXED( 0.0 ), DOUBLE_TO_FIXED( 0.0 ), DOUBLE_TO_FIXED( 1.0 ) }; #undef DOUBLE_TO_FIXED xcb_render_set_picture_transform(xcbConnection(), picture, xform); xcb_render_set_picture_filter(xcbConnection(), picture, 8, "bilinear", 0, NULL); const QRect &rect = m_lastRect[i]; xcb_render_composite(xcbConnection(), XCB_RENDER_PICT_OP_OVER, picture, XCB_RENDER_PICTURE_NONE, effects->xrenderBufferPicture(), 0, 0, 0, 0, qRound((rect.x()+rect.width()/2.0)*data.xScale() - rect.width()/2.0 + data.xTranslation()), qRound((rect.y()+rect.height()/2.0)*data.yScale() - rect.height()/2.0 + data.yTranslation()), rect.width(), rect.height()); } } #endif if (effects->compositingType() == QPainterCompositing && !m_image[0].isNull() && !m_image[1].isNull()) { QPainter *painter = effects->scenePainter(); const QPointF p = m_lastRect[0].topLeft() + QPoint(m_lastRect[0].width()/2.0, m_lastRect[0].height()/2.0); for (int i = 0; i < 2; ++i) { painter->save(); painter->translate(p.x(), p.y()); painter->rotate(i ? -2*m_angle : m_angle); painter->translate(-p.x(), -p.y()); painter->drawImage(m_lastRect[i], m_image[i]); painter->restore(); } } } void TrackMouseEffect::postPaintScreen() { - if (m_active) { - effects->addRepaint(m_lastRect[0].adjusted(-1,-1,1,1)); - } + effects->addRepaint(m_lastRect[0].adjusted(-1,-1,1,1)); effects->postPaintScreen(); } bool TrackMouseEffect::init() { effects->makeOpenGLContextCurrent(); #ifdef KWIN_HAVE_XRENDER_COMPOSITING if (!(m_texture[0] || m_picture[0] || !m_image[0].isNull())) { loadTexture(); if (!(m_texture[0] || m_picture[0] || !m_image[0].isNull())) return false; } #else if (!m_texture[0] || m_image[0].isNull()) { loadTexture(); if (!m_texture[0] || m_image[0].isNull()) return false; } #endif m_lastRect[0].moveCenter(cursorPos()); m_lastRect[1].moveCenter(cursorPos()); - m_active = true; m_angle = 0; return true; } void TrackMouseEffect::toggle() { - if (m_mousePolling) - return; + switch (m_state) { + case State::ActivatedByModifiers: + m_state = State::ActivatedByShortcut; + break; - if (m_active) { - m_active = false; - } else if (!init()) { - return; + case State::ActivatedByShortcut: + m_state = State::Inactive; + break; + + case State::Inactive: + if (!init()) { + return; + } + m_state = State::ActivatedByShortcut; + break; + + default: + Q_UNREACHABLE(); + break; } - effects->addRepaint(m_lastRect[0].adjusted(-1,-1,1,1)); + + effects->addRepaint(m_lastRect[0].adjusted(-1, -1, 1, 1)); } void TrackMouseEffect::slotMouseChanged(const QPoint&, const QPoint&, Qt::MouseButtons, Qt::MouseButtons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers) { - if (!m_mousePolling) // we didn't ask for it but maybe someone else did... + if (!m_mousePolling) { // we didn't ask for it but maybe someone else did... return; - if (m_modifiers && modifiers == m_modifiers) { - if (!m_active && !init()) { + } + + switch (m_state) { + case State::ActivatedByModifiers: + if (modifiers == m_modifiers) { return; } - effects->addRepaint(m_lastRect[0].adjusted(-1,-1,1,1)); - } else if (m_active) { - m_active = false; - effects->addRepaint(m_lastRect[0].adjusted(-1,-1,1,1)); + m_state = State::Inactive; + break; + + case State::ActivatedByShortcut: + return; + + case State::Inactive: + if (modifiers != m_modifiers) { + return; + } + if (!init()) { + return; + } + m_state = State::ActivatedByModifiers; + break; + + default: + Q_UNREACHABLE(); + break; } + + effects->addRepaint(m_lastRect[0].adjusted(-1, -1, 1, 1)); } void TrackMouseEffect::loadTexture() { QString f[2] = {QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("tm_outer.png")), QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("tm_inner.png"))}; if (f[0].isEmpty() || f[1].isEmpty()) return; for (int i = 0; i < 2; ++i) { if ( effects->isOpenGLCompositing()) { QImage img(f[i]); m_texture[i] = new GLTexture(img); m_lastRect[i].setSize(img.size()); } #ifdef KWIN_HAVE_XRENDER_COMPOSITING if ( effects->compositingType() == XRenderCompositing) { QImage pixmap(f[i]); m_picture[i] = new XRenderPicture(pixmap); m_size[i] = pixmap.size(); m_lastRect[i].setSize(pixmap.size()); } #endif if (effects->compositingType() == QPainterCompositing) { m_image[i] = QImage(f[i]); m_lastRect[i].setSize(m_image[i].size()); } } } bool TrackMouseEffect::isActive() const { - return m_active; + return m_state != State::Inactive; } } // namespace diff --git a/effects/trackmouse/trackmouse.h b/effects/trackmouse/trackmouse.h index fabf360b7..f2eb602ca 100644 --- a/effects/trackmouse/trackmouse.h +++ b/effects/trackmouse/trackmouse.h @@ -1,79 +1,87 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak Copyright (C) 2010 Jorge Mata +Copyright (C) 2018 Vlad Zagorodniy 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 KWIN_TRACKMOUSE_H #define KWIN_TRACKMOUSE_H #include class QAction; namespace KWin { class GLTexture; class TrackMouseEffect : public Effect { Q_OBJECT Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers) Q_PROPERTY(bool mousePolling READ isMousePolling) public: TrackMouseEffect(); virtual ~TrackMouseEffect(); virtual void prePaintScreen(ScreenPrePaintData& data, int time); virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data); virtual void postPaintScreen(); virtual void reconfigure(ReconfigureFlags); virtual bool isActive() const; // for properties Qt::KeyboardModifiers modifiers() const { return m_modifiers; } bool isMousePolling() const { return m_mousePolling; } private Q_SLOTS: void toggle(); void slotMouseChanged(const QPoint& pos, const QPoint& old, Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers); private: bool init(); void loadTexture(); QRect m_lastRect[2]; - bool m_active, m_mousePolling; + bool m_mousePolling; float m_angle; float m_angleBase; GLTexture* m_texture[2]; #ifdef KWIN_HAVE_XRENDER_COMPOSITING QSize m_size[2]; XRenderPicture *m_picture[2]; #endif QAction* m_action; QImage m_image[2]; Qt::KeyboardModifiers m_modifiers; + + enum class State { + ActivatedByModifiers, + ActivatedByShortcut, + Inactive + }; + State m_state = State::Inactive; }; } // namespace #endif diff --git a/effects/trackmouse/trackmouse_config.cpp b/effects/trackmouse/trackmouse_config.cpp index 51da99f47..94d321193 100644 --- a/effects/trackmouse/trackmouse_config.cpp +++ b/effects/trackmouse/trackmouse_config.cpp @@ -1,128 +1,124 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2007 Rivo Laks Copyright (C) 2010 Jorge Mata 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 #include #include #include #include #include #include #include #include #include #include "trackmouse_config.h" // KConfigSkeleton #include "trackmouseconfig.h" K_PLUGIN_FACTORY_WITH_JSON(TrackMouseEffectConfigFactory, "trackmouse_config.json", registerPlugin();) namespace KWin { +static const QString s_toggleTrackMouseActionName = QStringLiteral("TrackMouse"); + TrackMouseEffectConfigForm::TrackMouseEffectConfigForm(QWidget* parent) : QWidget(parent) { setupUi(this); } TrackMouseEffectConfig::TrackMouseEffectConfig(QWidget* parent, const QVariantList& args) : KCModule(KAboutData::pluginData(QStringLiteral("trackmouse")), parent, args) { TrackMouseConfig::instance(KWIN_CONFIG); m_ui = new TrackMouseEffectConfigForm(this); QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(m_ui); addConfig(TrackMouseConfig::self(), m_ui); m_actionCollection = new KActionCollection(this, QStringLiteral("kwin")); m_actionCollection->setComponentDisplayName(i18n("KWin")); m_actionCollection->setConfigGroup(QStringLiteral("TrackMouse")); m_actionCollection->setConfigGlobal(true); - QAction *a = m_actionCollection->addAction(QStringLiteral("TrackMouse")); + QAction *a = m_actionCollection->addAction(s_toggleTrackMouseActionName); a->setText(i18n("Track mouse")); a->setProperty("isConfigurationAction", true); KGlobalAccel::self()->setDefaultShortcut(a, QList()); KGlobalAccel::self()->setShortcut(a, QList()); connect(m_ui->shortcut, SIGNAL(keySequenceChanged(QKeySequence)), SLOT(shortcutChanged(QKeySequence))); load(); } TrackMouseEffectConfig::~TrackMouseEffectConfig() { } -void TrackMouseEffectConfig::checkModifiers() -{ - const bool modifiers = m_ui->kcfg_Shift->isChecked() || m_ui->kcfg_Alt->isChecked() || - m_ui->kcfg_Control->isChecked() || m_ui->kcfg_Meta->isChecked(); - m_ui->modifierRadio->setChecked(modifiers); - m_ui->shortcutRadio->setChecked(!modifiers); -} - void TrackMouseEffectConfig::load() { KCModule::load(); - checkModifiers(); - emit changed(false); + if (QAction *a = m_actionCollection->action(s_toggleTrackMouseActionName)) { + auto shortcuts = KGlobalAccel::self()->shortcut(a); + if (!shortcuts.isEmpty()) { + m_ui->shortcut->setKeySequence(shortcuts.first()); + } + } } void TrackMouseEffectConfig::save() { KCModule::save(); m_actionCollection->writeSettings(); OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QDBusConnection::sessionBus()); interface.reconfigureEffect(QStringLiteral("trackmouse")); } void TrackMouseEffectConfig::defaults() { KCModule::defaults(); m_ui->shortcut->clearKeySequence(); - checkModifiers(); } void TrackMouseEffectConfig::shortcutChanged(const QKeySequence &seq) { if (QAction *a = m_actionCollection->action(QStringLiteral("TrackMouse"))) { KGlobalAccel::self()->setShortcut(a, QList() << seq, KGlobalAccel::NoAutoloading); } -// m_actionCollection->writeSettings(); emit changed(true); } } // namespace #include "trackmouse_config.moc" diff --git a/effects/trackmouse/trackmouse_config.h b/effects/trackmouse/trackmouse_config.h index 211990d2b..56f9a60db 100644 --- a/effects/trackmouse/trackmouse_config.h +++ b/effects/trackmouse/trackmouse_config.h @@ -1,62 +1,61 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2007 Rivo Laks Copyright (C) 2010 Jorge Mata 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 KWIN_TRACKMOUSE_CONFIG_H #define KWIN_TRACKMOUSE_CONFIG_H #include #include "ui_trackmouse_config.h" class KActionCollection; namespace KWin { class TrackMouseEffectConfigForm : public QWidget, public Ui::TrackMouseEffectConfigForm { Q_OBJECT public: explicit TrackMouseEffectConfigForm(QWidget* parent); }; class TrackMouseEffectConfig : public KCModule { Q_OBJECT public: explicit TrackMouseEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); ~TrackMouseEffectConfig(); public Q_SLOTS: virtual void save(); virtual void load(); virtual void defaults(); private Q_SLOTS: void shortcutChanged(const QKeySequence &seq); private: - void checkModifiers(); TrackMouseEffectConfigForm* m_ui; KActionCollection* m_actionCollection; }; } // namespace #endif diff --git a/effects/trackmouse/trackmouse_config.ui b/effects/trackmouse/trackmouse_config.ui index 1c87ffa32..dff595d26 100644 --- a/effects/trackmouse/trackmouse_config.ui +++ b/effects/trackmouse/trackmouse_config.ui @@ -1,134 +1,104 @@ KWin::TrackMouseEffectConfigForm 0 0 - 327 - 104 + 345 + 112 QFormLayout::FieldsStayAtSizeHint - + + + + 75 + true + + - Trigger on + Trigger effect with: - + - Modifiers + Keyboard shortcut: - - - false + + + + + + Modifier keys: + + + + - + + 0 + + + 0 + + + 0 + + 0 Alt Ctrl Shift Meta - - - - Shortcut - - - - - - - false - - - KKeySequenceWidget QWidget
kkeysequencewidget.h
- - KTitleWidget - QWidget -
ktitlewidget.h
-
- - - shortcutRadio - toggled(bool) - shortcut - setEnabled(bool) - - - 107 - 75 - - - 183 - 75 - - - - - modifierRadio - toggled(bool) - widget - setEnabled(bool) - - - 99 - 44 - - - 309 - 52 - - - - +