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).
Related
I am redirecting the ncurses hmi to a different, already existing terminal. While the output part works fine (and is therefore not shown here), the input misses keys which then appear in the terminal as though they had been entered without ncurses.
#include <stdio.h>
#include <curses.h>
int main(int argc, char *argv[])
{
FILE *fd = fopen(argv[1], "r+");
SCREEN *scr = newterm(nullptr, fd, fd);
set_term(scr);
noecho();
keypad(stdscr, TRUE);
while (true) {
int ch = wgetch(stdscr);
printf("In %d\r\n", ch);
}
return 0;
}
I create two terminals on Ubuntu and get the name of one (let's call it the 'curses-terminal') using 'tty'. This name is then used as argument when starting the above in the other terminal.
When typing in the curses-terminal, I expect the codes of the keys to appear in the other terminal without seeing anything in the curses-terminal.
Instead, I see some of the characters diffuse into the curses-terminal without their code being displayed in the other one. This happens with normal characters when typing more quickly, but it happens especially with arrow keys and ALT- combinations, where the error rate is >> 50%.
Are there any settings which I have forgotten?
Using G.M.'s hint, I was able to reliably get all input.
Run
tail -f /dev/null
in the curses-terminal before attaching the ncurses app.
Should you be tempted (like me) though to send this command from within your app after fopen, you may end up frustrated.
I am trying to learn the PDcurses package in C but i keep getting this problem:
LINES value must be >= 2 and <= 1252: got -1
initscr(): Unable to create SP
My code:
#include <curses.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *lsofFile_p = popen("hostname", "r");
if (!lsofFile_p)
{
return -1;
}
int row,col;
char buffer[1024];
char *line_p = fgets(buffer, sizeof(buffer), lsofFile_p);
pclose(lsofFile_p);
initscr(); /* start the curses mode */
start_color();
init_pair(1,COLOR_GREEN,COLOR_BLACK);
init_pair(2,COLOR_BLUE,COLOR_BLACK);
getmaxyx(stdscr,row,col); /* get the number of rows and columns */
attron(COLOR_PAIR(1));
mvprintw(row/2,(col-strlen(line_p)-26)/2,"Your computer name is : ");
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(2)|A_BOLD);
printw("%s",line_p);
/* print the message at the center of the screen */
attroff(COLOR_PAIR(2)|A_BOLD);
wrefresh(stdscr);
system("pause");
endwin();
}
This works fine in Linux with ncurses instead of curses. If i simply try printing Hello world, it works too. So I have no idea where it is going wrong or how to fix it.
I am using MinGW gcc for compiling and I've got PDCurses installed from there too. I am running the code on Windows Terminal.
The error message indicates that PDcurses was unable to get the screen size from the Windows console. This may mean that it failed to figure out what type of terminal you are using (Windows console? Something else?). You may be able to get past this by setting the LINES environment variable to the correct value for your screen.
PDCurses tries to get this info by calling the windows function GetConsoleScreenBufferInfoEx in kernel32.dll, which should be pretty independent of what you're using compiler/terminal/whatnot, as long as you do have some kind of terminal window (not running headless)
In my C program I would like to know where my cursor is located in terminal. For example, another program could have written something before mine and I would like to know how much space is left before the last column of the terminal, or I could not know the terminal reaction to some special sequences (like colors: I could write it but they are not showed).
Any suggestion?
Edit: it would be better avoiding over complicated solutions like ncurses (ncurses doesn't know where's the cursor directly: it computes its position).
Edit 2: I found a way to do it, but it works only in non-graphical terminals: https://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
Edit 3: Nice code and it works well, but it uses /dev/vcsaN (same problem of Edit 2): http://dell9.ma.utexas.edu/cgi-bin/man-cgi?vcs+4
Ncurses is a big and powerful library for creating terminal-based text interfaces.
tputs is a simple low-level universal function for manipulating terminal capabilities.
Either one could serve your needs.
You could try using ncurses' getyx().
This solution is not optimal because it refers to /dev/vcsa*. Hope this could help someone else.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *device = "/dev/vcsa2";
struct {unsigned char lines, cols, x, y;} scrn;
fd = open(device, O_RDWR);
if (fd < 0) {
perror(device);
exit(EXIT_FAILURE);
}
(void) read(fd, &scrn, 4);
printf("%d %d\n", scrn.x, scrn.y);
exit(EXIT_SUCCESS);
}
Generally you are supposed to remember where you've left the cursor.
However, most terminals do respond to DSR; Device Status Request. By sending
CSI 6 n
you'll receive a CPR; cursor position report, in the form of
CSI Pl;Pc R
where Pl and Pc give the cursor line and column number, indexed from 1.
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.
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.