Some problem with touch events with cef and SDL2 - c++

I'm experiencing some problem to getting working touch events with CEF in offscreen rendering using SDL2 in some situation:
Im writing an SDL-CEF application that need to execute some online game into a videolottery. so I start the application from tty using startx and not in DE. Morever, I can't use the mouse but is only possible use touchscreen to interact with the machine.The touch event work pretty well in the most os cases, but with some game the click event is not recognized by the web application.
For pass the correct event to the CEF browser I have written some specialized handler functions that catchs the SDL_Event and converts their to CEF_Event. Fo example for processing tauch events I have a function called handleFingerEvent(SDL_Event, CEF_Browser*). This specialized function is called from a generic handleEvents(SDL_Event, VEF_Browser*) handler function of highter level .
// The Touch Event Hendler function
void handleFingerEvent(SDL_Event &e, CefBrowser* browser) {
CefMouseEvent event;
switch (e.type) {
case SDL_FINGERDOWN:
// W_SIZE and H_SIZE are the dimension of the screen in px
if (e.tfinger.pressure > 0.9) {
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseClickEvent(event,
MBT_LEFT,
false, 1);
}
break;
case SDL_FINGERUP:
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseClickEvent(event, MBT_LEFT, true, 1);
break;
case SDL_FINGERMOTION: {
int scrollX = static_cast<int>(e.tfinger.dx);
int scrollY = static_cast<int>(e.tfinger.dy);
event.x = static_cast<int>(e.tfinger.x*W_SIZE);
event.y = static_cast<int>(e.tfinger.y*H_SIZE);
browser->GetHost()->SendMouseWheelEvent(event, scrollX, scrollY);
break;
}
default:
break;
}
}
void handleEvents(SDL_Event &e, CefBrowser *browser) {
switch (e.type) {
// Key events
case SDL_KEYDOWN:
case SDL_KEYUP:
handleKeyEvent(e, browser);
break;
// Window events
case SDL_WINDOWEVENT:
handleWindowEvent(e, browser);
break;
//Mouse events
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEWHEEL:
handleMouseEvent(e, browser);
break;
// Touch events
case SDL_FINGERDOWN:
case SDL_FINGERMOTION:
case SDL_FINGERUP:
handleFingerEvent(e, browser);
break;
default:
break;
}
}
I call it from a SDL_PollEvent() while loop like this:
browser = CefBrowserHost::CreateBrowserSync(window_info,
browserClient, //My BrowserClient implementation
"https://www.something.sometother",
browserSettings, // The cef setting
nullptr, nullptr);
while(!browserClient->closeAllowed()) {
//Send events to the browser
SDL_Event e;
while(SDL_PollEvent(&e) != 0){
//Quit and window resize
if(e.type == SDL_QUIT) {
browser->GetHost()->CloseBrowser(false);
}
else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
renderHandler->resize(e.window.data1, e.window.data2);
browser->GetHost()->WasResized();
}
else {
handleEvents(e, browser.get());
}
}
// Cef main work loop
cefApp->doCefWork();
//Set background color
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//Clear window/renderer
SDL_RenderClear(renderer);
renderHandler->render();
//Update screen contents
SDL_RenderPresent(renderer);
}
Now I really don't know why in some game the event isn't caught by the browser. Morever if I open the game in a machine with mouse connected and a DM, and so I use the mouse pointer for interact with the game, it works without any problem. Maybe is there a better approach to send a click event to CefBrowser?

Related

SDL_PollEvent() fails to catch SDL_QUIT inside class function?

trying to setup my classes to programm faster with SDL2 - so far evrything worked fine.
But in the end of my last coding session my SDL_PollEvent does no longer catch SDL_QUIT.
I´m using my own SDL_Window class to handle events and other SDL relevant Vars.
In my Window class i have the function loadEvent(), its my gameloop function, and in it i call SDL_PollEvent and right after i check if it is SDL_QUIT and if so it returns a false and ends the gameloop, otherwise it returns true. SDL_PollEvent saves into a private SDL_Event varriable of my class so i can later ask for keys pressed by looking into the event of my window class.
Any keydown event works just fine, i can end my game with esc if i want to, but i never seem to catch SDL_QUIT.
There is no error, it just does not get any SDL_QUIT back.
Any ideas what could be the problem?
Code:
class My_SDL_Window{
private:
SDL_Window* window;
SDL_Surface* surface;
SDL_Renderer* renderer;
SDL_Event sEvent;
My_Object_Node* allObj;
public:
…
bool loadEvent()
{
if(SDL_PollEvent( &sEvent ) != 0)
{
if(sEvent.type == SDL_QUIT)
{
destroy();
return false ;
}
}
return true;
}
You're only checking whether there's an event once every time the program loops.
Replace:
if(SDL_PollEvent( &sEvent ) != 0) , which only checks whether there are any events at all, where you then only act on the first event in that list, with:
while (SDL_PollEvent(&sEvent)) , which loops through every event in the event queue, where you then act on every single event that was performed since the last time you checked.
You need to change how you handle the SDL_PoolEvent() instead a if use while, with this method you will catch all events on pool not only the first one.
For example:
bool quit = false;
SDL_Event event;
while(!quit) {
// Process input
while(SDL_PollEvent(&event) > 0) {
switch(event.type) {
case SDL_QUIT: quit = true; break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_UP: go_up(); break;
case SDLK_DOWN: go_dowm(); break;
// ... other keyboard handling
}
break;
}
}
// Update state
do_game_state_update();
// Render
do_screen_render();
}

