Find the answer to your Linux question:
Results 1 to 7 of 7
i'm writing a program that does a couple nested XQueryTree's to find window IDs based on window names. at initialization it works just fine getting the ID's of 3 windows. ...
  1. #1
    Just Joined!
    Join Date
    Apr 2008
    Posts
    4

    XLib - XQueryTree fails -- help

    i'm writing a program that does a couple nested XQueryTree's to find window IDs based on window names.

    at initialization it works just fine getting the ID's of 3 windows.

    the problem comes later on in execution where an event triggers another query using the same C function as used before... however this time if fails by having XQueryTree returning a 0. i'm sending the same Display Pointer and Root Window ID...

    is there any way to determine why XQueryTree is returning 0? or any ideas why it might be failing?

    thanks a bunch in advance.

  2. #2
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    According to the O'Reilly XLib Reference Manual, the only possible error is BadWindow.

    Could you possibly log somewhere the actual values of the first two parameters to XQueryTree just before you call it, both at the beginning (where it works) and later (where it fails), just to make sure they haven't changed? That's what I would do next, anyway.
    --
    Bill

    Old age and treachery will overcome youth and skill.

  3. #3
    Just Joined!
    Join Date
    Apr 2008
    Posts
    4
    the values of the first two arguments (Display Pointer and Root Window) are EXACTLY the same when it works and when it doesn't...

    here's what i have that breaks....
    Code:
    Window find_window_id(char *app_name, int repeat)
    {
        Window root_return, parent_return, *children_return, *chld_tmp, ret_val;
        int nchildren_return, tmp, i, j;
        int found = 0;
        char *win_name;
     
        do
        {
          if (XQueryTree(dpy, X_Root_Window, &root_return, &parent_return, &children_return, &nchildren_return))
          {
            for (i=0; i < nchildren_return; i++)
            {
            XQueryTree(dpy, children_return[i], &root_return, &parent_return, &chld_tmp, &tmp);
            for (j=0; j < tmp; j++) 
            {
              if (XFetchName(dpy, chld_tmp[j], &win_name)) 
              {
                if (strcmp (app_name, win_name) == 0) 
                {
                  found = 1;
                  break;
                }
              }
            }
            if (found == 1) break;
          }
          }
          else printf("didnt work\n");
        } while ((repeat == 1) && (found != 1));
        
        if (found == 1)
        {
          ret_val = chld_tmp[j];
          XFree(children_return);
          XFree(chld_tmp);
          return ret_val;
        }      
        else 
        {
          XFree(children_return);
          XFree(chld_tmp);
          return 0;
        }
    }

    i got a workaround that works... doing this...
    Code:
    Window find_window_id(char *app_name, int repeat)
    {
        Window root_return, parent_return, *children_return, *chld_tmp, ret_val;
        int nchildren_return, tmp, i, j;
        int found = 0;
        char *win_name;
        Display *tmp_dpy;
     
        tmp_dpy = XOpenDisplay ("192.168.1.99:0.0");
     
        do
        {
          if (XQueryTree(tmp_dpy, XDefaultRootWindow(tmp_dpy), &root_return, &parent_return, &children_return, &nchildren_return))
          {
          for (i=0; i < nchildren_return; i++)
          {
            XQueryTree(dpy, children_return[i], &root_return, &parent_return, &chld_tmp, &tmp);
            for (j=0; j < tmp; j++) 
            {
              if (XFetchName(dpy, chld_tmp[j], &win_name)) 
              {
                if (strcmp (app_name, win_name) == 0) 
                {
                  found = 1;
                  break;
                }
              }
            }
            if (found == 1) break;
          }
          }
          else printf("didnt work\n");
        } while ((repeat == 1) && (found != 1));
        
        if (found == 1)
        {
          ret_val = chld_tmp[j];
          XFree(children_return);
          XFree(chld_tmp);
          XCloseDisplay(tmp_dpy);
          return ret_val;
        }      
        else 
        {
          XFree(children_return);
          XFree(chld_tmp);
          XCloseDisplay(tmp_dpy);
          return 0;
        }
    }
    the work around makes no sense to me whatsoever since the values are the same... and the nested XQueryTree continues then to work fine using the global 'dpy' and 'X_Root_Window'

    any ideas?

  4. #4
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    I would say that someone is stomping on something that shouldn't be stomped on somewhere. I know that's a notoriously difficult thing to find, but I think that's what's going on. It could be that the window ID hasn't changed, but that stuff in your heap has been trashed.

    At any rate, three questions.

    First, in the first chunk of code, does it fail on the outer XQueryTree(), or the inner XQueryTree()?

    Second, when you say this:
    the values of the first two arguments (Display Pointer and Root Window) are EXACTLY the same when it works and when it doesn't
    do you know this from inspection of the code, or have you actually inserted printf() statements just before each XQueryTree call to make sure?

    Third, what happens when you try this instead? This is exactly like your first code (the code that misbehaves) except for the first call to XQueryTree().
    Code:
    Window find_window_id(char *app_name, int repeat)
    {
        Window root_return, parent_return, *children_return, *chld_tmp, ret_val;
        int nchildren_return, tmp, i, j;
        int found = 0;
        char *win_name;
    
        do
        {
          if (XQueryTree(dpy, XDefaultRootWindow(dpy), &root_return, &parent_return,
     &children_return, &nchildren_return))
          {
            for (i=0; i < nchildren_return; i++)
            {
            XQueryTree(dpy, children_return[i], &root_return, &parent_return, &chld_
    tmp, &tmp);
            for (j=0; j < tmp; j++)
            {
              if (XFetchName(dpy, chld_tmp[j], &win_name))
              {
                if (strcmp (app_name, win_name) == 0)
                {
                  found = 1;
                  break;
                }
              }
            }
            if (found == 1) break;
          }
          }
          else printf("didnt work\n");
        } while ((repeat == 1) && (found != 1));
    
        if (found == 1)
        {
          ret_val = chld_tmp[j];
          XFree(children_return);
          XFree(chld_tmp);
          return ret_val;
        }
        else
        {
          XFree(children_return);
          XFree(chld_tmp);
          return 0;
        }
    }
    --
    Bill

    Old age and treachery will overcome youth and skill.

  5. #5
    Just Joined!
    Join Date
    Apr 2008
    Posts
    4
    Quote Originally Posted by wje_lf View Post
    First, in the first chunk of code, does it fail on the outer XQueryTree(), or the inner XQueryTree()?
    if fails on the outer... inner works fine every time.

    do you know this from inspection of the code, or have you actually inserted printf() statements just before each XQueryTree call to make sure?
    i used printf's and compared when it worked to when it didn't and they were the same.

    Third, what happens when you try this instead? This is exactly like your first code (the code that misbehaves) except for the first call to XQueryTree().
    it still fails using dpy and xdefaultrootwindow(dpy)

    so here's the weird thing...
    this doesn't work
    Code:
    XQueryTree(dpy, X_Root_Window, ...
    but this does...
    Code:
    XQueryTree(tmp_dpy, X_Root_Window, ...
    same root window id but new display pointer. the inner query always works fine with the global display pointer. bizarre.

    some code in the same file will still do XQueryPointer's no problem using the same global display pointer.

    i'm at a loss... but at least i have a lousy work-around.

    any other insight?

  6. #6
    Just Joined!
    Join Date
    Apr 2008
    Posts
    4
    one other thing. these routines are being called externally by another program... dont know if that makes a difference.

  7. #7
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    any other insight?
    We've eliminated all the painless explanations, so the only one left is the painful one.

    Something somewhere in the application is stomping on something in your heap (or, less likely, the stack) that it shouldn't be stomping on. The offending code might even have nothing to do with X Window processing.

    So here's what you should probably do, painful as it is!

    Write a bare-bones X application which throws up a window with an arbitrary name and waits for keystroke input in the window. (This will, among other good effects, make sure that all the data gets flushed to the X server.) Then, in reaction to the keystroke event, call this function.

    Then wait for the event you talked about in your original post (it might be another keystroke; it doesn't matter), and call this function again.

    I'll bet the function works perfectly both times.

    If that's the case, it's almost certainly going to be a memory-stomping bug elsewhere in the application. If that's the case, the yellow brick road you are walking will be a long, hard yellow brick road.
    --
    Bill

    Old age and treachery will overcome youth and skill.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...