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;
117 xcb_get_property_cookie_t cookie;
118 xcb_get_property_reply_t *reply;
119 xcb_pixmap_t rootpixmap = XCB_NONE;
121 cookie = xcb_get_property ( c,
129 reply = xcb_get_property_reply ( c, cookie, NULL );
132 if ( xcb_get_property_value_length ( reply ) ==
sizeof ( xcb_pixmap_t ) ) {
133 memcpy ( &rootpixmap, xcb_get_property_value ( reply ),
sizeof ( xcb_pixmap_t ) );
144 if ( pm == XCB_NONE ) {
155 xcb_get_property_cookie_t c = xcb_get_property (
xcb->
connection, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX );
156 xcb_get_property_reply_t *r = xcb_get_property_reply (
xcb->
connection, c, NULL );
158 if ( xcb_get_property_value_length ( r ) > 0 ) {
160 if ( r->type ==
netatoms[UTF8_STRING] ) {
161 str = g_strndup ( xcb_get_property_value ( r ), xcb_get_property_value_length ( r ) );
163 else if ( r->type ==
netatoms[STRING] ) {
167 str = g_strdup (
"Invalid encoding." );
180 xcb_change_property (
xcb->
connection, XCB_PROP_MODE_REPLACE, w, prop, XCB_ATOM_ATOM, 32,
count, atoms );
210 xcb_randr_get_output_info_reply_t *op_reply;
211 xcb_randr_get_crtc_info_reply_t *crtc_reply;
212 xcb_randr_get_output_info_cookie_t it = xcb_randr_get_output_info (
xcb->
connection, out, XCB_CURRENT_TIME );
213 op_reply = xcb_randr_get_output_info_reply (
xcb->
connection, it, NULL );
214 if ( op_reply->crtc == XCB_NONE ) {
218 xcb_randr_get_crtc_info_cookie_t ct = xcb_randr_get_crtc_info (
xcb->
connection, op_reply->crtc, XCB_CURRENT_TIME );
219 crtc_reply = xcb_randr_get_crtc_info_reply (
xcb->
connection, ct, NULL );
225 retv->
x = crtc_reply->x;
226 retv->
y = crtc_reply->y;
227 retv->
w = crtc_reply->width;
228 retv->
h = crtc_reply->height;
230 retv->
mw = op_reply->mm_width;
231 retv->
mh = op_reply->mm_height;
233 char *tname = (
char *) xcb_randr_get_output_info_name ( op_reply );
234 int tname_len = xcb_randr_get_output_info_name_length ( op_reply );
236 retv->
name = g_malloc0 ( ( tname_len + 1 ) *
sizeof (
char ) );
237 memcpy ( retv->
name, tname, tname_len );
244 #if ( ( ( XCB_RANDR_MAJOR_VERSION >= RANDR_PREF_MAJOR_VERSION ) && ( XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION ) ) \
245 || XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION )
253 static workarea *x11_get_monitor_from_randr_monitor ( xcb_randr_monitor_info_t *
mon )
256 xcb_generic_error_t *err;
258 xcb_get_atom_name_reply_t *atom_reply = xcb_get_atom_name_reply (
xcb->
connection, anc, &err );
260 g_warning (
"Could not get RandR monitor name: X11 error code %d\n", err->error_code );
272 retv->
w =
mon->width;
273 retv->
h =
mon->height;
276 retv->
mw =
mon->width_in_millimeters;
277 retv->
mh =
mon->height_in_millimeters;
280 retv->
name = g_strdup_printf (
"%.*s", xcb_get_atom_name_name_length ( atom_reply ), xcb_get_atom_name_name ( atom_reply ) );
291 xcb_query_extension_cookie_t randr_cookie = xcb_query_extension (
xcb->
connection, strlen ( extension ), extension );
293 xcb_query_extension_reply_t *randr_reply = xcb_query_extension_reply (
xcb->
connection, randr_cookie, NULL );
295 int present = randr_reply->present;
297 free ( randr_reply );
304 xcb_xinerama_query_screens_cookie_t screens_cookie = xcb_xinerama_query_screens_unchecked (
308 xcb_xinerama_query_screens_reply_t *screens_reply = xcb_xinerama_query_screens_reply (
314 xcb_xinerama_screen_info_iterator_t screens_iterator = xcb_xinerama_query_screens_screen_info_iterator (
318 for (; screens_iterator.rem > 0; xcb_xinerama_screen_info_next ( &screens_iterator ) ) {
321 w->
x = screens_iterator.data->x_org;
322 w->
y = screens_iterator.data->y_org;
323 w->
w = screens_iterator.data->width;
324 w->
h = screens_iterator.data->height;
335 free ( screens_reply );
347 g_debug (
"Query XINERAMA for monitor layout." );
351 g_debug (
"No RANDR or Xinerama available for getting monitor layout." );
354 g_debug (
"Query RANDR for monitor layout." );
356 g_debug (
"Randr XCB api version: %d.%d.", XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION );
357 #if ( ( ( XCB_RANDR_MAJOR_VERSION == RANDR_PREF_MAJOR_VERSION ) && ( XCB_RANDR_MINOR_VERSION >= RANDR_PREF_MINOR_VERSION ) ) \
358 || XCB_RANDR_MAJOR_VERSION > RANDR_PREF_MAJOR_VERSION )
359 xcb_randr_query_version_cookie_t cversion = xcb_randr_query_version (
xcb->
connection,
361 xcb_randr_query_version_reply_t *rversion = xcb_randr_query_version_reply (
xcb->
connection, cversion, NULL );
363 g_debug (
"Found randr version: %d.%d", rversion->major_version, rversion->minor_version );
368 xcb_randr_get_monitors_reply_t *mreply = xcb_randr_get_monitors_reply (
xcb->
connection, t, NULL );
370 xcb_randr_monitor_info_iterator_t iter = xcb_randr_get_monitors_monitors_iterator ( mreply );
371 while ( iter.rem > 0 ) {
372 workarea *w = x11_get_monitor_from_randr_monitor ( iter.data );
377 xcb_randr_monitor_info_next ( &iter );
388 xcb_randr_get_screen_resources_current_reply_t *res_reply;
389 xcb_randr_get_screen_resources_current_cookie_t src;
391 res_reply = xcb_randr_get_screen_resources_current_reply (
xcb->
connection, src, NULL );
395 int mon_num = xcb_randr_get_screen_resources_current_outputs_length ( res_reply );
396 xcb_randr_output_t *ops = xcb_randr_get_screen_resources_current_outputs ( res_reply );
399 xcb_randr_get_output_primary_cookie_t pc = xcb_randr_get_output_primary (
xcb->
connection,
xcb->
screen->root );
400 xcb_randr_get_output_primary_reply_t *pc_rep = xcb_randr_get_output_primary_reply (
xcb->
connection, pc, NULL );
402 for (
int i = mon_num - 1; i >= 0; i-- ) {
407 if ( pc_rep && pc_rep->output == ops[i] ) {
422 iter->monitor_id = index++;
428 int is_term = isatty ( fileno ( stdout ) );
429 printf (
"Monitor layout:\n" );
431 printf (
"%s ID%s: %d", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->monitor_id );
432 if ( iter->primary ) {
433 printf (
" (primary)" );
437 printf (
"%s position%s: %d,%d\n", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->x, iter->y );
438 printf (
"%s size%s: %d,%d\n", ( is_term ) ?
color_bold :
"", is_term ?
color_reset :
"", iter->w, iter->h );
439 if ( iter->mw > 0 && iter->mh > 0 ) {
440 printf (
"%s size%s: %dmm,%dmm dpi: %.0f,%.0f\n",
445 iter->w * 25.4 / (
double) iter->mw,
446 iter->h * 25.4 / (
double) iter->mh
455 if ( context == NULL ) {
465 if ( context->
binary != NULL ) {
468 if ( context->
icon != NULL ) {
469 sn_launcher_context_set_icon_name (
sncontext, context->
icon );
471 if ( context->
app_id != NULL ) {
474 if ( context->
wmclass != NULL ) {
478 xcb_get_property_cookie_t c;
479 unsigned int current_desktop = 0;
482 if ( xcb_ewmh_get_current_desktop_reply ( &
xcb->
ewmh, c, ¤t_desktop, NULL ) ) {
483 sn_launcher_context_set_workspace (
sncontext, current_desktop );
488 *child_setup = (GSpawnChildSetupFunc) sn_launcher_context_setup_child_process;
515 if (
INTERSECT ( x, y, iter->x, iter->y, iter->w, iter->h ) ) {
535 xcb_query_pointer_cookie_t c = xcb_query_pointer (
xcb->
connection, root );
536 xcb_query_pointer_reply_t *r = xcb_query_pointer_reply (
xcb->
connection, c, NULL );
549 xcb_get_geometry_cookie_t c = xcb_get_geometry (
xcb->
connection,
id );
550 xcb_get_geometry_reply_t *r = xcb_get_geometry_reply (
xcb->
connection, c, NULL );
552 xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates (
xcb->
connection,
id, root, r->x, r->y );
553 xcb_translate_coordinates_reply_t *t = xcb_translate_coordinates_reply (
xcb->
connection, ct, NULL );
558 mon->
x = t->dst_x - r->x;
559 mon->
y = t->dst_y - r->y;
573 xcb_window_t active_window;
574 xcb_get_property_cookie_t awc;
576 if ( !xcb_ewmh_get_active_window_reply ( &
xcb->
ewmh, awc, &active_window, NULL ) ) {
577 g_debug (
"Failed to get active window, falling back to mouse location (-5)." );
580 xcb_query_tree_cookie_t tree_cookie = xcb_query_tree (
xcb->
connection, active_window );
581 xcb_query_tree_reply_t *tree_reply = xcb_query_tree_reply (
xcb->
connection, tree_cookie, NULL );
583 g_debug (
"Failed to get parent window, falling back to mouse location (-5)." );
587 xcb_get_geometry_cookie_t c = xcb_get_geometry (
xcb->
connection, active_window );
588 xcb_get_geometry_reply_t *r = xcb_get_geometry_reply (
xcb->
connection, c, NULL );
590 g_debug (
"Failed to get geometry of active window, falling back to mouse location (-5)." );
594 xcb_translate_coordinates_cookie_t ct = xcb_translate_coordinates (
xcb->
connection, tree_reply->parent, r->root, r->x, r->y );
595 xcb_translate_coordinates_reply_t *t = xcb_translate_coordinates_reply (
xcb->
connection, ct, NULL );
597 if ( mon_id == -2 ) {
601 mon->
x = t->dst_x - r->x;
602 mon->
y = t->dst_y - r->y;
607 else if ( mon_id == -4 ) {
614 g_debug (
"Failed to get translate position of active window, falling back to mouse location (-5)." );
625 if ( mon_id == -3 ) {
634 else if ( mon_id == -1 ) {
636 unsigned int current_desktop = 0;
637 xcb_get_property_cookie_t gcdc;
639 if ( xcb_ewmh_get_current_desktop_reply ( &
xcb->
ewmh, gcdc, ¤t_desktop, NULL ) ) {
641 xcb_ewmh_get_desktop_viewport_reply_t vp;
642 if ( xcb_ewmh_get_desktop_viewport_reply ( &
xcb->
ewmh, c, &vp, NULL ) ) {
643 if ( current_desktop < vp.desktop_viewport_len ) {
645 vp.desktop_viewport[current_desktop].y,
mon );
646 xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp );
650 g_debug (
"Viewport does not exist for current desktop: %d, falling back to mouse location (-5)", current_desktop );
652 xcb_ewmh_get_desktop_viewport_reply_wipe ( &vp );
655 g_debug (
"Failed to get viewport for current desktop: %d, falling back to mouse location (-5).", current_desktop );
659 g_debug (
"Failed to get current desktop, falling back to mouse location (-5)." );
662 else if ( mon_id == -2 || mon_id == -4 ) {
668 else if ( mon_id == -5 ) {
676 g_debug (
"Failed to find monitor, fall back to monitor showing mouse." );
694 if ( iter->primary ) {
702 xcb_drawable_t win = g_ascii_strtoll (
config.
monitor + 4, &end, 0 );
718 g_warning (
"Failed to find selected monitor." );
738 if ( xse->property == XCB_ATOM_NONE ) {
739 g_warning (
"Failed to convert selection" );
741 else if ( xse->property ==
xcb->
ewmh.UTF8_STRING ) {
743 if ( text != NULL && text[0] !=
'\0' ) {
744 unsigned int dl = strlen ( text );
746 for (
unsigned int i = 0; i < dl; i++ ) {
747 if ( text[i] ==
'\n' ) {
756 g_warning (
"Failed" );
762 switch ( x11_button )
765 *button = NK_BINDINGS_MOUSE_BUTTON_PRIMARY;
768 *button = NK_BINDINGS_MOUSE_BUTTON_SECONDARY;
771 *button = NK_BINDINGS_MOUSE_BUTTON_MIDDLE;
774 *button = NK_BINDINGS_MOUSE_BUTTON_BACK;
777 *button = NK_BINDINGS_MOUSE_BUTTON_FORWARD;
785 *button = NK_BINDINGS_MOUSE_BUTTON_EXTRA + x11_button;
793 switch ( x11_button )
799 *axis = NK_BINDINGS_SCROLL_AXIS_VERTICAL;
805 *axis = NK_BINDINGS_SCROLL_AXIS_HORIZONTAL;
819 if ( state == NULL ) {
823 switch ( event->response_type & ~0x80 )
828 case XCB_CONFIGURE_NOTIFY:
830 xcb_configure_notify_event_t *xce = (xcb_configure_notify_event_t *) event;
834 case XCB_MOTION_NOTIFY:
839 xcb_motion_notify_event_t *xme = (xcb_motion_notify_event_t *) event;
843 case XCB_BUTTON_PRESS:
845 xcb_button_press_event_t *bpe = (xcb_button_press_event_t *) event;
846 NkBindingsMouseButton button;
847 NkBindingsScrollAxis axis;
853 nk_bindings_seat_handle_button (
xcb->
bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_PRESS, bpe->time );
860 case XCB_BUTTON_RELEASE:
862 xcb_button_release_event_t *bre = (xcb_button_release_event_t *) event;
863 NkBindingsMouseButton button;
867 nk_bindings_seat_handle_button (
xcb->
bindings_seat, NULL, button, NK_BINDINGS_BUTTON_STATE_RELEASE, bre->time );
878 case XCB_SELECTION_NOTIFY:
881 case XCB_KEYMAP_NOTIFY:
883 xcb_keymap_notify_event_t *kne = (xcb_keymap_notify_event_t *) event;
884 for ( gint32 by = 0; by < 31; ++by ) {
885 for ( gint8 bi = 0; bi < 7; ++bi ) {
886 if ( kne->keys[by] & ( 1 << bi ) ) {
888 nk_bindings_seat_handle_key (
xcb->
bindings_seat, NULL, ( 8 * by + bi ) + 8, NK_BINDINGS_KEY_STATE_PRESSED );
896 xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *) event;
900 text = nk_bindings_seat_handle_key_with_modmask (
xcb->
bindings_seat, NULL, xkpe->state, xkpe->detail, NK_BINDINGS_KEY_STATE_PRESS );
901 if ( text != NULL ) {
906 case XCB_KEY_RELEASE:
908 xcb_key_release_event_t *xkre = (xcb_key_release_event_t *) event;
910 nk_bindings_seat_handle_key (
xcb->
bindings_seat, NULL, xkre->detail, NK_BINDINGS_KEY_STATE_RELEASE );
924 g_warning (
"The XCB connection to X server had a fatal error: %d", status );
926 return G_SOURCE_REMOVE;
929 g_warning (
"main_loop_x11_event_handler: ev == NULL, status == %d", status );
930 return G_SOURCE_CONTINUE;
933 uint8_t type = ev->response_type & ~0x80;
937 case XCB_XKB_MAP_NOTIFY:
942 xkb_keymap_unref ( keymap );
943 xkb_state_unref ( state );
946 case XCB_XKB_STATE_NOTIFY:
948 xcb_xkb_state_notify_event_t *ksne = (xcb_xkb_state_notify_event_t *) ev;
960 return G_SOURCE_CONTINUE;
966 return G_SOURCE_CONTINUE;
974 g_warning (
"Connection has error" );
975 exit ( EXIT_FAILURE );
977 xcb_grab_pointer_cookie_t cc = xcb_grab_pointer (
xcb->
connection, 1, w, XCB_EVENT_MASK_BUTTON_RELEASE,
978 XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, w, XCB_NONE, XCB_CURRENT_TIME );
979 xcb_grab_pointer_reply_t *r = xcb_grab_pointer_reply (
xcb->
connection, cc, NULL );
981 if ( r->status == XCB_GRAB_STATUS_SUCCESS ) {
987 if ( ( ++i ) > iters ) {
990 struct timespec del = {
994 nanosleep ( &del, NULL );
1004 g_warning (
"Connection has error" );
1005 exit ( EXIT_FAILURE );
1007 xcb_grab_keyboard_cookie_t cc = xcb_grab_keyboard (
xcb->
connection,
1008 1, w, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC,
1009 XCB_GRAB_MODE_ASYNC );
1010 xcb_grab_keyboard_reply_t *r = xcb_grab_keyboard_reply (
xcb->
connection, cc, NULL );
1012 if ( r->status == XCB_GRAB_STATUS_SUCCESS ) {
1018 if ( ( ++i ) > iters ) {
1021 struct timespec del = {
1025 nanosleep ( &del, NULL );
1041 static void error_trap_push ( G_GNUC_UNUSED SnDisplay *display, G_GNUC_UNUSED xcb_connection_t *xdisplay )
1046 static void error_trap_pop ( G_GNUC_UNUSED SnDisplay *display, xcb_connection_t *xdisplay )
1049 g_warning (
"Error trap underflow!" );
1050 exit ( EXIT_FAILURE );
1053 xcb_flush ( xdisplay );
1065 xcb_intern_atom_reply_t *r = xcb_intern_atom_reply (
xcb->
connection, cc, NULL );
1075 xcb_window_t wm_win = 0;
1076 xcb_get_property_cookie_t cc = xcb_ewmh_get_supporting_wm_check_unchecked ( &
xcb->
ewmh,
1079 if ( xcb_ewmh_get_supporting_wm_check_reply ( &
xcb->
ewmh, cc, &wm_win, NULL ) ) {
1080 xcb_ewmh_get_utf8_strings_reply_t wtitle;
1081 xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name_unchecked ( &(
xcb->
ewmh ), wm_win );
1082 if ( xcb_ewmh_get_wm_name_reply ( &(
xcb->
ewmh ), cookie, &wtitle, (
void *) 0 ) ) {
1083 if ( wtitle.strings_len > 0 ) {
1084 g_debug (
"Found window manager: %s", wtitle.strings );
1085 if ( g_strcmp0 ( wtitle.strings,
"i3" ) == 0 ) {
1089 xcb_ewmh_get_utf8_strings_reply_wipe ( &wtitle );
1098 char *display_str = (
char *) g_getenv (
"DISPLAY" );
1104 g_warning (
"Failed to open display: %s", display_str );
1109 TICK_N (
"Open Display" );
1116 xcb_generic_error_t *errors = NULL;
1117 xcb_ewmh_init_atoms_replies ( &
xcb->
ewmh, ac, &errors );
1119 g_warning (
"Failed to create EWMH atoms" );
1126 if ( xkb_x11_setup_xkb_extension (
xcb->
connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION,
1127 XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &
xcb->
xkb.
first_event, NULL ) < 0 ) {
1128 g_warning (
"cannot setup XKB extension!" );
1137 ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
1138 XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
1139 XCB_XKB_EVENT_TYPE_STATE_NOTIFY ),
1141 required_nkn_details =
1142 ( XCB_XKB_NKN_DETAIL_KEYCODES ),
1144 required_map_parts =
1145 ( XCB_XKB_MAP_PART_KEY_TYPES |
1146 XCB_XKB_MAP_PART_KEY_SYMS |
1147 XCB_XKB_MAP_PART_MODIFIER_MAP |
1148 XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
1149 XCB_XKB_MAP_PART_KEY_ACTIONS |
1150 XCB_XKB_MAP_PART_VIRTUAL_MODS |
1151 XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ),
1153 required_state_details =
1154 ( XCB_XKB_STATE_PART_MODIFIER_BASE |
1155 XCB_XKB_STATE_PART_MODIFIER_LATCH |
1156 XCB_XKB_STATE_PART_MODIFIER_LOCK |
1157 XCB_XKB_STATE_PART_GROUP_BASE |
1158 XCB_XKB_STATE_PART_GROUP_LATCH |
1159 XCB_XKB_STATE_PART_GROUP_LOCK ),
1162 static const xcb_xkb_select_events_details_t details = {
1163 .affectNewKeyboard = required_nkn_details,
1164 .newKeyboardDetails = required_nkn_details,
1165 .affectState = required_state_details,
1166 .stateDetails = required_state_details,
1177 if ( keymap == NULL ) {
1178 g_warning (
"Failed to get Keymap for current keyboard device." );
1182 if ( state == NULL ) {
1183 g_warning (
"Failed to get state object for current keyboard device." );
1188 xkb_state_unref ( state );
1189 xkb_keymap_unref ( keymap );
1195 g_warning (
"Connection has error" );
1202 g_warning (
"Connection has error" );
1210 g_warning (
"Connection has error" );
1219 xcb_depth_t *root_depth = NULL;
1220 xcb_depth_iterator_t depth_iter;
1221 for ( depth_iter = xcb_screen_allowed_depths_iterator (
xcb->
screen ); depth_iter.rem; xcb_depth_next ( &depth_iter ) ) {
1222 xcb_depth_t *d = depth_iter.data;
1224 xcb_visualtype_iterator_t visual_iter;
1225 for ( visual_iter = xcb_depth_visuals_iterator ( d ); visual_iter.rem; xcb_visualtype_next ( &visual_iter ) ) {
1226 xcb_visualtype_t *v = visual_iter.data;
1227 if ( ( v->bits_per_rgb_value == 8 ) && ( d->depth == 32 ) && ( v->_class == XCB_VISUAL_CLASS_TRUE_COLOR ) ) {
1231 if (
xcb->
screen->root_visual == v->visual_id ) {
1238 xcb_void_cookie_t c;
1239 xcb_generic_error_t *e;
1266 return G_SOURCE_REMOVE;
1269 return G_SOURCE_REMOVE;
1272 return G_SOURCE_CONTINUE;
1280 return G_SOURCE_REMOVE;
1283 return G_SOURCE_REMOVE;
1286 return G_SOURCE_CONTINUE;
1299 if (
find_arg (
"-normal-window" ) >= 0 ) {
1302 if (
find_arg (
"-no-lazy-grab" ) >= 0 ) {
1304 g_warning (
"Failed to grab keyboard, even after %d uS.", 500 * 1000 );
1308 g_warning (
"Failed to grab mouse pointer, even after %d uS.", 100 * 1000 );
1340 g_debug (
"Cleaning up XCB and XKB" );
1352 xcb_ewmh_connection_wipe ( &(
xcb->
ewmh ) );
1355 g_water_xcb_source_free (
xcb->
source );
1365 const uint32_t MWM_HINTS_DECORATIONS = ( 1 << 1 );
1371 uint32_t decorations;
1376 struct MotifWMHints hints;
1377 hints.flags = MWM_HINTS_DECORATIONS;
1378 hints.decorations = 0;
1379 hints.functions = 0;
1380 hints.inputMode = 0;
1383 xcb_atom_t ha =
netatoms[_MOTIF_WM_HINTS];
1384 xcb_change_property (
xcb->
connection, XCB_PROP_MODE_REPLACE, window, ha, ha, 32, 5, &hints );