[SDL 1.3] Simulating modal windows and SDL_RaiseWindow()

Hello,

I’m trying to simulate a modal window behavior with SDL, but I don’t
seem to be able to do it. I’m testing this on Kubuntu 8.04 (Linux,
KDE3), 10.04 and 10.10 (Linux, KDE4). I’m using the last (from a few
hours ago) SDL mercurial repository revision.

What I want is apparently simple: a main window creates a second
window to, for example, show a message to the user and waits for it to
be closed before allowing the user to change focus back to the main
window – what’s usually called a “modal” or “dialog” window (can also
be called a “transient window” on X11 terms, but it’s not exactly what
I want).

SDL 1.3 doesn’t seem to have any function to change the input focus to
some window, but at least I was expecting for SDL_RaiseWindow() to
work and force the “modal” window on top and then just ignore input on
the main window if it had the focus.

But SDL_RaiseWindow() doesn’t seem to do nothing. I checked the SDL
source and XRaiseWindow() is called, but also doesn’t seem to do
nothing.

Can someone please point me to what I’m doing wrong?

This minimal test program shows what I’m doing:

------ test_sdl_raise.c ------------------------------

#include “SDL.h”

int main( void )
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Window *win = SDL_CreateWindow( “Main Window”, -1,-1, 300,200,
SDL_WINDOW_SHOWN );
SDL_Window *modal = NULL;
SDL_Event ev;
int quit = 0;
int id;

while ( !quit && SDL_WaitEvent(&ev) )
{
    SDL_Window *cur = NULL;
    switch ( ev.type )
    {
    case SDL_QUIT:
        quit = 1;
        break;
    case SDL_KEYUP:
        id = ev.key.windowID;
        cur = SDL_GetWindowFromID( id );
        if ( cur == win && ev.key.keysym.sym == 0x1B )
            quit = 1;
        break;
    case SDL_WINDOWEVENT:
        id = ev.window.windowID;
        cur = SDL_GetWindowFromID( id );
        switch ( ev.window.event )
        {
        case SDL_WINDOWEVENT_CLOSE:
            if ( modal && cur == modal )
            {
                SDL_DestroyWindow( modal );
                modal = NULL;
            }
            break;
        case SDL_WINDOWEVENT_FOCUS_GAINED:
            printf( "SDL_WINDOWEVENT_FOCUS_GAINED - Window %d\n", id );
            if ( modal && cur != modal )
            {   /* FIXME:
                 *  Do something to switch input focus back to modal window
                 */
                SDL_RaiseWindow( modal );
            }
            break;
        }
        break;
    case SDL_MOUSEBUTTONUP:
        if ( !modal )
            modal = SDL_CreateWindow( "Modal Window", -1,-1, 200,100,
                                      SDL_WINDOW_SHOWN );
        break;
    }
}

if ( modal )
    SDL_DestroyWindow( modal );
SDL_DestroyWindow( win );
SDL_Quit( );

return 0;

}
------ test_sdl_raise.c ------------------------------

Thanks in advance for any pointers.

Regards,
~Nuno Lucas

Since both windows are controlled by the same event loop, you should be able
to “fake” focus, unless the issue is that you want the window to be in front
of the others.
-OzOn Wed, May 4, 2011 at 9:04 PM, Nuno Lucas wrote:

Hello,

I’m trying to simulate a modal window behavior with SDL, but I don’t
seem to be able to do it. I’m testing this on Kubuntu 8.04 (Linux,
KDE3), 10.04 and 10.10 (Linux, KDE4). I’m using the last (from a few
hours ago) SDL mercurial repository revision.

What I want is apparently simple: a main window creates a second
window to, for example, show a message to the user and waits for it to
be closed before allowing the user to change focus back to the main
window – what’s usually called a “modal” or “dialog” window (can also
be called a “transient window” on X11 terms, but it’s not exactly what
I want).

SDL 1.3 doesn’t seem to have any function to change the input focus to
some window, but at least I was expecting for SDL_RaiseWindow() to
work and force the “modal” window on top and then just ignore input on
the main window if it had the focus.

But SDL_RaiseWindow() doesn’t seem to do nothing. I checked the SDL
source and XRaiseWindow() is called, but also doesn’t seem to do
nothing.

Can someone please point me to what I’m doing wrong?

This minimal test program shows what I’m doing:

------ test_sdl_raise.c ------------------------------

#include “SDL.h”

int main( void )
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Window *win = SDL_CreateWindow( “Main Window”, -1,-1, 300,200,
SDL_WINDOW_SHOWN );
SDL_Window *modal = NULL;
SDL_Event ev;
int quit = 0;
int id;

