void schedule_window(xcb_window_t win) { coordinates_t loc; uint8_t override_redirect = 0; xcb_get_window_attributes_reply_t *wa = xcb_get_window_attributes_reply(dpy, xcb_get_window_attributes(dpy, win), NULL); if (wa != NULL) { override_redirect = wa->override_redirect; free(wa); } if (override_redirect || locate_window(win, &loc)) { return; } /* ignore pending windows */ for (pending_rule_t *pr = pending_rule_head; pr != NULL; pr = pr->next) { if (pr->win == win) { return; } } rule_consequence_t *csq = make_rule_conquence(); apply_rules(win, csq); if (!schedule_rules(win, csq)) { manage_window(win, csq, -1); free(csq); } }
/* * Go through all existing windows (if the window manager is restarted) and manage them * */ void manage_existing_windows(xcb_window_t root) { xcb_query_tree_reply_t *reply; int i, len; xcb_window_t *children; xcb_get_window_attributes_cookie_t *cookies; /* Get the tree of windows whose parent is the root window (= all) */ if ((reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, root), 0)) == NULL) return; len = xcb_query_tree_children_length(reply); cookies = smalloc(len * sizeof(*cookies)); /* Request the window attributes for every window */ children = xcb_query_tree_children(reply); for (i = 0; i < len; ++i) cookies[i] = xcb_get_window_attributes(conn, children[i]); /* Call manage_window with the attributes for every window */ for (i = 0; i < len; ++i) manage_window(children[i], cookies[i], true); free(reply); free(cookies); }
static void nextwin (void) { xcb_query_tree_reply_t *r; xcb_window_t *c,t = 0; xcb_get_window_attributes_cookie_t ac; xcb_get_window_attributes_reply_t *ar; r = xcb_query_tree_reply(conn, xcb_query_tree(conn, scr->root), 0); if (!r || !r->children_len) return; c = xcb_query_tree_children(r); for (unsigned int i=0; i < r->children_len; i++) { ac = xcb_get_window_attributes(conn, c[i]); ar = xcb_get_window_attributes_reply(conn, ac, NULL); if (ar && ar->map_state == XCB_MAP_STATE_VIEWABLE) { if (!(ar->override_redirect || c[i] == (*focuswin))) { t = c[i]; } break; } } if (t) { focus(t, ACTIVE); center_pointer(t); } free(r); }
static xcb_visualtype_t * get_visualtype_for_window(xcb_connection_t *conn, xcb_window_t window, unsigned *depth) { xcb_query_tree_cookie_t tree_cookie; xcb_get_window_attributes_cookie_t attrib_cookie; xcb_query_tree_reply_t *tree; xcb_get_window_attributes_reply_t *attrib; tree_cookie = xcb_query_tree(conn, window); attrib_cookie = xcb_get_window_attributes(conn, window); tree = xcb_query_tree_reply(conn, tree_cookie, NULL); attrib = xcb_get_window_attributes_reply(conn, attrib_cookie, NULL); if (attrib == NULL || tree == NULL) { free(attrib); free(tree); return NULL; } xcb_window_t root = tree->root; xcb_visualid_t visual_id = attrib->visual; free(attrib); free(tree); xcb_screen_t *screen = get_screen_for_root(conn, root); if (screen == NULL) return NULL; return screen_get_visualtype(screen, visual_id, depth); }
void enter_notify(xcb_generic_event_t *evt) { xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt; xcb_window_t win = e->event; PRINTF("enter notify %X %d %d\n", win, e->mode, e->detail); if (e->mode != XCB_NOTIFY_MODE_NORMAL || (mon->desk->focus != NULL && mon->desk->focus->client->window == win)) { return; } xcb_get_window_attributes_reply_t *wa = xcb_get_window_attributes_reply(dpy, xcb_get_window_attributes(dpy, motion_recorder), NULL); if (wa == NULL) { return; } if (wa->map_state == XCB_MAP_STATE_UNMAPPED) { enable_motion_recorder(); } else { disable_motion_recorder(); } }
static MetaGroup* meta_group_new (MetaX11Display *x11_display, Window group_leader) { MetaGroup *group; #define N_INITIAL_PROPS 3 Atom initial_props[N_INITIAL_PROPS]; int i; g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); group = g_new0 (MetaGroup, 1); group->x11_display = x11_display; group->windows = NULL; group->group_leader = group_leader; group->refcount = 1; /* owned by caller, hash table has only weak ref */ xcb_connection_t *xcb_conn = XGetXCBConnection (x11_display->xdisplay); xcb_generic_error_t *e; g_autofree xcb_get_window_attributes_reply_t *attrs = xcb_get_window_attributes_reply (xcb_conn, xcb_get_window_attributes (xcb_conn, group_leader), &e); if (e) return NULL; const uint32_t events[] = { attrs->your_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes (xcb_conn, group_leader, XCB_CW_EVENT_MASK, events); if (x11_display->groups_by_leader == NULL) x11_display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash, meta_unsigned_long_equal); g_assert (g_hash_table_lookup (x11_display->groups_by_leader, &group_leader) == NULL); g_hash_table_insert (x11_display->groups_by_leader, &group->group_leader, group); /* Fill these in the order we want them to be gotten */ i = 0; initial_props[i++] = x11_display->atom_WM_CLIENT_MACHINE; initial_props[i++] = x11_display->atom__NET_WM_PID; initial_props[i++] = x11_display->atom__NET_STARTUP_ID; g_assert (N_INITIAL_PROPS == i); meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS); meta_topic (META_DEBUG_GROUPS, "Created new group with leader 0x%lx\n", group->group_leader); return group; }
uint32_t _xcb_get_event_mask(xcb_connection_t* conn, xcb_window_t window) { if (window == XCB_NONE) { return 0; } xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(conn, window); xcb_get_window_attributes_reply_t* reply = xcb_get_window_attributes_reply(conn, cookie, NULL); if (!reply) { return 0; } uint32_t your_event_mask = reply->your_event_mask; free(reply); return your_event_mask; }
/* Generate a XCWM_EVENT_WINDOW_CREATE event for all existing mapped top-level windows when we start */ static void _xcwm_windows_adopt(xcwm_context_t *context, xcwm_event_cb_t callback_ptr) { xcb_query_tree_cookie_t tree_cookie = xcb_query_tree(context->conn, context->root_window->window_id); xcb_query_tree_reply_t *reply = xcb_query_tree_reply(context->conn, tree_cookie, NULL); if (NULL == reply) { return; } int len = xcb_query_tree_children_length(reply); xcb_window_t *children = xcb_query_tree_children(reply); int i; for (i = 0; i < len; i ++) { xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(context->conn, children[i]); xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(context->conn, cookie, NULL); if (!attr) { fprintf(stderr, "Couldn't get attributes for window 0x%08x\n", children[i]); continue; } if (attr->map_state == XCB_MAP_STATE_VIEWABLE) { printf("window 0x%08x viewable\n", children[i]); xcwm_window_t *window = _xcwm_window_create(context, children[i], context->root_window->window_id); if (!window) { continue; } _xcwm_window_composite_pixmap_update(window); xcwm_event_t return_evt; return_evt.window = window; return_evt.event_type = XCWM_EVENT_WINDOW_CREATE; callback_ptr(&return_evt); } else { printf("window 0x%08x non-viewable\n", children[i]); } free(attr); } free(reply); }
/* * Check if window is viewable */ static Bool Window_Is_Viewable(xcb_connection_t * dpy, xcb_window_t win) { Bool ok = False; xcb_get_window_attributes_cookie_t attr_cookie; xcb_get_window_attributes_reply_t *xwa; attr_cookie = xcb_get_window_attributes (dpy, win); xwa = xcb_get_window_attributes_reply (dpy, attr_cookie, NULL); if (xwa) { ok = (xwa->_class == XCB_WINDOW_CLASS_INPUT_OUTPUT) && (xwa->map_state == XCB_MAP_STATE_VIEWABLE); free (xwa); } return ok; }
static void handle_map_notify(xcb_map_notify_event_t *event) { if (fuzzy) { /* Create damage objects for new windows */ xcb_get_window_attributes_reply_t *attribs = xcb_get_window_attributes_reply( conn, xcb_get_window_attributes(conn, event->window), NULL); create_damage(conn, event->window, attribs); } if (!dont_fork) { /* After the first MapNotify, we never fork again. */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } }
// === WindowState() === LXCB::WINDOWSTATE LXCB::WindowState(WId win){ if(DEBUG){ qDebug() << "XCB: WindowState()"; } if(win==0){ return IGNORE; } xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win); if(cookie.sequence == 0){ return IGNORE; } xcb_ewmh_get_atoms_reply_t states; WINDOWSTATE cstate = IGNORE; //First Check for special states (ATTENTION in particular); if( 1 == xcb_ewmh_get_wm_state_reply(&EWMH, cookie, &states, NULL) ){ for(unsigned int i=0; i<states.atoms_len; i++){ if(states.atoms[i] == EWMH._NET_WM_STATE_DEMANDS_ATTENTION){ cstate = ATTENTION; break; } //nothing more urgent - stop here else if(states.atoms[i] == EWMH._NET_WM_STATE_HIDDEN){ cstate = INVISIBLE; } } } //Now check to see if the window is the active one if(cstate == IGNORE){ xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window_unchecked(&EWMH, 0); xcb_window_t actwin; if(1 == xcb_ewmh_get_active_window_reply(&EWMH, cookie, &actwin, NULL) ){ if(actwin == win){ cstate = ACTIVE; } } } //Now check for ICCCM Urgency hint (not sure if this is still valid with EWMH instead) /*if(cstate == IGNORE){ xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_hints_unchecked(QX11Info::connection(), win); xcb_icccm_wm_hints_t hints; if( 1== xcb_icccm_get_wm_hints_reply(QX11Info::connection(), cookie, &hints, NULL) ){ if(xcb_icccm_wm_hints_get_urgency(hints) ){ cstate = ATTENTION; }; } }*/ //Now check for standard visible/invisible attribute (current mapping state) if(cstate == IGNORE){ xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(QX11Info::connection(), win); xcb_get_window_attributes_reply_t *attr = xcb_get_window_attributes_reply(QX11Info::connection(), cookie, NULL); if(attr!=0){ if(attr->map_state==XCB_MAP_STATE_VIEWABLE){ cstate = VISIBLE; } else{ cstate = INVISIBLE; } free(attr); } } return cstate; }
/* * List all hidden windows. * */ int findhidden(void) { xcb_query_tree_reply_t *reply; int i; int len; xcb_window_t *children; xcb_get_window_attributes_reply_t *attr; uint32_t state; xcb_get_property_cookie_t cookie; xcb_icccm_get_text_property_reply_t prop; xcb_generic_error_t *error; /* Get all children. */ reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, screen->root), 0); if (NULL == reply) { return -1; } len = xcb_query_tree_children_length(reply); children = xcb_query_tree_children(reply); /* List all hidden windows on this root. */ for (i = 0; i < len; i ++) { attr = xcb_get_window_attributes_reply( conn, xcb_get_window_attributes(conn, children[i]), NULL); if (!attr) { fprintf(stderr, "Couldn't get attributes for window %d.", children[i]); continue; } /* * Don't bother windows in override redirect mode. * * This mode means they wouldn't have been reported to us * with a MapRequest if we had been running, so in the * normal case we wouldn't have seen them. */ if (!attr->override_redirect) { state = get_wm_state(children[i]); if (state == XCB_ICCCM_WM_STATE_ICONIC) { /* * Example names: * * _NET_WM_ICON_NAME(UTF8_STRING) = 0x75, 0x72, 0x78, * 0x76, 0x74 WM_ICON_NAME(STRING) = "urxvt" * _NET_WM_NAME(UTF8_STRING) = 0x75, 0x72, 0x78, 0x76, * 0x74 WM_NAME(STRING) = "urxvt" */ cookie = xcb_icccm_get_wm_icon_name(conn, children[i]); xcb_icccm_get_wm_icon_name_reply(conn, cookie, &prop, &error); prop.name[prop.name_len] = '\0'; if (printcommand) { /* FIXME: Need to escape : in prop.name. */ printf("'%s':'xdotool windowmap 0x%x windowraise 0x%x'\n", prop.name, children[i], children[i]); } else { puts(prop.name); } } } /* if not override redirect */ free(attr); } /* for */ free(reply); return 0; }
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows) { if (w == shapedPixmapWindow()->handle()->winId()) return 0; if (md) { xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w); xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0); if (!reply) return 0; if (reply->map_state != XCB_MAP_STATE_VIEWABLE) return 0; free(reply); xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w); xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0); if (!greply) return 0; QRect windowRect(greply->x, greply->y, greply->width, greply->height); free(greply); if (windowRect.contains(pos)) { bool windowContainsMouse = !ignoreNonXdndAwareWindows; { xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0); bool isAware = reply && reply->type != XCB_NONE; free(reply); if (isAware) { const QPoint relPos = pos - windowRect.topLeft(); // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we // need to check both here so that in the case one is set and the other is not we still get the correct result. if (connection()->hasInputShape()) windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_INPUT); if (windowContainsMouse && connection()->hasXShape()) windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_BOUNDING); if (!connection()->hasInputShape() && !connection()->hasXShape()) windowContainsMouse = true; if (windowContainsMouse) return w; } } xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w); xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0); if (!reply) return 0; int nc = xcb_query_tree_children_length(reply); xcb_window_t *c = xcb_query_tree_children(reply); xcb_window_t r = 0; for (uint i = nc; !r && i--;) r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows); free(reply); if (r) return r; // We didn't find a client window! Just use the // innermost window. // No children! if (!windowContainsMouse) return 0; else return w; } } return 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; }