I'm developing an app that should freeze all input, both keyboard and mouse, for a period of time. I've tried using XGrabKeyboard, but I cannot revert its effect using XUngrabKeyboard, it does nothing.
Here's a minimal example you can easily compile:
#include <iostream>
#include <thread>
#include <chrono>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
#include <X11/cursorfont.h>
int main(int argc, char *argv[])
{
Display * dpy = nullptr;
dpy = XOpenDisplay(0);
if(!dpy)
{
std::cerr << "Error" << std::endl;
return 1;
}
std::cerr << "Grabbing..." << std::endl;
XGrabKeyboard(dpy, DefaultRootWindow(dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime);
std::cerr << "Waiting 2 secs, you shouldn't be able to type anything" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::cerr << "Ungrabbing..." << std::endl;
XUngrabKeyboard(dpy, CurrentTime);
std::cerr << "Try to type now" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
You can see that you cannot write anything anymore. I've tried clicking on the terminal, in case the focus is lost or anything, to no avail. Once the program finishes the keyboard is released.
Not sure if it has something to do with the parameters in the XGrabKeyboard call, I've tried modifying them (Sync vs Async, etc). But there's no difference.
Adding an XSync(dpy, true); (*) after XUngrabKeyboard makes the code behave in the way you expected. So possibly you have to process all the events you grabbed before the event queue resumes?
(*): don't actually do this, this is just to demonstrate that the problem is with the queued events
Also works:
XUngrabKeyboard(dpy, CurrentTime);
XEvent foo;
while (XPending(dpy)) XNextEvent(dpy, &foo);
Update - also works:
XFlush(dpy);
So... the problem is that the ungrab was not actually sent?
Related
I want to start a console-program (qt, c++) and ask the user whether he wants to load the previous settings or set new ones. After 10 sec without input, I want to automatically load the settings.
My approach:
start the program with a qTimer and an additional thread
ask the user via std::cin for his input in the additional thread
fire the timer if there is no input to quit the thread and continue the main program
The problem I'm facing is, that I can not abort the std::cin programmatically. Even quitting the Thread would not abort std::cin.
So I guess my approach is not right, what's the best way to achieve my overall goal?
From your mention of threads I'm guessing the intent is to allow the user to enter text at a console prompt without blocking the Qt event loop. That being the case you can probably avoid explicit use of threads all together by making use of QSocketNotifier.
The following example demonstrates the basic idea...
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <QCoreApplication>
#include <QSocketNotifier>
#include <QTimer>
int
main (int argc, char **argv)
{
try {
QCoreApplication app(argc, argv);
QTimer timeout;
/*
* Create a QSocketNotifier and let it monitor stdin/std::cin. The
* connected lambda just reads one char at a time here.
*/
QSocketNotifier stdin_notifier(::fileno(stdin), QSocketNotifier::Read);
QObject::connect(&stdin_notifier, &QSocketNotifier::activated,
[&](QSocketDescriptor socket, QSocketNotifier::Type type)
{
/*
* We've received input so stop the timer and read a
* single char.
*/
timeout.stop();
char c;
::read(::fileno(stdin), &c, 1);
std::cout << "stdin: read `" << c << "'\n";
});
/*
* Start with a 5 second timeout.
*/
unsigned remaining = 5;
std::cout << "you have " << remaining << "s to start entering text\r" << std::flush;
QObject::connect(&timeout, &QTimer::timeout,
[&]
{
if (!--remaining) {
std::cout << std::left << std::setfill(' ') << std::setw(50)
<< "too late" << "\n";
app.quit();
} else {
std::cout << "you have " << remaining
<< "s to start entering text\r" << std::flush;
}
});
timeout.start(1000);
exit(app.exec());
}
catch (std::exception &ex) {
std::cerr << ex.what() << "\n";
}
catch (...) {
std::cerr << "unrecognized exception\n";
}
exit(1);
}
I am trying to make a basic game in c++ using the SFML library. For this game, I want a thread
drawing at a fixed rate and another thread checking for input as often as possible. The first problem I encountered was that the SFML library does not allow for window to be active on multiple threads. A simple fix for this was found by just deactivating the window in the main thread. The next problem that I have not yet found a fix for is that I cannot seem to check for input on my main thread (In this scenario).
This code is very unreliable. I can get two different error messages, or an infinite loop. What should happen is an infinite loop that can be closed with the escape key, and if you press d it prints a message.
The library I am using is libsfml-dev
My compile arguments are as follows: g++ test.cpp -pthread -lsfml-graphics -lsfml-window -lsfml-system
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
sf::RenderWindow window(sf::VideoMode(800, 800), "");
using namespace std;
void *func(void *threadid) {
cout << "New thread." << endl;
while (window.isOpen()) {
// In the actual implementation, this would be replaced with draw methods
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
window.close();
}
}
pthread_exit(NULL);
}
int main() {
// Needed so that window is only active on a single thread
window.setActive(false);
// Create new thread
pthread_t threads[1];
int val;
val = pthread_create(&threads[0], NULL, func, (void *)1);
cout << "Main thread." << endl;
while (window.isOpen()) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
cout << "D button pressed." << endl;
}
}
return 0;
}
Error Number 1
PS: XInitThreads doesn't help
Error Number 2
Looks like an error from my X server
When debugging an app using std::cout to print something, nothing appears in the debug console (3rd tab, not external console). One of the exceptions seems to be the use of std::endl:
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
while(true) {
Sleep(500);
std::cout << "Hello world!" << std::endl; // Works
}
}
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
while(true) {
Sleep(500);
std::cout << "Hello world!\n"; // Doesn't work
// std::cout << "Hello world!"; // Doesn't work
// std::cout << "Hello world!" << std::flush; // Doesn't work
}
}
In the first example our lines appear over time, while on the second doesn't appear at all (or the console refreshes somewhere around 60 secs). I think this is a bug but I'm not sure, so what is a workaround? Maybe I have to configure something instead? I found this problem while working on something else: C++: cannot see output in VS Code while debugging
Edit
The problem is what to do when u wanna output something without a new line
I've been searching for a while, and I don't achieve to find any way to get the input keys of my keyboard, to use them in my program...
Context : I'm starting on robotics, and C++, and I'd simply like to command a motor.
The idea is that "if I press the up arrow, the motor turns, if I press the down arrow, the motor stops" and that's it, no need to validate something or anything like that...
I am with raspbian, through VNC (controlling from my real computer), and the actual code is executed in the terminal.
I'll see later on to make that more complex.
I went through 20 or more pages and didn't find anything helpful... Isn't there an easy way to do something that seems so basically useful?
Some spoke about conio library, but apparently it's outdated, curses/ncurses took its place,but I didn't achieve to find/have anything working...
http://www.cplusplus.com/forum/general/74211/
Create a function to check for key press in unix using ncurses
Capture characters from standard input without waiting for enter to be pressed
This is apparently C code, and not C++, moreover, I don't really understand that...
How to detect key presses in a Linux C GUI program without prompting the user?
This, maybe? But it makes no sense to me (beginner in C++)
How can I get the keyboard state in Linux?
here they speak of "allegro", but apparently, it don't work on the PI 45 yet... and no idea how to install that anyway
http://www.cplusplus.com/forum/general/47357/
Does someone knows a simple little code that I can copy-past to do that, or any way? I'm quite shocked to not have something similar to windows C++ programming where it seems so simple
I mean something like "Keyboard.GetKeyStates(Key)"
I'll continue my research anyway, but please, help !
EDIT :
Apparently, the library SDL (SDL2) can help me do this...
I tried to implement it, it doesn't give any result...
Here is the code I got up to now (I deleted a good part that is useless in here), basically, it's a copy-past from internet SDL official web page :
#include <iostream>
#include <wiringPi.h> //Raspberry pi GPIO Library
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono> //library for counting time
#include <thread> //for "this thread sleep"
#include <SDL2/SDL.h> //for getting the keyboard buttons events
bool RUNNING = true; // global flag used to exit from the main loop
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
GPIO Pins definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
int SPser = 13, SPclk = 19, SPrclk = 26; //Define the output pins used
int Optocoupler = 17; //define the input pins used
/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SDL definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
//void PrintKeyInfo( SDL_KeyboardEvent *key );
//void PrintModifiers( SDLMod mod );
//SOME CODE
// Callback handler if CTRL-C signal is detected
void my_handler(int s) {
std::cout << "Detected CTRL-C signal no. " << s << '\n';
RUNNING = false;
}
//###################################################################################
int main(int argc, char *args[]) {
// Initialize wiringPi and allow the use of BCM pin numbering
wiringPiSetupGpio();
//Initialize SDL
if (SDL_Init(SDL_INIT_EVENTS) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
else
{
SDL_Log("SDL initialized");
}
SDL_Event event;
// Register a callback function to be called if the user presses CTRL-C
std::signal(SIGINT, my_handler);
while(RUNNING)
{
while( SDL_PollEvent( &event ) )
{
std::cout << "SDL While \n" << '\n';
//When the user presses a key
switch( event.type )
{
case SDL_KEYDOWN:
std::cout << "Key press detected \n" << '\n';
//printf( "Key press detected\n" );
break;
case SDL_KEYUP:
std::cout << "Key release detected \n" << '\n';
//printf( "Key release detected\n" );
break;
default:
break;
}
}
//std::cout << "Works??" << '\n';
/*for( i = 0; i <= 15; i++ )
{
//std::cout << "data input i =" << i << '\n';
if (i==0){
//std::cout << "if array " << i << '\n';
DataArr[i]=1;
DataArr[15]=0;
}
else{
j=i-1;
DataArr[j]=0;
DataArr[i]=1;
//std::cout << "in else i" << i << " and j " << j << '\n';
}
SendData(DataArr);
}*/
}
std::cout << "Program ended ...\n";
}
As I followed "dumbly" the tutorial, this should work, but the while loop is never entered as the "std::cout << "SDL While \n" << '\n';" is never shown...
But, as it achieve to compile, I guess the SDL library was installed correctly and things work...
When executing the code, it writes "SDL initialized", then, nothing... pressing keys do nothing
I'm still not sure how to check if the library is installed correctly, but when I type in de command prompt "sudo apt-get install libsdl2-dev", it shows a few lines and says "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded"
If you are on linux, you should use termios to stop the buffering
#include <termios.h>
void set_no_buffer()
{
struct termios term;
tcgetattr(0, &term);
term.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &term);
}
and then getchar() to get a character without entering
I'm trying to switch an application over from using boost::interprocess::named_mutex to boost::interprocess::file_lock for interprocess synchronization, but when I did so I noticed that my condition variables were never being woken up.
I've created two examples that demonstrate the types of changes I made and the issues I'm seeing. In both examples the same application should periodically send notifications if invoked with any arguments, or wait for notifications if invoked with no arguments
Originally my application used name_mutex and named_condition. The below example using name_mutex and named_condition works as expected: every time the "sender" application prints out "Notifying" the "receiver" application prints out "Notified!" (provided I manually clean out /dev/shm/ between runs).
#include <iostream>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/thread.hpp>
int main(int argc, char** argv)
{
boost::interprocess::named_mutex mutex(boost::interprocess::open_or_create,
"mutex");
// Create condition variable
boost::interprocess::named_condition cond(boost::interprocess::open_or_create, "cond");
while(true)
{
if(argc > 1)
{// Sender
std::cout << "Notifying" << std::endl;
cond.notify_all();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
else
{// Receiver
std::cout << "Acquiring lock..." << std::endl;
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(mutex);
std::cout << "Locked. Waiting for notification..." << std::endl;
cond.wait(lock);
std::cout << "Notified!" << std::endl;
}
}
return 0;
}
The following code represents my attempt to change the working code above from using name_mutex and named_condition to using file_lock and named_condition_any
#include <iostream>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_condition_any.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
int main(int argc, char** argv)
{
// Second option for locking
boost::interprocess::file_lock flock("/tmp/flock");
// Create condition variable
boost::interprocess::named_condition_any cond(boost::interprocess::open_or_create,
"cond_any");
while(true)
{
if(argc > 1)
{// Sender
std::cout << "Notifying" << std::endl;
cond.notify_all();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
else
{// Receiver
std::cout << "Acquiring lock..." << std::endl;
boost::interprocess::scoped_lock<boost::interprocess::file_lock> lock(flock);
std::cout << "Locked. Waiting for notification..." << std::endl;
cond.wait(lock);
std::cout << "Notified!" << std::endl;
}
}
return 0;
}
However I can't seem to get the "receiver" application to wake up when notified. The "sender" happily prints "Notifying" at ~1Hz, but the "receiver" hangs after printing "Locked. Waiting for notification..." once.
What am I doing wrong with my file_lock/named_condition_any implementation?
This appears to be caused by a bug in the implementation of boost::interprocess::named_condition_any.
boost::interprocess::named_condition_any is implemented using an instance of boost::interprocess::ipcdetail::shm_named_condition_any. boost::interprocess::ipcdetail::shm_named_condition_any has all of the member variables associated with its implementation aggregated into a class called internal_condition_members. When shm_named_condition_any is constructed it either creates or opens shared memory. If it creates the shared memory it also instantiates an internal_condition_members object in that shared memory.
The problem is that shm_named_condition_any also maintains a "local" (i.e. just on the stack, not in shared memory) member instance of an internal_condition_members object, and its wait, timed_wait, notify_one, and notify_all functions are all implemented using the local internal_condition_members member instead of the internal_condition_members from shared memory.
I was able to get the expected behavior from my example by editing boost/interprocess/sync/shm/named_condition_any.hpp and changing the implementation of the shm_named_condition_any class as follows:
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
internal_condition m_cond;
to
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
internal_condition &internal_cond()
{ return *static_cast<internal_condition*>(m_shmem.get_user_address()); }
and changing all usages of m_cond to this->internal_cond(). This is analogous to how the shm_named_condition class is implemented.