Why is SDL2 providing event values that are incorrect? - c++

I'm using SDL2 v2.0.9-3, 64 bit, with VS2019 C++. SDL_PollEvent returns events whose type field contains values that are incorrect. The returned values are consistent, but wrong, ALWAYS!
I'm running code that worked correctly with older versions of the library and VC compilers. I've tried building with VC2015 with the same result. I've also tried using the VCPKG version and compiling SDL2 from scratch. Always the same result.
Here's my code (with some debug output statements):
auto loop = true;
SDL_Event event;
long eventCounter = 0;
while (loop) {
while (SDL_PollEvent(&event)) {
std::wstringstream s;
s << "Event " << eventCounter++ << ", Type: 0x" << hex << event.type << std::endl;
OutputDebugString(s.str().c_str());
if (event.type == SDL_QUIT)
loop = false;
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
loop = false;
break;
case SDLK_SPACE:
DoSomething();
break;
default:
break;
}
}
}
keydown returns 0x10002 (bigger value than SDL_LASTEVENT - should be 0x300) and keyup returns 0x3 (should be 0x301). All other events are also consistent but wrong. Any clues?

Thank you Cubic! Your response clued me in to the problem. I had both SDL1 and SDL2 installed in vcpkg, so, even though I was including the correct header files, my program apparently was getting the SDL1 library linked in! I removed SDL1 from vcpkg and the problem went away.
It would seem that they should be able to coexist in a package manager, but I guess not. Lesson learned, don't have both SDL1 and SDL2 installed in vcpkg!

Related

SDL2 Key Repeat not working

