void MasterDevice::restart()

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();
    }
  }
}