while ( !quit && SDL_WaitEvent(&ev) )
{
SDL_Window cur = NULL;
switch ( ev.type )
{
case SDL_QUIT:
quit = 1;
break;
case SDL_KEYUP:
id = ev.key.windowID;
cur = SDL_GetWindowFromID( id );
if ( cur == win && ev.key.keysym.sym == 0x1B )
quit = 1;
break;
case SDL_WINDOWEVENT:
id = ev.window.windowID;
cur = SDL_GetWindowFromID( id );
switch ( ev.window.event )
{
case SDL_WINDOWEVENT_CLOSE:
if ( modal && cur == modal )
{
SDL_DestroyWindow( modal );
modal = NULL;
}
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
printf( “SDL_WINDOWEVENT_FOCUS_GAINED - Window %d\n”, id );
if ( modal && cur != modal )
{ /
FIXME:
* Do something to switch input focus back to modal
window
*/
SDL_RaiseWindow( modal );
}
break;
}
break;
case SDL_MOUSEBUTTONUP:
if ( !modal )
modal = SDL_CreateWindow( “Modal Window”, -1,-1, 200,100,
SDL_WINDOW_SHOWN );
break;
}
}

if ( modal )
SDL_DestroyWindow( modal );
SDL_DestroyWindow( win );
SDL_Quit( );

return 0;
}
------ test_sdl_raise.c ------------------------------

Thanks in advance for any pointers.

Regards,
~Nuno Lucas


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Since both windows are controlled by the same event loop, you should be able
to “fake” focus, unless the issue is that you want the window to be in front
of the others.

Right. I thought I was explicit about that.
The problem is SDL_RaiseWindow() doesn’t seem to do the latter.

The problem I want to solve is that if I show a small message box over
my main window to the user (like a confirmation dialog), and the user
clicks the main window by mistake, then he will need to go to the task
bar to show the message window again (or use Alt+TAB), which it’s
terrible for a non-technical user (and pretty irritant to a technical
one).

Regards,
~Nuno LucasOn Thu, May 5, 2011 at 02:51, Alex Barry <alex.barry at gmail.com> wrote:

-Oz

On Wed, May 4, 2011 at 9:04 PM, Nuno Lucas <@Nuno_Lucas> wrote:

Hello,

I’m trying to simulate a modal window behavior ?with SDL, but I don’t
seem to be able to do it. I’m testing this on Kubuntu 8.04 (Linux,
KDE3), 10.04 and 10.10 (Linux, KDE4). I’m using the last (from a few
hours ago) SDL mercurial repository revision.

What I want is apparently simple: a main window creates a second
window to, for example, show a message to the user and waits for it to
be closed before allowing the user to change focus back to the main
window – what’s usually called a “modal” or “dialog” window (can also
be called a “transient window” on X11 terms, but it’s not exactly what
I want).

SDL 1.3 doesn’t seem to have any function to change the input focus to
some window, but at least I was expecting for SDL_RaiseWindow() to
work and force the “modal” window on top and then just ignore input on
the main window if it had the focus.

But SDL_RaiseWindow() doesn’t seem to do nothing. I checked the SDL
source and XRaiseWindow() is called, but also doesn’t seem to do
nothing.

Can someone please point me to what I’m doing wrong?

This minimal test program shows what I’m doing:

------ test_sdl_raise.c ------------------------------

#include “SDL.h”

