Exemple #1
0
/** Check whether a composite manager is running.
 * \return True if such a manager is running.
 */
static bool
composite_manager_running(void)
{
    xcb_intern_atom_reply_t *atom_r;
    xcb_get_selection_owner_reply_t *selection_r;
    char *atom_name;
    bool result;

    if(!(atom_name = xcb_atom_name_by_screen("_NET_WM_CM", globalconf.default_screen)))
    {
        warn("error getting composite manager atom");
        return false;
    }

    atom_r = xcb_intern_atom_reply(globalconf.connection,
                                   xcb_intern_atom_unchecked(globalconf.connection, false,
                                                             a_strlen(atom_name), atom_name),
                                   NULL);
    p_delete(&atom_name);
    if(!atom_r)
        return false;

    selection_r = xcb_get_selection_owner_reply(globalconf.connection,
                                                xcb_get_selection_owner_unchecked(globalconf.connection,
                                                                                  atom_r->atom),
                                                NULL);
    p_delete(&atom_r);

    result = selection_r != NULL && selection_r->owner != XCB_NONE;
    p_delete(&selection_r);

    return result;
}
Exemple #2
0
void
atoms_init(xcb_connection_t *conn)
{
    unsigned int i;
    xcb_intern_atom_cookie_t cs[countof(ATOM_LIST)];
    xcb_intern_atom_reply_t *r;

    /* Create the atom and get the reply in a XCB way (e.g. send all
     * the requests at the same time and then get the replies) */
    for(i = 0; i < countof(ATOM_LIST); i++)
	cs[i] = xcb_intern_atom_unchecked(conn,
					  false,
					  a_strlen(ATOM_LIST[i].name),
					  ATOM_LIST[i].name);

    for(i = 0; i < countof(ATOM_LIST); i++)
    {
	if(!(r = xcb_intern_atom_reply(conn, cs[i], NULL)))
	    /* An error occured, get reply for next atom */
	    continue;

	*ATOM_LIST[i].atom = r->atom;
        p_delete(&r);
    }
}
EAPI void
ecore_x_atoms_get(const char  **names,
                  int           num,
                  Ecore_X_Atom *atoms)
{
   xcb_intern_atom_cookie_t cookies[num];
   int i = 0;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   CHECK_XCB_CONN;

   for (i = 0; i < num; i++)
     {
        cookies[i] =
          xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
                                    strlen(names[i]), names[i]);
     }
   for (i = 0; i < num; i++)
     {
        xcb_intern_atom_reply_t *reply = NULL;

        if (!(reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], 0)))
          continue;
        atoms[i] = reply->atom;
        free(reply);
     }
}
Exemple #4
0
/** Remove systray information in X.
 */
void
systray_cleanup(void)
{
    xcb_intern_atom_reply_t *atom_systray_r;
    char *atom_name;

    if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen))
       || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection,
                                                   xcb_intern_atom_unchecked(globalconf.connection,
                                                                             false,
                                                                             a_strlen(atom_name),
                                                                             atom_name),
                                                   NULL)))
    {
        warn("error getting systray atom");
        p_delete(&atom_name);
        return;
    }

    p_delete(&atom_name);

    xcb_set_selection_owner(globalconf.connection,
                            XCB_NONE,
                            atom_systray_r->atom,
                            XCB_CURRENT_TIME);

    p_delete(&atom_systray_r);

    xcb_unmap_window(globalconf.connection,
                     globalconf.systray.window);
}
Exemple #5
0
/** Initialize systray information in X.
 */
