C - Xlib - BadWindow Error using XGetWindowProperty for window title - c

I want to get a list of all open windows' titles using Xlib in C. I am running Ubuntu 12.04. I am using the following code to accomplish this:
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
Window *list(Display *disp, unsigned long *len)
{
Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
int form;
unsigned long remain;
unsigned char *list;
XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
&type, &form, &len, &remain, &list);
return (Window *)list;
}
char *name(Display *disp, Window window)
{
Atom prop = XInternAtom(disp, "WM_NAME", False), type;
int form;
unsigned long remain, len;
unsigned char *list;
XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
&type, &form, &len, &remain, &list);
return (char*)list;
}
int main(int argc, char *argv[])
{
Display *disp;
Window *wlist;
unsigned long len;
char *wname;
disp = XOpenDisplay(NULL);
wlist = (Window*)list(disp, &len);
int i;
for(i = 0; i < (int)len; i++){
if(wlist[i] != 0){
wname = name(disp, wlist[i]);
printf("%d: %s\n", i, wname);
free(wname);
}
}
return 0;
}
Now the problem that I'm having is that this goes through most windows and then gives me a BadWindow error:
0: DNDCollectionWindow
1: launcher
2: Desktop
3: panel
4: Dash
5: Hud
6: Switcher
7: Update Manager
8: Terminal
9: Ask a Question - Stack Overflow - Mozilla Firefox
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 20 (X_GetProperty)
Resource id in failed request: 0x41
Serial number of failed request: 22
Current serial number in output stream: 22
So I'm wondering if anyone knows what is causing this/how to fix it?
As far as I can tell the list function is returning some windows that I can't retrieve the name of, but I'm not sure.
Thanks in advance!

