in src/graphics/MasterDevice.cpp [508:637]
void MasterDevice::restart() {
DEVICE_TRACE;
shutdown();
if (currentDeviceInfos.empty()) {
addNewDevice();
}
auto masterDevDesc = new DevDesc;
auto dummySnapshotPath = currentSnapshotDirectory + "/" + SnapshotUtil::getDummySnapshotName();
deviceSlotLock = makePtr<DeviceSlotLock>(dummySnapshotPath, currentScreenParameters);
auto slaveDevDesc = deviceSlotLock->getSlaveDescriptor();
// Note: under some circumstances (R interpreter failures) slave device's descriptor can be null
if (!slaveDevDesc) {
delete masterDevDesc;
return;
}
setMasterDeviceSize(masterDevDesc, slaveDevDesc);
memset(masterDevDesc->reserved, 0, 64);
masterDevDesc->xCharOffset = slaveDevDesc->xCharOffset;
masterDevDesc->yCharOffset = slaveDevDesc->yCharOffset;
masterDevDesc->yLineBias = slaveDevDesc->yLineBias;
masterDevDesc->ipr[0] = slaveDevDesc->ipr[0];
masterDevDesc->ipr[1] = slaveDevDesc->ipr[1];
masterDevDesc->cra[0] = slaveDevDesc->cra[0];
masterDevDesc->cra[1] = slaveDevDesc->cra[1];
masterDevDesc->gamma = slaveDevDesc->gamma;
masterDevDesc->canClip = slaveDevDesc->canClip;
masterDevDesc->canChangeGamma = slaveDevDesc->canChangeGamma;
masterDevDesc->canHAdj = slaveDevDesc->canHAdj;
masterDevDesc->startps = slaveDevDesc->startps;
masterDevDesc->startcol = slaveDevDesc->startcol;
masterDevDesc->startfill = slaveDevDesc->startfill;
masterDevDesc->startlty = slaveDevDesc->startlty;
masterDevDesc->startfont = slaveDevDesc->startfont;
masterDevDesc->startgamma = slaveDevDesc->startgamma;
masterDevDesc->deviceSpecific = this; // OOP confirmed
masterDevDesc->displayListOn = isProxy ? FALSE : TRUE;
masterDevDesc->canGenMouseDown = FALSE;
masterDevDesc->canGenMouseMove = FALSE;
masterDevDesc->canGenMouseUp = FALSE;
masterDevDesc->canGenKeybd = FALSE;
masterDevDesc->gettingEvent = FALSE;
masterDevDesc->activate = nullptr; // NULL
masterDevDesc->circle = circle;
masterDevDesc->clip = clip;
masterDevDesc->close = close;
masterDevDesc->deactivate = nullptr; // NULL
masterDevDesc->locator = nullptr; // NULL
masterDevDesc->line = line;
masterDevDesc->metricInfo = metricInfo;
masterDevDesc->mode = mode;
masterDevDesc->newPage = newPage;
masterDevDesc->polygon = polygon;
masterDevDesc->polyline = polyline;
masterDevDesc->rect = rect;
masterDevDesc->path = path;
masterDevDesc->raster = raster;
masterDevDesc->cap = nullptr; // NULL
masterDevDesc->size = size;
masterDevDesc->strWidth = strWidth;
masterDevDesc->text = text;
masterDevDesc->onExit = nullptr; // NULL
masterDevDesc->getEvent = nullptr;
int rVersion = getRIntVersion();
if (rVersion >= 41) {
// In R 4.1 a couple of new function in the struct "DevDesc" were introduced. To setup them in R 4.1
// and not to break complication with R 3.4 it was decided to initialize these function via pointers.
auto masterDevDesc_4_1 = reinterpret_cast<SampleDevDesc *>(masterDevDesc);
masterDevDesc_4_1->setPattern = &setPattern;
masterDevDesc_4_1->releasePattern = &releasePattern;
masterDevDesc_4_1->setClipPath = &setClipPath;
masterDevDesc_4_1->releaseClipPath = &releaseClipPath;
masterDevDesc_4_1->setMask = &setMask;
masterDevDesc_4_1->releaseMask = &releaseMask;
}
masterDevDesc->newFrameConfirm = nullptr; // NULL
masterDevDesc->hasTextUTF8 = TRUE;
masterDevDesc->textUTF8 = textUTF8;
masterDevDesc->strWidthUTF8 = strWidthUTF8;
masterDevDesc->wantSymbolUTF8 = TRUE;
masterDevDesc->useRotatedTextInContour = FALSE;
masterDevDesc->eventEnv = R_NilValue;
masterDevDesc->eventHelper = nullptr;
masterDevDesc->holdflush = nullptr; // Previously was NULL
masterDevDesc->haveTransparency = 2;
masterDevDesc->haveTransparentBg = 2;
masterDevDesc->haveRaster = 2;
masterDevDesc->haveCapture = 1;
masterDevDesc->haveLocator = 2; // Previously was 1, I have set this according to RStudio source files
// Proxy device doesn't need its own device slot lock.
// Destroy it before the master device is added,
// so there is no "gap" in R device list
if (isProxy) {
deviceSlotLock = nullptr;
}
pGEDevDesc masterDevice = GEcreateDevDesc(masterDevDesc);
GEaddDevice2(masterDevice, isProxy ? PROXY_DEVICE_NAME : MASTER_DEVICE_NAME);
Rf_selectDevice(Rf_ndevNumber(masterDevice->dev));
masterDeviceDescriptor = masterDevice;
auto& current = currentDeviceInfos[currentSnapshotNumber].device;
if (current) {
if (current->isBlank()) {
current = nullptr;
} else {
std::cerr << "Failed to null current device: it's not blank\n"; // Note: normally this shouldn't happen
addNewDevice();
}
}
}