30 #define G_LOG_DOMAIN "X11Helper"
40 #include <cairo-xcb.h>
41 #include <librsvg/rsvg.h>
44 #include <xcb/xcb_aux.h>
45 #include <xcb/randr.h>
46 #include <xcb/xinerama.h>
47 #include <xcb/xcb_ewmh.h>
48 #include <xcb/xproto.h>
50 #include <xkbcommon/xkbcommon.h>
51 #include <xkbcommon/xkbcommon-x11.h>
53 #define SN_API_NOT_YET_FROZEN
55 #define sn_launcher_context_set_application_id sn_launcher_set_application_id
68 #define RANDR_PREF_MAJOR_VERSION 1
70 #define RANDR_PREF_MINOR_VERSION 5
73 #define INTERSECT( x, y, x1, y1, w1, h1 ) ( ( ( ( x ) >= ( x1 ) ) && ( ( x ) < ( x1 + w1 ) ) ) && ( ( ( y ) >= ( y1 ) ) && ( ( y ) < ( y1 + h1 ) ) ) )
94 xcb_colormap_t
map = XCB_COLORMAP_NONE;
104 xcb_depth_iterator_t d;
105 d = xcb_screen_allowed_depths_iterator ( s );
106 for (; d.rem; xcb_depth_next ( &d ) ) {
107 xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator ( d.data );
108 for (; v.rem; xcb_visualtype_next ( &v ) ) {
109 if ( v.data->visual_id ==
visual ) {
119 xcb_get_geometry_cookie_t cookie;
120 xcb_get_geometry_reply_t *reply;
123 reply = xcb_get_geometry_reply (
xcb->
connection, cookie, NULL );
124 if ( reply == NULL ) {
128 xcb_get_window_attributes_cookie_t attributesCookie = xcb_get_window_attributes (
xcb->
connection, window );
129 xcb_get_window_attributes_reply_t *attributes = xcb_get_window_attributes_reply (
xcb->
connection,
132 if ( attributes == NULL || ( attributes->map_state != XCB_MAP_STATE_VIEWABLE ) ) {
143 cairo_surface_t *t = cairo_xcb_surface_create (
xcb->
connection, window, vt, reply->width, reply->height );
145 if ( cairo_surface_status ( t ) != CAIRO_STATUS_SUCCESS ) {
146 cairo_surface_destroy ( t );
152 int max = MAX ( reply->width, reply->height );
153 double scale = (double) size / max;
155 cairo_surface_t *s2 = cairo_surface_create_similar_image ( t, CAIRO_FORMAT_ARGB32, reply->width * scale, reply->height * scale );
158 if ( cairo_surface_status ( s2 ) != CAIRO_STATUS_SUCCESS ) {
159 cairo_surface_destroy ( t );
163 cairo_t *d = cairo_create ( s2 );
164 cairo_scale ( d, scale, scale );
165 cairo_set_source_surface ( d, t, 0, 0 );
169 cairo_surface_destroy ( t );
187 xcb_get_property_cookie_t cookie;
188 xcb_get_property_reply_t *reply;
189 xcb_pixmap_t rootpixmap = XCB_NONE;
191 cookie = xcb_get_property ( c,
199 reply = xcb_get_property_reply ( c, cookie, NULL );
202 if ( xcb_get_property_value_length ( reply ) ==
sizeof ( xcb_pixmap_t ) ) {
203 memcpy ( &rootpixmap, xcb_get_property_value ( reply ),
sizeof ( xcb_pixmap_t ) );
214 if ( pm == XCB_NONE ) {
225 xcb_get_property_cookie_t c = xcb_get_property (
xcb->
connection, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX );
226 xcb_get_property_reply_t *r = xcb_get_property_reply (
xcb->
connection, c, NULL );
228 if ( xcb_get_property_value_length ( r ) > 0 ) {
230 if ( r->type ==
netatoms[UTF8_STRING] ) {
231 str = g_strndup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
233 else if ( r->type ==
netatoms[STRING] ) {
237 str = g_strdup (
"Invalid encoding." );
250 xcb_change_property (
xcb->
connection, XCB_PROP_MODE_REPLACE, w, prop, XCB_ATOM_ATOM, 32,
count, atoms );
280 xcb_randr_get_output_info_reply_t *op_reply;
281 xcb_randr_get_crtc_info_reply_t *crtc_reply;
282 xcb_randr_get_output_info_cookie_t it = xcb_randr_get_output_info (
xcb->
connection, out, XCB_CURRENT_TIME );
283 op_reply = xcb_randr_get_output_info_reply (
xcb->
connection, it, NULL );
284 if ( op_reply->crtc == XCB_NONE ) {
288 xcb_randr_get_crtc_info_cookie_t ct = xcb_randr_get_crtc_info (
xcb->
connection, op_reply->crtc, XCB_CURRENT_TIME );
289 crtc_reply = xcb_randr_get_crtc_info_reply (
xcb->
connection, ct, NULL );
295 retv->
x = crtc_reply->x;
296 retv->
y = crtc_reply->y;
297 retv->
w = crtc_reply->width;
298 retv->
h = crtc_reply->height;
300 retv->
mw = op_reply->mm_width;
301 retv->
mh = op_reply->mm_height;
303 char *tname = (
char *) xcb_randr_get_output_info_name ( op_reply );
304 int tname_len = xcb_randr_get_output_info_name_length ( op_reply );
306 retv->
name = g_malloc0 ( ( tname_len + 1 ) *
sizeof (
char ) );
307 memcpy ( retv->
name, tname, tname_len );
314 #if ( ( ( XCB_RANDR_MAJOR_VERSION >= RANDR_PREF_MAJOR_VERSION ) && ( XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION ) ) \
315 || XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION )
323 static workarea *x11_get_monitor_from_randr_monitor ( xcb_randr_monitor_info_t *
mon )
326 xcb_generic_error_t *err;
328 xcb_get_atom_name_reply_t *atom_reply = xcb_get_atom_name_reply (
xcb->
connection, anc, &err );
330 g_warning (
"Could not get RandR monitor name: X11 error code %d\n", err->error_code );
342 retv->
w =
mon->width;
343 retv->
h =
mon->height;
346 retv->
mw =
mon->width_in_millimeters;
347 retv->
mh =
mon->height_in_millimeters;
350 retv->
name = g_strdup_printf (
"%.*s", xcb_get_atom_name_name_length ( atom_reply ), xcb_get_atom_name_name ( atom_reply ) );
361 xcb_query_extension_cookie_t randr_cookie = xcb_query_extension (
xcb->
connection, strlen ( extension ), extension );
363 xcb_query_extension_reply_t *randr_reply = xcb_query_extension_reply (
xcb->
connection, randr_cookie, NULL );
365 int present = randr_reply->present;
367 free ( randr_reply );
374 xcb_xinerama_query_screens_cookie_t screens_cookie = xcb_xinerama_query_screens_unchecked (
378 xcb_xinerama_query_screens_reply_t *screens_reply = xcb_xinerama_query_screens_reply (
384 xcb_xinerama_screen_info_iterator_t screens_iterator = xcb_xinerama_query_screens_screen_info_iterator (
388 for (; screens_iterator.rem > 0; xcb_xinerama_screen_info_next ( &screens_iterator ) ) {
391 w->
x = screens_iterator.data->x_org;
392 w->
y = screens_iterator.data->y_org;
393 w->
w = screens_iterator.data->width;
394 w->
h = screens_iterator.data->height;
405 free ( screens_reply );
417 g_debug (
"Query XINERAMA for monitor layout." );
421 g_debug (
"No RANDR or Xinerama available for getting monitor layout." );
424 g_debug (
"Query RANDR for monitor layout." );
426 g_debug (
"Randr XCB api version: %d.%d.", XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION );
427 #if ( ( ( XCB_RANDR_MAJOR_VERSION == RANDR_PREF_MAJOR_VERSION ) && ( XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION ) ) \
428 || XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION )
429 xcb_randr_query_version_cookie_t cversion = xcb_randr_query_version (
xcb->
connection,
431 xcb_randr_query_version_reply_t *rversion = xcb_randr_query_version_reply (
xcb->
connection, cversion, NULL );
433 g_debug (
"Found randr version: %d.%d", rversion->major_version, rversion->minor_version );
438 xcb_randr_get_monitors_reply_t *mreply = xcb_randr_get_monitors_reply (
xcb->
connection, t, NULL );
440 xcb_randr_monitor_info_iterator_t iter = xcb_randr_get_monitors_monitors_iterator ( mreply );
441 while ( iter.rem > 0 ) {
442 workarea *w = x11_get_monitor_from_randr_monitor ( iter.data );
447 xcb_randr_monitor_info_next ( &iter );
458 xcb_randr_get_screen_resources_current_reply_t *res_reply;
459 xcb_randr_get_screen_resources_current_cookie_t src;
461 res_reply = xcb_randr_get_screen_resources_current_reply (
xcb->
connection, src, NULL );
465 int mon_num = xcb_randr_get_screen_resources_current_outputs_length ( res_reply );
466 xcb_randr_output_t *ops = xcb_randr_get_screen_resources_current_outputs ( res_reply );
469 xcb_randr_get_output_primary_cookie_t pc = xcb_randr_get_output_primary (
xcb->
connection,
xcb->
screen->root );
470 xcb_randr_get_output_primary_reply_t *pc_rep = xcb_randr_get_output_primary_reply (
xcb->
connection, pc, NULL );
472 for (
int i = mon_num - 1; i >= 0; i-- ) {
477 if ( pc_rep && pc_rep->output == ops[i] ) {
492 iter->monitor_id = index++;
498 int is_term = isatty ( fileno ( stdout ) );
499 printf (
"Monitor layout:\n" );
501 printf (
"%s ID%s: %d", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->monitor_id );
502 if ( iter->primary ) {
503 printf (
" (primary)" );
507 printf (
"%s position%s: %d,%d\n", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->x, iter->y );
508 printf (
"%s size%s: %d,%d\n", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->w, iter->h );
509 if ( iter->mw > 0 && iter->mh > 0 ) {
510 printf (
"%s size%s: %dmm,%dmm dpi: %.0f,%.0f\n",
515 iter->w * 25.4 / (
double) iter->mw,
516 iter->h * 25.4 / (
double) iter->mh
525 if ( context == NULL ) {
535 if ( context->
binary != NULL ) {
538 if ( context->
icon != NULL ) {
539 sn_launcher_context_set_icon_name (
sncontext, context->
icon );
541 if ( context->
app_id != NULL ) {
544 if ( context->
wmclass != NULL ) {
548 xcb_get_property_cookie_t c;
549 unsigned int current_desktop = 0;
552 if ( xcb_ewmh_get_current_desktop_reply ( &
xcb->
ewmh, c, ¤t_desktop, NULL ) ) {
553 sn_launcher_context_set_workspace (
sncontext, current_desktop );
558 *child_setup = (GSpawnChildSetupFunc) sn_launcher_context_setup_child_process;
585 if (
INTERSECT ( x, y, iter->x, iter->y, iter->w, iter->h ) ) {
605 xcb_query_pointer_cookie_t c = xcb_query_pointer (
xcb->
connection, root );
606 xcb_query_pointer_reply_t *r = xcb_query_pointer_reply (
xcb->
connection, c, NULL );
619 xcb_get_geometry_cookie_t c = xcb_get_geometry (
xcb->
connection,
id );
620 xcb_get_geometry_reply_t *r = xcb_get_geometry_reply (
xcb->
connection, c, NULL );
622 xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates (
xcb->
connection,
id, root, r->x, r->y );
623 xcb_translate_coordinates_reply_t *t = xcb_translate_coordinates_reply (
xcb->
connection, ct, NULL );
628 mon->
x = t->dst_x - r->x;
629 mon->
y = t->dst_y - r->y;
643 xcb_window_t active_window;
644 xcb_get_property_cookie_t awc;
646 if ( !xcb_ewmh_get_active_window_reply ( &
xcb->
ewmh, awc, &active_window, NULL ) ) {
647 g_debug (
"Failed to get active window, falling back to mouse location (-5)." );
650 xcb_query_tree_cookie_t tree_cookie = xcb_query_tree (
xcb->
connection, active_window );
651 xcb_query_tree_reply_t *tree_reply = xcb_query_tree_reply (
xcb->
connection, tree_cookie, NULL );
653 g_debug (
"Failed to get parent window, falling back to mouse location (-5)." );
657 xcb_get_geometry_cookie_t c = xcb_get_geometry (
xcb->
connection, active_window );
658 xcb_get_geometry_reply_t *r = xcb_get_geometry_reply (
xcb->
connection, c, NULL );
660 g_debug (
"Failed to get geometry of active window, falling back to mouse location (-5)." );
664 xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates (
xcb->
connection, tree_reply->parent, r->root, r->x, r->y );
665 xcb_translate_coordinates_reply_t *t = xcb_translate_coordinates_reply (
xcb->
connection, ct, NULL );
667 if ( mon_id == -2 ) {
671 mon->
x = t->dst_x - r->x;
672 mon->
y = t->dst_y - r->y;
677 else if ( mon_id == -4 ) {
684 g_debug (
"Failed to get translate position of active window, falling back to mouse location (-5)." );
695 if ( mon_id == -3 ) {
704 else if ( mon_id == -1 ) {
706 unsigned int current_desktop = 0;
707 xcb_get_property_cookie_t gcdc;
709 if ( xcb_ewmh_get_current_desktop_reply ( &
xcb->
ewmh, gcdc, ¤t_desktop, NULL ) ) {
711 xcb_ewmh_get_desktop_viewport_reply_t vp;
712 if ( xcb_ewmh_get_desktop_viewport_reply ( &
xcb->
ewmh, c, &vp, NULL ) ) {
713 if ( current_desktop < vp.desktop_viewport_len ) {
715 vp.desktop_viewport[current_desktop].y,
mon );
716 xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp );
720 g_debug (
"Viewport does not exist for current desktop: %d, falling back to mouse location (-5)", current_desktop );
722 xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp );
725 g_debug (
"Failed to get viewport for current desktop: %d, falling back to mouse location (-5).", current_desktop );
729 g_debug (
"Failed to get current desktop, falling back to mouse location (-5)." );
732 else if ( mon_id == -2 || mon_id == -4 ) {
738 else if ( mon_id == -5 ) {
746 g_debug (
"Failed to find monitor, fall back to monitor showing mouse." );
764 if ( iter->primary ) {
772 xcb_drawable_t win = g_ascii_strtoll (
config.
monitor + 4, &end, 0 );
788 g_warning (
"Failed to find selected monitor." );
808 if ( xse->property == XCB_ATOM_NONE ) {
809 g_warning (
"Failed to convert selection" );
811 else if ( xse->property ==
xcb->
ewmh.UTF8_STRING ) {
813 if ( text != NULL && text[0] !=
'\0' ) {
814 unsigned int dl = strlen ( text );
816 for (
unsigned int i = 0; i < dl; i++ ) {
817 if ( text[i] ==
'\n' ) {
826 g_warning (
"Failed" );
832 switch ( x11_button )
835 *button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
838 *button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
841 *button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
844 *button = NK_BINDINGS_MOUSE_BUTTON_BACK;
847 *button = NK_BINDINGS_MOUSE_BUTTON_FORWARD;
855 *button = NK_BINDINGS_MOUSE_BUTTON_EXTRA + x11_button;
863 switch ( x11_button )
869 *axis = NK_BINDINGS_SCROLL_AXIS_VERTICAL;
875 *axis = NK_BINDINGS_SCROLL_AXIS_HORIZONTAL;
889 if ( state == NULL ) {
893 switch ( event->response_type & ~0x80 )
898 case XCB_CONFIGURE_NOTIFY:
900 xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
904 case XCB_MOTION_NOTIFY:
909 xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *) event;
913 case XCB_BUTTON_PRESS:
915 xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
916 NkBindingsMouseButton button;
917 NkBindingsScrollAxis axis;
923 nk_bindings_seat_handle_button (
xcb->
bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
930 case XCB_BUTTON_RELEASE:
932 xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
933 NkBindingsMouseButton button;
937 nk_bindings_seat_handle_button (
xcb->
bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
948 case XCB_SELECTION_NOTIFY:
951 case XCB_KEYMAP_NOTIFY:
953 xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
954 for ( gint32 by = 0; by < 31; ++by ) {
955 for ( gint8 bi = 0; bi < 7; ++bi ) {
956 if ( kne->keys[by] & ( 1 << bi ) ) {
958 nk_bindings_seat_handle_key (
xcb->
bindings_seat, NULL, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
966 xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
970 text = nk_bindings_seat_handle_key_with_modmask (
xcb->
bindings_seat, NULL, xkpe->state, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
971 if ( text != NULL ) {
976 case XCB_KEY_RELEASE:
978 xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
980 nk_bindings_seat_handle_key (
xcb->
bindings_seat, NULL, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
994 g_warning (
"The XCB connection to X server had a fatal error: %d", status );
996 return G_SOURCE_REMOVE;
999 g_warning (
"main_loop_x11_event_handler: ev == NULL, status == %d", status );
1000 return G_SOURCE_CONTINUE;
1003 uint8_t type = ev->response_type & ~0x80;
1007 case XCB_XKB_MAP_NOTIFY:
1012 xkb_keymap_unref ( keymap );
1013 xkb_state_unref ( state );
1016 case XCB_XKB_STATE_NOTIFY:
1018 xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
1025 ksne->lockedGroup );
1030 return G_SOURCE_CONTINUE;
1036 return G_SOURCE_CONTINUE;
1044 g_warning (
"Connection has error" );
1045 exit ( EXIT_FAILURE );
1047 xcb_grab_pointer_cookie_t cc = xcb_grab_pointer (
xcb->
connection, 1, w, XCB_EVENT_MASK_BUTTON_RELEASE,
1048 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, w, XCB_NONE, XCB_CURRENT_TIME );
1049 xcb_grab_pointer_reply_t *r = xcb_grab_pointer_reply (
xcb->
connection, cc, NULL );
1051 if ( r->status == XCB_GRAB_STATUS_SUCCESS ) {
1057 if ( ( ++i ) > iters ) {
1060 struct timespec del = {
1064 nanosleep ( &del, NULL );
1074 g_warning (
"Connection has error" );
1075 exit ( EXIT_FAILURE );
1077 xcb_grab_keyboard_cookie_t cc = xcb_grab_keyboard (
xcb->
connection,
1078 1, w, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC,
1079 XCB_GRAB_MODE_ASYNC );
1080 xcb_grab_keyboard_reply_t *r = xcb_grab_keyboard_reply (
xcb->
connection, cc, NULL );
1082 if ( r->status == XCB_GRAB_STATUS_SUCCESS ) {
1088 if ( ( ++i ) > iters ) {
1091 struct timespec del = {
1095 nanosleep ( &del, NULL );
1111 static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
1116 static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
1119 g_warning (
"Error trap underflow!" );
1120 exit ( EXIT_FAILURE );
1123 xcb_flush ( xdisplay );
1135 xcb_intern_atom_reply_t *r = xcb_intern_atom_reply (
xcb->
connection, cc, NULL );
1145 xcb_window_t wm_win = 0;
1146 xcb_get_property_cookie_t cc = xcb_ewmh_get_supporting_wm_check_unchecked ( &
xcb->
ewmh,
1149 if ( xcb_ewmh_get_supporting_wm_check_reply ( &
xcb->
ewmh, cc, &wm_win, NULL ) ) {
1150 xcb_ewmh_get_utf8_strings_reply_t wtitle;
1151 xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked ( &(
xcb->
ewmh ), wm_win );
1152 if ( xcb_ewmh_get_wm_name_reply ( &(
xcb->
ewmh ), cookie, &wtitle, (
void *) 0 ) ) {
1153 if ( wtitle.strings_len > 0 ) {
1154 g_debug (
"Found window manager: %s", wtitle.strings );
1155 if ( g_strcmp0 ( wtitle.strings,
"i3" ) == 0 ) {
1159 xcb_ewmh_get_utf8_strings_reply_wipe ( &wtitle );
1168 char *display_str = (
char *) g_getenv (
"DISPLAY" );
1174 g_warning (
"Failed to open display: %s", display_str );
1179 TICK_N (
"Open Display" );
1186 xcb_generic_error_t *errors = NULL;
1187 xcb_ewmh_init_atoms_replies ( &
xcb->
ewmh, ac, &errors );
1189 g_warning (
"Failed to create EWMH atoms" );
1196 if ( xkb_x11_setup_xkb_extension (
xcb->
connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
1197 XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &
xcb->
xkb.
first_event, NULL ) < 0 ) {
1198 g_warning (
"cannot setup XKB extension!" );
1207 ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
1208 XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
1209 XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
1211 required_nkn_details =
1212 ( XCB_XKB_NKN_DETAIL_KEYCODES ),
1214 required_map_parts =
1215 ( XCB_XKB_MAP_PART_KEY_TYPES |
1216 XCB_XKB_MAP_PART_KEY_SYMS |
1217 XCB_XKB_MAP_PART_MODIFIER_MAP |
1218 XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
1219 XCB_XKB_MAP_PART_KEY_ACTIONS |
1220 XCB_XKB_MAP_PART_VIRTUAL_MODS |
1221 XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
1223 required_state_details =
1224 ( XCB_XKB_STATE_PART_MODIFIER_BASE |
1225 XCB_XKB_STATE_PART_MODIFIER_LATCH |
1226 XCB_XKB_STATE_PART_MODIFIER_LOCK |
1227 XCB_XKB_STATE_PART_GROUP_BASE |
1228 XCB_XKB_STATE_PART_GROUP_LATCH |
1229 XCB_XKB_STATE_PART_GROUP_LOCK ),
1232 static const xcb_xkb_select_events_details_t details = {
1233 .affectNewKeyboard = required_nkn_details,
1234 .newKeyboardDetails = required_nkn_details,
1235 .affectState = required_state_details,
1236 .stateDetails = required_state_details,
1247 if ( keymap == NULL ) {
1248 g_warning (
"Failed to get Keymap for current keyboard device." );
1252 if ( state == NULL ) {
1253 g_warning (
"Failed to get state object for current keyboard device." );
1258 xkb_state_unref ( state );
1259 xkb_keymap_unref ( keymap );
1265 g_warning (
"Connection has error" );
1272 g_warning (
"Connection has error" );
1280 g_warning (
"Connection has error" );
1289 xcb_depth_t *root_depth = NULL;
1290 xcb_depth_iterator_t depth_iter;
1291 for ( depth_iter = xcb_screen_allowed_depths_iterator (
xcb->
screen ); depth_iter.rem; xcb_depth_next ( &depth_iter ) ) {
1292 xcb_depth_t *d = depth_iter.data;
1294 xcb_visualtype_iterator_t visual_iter;
1295 for ( visual_iter = xcb_depth_visuals_iterator ( d ); visual_iter.rem; xcb_visualtype_next ( &visual_iter ) ) {
1296 xcb_visualtype_t *v = visual_iter.data;
1297 if ( ( v->bits_per_rgb_value == 8 ) && ( d->depth == 32 ) && ( v->_class == XCB_VISUAL_CLASS_TRUE_COLOR ) ) {
1301 if (
xcb->
screen->root_visual == v->visual_id ) {
1308 xcb_void_cookie_t c;
1309 xcb_generic_error_t *e;
1336 return G_SOURCE_REMOVE;
1339 return G_SOURCE_REMOVE;
1342 return G_SOURCE_CONTINUE;
1350 return G_SOURCE_REMOVE;
1353 return G_SOURCE_REMOVE;
1356 return G_SOURCE_CONTINUE;
1369 if (
find_arg (
"-normal-window" ) >= 0 ) {
1372 if (
find_arg (
"-no-lazy-grab" ) >= 0 ) {
1374 g_warning (
"Failed to grab keyboard, even after %d uS.", 500 * 1000 );
1378 g_warning (
"Failed to grab mouse pointer, even after %d uS.", 100 * 1000 );
1410 g_debug (
"Cleaning up XCB and XKB" );
1422 xcb_ewmh_connection_wipe ( &(
xcb->
ewmh ) );
1425 g_water_xcb_source_free (
xcb->
source );
1435 const uint32_t MWM_HINTS_DECORATIONS = ( 1 << 1 );
1441 uint32_t decorations;
1446 struct MotifWMHints hints;
1447 hints.flags = MWM_HINTS_DECORATIONS;
1448 hints.decorations = 0;
1449 hints.functions = 0;
1450 hints.inputMode = 0;
1453 xcb_atom_t ha =
netatoms[_MOTIF_WM_HINTS];
1454 xcb_change_property (
xcb->
connection, XCB_PROP_MODE_REPLACE, window, ha, ha, 32, 5, &hints );