Example #1
0
/**
* @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);
}
Example #2
0
/** 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;
}
Example #3
0
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");
	}
}
Example #4
0
//===============================
//===============================
// 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;
   }
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
File: xtitle.c Project: mmso/xtitle
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");
}
Example #8
0
/*
 * 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();
}
Example #9
0
    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__);
      }
    }
Example #10
0
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;
}
Example #11
0
//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);
}
Example #12
0
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;
}
Example #13
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;
}
Example #14
0
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);
}
Example #15
0
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;
}
Example #16
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;
}