Window/surface dimensions mismatch problem

Greetings,

I have SDL+OpenGL window resizing working fine, except for one problem. The
short decription is: SDL always wants SDL apps to specify their initial
window size, and to somehow know what that size should be. As far as I can
see, SDL does not provide a means for an SDL app to create its initial window
at a size requested by a Window manager.

Now for the long version: Sometimes a window manager has its own ideas about
what size a window should be. Actually, this is nice for users, as they
generally do not like it when an application window re-appears in a different
place than they last placed it, or at a different size than they last set it
to. In KDE, the ability to teach this behaviour to applications that don’t
understand such niceties is provided through the “store settings” option in
the window menu. When this option is set, instead of creating the
application’s window at the size specified by the application, KDE’s window
manager creates the window at a size and location it stored previously.

An SDL app with a resizable window doesn’t play nicely with this KDE feature,
in that it will go ahead and create the surface at the size it thinks is
right. This may not be the size of the window that the window manager
actually created, which results in a nasty mismatch that doesn’t go away
until a window resize event is received, probably generated by an irritated
user.

What to do about this? I don’t know, this seems a little messy, and I’m not
prepared to make a concrete suggestion or offer a patch at this point. Have
I missed something obvious?

Regards,

Daniel

An SDL app with a resizable window doesn’t play nicely with this KDE feature,
in that it will go ahead and create the surface at the size it thinks is
right. This may not be the size of the window that the window manager
actually created, which results in a nasty mismatch that doesn’t go away
until a window resize event is received, probably generated by an irritated
user.

SDL_SetVideoMode returns an SDL_Surface; the height and width values in
it should be the real dimensions of the window, which might be different
than requested. Are they being set? Use them instead of the values you
gave to SDL.

Aside:

Be careful not to actually change what you request. One bug I
encountered was that I was overwriting the “desired” resolution/dimensions
with those returned by SDL_SetVideoMode. With my 1024x768 screen, I
often get screens around 1024x760 in a window, since SDL makes it a
little smaller in Windows (to keep the titlebar on screen), then when
switching to fullscreen I was asking for 1024x760, which failed, of
course. Oops.

What to do about this? I don’t know, this seems a little messy, and I’m not
prepared to make a concrete suggestion or offer a patch at this point. Have
I missed something obvious?

Check the above. If the values returned in the SDL_Surface aren’t the
actual active window dimensions, there’s probably a bug somewhere.On Mon, Jan 13, 2003 at 03:59:15AM +0100, Daniel Phillips wrote:


Glenn Maynard

An SDL app with a resizable window doesn’t play nicely with this KDE
feature, in that it will go ahead and create the surface at the size it
thinks is right. This may not be the size of the window that the window
manager actually created, which results in a nasty mismatch that doesn’t
go away until a window resize event is received, probably generated by an
irritated user.

SDL_SetVideoMode returns an SDL_Surface; the height and width values in
it should be the real dimensions of the window, which might be different
than requested. Are they being set? Use them instead of the values you
gave to SDL.

I’m glad to here it’s supposed to work that way. Unfortunately, it doesn’t.
Here’s my code:

errcode set_videosize(unsigned xpix, unsigned ypix, unsigned flags)
{
const SDL_VideoInfo *video;
SDL_Surface *surface;

if (!(video = SDL_GetVideoInfo())) return -1; // ??? need this or SetVideoMode doesn't work
surface = SDL_SetVideoMode(xpix, ypix, video->vfmt->BitsPerPixel, flags);
if (!(video = SDL_GetVideoInfo())) return -2;

xpix = surface->w;
ypix = surface->h;
glViewport(0, 0, xpix, ypix);

}

I’d expect xpix and ypix to be updated to the actual window size, but this
does not happen. Now that I know it’s supposed to, I can investigate why.

Aside:

Be careful not to actually change what you request. One bug I
encountered was that I was overwriting the “desired” resolution/dimensions
with those returned by SDL_SetVideoMode. With my 1024x768 screen, I
often get screens around 1024x760 in a window, since SDL makes it a
little smaller in Windows (to keep the titlebar on screen), then when
switching to fullscreen I was asking for 1024x760, which failed, of
course. Oops.