As per my comments, as the code is listed in the question, I get the compiler warning:
In function ‘list’: 14:29: warning: passing argument 10 of
‘XGetWindowProperty’ from incompatible pointer type [enabled by
default]
&type, &form, &len, &remain, &list);
^
In file included ...:
/usr/include/X11/Xlib.h:2688:12: note: expected ‘long unsigned int ’ but argument is of type ‘long unsigned int *’
Which was fixed by removing the address-of operator from the 10th parameter, changing &len to len, as it's being passed to list() as unsigned long *len.
NOTE: in the name() function, as it's declared as unsigned long len, the address-of operator is necessary.
Therefore, I've started with the following code which compiled without warnings:
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
Window *list(Display *disp, unsigned long *len)
{
Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
int form;
unsigned long remain;
unsigned char *list;
XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
&type, &form, len, &remain, &list);
return (Window *)list;
}
char *name(Display *disp, Window window)
{
Atom prop = XInternAtom(disp, "WM_NAME", False), type;
int form;
unsigned long remain, len;
unsigned char *list;
XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
&type, &form, &len, &remain, &list);
return (char*)list;
}
int main(int argc, char *argv[])
{
Display *disp;
Window *wlist;
unsigned long len;
char *wname;
disp = XOpenDisplay(NULL);
wlist = (Window*)list(disp, &len);
int i;
for(i = 0; i < (int)len; i++){
if(wlist[i] != 0){
wname = name(disp, wlist[i]);
printf("%d: %s\n", i, wname);
free(wname);
}
}
return 0;
}
Initially I was not getting the BadWindow error, so I inserted a sleep( 3 ) on line 38, just prior to the for loop to give me enough time to close a window in an attempt to replicate the behaviour.
Sure enough, this reproduced the error: BadWindow (invalid Window parameter).
Scanning the code it originally appeared that the if( wlist[i]==0 ) should kick out invalid window handles, but this is not actually the case. Additionally, inserting a if( !window ) test into the name() function itself was equally futile.
However, the function XSetErrorHandler may be of some use, and I've included your code, revised, to show usage:
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
int catcher( Display *disp, XErrorEvent *xe )
{
printf( "Something had happened, bruh.\n" );
return 0;
}
Window *list(Display *disp, unsigned long *len)
{
Atom prop = XInternAtom(disp, "_NET_CLIENT_LIST", False), type;
int form;
unsigned long remain;
unsigned char *list;
XGetWindowProperty(disp, XDefaultRootWindow(disp), prop, 0, 1024, False, XA_WINDOW,
&type, &form, len, &remain, &list);
return (Window *)list;
}
char *name(Display *disp, Window window)
{
Atom prop = XInternAtom(disp, "WM_NAME", False), type;
int form;
unsigned long remain, len;
unsigned char *list;
XGetWindowProperty(disp, window, prop, 0, 1024, False, AnyPropertyType,
&type, &form, &len, &remain, &list);
return (char*)list;
}
int main(int argc, char *argv[])
{
Display *disp;
Window *wlist;
unsigned long len;
char *wname;
disp = XOpenDisplay(NULL);
wlist = (Window*)list(disp, &len);
sleep( 3 ); // <-- inserted to give me time to close an open window
XSetErrorHandler( catcher ); // <-- inserted to set error handler
int i;
for(i = 0; i < (int)len; i++){
// if(wlist[i] != 0){ // <-- apparently futile?
wname = name(disp, wlist[i]);
printf("%d: %s\n", i, wname);
free(wname);
// }
}
XSetErrorHandler( NULL ); // <-- restore the default error handler
return 0;
}
I've simply created a small function int catcher( Display*, XErrorEvent * ) to catch the errors, avoiding runtime termination.
In case you have more coding to follow, I've included a second call to XErrorHandler(), passing NULL to restore the default handler.
A few other notes, first tested this code by killing the last window I created, but that wasn't quite enough to determine if it would proceed after receiving the error. So I did a second test wherein I killed windows that came before the end of the list, and have verified success.
A few final notes:
Obviously the error handler is over-simplified. When the error is caught, the message is displayed, and the program continues to run.
However, the window item is still printed, but is reflected as (null)...
E.G.:
7: neo – Dolphin
8: neo – Dolphin
Something had happened, bruh.
9: (null)
10: neo – Dolphin
Hopefully this can get you started... I'll leave the fun parts, such as detecting which error 'had happened', and adjusting the numbering/display of the list up to you ; )

Related

How to get top-level windows and their names using libxcb

I have a Linux desktop with 2 open windows: a terminal and a browser. I'm trying to get the name of those windows with libxcb. Here's my code based on examples I found at https://www.systutorials.com/docs/linux/man/3-xcb_query_tree_reply/
Here's my code:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <xcb/xcb.h>
void get_children(xcb_connection_t* c, xcb_window_t window, xcb_window_t** children, int* count)
{
*count = 0;
*children = NULL;
auto cookie = xcb_query_tree(c, window);
auto reply = xcb_query_tree_reply(c, cookie, NULL);
if (reply)
{
*count = xcb_query_tree_children_length(reply);
*children = xcb_query_tree_children(reply);
free(reply);
}
}
void get_name(xcb_connection_t* c, xcb_window_t window, char** name, int* length)
{
*length = 0;
*name = NULL;
auto cookie = xcb_get_property(c, 0, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 0);
auto reply = xcb_get_property_reply(c, cookie, NULL);
if (reply)
{
*length = xcb_get_property_value_length(reply);
*name = (char*)xcb_get_property_value(reply);
free(reply);
}
}
int main()
{
auto c = xcb_connect(":0.0", NULL);
auto screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
auto rootWindow = screen->root;
int nChildren;
xcb_window_t* children;
get_children(c, screen->root, &children, &nChildren);
for (int i = 0; i < nChildren; i++)
{
auto wid = children[i];
int length;
char* name;
get_name(c, wid, &name, &length);
printf("%u %d\n", wid, length);
}
return 0;
}
This returns 40 windows all with their name's length of 0. For example:
20971989 0
20971802 0
20972112 0
20972308 0
... (truncated for brevity)
I'm trying to get something like the output of wmctrl -l.
What am I doing wrong?
I figured out the problem. I needed to add a length to the xcb_get_property function call. The following code works.
auto cookie = xcb_get_property(c, 0, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1000);

