glfwPollEvents() doesn't call keycallback on key press - c++

I have the code down below, it seems to be working if I use glfwGetKey(), but as it is it doesn't exit the loop,nor even seem to call the input function. I tried passing *input instead of input, but no dice. What could be causing this?
#include <display.h>
#include <GL/glfw.h>
#include <stdlib.h>
#include <stdio.h>
bool running;
void GLFWCALL input( int key, int action )
{
//if(key == GLFW_KEY_ESC ){
running = false;
//}
printf("%d",key);
}
int main(int argc, char* argv[])
{
running = true;
if(argc==3){
int width = atoi(argv[1]);
int height = atoi(argv[2]);
Display d(width,height);
glfwSetKeyCallback( *input );
d.open();
while(running){
glfwPollEvents();
printf("Running");
}
printf("\n %d,%d %d\n", width,height,GLFW_KEY_ESC);
d.close();
return 1;
}
else {
printf("Usage: GLFW_play width height");
return 0;
}
}

I think the only problem with your program is that you don't call glfwInit() before the other glfw functions.
According to page 5 of the GLFW User Guide, you must call glfwInit before any other function from the library to ensure proper functionality.
Also, don't pass *input, just pass input.

Related

NCurses getch always returns ERR (-1)

I've just started to work with ROS and I'm trying to write a node that publish keys in a topic.
I have created a node on a Linux Ubuntu 16.04.4 using ncurses.
This is my code:
#include <curses.h>
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
int ch;
nodelay(stdscr, TRUE);
ros::init(argc, argv, "keyboard_driver");
ros::NodeHandle n;
ros::Publisher key_pub = n.advertise<std_msgs::String>("keys", 1);
ros::Rate loop_rate(100);
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
if ((ch = getch()) != ERR)
{
ss << ch;
std::cout << ch;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
key_pub.publish(msg);
}
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
I'm using ncurses to avoid terminal buffer.
The topic appears, but I don't get anything if, in another terminal, I run this command:
rostopic echo /keys
Debugging it I have found that getch() always return -1.
How can I do to make it work?
UPDATE
I have tried this small program, and it doesn't print anything:
#include <iostream>
#include <curses.h>
int main(int argc, char **argv)
{
int ch;
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
You've set nodelay so getch will return immediately with ERR if there's no data ready from the terminal. That's why getch is returning -1 (ERR). You haven't set cbreak or raw to disable terminal buffering, so you're still getting that -- no data will come from the terminal until Enter is hit.
So add a call to cbreak() at the start (just before or after the call to nodelay()) and it should work as you expect.
To use getch() you have to do the following:
#include <iostream>
#include <curses.h>
#include <signal.h>
#include <stdlib.h>
void quit(int sig)
{
endwin();
exit(0);
}
int main(int argc, char **argv)
{
int ch;
signal(SIGINT,quit);
initscr();
cbreak();
nodelay(stdscr, TRUE);
for(;;)
{
if ((ch = getch()) != ERR)
{
std::cout << ch;
}
}
return 0;
}
I forget to add initscr(); call at the beginning and endwin(); at the end of the program.
More info about how to use ncurses library here.

C++ KeyboardEmulator

I'm trying to code a KeyBoard Emulator for Linux, first I thought to use python to achieve it, but all the libraries were using X (and I don't want to use it). I decided to code in C++ to write in the keyboard buffer. After a few days of learning C++ and doing some research on Linux and how the input system works, I came up with this:
#include <stdio.h>
#include <fcntl.h>
#include <linux/input.h>
#include <sstream>
#include <unistd.h>
#define EV_PRESSED 1
#define EV_RELEASED 0
int Emulate(char character)
{
printf("Starting the keyboard buffer writer\n");
int fd = 0;
char *device = "/dev/input/event1";
//write to buffer
if( (fd = open(device, O_RDWR)) > 0 )
{
struct input_event event;
printf("The keyboard code is: %d \n", KEY_A);
event.type = EV_KEY;
event.value = EV_PRESSED;
event.code = KEY_A;
write(fd, &event, sizeof(struct input_event));
event.value = EV_RELEASED;
event.code = KEY_A;
write(fd, &event, sizeof(struct input_event));
close(fd);
}
return 0;
}
int main(int argc, char *argv[]){
for(int i=0; i < sizeof(argv[1])/sizeof(int); i++){
Emulate(argv[1][i]);//for each car in the argv 1 call Emulate
}
}
As you can see I'm writing manually KEY_A to press the a key. And I was wondering if there is a function or a way to change a char to the keycodes definded in the file /usr/include/linux/input-event-codes.h.
Thank you for your help !

