void Utility::updateFullscreenState() { video.clear(); if(config().video.isFullscreen == false) { config().video.context = &config().video.windowed; mainWindow->showNormal(); updateMenubar(); updateStatusbar(); mainWindow->canvasContainer->setMouseTracking(false); mainWindow->canvasContainer->unsetCursor(); mainWindow->canvas->setMouseTracking(false); mainWindow->canvas->unsetCursor(); mainWindow->cursorTimer->disconnect(); } else { config().video.context = &config().video.fullscreen; mainWindow->showFullScreen(); mainWindow->menuBar->setVisible(config().video.autoHideFullscreenMenu == false); mainWindow->statusBar->setVisible(config().video.autoHideFullscreenMenu == false); mainWindow->canvasContainer->setMouseTracking(true); mainWindow->canvas->setMouseTracking(true); mainWindow->cursorTimer->start(); mainWindow->connect(mainWindow->cursorTimer, SIGNAL(timeout()), SLOT(hideCursor()), Qt::UniqueConnection); } QApplication::processEvents(); #if defined(PLATFORM_X) //Xlib requires time to propogate fullscreen state change message to window manager; //if window is resized before this occurs, canvas may not resize correctly usleep(50000); #endif //refresh options that are unique to each video context updateHardwareFilter(); updateSoftwareFilter(); mainWindow->syncUi(); } //if max exceeds x: x is set to max, and y is scaled down to keep proportion to x void Utility::constrainSize(unsigned &x, unsigned &y, unsigned max) { if(x > max) { double scalar = (double)max / (double)x; y = (unsigned)((double)y * (double)scalar); x = max; } } void Utility::resizeMainWindow() { //process all pending events to ensure window size is correct (after fullscreen state change, etc) usleep(2000); QApplication::processEvents(); unsigned screenWidth, screenHeight; if(config().video.isFullscreen == false) { screenWidth = QApplication::desktop()->availableGeometry(mainWindow).width(); screenHeight = QApplication::desktop()->availableGeometry(mainWindow).height(); } else { screenWidth = mainWindow->canvasContainer->size().width(); screenHeight = mainWindow->canvasContainer->size().height(); } unsigned region = config().video.context->region; unsigned multiplier = config().video.context->multiplier; unsigned &width = display.outputWidth; unsigned &height = display.outputHeight; width = 256 * multiplier; height = (region == 0 ? 224 : 239) * multiplier; if(config().video.context->correctAspectRatio) { if(region == 0) { width = (double)width * config().video.ntscAspectRatio + 0.5; //NTSC adjust } else { width = (double)width * config().video.palAspectRatio + 0.5; //PAL adjust } } display.cropLeft = config().video.cropLeft; display.cropTop = config().video.cropTop; display.cropRight = config().video.cropRight; display.cropBottom = config().video.cropBottom; //ensure window size will not be larger than viewable desktop area constrainSize(height, width, screenHeight); constrainSize(width, height, screenWidth); if(config().video.isFullscreen == false) { mainWindow->canvas->setFixedSize(width, height); mainWindow->show(); } else { if(multiplier == 6) { //Scale Max - Normal width = (double)width * (double)screenHeight / (double)height; height = screenHeight; } if(multiplier == 7) { //Scale Max - Wide width = screenWidth; height = screenHeight; } if(multiplier == 8) { //Scale Max - Wide Zoom //1. scale width and height proportionally until width of screen is completely filled //2. determine how much height goes out of screen by //3. cut half of the above value out of the visible input display region //this results in a 50% compromise between correct aspect ratio and fill mode; //while cropping out only 50% as much height as a fully proportional zoom would width = (double)width * (double)screenHeight / (double)height; height = screenHeight; unsigned widthDifference = screenWidth - width; unsigned adjustedHeight = (double)height * (double)(width + widthDifference) / (double)(width); unsigned heightDifference = adjustedHeight - height; width = screenWidth; display.cropLeft = 0; display.cropTop = 100.0 / (double)height * (heightDifference / 4); display.cropRight = 0; display.cropBottom = 100.0 / (double)height * (heightDifference / 4); } mainWindow->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mainWindow->canvas->setFixedSize(width, height); mainWindow->canvas->setMinimumSize(0, 0); } //workaround for Qt/Xlib bug: //if window resize occurs with cursor over it, Qt shows Qt::Size*DiagCursor // TODO: is this still an issue? mainWindow->setCursor(mainWindow->cursor()); mainWindow->canvasContainer->setCursor(mainWindow->canvasContainer->cursor()); mainWindow->canvas->setCursor(mainWindow->canvas->cursor()); //workaround for DirectSound(?) bug: //window resizing sometimes breaks audio sync, this call re-initializes it updateAvSync(); } void Utility::toggleSynchronizeVideo() { mainWindow->settings_emulationSpeed_syncVideo->toggleChecked(); config().video.synchronize = mainWindow->settings_emulationSpeed_syncVideo->isChecked(); updateAvSync(); } void Utility::toggleSynchronizeAudio() { mainWindow->settings_emulationSpeed_syncAudio->toggleChecked(); config().audio.synchronize = mainWindow->settings_emulationSpeed_syncAudio->isChecked(); updateAvSync(); } void Utility::setNtscMode() { config().video.context->region = 0; resizeMainWindow(); mainWindow->shrink(); mainWindow->syncUi(); } void Utility::setPalMode() { config().video.context->region = 1; resizeMainWindow(); mainWindow->shrink(); mainWindow->syncUi(); } void Utility::toggleSmoothVideoOutput() { mainWindow->settings_smoothVideo->toggleChecked(); config().video.context->hwFilter = mainWindow->settings_smoothVideo->isChecked(); updateHardwareFilter(); mainWindow->syncUi(); } void Utility::toggleAspectCorrection() { mainWindow->settings_videoMode_correctAspectRatio->toggleChecked(); config().video.context->correctAspectRatio = mainWindow->settings_videoMode_correctAspectRatio->isChecked(); resizeMainWindow(); mainWindow->shrink(); } void Utility::setScale(unsigned scale) { config().video.context->multiplier = scale; resizeMainWindow(); mainWindow->shrink(); mainWindow->syncUi(); } void Utility::toggleFullscreen() { config().video.isFullscreen = !config().video.isFullscreen; updateFullscreenState(); resizeMainWindow(); mainWindow->syncUi(); } void Utility::updateMenubar() { mainWindow->menuBar->setVisible(config().video.showMenubar); resizeMainWindow(); mainWindow->shrink(); } void Utility::updateStatusbar() { mainWindow->statusBar->setVisible(config().video.showStatusbar); resizeMainWindow(); mainWindow->shrink(); }