C programming - pthread_create() structure as parameter

I have been working out an example to demonstrate multithreading using POSIX on processing operation of an image. The encoding was done with lodepng library. I wanted the code to break a color inverse process of any loaded image into 4 equal threads. Although I have checked repeatedly, I still cant find out why the 4th thread starting and ending values are getting modified inside the threadFunc2() function. Its the same code used by other 3 threads getting correct start and end values. I have used a structure to pass start, end and thread number data into function. For example, if I load a 10x10 image which results in 100 pixels (each with 4 values for R,G, B and Transparency),it requires a 400 element array to store each color value. The 4th thread should start with 300 and 399. Its correctly calculated in the main() function before passing to function, but ends up as being 5 and 6 within the threadFunc2() at start.
#include <pthread.h>
#include "lodepng.h"
#include <stdio.h>
#include <stdlib.h>
#include "lodepng.c"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned int error;
unsigned int encError;
unsigned char* image;
unsigned int width;
unsigned int height;
int Arraysize;
const char* filename = "10x10Circle.png";
const char* newFileName = "10x10Result.png";
struct Markers{int start;int end;int no};
void *threadFunc(void *arg){ // function to load the image into an array
pthread_mutex_lock(&mutex);
error = lodepng_decode32_file(&image, &width, &height, filename);
if(error){
printf("error %u: %s\n", error, lodepng_error_text(error));
}
Arraysize = 4*height*width;
printf("arraysize:%d, %d \n",sizeof(image)/sizeof(image[0]),Arraysize);
pthread_mutex_unlock(&mutex);
return NULL; }
void *threadFunc2(void *arg){ //function to apply inverse process on loaded data
struct Markers*vars= (struct Markers*) arg;
printf("Thread %d start|start-%d,end-%d\n",vars->no,vars->start,vars->end);
for( int i = vars->start; i<(vars->end); i=i+4){
pthread_mutex_lock(&mutex);
image[0+i]= 255-image[0+i];
image[1+i]= 255-image[1+i];
image[2+i]= 255-image[2+i];
image[3+i]= 255-image[3+i];// can be ignored
printf("Thread: %d,round:%d\n",vars->no,i);// debug line
pthread_mutex_unlock(&mutex);
}
// printf("Thread: %d,after end:%d\n",vars->no,i);
printf("**************************\n");
printf("Thread end\n");
return NULL;
}
void *encodeprocessed(){
encError = lodepng_encode32_file(newFileName, image, width, height);
if(encError){
printf("error %u: %s\n", error, lodepng_error_text(encError)); }
free(image); }
Following is the main function
int main(void){
pthread_t pth,pth0, pth1, pth2, pth3;
pthread_create(&pth,NULL,threadFunc,NULL);
pthread_join(pth, NULL );
struct Markers Positions[3];
Positions[0].start = 0;
Positions[0].end = Arraysize/4 -1;
Positions[0].no = 1;
Positions[1].start =Arraysize/4;
Positions[1].end = Arraysize/2 -1;
Positions[1].no = 2;
Positions[2].start =Arraysize/2;
Positions[2].end = Arraysize*3/4 -1;
Positions[2].no = 3;
Positions[3].start =(Arraysize*3)/4;
Positions[3].end = Arraysize -1;
Positions[3].no = 4;
//debug line
printf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n",Arraysize,Positions[0].start,Positions[0].end,
Positions[1].start,Positions[1].end,Positions[2].start,Positions[2].end,
Positions[3].start,Positions[3].end);
pthread_create(&pth0,NULL,threadFunc2,&Positions[0]);
pthread_create(&pth1,NULL,threadFunc2,&Positions[1]);
pthread_create(&pth2,NULL,threadFunc2,&Positions[2]);
pthread_create(&pth3,NULL,threadFunc2,&Positions[3]);
pthread_join(pth0, NULL );
pthread_join(pth1, NULL );
pthread_join(pth2, NULL );
pthread_join(pth3, NULL );
encodeprocessed();
return 0;}
The code is running without any errors. Image gets inverted only 75% and gets saved. Anyone who can give me a clue is much appreciated.

