Thread: xlib: XTextProperty to string for comarison

  1. #1
    Registered User
    Join Date
    Oct 2021
    Posts
    10

    xlib: XTextProperty to string for comarison

    I'm trying to compare text.value to a string to catch when certain windows are open. It would be easy to use the XFetchName to do this, but it doesn't catch all the windows as XGetWMName does.

    focused:
    Code:
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
    #include <string.h>
    
    // gcc -Wall focused.c -o focused -lX11 && focused
    
    XTextProperty text;
    
    Window get_toplevel_parent(Display * display, Window window) {
    
         Window parent;
         Window root;
         Window * children;
         unsigned int num_children;
    
         while (1) {
    
             if (XQueryTree(display, window, &root,
                       &parent, &children, &num_children) == 0) {
                 printf("XQueryTree error\n");
             }
    
             if (children)
                 XFree(children);
             
             if (window == root || parent == root)
                return window;
             else {
                XGetWMName(display, window, &text);
                window = parent;
             } 
         }
    }
    
    int main(int argc, char *argv[]) {
    
       Display *display;
       display = XOpenDisplay(NULL);
       Window focus, toplevel_parent_of_focus;
       XWindowAttributes attr;
       int revert;
        
       while (1) {
    
          XGetInputFocus(display, &focus, &revert);
          toplevel_parent_of_focus = get_toplevel_parent(display, focus);
          XGetWindowAttributes(display, toplevel_parent_of_focus, &attr);
    
          // Can check for null
          if (text.value == NULL)
             printf("NULL\n");
    
          // Cannot do this (error below):
          if (strcmp(text.value, "xterm") != 0)
             printf("xterm found\n");
    
          printf("Text: %s\n", text.value);
    
          // .5 sec
          usleep(500000); // .5 sec
       }
    
       return 0;
    }
    Resulting error:
    Code:
    focused.c:58:22: warning: pointer targets in passing argument 1 of ‘strcmp’ differ in signedness [-Wpointer-sign]
       58 |       if (strcmp(text.value, "xterm") != 0)
          |                  ~~~~^~~~~~
          |                      |
          |                      unsigned char *
    In file included from focused.c:7:
    /usr/include/string.h:140:32: note: expected ‘const char *’ but argument is of type ‘unsigned char *’
      140 | extern int strcmp (const char *__s1, const char *__s2)
          |                    ~~~~~~~~~~~~^~~~
    There is this command: Xlib Programming Manual: XTextPropertyToStringList

    ... but I cannot figure out how to use it or if it would even be suitable to compare such strings.

    Any ideas?

  2. #2
    Registered User
    Join Date
    Oct 2019
    Posts
    46
    The warning has no implications on your side. To get around it you can cast your string to const char *
    Code:
       if (strcmp((const char *)text.value, "xterm") != 0)
    By the way should that be:

    Code:
      if (strcmp((const char *)text.value, "xterm") == 0)
    The signature mostly guides the API developers(strcmp in this case) into making sure the two strings are not modified from within the function/API.
    Last edited by ghoul; 10-25-2021 at 12:44 PM.

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    1,191
    Try replacing lines 58 and 59 with this:
    Code:
        if (text.format != 8)
            printf("bad format\n");
        else {
            char *v = text.value;
            while (*v) {
                if (strcmp(v, "xterm");
                    printf("xterm found\n");
                v += strlen(v);
            }
        }
    We live as it were by chance, and by chance we are governed. - Seneca

  4. #4
    Registered User
    Join Date
    Oct 2021
    Posts
    10
    Quote Originally Posted by ghoul View Post
    The warning has no implications on your side. To get around it you can cast your string to const char *
    Code:
       if (strcmp((const char *)text.value, "xterm") != 0)
    By the way should that be:

    Code:
      if (strcmp((const char *)text.value, "xterm") == 0)
    The signature mostly guides the API developers(strcmp in this case) into making sure the two strings are not modified from within the function/API.
    This code worked fine. I thought it was something to do with casting but didn't know how. I've started reading 'C Primer Plus' to refresh my knowledge of C, so that should help with the common knowledge questions like like.

    Code:
    john.c
    Try replacing lines 58 and 59 with this: Code: if (text.format != 8) printf("bad format\n"); else { char *v = text.value; while (*v) { if (strcmp(v, "xterm"); printf("xterm found\n"); v += strlen(v); } }
    I'm liking this text.format variable to indicate bad format. Very nice.

    The reason why I asked this question is to be able to tell if there's an open window on the screen (and to manipulate it if it meets the conditions) or to see if there are no windows open, and in that case just do nothing.

    The program's objective is to continually poll the focused window, panel, and virtual keyboard, and to change the width of the virtual keyboard if the panel is up or the height/width of the focused application depending on if the keyboard or panel is up. This way, screen space is always be used as efficiently as possible, and the virtual keyboard never overlaps the windows. I have this working just fine with some inefficient code that calls external programs as marked within the code.

    The efficient program works perfectly so long as there is always a window on the screen; else, the XResizeWindow() command tries to resize the root desktop (I presume), and thus ends in either a bad window error or creates a dead window on the screen, which stays there indefinitely.

    focused.c
    Code:
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
    #include <string.h>
    
    // gcc -Wall focused.c -o focused -lX11 && focused
    
    XTextProperty text;
    char *name;
    
    Window get_toplevel_parent(Display * display, Window window)
    {
         Window parent;
         Window root;
         Window * children;
         unsigned int num_children;
    
         while (1) {
    
             if (0 == XQueryTree(display, window, &root,
                       &parent, &children, &num_children)) {
    
                 fprintf(stderr, "XQueryTree error\n");
                 abort();
             }
    
             if (children)
                 XFree(children);
                      
             if (window == root || parent == root) {
     
                 return window;
    
             } else {
    
                // better at grabbing window names
                XGetWMName(display, window, &text);
    
                window = parent;
    
                // worse at grabbing window names
                XFetchName(display, window, &name);
            } 
        }
    }
    
    int main(int argc, char *argv[]) {
    
       Display *display; // 800x480
       Window focus, toplevel_parent_of_focus, window, last_window;
       XWindowAttributes attr;
       int revert, winNum, winPid, winX, winY = 240;
       char pidline [64] = "";
       char command [64] = "";
       char winName [64] = "";
    
       FILE *fpid;
    
       display = XOpenDisplay(NULL);
    
       // svkbd = virtual keyboard
       // panel = vertical panel on right side of screen    
       int svkbd, last_svkbd = 0, panel, last_panel = 0, last_window_x = 0, last_window_y = 0, last_win_x = 0;
    
       while (1) {
    
          XGetInputFocus(display, &focus, &revert);
          toplevel_parent_of_focus = get_toplevel_parent(display, focus);
    
          // check if the virtual keyboard is on 
          pidline[0] = '\0';
          fpid = popen("pidof svkbd-en&", "r");
          if (fgets(pidline, 64, fpid) != 0)
             svkbd = 1;
          else
             svkbd = 0;
          pclose(fpid);
    
          // Check if panel is up
          pidline[0] = '\0';
          fpid = popen("pidof panel&", "r");
          if (fgets(pidline, 64, fpid) != 0)
             panel = 1;
          else
             panel = 0;
          pclose(fpid);
    
          // Get focused window
          window = (unsigned)toplevel_parent_of_focus;
          printf("Name: %s\n", (const char *)text.value);
    
          // Only execute if current changes will affect the virt. keyboard or focused app; don't try to change to the same size 
          if ((svkbd != last_svkbd || panel != last_panel || window != last_window || attr.width != last_window_x || attr.height != last_window_y) ) {
    
             // Working but inefficient code
     /*      printf("Change found: %s\n", command);
             pidline[0] = '\0';
             fpid = popen("xdotool getactivewindow; xdotool getwindowname $(xdotool getactivewindow) &", "r");
             fgets(pidline, 64, fpid);
             winNum = strtoul(pidline, NULL, 10);
             pidline[0] = '\0';
             fgets(pidline, 64, fpid);
             strcpy(winName, pidline);
             winName[strlen(winName) - 1 ] = '\0'; 
             printf("PID: %i name: '%s'\n", winNum, winName);
             pclose(fpid);
    
             // This seems to notice the desktop (which is apparently called 'Openbox' but can be different depending on what program is grabbing the screen name
             if (strcmp(winName, "Menu") != 0 &&
                 strcmp(winName, "Openbox") != 0) {*/
     
                if (panel == 1)
                   winX = 750; // panel = 50 wide (scr. 800-50)
                else
                   winX = 800; // and screen is 800 wide
    
                if (svkbd == 1)
                   winY = 240; // virt. keyboard is 240 high
                else
                   winY = 480; // screen is 480 high
    
    // Several attempts to stop desktop from getting through
    // The code below must not be executed if no window is open in the window manager
                if (strcmp(winName, "Openbox") != 0 && text.format == 8 && text.value != NULL && strcmp((const char *)text.value, "") != 0 && strcmp((const char *)text.value, "(null)") != 0 && strcmp((const char *)text.value, "Openbox") != 0 && strcmp((const char *)text.value, "Menu") != 0) {
    
                   // Working inefficient code to adjust wndw size
                   /*snprintf(command, sizeof command, "xdotool windowsize %i %i %i", winNum, winX, winY); 
                   fpid = popen(command, "r");
                   pclose(fpid);*/
    
                   // Effient but non-working code
                   XGetWindowAttributes(display, toplevel_parent_of_focus, &attr);
                   // I believe this func. might be causing the
                   // bad window error when it is executed when no windows are up
                   XResizeWindow(display, window, winX, winY); 
                }
    
                // only refresh virtual keyboard if size is to be changed
                if (svkbd == 1 && ((last_win_x != winX &&  last_svkbd == svkbd) || (last_svkbd != svkbd && panel == 1))) {
    
                   // Will later use execl call but not apriority atm
                   if (panel == 1) 
                      fpid = popen("killall svkbd-en; svkbd-en -d -g 750x240 &", "r");
                   else            
                      fpid = popen("killall svkbd-en; svkbd-en -d -g 800x240 &", "r");
    
                   pclose(fpid);
                //}
             }
          }
    
          last_svkbd = svkbd;
          last_panel = panel;
          last_window = window;
          last_window_x = attr.width;
          last_window_y = attr.height;
          last_win_x = winX;
    
          // sleep one sec (or less if needed) 
          usleep(1000000);
    
       }
    
       return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Convert from CIE to RGB with Xlib
    By papos73 in forum Linux Programming
    Replies: 3
    Last Post: 06-23-2011, 07:07 AM
  2. x,xlib, xt, motif or ??
    By nga_tom in forum Linux Programming
    Replies: 10
    Last Post: 12-31-2007, 04:18 PM
  3. XLib documentation
    By Series X4 1.0 in forum Linux Programming
    Replies: 1
    Last Post: 03-20-2005, 06:31 PM
  4. Xlib
    By Fall Khadim in forum C Programming
    Replies: 2
    Last Post: 07-20-2003, 03:51 AM

Tags for this Thread