I've started to learn about ANSI escape sequences online through the magic of Google. It is neat being able to position the cursor \e[row;colH
on the screen and set the colors of the outputs (ie: \e[31m
).
Next I would like try and see how the mouse able to be captured in a virtual terminal. I realize this code is not portable, and I know I can use ncurses or some other curses library, but the goal here is to learn how it works, not write production code with it.
I have tried \e[?1003h
and it starts to fill the screen with mouse events. (Pretty cool!) However, how do I capture these in a C or C++ program?
I saw an example of what I would like to do in PHP: https://stackoverflow.com/a/58390575/1770034
However, when I try to port the code over to something in C it just locks up in the while loop. (Tested with GDB to find that out.)
#include <stdio.h> //bring in printf and fread
int main()
{
system("stty -echo"); //make the terminal not output mouse events
system("stty -icanon"); //put stdin in raw mode
printf("\e[?1003h\e[?1015h\e[?1006h"); //start getting mouse events
char* buffer[255];
while(fread(buffer, 16, 1, stdin)) // <-- suppose to read in the mouse events
{
printf("here"); //Did you actually work?!
}
printf("\e[?1000l"); //Turn off mouse events
system("stty echo"); //Turn echoing of the display back on
return 0; //end the program in a successful state
}
I have also tried scanf
and it just locks up until I hit enter, and I'm not convinced it is seeing the mouse events.
Edit
I now have some working code that spits out the mouse events.
Here is the updated code from applying the accepted answer to this question:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main()
{
system("stty -echo"); //don't show mouse events on screen
system("stty -icanon");
fprintf(stderr, "\e[?1003h\e[?1015h\e[?1006h"); //use stderr since not buffered turn on mouse event capture
char buffer[16] = " ";
char previousBuffer[16] = " ";
//Make standard in not be blocking
int flags = fcntl(stdin->_fileno, F_GETFL, 0);
fcntl(stdin->_fileno, F_SETFL, flags | O_NONBLOCK);
for (int hunSeconds = 0; hunSeconds < 500; hunSeconds++) //Run for 50 seconds
{
read(fileno(stdin), buffer, 16); //read mouse input
if (strcmp(buffer, previousBuffer) != 0) //only show event if it is different
{
fprintf(stderr, "%s", buffer);
strncpy(previousBuffer, buffer, 16);
}
usleep(100); // sleep for .1 seconds
}
printf("\e[?1000l"); //turn off mouse events
system("stty echo"); //turn on screen echo again
return 0;
}