[rkward-cvs] SF.net SVN: rkward-code:[4708] trunk/rkward/rkward
tfry at users.sf.net
tfry at users.sf.net
Mon Apr 22 19:02:19 UTC 2013
Revision: 4708
http://sourceforge.net/p/rkward/code/4708
Author: tfry
Date: 2013-04-22 19:02:17 +0000 (Mon, 22 Apr 2013)
Log Message:
-----------
Finish initial implementation of priority commands, and implement RK() device resize-handling on top of this.
So far this uses R_PolledEvents() for our hook into R's event loop. However, this is not perfect at least on Unix.
E.g. R_PolledEvents() does not get called during Sys.sleep() (and probably other select()s).
On Unix, it may be a better idea to use an input handler listening on a pipe. Not tested on Windows, yet.
Modified Paths:
--------------
trunk/rkward/rkward/rbackend/rinterface.cpp
trunk/rkward/rkward/rbackend/rinterface.h
trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp
trunk/rkward/rkward/rbackend/rkrbackend.cpp
trunk/rkward/rkward/rbackend/rkrbackend.h
trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp
trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h
trunk/rkward/rkward/rbackend/rktransmitter.cpp
trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
trunk/rkward/rkward/settings/rksettingsmodulewatch.cpp
Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -151,6 +151,22 @@
return 0;
}
+RCommandChain* RInterface::openSubcommandChain (RCommand* parent_command) {
+ RK_TRACE (RBACKEND);
+
+ current_commands_with_subcommands.append (parent_command);
+ return RCommandStack::startChain (parent_command);
+}
+
+void RInterface::closeSubcommandChain (RCommand* parent_command) {
+ RK_TRACE (RBACKEND);
+
+ if (current_commands_with_subcommands.contains (parent_command)) {
+ current_commands_with_subcommands.removeAll (parent_command);
+ doNextCommand (0);
+ }
+}
+
void RInterface::tryNextCommand () {
RK_TRACE (RBACKEND);
RCommand *command = RCommandStack::currentCommand ();
@@ -164,8 +180,8 @@
bool priority = command && (command->type () & RCommand::PriorityCommand);
bool on_top_level = all_current_commands.isEmpty ();
if (!(on_top_level && locked && !(priority))) { // do not respect locks for sub-commands
- if (!on_top_level && all_current_commands.contains (command)) { // all sub-commands of the current command have finished
- doNextCommand (0);
+ if ((!on_top_level) && all_current_commands.contains (command)) { // all sub-commands of the current command have finished, it became the top-most item of the RCommandStack, again
+ closeSubcommandChain (command);
return;
}
@@ -352,7 +368,7 @@
// The reason for doing it this way, instead of the reverse, is that this allows the backend thread / process to continue working, concurrently
// NOTE: cproxy should only ever be 0 in the very first cycle
if (cproxy) command = popPreviousCommand (cproxy->id);
- command_requests.append (request);
+ if (request->synchronous) command_requests.append (request);
tryNextCommand ();
if (cproxy) {
RK_ASSERT (command);
@@ -371,7 +387,7 @@
startup_errors = request->params["message"].toString ();
command_requests.append (request);
- RCommandChain *chain = RCommandStack::startChain (runningCommand ());
+ RCommandChain *chain = openSubcommandChain (runningCommand ());
issueCommand ("paste (R.version[c (\"major\", \"minor\")], collapse=\".\")\n", RCommand::GetStringVector | RCommand::App | RCommand::Sync, QString (), this, GET_R_VERSION, chain);
// find out about standard library locations
@@ -657,7 +673,7 @@
current_command = new RCommand (QString (), RCommand::App | RCommand::EmptyCommand | RCommand::Sync);
issueCommand (current_command);
}
- in_chain = startChain (current_command);
+ in_chain = openSubcommandChain (current_command);
QString call = calllist.value (0);
if (call == "sync") {
Modified: trunk/rkward/rkward/rbackend/rinterface.h
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.h 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rinterface.h 2013-04-22 19:02:17 UTC (rev 4708)
@@ -105,6 +105,10 @@
void handleCommandOut (RCommand *command);
bool previously_idle;
+ RCommandChain* openSubcommandChain (RCommand *parent_command);
+ QList<RCommand *> current_commands_with_subcommands;
+ void closeSubcommandChain (RCommand *parent_command);
+
/** @see locked */
enum LockType {
User=1 /**< locked on user request */
Modified: trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkbackendtransmitter.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -2,7 +2,7 @@
rkbackendtransmitter - description
-------------------
begin : Thu Nov 18 2010
- copyright : (C) 2010 by Thomas Friedrichsmeier
+ copyright : (C) 2010, 2013 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -90,14 +90,25 @@
// first check for requests which originated in the frontend
if (request->type == RBackendRequest::Interrupt) {
RKRBackend::this_pointer->interruptCommand (request->params.value ("commandid", -1).toInt ());
- // requests which originated in the backend below this line
- } else {
+ } else if (request->type == RBackendRequest::PriorityCommand) {
+ RKRBackend::this_pointer->setPriorityCommand (request->takeCommand ());
+ } else { // requests which originated in the backend below this line
if (current_sync_requests.isEmpty ()) {
RK_ASSERT (false);
return;
}
- RBackendRequest* current_sync_request = current_sync_requests.takeFirst ();
+ // "Synchronous" requests are not necessarily answered in the order they have been queued
+ int id = request->id;
+ RBackendRequest* current_sync_request = 0;
+ for (int i = current_sync_requests.size () - 1; i >= 0; --i) {
+ RBackendRequest *candidate = current_sync_requests[i];
+ if (id == candidate->id) {
+ current_sync_request = current_sync_requests.takeAt (i);
+ break;
+ }
+ }
+ RK_ASSERT (current_sync_request);
if (current_sync_request->type == RBackendRequest::Output) {
delete current_sync_request; // this was just our internal request
} else {
Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -2,7 +2,7 @@
rkrbackend - description
-------------------
begin : Sun Jul 25 2004
- copyright : (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 by Thomas Friedrichsmeier
+ copyright : (C) 2004 - 2013 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -456,6 +456,7 @@
void RWriteConsoleEx (const char *buf, int buflen, int type) {
RK_TRACE (RBACKEND);
+ RK_DEBUG (RBACKEND, DL_DEBUG, "raw output type %d, size %d: %s", type, buflen, buf);
// output while nothing else is running (including handlers?) -> This may be a syntax error.
if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.browser_context) && (!RKRBackend::this_pointer->isKilled ())) {
@@ -751,6 +752,7 @@
r_running = false;
current_command = 0;
+ pending_priority_command = 0;
stdout_stderr_fd = -1;
RK_ASSERT (this_pointer == 0);
@@ -997,6 +999,9 @@
}
SEXP RKStartGraphicsDevice (SEXP width, SEXP height, SEXP pointsize, SEXP family, SEXP bg, SEXP title, SEXP antialias);
+SEXP RKD_AdjustSize (SEXP devnum);
+void doPendingPriorityCommands ();
+void (* old_R_PolledEvents)(void);
bool RKRBackend::startR () {
RK_TRACE (RBACKEND);
@@ -1019,7 +1024,8 @@
#ifndef Q_OS_WIN
// re-direct stdout / stderr to a pipe, so we can read output from system() calls
int pfd[2];
- pipe (pfd);
+ int error = pipe (pfd);
+ RK_ASSERT (!error); // mostly to silence compile time warning about unused return value
dup2 (pfd[1], STDOUT_FILENO);
dup2 (pfd[1], STDERR_FILENO); // forward both to a single channel to avoid interleaving hell, for now.
close (pfd[1]);
@@ -1072,12 +1078,15 @@
{ "rk.update.locale", (DL_FUNC) &doUpdateLocale, 0 },
{ "rk.locale.name", (DL_FUNC) &doLocaleName, 0 },
{ "rk.graphics.device", (DL_FUNC) &RKStartGraphicsDevice, 7},
+ { "rk.graphics.device.resize", (DL_FUNC) &RKD_AdjustSize, 1},
{ 0, 0, 0 }
};
R_registerRoutines (R_getEmbeddingDllInfo(), NULL, callMethods, NULL, NULL);
connectCallbacks();
RKInsertToplevelStatementFinishedCallback (0);
+ old_R_PolledEvents = R_PolledEvents;
+ R_PolledEvents = doPendingPriorityCommands;
default_global_context = R_GlobalContext;
// get info on R runtime version
@@ -1324,6 +1333,37 @@
}
}
+void RKRBackend::setPriorityCommand (RCommandProxy* command) {
+ RK_TRACE (RBACKEND);
+ QMutexLocker lock (&priority_command_mutex);
+ RK_ASSERT (!(command && pending_priority_command)); // for the time being, we support only one priority command at a time
+ pending_priority_command = command;
+}
+
+void doPendingPriorityCommands () {
+ RK_TRACE (RBACKEND);
+
+ RCommandProxy *command = RKRBackend::this_pointer->pending_priority_command;
+ if (command) {
+ RK_DEBUG (RBACKEND, DL_DEBUG, "running priority command %s", qPrintable (command->command));
+ RKRBackend::this_pointer->setPriorityCommand (0);
+ {
+ QMutexLocker lock (&RKRBackend::this_pointer->all_current_commands_mutex);
+ RKRBackend::this_pointer->all_current_commands.append (command);
+ RKRBackend::this_pointer->current_command = command;
+ }
+
+ RKRBackend::this_pointer->runCommand (command);
+ RKRBackend::this_pointer->commandFinished (false);
+ // TODO: Oh boy, what a mess. Sending notifications should be split from fetchNextCommand() (which is not appropriate, here)
+ RBackendRequest req (false, RBackendRequest::CommandOut); // NOTE: We do *NOT* want a reply to this one, and in particular, we do *NOT* want to do
+ // (recursive) event processing while handling this.
+ req.command = command;
+ RKRBackend::this_pointer->handleRequest (&req);
+ }
+ if (old_R_PolledEvents) old_R_PolledEvents ();
+}
+
// On Windows, using runDirectCommand (".rk.cat.output ...") is not safe during some places where we call this, e.g. in RBusy.
// Not a problem on Linux with R 2.13.0, though
void RKRBackend::catToOutputFile (const QString &out) {
@@ -1440,6 +1480,8 @@
if (!request->done) RKRBackendProtocolBackend::msleep (++i < 200 ? 10 : 50);
}
+ while (pending_priority_command) processX11Events (); // Probably not needed, but make sure to process priority commands first at all times.
+
RCommandProxy* command = request->takeCommand ();
if (!command) return 0;
Modified: trunk/rkward/rkward/rbackend/rkrbackend.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.h 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkrbackend.h 2013-04-22 19:02:17 UTC (rev 4708)
@@ -2,7 +2,7 @@
rkrbackend - description
-------------------
begin : Sun Jul 25 2004
- copyright : (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 by Thomas Friedrichsmeier
+ copyright : (C) 2004 - 2013 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -194,6 +194,10 @@
bool fetchStdoutStderr (bool forcibly);
/** public for technical reasons */
QMutex stdout_stderr_mutex;
+
+ void setPriorityCommand (RCommandProxy *command);
+ RCommandProxy *pending_priority_command;
+ QMutex priority_command_mutex;
private:
void clearPendingInterrupt ();
protected:
Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -2,7 +2,7 @@
rkrbackendprotocol - description
-------------------
begin : Thu Nov 04 2010
- copyright : (C) 2010, 2011 by Thomas Friedrichsmeier
+ copyright : (C) 2010, 2011, 2013 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -35,11 +35,13 @@
}
+int RBackendRequest::_id = 0;
RBackendRequest::RBackendRequest (bool synchronous, RCallbackType type) {
RK_TRACE (RBACKEND);
RBackendRequest::synchronous = synchronous;
RBackendRequest::type = type;
+ id = ++_id;
done = false;
command = 0;
output = 0;
@@ -55,6 +57,7 @@
void RBackendRequest::mergeReply (RBackendRequest *reply) {
RK_TRACE (RBACKEND);
+ RK_ASSERT (reply->id == id);
command = reply->command;
params = reply->params;
output = reply->output;
@@ -66,6 +69,8 @@
RK_TRACE (RBACKEND);
RBackendRequest* ret = new RBackendRequest (synchronous, type);
+ --_id; // for pretty, consecutive numbering
+ ret->id = id;
ret->done = done;
ret->command = command;
ret->params = params;
Modified: trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkrbackendprotocol_shared.h 2013-04-22 19:02:17 UTC (rev 4708)
@@ -2,7 +2,7 @@
rkrbackendprotocol - description
-------------------
begin : Thu Nov 04 2010
- copyright : (C) 2010, 2011 by Thomas Friedrichsmeier
+ copyright : (C) 2010, 2011, 2013 by Thomas Friedrichsmeier
email : tfry at users.sourceforge.net
***************************************************************************/
@@ -32,17 +32,17 @@
ShowFiles,
ChooseFile,
EditFiles,
- ReadLine,
+ ReadLine, // 5
CommandOut,
Started,
EvalRequest,
CallbackRequest,
- HistoricalSubstackRequest,
+ HistoricalSubstackRequest, // 10
PlainGenericRequest,
SetParamsFromBackend,
Debugger,
CommandLineIn, /**< The next line of the current user command has been submitted in the backend. */
- Output, /**< A piece of output. Note: If the backend runs in a single process, output is handled in a pull fashion, instead of using requests. */
+ Output, /**< A piece of output. Note: If the backend runs in a single process, output is handled in a pull fashion, instead of using requests. */ //15
Interrupt, /**< Interrupt evaluation. This request type originates in the frontend, not the backend. */
PriorityCommand, /**< Send a command to be run during R's event processing. This request type originates in the frontend, not the backend. */
OutputStartedNotification, /**< Only used in the frontend: Notification that a new bit of output has arrived. Used to trigger flushing after a timeout. */
@@ -68,6 +68,8 @@
bool synchronous;
/** For synchronous requests, only: The frontend-thread will set this to true (using completed()), once the request has been "completed". Important: The backend thread MUST NOT touch a request after it has been sent, and before "done" has been set to true. */
bool volatile done;
+ int id;
+ static int _id;
RCallbackType type;
/** For synchronous requests, only: If the frontend wants any commands to be executed, it will place the next one in this slot. The backend thread should keep executing commands (in a sub-eventloop) while this is non-zero. Also, the backend-thread may place here any command that has just finished. */
RCommandProxy *command;
Modified: trunk/rkward/rkward/rbackend/rktransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rktransmitter.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rktransmitter.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -22,6 +22,7 @@
void RKRBackendSerializer::serialize (const RBackendRequest &request, QDataStream &stream) {
RK_TRACE (RBACKEND);
+ stream << (qint16) request.id;
stream << (qint8) request.type;
stream << request.synchronous;
stream << request.done; // well, not really needed, but...
@@ -45,9 +46,13 @@
RK_TRACE (RBACKEND);
RBackendRequest *request = new RBackendRequest (false, RBackendRequest::OtherRequest); // will be overwritten
+ RBackendRequest::_id--;
bool dummyb;
qint8 dummy8;
+ qint16 dummy16;
+ stream >> dummy16;
+ request->id = dummy16;
stream >> dummy8;
request->type = (RBackendRequest::RCallbackType) dummy8;
stream >> request->synchronous;
Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -28,6 +28,8 @@
#include <kdialog.h>
#include "rkgraphicsdevice_protocol_shared.h"
+#include "../rinterface.h"
+#include "../../rkglobals.h"
#include "../../debug.h"
@@ -40,13 +42,14 @@
interaction_opcode = -1;
dialog = 0;
- if (antialias) painter.setRenderHints (QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
view = new QLabel ();
view->installEventFilter (this);
+ view->setScaledContents (true); // this is just for preview during scaling. The area will be re-sized and re-drawn from R.
connect (view, SIGNAL (destroyed(QObject*)), this, SLOT (viewKilled()));
connect (&updatetimer, SIGNAL (timeout ()), this, SLOT (updateNow ()));
updatetimer.setSingleShot (true);
clear ();
+ if (antialias) painter.setRenderHints (QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
setActive (true); // sets window title
}
@@ -74,6 +77,9 @@
view->resize (area.size ());
view->show ();
}
+ if (view->size () != area.size ()) {
+ RKGlobals::rInterface ()->issueCommand (new RCommand ("rkward:::RK.resize (" + QString::number (devices.key (this) + 1) + ")", RCommand::PriorityCommand));
+ }
painter.begin (&area);
}
@@ -106,6 +112,13 @@
setClip (area.rect ()); // R's devX11.c resets clip on clear, so we do this, too.
}
+void RKGraphicsDevice::setAreaSize (const QSize& size) {
+ if (painter.isActive ()) painter.end ();
+ RK_DEBUG (GRAPHICS_DEVICE, DL_WARNING, "New Size %d, %d (view size is %d, %d)", size.width (), size.height (), view->width (), view->height ());
+ area = QPixmap (size.width (), size.height ());
+ clear ();
+}
+
void RKGraphicsDevice::setClip (const QRectF& new_clip) {
RK_TRACE (GRAPHICS_DEVICE);
@@ -270,6 +283,7 @@
return true;
}
}
+ if (event->type () == QEvent::Resize) triggerUpdate ();
return false;
}
Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h 2013-04-22 19:02:17 UTC (rev 4708)
@@ -56,6 +56,8 @@
void confirmNewPage ();
QWidget* viewPort () const { return view; };
+ QSizeF currentSize () const { return view->size (); }
+ void setAreaSize (const QSize &size);
public slots:
void stopInteraction ();
signals:
Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -288,6 +288,13 @@
}
}
streamer.writeOutBuffer ();
+ } else if (opcode == RKDGetSize) {
+ streamer.outstream << device->currentSize ();
+ streamer.writeOutBuffer ();
+ } else if (opcode == RKDSetSize) {
+ QSize size;
+ streamer.instream >> size;
+ device->setAreaSize (size);
} else if (opcode == RKDLocator) {
device->locator ();
#warning TODO keep track of status
@@ -322,6 +329,8 @@
} else if (opcode == RKDStrWidthUTF8) {
double width = 1;
streamer.outstream << width;
+ } else if (opcode == RKDGetSize) {
+ streamer.outstream << QSizeF ();
} else {
return; // nothing to write
}
Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h 2013-04-22 19:02:17 UTC (rev 4708)
@@ -62,31 +62,33 @@
enum RKDOpcodes {
// Asynchronous operations
- RKDCreate, // 0
+ RKDCreate, // 0
RKDCircle,
RKDLine,
RKDPolygon,
RKDPolyline,
- RKDRect, // 5
+ RKDRect, // 5
RKDTextUTF8,
RKDNewPage,
RKDClose,
RKDActivate,
- RKDDeActivate, // 10
+ RKDDeActivate, // 10
RKDClip,
RKDMode,
RKDRaster,
+ RKDSetSize,
// Synchronous operations
- RKDStrWidthUTF8,
- RKDMetricInfo, // 15
+ RKDStrWidthUTF8, // 15
+ RKDMetricInfo,
RKDLocator,
RKDNewPageConfirm,
RKDCapture,
- RKDQueryResolution,
+ RKDQueryResolution, // 20
+ RKDGetSize,
// Protocol operations
- RKDCancel // 20
+ RKDCancel
};
#include <QtGlobal>
Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -120,6 +120,7 @@
};
#include <QRectF>
+#include <QSizeF>
// This ought to be optimized away by the compiler:
#define SAFE_LINE_END(lend) (quint8) (lend == GE_ROUND_CAP ? RoundLineCap : (lend == GE_BUTT_CAP ? ButtLineCap : SquareLineCap))
@@ -165,14 +166,44 @@
RKD_OUT_STREAM << width << height << QString::fromUtf8 (title) << antialias;
}
-// TODO: Handle resizes
static void RKD_Size (double *left, double *right, double *top, double *bottom, pDevDesc dev) {
+// NOTE: This does *not* query the frontend for the current size. This is only done on request
*left = dev->left;
*top = dev->top;
*right = dev->right;
*bottom = dev->bottom;
}
+static void RKD_SetSize (pDevDesc dev) {
+ 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);
+ pDevDesc dev = gdev->dev;
+ {
+ RKGraphicsDataStreamWriteGuard wguard;
+ 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);
+ dev->left = dev->top = 0;
+ dev->right = size.width ();
+ dev->bottom = size.height ();
+
+ RKD_SetSize (dev); // This adjusts the rendering area in the frontend
+ GEplayDisplayList (gdev);
+ return R_NilValue;
+}
+
static void RKD_Circle (double x, double y, double r, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDCircle, dev);
Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal_graphics.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal_graphics.R 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal_graphics.R 2013-04-22 19:02:17 UTC (rev 4708)
@@ -32,6 +32,11 @@
invisible (x)
}
+# Fetch the current size of the given RK() device from the frontend, and redraw
+"RK.resize" <- function (devnum) {
+ .Call ("rk.graphics.device.resize", as.integer (devnum)-1, PACKAGE="(embedding)")
+}
+
#' @export
"x11" <- rk.screen.device
Modified: trunk/rkward/rkward/settings/rksettingsmodulewatch.cpp
===================================================================
--- trunk/rkward/rkward/settings/rksettingsmodulewatch.cpp 2013-04-21 18:26:22 UTC (rev 4707)
+++ trunk/rkward/rkward/settings/rksettingsmodulewatch.cpp 2013-04-22 19:02:17 UTC (rev 4708)
@@ -45,7 +45,7 @@
if (command->type () & RCommand::EmptyCommand) return false;
- if (command->type () & RCommand::Sync) {
+ if (command->type () & (RCommand::Sync | RCommand::PriorityCommand)) {
return (sync_filter & ShowInput);
} else if (command->type () & RCommand::User) {
return (user_filter & ShowInput);
@@ -66,7 +66,7 @@
if (command->type () & RCommand::EmptyCommand) return false;
if (!shouldShowInput (command)) return false;
- if (command->type () & RCommand::Sync) {
+ if (command->type () & (RCommand::Sync | RCommand::PriorityCommand)) {
return (sync_filter & ShowOutput);
} else if (command->type () & RCommand::User) {
return (user_filter & ShowOutput);
@@ -84,7 +84,7 @@
bool RKSettingsModuleWatch::shouldShowError (RCommand *command) {
RK_TRACE (SETTINGS);
- if (command->type () & RCommand::Sync) {
+ if (command->type () & (RCommand::Sync | RCommand::PriorityCommand)) {
return (sync_filter & ShowError);
} else if (command->type () & RCommand::User) {
return (user_filter & ShowError);
@@ -101,7 +101,7 @@
bool RKSettingsModuleWatch::shouldRaiseWindow (RCommand *command) {
RK_TRACE (SETTINGS);
- if (command->type () & RCommand::Sync) {
+ if (command->type () & (RCommand::Sync | RCommand::PriorityCommand)) {
return (sync_filter & RaiseWindow);
} else if (command->type () & RCommand::User) {
return (user_filter & RaiseWindow);
More information about the rkward-tracker
mailing list