Skip to content

Commit

Permalink
Mac OS X|Fixed: Window geometry after mode change
Browse files Browse the repository at this point in the history
It seems that one must wait a while after the mode change is complete
before updating the window.
  • Loading branch information
skyjake committed Mar 18, 2012
1 parent 43448ec commit 3af118a
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 39 deletions.
20 changes: 11 additions & 9 deletions doomsday/engine/mac/src/displaymode_macx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ static DisplayMode modeFromDict(CFDictionaryRef dict)

static std::vector<DisplayMode> displayModes;
static std::vector<CFDictionaryRef> displayDicts;
static CFDictionaryRef currentDisplayDict;

void DisplayMode_Native_Init(void)
{
Expand All @@ -75,6 +76,7 @@ void DisplayMode_Native_Init(void)
displayModes.push_back(modeFromDict(dict));
displayDicts.push_back(dict);
}
currentDisplayDict = (CFDictionaryRef) CGDisplayCurrentMode(kCGDirectMainDisplay);
}

static void releaseDisplays()
Expand Down Expand Up @@ -103,14 +105,9 @@ void DisplayMode_Native_GetMode(int index, DisplayMode* mode)
*mode = displayModes[index];
}

static CFDictionaryRef currentModeDict()
{
return (CFDictionaryRef) CGDisplayCurrentMode(kCGDirectMainDisplay);
}

void DisplayMode_Native_GetCurrentMode(DisplayMode* mode)
{
*mode = modeFromDict(currentModeDict());
*mode = modeFromDict(currentDisplayDict);
}

static int findIndex(const DisplayMode* mode)
Expand Down Expand Up @@ -150,20 +147,25 @@ int DisplayMode_Native_Change(const DisplayMode* mode)
}
if(result == kCGErrorSuccess)
{
CFDictionaryRef current = currentModeDict();

qDebug() << "Changing to native mode" << findIndex(mode);

// Try to change.
result = CGDisplaySwitchToMode(kCGDirectMainDisplay, displayDicts[findIndex(mode)]);
if(result != kCGErrorSuccess)
{
// Oh no!
CGDisplaySwitchToMode(kCGDirectMainDisplay, current);
CGDisplaySwitchToMode(kCGDirectMainDisplay, currentDisplayDict);
if(!wasPreviouslyCaptured) releaseDisplays();
}
else
{
currentDisplayDict = displayDicts[findIndex(mode)];
}
}

DisplayMode dm = modeFromDict(currentDisplayDict);
qDebug() << "Native current is now" << dm.width << dm.height;

// Fade back to normal.
CGDisplayFade(token, 2*fadeTime, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, false);
CGReleaseDisplayFadeReservation(token);
Expand Down
2 changes: 2 additions & 0 deletions doomsday/engine/portable/include/displaymode.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ void DisplayMode_Shutdown(void);

const DisplayMode* DisplayMode_OriginalMode(void);

const DisplayMode* DisplayMode_Current(void);

int DisplayMode_Count(void);

const DisplayMode* DisplayMode_ByIndex(int index);
Expand Down
4 changes: 4 additions & 0 deletions doomsday/engine/portable/src/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ struct Canvas::Instance

void grabMouse()
{
if(mouseGrabbed) return;

mouseGrabbed = true;

// Start grabbing the mouse now.
Expand All @@ -79,6 +81,8 @@ struct Canvas::Instance

void ungrabMouse()
{
if(!mouseGrabbed) return;

mouseGrabbed = false;
self->releaseMouse();
qApp->restoreOverrideCursor();
Expand Down
10 changes: 10 additions & 0 deletions doomsday/engine/portable/src/displaymode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ const DisplayMode* DisplayMode_OriginalMode(void)
return &originalMode;
}

const DisplayMode* DisplayMode_Current(void)
{
static Mode currentMode;
// Update it with current mode.
currentMode = Mode::fromCurrent();
return &currentMode;
}

int DisplayMode_Count(void)
{
return (int) modes.size();
Expand Down Expand Up @@ -213,10 +221,12 @@ const DisplayMode* DisplayMode_FindClosest(int width, int height, int depth, flo

if(!best || score < bestScore)
{
/*
#ifdef _DEBUG
i->debugPrint();
qDebug() << "Score for" << width << "x" << height << "pixels, depth:" << depth << "bpp, freq:" << freq << "Hz is" << score;
#endif
*/

bestScore = score;
best = &*i;
Expand Down
99 changes: 69 additions & 30 deletions doomsday/engine/portable/src/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ static QRect desktopValidRect()
-DESKTOP_EDGE_GRACE, -DESKTOP_EDGE_GRACE);
}

static void updateMainWindowLayout(void);

struct ddwindow_s
{
CanvasWindow* widget; ///< The widget this window represents.
Expand Down Expand Up @@ -195,13 +197,20 @@ struct ddwindow_s
if(DisplayMode_Change(mode))
{
widget->canvas().trapMouse();

geometry.size.width = DisplayMode_Current()->width;
geometry.size.height = DisplayMode_Current()->height;

#ifdef MACOSX
// Pull the window again over the shield after the mode change.
DisplayMode_Native_Raise(Window_NativeHandle(this));
#endif
}
}
}
else
{
DisplayMode_Change(DisplayMode_OriginalMode());
widget->canvas().trapMouse(false);
}
}

