Commit 8e3b57e2 authored by David Jarvie's avatar David Jarvie

Bug 352889: allow typing in New Alarm dialog while alarm displayed

The Unity desktop (Ubuntu 14.04) doesn't handle transferring keyboard
focus between top level windows in the application, so that it was
impossible to type into the New Alarm dialog if an alarm message
window was currently displayed.

This fix is a hack which is only activated on Unity.

Forward port of 08e5d90f (4.14 branch)
parent fba81957
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 ===
......
/*
* editdlg.cpp - dialog to create or modify an alarm or alarm template
* Program: kalarm
* Copyright © 2001-2012 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2015 by David Jarvie <djarvie@kde.org>
*
* 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*> 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<QWidget*> children = findChildren<QWidget*>();
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"
......
/*
* editdlg.h - dialog to create or modify an alarm or alarm template
* Program: kalarm
* Copyright © 2001-2013 by David Jarvie <djarvie@kde.org>
* Copyright © 2001-2015 by David Jarvie <djarvie@kde.org>
*
* 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<EditAlarmDlg*> mWindowList; // list of instances
QTabWidget* mTabs; // the tabs in the dialog
StackedScrollGroup* mTabScrollGroup;
int mMainPageIndex;
......
......@@ -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
......
......@@ -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.
......
......@@ -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(); }
......
/*
* mainwindowbase.cpp - base class for main application windows
* Program: kalarm
* Copyright © 2002,2003,2007 by David Jarvie <djarvie@kde.org>
* Copyright © 2002,2003,2007,2015 by David Jarvie <djarvie@kde.org>
*
* 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:
/*
* mainwindowbase.h - base class for main application windows
* Program: kalarm
* Copyright © 2002,2006,2007 by David Jarvie <djarvie@kde.org>
* Copyright © 2002,2006,2007,2015 by David Jarvie <djarvie@kde.org>
*
* 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment