0

Given the code:

/*
 * XWindows study on if we can turn the frame on and off.
 */
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#define MAPIT
#define REPEAT

void waitxevt(Display* d, int type)

{

    XEvent e; /* XEvent holder */

    do { XNextEvent(d, &e); } while (e.type != type);

}

void frame(Display* d, Window w, int e)

{

    Atom window_type;
    long value;

#ifdef MAPIT
    XUnmapWindow(d, w);
    waitxevt(d, UnmapNotify);
#endif
    window_type = XInternAtom(d, "_NET_WM_WINDOW_TYPE", False);
    if (e) value = XInternAtom(d, "_NET_WM_WINDOW_TYPE_NORMAL", False);
    else value = XInternAtom(d, "_NET_WM_WINDOW_TYPE_DOCK", False);
    XChangeProperty(d, w, window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
#ifdef MAPIT
    XMapWindow(d, w);
    waitxevt(d, MapNotify);
#endif

}

int main(void) {

    Display*     d;
    Window       w;
    XEvent       e;
    const char*  msg = "Hello, World!";
    int          s;
    GC           gracxt;
    int          frmenb = 0;
 
    d = XOpenDisplay(NULL);
    if (d == NULL) {

        fprintf(stderr, "Cannot open display\n");
        exit(1);

    }
 
    s = DefaultScreen(d);
    gracxt = XDefaultGC(d, s);

    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 640, 480, 5,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w, ExposureMask|KeyPressMask|StructureNotifyMask);
    XMapWindow(d, w);
    waitxevt(d, MapNotify);

    while (1) {

        XNextEvent(d, &e);
        if (e.type == Expose) XDrawString(d, w, gracxt, 10, 50, msg, strlen(msg));
        if (e.type == KeyPress) {

            frame(d, w, frmenb);
            frmenb = !frmenb;
#ifdef REPEAT
            frame(d, w, frmenb);
            frmenb = !frmenb;
#endif

        }

    }

    XCloseDisplay(d);

    return 0;

}

The purpose of the code is to turn the frame on and off for the window w. With no map/unmap operation, The "off" call works correctly, and the window changes (onscreen) to have no frame, and is not sizable, and the titlebar no longer appears.

However, on turning it back on using the routine, the titlebar is not visible, but it is sizable. If you resize the window, the titlebars reappear.

The suggestion was made to unmap the window before setting the property and remap after. The result of this is that the window without frame no longer can have focus, and thus cannot get a key to change back. I put in a "repeat" flag to make it immediately revert back to full frame mode, and thus prove that the return to framing works. It does. Another side effect is that the position of the window gets reset after the map operation, but I can compensate for that.

This is on Ubuntu 20.04.

What is the purpose? This code is part of a toolkit to port between Windows and Linux. The frame on/off is used for two purposes (so far):

  1. To make component windows (widgets) without frames.
  2. To toggle the frame. For example, I have a clock program that if you click on it, it will remove the frame, making it both smaller and immobile. Another click restores it.

The first one works now, since it only turns off the frame once, and that happens before mapping. The second one does not work.

New program, now works, using the suggestions:

/*
 * XWindows study on if we can turn the frame on and off.
 */
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct MwmHints {
    unsigned long flags;
    unsigned long functions;
    unsigned long decorations;
    long input_mode;
    unsigned long status;
};
enum {
    MWM_HINTS_FUNCTIONS = (1L << 0),
    MWM_HINTS_DECORATIONS =  (1L << 1),

    MWM_FUNC_ALL = (1L << 0),
    MWM_FUNC_RESIZE = (1L << 1),
    MWM_FUNC_MOVE = (1L << 2),
    MWM_FUNC_MINIMIZE = (1L << 3),
    MWM_FUNC_MAXIMIZE = (1L << 4),
    MWM_FUNC_CLOSE = (1L << 5)
};

void frame(Display* d, Window w, int e)

{

    Atom mwmHintsProperty;
    struct MwmHints hints;

    mwmHintsProperty = XInternAtom(d, "_MOTIF_WM_HINTS", 0);
    hints.flags = MWM_HINTS_DECORATIONS;
    hints.decorations = !!e;
    XChangeProperty(d, w, mwmHintsProperty, mwmHintsProperty, 32,
                        PropModeReplace, (unsigned char *)&hints, 5);

}

int main(void) {

    Display*     d;
    Window       w;
    XEvent       e;
    const char*  msg = "Hello, World!";
    int          s;
    GC           gracxt;
    int          frmenb = 0;
 
    d = XOpenDisplay(NULL);
    if (d == NULL) {

        fprintf(stderr, "Cannot open display\n");
        exit(1);

    }
 
    s = DefaultScreen(d);
    gracxt = XDefaultGC(d, s);

    w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 640, 480, 5,
                            BlackPixel(d, s), WhitePixel(d, s));
    XSelectInput(d, w, ExposureMask|KeyPressMask|StructureNotifyMask);
    XMapWindow(d, w);

    while (1) {

        XNextEvent(d, &e);
        if (e.type == Expose) XDrawString(d, w, gracxt, 10, 50, msg, strlen(msg));
        if (e.type == KeyPress) {

            frame(d, w, frmenb);
            frmenb = !frmenb;

        }

    }

    XCloseDisplay(d);

    return 0;

}
Scott Franco
  • 481
  • 2
  • 15
  • This is not the [right way](https://stackoverflow.com/questions/5134297/xlib-how-does-this-removing-window-decoration-work) to turn decorations on and off, but if you insist, unmap the window, apply the property, and map again. – n. m. could be an AI Aug 18 '21 at 05:15
  • Thanks for the feedback, I refactored the example as a stand-alone program using your mapping suggestion. It still does not quite work. Also, please could you expand on your comment "This is not the right way to turn decorations on and off" or point me to an example? Thanks. – Scott Franco Aug 18 '21 at 19:22
  • So I notice from trying different windows types that some others do allow the unframed window to get focus. Each of the windows types appears to be a collection of characteristics. I suppose one method of attack would be to try and find the underlying sets for them. – Scott Franco Aug 18 '21 at 19:31
  • In case it was not painfully obvious, I am reading "Extended Window Manager Hints" document to resolve this. – Scott Franco Aug 18 '21 at 19:38
  • _NET_WM_WINDOW_TYPE is responsible for the window type. _MOTIF_WM_HINTS is responsible for the decorations, functions, and a few other things. Each window type usually entails certain decorations, and a lot of other window behaviour which you may or may not want. If you want to control just the decorations, why not control decorations directly with a tool designed to do just that? – n. m. could be an AI Aug 18 '21 at 19:44
  • Cool, learning new stuff, thanks. See also https://stackoverflow.com/questions/5134297/xlib-how-does-this-removing-window-decoration-work which strongly implies that _MOTIF_WM_HINTS is obsolete. – Scott Franco Aug 18 '21 at 20:18
  • That's the link I gave you in the first comment... _MOTIF_WM_HINTS is not so much obsolete, it just never was any kind of formal standard, but most WMs support it. – n. m. could be an AI Aug 18 '21 at 20:29
  • Nice. Posted the now working example in the original text. If you post your solution as an answer, I can give you credit. – Scott Franco Aug 18 '21 at 20:54

0 Answers0