Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: BloodSharp en 22 Febrero 2019, 21:57 pm



Título: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 22 Febrero 2019, 21:57 pm
Buenas gente del foro, tengo una consulta con SDL2 que ojalá algún gurú de esta librería sepa resolver... :-[

Estaba creando una ventana con renderizado en OpenGL y mi problema es que al mover la ventana manteniendo click produce un temblor en el movimiento demasiado extraño. Con WinAPI no tengo problema en mi código pero al portar esto a SDL2 (porque deseo crear la aplicación multiplataforma) produce esa sacudida extraña...

(https://i.imgur.com/DcR1Wb7.gif)

Código
  1.    // Main loop
  2.    bool bOpen = true;
  3.    while (bOpen)
  4.    {
  5.        SDL_Event event;
  6.        static bool bMouseClicked=false;
  7.        static int xMPos=0,yMPos=0;
  8.        while (SDL_PollEvent(&event))
  9.        {
  10.            if(event.type == SDL_MOUSEBUTTONDOWN)
  11.            {
  12.                if(event.button.button == SDL_BUTTON_LEFT)
  13.                {
  14.                    bMouseClicked=true;
  15.                    SDL_CaptureMouse(SDL_TRUE);
  16.                    SDL_GetMouseState(&xMPos,&yMPos);
  17.                }
  18.            }
  19.            if(event.type == SDL_MOUSEBUTTONUP)
  20.            {
  21.                if(event.button.button == SDL_BUTTON_LEFT)
  22.                {
  23.                    bMouseClicked=false;
  24.                    SDL_CaptureMouse(SDL_FALSE);
  25.                }
  26.            }
  27.            if(event.type == SDL_MOUSEMOTION)
  28.            {
  29.                int xPos,yPos,xMPosN,yMPosN;
  30.                if(bMouseClicked)
  31.                {
  32.                    SDL_GetWindowPosition(window,&xPos,&yPos);
  33.                    SDL_GetMouseState(&xMPosN,&yMPosN);
  34.                    xPos+=xMPosN-xMPos;
  35.                    yPos+=yMPosN-yMPos;
  36.                    SDL_SetWindowPosition(window,xPos,yPos);
  37.                    //SDL_FlushEvent(SDL_WINDOWEVENT_MOVED);
  38.                    //SDL_FlushEvents(SDL_WINDOWEVENT,SDL_SYSWMEVENT);
  39.                }
  40.            }
  41.            if (event.type == SDL_QUIT)
  42.                bOpen = false;
  43.        }


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: srWhiteSkull en 23 Febrero 2019, 17:02 pm
...depura en esa parte, quizás tengas el problema ahí,
Código
  1. ...
  2.            if(event.type == SDL_MOUSEMOTION)
  3.            {
  4.                int xPos,yPos,xMPosN,yMPosN;
  5.                if(bMouseClicked)
  6.                {
  7.                    SDL_GetWindowPosition(window,&xPos,&yPos);
  8.                    SDL_GetMouseState(&xMPosN,&yMPosN);
  9.                    xPos+=xMPosN-xMPos; // Puede que sea por esta operación
  10.                    yPos+=yMPosN-yMPos; // Puede que sea por esta operación
  11.                    SDL_SetWindowPosition(window,xPos,yPos);
  12. ...

Si te funciona en otra plataforma entonces deberías crear una macro función que actúe en función de que plataforma por medio de las instrucciones condicionales de preprocesador #if etc...


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 23 Febrero 2019, 20:47 pm
Si te funciona en otra plataforma entonces deberías crear una macro función que actúe en función de que plataforma por medio de las instrucciones condicionales de preprocesador #if etc...

Hola, gracias por responder. He probado recién en Windows y funciona perfectamente sin realizar el temblor por lo que asumo el código está correcto. Por ahora probé unicamente en el escritorio de Deepin voy a probar en distintos, si ocurre el mismo problema en varios voy a reportar el error a los desarrolladores de Valve para que arreglen la librería (porque podré asumir que solamente ocurre en Linux).


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: srWhiteSkull en 23 Febrero 2019, 20:54 pm
Pero depuraste para ver los valores que contienen esos variables? xMpos, xMposN, yMpos y yMposN, quizás simplemente haya que hacer un cambio en la operación porque trabaje de otra forma,


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 23 Febrero 2019, 21:52 pm
Pero depuraste para ver los valores que contienen esos valores? xMpos, xMposN, yMpos y yMposN, quizás simplemente haya que hacer un cambio en la operación porque trabaje de otra forma.

En teoría no debería funcionar diferente, al menos con los resultados devuelto por la librería, dado a que es una librería multiplataforma que debería funcionar con los mismos parámetros de retorno en cualquier sistema.

Por otro lado, me fijé los valores y son correctos: (la ventana es de 400x150)

(https://i.imgur.com/NjWpJCT.gif)

Probaré con KDE, ya probé con gnome y provoca el mismo resultado...


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: CalgaryCorpus en 23 Febrero 2019, 22:16 pm
Que pasa si mueves la instruccion que toma la posicion de la ventana al momento donde se detecta el click del mouse?

osea

Código
  1. SDL_GetWindowPosition(window,&xPos,&yPos);

al interior del
Código
  1. if(event.button.button == SDL_BUTTON_LEFT)

?

(Eliminando donde ahora esta')


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 23 Febrero 2019, 22:22 pm
Que pasa si mueves la instruccion que toma la posicion de la ventana al momento donde se detecta el click del mouse? Al interior del
Código
  1. if(event.button.button == SDL_BUTTON_LEFT)

Pasa lo mismo, supongo que el problema real reside en SDL_SetWindowPosition de Linux...


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: CalgaryCorpus en 23 Febrero 2019, 22:31 pm
En ese caso, tal vez funciona mejor asi?

Código
  1.    // Main loop
  2.    bool bOpen = true;
  3.    while (bOpen)
  4.    {
  5.        SDL_Event event;
  6.        static bool bMouseClicked=false;
  7.        int xPos, yPos;
  8.        static int xMPos=0,yMPos=0;
  9.        while (SDL_PollEvent(&event))
  10.        {
  11.            if(event.type == SDL_MOUSEBUTTONDOWN)
  12.            {
  13.                if(event.button.button == SDL_BUTTON_LEFT && !bMouseClicked)
  14.                {
  15.                    bMouseClicked=true;
  16.                    SDL_GetWindowPosition(window,&xPos,&yPos);
  17.                    SDL_CaptureMouse(SDL_TRUE);
  18.                    SDL_GetMouseState(&xMPos,&yMPos);
  19.                }
  20.            } else
  21.            if(event.type == SDL_MOUSEBUTTONUP)
  22.            {
  23.                if(event.button.button == SDL_BUTTON_LEFT)
  24.                {
  25.                    bMouseClicked=false;
  26.                    SDL_CaptureMouse(SDL_FALSE);
  27.                }
  28.            } else
  29.            if(event.type == SDL_MOUSEMOTION)
  30.            {
  31.                int xMPosN,yMPosN;
  32.                if(bMouseClicked)
  33.                {
  34.                    SDL_GetMouseState(&xMPosN,&yMPosN);
  35.                    xPos+=xMPosN-xMPos;
  36.                    yPos+=yMPosN-yMPos;
  37.                    SDL_SetWindowPosition(window,xPos,yPos);
  38.                }
  39.            } else
  40.            if (event.type == SDL_QUIT)
  41.                bOpen = false;
  42.        }
  43.  


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 23 Febrero 2019, 22:47 pm
En ese caso, tal vez funciona mejor asi?

(https://i.imgur.com/PII6SQp.gif)


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: srWhiteSkull en 23 Febrero 2019, 23:20 pm
Al final funcionó a la manera de CalgaryCorpus. Claro al no hacer un else seguía detectando el evento de pulsado e interfería al mover con el ratón pulsado.

Entonces queda cerrado el tema.

Gracias CalgaryCorpus por tú colaboración  ;-)


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 23 Febrero 2019, 23:43 pm
Al final funcionó a la manera de CalgaryCorpus. Claro al no hacer un else seguía detectando el evento de pulsado e interfería al mover con el ratón pulsado.

De hecho no, el "area no cliente" son los bordes, botones minimizar, maximizar y cerrar de la ventana del escritorio real, lo que yo quiero realizar es lo mismo que hace el "area no cliente" en el "area cliente". Si te fijás otra vez el gif sigue idéntico el comportamiento aún con las modificaciones de @CalgaryCorpus...

Imágen de internet de referencia:
(https://www.codeproject.com/KB/GDI/updatergn/c_vs_nc.gif)


B#


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: srWhiteSkull en 24 Febrero 2019, 00:03 am
Vale, pensaba que querías corregir el salto molesto ese que en el último gif ya no se apreciaba.

Bueno, como no tengo nada que hacer es posible que haga una prueba en una máquinita virtual que tengo con un Ubuntu con gnome. Ya te cuento entonces,


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: srWhiteSkull en 24 Febrero 2019, 19:25 pm
Bueno, fallo, fallo no se puede considerar que sea. Mi conclusión es que debes hacerlo de otra forma, ya que el problema radica cuando el puntero del ratón queda fuera de la ventana y se pierde el foco. Entonces en ese momento para forzar la recuperación del foco usas SDL_CaptureMouse() y ésto permite que los eventos del ratón se puedan seguir capturando fuera de la ventana. Esa parte es la responsable del comportamiento errático del arrastre. Yo conseguí reducirlo un poco, pero ocasionalmente me daba ese salto por ejemplo al pasar el cursor cuando salía del marco por encima del borde de la ventana de la terminal.

(https://drive.google.com/uc?id=1sUBx2BG6up45vzNi3q0f5v8NNS7jVVZk)

Código
  1. #include <SDL2/SDL.h>
  2. #include <stdio.h>
  3.  
  4. #define SCREEN_WIDTH 640
  5. #define SCREEN_HEIGHT 200
  6.  
  7. static bool salida = false;
  8.  
  9. int main(int argc, char* args[]) {
  10.    SDL_Window* window = NULL;
  11.    SDL_Surface* screenSurface = NULL;
  12.    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  13.        fprintf(stderr, "could not initialize sdl2: %s\n", SDL_GetError());
  14.        return 1;
  15.    }
  16.    window = SDL_CreateWindow(
  17.    "hello_sdl2",
  18.    SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  19.    SCREEN_WIDTH, SCREEN_HEIGHT,
  20.    SDL_WINDOW_SHOWN);
  21.  
  22.    if (window == NULL) {
  23.        fprintf(stderr, "could not create window: %s\n", SDL_GetError());
  24.        return 1;
  25.    }
  26.    screenSurface = SDL_GetWindowSurface(window);
  27.    SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF));
  28.    SDL_UpdateWindowSurface(window);
  29.  
  30.    int xPos,yPos,xMPosN,yMPosN;
  31.    static bool bMouseClicked=false, bMouseMoving=false;
  32.    static int xMPos=0,yMPos=0;
  33.    char buffer [50];
  34.    while(!salida){
  35.  
  36.        SDL_Event event;
  37.        while( SDL_PollEvent(&event) ) {
  38.  
  39.            switch(event.type ){
  40.  
  41.                case SDL_MOUSEBUTTONDOWN:
  42.                    if(event.button.button == SDL_BUTTON_LEFT){
  43.                        if (!bMouseClicked) {
  44.                            bMouseClicked=true;
  45.                            SDL_GetMouseState(&xMPos,&yMPos);
  46.                            SDL_GetWindowPosition(window,&xPos,&yPos);
  47.                        }
  48.                    }
  49.  
  50.                break;
  51.                case SDL_MOUSEBUTTONUP:
  52.                    if (bMouseClicked) { // Impedimos que entre varias veces
  53.                        if(event.button.button == SDL_BUTTON_LEFT){
  54.                            bMouseClicked=false;
  55.                            SDL_CaptureMouse(SDL_FALSE);
  56.                        }
  57.                    }
  58.  
  59.                break;
  60.                case SDL_MOUSEMOTION:
  61.  
  62.                    if(bMouseClicked) bMouseMoving = true;
  63.                break;
  64.                case SDL_QUIT:
  65.                    salida = true;
  66.            } // fin switch
  67.  
  68.        } // fin loop de eventos
  69.  
  70.        // renderizamos o dibujamos
  71.        if(bMouseClicked && bMouseMoving){
  72.            SDL_CaptureMouse(SDL_TRUE); // Se desabilita al perder el foco
  73.            SDL_GetMouseState(&xMPosN,&yMPosN);
  74.            xPos-=(xMPos-xMPosN);
  75.            yPos-=(yMPos-yMPosN);
  76.            SDL_SetWindowPosition(window,xPos,yPos);
  77.        }
  78.        sprintf (buffer, "xM=%d yM=%d / xW=%d yW=%d / xCM=%d yCM=%d", xMPosN, yMPosN, xPos, yPos, xMPos, yMPos);
  79.        SDL_SetWindowTitle(window,buffer);
  80.        bMouseMoving = false;
  81.        SDL_Delay(10);
  82.    }
  83.    //SDL_CaptureMouse(SDL_FALSE);
  84.    SDL_DestroyWindow(window);
  85.    SDL_Quit();
  86.    return 0;
  87. }


Título: Re: [Consulta] SDL2 arreglar movimiento de ventana con click
Publicado por: BloodSharp en 24 Febrero 2019, 21:01 pm
(...)Yo conseguí reducirlo un poco, pero ocasionalmente me daba ese salto por ejemplo al pasar el cursos cuando salía del marco por encima del borde de la ventana de la terminal.

¿Un poco? Quedó igual de perfecto que con WinAPI.

¡Gracias por la ayuda! ;-) ;-)  ;-) :-[

(https://i.imgur.com/QlNRsik.gif)

Tema solucionado.


B#