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.
//Using SDL and standard IO
#include <windows.h>
#include <SDL.h>
#include <SDL_syswm.h>
#include <stdio.h>
//Screen dimension constants
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;
//The window we'll be rendering to
SDL_Window* window = NULL;
//The surface contained by the window
SDL_Surface* screenSurface = NULL;
SDL_Event e;
SDL_SysWMinfo windowInfo;
HWND windowHandle;
Point mousePos, windowPos, newWindowPos, newWindowSize, mWindowResizeOffset;
//Initialize SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
//Create window
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS); // | SDL_WINDOW_RESIZABLE
if(window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
//Get window surface
screenSurface = SDL_GetWindowSurface(window);
SDL_VERSION(&windowInfo.version);
SDL_GetWindowWMInfo(window, &windowInfo);
windowHandle = windowInfo.info.win.window;
//While application is running
while(!quit)
{
//Handle events on queue
while(SDL_PollEvent(&e) != 0)
{
//process events
switch(e.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_WINDOWEVENT:
if(e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
screenSurface = SDL_GetWindowSurface(window);
}
//Fill the surface blue
SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0xA2, 0xE8));
//Update the surface
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;
//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);
/*RECT drawRect;
drawRect.left = windowPos.x;
drawRect.top = windowPos.y;
drawRect.right = windowPos.x + newWindowSize.x;
drawRect.bottom = windowPos.y + newWindowSize.y;
InvalidateRect(windowHandle, &drawRect, TRUE);*/
windowPos = newWindowPos;
}
break;
}
}
SDL_Delay(1);
}
}
}
//Destroy window
SDL_DestroyWindow(window);
//Quit SDL subsystems
SDL_Quit();
return 0;
}