Resizing window using SDL and OpenGL

Before writing this question, I have read the question: Handling window resizing using OpenGL and SDL. However that question does not solve my problem, since I am using SDL2 and not SDL1.2. But I do use OpenGL2. My complete source code is available at: http://dpaste.com/17BVBP6
I am writing a program that displays a white square in the window. However I am having trouble while handling window resize events.Here is my resize function:
void resize(int width,int height)
{
if(height<=0) height=1;
glViewport(0,0,(GLsizei)width,(GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,float(width)/float(height),1.0f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
My Main event loop:
while( !quit )
{
while( SDL_PollEvent( &e ) != 0 )
{
switch (e.type) {
case SDL_QUIT:
quit=true;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
resize(e.window.data1,e.window.data2);
break;
case SDL_KEYDOWN:
switch (e.key.keysym.sym) {
case SDLK_ESCAPE:
quit=true;
break;
default:
break;
}
default:
break;
}
}
render();
update(gWindow);
}
Here is my window when it is not resized:
Here is my window when it is resized:
What is the causing the problem here??
SDL_WINDOWEVENT_SIZE_CHANGED is not an event type, it is variation of SDL_WINDOWEVENT. Your event checking should be like
switch(e.type) {
case SDL_WINDOWEVENT:
if(e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
resize(e.window.data1,e.window.data2);
}
break;
Also remove your perspective projection setting - it is inconsistend with your draw, and you don't have perspective setup before resize.

Non instantaneous/jerky movement using SDL2 & OpenGL

I've been working on a little 3D engine trying to fix up the camera and make it less jerky. I've been using SDL for the input and while it works it's doing this thing where if I press and hold a button it will instantly move once then pause and then start moving properly making the movement feel unresponsive.
I recorded a GIF of it and while it may be slightly hard to see what's happening hopefully it'll give some idea:
Moving forward and then right would be like:
w wwwwwwwwwwwwwwww a aaaaaaaaaaaaaaaaaaaaa
The important code is here but feel free to ask for more if necessary:
//Poll events
SDL_Event event;
while (m_EngineState != EngineState::EXIT)
{
m_last = m_current;
m_current = SDL_GetPerformanceCounter();
deltaTime = (double)((m_current - m_last) * 1000 / SDL_GetPerformanceFrequency());
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_QUIT:
m_EngineState = EngineState::EXIT;
break;
case SDL_MOUSEMOTION:
break;
case SDL_KEYDOWN:
m_Keys[event.key.keysym.sym] = true;
break;
case SDL_KEYUP:
m_Keys[event.key.keysym.sym] = false;
break;
}
ProcessEvents();
}
void Engine::ProcessEvents()
{
if (m_Keys[SDLK_w])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_s])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_d])
{
m_Camera->MoveRight(5.0f*(deltaTime*0.001));
}
if (m_Keys[SDLK_a])
{
m_Camera->MoveRight(-5.0f*(deltaTime*0.001));
}
}
void Camera::MoveForward(float amount)
{
m_pos += m_forward * amount;
}
void Camera::MoveRight(float amount)
{
m_pos += glm::cross(m_forward, m_up) * amount;
}
Do not use SDL_PollEvent with the SDL_KEYDOWN and SDL_KEYUP events, it is subject to OS keyboard repeat rates. Which is great for typing, but not for camera/player controls. Use SDL_GetKeyboardState(NULL) in stead to query the current state of the keys.
For example:
Uint8* keystate = SDL_GetKeyboardState(NULL);
if (keystate[SDL_SCANCODE_W])
{
m_Camera->MoveForward(5.0f*(deltaTime*0.001));
}
if (keystate[SDL_SCANCODE_S])
{
m_Camera->MoveForward(-5.0f*(deltaTime*0.001));
}

Resolving inconsistent SDL2 key press detection?

