pidgin/quail/quail-redux

Parents 777509d81ef2
Children 1b96f1615999
Another attempt at implementing a Qt Glib Windows Event loop, based on advice from Thiago Macieira
--- a/Quail-redux.pro Thu Sep 05 10:31:00 2013 +0100
+++ b/Quail-redux.pro Fri Sep 13 13:58:43 2013 +0100
@@ -1,166 +1,169 @@
-DEFINES += APP_DISPLAY_VERSION=\\\"0.1.0\\\"
-DEFINES += APP_MAJOR_VERSION=\\\"0\\\"
-
-TEMPLATE = app
-TARGET = Quail
-VERSION = $${APP_DISPLAY_VERSION}
-CONFIG = qt warn_on debug_and_release
-
-DEFINES += APP_NAME=\\\"Quail\\\"
-DEFINES += QUAIL_PREFS_ROOT=\\\"/quail\\\"
-DEFINES += UI_ID=\\\"quail\\\"
-# Check that we have the repository folder
-exists(.hg):DEFINES += BUILDREVISION=\\\"$$system( hg parent --template \"{node}\")\\\"
-else:DEFINES += BUILDREVISION=\\\"NOTBUILTFROMSOURCEREPOSITORY\\\"
-
-#win32-g++ {
-# DEFINES += BUILDTIME=\\\"$$system('time/T')\\\"
-# DEFINES += BUILDDATE=\\\"$$system('echo %date%')\\\"
-#}
-#else {
-# DEFINES += BUILDTIME=\\\"$$system(date '+%H:%M.%s')\\\"
-# DEFINES += BUILDDATE=\\\"$$system(date '+%d/%m/%y')\\\"
-#}
-
-QT += core gui webkit
-greaterThan(QT_MAJOR_VERSION, 4) {
- message("Using QT5")
- DEFINES += USE_QT5
- QT += widgets
- QT += webkitwidgets
-}
-
-HEADERS = \
- src/QuailAccountBox.h \
- src/QuailAccountEditor.h \
- src/QuailAccountsWindow.h \
- src/QuailAction.h \
- src/QuailBListWindow.h \
- src/QuailBuddyList.h \
- src/QuailConnectionMeter.h \
- src/QuailConvButton.h \
- src/QuailConvWindow.h \
- src/QuailDebugWindow.h \
- src/QuailEventLoop.h \
- src/QuailDialogs.h \
- src/QuailImageUtils.h \
- src/QuailInputDialog.h \
- src/QuailMainWindow.h \
- src/QuailMultiLineEdit.h \
- src/QuailNotify.h \
- src/QuailPrefsDialog.h \
- src/QuailProtocolBox.h \
- src/QuailProtocolUtils.h \
- src/QuailRequest.h \
- src/QuailTabBar.h \
- src/QuailTabWidget.h \
- src/global.h \
- src/QuailConvDisplay.h \
- src/QuailStatusSelector.h \
- src/QuailBlistItem.h
-
-
-SOURCES = \
- src/QuailAccountBox.cpp \
- src/QuailAccountEditor.cpp \
- src/QuailAccountsWindow.cpp \
- src/QuailBListWindow.cpp \
- src/QuailBuddyList.cpp \
- src/QuailConnectionMeter.cpp \
- src/QuailConvButton.cpp \
- src/QuailConvWindow.cpp \
- src/QuailDebugWindow.cpp \
- src/QuailDialogs.cpp \
- src/QuailEventLoop.cpp \
- src/QuailImageUtils.cpp \
- src/QuailInputDialog.cpp \
- src/QuailMainWindow.cpp \
- src/QuailMultiLineEdit.cpp \
- src/QuailNotify.cpp \
- src/QuailPrefsDialog.cpp \
- src/QuailProtocolBox.cpp \
- src/QuailProtocolUtils.cpp \
- src/QuailRequest.cpp \
- src/QuailTabBar.cpp \
- src/QuailTabWidget.cpp \
- src/main.cpp \
- src/QuailConvDisplay.cpp \
- src/QuailStatusSelector.cpp \
- src/QuailBlistItem.cpp
-
-
-DISTFILES = \
- AUTHORS \
- ChangeLog \
- NEWS \
- README \
- quail.png \
- make.sh \
- mkstuff.conf \
- mkipk.sh \
- mktarball.sh
-
-linux-g++* {
- message("Using unix")
- CONFIG += link_pkgconfig
- PKGCONFIG += purple glib-2.0 gmodule-2.0
-}
-
-win32-g++ {
- message("Using win32")
- INCLUDEPATH += /cygdrive/c/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0 \
- /cygdrive/c/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0/include \
- /cygdrive/c/dev/pidgin-main \
- c:/dev/pidgin-main \
- c:/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0 \
- C:/dev/win32-dev/gtk_2_0-2.14/lib/glib-2.0/include
-
- LIBS += -L"C:/dev/win32-dev/gtk-2.24.10/lib"
- LIBS += -L"C:/dev/pidgin-main/libpurple"
- LIBS += -L"C:/Qt/4.8.5/lib"
- LIBS += -L"/cygdrive/c/Qt/4.8.5/lib"
-
- #RC_FILE = resource.rc
-
- LIBS += -llibpurple -lglib-2.0 -lgmodule-2.0
-}
-
-INCLUDEPATH += $$(LIBPURPLE_ROOT)
-#INCLUDEPATH += $$(QTDIR)
-
-OBJECTS_DIR = obj
-MOC_DIR = moc
-
-RESOURCES += \
- quail.qrc
-
-OTHER_FILES += \
- android/AndroidManifest.xml \
- android/res/layout/splash.xml \
- android/res/values/libs.xml \
- android/res/values/strings.xml \
- android/res/values-de/strings.xml \
- android/res/values-el/strings.xml \
- android/res/values-es/strings.xml \
- android/res/values-et/strings.xml \
- android/res/values-fa/strings.xml \
- android/res/values-fr/strings.xml \
- android/res/values-id/strings.xml \
- android/res/values-it/strings.xml \
- android/res/values-ja/strings.xml \
- android/res/values-ms/strings.xml \
- android/res/values-nb/strings.xml \
- android/res/values-nl/strings.xml \
- android/res/values-pl/strings.xml \
- android/res/values-pt-rBR/strings.xml \
- android/res/values-ro/strings.xml \
- android/res/values-rs/strings.xml \
- android/res/values-ru/strings.xml \
- android/res/values-zh-rCN/strings.xml \
- android/res/values-zh-rTW/strings.xml \
- android/src/org/kde/necessitas/ministro/IMinistro.aidl \
- android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \
- android/src/org/qtproject/qt5/android/bindings/QtActivity.java \
- android/src/org/qtproject/qt5/android/bindings/QtApplication.java \
- android/version.xml \
- TODO.txt
+DEFINES += APP_DISPLAY_VERSION=\\\"0.1.0\\\"
+DEFINES += APP_MAJOR_VERSION=\\\"0\\\"
+
+TEMPLATE = app
+TARGET = Quail
+VERSION = $${APP_DISPLAY_VERSION}
+CONFIG = qt warn_on debug_and_release
+
+DEFINES += APP_NAME=\\\"Quail\\\"
+DEFINES += QUAIL_PREFS_ROOT=\\\"/quail\\\"
+DEFINES += UI_ID=\\\"quail\\\"
+# Check that we have the repository folder
+exists(.hg):DEFINES += BUILDREVISION=\\\"$$system( hg parent --template \"{node}\")\\\"
+else:DEFINES += BUILDREVISION=\\\"NOTBUILTFROMSOURCEREPOSITORY\\\"
+
+#win32-g++ {
+# DEFINES += BUILDTIME=\\\"$$system('time/T')\\\"
+# DEFINES += BUILDDATE=\\\"$$system('echo %date%')\\\"
+#}
+#else {
+# DEFINES += BUILDTIME=\\\"$$system(date '+%H:%M.%s')\\\"
+# DEFINES += BUILDDATE=\\\"$$system(date '+%d/%m/%y')\\\"
+#}
+
+QT += core gui webkit
+greaterThan(QT_MAJOR_VERSION, 4) {
+ message("Using QT5")
+ DEFINES += USE_QT5
+ QT += widgets
+ QT += webkitwidgets
+}
+
+HEADERS = \
+ src/QuailAccountBox.h \
+ src/QuailAccountEditor.h \
+ src/QuailAccountsWindow.h \
+ src/QuailAction.h \
+ src/QuailBListWindow.h \
+ src/QuailBuddyList.h \
+ src/QuailConnectionMeter.h \
+ src/QuailConvButton.h \
+ src/QuailConvWindow.h \
+ src/QuailDebugWindow.h \
+ src/QuailEventLoop.h \
+ src/QuailDialogs.h \
+ src/QuailImageUtils.h \
+ src/QuailInputDialog.h \
+ src/QuailMainWindow.h \
+ src/QuailMultiLineEdit.h \
+ src/QuailNotify.h \
+ src/QuailPrefsDialog.h \
+ src/QuailProtocolBox.h \
+ src/QuailProtocolUtils.h \
+ src/QuailRequest.h \
+ src/QuailTabBar.h \
+ src/QuailTabWidget.h \
+ src/global.h \
+ src/QuailConvDisplay.h \
+ src/QuailStatusSelector.h \
+ src/QuailBlistItem.h
+
+
+SOURCES = \
+ src/QuailAccountBox.cpp \
+ src/QuailAccountEditor.cpp \
+ src/QuailAccountsWindow.cpp \
+ src/QuailBListWindow.cpp \
+ src/QuailBuddyList.cpp \
+ src/QuailConnectionMeter.cpp \
+ src/QuailConvButton.cpp \
+ src/QuailConvWindow.cpp \
+ src/QuailDebugWindow.cpp \
+ src/QuailDialogs.cpp \
+ src/QuailEventLoop.cpp \
+ src/QuailImageUtils.cpp \
+ src/QuailInputDialog.cpp \
+ src/QuailMainWindow.cpp \
+ src/QuailMultiLineEdit.cpp \
+ src/QuailNotify.cpp \
+ src/QuailPrefsDialog.cpp \
+ src/QuailProtocolBox.cpp \
+ src/QuailProtocolUtils.cpp \
+ src/QuailRequest.cpp \
+ src/QuailTabBar.cpp \
+ src/QuailTabWidget.cpp \
+ src/main.cpp \
+ src/QuailConvDisplay.cpp \
+ src/QuailStatusSelector.cpp \
+ src/QuailBlistItem.cpp
+
+
+DISTFILES = \
+ AUTHORS \
+ ChangeLog \
+ NEWS \
+ README \
+ quail.png \
+ make.sh \
+ mkstuff.conf \
+ mkipk.sh \
+ mktarball.sh
+
+linux-g++* {
+ message("Using unix")
+ CONFIG += link_pkgconfig
+ PKGCONFIG += purple glib-2.0 gmodule-2.0
+}
+
+win32-g++ {
+ message("Using win32")
+ HEADERS += src/QuailWinGlibEventLoop.h
+ SOURCES += src/QuailWinGlibEventLoop.cpp
+
+ INCLUDEPATH += /cygdrive/c/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0 \
+ /cygdrive/c/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0/include \
+ /cygdrive/c/dev/pidgin-main \
+ c:/dev/pidgin-main \
+ c:/dev/win32-dev/gtk_2_0-2.14/include/glib-2.0 \
+ C:/dev/win32-dev/gtk_2_0-2.14/lib/glib-2.0/include
+
+ LIBS += -L"C:/dev/win32-dev/gtk-2.24.10/lib"
+ LIBS += -L"C:/dev/pidgin-main/libpurple"
+ LIBS += -L"C:/Qt/4.8.5/lib"
+ LIBS += -L"/cygdrive/c/Qt/4.8.5/lib"
+
+ #RC_FILE = resource.rc
+
+ LIBS += -llibpurple -lglib-2.0 -lgmodule-2.0
+}
+
+INCLUDEPATH += $$(LIBPURPLE_ROOT)
+#INCLUDEPATH += $$(QTDIR)
+
+OBJECTS_DIR = obj
+MOC_DIR = moc
+
+RESOURCES += \
+ quail.qrc
+
+OTHER_FILES += \
+ android/AndroidManifest.xml \
+ android/res/layout/splash.xml \
+ android/res/values/libs.xml \
+ android/res/values/strings.xml \
+ android/res/values-de/strings.xml \
+ android/res/values-el/strings.xml \
+ android/res/values-es/strings.xml \
+ android/res/values-et/strings.xml \
+ android/res/values-fa/strings.xml \
+ android/res/values-fr/strings.xml \
+ android/res/values-id/strings.xml \
+ android/res/values-it/strings.xml \
+ android/res/values-ja/strings.xml \
+ android/res/values-ms/strings.xml \
+ android/res/values-nb/strings.xml \
+ android/res/values-nl/strings.xml \
+ android/res/values-pl/strings.xml \
+ android/res/values-pt-rBR/strings.xml \
+ android/res/values-ro/strings.xml \
+ android/res/values-rs/strings.xml \
+ android/res/values-ru/strings.xml \
+ android/res/values-zh-rCN/strings.xml \
+ android/res/values-zh-rTW/strings.xml \
+ android/src/org/kde/necessitas/ministro/IMinistro.aidl \
+ android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \
+ android/src/org/qtproject/qt5/android/bindings/QtActivity.java \
+ android/src/org/qtproject/qt5/android/bindings/QtApplication.java \
+ android/version.xml \
+ TODO.txt
--- a/src/QuailEventLoop.h Thu Sep 05 10:31:00 2013 +0100
+++ b/src/QuailEventLoop.h Fri Sep 13 13:58:43 2013 +0100
@@ -30,6 +30,12 @@
/* http://harmattan-dev.nokia.com/docs/library/html/qt4/qabstracteventdispatcher.html */
#include <QAbstractEventDispatcher>
+struct QuailTimerInfo {
+ int id;
+ int interval;
+ QQuailTimer *quailTimer;
+};
+
class QQuailTimer : public QTimer
{
Q_OBJECT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/QuailWinGlibEventLoop.cpp Fri Sep 13 13:58:43 2013 +0100
@@ -0,0 +1,5 @@
+#include "QuailWinGlibEventLoop.h"
+
+QuailWinGlibEventLoop::QuailWinGlibEventLoop()
+{
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/QuailWinGlibEventLoop.h Fri Sep 13 13:58:43 2013 +0100
@@ -0,0 +1,149 @@
+#ifndef QUAILWINGLIBEVENTLOOP_H
+#define QUAILWINGLIBEVENTLOOP_H
+
+#include "QtCore/qt_windows.h"
+#include <QAbstractEventDispatcher>
+#include <QHash>
+
+typedef struct _GMainContext GMainContext;
+
+class QWinEventNotifier;
+class QuailEventDispatcherWinGlibPrivate;
+
+// forward declaration
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+int qt_msectime();
+
+
+class QuailEventDispatcherWinGlib : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QuailEventDispatcherWinGlib)
+ void createInternalHwnd();
+
+public:
+ explicit QuailEventDispatcherWinGlib(QObject parent = 0);
+ explicit QuailEventDispatcherWinGlib(GMainContext *context, QObject *parent = 0);
+ ~QuailEventDispatcherWinGlib();
+
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ bool registerEventNotifier(QWinEventNotifier *notifier);
+ void unregisterEventNotifier(QWinEventNotifier *notifier);
+ void activateEventNotifiers();
+
+ int remainingTime(int timerId);
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+ bool event(QEvent *e);
+
+ /* Glib */
+ static bool versionSupported();
+
+protected:
+ QEventDispatcherWinGlib(QuailEventDispatcherWinGlibPrivate &dd, QObject *parent = 0);
+ virtual void sendPostedEvents();
+
+private:
+ friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+ friend LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int, WPARAM, LPARAM);
+};
+
+struct GPostEventSource;
+struct GSocketNotifierSource;
+struct GTimerSource;
+struct GIdleTimerSource;
+
+struct QSockNot {
+ QSocketNotifier *obj;
+ int fd;
+};
+typedef QHash<int, QSockNot *> QSNDict;
+
+struct WinTimerInfo { // internal timer info
+ QObject *dispatcher;
+ int timerId;
+ int interval;
+ Qt::TimerType timerType;
+ quint64 timeout; // - when to actually fire
+ QObject *obj; // - object to receive events
+ bool inTimerEvent;
+ int fastTimerId;
+};
+
+class QZeroTimerEvent : public QTimerEvent
+{
+public:
+ explicit inline QZeroTimerEvent(int timerId)
+ : QTimerEvent(timerId)
+ { t = QEvent::ZeroTimerEvent; }
+};
+
+typedef QList<WinTimerInfo*> WinTimerVec; // vector of TimerInfo structs
+typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
+
+class Q_CORE_EXPORT QuailEventDispatcherWinGlibPrivate : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherWinGlib)
+public:
+ QEventDispatcherWinGlibPrivate();
+ QEventDispatcherWinGlibPrivate(GMainContext *context = 0);
+ ~QEventDispatcherWinGlibPrivate();
+
+ GMainContext *mainContext;
+ GPostEventSource *postEventSource;
+ GSocketNotifierSource *socketNotifierSource;
+ GTimerSource *timerSource;
+ GIdleTimerSource *idleTimerSource;
+
+ void runTimersOnceWithNormalPriority();
+
+ DWORD threadId;
+
+ bool interrupt;
+
+ // internal window handle used for socketnotifiers/timers/etc
+ HWND internalHwnd;
+ HHOOK getMessageHook;
+
+ // for controlling when to send posted events
+ QAtomicInt serialNumber;
+ int lastSerialNumber, sendPostedEventsWindowsTimerId;
+ QAtomicInt wakeUps;
+
+ // timers
+ WinTimerVec timerVec;
+ WinTimerDict timerDict;
+ void registerTimer(WinTimerInfo *t);
+ void unregisterTimer(WinTimerInfo *t);
+ void sendTimerEvent(int timerId);
+
+ // socket notifiers
+ QSNDict sn_read;
+ QSNDict sn_write;
+ QSNDict sn_except;
+ void doWsaAsyncSelect(int socket);
+
+ QList<QWinEventNotifier *> winEventNotifierList;
+ void activateEventNotifier(QWinEventNotifier * wen);
+
+ QList<MSG> queuedUserInputEvents;
+ QList<MSG> queuedSocketEvents;
+};
+
+#endif // QUAILWINGLIBEVENTLOOP_H
--- a/src/main.cpp Thu Sep 05 10:31:00 2013 +0100
+++ b/src/main.cpp Fri Sep 13 13:58:43 2013 +0100
@@ -20,14 +20,19 @@
* MA 02111-1307 USA
*/
+#ifdef Q_OS_WIN
#include "QuailEventLoop.h"
+#include "QuailWinGlibEventLoop.h"
+#endif
#include "QuailMainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
- QuailEventLoop quailEventLoop;
+#ifdef Q_OS_WIN
+ QuailWinGlibEventLoop quailEventLoop;
+#endif
QApplication a(argc, argv);
QQuailMainWindow w;
w.show();