Thread: The xlib program does not want to change the background color

  1. #1
    Registered User
    Join Date
    Jan 2019
    Posts
    4

    Exclamation The xlib program does not want to change the background color

    Code:
    Code:
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <X11/Xos.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    #define X 100
    #define Y 100
    #define WIDTH 200
    #define HEIGHT 200
    #define WIDTH_MIN 50
    #define HEIGHT_MIN 50
    #define BORDER_WIDTH 5
    #define TITLE "Example"
    #define ICON_TITLE "Example"
    #define PRG_CLASS "Example"
    
    static void SetWindowManagerHints (
     Display * display,
     char * PClass,
     char * argv[],
     int argc,
     Window window,
     int x,
     int y,
     int win_wdt,
     int win_hgt,
     int win_wdt_min,
     int win_hgt_min,
     char * ptrTitle,
     char * ptrITitle,
     Pixmap pixmap
    )
    {
     XSizeHints size_hints;
    
     XWMHints wm_hints;
     XClassHint class_hint;
     XTextProperty windowname, iconname;
    
     if ( !XStringListToTextProperty (&ptrTitle, 1, &windowname ) ||
        !XStringListToTextProperty (&ptrITitle, 1, &iconname ) ) {
      puts ( "No memory!\n");
      _exit ( 1 );
    }
    
    size_hints.flags = PPosition | PSize | PMinSize;
    size_hints.min_width = win_wdt_min;
    size_hints.min_height = win_hgt_min;
    wm_hints.flags = StateHint | IconPixmapHint | InputHint;
    wm_hints.initial_state = NormalState;
    wm_hints.input = True;
    wm_hints.icon_pixmap= pixmap;
    class_hint.res_name = argv[0];
    class_hint.res_class = PClass;
    
    XSetWMProperties ( display, window, &windowname,
      &iconname, argv, argc, &size_hints, &wm_hints,
      &class_hint );
    }
    
    Display * display;
    
    unsigned long getColor(char color[]) {
        XColor hex;
        Colormap colormap = DefaultColormap(display, 0);
        XParseColor(display, colormap, color, &hex);
        XAllocColor(display, colormap, &hex);
        return hex.pixel;
    }
    
    void main(int argc, char *argv[])
    {
    
     int ScreenNumber;
     GC gc;
     XEvent report;
     Window window;
    
     if ( ( display = XOpenDisplay ( NULL ) ) == NULL ) {
      puts ("Can not connect to the X server!\n");
      _exit ( 1 );
     }
    
     ScreenNumber = DefaultScreen ( display );
    
     window = XCreateSimpleWindow ( display,
         RootWindow ( display, ScreenNumber ),
         X, Y, WIDTH, HEIGHT, BORDER_WIDTH,
         BlackPixel ( display, ScreenNumber ),
         WhitePixel ( display, ScreenNumber ) );
    
     SetWindowManagerHints ( display, PRG_CLASS, argv, argc,
       window, X, Y, WIDTH, HEIGHT, WIDTH_MIN,
       HEIGHT_MIN, TITLE, ICON_TITLE, 0 );
    
     XSelectInput ( display, window, ExposureMask | KeyPressMask);
    
     XMapWindow ( display, window );
    
     while ( 1 ) {
      XNextEvent ( display, &report );
    
      switch ( report.type ) {
        case Expose :
        {
            if ( report.xexpose.count != 0 )
            break;
    
            gc = XCreateGC(display, window, 0, NULL);
    
            XSetForeground ( display, gc, getColor("#ff00ff"));
            XDrawString ( display, window, gc, 20,50,
            "First example", strlen ( "First example" ) );
            XFreeGC ( display, gc );
            XFlush(display);
            break;
        }
    
        case KeyPress:
        {
            XGCValues values;
            values.background = getColor("#00ff00");
            XChangeGC(display, gc, GCBackground, &values);
        }
      }
     }
    }
    When I launched the program and pressed the key, I didn’t see any changes, I cannot understand what the problem is

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    When in doubt, read the manual page and observe that functions do return error codes.
    Code:
        case KeyPress:
        {
            fprintf(stderr,"Key\n");
            XGCValues values;
            values.background = getColor("#00ff00");
            int result = XChangeGC(display, gc, GCBackground, &values);
            {
                fprintf(stderr,"Change result=%d\n", result);
                char buff[200];
                XGetErrorText(display, result, buff, sizeof(buff));
                fprintf(stderr,"Change result=%s\n", buff);
            }
        }
    Code:
    $ gcc -Wall main.c -lX11
    main.c:73:6: warning: return type of ‘main’ is not ‘int’ [-Wmain]
     void main(int argc, char *argv[])
          ^
    $ ./a.out 
    Expose
    Key
    Change result=1
    Change result=BadRequest (invalid request code or no such operation)
    XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
          after 24 requests (24 known processed) with 0 events remaining.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    This seems to work.
    Code:
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    //#include <X11/Xos.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
      
    #define X 100
    #define Y 100
    #define WIDTH 200
    #define HEIGHT 200
    #define WIDTH_MIN 50
    #define HEIGHT_MIN 50
    #define BORDER_WIDTH 5  // probably ignored by window manager
    #define TITLE "Example"
    #define ICON_TITLE "Example"
    #define PRG_CLASS "Example"
     
    Display *display;
    Atom wm_delete_window; // to handle window's X (close) button
     
    static void SetWindowManagerHints (
        Display *display, char *PClass, char *argv[], int argc,
        Window window, int win_wdt_min, int win_hgt_min,
        char *ptrTitle, char *ptrITitle, Pixmap pixmap)
    {
        XSizeHints size_hints;
        XWMHints wm_hints;
        XClassHint class_hint;
        XTextProperty windowname, iconname;
     
        if (!XStringListToTextProperty(&ptrTitle, 1, &windowname) ||
            !XStringListToTextProperty(&ptrITitle, 1, &iconname)) {
            puts("No memory!\n");
            _exit(1);
        }
      
        size_hints.flags = PPosition | PSize | PMinSize;
        size_hints.min_width = win_wdt_min;
        size_hints.min_height = win_hgt_min;
        wm_hints.flags = StateHint | IconPixmapHint | InputHint;
        wm_hints.initial_state = NormalState;
        wm_hints.input = True;
        wm_hints.icon_pixmap= pixmap;
        class_hint.res_name = argv[0];
        class_hint.res_class = PClass;
      
        XSetWMProperties(display, window, &windowname,
            &iconname, argv, argc, &size_hints, &wm_hints,
            &class_hint);
    }
     
    unsigned long getColor(char color[]) {
        XColor hex;
        Colormap colormap = DefaultColormap(display, 0);
        XParseColor(display, colormap, color, &hex);
        XAllocColor(display, colormap, &hex);
        return hex.pixel;
    }
     
    int main(int argc, char *argv[]) { 
        if ((display = XOpenDisplay(NULL)) == NULL) {
            puts("Can not connect to the X server!\n");
            _exit(1);
        }
        int ScreenNumber = DefaultScreen(display);
        Window window = XCreateSimpleWindow(display,
            RootWindow(display, ScreenNumber),
            X, Y, WIDTH, HEIGHT, BORDER_WIDTH,
            BlackPixel(display, ScreenNumber),
            WhitePixel(display, ScreenNumber));
        SetWindowManagerHints(display, PRG_CLASS, argv, argc,
            window, WIDTH_MIN, HEIGHT_MIN, TITLE, ICON_TITLE, 0);
        XSelectInput(display, window, ExposureMask | KeyPressMask);
        XMapWindow(display, window);
        wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
        XSetWMProtocols(display, window, &wm_delete_window, 1);
        GC gc = XCreateGC(display, window, 0, NULL);
     
        while (1) {
            XEvent report;
            XNextEvent(display, &report);
     
            switch (report.type) {
            case Expose: {
                fprintf(stderr,"Expose\n");
                XSetForeground(display, gc, getColor("#00ffff"));
                const char title[] = "First example";
                XDrawString(display, window, gc, 20, 50, title, sizeof title - 1);
                XFlush(display);
                break;
            }
            case KeyPress: {
                fprintf(stderr,"Key\n");
                XSetWindowBackground(display, window, getColor("#000000"));
                XClearArea(display, window, 0, 0, 0, 0, True);
                break;
            }
            case ClientMessage:
                if ((Atom)report.xclient.data.l[0] == wm_delete_window)
                    goto quit_label;
                break;
            }
        }
     
    quit_label:
        XFreeGC(display, gc);
        XDestroyWindow(display, window);
        XCloseDisplay(display);
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  4. #4
    Registered User
    Join Date
    Jan 2019
    Posts
    4
    Everything works, but I still do not understand why there is an error: BadRequest (invalid request code or no such operation)
    Now my code looks like this:
    Code:
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>
    #include <X11/Xos.h>
    #include <X11/Xatom.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    #define X 100
    #define Y 100
    #define WIDTH 200
    #define HEIGHT 200
    #define WIDTH_MIN 50
    #define HEIGHT_MIN 50
    #define BORDER_WIDTH 5
    #define TITLE "Example"
    #define ICON_TITLE "Example"
    #define PRG_CLASS "Example"
    
    static void SetWindowManagerHints (
     Display * display,
     char * PClass,
     char * argv[],
     int argc,
     Window window,
     int x,
     int y,
     int win_wdt,
     int win_hgt,
     int win_wdt_min,
     int win_hgt_min,
     char * ptrTitle,
     char * ptrITitle,
     Pixmap pixmap
    )
    {
     XSizeHints size_hints;
    
     XWMHints wm_hints;
     XClassHint class_hint;
     XTextProperty windowname, iconname;
    
     if ( !XStringListToTextProperty (&ptrTitle, 1, &windowname ) ||
        !XStringListToTextProperty (&ptrITitle, 1, &iconname ) ) {
      puts ( "No memory!\n");
      _exit ( 1 );
    }
    
    size_hints.flags = PPosition | PSize | PMinSize;
    size_hints.min_width = win_wdt_min;
    size_hints.min_height = win_hgt_min;
    wm_hints.flags = StateHint | IconPixmapHint | InputHint;
    wm_hints.initial_state = NormalState;
    wm_hints.input = True;
    wm_hints.icon_pixmap= pixmap;
    class_hint.res_name = argv[0];
    class_hint.res_class = PClass;
    
    XSetWMProperties ( display, window, &windowname,
      &iconname, argv, argc, &size_hints, &wm_hints,
      &class_hint );
    }
    
    Display * display;
    
    unsigned long getColor(char color[]) {
        XColor hex;
        Colormap colormap = DefaultColormap(display, 0);
        XParseColor(display, colormap, color, &hex);
        XAllocColor(display, colormap, &hex);
        return hex.pixel;
    }
    
    int main(int argc, char *argv[])
    {
        int ScreenNumber;
        XEvent report;
        Window window;
    
        if ( ( display = XOpenDisplay ( NULL ) ) == NULL ) {
        puts ("Can not connect to the X server!\n");
        _exit ( 1 );
        }
    
        ScreenNumber = DefaultScreen ( display );
    
        window = XCreateSimpleWindow ( display,
        RootWindow ( display, ScreenNumber ),
        X, Y, WIDTH, HEIGHT, BORDER_WIDTH,
        BlackPixel ( display, ScreenNumber ),
        WhitePixel ( display, ScreenNumber ) );
    
        // register interest in the delete window message
        Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
        XSetWMProtocols(display, window, &wmDeleteMessage, 1);
    
        SetWindowManagerHints ( display, PRG_CLASS, argv, argc,
        window, X, Y, WIDTH, HEIGHT, WIDTH_MIN,
        HEIGHT_MIN, TITLE, ICON_TITLE, 0 );
    
        XSelectInput ( display, window, ExposureMask | KeyPressMask);
    
        XMapWindow ( display, window );
    
        GC gc = XCreateGC(display, window, 0, NULL);
    
        while ( 1 ) {
            XNextEvent ( display, &report );
    
            if(report.type == ClientMessage && report.xclient.data.l[0] == wmDeleteMessage) {
                printf("Shutdown!\n");
                break;
            }
            switch ( report.type ) {
            case Expose :
            {
                if(report.xexpose.count != 0)
                break;
    
                XSetForeground ( display, gc, getColor("#ff00ff"));
                XDrawString ( display, window, gc, 20,50,
                "First example", strlen ( "First example" ) );
                XFreeGC ( display, gc );
                XFlush(display);
                break;
            }
    
            case KeyPress:
            {
                XGCValues values;
                values.background = getColor("#00ff00");
                int result = XChangeGC(display, gc, GCBackground, &values);
                printf("%i:%i\n", result, BadAlloc);
                char buff[200];
                XGetErrorText(display, result, buff, sizeof(buff));
                printf("%s\n", buff);
                // XSetWindowBackground(display, window, getColor("#000000"));
                // XClearArea(display, window, 0, 0, 0, 0, True);
                }
            }
        }
    }
    I need to change the background through the function XChangeGC, another method does not work in my case

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    I need to change the background through the function XChangeGC, another method does not work in my case
    Why?
    A little inaccuracy saves tons of explanation. - H.H. Munro

  6. #6
    Registered User
    Join Date
    Jan 2019
    Posts
    4

    Cool

    Quote Originally Posted by john.c View Post
    Why?
    This is required in my task, which needs to be solved. And it is very strange why the function in which everything is indicated according to the instructions does not work

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You might want to seek for feedback from the person who gave you those instructions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    I wish I said a little more than "why" in my last post, but I had no idea the website was going to go down yet again, for HOURS! I should have known. Is the site ever going to be fixed?

    Some points:

    * XChangeGC is not failing. It will return 0 if it fails.

    * normally you would use the "convenience function" XSetBackground (which calls XChangeGC).

    * setting the background pixel of a graphics context doesn't change the background pixel of the window (if that's what you are trying to do).

    * if you really only want to change the gc background, then XDrawString will not be affected. Try XDrawImageString, which will first fill the text rectangle with the gc background.

    * it's probably not a good idea to free the gc in the Expose event if you want to modify it in the KeyPress event!

    * the window will not be redrawn just because you change the background of the gc or the window. Hence my XClearArea call which, if the last parameter is True, sends an Expose event and therefore reruns your drawing routine.

    If you have a link to the instructions you are following, I can take a look at them.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  9. #9
    Registered User
    Join Date
    Jan 2019
    Posts
    4

    Lightbulb

    Quote Originally Posted by john.c View Post
    I wish I said a little more than "why" in my last post, but I had no idea the website was going to go down yet again, for HOURS! I should have known. Is the site ever going to be fixed?

    Some points:

    * XChangeGC is not failing. It will return 0 if it fails.

    * normally you would use the "convenience function" XSetBackground (which calls XChangeGC).

    * setting the background pixel of a graphics context doesn't change the background pixel of the window (if that's what you are trying to do).

    * if you really only want to change the gc background, then XDrawString will not be affected. Try XDrawImageString, which will first fill the text rectangle with the gc background.

    * it's probably not a good idea to free the gc in the Expose event if you want to modify it in the KeyPress event!

    * the window will not be redrawn just because you change the background of the gc or the window. Hence my XClearArea call which, if the last parameter is True, sends an Expose event and therefore reruns your drawing routine.

    If you have a link to the instructions you are following, I can take a look at them.
    The XChangeGC function returns one instead of zero. I looked at the internal implementation and it all comes down to such actions:
    Code:
    LockDisplay(dpy);
        if (gc->values.background != background) {
            gc->values.background = background;
            gc->dirty |= GCBackground;
        }
        UnlockDisplay(dpy);
        SyncHandle();
    That is, all this is done inside the library and does not work in normal code.
    As you can see, there is no need to paint anything with the XDrawImageString function and this is an ideal solution, but the XChangeGC function returns 0 and I cannot understand what the error is: BadRequest (invalid request code or no such operation)
    This error is not specified in the documentation.
    I read this tutorial https://www.niksula.hut.fi/~jkirma/books/xlib.pdf, on page 90 there is an example 5-2 which shows how to use XChangeGC
    Although it does not show how to use XChangeGC, can the function be outdated at all?
    Last edited by NegroMike; 01-23-2019 at 09:20 PM.

  10. #10
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Obviously I'm wasting my time with you. (Some kind of learning disability?)
    A little inaccuracy saves tons of explanation. - H.H. Munro

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 07-17-2011, 08:48 AM
  2. change background color
    By new_in_c++ in forum Windows Programming
    Replies: 1
    Last Post: 07-12-2011, 11:08 AM
  3. how to change background color in console mode
    By smore in forum C++ Programming
    Replies: 1
    Last Post: 12-02-2003, 01:44 PM
  4. How do I change background color?
    By kinghajj in forum Windows Programming
    Replies: 16
    Last Post: 11-10-2003, 02:20 AM
  5. Can I change background color
    By Bryan in forum C++ Programming
    Replies: 2
    Last Post: 10-25-2002, 12:14 PM

Tags for this Thread