I use the fullscreen dimensions as returned by SDL_ListModes. In that case,
the non-fullscreen dimensions need to be remembered, as this isn’t just a
toggle any more. On that note, it seems to me that SDL_ToggleFullscreen has
got a pretty big disconnect in that it tries to use the windowed dimensions
of the surface in fullscreen mode.

What to do about this? I don’t know, this seems a little messy, and I’m
not prepared to make a concrete suggestion or offer a patch at this
point. Have I missed something obvious?

Check the above. If the values returned in the SDL_Surface aren’t the
actual active window dimensions, there’s probably a bug somewhere.

They aren’t, and yup, it smells like a bug. I’m glad it’s that and not a
design problem.

Regards,

DanielOn Monday 13 January 2003 04:15, Glenn Maynard wrote:

On Mon, Jan 13, 2003 at 03:59:15AM +0100, Daniel Phillips wrote:

That’s how the code I’m using is written, and that’s how it seems to
work. Don’t take my word for it. :slight_smile: (But it seems to make sense; in
the case of window sizes, many environments probably can’t easily tell
you how big a window will be without actually creating one.)On Mon, Jan 13, 2003 at 04:45:56AM +0100, Daniel Phillips wrote:

I’m glad to here it’s supposed to work that way. Unfortunately, it doesn’t.


Glenn Maynard

I’m looking through X11_CreateWindow in SDL_x11video.c and I do not see
where (XWindowAttributes)a.width and .height are accessed to set the surface
dimensions to the actual window dimensions. I think I don’t see it because
it’s not there, which would explain the behaviour I get.

Are you using X?

Regards,

DanielOn Monday 13 January 2003 04:50, Glenn Maynard wrote:

On Mon, Jan 13, 2003 at 04:45:56AM +0100, Daniel Phillips wrote:

I’m glad to here it’s supposed to work that way. Unfortunately, it
doesn’t.

That’s how the code I’m using is written, and that’s how it seems to
work. Don’t take my word for it. :slight_smile: (But it seems to make sense; in
the case of window sizes, many environments probably can’t easily tell
you how big a window will be without actually creating one.)

Nope. The behavior I described happens in Windows.

Do the docs say anything about this? If they don’t say anything at all,
then it’s just implementation differences, and Sam might want to
document which is correct so it can be made more consistent. If he’ll
confirm that the behavior I described what’s intended in these
circumstances, then he might accept a patch to handle that in X.On Mon, Jan 13, 2003 at 05:13:53AM +0100, Daniel Phillips wrote:

I’m looking through X11_CreateWindow in SDL_x11video.c and I do not see
where (XWindowAttributes)a.width and .height are accessed to set the surface
dimensions to the actual window dimensions. I think I don’t see it because
it’s not there, which would explain the behaviour I get.

Are you using X?


Glenn Maynard

I don’t see how anything other than the requirement to confirm the actual
dimensions could be considered correct. I suspect this slipped through the
cracks because surface resizing is a relatively recent feature. The docs
don’t have anything to say about it, probably for the same reason.

Regards,

DanielOn Monday 13 January 2003 05:23, Glenn Maynard wrote:

On Mon, Jan 13, 2003 at 05:13:53AM +0100, Daniel Phillips wrote:

I’m looking through X11_CreateWindow in SDL_x11video.c and I do not see
where (XWindowAttributes)a.width and .height are accessed to set the
surface dimensions to the actual window dimensions. I think I don’t see
it because it’s not there, which would explain the behaviour I get.

Are you using X?

Nope. The behavior I described happens in Windows.

Do the docs say anything about this? If they don’t say anything at all,
then it’s just implementation differences, and Sam might want to
document which is correct so it can be made more consistent. If he’ll
confirm that the behavior I described what’s intended in these
circumstances, then he might accept a patch to handle that in X.

As a preliminary step in tracking down the X window/OpenGL window size mismatch, I
modified X11_GL_CreateWindow to read as follows:

