diff --git a/Changelog b/Changelog index 9f6054727a112340d15d9c850c4a1b1c1d148016..806df1e7d32d9a2f6e2db127a978fa2b5135fa84 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,9 @@ KAlarm Change Log -=== Version 2.11.1 --- 1 September 2015 === +=== Version 2.11.2 --- 24 September 2015 === +- Enable typing into New Alarm dialogue while alarm is displayed (Unity desktop) [KDE Bug 352889] + +=== Version 2.11.1 (KDE Applications 15.08.1)--- 1 September 2015 === - Fix conversion error in sub-repetition value from command line or D-Bus command. === Version 2.11.0 --- July 2015 === diff --git a/editdlg.cpp b/editdlg.cpp index 4432cc0469f7249c96ae3ed79907ffdcca781ae1..70e7ac0359f3171786464e58b5b3f446b7615e4e 100644 --- a/editdlg.cpp +++ b/editdlg.cpp @@ -1,7 +1,7 @@ /* * editdlg.cpp - dialog to create or modify an alarm or alarm template * Program: kalarm - * Copyright © 2001-2012 by David Jarvie + * Copyright © 2001-2015 by David Jarvie * * 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 @@ -90,6 +90,8 @@ inline QString recurText(const KAEvent& event) return i18nc("@title:tab", "Recurrence - [%1]", r); } +QList EditAlarmDlg::mWindowList; + // Collect these widget labels together to ensure consistent wording and // translations across different modules. QString EditAlarmDlg::i18n_chk_ShowInKOrganizer() { return i18nc("@option:check", "Show in KOrganizer"); } @@ -153,6 +155,7 @@ EditAlarmDlg::EditAlarmDlg(bool Template, KAEvent::SubAction action, QWidget* pa mSavedEvent(Q_NULLPTR) { init(Q_NULLPTR, getResource); + mWindowList.append(this); } EditAlarmDlg::EditAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, QWidget* parent, @@ -177,6 +180,7 @@ EditAlarmDlg::EditAlarmDlg(bool Template, const KAEvent* event, bool newAlarm, Q mSavedEvent(Q_NULLPTR) { init(event, getResource); + mWindowList.append(this); } void EditAlarmDlg::init(const KAEvent* event, GetResourceType getResource) @@ -444,11 +448,27 @@ void EditAlarmDlg::init(const KAEvent* event) // desktop. If the user invokes the dialog via the system tray on a different desktop, // that can cause confusion. mDesktop = KWindowSystem::currentDesktop(); + + if (theApp()->windowFocusBroken()) + { + const QList children = findChildren(); + foreach (QWidget* w, children) + w->installEventFilter(this); + } } EditAlarmDlg::~EditAlarmDlg() { delete mSavedEvent; + mWindowList.removeAll(this); +} + +/****************************************************************************** +* Return the number of instances. +*/ +int EditAlarmDlg::instanceCount() +{ + return mWindowList.count(); } /****************************************************************************** @@ -832,6 +852,46 @@ void EditAlarmDlg::showEvent(QShowEvent* se) } slotResize(); KWindowSystem::setOnDesktop(winId(), mDesktop); // ensure it displays on the desktop expected by the user + + if (theApp()->needWindowFocusFix()) + { + QApplication::setActiveWindow(this); + QTimer::singleShot(0, this, SLOT(focusFixTimer())); + } +} + +/****************************************************************************** +* Called when the window is first shown, to ensure that it initially becomes +* the active window. +* This is only required on Ubuntu's Unity desktop, which doesn't transfer +* keyboard focus properly between Edit Alarm Dialog windows and MessageWin +* windows. +*/ +void EditAlarmDlg::focusFixTimer() +{ + if (theApp()->needWindowFocusFix() + && QApplication::focusWidget()->window() != this) + { + QApplication::setActiveWindow(this); + QTimer::singleShot(0, this, SLOT(focusFixTimer())); + } +} + +/****************************************************************************** +* Called to detect when the mouse is pressed anywhere inside the window. +* Activates this window if a MessageWin window is also active. +* This is only required on Ubuntu's Unity desktop, which doesn't transfer +* keyboard focus properly between Edit Alarm Dialog windows and MessageWin +* windows. +*/ +bool EditAlarmDlg::eventFilter(QObject*, QEvent* e) +{ + if (theApp()->needWindowFocusFix()) + { + if (e->type() == QEvent::MouseButtonPress) + QApplication::setActiveWindow(this); + } + return false; } /****************************************************************************** @@ -1384,6 +1444,7 @@ void EditAlarmDlg::showMainPage() { mTabs->setCurrentIndex(mMainPageIndex); } + #include "moc_editdlg.cpp" #include "moc_editdlg_p.cpp" diff --git a/editdlg.h b/editdlg.h index 6a8d729f4f33245e879d8421b9f7ccfd10df5e19..a7f3ff73850713b34d8227134466de5ee07bec8d 100644 --- a/editdlg.h +++ b/editdlg.h @@ -1,7 +1,7 @@ /* * editdlg.h - dialog to create or modify an alarm or alarm template * Program: kalarm - * Copyright © 2001-2013 by David Jarvie + * Copyright © 2001-2015 by David Jarvie * * 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 @@ -82,6 +82,7 @@ class EditAlarmDlg : public KDialog QSize sizeHint() const Q_DECL_OVERRIDE { return minimumSizeHint(); } + static int instanceCount(); static QString i18n_chk_ShowInKOrganizer(); // text of 'Show in KOrganizer' checkbox protected: @@ -93,6 +94,7 @@ class EditAlarmDlg : public KDialog void resizeEvent(QResizeEvent*) Q_DECL_OVERRIDE; void showEvent(QShowEvent*) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent*) Q_DECL_OVERRIDE; + bool eventFilter(QObject*, QEvent*) Q_DECL_OVERRIDE; virtual QString type_caption() const = 0; virtual void type_init(QWidget* parent, QVBoxLayout* frameLayout) = 0; virtual void type_initValues(const KAEvent*) = 0; @@ -135,6 +137,7 @@ class EditAlarmDlg : public KDialog void slotTemplateTimeType(QAbstractButton*); void slotSetSubRepetition(); void slotResize(); + void focusFixTimer(); private: void init(const KAEvent* event, GetResourceType getResource); @@ -148,6 +151,7 @@ class EditAlarmDlg : public KDialog protected: KAEvent::SubAction mAlarmType; // actual alarm type private: + static QList mWindowList; // list of instances QTabWidget* mTabs; // the tabs in the dialog StackedScrollGroup* mTabScrollGroup; int mMainPageIndex; diff --git a/kalarm.h b/kalarm.h index d0bf03773b437c71e30ad25ece1028e0cdbcee8e..893da563a4f5f5f26d6fdacf7f50860272fe7c7e 100644 --- a/kalarm.h +++ b/kalarm.h @@ -24,7 +24,7 @@ #undef QT3_SUPPORT #define VERSION_SUFFIX "-5ak" -#define KALARM_VERSION "2.11.1" VERSION_SUFFIX +#define KALARM_VERSION "2.11.2" VERSION_SUFFIX #define KALARM_NAME "KAlarm" #define KALARM_DBUS_SERVICE "org.kde.kalarm" // D-Bus service name of KAlarm application diff --git a/kalarmapp.cpp b/kalarmapp.cpp index 91f4f7db24a112957cff355a758c86c560cc64c2..fe47dd9674e0135929310e7c2a55d8ce2b3819c9 100644 --- a/kalarmapp.cpp +++ b/kalarmapp.cpp @@ -171,6 +171,9 @@ KAlarmApp::KAlarmApp() const QString korg = QLatin1String("korganizer"); mKOrganizerEnabled = !QStandardPaths::findExecutable(korg).isNull() || !KStandardDirs::findExe(korg).isNull(); if (!mKOrganizerEnabled) { qCDebug(KALARM_LOG) << "KOrganizer options disabled (KOrganizer not found)"; } + // Check if the window manager can't handle keyboard focus transfer between windows + mWindowFocusBroken = (QProcessEnvironment::systemEnvironment().value(QStringLiteral("XDG_CURRENT_DESKTOP")) == QLatin1String("Unity")); + if (mWindowFocusBroken) { qCDebug(KALARM_LOG) << "Window keyboard focus broken"; } } /****************************************************************************** @@ -1272,6 +1275,27 @@ void KAlarmApp::setSpreadWindowsState(bool spread) Q_EMIT spreadWindowsToggled(spread); } +/****************************************************************************** +* Check whether the window manager's handling of keyboard focus transfer +* between application windows is broken. This is true for Ubuntu's Unity +* desktop, where MessageWin windows steal keyboard focus from EditAlarmDlg +* windows. +*/ +bool KAlarmApp::windowFocusBroken() const +{ + return mWindowFocusBroken; +} + +/****************************************************************************** +* Check whether window/keyboard focus currently needs to be fixed manually due +* to the window manager not handling it correctly. This will occur if there are +* both EditAlarmDlg and MessageWin windows currently active. +*/ +bool KAlarmApp::needWindowFocusFix() const +{ + return mWindowFocusBroken && MessageWin::instanceCount(true) && EditAlarmDlg::instanceCount(); +} + /****************************************************************************** * Called to schedule a new alarm, either in response to a DCOP notification or * to command line options. diff --git a/kalarmapp.h b/kalarmapp.h index f8994557947bb44740c4f2f8afc7829bc4b79b22..fa2d7866b9c73e12edab0c3dd94a7d4c53b4712d 100644 --- a/kalarmapp.h +++ b/kalarmapp.h @@ -82,6 +82,8 @@ class KAlarmApp : public KUniqueApplication void commandMessage(ShellProcess*, QWidget* parent); void notifyAudioPlaying(bool playing); void setSpreadWindowsState(bool spread); + bool windowFocusBroken() const; + bool needWindowFocusFix() const; // Methods called indirectly by the DCOP interface bool scheduleEvent(KAEvent::SubAction, const QString& text, const KDateTime&, int lateCancel, KAEvent::Flags flags, const QColor& bg, const QColor& fg, @@ -221,6 +223,7 @@ class KAlarmApp : public KUniqueApplication bool mAlarmsEnabled; // alarms are enabled bool mSpeechEnabled; // speech synthesis is enabled (kttsd exists) bool mKOrganizerEnabled; // KOrganizer options are enabled (korganizer exists) + bool mWindowFocusBroken; // keyboard focus transfer between windows doesn't work }; inline KAlarmApp* theApp() { return KAlarmApp::getInstance(); } diff --git a/mainwindowbase.cpp b/mainwindowbase.cpp index 7f3bb9ce3837a50c88a8285fdeaac2761f762aad..2e5f4962538c7dfde3fe94d960b3a5353f331464 100644 --- a/mainwindowbase.cpp +++ b/mainwindowbase.cpp @@ -1,7 +1,7 @@ /* * mainwindowbase.cpp - base class for main application windows * Program: kalarm - * Copyright © 2002,2003,2007 by David Jarvie + * Copyright © 2002,2003,2007,2015 by David Jarvie * * 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 @@ -30,5 +30,18 @@ MainWindowBase::MainWindowBase(QWidget* parent, Qt::WindowFlags f) setWindowModality(Qt::WindowModal); } +/****************************************************************************** +* Called when the mouse cursor enters the window. +* Activates this window if an Edit Alarm Dialog has activated itself. +* This is only required on Ubuntu's Unity desktop, which doesn't transfer +* keyboard focus properly between Edit Alarm Dialog windows and MessageWin +* windows. +*/ +void MainWindowBase::enterEvent(QEvent* e) +{ + if (theApp()->needWindowFocusFix()) + QApplication::setActiveWindow(this); + KXmlGuiWindow::enterEvent(e); +} // vim: et sw=4: diff --git a/mainwindowbase.h b/mainwindowbase.h index 18732dcfc448144e7b5c6d022fda573bc59de808..3ccf05384cc7034f0e0cd386977c36cf8e131174 100644 --- a/mainwindowbase.h +++ b/mainwindowbase.h @@ -1,7 +1,7 @@ /* * mainwindowbase.h - base class for main application windows * Program: kalarm - * Copyright © 2002,2006,2007 by David Jarvie + * Copyright © 2002,2006,2007,2015 by David Jarvie * * 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 @@ -36,6 +36,9 @@ class MainWindowBase : public KXmlGuiWindow public: explicit MainWindowBase(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::Window); + + protected: + void enterEvent(QEvent*) Q_DECL_OVERRIDE; }; #endif // MAINWINDOWBASE_H