OS X move terminal caret with arrow keys

I made a simple C programme that demonstrates the issue. Here it is.
#include <stdio.h>
int main(int argc, const char * argv[]) {
char buffer[128];
memset(buffer, 0, sizeof(buffer));
printf("Type data:\n");
scanf("%126s", buffer);
printf("%s\n", buffer);
getchar();
return 0;
}
The problem is that when the application is waiting for user input with scanf() and user user wants to edit line he typed, and to do move caret with arrows, the caret is not moving but new ugly input is inserted.
For some reason it does not handle the keys in a way I expect. I'm not able to go to the previous typed line with the up key, as well.
Obviously I should deliberately enable this behaviour. Could you advice, how can I do that?
Use readline(). Here's a simple example:
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <ctype.h>
#define MAX_LINE_LEN 80
int main() {
char *line_buffer;
int n, i;
while (1) {
line_buffer = readline("Say something: ");
if (!line_buffer) break;
for (i=0; line_buffer[i]; i++) {
line_buffer[i] = toupper(line_buffer[i]);
}
printf("YOU SAID: %s\n",line_buffer);
}
putchar('\n');
return 0;
}
/* (Compile with cc foo.c -lreadline -o foo) */

Xlib test window names

I'm trying to get control of the the Xterm with Xlib.
For that i'm making a Xterm with a strange title. After I list all window and check they names. But something is bugged the nammes of my Xterm does not appear when they are listed. Here is the code for list all window :
void CMD::getWindowTerminal()
{
Atom a = XInternAtom(m_display, "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long numItems, bytesAfter;
unsigned char *data = 0;
int status = XGetWindowProperty(m_display, m_root_win, a, 0L, (~0L), false,
AnyPropertyType, &actualType, &format, &numItems,
&bytesAfter, &data);
if (status >= Success && numItems)
{
long *array = (long*) data;
for (unsigned long k = 0; k < numItems; k++)
{
// get window Id:
Window w = (Window) array[k];
char* name = '\0';
status = XFetchName(m_display, w, &name);
if (status >= Success)
{
std::cout << w << " " << name << std::endl;
if (name == NULL)
{
m_window_terminal = w;
std::cout << "TERMINAL FOUND" << std::endl;
}
}
XFree(name);
}
XFree(data);
}
}
I cannot reproduce the error; your code finds my xterm windows. Are you querying the window of an xterm you only just spawned? If so, you might have a race condition in that you try to find the window before xterm had a chance of making it. In that case, a crummy solution would be to wait a bit and try again several times.
If that is not the case, I can only speculate (more) about causes (my speculations involve a misbehaving window manager or very old software), but perhaps I can suggest a solution: if the xterm doesn't show up in the root window's _NET_CLIENT_LIST, let's dig directly into the window tree and see if we can find it there. This bit of C code (porting to C++ should not be difficult, and anyway it's enough to try it out) traverses the window tree recursively with XQueryTree, so it queries all windows:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
Window window_from_name_search(Display *display, Window current, char const *needle) {
Window retval, root, parent, *children;
unsigned children_count;
char *name = NULL;
/* Check if this window has the name we seek */
if(XFetchName(display, current, &name) > 0) {
int r = strcmp(needle, name);
XFree(name);
if(r == 0) {
return current;
}
}
retval = 0;
/* If it does not: check all subwindows recursively. */
if(0 != XQueryTree(display, current, &root, &parent, &children, &children_count)) {
unsigned i;
for(i = 0; i < children_count; ++i) {
Window win = window_from_name_search(display, children[i], needle);
if(win != 0) {
retval = win;
break;
}
}
XFree(children);
}
return retval;
}
// frontend function: open display connection, start searching from the root window.
Window window_from_name(char const *name) {
Display *display = XOpenDisplay(NULL);
Window w = window_from_name_search(display, XDefaultRootWindow(display), name);
XCloseDisplay(display);
return w;
}
Since it handles all windows, your xterm window has to be among them. If it is not, refer back to the beginning (the bit about a possible race condition). And if that's not it, then something's very strange.

C++ pipes between multiple children

I am working on a project and I got it mostly figured out except for one minor(big) problem. I can't seem to figure out how to create pipes between any number of children.
for example I am taking in command line arguments to determine how many children will be produced. The first child doesn't have input but has output and the last child outputs to STD output. I need to pass values into the first child and into each child after that in order. Here is what i got:
#include <errno.h>
#include <cstdio>
#include <iostream>
#include <sys/wait.h>
using namespace std;
int main(int argc, char *argv[]) {
pid_t childpid;
int x2ypipe[2];
pipe(x2ypipe);
if(x2ypipe==0) {
cout<<"ERROR:"<<errno<<endl;
}
int y2zpipe[2];
pipe(y2zpipe);
if(y2zpipe==0) {
cout<<"ERROR:"<<errno<<endl;
}
pid_t xchild =fork();
if(xchild==0) {
dup2(x2ypipe[1],STDOUT_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
int a=execl(argv[1],argv[1], (char*)NULL);
if(a==-1) {
perror("The following error occurred at A");
}
}
for(int i=2; i<(argc-1); i++) {
childpid =fork();
if(childpid==0) {
dup2(x2ypipe[0],STDIN_FILENO);
close(x2ypipe[0]);
close(x2ypipe[1]);
//direct y2z pipe to standard output and replace the child with the program part2
dup2(x2ypipe[1],y2zpipe[1]);
dup2(y2zpipe[1],STDOUT_FILENO);
close(y2zpipe[0]);
close(y2zpipe[1]);
int b=execl(argv[i],argv[i],(char *)NULL);
if(b==-1) {
perror("The following error occurred at B");
}
}
}
pid_t zchild =fork();
if(zchild==0) {
dup2(y2zpipe[0],STDIN_FILENO);
close(y2zpipe[0]);
close(y2zpipe[1]);
int c=execl(argv[argc-1],argv[argc-1],(char *)NULL);
if(c==-1) {
perror("The following error occurred at C");
}
}
close(x2ypipe[0]);
close(x2ypipe[1]);
wait(NULL);
wait(NULL);
wait(NULL);
}
now right now I am only passing in three programs in to the argv[] and it works fine. I will have to add a if statement in my for loop to check for the last/highest possible value of i to connect the y2z pipe to the zchild. What I am having trouble doing it connecting the children to each other within the for loop. How would I go about creating a new pipe for each child from the last child?
Maybe this will help. Notice how I call pipe() inside my for loop, so I don't have to think of new "x2y", "y2z", "z2omega", etc, etc names for the pipe pairs.
Also notice how I used a variable prevfd from outside the for loop to carry the previous iterations's pipe file descriptor into the next iteration. And how it points to "/dev/null" to start with.
Finally, notice how I call wait() precisely as many times as I need to, in a loop, rather than writing it 3 (or 4 or 5 or ... 1,397) times.
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int prevfd;
prevfd = open("/dev/null", O_RDONLY);
if(prevfd < 0) {
perror("/dev/null");
exit(1);
}
for(int i = 1; i < argc; ++i) {
int pipefd[2];
int kid;
if(i != argc-1 && pipe(pipefd)) {
perror("pipe");
break;
}
if(!fork()) {
dup2(prevfd, 0);
close(prevfd);
if(i != argc-1) {
dup2(pipefd[1], 1);
close(pipefd[0]);
close(pipefd[1]);
}
execl(argv[i], argv[i], (char*)0);
perror(argv[i]);
exit(1);
}
close(prevfd);
prevfd = pipefd[0];
close(pipefd[1]);
}
while(wait((int*)0) != -1)
;
return 0;
}
You need a separate pipe between each pair of connected processes.