[rkward/frameworks] rkward: Move functionality out of RKWardApplication. Somehow it was getting in the way of command line parsing.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Fri Nov 20 09:46:41 UTC 2015
Git commit 81c6f308b703fd90e19cff0b91ba1a2b938c4f19 by Thomas Friedrichsmeier.
Committed on 20/11/2015 at 09:45.
Pushed by tfry into branch 'frameworks'.
Move functionality out of RKWardApplication. Somehow it was getting in the way of command line parsing.
Note that the window-capturing functionality is currently inactive, anyway, as Q_WS_X11 is no longer defined.
M +0 -1 rkward/CMakeLists.txt
M +7 -2 rkward/main.cpp
D +0 -108 rkward/rkwardapplication.cpp
D +0 -62 rkward/rkwardapplication.h
M +55 -11 rkward/windows/rkwindowcatcher.cpp
M +15 -1 rkward/windows/rkwindowcatcher.h
http://commits.kde.org/rkward/81c6f308b703fd90e19cff0b91ba1a2b938c4f19
diff --git a/rkward/CMakeLists.txt b/rkward/CMakeLists.txt
index 9c24f3c..73f1e9c 100644
--- a/rkward/CMakeLists.txt
+++ b/rkward/CMakeLists.txt
@@ -40,7 +40,6 @@ SET(RKWard_Sources
rkglobals.cpp
robjectviewer.cpp
rkconsole.cpp
- rkwardapplication.cpp
)
# somehow the needed libdirs for R do not get passed down automatically
diff --git a/rkward/main.cpp b/rkward/main.cpp
index 26e01f4..6d8f68a 100644
--- a/rkward/main.cpp
+++ b/rkward/main.cpp
@@ -55,6 +55,8 @@
#include <klocale.h>
#include <kstandarddirs.h>
#include <kglobal.h>
+#include <KUrlAuthorized>
+#include <kurl.h>
#include <qstring.h>
#include <QMutex>
@@ -68,7 +70,6 @@
#include "rkward.h"
#include "rkglobals.h"
-#include "rkwardapplication.h"
#include "settings/rksettingsmoduledebug.h"
#include "windows/rkdebugmessagewindow.h"
@@ -129,7 +130,11 @@ int main (int argc, char *argv[]) {
argv_copy[i] = argv[i];
}
- RKWardApplication app (argc, argv_copy);
+ QApplication app (argc, argv_copy);
+ // Don't complain when linking rkward://-pages from Rd pages
+ KUrlAuthorized::allowUrlAction ("redirect", KUrl ("http://"), KUrl ("rkward://"));
+ // Don't complain when trying to open help pages
+ KUrlAuthorized::allowUrlAction ("redirect", KUrl ("rkward://"), KUrl ("help:"));
KAboutData aboutData ("rkward", i18n ("RKWard"), RKWARD_VERSION, i18n ("Frontend to the R statistics language"), KAboutLicense::GPL, i18n ("(c) 2002, 2004 - 2015"), QString (), "http://rkward.kde.org");
aboutData.addAuthor (i18n ("Thomas Friedrichsmeier"), i18n ("Project leader / main developer"));
diff --git a/rkward/rkwardapplication.cpp b/rkward/rkwardapplication.cpp
deleted file mode 100644
index ebf3687..0000000
--- a/rkward/rkwardapplication.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/***************************************************************************
- rkwardapplication - description
- -------------------
- begin : Sun Nov 26 2006
- copyright : (C) 2006, 2007, 2010 by Thomas Friedrichsmeier
- email : thomas.friedrichsmeier at kdemail.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-
-#include "rkwardapplication.h"
-
-#include "windows/rkmdiwindow.h"
-
-#include <KWindowInfo>
-#include <KWindowSystem>
-#include <KUrlAuthorized>
-#include <kurl.h>
-
-#include "debug.h"
-
-//static
-RKWardApplication *RKWardApplication::rkapp = 0;
-
-RKWardApplication::RKWardApplication (int argc, char *argv[]) : QApplication (argc, argv) {
- //RK_TRACE (APP); // would be called before initialization of debug-level
- RK_ASSERT (!rkapp);
-
- // Don't complain when linking rkward://-pages from Rd pages
- KUrlAuthorized::allowUrlAction ("redirect", KUrl ("http://"), KUrl ("rkward://"));
- // Don't complain when trying to open help pages
- KUrlAuthorized::allowUrlAction ("redirect", KUrl ("rkward://"), KUrl ("help:"));
-
- rkapp = this;
-}
-
-RKWardApplication::~RKWardApplication () {
- RK_TRACE (APP);
-}
-
-RKWardApplication *RKWardApplication::getApp () {
- RK_TRACE (APP);
- RK_ASSERT (rkapp == QApplication::instance ());
- return rkapp;
-}
-
-void RKWardApplication::startWindowCreationDetection () {
- RK_TRACE (APP);
-
- created_window = 0;
-
- connect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
-}
-
-WId RKWardApplication::endWindowCreationDetection () {
- RK_TRACE (APP);
-
- if (!created_window) {
- // we did not see the window, yet? Maybe the event simply hasn't been processed, yet.
- processEvents ();
- }
- disconnect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
- return created_window;
-}
-
-void RKWardApplication::windowAdded (WId id) {
- RK_TRACE (APP);
-
- // KF5 TODO: Note: Previously, on windows we checked for IsWindow (hwnd) and IsWindowVisible (hwnd), as sometimes invisible ghost windows
- // would be created in addition to the real device window. Is this still needed?
- created_window = id;
-}
-
-void RKWardApplication::windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2) {
- Q_UNUSED (properties2);
- if (!(properties & NET::WMName)) return;
- RK_TRACE (APP);
- RKMDIWindow *watcher = name_watchers_list.value (id);
- if (!watcher) return;
- watcher->setCaption (KWindowInfo (id, NET::WMName).name ());
-}
-
-void RKWardApplication::registerNameWatcher (WId watched, RKMDIWindow *watcher) {
- RK_TRACE (APP);
- RK_ASSERT (!name_watchers_list.contains (watched));
-
- if (name_watchers_list.isEmpty ()) {
- connect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
- }
- name_watchers_list.insert (watched, watcher);
-}
-
-void RKWardApplication::unregisterNameWatcher (WId watched) {
- RK_TRACE (APP);
- RK_ASSERT (name_watchers_list.contains (watched));
-
- name_watchers_list.remove (watched);
- if (name_watchers_list.isEmpty ()) {
- disconnect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
- }
-}
diff --git a/rkward/rkwardapplication.h b/rkward/rkwardapplication.h
deleted file mode 100644
index 14d09b5..0000000
--- a/rkward/rkwardapplication.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/***************************************************************************
- rkwardapplication - description
- -------------------
- begin : Sun Nov 26 2006
- copyright : (C) 2006, 2009 by Thomas Friedrichsmeier
- email : thomas.friedrichsmeier at kdemail.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-
-#ifndef RKWARDAPPLICATION_H
-#define RKWARDAPPLICATION_H
-
-#include <QApplication>
-#include <netwm_def.h>
-
-#include <qmap.h>
-
-class RKMDIWindow;
-
-/** The purpose of subclassing KApplication as RKWardApplication, is to obtain raw access to X11 events. This is needed to detect the creation of new toplevel windows (R X11 windows), and changed in the caption of those windows.
- *
- * KF5 TODO: This class should no longer be needed, but should be moved to window catcher (if the code that is in it now, works)
-*/
-
-class RKWardApplication : public QApplication {
- Q_OBJECT
-public:
- RKWardApplication (int argc, char *argv[]);
- ~RKWardApplication ();
-
- /** like KApplication::kApplication () (and actually, this should always return the same pointer), but without the need to cast */
- static RKWardApplication *getApp ();
-
- /** start looking for new top-level windows created on the screen */
- void startWindowCreationDetection ();
- /** stop looking for new top-level windows created on the screen
- @returns the window id of the last top-level window created after the last call to startWindowCreation, hoping it was only one. 0 if no window was created/detected. */
- WId endWindowCreationDetection ();
-
- /** watch the given window for changes in its WM_NAME property (i.e. changes in caption). When a change is detected, the caption will be set on watcher. WARNING: Do not use to watch windows managed by Qt! WARNING: Remember to call unregisterNameWatcher, when watcher is deleted! */
- void registerNameWatcher (WId watched, RKMDIWindow *watcher);
- /** remove a watch created with registerNameWatcher */
- void unregisterNameWatcher (WId watched);
-public slots:
- void windowAdded (WId id);
- void windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2);
-private:
- static RKWardApplication *rkapp;
- WId created_window;
-
- QMap<WId, RKMDIWindow*> name_watchers_list;
-};
-
-#endif
diff --git a/rkward/windows/rkwindowcatcher.cpp b/rkward/windows/rkwindowcatcher.cpp
index 2d15236..d748727 100644
--- a/rkward/windows/rkwindowcatcher.cpp
+++ b/rkward/windows/rkwindowcatcher.cpp
@@ -25,16 +25,16 @@
#include <kmessagebox.h>
#include <klocale.h>
-#include <kwindowsystem.h>
+#include <KWindowSystem>
+#include <KWindowInfo>
-#include "../rkwardapplication.h"
#include "../settings/rksettingsmodulegraphics.h"
#include "../dialogs/rkerrordialog.h"
#include "rkworkplace.h"
#include "../misc/rkstandardicons.h"
#include "../debug.h"
-RKWindowCatcher::RKWindowCatcher () {
+RKWindowCatcher::RKWindowCatcher () : QObject () {
RK_TRACE (MISC);
}
@@ -46,25 +46,31 @@ void RKWindowCatcher::start (int prev_cur_device) {
RK_TRACE (MISC);
RK_DEBUG (RBACKEND, DL_DEBUG, "Window Catcher activated");
- RKWardApplication::getApp ()->startWindowCreationDetection ();
last_cur_device = prev_cur_device;
+ created_window = 0;
+ connect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
}
void RKWindowCatcher::stop (int new_cur_device) {
RK_TRACE (MISC);
RK_DEBUG (RBACKEND, DL_DEBUG, "Window Catcher deactivated");
- WId w = RKWardApplication::getApp ()->endWindowCreationDetection ();
+ if (!created_window) {
+ // we did not see the window, yet? Maybe the event simply hasn't been processed, yet.
+ qApp->processEvents ();
+ }
+ disconnect (KWindowSystem::self (), SIGNAL (windowAdded(WId)), this, SLOT (windowAdded(WId)));
+
if (new_cur_device != last_cur_device) {
- if (w) {
- RKWorkplace::mainWorkplace ()->newX11Window (w, new_cur_device);
+ if (created_window) {
+ RKWorkplace::mainWorkplace ()->newX11Window (created_window, new_cur_device);
#if defined Q_WS_X11
// All this syncing looks like a bloody hack? Absolutely. It appears to work around the occasional error "figure margins too large" from R, though.
qApp->processEvents ();
qApp->syncX ();
qApp->processEvents ();
// this appears to have the side-effect of forcing the captured window to sync with X, which is exactly, what we're trying to achieve.
- KWindowInfo wininfo = KWindowSystem::windowInfo (w, NET::WMName | NET::WMGeometry);
+ KWindowInfo wininfo = KWindowSystem::windowInfo (created_window, NET::WMName | NET::WMGeometry);
#endif
} else {
#if defined Q_WS_MAC
@@ -77,6 +83,43 @@ void RKWindowCatcher::stop (int new_cur_device) {
last_cur_device = new_cur_device;
}
+void RKWindowCatcher::windowAdded (WId id) {
+ RK_TRACE (APP);
+
+ // KF5 TODO: Note: Previously, on windows we checked for IsWindow (hwnd) and IsWindowVisible (hwnd), as sometimes invisible ghost windows
+ // would be created in addition to the real device window. Is this still needed?
+ created_window = id;
+}
+
+void RKWindowCatcher::windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2) {
+ Q_UNUSED (properties2);
+ if (!(properties & NET::WMName)) return;
+ RK_TRACE (APP);
+ RKMDIWindow *watcher = name_watchers_list.value (id);
+ if (!watcher) return;
+ watcher->setCaption (KWindowInfo (id, NET::WMName).name ());
+}
+
+void RKWindowCatcher::registerNameWatcher (WId watched, RKMDIWindow *watcher) {
+ RK_TRACE (APP);
+ RK_ASSERT (!name_watchers_list.contains (watched));
+
+ if (name_watchers_list.isEmpty ()) {
+ connect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
+ }
+ name_watchers_list.insert (watched, watcher);
+}
+
+void RKWindowCatcher::unregisterNameWatcher (WId watched) {
+ RK_TRACE (APP);
+ RK_ASSERT (name_watchers_list.contains (watched));
+
+ name_watchers_list.remove (watched);
+ if (name_watchers_list.isEmpty ()) {
+ disconnect (KWindowSystem::self (), SIGNAL (windowChanged(WId,NET::Properties,NET::Properties2)), this, SLOT (windowChanged(WId,NET::Properties,NET::Properties2)));
+ }
+}
+
void RKWindowCatcher::updateHistory (QStringList params) {
RK_TRACE (MISC);
RK_ASSERT (params.count () >= 1);
@@ -119,6 +162,7 @@ void RKWindowCatcher::killDevice (int device_number) {
#elif defined Q_WS_X11
# include <QX11EmbedContainer>
#endif
+#warning TODO: Q_WS_X11 is simply no longer defined. Adjust this functionality.
#include <QTimer>
#include <QCloseEvent>
@@ -247,7 +291,7 @@ void RKCaughtX11Window::doEmbed () {
capture->embedClient (embedded);
connect (capture, SIGNAL (clientClosed()), this, SLOT (deleteLater()));
- RKWardApplication::getApp ()->registerNameWatcher (embedded, this);
+ RKWindowCatcher::registerNameWatcher (embedded, this);
#endif
}
// make xembed_container resizable, again, now that it actually has a content
@@ -269,7 +313,7 @@ RKCaughtX11Window::~RKCaughtX11Window () {
close (false);
#ifdef Q_WS_X11
- if (embedded) RKWardApplication::getApp ()->unregisterNameWatcher (embedded);
+ if (embedded) RKWindowCatcher::unregisterNameWatcher (embedded);
#endif
error_dialog->autoDeleteWhenDone ();
delete status_popup;
@@ -322,7 +366,7 @@ void RKCaughtX11Window::reEmbed () {
// somehow, since some version of Qt, the QX11EmbedContainer would loose its client while reparenting. This allows us to circumvent the problem.
capture->discardClient ();
capture->deleteLater ();
- RKWardApplication::getApp ()->unregisterNameWatcher (embedded);
+ RKWindowCatcher::unregisterNameWatcher (embedded);
QTimer::singleShot (0, this, SLOT(doEmbed()));
#endif
}
diff --git a/rkward/windows/rkwindowcatcher.h b/rkward/windows/rkwindowcatcher.h
index 12fa94d..9ce9e0a 100644
--- a/rkward/windows/rkwindowcatcher.h
+++ b/rkward/windows/rkwindowcatcher.h
@@ -22,6 +22,10 @@
#ifndef DISABLE_RKWINDOWCATCHER
#include <qwidget.h>
+#include <QMap>
+
+#include <netwm_def.h>
+class RKMDIWindow;
/** This is a simple helper class helping in catching R X11 device windows. The start () and stop () functions are called from RInterface, and then this class takes care of handling those.
@@ -55,7 +59,8 @@ Catch R X11 device windows
@author Thomas Friedrichsmeier
*/
-class RKWindowCatcher {
+class RKWindowCatcher : public QObject {
+ Q_OBJECT
public:
/** ctor. Probably you'll only ever need one instance of RKWindowCatcher. */
RKWindowCatcher ();
@@ -74,8 +79,17 @@ public:
/** Kill an R device
@param device_number R device number of the device to kil */
void killDevice (int device_number);
+ /** watch the given window for changes in its WM_NAME property (i.e. changes in caption). When a change is detected, the caption will be set on watcher. WARNING: Do not use to watch windows managed by Qt! WARNING: Remember to call unregisterNameWatcher, when watcher is deleted! */
+ void registerNameWatcher (WId watched, RKMDIWindow *watcher);
+ /** remove a watch created with registerNameWatcher */
+ void unregisterNameWatcher (WId watched);
+private slots:
+ void windowAdded (WId id);
+ void windowChanged (WId id, NET::Properties properties, NET::Properties2 properties2);
private:
int last_cur_device;
+ WId created_window;
+ QMap<WId, RKMDIWindow*> name_watchers_list;
};
More information about the rkward-tracker
mailing list