[education/rkward] /: Fix some synchronization bugs around closing devices.
Thomas Friedrichsmeier
null at kde.org
Sat Mar 19 21:57:45 GMT 2022
Git commit 9d8ed3bb51643d80afff5e7cc669007a077a1e1f by Thomas Friedrichsmeier.
Committed on 19/03/2022 at 21:57.
Pushed by tfry into branch 'master'.
Fix some synchronization bugs around closing devices.
M +2 -1 ChangeLog
M +1 -1 VERSION.cmake
M +2 -2 rkward/rbackend/rkrbackend.cpp
M +7 -3 rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
M +3 -2 rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
M +17 -6 rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
M +2 -2 rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
M +10 -6 rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
M +92 -29 rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
M +1 -1 rkward/rbackend/rpackages/rkward/DESCRIPTION
M +4 -2 rkward/rbackend/rpackages/rkward/R/internal_graphics.R
M +1 -1 rkward/windows/rkwindowcatcher.cpp
https://invent.kde.org/education/rkward/commit/9d8ed3bb51643d80afff5e7cc669007a077a1e1f
diff --git a/ChangeLog b/ChangeLog
index 023df0e8..25e031a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,11 @@
TODO:
-- RKDClose needs to be synchronous to avoid race-condition while closing device
+- Fix initial graphics window size
TODOS for autotests:
- Check and update the standards files
- Use options(warn=1), in order to get warnings into the test?
+- Fix some buglets around closing on-screen devices
- Implement new R graphics functions: gradients, patterns, clip paths
- Add icons to settings dialog for quick visual orientation
- Merge ktexteditor (script) settings into the main settings dialog
diff --git a/VERSION.cmake b/VERSION.cmake
index 7e7d01ee..adb07cee 100644
--- a/VERSION.cmake
+++ b/VERSION.cmake
@@ -1,3 +1,3 @@
# DO NOT CHANGE THIS FILE MANUALLY!
# It will be overwritten by scripts/set_dist_version.sh
-SET(RKVERSION_NUMBER 0.7.2z+0.7.3+devel2)
+SET(RKVERSION_NUMBER 0.7.2z+0.7.3+devel4)
diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index f27968ea..4fd5fefb 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -1067,7 +1067,7 @@ SEXP doCaptureOutput (SEXP mode, SEXP capture_messages, SEXP capture_output, SEX
}
SEXP RKStartGraphicsDevice (SEXP width, SEXP height, SEXP pointsize, SEXP family, SEXP bg, SEXP title, SEXP antialias);
-SEXP RKD_AdjustSize (SEXP devnum);
+SEXP RKD_AdjustSize (SEXP devnum, SEXP id);
SEXP doWs (SEXP name);
void doPendingPriorityCommands ();
@@ -1157,7 +1157,7 @@ bool RKRBackend::startR () {
{ "rk.update.locale", (DL_FUNC) (void*) &doUpdateLocale, 0 },
{ "rk.capture.output", (DL_FUNC) (void*) &doCaptureOutput, 5 },
{ "rk.graphics.device", (DL_FUNC) (void*) &RKStartGraphicsDevice, 7},
- { "rk.graphics.device.resize", (DL_FUNC) (void*) &RKD_AdjustSize, 1},
+ { "rk.graphics.device.resize", (DL_FUNC) (void*) &RKD_AdjustSize, 2},
{ 0, 0, 0 }
};
R_registerRoutines (R_getEmbeddingDllInfo(), NULL, callMethods, NULL, NULL);
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
index c0b59e1f..9ed62900 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
@@ -50,6 +50,7 @@ RKGraphicsDevice::RKGraphicsDevice (double width, double height, const QString &
interaction_opcode = -1;
dialog = 0;
+ id = 0;
recording_path = false;
view = new QLabel ();
view->installEventFilter (this);
@@ -163,7 +164,7 @@ int RKGraphicsDevice::finalizeTilingPattern(int extend) {
void RKGraphicsDevice::viewKilled () {
RK_TRACE (GRAPHICS_DEVICE);
view = 0;
- closeDevice (devices.key (this));
+// closeDevice(devices.key(this)); // Do not do this, here. Don't mark the device as dead until R thinks so, too, and tells us about it.
}
void RKGraphicsDevice::triggerUpdate () {
@@ -204,12 +205,13 @@ void RKGraphicsDevice::forceSync() {
void RKGraphicsDevice::checkSize() {
RK_TRACE (GRAPHICS_DEVICE);
+ if(!view) return;
if (view->size () != area.size ()) {
- RKGlobals::rInterface ()->issueCommand (new RCommand ("rkward:::RK.resize (" + QString::number (devices.key (this) + 1) + ')', RCommand::PriorityCommand));
+ RKGlobals::rInterface()->issueCommand(new RCommand ("rkward:::RK.resize(" + QString::number(devices.key(this) + 1) + ',' + QString::number(id) + ')', RCommand::PriorityCommand));
}
}
-RKGraphicsDevice* RKGraphicsDevice::newDevice (int devnum, double width, double height, const QString &title, bool antialias) {
+RKGraphicsDevice* RKGraphicsDevice::newDevice (int devnum, double width, double height, const QString &title, bool antialias, quint32 id) {
RK_TRACE (GRAPHICS_DEVICE);
if (devices.contains (devnum)) {
@@ -217,6 +219,7 @@ RKGraphicsDevice* RKGraphicsDevice::newDevice (int devnum, double width, double
closeDevice (devnum);
}
RKGraphicsDevice* dev = new RKGraphicsDevice (width, height, title.isEmpty () ? i18n ("Graphics Device Number %1", QString::number (devnum+1)) : title, antialias);
+ dev->id = id;
devices.insert (devnum, dev);
return (dev);
}
@@ -479,6 +482,7 @@ QImage RKGraphicsDevice::capture () const {
void RKGraphicsDevice::setActive (bool active) {
RK_TRACE (GRAPHICS_DEVICE);
+ if (!view) return;
if (active) view->setWindowTitle (i18nc ("Window title", "%1 (Active)", base_title));
else view->setWindowTitle (i18nc ("Window title", "%1 (Inactive)", base_title));
emit (activeChanged (active));
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
index 4ebbc72a..0b9650b5 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
@@ -51,7 +51,7 @@ protected:
RKGraphicsDevice (double width, double height, const QString &title, bool antialias);
~RKGraphicsDevice ();
public:
- static RKGraphicsDevice* newDevice (int devnum, double width, double height, const QString &title, bool antialias);
+ static RKGraphicsDevice* newDevice (int devnum, double width, double height, const QString &title, bool antialias, quint32 id);
static void closeDevice (int devnum);
static QHash<int, RKGraphicsDevice*> devices;
@@ -89,7 +89,7 @@ public:
void stopGettingEvents ();
QWidget* viewPort () const { return view; };
- QSizeF currentSize () const { return view->size (); }
+ QSizeF currentSize () const { return view ? view->size() : QSizeF(); }
void setAreaSize (const QSize &size);
/** Patterns / gradients are registered per device in R */
@@ -139,6 +139,7 @@ private:
bool recording_path;
int interaction_opcode; /**< Current interactive operation (from RKDOpcodes enum), or -1 is there is no current interactive operation */
+ quint32 id;
QList<StoredEvent> stored_events;
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
index 72c0163e..fa20803f 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
@@ -245,8 +245,9 @@ void RKGraphicsDeviceFrontendTransmitter::newData () {
double width, height;
QString title;
bool antialias;
- streamer.instream >> width >> height >> title >> antialias;
- device = RKGraphicsDevice::newDevice (devnum, width, height, title, antialias);
+ quint32 id;
+ streamer.instream >> width >> height >> title >> antialias >> id;
+ device = RKGraphicsDevice::newDevice (devnum, width, height, title, antialias, id);
RKWorkplace::mainWorkplace ()->newRKWardGraphisWindow (device, devnum+1);
connect (device, &RKGraphicsDevice::locatorDone, this, &RKGraphicsDeviceFrontendTransmitter::locatorDone);
connect (device, &RKGraphicsDevice::newPageConfirmDone, this, &RKGraphicsDeviceFrontendTransmitter::newPageConfirmDone);
@@ -331,7 +332,8 @@ void RKGraphicsDeviceFrontendTransmitter::newData () {
} else if (opcode == RKDNewPage) {
device->clear(readBrush(streamer.instream, device));
} else if (opcode == RKDClose) {
- RKGraphicsDevice::closeDevice (devnum);
+ RKGraphicsDevice::closeDevice(devnum);
+ sendDummyReply(devnum);
} else if (opcode == RKDActivate) {
device->setActive (true);
} else if (opcode == RKDDeActivate) {
@@ -378,7 +380,7 @@ void RKGraphicsDeviceFrontendTransmitter::newData () {
} else if (opcode == RKDSetClipPath) {
qint32 index;
streamer.instream >> index;
- bool ok = device->setClipToCachedPath(index);
+ qint8 ok = device->setClipToCachedPath(index) ? 1 : 0;
streamer.outstream << ok;
streamer.writeOutBuffer();
} else if (opcode == RKDReleaseClipPath) {
@@ -442,8 +444,7 @@ void RKGraphicsDeviceFrontendTransmitter::newData () {
device->confirmNewPage ();
} else if (opcode == RKDForceSync) {
device->forceSync();
- streamer.outstream << (qint8) 0;
- streamer.writeOutBuffer();
+ sendDummyReply(devnum);
} else {
RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skipping.", opcode, devnum+1);
}
@@ -472,10 +473,20 @@ void RKGraphicsDeviceFrontendTransmitter::sendDummyReply (quint8 opcode) {
} else if (opcode == RKDStrWidthUTF8) {
double width = 1;
streamer.outstream << width;
+ } else if (opcode == RKDCapture) {
+ streamer.outstream << (quint32) 0 << (quint32) 0;
+// } else if (opcode == RKDQueryResolution) {
+// streamer.outstream << (qint32) 0;
} else if (opcode == RKDGetSize) {
streamer.outstream << QSizeF ();
+ } else if (opcode == RKDSetPattern || opcode == RKDEndRecordTilingPattern || opcode == RKDEndRecordClipPath) {
+ streamer.outstream << (qint32) -1;
+ } else if (opcode == RKDSetClipPath) {
+ streamer.outstream << (qint32) 0;
} else if (opcode == RKDFetchNextEvent) {
streamer.outstream << (qint8) RKDNothing;
+ } else if (opcode == RKDClose || opcode == RKDForceSync) {
+ streamer.outstream << (qint8) RKDNothing;
} else {
return; // nothing to write
}
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
index afadb26f..12daa58d 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
@@ -96,14 +96,13 @@ enum RKDOpcodes {
RKDRect,
RKDTextUTF8,
RKDNewPage,
- RKDClose,
+ RKDStartGettingEvents,
RKDActivate, // 10
RKDDeActivate,
RKDClip,
RKDMode,
RKDRaster,
RKDSetSize, // 15
- RKDStartGettingEvents,
RKDStopGettingEvents,
RKDReleasePattern,
RKDStartRecordTilingPattern, // part of setPattern in R
@@ -124,6 +123,7 @@ enum RKDOpcodes {
RKDSetClipPath, // 110
RKDEndRecordClipPath,
RKDForceSync,
+ RKDClose,
// Protocol operations
RKDCancel = 200
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
index da9e47a0..a91f8127 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
@@ -44,6 +44,7 @@
struct RKGraphicsDeviceDesc {
bool init (pDevDesc dev, double pointsize, const QStringList &family, rcolor bg);
int devnum;
+ quint32 id;
double width, height;
int dpix, dpiy;
QString getFontFamily (bool symbolfont) const {
@@ -66,6 +67,7 @@ struct RKGraphicsDeviceDesc {
#define RKGD_DPI 72.0
void RKStartGraphicsDevice (double width, double height, double pointsize, const QStringList &family, rcolor bg, const char* title, bool antialias) {
+ static quint32 id = 0;
if (width <= 0 || height <= 0) {
Rf_error ("Invalid width or height: (%g, %g)", width, height);
}
@@ -89,12 +91,14 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
delete (desc);
desc = 0;
} else {
- desc->devnum = 0; // graphics engine will send an Activate-event, before we were even
- // able to see our own devnum and call RKD_Create. Therefore, initialize
- // devnum to 0, so as not to confuse the frontend
- pGEDevDesc gdd = GEcreateDevDesc (dev);
+ desc->devnum = 0; // graphics engine will send an Activate-event, before we were even
+ // able to see our own devnum and call RKD_Create. Therefore, initialize
+ // devnum to 0, so as not to confuse the frontend
+ desc->id = id++; // extra identifier to make sure, R and the frontend are really talking about the same device
+ // in case of potentially out-of-sync operations (notably RKDADjustSize)
+ pGEDevDesc gdd = GEcreateDevDesc(dev);
gdd->displayList = R_NilValue;
- GEaddDevice2 (gdd, "RKGraphicsDevice");
+ GEaddDevice2(gdd, "RKGraphicsDevice");
#ifdef _MSC_VER
// See RKD_Close()
desc->rgdevdesc = gdd;
@@ -104,7 +108,7 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
if (desc) {
desc->devnum = curDevice ();
- RKD_Create (desc->width, desc->height, dev, title, antialias);
+ RKD_Create (desc->width, desc->height, dev, title, antialias, desc->id);
} else {
Rf_error("unable to start device");
}
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index f82b5d87..a537abaa 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -2,7 +2,7 @@
rkgraphicsdevice_stubs - description
-------------------
begin : Mon Mar 18 20:06:08 CET 2013
- copyright : (C) 2013-2021 by Thomas Friedrichsmeier
+ copyright : (C) 2013-2022 by Thomas Friedrichsmeier
email : thomas.friedrichsmeier at kdemail.net
***************************************************************************/
@@ -25,6 +25,22 @@
#include "../rkreventloop.h"
#include "../../debug.h"
+#undef RK_TRACE
+#define RK_TRACE(flags)
+/*
+#define RK_TRACE(flags) RKFullTrace _rk_full_trace(__FILE__, __FUNCTION__, __LINE__);
+class RKFullTrace {
+public:
+ RKFullTrace(char *file, const char *function, int line) : _function(function){
+ qDebug("Trace enter: %s - function %s line %d", file, _function, line);
+ };
+ ~RKFullTrace() {
+ qDebug("Trace leave: function %s", _function);
+ };
+ const char *_function;
+}; */
+
+
#include <R_ext/GraphicsEngine.h>
#define RKD_IN_STREAM RKGraphicsDeviceBackendTransmitter::streamer.instream
@@ -177,6 +193,7 @@ public:
RKD_OUT_STREAM << gc->cex << gc->ps << gc->lineheight << (quint8) gc->fontface << (gc->fontfamily[0] ? QString (gc->fontfamily) : (static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->getFontFamily (gc->fontface == 5)))
static void RKD_QueryResolution (int *dpix, int *dpiy) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER_NUM (RKDQueryResolution, 0);
@@ -189,11 +206,12 @@ static void RKD_QueryResolution (int *dpix, int *dpiy) {
}
}
-static void RKD_Create (double width, double height, pDevDesc dev, const char *title, bool antialias) {
+static void RKD_Create (double width, double height, pDevDesc dev, const char *title, bool antialias, quint32 id) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDCreate, dev);
- RKD_OUT_STREAM << width << height << QString::fromUtf8 (title) << antialias;
+ RKD_OUT_STREAM << width << height << QString::fromUtf8 (title) << antialias << id;
}
{
// Reading a reply in order to force this to be synchronous. .rk.with.placement.hint() may run into race conditions, otherwise.
@@ -204,6 +222,7 @@ static void RKD_Create (double width, double height, pDevDesc dev, const char *t
}
static void RKD_Size (double *left, double *right, double *top, double *bottom, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
// NOTE: This does *not* query the frontend for the current size. This is only done on request
*left = dev->left;
*top = dev->top;
@@ -212,36 +231,57 @@ static void RKD_Size (double *left, double *right, double *top, double *bottom,
}
static void RKD_SetSize (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER (RKDSetSize, dev);
RKD_OUT_STREAM << QSize (qAbs (dev->right - dev->left) + .2, qAbs (dev->bottom - dev->top) + .2);
}
-SEXP RKD_AdjustSize (SEXP _devnum) {
- int devnum = Rf_asInteger (_devnum);
- pGEDevDesc gdev = GEgetDevice (devnum);
- if (!gdev) Rf_error ("No such device %d", devnum);
+static void RKD_Activate (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
+ RKGraphicsDataStreamWriteGuard guard;
+ WRITE_HEADER (RKDActivate, dev);
+}
+
+static void RKD_Deactivate (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
+ RKGraphicsDataStreamWriteGuard guard;
+ WRITE_HEADER (RKDDeActivate, dev);
+}
+
+SEXP RKD_AdjustSize(SEXP _devnum, SEXP _id) {
+ RK_TRACE(GRAPHICS_DEVICE);
+ int devnum = Rf_asInteger(_devnum);
+ quint32 id = Rf_asInteger(_id);
+ pGEDevDesc gdev = GEgetDevice(devnum);
+ if (!gdev) Rf_error("No such device %d", devnum);
pDevDesc dev = gdev->dev;
+ // This is called from rkward:::RK.resize(), which in turn may be out of sync with R's device list. Before doing anything,
+ // double check that this is really the device we think it is.
+ if (dev->activate != RKD_Activate) Rf_error("Not an RKWard device", devnum);
+ if (static_cast<RKGraphicsDeviceDesc*>(dev->deviceSpecific)->id != id) Rf_error("Graphics device mismatch", devnum);
+
{
RKGraphicsDataStreamWriteGuard wguard;
- WRITE_HEADER (RKDGetSize, dev);
+ WRITE_HEADER(RKDGetSize, dev);
}
QSizeF size;
{
RKGraphicsDataStreamReadGuard rguard;
RKD_IN_STREAM >> size;
}
- if (size.isNull ()) Rf_error ("Could not determine current size of device %d. Not an RK device?", devnum);
+ if (size.isNull()) Rf_error("Could not determine current size of device %d. Device closed?", devnum);
dev->left = dev->top = 0;
- dev->right = size.width ();
- dev->bottom = size.height ();
+ dev->right = size.width();
+ dev->bottom = size.height();
- RKD_SetSize (dev); // This adjusts the rendering area in the frontend
- GEplayDisplayList (gdev);
+ RKD_SetSize(dev); // This adjusts the rendering area in the frontend
+ if(gdev->dirty) GEplayDisplayList(gdev);
return R_NilValue;
}
static void RKD_Circle (double x, double y, double r, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDCircle, dev);
RKD_OUT_STREAM << x << y << r;
@@ -250,6 +290,7 @@ static void RKD_Circle (double x, double y, double r, R_GE_gcontext *gc, pDevDes
}
static void RKD_Line (double x1, double y1, double x2, double y2, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDLine, dev);
RKD_OUT_STREAM << x1 << y1 << x2 << y2;
@@ -258,6 +299,7 @@ static void RKD_Line (double x1, double y1, double x2, double y2, R_GE_gcontext
}
static void RKD_Polygon (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDPolygon, dev);
quint32 _n = qMin (n, 1 << 25); // skip stuff exceeding reasonable limits to keep protocol simple
@@ -271,6 +313,7 @@ static void RKD_Polygon (int n, double *x, double *y, R_GE_gcontext *gc, pDevDes
}
static void RKD_Polyline (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDPolyline, dev);
quint32 _n = qMin (n, 1 << 25); // skip stuff exceeding reasonable limits to keep protocol simple
@@ -283,6 +326,7 @@ static void RKD_Polyline (int n, double *x, double *y, R_GE_gcontext *gc, pDevDe
}
static void RKD_Path (double *x, double *y, int npoly, int *nper, Rboolean winding, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDPath, dev);
quint32 total_points = 0;
@@ -303,6 +347,7 @@ static void RKD_Path (double *x, double *y, int npoly, int *nper, Rboolean windi
}
static void RKD_Rect (double x0, double y0, double x1, double y1, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDRect, dev);
RKD_OUT_STREAM << QRectF (x0, y0, x1-x0, y1-y0);
@@ -312,6 +357,7 @@ static void RKD_Rect (double x0, double y0, double x1, double y1, R_GE_gcontext
}
static void RKD_TextUTF8 (double x, double y, const char *str, double rot, double hadj, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDTextUTF8, dev);
RKD_OUT_STREAM << x << y << QString::fromUtf8 (str) << rot << hadj; // NOTE: yes, even Symbols are sent as UTF-8, here.
@@ -320,6 +366,7 @@ static void RKD_TextUTF8 (double x, double y, const char *str, double rot, doubl
}
static double RKD_StrWidthUTF8 (const char *str, R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDStrWidthUTF8, dev);
@@ -335,12 +382,14 @@ static double RKD_StrWidthUTF8 (const char *str, R_GE_gcontext *gc, pDevDesc dev
}
static void RKD_NewPage (R_GE_gcontext *gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDNewPage, dev);
WRITE_FILL ();
}
static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* descent, double* width, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER (RKDMetricInfo, dev);
@@ -363,8 +412,10 @@ static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* de
}
static void RKD_Close (pDevDesc dev) {
- RKGraphicsDataStreamWriteGuard guard;
- WRITE_HEADER (RKDClose, dev);
+ RK_TRACE(GRAPHICS_DEVICE);
+ {
+ RKGraphicsDataStreamWriteGuard guard;
+ WRITE_HEADER (RKDClose, dev);
#ifdef _MSC_VER
// Ok, this is a terribly crude HACK, obviously, and it's just waiting to come back to bite us. However:
// We had to allocate the DevDesc in our own (MSVC-compiled) code (that's the way it is done), but if we allow R to delete
@@ -374,23 +425,20 @@ static void RKD_Close (pDevDesc dev) {
// If (or when) this breaks, we could try to just call some other device's init-routine, then hijack that device. Or out-source
// the RKGraphicsDevice backend init code into an R package...
// Or can we use R's Calloc/Malloc, instead? -> Manual caution not to use free() (only Free()), on that, though.
- static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->rgdevdesc->dev = NULL;
+ static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->rgdevdesc->dev = NULL;
free (dev);
#endif
- delete static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific);
-}
-
-static void RKD_Activate (pDevDesc dev) {
- RKGraphicsDataStreamWriteGuard guard;
- WRITE_HEADER (RKDActivate, dev);
-}
-
-static void RKD_Deactivate (pDevDesc dev) {
- RKGraphicsDataStreamWriteGuard guard;
- WRITE_HEADER (RKDDeActivate, dev);
+ delete static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific);
+ }
+ {
+ RKGraphicsDataStreamWriteGuard rguard;
+ qint8 dummy;
+ RKD_IN_STREAM >> dummy;
+ }
}
static void RKD_Clip (double left, double right, double top, double bottom, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
dev->clipLeft = left;
dev->clipRight = right;
dev->clipTop = top;
@@ -401,6 +449,7 @@ static void RKD_Clip (double left, double right, double top, double bottom, pDev
}
static void RKD_Mode (int mode, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
Q_UNUSED (mode);
Q_UNUSED (dev);
/* Left empty for now. 1 is start signal, 0 is stop signal. Might be useful for flushing, though.
@@ -411,6 +460,7 @@ static void RKD_Mode (int mode, pDevDesc dev) {
}
static void RKD_Raster (unsigned int *raster, int w, int h, double x, double y, double width, double height, double rot, Rboolean interpolate, const pGEcontext gc, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
Q_UNUSED (gc);
RKGraphicsDataStreamWriteGuard wguard;
@@ -430,6 +480,7 @@ static void RKD_Raster (unsigned int *raster, int w, int h, double x, double y,
}
static SEXP RKD_Capture (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER (RKDCapture, dev);
@@ -471,6 +522,7 @@ static SEXP RKD_Capture (pDevDesc dev) {
}
static Rboolean RKD_Locator (double *x, double *y, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER (RKDLocator, dev);
@@ -485,6 +537,7 @@ static Rboolean RKD_Locator (double *x, double *y, pDevDesc dev) {
}
static Rboolean RKD_NewFrameConfirm (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER (RKDNewPageConfirm, dev);
@@ -501,6 +554,7 @@ static Rboolean RKD_NewFrameConfirm (pDevDesc dev) {
#if R_VERSION >= R_Version (2, 12, 0)
void RKD_EventHelper (pDevDesc dev, int code) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
if (code == 1) {
@@ -576,6 +630,7 @@ void RKD_EventHelper (pDevDesc dev, int code) {
}
void RKD_onExit (pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
if (rkd_suppress_on_exit > 0) {
--rkd_suppress_on_exit;
return;
@@ -590,6 +645,7 @@ void RKD_onExit (pDevDesc dev) {
#if R_VERSION >= R_Version (2, 14, 0)
int RKD_HoldFlush (pDevDesc dev, int level) {
+ RK_TRACE(GRAPHICS_DEVICE);
#ifdef __GNUC__
#warning implement me
#endif
@@ -614,7 +670,8 @@ SEXP makeInt(int val) {
}
void forceSync(pDevDesc dev) {
-// NOTE: See commen7 in RKGraphicsDevice::forceSync();
+ RK_TRACE(GRAPHICS_DEVICE);
+// NOTE: See comment in RKGraphicsDevice::forceSync();
// KF6 TODO: Still neded with Qt6?
{
RKGraphicsDataStreamWriteGuard wguard;
@@ -628,6 +685,7 @@ void forceSync(pDevDesc dev) {
}
SEXP RKD_SetPattern (SEXP pattern, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
auto ptype = R_GE_patternType(pattern);
if ((ptype == R_GE_linearGradientPattern) || (ptype == R_GE_radialGradientPattern)) {
RKGraphicsDataStreamWriteGuard wguard;
@@ -691,6 +749,7 @@ SEXP RKD_SetPattern (SEXP pattern, pDevDesc dev) {
}
void RKD_ReleasePattern (SEXP ref, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
qint32 index;
if (Rf_isNull(ref)) index = 0; // means: destroy all patterns
else index = INTEGER(ref)[0];
@@ -702,6 +761,7 @@ void RKD_ReleasePattern (SEXP ref, pDevDesc dev) {
}
SEXP RKD_SetClipPath (SEXP path, SEXP ref, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
qint32 index = -1;
if (!Rf_isNull(ref)) index = INTEGER(ref)[0];
// NOTE: just because we have a reference, doesn't mean, it's also valid, according to R sources
@@ -713,7 +773,7 @@ SEXP RKD_SetClipPath (SEXP path, SEXP ref, pDevDesc dev) {
}
{
RKGraphicsDataStreamReadGuard rguard;
- bool ok;
+ qint8 ok;
RKD_IN_STREAM >> ok;
if (!ok) Rf_warning("Invalid reference to clipping path");
else return R_NilValue;
@@ -751,6 +811,7 @@ SEXP RKD_SetClipPath (SEXP path, SEXP ref, pDevDesc dev) {
}
void RKD_ReleaseClipPath (SEXP ref, pDevDesc dev) {
+ RK_TRACE(GRAPHICS_DEVICE);
{
RKGraphicsDataStreamWriteGuard wguard;
WRITE_HEADER(RKDReleaseClipPath, dev);
@@ -767,6 +828,7 @@ void RKD_ReleaseClipPath (SEXP ref, pDevDesc dev) {
}
SEXP RKD_SetMask (SEXP path, SEXP ref, pDevDesc dd) {
+ RK_TRACE(GRAPHICS_DEVICE);
#ifdef __GNUC__
#warning implement me
#endif
@@ -774,6 +836,7 @@ SEXP RKD_SetMask (SEXP path, SEXP ref, pDevDesc dd) {
}
void RKD_ReleaseMask (SEXP ref, pDevDesc dd) {
+ RK_TRACE(GRAPHICS_DEVICE);
#ifdef __GNUC__
#warning implement me
#endif
diff --git a/rkward/rbackend/rpackages/rkward/DESCRIPTION b/rkward/rbackend/rpackages/rkward/DESCRIPTION
index c816fd30..d6eb97db 100755
--- a/rkward/rbackend/rpackages/rkward/DESCRIPTION
+++ b/rkward/rbackend/rpackages/rkward/DESCRIPTION
@@ -18,7 +18,7 @@ Authors at R: c(person(given="Thomas", family="Friedrichsmeier",
role=c("aut")), person(given="the RKWard team",
email="rkward-devel at kde.org", role=c("cre","ctb")))
Version: 0.7.3
-Date: 2022-03-10
+Date: 2022-03-19
RoxygenNote: 7.1.2
Collate:
'base_overrides.R'
diff --git a/rkward/rbackend/rpackages/rkward/R/internal_graphics.R b/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
index 3c027184..d4020d4b 100644
--- a/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
+++ b/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
@@ -14,9 +14,11 @@
}
# Fetch the current size of the given RK() device from the frontend, and redraw
-"RK.resize" <- function (devnum) {
+"RK.resize" <- function (devnum, id) {
# Note: RK.resize() often fails, if something is currently being plotted. That's usually benign, and should not produce warning messages.
- try (.Call ("rk.graphics.device.resize", as.integer (devnum)-1, PACKAGE="(embedding)"), silent=TRUE)
+ suppressWarnings(
+ try (.Call ("rk.graphics.device.resize", as.integer (devnum)-1, as.integer(id), PACKAGE="(embedding)"), silent=TRUE)
+ )
}
#' @include internal.R
diff --git a/rkward/windows/rkwindowcatcher.cpp b/rkward/windows/rkwindowcatcher.cpp
index 78dcd023..0371669d 100644
--- a/rkward/windows/rkwindowcatcher.cpp
+++ b/rkward/windows/rkwindowcatcher.cpp
@@ -368,7 +368,7 @@ void RKCaughtX11Window::commonClose(bool in_destructor) {
if (rk_native_device) rk_native_device->stopInteraction();
QString status = i18n("Closing device (saving history)");
- if (!close_attempted) {
+ if (!(close_attempted || killed_in_r)) {
RCommand* c = new RCommand("dev.off (" + QString::number(device_number) + ')', RCommand::App, i18n("Shutting down device number %1", device_number));
if (!in_destructor) setStatusMessage(status, c);
RKGlobals::rInterface()->issueCommand(c);
More information about the rkward-tracker
mailing list