1 /* xob - A lightweight overlay volume/anything bar for the X Window System.
2 * Copyright (C) 2021 Florent Ch.
3 * Copyright (C) 2021 Oliver Hattshire
4 *
5 * xob is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * xob is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with xob. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19 #include "display.h"
20 #include <X11/extensions/Xrender.h>
21 #include <stdlib.h>
22
is_alpha_visual(Display_context dc,Visual * visual)23 static Bool is_alpha_visual(Display_context dc, Visual *visual)
24 {
25 XRenderPictFormat *fmt = XRenderFindVisualFormat(dc.x.display, visual);
26 return (fmt->type == PictTypeDirect && fmt->direct.alphaMask);
27 }
28
get_alpha_depth_if_available(Display_context dc)29 static Depth get_alpha_depth_if_available(Display_context dc)
30 {
31 Depth depth;
32 depth.nvisuals = 0;
33
34 int depths_list_num;
35 int *depths_list =
36 XListDepths(dc.x.display, dc.x.screen_number, &depths_list_num);
37
38 for (int i = depths_list_num - 1; i != 0; i--)
39 {
40 if (depths_list[i] == 32)
41 {
42 int visuals_count;
43 XVisualInfo *visuals_available;
44
45 static long visual_template_mask =
46 VisualScreenMask | VisualDepthMask | VisualClassMask;
47 XVisualInfo visual_template = {
48 .screen = dc.x.screen_number, .depth = 32, .class = TrueColor};
49
50 visuals_available =
51 XGetVisualInfo(dc.x.display, visual_template_mask,
52 &visual_template, &visuals_count);
53
54 for (int i = 0; i < visuals_count; i++)
55 {
56 if (is_alpha_visual(dc, visuals_available[i].visual))
57 {
58 depth.visuals = visuals_available[i].visual;
59 depth.nvisuals = 1;
60 depth.depth = 32;
61 break;
62 }
63 }
64 XFree(visuals_available);
65 break;
66 }
67 }
68 XFree(depths_list);
69 return depth;
70 }
71
xrendercolor_from_color(Color color)72 static XRenderColor xrendercolor_from_color(Color color)
73 {
74 unsigned short alpha = color.alpha * 257;
75 return (XRenderColor){.alpha = alpha,
76 .red = (color.red * 257 * alpha) / 0xffffU,
77 .green = (color.green * 257 * alpha) / 0xffffU,
78 .blue = (color.blue * 257 * alpha) / 0xffffU};
79 }
80
fill_rectangle(X_context xc,Color c,int x,int y,unsigned int w,unsigned int h)81 void fill_rectangle(X_context xc, Color c, int x, int y, unsigned int w,
82 unsigned int h)
83 {
84 XRenderColor xrc = xrendercolor_from_color(c);
85 XWindowAttributes attrib;
86 XGetWindowAttributes(xc.display, xc.window, &attrib);
87 XRenderPictFormat *pfmt =
88 XRenderFindVisualFormat(xc.display, attrib.visual);
89
90 Picture pict = XRenderCreatePicture(xc.display, xc.window, pfmt, 0, 0);
91 XRenderFillRectangle(xc.display, PictOpSrc, pict, &xrc, x, y, w, h);
92 XRenderFreePicture(xc.display, pict);
93 }
94
get_display_context_depth(Display_context dc)95 Depth get_display_context_depth(Display_context dc)
96 {
97 Depth depth = {.depth = DefaultDepth(dc.x.display, dc.x.screen_number),
98 .visuals = DefaultVisual(dc.x.display, dc.x.screen_number),
99 .nvisuals = 1};
100 Depth adepth = get_alpha_depth_if_available(dc);
101 return adepth.nvisuals == 1 ? adepth : depth;
102 }
103