Skip to content

Instantly share code, notes, and snippets.

@Toqozz
Last active April 19, 2023 14:04
Show Gist options
  • Save Toqozz/ab499d3a06124dc77e2b4edbfe1f88e4 to your computer and use it in GitHub Desktop.
Save Toqozz/ab499d3a06124dc77e2b4edbfe1f88e4 to your computer and use it in GitHub Desktop.
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "x.h"
#include "datatypes.h"
// Apply atoms to window.
static void
x_set_wm(Window win, Display *dsp)
{
Atom property[3]; // Reusable array, (parent + 2 children).
// Set window's WM_NAME property.
// char *title = "yarn"; -- only used twice.
XStoreName(dsp, win, "yarn");
// No children.
property[2] = XInternAtom(dsp, "_NET_WM_NAME", false); // Get WM_NAME atom and store it in _net_wm_title.
XChangeProperty(dsp, win, property[2], XInternAtom(dsp, "UTF8_STRING", false), 8, PropModeReplace, (unsigned char *) "yarn", 4);
// Set window's class.
// char *class = "yarn"; -- only used once.
XClassHint classhint = { "yarn", "yarn" };
XSetClassHint(dsp, win, &classhint);
// Parent.
property[2] = XInternAtom(dsp, "_NET_WM_WINDOW_TYPE", false); // Let WM know type.
// Children.
property[0] = XInternAtom(dsp, "_NET_WM_WINDOW_TYPE_NOTIFICATION", false);
property[1] = XInternAtom(dsp, "_NET_WM_WINDOW_TYPE_UTILITY", false);
// Reach for 2 longs, (2L).
XChangeProperty(dsp, win, property[2], XA_ATOM, 32, PropModeReplace, (unsigned char *) property, 2L);
/*
// Parent.
property[2] = XInternAtom(dsp, "_NET_WM_STATE", false); // Let WM know state.
// Child.
property[0] = XInternAtom(dsp, "_NET_WM_STATE_ABOVE", false);
// Reach for 1 long, (1L).
XChangeProperty(dsp, win, property[2], XA_ATOM, 32, PropModeReplace, (unsigned char *) property, 1L);
*/
}
// Map window and return surface for that window.
cairo_surface_t *
cairo_create_x11_surface(int x, int y, int w, int h)
{
Display *display;
Drawable drawable;
int screen; // Screen #.
cairo_surface_t *surface;
// Error if no open..
if ((display = XOpenDisplay(NULL)) == NULL) // Set display though.
exit(1);
screen = DefaultScreen(display); // Use primary display.
XVisualInfo vinfo;
// Match the display settings.
// TODO, default depth instead of guess?
XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo);
XSetWindowAttributes attr;
// We need all 3 of these attributes, or BadMatch: http://stackoverflow.com/questions/3645632/how-to-create-a-window-with-a-bit-depth-of-32
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0;
drawable = XCreateWindow(display, DefaultRootWindow(display), // Returns a window (a drawable place).
x,y, // Position on screen.
w,h, // Width, Height.
0, // Border width.
vinfo.depth, InputOutput, vinfo.visual, // Depth, Class, Visual type.
CWColormap | CWBorderPixel | CWBackPixel, // Overwritten attributes.
&attr);
// Apply the Atoms to the new window.
// Request that the X server report these events.
x_set_wm(drawable, display);
XSelectInput(display, drawable, ExposureMask | ButtonPressMask | KeyPressMask);
// Show window on screen.
XMapWindow(display, drawable);
Atom above_atom = XInternAtom(display, "_NET_WM_STATE_ABOVE", 1);
Atom net_wm_state = XInternAtom(display, "_NET_WM_STATE", 1);
XClientMessageEvent xclient;
memset(&xclient, 0, sizeof(xclient));
xclient.type = ClientMessage;
xclient.window = drawable;
xclient.message_type = net_wm_state;
xclient.format = 32;
xclient.data.l[0] = 1;
xclient.data.l[1] = above_atom;
xclient.data.l[2] = 0;
xclient.data.l[3] = 0;
xclient.data.l[4] = 0;
XSendEvent(display, DefaultRootWindow(display), false, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xclient);
XFlush(display);
return surface;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment