I am searching for a way to automatically take a screenshot of my X server if a window is created or the contents of a windows have changed.
I am currently achieving this by listening to X11 events, but not all changes are reported.
Look at XDamageNotifyEvent, XDamageQueryExtension, XDamageCreate, XDamageSubtract from the Damage extension. This extension is used to track changing window contents.
http://www.freedesktop.org/wiki/Software/XDamage
A good source of sample code would be anything that makes thumbnails of windows. Also, any compositing window manager (Compiz, some flavors of metacity, etc.) would contain damage-tracking code.
Without the extension, you basically have to poll (update window contents in a timeout).
I know this post is quite dead. And yet, the documentation of X11 is terrible, and it took me a long time to get XDamage working in any regard. So here is an example that will print a line to the console every time the root X11 window changes, based on the documentation mentioned in Havoc's post, and loosely based on this link:
#include <stdio.h>
#include <stdlib.h>
#include <X11/extensions/Xdamage.h>
#include <X11/Xlib.h>
#include <signal.h>
int endnow = 0;
void cleanup(int SIGNUM){
endnow = 1;
}
int main(){
Display *display;
display = XOpenDisplay(":0");
if(!display){
perror("could not open display");
exit(1);
}
Window root = DefaultRootWindow(display);
int damage_event, damage_error, test;
//this line is necessary to initialize things
test = XDamageQueryExtension(display, &damage_event, &damage_error);
/*The "event" output is apparently the integer that appears in the
Xevent.type field when XNextEvent returns an XDamage event */
printf("test = %d, event = %d, error = %d\n",test,damage_event, damage_error);
//This is the handler for the XDamage interface
//See the XDamage documentation for more damage report levels
// http://www.freedesktop.org/wiki/Software/XDamage
Damage damage = XDamageCreate(display, root, XDamageReportNonEmpty);
signal(SIGINT,cleanup);
// XCloseDisplay(display);
while(endnow == 0){
XEvent event;
XNextEvent(display,&event);
printf("event.type = %d\n",event.type);
//this line resets the XDamage handler
XDamageSubtract(display,damage,None,None);
}
XCloseDisplay(display);
printf("done\n");
exit(0);
}
Naturally, if you run this from a console on the same screen as your display :0, every line it prints it will activate itself, and be kinda unstable. But it is a good demonstration if you run it from an ssh terminal on another computer.
Related
I am working on an SDL project in C and I am having trouble with the input handling.
whenever I start my SDL app it remembers the last app's inputted keys and SDL_PollEvent always gives repeatedly the last key that was pressed in the previous instance of the program.
btw I am compiling the code in a WSL window I have tried the same piece of code in a visual studio environment and it worked perfectly fine. So can someone explain what's happening?
Here is the sample code:
#include <SDL2/SDL.h>
#include <stdio.h>
int main() {
SDL_Event event;
SDL_Window* sdlwind;
if(SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "SDL_Init Error : %s", SDL_GetError());
return 1;
}
sdlwind = SDL_CreateWindow("Engine", 0, 0, 1080, 840, SDL_WINDOW_SHOWN);
if(!sdlwind) {
fprintf(stderr, "SDL_CreateWindow Error : %s", SDL_GetError());
return 1;
}
printf("Start");
while (1)
{
while (SDL_PollEvent(&event))
{
printf("%c\n", event.key.keysym.sym);
}
if(event.key.keysym.sym == SDLK_a) {
break;
}
}
SDL_DestroyWindow(sdlwind);
SDL_Quit();
return 0;
}
This sample code has outputted the first time:
OUTPUT
,
,
,
,
,
,
// etc since the last key pressed in the previous instance was , and after terminating the program by pressing a
// the next output becomes
OUTPUT
a
a
a
a
a
// etc
I have tried removing the executable and launching another SDL program but the same problem persists. I have later tried to take input normally with getchar() but it didn't register any key so I am not sure but it might not be a problem related to the stdin it must be smthng with SDL and WSL.
It sounds like you are experiencing the same root problem as in this Super User question and issue #58 against WSLg.
It's fixed in the latest Preview releases, which you can install from this Microsoft Store link (since you seem to be on Windows 11).
The Github issue was never closed, and I never saw any release notes on it, so it may have been an upstream fix (perhaps FreeRDP), but it definitely is resolved for both me as well as the OP of that Super User question.
This is the code I'm using,
#include <stdio.h>
#include <X11/Xlib.h>
Display *dpy;
char *window_name_return = NULL;
Window focused;
int revert_to;
void main(){
dpy = XOpenDisplay(NULL) ;
if(!dpy) printf("error\n");
XGetInputFocus(dpy, &focused, &revert_to);
XFetchName(dpy, focused, &window_name_return);
XFree(window_name_return);
printf("Focus on %s\n", window_name_return);
XCloseDisplay(dpy);
}
This works only for terminal emulator windows, for other window, the program returns, null.
The documentation for XFetchName says,
If the WM_NAME property has not been set for this window, XFetchName()
sets window_name_return to NULL
Is this why its not working? I use dwm window manager, running the code in Openbox did not work either.
How do I alter the code so that it works for all types of window?
There are multiple problems in your code:
The first is that you don't check the status returned by XFetchName;
The second that you don't check if window_name_return is null or not;
And the third and worst problem is that you free the string before you print it (making the pointer invalid).
I'm writing a Z80 simulator with a GUI running on GTK (https://github.com/clancyj4/z80sim/tree/dev for those interested).
My problem is that I need to trap the IN opcode and allow a window to be edited to provide the IO codes. Let me show you what I've got so far:
/* get a byte (char?) from the input part of the Port window */
/* What we really want to do is have a queue */
BYTE IOPort_IN(int port)
{
char whole_buffer[IOINBUFLEN * 4]; /* 4x in case of Hex */
BYTE c;
int i;
if (IOPort[port] == NULL) /* struct exists? */
Create_IOPort_Struct(port);
printf("IOPort_IN: port=%d in_len=%d in_ptr=%d\n",
port, IOPort[port]->in_len, IOPort[port]->in_ptr);
if (IOPort[port]->in_len == 0)
{
sprintf(tstr, "Port %d requires input", port);
Add_to_Log(tstr);
show_log(TRUE);
gtk_text_buffer_set_text(inportprompt_textbuffer, "Input Required", -1);
/* somehow keep the gtk main loop running so the interface updates and allows the editing of the ioportin_textbuffer,
but wait for the input submission button the be pressed */
i = gtk_text_buffer_get_char_count(ioportin_textbuffer);
printf("in port buff len is %d.\n", i);
}
return(c);
}
The trapping of the opcode is OK and this function is called. The trouble is that I have no idea how to implement the comment in the middle.
The aim is to have the rest of the simulation on hold, but with the GTK main loop still running, so the Log window etc get updated and I can enter a string in the IO window. But it waits until a submit button is pressed. I can freeze the Z80 simulation by setting a flag, so that's no problem.
I have a nasty feeling that I haven't expressed the problem very well, so please bear with me and ask any questions that would clarify the situation.
Cheers,
Justin.
I sidestepped the issue and forced a return of 00 if there wasn't an input queue already in place. With plenty of warnings, of course.
I would still like to know how to get GTK to hold execution on the main thread until a sub-window has been activated. When I know, I'll put the answer in here.
This question is a bit unclear. This will setup the callback for a function, it will call whatever function you pass through it.
void button_connect_callback(GtkWidget *button, void *button_callback)
{
g_signal_connect(button, "clicked", G_CALLBACK(button_callback), NULL);
}
I have some tutorials that might be of help here
What I am trying to do
So, I have been trying to access keyboard input in Linux. Specifically, I need to be able to access modifier key presses without other keys being pressed. Furthermore, I want to be able to do this without an X system running.
So, in short, my requirements are these:
Works on Linux
Does not need X11
Can retrieve modifier key press without any other keys being pressed
This includes the following keys:
Shift
Control
Alt
All I need is a simple 0 = not pressed, 1 = currently pressed to let me know if
the key is being held down when the keyboard is checked
My computer setup
My normal Linux machine is on a truck towards my new apartment; so, I only have a Macbook Air to work with right now. Therefore, I am running Linux in a VM to test this out.
Virtual Machine in VirtualBox
OS: Linux Mint 16
Desktop Environment: XFCE
Everything below was done in this environment. I've tried both with X running and in one of the other ttys.
My Thoughts
I'll alter this if someone can correct me.
I've done a fair bit of reading to realize that higher-level libraries do not provide this kind of functionality. Modifier keys are used with other keys to provide an alternate key code. Accessing the modifier keys themselves through a high-level library in Linux isn't as easy. Or, rather, I haven't found a high-level API for this on Linux.
I thought libtermkey would be the answer, but it doesn't seem to support the Shift modifier key any better than normal keystroke retrieval. I'm also not sure if it works without X.
While working with libtermkey (before I realized it didn't get shift in cases like Shift-Return), I was planning to write a daemon that would run to gather keyboard events. Running copies of the daemon program would simply pipe requests for keyboard data and receive keyboard data in response. I could use this setup to have something always running in the background, in case I cannot check key code statuses at specific times (have to be receive key codes as they happen).
Below are my two attempts to write a program that can read from the Linux keyboard device. I've also included my small check to make sure I had the right device.
Attempt #1
I have tried to access the keyboard device directly, but am encountering issues. I have tried the suggestion here that is in another Stack Overflow thread. It gave me a segmentation fault; so, I changed it from fopen to open:
// ...
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
char key_map[KEY_MAX/8 + 1];
memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);
// ...
While there was no segmentation fault, there was no indicator of any key press (not just modifier keys). I tested this using:
./foo && echo "TRUE" || echo "FALSE"
I've used that to test for successful return codes from commands quite a lot; so, I know that's fine. I've also outputted the key (always 0) and mask (0100) to check. It just doesn't seem to detect anything.
Attempt #2
From here, I thought I'd try a slightly different approach. I wanted to figure out what I was doing wrong. Following this page providing a snippet demonstrating printing out key codes, I bundled that into a program:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char** argv) {
uint8_t keys[128];
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
for (;;) {
memset(keys, 0, 128);
ioctl (fd, EVIOCGKEY(sizeof keys), keys);
int i, j;
for (i = 0; i < sizeof keys; i++)
for (j = 0; j < 8; j++)
if (keys[i] & (1 << j))
printf ("key code %d\n", (i*8) + j);
}
return 0;
}
Previously, I had the size to 16 bytes instead of 128 bytes. I should honestly spend a bit more time understanding ioctl and EVIOCGKEY. I just know that it supposedly maps bits to specific keys to indicate presses, or something like that (correct me if I'm wrong, please!).
I also didn't have a loop initially and would just hold down various keys to see if a key code appeared. I received nothing; so, I thought a loop might make the check easier to test in case a missed something.
How I know the input device is the right one
I tested it by running cat on the input device. Specifically:
$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
Garbage ASCII was sent to my terminal on key press and release events starting with the return (enter) key when I began the output using cat. I also know that this seems to work fine with modifier keys like shift, control, function, and even Apple's command key on my Macbook running a Linux VM. Output appeared when a key was pressed, began to appear rapidly from subsequent signals sent by holding the key down, and outputted more data when a key was released.
So, while my approach may not be the right one (I'm willing to hear any alternative), the device seems to provide what I need.
Furthermore, I know that this device is just a link pointing to /dev/input/event2 from running:
$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
I've tried both programs above with /dev/input/event2 and received no data. Running cat on /dev/input/event2 provided the same output as with the link.
Open the input device,
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
int main(void)
{
const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
and then read keyboard events from the device:
while (1) {
n = read(fd, &ev, sizeof ev);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
The above snippet breaks out from the loop if any error occurs, or if the userspace receives only a partial event structure (which should not happen, but might in some future/buggy kernels). You might wish to use a more robust read loop; I personally would be satisfied by replacing the last break with continue, so that partial event structures are ignored.
You can then examine the ev event structure to see what occurred, and finish the program:
if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
For a keypress,
ev.time: time of the event (struct timeval type)
ev.type: EV_KEY
ev.code: KEY_*, key identifier; see complete list in /usr/include/linux/input.h
ev.value: 0 if key release, 1 if key press, 2 if autorepeat keypress
See Documentation/input/input.txt in the Linux kernel sources for further details.
The named constants in /usr/include/linux/input.h are quite stable, because it is a kernel-userspace interface, and the kernel developers try very hard to maintain compatibility. (That is, you can expect there to be new codes every now and then, but existing codes rarely change.)
While using readline (blocking) for user input, I would like to output lines of text to the console asynchronously from another thread. Further, I would like that the readline prompt and current partial input line be removed from the console, the output line written, then the readline prompt and the partial user line restored - so as to give the appearance that the output was written "above" the prompt.
By what combination of readline redisplay functions (or otherwise) can this be achieved?
(Redisplay function documentation: http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC35)
problem demo:
#include <readline/readline.h>
#include <readline/history.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
bool run = true;
void* log_thread(void*)
{
while (run)
{
sleep(1);
// WHAT TO DO HERE?
write(1, "tick\n", 5);
}
}
int main()
{
pthread_t t;
pthread_create(&t, 0, log_thread, 0);
while (true)
{
char* p = readline("? ");
free(p);
if (!p)
break;
}
run = false;
pthread_join(t,0);
}
build:
$ g++ -pthread -lreadline test.cpp
$ ./a.out
observed output: (input "foo\nbar\n" typed slowly)
? tick
ftick
otick
otick
? tick
tick
bartick
tick
? tick
^C
desired output: (input "foo\nbar\n" typed slowly)
tick
tick
tick
tick
tick
? foo
tick
tick
tick
tick
tick
? bar
tick
? ^C
I'm doing this in the console version of my program omphalos (https://github.com/dankamongmen/omphalos). This particular code comes from https://github.com/dankamongmen/omphalos/blob/master/src/ui/tty/tty.c.
I have:
// Call whenever we generate output, so that the prompt is updated
static inline void
wake_input_thread(void){
if(input_tid){
pthread_kill(*input_tid,SIGWINCH);
rl_redisplay(); // FIXME probably need call from readline contex
}
pthread_mutex_unlock(&promptlock);
}
and
static inline void
clear_for_output(FILE *fp){
fputc('\r',fp);
}
Whenever something wants to print, it takes the lock and calls clear_for_output(), moving the cursor to the beginning of the current line. It can change the prompt at this time if necessary, by calling rl_set_prompt(). When done, it calls wake_input_thread(), releasing the lock and causing a redisplay.
I'm not sure if this works in the case where you've typed more than a line of text in, and doubt it, and don't care to formally discover what's likely a new and depressing bug right this moment, so you can experiment with that yourself.
The functions that should be used:
rl_clear_visible_line(). Printing \r won't do it well, because it just moves the cursor to the start of the line without deleting the line content, plus it fails to work properly when there's more than one input line.
rl_on_new_line(); rl_redisplay(); (or rl_forced_update_display();): After printing.
It appears that it's okay to call these two functions from any thread; however it may introduce race conditions (the documentation says nothing be whether it's safe to use readline functions from multiple threads), therefore it's better to use rl_event_hook and rl_getc_function (because rl_event_hook is not called when a key is held) to call the function for the main thread. Also remember to handle the says when there's no running readline function.