I picked up SDL2 and spent the last few hours experimenting with different window moving/sizing/redrawing APIs:
SDL_SetWindowPosition(window, newWindowPos.x, newWindowPos.y);
SDL_SetWindowSize(window, newWindowSize.x, newWindowSize.y);
SetWindowPos(windowHandle, nullptr, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, SWP_SHOWWINDOW);
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
and
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
InvalidateRect(windowHandle, &windowRect, TRUE);
I've learned that the SDL APIs do okay with slow, small drags, but larger, faster drags trigger the visual glitch you describe.
SetWindowPos
and MoveWindow
seem almost identical - both work correctly on my system. There is some glitching on the left edge of the window during dragging, but this is consistent with the behavior of other windows on my system. The right edge stays visually fixed in place without glitching. I would probably pick the MoveWindow
call for a permanent solution, although that's mostly gut feeling based on how the different API setups ran. YMMV.
InvalidateRect
doesn't seem to make any difference in how things are drawn. It does not exacerbate the left-border glitch I mentioned, nor does it alleviate it. I would guess this is because I specified a redrawing flag for the MoveWindow
call.
For reference, here's the code I used for testing. I just commented/uncommented the relevant APIs and rebuilt the project as needed. Sorry about the messiness - I was more interested in getting something up and running than making the code look perfect. Let me know if you'd like me to clean it up a bit.
#include <windows.h>
#include <SDL.h>
#include <SDL_syswm.h>
#include <stdio.h>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
struct Point
{
int x;
int y;
};
int main(int argc, char* args[])
{
bool quit = false, dragging = false;
SDL_Window* window = NULL;
SDL_Surface* screenSurface = NULL;
SDL_Event e;
SDL_SysWMinfo windowInfo;
HWND windowHandle;
Point mousePos, windowPos, newWindowPos, newWindowSize, mWindowResizeOffset;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS);
if(window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
screenSurface = SDL_GetWindowSurface(window);
SDL_VERSION(&windowInfo.version);
SDL_GetWindowWMInfo(window, &windowInfo);
windowHandle = windowInfo.info.win.window;
while(!quit)
{
while(SDL_PollEvent(&e) != 0)
{
switch(e.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_WINDOWEVENT:
if(e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
screenSurface = SDL_GetWindowSurface(window);
}
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0xA2, 0xE8));
SDL_UpdateWindowSurface(window);
break;
case SDL_MOUSEBUTTONDOWN:
SDL_GetMouseState(&mWindowResizeOffset.x, &mWindowResizeOffset.y);
SDL_GetWindowPosition(window, &windowPos.x, &windowPos.y);
dragging = true;
break;
case SDL_MOUSEBUTTONUP:
dragging = false;
break;
case SDL_MOUSEMOTION:
if(dragging)
{
SDL_GetMouseState(&mousePos.x, &mousePos.y);
SDL_GetWindowPosition(window, &newWindowPos.x, &newWindowPos.y);
SDL_GetWindowSize(window, &newWindowSize.x, &newWindowSize.y);
newWindowPos.x = newWindowPos.x + mousePos.x - mWindowResizeOffset.x;
newWindowSize.x += windowPos.x - newWindowPos.x;
MoveWindow(windowHandle, newWindowPos.x, newWindowPos.y, newWindowSize.x, newWindowSize.y, TRUE);
windowPos = newWindowPos;
}
break;
}
}
SDL_Delay(1);
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
SDL_SetWindowPosition
andSDL_SetWindowSize
causes these jumps. – ysalmi