Try to fix long-standing crash-on-resize in Linux.

It appear's SDL's SetVideoMode can cause repeat SDL_VIDEORESIZE message and shouldn't be called again.
This commit is contained in:
Siana Gearz
2013-01-27 01:41:17 +01:00
parent 5e799b1f81
commit aed472af77

View File

@@ -1730,204 +1730,206 @@ void LLWindowSDL::gatherInput()
{ {
switch (event.type) switch (event.type)
{ {
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
{
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
MASK mask = gKeyboard->currentMask(TRUE);
mCallbacks->handleMouseMove(this, openGlCoord, mask);
break;
}
case SDL_KEYDOWN:
mKeyScanCode = event.key.keysym.scancode;
mKeyVirtualKey = event.key.keysym.unicode;
mKeyModifiers = event.key.keysym.mod;
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
// part of the fix for SL-13243
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
SDLReallyCaptureInput(TRUE);
if (event.key.keysym.unicode)
{ {
LLCoordWindow winCoord(event.button.x, event.button.y); handleUnicodeUTF16(event.key.keysym.unicode,
LLCoordGL openGlCoord; gKeyboard->currentMask(FALSE));
convertCoords(winCoord, &openGlCoord);
MASK mask = gKeyboard->currentMask(TRUE);
mCallbacks->handleMouseMove(this, openGlCoord, mask);
break;
} }
break;
case SDL_KEYDOWN: case SDL_KEYUP:
mKeyScanCode = event.key.keysym.scancode; mKeyScanCode = event.key.keysym.scancode;
mKeyVirtualKey = event.key.keysym.unicode; mKeyVirtualKey = event.key.keysym.unicode;
mKeyModifiers = event.key.keysym.mod; mKeyModifiers = event.key.keysym.mod;
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod); if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
// part of the fix for SL-13243 SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
SDLReallyCaptureInput(TRUE);
if (event.key.keysym.unicode) gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
{ break;
handleUnicodeUTF16(event.key.keysym.unicode,
gKeyboard->currentMask(FALSE));
}
break;
case SDL_KEYUP: case SDL_MOUSEBUTTONDOWN:
mKeyScanCode = event.key.keysym.scancode; {
mKeyVirtualKey = event.key.keysym.unicode; bool isDoubleClick = false;
mKeyModifiers = event.key.keysym.mod; LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
MASK mask = gKeyboard->currentMask(TRUE);
if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
break;
case SDL_MOUSEBUTTONDOWN:
{ {
bool isDoubleClick = false; Uint32 now = SDL_GetTicks();
LLCoordWindow winCoord(event.button.x, event.button.y); if ((now - lastLeftDown) > CLICK_THRESHOLD)
LLCoordGL openGlCoord; leftClick = 1;
convertCoords(winCoord, &openGlCoord); else
MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking...
{ {
Uint32 now = SDL_GetTicks(); if (++leftClick >= 2)
if ((now - lastLeftDown) > CLICK_THRESHOLD)
leftClick = 1;
else
{ {
if (++leftClick >= 2) leftClick = 0;
{ isDoubleClick = true;
leftClick = 0;
isDoubleClick = true;
}
} }
lastLeftDown = now;
} }
else if (event.button.button == SDL_BUTTON_RIGHT) lastLeftDown = now;
}
else if (event.button.button == SDL_BUTTON_RIGHT)
{
Uint32 now = SDL_GetTicks();
if ((now - lastRightDown) > CLICK_THRESHOLD)
rightClick = 1;
else
{ {
Uint32 now = SDL_GetTicks(); if (++rightClick >= 2)
if ((now - lastRightDown) > CLICK_THRESHOLD)
rightClick = 1;
else
{ {
if (++rightClick >= 2) rightClick = 0;
{ isDoubleClick = true;
rightClick = 0;
isDoubleClick = true;
}
} }
lastRightDown = now;
} }
lastRightDown = now;
}
if (event.button.button == SDL_BUTTON_LEFT) // left if (event.button.button == SDL_BUTTON_LEFT) // left
{
if (isDoubleClick)
mCallbacks->handleDoubleClick(this, openGlCoord, mask);
else
mCallbacks->handleMouseDown(this, openGlCoord, mask);
}
else if (event.button.button == SDL_BUTTON_RIGHT) // right
{
mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
}
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
{
mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
}
else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons".
mCallbacks->handleScrollWheel(this, -1);
else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons".
mCallbacks->handleScrollWheel(this, 1);
break;
}
case SDL_MOUSEBUTTONUP:
{
LLCoordWindow winCoord(event.button.x, event.button.y);
LLCoordGL openGlCoord;
convertCoords(winCoord, &openGlCoord);
MASK mask = gKeyboard->currentMask(TRUE);
if (event.button.button == SDL_BUTTON_LEFT) // left
mCallbacks->handleMouseUp(this, openGlCoord, mask);
else if (event.button.button == SDL_BUTTON_RIGHT) // right
mCallbacks->handleRightMouseUp(this, openGlCoord, mask);
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask);
// don't handle mousewheel here...
break;
}
case SDL_VIDEOEXPOSE: // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing!
mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h);
break;
case SDL_VIDEORESIZE:
{
llinfos << "Handling a resize event: " << event.resize.w <<
"x" << event.resize.h << llendl;
S32 width = llmax(event.resize.w, MIN_WINDOW_WIDTH);
S32 height = llmax(event.resize.h, MIN_WINDOW_HEIGHT);
if (width != mWindow->w || height != mWindow->h)
{
mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
}
if (!mWindow)
{
// *FIX: More informative dialog?
llinfos << "Could not recreate context after resize! Quitting..." << llendl;
if(mCallbacks->handleCloseRequest(this))
{ {
if (isDoubleClick) // Get the app to initiate cleanup.
mCallbacks->handleDoubleClick(this, openGlCoord, mask); mCallbacks->handleQuit(this);
// The app is responsible for calling destroyWindow when done with GL
}
break;
}
mCallbacks->handleResize(this, width, height);
break;
}
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPINPUTFOCUS)
{
// Note that for SDL (particularly on X11), keyboard
// and mouse focus are independent things. Here we are
// tracking keyboard focus state changes.
// We have to do our own state massaging because SDL
// can send us two unfocus events in a row for example,
// which confuses the focus code [SL-24071].
if (event.active.gain != mHaveInputFocus)
{
mHaveInputFocus = !!event.active.gain;
if (mHaveInputFocus)
mCallbacks->handleFocus(this);
else else
mCallbacks->handleMouseDown(this, openGlCoord, mask); mCallbacks->handleFocusLost(this);
} }
else if (event.button.button == SDL_BUTTON_RIGHT) // right
{
mCallbacks->handleRightMouseDown(this, openGlCoord, mask);
}
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle
{
mCallbacks->handleMiddleMouseDown(this, openGlCoord, mask);
}
else if (event.button.button == 4) // mousewheel up...thanks to X11 for making SDL consider these "buttons".
mCallbacks->handleScrollWheel(this, -1);
else if (event.button.button == 5) // mousewheel down...thanks to X11 for making SDL consider these "buttons".
mCallbacks->handleScrollWheel(this, 1);
break;
} }
if (event.active.state & SDL_APPACTIVE)
case SDL_MOUSEBUTTONUP:
{ {
LLCoordWindow winCoord(event.button.x, event.button.y); // Change in iconification/minimization state.
LLCoordGL openGlCoord; if ((!event.active.gain) != mIsMinimized)
convertCoords(winCoord, &openGlCoord); {
MASK mask = gKeyboard->currentMask(TRUE); mIsMinimized = (!event.active.gain);
if (event.button.button == SDL_BUTTON_LEFT) // left mCallbacks->handleActivate(this, !mIsMinimized);
mCallbacks->handleMouseUp(this, openGlCoord, mask); lldebugs << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl;
else if (event.button.button == SDL_BUTTON_RIGHT) // right }
mCallbacks->handleRightMouseUp(this, openGlCoord, mask); else
else if (event.button.button == SDL_BUTTON_MIDDLE) // middle {
mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); llinfos << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << llendl;
// don't handle mousewheel here... }
break;
} }
break;
case SDL_VIDEOEXPOSE: // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing! case SDL_QUIT:
mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h); if(mCallbacks->handleCloseRequest(this))
break;
case SDL_VIDEORESIZE: // *FIX: handle this?
{ {
llinfos << "Handling a resize event: " << event.resize.w << // Get the app to initiate cleanup.
"x" << event.resize.h << llendl; mCallbacks->handleQuit(this);
// The app is responsible for calling destroyWindow when done with GL
S32 width = llmax(event.resize.w, MIN_WINDOW_WIDTH);
S32 height = llmax(event.resize.h, MIN_WINDOW_HEIGHT);
// *FIX: I'm not sure this is necessary!
mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags);
if (!mWindow)
{
// *FIX: More informative dialog?
llinfos << "Could not recreate context after resize! Quitting..." << llendl;
if(mCallbacks->handleCloseRequest(this))
{
// Get the app to initiate cleanup.
mCallbacks->handleQuit(this);
// The app is responsible for calling destroyWindow when done with GL
}
break;
}
mCallbacks->handleResize(this, width, height);
break;
} }
case SDL_ACTIVEEVENT: break;
if (event.active.state & SDL_APPINPUTFOCUS) default:
{ //llinfos << "Unhandled SDL event type " << event.type << llendl;
// Note that for SDL (particularly on X11), keyboard break;
// and mouse focus are independent things. Here we are
// tracking keyboard focus state changes.
// We have to do our own state massaging because SDL
// can send us two unfocus events in a row for example,
// which confuses the focus code [SL-24071].
if (event.active.gain != mHaveInputFocus)
{
mHaveInputFocus = !!event.active.gain;
if (mHaveInputFocus)
mCallbacks->handleFocus(this);
else
mCallbacks->handleFocusLost(this);
}
}
if (event.active.state & SDL_APPACTIVE)
{
// Change in iconification/minimization state.
if ((!event.active.gain) != mIsMinimized)
{
mIsMinimized = (!event.active.gain);
mCallbacks->handleActivate(this, !mIsMinimized);
lldebugs << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl;
}
else
{
llinfos << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << llendl;
}
}
break;
case SDL_QUIT:
if(mCallbacks->handleCloseRequest(this))
{
// Get the app to initiate cleanup.
mCallbacks->handleQuit(this);
// The app is responsible for calling destroyWindow when done with GL
}
break;
default:
//llinfos << "Unhandled SDL event type " << event.type << llendl;
break;
} }
} }