int X11_GL_CreateWindow(_THIS, int w, int h)
{
int retval;
#ifdef HAVE_OPENGL
XSetWindowAttributes attributes;
unsigned long mask;
unsigned long black;

black = (glx_visualinfo->visual == DefaultVisual(SDL_Display,
					 	SDL_Screen))
       	? BlackPixel(SDL_Display, SDL_Screen) : 0;
attributes.background_pixel = black;
attributes.border_pixel = black;
attributes.colormap = SDL_XColorMap;
mask = CWBackPixel | CWBorderPixel | CWColormap;

SDL_Window = XCreateWindow(SDL_Display, WMwindow,
		0, 0, w, h, 0, glx_visualinfo->depth,
		InputOutput, glx_visualinfo->visual,
		mask, &attributes);
if ( !SDL_Window ) {
	SDL_SetError("Could not create window");
	return -1;
}
{
	XWindowAttributes attributes;
	XGetWindowAttributes(SDL_Display, SDL_Window, &attributes);
	printf("Requested size: (%i, %i); got (%i, %i)\n", w, h, attributes.width, attributes.height);
}
retval = 0;

#else
SDL_SetError(“X11 driver not configured with OpenGL”);
retval = -1;
#endif
return(retval);
}

I run this under KDE, having selected “Store Settings” on the KDE window on a
previous run, and supply w=640, h=480 to SDL_SetVideoMode. To my surprise and
displeasure, even when the created/displayed window is not in fact the requested
size, I always see:

Requested size: (640, 480); got (640, 480)

In other words, X is telling SDL that the window is 640 x 480, even though it is
displaying some other size. I say “displeasure”, because if I’d been able to detect
the mismatch at this point I’d be well on my way to producing a patch by now. As
it stands, I have to admit that the mechanism involved is more convoluted than I
thought. It probably requires exploring the KDE and/or QT source, which would be
more of a time commitment that I was expecting. Bob, perhaps you can shed some
light on this?

The first time I get an SDL window resize event and act on it, everything snaps
properly into place. But this isn’t a good situation, it means resizable SDL
windows are broken on KDE, so this needs to be tracked down.

On the positive size, it turns out that my SDL+OpenGL application runs perfectly
with no window manager at all, which is an interesting fact that suggests a fun
project, namely an SDL+OpenGL-based hardware-accelerated desktop.

Regards,

Daniel

As a preliminary step in tracking down the X window/OpenGL window size mismatch, I
modified X11_GL_CreateWindow to read as follows:

int X11_GL_CreateWindow(_THIS, int w, int h)
{
int retval;
#ifdef HAVE_OPENGL
XSetWindowAttributes attributes;
unsigned long mask;
unsigned long black;

black = (glx_visualinfo->visual == DefaultVisual(SDL_Display,
SDL_Screen))
? BlackPixel(SDL_Display, SDL_Screen) : 0;
attributes.background_pixel = black;
attributes.border_pixel = black;
attributes.colormap = SDL_XColorMap;
mask = CWBackPixel | CWBorderPixel | CWColormap;

SDL_Window = XCreateWindow(SDL_Display, WMwindow,
0, 0, w, h, 0, glx_visualinfo->depth,
InputOutput, glx_visualinfo->visual,
mask, &attributes);
if ( !SDL_Window ) {
SDL_SetError(“Could not create window”);
return -1;
}
{
XWindowAttributes attributes;
XGetWindowAttributes(SDL_Display, SDL_Window, &attributes);
printf(“Requested size: (%i, %i); got (%i, %i)\n”, w, h, attributes.width, attributes.height);
}
retval = 0;
#else
SDL_SetError(“X11 driver not configured with OpenGL”);
retval = -1;
#endif
return(retval);
}

I run this under KDE, having selected “Store Settings” on the KDE window on a
previous run, and supply w=640, h=480 to SDL_SetVideoMode. To my surprise and
displeasure, even when the created/displayed window is not in fact the requested
size, I always see:

Requested size: (640, 480); got (640, 480)

In other words, X is telling SDL that the window is 640 x 480, even though it is
displaying some other size. I say “displeasure”, because if I’d been able to detect
the mismatch at this point I’d be well on my way to producing a patch by now. As
it stands, I have to admit that the mechanism involved is more convoluted than I
thought. It probably requires exploring the KDE and/or QT source, which would be
more of a time commitment that I was expecting. Bob, perhaps you can shed some
light on this?

I know I replied privately, but for the rest of you, what can I say, I
haven’t been following this thread. And, I’ve either never run into, or
never noticed this problem. Could be because I use GNOME, but I doubt
it.