Expand All @@ -218,7 +227,16 @@ struct ddwindow_s

if(flags & DDWF_FULLSCREEN)
{
if(widget->isVisible()) widget->showFullScreen();
if(widget->isVisible())
{
// The window is already visible, so let's allow a mode change to resolve itself
// before we go changing the window.
LegacyCore_Timer(de2LegacyCore, 100, updateMainWindowLayout);
}
else
{
widget->setGeometry(0, 0, DisplayMode_Current()->width, DisplayMode_Current()->height);
}
}
else
{
Expand Down Expand Up @@ -283,6 +301,7 @@ struct ddwindow_s
{
if(width() < WINDOW_MIN_WIDTH) return false;
if(height() < WINDOW_MIN_HEIGHT) return false;
qDebug() << desktopValidRect() << rect() << desktopValidRect().contains(rect());
return desktopValidRect().contains(rect());
}

Expand Down Expand Up @@ -332,7 +351,7 @@ struct ddwindow_s

// Check geometry for validity (window must be on the desktop
// at least partially).
if(!isGeometryValid())
if(!(flags & DDWF_FULLSCREEN) && !isGeometryValid())
{
// We can't place the window completely outside the desktop.
return false;
Expand All @@ -342,6 +361,39 @@ struct ddwindow_s
applyWindowGeometry();
return true;
}

void updateLayout()
{
qDebug() << "Window::updateLayout:" << widget->geometry() << widget->canvas().geometry();

if(!(flags & DDWF_FULLSCREEN))
{
setFlag(DDWF_CENTER, false);
geometry.size.width = widget->width();
geometry.size.height = widget->height();

DEBUG_Message(("Updating view geometry for window, fetched %i x %i.\n",
width(), height()));
}
else
{
DEBUG_Message(("Updating view geometry for fullscreen (%i x %i).\n",
width(), height()));
}

// Update viewports.
R_SetViewGrid(0, 0);
if(Con_IsBusy() || UI_IsActive())
{
// Update for busy mode.
R_UseViewPort(0);
}
if(UI_IsActive())
{
UI_UpdatePageLayout();
}
R_LoadSystemFonts();
}
};

/// Current active window where all drawing operations occur.
Expand All @@ -352,10 +404,18 @@ static boolean winManagerInited = false;
static Window mainWindow;
static boolean mainWindowInited = false;

/*
static int screenWidth, screenHeight, screenBPP;
static boolean screenIsWindow;
*/
static void updateMainWindowLayout(void)
{
Window* win = Window_Main();

#ifdef MACOSX
// For some interesting reason, we have to scale the window twice in fullscreen mode
// or the resulting layout won't be correct.
win->widget->setGeometry(QRect(0, 0, 320, 240));
#endif

win->widget->setGeometry(QRect(0, 0, win->geometry.size.width, win->geometry.size.height));
}

Window* Window_Main(void)
{
Expand Down Expand Up @@ -808,26 +868,8 @@ static void windowWasMoved(CanvasWindow& cw)
static void windowWasResized(Canvas& canvas)
{
Window* win = canvasToWindow(canvas);

DEBUG_Message(("Updating view geometry.\n"));

win->setFlag(DDWF_CENTER, false);

win->geometry.size.width = win->widget->width();
win->geometry.size.height = win->widget->height();

// Update viewports.
R_SetViewGrid(0, 0);
if(Con_IsBusy() || UI_IsActive())
{
// Update for busy mode.
R_UseViewPort(0);
}
if(UI_IsActive())
{
UI_UpdatePageLayout();
}
R_LoadSystemFonts();
win->assertWindow();
win->updateLayout();
}

static Window* createWindow(ddwindowtype_t type, const char* title)
Expand Down Expand Up @@ -1270,7 +1312,4 @@ void Window_RestoreState(Window* wnd)
wnd->setFlag(DDWF_CENTER, st.value(settingsKey(idx, "center"), true).toBool());
wnd->setFlag(DDWF_MAXIMIZE, st.value(settingsKey(idx, "maximize"), false).toBool());
wnd->setFlag(DDWF_FULLSCREEN, st.value(settingsKey(idx, "fullscreen"), true).toBool());

// testing
wnd->setFlag(DDWF_FULLSCREEN, false);
}

0 comments on commit 3af118a

Please sign in to comment.