diff options
Diffstat (limited to 'x11.c')
| -rw-r--r-- | x11.c | 104 |
1 files changed, 79 insertions, 25 deletions
@@ -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); |
