-
Notifications
You must be signed in to change notification settings - Fork 84
/
activate_linux.c
234 lines (199 loc) · 7.02 KB
/
activate_linux.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/Xinerama.h>
#include <cairo.h>
#include <cairo-xlib.h>
//struct to hold rgb color
struct RGBAColor
{
//rgba color values from 0 to 1
float r;
float g;
float b;
float a;
};
// draw text
void draw(cairo_t *cr, char *title, char *subtitle, float scale, struct RGBAColor color) {
//set color
cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
// set font size, and scale up or down
cairo_set_font_size(cr, 24 * scale);
cairo_move_to(cr, 20, 30 * scale);
cairo_show_text(cr, title);
cairo_set_font_size(cr, 16 * scale);
cairo_move_to(cr, 20, 55 * scale);
cairo_show_text(cr, subtitle);
}
//fill RGBAColor struct values from a string formatted in "r-g-b-a" from 0.0 to 1.0
void RGBAColor_from_string(struct RGBAColor* color, char* text)
{
//split text into 4 parts along "-". If the input is not valid, use default setting
char* red = strtok(text, "-");
if (red != NULL)
{
color->r = atof(red);
}
char* green = strtok(NULL, "-");
if (green != NULL)
{
color->g = atof(green);
}
char* blue = strtok(NULL, "-");
if (green != NULL)
{
color->b = atof(blue);
}
char* alpha = strtok(NULL, "-");
if (alpha != NULL)
{
color->a = atof(alpha);
}
}
int main(int argc, char *argv[]) {
Display *d = XOpenDisplay(NULL);
Window root = DefaultRootWindow(d);
int default_screen = XDefaultScreen(d);
int num_entries = 0;
// get all screens in use
XineramaScreenInfo *si = XineramaQueryScreens(d, &num_entries);
// if xinerama fails
if (si == NULL) {
perror("Required X extension Xinerama is not active");
XCloseDisplay(d);
return 1;
}
//title and subtitle text
char *title, *subtitle;
int overlay_width = 340;
int overlay_height = 120;
//color of text - set default as light grey
struct RGBAColor text_color = {.r= 1.0, .g= 1.0, .b= 1.0, .a= 0.35};
// default scale
float scale = 1.0f;
// switch on arguments
switch (argc) {
// if there are no arguments (1 is for program name)
case (1):
#ifdef __APPLE__
title = "Activate macOS";
subtitle = "Go to Settings to activate macOS.";
#else
title = "Activate Linux";
subtitle = "Go to Settings to activate Linux.";
#endif
break;
// 1 argument
case (2):
// if argument is a number, use as scale
if(atof(argv[1]) != 0) {
scale = atof(argv[1]);
#ifdef __APPLE__
title = "Activate MacOS";
subtitle = "Go to Settings to activate MacOS";
#else
title = "Activate Linux";
subtitle = "Go to Settings to activate Linux.";
#endif
}
else {
title = argv[1];
subtitle = "";
}
break;
// 2 arguments
case (3):
title = argv[1];
subtitle = argv[2];
break;
// 3 arguments
case (4):
title = argv[1];
subtitle = argv[2];
scale = atof(argv[3]);
break;
//4 arguments
case (5):
title = argv[1];
subtitle = argv[2];
scale = atof(argv[3]);
RGBAColor_from_string(&text_color, argv[4]);
break;
// if there are more than 3 arguments, print usage
default:
printf("More than needed arguments have been passed. This program only supports at most 4 arguments.\n");
return 1;
}
XSetWindowAttributes attrs;
attrs.override_redirect = 1;
XVisualInfo vinfo;
// MacOS doesnt support 32 bit color through XQuartz, massive hack
#ifdef __APPLE__
int colorDepth = 24;
#else
int colorDepth = 32;
#endif
if (!XMatchVisualInfo(d, default_screen, colorDepth, TrueColor, &vinfo)) {
printf("No visual found supporting 32 bit color, terminating\n");
exit(EXIT_FAILURE);
}
// sets 32 bit color depth
attrs.colormap = XCreateColormap(d, root, vinfo.visual, AllocNone);
attrs.background_pixel = 0;
attrs.border_pixel = 0;
Window overlay[num_entries];
cairo_surface_t *surface[num_entries];
cairo_t *cairo_ctx[num_entries];
overlay_height *= scale;
overlay_width *= scale;
// create overlay on each screen
for (int i = 0; i < num_entries; i++) {
overlay[i] = XCreateWindow(
d, // display
root, // parent
si[i].x_org + si[i].width - overlay_width, // x position
si[i].y_org + si[i].height - overlay_height, // y position
overlay_width, // width
overlay_height, // height
0, // border width
vinfo.depth, // depth
InputOutput, // class
vinfo.visual, // visual
CWOverrideRedirect | CWColormap | CWBackPixel | CWBorderPixel, // value mask
&attrs // attributes
);
XMapWindow(d, overlay[i]);
// allows the mouse to click through the overlay
XRectangle rect;
XserverRegion region = XFixesCreateRegion(d, &rect, 1);
XFixesSetWindowShapeRegion(d, overlay[i], ShapeInput, 0, 0, region);
XFixesDestroyRegion(d, region);
// sets a WM_CLASS to allow the user to blacklist some effect from compositor
XClassHint *xch = XAllocClassHint();
xch->res_name = "activate-linux";
xch->res_class = "activate-linux";
XSetClassHint(d, overlay[i], xch);
// cairo context
surface[i] = cairo_xlib_surface_create(d, overlay[i], vinfo.visual, overlay_width, overlay_height);
cairo_ctx[i] = cairo_create(surface[i]);
draw(cairo_ctx[i], title, subtitle, scale, text_color);
}
// wait for X events forever
XEvent event;
while(1) {
XNextEvent(d, &event);
}
// free used resources
for (int i = 0; i < num_entries; i++) {
XUnmapWindow(d, overlay[i]);
cairo_destroy(cairo_ctx[i]);
cairo_surface_destroy(surface[i]);
}
XFree(si);
XCloseDisplay(d);
return 0;
}