[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