XGetImage is mangled for chrome, firefox, electron, when using XCompositeRedirectWindow

I am attempting to create a thumbnailer (for i3wm on linux) which generates an icon from a screenshot for all the available windows. The aim being to replicate something like how windows uses Alt-Tab to produce a pane of windows to choose from;
The current prototype uses pygtk to generate the dialog, and it creates thumbnails of the windows in the _NET_CLIENT_LIST using XGetImage where the windows have been redirected using XCompositeRedirectWindow. It works pretty well except for that images captured from windows which are browsers, (e.g. firefox, chrome, electron) are mangled, or wrong;
Basically, tools like xwd, scrot and import don't work for the hidden windows in i3, presumably because they are unmapped. So I have pulled some code together to create the thumbnails. The core of it is based on an example using XCompositeRedirectWindow from X11/extensions/Xcomposite.h from here.
My attempt at creating a short example is here;
https://gist.github.com/tolland/4bb1e97db258b92618adfb783ce66fac
it can be compiled with;
$ gcc example.c -lX11 -lXcomposite -lXrender -lpng -o example
and then to output png files for each of the windows;
$ mkdir -p /tmp/png_out && ./example
will produce pngs for each of the images
window found was 58720312
found window name for 58720312 : build : sudo
filename /tmp/png_out/58720312_test3.png
window found was 79691781
found window name for 79691781 : .xsession-errors - glogg
filename /tmp/png_out/79691781_test3.png
window found was 62914576
found window name for 62914576 : Edit - Stack Overflow - Mozilla Firefox
filename /tmp/png_out/62914576_test3.png
So the code I am currently using to walk the _NET_CLIENT_LIST is this;
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <libpng16/png.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
//Compile hint: gcc -shared -O3 -lX11 -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c
typedef int bool;
#define true 1
#define false 0
const int DEBUG = 0;
void getScreen2(const int, const int, const int, const int, const XID);
void write_png_for_image(XImage *image, XID xid, int width, int height,
char *filename);
typedef int (*handler)(Display *, XErrorEvent *);
XID getWindows(Display *display, Window parent, Window window, XID xid,
int depth);
int main() {
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
uint nwindows;
Window root_return, parent_return, *windows;
Atom a = XInternAtom(display, "_NET_CLIENT_LIST", true);
Atom actualType;
int format;
unsigned long numItems, bytesAfter;
unsigned char *data = 0;
int status = XGetWindowProperty(display, root, a, 0L, (~0L),
false,
AnyPropertyType, &actualType, &format, &numItems, &bytesAfter, &data);
char* window_name_return;
if (status >= Success && numItems) {
long *array = (long*) data;
for (long k = 0; k < numItems; k++) {
Window window = (Window) array[k];
//not finding chrome window name
printf("window found was %d \n", window);
if (XFetchName(display, window, &window_name_return)) {
printf("found window name for %d : %s \n", window,
window_name_return);
}
//XMapWindow(display, parent);
XMapWindow(display, window);
XWindowAttributes attr;
Status status = XGetWindowAttributes(display, window, &attr);
if (status == 0)
printf("Fail to get window attributes!\n");
getScreen2(0, 0, attr.width, attr.height, window);
}
XFree(data);
}
return 0;
}
which calls this function to map the window and call XCompositeRedirectWindow;
void getScreen2(const int xx, const int yy, const int W, const int H,
const XID xid) {
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
// turn on --sync to force error on correct method
//https://www.x.org/releases/X11R7.6/doc/man/man3/XSynchronize.3.xhtml
XSynchronize(display, True);
int counter = 1;
// select which xid to operate on, the winder or its parent
//XID xwid = fparent;
XID xwid = xid;
// Requests the X server to direct the hierarchy starting at window to off-screen storage
XCompositeRedirectWindow(display, xwid, CompositeRedirectAutomatic);
XWindowAttributes attr;
Status status = XGetWindowAttributes(display, xwid, &attr);
int width = attr.width;
int height = attr.height;
int depth = attr.depth;
Pixmap xc_pixmap = XCompositeNameWindowPixmap(display, xwid);
if (!xc_pixmap) {
printf("xc_pixmap not found\n");
}
//XWriteBitmapFile(display, "test1.xpm", pixmap, W, H, -1, -1);
XRenderPictFormat *format = XRenderFindVisualFormat(display, attr.visual);
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
Picture picture = XRenderCreatePicture(display, xwid, format,
CPSubwindowMode, &pa);
char buffer[50];
int n;
int file_counter = 1;
n = sprintf(buffer, "/tmp/%d_test%d.xpm", xid, file_counter++);
XWriteBitmapFile(display, buffer, xc_pixmap, W, H, -1, -1);
n = sprintf(buffer, "/tmp/%d_test%d.xpm", xid, file_counter++);
XWriteBitmapFile(display, buffer, xid, W, H, -1, -1);
XImage *image = XGetImage(display, xid, 0, 0, W, H, AllPlanes, ZPixmap);
if (!image) {
printf("XGetImage failed\n");
}
char filename[255];
int n2;
n2 = sprintf(filename, "/tmp/png_out/%d_test%d.png", xid, file_counter++);
printf("filename %s \n", filename);
write_png_for_image(image, xid, W, H, filename);
//XFree(image);
XDestroyImage(image);
XDestroyWindow(display, root);
XCloseDisplay(display);
}
and then this to write out the png;
void write_png_for_image(XImage *image, XID xid, int width, int height,
char *filename) {
int code = 0;
FILE *fp;
png_structp png_ptr;
png_infop png_info_ptr;
png_bytep png_row;
char buffer[50];
int n;
n = sprintf(buffer, filename, xid);
// Open file
fp = fopen(buffer, "wb");
if (fp == NULL) {
fprintf(stderr, "Could not open file for writing\n");
code = 1;
}
// Initialize write structure
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fprintf(stderr, "Could not allocate write struct\n");
code = 1;
}
// Initialize info structure
png_info_ptr = png_create_info_struct(png_ptr);
if (png_info_ptr == NULL) {
fprintf(stderr, "Could not allocate info struct\n");
code = 1;
}
// Setup Exception handling
if (setjmp(png_jmpbuf (png_ptr))) {
fprintf(stderr, "Error during png creation\n");
code = 1;
}
png_init_io(png_ptr, fp);
// Write header (8 bit colour depth)
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
// Set title
char *title = "Screenshot";
if (title != NULL) {
png_text title_text;
title_text.compression = PNG_TEXT_COMPRESSION_NONE;
title_text.key = "Title";
title_text.text = title;
png_set_text(png_ptr, png_info_ptr, &title_text, 1);
}
png_write_info(png_ptr, png_info_ptr);
// Allocate memory for one row (3 bytes per pixel - RGB)
png_row = (png_bytep) malloc(3 * width * sizeof(png_byte));
unsigned long red_mask = image->red_mask;
unsigned long green_mask = image->green_mask;
unsigned long blue_mask = image->blue_mask;
// Write image data
//int xxx, yyy;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned long pixel = XGetPixel(image, x, y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
png_byte *ptr = &(png_row[x * 3]);
ptr[0] = red;
ptr[1] = green;
ptr[2] = blue;
}
png_write_row(png_ptr, png_row);
}
// End write
png_write_end(png_ptr, NULL);
// Free
fclose(fp);
if (png_info_ptr != NULL)
png_free_data(png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL)
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
if (png_row != NULL)
free(png_row);
}
However when the windows is browser based, the image is mangled like so;
Do I need to do something special to get browser windows working?
References;
https://www.talisman.org/~erlkonig/misc/x11-composite-tutorial/
Get a screenshot of a window that is cover or not visible or minimized with Xcomposite extension for X11

