/** * @brief Create the EWMH connection, request all of the atoms and set some * sensible defaults for them. */ void setup_ewmh(void) { xcb_ewmh_coordinates_t viewport[] = { {0, 0} }; xcb_ewmh_geometry_t workarea[] = { {0, conf.bar_bottom ? 0 : wss[cw].bar_height, screen_width, screen_height - wss[cw].bar_height} }; ewmh = calloc(1, sizeof(xcb_ewmh_connection_t)); if (!ewmh) { log_err("Unable to create ewmh connection\n"); exit(EXIT_FAILURE); } if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0) log_err("Couldn't initialise ewmh atoms"); xcb_atom_t ewmh_net_atoms[] = { ewmh->_NET_SUPPORTED, ewmh->_NET_SUPPORTING_WM_CHECK, ewmh->_NET_DESKTOP_VIEWPORT, ewmh->_NET_WM_NAME, ewmh->_NET_WM_STATE, ewmh->_NET_CLOSE_WINDOW, ewmh->_NET_WM_STATE_FULLSCREEN, ewmh->_NET_CURRENT_DESKTOP, ewmh->_NET_NUMBER_OF_DESKTOPS, ewmh->_NET_DESKTOP_GEOMETRY, ewmh->_NET_WORKAREA, ewmh->_NET_ACTIVE_WINDOW }; xcb_ewmh_set_supported(ewmh, 0, LENGTH(ewmh_net_atoms), ewmh_net_atoms); xcb_ewmh_set_supporting_wm_check(ewmh, 0, screen->root); xcb_ewmh_set_desktop_viewport(ewmh, 0, LENGTH(viewport), viewport); xcb_ewmh_set_wm_name(ewmh, 0, strlen("howm"), "howm"); xcb_ewmh_set_current_desktop(ewmh, 0, cw); xcb_ewmh_set_number_of_desktops(ewmh, 0, WORKSPACES); xcb_ewmh_set_workarea(ewmh, 0, LENGTH(workarea), workarea); xcb_ewmh_set_desktop_geometry(ewmh, 0, screen_width, screen_height); }
/** Get replies to the previously sent InternAtom request. This * function is not thread-safe but we don't care as it is only used * during initialisation * * \return true on success, false otherwise */ bool atoms_init_finalise(xcb_intern_atom_cookie_t *ewmh_cookies) { if(!xcb_ewmh_init_atoms_replies(&globalconf.ewmh, ewmh_cookies, NULL)) goto init_atoms_error; xcb_intern_atom_reply_t *atom_reply; for(int atom_n = 0; atom_n < atoms_list_len; atom_n++) { assert(atoms_list[atom_n].cookie.sequence); atom_reply = xcb_intern_atom_reply(globalconf.connection, atoms_list[atom_n].cookie, NULL); if(!atom_reply) goto init_atoms_error; *(atoms_list[atom_n].value) = atom_reply->atom; free(atom_reply); } globalconf.atoms_supported.cookie = xcb_ewmh_get_supported_unchecked(&globalconf.ewmh, globalconf.screen_nbr); return true; init_atoms_error: fatal("Cannot initialise atoms"); return false; }
void ewmh_init(void) { ewmh = malloc(sizeof(xcb_ewmh_connection_t)); if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0) { err("Can't initialize EWMH atoms.\n"); } }
//=============================== //=============================== // XCB LIBRARY FUNCTIONS //=============================== //=============================== LXCB::LXCB(){ xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(QX11Info::connection(), &EWMH); if(!xcb_ewmh_init_atoms_replies(&EWMH, cookie, NULL) ){ qDebug() << "Error with XCB atom initializations"; }else{ qDebug() << "Number of XCB screens:" << EWMH.nb_screens; } }
x_ewmh::x_ewmh(x_connection & c) : m_c(c) { m_c.attach(10, XCB_PROPERTY_NOTIFY, this); update_net_active_window(); xcb_intern_atom_cookie_t * cookie = xcb_ewmh_init_atoms(m_c(), &m_ewmh); xcb_ewmh_init_atoms_replies(&m_ewmh, cookie, NULL); }
void ewmh_init(void) { if (!(cfg.ewmh = calloc(1, sizeof(xcb_ewmh_connection_t)))) err("failed to allocate ewmh object\n"); xcb_intern_atom_cookie_t *cookie = xcb_ewmh_init_atoms(cfg.conn, cfg.ewmh); xcb_ewmh_init_atoms_replies(cfg.ewmh, cookie, (void *)0); }
void setup(void) { dpy = xcb_connect(NULL, &default_screen); if (xcb_connection_has_error(dpy)) err("Can't open display.\n"); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; if (screen == NULL) err("Can't acquire screen.\n"); root = screen->root; ewmh = malloc(sizeof(xcb_ewmh_connection_t)); if (xcb_ewmh_init_atoms_replies(ewmh, xcb_ewmh_init_atoms(dpy, ewmh), NULL) == 0) err("Can't initialize EWMH atoms.\n"); }
/* * Initialize yabar */ void ya_init() { signal(SIGTERM, ya_sighandler); signal(SIGINT, ya_sighandler); signal(SIGKILL, ya_sighandler); signal(SIGHUP, ya_sighandler); ya.depth = 32; ya.c = xcb_connect(NULL, NULL); ya.scr = xcb_setup_roots_iterator(xcb_get_setup(ya.c)).data; ya.visualtype = ya_get_visualtype(); if (ya.visualtype == NULL) { // if depth=32 not found, fallback to depth=24 ya.depth = 24; ya.visualtype = ya_get_visualtype(); } ya.colormap = xcb_generate_id(ya.c); xcb_create_colormap(ya.c, XCB_COLORMAP_ALLOC_NONE, ya.colormap, ya.scr->root, ya.visualtype->visual_id); const xcb_query_extension_reply_t *ya_reply; ya_reply = xcb_get_extension_data(ya.c, &xcb_randr_id); if (ya_reply->present) { ya.gen_flag |= GEN_RANDR; ya_init_randr(); } #ifdef YA_INTERNAL_EWMH ya.ewmh = malloc(sizeof(xcb_ewmh_connection_t)); if (xcb_ewmh_init_atoms_replies(ya.ewmh, xcb_ewmh_init_atoms(ya.c, ya.ewmh), NULL)==0) { fprintf(stderr, "Cannot use EWMH\n"); //Should exit program or not? //To be decided. } ya.lstwin = XCB_NONE; uint32_t evm = XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes(ya.c, ya.curwin, XCB_CW_EVENT_MASK, &evm); xcb_change_window_attributes(ya.c, ya.scr->root, XCB_CW_EVENT_MASK, &evm); xcb_get_property_cookie_t prop_ck = xcb_ewmh_get_active_window(ya.ewmh, 0); xcb_ewmh_get_active_window_reply(ya.ewmh, prop_ck, &ya.curwin, NULL); xcb_get_property_cookie_t ws_ck = xcb_ewmh_get_current_desktop(ya.ewmh, 0); xcb_ewmh_get_current_desktop_reply(ya.ewmh, ws_ck, &ya.curws, NULL); //fprintf(stderr, "WINNN = %x DESK= %x\n", ya.curwin, ya.curws); #endif //YA_INTERNAL_EWMH ya_config_parse(); }
Ewmh(xcb_connection_t * const c) { m_ewmh = std::shared_ptr<xcb_ewmh_connection_t>(new xcb_ewmh_connection_t, [](xcb_ewmh_connection_t * ec) { xcb_ewmh_connection_wipe(ec); std::free(ec); }); xcb_intern_atom_cookie_t * cookies = xcb_ewmh_init_atoms(c, m_ewmh.get()); if (cookies) { xcb_generic_error_t * error = NULL; xcb_ewmh_init_atoms_replies(m_ewmh.get(), cookies, &error); if (error) { std::free(error); std::free(cookies); throw std::runtime_error(__PRETTY_FUNCTION__); } } else { throw std::runtime_error(__PRETTY_FUNCTION__); } }
int main ( int argc, char *argv[] ) { TIMINGS_START (); cmd_set_arguments ( argc, argv ); // Version if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) { #ifdef GIT_VERSION fprintf ( stdout, "Version: "GIT_VERSION "\n" ); #else fprintf ( stdout, "Version: "VERSION "\n" ); #endif exit ( EXIT_SUCCESS ); } // Detect if we are in dmenu mode. // This has two possible causes. // 1 the user specifies it on the command-line. if ( find_arg ( "-dmenu" ) >= 0 ) { dmenu_mode = TRUE; } // 2 the binary that executed is called dmenu (e.g. symlink to rofi) else{ // Get the base name of the executable called. char *base_name = g_path_get_basename ( argv[0] ); const char * const dmenu_str = "dmenu"; dmenu_mode = ( strcmp ( base_name, dmenu_str ) == 0 ); // Free the basename for dmenu detection. g_free ( base_name ); } TICK (); // Get the path to the cache dir. cache_dir = g_get_user_cache_dir (); // Create pid file path. const char *path = g_get_user_runtime_dir (); if ( path ) { pidfile = g_build_filename ( path, "rofi.pid", NULL ); } config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" ); if ( find_arg ( "-config" ) < 0 ) { const char *cpath = g_get_user_config_dir (); if ( cpath ) { config_path = g_build_filename ( cpath, "rofi", "config", NULL ); } } else { char *c = NULL; find_arg_str ( "-config", &c ); config_path = rofi_expand_path ( c ); } TICK (); // Register cleanup function. atexit ( cleanup ); TICK (); // Get DISPLAY, first env, then argument. char *display_str = getenv ( "DISPLAY" ); find_arg_str ( "-display", &display_str ); if ( setlocale ( LC_ALL, "" ) == NULL ) { fprintf ( stderr, "Failed to set locale.\n" ); return EXIT_FAILURE; } xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Failed to open display: %s", display_str ); return EXIT_FAILURE; } TICK_N ( "Open Display" ); xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr ); xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh ); xcb_generic_error_t *errors = NULL; xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors ); if ( errors ) { fprintf ( stderr, "Failed to create EWMH atoms\n" ); free ( errors ); } if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xkb.first_event, NULL ) < 0 ) { fprintf ( stderr, "cannot setup XKB extension!\n" ); return EXIT_FAILURE; } xkb.context = xkb_context_new ( XKB_CONTEXT_NO_FLAGS ); if ( xkb.context == NULL ) { fprintf ( stderr, "cannot create XKB context!\n" ); return EXIT_FAILURE; } xkb.xcb_connection = xcb->connection; xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection ); enum { required_events = ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY ), required_nkn_details = ( XCB_XKB_NKN_DETAIL_KEYCODES ), required_map_parts = ( XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ), required_state_details = ( XCB_XKB_STATE_PART_MODIFIER_BASE | XCB_XKB_STATE_PART_MODIFIER_LATCH | XCB_XKB_STATE_PART_MODIFIER_LOCK | XCB_XKB_STATE_PART_GROUP_BASE | XCB_XKB_STATE_PART_GROUP_LATCH | XCB_XKB_STATE_PART_GROUP_LOCK ), }; static const xcb_xkb_select_events_details_t details = { .affectNewKeyboard = required_nkn_details, .newKeyboardDetails = required_nkn_details, .affectState = required_state_details, .stateDetails = required_state_details, }; xcb_xkb_select_events ( xcb->connection, xkb.device_id, required_events, /* affectWhich */ 0, /* clear */ required_events, /* selectAll */ required_map_parts, /* affectMap */ required_map_parts, /* map */ &details ); xkb.keymap = xkb_x11_keymap_new_from_device ( xkb.context, xcb->connection, xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS ); if ( xkb.keymap == NULL ) { fprintf ( stderr, "Failed to get Keymap for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.state = xkb_x11_state_new_from_device ( xkb.keymap, xcb->connection, xkb.device_id ); if ( xkb.state == NULL ) { fprintf ( stderr, "Failed to get state object for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.compose.table = xkb_compose_table_new_from_locale ( xkb.context, setlocale ( LC_CTYPE, NULL ), 0 ); if ( xkb.compose.table != NULL ) { xkb.compose.state = xkb_compose_state_new ( xkb.compose.table, 0 ); } else { fprintf ( stderr, "Failed to get keyboard compose table. Trying to limp on.\n" ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } x11_setup ( &xkb ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } const xcb_query_extension_reply_t *er = xcb_get_extension_data ( xcb->connection, &xcb_xinerama_id ); if ( er ) { if ( er->present ) { xcb_xinerama_is_active_cookie_t is_active_req = xcb_xinerama_is_active ( xcb->connection ); xcb_xinerama_is_active_reply_t *is_active = xcb_xinerama_is_active_reply ( xcb->connection, is_active_req, NULL ); xcb->has_xinerama = is_active->state; free ( is_active ); } } main_loop = g_main_loop_new ( NULL, FALSE ); TICK_N ( "Setup mainloop" ); // startup not. xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } if ( xcb->sndisplay != NULL ) { xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } TICK_N ( "Startup Notification" ); // Initialize Xresources subsystem. config_parse_xresource_init (); TICK_N ( "Initialize Xresources system" ); // Setup keybinding setup_abe (); TICK_N ( "Setup abe" ); if ( find_arg ( "-no-config" ) < 0 ) { load_configuration ( ); } if ( !dmenu_mode ) { // setup_modi setup_modi (); } if ( find_arg ( "-no-config" ) < 0 ) { // Reload for dynamic part. load_configuration_dynamic ( ); } // Dump. // catch help request if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { help ( argc, argv ); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources" ) >= 0 ) { config_parse_xresource_dump (); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources-theme" ) >= 0 ) { config_parse_xresources_theme_dump (); exit ( EXIT_SUCCESS ); } main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, NULL, NULL ); TICK_N ( "X11 Setup " ); rofi_view_workers_initialize (); // Setup signal handling sources. // SIGINT g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL ); g_idle_add ( startup, NULL ); // Start mainloop. g_main_loop_run ( main_loop ); return return_code; }
//appContext X11AppContext::X11AppContext() { //XInitThreads(); //todo, make this optional impl_ = std::make_unique<Impl>(); xDisplay_ = ::XOpenDisplay(nullptr); if(!xDisplay_) throw std::runtime_error("ny::X11AppContext: could not connect to X Server"); xDefaultScreenNumber_ = ::XDefaultScreen(xDisplay_); xConnection_ = ::XGetXCBConnection(xDisplay_); if(!xConnection_ || xcb_connection_has_error(xConnection_)) throw std::runtime_error("ny::X11AppContext: unable to get xcb connection"); impl_->errorCategory = {*xDisplay_, *xConnection_}; auto ewmhCookie = xcb_ewmh_init_atoms(&xConnection(), &ewmhConnection()); //query information auto iter = xcb_setup_roots_iterator(xcb_get_setup(&xConnection())); for(auto i = 0; iter.rem; ++i, xcb_screen_next(&iter)) { if(i == xDefaultScreenNumber_) { xDefaultScreen_ = iter.data; break; } } //This must be called because xcb is used to access the event queue ::XSetEventQueueOwner(xDisplay_, XCBOwnsEventQueue); //Generate an x dummy window that can e.g. be used for selections //This window remains invisible, i.e. it is not begin mapped xDummyWindow_ = xcb_generate_id(xConnection_); auto cookie = xcb_create_window_checked(xConnection_, XCB_COPY_FROM_PARENT, xDummyWindow_, xDefaultScreen_->root, 0, 0, 50, 50, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, 0, nullptr); errorCategory().checkThrow(cookie, "ny::X11AppContext: create_window for dummy window failed"); //Load all default required atoms auto& atoms = impl_->atoms; struct { xcb_atom_t& atom; const char* name; } atomNames[] = { {atoms.xdndEnter, "XdndEnter"}, {atoms.xdndPosition, "XdndPosition"}, {atoms.xdndStatus, "XdndStatus"}, {atoms.xdndTypeList, "XdndTypeList"}, {atoms.xdndActionCopy, "XdndActionCopy"}, {atoms.xdndActionMove, "XdndActionMove"}, {atoms.xdndActionAsk, "XdndActionAsk"}, {atoms.xdndDrop, "XdndDrop"}, {atoms.xdndLeave, "XdndLeave"}, {atoms.xdndFinished, "XdndFinished"}, {atoms.xdndSelection, "XdndSelection"}, {atoms.xdndProxy, "XdndProxy"}, {atoms.xdndAware, "XdndAware"}, {atoms.clipboard, "CLIPBOARD"}, {atoms.targets, "TARGETS"}, {atoms.text, "TEXT"}, {atoms.utf8string, "UTF8_STRING"}, {atoms.fileName, "FILE_NAME"}, {atoms.wmDeleteWindow, "WM_DELETE_WINDOW"}, {atoms.motifWmHints, "_MOTIF_WM_HINTS"}, {atoms.mime.textPlain, "text/plain"}, {atoms.mime.textPlainUtf8, "text/plain;charset=utf8"}, {atoms.mime.textUriList, "text/uri-list"}, {atoms.mime.imageJpeg, "image/jpeg"}, {atoms.mime.imageGif, "image/gif"}, {atoms.mime.imagePng, "image/png"}, {atoms.mime.imageBmp, "image/bmp"}, {atoms.mime.imageData, "image/x-ny-data"}, {atoms.mime.timePoint, "x-application/ny-time-point"}, {atoms.mime.timeDuration, "x-application/ny-time-duration"}, {atoms.mime.raw, "x-application/ny-raw-buffer"}, }; auto length = sizeof(atomNames) / sizeof(atomNames[0]); std::vector<xcb_intern_atom_cookie_t> atomCookies; atomCookies.reserve(length); for(auto& name : atomNames) atomCookies.push_back(xcb_intern_atom(xConnection_, 0, std::strlen(name.name), name.name)); for(auto i = 0u; i < atomCookies.size(); ++i) { xcb_generic_error_t* error {}; auto reply = xcb_intern_atom_reply(xConnection_, atomCookies[i], &error); if(reply) { atomNames[i].atom = reply->atom; free(reply); continue; } else if(error) { auto msg = x11::errorMessage(xDisplay(), error->error_code); free(error); warning("ny::X11AppContext: Failed to load atom ", atomNames[i].name, ": ", msg); } } //ewmh xcb_ewmh_init_atoms_replies(&ewmhConnection(), ewmhCookie, nullptr); //input keyboardContext_ = std::make_unique<X11KeyboardContext>(*this); mouseContext_ = std::make_unique<X11MouseContext>(*this); }
int _xcwm_atoms_init(xcwm_context_t *context) { xcb_intern_atom_cookie_t *atom_cookies; xcb_generic_error_t *error; /* Initialization for the xcb_ewmh connection and EWMH atoms */ atom_cookies = xcb_ewmh_init_atoms(context->conn, &context->atoms.ewmh_conn); if (!xcb_ewmh_init_atoms_replies(&context->atoms.ewmh_conn, atom_cookies, &error)) { return error->major_code;; } /* Set the _NET_SUPPORTED atom for this context * Most of these are defined as MUSTs in the * EWMH standards for window managers. * NOTE: Starting with only a limited set of _NET_WM_STATE. This * may be expanded. */ xcb_atom_t supported[] = { context->atoms.ewmh_conn.WM_PROTOCOLS, context->atoms.ewmh_conn._NET_SUPPORTED, context->atoms.ewmh_conn._NET_SUPPORTING_WM_CHECK, context->atoms.ewmh_conn._NET_CLOSE_WINDOW, context->atoms.ewmh_conn._NET_WM_NAME, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_TOOLBAR, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_MENU, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_UTILITY, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_SPLASH, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_DIALOG, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_DROPDOWN_MENU, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_POPUP_MENU, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_TOOLTIP, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_NOTIFICATION, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_COMBO, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_DND, context->atoms.ewmh_conn._NET_WM_WINDOW_TYPE_NORMAL, context->atoms.ewmh_conn._NET_WM_STATE, context->atoms.ewmh_conn._NET_WM_STATE_MODAL, context->atoms.ewmh_conn._NET_WM_STATE_HIDDEN }; xcb_ewmh_set_supported(&context->atoms.ewmh_conn, context->conn_screen, 21, /* Length of supported[] */ supported); /* Used erroneously instead of _NET_WM_WINDOW_TYPE_SPLASH by some applications */ context->atoms.net_wm_window_type_splashscreen = _xcwm_atom_get(context, "_NET_WM_WINDOW_TYPE_SPLASHSCREEN"); /* Get the ICCCM atoms we need that are not included in the * xcb_ewmh_connection_t. */ _xcwm_atom_register(context, "_NET_WM_NAME", set_window_name, XCWM_EVENT_WINDOW_NAME); _xcwm_atom_register(context, "WM_NAME", set_window_name, XCWM_EVENT_WINDOW_NAME); _xcwm_atom_register(context, "_NET_WM_WINDOW_TYPE", setup_window_type, XCWM_EVENT_WINDOW_APPEARANCE); _xcwm_atom_register(context, "WM_NORMAL_HINTS", set_window_size_hints, 0); _xcwm_atom_register(context, "_NET_WM_WINDOW_OPACITY", set_window_opacity, XCWM_EVENT_WINDOW_APPEARANCE); /* WM_DELETE_WINDOW atom */ context->atoms.wm_delete_window_atom = _xcwm_atom_get(context, "WM_DELETE_WINDOW"); if (!check_wm_cm_owner(context)) { return XCB_WINDOW; } create_wm_cm_window(context); /* WM_STATE atom */ context->atoms.wm_state_atom = _xcwm_atom_get(context, "WM_STATE"); return 0; }
static gboolean _eventd_nd_xcb_start(EventdNdBackendContext *self, const gchar *target) { gint r; gchar *h; gint d; r = xcb_parse_display(target, &h, &d, NULL); if ( r == 0 ) return FALSE; free(h); const xcb_query_extension_reply_t *extension_query; gint screen; self->source = g_water_xcb_source_new(NULL, target, &screen, _eventd_nd_xcb_events_callback, self, NULL); if ( self->source == NULL ) { g_warning("Couldn't initialize X connection for '%s'", target); return FALSE; } self->xcb_connection = g_water_xcb_source_get_connection(self->source); self->screen_number = screen; self->screen = xcb_aux_get_screen(self->xcb_connection, screen); self->bubbles = g_hash_table_new(NULL, NULL); if ( self->follow_focus != EVENTD_ND_XCB_FOLLOW_FOCUS_NONE ) { guint32 mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes(self->xcb_connection, self->screen->root, XCB_CW_EVENT_MASK, mask); } xcb_intern_atom_cookie_t *ac; ac = xcb_ewmh_init_atoms(self->xcb_connection, &self->ewmh); xcb_ewmh_init_atoms_replies(&self->ewmh, ac, NULL); extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_randr_id); if ( ! extension_query->present ) g_warning("No RandR extension"); else { self->randr = TRUE; self->randr_event_base = extension_query->first_event; xcb_randr_select_input(self->xcb_connection, self->screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); } self->custom_map = _eventd_nd_xcb_get_colormap(self); if ( self->custom_map ) { /* We have a 32bit color map, try to support compositing */ xcb_get_selection_owner_cookie_t oc; xcb_window_t owner; oc = xcb_ewmh_get_wm_cm_owner(&self->ewmh, self->screen_number); self->compositing = xcb_ewmh_get_wm_cm_owner_reply(&self->ewmh, oc, &owner, NULL) && ( owner != XCB_WINDOW_NONE ); extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_xfixes_id); if ( ! extension_query->present ) g_warning("No XFixes extension"); else { xcb_xfixes_query_version_cookie_t vc; xcb_xfixes_query_version_reply_t *r; vc = xcb_xfixes_query_version(self->xcb_connection, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); r = xcb_xfixes_query_version_reply(self->xcb_connection, vc, NULL); if ( r == NULL ) g_warning("Cannot get XFixes version"); else { self->xfixes = TRUE; self->xfixes_event_base = extension_query->first_event; xcb_xfixes_select_selection_input_checked(self->xcb_connection, self->screen->root, self->ewmh._NET_WM_CM_Sn[self->screen_number], XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE); } } } extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_shape_id); if ( ! extension_query->present ) g_warning("No Shape extension"); else self->shape = TRUE; xcb_flush(self->xcb_connection); _eventd_nd_xcb_check_geometry(self); return TRUE; }
void* widget_main (struct widget *widget) { unsigned short i; int xcb_fd; int screen_nbr = 0; xcb_connection_t *conn = xcb_connect(NULL, NULL); xcb_ewmh_connection_t *ewmh = malloc(sizeof(xcb_ewmh_connection_t)); struct epoll_event xcb_event; widget_epoll_init(widget); if (xcb_connection_has_error(conn)) { LOG_ERR("could not connect to display %s", getenv("DISPLAY")); goto cleanup; } xcb_intern_atom_cookie_t *ewmh_cookie = xcb_ewmh_init_atoms(conn, ewmh); xcb_ewmh_init_atoms_replies(ewmh, ewmh_cookie, NULL); uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_generic_event_t *evt; xcb_generic_error_t *err = xcb_request_check(ewmh->connection, xcb_change_window_attributes_checked(ewmh->connection, ewmh->screens[screen_nbr]->root, XCB_CW_EVENT_MASK, values)); if (err != NULL) { LOG_ERR("could not request EWMH property change notifications"); goto cleanup; } xcb_fd = xcb_get_file_descriptor(ewmh->connection); xcb_event.data.fd = xcb_fd; xcb_event.events = EPOLLIN | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, xcb_fd, &xcb_event) == -1) { LOG_ERR("failed to add fd to epoll instance: %s", strerror(errno)); return 0; } widget_update(widget, ewmh, screen_nbr); while (true) { while ((nfds = epoll_wait(efd, events, MAX_EVENTS, -1)) > 0) { for (i = 0; i < nfds; i++) { if (events[i].data.fd == widget->bar->efd) { goto cleanup; } } while ((evt = xcb_poll_for_event(ewmh->connection)) != NULL) { xcb_property_notify_event_t *pne; switch (XCB_EVENT_RESPONSE_TYPE(evt)) { case XCB_PROPERTY_NOTIFY: pne = (xcb_property_notify_event_t*)evt; if (pne->atom == ewmh->_NET_DESKTOP_NAMES) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_NUMBER_OF_DESKTOPS) { widget_update(widget, ewmh, screen_nbr); } else if (pne->atom == ewmh->_NET_CURRENT_DESKTOP) { widget_update(widget, ewmh, screen_nbr); } default: break; } free(evt); } } } cleanup: if (ewmh != NULL) { xcb_ewmh_connection_wipe(ewmh); } if (conn != NULL) { xcb_disconnect(conn); } widget_epoll_cleanup(widget); widget_clean_exit(widget); }
static int CreateWindowAndContext( Display* display, xcb_connection_t* connection, int default_screen, xcb_screen_t* screen, int width, int height, ae3d::WindowCreateFlags flags ) { GLXFBConfig* fb_configs = nullptr; int num_fb_configs = 0; fb_configs = glXGetFBConfigs( display, default_screen, &num_fb_configs ); if (!fb_configs || num_fb_configs == 0) { std::cerr << "glXGetFBConfigs failed." << std::endl; return -1; } /* Select first framebuffer config and query visualID */ int visualID = 0; GLXFBConfig fb_config = fb_configs[ 0 ]; glXGetFBConfigAttrib( display, fb_config, GLX_VISUAL_ID, &visualID ); GLXContext context = glXCreateNewContext( display, fb_config, GLX_RGBA_TYPE, nullptr, True ); if (!context) { std::cerr << "glXCreateNewContext failed." << std::endl; return -1; } /* Create XID's for colormap and window */ xcb_colormap_t colormap = xcb_generate_id( connection ); WindowGlobal::window = xcb_generate_id( connection ); WindowGlobal::windowWidth = width == 0 ? screen->width_in_pixels : width; WindowGlobal::windowHeight = height == 0 ? screen->height_in_pixels : height; xcb_create_colormap( connection, XCB_COLORMAP_ALLOC_NONE, colormap, screen->root, visualID ); const uint32_t eventmask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION; const uint32_t valuelist[] = { eventmask, colormap, 0 }; const uint32_t valuemask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; xcb_create_window( connection, XCB_COPY_FROM_PARENT, WindowGlobal::window, screen->root, 0, 0, WindowGlobal::windowWidth, WindowGlobal::windowHeight, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visualID, valuemask, valuelist ); xcb_map_window( connection, WindowGlobal::window ); if ((flags & ae3d::WindowCreateFlags::Fullscreen) != 0) { WindowGlobal::EWMHCookie = xcb_ewmh_init_atoms( WindowGlobal::connection, &WindowGlobal::EWMH ); if (!xcb_ewmh_init_atoms_replies( &WindowGlobal::EWMH, WindowGlobal::EWMHCookie, nullptr )) { std::cout << "Fullscreen not supported." << std::endl; } xcb_ewmh_request_change_wm_state( &WindowGlobal::EWMH, XDefaultScreen( display ), WindowGlobal::window, XCB_EWMH_WM_STATE_ADD, WindowGlobal::EWMH._NET_WM_STATE_FULLSCREEN, 0, XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL ); xcb_ewmh_request_change_active_window( &WindowGlobal::EWMH, XDefaultScreen( display ), WindowGlobal::window, XCB_EWMH_CLIENT_SOURCE_TYPE_NORMAL, XCB_CURRENT_TIME, XCB_WINDOW_NONE ); xcb_generic_error_t* error; xcb_get_window_attributes_reply_t* reply = xcb_get_window_attributes_reply( WindowGlobal::connection, xcb_get_window_attributes( WindowGlobal::connection, WindowGlobal::window ), &error ); if (!reply) { std::cerr << "Full screen reply failed" << std::endl; } } //xcb_change_property( WindowGlobal::connection, XCB_PROP_MODE_REPLACE, WindowGlobal::window, WindowGlobal::EWMH._NET_WM_STATE, XCB_ATOM, 32, 1, &(WindowGlobal::EWMH._NET_WM_STATE_FULLSCREEN)); // End test GLXWindow glxwindow = glXCreateWindow( display, fb_config, WindowGlobal::window, nullptr ); if (!glxwindow) { xcb_destroy_window( connection, WindowGlobal::window ); glXDestroyContext( display, context ); std::cerr << "glXDestroyContext failed" << std::endl; return -1; } WindowGlobal::drawable = glxwindow; if (!glXMakeContextCurrent( display, WindowGlobal::drawable, WindowGlobal::drawable, context )) { xcb_destroy_window( connection, WindowGlobal::window ); glXDestroyContext( display, context ); std::cerr << "glXMakeContextCurrent failed" << std::endl; return -1; } return 0; }
Compositor::Compositor() : connection_(QX11Info::connection()), root_(QX11Info::appRootWindow()), damageExt_(xcb_get_extension_data(connection_, &xcb_damage_id)), initFinished_(false) { qRegisterMetaType<ClientWindow *>(); Q_ASSERT(QCoreApplication::instance()); QCoreApplication::instance()->installNativeEventFilter(this); auto ewmhCookie = xcb_ewmh_init_atoms(connection_, &ewmh_); if (!xcb_ewmh_init_atoms_replies(&ewmh_, ewmhCookie, Q_NULLPTR)) { qFatal("Cannot init EWMH"); } auto wmCmCookie = xcb_ewmh_get_wm_cm_owner_unchecked(&ewmh_, QX11Info::appScreen()); xcb_window_t wmCmOwnerWin = XCB_NONE; if (!xcb_ewmh_get_wm_cm_owner_reply(&ewmh_, wmCmCookie, &wmCmOwnerWin, Q_NULLPTR)) { qFatal("Cannot check _NET_WM_CM_Sn"); } if (wmCmOwnerWin) { qFatal("Another compositing manager is already running"); } auto attributesCookie = xcb_get_window_attributes_unchecked(connection_, root_); auto damageQueryVersionCookie = xcb_damage_query_version_unchecked(connection_, 1, 1); auto overlayWindowCookie = xcb_composite_get_overlay_window_unchecked(connection_, root_); auto attributes = xcbReply(xcb_get_window_attributes_reply(connection_, attributesCookie, Q_NULLPTR)); if (!attributes) { qFatal("Cannot get root window attributes"); } auto newEventMask = attributes->your_event_mask | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes(connection_, root_, XCB_CW_EVENT_MASK, &newEventMask); auto treeCookie = xcb_query_tree_unchecked(connection_, root_); auto rootGeometryCookie = xcb_get_geometry_unchecked(connection_, root_); auto damageVersion = xcbReply(xcb_damage_query_version_reply(connection_, damageQueryVersionCookie, Q_NULLPTR)); if (!damageVersion) { qFatal("Cannot query version of Damage extension"); } auto overlayWindow = xcbReply(xcb_composite_get_overlay_window_reply(connection_, overlayWindowCookie, Q_NULLPTR)); if (!overlayWindow) { qFatal("Cannot get overlay window"); } overlayWindow_.reset(QWindow::fromWinId(overlayWindow->overlay_win)); auto region = xcb_generate_id(connection_); xcb_xfixes_create_region(connection_, region, 0, Q_NULLPTR); xcb_xfixes_set_window_shape_region(connection_, overlayWindow->overlay_win, XCB_SHAPE_SK_INPUT, 0, 0, region); xcb_xfixes_destroy_region(connection_, region); xcb_composite_redirect_subwindows(connection_, root_, XCB_COMPOSITE_REDIRECT_MANUAL); auto rootGeometry = xcbReply(xcb_get_geometry_reply(connection_, rootGeometryCookie, Q_NULLPTR)); if (!rootGeometry) { qFatal("Cannot query root window geometry"); } rootGeometry_ = QRect(rootGeometry->x, rootGeometry->y, rootGeometry->width, rootGeometry->height); auto tree = xcbReply(xcb_query_tree_reply(connection_, treeCookie, Q_NULLPTR)); if (!tree) { qFatal("Cannot query window tree"); } auto children = xcb_query_tree_children(tree.get()); for (int i = 0; i < xcb_query_tree_children_length(tree.get()); i++) { addChildWindow(children[i]); } updateActiveWindow(); initFinished_ = true; }