int main( void )
{
? ?SDL_Init( SDL_INIT_VIDEO );
? ?SDL_Window *win = SDL_CreateWindow( “Main Window”, -1,-1, 300,200,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SDL_WINDOW_SHOWN );
? ?SDL_Window *modal = NULL;
? ?SDL_Event ev;
? ?int quit = 0;
? ?int id;

? ?while ( !quit && SDL_WaitEvent(&ev) )
? ?{
? ? ? ?SDL_Window cur = NULL;
? ? ? ?switch ( ev.type )
? ? ? ?{
? ? ? ?case SDL_QUIT:
? ? ? ? ? ?quit = 1;
? ? ? ? ? ?break;
? ? ? ?case SDL_KEYUP:
? ? ? ? ? ?id = ev.key.windowID;
? ? ? ? ? ?cur = SDL_GetWindowFromID( id );
? ? ? ? ? ?if ( cur == win && ev.key.keysym.sym == 0x1B )
? ? ? ? ? ? ? ?quit = 1;
? ? ? ? ? ?break;
? ? ? ?case SDL_WINDOWEVENT:
? ? ? ? ? ?id = ev.window.windowID;
? ? ? ? ? ?cur = SDL_GetWindowFromID( id );
? ? ? ? ? ?switch ( ev.window.event )
? ? ? ? ? ?{
? ? ? ? ? ?case SDL_WINDOWEVENT_CLOSE:
? ? ? ? ? ? ? ?if ( modal && cur == modal )
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?SDL_DestroyWindow( modal );
? ? ? ? ? ? ? ? ? ?modal = NULL;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case SDL_WINDOWEVENT_FOCUS_GAINED:
? ? ? ? ? ? ? ?printf( “SDL_WINDOWEVENT_FOCUS_GAINED - Window %d\n”, id );
? ? ? ? ? ? ? ?if ( modal && cur != modal )
? ? ? ? ? ? ? ?{ ? /
FIXME:
? ? ? ? ? ? ? ? ? ? * ?Do something to switch input focus back to modal
window
? ? ? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? ? ? ?SDL_RaiseWindow( modal );
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?}
? ? ? ? ? ?break;
? ? ? ?case SDL_MOUSEBUTTONUP:
? ? ? ? ? ?if ( !modal )
? ? ? ? ? ? ? ?modal = SDL_CreateWindow( “Modal Window”, -1,-1, 200,100,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SDL_WINDOW_SHOWN );
? ? ? ? ? ?break;
? ? ? ?}
? ?}

? ?if ( modal )
? ? ? ?SDL_DestroyWindow( modal );
? ?SDL_DestroyWindow( win );
? ?SDL_Quit( );

? ?return 0;
}
------ test_sdl_raise.c ------------------------------

Thanks in advance for any pointers.

Regards,
~Nuno Lucas


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I would think SDL_Grab should do the trick
http://wiki.libsdl.org/moin.cgi/SDL_SetWindowGrab?highlight=(\bCategoryVideo\b)|(CategoryEnum)|(CategoryStruct)
http://wiki.libsdl.org/moin.cgi/SDL_SetWindowGrab?highlight=(\bCategoryVideo\b)|(CategoryEnum)|(CategoryStruct)
-OzOn Wed, May 4, 2011 at 10:30 PM, Nuno Lucas wrote:

On Thu, May 5, 2011 at 02:51, Alex Barry <@Alex_Barry> wrote:

Since both windows are controlled by the same event loop, you should be
able
to “fake” focus, unless the issue is that you want the window to be in
front
of the others.

Right. I thought I was explicit about that.
The problem is SDL_RaiseWindow() doesn’t seem to do the latter.

The problem I want to solve is that if I show a small message box over
my main window to the user (like a confirmation dialog), and the user
clicks the main window by mistake, then he will need to go to the task
bar to show the message window again (or use Alt+TAB), which it’s
terrible for a non-technical user (and pretty irritant to a technical
one).

Regards,
~Nuno Lucas

-Oz

On Wed, May 4, 2011 at 9:04 PM, Nuno Lucas wrote:

Hello,

I’m trying to simulate a modal window behavior with SDL, but I don’t
seem to be able to do it. I’m testing this on Kubuntu 8.04 (Linux,
KDE3), 10.04 and 10.10 (Linux, KDE4). I’m using the last (from a few
hours ago) SDL mercurial repository revision.

What I want is apparently simple: a main window creates a second
window to, for example, show a message to the user and waits for it to
be closed before allowing the user to change focus back to the main
window – what’s usually called a “modal” or “dialog” window (can also
be called a “transient window” on X11 terms, but it’s not exactly what
I want).

SDL 1.3 doesn’t seem to have any function to change the input focus to
some window, but at least I was expecting for SDL_RaiseWindow() to
work and force the “modal” window on top and then just ignore input on
the main window if it had the focus.

But SDL_RaiseWindow() doesn’t seem to do nothing. I checked the SDL
source and XRaiseWindow() is called, but also doesn’t seem to do
nothing.

Can someone please point me to what I’m doing wrong?

This minimal test program shows what I’m doing:

------ test_sdl_raise.c ------------------------------

#include “SDL.h”

int main( void )
{
SDL_Init( SDL_INIT_VIDEO );
SDL_Window *win = SDL_CreateWindow( “Main Window”, -1,-1, 300,200,
SDL_WINDOW_SHOWN );
SDL_Window *modal = NULL;
SDL_Event ev;
int quit = 0;
int id;

while ( !quit && SDL_WaitEvent(&ev) )
{
SDL_Window *cur = NULL;
switch ( ev.type )
{
case SDL_QUIT:
quit = 1;
break;
case SDL_KEYUP:
id = ev.key.windowID;
cur = SDL_GetWindowFromID( id );
if ( cur == win && ev.key.keysym.sym == 0x1B )
quit = 1;
break;
case SDL_WINDOWEVENT:
id = ev.window.windowID;
cur = SDL_GetWindowFromID( id );
switch ( ev.window.event )
{
case SDL_WINDOWEVENT_CLOSE:
if ( modal && cur == modal )
{
SDL_DestroyWindow( modal );
modal = NULL;
}
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
printf( “SDL_WINDOWEVENT_FOCUS_GAINED - Window %d\n”, id
);

           if ( modal && cur != modal )
           {   /* FIXME:
                *  Do something to switch input focus back to modal

window
*/
SDL_RaiseWindow( modal );
}
break;
}
break;
case SDL_MOUSEBUTTONUP:
if ( !modal )
modal = SDL_CreateWindow( “Modal Window”, -1,-1, 200,100,
SDL_WINDOW_SHOWN );
break;
}
}

if ( modal )
SDL_DestroyWindow( modal );
SDL_DestroyWindow( win );
SDL_Quit( );

return 0;
}
------ test_sdl_raise.c ------------------------------

Thanks in advance for any pointers.

Regards,
~Nuno Lucas


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I would think SDL_Grab should do the trick
http://wiki.libsdl.org/moin.cgi/SDL_SetWindowGrab?highlight=(\bCategoryVideo\b)|(CategoryEnum)|(CategoryStruct)

No, that would make the user unable to move out of the window (not
even Alt+TAB would work if not explicitly handled by the application).
That’s only desirable on full-screen or virtual machines (e.g. qemu) scenarios.

Regards,
~Nuno Lucas

-Oz

Since both windows are controlled by the same event loop, you should be
able
to “fake” focus, unless the issue is that you want the window to be in
front
of the others.

Right. I thought I was explicit about that.
The problem is SDL_RaiseWindow() doesn’t seem to do the latter.

The problem I want to solve is that if I show a small message box over
my main window to the user (like a confirmation dialog), and the user
clicks the main window by mistake, then he will need to go to the task
bar to show the message window again (or use Alt+TAB), which it’s
terrible for a non-technical user (and pretty irritant to a technical
one).

Regards,
~Nuno Lucas
[…]On Thu, May 5, 2011 at 03:35, Alex Barry <alex.barry at gmail.com> wrote:
On Wed, May 4, 2011 at 10:30 PM, Nuno Lucas <@Nuno_Lucas> wrote:

On Thu, May 5, 2011 at 02:51, Alex Barry <alex.barry at gmail.com> wrote:

But if you were to grab the input, then stop grabbing, it should force it to
be the “front” window - but it’s sort of hackish

SDL_Grab( your_window, SDL_TRUE ); SDL_Grab( your_window, SDL_FALSE );On Wed, May 4, 2011 at 10:52 PM, Nuno Lucas wrote:

On Thu, May 5, 2011 at 03:35, Alex Barry <@Alex_Barry> wrote:

I would think SDL_Grab should do the trick

http://wiki.libsdl.org/moin.cgi/SDL_SetWindowGrab?highlight=(\bCategoryVideo\b)|(CategoryEnum)|(CategoryStruct)

No, that would make the user unable to move out of the window (not
even Alt+TAB would work if not explicitly handled by the application).
That’s only desirable on full-screen or virtual machines (e.g. qemu)
scenarios.

Regards,
~Nuno Lucas

-Oz

On Wed, May 4, 2011 at 10:30 PM, Nuno Lucas wrote:

On Thu, May 5, 2011 at 02:51, Alex Barry <@Alex_Barry> wrote:

Since both windows are controlled by the same event loop, you should
be

able
to “fake” focus, unless the issue is that you want the window to be in
front
of the others.

Right. I thought I was explicit about that.
The problem is SDL_RaiseWindow() doesn’t seem to do the latter.

The problem I want to solve is that if I show a small message box over
my main window to the user (like a confirmation dialog), and the user
clicks the main window by mistake, then he will need to go to the task
bar to show the message window again (or use Alt+TAB), which it’s
terrible for a non-technical user (and pretty irritant to a technical
one).

Regards,
~Nuno Lucas
[…]


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I tried it, but it doesn’t work. SDL_SetWindowGrab() doesn’t force the
window to the front and SDL_RaiseWindow() doesn’t seem to work.

Thanks
~Nuno LucasOn Thu, May 5, 2011 at 03:55, Alex Barry <alex.barry at gmail.com> wrote:

But if you were to grab the input, then stop grabbing, it should force it to
be the “front” window - but it’s sort of hackish

SDL_Grab( your_window, SDL_TRUE );?SDL_Grab( your_window, SDL_FALSE );