void
systray_init(void)
{
    xcb_intern_atom_cookie_t atom_systray_q;
    xcb_intern_atom_reply_t *atom_systray_r;
    char *atom_name;
    xcb_screen_t *xscreen = globalconf.screen;

    globalconf.systray.window = xcb_generate_id(globalconf.connection);
    xcb_create_window(globalconf.connection, xscreen->root_depth,
                      globalconf.systray.window,
                      xscreen->root,
                      -1, -1, 1, 1, 0,
                      XCB_COPY_FROM_PARENT, xscreen->root_visual,
                      0, NULL);

    atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen);
    if(!atom_name)
        fatal("error getting systray atom name");

    atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false,
                                               a_strlen(atom_name), atom_name);

    p_delete(&atom_name);

    atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL);
    if(!atom_systray_r)
        fatal("error getting systray atom");

    globalconf.systray.atom = atom_systray_r->atom;
    p_delete(&atom_systray_r);
}
bool KWinKScreenHelperEffect::checkValid()
{
#ifdef HAVE_XCB
    if (QX11Info::isPlatformX11()) {
        QScopedPointer<xcb_list_properties_reply_t, QScopedPointerPodDeleter> propsReply(xcb_list_properties_reply(QX11Info::connection(),
            xcb_list_properties_unchecked(QX11Info::connection(), QX11Info::appRootWindow()),
        NULL));
        QScopedPointer<xcb_intern_atom_reply_t, QScopedPointerPodDeleter> atomReply(xcb_intern_atom_reply(QX11Info::connection(),
            xcb_intern_atom_unchecked(QX11Info::connection(), false, 25, "_KDE_KWIN_KSCREEN_SUPPORT"),
        NULL));

        if (propsReply.isNull() || atomReply.isNull()) {
            return false;
        }

        auto *atoms = xcb_list_properties_atoms(propsReply.data());
        for (int i = 0; i < propsReply->atoms_len; ++i) {
            if (atoms[i] == atomReply->atom) {
                m_atom = atomReply->atom;
                return true;
            }
        }

        m_atom = 0;
        return false;
    }
#endif
    return false;
}
xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
{
    if (m_sysTraySelectionAtom == XCB_ATOM_NONE) {
        const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1();
        xcb_intern_atom_cookie_t intern_c =
            xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray);

        xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0);

        if (!intern_r)
            return XCB_WINDOW_NONE;

        m_sysTraySelectionAtom = intern_r->atom;
        free(intern_r);
    }

    xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom);
    xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0);

    if (!sel_owner_r)
        return XCB_WINDOW_NONE;

    xcb_window_t selection_window = sel_owner_r->owner;
    free(sel_owner_r);

    return selection_window;
}
/** Remove systray information in X.
 * \param phys_screen Physical screen.
 */
void
systray_cleanup(int phys_screen)
{
    xcb_intern_atom_reply_t *atom_systray_r;
    char *atom_name;

    if(!globalconf.screens.tab[phys_screen].systray.registered)
        return;
    globalconf.screens.tab[phys_screen].systray.registered = false;

    if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen))
       || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection,
                                                   xcb_intern_atom_unchecked(globalconf.connection,
                                                                             false,
                                                                             a_strlen(atom_name),
                                                                             atom_name),
                                                   NULL)))
    {
        warn("error getting systray atom");
        p_delete(&atom_name);
        return;
    }

    p_delete(&atom_name);

    xcb_set_selection_owner(globalconf.connection,
                            XCB_NONE,
                            atom_systray_r->atom,
                            XCB_CURRENT_TIME);

    p_delete(&atom_systray_r);
}
/**
 * Sends the InternAtom request.
 * @param name Name of the requested atom.
 * @ingroup Ecore_X_Atom_Group
 */
EAPI void
ecore_x_atom_get_prefetch(const char *name)
{
   xcb_intern_atom_cookie_t cookie;

   cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(name), name);
   _ecore_xcb_cookie_cache(cookie.sequence);
}
Exemple #10
0
/** Initialize systray information in X.
 * \param phys_screen Physical screen.
 */