After creating threads using CreatThread api the output on the console consists of question marks

everyone... I've just started to learn how to create process and thread using Windows API. My code does work if I want thread to display integer on the screen but it doesn't work when using array of chars... Can someone tell me what am I doing wrong? The code:
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#include<tchar.h>
#include<strsafe.h>
#include<string.h>
#define N 4
#define bufferSize 255
DWORD WINAPI Threader(LPVOID Parameter);
typedef struct Data {
char value[bufferSize];
} Data, *pToData;
int main()
{
int i;
char c[bufferSize];
pToData threadData[N];
HANDLE handleArray[N];
DWORD threadID[N];
FILE *file=fopen("niti.txt", "r");
for(i=0; i<N; i++)
{
fscanf(file, "%s", c);
threadData[i] = (pToData) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Data));
strcpy(threadData[i]->value, c);
handleArray[i]=CreateThread(NULL, 0, Threader, threadData[i], 0, &threadID[i]);
}
WaitForMultipleObjects(N, handleArray, TRUE, INFINITE);
for(i=0; i<N; i++)
{
CloseHandle(handleArray[i]);
if(threadData[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, threadData[i]);
threadData[i] = NULL;
}
}
fclose(file);
return 0;
}
DWORD WINAPI Threader(LPVOID Parameter)
{
HANDLE hStdOut;
TCHAR messageBuffer[bufferSize];
size_t cchStringSize;
DWORD dwChars;
pToData dataArray;
char temp[bufferSize];
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdOut == INVALID_HANDLE_VALUE )
return 1;
dataArray=(pToData)Parameter;
StringCchPrintf(messageBuffer, bufferSize, TEXT("Parameter = %s\n"), dataArray->value);
StringCchLength(messageBuffer, bufferSize, &cchStringSize);
WriteConsole(hStdOut, messageBuffer, (DWORD)cchStringSize, &dwChars, NULL);
return 0;
}
If I change value in my struct to int and do the same in main the output is correct. Any suggestions?
Thank you!
You are probably compiling for Unicode but outputting a char array. Your symptoms sound like an encoding mismatch and Unicode output function mis-matched against ANSI char array is the mismatch that results in lots of questions marks.
In other words I hypothesise that your code resolves StringCchPrintf as StringCchPrintfW. And you then fail to satisfy the contract by passing char* rather than wchar_t* when you pass dataArray->value.
Use wchar_t or TCHAR instead of char for dataArray->value. Or call the A version of the output functions. Or compile for ANSI.