Could you explain how you know the displayed size is wrong?

	Bob PendletonOn Mon, 2003-01-13 at 16:38, Daniel Phillips wrote:

The first time I get an SDL window resize event and act on it, everything snaps
properly into place. But this isn’t a good situation, it means resizable SDL
windows are broken on KDE, so this needs to be tracked down.

On the positive size, it turns out that my SDL+OpenGL application runs perfectly
with no window manager at all, which is an interesting fact that suggests a fun
project, namely an SDL+OpenGL-based hardware-accelerated desktop.

Regards,

Daniel


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-----------------------------------+

Could you explain how you know the displayed size is wrong?

Err, first message in this thread:On Tue, Jan 14, 2003 at 07:40:12AM -0600, Bob Pendleton wrote:

Now for the long version: Sometimes a window manager has its own ideas about
what size a window should be. Actually, this is nice for users, as they
generally do not like it when an application window re-appears in a different
place than they last placed it, or at a different size than they last set it
to. In KDE, the ability to teach this behaviour to applications that don’t
understand such niceties is provided through the “store settings” option in
the window menu. When this option is set, instead of creating the
application’s window at the size specified by the application, KDE’s window
manager creates the window at a size and location it stored previously.


Glenn Maynard

It’s plainly visible on the screen. Either there is a black border around
the OpenGL surface, or only part of my OpenGL surface is displayed. SDL
returns and clamps the mouse coordinates consistently with the dimensions at
which it created the surface, in other words, inconsistent with the actual
window size.

I inserted debug output into SDL_PrivateMouseMotion, and by watching the
mouse coordinates, confirmed that SDL really thinks SDL_VideoSurface->(w,h)
are as specified in SDL_SetVideoMode and as returned by XGetWindowAttributes.
The latter is the real problem. What it means is that X is not telling SDL
the actual size of the created window, or at least, SDL has not asked the
right question. Perhaps there is more than one window involved, and the
"real" window is not the one handed back to SDL. I don’t know, I haven’t
really drilled into this yet.

I also have not tested this with a non-opengl SDL surface, though I believe
the result will be the same, as the same window creation mechanism is used.

I checked Xterm, and it is in fact fooled by a KDE “store settings” window,
as it does not generate linefeeds at the correct place, at least, not until
after it gets its first resize event. Strangely enough, the text output in
the terminal window is aware of the real size of the window, and wraps at the
correct place. However, Xterm will later overwrite some of the wrapped text.
This is a case of one part of X knowing about the real window dimensions and
another part (the Xterm application) not knowing.

Galeon gets it right - when starting up in a KDE “store settings” window, it
always dimensions the html rendering area correctly. Perhaps it is able to
do this because it remembers the last-resized window dimensions in a file in
your home directory. If so, that would require me to do a similar nasty,
disgusting hack, and I would only do that after investigating all other
possibilities. I don’t think this is what’s going on though.

Gfontview gets it right as well. After checking a few times, I did not
notice any disk activity associated with resizing or closing gfontview, so
here we have a good example of Gtk doing the right thing - somehow - whereas
SDL and Xterm do not. I’m interested in what the “somehow” mechanism is.
Now I have a choice of reading the KDE source, the GTK source to find out.
However, I thought it would be worth a try to save some effort, and see if
somebody out there already know’s what’s going on.

DanielOn Tuesday 14 January 2003 14:40, Bob Pendleton wrote:

On Mon, 2003-01-13 at 16:38, Daniel Phillips wrote:

…X is telling SDL that the window is 640 x 480, even
though it is displaying some other size. I say “displeasure”, because if
I’d been able to detect the mismatch at this point I’d be well on my way
to producing a patch by now. As it stands, I have to admit that the
mechanism involved is more convoluted than I thought. It probably
requires exploring the KDE and/or QT source, which would be more of a
time commitment that I was expecting. Bob, perhaps you can shed some
light on this?

I know I replied privately, but for the rest of you, what can I say, I
haven’t been following this thread. And, I’ve either never run into, or
never noticed this problem. Could be because I use GNOME, but I doubt
it.

Could you explain how you know the displayed size is wrong?

Could you explain how you know the displayed size is wrong?

Err, first message in this thread:

Now for the long version: Sometimes a window manager has its own ideas about
what size a window should be. Actually, this is nice for users, as they
generally do not like it when an application window re-appears in a different
place than they last placed it, or at a different size than they last set it
to. In KDE, the ability to teach this behaviour to applications that don’t
understand such niceties is provided through the “store settings” option in
the window menu. When this option is set, instead of creating the
application’s window at the size specified by the application, KDE’s window
manager creates the window at a size and location it stored previously.

Well, yeah, all window managers do that. Like I said, I wasn’t following
the thread and only responded because I was specifically asked to
respond. The experience is rather like day dreaming in math class and
then being asked to solve the problem on the board. :slight_smile:

Anyway, is the KDE window manager sending the application a resize
event? If it is, what’s the problem?

Bob PendletonOn Tue, 2003-01-14 at 13:37, Glenn Maynard wrote:

On Tue, Jan 14, 2003 at 07:40:12AM -0600, Bob Pendleton wrote:


Glenn Maynard


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-----------------------------------+

…The experience is rather like day dreaming in math class and
then being asked to solve the problem on the board. :slight_smile:

Considerable knowledge of X minutae is needed here, which is why I thought of
you.

Anyway, is the KDE window manager sending the application a resize
event? If it is, what’s the problem?

It’s not. The problem manifests at the time of application startup, in the
initial SDL_SetVideoMode.

Anyway, it would be wrong for KDE to take the liberty of sending a resize
event at application startup time, as that would require any just-performed
window initialization work to be discarded without ever being used, which
would be perverse. What I would expect in this case is for X to create the
new window at a size other than that specified by the XCreateWindow call,
requiring the application to take note of this and handle the situation
accordingly. But that is not what is happening. Instead, X returns a window
that is dimensioned at the requested size, a size that does not correspond to
the size of the window actually displayed.

I suspect that there is another window somehow involved, and that the
window being returned to SDL by XCreateWindow is (bizarrely) being clipped to
display within that mysterious other window. This is just a theory, and
actually, it mainly shows how little I know about X at this point.

Daniel

DanielOn Tuesday 14 January 2003 21:24, Bob Pendleton wrote:

I suspect that there is another window somehow involved, and that the
window being returned to SDL by XCreateWindow is (bizarrely) being clipped to
display within that mysterious other window. This is just a theory, and
actually, it mainly shows how little I know about X at this point.

Actually, it sounds like KDE is creating a window on top of the SDL window,
and GTk knows to look for children… at least that’s my impression, I haven’t
actually seen this behavior.

It looks like you’ll have to dig into the source. :slight_smile:

For the record, SDL really is supposed to return a surface the size requested.
The code in the Windows driver is just to handle the bizzare case where the
video mode is exactly the size of the screen and Windows needs to have a title
bar.

See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment

I suspect that there is another window somehow involved, and that the
window being returned to SDL by XCreateWindow is (bizarrely) being
clipped to display within that mysterious other window. This is just a
theory, and actually, it mainly shows how little I know about X at this
point.

Actually, it sounds like KDE is creating a window on top of the SDL window,
and GTk knows to look for children… at least that’s my impression, I
haven’t actually seen this behavior.

I expect I’ll post my demo tomorrow, complete with glitch, then it will be
easy to see.

It looks like you’ll have to dig into the source. :slight_smile:

Yup.

For the record, SDL really is supposed to return a surface the size
requested. The code in the Windows driver is just to handle the bizzare
case where the video mode is exactly the size of the screen and Windows
needs to have a title bar.

I know life would be easier for SDL if you could always create the surface
exactly as the application specified, however, from the horse’s mouth:

“A window manager can override your choice of size, border
width, and position for a top-level window. Your program
must be prepared to use the actual size and position of the
top window. It is not acceptable for a client application
to resize itself unless in direct response to a human com-
mand to do so. Instead, either your program should use the
space given to it, or if the space is too small for any use-
ful work, your program might ask the user to resize the win-
dow. The border of your top-level window is considered fair
game for window managers.”
(James Gettys, http://ftp.xfree86.org/pub/XFree86/4.2.0/doc/xlib.TXT)

So the Windows situation just left no alternative but to do the right thing,
and similarly, KDE’s “store settings” forces that for X.

By the way, I really like SDL, thanks for making it.

Regards,

DanielOn Wednesday 15 January 2003 11:01, Sam Lantinga wrote: