Как создать полупрозрачное белое окно в XLib

#c #x11 #transparent #alpha #xlib

#c #x11 #прозрачный #альфа #xlib

Вопрос:

Я хотел бы создать полупрозрачное белое окно в XLib, но окно не полупрозрачное, оно остается полностью непрозрачным. Я использую compton compositor, и в системе есть прозрачные окна, поэтому проблема в коде:

 #include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    Display* display = XOpenDisplay(NULL);

    XVisualInfo vinfo;

    XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, amp;vinfo);

    XSetWindowAttributes attr;
    attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
    attr.border_pixel = 0;
    attr.background_pixel = 0x80ffffff;

    Window win = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 200, 0, vinfo.depth, InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, amp;attr);
    XSelectInput(display, win, StructureNotifyMask);
    GC gc = XCreateGC(display, win, 0, 0);

    Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0);
    XSetWMProtocols(display, win, amp;wm_delete_window, 1);

    XMapWindow(display, win);

    int keep_running = 1;
    XEvent event;

    while (keep_running) {
        XNextEvent(display, amp;event);

        switch(event.type) {
            case ClientMessage:
                if (event.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1) amp;amp; (Atom)event.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1))
                    keep_running = 0;

                break;

            default:
                break;
        }
    }

    XDestroyWindow(display, win);
    XCloseDisplay(display);
    return 0;
}
  

Комментарии:

1. Обратите внимание, поскольку в OP упоминается, что для того, чтобы все это работало, в вашей системе необходимо иметь программу-компилятор, запущенную в вашей системе. В Lubuntu этого нет, нужен xcompmgr или аналогичный.

Ответ №1:

X11 ожидает предварительно умноженные цвета, т. Е. Реальные непрозрачные цвета необходимо умножить на альфа-значение (и соответственно масштабировать, т. Е. Разделить на 256, когда ширина канала равна 8 битам). С этим форматом легче работать, когда вам нужно объединить много уровней. Смотрите формулы здесь. Когда все предварительно умножено, требуется меньше вычислений.

Итак, вам нужно умножить каждый из ваших каналов R, G и B на альфа-значение (0x80) и разделить на 256.

Установка фона на 0x80808080 дает желаемый результат:

Обратите внимание, что результат отличается от того, что предлагает @patthoyts: здесь только само окно полупрозрачно, оформление WM остается непрозрачным; там и само окно, и оформление становятся прозрачными с помощью WM (и WM выполняет необходимое смешивание цветов).

Комментарии:

1. Нет, дело не в этом. Проверьте это изображение: oscomp.hu/depot/white_transparency_qt5_vs_xlib.png Цвет фона эквивалентен в обоих окнах: 0x80ffffff; Qt5 нравится, как мне это нужно, а XLib — нет. Должно быть, что-то в коде, я делаю неправильно, но что?

2. @jsr Вы пытались это сделать? Посмотрите на изображение. Как вы думаете, я отредактировал его в gimp или что?

3. Qt не является XLib. Это портативный инструментарий, который работает с X11, Windows GDI, raw фреймбуферами Linux и другими. Я понятия не имею, что Qt делает внутренне, чтобы угодить пользователю и поддерживать согласованный API. X11 делает именно то, что вы можете видеть на изображении, которое я опубликовал.

4. Qt использует расширение XRender. И это моя настоящая проблема, а не прозрачное окно: Qt правильно смешивает альфа-изображения с окнами X11 с помощью XRenderComposite, в то время как если я использую XRenderComposite, то происходит тот же эффект: чем ближе один пиксель к белому, тем меньше работает прозрачность пикселя. Если пиксель полностью белый, то XRenderComposite рисует там белый пиксель, независимо от того, какая альфа была у этого пикселя. Я уверен, что это не предполагаемое поведение смешивания XRender… Если бы вы могли показать мне, как правильно использовать XRenderComposite, тогда это было бы хорошо для меня.

5. И, конечно, я попытался изменить яркость цвета: чем ближе цвет к белому, тем меньше работает альфа, чем ближе цвет к черному, тем больше работает альфа, но это ошибочно! Если я установлю альфа-значение равным нулю, то цвет должен быть полностью прозрачным, независимо от цвета. Проверьте примеры фотографий в моей теме compton: github.com/chjj/compton/issues/382

Ответ №2:

Вам нужно установить _NET_WM_WINDOW_OPACITY. Вот фрагмент, который нужно добавить перед отображением окна:

 double alpha = 0.8;
unsigned long opacity = (unsigned long)(0xFFFFFFFFul * alpha);
Atom XA_NET_WM_WINDOW_OPACITY = XInternAtom(display, "_NET_WM_WINDOW_OPACITY", False);
XChangeProperty(display, win, XA_NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
                PropModeReplace, (unsigned char *)amp;opacity, 1L);
  

Примечание, которое вы должны добавить #include <X11/Xatom.h> , чтобы получить объявление XA_CARDINAL .

Я не совсем уверен, насколько стабилен этот интерфейс. Похоже, это предлагаемое расширение спецификации расширенных подсказок диспетчера окон, но, насколько я вижу, оно не вошло ни в какую окончательную редакцию. Я знаю, что именно так Tk реализует поддержку прозрачности в unix.

Результат выглядит так:

прозрачное окно X11 поверх редактора

Комментарии:

1. К сожалению, это не сработало. Я пробовал это в Xfce, TDE и MotifWM с compton, и оно по-прежнему полностью белое во всех средах. У меня есть код Qt5, который может установить прозрачность фона, просто установив верхний 8 бит цвета фона. Единственное, что он делает раньше, это установка атрибута «WA_TranslucentBackground» окна. Я все еще пытаюсь выяснить, что он делает, просматривая исходные коды Qt5, но безуспешно.

2. @jsr работает с последним KDE. Я думаю, вы можете изменить оконный менеджер в Xfce и TDE на что-то, что поддерживает этот atom.

3. Мне нужно универсальное решение, а не зависящее от WM. Кроме того, Qt5 может создавать полупрозрачное белое окно: oscomp.hu/depot/white_transparency_qt5_vs_xlib.png Цвет фона эквивалентен в двух программах: 0x80ffffff, и все же чистый XLib показывает полностью непрозрачное окно.