I'm trying to make a simple character that can move around a shoot bullets. My event handler currently looks like this:
while( SDL_PollEvent( &e ) != 0 ) {
if( e.type == SDL_QUIT ) {
quit = true;
} else if (e.type == SDL_KEYDOWN && e.key.repeat == 0) {
switch (e.key.keysym.sym) {
case SDLK_UP:
p->setVelY(-1);
break;
case SDLK_DOWN:
p->setVelY(1);
break;
case SDLK_LEFT:
p->setVelX(-1);
break;
case SDLK_RIGHT:
p->setVelX(1);
break;
case SDLK_SPACE:
cout << "Firing" << endl;
p->Fire();
break;
}
} else if (e.type == SDL_KEYUP && e.key.repeat == 0) {
...
The problem is that if I hold the space bar, I only want my character to fire once. Right now though, it fires once, delays for like a quarter second, and then rapidly continues to fire. From my understanding, the repeat flag was the way to avoid this problem? It isn't working currently however. I saw somewhere to use scancodes instead, but I still had the same problem. I could make a map manually, but I wanted to just use the built in way to avoid key repeats. I'm currently using SDL 2.0.5 on Ubuntu 16.04. I'm just starting with SDL, so any help is appreciated.
Edit: Still not working, but I see now that the KEYUP is happening immediately in the next frame after every KEYDOWN, but then a new KEYDOWN is triggered (while I am still holding the key), and so forth. So it just keeps rapidly doing keydown and up events. This doesn't even let me do my own mapping for key press / release... any ideas?

AntTweakBar doesn't register SFML mouse events

I'm trying to add GUI for easier level editing in our game engine. We're using SFML for all the basic stuff (window management, input events etc). I've chosen AntTweakBar because it is a well known library with a few examples around. I was following the tutorial at AntTweakBar's website
I was able to draw a simple bar with those example codes. However, mouse events received by SFML are not registered by AntTweakBar's TwEventSDL()function. Here is an example code for Input:
sf::Event event;
while (_pWindow->pollEvent(event))
{
// Check if the event should be handled by AntTweakBar
int handled = TwEventSFML(&event, 2, 3); // for SFML version 2.3
if (!handled){
switch (event.type)
{
case sf::Event::MouseButtonPressed: // To check whether SFML received mouse button events properly
if (event.mouseButton.button == sf::Mouse::Button::Left){
std::cout << "Left button pressed" << std::endl;
std::cout << "x: " << event.mouseButton.x << std::endl;
std::cout << "y: " << event.mouseButton.y << std::endl;
}
}
}
else{ //To check whether TwEventSFML received events
std::cout << "FINALLY!" << std::endl;
}
When I press buttons, I can see "FINALLY!" showing up. I can also see that my mouse clicks are received by SFML. However, when I click on an AntTweakBar element (be it a button or help section) it doesn't register it. (Also, I can't see "FINALLY!" when I use the mouse).
Any help or ideas will be appreciated.
Anttweakbar hasnt been updated in 3 years, last SFML integration was for SFML 1.6
What version of SFML are you using ?
If not 1.6 then you have to create your own input handler for it.

My xlib code can listen to keyboard events but it fails for some windows

I have this code to listen to keyboard events of the active window:
#include<X11/Xlib.h>
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
#include <thread>
using namespace std;
#define IR_MODE 8192
#define SHIFT_MODE 16
#define US_MODE 0
static int ErrorHandler (Display *display, XErrorEvent *error)
{
cout<< "An error ocurred. We don't know anything.";
return 0;
}
int main()
{
Display *d = XOpenDisplay(0);
if(d == 0)
{
cout<< "Cannot open display\n";
exit(0);
}
Window root = DefaultRootWindow(d);
XSetErrorHandler(ErrorHandler);
Window current_window;
int rev;
XGetInputFocus(d,&current_window,&rev);
XSelectInput(d,current_window, KeyPressMask | KeyReleaseMask | FocusChangeMask);
while(true)
{
XEvent e;
XNextEvent(d, &e);
switch(e.type)
{
case FocusOut:
XGetInputFocus(d,&current_window,&rev);
if(current_window == PointerRoot || current_window == None)
{
current_window = root;
}
XSelectInput(d,current_window, KeyPressMask | KeyReleaseMask | FocusChangeMask);
break;
case KeyPress:
{
cout<< "key pressed\n";
break;
}
case KeyRelease:
cout<< "key released\n";
break;
}
}
XCloseDisplay(d);//*/
}
It works for many windows. But it fails for some windows, specially for gnome applications, e.g. nautilus. Why does this happen and how can I solve the problem?
The program just tries to listen to keyboard without interfering anything. As if the keyboard is being tapped with a difference: the program doesn't intend to lose language layout info. When a key is pressed, some information including ASCII codes are chosen and attached to the key event according to language layout and then the key event is sent. The program needs the key event with the information attached to it. So The program does not intend to Grab keyboard. It does not care for active or focused window. It just tries to listen to keys even if the program's window is not active. There are programs which check regularly with XQueryKeymap, but I'm not going to use that. Because it uses up CPU and then it will be more than just a fair listener. Also if checking is not frequent some keys may escape.
I guess your program does not work with GTK3 windows which uses xinput2. This is true if GTK3 was built without --disable-xinput.
AFAIK XSelectInput() won't work with xinput2, you need XISelectEvents() for such windows.
Look at meta_core_select_events() function from Mutter sources. It works both for xinput2 and traditional windows. This patch may be also helpful.

Why this code doesn't work when "cout"s are commented?

I'm writing a server for an online game based on IOCP, and the core codes handling game message is something like below:
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
/*if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
cout<<endl;
}*/
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
while(game_host[now_roomnum].Ready(now_playernum) == true)
{
;
}
//cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].SetReady(now_playernum, true);
game_host[now_roomnum].SetUsed(now_playernum, false);
while(true)
{
bool tmp = game_host[now_roomnum].AllReady();
if(tmp == true)
break;
}
//cout<<"AllReady from"<<now_playernum<<endl;
string all_msg = game_host[now_roomnum].GetAllMessage();
game_host[now_roomnum].SetUsed(now_playernum, true);
while(!game_host[now_roomnum].AllUsed())
{
;
}
//cout<<"AllUsed from "<<now_playernum<<endl;
EnterCriticalSection(&cs);
game_host[now_roomnum].ClearReady();
LeaveCriticalSection(&cs);
strcpy_s(ret.msg, all_msg.c_str());
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
}
return ret;
Now, the problem is: on a PC, when all cout are commented like above, the game freezes at once; but when I cancel the comments, the server works well.
What's more, when I run the server on my laptop, everything goes fine, no matter whether I comment the cout or not. The main difference between my laptop and PC is that my laptop's OS is Windows 8.1, while the PC is Windows 7.
I'm totally confused. It will be of great help if someone can tell me what to do. Thank you!
Looks like a multithreading issue.
By the way I see you use a Critical section around ClearReady but not when testing for AllReady. That call should be wrapped as well (or, better, write a LockedAllReady that makes use of the lock).
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
What you mean by ret.msg? if msg is method you must do ret.msg(); , is it a field?
If you have this good then like they say above probably a timing problem, try to do cout without ret.msg and see what will happen, and then you know from where the problem is.

Why can't webrtc find the capturer it suggested?

I'm creating a webrtc-based voip app for windows in C++. I'm trying to initialize a peerconnection. I'm stuck at the part to fetch a camera. I'm using the following code to find a camera to start streaming media from (copied from the peerconnection client example):
rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager(cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector<cricket::Device> devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector<cricket::Device>::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
capturer is empty after this procedure. I stepped through the code to see what was wrong. dev_manager is succesfully intialized, devs gets a single entry (my webcam) with a name:
"logitech HD webcam c270"
And an id:
"\\\\?\\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}"
But after the CreateVideoCapturer() call, capturer is still empty. I get a warning in the console saying:
Warning(webrtcvideocapturer.cc:175): Failed to find capturer for id: \\?\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
I checked if the id I get in devs and this one match and they do. The entire log for my app can be found in this pastebin. As you can see, right after trying to assign the camera as capturer and failing, the app crashes on an assert(capturer != NULL) call somewhere in videosource.cc.
The camera is not in use, nor is it defect. The peerconnection client example works perfectly and uses the same code. I think I'm missing some step in the initialization of webrtc, but I can't find which step.
edit with additional info
I'm debug stepping through the library now. In webrtcvideocapturer.cc around line 160 is the following code:
int num_cams = info->NumberOfDevices();
char vcm_id[256] = "";
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
int32 i = info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), vcm_id, ARRAY_SIZE(vcm_id));
if (i != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
}
}
}
if (!found) {
LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
factory_->DestroyDeviceInfo(info);
return false;
}
There are two problems with this part. First of all, if I step into info->NumberOfDevices() it shows me that that function's only content is the line return 0;. I tried hard-coding 1 there, to at least get into the for loop. Then when I step into the info->GetDeviceName() call it shows me that the content of that function is return -1;.
These two functions are meant to be implemented by a class that inherits from webrtc::VideoCaptureModule::DeviceInfo, so there is clearly something not initialized that does needs to be initialized. What do I still need to do before trying to get a camera?
What libraries did you link?
Because Google WebRTC source codes are changing rapidly, it is difficult to track down issues to the source level.
But I remember the almost same problem occurred when I accidentally linked external capture module library (video_capture_module_impl ??) or (I'm not sure) omitted internal impl (video_capture_module_internal_impl ??).