c++user-interfacex11motif

Set dialog window's border color


The root question here is this: How do I set the color for the border around a window (more specifically, a dialog window)?

I have a dialog window which pops up with an alert. Due to the critical safety nature of the alert, there is a requirement that some parts of the window be red, including the dialog's window-border. When I got this requirement in, I thought it was a good idea. Seems reasonable and simple enough.

The application uses X/motif for its graphics. I started by making other requested parts red, such as the acknowledgement button. Getting everything else done was simple enough by changing graphics contexts and color resources.

The dialog's border, however, has been a pain. There is an XmNborderColor resource, so I tried changing that. It didn't seem to work. Eventually, after trying to set it for different widgets (frame and it's ancestors), I did the following out of desparation:

Widget w = button;

for(int i = 0; i <= 20; i += 1)
{
    printf("i = %d, w = %d\n", i, w);
    if(w <= 0) break;
    XtVaSetValues( w, XmNborderColor, border, NULL);
    w = XtParent(w);
}

I did that to just set it on everything from the button to the root and everything between.

After doing some more research, I realized that I might need to be changing the window attributes instead, such as via XChangeWindowAttributes(display, window, mask, values). The structure for the values includes a border_pixel, which I'm assuming is the border color but can't find confirmation on that - documentation just says it's for setting "the border pixel." Fortunately, there is a convenience function for setting just the border pixel so that you do not need to pass an entire values structure; the convenience function that changes only the border pixel is XSetWindowBorder(display, window, border_pixel).

So I wanted to try that. I now have:

// control_area is the widget containing the other 
XSetWindowBorder(XtDisplay(shell), window, border);

shell is set elsewhere with the following function:

Widget myClass :: createShell( Widget parent, string title )
{
    while( !XtIsApplicationShell(parent) )
    {
        parent = XtParent( parent );
    }

    shell = XtVaCreatePopupShell( name, xmDialogShellWidgetClass, parent,
        XtNvisual, visual, // visual, colormap, depth are class member variables
        XtNcolormap, colormap,
        XtNdepth, depth,
        NULL );

    XtVaSetValues( shell,
        XmNmwmDecorations, MWM_DECOR_BORDER,
        XtNtitle, const_cast<char*> (title.c_str()),
        XmNmwmFunctions, NO_FUNCTIONS,
        XmNresizePolicy, XmRESIZE_NONE,
        NULL );

    return shell;
}

From another place in the code, it looks like window might be a reference to the root window - maybe that's the problem?

I am surprised by the lack of information about this and by how difficult it has been to find a direct answer.

How do I set the border color? If I should be using XSetWindowBorder(), what am I doing wrong? If it's because my window variable might not be referencing the correct window, how do I get the a reference to the correct window knowing the shell and contained widgets (maybe I should make a separate question out of this one if this question doesn't get traction)?


Solution

  • The colour of the border is most likely controlled by your window manager unless you are running without a window manager. You need to override the default colour for that specific window in your ~/.Xdefaults file. Something like:

    [title]*bordercolor: red

    Where [title] is the same as the string you pass to createShell().