aboutsummaryrefslogtreecommitdiff
path: root/apps/xwininfo/dsimple.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/xwininfo/dsimple.c')
-rw-r--r--apps/xwininfo/dsimple.c761
1 files changed, 529 insertions, 232 deletions
diff --git a/apps/xwininfo/dsimple.c b/apps/xwininfo/dsimple.c
index b70aa43f2..a9b867896 100644
--- a/apps/xwininfo/dsimple.c
+++ b/apps/xwininfo/dsimple.c
@@ -1,4 +1,25 @@
-/* $Xorg: dsimple.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
/*
Copyright 1993, 1998 The Open Group
@@ -26,21 +47,19 @@ other dealings in this Software without prior written authorization
from The Open Group.
*/
-/* $XFree86: xc/programs/xlsfonts/dsimple.c,v 3.6 2001/12/14 20:02:09 dawes Exp $ */
-#include <X11/Xos.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
+#include "config.h"
+
+#include <xcb/xcb.h>
+#include <xcb/xproto.h>
+#ifdef USE_XCB_ICCCM
+# include <xcb/xcb_icccm.h>
+#endif
#include <X11/cursorfont.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-/*
- * Other_stuff.h: Definitions of routines in other_stuff.
- *
- * Written by Mark Lillibridge. Last updated 7/1/87
- */
-
+#include <string.h>
#include "clientwin.h"
#include "dsimple.h"
@@ -48,287 +67,565 @@ from The Open Group.
* Just_display: A group of routines designed to make the writing of simple
* X11 applications which open a display but do not open
* any windows much faster and easier. Unless a routine says
- * otherwise, it may be assumed to require program_name, dpy,
- * and screen already defined on entry.
+ * otherwise, it may be assumed to require program_name
+ * to be already defined on entry.
*
* Written by Mark Lillibridge. Last updated 7/1/87
*/
-/* This stuff is defined in the calling program by just_display.h */
+/* This stuff is defined in the calling program by dsimple.h */
char *program_name = "unknown_program";
-Display *dpy = NULL;
-int screen = 0;
-
/*
- * Get_Display_Name (argc, argv) Look for -display, -d, or host:dpy (obselete)
- * If found, remove it from command line. Don't go past a lone -.
+ * Get_Display_Name (argc, argv) - return string representing display name
+ * that would be used given the specified argument (i.e. if it's NULL, check
+ * getenv("DISPLAY") - always returns a non-NULL pointer, though it may be
+ * an unwritable constant, so is safe to printf() on platforms that crash
+ * on NULL printf arguments.
*/
-char *Get_Display_Name(
- int *pargc, /* MODIFIED */
- char **argv) /* MODIFIED */
+const char *Get_Display_Name (const char *display_name)
{
- int argc = *pargc;
- char **pargv = argv+1;
- char *displayname = NULL;
- int i;
-
- for (i = 1; i < argc; i++) {
- char *arg = argv[i];
+ const char *name = display_name;
- if (!strcmp (arg, "-display") || !strcmp (arg, "-d")) {
- if (++i >= argc) usage ();
-
- displayname = argv[i];
- *pargc -= 2;
- continue;
- }
- if (!strcmp(arg,"-")) {
- while (i<argc)
- *pargv++ = argv[i++];
- break;
- }
- *pargv++ = arg;
+ if (!name) {
+ name = getenv ("DISPLAY");
+ if (!name)
+ name = "";
}
-
- *pargv = NULL;
- return (displayname);
+ return (name);
}
-
/*
- * Open_Display: Routine to open a display with correct error handling.
- * Does not require dpy or screen defined on entry.
+ * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
+ * it calls Get_Display_Name) and then stores a
+ * pointer to it in dpy. The default screen
+ * for this display is then stored in screen.
*/
-Display *Open_Display(char *display_name)
+void Setup_Display_And_Screen (
+ const char *display_name,
+ xcb_connection_t **dpy, /* MODIFIED */
+ xcb_screen_t **screen) /* MODIFIED */
{
- Display *d;
+ int screen_number, i;
- d = XOpenDisplay(display_name);
- if (d == NULL) {
- fprintf (stderr, "%s: unable to open display '%s'\n",
- program_name, XDisplayName (display_name));
- exit(1);
- }
+ /* Open Display */
+ *dpy = xcb_connect (display_name, &screen_number);
+ if (xcb_connection_has_error (*dpy)) {
+ Fatal_Error ("unable to open display \"%s\"",
+ Get_Display_Name(display_name) );
+ }
- return(d);
-}
+ if (screen) {
+ /* find our screen */
+ const xcb_setup_t *setup = xcb_get_setup(*dpy);
+ xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(setup);
+ for (i = 0; i < screen_number; i++)
+ xcb_screen_next(&screen_iter);
+ *screen = screen_iter.data;
+ }
+}
/*
- * Setup_Display_And_Screen: This routine opens up the correct display (i.e.,
- * it calls Get_Display_Name) and then stores a
- * pointer to it in dpy. The default screen
- * for this display is then stored in screen.
- * Does not require dpy or screen defined.
+ * xcb equivalent of XCreateFontCursor
*/
-void Setup_Display_And_Screen(
- int *argc, /* MODIFIED */
- char **argv) /* MODIFIED */
+static xcb_cursor_t
+Create_Font_Cursor (xcb_connection_t *dpy, uint16_t glyph)
{
- char *displayname = NULL;
-
- displayname = Get_Display_Name(argc, argv);
- dpy = Open_Display (displayname);
- screen = XDefaultScreen(dpy);
+ static xcb_font_t cursor_font;
+ xcb_cursor_t cursor;
+
+ if (!cursor_font) {
+ cursor_font = xcb_generate_id (dpy);
+ xcb_open_font (dpy, cursor_font, strlen ("cursor"), "cursor");
+ }
+
+ cursor = xcb_generate_id (dpy);
+ xcb_create_glyph_cursor (dpy, cursor, cursor_font, cursor_font,
+ glyph, glyph + 1,
+ 0, 0, 0, 0xffff, 0xffff, 0xffff); /* rgb, rgb */
+
+ return cursor;
}
/*
- * Close_Display: Close display
+ * Routine to let user select a window using the mouse
*/
-void Close_Display(void)
+
+xcb_window_t Select_Window(xcb_connection_t *dpy,
+ const xcb_screen_t *screen,
+ int descend)
{
- if (dpy == NULL)
- return;
-
- XCloseDisplay(dpy);
- dpy = NULL;
+ xcb_cursor_t cursor;
+ xcb_generic_event_t *event;
+ xcb_window_t target_win = XCB_WINDOW_NONE;
+ xcb_window_t root = screen->root;
+ int buttons = 0;
+ xcb_generic_error_t *err;
+ xcb_grab_pointer_cookie_t grab_cookie;
+ xcb_grab_pointer_reply_t *grab_reply;
+
+ /* Make the target cursor */
+ cursor = Create_Font_Cursor (dpy, XC_crosshair);
+
+ /* Grab the pointer using target cursor, letting it room all over */
+ grab_cookie = xcb_grab_pointer
+ (dpy, False, root,
+ XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE,
+ XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
+ root, cursor, XCB_TIME_CURRENT_TIME);
+ grab_reply = xcb_grab_pointer_reply (dpy, grab_cookie, &err);
+ if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS)
+ Fatal_Error ("Can't grab the mouse.");
+
+ /* Let the user select a window... */
+ while ((target_win == XCB_WINDOW_NONE) || (buttons != 0)) {
+ /* allow one more event */
+ xcb_allow_events (dpy, XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME);
+ xcb_flush (dpy);
+ event = xcb_wait_for_event (dpy);
+ switch (event->response_type & 0x7f) {
+ case XCB_BUTTON_PRESS:
+ {
+ xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event;
+
+ if (target_win == XCB_WINDOW_NONE) {
+ target_win = bp->child; /* window selected */
+ if (target_win == XCB_WINDOW_NONE)
+ target_win = root;
+ }
+ buttons++;
+ break;
+ }
+ case XCB_BUTTON_RELEASE:
+ if (buttons > 0) /* there may have been some down before we started */
+ buttons--;
+ break;
+ default:
+ /* just discard all other events */
+ break;
+ }
+ free (event);
+ }
+
+ xcb_ungrab_pointer (dpy, XCB_TIME_CURRENT_TIME); /* Done with pointer */
+
+ if (!descend || (target_win == root))
+ return (target_win);
+
+ target_win = Find_Client (dpy, root, target_win);
+
+ return (target_win);
}
/*
- * Select_Window_Args: a rountine to provide a common interface for
- * applications that need to allow the user to select one
- * window on the screen for special consideration.
- * This routine implements the following command line
- * arguments:
- *
- * -root Selects the root window.
- * -id <id> Selects window with id <id>. <id> may
- * be either in decimal or hex.
- * -name <name> Selects the window with name <name>.
- *
- * Call as Select_Window_Args(&argc, argv) in main before
- * parsing any of your program's command line arguments.
- * Select_Window_Args will remove its arguments so that
- * your program does not have to worry about them.
- * The window returned is the window selected or 0 if
- * none of the above arguments was present. If 0 is
- * returned, Select_Window should probably be called after
- * all command line arguments, and other setup is done.
- * For examples of usage, see xwininfo, xwd, or xprop.
+ * Window_With_Name: routine to locate a window with a given name on a display.
+ * If no window with the given name is found, 0 is returned.
+ * If more than one window has the given name, the first
+ * one found will be returned. Only top and its subwindows
+ * are looked at. Normally, top should be the RootWindow.
*/
-Window Select_Window_Args(
- int *rargc,
- char **argv)
-#define ARGC (*rargc)
+
+struct wininfo_cookies {
+ xcb_get_property_cookie_t get_net_wm_name;
+ xcb_get_property_cookie_t get_wm_name;
+ xcb_query_tree_cookie_t query_tree;
+};
+
+#ifndef USE_XCB_ICCCM
+# define xcb_get_wm_name(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, XCB_ATOM_WM_NAME, \
+ XCB_GET_PROPERTY_TYPE_ANY, 0, BUFSIZ)
+#endif
+
+static xcb_atom_t atom_net_wm_name, atom_utf8_string;
+
+# define xcb_get_net_wm_name(Dpy, Win) \
+ xcb_get_property (Dpy, False, Win, atom_net_wm_name, \
+ atom_utf8_string, 0, BUFSIZ)
+
+
+static xcb_window_t
+recursive_Window_With_Name (
+ xcb_connection_t *dpy,
+ xcb_window_t window,
+ struct wininfo_cookies *cookies,
+ const char *name)
{
- int nargc=1;
- int argc;
- char **nargv;
- Window w=0;
-
- nargv = argv+1; argc = ARGC;
-#define OPTION argv[0]
-#define NXTOPTP ++argv, --argc>0
-#define NXTOPT if (++argv, --argc==0) usage()
-#define COPYOPT nargv++[0]=OPTION, nargc++
-
- while (NXTOPTP) {
- if (!strcmp(OPTION, "-")) {
- COPYOPT;
- while (NXTOPTP)
- COPYOPT;
- break;
- }
- if (!strcmp(OPTION, "-root")) {
- w=RootWindow(dpy, screen);
- continue;
- }
- if (!strcmp(OPTION, "-name")) {
- NXTOPT;
- w = Window_With_Name(dpy, RootWindow(dpy, screen),
- OPTION);
- if (!w)
- Fatal_Error("No window with name %s exists!",OPTION);
- continue;
+ xcb_window_t *children;
+ unsigned int nchildren;
+ int i;
+ xcb_window_t w = 0;
+ xcb_generic_error_t *err;
+ xcb_query_tree_reply_t *tree;
+ struct wininfo_cookies *child_cookies;
+ xcb_get_property_reply_t *prop;
+
+ if (cookies->get_net_wm_name.sequence) {
+ prop = xcb_get_property_reply (dpy, cookies->get_net_wm_name, &err);
+
+ if (prop) {
+ if (prop->type == atom_utf8_string) {
+ const char *prop_name = xcb_get_property_value (prop);
+ int prop_name_len = xcb_get_property_value_length (prop);
+
+ /* can't use strcmp, since prop.name is not null terminated */
+ if (strncmp (prop_name, name, prop_name_len) == 0) {
+ w = window;
}
- if (!strcmp(OPTION, "-id")) {
- NXTOPT;
- w=0;
- sscanf(OPTION, "0x%lx", &w);
- if (!w)
- sscanf(OPTION, "%lu", &w);
- if (!w)
- Fatal_Error("Invalid window id format: %s.", OPTION);
- continue;
+ }
+ free (prop);
+ } else if (err) {
+ if (err->response_type == 0)
+ Print_X_Error (dpy, err);
+ return 0;
+ }
+ }
+
+ if (w) {
+ xcb_discard_reply (dpy, cookies->get_wm_name.sequence);
+ } else {
+#ifdef USE_XCB_ICCCM
+ xcb_get_text_property_reply_t nameprop;
+
+ if (xcb_get_wm_name_reply (dpy, cookies->get_wm_name,
+ &nameprop, &err)) {
+ /* can't use strcmp, since nameprop.name is not null terminated */
+ if (strncmp (nameprop.name, name, nameprop.name_len) == 0) {
+ w = window;
+ }
+
+ xcb_get_text_property_reply_wipe (&nameprop);
+ }
+#else
+ prop = xcb_get_property_reply (dpy, cookies->get_wm_name, &err);
+
+ if (prop) {
+ if (prop->type == XCB_ATOM_STRING) {
+ const char *prop_name = xcb_get_property_value (prop);
+ int prop_name_len = xcb_get_property_value_length (prop);
+
+ /* can't use strcmp, since prop.name is not null terminated */
+ if (strncmp (prop_name, name, prop_name_len) == 0) {
+ w = window;
}
- COPYOPT;
+ }
+ free (prop);
}
- ARGC = nargc;
-
- return(w);
+#endif
+ else if (err) {
+ if (err->response_type == 0)
+ Print_X_Error (dpy, err);
+ return 0;
+ }
+ }
+
+ if (w)
+ {
+ xcb_discard_reply (dpy, cookies->query_tree.sequence);
+ return w;
+ }
+
+ tree = xcb_query_tree_reply (dpy, cookies->query_tree, &err);
+ if (!tree) {
+ if (err->response_type == 0)
+ Print_X_Error (dpy, err);
+ return 0;
+ }
+
+ nchildren = xcb_query_tree_children_length (tree);
+ children = xcb_query_tree_children (tree);
+ child_cookies = calloc(nchildren, sizeof(struct wininfo_cookies));
+
+ if (child_cookies == NULL)
+ Fatal_Error("Failed to allocate memory in recursive_Window_With_Name");
+
+ for (i = 0; i < nchildren; i++) {
+ if (atom_net_wm_name && atom_utf8_string)
+ child_cookies[i].get_net_wm_name =
+ xcb_get_net_wm_name (dpy, children[i]);
+ child_cookies[i].get_wm_name = xcb_get_wm_name (dpy, children[i]);
+ child_cookies[i].query_tree = xcb_query_tree (dpy, children[i]);
+ }
+ xcb_flush (dpy);
+
+ for (i = 0; i < nchildren; i++) {
+ w = recursive_Window_With_Name (dpy, children[i],
+ &child_cookies[i], name);
+ if (w)
+ break;
+ }
+
+ if (w)
+ {
+ /* clean up remaining replies */
+ for (/* keep previous i */; i < nchildren; i++) {
+ if (child_cookies[i].get_net_wm_name.sequence)
+ xcb_discard_reply (dpy,
+ child_cookies[i].get_net_wm_name.sequence);
+ xcb_discard_reply (dpy, child_cookies[i].get_wm_name.sequence);
+ xcb_discard_reply (dpy, child_cookies[i].query_tree.sequence);
+ }
+ }
+
+ free (child_cookies);
+ free (tree); /* includes storage for children[] */
+ return (w);
}
-/*
- * Other_stuff: A group of routines which do common X11 tasks.
- *
- * Written by Mark Lillibridge. Last updated 7/1/87
- */
+xcb_window_t
+Window_With_Name (
+ xcb_connection_t *dpy,
+ xcb_window_t top,
+ const char *name)
+{
+ struct wininfo_cookies cookies;
+
+ atom_net_wm_name = Get_Atom (dpy, "_NET_WM_NAME");
+ atom_utf8_string = Get_Atom (dpy, "UTF8_STRING");
+
+ if (atom_net_wm_name && atom_utf8_string)
+ cookies.get_net_wm_name = xcb_get_net_wm_name (dpy, top);
+ cookies.get_wm_name = xcb_get_wm_name (dpy, top);
+ cookies.query_tree = xcb_query_tree (dpy, top);
+ xcb_flush (dpy);
+ return recursive_Window_With_Name(dpy, top, &cookies, name);
+}
/*
- * Routine to let user select a window using the mouse
+ * Standard fatal error routine - call like printf
*/
+void Fatal_Error (char *msg, ...)
+{
+ va_list args;
+ fflush (stdout);
+ fflush (stderr);
+ fprintf (stderr, "%s: error: ", program_name);
+ va_start (args, msg);
+ vfprintf (stderr, msg, args);
+ va_end (args);
+ fprintf (stderr, "\n");
+ exit (EXIT_FAILURE);
+}
-Window Select_Window(Display *dpy, int descend)
+/*
+ * Print X error information like the default Xlib error handler
+ */
+void
+Print_X_Error (
+ xcb_connection_t *dpy,
+ xcb_generic_error_t *err
+ )
{
- int status;
- Cursor cursor;
- XEvent event;
- Window target_win = None, root = RootWindow(dpy,screen);
- int buttons = 0;
-
- /* Make the target cursor */
- cursor = XCreateFontCursor(dpy, XC_crosshair);
-
- /* Grab the pointer using target cursor, letting it room all over */
- status = XGrabPointer(dpy, root, False,
- ButtonPressMask|ButtonReleaseMask, GrabModeSync,
- GrabModeAsync, root, cursor, CurrentTime);
- if (status != GrabSuccess) Fatal_Error("Can't grab the mouse.");
-
- /* Let the user select a window... */
- while ((target_win == None) || (buttons != 0)) {
- /* allow one more event */
- XAllowEvents(dpy, SyncPointer, CurrentTime);
- XWindowEvent(dpy, root, ButtonPressMask|ButtonReleaseMask, &event);
- switch (event.type) {
- case ButtonPress:
- if (target_win == None) {
- target_win = event.xbutton.subwindow; /* window selected */
- if (target_win == None) target_win = root;
- }
- buttons++;
- break;
- case ButtonRelease:
- if (buttons > 0) /* there may have been some down before we started */
- buttons--;
- break;
+ char buffer[256] = "";
+
+ if ((err == NULL) || (err->response_type != 0)) /* not an error */
+ return;
+
+ /* Todo: find a more user friendly way to show request/extension info */
+ if (err->error_code >= 128)
+ {
+ fprintf (stderr, "X Extension Error: Error code %d\n",
+ err->error_code);
}
- }
+ else
+ {
+ switch (err->error_code)
+ {
+ case XCB_REQUEST:
+ snprintf (buffer, sizeof(buffer), ": Bad Request");
+ break;
+
+ case XCB_VALUE:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Value: 0x%x", err->resource_id);
+ break;
+
+ case XCB_WINDOW:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Window: 0x%x", err->resource_id);
+ break;
+
+ case XCB_PIXMAP:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Pixmap: 0x%x", err->resource_id);
+ break;
+
+ case XCB_ATOM:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Atom: 0x%x", err->resource_id);
+ break;
+
+ case XCB_CURSOR:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Cursor: 0x%x", err->resource_id);
+ break;
+
+ case XCB_FONT:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Font: 0x%x", err->resource_id);
+ break;
+
+ case XCB_MATCH:
+ snprintf (buffer, sizeof(buffer), ": Bad Match");
+ break;
+
+ case XCB_DRAWABLE:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Drawable: 0x%x", err->resource_id);
+ break;
+
+ case XCB_ACCESS:
+ snprintf (buffer, sizeof(buffer), ": Access Denied");
+ break;
+
+ case XCB_ALLOC:
+ snprintf (buffer, sizeof(buffer),
+ ": Server Memory Allocation Failure");
+ break;
+
+ case XCB_COLORMAP:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Color: 0x%x", err->resource_id);
+ break;
+
+ case XCB_G_CONTEXT:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad GC: 0x%x", err->resource_id);
+ break;
- XUngrabPointer(dpy, CurrentTime); /* Done with pointer */
+ case XCB_ID_CHOICE:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad XID: 0x%x", err->resource_id);
+ break;
+
+ case XCB_NAME:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Name");
+ break;
- if (!descend || (target_win == root))
- return(target_win);
+ case XCB_LENGTH:
+ snprintf (buffer, sizeof(buffer),
+ ": Bad Request Length");
+ break;
+
+ case XCB_IMPLEMENTATION:
+ snprintf (buffer, sizeof(buffer),
+ ": Server Implementation Failure");
+ break;
- target_win = Find_Client(dpy, root, target_win);
+ default:
+ snprintf (buffer, sizeof(buffer), ": Unknown error");
+ break;
+ }
+ fprintf (stderr, "X Error: %d%s\n", err->error_code, buffer);
+ }
+
+ fprintf (stderr, " Request Major code: %d\n", err->major_code);
+ if (err->major_code >= 128)
+ {
+ fprintf (stderr, " Request Minor code: %d\n", err->minor_code);
+ }
- return(target_win);
+ fprintf (stderr, " Request serial number: %d\n", err->full_sequence);
}
+/*
+ * Cache for atom lookups in either direction
+ */
+struct atom_cache_entry {
+ xcb_atom_t atom;
+ const char *name;
+ xcb_intern_atom_cookie_t intern_atom;
+ struct atom_cache_entry *next;
+};
+
+static struct atom_cache_entry *atom_cache;
/*
- * Window_With_Name: routine to locate a window with a given name on a display.
- * If no window with the given name is found, 0 is returned.
- * If more than one window has the given name, the first
- * one found will be returned. Only top and its subwindows
- * are looked at. Normally, top should be the RootWindow.
+ * Send a request to the server for an atom by name
+ * Does not create the atom if it is not already present
*/
-Window Window_With_Name(
- Display *dpy,
- Window top,
- char *name)
+struct atom_cache_entry *Intern_Atom (xcb_connection_t * dpy, const char *name)
{
- Window *children, dummy;
- unsigned int nchildren;
- int i;
- Window w=0;
- char *window_name;
-
- if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
- return(top);
-
- if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
- return(0);
-
- for (i=0; i<nchildren; i++) {
- w = Window_With_Name(dpy, children[i], name);
- if (w)
- break;
- }
- if (children) XFree ((char *)children);
- return(w);
+ struct atom_cache_entry *a;
+
+ for (a = atom_cache ; a != NULL ; a = a->next) {
+ if (strcmp (a->name, name) == 0)
+ return a; /* already requested or found */
+ }
+
+ a = calloc(1, sizeof(struct atom_cache_entry));
+ if (a != NULL) {
+ a->name = name;
+ a->intern_atom = xcb_intern_atom (dpy, False, strlen (name), (name));
+ a->next = atom_cache;
+ atom_cache = a;
+ }
+ return a;
}
+/* Get an atom by name when it is needed. */
+xcb_atom_t Get_Atom (xcb_connection_t * dpy, const char *name)
+{
+ struct atom_cache_entry *a = Intern_Atom (dpy, name);
-/*
- * Standard fatal error routine - call like printf
- * Does not require dpy or screen defined.
- */
-void Fatal_Error(char *msg, ...)
+ if (a == NULL)
+ return XCB_ATOM_NONE;
+
+ if (a->atom == XCB_ATOM_NONE) {
+ xcb_intern_atom_reply_t *reply;
+
+ reply = xcb_intern_atom_reply(dpy, a->intern_atom, NULL);
+ if (reply) {
+ a->atom = reply->atom;
+ free (reply);
+ } else {
+ a->atom = -1;
+ }
+ }
+ if (a->atom == -1) /* internal error */
+ return XCB_ATOM_NONE;
+
+ return a->atom;
+}
+
+/* Get the name for an atom when it is needed. */
+const char *Get_Atom_Name (xcb_connection_t * dpy, xcb_atom_t atom)
{
- va_list args;
- fflush(stdout);
- fflush(stderr);
- fprintf(stderr, "%s: error: ", program_name);
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- fprintf(stderr, "\n");
- Close_Display();
- exit(EXIT_FAILURE);
+ struct atom_cache_entry *a;
+
+ for (a = atom_cache ; a != NULL ; a = a->next) {
+ if (a->atom == atom)
+ return a->name; /* already requested or found */
+ }
+
+ a = calloc(1, sizeof(struct atom_cache_entry));
+ if (a != NULL) {
+ xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name (dpy, atom);
+ xcb_get_atom_name_reply_t *reply
+ = xcb_get_atom_name_reply (dpy, cookie, NULL);
+
+ a->atom = atom;
+ if (reply) {
+ int len = xcb_get_atom_name_name_length (reply);
+ char *name = malloc(len + 1);
+ if (name) {
+ memcpy (name, xcb_get_atom_name_name (reply), len);
+ name[len] = '\0';
+ a->name = name;
+ }
+ free (reply);
+ }
+
+ a->next = atom_cache;
+ atom_cache = a;
+
+ return a->name;
+ }
+ return NULL;
}