XFetchName always returns 0
Asked Answered
H

3

7

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.

Haihaida answered 11/1, 2012 at 19:47 Comment(2)
Your code works perfectly fine on the machine I'm currently using (OSX Lion) when run from an Xterm (which by default has the name xterm set). In addition, I added a call to XStoreName() to set it to something else first and that worked as expected as well with your code retrieving the new name just fine. This is of course after renaming _main() to main() - How are you running your program?Dollar
the '_' is just to define an entry point name with the command line "-Wl,-e__main" because im not using stdlib, i dont think this has to do anything. and still when executed from Ubuntu's Terminal it returns 0, but works from xterm, is there a reason for this?Haihaida
A
7

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
Academia answered 1/12, 2014 at 11:36 Comment(3)
Thanks this is really helpful :)Elder
You could use a static variable for the depth parameter, that way you don't need to use those extra 4 bytes of stack space per recursive call.Pipestone
Also, the last parameter of XQueryTree is unsigned.Pipestone
A
0
 /*
  * 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

Annoying answered 1/8, 2016 at 18:41 Comment(0)
A
-1

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[]) 
Arbor answered 11/1, 2012 at 19:54 Comment(5)
I suspect the _main() is because it's a hook into a larger framework which could be the actual problem.Dollar
@BrianRoach Thats a good point. We need to hear more details from the OP.Arbor
the '_' is just to define an entry point name "-Wl,-e__main" because im not using stdlibHaihaida
well, it works when executed under xterm, but not when executed from normal terminal !Haihaida
Perhaps the "normal terminal" is only setting the modern _NET_WM_NAME and not the older WM_NAME? standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2506989Upon

© 2022 - 2024 — McMap. All rights reserved.