Drawing A Yellow Rectangle

C, Xlib, Xrandr on Linux/Xorg

This solution requires a C compiler, a working X server supporting RANDR and Xlib development files.

The code was compiled using GCC with the following commandline:

gcc -std=c99 -pedantic -Wall -Werror -O3 -o rectangle-fullscreen rectangle-fullscreen.c -lX11

It has been tested on GNU/Linux with GCC and the Xorg X server.

Known restriction: The program performs a fullscreen display by altering the display size to 640 pixels width and 480 pixels height if such a size is available (aborting otherwise), then creating a window, then sending a _NET_WM_STATE_FULLSCREEN message about the window to the window manager. Please note that not all window managers might adhere to this message correctly; this procedure has been successfully tested with the Xfce window manager.

/* rectangle.c - Draw a yellow rectangle using Xlib. */
/* Released into the Public Domain on Mar 11 2018 by Tilman Kranz . */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>

#define WIDTH 640
#define HEIGHT 480

int main(int argc, char *argv[]) {
    Display *display;
    Window window;
    Window root;
    int screen;
    XEvent event;
    XColor yellow;
    Colormap colormap;
    Status rc;
    GC gc;
    XRRScreenSize *xrrs;
    XRRScreenConfiguration *conf;
    short possible_frequencies[64][64];
    short original_rate;
    Rotation original_rotation;
    SizeID original_size_id;
    int num_sizes;
    int consider;

    display = XOpenDisplay(NULL);

    if (display == NULL) {
       fprintf(stderr, "%s: cannot connect to X server\n", argv[0]);

       exit(1);
    }

    screen = DefaultScreen(display);

    root = RootWindow(display, screen);

    xrrs = XRRSizes(display, 0, &num_sizes);

    consider = -1;

    for(int i = 0; i < num_sizes; i ++) {
        short *rates;
        int num_rates;

        if(xrrs[i].width!=WIDTH || xrrs[i].height!=HEIGHT) {
            continue;
        }

        consider = i;

        rates = XRRRates(display, 0, i, &num_rates);

        for(int j = 0; j < num_rates; j ++) {
            possible_frequencies[i][j] = rates[j];
        }

        break;
    }
    if(consider==-1) {
        fprintf(stderr, "no suitable mode for 640x480 found, aborting.");

        exit(1);
    }

    conf = XRRGetScreenInfo(display, root);
    original_rate = XRRConfigCurrentRate(conf);
    original_size_id = XRRConfigCurrentConfiguration(conf, &original_rotation);

    XRRSetScreenConfigAndRate(
        display, conf, root, consider, RR_Rotate_0,
        possible_frequencies[consider][0],
        CurrentTime
    );

    colormap = DefaultColormap(display, screen);
    gc = DefaultGC(display, screen);

    window =
        XCreateSimpleWindow(
        display, root,
        10, 10, WIDTH, HEIGHT, 1,
        BlackPixel(display, screen), BlackPixel(display, screen)
    );

    XSelectInput(
        display, window,
        StructureNotifyMask | ExposureMask | KeyPressMask
    );

    XMapWindow(display, window);

    XClientMessageEvent msg = {
        .type = ClientMessage, .display = display, .window = window,
        .message_type = XInternAtom(display, "_NET_WM_STATE", True),
        .format = 32,
        .data = { .l = {
            1,
            XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", True),
            None,
            0,
            1
        }}
    };

    XSendEvent(
        display, DefaultRootWindow(display), False,
        SubstructureRedirectMask | SubstructureNotifyMask,
        (XEvent*) &msg
    );

    rc = XAllocNamedColor(display, colormap, "yellow", &yellow, &yellow);

    if(rc==0) {
        fprintf(stderr, "%s: cannot allocate color \"yellow\".\n", argv[0]);

        exit(1);
    }

    XSetForeground(display, gc, yellow.pixel);

    while (1) {
        XNextEvent(display, &event);

        if (event.type == Expose) {
            XFillRectangle(display, window, gc, 10, 20, 100, 75);
        }

        if (event.type == KeyPress) {
            break;
        }
    }

    XRRSetScreenConfigAndRate(
        display, conf, root,
        original_size_id, original_rotation, original_rate,
        CurrentTime
    );

    XCloseDisplay(display);

    return 0;
}
Imprint RSS