XFetchName always returns 0

im trying to write a C code to get the title of the Active Window in my Linux System, but the Function XFetchName always returnes zero, i also tried XGetWMName, same result...
but using xprop, i can see that there is a string in the "WM_NAME" property
can anyone tell me whats wrong with my code?
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdarg.h>
int main( int argc, char* argv[] )
{
Display *display;
Window focus;
char *window_name;
int revert;
display = XOpenDisplay(NULL);
XGetInputFocus(display, &focus, &revert);
int ret = XFetchName(display, focus, &window_name);
printf("ret = %d\n", ret);
if (window_name) printf("Title = %s\n", window_name);
return 0;
}
thanks.
You can try using XGetWMName function. Although the discriptions of XGetWMName and XFetchName both say they will return the WM_NAME property, it seems that they are different from each other. Some times, they return the same name. Some times, only XGetWMName returns the name.
You can also use xwininfo -root -tree to get all the windows' name, and compare with the result of XFetchName and XGetWMName.
This code can list all the windows and print the window id and result of XFetchName and XGetWMName. You can use the window id to look up in the output of xwininfo -root -tree.
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void enum_windows(Display* display, Window window, int depth) {
int i;
XTextProperty text;
XGetWMName(display, window, &text);
char* name;
XFetchName(display, window, &name);
for (i = 0; i < depth; i++)
printf("\t");
printf("id=0x%x, XFetchName=\"%s\", XGetWMName=\"%s\"\n", window, name != NULL ? name : "(no name)", text.value);
Window root, parent;
Window* children;
int n;
XQueryTree(display, window, &root, &parent, &children, &n);
if (children != NULL) {
for (i = 0; i < n; i++) {
enum_windows(display, children[i], depth + 1);
}
XFree(children);
}
}
int main() {
Display* display = XOpenDisplay(NULL);
Window root = XDefaultRootWindow(display);
enum_windows(display, root, 0);
}
Here's a piece of output showing that the result of two functions may be different.
id=0x2c7, XFetchName="(no name)", XGetWMName="(null)"
id=0x400001, XFetchName="(no name)", XGetWMName="(null)"
id=0x800036, XFetchName="(no name)", XGetWMName="(null)"
id=0x1400001, XFetchName="(no name)", XGetWMName="c - XFetchName always returns 0 - Stack Overflow - Chromium"
id=0x1000001, XFetchName="terminator", XGetWMName="terminator"
id=0x1000002, XFetchName="(no name)", XGetWMName="(null)"
id=0x1200001, XFetchName="chromium", XGetWMName="chromium"
id=0x1200002, XFetchName="(no name)", XGetWMName="(null)"
Here's a piece of the output of xwininfo -root -tree showing the name of these windows.
xwininfo: Window id: 0x2c7 (the root window) (has no name)
Root window id: 0x2c7 (the root window) (has no name)
Parent window id: 0x0 (none)
29 children:
0x1200001 "chromium": ("chromium" "Chromium") 10x10+10+10 +10+10
1 child:
0x1200002 (has no name): () 1x1+-1+-1 +9+9
0x1000001 "terminator": ("terminator" "Terminator") 10x10+10+10 +10+10
1 child:
0x1000002 (has no name): () 1x1+-1+-1 +9+9
0x800036 (has no name): () 1364x741+0+25 +0+25
1 child:
0x1400001 "c - XFetchName always returns 0 - Stack Overflow - Chromium": ("Chromium" "Chromium") 1364x741+0+0 +1+26
0x400001 (has no name): () 10x10+-20+-20 +-20+-20
/*
* The following functions are internationalized substitutions
* for XFetchName and XGetIconName using XGetWMName and
* XGetWMIconName.
*
* Please note that the third arguments have to be freed using free(),
* not XFree().
*/
Status
I18N_FetchName(dpy, w, winname)
Display *dpy;
Window w;
char ** winname;
{
int status;
XTextProperty text_prop;
char **list;
int num;
status = XGetWMName(dpy, w, &text_prop);
if (!status || !text_prop.value || !text_prop.nitems) return 0;
status = XmbTextPropertyToTextList(dpy, &text_prop, &list, &num);
if (status < Success || !num || !*list) return 0;
XFree(text_prop.value);
*winname = (char *)strdup(*list);
XFreeStringList(list);
return 1;
}
//XFetchName uses XGetWMName
see: enter link description here
The XFetchName function returns the name of the specified window. If it succeeds, it returns a nonzero status; otherwise, no name has been set for the window, and it returns zero.
You need to set a name for your window.
I started an xterm session and executed you code and got the following output:
sangeeth#home:~/work/test$ ./a.out
ret = 1
Title = sangeeth#home: ~/work/test
sangeeth#home:~/work/test$
OTOH, I tried compiling your program and got the following error:
(.text+0x18): undefined reference to `main'
You need to change
int _main( int argc, char* argv[] )
to
int main(int argc, char* argv[])

Resources