I am trying to detect when a key is pressed down using the SDL_Event system.
I am using this code to detect the key presses:
void GameLoop::update(SDL_Event eventHandler, Camera &camera){
Vector2 move = Vector2();
if (eventHandler.type == SDL_KEYDOWN){
switch (eventHandler.key.keysym.sym){
case SDLK_w:
move = Vector2(0, -1);
break;
case SDLK_s:
move = Vector2(0, 1);
break;
case SDLK_a:
move = Vector2(-1, 0);
break;
case SDLK_d:
move = Vector2(1, 0);
break;
}
}
camera.translateCamera(move);
}
If I switch out 'WASD' inputs to 'UP DOWN LEFT RIGHT' The system works and if I remove the line:
if (eventHandler.type == SDL_KEYDOWN){
It works due to the SDL_KEYUP type, using 'WASD' or 'UP DOWN LEFT RIGHT'
What is causing this behaviour and how to fix it?
SDL literally checks IF the keyboard is pressed, it just so happens that the program reads faster than the actual press which will result in numerous presses, I'm not sure about your up, down, left, right buttons, maybe they are meant to be read by SDL but their physical connection might not be the same with the letters in the keyboard.
Now if you change KEYDOWN to KEYUP, all it would read is IF it is up, this isn't really good.
What you would want to do is use booleans and ticks
if (eventHandler.type == SDL_KEYDOWN && !clicked){
ticking2 = SDL_GetTicks();
switch (eventHandler.key.keysym.sym){
case SDLK_w:
clicked = true;
break;
case SDLK_s:
clicked = true;
break;
}
}
if (eventHandler.type == SDL_KEYUP && clicked){
ticking = SDL_GetTicks();
switch (eventHandler.key.keysym.sym){
case SDLK_w:
if(ticking-ticking2 >= 3000)
{
move = Vector2(0, -1);
clicked = false;
}
break;
case SDLK_s:
if(ticking-ticking2 >= 3000)
{
move = Vector2(0, 1);
clicked = false;
}
break;
}
}
Upon pressing a button, it gets the time and pushes it into ticking2 but then after upon a click, it turns the bool clicked into true which then makes it stop reading the loop, thus, freezing the value of ticking 2.
Upon releasing a button, it checks if clicked is true so that the actions will only be made IF the button was actually pressed.
It gets the time and pushes it into ticking, ticking-ticking2 should equal to something around 0, I made those to ensure that effects won't be instant since it might cause some glitches.

Managing multiple RenderWindow's in sfml

I seem to be having a bit of trouble when managing multiple windows in SFML C++. When I try to manage multiple windows, they both open correctly and I can interact in the larger one, however, the smaller one, which upon creation is overlapping the larger window, I can not interact with until I move the large window away. An image is below to help with the visual. Also below is the main loop for my code.
The main loop of the code is as follows:
while (MainWin.isOpen() || F1Menu.isOpen())
{
sf::Event Event;
if (MainWin.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
MainWin.close();
if (F1Menu.isOpen())
F1Menu.close();
break;
case sf::Event::Resized:
MainView.reset(sf::FloatRect(0.f, 0.f, (MainWin.getSize().x*0.9f), (MainWin.getSize().y*0.9)));
MainWin.setView(MainView);
break;
case sf::Event::KeyPressed:
if (Event.key.code == sf::Keyboard::F1)
F1Menu.create(sf::VideoMode(200, 500), "SFML 2D - F1 Menu");
else if (Event.key.code == sf::Keyboard::Escape)
{
MainWin.close();
if (F1Menu.isOpen())
F1Menu.close();
}
break;
}
}
if (F1Menu.pollEvent(Event))
{
switch (Event.type)
{
case sf::Event::Closed:
F1Menu.close();
break;
case sf::Event::MouseButtonReleased:
if (Event.mouseButton.button == sf::Mouse::Left)
if (LMButton.mouseIn(F1Menu))
LoadMap("MapA.dat");
break;
case sf::Event::MouseMoved:
if (LMButton.mouseIn(F1Menu))
LMButton.setColor(sf::Color::Yellow);
else
LMButton.setColor(sf::Color::White);
break;
}
}
moveClock.restart();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
player.move(0, -4 * time);
player.setDirection(sfm::Direction::Up);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
player.move(0, 4 * time);
player.setDirection(sfm::Direction::Down);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
player.move(-4 * time, 0);
player.setDirection(sfm::Direction::Left);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
player.move(4 * time, 0);
player.setDirection(sfm::Direction::Right);
}
if (F1Menu.isOpen())
{
F1Menu.clear();
F1Menu.draw(LMButton);
F1Menu.display();
}
if (MainWin.isOpen())
{
MainWin.clear();
if (SplashScreen.didAnimate)
SplashScreen.Animate(MainWin, sfg::Animation::FadeIn);
if (inMenu)
{
}
if (isPlaying)
{
DrawMap(MainWin);
MainWin.draw(player);
}
MainWin.display();
}
}
In my knowledge, you aren't able to poll two separate windows with one sf::Event object. this is because when polling events, you are essentially popping off of the event stack and handling each one. The signature of pollEvent is
bool pollEvent(sf::Event &event);
note that there is no const qualifier here, because each processed event gets popped off the event stack. By the time you finish polling your main window there are no events left for your other window. This could be the cause of your window being unable to focus. Your second window should use it's own separate sf::Event
On a side note I would highly recommend encapsulating your data inside classes. You can find a great reference here on how to go about doing so. It's great coding practice and helps minimize confusion when bug hunting