在 xlib 中创建 32 位根 window
Create a 32-bit root window in xlib
我已经在这几天了,但我似乎无法弄清楚如何创建 32 位根 window 以便我可以在 child window,并且 child window 不能使用 32 位颜色深度(RGB 为 24 位,Alpha 通道为 8 位)如果 parent,或在这种情况下,root window 没有 32 位颜色深度。我正在使用以下代码将根 window 的背景设置为颜色深度为 24 位的 RGB 图像,因此当我将 XCreatePixmap 设置为颜色深度为 24 位时它就可以工作,但是我需要此根 window 具有用于 alpha 合成的 32 位颜色深度:
/* displays an image or sets root background
* PUBLIC DOMAIN - CC0 http://creativecommons.org/publicdomain/zero/1.0/
* J.Mayo 2013
*
* gcc -Wall -W -g3 -o background background.c -lX11 -lImlib2
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <Imlib2.h>
struct screenAttributes {
int height;
int width;
};
struct screenAttributes screenAttr;
void initializeScreenAttributes(Screen *screen) {
screenAttr.height=screen->height;
screenAttr.width=screen->width;
}
int main(int argc, char **argv)
{
Imlib_Image img;
Display *dpy;
Pixmap pix;
Window root;
Screen *scn;
// Window topPanel;
int width, height;
const char *filename = "/sampleImage.png";
img = imlib_load_image(filename);
if (!img) {
fprintf(stderr, "%s:Unable to load image\n", filename);
goto usage;
}
imlib_context_set_image(img);
width = imlib_image_get_width();
height = imlib_image_get_height();
dpy = XOpenDisplay(NULL);
if (!dpy) return 0;
scn = DefaultScreenOfDisplay(dpy);
root = DefaultRootWindow(dpy);
pix = XCreatePixmap(dpy, root, width, height,32); //when depth is set to 24 it just works, but when it is set to 32 it fails.
//scale the image
initializeScreenAttributes(scn);
imlib_blend_image_onto_image(img,0,0,0,width,height,0,0,
screenAttr.width, screenAttr.height);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
imlib_context_set_drawable(pix);
imlib_render_image_on_drawable(0, 0);
XSetWindowBackgroundPixmap(dpy, root, pix);
XClearWindow(dpy, root);
while (XPending(dpy)) {
XEvent ev;
XNextEvent(dpy, &ev);
}
XFreePixmap(dpy, pix);
imlib_free_image();
sleep(10);
//XFreePixmap(dpy, pix);
//imlib_free_image();
XCloseDisplay(dpy);
return 0;
usage:
fprintf(stderr, "usage: %s <image_file>\n", argv[0]);
return 1;
}
当我将 XCreapePixmap 的颜色深度设置为 32 位时,我得到:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor Opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request : 28
Current serial number in output stream: 29 xinit: connection to X server lost
所以,换句话说,我不太确定如何将根 window 的颜色深度设置为 32 位,并将 24 位 RGB 图像设置为背景根 window.
谢谢!
P.S。我没有安装任何 window 管理器或任何桌面环境,因此无法使用其中的任何可用工具。
没有。您不必让 root window 的深度为 32 就可以让 children 的深度为 32
也。否则你怎么认为 windows 可以有 alpha 通道
作曲家?你怎么看这个:
http://www.enlightenment.org/ss/e-5872c6ec3ddce1.54730231.png
没有 2 个 windows 具有 32 位深度是可能的吗? (左边的 2 -
时钟和半透明终端)。 :)
半透明的工作方式是合成器的干预(现在通常是你的
window manager) 并且合成了 32bit windows 在上面(也可能是 deals
在底部也重绘根 window - 这可能取决于)。所以说 "I don't have a compositor/window manager so that's out of the question" 基本上就是说 "I don't want to do the one and only thing I HAVE TO DO in order to get translucency" 所以我建议你 re-evaluate 这个位置。
所以你真正想要的是一个合成器和 32 位 windows。要么使用
合成 window 管理器,然后创建 32 位 windows,或 运行 一个单独的
合成器和你现有的 WM,或者编写你自己的合成器......(不打算
正确快速地完成这项工作会很有趣)...
现在要创建 ARGB window,您需要 XRender 的视觉帮助。就像下面的 disp 是你的 Xlib Display 而 parent 是 parent Window (例如root):
Window win;
XSetWindowAttributes attr;
XWindowAttributes att;
XVisualInfo *xvi;
XVisualInfo vi_in;
int nvi, i, scr = 0;
XRenderPictFormat *fmt;
Visual *vis;
vi_in.screen = scr;
vi_in.depth = 32;
vi_in.class = TrueColor;
xvi = XGetVisualInfo(disp,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&vi_in,
&nvi);
if (!xvi) return 0;
vis = NULL;
for (i = 0; i < nvi; i++)
{
fmt = XRenderFindVisualFormat(disp, xvi[i].visual);
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
{
vis = xvi[i].visual;
break;
}
}
XFree (xvi);
attr.backing_store = NotUseful;
attr.override_redirect = 0;
attr.colormap = XCreateColormap(disp, parent,
vis, AllocNone);
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = 0;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(disp, parent,
x, y, w, h, 0,
32,
InputOutput,
vis,
CWBackingStore |
CWOverrideRedirect |
CWColormap |
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
代码来自这里:https://git.enlightenment.org/core/efl.git/tree/src/lib/ecore_x/ecore_x_window.c#n1644
我们曾经有一个 XCB back-end 和 XCB 中的所有这些代码,但我们在大约十年后放弃了 XCB。如果你克隆上面的内容并挖掘历史,如果你真的想挖掘它,你会发现 ecore_x 曾经有 xlib 和 xcb sub-dirs 的目录。
这就是我编写 xlib abstractor/detail 填充程序的原因,因为如果您将常见的冗长 Xlib 用法隐藏在更简单的 API 后面,那么编写的代码就会少得多。
看来您遇到的问题与我在此处描述的问题完全相同:How to upload 32 bit image to server-side pixmap
如果你创建 32 位 window 并且你有 24 位根,你不能使用 DefaultVisualOfScreen
/ DefaultColormapOfScreen
- 他们会设置 visual/colormap对根有效(因此,24 位)。
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
我对 imlib api 不是很熟悉,但看起来您应该能够为您的 window/pixmap 手动创建颜色图并将其传递给 imlib
创建 32 位深的最简单方法window:
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
Window win = XCreateWindow(display, DefaultRootWindow(display),
0, 0, width, height, 0,
vinfo.depth, // <---------------!!!
InputOutput,
vinfo.visual, // <---------------!!!
mask, &attr);
您无法让根 window 具有您想要的深度 — 它已经存在并且具有它所具有的深度。
想提供一个更简单的解决方案(基本上与@n.m. 解决方案相同,但有更多代码):
Display *d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
attrs.override_redirect = true;
XVisualInfo vinfo;
if (!XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo)) {
printf("No visual found supporting 32 bit color, terminating\n");
exit(EXIT_FAILURE);
}
attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
// Window XCreateWindow(
// Display *display, Window parent,
// int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
// int depth, unsigned int class,
// Visual *visual,
// unsigned long valuemask, XSetWindowAttributes *attributes
// );
Window overlay = XCreateWindow(
d, root,
0, 0, 200, 200, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
基本上,除了获得正确的视觉效果之外,您还需要指定颜色图、背景像素 (CWBackPixel
) 和边框像素。无需使用 XGetVisualInfo
遍历所有可用的视觉效果,XMatchVisualInfo
会为您完成工作。请注意,我没有对此过程执行错误检查,您应该在生产中实施
我已经在这几天了,但我似乎无法弄清楚如何创建 32 位根 window 以便我可以在 child window,并且 child window 不能使用 32 位颜色深度(RGB 为 24 位,Alpha 通道为 8 位)如果 parent,或在这种情况下,root window 没有 32 位颜色深度。我正在使用以下代码将根 window 的背景设置为颜色深度为 24 位的 RGB 图像,因此当我将 XCreatePixmap 设置为颜色深度为 24 位时它就可以工作,但是我需要此根 window 具有用于 alpha 合成的 32 位颜色深度:
/* displays an image or sets root background
* PUBLIC DOMAIN - CC0 http://creativecommons.org/publicdomain/zero/1.0/
* J.Mayo 2013
*
* gcc -Wall -W -g3 -o background background.c -lX11 -lImlib2
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <Imlib2.h>
struct screenAttributes {
int height;
int width;
};
struct screenAttributes screenAttr;
void initializeScreenAttributes(Screen *screen) {
screenAttr.height=screen->height;
screenAttr.width=screen->width;
}
int main(int argc, char **argv)
{
Imlib_Image img;
Display *dpy;
Pixmap pix;
Window root;
Screen *scn;
// Window topPanel;
int width, height;
const char *filename = "/sampleImage.png";
img = imlib_load_image(filename);
if (!img) {
fprintf(stderr, "%s:Unable to load image\n", filename);
goto usage;
}
imlib_context_set_image(img);
width = imlib_image_get_width();
height = imlib_image_get_height();
dpy = XOpenDisplay(NULL);
if (!dpy) return 0;
scn = DefaultScreenOfDisplay(dpy);
root = DefaultRootWindow(dpy);
pix = XCreatePixmap(dpy, root, width, height,32); //when depth is set to 24 it just works, but when it is set to 32 it fails.
//scale the image
initializeScreenAttributes(scn);
imlib_blend_image_onto_image(img,0,0,0,width,height,0,0,
screenAttr.width, screenAttr.height);
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
imlib_context_set_drawable(pix);
imlib_render_image_on_drawable(0, 0);
XSetWindowBackgroundPixmap(dpy, root, pix);
XClearWindow(dpy, root);
while (XPending(dpy)) {
XEvent ev;
XNextEvent(dpy, &ev);
}
XFreePixmap(dpy, pix);
imlib_free_image();
sleep(10);
//XFreePixmap(dpy, pix);
//imlib_free_image();
XCloseDisplay(dpy);
return 0;
usage:
fprintf(stderr, "usage: %s <image_file>\n", argv[0]);
return 1;
}
当我将 XCreapePixmap 的颜色深度设置为 32 位时,我得到:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor Opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request : 28
Current serial number in output stream: 29 xinit: connection to X server lost
所以,换句话说,我不太确定如何将根 window 的颜色深度设置为 32 位,并将 24 位 RGB 图像设置为背景根 window.
谢谢!
P.S。我没有安装任何 window 管理器或任何桌面环境,因此无法使用其中的任何可用工具。
没有。您不必让 root window 的深度为 32 就可以让 children 的深度为 32 也。否则你怎么认为 windows 可以有 alpha 通道 作曲家?你怎么看这个:
http://www.enlightenment.org/ss/e-5872c6ec3ddce1.54730231.png
没有 2 个 windows 具有 32 位深度是可能的吗? (左边的 2 - 时钟和半透明终端)。 :)
半透明的工作方式是合成器的干预(现在通常是你的 window manager) 并且合成了 32bit windows 在上面(也可能是 deals 在底部也重绘根 window - 这可能取决于)。所以说 "I don't have a compositor/window manager so that's out of the question" 基本上就是说 "I don't want to do the one and only thing I HAVE TO DO in order to get translucency" 所以我建议你 re-evaluate 这个位置。
所以你真正想要的是一个合成器和 32 位 windows。要么使用 合成 window 管理器,然后创建 32 位 windows,或 运行 一个单独的 合成器和你现有的 WM,或者编写你自己的合成器......(不打算 正确快速地完成这项工作会很有趣)...
现在要创建 ARGB window,您需要 XRender 的视觉帮助。就像下面的 disp 是你的 Xlib Display 而 parent 是 parent Window (例如root):
Window win;
XSetWindowAttributes attr;
XWindowAttributes att;
XVisualInfo *xvi;
XVisualInfo vi_in;
int nvi, i, scr = 0;
XRenderPictFormat *fmt;
Visual *vis;
vi_in.screen = scr;
vi_in.depth = 32;
vi_in.class = TrueColor;
xvi = XGetVisualInfo(disp,
VisualScreenMask |
VisualDepthMask |
VisualClassMask,
&vi_in,
&nvi);
if (!xvi) return 0;
vis = NULL;
for (i = 0; i < nvi; i++)
{
fmt = XRenderFindVisualFormat(disp, xvi[i].visual);
if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask))
{
vis = xvi[i].visual;
break;
}
}
XFree (xvi);
attr.backing_store = NotUseful;
attr.override_redirect = 0;
attr.colormap = XCreateColormap(disp, parent,
vis, AllocNone);
attr.border_pixel = 0;
attr.background_pixmap = None;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
attr.save_under = 0;
attr.do_not_propagate_mask = NoEventMask;
attr.event_mask = KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask |
EnterWindowMask |
LeaveWindowMask |
PointerMotionMask |
ExposureMask |
VisibilityChangeMask |
StructureNotifyMask |
FocusChangeMask |
PropertyChangeMask |
ColormapChangeMask;
win = XCreateWindow(disp, parent,
x, y, w, h, 0,
32,
InputOutput,
vis,
CWBackingStore |
CWOverrideRedirect |
CWColormap |
CWBorderPixel |
CWBackPixmap |
CWSaveUnder |
CWDontPropagate |
CWEventMask |
CWBitGravity |
CWWinGravity,
&attr);
代码来自这里:https://git.enlightenment.org/core/efl.git/tree/src/lib/ecore_x/ecore_x_window.c#n1644
我们曾经有一个 XCB back-end 和 XCB 中的所有这些代码,但我们在大约十年后放弃了 XCB。如果你克隆上面的内容并挖掘历史,如果你真的想挖掘它,你会发现 ecore_x 曾经有 xlib 和 xcb sub-dirs 的目录。
这就是我编写 xlib abstractor/detail 填充程序的原因,因为如果您将常见的冗长 Xlib 用法隐藏在更简单的 API 后面,那么编写的代码就会少得多。
看来您遇到的问题与我在此处描述的问题完全相同:How to upload 32 bit image to server-side pixmap
如果你创建 32 位 window 并且你有 24 位根,你不能使用 DefaultVisualOfScreen
/ DefaultColormapOfScreen
- 他们会设置 visual/colormap对根有效(因此,24 位)。
imlib_context_set_visual(DefaultVisualOfScreen(scn));
imlib_context_set_colormap(DefaultColormapOfScreen(scn));
我对 imlib api 不是很熟悉,但看起来您应该能够为您的 window/pixmap 手动创建颜色图并将其传递给 imlib
创建 32 位深的最简单方法window:
XVisualInfo vinfo;
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
Window win = XCreateWindow(display, DefaultRootWindow(display),
0, 0, width, height, 0,
vinfo.depth, // <---------------!!!
InputOutput,
vinfo.visual, // <---------------!!!
mask, &attr);
您无法让根 window 具有您想要的深度 — 它已经存在并且具有它所具有的深度。
想提供一个更简单的解决方案(基本上与@n.m. 解决方案相同,但有更多代码):
Display *d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
XSetWindowAttributes attrs;
attrs.override_redirect = true;
XVisualInfo vinfo;
if (!XMatchVisualInfo(d, DefaultScreen(d), 32, TrueColor, &vinfo)) {
printf("No visual found supporting 32 bit color, terminating\n");
exit(EXIT_FAILURE);
}
attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
// Window XCreateWindow(
// Display *display, Window parent,
// int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
// int depth, unsigned int class,
// Visual *visual,
// unsigned long valuemask, XSetWindowAttributes *attributes
// );
Window overlay = XCreateWindow(
d, root,
0, 0, 200, 200, 0,
vinfo.depth, InputOutput,
vinfo.visual,
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, &attrs
);
基本上,除了获得正确的视觉效果之外,您还需要指定颜色图、背景像素 (CWBackPixel
) 和边框像素。无需使用 XGetVisualInfo
遍历所有可用的视觉效果,XMatchVisualInfo
会为您完成工作。请注意,我没有对此过程执行错误检查,您应该在生产中实施