void
systray_init(int phys_screen)
{
    xcb_client_message_event_t ev;
    xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen);
    char *atom_name;
    xcb_intern_atom_cookie_t atom_systray_q;
    xcb_intern_atom_reply_t *atom_systray_r;
    xcb_atom_t atom_systray;

    /* Send requests */
    if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen)))
    {
        warn("error getting systray atom");
        return;
    }

    atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false,
                                               a_strlen(atom_name), atom_name);

    p_delete(&atom_name);

    globalconf.screens[phys_screen].systray.window = xcb_generate_id(globalconf.connection);
    xcb_create_window(globalconf.connection, xscreen->root_depth,
                      globalconf.screens[phys_screen].systray.window,
                      xscreen->root,
                      -1, -1, 1, 1, 0,
                      XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL);

    /* Fill event */
    p_clear(&ev, 1);
    ev.response_type = XCB_CLIENT_MESSAGE;
    ev.window = xscreen->root;
    ev.format = 32;
    ev.type = MANAGER;
    ev.data.data32[0] = XCB_CURRENT_TIME;
    ev.data.data32[2] = globalconf.screens[phys_screen].systray.window;
    ev.data.data32[3] = ev.data.data32[4] = 0;

    if(!(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL)))
    {
        warn("error getting systray atom");
        return;
    }

    ev.data.data32[1] = atom_systray = atom_systray_r->atom;

    p_delete(&atom_systray_r);

    xcb_set_selection_owner(globalconf.connection,
                            globalconf.screens[phys_screen].systray.window,
                            atom_systray,
                            XCB_CURRENT_TIME);

    xcb_send_event(globalconf.connection, false, xscreen->root, 0xFFFFFF, (char *) &ev);
}
/** Register systray in X.
 * \param phys_screen Physical screen.
 */
void
systray_register(int phys_screen)
{
    xcb_client_message_event_t ev;
    xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen);
    char *atom_name;
    xcb_intern_atom_cookie_t atom_systray_q;
    xcb_intern_atom_reply_t *atom_systray_r;
    xcb_atom_t atom_systray;

    /* Set registered even if it fails to don't try again unless forced */
    if(globalconf.screens.tab[phys_screen].systray.registered)
        return;
    globalconf.screens.tab[phys_screen].systray.registered = true;

    /* Send requests */
    if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen)))
    {
        warn("error getting systray atom");
        return;
    }

    atom_systray_q = xcb_intern_atom_unchecked(globalconf.connection, false,
                                               a_strlen(atom_name), atom_name);

    p_delete(&atom_name);

    /* Fill event */
    p_clear(&ev, 1);
    ev.response_type = XCB_CLIENT_MESSAGE;
    ev.window = xscreen->root;
    ev.format = 32;
    ev.type = MANAGER;
    ev.data.data32[0] = XCB_CURRENT_TIME;
    ev.data.data32[2] = globalconf.screens.tab[phys_screen].systray.window;
    ev.data.data32[3] = ev.data.data32[4] = 0;

    if(!(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, atom_systray_q, NULL)))
    {
        warn("error getting systray atom");
        return;
    }

    ev.data.data32[1] = atom_systray = atom_systray_r->atom;

    p_delete(&atom_systray_r);

    xcb_set_selection_owner(globalconf.connection,
                            globalconf.screens.tab[phys_screen].systray.window,
                            atom_systray,
                            XCB_CURRENT_TIME);

    xcb_send_event(globalconf.connection, false, xscreen->root, 0xFFFFFF, (char *) &ev);
}
Exemple #12
0
/** Send InternAtom requests to get the Atoms X identifiers
 *
 * @return The EWMH InternAtom cookies
 */
