[rkward/work/kf5_fix_device_embedding] rkward: Device embedding on X11 seems to be reliable, now, with not-too-much sleeping involved.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Mon Feb 15 09:50:59 UTC 2016
Git commit 7f88ab2d8837119d4167dfff8422ed2bd07c6b17 by Thomas Friedrichsmeier.
Committed on 15/02/2016 at 09:49.
Pushed by tfry into branch 'work/kf5_fix_device_embedding'.
Device embedding on X11 seems to be reliable, now, with not-too-much sleeping involved.
M +7 -0 rkward/rbackend/rpackages/rkward/R/public_graphics.R
M +12 -14 rkward/windows/rkwindowcatcher.cpp
M +1 -0 rkward/windows/rkwindowcatcher.h
http://commits.kde.org/rkward/7f88ab2d8837119d4167dfff8422ed2bd07c6b17
diff --git a/rkward/rbackend/rpackages/rkward/R/public_graphics.R b/rkward/rbackend/rpackages/rkward/R/public_graphics.R
index 3775d75..d62eced 100644
--- a/rkward/rbackend/rpackages/rkward/R/public_graphics.R
+++ b/rkward/rbackend/rpackages/rkward/R/public_graphics.R
@@ -154,8 +154,15 @@
oldd <- dev.cur ()
.rk.do.call ("startOpenX11", as.character (oldd));
on.exit (.rk.do.call ("endOpenX11", as.character (dev.cur())));
+ on.exit ({ # This serves to make R do all necessary X11 event processing, _while_ we are in the process of embedding the device in the frontend.
+ for (i in 1:10) {
+ if (.rk.variables$devembedded) break
+ Sys.sleep (.1)
+ }}, add=TRUE);
+ .rk.variables$devembedded <- FALSE
x <- eval.parent (expr)
+ Sys.sleep (.1) # This serves to make R do initial X11 event processing _before_ we try to embed the device in the frontend.
if (oldd != dev.cur ()) on.exit (rk.record.plot$onAddDevice (), add=TRUE)
else warning ("No device appears to have been created (dev.cur() has not changed)");
diff --git a/rkward/windows/rkwindowcatcher.cpp b/rkward/windows/rkwindowcatcher.cpp
index 978ab5d..03bf1cf 100644
--- a/rkward/windows/rkwindowcatcher.cpp
+++ b/rkward/windows/rkwindowcatcher.cpp
@@ -77,15 +77,10 @@ void RKWindowCatcher::stop (int new_cur_device) {
if (new_cur_device != last_cur_device) {
if (created_window) {
- qDebug ("using %x", created_window);
- //qApp->sync ();
// 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 (created_window, NET::WMName | NET::WMGeometry);
QWindow *window = QWindow::fromWinId (created_window);
RKWorkplace::mainWorkplace ()->newX11Window (window, new_cur_device);
- // 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->processEvents ();
} else {
#if defined Q_OS_MAC
KMessageBox::information (0, i18n ("You have tried to embed a new R graphics device window in RKWard. However, this is not currently supported in this build of RKWard on Mac OS X. See http://rkward.kde.org/mac for more information."), i18n ("Could not embed R X11 window"), "embed_x11_device_not_supported");
@@ -215,11 +210,8 @@ RKCaughtX11Window::RKCaughtX11Window (QWindow* window_to_embed, int device_numbe
RK_ASSERT (false);
#endif
- // KF5 TODO: Still needed?
- // somehow in Qt 4.4.3, when the RKCaughtWindow is reparented the first time, the QX11EmbedContainer may kill its client. Hence we delay the actual embedding until after the window was shown.
- // In some previous version of Qt, this was not an issue, but I did not track the versions.
- QTimer::singleShot (2000, this, SLOT (doEmbed()));
- //doEmbed ();
+ // We need to make sure that the R backend has had a chance to do event processing on the new device, or else embedding will fail (sometimes).
+ QTimer::singleShot (100, this, SLOT (doEmbed()));
}
RKCaughtX11Window::RKCaughtX11Window (RKGraphicsDevice* rkward_device, int device_number) : RKMDIWindow (0, X11Window) {
@@ -245,6 +237,7 @@ void RKCaughtX11Window::commonInit (int device_number) {
capture = 0;
embedded = 0;
+ embedding_complete = false;
rk_native_device = 0;
killed_in_r = close_attempted = false;
RKCaughtX11Window::device_number = device_number;
@@ -279,7 +272,7 @@ void RKCaughtX11Window::doEmbed () {
RK_TRACE (MISC);
if (embedded) {
-/* if (capture) {
+/* if (capture) { // Old re-embedding code, moved here. No longer needed?
embedded->setParent (0);
capture->deleteLater ();
} */
@@ -287,8 +280,8 @@ void RKCaughtX11Window::doEmbed () {
KWindowInfo wininfo = KWindowSystem::windowInfo (embedded->winId (), NET::WMName | NET::WMGeometry);
capture = QWidget::createWindowContainer (embedded, xembed_container);
xembed_container->layout ()->addWidget (capture);
- QTimer::singleShot (100, xembed_container, SLOT (show ()));
- // KF5 TODO: Will this detect closed device, correclty? No, will probably need assistance from KWindowSystem.
+ xembed_container->show ();
+ // KF5 TODO: Will this detect closed device, correctly? No, will probably need assistance from KWindowSystem.
connect (embedded, &QObject::destroyed, this, &RKCaughtX11Window::deleteLater);
// KF5 TODO: Window caption?
}
@@ -296,7 +289,7 @@ void RKCaughtX11Window::doEmbed () {
if (!isAttached ()) {
// make xembed_container resizable, again, now that it actually has a content
dynamic_size_action->setChecked (true);
- QTimer::singleShot (1000, this, SLOT (fixedSizeToggled ()));
+ QTimer::singleShot (0, this, SLOT (fixedSizeToggled ())); // For whatever reason, apparently we have to wait for the next event loop with this.
}
// try to be helpful when the window is too large to fit on screen
@@ -423,6 +416,11 @@ void RKCaughtX11Window::fixedSizeToggled () {
scroll_widget->setWidget (xembed_container);
scroll_widget->show ();
}
+
+ if (embedded && !embedding_complete) {
+ embedding_complete = true;
+ RKGlobals::rInterface ()->issueCommand ("assign ('devembedded', TRUE, rkward:::.rk.variables)", RCommand::App | RCommand::Sync | RCommand::PriorityCommand);
+ }
}
void RKCaughtX11Window::setFixedSize1 () {
diff --git a/rkward/windows/rkwindowcatcher.h b/rkward/windows/rkwindowcatcher.h
index 32f6ccd..53cc888 100644
--- a/rkward/windows/rkwindowcatcher.h
+++ b/rkward/windows/rkwindowcatcher.h
@@ -184,6 +184,7 @@ private:
static QHash<int, RKCaughtX11Window*> device_windows;
QWindow *embedded;
+ bool embedding_complete;
QWidget *capture; // The captured window (0, if using an rk native device)
RKGraphicsDevice *rk_native_device;
More information about the rkward-tracker
mailing list