30#define G_LOG_DOMAIN "X11Helper"
35#include <xcb-imdkit/encoding.h>
36#include <xcb/xcb_keysyms.h>
49#include <xcb/xcb_aux.h>
50#include <xcb/xcb_cursor.h>
51#include <xcb/xcb_ewmh.h>
52#include <xcb/xinerama.h>
54#include <xcb/xproto.h>
55#include <xkbcommon/xkbcommon-x11.h>
56#include <xkbcommon/xkbcommon.h>
58#define SN_API_NOT_YET_FROZEN
61#define sn_launcher_context_set_application_id sn_launcher_set_application_id
79#define RANDR_PREF_MAJOR_VERSION 1
81#define RANDR_PREF_MINOR_VERSION 5
84#define INTERSECT(x, y, x1, y1, w1, h1) \
85 ((((x) >= (x1)) && ((x) < (x1 + w1))) && (((y) >= (y1)) && ((y) < (y1 + h1))))
110xcb_colormap_t
map = XCB_COLORMAP_NONE;
131 {
"default",
"left_ptr"}, {
"pointer",
"hand"}, {
"text",
"xterm"}};
133static xcb_visualtype_t *
lookup_visual(xcb_screen_t *s, xcb_visualid_t vis) {
134 xcb_depth_iterator_t d;
135 d = xcb_screen_allowed_depths_iterator(s);
136 for (; d.rem; xcb_depth_next(&d)) {
137 xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator(d.data);
138 for (; v.rem; xcb_visualtype_next(&v)) {
139 if (v.data->visual_id == vis) {
151static uint32_t *
create_kernel(
int radius,
double deviation, uint32_t *sum2) {
152 int size = 2 * (radius) + 1;
153 uint32_t *kernel = (uint32_t *)(g_malloc(
sizeof(uint32_t) * (size + 1)));
154 double radiusf = abs(radius) + 1.0;
155 double value = -radius;
159 if (deviation == 0.0) {
160 deviation = sqrt(-(radiusf * radiusf) / (2.0 * log(1.0 / 255.0)));
165 for (i = 0; i < size; i++) {
166 kernel[1 + i] = INT16_MAX / (2.506628275 * deviation) *
167 exp(-((value * value) / (2.0 * (deviation * deviation))));
169 sum += kernel[1 + i];
181 uint32_t *kernel = 0;
182 cairo_format_t format;
183 unsigned int channels;
185 if (cairo_surface_status(surface)) {
189 uint8_t *data = cairo_image_surface_get_data(surface);
190 format = cairo_image_surface_get_format(surface);
191 const int width = cairo_image_surface_get_width(surface);
192 const int height = cairo_image_surface_get_height(surface);
193 const int stride = cairo_image_surface_get_stride(surface);
194 if (radius > (height / 2)) {
195 radius = height / 2 - 1;
197 if (radius > (width / 2)) {
198 radius = width / 2 - 1;
204 if (format == CAIRO_FORMAT_ARGB32) {
210 horzBlur = (uint32_t *)(g_malloc(
sizeof(uint32_t) * height * stride));
217 uint32_t *horzBlur_ptr = horzBlur;
218 for (
int iY = 0; iY < height; iY++) {
219 const int iYs = iY * stride;
220 for (
int iX = 0; iX < width; iX++) {
225 int offset = (int)(kernel[0]) / -2;
227 for (
int i = 0; i < (int)(kernel[0]); i++) {
230 if (x < 0 || x >= width) {
235 uint8_t *dataPtr = &data[iYs + x * channels];
236 const uint32_t kernip1 = kernel[i + 1];
238 blue += kernip1 * dataPtr[0];
239 green += kernip1 * dataPtr[1];
240 red += kernip1 * dataPtr[2];
241 alpha += kernip1 * dataPtr[3];
245 *horzBlur_ptr++ = blue / sum;
246 *horzBlur_ptr++ = green / sum;
247 *horzBlur_ptr++ = red / sum;
248 *horzBlur_ptr++ = alpha / sum;
254 for (
int iY = 0; iY < height; iY++) {
255 for (
int iX = 0; iX < width; iX++) {
260 int offset = (int)(kernel[0]) / -2;
262 const int iXs = iX * channels;
263 for (
int i = 0; i < (int)(kernel[0]); i++) {
266 if (y < 0 || y >= height) {
271 uint32_t *dataPtr = &horzBlur[y * stride + iXs];
272 const uint32_t kernip1 = kernel[i + 1];
274 blue += kernip1 * dataPtr[0];
275 green += kernip1 * dataPtr[1];
276 red += kernip1 * dataPtr[2];
277 alpha += kernip1 * dataPtr[3];
282 *data++ = blue / sum;
283 *data++ = green / sum;
285 *data++ = alpha / sum;
298 xcb_get_geometry_cookie_t cookie;
299 xcb_get_geometry_reply_t *reply;
301 cookie = xcb_get_geometry(
xcb->connection, window);
302 reply = xcb_get_geometry_reply(
xcb->connection, cookie, NULL);
307 xcb_get_window_attributes_cookie_t attributesCookie =
308 xcb_get_window_attributes(
xcb->connection, window);
309 xcb_get_window_attributes_reply_t *attributes =
310 xcb_get_window_attributes_reply(
xcb->connection, attributesCookie, NULL);
311 if (attributes == NULL || (attributes->map_state != XCB_MAP_STATE_VIEWABLE)) {
322 cairo_surface_t *t = cairo_xcb_surface_create(
xcb->connection, window, vt,
323 reply->width, reply->height);
325 if (cairo_surface_status(t) != CAIRO_STATUS_SUCCESS) {
326 cairo_surface_destroy(t);
332 int max = MAX(reply->width, reply->height);
333 double scale = (double)size / max;
335 cairo_surface_t *s2 = cairo_surface_create_similar_image(
336 t, CAIRO_FORMAT_ARGB32, reply->width * scale, reply->height * scale);
339 if (cairo_surface_status(s2) != CAIRO_STATUS_SUCCESS) {
340 cairo_surface_destroy(t);
344 cairo_t *d = cairo_create(s2);
345 cairo_scale(d, scale, scale);
346 cairo_set_source_surface(d, t, 0, 0);
350 cairo_surface_destroy(t);
360 xcb->screen->height_in_pixels);
365 xcb_get_property_cookie_t cookie;
366 xcb_get_property_reply_t *reply;
367 xcb_pixmap_t rootpixmap = XCB_NONE;
369 cookie = xcb_get_property(c, 0, screen->root, atom, XCB_ATOM_PIXMAP, 0, 1);
371 reply = xcb_get_property_reply(c, cookie, NULL);
374 if (xcb_get_property_value_length(reply) ==
sizeof(xcb_pixmap_t)) {
375 memcpy(&rootpixmap, xcb_get_property_value(reply),
sizeof(xcb_pixmap_t));
386 if (pm == XCB_NONE) {
390 xcb->screen->width_in_pixels,
391 xcb->screen->height_in_pixels);
398 xcb_get_property_cookie_t c = xcb_get_property(
399 xcb->connection, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
400 xcb_get_property_reply_t *r =
401 xcb_get_property_reply(
xcb->connection, c, NULL);
403 if (xcb_get_property_value_length(r) > 0) {
405 if (r->type ==
netatoms[UTF8_STRING]) {
407 xcb_get_property_value_length(r));
408 }
else if (r->type ==
netatoms[STRING]) {
410 xcb_get_property_value_length(r));
412 str = g_strdup(
"Invalid encoding.");
425 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE, w, prop,
426 XCB_ATOM_ATOM, 32,
count, atoms);
442 while (
xcb->monitors != NULL) {
455 double ratio_res = w->
w / (double)w->
h;
456 double ratio_size = w->
mw / (double)w->
mh;
458 if ((ratio_res < 1.0 && ratio_size > 1.0) ||
459 (ratio_res > 1.0 && ratio_size < 1.0)) {
470 xcb_randr_get_output_info_reply_t *op_reply;
471 xcb_randr_get_crtc_info_reply_t *crtc_reply;
472 xcb_randr_get_output_info_cookie_t it =
473 xcb_randr_get_output_info(
xcb->connection, out, XCB_CURRENT_TIME);
474 op_reply = xcb_randr_get_output_info_reply(
xcb->connection, it, NULL);
475 if (op_reply->crtc == XCB_NONE) {
479 xcb_randr_get_crtc_info_cookie_t ct = xcb_randr_get_crtc_info(
480 xcb->connection, op_reply->crtc, XCB_CURRENT_TIME);
481 crtc_reply = xcb_randr_get_crtc_info_reply(
xcb->connection, ct, NULL);
487 retv->
x = crtc_reply->x;
488 retv->
y = crtc_reply->y;
489 retv->
w = crtc_reply->width;
490 retv->
h = crtc_reply->height;
492 retv->
mw = op_reply->mm_width;
493 retv->
mh = op_reply->mm_height;
496 char *tname = (
char *)xcb_randr_get_output_info_name(op_reply);
497 int tname_len = xcb_randr_get_output_info_name_length(op_reply);
499 retv->
name = g_malloc0((tname_len + 1) *
sizeof(
char));
500 memcpy(retv->
name, tname, tname_len);
507#if (((XCB_RANDR_MAJOR_VERSION >= RANDR_PREF_MAJOR_VERSION) && \
508 (XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION)) || \
509 XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION)
518x11_get_monitor_from_randr_monitor(xcb_randr_monitor_info_t *
mon) {
520 xcb_generic_error_t *err;
521 xcb_get_atom_name_cookie_t anc =
522 xcb_get_atom_name(
xcb->connection,
mon->name);
523 xcb_get_atom_name_reply_t *atom_reply =
524 xcb_get_atom_name_reply(
xcb->connection, anc, &err);
526 g_warning(
"Could not get RandR monitor name: X11 error code %d\n",
539 retv->
w =
mon->width;
540 retv->
h =
mon->height;
543 retv->
mw =
mon->width_in_millimeters;
544 retv->
mh =
mon->height_in_millimeters;
549 g_strdup_printf(
"%.*s", xcb_get_atom_name_name_length(atom_reply),
550 xcb_get_atom_name_name(atom_reply));
560 xcb_query_extension_cookie_t randr_cookie =
561 xcb_query_extension(
xcb->connection, strlen(extension), extension);
563 xcb_query_extension_reply_t *randr_reply =
564 xcb_query_extension_reply(
xcb->connection, randr_cookie, NULL);
566 int present = randr_reply->present;
574 xcb_xinerama_query_screens_cookie_t screens_cookie =
575 xcb_xinerama_query_screens_unchecked(
xcb->connection);
577 xcb_xinerama_query_screens_reply_t *screens_reply =
578 xcb_xinerama_query_screens_reply(
xcb->connection, screens_cookie, NULL);
580 xcb_xinerama_screen_info_iterator_t screens_iterator =
581 xcb_xinerama_query_screens_screen_info_iterator(screens_reply);
583 for (; screens_iterator.rem > 0;
584 xcb_xinerama_screen_info_next(&screens_iterator)) {
587 w->
x = screens_iterator.data->x_org;
588 w->
y = screens_iterator.data->y_org;
589 w->
w = screens_iterator.data->width;
590 w->
h = screens_iterator.data->height;
597 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
598 iter->monitor_id = index++;
612 g_debug(
"Query XINERAMA for monitor layout.");
616 g_debug(
"No RANDR or Xinerama available for getting monitor layout.");
619 g_debug(
"Query RANDR for monitor layout.");
621 g_debug(
"Randr XCB api version: %d.%d.", XCB_RANDR_MAJOR_VERSION,
622 XCB_RANDR_MINOR_VERSION);
623#if (((XCB_RANDR_MAJOR_VERSION == RANDR_PREF_MAJOR_VERSION) && \
624 (XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION)) || \
625 XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION)
626 xcb_randr_query_version_cookie_t cversion = xcb_randr_query_version(
628 xcb_randr_query_version_reply_t *rversion =
629 xcb_randr_query_version_reply(
xcb->connection, cversion, NULL);
631 g_debug(
"Found randr version: %d.%d", rversion->major_version,
632 rversion->minor_version);
637 xcb_randr_get_monitors_cookie_t t =
638 xcb_randr_get_monitors(
xcb->connection,
xcb->screen->root, 1);
639 xcb_randr_get_monitors_reply_t *mreply =
640 xcb_randr_get_monitors_reply(
xcb->connection, t, NULL);
642 xcb_randr_monitor_info_iterator_t iter =
643 xcb_randr_get_monitors_monitors_iterator(mreply);
644 while (iter.rem > 0) {
645 workarea *w = x11_get_monitor_from_randr_monitor(iter.data);
650 xcb_randr_monitor_info_next(&iter);
660 if (
xcb->monitors == NULL) {
661 xcb_randr_get_screen_resources_current_reply_t *res_reply;
662 xcb_randr_get_screen_resources_current_cookie_t src;
663 src = xcb_randr_get_screen_resources_current(
xcb->connection,
665 res_reply = xcb_randr_get_screen_resources_current_reply(
xcb->connection,
671 xcb_randr_get_screen_resources_current_outputs_length(res_reply);
672 xcb_randr_output_t *ops =
673 xcb_randr_get_screen_resources_current_outputs(res_reply);
676 xcb_randr_get_output_primary_cookie_t pc =
677 xcb_randr_get_output_primary(
xcb->connection,
xcb->screen->root);
678 xcb_randr_get_output_primary_reply_t *pc_rep =
679 xcb_randr_get_output_primary_reply(
xcb->connection, pc, NULL);
681 for (
int i = mon_num - 1; i >= 0; i--) {
686 if (pc_rep && pc_rep->output == ops[i]) {
700 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
701 iter->monitor_id = index++;
706 int is_term = isatty(fileno(stdout));
707 printf(
"Monitor layout:\n");
708 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
709 printf(
"%s ID%s: %d", (is_term) ?
color_bold :
"",
712 printf(
" (primary)");
715 printf(
"%s name%s: %s\n", (is_term) ?
color_bold :
"",
717 printf(
"%s position%s: %d,%d\n", (is_term) ?
color_bold :
"",
719 printf(
"%s size%s: %d,%d\n", (is_term) ?
color_bold :
"",
721 if (iter->mw > 0 && iter->mh > 0) {
722 printf(
"%s size%s: %dmm,%dmm dpi: %.0f,%.0f\n",
724 iter->mh, iter->w * 25.4 / (
double)iter->mw,
725 iter->h * 25.4 / (
double)iter->mh);
732 GSpawnChildSetupFunc *child_setup,
733 gpointer *user_data) {
734 if (context == NULL) {
738 SnLauncherContext *sncontext;
740 sncontext = sn_launcher_context_new(
xcb->sndisplay,
xcb->screen_nbr);
742 sn_launcher_context_set_name(sncontext, context->
name);
743 sn_launcher_context_set_description(sncontext, context->
description);
744 if (context->
binary != NULL) {
745 sn_launcher_context_set_binary_name(sncontext, context->
binary);
747 if (context->
icon != NULL) {
748 sn_launcher_context_set_icon_name(sncontext, context->
icon);
750 if (context->
app_id != NULL) {
753 if (context->
wmclass != NULL) {
754 sn_launcher_context_set_wmclass(sncontext, context->
wmclass);
757 xcb_get_property_cookie_t c;
758 unsigned int current_desktop = 0;
760 c = xcb_ewmh_get_current_desktop(&
xcb->ewmh,
xcb->screen_nbr);
761 if (xcb_ewmh_get_current_desktop_reply(&
xcb->ewmh, c, ¤t_desktop,
763 sn_launcher_context_set_workspace(sncontext, current_desktop);
766 sn_launcher_context_initiate(sncontext,
"rofi", context->
command,
767 xcb->last_timestamp);
769 *child_setup = (GSpawnChildSetupFunc)sn_launcher_context_setup_child_process;
770 *user_data = sncontext;
775 mon->w =
xcb->screen->width_in_pixels;
776 mon->h =
xcb->screen->height_in_pixels;
779 for (iter =
xcb->monitors; iter; iter = iter->
next) {
790 g_error(
"%s: mon == NULL", __func__);
794 mon->w =
xcb->screen->width_in_pixels;
795 mon->h =
xcb->screen->height_in_pixels;
797 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
798 if (
INTERSECT(x, y, iter->x, iter->y, iter->w, iter->h)) {
818 xcb_query_pointer_cookie_t c = xcb_query_pointer(
xcb->connection, root);
819 xcb_query_pointer_reply_t *r =
820 xcb_query_pointer_reply(
xcb->connection, c, NULL);
832 g_error(
"%s: mon == NULL", __func__);
836 xcb_get_geometry_cookie_t c = xcb_get_geometry(
xcb->connection,
id);
837 xcb_get_geometry_reply_t *r =
838 xcb_get_geometry_reply(
xcb->connection, c, NULL);
840 xcb_translate_coordinates_cookie_t ct =
841 xcb_translate_coordinates(
xcb->connection,
id, root, r->x, r->y);
842 xcb_translate_coordinates_reply_t *t =
843 xcb_translate_coordinates_reply(
xcb->connection, ct, NULL);
848 mon->x = t->dst_x - r->x;
849 mon->y = t->dst_y - r->y;
863 xcb_get_property_cookie_t awc;
865 g_error(
"%s: mon == NULL", __func__);
868 awc = xcb_ewmh_get_active_window(&
xcb->ewmh,
xcb->screen_nbr);
869 if (!xcb_ewmh_get_active_window_reply(&
xcb->ewmh, awc, &active_window,
872 "Failed to get active window, falling back to mouse location (-5).");
875 xcb_query_tree_cookie_t tree_cookie =
876 xcb_query_tree(
xcb->connection, active_window);
877 xcb_query_tree_reply_t *tree_reply =
878 xcb_query_tree_reply(
xcb->connection, tree_cookie, NULL);
881 "Failed to get parent window, falling back to mouse location (-5).");
885 xcb_get_geometry_cookie_t c =
886 xcb_get_geometry(
xcb->connection, active_window);
887 xcb_get_geometry_reply_t *r =
888 xcb_get_geometry_reply(
xcb->connection, c, NULL);
890 g_debug(
"Failed to get geometry of active window, falling back to mouse "
895 if (tree_reply->parent != r->root) {
896 xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates(
897 xcb->connection, tree_reply->parent, r->root, r->x, r->y);
898 xcb_translate_coordinates_reply_t *t =
899 xcb_translate_coordinates_reply(
xcb->connection, ct, NULL);
905 g_debug(
"Failed to get translate position of active window, falling back "
906 "to mouse location (-5).");
916 mon->x = r->x + r->border_width;
917 mon->y = r->y + r->border_width;
921 }
else if (mon_id == -4) {
922 g_debug(
"Find monitor at location: %d %d", r->x, r->y);
926 g_debug(
"mon pos: %d %d %d-%d",
mon->x,
mon->y,
mon->w,
mon->h);
935 g_error(
"%s: mon == NULL", __func__);
938 g_debug(
"Monitor id: %d", mon_id);
949 else if (mon_id == -1) {
950 g_debug(
"rofi on current monitor");
952 unsigned int current_desktop = 0;
953 xcb_get_property_cookie_t gcdc;
954 gcdc = xcb_ewmh_get_current_desktop(&
xcb->ewmh,
xcb->screen_nbr);
955 if (xcb_ewmh_get_current_desktop_reply(&
xcb->ewmh, gcdc, ¤t_desktop,
957 g_debug(
"Found current desktop: %u", current_desktop);
958 xcb_get_property_cookie_t c =
959 xcb_ewmh_get_desktop_viewport(&
xcb->ewmh,
xcb->screen_nbr);
960 xcb_ewmh_get_desktop_viewport_reply_t vp;
961 if (xcb_ewmh_get_desktop_viewport_reply(&
xcb->ewmh, c, &vp, NULL)) {
962 g_debug(
"Found %d number of desktops", vp.desktop_viewport_len);
963 if (current_desktop < vp.desktop_viewport_len) {
964 g_debug(
"Found viewport for desktop: %d %d",
965 vp.desktop_viewport[current_desktop].x,
966 vp.desktop_viewport[current_desktop].y);
968 vp.desktop_viewport[current_desktop].y,
mon);
969 g_debug(
"Found monitor @: %d %d %dx%d",
mon->x,
mon->y,
mon->w,
971 xcb_ewmh_get_desktop_viewport_reply_wipe(&vp);
974 g_debug(
"Viewport does not exist for current desktop: %d, falling "
975 "back to mouse location (-5)",
978 xcb_ewmh_get_desktop_viewport_reply_wipe(&vp);
980 g_debug(
"Failed to get viewport for current desktop: %d, falling back "
981 "to mouse location (-5).",
985 g_debug(
"Failed to get current desktop, falling back to mouse location "
988 }
else if (mon_id == -2 || mon_id == -4) {
994 else if (mon_id == -5) {
1002 g_debug(
"Failed to find monitor, fall back to monitor showing mouse.");
1014 g_error(
"%s: mon == NULL", __func__);
1017 g_debug(
"Monitor active");
1022 if (
config.monitor != NULL) {
1023 g_debug(
"Monitor lookup by name : %s",
config.monitor);
1024 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
1025 if (g_strcmp0(
config.monitor, iter->name) == 0) {
1033 g_debug(
"Monitor lookup by name failed: %s",
config.monitor);
1035 if (g_strcmp0(
config.monitor,
"primary") == 0) {
1036 for (
workarea *iter =
xcb->monitors; iter; iter = iter->next) {
1037 if (iter->primary) {
1045 if (g_str_has_prefix(
config.monitor,
"wid:")) {
1047 xcb_drawable_t win = g_ascii_strtoll(
config.monitor + 4, &end, 0);
1048 if (end !=
config.monitor) {
1059 gint64 mon_id = g_ascii_strtoll(
config.monitor, &end, 0);
1060 if (end !=
config.monitor) {
1067 g_warning(
"Failed to find selected monitor.");
1084 xcb_get_atom_name_cookie_t cookie;
1085 xcb_get_atom_name_reply_t *reply;
1094 cookie = xcb_get_atom_name(conn, atom);
1095 reply = xcb_get_atom_name_reply(conn, cookie, NULL);
1099 length = xcb_get_atom_name_name_length(reply);
1100 name = xcb_get_atom_name_name(reply);
1102 (*out) = g_strndup(name, length);
1119 xcb_selection_notify_event_t *xse) {
1120 if (xse->property == XCB_ATOM_NONE) {
1121 g_debug(
"Failed to convert selection");
1122 }
else if (xse->property ==
xcb->ewmh.UTF8_STRING) {
1124 if (text != NULL && text[0] !=
'\0') {
1125 unsigned int dl = strlen(text);
1127 for (
unsigned int i = 0; i < dl; i++) {
1128 if (text[i] ==
'\n') {
1138 g_debug(
"rofi_view_paste: Got unknown atom: %s", out);
1141 g_debug(
"rofi_view_paste: Got unknown, unnamed: %s", out);
1148 NkBindingsMouseButton *button) {
1149 switch (x11_button) {
1151 *button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
1154 *button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
1157 *button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
1160 *button = NK_BINDINGS_MOUSE_BUTTON_BACK;
1163 *button = NK_BINDINGS_MOUSE_BUTTON_FORWARD;
1171 *button = NK_BINDINGS_MOUSE_BUTTON_EXTRA + x11_button;
1177 NkBindingsScrollAxis *axis,
1180 switch (x11_button) {
1185 *axis = NK_BINDINGS_SCROLL_AXIS_VERTICAL;
1191 *axis = NK_BINDINGS_SCROLL_AXIS_HORIZONTAL;
1202 g_log(
"IMDKit", G_LOG_LEVEL_DEBUG,
"press handler %d", xkpe->detail);
1204 xcb->last_timestamp = xkpe->time;
1205 if (
config.xserver_i300_workaround) {
1206 text = nk_bindings_seat_handle_key_with_modmask(
1207 xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
1208 NK_BINDINGS_KEY_STATE_PRESS);
1210 text = nk_bindings_seat_handle_key(
xcb->bindings_seat, NULL, xkpe->detail,
1211 NK_BINDINGS_KEY_STATE_PRESS);
1221 g_log(
"IMDKit", G_LOG_LEVEL_DEBUG,
"release handler %d", xkre->detail);
1222 xcb->last_timestamp = xkre->time;
1223 nk_bindings_seat_handle_key(
xcb->bindings_seat, NULL, xkre->detail,
1224 NK_BINDINGS_KEY_STATE_RELEASE);
1232 if (state == NULL) {
1236 switch (event->response_type & ~0x80) {
1237 case XCB_CLIENT_MESSAGE: {
1238 xcb_client_message_event_t *cme = (xcb_client_message_event_t *)event;
1239 xcb_atom_t atom = cme->data.data32[0];
1241 if (atom ==
netatoms[WM_TAKE_FOCUS]) {
1242 xcb_set_input_focus(
xcb->connection, XCB_INPUT_FOCUS_NONE, cme->window,
1244 xcb_flush(
xcb->connection);
1248 case XCB_DESTROY_NOTIFY: {
1249 xcb_window_t win = ((xcb_destroy_notify_event_t *)event)->window;
1252 window_client_handle_signal(win, FALSE);
1255 g_main_loop_quit(
xcb->main_loop);
1259 case XCB_CREATE_NOTIFY: {
1260 xcb_window_t win = ((xcb_create_notify_event_t *)event)->window;
1263 window_client_handle_signal(win, TRUE);
1271 case XCB_CONFIGURE_NOTIFY: {
1276 case XCB_MOTION_NOTIFY: {
1277 xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *)event;
1278 gboolean button_mask = xme->state & XCB_EVENT_MASK_BUTTON_1_MOTION;
1280 !button_mask &&
config.hover_select);
1283 case XCB_BUTTON_PRESS: {
1284 xcb_button_press_event_t *bpe = (xcb_button_press_event_t *)event;
1285 NkBindingsMouseButton button;
1286 NkBindingsScrollAxis axis;
1289 xcb->last_timestamp = bpe->time;
1292 nk_bindings_seat_handle_button(
xcb->bindings_seat, NULL, button,
1293 NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time);
1295 nk_bindings_seat_handle_scroll(
xcb->bindings_seat, NULL, axis, steps);
1300 case XCB_SELECTION_CLEAR: {
1301 g_debug(
"Selection Clear.");
1304 case XCB_SELECTION_REQUEST: {
1305 g_debug(
"Selection Request.");
1306 xcb_selection_request_event_t *req = (xcb_selection_request_event_t *)event;
1307 if (req->selection ==
netatoms[CLIPBOARD]) {
1308 xcb_atom_t targets[2];
1309 xcb_selection_notify_event_t selection_notify = {
1310 .response_type = XCB_SELECTION_NOTIFY,
1313 .requestor = req->requestor,
1314 .selection = req->selection,
1315 .target = req->target,
1316 .property = XCB_ATOM_NONE,
1319 if (
xcb->clipboard) {
1321 if (req->target ==
netatoms[UTF8_STRING]) {
1322 g_debug(
"Selection Request UTF-8.");
1323 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE,
1324 req->requestor, req->property,
1326 strlen(
xcb->clipboard) + 1,
xcb->clipboard);
1327 selection_notify.property = req->property;
1328 }
else if (req->target ==
netatoms[TARGETS]) {
1329 g_debug(
"Selection Request Targets.");
1331 targets[0] =
netatoms[UTF8_STRING];
1332 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE,
1333 req->requestor, req->property, XCB_ATOM_ATOM, 32,
1335 selection_notify.property = req->property;
1339 xcb_send_event(
xcb->connection,
1341 req->requestor, XCB_EVENT_MASK_NO_EVENT,
1342 (
const char *)&selection_notify);
1343 xcb_flush(
xcb->connection);
1346 case XCB_BUTTON_RELEASE: {
1347 xcb_button_release_event_t *bre = (xcb_button_release_event_t *)event;
1348 NkBindingsMouseButton button;
1350 xcb->last_timestamp = bre->time;
1352 nk_bindings_seat_handle_button(
xcb->bindings_seat, NULL, button,
1353 NK_BINDINGS_BUTTON_STATE_RELEASE,
1356 if (
config.click_to_exit == TRUE) {
1357 if (!
xcb->mouse_seen) {
1365 case XCB_SELECTION_NOTIFY:
1368 case XCB_KEYMAP_NOTIFY: {
1369 xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *)event;
1370 for (gint32 by = 0; by < 31; ++by) {
1371 for (gint8 bi = 0; bi < 7; ++bi) {
1372 if (kne->keys[by] & (1 << bi)) {
1374 nk_bindings_seat_handle_key(
xcb->bindings_seat, NULL,
1376 NK_BINDINGS_KEY_STATE_PRESSED);
1382 case XCB_KEY_PRESS: {
1383 xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *)event;
1386 g_log(
"IMDKit", G_LOG_LEVEL_DEBUG,
"press key %d to xim", xkpe->detail);
1387 xcb_xim_forward_event(
xcb->im,
xcb->ic, xkpe);
1396 case XCB_KEY_RELEASE: {
1397 xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
1400 g_log(
"IMDKit", G_LOG_LEVEL_DEBUG,
"release key %d to xim", xkre->detail);
1406 xcb_keysym_t sym = xcb_key_press_lookup_keysym(
xcb->syms, xkre, 0);
1407 if (xcb_is_modifier_key(sym)) {
1408 struct timespec five_millis = {.tv_sec = 0, .tv_nsec = 5000000};
1409 nanosleep(&five_millis, NULL);
1411 xcb_xim_forward_event(
xcb->im,
xcb->ic, xkre);
1427void x11_event_handler_fowarding(G_GNUC_UNUSED xcb_xim_t *im,
1428 G_GNUC_UNUSED xcb_xic_t ic,
1429 xcb_key_press_event_t *event,
1430 G_GNUC_UNUSED
void *user_data) {
1432 if (state == NULL) {
1436 uint8_t type =
event->response_type & ~0x80;
1437 if (type == XCB_KEY_PRESS) {
1439 }
else if (type == XCB_KEY_RELEASE) {
1440 xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
1448 G_GNUC_UNUSED gpointer user_data) {
1450 int status = xcb_connection_has_error(
xcb->connection);
1452 g_warning(
"The XCB connection to X server had a fatal error: %d", status);
1453 g_main_loop_quit(
xcb->main_loop);
1454 return G_SOURCE_REMOVE;
1460 return G_SOURCE_CONTINUE;
1464 if (
config.enable_imdkit &&
xcb->im && xcb_xim_filter_event(
xcb->im, ev))
1465 return G_SOURCE_CONTINUE;
1468 uint8_t type = ev->response_type & ~0x80;
1469 if (type ==
xcb->xkb.first_event) {
1471 case XCB_XKB_MAP_NOTIFY: {
1472 struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device(
1473 nk_bindings_seat_get_context(
xcb->bindings_seat),
xcb->connection,
1474 xcb->xkb.device_id, 0);
1475 struct xkb_state *state = xkb_x11_state_new_from_device(
1476 keymap,
xcb->connection,
xcb->xkb.device_id);
1477 nk_bindings_seat_update_keymap(
xcb->bindings_seat, keymap, state);
1478 xkb_keymap_unref(keymap);
1479 xkb_state_unref(state);
1482 case XCB_XKB_STATE_NOTIFY: {
1483 xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *)ev;
1484 nk_bindings_seat_update_mask(
xcb->bindings_seat, NULL, ksne->baseMods,
1485 ksne->latchedMods, ksne->lockedMods,
1486 ksne->baseGroup, ksne->latchedGroup,
1492 return G_SOURCE_CONTINUE;
1494 if (
xcb->sndisplay != NULL) {
1495 sn_xcb_display_process_event(
xcb->sndisplay, ev);
1499 return G_SOURCE_CONTINUE;
1505 if (xcb_connection_has_error(
xcb->connection)) {
1506 g_warning(
"Connection has error");
1509 xcb_grab_pointer_cookie_t cc =
1510 xcb_grab_pointer(
xcb->connection, 1, w, XCB_EVENT_MASK_BUTTON_RELEASE,
1511 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, w, XCB_NONE,
1513 xcb_grab_pointer_reply_t *r =
1514 xcb_grab_pointer_reply(
xcb->connection, cc, NULL);
1516 if (r->status == XCB_GRAB_STATUS_SUCCESS) {
1522 if ((++i) > iters) {
1525 struct timespec del = {.tv_sec = 0, .tv_nsec = 1000000};
1526 nanosleep(&del, NULL);
1534 if (xcb_connection_has_error(
xcb->connection)) {
1535 g_warning(
"Connection has error");
1538 xcb_grab_keyboard_cookie_t cc =
1539 xcb_grab_keyboard(
xcb->connection, 1, w, XCB_CURRENT_TIME,
1540 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
1541 xcb_grab_keyboard_reply_t *r =
1542 xcb_grab_keyboard_reply(
xcb->connection, cc, NULL);
1544 if (r->status == XCB_GRAB_STATUS_SUCCESS) {
1550 if ((++i) > iters) {
1553 struct timespec del = {.tv_sec = 0, .tv_nsec = 1000000};
1554 nanosleep(&del, NULL);
1560 xcb_ungrab_keyboard(
xcb->connection, XCB_CURRENT_TIME);
1563 xcb_ungrab_pointer(
xcb->connection, XCB_CURRENT_TIME);
1569 G_GNUC_UNUSED xcb_connection_t *xdisplay) {
1574 xcb_connection_t *xdisplay) {
1576 g_warning(
"Error trap underflow!");
1580 xcb_flush(xdisplay);
1590 xcb_intern_atom_cookie_t cc = xcb_intern_atom(
1592 xcb_intern_atom_reply_t *r =
1593 xcb_intern_atom_reply(
xcb->connection, cc, NULL);
1604 xcb_get_property_cookie_t cc = xcb_ewmh_get_supporting_wm_check_unchecked(
1607 if (xcb_ewmh_get_supporting_wm_check_reply(&
xcb->ewmh, cc, &wm_win, NULL)) {
1608 xcb_ewmh_get_utf8_strings_reply_t wtitle;
1609 xcb_get_property_cookie_t cookie =
1610 xcb_ewmh_get_wm_name_unchecked(&(
xcb->ewmh), wm_win);
1611 if (xcb_ewmh_get_wm_name_reply(&(
xcb->ewmh), cookie, &wtitle, (
void *)0)) {
1612 if (wtitle.strings_len > 0) {
1613 retv = g_strndup(wtitle.strings, wtitle.strings_len);
1615 xcb_ewmh_get_utf8_strings_reply_wipe(&wtitle);
1623 xcb_get_property_cookie_t cc = xcb_ewmh_get_supporting_wm_check_unchecked(
1626 if (xcb_ewmh_get_supporting_wm_check_reply(&
xcb->ewmh, cc, &wm_win, NULL)) {
1627 xcb_ewmh_get_utf8_strings_reply_t wtitle;
1628 xcb_get_property_cookie_t cookie =
1629 xcb_ewmh_get_wm_name_unchecked(&(
xcb->ewmh), wm_win);
1630 if (xcb_ewmh_get_wm_name_reply(&(
xcb->ewmh), cookie, &wtitle, (
void *)0)) {
1631 if (wtitle.strings_len > 0) {
1633 char *str = g_strndup(wtitle.strings, wtitle.strings_len);
1634 g_debug(
"Found window manager: |%s|", str);
1635 if (g_strcmp0(str,
"i3") == 0) {
1641 xcb_ewmh_get_utf8_strings_reply_wipe(&wtitle);
1649 char *display_str = (
char *)g_getenv(
"DISPLAY");
1654 if (
config.enable_imdkit) {
1655 xcb_compound_text_init();
1658 xcb->source = g_water_xcb_source_new(g_main_loop_get_context(
xcb->main_loop),
1659 display_str, &
xcb->screen_nbr,
1661 if (
xcb->source == NULL) {
1662 g_warning(
"Failed to open display: %s", display_str);
1665 xcb->connection = g_water_xcb_source_get_connection(
xcb->source);
1667 if (
config.enable_imdkit) {
1668 xcb->im = xcb_xim_create(
xcb->connection,
xcb->screen_nbr, NULL);
1669 xcb->syms = xcb_key_symbols_alloc(
xcb->connection);
1677#ifndef XCB_IMDKIT_1_0_3_LOWER
1678 if (
config.enable_imdkit) {
1679 xcb_xim_set_use_compound_text(
xcb->im,
true);
1680 xcb_xim_set_use_utf8_string(
xcb->im,
true);
1687 xcb->screen = xcb_aux_get_screen(
xcb->connection,
xcb->screen_nbr);
1691 xcb_intern_atom_cookie_t *ac =
1692 xcb_ewmh_init_atoms(
xcb->connection, &
xcb->ewmh);
1693 xcb_generic_error_t *errors = NULL;
1694 xcb_ewmh_init_atoms_replies(&
xcb->ewmh, ac, &errors);
1696 g_warning(
"Failed to create EWMH atoms");
1703 if (xkb_x11_setup_xkb_extension(
1704 xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION,
1705 XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
1706 NULL, NULL, &
xcb->xkb.first_event, NULL) < 0) {
1707 g_warning(
"cannot setup XKB extension!");
1711 xcb->xkb.device_id = xkb_x11_get_core_keyboard_device_id(
xcb->connection);
1715 (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
1716 XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY),
1718 required_nkn_details = (XCB_XKB_NKN_DETAIL_KEYCODES),
1720 required_map_parts =
1721 (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS |
1722 XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
1723 XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS |
1724 XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP),
1726 required_state_details =
1727 (XCB_XKB_STATE_PART_MODIFIER_BASE | XCB_XKB_STATE_PART_MODIFIER_LATCH |
1728 XCB_XKB_STATE_PART_MODIFIER_LOCK | XCB_XKB_STATE_PART_GROUP_BASE |
1729 XCB_XKB_STATE_PART_GROUP_LATCH | XCB_XKB_STATE_PART_GROUP_LOCK),
1732 static const xcb_xkb_select_events_details_t details = {
1733 .affectNewKeyboard = required_nkn_details,
1734 .newKeyboardDetails = required_nkn_details,
1735 .affectState = required_state_details,
1736 .stateDetails = required_state_details,
1738 xcb_xkb_select_events(
xcb->connection,
xcb->xkb.device_id,
1746 xcb->bindings_seat = nk_bindings_seat_new(
bindings, XKB_CONTEXT_NO_FLAGS);
1747 struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device(
1748 nk_bindings_seat_get_context(
xcb->bindings_seat),
xcb->connection,
1749 xcb->xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS);
1750 if (keymap == NULL) {
1751 g_warning(
"Failed to get Keymap for current keyboard device.");
1754 struct xkb_state *state = xkb_x11_state_new_from_device(
1755 keymap,
xcb->connection,
xcb->xkb.device_id);
1756 if (state == NULL) {
1757 g_warning(
"Failed to get state object for current keyboard device.");
1761 nk_bindings_seat_update_keymap(
xcb->bindings_seat, keymap, state);
1762 xkb_state_unref(state);
1763 xkb_keymap_unref(keymap);
1768 if (xcb_connection_has_error(
xcb->connection)) {
1769 g_warning(
"Connection has error");
1773 uint32_t val[] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY};
1775 XCB_CW_EVENT_MASK, val);
1779 if (xcb_connection_has_error(
xcb->connection)) {
1780 g_warning(
"Connection has error");
1784 if (
xcb->sndisplay != NULL) {
1785 xcb->sncontext = sn_launchee_context_new_from_environment(
xcb->sndisplay,
1788 if (xcb_connection_has_error(
xcb->connection)) {
1789 g_warning(
"Connection has error");
1797 xcb_depth_t *root_depth = NULL;
1798 xcb_depth_iterator_t depth_iter;
1799 for (depth_iter = xcb_screen_allowed_depths_iterator(
xcb->screen);
1800 depth_iter.rem; xcb_depth_next(&depth_iter)) {
1801 xcb_depth_t *d = depth_iter.data;
1803 xcb_visualtype_iterator_t visual_iter;
1804 for (visual_iter = xcb_depth_visuals_iterator(d); visual_iter.rem;
1805 xcb_visualtype_next(&visual_iter)) {
1806 xcb_visualtype_t *v = visual_iter.data;
1807 if ((v->bits_per_rgb_value == 8) && (d->depth == 32) &&
1808 (v->_class == XCB_VISUAL_CLASS_TRUE_COLOR)) {
1812 if (
xcb->screen->root_visual == v->visual_id) {
1819 xcb_void_cookie_t c;
1820 xcb_generic_error_t *e;
1821 map = xcb_generate_id(
xcb->connection);
1822 c = xcb_create_colormap_checked(
xcb->connection, XCB_COLORMAP_ALLOC_NONE,
1824 e = xcb_request_check(
xcb->connection, c);
1835 map =
xcb->screen->default_colormap;
1840 xcb_cursor_context_t *ctx;
1842 if (xcb_cursor_context_new(
xcb->connection,
xcb->screen, &ctx) < 0) {
1849 if (
cursors[i] == XCB_CURSOR_NONE) {
1855 xcb_cursor_context_free(ctx);
1865 g_warning(
"Failed to grab pointer after %u times. Giving up.",
1867 return G_SOURCE_REMOVE;
1870 return G_SOURCE_REMOVE;
1873 return G_SOURCE_CONTINUE;
1878 g_warning(
"Failed to grab keyboard after %u times. Giving up.",
1880 g_main_loop_quit(
xcb->main_loop);
1881 return G_SOURCE_REMOVE;
1884 return G_SOURCE_REMOVE;
1887 return G_SOURCE_CONTINUE;
1901 if (
find_arg(
"-normal-window") >= 0 ||
find_arg(
"-transient-window") >= 0) {
1904 if (
find_arg(
"-no-lazy-grab") >= 0) {
1906 g_warning(
"Failed to grab keyboard, even after %d uS.", 500 * 1000);
1910 g_warning(
"Failed to grab mouse pointer, even after %d uS.", 100 * 1000);
1928 xcb_flush(
xcb->connection);
1932 if (
xcb->connection == NULL) {
1936 g_debug(
"Cleaning up XCB and XKB");
1938 nk_bindings_seat_free(
xcb->bindings_seat);
1939 if (
xcb->sncontext != NULL) {
1940 sn_launchee_context_unref(
xcb->sncontext);
1941 xcb->sncontext = NULL;
1943 if (
xcb->sndisplay != NULL) {
1944 sn_display_unref(
xcb->sndisplay);
1945 xcb->sndisplay = NULL;
1948 xcb_ewmh_connection_wipe(&(
xcb->ewmh));
1949 xcb_flush(
xcb->connection);
1950 xcb_aux_sync(
xcb->connection);
1952 if (
config.enable_imdkit) {
1953 xcb_xim_close(
xcb->im);
1954 xcb_xim_destroy(
xcb->im);
1958 g_water_xcb_source_free(
xcb->source);
1960 xcb->connection = NULL;
1962 xcb->screen_nbr = 0;
1967 const uint32_t MWM_HINTS_DECORATIONS = (1 << 1);
1969 struct MotifWMHints {
1972 uint32_t decorations;
1977 struct MotifWMHints hints;
1978 hints.flags = MWM_HINTS_DECORATIONS;
1979 hints.decorations = 0;
1980 hints.functions = 0;
1981 hints.inputMode = 0;
1984 xcb_atom_t ha =
netatoms[_MOTIF_WM_HINTS];
1985 xcb_change_property(
xcb->connection, XCB_PROP_MODE_REPLACE, window, ha, ha,
1994 if (
cursors[type] == XCB_CURSOR_NONE) {
1998 xcb_change_window_attributes(
xcb->connection, window, XCB_CW_CURSOR,
2002 g_free(
xcb->clipboard);
2003 xcb->clipboard = data;
2007 if (
config.steal_focus != TRUE) {
2008 xcb->focus_revert = 0;
2011 xcb_generic_error_t *error;
2012 xcb_get_input_focus_reply_t *freply;
2013 xcb_get_input_focus_cookie_t fcookie = xcb_get_input_focus(
xcb->connection);
2014 freply = xcb_get_input_focus_reply(
xcb->connection, fcookie, &error);
2015 if (error != NULL) {
2016 g_warning(
"Could not get input focus (error %d), will revert focus to best "
2020 xcb->focus_revert = 0;
2022 xcb->focus_revert = freply->focus;
2024 xcb_set_input_focus(
xcb->connection, XCB_INPUT_FOCUS_POINTER_ROOT, w,
2026 xcb_flush(
xcb->connection);
2030 if (
xcb->focus_revert == 0) {
2034 xcb_set_input_focus(
xcb->connection, XCB_INPUT_FOCUS_POINTER_ROOT,
2035 xcb->focus_revert, XCB_CURRENT_TIME);
2036 xcb_flush(
xcb->connection);
struct _display_proxy display_proxy
struct _workarea workarea
char * rofi_latin_to_utf8_strdup(const char *input, gssize length)
int find_arg_str(const char *const key, char **val)
int find_arg(const char *const key)
char * rofi_force_utf8(const gchar *data, ssize_t length)
xcb_window_t rofi_view_get_window(void)
RofiViewState * rofi_view_get_active(void)
void rofi_view_handle_text(RofiViewState *state, const char *text)
void rofi_view_handle_mouse_motion(RofiViewState *state, gint x, gint y, gboolean find_mouse_target)
void rofi_view_temp_click_to_exit(RofiViewState *state, xcb_window_t target)
void rofi_view_temp_configure_notify(RofiViewState *state, xcb_configure_notify_event_t *xce)
void rofi_view_frame_callback(void)
void rofi_view_maybe_update(RofiViewState *state)
const view_proxy * xcb_view_proxy
const gchar * description
static display_proxy display_
int xcb_configure_notify_event_t
display_proxy *const xcb_proxy
static int xcb_display_monitor_active(workarea *mon)
static int take_pointer(xcb_window_t w, int iters)
#define RANDR_PREF_MAJOR_VERSION
const char * traditional_name
static int x11_is_extension_present(const char *extension)
static gboolean lazy_grab_pointer(G_GNUC_UNUSED gpointer data)
static void x11_workarea_fix_rotation(workarea *w)
cairo_surface_t * x11_helper_get_screenshot_surface(void)
const struct @325247206057200222067346210140327350042210125211 cursor_names[]
static void x11_build_monitor_layout(void)
char * window_get_text_prop(xcb_window_t w, xcb_atom_t atom)
static gboolean xcb_display_setup(GMainLoop *main_loop, NkBindings *bindings)
static xcb_pixmap_t get_root_pixmap(xcb_connection_t *c, xcb_screen_t *screen, xcb_atom_t atom)
static void release_pointer(void)
static void xcb_display_set_input_focus(guint w)
static bool get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out)
struct _xcb_stuff xcb_int
static int monitor_active_from_winid(xcb_drawable_t id, workarea *mon)
static void x11_create_visual_and_colormap(void)
static gboolean x11_button_to_nk_bindings_scroll(guint32 x11_button, NkBindingsScrollAxis *axis, gint32 *steps)
static void monitor_dimensions(int x, int y, workarea *mon)
cairo_surface_t * x11_helper_get_bg_surface(void)
static void x11_lookup_cursors(void)
static gboolean lazy_grab_keyboard(G_GNUC_UNUSED gpointer data)
#define INTERSECT(x, y, x1, y1, w1, h1)
static workarea * x11_get_monitor_from_output(xcb_randr_output_t out)
static void error_trap_pop(G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay)
void x11_set_cursor(xcb_window_t window, X11CursorType type)
static void x11_build_monitor_layout_xinerama(void)
static xcb_visualtype_t * lookup_visual(xcb_screen_t *s, xcb_visualid_t vis)
unsigned int lazy_grab_retry_count_pt
static xcb_visualtype_t * root_visual
static uint32_t * create_kernel(int radius, double deviation, uint32_t *sum2)
char * x11_helper_get_window_manager(void)
static void x11_create_frequently_used_atoms(void)
static int monitor_active_from_id_focused(int mon_id, workarea *mon)
void cairo_image_surface_blur(cairo_surface_t *surface, int radius, double deviation)
static gboolean x11_button_to_nk_bindings_button(guint32 x11_button, NkBindingsMouseButton *button)
xcb_cursor_t cursors[NUM_CURSORS]
static void x11_monitor_free(workarea *m)
static void x11_helper_discover_window_manager(void)
static const struct _view_proxy * xcb_display_view_proxy(void)
static int monitor_get_dimension(int monitor_id, workarea *mon)
static void xcb_display_dump_monitor_layout(void)
static int take_keyboard(xcb_window_t w, int iters)
xcb_window_t xcb_stuff_get_root_window(void)
unsigned int lazy_grab_retry_count_kb
static void rofi_view_paste(RofiViewState *state, xcb_selection_notify_event_t *xse)
static gboolean xcb_display_late_setup(void)
void window_set_atom_prop(xcb_window_t w, xcb_atom_t prop, xcb_atom_t *atoms, int count)
static void xcb_display_startup_notification(RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data)
const char * netatom_names[]
static int monitor_active_from_id(int mon_id, workarea *mon)
static void x11_monitors_free(void)
static guint xcb_display_scale(void)
static void error_trap_push(G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay)
WindowManagerQuirk current_window_manager
static int pointer_get(xcb_window_t root, int *x, int *y)
#define RANDR_PREF_MINOR_VERSION
#define sn_launcher_context_set_application_id
static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe, RofiViewState *state)
static void rofi_key_release_event_handler(xcb_key_release_event_t *xkre, G_GNUC_UNUSED RofiViewState *state)
void xcb_stuff_set_clipboard(char *data)
static int error_trap_depth
static void release_keyboard(void)
static void xcb_display_cleanup(void)
static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev, G_GNUC_UNUSED gpointer user_data)
static void xcb_display_early_cleanup(void)
void x11_disable_decoration(xcb_window_t window)
static void main_loop_x11_event_handler_view(xcb_generic_event_t *event)
xcb_atom_t netatoms[NUM_NETATOMS]
xcb_visualtype_t * visual
static void xcb_display_revert_input_focus(void)
cairo_surface_t * x11_helper_get_screenshot_surface_window(xcb_window_t window, int size)
struct _xcb_stuff xcb_stuff
@ WM_PANGO_WORKSPACE_NAMES
@ WM_DO_NOT_CHANGE_CURRENT_DESKTOP