diff --git a/README.md b/README.md index 06e6d9d..5147641 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ The add-on and system tray application can do: - custom new mail icon - display number of unread mails -- to be implemented: show / hide Thunderbird +- show / hide Thunderbird (minimize) +- to be implemented: remove from task bar when minimized - to be implemented: start a new mail - to be implemented: open the last used account diff --git a/app/SysTray-X/SysTray-X.pro b/app/SysTray-X/SysTray-X.pro index 38ab0f3..febb3d3 100644 --- a/app/SysTray-X/SysTray-X.pro +++ b/app/SysTray-X/SysTray-X.pro @@ -116,6 +116,17 @@ message("Git branch: "$$GIT_BRANCH) message("Version: "$$VERSION_MAJOR"."$$VERSION_MINOR"."$$VERSION_PATCH) #message($$QMAKESPEC) +win32: { + CONFIG(debug, debug|release) { + QMAKE_POST_LINK = $$[QT_INSTALL_BINS]\windeployqt.exe "$$shell_path($${OUT_PWD}/debug/$${TARGET}.exe)" + +# QMAKE_POST_LINK += xcopy /Y \"$$shell_path($$[QT_INSTALL_BINS]/Qt5widgetsd.dll)\" \"$$shell_path($${OUT_PWD}/debug/)\" & + } else { + QMAKE_POST_LINK = $$[QT_INSTALL_BINS]\windeployqt.exe "$$shell_path($${OUT_PWD}/release/$${TARGET}.exe)" + +# QMAKE_POST_LINK += xcopy /Y \"$$shell_path($$[QT_INSTALL_BINS]/Qt5widgets.dll)\" \"$$shell_path($${OUT_PWD}/release/)\" & + } +} # # DO NOT COMPRESS THE RESOURCES. QFile.map() cannot handle it... @@ -131,6 +142,14 @@ SOURCES += \ debugwidget.cpp \ preferencesdialog.cpp \ preferences.cpp +unix: { +SOURCES += \ + windowctrl-unix.cpp +} +win32: { +SOURCES += \ + windowctrl-win.cpp +} HEADERS += \ systrayxlink.h \ @@ -138,7 +157,16 @@ HEADERS += \ systrayx.h \ debugwidget.h \ preferencesdialog.h \ - preferences.h + preferences.h \ + windowctrl.h +unix: { +HEADERS += \ + windowctrl-unix.h +} +win32: { +HEADERS += \ + windowctrl-win.h +} FORMS += \ debugwidget.ui \ diff --git a/app/SysTray-X/systrayx.cpp b/app/SysTray-X/systrayx.cpp index f5f5b19..c009ead 100644 --- a/app/SysTray-X/systrayx.cpp +++ b/app/SysTray-X/systrayx.cpp @@ -7,6 +7,7 @@ #include "preferencesdialog.h" #include "systrayxlink.h" #include "systrayxicon.h" +#include "windowctrl.h" /* * Qt includes @@ -30,6 +31,11 @@ SysTrayX::SysTrayX( QObject *parent ) : QObject( parent ) */ m_preferences = new Preferences(); + /* + * Setup window control + */ + m_win_ctrl = new WindowCtrl(); + /* * Setup the link */ @@ -54,9 +60,6 @@ SysTrayX::SysTrayX( QObject *parent ) : QObject( parent ) m_debug->show(); } -// connect( m_trayIcon, &QSystemTrayIcon::messageClicked, this, &SysTrayX::messageClicked); - connect( m_tray_icon, &QSystemTrayIcon::activated, this, &SysTrayX::iconActivated); - /* * Connect debug link signals */ @@ -72,10 +75,11 @@ SysTrayX::SysTrayX( QObject *parent ) : QObject( parent ) connect( m_pref_dialog, &PreferencesDialog::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage ); connect( m_tray_icon, &SysTrayXIcon::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage ); connect( m_link, &SysTrayXLink::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage ); + connect( m_win_ctrl, &WindowCtrl::signalDebugMessage, m_debug, &DebugWidget::slotDebugMessage ); /* - * Connect preferences signals + * Connect preferences signals */ connect( m_preferences, &Preferences::signalIconTypeChange, m_tray_icon, &SysTrayXIcon::slotIconTypeChange ); connect( m_preferences, &Preferences::signalIconDataChange, m_tray_icon, &SysTrayXIcon::slotIconDataChange ); @@ -91,10 +95,22 @@ SysTrayX::SysTrayX( QObject *parent ) : QObject( parent ) connect( m_preferences, &Preferences::signalDebugChange, m_debug, &DebugWidget::slotDebugChange ); /* - * Connect link signals + * Connect link signals */ connect( m_link, &SysTrayXLink::signalUnreadMail, m_tray_icon, &SysTrayXIcon::slotSetUnreadMail ); connect( m_link, &SysTrayXLink::signalShutdown, this, &SysTrayX::slotShutdown ); + connect( m_link, &SysTrayXLink::signalWindowState, m_win_ctrl, &WindowCtrl::slotWindowState ); + + /* + * Connect window signals + */ + connect( m_win_ctrl, &WindowCtrl::signalWindowNormal, m_link, &SysTrayXLink::slotWindowNormal ); + connect( m_win_ctrl, &WindowCtrl::signalWindowMinimize, m_link, &SysTrayXLink::slotWindowMinimize ); + + /* + * Connect system tray signals + */ + connect( m_tray_icon, &SysTrayXIcon::signalShowHide, m_win_ctrl, &WindowCtrl::slotShowHide ); /* * Request preferences from add-on @@ -116,22 +132,6 @@ void SysTrayX::getPreferences() } -/* - * Handle a click on the system tray icon - */ -void SysTrayX::iconActivated( QSystemTrayIcon::ActivationReason reason ) -{ - switch (reason) { - case QSystemTrayIcon::Trigger: - case QSystemTrayIcon::DoubleClick: - case QSystemTrayIcon::MiddleClick: - break; - default: - ; - } -} - - /* * Create the actions for the system tray icon menu */ @@ -148,6 +148,9 @@ void SysTrayX::createActions() connect( m_restoreAction, &QAction::triggered, this, &QWidget::showNormal ); */ + m_showhide_action = new QAction(tr("&Show/Hide"), this); + connect( m_showhide_action, &QAction::triggered, m_win_ctrl, &WindowCtrl::slotShowHide ); + m_pref_action = new QAction(tr("&Preferences"), this); connect( m_pref_action, &QAction::triggered, m_pref_dialog, &PreferencesDialog::showNormal ); @@ -175,6 +178,8 @@ void SysTrayX::createTrayIcon() // m_trayIconMenu->addAction( m_maximizeAction ); // m_trayIconMenu->addAction( m_restoreAction ); + m_tray_icon_menu->addAction( m_showhide_action ); + m_tray_icon_menu->addSeparator(); m_tray_icon_menu->addAction( m_pref_action ); m_tray_icon_menu->addSeparator(); m_tray_icon_menu->addAction( m_quit_action ); diff --git a/app/SysTray-X/systrayx.h b/app/SysTray-X/systrayx.h index 2a0551e..ad787c5 100644 --- a/app/SysTray-X/systrayx.h +++ b/app/SysTray-X/systrayx.h @@ -22,6 +22,7 @@ class DebugWidget; class PreferencesDialog; class SysTrayXIcon; class SysTrayXLink; +class WindowCtrl; /** * @brief The SysTrayX class @@ -50,12 +51,6 @@ class SysTrayX : public QObject */ void getPreferences(); - /** - * @brief iconActivated - * @param reason - */ - void iconActivated( QSystemTrayIcon::ActivationReason reason ); - /** * @brief createTrayIcon. Create the system tray icon. */ @@ -94,6 +89,11 @@ class SysTrayX : public QObject */ DebugWidget *m_debug; + /** + * @brief m_win_ctrl. Pointer to the window control. + */ + WindowCtrl *m_win_ctrl; + /** * @brief m_link. Pointer to the link object. */ @@ -119,6 +119,7 @@ class SysTrayX : public QObject */ QAction *m_pref_action; QAction *m_quit_action; + QAction *m_showhide_action; }; #endif // SYSTRAYX_H diff --git a/app/SysTray-X/systrayxicon.cpp b/app/SysTray-X/systrayxicon.cpp index f9068c6..a3a82f0 100644 --- a/app/SysTray-X/systrayxicon.cpp +++ b/app/SysTray-X/systrayxicon.cpp @@ -28,6 +28,8 @@ SysTrayXIcon::SysTrayXIcon( SysTrayXLink *link, Preferences *pref, QObject *pare m_pref = pref; m_unread_mail = 0; + + connect( this, &QSystemTrayIcon::activated, this, &SysTrayXIcon::slotIconActivated ); } @@ -188,3 +190,26 @@ void SysTrayXIcon::slotIconDataChange() setIconMime( m_pref->getIconMime() ); setIconData( m_pref->getIconData() ); } + + +/* + * Handle activation of the tray icon + */ +void SysTrayXIcon::slotIconActivated( QSystemTrayIcon::ActivationReason reason ) +{ + switch (reason) { + case QSystemTrayIcon::Trigger: + { + // Clicked + emit signalShowHide(); + break; + } + + case QSystemTrayIcon::DoubleClick: + case QSystemTrayIcon::MiddleClick: + break; + + default: + ; + } +} diff --git a/app/SysTray-X/systrayxicon.h b/app/SysTray-X/systrayxicon.h index 478892a..c9beb57 100644 --- a/app/SysTray-X/systrayxicon.h +++ b/app/SysTray-X/systrayxicon.h @@ -61,6 +61,13 @@ class SysTrayXIcon : public QSystemTrayIcon */ void setUnreadMail( int unread_mail ); + private: + + /** + * @brief setIcon. Set a new rendered icon. + */ + void renderIcon(); + signals: /** @@ -70,6 +77,11 @@ class SysTrayXIcon : public QSystemTrayIcon */ void signalDebugMessage( QString message ); + /** + * @brief signalShowHide. Signal show / hide window. + */ + void signalShowHide(); + public slots: /** @@ -89,12 +101,14 @@ class SysTrayXIcon : public QSystemTrayIcon */ void slotIconDataChange(); - private: + private slots: /** - * @brief setIcon. Set a new rendered icon. + * @brief slotIconActivated. Hnadle activation signal of the tray icon. + * + * @param reason Activation reason. */ - void renderIcon(); + void slotIconActivated( QSystemTrayIcon::ActivationReason reason ); private: diff --git a/app/SysTray-X/systrayxlink.cpp b/app/SysTray-X/systrayxlink.cpp index 27a18f0..f393ae2 100644 --- a/app/SysTray-X/systrayxlink.cpp +++ b/app/SysTray-X/systrayxlink.cpp @@ -8,7 +8,6 @@ /* * System includes */ -#include /* * Qt includes @@ -52,10 +51,10 @@ SysTrayXLink::SysTrayXLink( Preferences *pref ) /* * Setup the notifiers */ - m_notifier_link_read = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Read, this ); + m_notifier_link_read = new QSocketNotifier( 0, QSocketNotifier::Read, this ); connect( m_notifier_link_read, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkRead ); - m_notifier_link_read_exception = new QSocketNotifier( STDIN_FILENO, QSocketNotifier::Exception, this ); + m_notifier_link_read_exception = new QSocketNotifier( 0, QSocketNotifier::Exception, this ); connect( m_notifier_link_read_exception, &QSocketNotifier::activated, this, &SysTrayXLink::slotLinkReadException ); } @@ -129,6 +128,52 @@ void SysTrayXLink::sendPreferences() } +/* + * Send the window normal command + */ +void SysTrayXLink::sendWindowNormal() +{ + /* + * Create command + */ + QJsonObject windowObject; + windowObject.insert("window", "normal" ); + + /* + * Create doc + */ + QJsonDocument doc( windowObject ); + + /* + * Send the command + */ + linkWrite( doc.toJson( QJsonDocument::Compact ) ); +} + + +/* + * Send the window minimize command + */ +void SysTrayXLink::sendWindowMinimize() +{ + /* + * Create command + */ + QJsonObject windowObject; + windowObject.insert("window", "minimized" ); + + /* + * Create doc + */ + QJsonDocument doc( windowObject ); + + /* + * Send the command + */ + linkWrite( doc.toJson( QJsonDocument::Compact ) ); +} + + /* * Decode JSON message */ @@ -141,15 +186,21 @@ void SysTrayXLink::DecodeMessage( const QByteArray& message ) { QJsonObject jsonObject = jsonResponse.object(); + if( jsonObject.contains( "unreadMail" ) && jsonObject[ "unreadMail" ].isDouble() ) + { + int unreadMail = jsonObject[ "unreadMail" ].toInt(); + emit signalUnreadMail( unreadMail ); + } + if( jsonObject.contains( "shutdown" ) && jsonObject[ "shutdown" ].isString() ) { emit signalShutdown(); } - if( jsonObject.contains( "unreadMail" ) && jsonObject[ "unreadMail" ].isDouble() ) + if( jsonObject.contains( "window" ) && jsonObject[ "window" ].isString() ) { - int unreadMail = jsonObject[ "unreadMail" ].toInt(); - emit signalUnreadMail( unreadMail ); + QString window_state = jsonObject[ "window" ].toString(); + emit signalWindowState( window_state ); } if( jsonObject.contains( "preferences" ) && jsonObject[ "preferences" ].isObject() ) @@ -331,3 +382,21 @@ void SysTrayXLink::slotIconDataChange() sendPreferences(); } } + + +/* + * Handle the window normal signal + */ +void SysTrayXLink::slotWindowNormal() +{ + sendWindowNormal(); +} + + +/* + * Handle the window minimize signal + */ +void SysTrayXLink::slotWindowMinimize() +{ + sendWindowMinimize(); +} diff --git a/app/SysTray-X/systrayxlink.h b/app/SysTray-X/systrayxlink.h index f428474..881836c 100644 --- a/app/SysTray-X/systrayxlink.h +++ b/app/SysTray-X/systrayxlink.h @@ -45,6 +45,16 @@ class SysTrayXLink : public QObject */ void sendPreferences(); + /** + * @brief sendWindowNormal. Send the window normal command. + */ + void sendWindowNormal(); + + /** + * @brief sendWindowMinimize. Send the window minimize command. + */ + void sendWindowMinimize(); + private: /** @@ -75,6 +85,11 @@ class SysTrayXLink : public QObject */ void signalShutdown(); + /** + * @brief signalWindowState. Signal a change in the window state. + */ + void signalWindowState( QString state ); + /** * @brief signalReceivedMessageLength * @@ -132,6 +147,16 @@ class SysTrayXLink : public QObject */ void slotIconDataChange(); + /** + * @brief slotWindowNormal. Slot for handling window normal signals. + */ + void slotWindowNormal(); + + /** + * @brief slotWindowMinimize. Slot for handling window minimize signals. + */ + void slotWindowMinimize(); + private slots: /** diff --git a/app/SysTray-X/windowctrl-unix.cpp b/app/SysTray-X/windowctrl-unix.cpp new file mode 100644 index 0000000..9101a5a --- /dev/null +++ b/app/SysTray-X/windowctrl-unix.cpp @@ -0,0 +1,41 @@ +#include "windowctrl-unix.h" + +#ifdef Q_OS_UNIX + +/* + * Constructor + */ +WindowCtrl::WindowCtrl(QObject *parent) : QObject(parent) +{ + +} + + +/* + * Handle change in window state + */ +void WindowCtrl::slotWindowState( QString state ) +{ + m_state = state; + + emit signalDebugMessage( "Win state: " + state ); +} + + +/* + * Handle show / hide signal + */ +void WindowCtrl::slotShowHide() +{ + if( m_state == "minimized" ) + { + m_state = "normal"; + emit signalWindowNormal(); + } else { + m_state = "minimized"; + emit signalWindowMinimize(); + } +} + + +#endif // Q_OS_UNIX diff --git a/app/SysTray-X/windowctrl-unix.h b/app/SysTray-X/windowctrl-unix.h new file mode 100644 index 0000000..f1302e6 --- /dev/null +++ b/app/SysTray-X/windowctrl-unix.h @@ -0,0 +1,65 @@ +#include +#ifdef Q_OS_UNIX + +#ifndef WINDOWCTRLLINUX_H +#define WINDOWCTRLLINUX_H + +#include + +class WindowCtrl : public QObject +{ + Q_OBJECT + + public: + + /** + * @brief WindowCtrl. Constructor. + * + * @param parent My parent. + */ + explicit WindowCtrl( QObject *parent = nullptr ); + + signals: + + /** + * @brief signalDebugMessage. Signal a debug message. + * + * @param message The message. + */ + void signalDebugMessage( QString message ); + + /** + * @brief signalWindowNormal. Signal normal window. + */ + void signalWindowNormal(); + + /** + * @brief signalWindowMinimuze. Signal minimize window. + */ + void signalWindowMinimize(); + + public slots: + + /** + * @brief slotWindowState. Handle the window state change signal. + * + * @param state The new state. + */ + void slotWindowState( QString state ); + + /** + * @brief slotShowHide. Slot for handling of the show / hide window signal. + */ + void slotShowHide(); + + private: + + /** + * @brief m_state. State of the TB window. + */ + QString m_state; +}; + +#endif // WINDOWCTRLLINUX_H + +#endif // Q_OS_UNIX diff --git a/app/SysTray-X/windowctrl-win.cpp b/app/SysTray-X/windowctrl-win.cpp new file mode 100644 index 0000000..fecde09 --- /dev/null +++ b/app/SysTray-X/windowctrl-win.cpp @@ -0,0 +1,40 @@ +#include "windowctrl-win.h" + +#ifdef Q_OS_WIN + +/* + * Constructor + */ +WindowCtrl::WindowCtrl(QObject *parent) : QObject(parent) +{ + +} + + +/* + * Handle change in window state + */ +void WindowCtrl::slotWindowState( QString state ) +{ + m_state = state; + + emit signalDebugMessage( "Win state: " + state ); +} + + +/* + * Handle show / hide signal + */ +void WindowCtrl::slotShowHide() +{ + if( m_state == "minimized" ) + { + m_state = "normal"; + emit signalWindowNormal(); + } else { + m_state = "minimized"; + emit signalWindowMinimize(); + } +} + +#endif // Q_OS_WIN diff --git a/app/SysTray-X/windowctrl-win.h b/app/SysTray-X/windowctrl-win.h new file mode 100644 index 0000000..23f4863 --- /dev/null +++ b/app/SysTray-X/windowctrl-win.h @@ -0,0 +1,65 @@ +#include +#ifdef Q_OS_WIN + +#ifndef WINDOWCTRLWIN_H +#define WINDOWCTRLWIN_H + +#include + +class WindowCtrl : public QObject +{ + Q_OBJECT + + public: + + /** + * @brief WindowCtrl. Constructor. + * + * @param parent My parent. + */ + explicit WindowCtrl( QObject *parent = nullptr ); + + signals: + + /** + * @brief signalDebugMessage. Signal a debug message. + * + * @param message The message. + */ + void signalDebugMessage( QString message ); + + /** + * @brief signalWindowNormal. Signal normal window. + */ + void signalWindowNormal(); + + /** + * @brief signalWindowMinimuze. Signal minimize window. + */ + void signalWindowMinimize(); + + public slots: + + /** + * @brief slotWindowState. Handle the window state change signal. + * + * @param state The new state. + */ + void slotWindowState( QString state ); + + /** + * @brief slotShowHide. Slot for handling of the show / hide window signal. + */ + void slotShowHide(); + + private: + + /** + * @brief m_state. State of the TB window. + */ + QString m_state; +}; + +#endif // WINDOWCTRLWIN_H + +#endif // Q_OS_WIN diff --git a/app/SysTray-X/windowctrl.h b/app/SysTray-X/windowctrl.h new file mode 100644 index 0000000..04288c1 --- /dev/null +++ b/app/SysTray-X/windowctrl.h @@ -0,0 +1,14 @@ +#ifndef WINDOWCTRL_H +#define WINDOWCTRL_H + +#include + +#ifdef Q_OS_UNIX +#include "windowctrl-unix.h" +#endif // Q_OS_UNIX + +#ifdef Q_OS_WIN +#include "windowctrl-win.h" +#endif // Q_OS_WIN + +#endif // WINDOWCTRL_H diff --git a/webext/background.js b/webext/background.js index 6a8de7c..98d0517 100644 --- a/webext/background.js +++ b/webext/background.js @@ -23,17 +23,11 @@ SysTrayX.Messaging = { // this.unReadMessages(this.unreadFiltersTest).then(this.unreadCb); window.setInterval(SysTrayX.Messaging.pollAccounts, 10000); - // Semd the app a close command - browser.windows.onRemoved.addListener(SysTrayX.Messaging.closeApp); - }, + // Send the app a close command if the window closes + browser.windows.onRemoved.addListener(SysTrayX.Window.closed); - closeApp: function() { - console.debug("Shutting down"); - - // Send it to the app - SysTrayX.Link.postSysTrayXMessage({ - shutdown: "" - }); + // Try to catch the window state + browser.windows.onFocusChanged.addListener(SysTrayX.Window.focusChanged); }, // @@ -233,6 +227,23 @@ SysTrayX.Link = { receiveSysTrayXMessage: function(response) { console.log(`Received: ${response}`); + if (response["window"]) { + console.log("Window received: " + response["window"]); + + if (response["window"] === "minimized") { + browser.windows.update(SysTrayX.Window.startWindow.id, { + state: "minimized" + }); + } + + if (response["window"] === "normal") { + browser.windows.update(SysTrayX.Window.startWindow.id, { + state: "normal", + focused: true + }); + } + } + if (response["preferences"]) { // Store the preferences from the app console.log("Preferences received"); @@ -268,10 +279,60 @@ SysTrayX.Link = { } }; +SysTrayX.Window = { + startWindow: undefined, + + closed: function() { + // Window closed + console.debug("Shutting down"); + + // Send it to the app + SysTrayX.Link.postSysTrayXMessage({ + shutdown: "" + }); + }, + + focusChanged: function(windowId) { + console.debug("Win focus changed"); + + browser.windows.getCurrent().then(win => { + SysTrayX.Link.postSysTrayXMessage({ window: win.state }); + }); + + /* + if (windowId === -1) { + // Assume minimized + SysTrayX.Link.postSysTrayXMessage({ + window: "minimized" + }); + } else { + browser.windows.get(windowId, function(win) { + SysTrayX.Link.postSysTrayXMessage({ + window: win.state + }); + }); + } +*/ + } +}; + async function start() { // Init defaults before everything await getDefaultIcon(); + SysTrayX.Window.startWindow = await browser.windows + .getCurrent() + .then(currentWindow => currentWindow); + + console.debug("Window focus: " + SysTrayX.Window.startWindow.focused); + console.debug("Window name: " + SysTrayX.Window.startWindow.title); + console.debug("Window name: " + SysTrayX.Window.startWindow.state); + + // browser.windows.update(currentWindow.id, { state: "minimized" }); + // browser.windows.update(currentWindow.id, { state: "normal", focused: true }); + + // ?? browser.windows.update(currentWindow.id, { state: "docked" }); + // Setup the link first SysTrayX.Link.init(); diff --git a/webext/manifest.json b/webext/manifest.json index cb05c3f..d037a97 100644 --- a/webext/manifest.json +++ b/webext/manifest.json @@ -19,7 +19,7 @@ "default_locale": "en-US", - "permissions": ["accountsRead", "messagesRead", "storage", "nativeMessaging"], + "permissions": ["accountsRead", "messagesRead", "storage", "nativeMessaging", "tabs"], "background": { "page": "background.html"