aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2023-11-13 20:47:28 +0100
committerFederico Angelilli <code@fedang.net>2023-11-13 20:47:28 +0100
commitec91f4c1ea7b1ef10d8bbddff5d6993ba165607e (patch)
treeee0bca2bcb184a29b1d44d12f0035d3b96858447
parent818800377e039ad780ab3aa932872ab7306aae07 (diff)
Support wm with `xcb-ewmh`
-rw-r--r--x11.c104
-rw-r--r--x11.h2
2 files changed, 80 insertions, 26 deletions
diff --git a/x11.c b/x11.c
index d2eb233..36b2f9d 100644
--- a/x11.c
+++ b/x11.c
@@ -1,4 +1,5 @@
#include <glib.h>
+#include <unistd.h>
#include <math.h>
#include <cairo.h>
#include <cairo-xcb.h>
@@ -6,6 +7,7 @@
#include <xcb/xproto.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_icccm.h>
+#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_xrm.h>
#include <xcb/randr.h>
#include <xcb/xcb_errors.h>
@@ -23,6 +25,7 @@ struct Window {
xcb_errors_context_t *errors;
xcb_drawable_t window;
xcb_visualtype_t *visual_type;
+ xcb_ewmh_connection_t ewmh;
cairo_surface_t *surface;
cairo_t *cr;
double dpi;
@@ -39,18 +42,6 @@ typedef struct {
xcb_generic_event_t *event;
} XcbSource;
-static xcb_atom_t intern_atom(Window *win, const char *atom)
-{
- xcb_generic_error_t *error;
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(win->connection, false, strlen(atom), atom);
- xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(win->connection, cookie, &error);
-
- g_assert_null(error);
- xcb_atom_t id = reply->atom;
- g_free(reply);
- return id;
-}
-
static gboolean xcb_source_check(GSource *source)
{
XcbSource *xsource = (XcbSource *)source;
@@ -98,8 +89,8 @@ static gboolean xcb_source_dispatch(GSource *source, GSourceFunc callback, gpoin
break;
}
- case XCB_BUTTON_PRESS: {
- log_debug("Keypress event");
+ case XCB_BUTTON_RELEASE: {
+ log_debug("Mouse event");
break;
}
@@ -159,6 +150,63 @@ static void attach_source(Window *win)
g_source_attach(win->source, NULL);
}
+static xcb_atom_t intern_atom(Window *win, const char *atom)
+{
+ xcb_generic_error_t *error;
+ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(win->connection, false, strlen(atom), atom);
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(win->connection, cookie, &error);
+
+ g_assert_null(error);
+ xcb_atom_t id = reply->atom;
+ g_free(reply);
+ return id;
+}
+
+static void wm_set_size(Window *win)
+{
+ xcb_size_hints_t hints;
+ xcb_icccm_size_hints_set_size(&hints, false, win->width, win->height);
+ xcb_icccm_size_hints_set_min_size(&hints, win->width, win->height);
+ xcb_icccm_size_hints_set_max_size(&hints, win->width, win->height);
+ xcb_icccm_size_hints_set_base_size(&hints, win->width, win->height);
+ xcb_icccm_size_hints_set_position(&hints, false, win->x, win->y);
+
+ xcb_icccm_set_wm_size_hints(win->connection, win->window, XCB_ATOM_WM_NORMAL_HINTS, &hints);
+ log_debug("Xcb icccm updated size hints");
+}
+
+static void wm_setup(Window *win)
+{
+ const char *title = "comet";
+ xcb_icccm_set_wm_name(win->connection, win->window, XCB_ATOM_STRING, 8, strlen(title), title);
+ log_debug("Window updated title [%s]", title);
+
+ const char class[] = "comet\0Comet";
+ xcb_icccm_set_wm_class(win->connection, win->window, strlen(class), class);
+ log_debug("Window updated class [%s]", "comet\\0Comet");
+
+ xcb_generic_error_t *error;
+ xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(win->connection, &win->ewmh);
+
+ g_assert_true(xcb_ewmh_init_atoms_replies(&win->ewmh, ewmh_cookie, &error));
+ g_assert_null(error);
+ log_debug("Xcb ewmh connected");
+
+ xcb_ewmh_set_wm_window_type(&win->ewmh, win->window, 1, &win->ewmh._NET_WM_WINDOW_TYPE_DOCK);
+
+ xcb_atom_t state[] = {
+ win->ewmh._NET_WM_STATE_STICKY,
+ win->ewmh._NET_WM_STATE_ABOVE
+ };
+ xcb_ewmh_set_wm_state(&win->ewmh, win->window, G_N_ELEMENTS(state), state);
+
+ xcb_ewmh_set_wm_desktop(&win->ewmh, win->window, 0xFFFFFFFF);
+
+ xcb_ewmh_set_wm_pid(&win->ewmh, win->window, getpid());
+
+ wm_set_size(win);
+}
+
Window *window_create(void)
{
Window *win = g_malloc0(sizeof(Window));
@@ -166,7 +214,7 @@ Window *window_create(void)
int preferred_screen = 0;
win->connection = xcb_connect(NULL, &preferred_screen);
g_assert_true(win->connection != NULL && !xcb_connection_has_error(win->connection));
- log_debug("Xcb established connection");
+ log_debug("Xcb connected");
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(win->connection));
log_debug("Default screen %d", preferred_screen);
@@ -188,7 +236,7 @@ Window *window_create(void)
&error);
g_assert_null(error);
- log_debug("RandR version %d.%d", randr_version->major_version, randr_version->minor_version);
+ log_debug("RandR loaded [version=%d.%d]", randr_version->major_version, randr_version->minor_version);
g_assert_cmpint(randr_version->major_version, >=, 1);
xcb_randr_get_screen_info_cookie_t cookie = xcb_randr_get_screen_info(win->connection, win->screen->root);
@@ -216,6 +264,7 @@ Window *window_create(void)
window_update_scale(win);
g_assert(xcb_errors_context_new(win->connection, &win->errors) == 0);
+ log_debug("Xcb errors loaded");
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(win->screen);
while (depth_iter.rem) {
@@ -232,7 +281,7 @@ Window *window_create(void)
}
found_visual:
- log_debug("Xcb visual type found (id %u)", win->visual_type->visual_id);
+ log_debug("Xcb visual type found [id=%u]", win->visual_type->visual_id);
const uint32_t value_mask = XCB_CW_BACK_PIXMAP | XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL
| XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
@@ -243,7 +292,7 @@ found_visual:
xcb_colormap_t colormap = xcb_generate_id(win->connection);
xcb_create_colormap(win->connection, XCB_COLORMAP_ALLOC_NONE, colormap, win->screen->root, win->visual_type->visual_id);
- log_debug("Xcb colormap created (id %u)", colormap);
+ log_debug("Xcb colormap created [id=%u]", colormap);
const uint32_t value_list[] = {
XCB_NONE, // back pixmap
@@ -272,11 +321,12 @@ found_visual:
value_mask,
value_list);
- log_debug("Xcb window created (id %u)", win->window);
+ log_debug("Xcb window created [id=%u]", win->window);
- xcb_icccm_set_wm_name(win->connection, win->window, XCB_ATOM_STRING, 8, strlen("comet"), "comet");
- xcb_map_window(win->connection, win->window);
+ wm_setup(win);
+ log_debug("Window wm options completed");
+ xcb_map_window(win->connection, win->window);
xcb_flush(win->connection);
log_debug("Xcb initialized");
@@ -336,23 +386,23 @@ void window_get_screen_size(Window *win, int *width, int *height)
*height = win->screen_height;
}
-void window_set_transparency(Window *win, double alpha)
+void window_set_opacity(Window *win, double alpha)
{
// Value between 0 and 1
g_assert_true(alpha >= 0 && alpha <= 1);
unsigned long opacity = 0xffffffff * alpha;
- xcb_atom_t NET_WM_WINDOW_OPACITY = intern_atom(win, "_NET_WM_WINDOW_OPACITY");
+ xcb_atom_t _NET_WM_WINDOW_OPACITY = intern_atom(win, "_NET_WM_WINDOW_OPACITY");
xcb_change_property(win->connection,
XCB_PROP_MODE_REPLACE,
win->window,
- NET_WM_WINDOW_OPACITY,
+ _NET_WM_WINDOW_OPACITY,
XCB_ATOM_CARDINAL,
32,
1,
(char *)&opacity);
- log_debug("Window transparency set to '%.2lf%%'", alpha * 100.0);
+ log_debug("Window updated opacity [%.2lf%%]", alpha * 100.0);
}
@@ -386,6 +436,8 @@ void window_resize(Window *win, int width, int height)
values);
log_debug("Window updated size [width=%d, height=%d]", win->width, win->height);
+
+ wm_set_size(win);
}
void window_paint_surface(Window *win, cairo_surface_t *surface, int width, int height)
@@ -397,6 +449,7 @@ void window_paint_surface(Window *win, cairo_surface_t *surface, int width, int
cairo_paint(win->cr);
cairo_show_page(win->cr);
+ xcb_circulate_window(win->connection, XCB_CIRCULATE_RAISE_LOWEST, win->window);
xcb_flush(win->connection);
}
@@ -408,6 +461,7 @@ void window_destroy(Window *win)
cairo_destroy(win->cr);
cairo_surface_destroy(win->surface);
+ xcb_ewmh_connection_wipe(&win->ewmh);
xcb_errors_context_free(win->errors);
xcb_xrm_database_free(win->database);
xcb_disconnect(win->connection);
diff --git a/x11.h b/x11.h
index b65310b..daf6aff 100644
--- a/x11.h
+++ b/x11.h
@@ -15,7 +15,7 @@ double window_get_scale(Window *win);
void window_get_screen_size(Window *win, int *width, int *height);
-void window_set_transparency(Window *win, double alpha);
+void window_set_opacity(Window *win, double alpha);
void window_move(Window *win, int x, int y);