I'm trying to catch keypress events using XLib. But for some reasons XNextEvent not working.
I'm not receiving any errors, but it looks like my program stuck on the line of "XNextEvent" call.
Here is my code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
using namespace std;
int main()
{
XEvent event;
KeySym key;
char text[255];
Display *dis;
dis = XOpenDisplay(NULL);
while (1) {
XNextEvent(dis, &event);
if (event.type==KeyPress && XLookupString(&event.xkey,text,255,&key,0) == 1) {
if (text[0]=='q') {
XCloseDisplay(dis);
return 0;
}
printf("You pressed the %c key!\n", text[0]);
}
}
return 0;
}
This is not how X11 windowing system works.
Read this carefully. The key point is :
The source of the event is the viewable window that the pointer is in.
You do not create a window, therefore your program doesn't receive keyboard events. Even if you created window, it has to have focus :
The window used by the X server to report these events depends on the window's position in the window hierarchy and whether any intervening window prohibits the generation of these events.
Working example
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
using namespace std;
int main()
{
XEvent event;
Display *dis;
Window root;
Bool owner_events = False;
unsigned int modifiers = ControlMask | LockMask;
dis = XOpenDisplay(NULL);
root = XDefaultRootWindow(dis);
unsigned int keycode = XKeysymToKeycode(dis, XK_P);
XSelectInput(dis,root, KeyPressMask);
XGrabKey(dis, keycode, modifiers, root, owner_events, GrabModeAsync, GrabModeAsync);
while (1) {
Bool QuiteCycle = False;
XNextEvent(dis, &event);
if (event.type == KeyPress) {
cout << "Hot key pressed!" << endl;
XUngrabKey(dis, keycode, modifiers, root);
QuiteCycle = True;
}
if (QuiteCycle) {
break;
}
}
XCloseDisplay(dis);
return 0;
}
Related
Here is the main file of the game snake I am developing. It uses OpenGL and ncurses. Everything runs exactly like I want it too, but I can only input my key presses to play the game if my command line terminal is the top level process of my computer. Currently, when I run the program, the OpenGL window spawns ontop of my command line prompt and then I need to re select my command line prompt and bring it to the front to play my game.
I want my terminal to recognize my key presses when the terminal is behind the openGL window. How do I do this if it is possible? I am using Ubuntu Linux.
#include <chrono>
#include <thread>
#include <unistd.h>
#include <ncurses.h>
#include "Snake.h"
#include <GL/glut.h>
int khbit(void)
{
int ch = getch();
if (ch != ERR)
{
ungetch(ch);
return 1;
}
else
{
return 0;
}
}
int main(int argc, char **argv)
{
std::unique_ptr<GameBoxes::Box> squareBackground(new GameBoxes::Box(std::stoi(argv[1]), std::stoi(argv[2]),
std::stoi(argv[3]), std::stoi(argv[4])));
int cArgs[4];
(*squareBackground).getSizeArray(cArgs);
glutInit(&argc, argv);
(*squareBackground).createBackGroundTexture();
glClear(GL_COLOR_BUFFER_BIT); //new
// initialize random seed:
srand (time(NULL));
// start ncurses
initscr();
// Line buffering disabled
cbreak();
// Don't echo while we do getch
noecho();
// Allows checking for Keypress
nodelay(stdscr, TRUE);
scrollok(stdscr, TRUE);
bool play = true;
while (play == true)
{
bool alive = true;
std::unique_ptr<GameBoxes::Snake> snake(new GameBoxes::Snake(*squareBackground, cArgs)); //new
int direction;
char directionTwo = 't';
flushinp();
while (alive == true)
{
if (khbit())
{
direction = getch();
directionTwo = direction;
alive = (*snake).moveSnake(*squareBackground, direction, cArgs); // Grow into a loop
flushinp();
}
else
{
alive = (*snake).moveSnake(*squareBackground, directionTwo, cArgs); // Grow into a loop
}
if (direction == 'k')
{
endwin();
return 0;
}
std::chrono::milliseconds dura( 40);
std::this_thread::sleep_for( dura );
}
}
glutMainLoop();
return 0;
}
I'm trying to open web-cam video and then pause it on first tap and then close it on second tap on a touchscreen display. I'm using OpenCV version 3.4.0.
Currently I can do it by either pressing q key or by closing window but I am unable to do it with screen tap. Here is my code sample:
bool exit_flag = false;
do
{
cv::imshow("window", draw_frame);
int key = cv::waitKey(3);
if (key == 'q'|| cv::getWindowProperty("window", cv::WND_PROP_ASPECT_RATIO) < 0)
{
//do_something
exit_flag = true;
}
} while (!exit_flag);
cv::waitKey(0);
cv::destroyWindow("window");
I tried using cv::EVENT_LBUTTONDOWN but couldn't use it properly to bring any positive results.
Pardon me if code isn't proper, I have created a sample for demonstration and I'm not very good at C++.
If you want to close your imshow window using mouse, you can simply use setMouseCallback. Here is my approach: you can close your window by "q" keyword or by simply clicking to window:
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
static bool exit_flag = false;
static void mouseHandler(int event,int x,int y, int flags,void* param){
if(event==1)
exit_flag = true;
}
int main(int argc, char **argv) {
Mat draw_frame = imread("/ur/image/directory/photo.jpg");
do {
cv::imshow("window", draw_frame);
int key = cv::waitKey(3);
setMouseCallback("window",mouseHandler);
if (key == 'q'|| cv::getWindowProperty("window", cv::WND_PROP_ASPECT_RATIO) < 0)
{
//do_something
exit_flag = true;
}
} while (!exit_flag);
cv::destroyWindow("window");
}
I have a program in which I shutdown windows this emits a sound. Up to this point all great. But when I hide the window console the program does not emit the sound. Is there some solution for this?
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <fstream>
#include <direct.h>
#include <dirent.h>
#include <sstream>
BOOL CtrlHandler(DWORD fdwCtrlType)
{
switch (fdwCtrlType)
{
case CTRL_SHUTDOWN_EVENT:
Beep(750, 500);
return FALSE;
default:
return FALSE;
}
}
int main(void)
{
//ShowWindow(GetForegroundWindow(),SW_HIDE);//Hide the window console
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE))
{
while (1)
{
Sleep(500);
}
}
else
printf("\nERROR: Could not set control handler");
}
When windows launches my program with /p argument, it initializes SDL window over HWND of that little preview monitor. The problem is, when the preview window closes, my process keeps running. I've tried to catch WM_DESTROY using SDL_SYSWMEVENT, but it didn't work: it catches WM_SETCURSOR, WM_NCHITTEST and some others, but not destroy. How to fix that problem?
Here's my code.
#include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <windows.h>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
char *lowercase(const char *str) {
char *ans=new char[strlen(str)+1]; int i;
for (i=0;str[i]>0;i++) ans[i]=tolower(str[i]);
ans[i]=0; return ans;
}
int main(int argc,char **argv) {
if (argc>1&&(strcmp(lowercase(argv[1]),"/c")==0||strcmp(lowercase(argv[1]),"-c")==0)) {
MessageBox(NULL,"Config should be there, WIP!","Screensaver",MB_OK);
return 0;
}
FILE *f;
SDL_Init(SDL_INIT_VIDEO);
int SCREEN_WIDTH,SCREEN_HEIGHT;
SDL_Window *wnd;
bool preview;
if (preview=(argc>2&&(strcmp(lowercase(argv[1]),"/p")==0||strcmp(lowercase(argv[1]),"-p")==0))) {
wnd=SDL_CreateWindowFrom((HWND)atoi(argv[2]));
SDL_GetWindowSize(wnd,&SCREEN_WIDTH,&SCREEN_HEIGHT);
} else {
SDL_DisplayMode tmp;
SDL_GetCurrentDisplayMode(0,&tmp);
SCREEN_WIDTH=tmp.w;SCREEN_HEIGHT=tmp.h;
wnd=SDL_CreateWindow("",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_SHOWN|SDL_WINDOW_FULLSCREEN);
}
SDL_Renderer *rnd=SDL_CreateRenderer(wnd,-1,SDL_RENDERER_ACCELERATED);
SDL_DisableScreenSaver();
bool quit=false;
SDL_Event evt;
SDL_EventState(SDL_SYSWMEVENT,SDL_ENABLE);
while (SDL_PollEvent(&evt)); //clear event queue
while (!quit) {
while (SDL_PollEvent(&evt)) switch (evt.type) {
/* does not work
case SDL_SYSWMEVENT: {
if (evt.syswm.msg->msg.win.msg==WM_DESTROY) quit=true;
break;
}
*/
case SDL_QUIT:
quit=true;
break;
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEMOTION:
if (!preview) quit=true;
break;
}
SDL_RenderClear(rnd);
SDL_SetRenderDrawColor(rnd,255,255,255,255);
SDL_RenderDrawLine(rnd,0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
SDL_SetRenderDrawColor(rnd,0,0,0,255);
SDL_RenderPresent(rnd);
SDL_Delay(20);
}
SDL_Quit();
return 0;
}
Looking at this article, it appears the message combo you are looking for is
WM_SYSCOMMAND SC_CLOSE
Okay, after long research I've found an answer. Thanks to that guy.
if (!IsWindow(previewHwnd)) quit=true;
I recently got started trying to use SFML. For some reason my simple program will not render the window. I've tried throwing everything into main to see if there was an error in my code that had to do with multiple files etc. but to no avail.
I'll launch my program and nothing will appear.
What's the problem?
//main.h
#ifndef MAIN_H
#define MAIN_H
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <fstream>
using namespace std;
using namespace sf;
class game
{
public:
void startLoop(int SCREEN_W, int SCREEN_H, string SCREEN_NAME);
void log(const string logging);
game()
{
QUIT = false;
pendingFile.open("Log.txt", ios::out);
pendingFile << "---Brain Bread Log---";
}
~game()
{
pendingFile.close();
}
private:
bool QUIT;
ofstream pendingFile;
};
#endif
//main.cpp
#include "main.h"
void game::log(const string logging)
{
pendingFile << logging;
}
void game::startLoop(int SCREEN_W, int SCREEN_H, string SCREEN_NAME)
{
Window Game(VideoMode(SCREEN_W, SCREEN_H, 32), SCREEN_NAME);
while(QUIT == false)
{
Game.Display();
}
}
int main(int argc, char* argv[])
{
game gameObj;
gameObj.startLoop(800, 600, "Brain Bread");
return 0;
}
I tried your code and it behaves exactly as I expect it to - that is to say that an iconless window with a black body pops up and it doesn't respond to events. Is that what you're getting? If not, you might need to rebuild SFML.
You might want to try introducing event-handling so that your startLoop looks more like this:
void game::startLoop(int SCREEN_W, int SCREEN_H, string SCREEN_NAME)
{
// Init stuff
while (Game.IsOpened())
{
sf::Event newEvent;
while (Game.GetEvent(newEvent))
{
// Process event
}
// Do graphics stuff
Game.Display();
}
}