xcb_intern_atom_cookie_t *
atoms_init(void)
{
  for(int atom_n = 0; atom_n < atoms_list_len; atom_n++)
    atoms_list[atom_n].cookie = xcb_intern_atom_unchecked(globalconf.connection,
							  false,
							  atoms_list[atom_n].name_len,
							  atoms_list[atom_n].name);

  return xcb_ewmh_init_atoms(globalconf.connection, &globalconf.ewmh);
}
Exemple #13
0
static xcb_atom_t
towel_window_get_atom(towel_window_t *win, const char *atom)
{
  xcb_intern_atom_cookie_t cookie;
  xcb_intern_atom_reply_t *reply;
  xcb_atom_t ret;
  cookie = xcb_intern_atom_unchecked(win->conn, 0, strlen(atom), atom);
  reply = xcb_intern_atom_reply(win->conn, cookie, NULL);
  ret = reply->atom;
  free(reply);
  return ret;
}
Exemple #14
0
// === EmbedWindow() ===
uint LXCB::EmbedWindow(WId win, WId container){
  if(DEBUG){ qDebug() << "XCB: EmbedWindow()"; }
  //This returns the damage control ID number (or 0 for a failure)
  if(win==0 || container==0){ return 0; }
  //qDebug() << "Embed Window:" << win << container;

  //Initialize any atoms that will be needed
  xcb_intern_atom_cookie_t ecookie = xcb_intern_atom_unchecked(QX11Info::connection(), 0, 7, "_XEMBED");
  
  xcb_intern_atom_reply_t *ereply = xcb_intern_atom_reply(QX11Info::connection(), ecookie, NULL);
  if(ereply==0){ return 0; } //unable to initialize the atom
  xcb_atom_t emb = ereply->atom;
  free(ereply); //done with this structure
  
  //Reparent the window into the container
  xcb_reparent_window(QX11Info::connection(), win, container, 0, 0);
  xcb_map_window(QX11Info::connection(), win);
  
  //Now send the embed event to the app
  //qDebug() << " - send _XEMBED event";
  xcb_client_message_event_t event;
    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.window = win;
    event.type = emb; //_XEMBED
    event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; 
    event.data.data32[1] = 0; //XEMBED_EMBEDDED_NOTIFY
    event.data.data32[2] = 0;
    event.data.data32[3] = container; //WID of the container
    event.data.data32[4] = 0;

    xcb_send_event(QX11Info::connection(), 0, win,  XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
  
  //Now setup any redirects and return
  //qDebug() << " - select Input";
  //XSelectInput(disp, win, StructureNotifyMask); //Notify of structure changes
  //uint32_t val[] = {XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY};
  //xcb_change_window_attributes(QX11Info::connection(), win, XCB_CW_EVENT_MASK, val);
  this->SelectInput(win);
  //qDebug() << " - Composite Redirect";
  xcb_composite_redirect_window(QX11Info::connection(), win, XCB_COMPOSITE_REDIRECT_MANUAL);

  //Now map the window (will be a transparent child of the container)
  xcb_map_window(QX11Info::connection(), win);
  
  //Now create/register the damage handler
  xcb_damage_damage_t dmgID = xcb_generate_id(QX11Info::connection()); //This is a typedef for a 32-bit unsigned integer
  xcb_damage_create(QX11Info::connection(), dmgID, win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
  
  //qDebug() << " - Done";
  return ( (uint) dmgID );	
}
/** Register a new xproperty.
 * \param L The Lua VM state.
 * \return The number of elements pushed on stack.
 * \luastack
 * \lparam The name of the X11 property
 * \lparam One of "string", "number" or "boolean"
 */
int
luaA_register_xproperty(lua_State *L)
{
    const char *name;
    struct xproperty property;
    struct xproperty *found;
    const char *const args[] = { "string", "number", "boolean" };
    xcb_intern_atom_reply_t *atom_r;
    int type;

    name = luaL_checkstring(L, 1);
    type = luaL_checkoption(L, 2, NULL, args);
    if (type == 0)
        property.type = PROP_STRING;
    else if (type == 1)
        property.type = PROP_NUMBER;
    else
        property.type = PROP_BOOLEAN;

    atom_r = xcb_intern_atom_reply(globalconf.connection,
                                   xcb_intern_atom_unchecked(globalconf.connection, false,
                                                             a_strlen(name), name),
                                   NULL);
    if(!atom_r)
        return 0;

    property.atom = atom_r->atom;
    p_delete(&atom_r);

    found = xproperty_array_lookup(&globalconf.xproperties, &property);
    if(found)
    {
        /* Property already registered */
        if(found->type != property.type)
            return luaL_error(L, "xproperty '%s' already registered with different type", name);
    }
    else
    {
        buffer_t buf;
        buffer_inita(&buf, a_strlen(name) + a_strlen("xproperty::") + 1);
        buffer_addf(&buf, "xproperty::%s", name);

        property.name = a_strdup(name);
        xproperty_array_insert(&globalconf.xproperties, property);
        signal_add(&window_class.signals, buf.s);
        signal_add(&global_signals, buf.s);
        buffer_wipe(&buf);
    }

    return 0;
}
Exemple #16
0
static int
_e_alert_atom_get(const char *name)
{
   xcb_intern_atom_cookie_t cookie;
   xcb_intern_atom_reply_t *reply;
   int a;

   cookie = xcb_intern_atom_unchecked(conn, 0, strlen(name), name);
   reply = xcb_intern_atom_reply(conn, cookie, NULL);
   if (!reply) return XCB_ATOM_NONE;
   a = reply->atom;
   free(reply);
   return a;
}
void
_ecore_xcb_atoms_init(void)
{
   int i = 0, num = 0;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   CHECK_XCB_CONN;

   num = (sizeof(atom_items) / sizeof(Atom_Item));
   for (i = 0; i < num; i++)
     {
        cookies[i] =
          xcb_intern_atom_unchecked(_ecore_xcb_conn, 0,
                                    strlen(atom_items[i].name), atom_items[i].name);
     }
}
/**
 * Retrieves the atom value associated to a name.
 *
 * @param  name Unused.
 * @return      Associated atom value.
 *
 * Retrieves the atom value associated to a name. The reply is the
 * returned value of the function ecore_xcb_intern_atom_reply(). If
 * @p reply is @c NULL, the NULL atom is returned. Otherwise, the atom
 * associated to the name is returned.
 *
 * @ingroup Ecore_X_Atom_Group
 */
EAPI Ecore_X_Atom
ecore_x_atom_get(const char *name)
{
   xcb_intern_atom_cookie_t cookie;
   xcb_intern_atom_reply_t *reply;
   Ecore_X_Atom a;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   CHECK_XCB_CONN;

   cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(name), name);
   reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL);
   if (!reply) return XCB_ATOM_NONE;
   a = reply->atom;
   free(reply);
   return a;
}
Exemple #19
0
static void
do_name(xcb_connection_t *c, const char *format, char *name)
{
    xcb_intern_atom_reply_t *a = xcb_intern_atom_reply(c, 
	xcb_intern_atom_unchecked(c, 1, strlen(name), name), NULL);

    if (a && a->atom != XCB_NONE) {
	printf (format, (unsigned long) a->atom, name);
	putchar ('\n');
    } else {
	fprintf (stderr, "%s:  no atom named \"%s\" on server \"%s\"\n",
		 ProgramName, name, DisplayString);
    }

    if (a)
	free(a);
}
Exemple #20
0
int main(int argc,char**argv){
	xcb_connection_t*d=xcb_connect(0,0);
	int32_t*x,*y,*tx=0,mx,my,rt=xcb_setup_roots_iterator(xcb_get_setup(d)).data->root,cs[255],*cz=cs+1;
	uint8_t mz,mZ;
	xcb_change_window_attributes(d,rt,XCB_CW_EVENT_MASK,&cwa);
	xcb_grab_key(d,1,rt,0,64,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);
	xcb_grab_key(d,1,rt,8,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);
	xcb_grab_button(d,1,rt,XCB_EVENT_MASK_BUTTON_PRESS,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_GRAB_ANY,8);
	#ifdef COMPOSITE
	xcb_composite_redirect_subwindows(d,rt,XCB_COMPOSITE_REDIRECT_AUTOMATIC);
	#endif
	xcb_generic_event_t*e=0;
main:xcb_flush(d);
	waitpid(-1,0,WNOHANG);
noflush:x=y=cz-1;
again:free(e);
	switch((e=xcb_wait_for_event(d))->response_type&127){
	case XCB_BUTTON_PRESS:
		for(;x>cs;x--)
			if(*x==((xcb_button_press_event_t*)e)->child){
				if(((xcb_key_press_event_t*)e)->detail==2)goto pocus;
			case XCB_KEY_PRESS:
				mz=128|((xcb_key_press_event_t*)e)->detail;
				my=((xcb_key_press_event_t*)e)->state;
				goto*(cz==cs+1?&&kcode:&&stack);
			}
		goto noflush;
	case XCB_KEY_RELEASE:
		if(((xcb_key_press_event_t*)e)->detail!=64||!tx)default:goto again;
		xt:x=tx;
		tx=0;
		goto stack;
	case XCB_CONFIGURE_REQUEST:{
		void*p=buf;
		for(mz=0;mz<5;mz++)
			if(((xcb_configure_request_event_t*)e)->value_mask&1<<mz){*(uint32_t*)p=*(int16_t*)(((void*)e)+16+mz*2);p+=4;}
		if(((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_SIBLING){*(uint32_t*)p=((xcb_configure_request_event_t*)e)->sibling;p+=4;}
		if(mz=((xcb_configure_request_event_t*)e)->value_mask&XCB_CONFIG_WINDOW_STACK_MODE)*(uint32_t*)p=((xcb_configure_request_event_t*)e)->stack_mode;
		xcb_configure_window(d,((xcb_configure_request_event_t*)e)->window,((xcb_configure_request_event_t*)e)->value_mask,buf);
		if(mz){
			p=xcb_query_tree_reply(d,xcb_query_tree_unchecked(d,rt),0);
			int32_t*cl=p+32+((xcb_query_tree_reply_t*)p)->children_len*4;
			for(y=p+32;y<cl;y++){
				for(x=cs+1;x<cz;x++)
					if(*x==*y)goto nono;
				*y=0;
				nono:;
			}
			x=cs;
			for(y=p+32;y<cl;y++)
				if(*y)*++x=*y;
			free(p);
			goto pocus;
		}else goto main;}
	case XCB_MAP_REQUEST:{
		void*p=xcb_get_window_attributes_reply(d,xcb_get_window_attributes_unchecked(d,((xcb_map_request_event_t*)e)->window),0);
		if(((xcb_get_window_attributes_reply_t*)p)->override_redirect){
			free(p);
			goto pocus;
		}
		free(p);
		for(;x>cs;x--)
			if(*x==((xcb_map_request_event_t*)e)->window)goto noflush;
		xcb_map_window(d,*cz++=((xcb_map_request_event_t*)e)->window);
		goto hocus;}
	case XCB_MOTION_NOTIFY:
		*buf=mZ&&((xcb_motion_notify_event_t*)e)->root_x<=mx?:((xcb_motion_notify_event_t*)e)->root_x-mx;
		buf[1]=mZ&&((xcb_motion_notify_event_t*)e)->root_y<=my?:((xcb_motion_notify_event_t*)e)->root_y-my;
		xcb_configure_window(d,*x,mZ?XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT:XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y,buf);
		goto main;
	case XCB_BUTTON_RELEASE:
		xcb_ungrab_pointer(d,XCB_CURRENT_TIME);
		goto main;
	case XCB_UNMAP_NOTIFY:unmap:goto*(x==cs?&&noflush:*x==((xcb_unmap_notify_event_t*)e)->window&&--cz>cs+1?&&stack:(x--,&&unmap));
	}
stack:mx=*x;
	for(;x!=y;x+=x<y?:-1)*x=x[x<y?:-1];
	*x=mx;
hocus:x=cz-1;
	xcb_configure_window(d,*x,XCB_CONFIG_WINDOW_STACK_MODE,di);
pocus:xcb_set_input_focus(d,XCB_INPUT_FOCUS_POINTER_ROOT,*x,XCB_CURRENT_TIME);
	if(!(mz&128))goto main;
kcode:switch(mz&=127){
	void*p;
	case 1:case 3:
		p=xcb_grab_pointer_reply(d,xcb_grab_pointer_unchecked(d,0,rt,XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_POINTER_MOTION,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC,XCB_NONE,XCB_NONE,XCB_CURRENT_TIME),0);
		if(((xcb_grab_pointer_reply_t*)p)->status!=XCB_GRAB_STATUS_SUCCESS){
			free(p);
			goto noflush;
		}
		free(p);
		p=xcb_get_geometry_reply(d,xcb_get_geometry_unchecked(d,*y),0);
		mx=((xcb_get_geometry_reply_t*)p)->x;
		my=((xcb_get_geometry_reply_t*)p)->y;
		free(p);
		if(mZ=mz==1){
			p=xcb_query_pointer_reply(d,xcb_query_pointer_unchecked(d,rt),0);
			mx=((xcb_query_pointer_reply_t*)p)->root_x-mx;
			my=((xcb_query_pointer_reply_t*)p)->root_y-my;
			free(p);
		}
		goto noflush;
	case 23:case 49:
		if(cz-cs<3)goto main;
		y=tx;
		tx=mz==23?(y!=cs+1?(y?:x)-1:x):!y||y==x?cs+1:y+1;
		if(y&&y<cz-1){
			*buf=y[mz==23?:-1];
			buf[1]=mz==23;
			xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_SIBLING|XCB_CONFIG_WINDOW_STACK_MODE,buf);
		}
		xcb_configure_window(d,*tx,XCB_CONFIG_WINDOW_STACK_MODE,di);
		goto main;
	case 32:return 0;
	case 44:
		if(cz>cs+1)xcb_configure_window(d,*y,XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT,di);
		goto main;
	case 46:
		if(cz==cs+1)goto main;
		if(tx)goto*(mz|=128,&&xt);
		{xcb_intern_atom_cookie_t c1=xcb_intern_atom_unchecked(d,0,12,"WM_PROTOCOLS"),c2=xcb_intern_atom_unchecked(d,0,16,"WM_DELETE_WINDOW");
		p=xcb_intern_atom_reply(d,c1,0);
		mx=((xcb_intern_atom_reply_t*)p)->atom;
		free(p);
		p=xcb_intern_atom_reply(d,c2,0);}
		my=((xcb_intern_atom_reply_t*)p)->atom;
		free(p);
		p=xcb_get_property_reply(d,xcb_get_property_unchecked(d,0,*y,mx,XCB_ATOM_ATOM,0,-1),0);
		xcb_send_event(d,0,*y,XCB_EVENT_MASK_NO_EVENT,(void*)(xcb_client_message_event_t[]){{.response_type=XCB_CLIENT_MESSAGE,.window=*y,.type=mx,.format=32,.data.data32={my,XCB_CURRENT_TIME}}});
Exemple #21
0
void init_tabletwm() {

	memset(&key_win, 0, sizeof(key_win));
	memset(&shutdown_win, 0, sizeof(shutdown_win));
	xcb_void_cookie_t void_cookie;
	xcb_intern_atom_cookie_t atom_cookie[TWM_ATOM_LAST_VALUE];
	uint32_t v[] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE};
	int i;

	char *a_atoms[TWM_ATOM_LAST_VALUE] = {
		"WM_SIZE_HINTS",
		"WM_NORMAL_HINTS",
		"WM_PROTOCOLS",
		"WM_DELETE_WINDOW",
		"WM_TRANSIENT_FOR",
		"_NET_SUPPORTING_WM_CHECK",
		"_NET_WM_NAME",
		"_NET_SUPPORTED",

		"_NET_WM_WINDOW_TYPE",
		"_NET_WM_WINDOW_TYPE_DESKTOP",
		"_NET_WM_WINDOW_TYPE_DOCK",
		"_NET_WM_WINDOW_TYPE_TOOLBAR",
		"_NET_WM_WINDOW_TYPE_MENU",
		"_NET_WM_WINDOW_TYPE_UTILITY",
		"_NET_WM_WINDOW_TYPE_SPLASH",
		"_NET_WM_WINDOW_TYPE_DIALOG",
		"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
		"_NET_WM_WINDOW_TYPE_POPUP_MENU",
		"_NET_WM_WINDOW_TYPE_TOOLTIP",
		"_NET_WM_WINDOW_TYPE_NOTIFICATION",
		"_NET_WM_WINDOW_TYPE_COMBO",
		"_NET_WM_WINDOW_TYPE_DND",
		"_NET_WM_WINDOW_TYPE_NORMAL",

		"_NET_WM_ALLOWED_ACTIONS",
		"_NET_WM_ACTION_MOVE",
		"_NET_WM_ACTION_RESIZE",
		"_NET_WM_ACTION_MINIMIZE",
		"_NET_WM_ACTION_SHADE",
		"_NET_WM_ACTION_STICK",
		"_NET_WM_ACTION_MAXIMIZE_HORZ",
		"_NET_WM_ACTION_MAXIMIZE_VERT",
		"_NET_WM_ACTION_FULLSCREEN",
		"_NET_WM_ACTION_CHANGE_DESKTOP",
		"_NET_WM_ACTION_CLOSE",
		"_NET_WM_ACTION_ABOVE",
		"_NET_WM_ACTION_BELOW",

		"WM_CLASS",
		"WM_STATE",
		"_NET_ACTIVE_WINDOW",
		"WM_HINTS",
		"_XKB_RULES_NAMES",
	};

	init_load_config();

	wincache_init();

	conn = xcb_connect(0, 0);
	assert(conn);

	scr = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;
	width = scr->width_in_pixels;
	height = scr->height_in_pixels; // reserve the bottom part for the 1pixel-height, collapsed menu bar

	xcb_change_window_attributes(conn, scr->root, XCB_CW_EVENT_MASK, v);

	xcb_depth_iterator_t depth_iter;
	xcb_visualid_t root_visual = { 0 };
	visual_type = NULL;

	for (depth_iter = xcb_screen_allowed_depths_iterator (scr); depth_iter.rem; xcb_depth_next (&depth_iter)) {
		xcb_visualtype_iterator_t visual_iter;

		visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
		for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
			if (scr->root_visual == visual_iter.data->visual_id) {
				visual_type = visual_iter.data;
				break;
			}
		}
	}

	/* get atoms */
	for(i=0; i < TWM_ATOM_LAST_VALUE; i++) {
		atom_cookie[i] = xcb_intern_atom_unchecked(conn, 0, strlen(a_atoms[i]), a_atoms[i]);
	};

	xcb_flush(conn);

	xcb_intern_atom_reply_t *atom_reply;
	for(i=0; i < TWM_ATOM_LAST_VALUE; i++) {
		atom_reply = xcb_intern_atom_reply(conn, atom_cookie[i], 0),
		atoms[i] = atom_reply->atom;
		free(atom_reply);
	};

	xcb_change_property(conn, XCB_PROP_MODE_REPLACE, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM_WM_DELETE_WINDOW]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DESKTOP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DOCK]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_TOOLBAR]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED] , XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_UTILITY]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_SPLASH]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DIALOG]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DROPDOWN_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_POPUP_MENU]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_TOOLTIP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_NOTIFICATION]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_COMBO]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_DND]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_WINDOW_TYPE_NORMAL]);

	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ALLOWED_ACTIONS]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MOVE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_RESIZE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MINIMIZE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_SHADE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_STICK]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MAXIMIZE_HORZ]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_MAXIMIZE_VERT]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_FULLSCREEN]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_CHANGE_DESKTOP]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_CLOSE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_ABOVE]);
	xcb_change_property(conn, XCB_PROP_MODE_APPEND, scr->root, atoms[TWM_ATOM__NET_SUPPORTED], XCB_ATOM_ATOM, 32, 1, &atoms[TWM_ATOM__NET_WM_ACTION_BELOW]);

	// This window contains the menu and the virtual keyboard (when showed)
	// It is also used to ensure that the window manager is recognized as an Extended Window Manager Hints WM
	// By default it occupies one pixel at the bottom of the screen, to allow to detect when the mouse is moved to the bottom

	xcb_get_property_cookie_t kbd_info_cookie;
	xcb_get_property_reply_t *kbd_info;
	kbd_info_cookie = xcb_get_property(conn, 0, scr->root, atoms[TWM__XKB_RULES_NAMES], XCB_ATOM_STRING, 0, 1024);

	key_win.window = xcb_generate_id(conn);
	uint32_t values[1] = {XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_BUTTON_RELEASE|XCB_EVENT_MASK_BUTTON_PRESS|XCB_EVENT_MASK_ENTER_WINDOW|XCB_EVENT_MASK_LEAVE_WINDOW};
	void_cookie=xcb_create_window_checked (conn, XCB_COPY_FROM_PARENT, key_win.window, scr->root, 0, height-1, width, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, XCB_CW_EVENT_MASK, values);

	xcb_flush(conn);

	kbd_info = xcb_get_property_reply(conn, kbd_info_cookie, 0);
	if (kbd_info!=NULL) {
		if (kbd_info->length>0) {
			char *p=((char *)(xcb_get_property_value(kbd_info)));
			int counter=0;
			int len, max;
			max=xcb_get_property_value_length(kbd_info);
			char *end=p+max;
			do {
				len = strnlen(p, max);
				if (*p!=0) {
					xkb_names[counter++] = strdup(p);
				}
				p+=len+1;
				max-=len+1;
			} while ((p < end) && (counter < 5));
		}
		free(kbd_info);
	}

	if (xcb_request_check(conn, void_cookie)) {
		printf("Can't create the fake window\n");
	} else {
		menuwin_init();
	}
	shutdown_init();
}