diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..ed2f649 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,14 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.guess +config.log +config.status +config.sub +configure +depcomp +install-sh +libtool +ltmain.sh +missing diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..b915677 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,139 @@ +PROJECT_NAME = XCB Utility +PROJECT_NUMBER = +OUTPUT_DIRECTORY = doc/ +INPUT = xcb_util_intro image/ +IMAGE_PATH = doc/img +OUTPUT_LANGUAGE = English +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +ENUM_VALUES_PER_LINE = 1 +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = NO +SHOW_INCLUDE_FILES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 2 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = NO +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 +IGNORE_PREFIX = +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = YES +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = YES +GENERATE_XML = YES +XML_SCHEMA = +XML_DTD = +GENERATE_AUTOGEN_DEF = NO +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +GRAPHICAL_HIERARCHY = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 512 +MAX_DOT_GRAPH_HEIGHT = 512 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..88a8993 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,4 @@ + +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = atom convenient event icccm image keysyms property reply wm diff --git a/atom/.cvsignore b/atom/.cvsignore new file mode 100644 index 0000000..829115e --- /dev/null +++ b/atom/.cvsignore @@ -0,0 +1,11 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc +atoms.c +atoms.gperf +xcb_atom.h diff --git a/atom/Makefile.am b/atom/Makefile.am new file mode 100644 index 0000000..247dc6f --- /dev/null +++ b/atom/Makefile.am @@ -0,0 +1,27 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBAtom.la + +xcbinclude_HEADERS = xcb_atom.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) +LDADD = $(XCB_LIBS) + +libXCBAtom_la_SOURCES = atoms.c + +pkgconfig_DATA = xcb-atom.pc + +EXTRA_DIST = xcb-atom.pc.in + +BUILT_SOURCES = atoms.c atoms.gperf xcb_atom.h + +%.c: %.gperf + $(GPERF) --output-file $@ $*.gperf + +atoms.gperf: atomlist.m4 +xcb_atom.h: atomlist.m4 + +%: %.m4 + $(M4) $< > $@ diff --git a/atom/atomlist.m4 b/atom/atomlist.m4 new file mode 100644 index 0000000..1c84740 --- /dev/null +++ b/atom/atomlist.m4 @@ -0,0 +1,71 @@ +define(`FOREACH', `ifelse(`$1', , , `DO($1) +FOREACH(shift($@))')')FOREACH( +PRIMARY, +SECONDARY, +ARC, +ATOM, +BITMAP, +CARDINAL, +COLORMAP, +CURSOR, +CUT_BUFFER0, +CUT_BUFFER1, +CUT_BUFFER2, +CUT_BUFFER3, +CUT_BUFFER4, +CUT_BUFFER5, +CUT_BUFFER6, +CUT_BUFFER7, +DRAWABLE, +FONT, +INTEGER, +PIXMAP, +POINT, +RECTANGLE, +RESOURCE_MANAGER, +RGB_COLOR_MAP, +RGB_BEST_MAP, +RGB_BLUE_MAP, +RGB_DEFAULT_MAP, +RGB_GRAY_MAP, +RGB_GREEN_MAP, +RGB_RED_MAP, +STRING, +VISUALID, +WINDOW, +WM_COMMAND, +WM_HINTS, +WM_CLIENT_MACHINE, +WM_ICON_NAME, +WM_ICON_SIZE, +WM_NAME, +WM_NORMAL_HINTS, +WM_SIZE_HINTS, +WM_ZOOM_HINTS, +MIN_SPACE, +NORM_SPACE, +MAX_SPACE, +END_SPACE, +SUPERSCRIPT_X, +SUPERSCRIPT_Y, +SUBSCRIPT_X, +SUBSCRIPT_Y, +UNDERLINE_POSITION, +UNDERLINE_THICKNESS, +STRIKEOUT_ASCENT, +STRIKEOUT_DESCENT, +ITALIC_ANGLE, +X_HEIGHT, +QUAD_WIDTH, +WEIGHT, +POINT_SIZE, +RESOLUTION, +COPYRIGHT, +NOTICE, +FONT_NAME, +FAMILY_NAME, +FULL_NAME, +CAP_HEIGHT, +WM_CLASS, +WM_TRANSIENT_FOR, +)dnl diff --git a/atom/atoms.gperf.m4 b/atom/atoms.gperf.m4 new file mode 100644 index 0000000..63c98db --- /dev/null +++ b/atom/atoms.gperf.m4 @@ -0,0 +1,108 @@ +%{ +#include +#include +#include "xcb_atom.h" + +define(`COUNT', 0)dnl +define(`DO', `const XCBATOM $1 = { define(`COUNT', incr(COUNT))COUNT };')dnl +include(atomlist.m4)`'dnl +%} + +%readonly-tables +%pic +%null-strings +%enum +%includes +%compare-strncmp + +%struct-type +struct atom_map { int name; XCBATOM value; }; +%% +define(`DO', `$1,{ define(`COUNT', incr(COUNT))COUNT }')dnl +include(atomlist.m4)`'dnl +%% +static const char *const atom_names[] = { +define(`DO', ` "$1",')dnl +include(atomlist.m4)`'dnl +}; + +XCBATOM InternAtomPredefined(CARD16 name_len, const char *name) +{ + const struct atom_map *value = in_word_set(name, name_len); + XCBATOM ret = { None }; + if(value) + ret = value->value; + return ret; +} + +InternAtomFastCookie InternAtomFast(XCBConnection *c, BOOL only_if_exists, CARD16 name_len, const char *name) +{ + InternAtomFastCookie cookie; + + if((cookie.u.atom = InternAtomPredefined(name_len, name)).xid != None) + { + cookie.tag = TAG_VALUE; + return cookie; + } + + cookie.tag = TAG_COOKIE; + cookie.u.cookie = XCBInternAtom(c, only_if_exists, name_len, name); + return cookie; +} + +XCBATOM InternAtomFastReply(XCBConnection *c, InternAtomFastCookie cookie, XCBGenericError **e) +{ + switch(cookie.tag) + { + XCBInternAtomRep *reply; + case TAG_VALUE: + if(e) + *e = 0; + break; + case TAG_COOKIE: + reply = XCBInternAtomReply(c, cookie.u.cookie, e); + if(reply) + { + cookie.u.atom = reply->atom; + free(reply); + } + else + cookie.u.atom.xid = 0; + break; + } + return cookie.u.atom; +} + +const char *GetAtomNamePredefined(XCBATOM atom) +{ + if(atom.xid <= 0 || atom.xid > (sizeof(atom_names) / sizeof(*atom_names))) + return 0; + return atom_names[atom.xid - 1]; +} + +int GetAtomName(XCBConnection *c, XCBATOM atom, const char **namep, int *lengthp) +{ + static char buf[100]; + const char *name = GetAtomNamePredefined(atom); + int len; + XCBGetAtomNameCookie atomc; + XCBGetAtomNameRep *atomr; + if(name) + { + *namep = name; + *lengthp = strlen(name); + return 1; + } + atomc = XCBGetAtomName(c, atom); + atomr = XCBGetAtomNameReply(c, atomc, 0); + if(!atomr) + return 0; + len = XCBGetAtomNameNameLength(atomr); + if(len > sizeof(buf)) + len = sizeof(buf); + *lengthp = len; + memcpy(buf, XCBGetAtomNameName(atomr), len); + *namep = buf; + free(atomr); + return 1; +} diff --git a/atom/xcb-atom.pc.in b/atom/xcb-atom.pc.in new file mode 100644 index 0000000..cda6d42 --- /dev/null +++ b/atom/xcb-atom.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBAtom +Description: XCB atom cache +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBAtom @LIBS@ +Cflags: -I${includedir} diff --git a/atom/xcb_atom.h.m4 b/atom/xcb_atom.h.m4 new file mode 100644 index 0000000..7a88cfc --- /dev/null +++ b/atom/xcb_atom.h.m4 @@ -0,0 +1,26 @@ +#ifndef ATOMS_H +#define ATOMS_H + +enum tag_t { + TAG_COOKIE, + TAG_VALUE +}; +typedef struct { + enum tag_t tag; + union { + XCBInternAtomCookie cookie; + XCBATOM atom; + } u; +} InternAtomFastCookie; + +XCBATOM InternAtomPredefined(CARD16 name_len, const char *name); +InternAtomFastCookie InternAtomFast(XCBConnection *c, BOOL only_if_exists, CARD16 name_len, const char *name); +XCBATOM InternAtomFastReply(XCBConnection *c, InternAtomFastCookie cookie, XCBGenericError **e); + +const char *GetAtomNamePredefined(XCBATOM atom); +int GetAtomName(XCBConnection *c, XCBATOM atom, const char **namep, int *lengthp); + +define(`DO', `extern const XCBATOM $1;')dnl +include(atomlist.m4)`'dnl + +#endif /* ATOMS_H */ diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..d68a142 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,3 @@ +#! /bin/sh +autoreconf -v --install || exit 1 +./configure "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..4f5bbd7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,33 @@ +AC_PREREQ(2.57) +AC_INIT([xcb-util],0.1,[jamey@minilop.net]) +AC_CONFIG_SRCDIR([Makefile.am]) +AM_INIT_AUTOMAKE([foreign dist-bzip2]) + +AC_CHECK_PROGS(M4, m4) +AC_CHECK_PROGS(GPERF, gperf, [no]) +if test $GPERF = "no"; then + AC_MSG_ERROR([Can't find gperf, please install it and try again]) +fi +AC_PROG_CC +AC_PROG_LIBTOOL + +xcbincludedir='${includedir}/X11/XCB' +AC_SUBST(xcbincludedir) + +pkgconfigdir='${libdir}/pkgconfig' +AC_SUBST(pkgconfigdir) + +PKG_CHECK_MODULES(XCB, xcb) + +AC_OUTPUT([Makefile + convenient/Makefile convenient/xcb-aux.pc + reply/Makefile reply/xcb-reply.pc + image/Makefile image/xcb-image.pc + atom/Makefile atom/xcb-atom.pc + event/Makefile event/xcb-event.pc + keysyms/Makefile keysyms/xcb-keysyms.pc + property/Makefile property/xcb-property.pc + icccm/Makefile icccm/xcb-icccm.pc + wm/Makefile wm/xcb-wm.pc + xcb_util_intro + ]) diff --git a/convenient/.cvsignore b/convenient/.cvsignore new file mode 100644 index 0000000..65e939d --- /dev/null +++ b/convenient/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc diff --git a/convenient/Makefile.am b/convenient/Makefile.am new file mode 100644 index 0000000..c0e9a0b --- /dev/null +++ b/convenient/Makefile.am @@ -0,0 +1,16 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBAux.la + +xcbinclude_HEADERS = xcb_aux.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) +LDADD = $(XCB_LIBS) + +libXCBAux_la_SOURCES = xcb_aux.c + +pkgconfig_DATA = xcb-aux.pc + +EXTRA_DIST=xcb-aux.pc.in diff --git a/convenient/xcb-aux.pc.in b/convenient/xcb-aux.pc.in new file mode 100644 index 0000000..4cb5569 --- /dev/null +++ b/convenient/xcb-aux.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBAux library +Description: XCB convenient functions +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBAux @LIBS@ +Cflags: -I${includedir} diff --git a/convenient/xcb_aux.c b/convenient/xcb_aux.c new file mode 100644 index 0000000..6f11257 --- /dev/null +++ b/convenient/xcb_aux.c @@ -0,0 +1,63 @@ +#include +#include + +#include + +/* Connection related functions */ + +CARD8 +XCBAuxGetDepth (XCBConnection *c, + XCBSCREEN *screen) +{ + XCBDRAWABLE drawable; + XCBGetGeometryRep *geom; + int depth; + + drawable.window = screen->root; + geom = XCBGetGeometryReply (c, XCBGetGeometry(c, drawable), 0); + + if (!geom) { + perror ("GetGeometry(root) failed"); + exit (0); + } + + depth = geom->depth; + free (geom); + + return depth; +} + +XCBSCREEN * +XCBAuxGetScreen (XCBConnection *c, + int screen) +{ + XCBSCREENIter i = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)); + for (; i.rem; --screen, XCBSCREENNext(&i)) + if (screen == 0) + return i.data; + return 0; +} + +XCBVISUALTYPE * +XCBAuxGetVisualtype (XCBConnection *c, + int scr, + XCBVISUALID vid) +{ + XCBSCREEN *screen; + XCBDEPTH *depth; + XCBVISUALTYPEIter iter; + int cur; + + screen = XCBAuxGetScreen (c, scr); + if (!screen) return NULL; + + depth = XCBSCREENAllowedDepthsIter(screen).data; + if (!depth) return NULL; + + iter = XCBDEPTHVisualsIter(depth); + for (cur = 0 ; cur < iter.rem ; XCBVISUALTYPENext(&iter), ++cur) + if (vid.id == iter.data->visual_id.id) + return iter.data; + + return NULL; +} diff --git a/convenient/xcb_aux.h b/convenient/xcb_aux.h new file mode 100644 index 0000000..c948475 --- /dev/null +++ b/convenient/xcb_aux.h @@ -0,0 +1,16 @@ +#ifndef __XCB_AUX_H__ +#define __XCB_AUX_H__ + + +CARD8 XCBAuxGetDepth (XCBConnection *c, + XCBSCREEN *screen); + +XCBSCREEN *XCBAuxGetScreen (XCBConnection *c, + int screen); + +XCBVISUALTYPE *XCBAuxGetVisualtype (XCBConnection *c, + int screen, + XCBVISUALID vid); + + +#endif /* __XCB_CONVENIENT_H__ */ diff --git a/event/.cvsignore b/event/.cvsignore new file mode 100644 index 0000000..65e939d --- /dev/null +++ b/event/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc diff --git a/event/Makefile.am b/event/Makefile.am new file mode 100644 index 0000000..2b83c56 --- /dev/null +++ b/event/Makefile.am @@ -0,0 +1,16 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBEvent.la + +xcbinclude_HEADERS = xcb_event.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) +LDADD = $(XCB_LIBS) + +libXCBEvent_la_SOURCES = events.c + +pkgconfig_DATA = xcb-event.pc + +EXTRA_DIST = xcb-event.pc.in diff --git a/event/events.c b/event/events.c new file mode 100644 index 0000000..6649eee --- /dev/null +++ b/event/events.c @@ -0,0 +1,88 @@ +#include +#include + +#include "xcb_event.h" + +typedef struct { + GenericEventHandler handler; + void *data; +} EventHandler; + +struct EventHandlers { + EventHandler event[126]; + EventHandler error[256]; + XCBConnection *c; +}; + +EventHandlers *allocEventHandlers(XCBConnection *c) +{ + EventHandlers *ret = calloc(1, sizeof(EventHandlers)); + if(ret) + ret->c = c; + return ret; +} + +void freeEventHandlers(EventHandlers *evenths) +{ + free(evenths); +} + +XCBConnection *getXCBConnection(EventHandlers *evenths) +{ + return evenths->c; +} + +static EventHandler *getEventHandler(EventHandlers *evenths, int event) +{ + assert(event < 256); + event &= 0x7f; + assert(event >= 2); + return &evenths->event[event - 2]; +} + +static EventHandler *getErrorHandler(EventHandlers *evenths, int error) +{ + assert(error >= 0 && error < 256); + return &evenths->error[error]; +} + +static int handleEvent(EventHandlers *evenths, XCBGenericEvent *event) +{ + EventHandler *eventh = 0; + assert(event->response_type != 1); + + if(event->response_type == 0) + eventh = getErrorHandler(evenths, ((XCBGenericError *) event)->error_code); + else + eventh = getEventHandler(evenths, event->response_type); + + if(eventh->handler) + return eventh->handler(eventh->data, evenths->c, event); + return 0; +} + +void eventLoop(EventHandlers *evenths) +{ + XCBGenericEvent *event; + while((event = XCBWaitForEvent(evenths->c))) + { + handleEvent(evenths, event); + free(event); + } +} + +static void setHandler(GenericEventHandler handler, void *data, EventHandler *place) +{ + EventHandler eventh = { handler, data }; + *place = eventh; +} + +void setEventHandler(EventHandlers *evenths, int event, GenericEventHandler handler, void *data) +{ + setHandler(handler, data, getEventHandler(evenths, event)); +} + +void setErrorHandler(EventHandlers *evenths, int error, GenericErrorHandler handler, void *data) +{ + setHandler((GenericEventHandler) handler, data, getErrorHandler(evenths, error)); +} diff --git a/event/xcb-event.pc.in b/event/xcb-event.pc.in new file mode 100644 index 0000000..863fc6e --- /dev/null +++ b/event/xcb-event.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBEvent +Description: XCB event callback interface +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBEvent @LIBS@ +Cflags: -I${includedir} diff --git a/event/xcb_event.h b/event/xcb_event.h new file mode 100644 index 0000000..5d94e4b --- /dev/null +++ b/event/xcb_event.h @@ -0,0 +1,59 @@ +#ifndef EVENTS_H +#define EVENTS_H + +#include + +typedef struct EventHandlers EventHandlers; +EventHandlers *allocEventHandlers(XCBConnection *c); +void freeEventHandlers(EventHandlers *evenths); +XCBConnection *getXCBConnection(EventHandlers *evenths); + +void eventLoop(EventHandlers *evenths); + +typedef int (*GenericEventHandler)(void *data, XCBConnection *c, XCBGenericEvent *event); +typedef int (*GenericErrorHandler)(void *data, XCBConnection *c, XCBGenericError *error); + +void setEventHandler(EventHandlers *evenths, int event, GenericEventHandler handler, void *data); +void setErrorHandler(EventHandlers *evenths, int error, GenericErrorHandler handler, void *data); + +#define MAKE_HANDLER(cls,kind) \ +static inline void set##kind##cls##Handler(EventHandlers *evenths, int (*handler)(void *, XCBConnection *, XCB##kind##cls *), void *data) \ +{ \ + set##cls##Handler(evenths, XCB##kind, (GenericEventHandler) handler, data); \ +} + +MAKE_HANDLER(Event, KeyPress) +MAKE_HANDLER(Event, KeyRelease) +MAKE_HANDLER(Event, ButtonPress) +MAKE_HANDLER(Event, ButtonRelease) +MAKE_HANDLER(Event, MotionNotify) +MAKE_HANDLER(Event, EnterNotify) +MAKE_HANDLER(Event, LeaveNotify) +MAKE_HANDLER(Event, FocusIn) +MAKE_HANDLER(Event, FocusOut) +MAKE_HANDLER(Event, KeymapNotify) +MAKE_HANDLER(Event, Expose) +MAKE_HANDLER(Event, GraphicsExposure) +MAKE_HANDLER(Event, NoExposure) +MAKE_HANDLER(Event, VisibilityNotify) +MAKE_HANDLER(Event, CreateNotify) +MAKE_HANDLER(Event, DestroyNotify) +MAKE_HANDLER(Event, UnmapNotify) +MAKE_HANDLER(Event, MapNotify) +MAKE_HANDLER(Event, MapRequest) +MAKE_HANDLER(Event, ReparentNotify) +MAKE_HANDLER(Event, ConfigureNotify) +MAKE_HANDLER(Event, ConfigureRequest) +MAKE_HANDLER(Event, GravityNotify) +MAKE_HANDLER(Event, ResizeRequest) +MAKE_HANDLER(Event, CirculateNotify) +MAKE_HANDLER(Event, CirculateRequest) +MAKE_HANDLER(Event, PropertyNotify) +MAKE_HANDLER(Event, SelectionClear) +MAKE_HANDLER(Event, SelectionRequest) +MAKE_HANDLER(Event, SelectionNotify) +MAKE_HANDLER(Event, ColormapNotify) +MAKE_HANDLER(Event, ClientMessage) +MAKE_HANDLER(Event, MappingNotify) + +#endif /* EVENTS_H */ diff --git a/gendoc b/gendoc new file mode 100755 index 0000000..7b53f45 --- /dev/null +++ b/gendoc @@ -0,0 +1,7 @@ +#!/bin/sh +rm -rf ./doc/html ./doc/latex ./doc/man +doxygen +rm -f xcb_util_docs.tar xcb_util_docs.tar.gz +tar -cvf xcb_util_docs.tar doc/html doc/man doc/latex doc/xml +gzip -9 xcb_util_docs.tar +exit 0 diff --git a/icccm/.cvsignore b/icccm/.cvsignore new file mode 100644 index 0000000..65e939d --- /dev/null +++ b/icccm/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc diff --git a/icccm/Makefile.am b/icccm/Makefile.am new file mode 100644 index 0000000..f7f8a5a --- /dev/null +++ b/icccm/Makefile.am @@ -0,0 +1,19 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBICCCM.la + +xcbinclude_HEADERS = xcb_icccm.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) -I../atom -I../event -I../property +LDADD = $(XCB_LIBS) \ + -L../atom -lXCBAtom \ + -L../event -lXCBEvent \ + -L../property -lXCBProperty + +libXCBICCCM_la_SOURCES = icccm.c + +pkgconfig_DATA = xcb-icccm.pc + +EXTRA_DIST = xcb-icccm.pc.in diff --git a/icccm/icccm.c b/icccm/icccm.c new file mode 100644 index 0000000..46d2c5a --- /dev/null +++ b/icccm/icccm.c @@ -0,0 +1,831 @@ +#include +#include +#include "xcb_icccm.h" +#include "xcb_atom.h" + +/* WM_NAME */ + +void +SetWMName (XCBConnection *c, + XCBWINDOW window, + XCBATOM encoding, + CARD32 name_len, + const char *name) +{ + XCBChangeProperty(c, PropModeReplace, window, WM_NAME, encoding, 8, name_len, name); +} + +int +GetWMName (XCBConnection *c, + XCBWINDOW window, + CARD8 *format, + XCBATOM *encoding, + CARD32 *name_len, + char **name) +{ + XCBGetPropertyCookie cookie; + XCBGetPropertyRep *reply; + cookie = GetAnyProperty(c, 0, window, WM_NAME, 128); + reply = XCBGetPropertyReply(c, cookie, 0); + if(!reply) + return 0; + *format = reply->format; + *encoding = reply->type; + *name_len = XCBGetPropertyValueLength(reply) * *format / 8; + if(reply->bytes_after) + { + cookie = XCBGetProperty(c, 0, window, WM_NAME, reply->type, 0, *name_len); + free(reply); + reply = XCBGetPropertyReply(c, cookie, 0); + if(!reply) + return 0; + } + memmove(reply, XCBGetPropertyValue(reply), *name_len); + *name = (char *) reply; + return 1; +} + +void +WatchWMName (PropertyHandlers *prophs, + CARD32 long_len, + GenericPropertyHandler handler, + void *data) +{ + SetPropertyHandler(prophs, WM_NAME, long_len, handler, data); +} + +/* WM_ICON_NAME */ + +void +SetWMIconName (XCBConnection *c, + XCBWINDOW window, + XCBATOM encoding, + CARD32 name_len, + const char *name) +{ + XCBChangeProperty(c, PropModeReplace, window, WM_ICON_NAME, encoding, 8, name_len, name); +} + +void +WatchWMIconName (PropertyHandlers *prophs, + CARD32 long_len, + GenericPropertyHandler handler, + void *data) +{ + SetPropertyHandler(prophs, WM_ICON_NAME, long_len, handler, data); +} + +/* WM_SIZE_HINTS */ + +typedef enum { + USPosition = 1 << 0, + USSize = 1 << 1, + PPosition = 1 << 2, + PSize = 1 << 3, + PMinSize = 1 << 4, + PMaxSize = 1 << 5, + PResizeInc = 1 << 6, + PAspect = 1 << 7, + PBaseSize = 1 << 8, + PWinGravity = 1 << 9 +} SizeHintsFlags; + +struct SizeHints { + CARD32 flags; + INT32 x, y, width, height; + INT32 min_width, min_height; + INT32 max_width, max_height; + INT32 width_inc, height_inc; + INT32 min_aspect_num, min_aspect_den; + INT32 max_aspect_num, max_aspect_den; + INT32 base_width, base_height; + CARD32 win_gravity; +}; + +SizeHints * +AllocSizeHints() +{ + return calloc(1, sizeof(SizeHints)); +} + +void +FreeSizeHints(SizeHints *hints) +{ + free(hints); +} + +void +SizeHintsGetPosition (SizeHints *hints, + INT32 *x, + INT32 *y) +{ + *x = hints->x; + *y = hints->y; +} + +void +SizeHintsGetSize (SizeHints *hints, + INT32 *width, + INT32 *height) +{ + *width = hints->width; + *height = hints->height; +} + +void +SizeHintsGetMinSize (SizeHints *hints, + INT32 *min_width, + INT32 *min_height) +{ + *min_width = hints->min_width; + *min_height = hints->min_height; +} + +void +SizeHintsGetMaxSize (SizeHints *hints, + INT32 *max_width, + INT32 *max_height) +{ + *max_width = hints->max_width; + *max_height = hints->max_height; +} + +void +SizeHintsGetIncrease (SizeHints *hints, + INT32 *width_inc, + INT32 *height_inc) +{ + *width_inc = hints->width_inc; + *height_inc = hints->height_inc; +} + +void +SizeHintsGetMinAspect (SizeHints *hints, + INT32 *min_aspect_num, + INT32 *min_aspect_den) +{ + *min_aspect_num = hints->min_aspect_num; + *min_aspect_den = hints->min_aspect_den; +} + +void +SizeHintsGetMaxAspect (SizeHints *hints, + INT32 *max_aspect_num, + INT32 *max_aspect_den) +{ + *max_aspect_num = hints->max_aspect_num; + *max_aspect_den = hints->max_aspect_den; +} + +void +SizeHintsGetBaseSize (SizeHints *hints, + INT32 *base_width, + INT32 *base_height) +{ + *base_width = hints->base_width; + *base_height = hints->base_height; +} + +CARD32 +SizeHintsGetWinGravity (SizeHints *hints) +{ + return hints->win_gravity; +} + +BOOL +SizeHintsIsUSPosition (SizeHints *hints) +{ + return (hints->flags & USPosition); +} + +BOOL +SizeHintsIsUSSize (SizeHints *hints) +{ + return (hints->flags & USSize); +} + +BOOL +SizeHintsIsPPosition (SizeHints *hints) +{ + return (hints->flags & PPosition); +} + +BOOL +SizeHintsIsPSize (SizeHints *hints) +{ + return (hints->flags & PSize); +} + +BOOL +SizeHintsIsPMinSize (SizeHints *hints) +{ + return (hints->flags & PMinSize); +} + +BOOL +SizeHintsIsPMaxSize (SizeHints *hints) +{ + return (hints->flags & PMaxSize); +} + +BOOL +SizeHintsIsPResizeInc (SizeHints *hints) +{ + return (hints->flags & PResizeInc); +} + +BOOL +SizeHintsIsPAspect (SizeHints *hints) +{ + return (hints->flags & PAspect); +} + +BOOL +SizeHintsIsPBaseSize (SizeHints *hints) +{ + return (hints->flags & PBaseSize); +} + +BOOL +SizeHintsIsPWinGravity (SizeHints *hints) +{ + return (hints->flags & PWinGravity); +} + +void +SizeHintsSetFlagNone (SizeHints *hints) +{ + hints->flags = 0; +} + +void +SizeHintsSetFlagUSPosition (SizeHints *hints) +{ + hints->flags = USPosition; +} + +void +SizeHintsSetFlagUSSize (SizeHints *hints) +{ + hints->flags = USSize; +} + +void +SizeHintsSetFlagPPosition (SizeHints *hints) +{ + hints->flags = PPosition; +} + +void +SizeHintsSetFlagPSize (SizeHints *hints) +{ + hints->flags = PSize; +} + +void +SizeHintsSetFlagPMinSize (SizeHints *hints) +{ + hints->flags = PMinSize; +} + +void +SizeHintsSetFlagPMaxSize (SizeHints *hints) +{ + hints->flags = PMaxSize; +} + +void +SizeHintsSetFlagPResizeInc (SizeHints *hints) +{ + hints->flags = PResizeInc; +} + +void +SizeHintsSetFlagPAspect (SizeHints *hints) +{ + hints->flags = PAspect; +} + +void +SizeHintsSetFlagPBaseSize (SizeHints *hints) +{ + hints->flags = PBaseSize; +} + +void +SizeHintsSetFlagPWinGravity (SizeHints *hints) +{ + hints->flags = PWinGravity; +} + +void +SizeHintsSetPosition (SizeHints *hints, + int user_specified, + INT32 x, + INT32 y) +{ + hints->flags &= ~(USPosition | PPosition); + if (user_specified) + hints->flags |= USPosition; + else + hints->flags |= PPosition; + hints->x = x; + hints->y = y; +} + +void +SizeHintsSetSize (SizeHints *hints, + int user_specified, + INT32 width, + INT32 height) +{ + hints->flags &= ~(USSize | PSize); + if (user_specified) + hints->flags |= USSize; + else + hints->flags |= PSize; + hints->width = width; + hints->height = height; +} + +void +SizeHintsSetMinSize (SizeHints *hints, + INT32 min_width, + INT32 min_height) +{ + hints->flags |= PMinSize; + hints->min_width = min_width; + hints->min_height = min_height; +} + +void +SizeHintsSetMaxSize (SizeHints *hints, + INT32 max_width, + INT32 max_height) +{ + hints->flags |= PMaxSize; + hints->max_width = max_width; + hints->max_height = max_height; +} + +void +SizeHintsSetResizeInc (SizeHints *hints, + INT32 width_inc, + INT32 height_inc) +{ + hints->flags |= PResizeInc; + hints->width_inc = width_inc; + hints->height_inc = height_inc; +} + +void +SizeHintsSetAspect (SizeHints *hints, + INT32 min_aspect_num, + INT32 min_aspect_den, + INT32 max_aspect_num, + INT32 max_aspect_den) +{ + hints->flags |= PAspect; + hints->min_aspect_num = min_aspect_num; + hints->min_aspect_den = min_aspect_den; + hints->max_aspect_num = max_aspect_num; + hints->max_aspect_den = max_aspect_den; +} + +void +SizeHintsSetBaseSize (SizeHints *hints, + INT32 base_width, + INT32 base_height) +{ + hints->flags |= PBaseSize; + hints->base_width = base_width; + hints->base_height = base_height; +} + +void +SizeHintsSetWinGravity (SizeHints *hints, + CARD8 win_gravity) +{ + hints->flags |= PWinGravity; + hints->win_gravity = win_gravity; +} + +void +SetWMSizeHints (XCBConnection *c, + XCBWINDOW window, + XCBATOM property, + SizeHints *hints) +{ + XCBChangeProperty(c, PropModeReplace, window, property, WM_SIZE_HINTS, 32, sizeof(*hints) / 4, hints); +} + +int +GetWMSizeHints (XCBConnection *c, + XCBWINDOW window, + XCBATOM property, + SizeHints *hints, + long *supplied) +{ + XCBGetPropertyCookie cookie; + XCBGetPropertyRep *rep; + + cookie = XCBGetProperty (c, 0, window, + property, WM_SIZE_HINTS, + 0L, 18); /* NumPropSizeElements = 18 (ICCCM version 1) */ + rep = XCBGetPropertyReply (c, cookie, 0); + if (!rep) + return 0; + + if ((rep->type.xid == WM_SIZE_HINTS.xid) && + ((rep->format == 8) || + (rep->format == 16) || + (rep->format == 32)) && + (rep->value_len >= 15)) /* OldNumPropSizeElements = 15 (pre-ICCCM) */ + { + long length; + unsigned char *prop; + + length = XCBGetPropertyValueLength (rep); + /* FIXME: in GetProp.c of xcl, one move the memory. + * Should we do that too ? */ + prop = (unsigned char *)malloc(sizeof(unsigned char)*length); + memcpy(prop, XCBGetPropertyValue (rep), length); + prop[length] = '\0'; + hints = (SizeHints *)strdup (prop); + + *supplied = (USPosition | USSize | + PPosition | PSize | + PMinSize | PMaxSize | + PResizeInc | PAspect); + if (rep->value_len >= 18) /* NumPropSizeElements = 18 (ICCCM version 1) */ + *supplied |= (PBaseSize | PWinGravity); + else + { + hints->base_width = 0; + hints->base_height = 0; + hints->win_gravity = 0; + } + hints->flags &= (*supplied); /* get rid of unwanted bits */ + + free (rep); + + return 1; + } + + hints = NULL; + free (rep); + + return 0; +} + +/* WM_NORMAL_HINTS */ + +void +SetWMNormalHints (XCBConnection *c, + XCBWINDOW window, + SizeHints *hints) +{ + SetWMSizeHints(c, window, WM_NORMAL_HINTS, hints); +} + +int +GetWMNormalHints (XCBConnection *c, + XCBWINDOW window, + SizeHints *hints, + long *supplied) +{ + return (GetWMSizeHints (c, window, WM_NORMAL_HINTS, hints, supplied)); +} + +/* WM_HINTS */ + +struct WMHints { + INT32 flags; /* marks which fields in this structure are defined */ + BOOL input; /* does this application rely on the window manager + to get keyboard input? */ + INT32 initial_state; /* see below */ + XCBPIXMAP icon_pixmap; /* pixmap to be used as icon */ + XCBWINDOW icon_window; /* window to be used as icon */ + INT32 icon_x; /* initial position of icon */ + INT32 icon_y; + XCBPIXMAP icon_mask; /* icon mask bitmap */ + XCBWINDOW window_group; /* id of related window group */ + /* this structure may be extended in the future */ +}; + +typedef enum { + XCBWMInputHint = (1L << 0), + XCBWMStateHint = (1L << 1), + XCBWMIconPixmapHint = (1L << 2), + XCBWMIconWindowHint = (1L << 3), + XCBWMIconPositionHint = (1L << 4), + XCBWMIconMaskHint = (1L << 5), + XCBWMWindowGroupHint = (1L << 6), + XCBWMXUrgencyHint = (1L << 8) +} XCBWM; + +#define XCBWMAllHints (InputHint | StateHint | IconPixmapHint | \ + IconWindowHint| IconPositionHint | IconMaskHint | \ + WindowGroupHint) + +BOOL +WMHintsGetInput(WMHints *hints) +{ + return hints->input; +} + +XCBPIXMAP +WMHintsGetIconPixmap(WMHints *hints) +{ + return hints->icon_pixmap; +} + +XCBPIXMAP +WMHintsGetIconMask(WMHints *hints) +{ + return hints->icon_mask; +} + +XCBWINDOW +WMHintsGetIconWindow(WMHints *hints) +{ + return hints->icon_window; +} + +XCBWINDOW +WMHintsGetWindowGroup(WMHints *hints) +{ + return hints->window_group; +} + + +BOOL +WMHintsIsInputHint(WMHints *hints) +{ + return (hints->flags & XCBWMInputHint); +} + +BOOL +WMHintsIsStateHint(WMHints *hints) +{ + return (hints->flags & XCBWMStateHint); +} + +BOOL +WMHintsIsIconPixmapHint(WMHints *hints) +{ + return (hints->flags & XCBWMIconPixmapHint); +} + +BOOL +WMHintsIsIconWindowHint(WMHints *hints) +{ + return (hints->flags & XCBWMIconWindowHint); +} + +BOOL +WMHintsIsIconPositionHint(WMHints *hints) +{ + return (hints->flags & XCBWMIconPositionHint); +} + +BOOL +WMHintsIsIconMaskHint(WMHints *hints) +{ + return (hints->flags & XCBWMIconMaskHint); +} + +BOOL +WMHintsIsWindowGroupHint(WMHints *hints) +{ + return (hints->flags & XCBWMWindowGroupHint); +} + +BOOL +WMHintsIsXUrgencyHint(WMHints *hints) +{ + return (hints->flags & XCBWMXUrgencyHint); +} + +BOOL +WMHintsStateIsWithdrawn(WMHints *hints) +{ + return (hints->initial_state == XCBWMWithdrawnState); +} + +BOOL +WMHintsStateIsNormal(WMHints *hints) +{ + return (hints->initial_state == XCBWMNormalState); +} + +BOOL +WMHintsStateIsIconic(WMHints *hints) +{ + return (hints->initial_state == XCBWMIconicState); +} + +void +WMHintsSetInput(WMHints *hints, BOOL input) +{ + hints->input = input; + hints->flags |= XCBWMInputHint; +} + +void +WMHintsSetIconic(WMHints *hints) +{ + hints->initial_state = XCBWMIconicState; + hints->flags |= XCBWMStateHint; +} + +void +WMHintsSetNormal(WMHints *hints) +{ + hints->initial_state = XCBWMNormalState; + hints->flags |= XCBWMStateHint; +} + +void +WMHintsSetWithdrawn(WMHints *hints) +{ + hints->initial_state = XCBWMWithdrawnState; + hints->flags |= XCBWMStateHint; +} + +void +WMHintsSetNone(WMHints *hints) +{ + hints->flags &= ~XCBWMStateHint; +} + +void +WMHintsSetUrgent(WMHints *hints) +{ + hints->flags |= XCBWMXUrgencyHint; +} + +void +WMHintsSetIconPixmap(WMHints *hints, XCBPIXMAP icon_pixmap) +{ + hints->icon_pixmap = icon_pixmap; + hints->flags |= XCBWMIconPixmapHint; +} + +void +WMHintsSetIconMask(WMHints *hints, XCBPIXMAP icon_mask) +{ + hints->icon_mask = icon_mask; + hints->flags |= XCBWMIconMaskHint; +} + +void +WMHintsSetIconWindow(WMHints *hints, XCBWINDOW icon_window) +{ + hints->icon_window = icon_window; + hints->flags |= XCBWMIconWindowHint; +} + +void +WMHintsSetWindowGroup(WMHints *hints, XCBWINDOW window_group) +{ + hints->window_group = window_group; + hints->flags |= XCBWMWindowGroupHint; +} + + + + + +WMHints * +GetWMHints (XCBConnection *c, + XCBWINDOW window) +{ + XCBGetPropertyCookie cookie; + XCBGetPropertyRep *rep; + WMHints *hints; + long length; + unsigned char *prop; + + cookie = XCBGetProperty (c, 0, window, + WM_HINTS, WM_HINTS, + 0L, NumWMHintsElements); + rep = XCBGetPropertyReply (c, cookie, 0); + if (!rep) + return NULL; + + if ((rep->type.xid != WM_HINTS.xid) || + (rep->value_len < (NumWMHintsElements - 1)) || + (rep->format != 32)) + { + free (rep); + return NULL; + } + hints = (WMHints *)calloc (1, (unsigned)sizeof (WMHints)); + if (!hints) + { + free (rep); + return NULL; + } + + length = XCBGetPropertyValueLength (rep); + prop = (unsigned char *) XCBGetPropertyValue (rep); + prop[length] = '\0'; + hints = (WMHints *)strdup (prop); + if (rep->value_len < NumWMHintsElements) + hints->window_group.xid = 0; + + return hints; +} + +/* WM_PROTOCOLS */ + +void +SetWMProtocols (XCBConnection *c, + XCBWINDOW window, + CARD32 list_len, + XCBATOM *list) +{ + InternAtomFastCookie proto; + XCBATOM WM_PROTOCOLS; + + proto = InternAtomFast(c, 0, sizeof("WM_PROTOCOLS") - 1, "WM_PROTOCOLS"); + WM_PROTOCOLS = InternAtomFastReply(c, proto, 0); + + XCBChangeProperty(c, PropModeReplace, window, WM_PROTOCOLS, ATOM, 32, list_len, list); +} + +int +GetWMProtocols (XCBConnection *c, + XCBWINDOW window, + CARD32 *list_len, + XCBATOM **list) +{ + XCBGetPropertyCookie cookie; + XCBGetPropertyRep *rep; + XCBATOM property; + + property = InternAtomFastReply(c, + InternAtomFast(c, + 0, + strlen("WM_PROTOCOLS"), + "WM_PROTOCOLS"), + NULL); + cookie = XCBGetProperty(c, 0, window, + property, ATOM, 0, 1000000L); + rep = XCBGetPropertyReply(c, cookie, 0); + if (!rep) + return 0; + if ((rep->type.xid == ATOM.xid) || + (rep->format == 32)) + { + int length; + + length = XCBGetPropertyValueLength(rep); + *list_len = length; + *list = (XCBATOM *)malloc(sizeof(XCBATOM) * length); + if (!(*list)) + { + free(rep); + return 0; + } + memcpy(*list, XCBGetPropertyValue(rep), length); + free(rep); + return 1; + } + return 0; +} + +#if HAS_DISCRIMINATED_NAME +#include +static char *makename(const char *fmt, ...) +{ + char *ret; + int n; + va_list ap; + va_start(ap, fmt); + n = vasprintf(&ret, fmt, ap); + va_end(ap); + if(n < 0) + return 0; + return ret; +} + +char *DiscriminatedAtomNameByScreen(const char *base, CARD8 screen) +{ + return makename("%s_S%u", base, screen); +} + +char *DiscriminatedAtomNameByResource(const char *base, CARD32 resource) +{ + return makename("%s_R%08X", base, resource); +} + +char *DiscriminatedAtomNameUnique(const char *base, CARD32 id) +{ + if(base) + return makename("%s_U%lu", base, id); + else + return makename("U%lu", id); +} +#endif diff --git a/icccm/xcb-icccm.pc.in b/icccm/xcb-icccm.pc.in new file mode 100644 index 0000000..c1c4e2d --- /dev/null +++ b/icccm/xcb-icccm.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBICCCM +Description: XCB ICCCM binding +Version: @PACKAGE_VERSION@ +Requires: xcb xcb-atom xcb-event xcb-property +Libs: -L${libdir} -lXCBICCCM @LIBS@ +Cflags: -I${includedir} diff --git a/icccm/xcb_icccm.h b/icccm/xcb_icccm.h new file mode 100644 index 0000000..0bc3459 --- /dev/null +++ b/icccm/xcb_icccm.h @@ -0,0 +1,216 @@ +#ifndef ICCCM_H +#define ICCCM_H + +#include +#include "xcb_property.h" + +/* WM_NAME */ + +void SetWMName (XCBConnection *c, + XCBWINDOW window, + XCBATOM encoding, + CARD32 name_len, + const char *name); + +int GetWMName (XCBConnection *c, + XCBWINDOW window, + CARD8 *format, + XCBATOM *encoding, + CARD32 *name_len, + char **name); + +void WatchWMName (PropertyHandlers *prophs, + CARD32 long_len, + GenericPropertyHandler handler, + void *data); + +/* WM_ICON_NAME */ + +void SetWMIconName (XCBConnection *c, + XCBWINDOW window, + XCBATOM encoding, + CARD32 name_len, + const char *name); + +void WatchWMIconName (PropertyHandlers *prophs, + CARD32 long_len, + GenericPropertyHandler handler, + void *data); + +/* WM_SIZE_HINTS */ + +typedef struct SizeHints SizeHints; + +SizeHints *AllocSizeHints (); + +void FreeSizeHints (SizeHints *hints); + +void SizeHintsGetPosition (SizeHints *hints, + INT32 *x, + INT32 *y); +void SizeHintsGetSize (SizeHints *hints, + INT32 *width, + INT32 *height); +void SizeHintsGetMinSize (SizeHints *hints, + INT32 *min_width, + INT32 *min_height); +void SizeHintsGetMaxSize (SizeHints *hints, + INT32 *max_width, + INT32 *max_height); +void SizeHintsGetIncrease (SizeHints *hints, + INT32 *width_inc, + INT32 *height_inc); +void SizeHintsGetMinAspect (SizeHints *hints, + INT32 *min_aspect_num, + INT32 *min_aspect_den); +void SizeHintsGetMaxAspect (SizeHints *hints, + INT32 *max_aspect_num, + INT32 *max_aspect_den); +void SizeHintsGetBaseSize (SizeHints *hints, + INT32 *base_width, + INT32 *base_height); +CARD32 SizeHintsGetWinGravity (SizeHints *hints); + +BOOL SizeHintsIsUSPosition (SizeHints *hints); +BOOL SizeHintsIsUSSize (SizeHints *hints); +BOOL SizeHintsIsPPosition (SizeHints *hints); +BOOL SizeHintsIsPSize (SizeHints *hints); +BOOL SizeHintsIsPMinSize (SizeHints *hints); +BOOL SizeHintsIsPMaxSize (SizeHints *hints); +BOOL SizeHintsIsPResizeInc (SizeHints *hints); +BOOL SizeHintsIsPAspect (SizeHints *hints); +BOOL SizeHintsIsPBaseSize (SizeHints *hints); +BOOL SizeHintsIsPWinGravity (SizeHints *hints); + +void SizeHintsSetFlagNone (SizeHints *hints); +void SizeHintsSetFlagUSPosition (SizeHints *hints); +void SizeHintsSetFlagUSSize (SizeHints *hints); +void SizeHintsSetFlagPPosition (SizeHints *hints); +void SizeHintsSetFlagPSize (SizeHints *hints); +void SizeHintsSetFlagPMinSize (SizeHints *hints); +void SizeHintsSetFlagPMaxSize (SizeHints *hints); +void SizeHintsSetFlagPResizeInc (SizeHints *hints); +void SizeHintsSetFlagPAspect (SizeHints *hints); +void SizeHintsSetFlagPBaseSize (SizeHints *hints); +void SizeHintsSetFlagPWinGravity (SizeHints *hints); + +void SizeHintsSetPosition (SizeHints *hints, + int user_specified, + INT32 x, + INT32 y); + +void SizeHintsSetSize (SizeHints *hints, + int user_specified, + INT32 width, + INT32 height); + +void SizeHintsSetMinSize (SizeHints *hints, + INT32 min_width, + INT32 min_height); + +void SizeHintsSetMaxSize (SizeHints *hints, + INT32 max_width, + INT32 max_height); + +void SizeHintsSetResizeInc (SizeHints *hints, + INT32 width_inc, + INT32 height_inc); + +void SizeHintsSetAspect (SizeHints *hints, + INT32 min_aspect_num, + INT32 min_aspect_den, + INT32 max_aspect_num, + INT32 max_aspect_den); + +void SizeHintsSetBaseSize (SizeHints *hints, + INT32 base_width, + INT32 base_height); + +void SizeHintsSetWinGravity (SizeHints *hints, + CARD8 win_gravity); + +void SetWMSizeHints (XCBConnection *c, + XCBWINDOW window, + XCBATOM property, + SizeHints *hints); + +int GetWMSizeHints (XCBConnection *c, + XCBWINDOW window, + XCBATOM property, + SizeHints *hints, + long *supplied); + +/* WM_NORMAL_HINTS */ + +void SetWMNormalHints (XCBConnection *c, + XCBWINDOW window, + SizeHints *hints); + +int GetWMNormalHints (XCBConnection *c, + XCBWINDOW window, + SizeHints *hints, + long *supplied); + +/* WM_HINTS */ + +typedef struct WMHints WMHints; +#define NumWMHintsElements 9 /* number of elements in this structure */ + +typedef enum { + XCBWMWithdrawnState = 0, + XCBWMNormalState = 1, + XCBWMIconicState = 3 +} XCBWMState; + +BOOL WMHintsGetInput (WMHints *hints); +XCBPIXMAP WMHintsGetIconPixmap (WMHints *hints); +XCBPIXMAP WMHintsGetIconMask (WMHints *hints); +XCBWINDOW WMHintsGetIconWindow (WMHints *hints); +XCBWINDOW WMHintsGetWindowGroup (WMHints *hints); + +BOOL WMHintsIsInputHint (WMHints *hints); +BOOL WMHintsIsStateHint (WMHints *hints); +BOOL WMHintsIsIconPixmapHint (WMHints *hints); +BOOL WMHintsIsIconWindowHint (WMHints *hints); +BOOL WMHintsIsIconPositionHint (WMHints *hints); +BOOL WMHintsIsIconMaskHint (WMHints *hints); +BOOL WMHintsIsWindowGroupHint (WMHints *hints); +BOOL WMHintsIsXUrgencyHint (WMHints *hints); + +BOOL WMHintsStateIsWithdrawn (WMHints *hints); +BOOL WMHintsStateIsNormal (WMHints *hints); +BOOL WMHintsStateIsIconic (WMHints *hints); + +void WMHintsSetInput (WMHints *hints, BOOL input); +void WMHintsSetIconic (WMHints *hints); +void WMHintsSetNormal (WMHints *hints); +void WMHintsSetWithdrawn (WMHints *hints); +void WMHintsSetNone (WMHints *hints); +void WMHintsSetUrgent (WMHints *hints); +void WMHintsSetIconPixmap (WMHints *hints, XCBPIXMAP icon_pixmap); +void WMHintsSetIconMask (WMHints *hints, XCBPIXMAP icon_mask); +void WMHintsSetIconWindow (WMHints *hints, XCBWINDOW icon_window); +void WMHintsSetWindowGroup (WMHints *hints, XCBWINDOW window_group); + +WMHints *GetWMHints (XCBConnection *c, + XCBWINDOW window); + +/* WM_PROTOCOLS */ + +void SetWMProtocols (XCBConnection *c, + XCBWINDOW window, + CARD32 list_len, + XCBATOM *list); +int GetWMProtocols (XCBConnection *c, + XCBWINDOW window, + CARD32 *list_len, + XCBATOM **list); + +#define HAS_DISCRIMINATED_NAME 0 +#if HAS_DISCRIMINATED_NAME +char *DiscriminatedAtomNameByScreen (const char *base, CARD8 screen); +char *DiscriminatedAtomNameByResource (const char *base, CARD32 resource); +char *DiscriminatedAtomNameUnique (const char *base, CARD32 id); +#endif + +#endif /* ICCCM_H */ diff --git a/image/.cvsignore b/image/.cvsignore new file mode 100644 index 0000000..586d052 --- /dev/null +++ b/image/.cvsignore @@ -0,0 +1,10 @@ +.deps +.libs +Makefile.in +Makefile +*.lo +*.loT +*.la +test_xcb_image +test_xcb_image_shm +*.pc diff --git a/image/Makefile.am b/image/Makefile.am new file mode 100644 index 0000000..738949d --- /dev/null +++ b/image/Makefile.am @@ -0,0 +1,24 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBImage.la + +xcbinclude_HEADERS = xcb_image.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) -I../convenient +LDADD = $(XCB_LIBS) -L../convenient -lXCBAux + +libXCBImage_la_SOURCES = xcb_image.c + +pkgconfig_DATA = xcb-image.pc + +EXTRA_DIST=xcb-image.pc.in + +noinst_PROGRAMS = test_xcb_image test_xcb_image_shm + +test_xcb_image_LDADD = $(LDADD) -L. -lXCBImage +test_xcb_image_SOURCES = test_xcb_image.c + +test_xcb_image_shm_LDADD = $(LDADD) -L. -lXCBImage +test_xcb_image_shm_SOURCES = test_xcb_image_shm.c diff --git a/image/test_xcb_image.c b/image/test_xcb_image.c new file mode 100644 index 0000000..726c3fa --- /dev/null +++ b/image/test_xcb_image.c @@ -0,0 +1,231 @@ +/* gcc -g -O2 -Wall `pkg-config --cflags --libs xcb` -o test xcb_image.o test_xcb_image.c */ + +#include +#include + +#include +#include +#include + +#include "xcb_aux.h" +#include "xcb_image.h" + +#define W_W 4 +#define W_H 4 + +void +reflect_window (XCBConnection *c, + XCBDRAWABLE win, + XCBDRAWABLE new_win, + XCBGCONTEXT gc, + CARD16 width, + CARD16 height) +{ + XCBImage *image; + CARD32 pixel1; + CARD32 pixel2; + INT32 left_x; + INT32 right_x; + INT32 y; + + int i, j; + int format; + + format = ZPixmap; + + printf ("get_image %d %d\n", width, height); + image = XCBImageGet (c, win, + 0, 0, width, height, + AllPlanes, + format); + + printf ("Create image summary:\n"); + printf (" * format..........: %d\n", image->format); + printf (" * byte order......: %d\n", image->image_byte_order); + printf (" * bitmap unit.....: %d\n", image->bitmap_format_scanline_unit); + printf (" * bitmap order....: %d\n", image->bitmap_format_bit_order); + printf (" * bitmap pad......: %d\n", image->bitmap_format_scanline_pad); + printf (" * depth...........: %d\n", image->depth); + printf (" * bytes/line......: %ld\n", image->bytes_per_line); + printf (" * bits/pixel......: %d\n", image->bits_per_pixel); + + printf ("bpl %ld %d\n", image->bytes_per_line, image->height); + + for (j = 0 ; j < image->height ; j++) + { + for (i = 0 ; i < image->width ; i++) + { + pixel1 = XCBImageGetPixel (image, i, j); + printf ("%6ld ", pixel1); + } + printf ("\n"); + } + + printf("calculating reflection -- this may take awhile...\n"); + + for (left_x = 0 ; left_x < width/2 ; left_x++) + { + for (y = 0 ; y < height ; y++) + { + pixel1 = XCBImageGetPixel (image, left_x, y); + right_x = width - left_x-1; + if (left_x != right_x) + { + pixel2 = XCBImageGetPixel (image, right_x, y); + XCBImagePutPixel (image, left_x, y, pixel2); + } + XCBImagePutPixel (image, right_x, y, pixel1); + } + printf ("\n"); + } + printf("putting image\n"); + for (j = 0 ; j < image->height ; j++) + { + for (i = 0 ; i < image->width ; i++) + { + pixel1 = XCBImageGetPixel (image, i, j); + printf ("%6ld ", pixel1); + } + printf ("\n"); + } + XCBImagePut (c, new_win, gc, image, + 0, 0, 0, 0, width, height); + image = XCBImageGet (c, new_win, + 0, 0, width, height, + AllPlanes, + format); + printf ("New : \n"); + for (j = 0 ; j < image->height ; j++) + { + for (i = 0 ; i < image->width ; i++) + { + pixel1 = XCBImageGetPixel (image, i, j); + printf ("%6ld ", pixel1); + } + printf ("\n"); + } + printf ("done\n"); +} + +int +main (int argc, char *argv[]) +{ + XCBConnection *c; + XCBSCREEN *screen; + XCBDRAWABLE win; + XCBDRAWABLE new_win; + XCBDRAWABLE rect; + XCBRECTANGLE rect_coord = { 0, 0, W_W, W_H}; + XCBGCONTEXT bgcolor, fgcolor; + XCBPOINT points[2]; + CARD32 mask; + CARD32 valgc[2]; + CARD32 valwin[3]; + int depth; + int screen_nbr; + XCBGenericEvent *e; + + /* Open the connexion to the X server and get the first screen */ + c = XCBConnect (NULL, &screen_nbr); + screen = XCBAuxGetScreen (c, screen_nbr); + depth = XCBAuxGetDepth (c, screen); + + /* Create a black graphic context for drawing in the foreground */ + win.window = screen->root; + + fgcolor = XCBGCONTEXTNew(c); + mask = GCForeground | GCGraphicsExposures; + valgc[0] = screen->black_pixel; + valgc[1] = 0; /* no graphics exposures */ + XCBCreateGC(c, fgcolor, win, mask, valgc); + + bgcolor = XCBGCONTEXTNew(c); + mask = GCForeground | GCGraphicsExposures; + valgc[0] = screen->white_pixel; + valgc[1] = 0; /* no graphics exposures */ + XCBCreateGC(c, bgcolor, win, mask, valgc); + + /* Ask for our window's Id */ + win.window = XCBWINDOWNew(c); + + /* Create the window */ + mask = XCBCWBackPixel | XCBCWEventMask | XCBCWDontPropagate; + valwin[0] = screen->white_pixel; + valwin[1] = KeyPressMask | ButtonReleaseMask | ExposureMask; + valwin[2] = ButtonPressMask; + XCBCreateWindow (c, /* Connection */ + 0, /* depth */ + win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + W_W, W_H, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + mask, valwin); /* masks, not used yet */ + + /* Map the window on the screen */ + XCBMapWindow (c, win.window); + + /* Create a Pixmap that will fill the window */ + rect.pixmap = XCBPIXMAPNew (c); + XCBCreatePixmap(c, depth, rect.pixmap, win, W_W, W_H); + XCBPolyFillRectangle(c, rect, bgcolor, 1, &rect_coord); + points[0].x = 0; + points[0].y = 0; + points[1].x = 1; + points[1].y = 1; + XCBPolyLine(c, CoordModeOrigin, rect, fgcolor, 2, points); +/* points[0].x = 10; */ +/* points[0].y = 10; */ +/* points[1].x = 10; */ +/* points[1].y = 40; */ +/* XCBPolyLine(c, CoordModeOrigin, rect, fgcolor, 2, points); */ + + /* Ask for our window's Id */ + new_win.window = XCBWINDOWNew(c); + + /* Create the window */ + mask = XCBCWBackPixel | XCBCWEventMask | XCBCWDontPropagate; + valwin[0] = screen->white_pixel; + valwin[1] = KeyPressMask | ButtonReleaseMask | ExposureMask; + valwin[2] = ButtonPressMask; + XCBCreateWindow (c, /* Connection */ + 0, /* depth */ + new_win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + W_W, W_H, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + mask, valwin); /* masks, not used yet */ + + + + /* Map the window on the screen */ + XCBMapWindow (c, new_win.window); + + + XCBSync (c, 0); + + while ((e = XCBWaitForEvent(c))) + { + switch (e->response_type) + { + case XCBExpose: + { + XCBCopyArea(c, rect, win, bgcolor, + 0, 0, 0, 0, W_W, W_H); + reflect_window (c, win, new_win, + fgcolor, + W_W, W_H); + XCBSync (c, 0); + break; + } + } + free (e); + } + + return 1; +} diff --git a/image/test_xcb_image_shm.c b/image/test_xcb_image_shm.c new file mode 100644 index 0000000..4975fe5 --- /dev/null +++ b/image/test_xcb_image_shm.c @@ -0,0 +1,167 @@ +#include +#include + +#include +#include + +#include +#include +#include + +#include "xcb_aux.h" +#include "xcb_image.h" + +#define W_W 40 +#define W_H 40 + + + +int +main (int argc, char *argv[]) +{ + XCBConnection *c; + XCBSCREEN *screen; + XCBDRAWABLE win; + XCBDRAWABLE rect; + XCBRECTANGLE rect_coord = { 0, 0, W_W, W_H}; + XCBGCONTEXT bgcolor, fgcolor; + XCBPOINT points[2]; + CARD32 mask; + CARD32 valgc[2]; + CARD32 valwin[3]; + int depth; + int screen_nbr; + XCBGenericEvent *e; + + /* Open the connexion to the X server and get the first screen */ + c = XCBConnect (NULL, &screen_nbr); + screen = XCBAuxGetScreen (c, screen_nbr); + depth = XCBAuxGetDepth (c, screen); + + /* Create a black graphic context for drawing in the foreground */ + win.window = screen->root; + + fgcolor = XCBGCONTEXTNew(c); + mask = GCForeground | GCGraphicsExposures; + valgc[0] = screen->black_pixel; + valgc[1] = 0; /* no graphics exposures */ + XCBCreateGC(c, fgcolor, win, mask, valgc); + + bgcolor = XCBGCONTEXTNew(c); + mask = GCForeground | GCGraphicsExposures; + valgc[0] = screen->white_pixel; + valgc[1] = 0; /* no graphics exposures */ + XCBCreateGC(c, bgcolor, win, mask, valgc); + + /* Shm test */ + printf ("shm test begin\n"); + XCBImage *img = 0; + XCBShmQueryVersionRep *rep; + XCBShmSegmentInfo shminfo; + + rep = XCBShmQueryVersionReply (c, + XCBShmQueryVersion (c), + NULL); + if (rep) + { + CARD8 format; + + if (rep->shared_pixmaps && + (rep->major_version > 1 || rep->minor_version > 0)) + format = rep->pixmap_format; + else + format = 0; + img = XCBImageSHMCreate (c, depth, format, NULL, W_W, W_H); + + printf ("Create image summary:\n"); + printf (" * format..........: %d\n", img->format); + printf (" * byte order......: %d\n", img->image_byte_order); + printf (" * bitmap unit.....: %d\n", img->bitmap_format_scanline_unit); + printf (" * bitmap order....: %d\n", img->bitmap_format_bit_order); + printf (" * bitmap pad......: %d\n", img->bitmap_format_scanline_pad); + + shminfo.shmid = shmget (IPC_PRIVATE, + img->bytes_per_line*img->height, + IPC_CREAT|0777); + shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); + img->data = shminfo.shmaddr; + + shminfo.shmseg = XCBShmSEGNew (c); + XCBShmAttach(c, shminfo.shmseg, + shminfo.shmid, 0); + shmctl(shminfo.shmid, IPC_RMID, 0); + } + + if (!img) + { + printf ("Can't use shm...\n"); + exit (0); + } + + /* Draw in the image */ + printf ("put the pixel\n"); + XCBImagePutPixel (img, 20, 20, 65535); + printf ("fin put pixel\n"); + + /* Ask for our window's Id */ + win.window = XCBWINDOWNew(c); + + /* Create the window */ + mask = XCBCWBackPixel | XCBCWEventMask | XCBCWDontPropagate; + valwin[0] = screen->white_pixel; + valwin[1] = KeyPressMask | ButtonReleaseMask | ExposureMask; + valwin[2] = ButtonPressMask; + XCBCreateWindow (c, /* Connection */ + 0, /* depth */ + win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + W_W, W_H, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + mask, valwin); /* masks, not used yet */ + + /* Map the window on the screen */ + XCBMapWindow (c, win.window); + + /* Create a Pixmap that will fill the window */ + rect.pixmap = XCBPIXMAPNew (c); + XCBCreatePixmap(c, depth, rect.pixmap, win, W_W, W_H); + XCBPolyFillRectangle(c, rect, bgcolor, 1, &rect_coord); + points[0].x = 0; + points[0].y = 0; + points[1].x = 1; + points[1].y = 1; + XCBPolyLine(c, CoordModeOrigin, rect, fgcolor, 2, points); +/* points[0].x = 10; */ +/* points[0].y = 10; */ +/* points[1].x = 10; */ +/* points[1].y = 40; */ +/* XCBPolyLine(c, CoordModeOrigin, rect, fgcolor, 2, points); */ + + + XCBSync (c, 0); + + while ((e = XCBWaitForEvent(c))) + { + switch (e->response_type) + { + case XCBExpose: + { + XCBCopyArea(c, rect, win, bgcolor, + 0, 0, 0, 0, W_W, W_H); + printf ("put image\n"); + XCBImageSHMPut (c, win, fgcolor, + img, shminfo, + 0, 0, 0, 0, W_W,W_H, + 0); + XCBSync (c, 0); + break; + } + } + free (e); + } + + return 1; +} diff --git a/image/xcb-image.pc.in b/image/xcb-image.pc.in new file mode 100644 index 0000000..8f7771c --- /dev/null +++ b/image/xcb-image.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBImage +Description: XCB image convenience library +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBImage @LIBS@ +Cflags: -I${includedir} diff --git a/image/xcb_image.c b/image/xcb_image.c new file mode 100644 index 0000000..ec0f8e1 --- /dev/null +++ b/image/xcb_image.c @@ -0,0 +1,624 @@ +/* gcc -g -O2 -Wall -c `pkg-config --cflags xcb` -o xcb_image.o xcb_image.c */ + +#include +#include +#include + +#include +#include + +#include "xcb_image.h" + +/* Convenient */ +static CARD8 xcb_bits_per_pixel (XCBConnection *c, CARD8 depth); +static CARD32 xcb_bytes_per_line (CARD8 pad, CARD16 width, CARD8 bpp); +static CARD8 xcb_scanline_pad_get (XCBConnection *conn, + CARD8 depth); + +static inline CARD32 _lomask(int n) +{ + return (1 << n) - 1; +} + +static unsigned int Ones( /* HACKMEM 169 */ + CARD32 mask) +{ + register CARD32 y; + + y = (mask >> 1) &033333333333; + y = mask - y - ((y >>1) & 033333333333); + return ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077)); +} + + +/* Convenient functions */ + +static CARD8 +xcb_bits_per_pixel (XCBConnection *c, CARD8 depth) +{ + XCBFORMAT *fmt = XCBConnSetupSuccessRepPixmapFormats(XCBGetSetup(c)); + XCBFORMAT *fmtend = fmt + XCBConnSetupSuccessRepPixmapFormatsLength(XCBGetSetup(c)); + + for(; fmt != fmtend; ++fmt) + if(fmt->depth == depth) + return fmt->bits_per_pixel; + + if(depth <= 4) + return 4; + if(depth <= 8) + return 8; + if(depth <= 16) + return 16; + return 32; +} + +static CARD32 +xcb_bytes_per_line (CARD8 pad, CARD16 width, CARD8 bpp) +{ + return ((bpp * width + pad - 1) & -pad) >> 3; +} + +static CARD8 +xcb_scanline_pad_get (XCBConnection *conn, + CARD8 depth) +{ + XCBFORMAT *fmt = XCBConnSetupSuccessRepPixmapFormats(XCBGetSetup(conn)); + XCBFORMAT *fmtend = fmt + XCBConnSetupSuccessRepPixmapFormatsLength(XCBGetSetup(conn)); + + for(; fmt != fmtend; ++fmt) + if(fmt->depth == depth) + { + return fmt->scanline_pad; + } + + return XCBGetSetup (conn)->bitmap_format_scanline_pad; + +/* XCBFORMATIter iter; */ +/* int cur; */ + +/* iter = XCBConnSetupSuccessRepPixmapFormatsIter (conn->setup); */ +/* for (cur = 0 ; cur < iter.rem ; cur++, XCBFORMATNext (&iter)) */ +/* if (iter.data->depth == depth) */ +/* return iter.data->scanline_pad; */ + +/* return XCBGetSetup (conn)->bitmap_format_scanline_pad; */ +} + + +XCBImage * +XCBImageCreate (XCBConnection *conn, + CARD8 depth, + CARD8 format, + unsigned int offset, + BYTE *data, + CARD16 width, + CARD16 height, + CARD8 xpad, + CARD32 bytes_per_line) +{ + XCBImage *image; + XCBConnSetupSuccessRep *rep; + CARD8 bpp = 1; /* bits per pixel */ + + if (depth == 0 || depth > 32 || + (format != XYBitmap && format != XYPixmap && format != ZPixmap) || + (format == XYBitmap && depth != 1) || + (xpad != 8 && xpad != 16 && xpad != 32)) + return (XCBImage *) NULL; + + image = (XCBImage *)malloc (sizeof (XCBImage)); + if (image == NULL) + return NULL; + + rep = XCBGetSetup (conn); + + image->width = width; + image->height = height; + image->format = format; + image->image_byte_order = rep->image_byte_order; + image->bitmap_format_scanline_unit = rep->bitmap_format_scanline_unit; + image->bitmap_format_bit_order = rep->bitmap_format_bit_order; + image->bitmap_format_scanline_pad = xpad; + + if (format == ZPixmap) + { + bpp = xcb_bits_per_pixel (conn, depth); + } + + image->xoffset = offset; + image->depth = depth; + image->data = data; + + /* + * compute per line accelerator. + */ + if (bytes_per_line == 0) + { + if (format == ZPixmap) + image->bytes_per_line = + xcb_bytes_per_line (image->bitmap_format_scanline_pad, + width, bpp); + else + image->bytes_per_line = + xcb_bytes_per_line (image->bitmap_format_scanline_pad, + width + offset, 1); + } + else + image->bytes_per_line = bytes_per_line; + + image->bits_per_pixel = bpp; + + return image; +} + +int +XCBImageInit (XCBImage *image) +{ + if ((image->depth == 0 || image->depth > 32) || + (image->format != XYBitmap && + image->format != XYPixmap && + image->format != ZPixmap) || + (image->format == XYBitmap && image->depth != 1) || + (image->bitmap_format_scanline_pad != 8 && + image->bitmap_format_scanline_pad != 16 && + image->bitmap_format_scanline_pad != 32)) + return 0; + + /* + * compute per line accelerator. + */ + if (image->bytes_per_line == 0) + { + if (image->format == ZPixmap) + image->bytes_per_line = + xcb_bytes_per_line (image->bitmap_format_scanline_pad, + image->width, + image->bits_per_pixel); + else + image->bytes_per_line = + xcb_bytes_per_line (image->bitmap_format_scanline_pad, + image->width + image->xoffset, + 1); + } + + return 1; +} + +int +XCBImageDestroy (XCBImage *image) +{ + if (image->data != NULL) + free (image->data); + free (image); + + return 1; +} + +XCBImage * +XCBImageGet (XCBConnection *conn, + XCBDRAWABLE draw, + INT16 x, + INT16 y, + CARD16 width, + CARD16 height, + CARD32 plane_mask, + CARD8 format) +{ + XCBImage *image; + XCBGetImageRep *rep; + BYTE *data; + + rep = XCBGetImageReply (conn, + XCBGetImage (conn, + format, + draw, + x, y, + width, height, + plane_mask), + NULL); + if (!rep) + return NULL; + + data = malloc(XCBGetImageDataLength(rep)); + if (!data) + return NULL; + memcpy(data, XCBGetImageData (rep), XCBGetImageDataLength (rep)); + + if (format == XYPixmap) + { + image = XCBImageCreate (conn, + Ones (plane_mask & _lomask(rep->depth)), + format, + 0, + data, + width, height, + xcb_scanline_pad_get (conn, rep->depth), + 0); + } + else /* format == ZPixmap */ + { + image = XCBImageCreate (conn, + rep->depth, + ZPixmap, + 0, + data, + width, height, + xcb_scanline_pad_get (conn, rep->depth), + 0); + } + if (!image) + free (data); + + free (rep); + + return image; +} + +int +XCBImagePut (XCBConnection *conn, + XCBDRAWABLE draw, + XCBGCONTEXT gc, + XCBImage *image, + INT16 x_offset, + INT16 y_offset, + INT16 x, + INT16 y, + CARD16 width, + CARD16 height) +{ + INT32 w; + INT32 h; + int dest_bits_per_pixel; + int dest_scanline_pad; + int left_pad; + + w = width; + h = height; + + if (x_offset < 0) + { + w += x_offset; + x_offset = 0; + } + + if (y_offset < 0) + { + h += y_offset; + y_offset = 0; + } + + if ((w + x_offset) > image->width) + w = image->width - x_offset; + + if ((h + y_offset) > image->height) + h = image->height - y_offset; + + if ((w <= 0) || (h <= 0)) + return 0; + + if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) + { + dest_bits_per_pixel = 1; + dest_scanline_pad = XCBGetSetup (conn)->bitmap_format_scanline_pad; + left_pad = image->xoffset & (XCBGetSetup (conn)->bitmap_format_scanline_unit- 1); + } + else + { + XCBFORMATIter iter; + + dest_bits_per_pixel = image->bits_per_pixel; + dest_scanline_pad = image->bitmap_format_scanline_pad; + left_pad = 0; + iter = XCBConnSetupSuccessRepPixmapFormatsIter (XCBGetSetup (conn)); + for (; iter.rem ; XCBFORMATNext (&iter)) + if (iter.data->depth == image->depth) + { + dest_bits_per_pixel = iter.data->bits_per_pixel; + dest_scanline_pad = iter.data->scanline_pad; + } + + if (dest_bits_per_pixel != image->bits_per_pixel) { + XCBImage img; + register INT32 i, j; + XCBConnSetupSuccessRep *rep; + + /* XXX slow, but works */ + rep = XCBGetSetup (conn); + img.width = width; + img.height = height; + img.xoffset = 0; + img.format = ZPixmap; + img.image_byte_order = rep->image_byte_order; + img.bitmap_format_scanline_unit = rep->bitmap_format_scanline_unit; + img.bitmap_format_bit_order = rep->bitmap_format_bit_order; + img.bitmap_format_scanline_pad = dest_scanline_pad; + img.depth = image->depth; + img.bits_per_pixel = dest_bits_per_pixel; + img.bytes_per_line = xcb_bytes_per_line (dest_scanline_pad, + width, + dest_bits_per_pixel); + img.data = malloc((CARD8) (img.bytes_per_line * height)); + + if (img.data == NULL) + return 0; + + for (j = height; --j >= 0; ) + for (i = width; --i >= 0; ) + XCBImagePutPixel(&img, + i, j, + XCBImageGetPixel(image, + x_offset + i, + y_offset + j)); + + XCBPutImage(conn, img.format, draw, gc, + w, h, x, y, + dest_scanline_pad, + img.depth, + img.bytes_per_line * height, + img.data); + + free(img.data); + return 0; + } + } + + XCBPutImage(conn, image->format, draw, gc, + w, h, x, y, + left_pad, + image->depth, image->bytes_per_line * height, + image->data); + + return 0; +} + +/* + * Shm stuff + */ + +XCBImage * +XCBImageSHMCreate (XCBConnection *conn, + CARD8 depth, + CARD8 format, + BYTE *data, + CARD16 width, + CARD16 height) +{ + XCBImage *image; + XCBConnSetupSuccessRep *rep; + + image = (XCBImage *)malloc (sizeof (XCBImage)); + if (!image) + return NULL; + + rep = XCBGetSetup (conn); + + image->width = width; + image->height = height; + image->xoffset = 0; + image->format = format; + image->data = data; + image->depth = depth; + + image->image_byte_order = rep->image_byte_order; + image->bitmap_format_scanline_unit = rep->bitmap_format_scanline_unit; + image->bitmap_format_bit_order = rep->bitmap_format_bit_order; + image->bitmap_format_scanline_pad = xcb_scanline_pad_get (conn, depth); + + if (format == ZPixmap) + image->bits_per_pixel = xcb_bits_per_pixel (conn, depth); + else + image->bits_per_pixel = 1; + + image->bytes_per_line = xcb_bytes_per_line (image->bitmap_format_scanline_pad, + width, + image->bits_per_pixel); + + return image; +} + +int +XCBImageSHMDestroy (XCBImage *image) +{ + if (image) + free (image); + + return 1; +} + +int +XCBImageSHMPut (XCBConnection *conn, + XCBDRAWABLE draw, + XCBGCONTEXT gc, + XCBImage *image, + XCBShmSegmentInfo shminfo, + INT16 src_x, + INT16 src_y, + INT16 dest_x, + INT16 dest_y, + CARD16 src_width, + CARD16 src_height, + CARD8 send_event) +{ + if (!shminfo.shmaddr) + return 0; + + XCBShmPutImage(conn, draw, gc, + image->width, image->height, + src_x, src_y, src_width, src_height, + dest_x, dest_y, + image->depth, image->format, + send_event, + shminfo.shmseg, + image->data - shminfo.shmaddr); + return 1; +} + +int +XCBImageSHMGet (XCBConnection *conn, + XCBDRAWABLE draw, + XCBImage *image, + XCBShmSegmentInfo shminfo, + INT16 x, + INT16 y, + CARD32 plane_mask) +{ + XCBShmGetImageRep *rep; + XCBShmGetImageCookie cookie; + + if (!shminfo.shmaddr) + return 0; + + cookie = XCBShmGetImage(conn, draw, + x, y, + image->width, image->height, + plane_mask, + image->format, + shminfo.shmseg, + image->data - shminfo.shmaddr); + rep = XCBShmGetImageReply(conn, cookie, NULL); + /* rep would be useful to get the visual id */ + /* but i don't use it */ + /* So, should we remove it ? */ + + return 1; +} + +/* GetPixel/PutPixel */ + +static inline int XYINDEX (int x, XCBImage *img, int *bitp) +{ + int mask = img->bitmap_format_scanline_unit - 1; + int unit = (x + img->xoffset) & ~mask; + int byte = (x + img->xoffset) & mask; + if (img->bitmap_format_bit_order == MSBFirst) + byte = img->bitmap_format_scanline_unit - byte; + *bitp = byte & 7; + if (img->image_byte_order == MSBFirst) + byte = img->bitmap_format_scanline_unit - byte; + return (unit + byte) >> 3; +} + +static inline int ZINDEX (int x, XCBImage *img) +{ + return (x * img->bits_per_pixel) >> 3; +} + +static inline void set_bit (CARD8 *byte, int bit, int value) +{ + if (value) + *byte |= 1 << bit; + else + *byte &= ~(1 << bit); +} + +int +XCBImagePutPixel (XCBImage *image, int x, int y, CARD32 pixel) +{ + register BYTE *src = image->data + (y * image->bytes_per_line); + + if (image->format == XYPixmap || (image->bits_per_pixel | image->depth) == 1) + { + int plane, bit; + /* do least signif plane 1st */ + src += XYINDEX(x, image, &bit) + image->bytes_per_line * image->height * image->depth; + for (plane = image->depth; --plane >= 0; pixel >>= 1) + { + src -= image->bytes_per_line * image->height; + set_bit (src, bit, pixel & 1); + } + } + else + if (image->format == ZPixmap) + { + src += ZINDEX(x, image); + if (image->bits_per_pixel == 4) + { + CARD8 mask = ~_lomask(4); + pixel &= _lomask(image->depth); + /* if x is odd and byte order is LSB, or + * if x is even and byte order is MSB, then + * want high nibble; else want low nibble. */ + if ((x & 1) == (image->image_byte_order == LSBFirst)) + { + mask = ~mask; + pixel <<= 4; + } + *src = (*src & mask) | pixel; + } + else + { + int nbytes = image->bits_per_pixel >> 3; + int rev = image->image_byte_order == MSBFirst; + if(rev) + src += nbytes - 1; + while (--nbytes >= 0) + { + *src = pixel; + pixel >>= 8; + if(rev) + --src; + else + ++src; + } + } + } + else + { + return 0; /* bad image */ + } + return 1; +} + +CARD32 +XCBImageGetPixel (XCBImage *image, int x, int y) +{ + CARD32 pixel = 0; + register BYTE *src = image->data + (y * image->bytes_per_line); + + if (image->format == XYPixmap || (image->bits_per_pixel | image->depth) == 1) + { + int plane, bit; + src += XYINDEX(x, image, &bit); + for (plane = image->depth; --plane >= 0; ) + { + pixel <<= 1; + pixel |= (*src >> bit) & 1; + src += image->bytes_per_line * image->height; + } + } + else + if (image->format == ZPixmap) + { + src += ZINDEX(x, image); + if (image->bits_per_pixel == 4) + { + pixel = *src; + /* if x is odd and byte order is LSB, or + * if x is even and byte order is MSB, then + * want high nibble; else want low nibble. */ + if ((x & 1) == (image->image_byte_order == LSBFirst)) + pixel >>= 4; + } + else + { + int nbytes = image->bits_per_pixel >> 3; + int rev = image->image_byte_order == MSBFirst; + if(rev) + src += nbytes - 1; + while (--nbytes >= 0) + { + pixel <<= 8; + pixel = *src; + if(rev) + --src; + else + ++src; + } + } + } + else + { + return 0; /* bad image */ + } + return pixel & _lomask(image->depth); +} diff --git a/image/xcb_image.h b/image/xcb_image.h new file mode 100644 index 0000000..36d33a7 --- /dev/null +++ b/image/xcb_image.h @@ -0,0 +1,361 @@ + +#ifndef __XCB_IMAGE_H__ +#define __XCB_IMAGE_H__ + + +/** + * @defgroup XCB_Image XCB Image Functions + * + * Functions used to create and manipulate images. + * + * @{ + */ + + +typedef struct XCBImage_ XCBImage; + +/** + * @struct XCBImage + * A structure that describes an XCBImage. + */ +struct XCBImage_ +{ + CARD16 width; + CARD16 height; + unsigned int xoffset; + CARD8 format; + BYTE *data; + CARD8 image_byte_order; + CARD8 bitmap_format_scanline_unit; + CARD8 bitmap_format_bit_order; + CARD8 bitmap_format_scanline_pad; + CARD8 depth; + CARD32 bytes_per_line; + CARD8 bits_per_pixel; +}; + +typedef struct XCBShmSegmentInfo_ XCBShmSegmentInfo; + +/** + * @struct XCBShmSegmentInfo + * A structure that stores the informations needed by the MIT Shm + * Extension. + */ +struct XCBShmSegmentInfo_ +{ + XCBShmSEG shmseg; + CARD32 shmid; + BYTE *shmaddr; +}; + +/** + * Create a new Image. + * @param conn The connection to the X server. + * @param depth The depth of the image. + * @param format The format of the image. You can pass XYBitmap, + * XYPixmap, or ZPixmap. + * @param offset The number of pixels to ignore at the beginning of + * the scanline. + * @param data The image data. + * @param width The width of the image, in pixels. + * @param height The height of the image, in pixels. + * @param xpad The quantum of a scanline (8, 16, or 32). + * @param bytes_per_line The number of bytes in the client image + * between the start of one scanline and the start of the next. + * @return The new image. + * + * This function allocates the memory needed for an XCBImage structure + * for the specified connection but does not allocate space for the image + * itself. It initializes the structure byte-order, bit-order, and + * bitmap-unit values from the connection and returns a pointer to the + * XCBImage structure. + * + * The @p offset parameter permits the rapid displaying of the image + * without requiring each scanline to be shifted into position. + * + * The image must be destroyed with @ref XCBImageDestroy. + * @ingroup XCB_Image + */ +XCBImage *XCBImageCreate (XCBConnection *conn, + CARD8 depth, + CARD8 format, + unsigned int offset, + BYTE *data, + CARD16 width, + CARD16 height, + CARD8 xpad, + CARD32 bytes_per_line); + +/** + * Initialize an Image. + * @param image The image to be destroyed. + * @return 1 if the operation has succeeded. + * + * This function initializes the image structure. + * @ingroup XCB_Image + */ +int XCBImageInit (XCBImage *image); + +/** + * Destroy an Image. + * @param image The image to be destroyed. + * @return 1 if the operation has succeeded. + * + * This function deallocates both the memory associated with the @p image + * parameter and its data. + * @ingroup XCB_Image + */ +int XCBImageDestroy (XCBImage *image); + +/** + * Return a pointer to a XCBImage. + * @param conn The connection to the X server. + * @param draw The draw you get the image from. + * @param x The x coordinate, which are relative to the origin of the + * drawable and define the upper-left corner of the rectangle. + * @param y The y coordinate, which are relative to the origin of the + * drawable and define the upper-left corner of the rectangle. + * @param width The width of the subimage, in pixels. + * @param height The height of the subimage, in pixels. + * @param plane_mask The plane mask. + * @param format The format of the image. You can pass XYBitmap, + * XYPixmap, or ZPixmap. + * @return The subimage of @p draw defined by @p x, @p y, @p w, @p h. + * + * This function returns a subimage of @p draw defined by @p x, @p y, + * @p w, @p h. The depth of the image is the one of the drawable @p + * draw, except when getting a subset of the plane in @c XYPixmap + * format. + * + * If a problem occurs, the functons returns @c NULL. + * @ingroup XCB_Image + */ +XCBImage *XCBImageGet (XCBConnection *conn, + XCBDRAWABLE draw, + INT16 x, + INT16 y, + CARD16 width, + CARD16 height, + CARD32 plane_mask, + CARD8 format); + +/* Not implemented. Should be ? */ +XCBImage xcb_image_subimage_get (XCBConnection *conn, + XCBDRAWABLE draw, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long plane_mask, + CARD8 format, + XCBImage *dest_im, + int dest_x, + int dest_y); + +/** + * Put the data of an XCBImage onto a drawable. + * @param conn The connection to the X server. + * @param draw The draw you get the image from. + * @param gc The graphic context. + * @param image The image you want to combine with the rectangle. + * @param x_offset The offset in x from the left edge of the image + * defined by the XCBImage structure. + * @param y_offset The offset in y from the left edge of the image + * defined by the XCBImage structure. + * @param x The x coordinate, which is relative to the origin of the + * drawable and defines the x coordinate of the upper-left corner of the + * rectangle. + * @param y The y coordinate, which is relative to the origin of the + * drawable and defines the x coordinate of the upper-left corner of + * the rectangle. + * @param width The width of the subimage, in pixels. + * @param height The height of the subimage, in pixels. + * @return 1 is no problems occurs. + * + * This function combines an image with a rectangle of the specified + * drawable. The section of the image defined by the @p x, @p y, + * @p width, and @p height arguments is drawn on the specified part of + * the drawable. The foreground pixel in @p gc defines the source for + * the one bits in the image, and the background pixel defines the + * source for the zero bits. For XYPixmap and ZPixmap formats, the + * depth of the image must match the depth of the drawable. + * + * If a problem occurs, the functons returns @c NULL. + * @ingroup XCB_Image + */ +int XCBImagePut (XCBConnection *conn, + XCBDRAWABLE draw, + XCBGCONTEXT gc, + XCBImage *image, + INT16 x_offset, + INT16 y_offset, + INT16 x, + INT16 y, + CARD16 width, + CARD16 height); + +/** + * Put a pixel in a image + * @param image The image. + * @param x The x coordinate of the pixel. + * @param y The y coordinate of the pixel. + * @param pixel The new pixel value. + * @return 1 if the operation has succeeded. + * + * This function overwrites the pixel in the named image with the + * specified @p pixel value. The input pixel value must be in normalized + * format (that is, the least-significant byte of the long is the + * least-significant byte of the pixel). The image must contain the @p x + * and @p y coordinates. + * @ingroup XCB_Image + */ +int XCBImagePutPixel (XCBImage *image, + int x, + int y, + CARD32 pixel); + +/** + * Get a pixel in a image + * @param image The image. + * @param x The x coordinate of the pixel. + * @param y The y coordinate of the pixel. + * @return The pixel value. + * + * This function returns the specified pixel from the named image. The + * pixel value is returned in normalized format (that is, the + * least-significant byte of the long is the least-significant byte of + * the pixel). The image must contain the @p x and @p y coordinates. + * @ingroup XCB_Image + */ +CARD32 XCBImageGetPixel (XCBImage *image, + int x, + int y); + +/* + * Shm stuff + */ + +/** + * Create an XCBImage to be used with the MIT Shm Extension + * @param conn The connection to the X server. + * @param depth The depth of the image. + * @param format The format of the image. You can pass XYBitmap, + * XYPixmap, or ZPixmap. + * @param data The image data. + * @param width The width of the image, in pixels. + * @param height The height of the image, in pixels. + * @return The new image. + * + * This function allocates the memory needed for an XCBImage structure + * for the specified display but does not allocate space for the image + * itself. + * + * The image must be destroyed with @ref XCBImageSHMDestroy. + * + * @ingroup XCB_Image + */ +XCBImage *XCBImageSHMCreate (XCBConnection *conn, + CARD8 depth, + CARD8 format, + BYTE *data, + CARD16 width, + CARD16 height); + +/** + * Destroy an Image created by XCBImageSHMCreate. + * @param image The image to be destroyed. + * @return 1 if the operation has succeeded. + * + * This function deallocates both the memory associated with the @p image + * parameter and its data. + * @ingroup XCB_Image + */ +int XCBImageSHMDestroy (XCBImage *image); + +/** + * Put the data of an XCBImage onto a drawable using the MIT Shm + * Extension. + * @param conn The connection to the X server. + * @param draw The draw you get the image from. + * @param gc The graphic context. + * @param image The image you want to combine with the rectangle. + * @param shminfo A @ref XCBShmSegmentInfo structure. + * @param x The offset in x from the left edge of the image + * defined by the XCBImage structure. + * @param y The offset in y from the left edge of the image + * defined by the XCBImage structure. + * @param dest_x The x coordinate, which is relative to the origin of the + * drawable and defines the x coordinate of the upper-left corner of the + * rectangle. + * @param dest_y The y coordinate, which is relative to the origin of the + * drawable and defines the x coordinate of the upper-left corner of + * the rectangle. + * @param width The width of the subimage, in pixels. + * @param height The height of the subimage, in pixels. + * @param send_event Indicates whether or not a completion event + * should occur when the image write is complete. + * @return 1 is no problems occurs. + * + * This function combines an image in memory with a shape of the + * specified drawable. The section of the image defined by the @p x, @p y, + * @p width, and @p height arguments is drawn on the specified part of + * the drawable. If XYBitmap format is used, the depth must be + * one, or a``BadMatch'' error results. The foreground pixel in the + * Graphic Context @p gc defines the source for the one bits in the + * image, and the background pixel defines the source for the zero + * bits. For XYPixmap and ZPixmap, the depth must match the depth of + * the drawable, or a ``BadMatch'' error results. + * + * If a problem occurs, the functons returns @c 0. Otherwise, it + * returns @c 1. + * @ingroup XCB_Image + */ +int XCBImageSHMPut (XCBConnection *conn, + XCBDRAWABLE draw, + XCBGCONTEXT gc, + XCBImage *image, + XCBShmSegmentInfo shminfo, + INT16 x, + INT16 y, + INT16 dest_x, + INT16 dest_y, + CARD16 width, + CARD16 height, + CARD8 send_event); + +/** + * Read image data into a shared memory XCBImage. + * @param conn The connection to the X server. + * @param draw The draw you get the image from. + * @param image The image you want to combine with the rectangle. + * @param shminfo A @ref XCBShmSegmentInfo structure. + * @param x The x coordinate, which are relative to the origin of the + * drawable and define the upper-left corner of the rectangle. + * @param y The y coordinate, which are relative to the origin of the + * drawable and define the upper-left corner of the rectangle. + * @param plane_mask The plane mask. + * @return The subimage of @p draw defined by @p x, @p y, @p w, @p h. + * + * This function reads image data into a shared memory XCBImage where + * @p conn is the connection to the X server, @p draw is the source + * drawable, @p image is the destination XCBImage, @p x and @p y are offsets + * within the drawable, and @p plane_mask defines which planes are to be + * read. + * + * If a problem occurs, the functons returns @c 0. It returns 1 + * otherwise. + * @ingroup XCB_Image + */ +int XCBImageSHMGet (XCBConnection *conn, + XCBDRAWABLE draw, + XCBImage *image, + XCBShmSegmentInfo shminfo, + INT16 x, + INT16 y, + CARD32 plane_mask); + +/** + * @} + */ + +#endif /* __XCB_IMAGE_H__ */ diff --git a/keysyms/Makefile.am b/keysyms/Makefile.am new file mode 100644 index 0000000..1d602f3 --- /dev/null +++ b/keysyms/Makefile.am @@ -0,0 +1,16 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBKeysyms.la + +xcbinclude_HEADERS = xcb_keysyms.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) +LDADD = $(XCB_LIBS) + +libXCBKeysyms_la_SOURCES = keysyms.c + +pkgconfig_DATA = xcb-keysyms.pc + +EXTRA_DIST=xcb-keysyms.pc.in diff --git a/keysyms/keysyms.c b/keysyms/keysyms.c new file mode 100644 index 0000000..f713450 --- /dev/null +++ b/keysyms/keysyms.c @@ -0,0 +1,378 @@ +#include + +#include +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_CYRILLIC +#define XK_GREEK +#define XK_ARMENIAN +#include + +#include "xcb_keysyms.h" + +/* Private declaration */ +enum tag_t { + TAG_COOKIE, + TAG_VALUE +}; + +struct _XCBKeySymbols +{ + XCBConnection *c; + enum tag_t tag; + union { + XCBGetKeyboardMappingCookie cookie; + XCBGetKeyboardMappingRep *reply; + } u; +}; + +static void XCBConvertCase(XCBKEYSYM sym, + XCBKEYSYM *lower, + XCBKEYSYM *upper); + +static void XCBKeySymbolsGetReply (XCBKeySymbols *syms, + XCBGenericError **e); + +/* public implementation */ + +XCBKeySymbols * +XCBKeySymbolsAlloc (XCBConnection *c) +{ + XCBKeySymbols *syms; + XCBKEYCODE min_keycode; + XCBKEYCODE max_keycode; + + if (!c) + return NULL; + + syms = (XCBKeySymbols *)malloc (sizeof (XCBKeySymbols)); + + syms->c = c; + syms->tag = TAG_COOKIE; + + min_keycode = XCBGetSetup (c)->min_keycode; + max_keycode = XCBGetSetup (c)->max_keycode; + + syms->u.cookie = XCBGetKeyboardMapping(c, + min_keycode, + max_keycode.id - min_keycode.id + 1); + + return syms; +} + +void +XCBKeySymbolsFree (XCBKeySymbols *syms) +{ + if (syms) + { + if (syms->tag == TAG_VALUE) + free (syms->u.reply); + free (syms); + syms = NULL; + } +} + +XCBKEYSYM XCBKeySymbolsGetKeysym (XCBKeySymbols *syms, + XCBKEYCODE keycode, + int col) +{ + XCBKEYSYM *keysyms; + XCBKEYSYM keysym_null = { 0 }; + XCBKEYSYM lsym; + XCBKEYSYM usym; + XCBKEYCODE min_keycode; + XCBKEYCODE max_keycode; + int per; + + if (!syms) + return keysym_null; + + XCBKeySymbolsGetReply (syms, NULL); + + keysyms = XCBGetKeyboardMappingKeysyms (syms->u.reply); + min_keycode = XCBGetSetup (syms->c)->min_keycode; + max_keycode = XCBGetSetup (syms->c)->max_keycode; + + per = syms->u.reply->keysyms_per_keycode; + if ((col < 0) || ((col >= per) && (col > 3)) || + (keycode.id < min_keycode.id) || + (keycode.id > max_keycode.id)) + return keysym_null; + + keysyms = &keysyms[(keycode.id - min_keycode.id) * per]; + if (col < 4) + { + if (col > 1) + { + while ((per > 2) && (keysyms[per - 1].id == 0)) + per--; + if (per < 3) + col -= 2; + } + if ((per <= (col|1)) || (keysyms[col|1].id == 0)) + { + XCBConvertCase(keysyms[col&~1], &lsym, &usym); + if (!(col & 1)) + return lsym; + else if (usym.id == lsym.id) + return keysym_null; + else + return usym; + } + } + return keysyms[col]; +} + + +XCBKEYCODE +XCBKeySymbolsGetKeycode (XCBKeySymbols *syms, + XCBKEYSYM keysym) +{ + XCBKEYSYM ks; + XCBKEYCODE keycode_null = { 0 }; + int i, j; + + if (!syms) + return keycode_null; + + XCBKeySymbolsGetReply (syms, NULL); + + for (j = 0; j < syms->u.reply->keysyms_per_keycode; j++) + { + for (i = XCBGetSetup (syms->c)->min_keycode.id; i <= XCBGetSetup (syms->c)->max_keycode.id; i++) + { + XCBKEYCODE keycode; + + keycode.id = i; + ks = XCBKeySymbolsGetKeysym (syms, keycode, j); + if (ks.id == keysym.id) + return keycode; + } + } + + return keycode_null; +} + +XCBKEYSYM +XCBKeyPressLookupKeysym (XCBKeySymbols *syms, + XCBKeyPressEvent *event, + int col) +{ + return XCBKeySymbolsGetKeysym (syms, event->detail, col); +} + +XCBKEYSYM +XCBKeyReleaseLookupKeysym (XCBKeySymbols *syms, + XCBKeyReleaseEvent *event, + int col) +{ + return XCBKeySymbolsGetKeysym (syms, event->detail, col); +} + +int +XCBRefreshKeyboardMapping (XCBKeySymbols *syms, + XCBMappingNotifyEvent *event) +{ + if (event->request == MappingKeyboard && syms) { + if (syms->tag == TAG_VALUE) { + XCBKEYCODE min_keycode; + XCBKEYCODE max_keycode; + + if (syms->u.reply) { + free (syms->u.reply); + syms->u.reply = NULL; + } + syms->tag = TAG_COOKIE; + min_keycode = XCBGetSetup (syms->c)->min_keycode; + max_keycode = XCBGetSetup (syms->c)->max_keycode; + + syms->u.cookie = XCBGetKeyboardMapping(syms->c, + min_keycode, + max_keycode.id - min_keycode.id + 1); + + } + return 1; + } + return 0; +} + + +/* Tests for classes of symbols */ + +int +XCBIsKeypadKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= XK_KP_Space) && (keysym.id <= XK_KP_Equal)); +} + +int +XCBIsPrivateKeypadKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= 0x11000000) && (keysym.id <= 0x1100FFFF)); +} + +int +XCBIsCursorKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= XK_Home) && (keysym.id <= XK_Select)); +} + +int +XCBIsPFKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= XK_KP_F1) && (keysym.id <= XK_KP_F4)); +} + +int +XCBIsFunctionKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= XK_F1) && (keysym.id <= XK_F35)); +} + +int +XCBIsMiscFunctionKey (XCBKEYSYM keysym) +{ + return ((keysym.id >= XK_Select) && (keysym.id <= XK_Break)); +} + +int +XCBIsModifierKey (XCBKEYSYM keysym) +{ + return (((keysym.id >= XK_Shift_L) && (keysym.id <= XK_Hyper_R)) || + ((keysym.id >= XK_ISO_Lock) && (keysym.id <= XK_ISO_Last_Group_Lock)) || + (keysym.id == XK_Mode_switch) || + (keysym.id == XK_Num_Lock)); +} + +/* private functions */ + +void +XCBConvertCase(XCBKEYSYM sym, + XCBKEYSYM *lower, + XCBKEYSYM *upper) +{ + lower->id = sym.id; + upper->id = sym.id; + + switch(sym.id >> 8) + { + case 0: /* Latin 1 */ + if ((sym.id >= XK_A) && (sym.id <= XK_Z)) + lower->id += (XK_a - XK_A); + else if ((sym.id >= XK_a) && (sym.id <= XK_z)) + upper->id -= (XK_a - XK_A); + else if ((sym.id >= XK_Agrave) && (sym.id <= XK_Odiaeresis)) + lower->id += (XK_agrave - XK_Agrave); + else if ((sym.id >= XK_agrave) && (sym.id <= XK_odiaeresis)) + upper->id -= (XK_agrave - XK_Agrave); + else if ((sym.id >= XK_Ooblique) && (sym.id <= XK_Thorn)) + lower->id += (XK_oslash - XK_Ooblique); + else if ((sym.id >= XK_oslash) && (sym.id <= XK_thorn)) + upper->id -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym.Id is a legal value (ignore discontinuities) */ + if (sym.id == XK_Aogonek) + lower->id = XK_aogonek; + else if (sym.id >= XK_Lstroke && sym.id <= XK_Sacute) + lower->id += (XK_lstroke - XK_Lstroke); + else if (sym.id >= XK_Scaron && sym.id <= XK_Zacute) + lower->id += (XK_scaron - XK_Scaron); + else if (sym.id >= XK_Zcaron && sym.id <= XK_Zabovedot) + lower->id += (XK_zcaron - XK_Zcaron); + else if (sym.id == XK_aogonek) + upper->id = XK_Aogonek; + else if (sym.id >= XK_lstroke && sym.id <= XK_sacute) + upper->id -= (XK_lstroke - XK_Lstroke); + else if (sym.id >= XK_scaron && sym.id <= XK_zacute) + upper->id -= (XK_scaron - XK_Scaron); + else if (sym.id >= XK_zcaron && sym.id <= XK_zabovedot) + upper->id -= (XK_zcaron - XK_Zcaron); + else if (sym.id >= XK_Racute && sym.id <= XK_Tcedilla) + lower->id += (XK_racute - XK_Racute); + else if (sym.id >= XK_racute && sym.id <= XK_tcedilla) + upper->id -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym.Id is a legal value (ignore discontinuities) */ + if (sym.id >= XK_Hstroke && sym.id <= XK_Hcircumflex) + lower->id += (XK_hstroke - XK_Hstroke); + else if (sym.id >= XK_Gbreve && sym.id <= XK_Jcircumflex) + lower->id += (XK_gbreve - XK_Gbreve); + else if (sym.id >= XK_hstroke && sym.id <= XK_hcircumflex) + upper->id -= (XK_hstroke - XK_Hstroke); + else if (sym.id >= XK_gbreve && sym.id <= XK_jcircumflex) + upper->id -= (XK_gbreve - XK_Gbreve); + else if (sym.id >= XK_Cabovedot && sym.id <= XK_Scircumflex) + lower->id += (XK_cabovedot - XK_Cabovedot); + else if (sym.id >= XK_cabovedot && sym.id <= XK_scircumflex) + upper->id -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym.Id is a legal value (ignore discontinuities) */ + if (sym.id >= XK_Rcedilla && sym.id <= XK_Tslash) + lower->id += (XK_rcedilla - XK_Rcedilla); + else if (sym.id >= XK_rcedilla && sym.id <= XK_tslash) + upper->id -= (XK_rcedilla - XK_Rcedilla); + else if (sym.id == XK_ENG) + lower->id = XK_eng; + else if (sym.id == XK_eng) + upper->id = XK_ENG; + else if (sym.id >= XK_Amacron && sym.id <= XK_Umacron) + lower->id += (XK_amacron - XK_Amacron); + else if (sym.id >= XK_amacron && sym.id <= XK_umacron) + upper->id -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym.Id is a legal value (ignore discontinuities) */ + if (sym.id >= XK_Serbian_DJE && sym.id <= XK_Serbian_DZE) + lower->id -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym.id >= XK_Serbian_dje && sym.id <= XK_Serbian_dze) + upper->id += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym.id >= XK_Cyrillic_YU && sym.id <= XK_Cyrillic_HARDSIGN) + lower->id -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym.id >= XK_Cyrillic_yu && sym.id <= XK_Cyrillic_hardsign) + upper->id += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym.Id is a legal value (ignore discontinuities) */ + if (sym.id >= XK_Greek_ALPHAaccent && sym.id <= XK_Greek_OMEGAaccent) + lower->id += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym.id >= XK_Greek_alphaaccent && sym.id <= XK_Greek_omegaaccent && + sym.id != XK_Greek_iotaaccentdieresis && + sym.id != XK_Greek_upsilonaccentdieresis) + upper->id -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym.id >= XK_Greek_ALPHA && sym.id <= XK_Greek_OMEGA) + lower->id += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym.id >= XK_Greek_alpha && sym.id <= XK_Greek_omega && + sym.id != XK_Greek_finalsmallsigma) + upper->id -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + case 0x14: /* Armenian */ + if (sym.id >= XK_Armenian_AYB && sym.id <= XK_Armenian_fe) { + lower->id = sym.id | 1; + upper->id = sym.id & ~1; + } + break; + } +} + +void +XCBKeySymbolsGetReply (XCBKeySymbols *syms, + XCBGenericError **e) +{ + if (!syms) + return; + + if (syms->tag == TAG_COOKIE) + { + syms->tag = TAG_VALUE; + syms->u.reply = XCBGetKeyboardMappingReply(syms->c, + syms->u.cookie, + e); + } +} diff --git a/keysyms/xcb-keysyms.pc.in b/keysyms/xcb-keysyms.pc.in new file mode 100644 index 0000000..596017f --- /dev/null +++ b/keysyms/xcb-keysyms.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBKeysyms +Description: XCB Keysyms +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBKeysyms @LIBS@ +Cflags: -I${includedir} diff --git a/keysyms/xcb_keysyms.h b/keysyms/xcb_keysyms.h new file mode 100644 index 0000000..a2e3d3e --- /dev/null +++ b/keysyms/xcb_keysyms.h @@ -0,0 +1,49 @@ +#ifndef __XCB_KEYSYMS_H__ +#define __XCB_KEYSYMS_H__ + + + +typedef struct _XCBKeySymbols XCBKeySymbols; + + +XCBKeySymbols *XCBKeySymbolsAlloc (XCBConnection *c); + +void XCBKeySymbolsFree (XCBKeySymbols *syms); + +XCBKEYSYM XCBKeySymbolsGetKeysym (XCBKeySymbols *syms, + XCBKEYCODE keycode, + int col); + +XCBKEYCODE XCBKeySymbolsGetKeycode (XCBKeySymbols *syms, + XCBKEYSYM keysym); + +XCBKEYSYM XCBKeyPressLookupKeysym (XCBKeySymbols *syms, + XCBKeyPressEvent *event, + int col); + +XCBKEYSYM XCBKeyReleaseLookupKeysym (XCBKeySymbols *syms, + XCBKeyReleaseEvent *event, + int col); + +int XCBRefreshKeyboardMapping (XCBKeySymbols *syms, + XCBMappingNotifyEvent *event); + + +/* Tests for classes of symbols */ + +int XCBIsKeypadKey (XCBKEYSYM keysym); + +int XCBIsPrivateKeypadKey (XCBKEYSYM keysym); + +int XCBIsCursorKey (XCBKEYSYM keysym); + +int XCBIsPFKey (XCBKEYSYM keysym); + +int XCBIsFunctionKey (XCBKEYSYM keysym); + +int XCBIsMiscFunctionKey (XCBKEYSYM keysym); + +int XCBIsModifierKey (XCBKEYSYM keysym); + + +#endif /* __XCB_KEYSYMS_H__ */ diff --git a/property/.cvsignore b/property/.cvsignore new file mode 100644 index 0000000..65e939d --- /dev/null +++ b/property/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc diff --git a/property/Makefile.am b/property/Makefile.am new file mode 100644 index 0000000..d7b0fea --- /dev/null +++ b/property/Makefile.am @@ -0,0 +1,16 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBProperty.la + +xcbinclude_HEADERS = xcb_property.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) -I../event +LDADD = $(XCB_LIBS) -L../event -lXCBEvent + +libXCBProperty_la_SOURCES = prop.c + +pkgconfig_DATA = xcb-property.pc + +EXTRA_DIST = xcb-property.pc.in diff --git a/property/prop.c b/property/prop.c new file mode 100644 index 0000000..e5375dd --- /dev/null +++ b/property/prop.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include "xcb_property.h" + +typedef struct { + CARD32 long_len; + GenericPropertyHandler handler; + void *data; +} propHandler; + +typedef struct node node; +struct node { + node *next; + XCBATOM name; + propHandler h; +}; + +struct PropertyHandlers { + node *head; + propHandler *def; + EventHandlers *evenths; +}; + +XCBGetPropertyCookie GetAnyProperty(XCBConnection *c, BOOL del, XCBWINDOW window, XCBATOM name, CARD32 long_len) +{ + static const XCBATOM type = { AnyPropertyType }; + return XCBGetProperty(c, del, window, name, type, 0, long_len); +} + +static int callHandler(XCBConnection *c, BYTE state, XCBWINDOW window, XCBATOM atom, propHandler *h) +{ + XCBGetPropertyRep *propr = 0; + int ret; + if(state != PropertyDelete) + { + XCBGetPropertyCookie cookie = GetAnyProperty(c, 0, window, atom, h->long_len); + propr = XCBGetPropertyReply(c, cookie, 0); + } + ret = h->handler(h->data, c, state, window, atom, propr); + free(propr); + return ret; +} + +int PropertyChanged(PropertyHandlers *prophs, BYTE state, XCBWINDOW window, XCBATOM atom) +{ + XCBConnection *c = getXCBConnection(GetPropertyEventHandlers(prophs)); + node *cur; + for(cur = prophs->head; cur; cur = cur->next) + if(cur->name.xid == atom.xid) + return callHandler(c, state, window, atom, &cur->h); + if(prophs->def) + return callHandler(c, state, window, atom, prophs->def); + return 0; +} + +static int handlePropertyNotifyEvent(void *data, XCBConnection *c, XCBPropertyNotifyEvent *e) +{ + PropertyHandlers *prophs = data; + BYTE state = e->state; + XCBWINDOW window = e->window; + XCBATOM atom = e->atom; + + return PropertyChanged(prophs, state, window, atom); +} + +PropertyHandlers *AllocPropertyHandlers(EventHandlers *evenths) +{ + PropertyHandlers *prophs = malloc(sizeof(PropertyHandlers)); + if(prophs) + { + prophs->head = 0; + prophs->def = 0; + prophs->evenths = evenths; + setPropertyNotifyEventHandler(evenths, handlePropertyNotifyEvent, prophs); + } + return prophs; +} + +void FreePropertyHandlers(PropertyHandlers *prophs) +{ + free(prophs); +} + +EventHandlers *GetPropertyEventHandlers(PropertyHandlers *prophs) +{ + return prophs->evenths; +} + +static inline void setPropHandler(propHandler *cur, CARD32 long_len, GenericPropertyHandler handler, void *data) +{ + cur->long_len = long_len; + cur->handler = handler; + cur->data = data; +} + +int SetPropertyHandler(PropertyHandlers *prophs, XCBATOM name, CARD32 long_len, GenericPropertyHandler handler, void *data) +{ + node *cur = malloc(sizeof(node)); + if(!cur) + return 0; + cur->next = prophs->head; + cur->name = name; + setPropHandler(&cur->h, long_len, handler, data); + prophs->head = cur; + return 1; +} + +int SetDefaultPropertyHandler(PropertyHandlers *prophs, CARD32 long_len, GenericPropertyHandler handler, void *data) +{ + assert(!prophs->def); + prophs->def = malloc(sizeof(propHandler)); + if(!prophs->def) + return 0; + setPropHandler(prophs->def, long_len, handler, data); + return 1; +} + +int rootOfScreen(XCBConnection *c, int screen, XCBWINDOW *root) +{ + XCBSCREENIter i = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)); + if(screen >= i.rem) + return 0; + for(; screen && i.rem; --screen, XCBSCREENNext(&i)) + /* empty */; + *root = i.data->root; + return 1; +} + +XCBVoidCookie sendToWindow(XCBConnection *c, XCBWINDOW root, const XCBClientMessageEvent *ev) +{ + return XCBSendEvent(c, /* propagate */ 0, root, SubstructureNotifyMask | SubstructureRedirectMask, (const char *) ev); +} diff --git a/property/xcb-property.pc.in b/property/xcb-property.pc.in new file mode 100644 index 0000000..543bdc5 --- /dev/null +++ b/property/xcb-property.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBImage +Description: XCB image convenience library +Version: @PACKAGE_VERSION@ +Requires: xcb xcb-event +Libs: -L${libdir} -lXCBProperty @LIBS@ +Cflags: -I${includedir} diff --git a/property/xcb_property.h b/property/xcb_property.h new file mode 100644 index 0000000..185b9a0 --- /dev/null +++ b/property/xcb_property.h @@ -0,0 +1,21 @@ +#ifndef PROP_H +#define PROP_H + +#include "xcb_event.h" + +XCBGetPropertyCookie GetAnyProperty(XCBConnection *c, BOOL del, XCBWINDOW window, XCBATOM name, CARD32 long_len); + +typedef struct PropertyHandlers PropertyHandlers; + +PropertyHandlers *AllocPropertyHandlers(EventHandlers *evenths); +void FreePropertyHandlers(PropertyHandlers *prophs); +EventHandlers *GetPropertyEventHandlers(PropertyHandlers *prophs); + +typedef int (*GenericPropertyHandler)(void *data, XCBConnection *c, BYTE state, XCBWINDOW window, XCBATOM atom, XCBGetPropertyRep *property); + +int SetPropertyHandler(PropertyHandlers *prophs, XCBATOM name, CARD32 long_len, GenericPropertyHandler handler, void *data); +int SetDefaultPropertyHandler(PropertyHandlers *prophs, CARD32 long_len, GenericPropertyHandler handler, void *data); + +int PropertyChanged(PropertyHandlers *prophs, BYTE state, XCBWINDOW window, XCBATOM atom); + +#endif /* PROP_H */ diff --git a/reply/.cvsignore b/reply/.cvsignore new file mode 100644 index 0000000..fb7d9c8 --- /dev/null +++ b/reply/.cvsignore @@ -0,0 +1,9 @@ +.deps +.libs +Makefile.in +Makefile +*.lo +*.loT +*.la +*.pc +test_reply diff --git a/reply/Makefile.am b/reply/Makefile.am new file mode 100644 index 0000000..ddfffa6 --- /dev/null +++ b/reply/Makefile.am @@ -0,0 +1,22 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBReply.la + +xcbinclude_HEADERS = xcb_reply.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) +LDADD = $(XCB_LIBS) + +libXCBReply_la_LIBADD = -lpthread +libXCBReply_la_SOURCES = reply.c + +pkgconfig_DATA = xcb-reply.pc + +EXTRA_DIST=xcb-reply.pc.in + +noinst_PROGRAMS = test_reply + +test_reply_LDADD = $(LDADD) -L. -lXCBReply +test_reply_SOURCES = test_reply.c diff --git a/reply/reply.c b/reply/reply.c new file mode 100644 index 0000000..5045690 --- /dev/null +++ b/reply/reply.c @@ -0,0 +1,141 @@ +#include "xcb_reply.h" + +#include +#include + +struct node { + struct node *next; + unsigned int request; + GenericReplyHandler handler; + void *data; + char handled; +}; + +struct ReplyHandlers { + pthread_mutex_t lock; + pthread_cond_t cond; + struct node *head; + XCBConnection *c; + char stop; +}; + +ReplyHandlers *allocReplyHandlers(XCBConnection *c) +{ + ReplyHandlers *ret = calloc(1, sizeof(ReplyHandlers)); + if(ret) + { + static const pthread_mutex_t proto_lock = PTHREAD_MUTEX_INITIALIZER; + static const pthread_cond_t proto_cond = PTHREAD_COND_INITIALIZER; + ret->lock = proto_lock; + ret->cond = proto_cond; + ret->c = c; + } + return ret; +} + +void freeReplyHandlers(ReplyHandlers *h) +{ + free(h); +} + +XCBConnection *getXCBConnection(ReplyHandlers *h) +{ + return h->c; +} + +static void insert_handler(ReplyHandlers *h, struct node *cur) +{ + struct node **prev = &h->head; + while(*prev && (*prev)->request < cur->request) + prev = &(*prev)->next; + cur->next = *prev; + *prev = cur; +} + +static int do_poll(ReplyHandlers *h) +{ + XCBGenericRep *reply; + XCBGenericError *error; + int handled; + struct node *cur = h->head; + h->head = cur->next; + + pthread_mutex_unlock(&h->lock); + pthread_cleanup_push((void (*)(void *)) pthread_mutex_lock, &h->lock); + reply = XCBWaitForReply(h->c, cur->request, &error); + + if(reply || error) + { + cur->handler(cur->data, h->c, reply, error); + handled = cur->handled = 1; + free(reply); + free(error); + } + else + { + handled = cur->handled; + free(cur); + } + + pthread_cleanup_pop(1); + if(reply || error) + insert_handler(h, cur); + return handled; +} + +int PollReplies(ReplyHandlers *h) +{ + int ret = 1; + XCBFlush(h->c); + pthread_mutex_lock(&h->lock); + while(ret && h->head && XCBGetRequestRead(h->c) >= h->head->request) + ret = do_poll(h); + pthread_mutex_unlock(&h->lock); + return ret; +} + +static void *reply_thread(void *hvp) +{ + ReplyHandlers *h = hvp; + pthread_mutex_lock(&h->lock); + pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &h->lock); + while(1) + { + while(h->head) + do_poll(h); + if(h->stop) + break; + pthread_cond_wait(&h->cond, &h->lock); + } + pthread_cleanup_pop(1); + return 0; +} + +pthread_t StartReplyThread(ReplyHandlers *h) +{ + pthread_t ret; + pthread_create(&ret, 0, reply_thread, h); + return ret; +} + +void StopReplyThreads(ReplyHandlers *h) +{ + pthread_mutex_lock(&h->lock); + h->stop = 1; + pthread_cond_broadcast(&h->cond); + pthread_mutex_unlock(&h->lock); +} + +void AddReplyHandler(ReplyHandlers *h, unsigned int request, GenericReplyHandler handler, void *data) +{ + struct node *cur = malloc(sizeof(struct node)); + cur->request = request; + cur->handler = handler; + cur->data = data; + cur->handled = 0; + + pthread_mutex_lock(&h->lock); + insert_handler(h, cur); + pthread_cond_broadcast(&h->cond); + pthread_mutex_unlock(&h->lock); +} diff --git a/reply/test_reply.c b/reply/test_reply.c new file mode 100644 index 0000000..d6948fa --- /dev/null +++ b/reply/test_reply.c @@ -0,0 +1,46 @@ +#include "xcb_reply.h" + +#include +#include +#include +#include + +void fontinfo_handler(void *data, XCBConnection *c, XCBGenericRep *rg, XCBGenericError *eg) +{ + XCBListFontsWithInfoRep *rep = (XCBListFontsWithInfoRep *) rg; + if(rep) + { + int len = XCBListFontsWithInfoNameLength(rep); + if(len) + printf("(+%u) Font \"%.*s\"\n", + (unsigned int) rep->replies_hint, + len, XCBListFontsWithInfoName(rep)); + else + printf("End of font list.\n"); + } + if(eg) + printf("Error from ListFontsWithInfo: %d\n", eg->error_code); +} + +int main(int argc, char **argv) +{ + int count = 10; + char *pattern = "*"; + XCBConnection *c = XCBConnect(NULL, NULL); + ReplyHandlers *h = allocReplyHandlers(c); + pthread_t reply_thread; + + if(argc > 1) + count = atoi(argv[1]); + if(argc > 2) + pattern = argv[2]; + + AddReplyHandler(h, XCBListFontsWithInfo(c, count, strlen(pattern), pattern).sequence, fontinfo_handler, 0); + reply_thread = StartReplyThread(h); + + XCBSync(c, 0); + StopReplyThreads(h); + pthread_join(reply_thread, 0); + XCBDisconnect(c); + exit(0); +} diff --git a/reply/xcb-reply.pc.in b/reply/xcb-reply.pc.in new file mode 100644 index 0000000..a383165 --- /dev/null +++ b/reply/xcb-reply.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBReply +Description: XCB reply convenience library +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lXCBReply @LIBS@ +Cflags: -I${includedir} diff --git a/reply/xcb_reply.h b/reply/xcb_reply.h new file mode 100644 index 0000000..b345d84 --- /dev/null +++ b/reply/xcb_reply.h @@ -0,0 +1,20 @@ +#ifndef REPLY_H +#define REPLY_H + +#include +#include + +typedef struct ReplyHandlers ReplyHandlers; +ReplyHandlers *allocReplyHandlers(XCBConnection *c); +void freeReplyHandlers(ReplyHandlers *h); +XCBConnection *getXCBConnection(ReplyHandlers *h); + +int PollReplies(ReplyHandlers *h); +pthread_t StartReplyThread(ReplyHandlers *h); +void StopReplyThreads(ReplyHandlers *h); + +typedef void (*GenericReplyHandler)(void *data, XCBConnection *c, XCBGenericRep *reply, XCBGenericError *error); + +void AddReplyHandler(ReplyHandlers *h, unsigned int request, GenericReplyHandler handler, void *data); + +#endif /* REPLY_H */ diff --git a/wm/.cvsignore b/wm/.cvsignore new file mode 100644 index 0000000..c95cdce --- /dev/null +++ b/wm/.cvsignore @@ -0,0 +1,9 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +*.loT +*.la +*.pc +xcbwm-test diff --git a/wm/Makefile.am b/wm/Makefile.am new file mode 100644 index 0000000..994aec6 --- /dev/null +++ b/wm/Makefile.am @@ -0,0 +1,26 @@ + +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libXCBWM.la + +xcbinclude_HEADERS = xcb_wm.h + +AM_CFLAGS = -Wall +INCLUDES = $(XCB_CFLAGS) -I../convenient -I../atom -I../event -I../property -I../icccm +LDADD = $(XCB_LIBS) \ + -L../convenient -lXCBAux \ + -L../atom -lXCBAtom \ + -L../event -lXCBEvent \ + -L../property -lXCBProperty \ + -L../icccm -lXCBICCCM + +libXCBWM_la_SOURCES = manage.c table.c + +pkgconfig_DATA = xcb-wm.pc + +EXTRA_DIST = xcb-wm.pc.in + +noinst_PROGRAMS = xcbwm-test + +xcbwm_test_LDADD = $(LDADD) -L. -lXCBWM -lpthread +xcbwm_test_SOURCES = xcbwm-test.c reply_formats.c reply_formats.h diff --git a/wm/manage.c b/wm/manage.c new file mode 100644 index 0000000..b196055 --- /dev/null +++ b/wm/manage.c @@ -0,0 +1,115 @@ +#include +#include +#include "xcb_wm.h" + +Table *byChild = 0; +Table *byParent = 0; + +void manageWindow(PropertyHandlers *prophs, XCBConnection *c, XCBWINDOW window, WindowAttributes wa) +{ + XCBDRAWABLE d = { window }; + XCBGetGeometryCookie geomc; + XCBGetGeometryRep *geom; + XCBGetWindowAttributesRep *attr = 0; + if(wa.tag == TAG_COOKIE) + { + attr = XCBGetWindowAttributesReply(c, wa.u.cookie, 0); + if(!attr) + return; + if(attr->map_state != IsViewable) + { + printf("Window 0x%08lx is not mapped. Ignoring.\n", window.xid); + free(attr); + return; + } + wa.tag = TAG_VALUE; + wa.u.override_redirect = attr->override_redirect; + } + if(!wa.u.override_redirect && TableGet(byChild, window.xid)) + { + printf("Window 0x%08lx already managed. Ignoring.\n", window.xid); + free(attr); + return; + } + if(wa.u.override_redirect) + { + printf("Window 0x%08lx has override-redirect set. Ignoring.\n", window.xid); + free(attr); + return; + } + geomc = XCBGetGeometry(c, d); + if(!attr) + { + wa.tag = TAG_COOKIE; + wa.u.cookie = XCBGetWindowAttributes(c, window); + attr = XCBGetWindowAttributesReply(c, wa.u.cookie, 0); + } + geom = XCBGetGeometryReply(c, geomc, 0); + if(attr && geom) + { + reparentWindow(c, window, attr->visual, geom->root, geom->depth, geom->x, geom->y, geom->width, geom->height); + PropertyChanged(prophs, PropertyNewValue, window, WM_NAME); + } + free(attr); + free(geom); +} + +int handleMapNotifyEvent(void *prophs, XCBConnection *c, XCBMapNotifyEvent *e) +{ + WindowAttributes wa = { TAG_VALUE }; + wa.u.override_redirect = e->override_redirect; + printf("MapNotify for 0x%08lx.\n", e->window.xid); + manageWindow(prophs, c, e->window, wa); + return 1; +} + +int handleUnmapNotifyEvent(void *data, XCBConnection *c, XCBUnmapNotifyEvent *e) +{ + ClientWindow *client = TableRemove(byChild, e->event.xid); + XCBWINDOW root; + printf("UnmapNotify for 0x%08lx (received from 0x%08lx): ", e->window.xid, e->event.xid); + if(!client) + { + printf("not a managed window. Ignoring.\n"); + return 0; + } + + root = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)).data->root; + printf("child of 0x%08lx.\n", client->parent.xid); + XCBReparentWindow(c, client->child, root, 0, 0); + XCBDestroyWindow(c, client->parent); + XCBFlush(c); + TableRemove(byParent, client->parent.xid); + free(client); + return 1; +} + +void manageExistingWindows(XCBConnection *c, PropertyHandlers *prophs, XCBWINDOW root) +{ + XCBQueryTreeCookie wintree; + XCBQueryTreeRep *rep; + int i, len; + XCBWINDOW *children; + XCBGetWindowAttributesCookie *cookies; + + wintree = XCBQueryTree(c, root); + rep = XCBQueryTreeReply(c, wintree, 0); + if(!rep) + return; + len = XCBQueryTreeChildrenLength(rep); + cookies = malloc(len * sizeof(*cookies)); + if(!cookies) + { + free(rep); + return; + } + children = XCBQueryTreeChildren(rep); + for(i = 0; i < len; ++i) + cookies[i] = XCBGetWindowAttributes(c, children[i]); + for(i = 0; i < len; ++i) + { + WindowAttributes wa = { TAG_COOKIE, { cookies[i] } }; + manageWindow(prophs, c, children[i], wa); + } + free(rep); +} diff --git a/wm/reply_formats.c b/wm/reply_formats.c new file mode 100644 index 0000000..d2e20d8 --- /dev/null +++ b/wm/reply_formats.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. See the file COPYING in this directory + * for licensing information. + */ + +#include +#include "reply_formats.h" + +#define WINFMT "0x%08x" + +int formatGetWindowAttributesReply(XCBWINDOW wid, XCBGetWindowAttributesRep *reply) +{ + if(!reply) + { + fprintf(stderr, "Failed to get attributes for window " WINFMT ".\n", + (unsigned int) wid.xid); + return 0; + } + + printf("Window " WINFMT " has attributes:\n" + " backingStore = %d\n" + " visualID = %#x\n" + " class = %d\n" + " bitGravity = %d\n" + " winGravity = %d\n" + " backingBitPlanes = 0x%08lx\n" + " backingPixel = %ld\n" + " saveUnder = %d\n" + " mapInstalled = %d\n" + " mapState = %d\n" + " override = %d\n" + " colormap = 0x%08x\n" + " allEventMasks = 0x%08x\n" + " yourEventMask = 0x%08x\n" + " doNotPropagateMask = 0x%08x\n", + (unsigned int) wid.xid, + reply->backing_store, + (unsigned int) reply->visual.id, + reply->_class, + reply->bit_gravity, + reply->win_gravity, + reply->backing_planes, + reply->backing_pixel, + reply->save_under, + reply->map_is_installed, + reply->map_state, + reply->override_redirect, + (unsigned int) reply->colormap.xid, + (unsigned int) reply->all_event_masks, + (unsigned int) reply->your_event_mask, + reply->do_not_propagate_mask); + + fflush(stdout); + return 1; +} + +int formatGetGeometryReply(XCBWINDOW wid, XCBGetGeometryRep *reply) +{ + if(!reply) + { + fprintf(stderr, "Failed to get geometry for window " WINFMT ".\n", + (unsigned int) wid.xid); + return 0; + } + + printf("Geometry for window " WINFMT ": %dx%d%+d%+d\n", + (unsigned int) wid.xid, + reply->width, + reply->height, + reply->x, + reply->y); + + fflush(stdout); + return 1; +} + +int formatQueryTreeReply(XCBWINDOW wid, XCBQueryTreeRep *reply) +{ + int i; + + if(!reply) + { + fprintf(stderr, "Failed to query tree for window " WINFMT ".\n", + (unsigned int) wid.xid); + return 0; + } + + printf("Window " WINFMT " has parent " WINFMT ", root " WINFMT ", and %d children%c\n", + (unsigned int) wid.xid, + (unsigned int) reply->parent.xid, + (unsigned int) reply->root.xid, + (unsigned int) reply->children_len, + reply->children_len ? ':' : '.'); + + for(i = 0; i < reply->children_len; ++i) + printf(" window " WINFMT "\n", + (unsigned int) XCBQueryTreeChildren(reply)[i].xid); + + fflush(stdout); + return 1; +} + +static const char *labelError[] = { + "Success", + "BadRequest", + "BadValue", + "BadWindow", + "BadPixmap", + "BadAtom", + "BadCursor", + "BadFont", + "BadMatch", + "BadDrawable", + "BadAccess", + "BadAlloc", + "BadColor", + "BadGC", + "BadIDChoice", + "BadName", + "BadLength", + "BadImplementation", +}; + +static const char *labelRequest[] = { + "no request", + "CreateWindow", + "ChangeWindowAttributes", + "GetWindowAttributes", + "DestroyWindow", + "DestroySubwindows", + "ChangeSaveSet", + "ReparentWindow", + "MapWindow", + "MapSubwindows", + "UnmapWindow", + "UnmapSubwindows", + "ConfigureWindow", + "CirculateWindow", + "GetGeometry", + "QueryTree", + "InternAtom", + "GetAtomName", + "ChangeProperty", + "DeleteProperty", + "GetProperty", + "ListProperties", + "SetSelectionOwner", + "GetSelectionOwner", + "ConvertSelection", + "SendEvent", + "GrabPointer", + "UngrabPointer", + "GrabButton", + "UngrabButton", + "ChangeActivePointerGrab", + "GrabKeyboard", + "UngrabKeyboard", + "GrabKey", + "UngrabKey", + "AllowEvents", + "GrabServer", + "UngrabServer", + "QueryPointer", + "GetMotionEvents", + "TranslateCoords", + "WarpPointer", + "SetInputFocus", + "GetInputFocus", + "QueryKeymap", + "OpenFont", + "CloseFont", + "QueryFont", + "QueryTextExtents", + "ListFonts", + "ListFontsWithInfo", + "SetFontPath", + "GetFontPath", + "CreatePixmap", + "FreePixmap", + "CreateGC", + "ChangeGC", + "CopyGC", + "SetDashes", + "SetClipRectangles", + "FreeGC", + "ClearArea", + "CopyArea", + "CopyPlane", + "PolyPoint", + "PolyLine", + "PolySegment", + "PolyRectangle", + "PolyArc", + "FillPoly", + "PolyFillRectangle", + "PolyFillArc", + "PutImage", + "GetImage", + "PolyText", + "PolyText", + "ImageText", + "ImageText", + "CreateColormap", + "FreeColormap", + "CopyColormapAndFree", + "InstallColormap", + "UninstallColormap", + "ListInstalledColormaps", + "AllocColor", + "AllocNamedColor", + "AllocColorCells", + "AllocColorPlanes", + "FreeColors", + "StoreColors", + "StoreNamedColor", + "QueryColors", + "LookupColor", + "CreateCursor", + "CreateGlyphCursor", + "FreeCursor", + "RecolorCursor", + "QueryBestSize", + "QueryExtension", + "ListExtensions", + "ChangeKeyboardMapping", + "GetKeyboardMapping", + "ChangeKeyboardControl", + "GetKeyboardControl", + "Bell", + "ChangePointerControl", + "GetPointerControl", + "SetScreenSaver", + "GetScreenSaver", + "ChangeHosts", + "ListHosts", + "SetAccessControl", + "SetCloseDownMode", + "KillClient", + "RotateProperties", + "ForceScreenSaver", + "SetPointerMapping", + "GetPointerMapping", + "SetModifierMapping", + "GetModifierMapping", + "major 120", + "major 121", + "major 122", + "major 123", + "major 124", + "major 125", + "major 126", + "NoOperation", +}; + +static const char *labelEvent[] = { + "error", + "reply", + "KeyPress", + "KeyRelease", + "ButtonPress", + "ButtonRelease", + "MotionNotify", + "EnterNotify", + "LeaveNotify", + "FocusIn", + "FocusOut", + "KeymapNotify", + "Expose", + "GraphicsExpose", + "NoExpose", + "VisibilityNotify", + "CreateNotify", + "DestroyNotify", + "UnmapNotify", + "MapNotify", + "MapRequest", + "ReparentNotify", + "ConfigureNotify", + "ConfigureRequest", + "GravityNotify", + "ResizeRequest", + "CirculateNotify", + "CirculateRequest", + "PropertyNotify", + "SelectionClear", + "SelectionRequest", + "SelectionNotify", + "ColormapNotify", + "ClientMessage", + "MappingNotify", +}; + +static const char *labelSendEvent[] = { + "", + " (from SendEvent)", +}; + +int formatEvent(XCBGenericEvent *e) +{ + BYTE sendEvent; + CARD16 seqnum; + + sendEvent = (e->response_type & 0x80) ? 1 : 0; + e->response_type &= ~0x80; + seqnum = *((CARD16 *) e + 1); + + switch(e->response_type) + { + case 0: + printf("Error %s on seqnum %d (%s).\n", + labelError[*((BYTE *) e + 1)], + seqnum, + labelRequest[*((CARD8 *) e + 10)]); + break; + default: + printf("Event %s following seqnum %d%s.\n", + labelEvent[e->response_type], + seqnum, + labelSendEvent[sendEvent]); + break; + case XCBKeymapNotify: + printf("Event %s%s.\n", + labelEvent[e->response_type], + labelSendEvent[sendEvent]); + break; + } + + fflush(stdout); + return 1; +} diff --git a/wm/reply_formats.h b/wm/reply_formats.h new file mode 100644 index 0000000..998e88d --- /dev/null +++ b/wm/reply_formats.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2001-2002 Bart Massey and Jamey Sharp. + * All Rights Reserved. See the file COPYING in this directory + * for licensing information. + */ + +#ifndef REPLY_FORMATS_H +#define REPLY_FORMATS_H + +#include + +int formatGetWindowAttributesReply(XCBWINDOW wid, XCBGetWindowAttributesRep *reply); +int formatGetGeometryReply(XCBWINDOW wid, XCBGetGeometryRep *reply); +int formatQueryTreeReply(XCBWINDOW wid, XCBQueryTreeRep *reply); +int formatEvent(XCBGenericEvent *e); + +#if 0 /* not yet ready */ +int formatButtonReleaseEvent(void *data, XCBConnection *c, XCBButtonReleaseEvent *event); +int formatEnterNotifyEvent(void *data, XCBConnection *c, XCBEnterNotifyEvent *event); +int formatExposeEvent(void *data, XCBConnection *c, XCBExposeEvent *event); +int formatDestroyNotifyEvent(void *data, XCBConnection *c, XCBDestroyNotifyEvent *event); +int formatUnmapNotifyEvent(void *data, XCBConnection *c, XCBUnmapNotifyEvent *event); +int formatMapNotifyEvent(void *data, XCBConnection *c, XCBMapNotifyEvent *event); +int formatReparentNotifyEvent(void *data, XCBConnection *c, XCBReparentNotifyEvent *event); +int formatConfigureNotifyEvent(void *data, XCBConnection *c, XCBConfigureNotifyEvent *event); +int formatGravityNotifyEvent(void *data, XCBConnection *c, XCBGravityNotifyEvent *event); +int formatCirculateNotifyEvent(void *data, XCBConnection *c, XCBCirculateNotifyEvent *event); +int formatClientMessageEvent(void *data, XCBConnection *c, XCBClientMessageEvent *event); +#endif + +#endif /* REPLY_FORMATS_H */ diff --git a/wm/table.c b/wm/table.c new file mode 100644 index 0000000..5ab33a1 --- /dev/null +++ b/wm/table.c @@ -0,0 +1,59 @@ +#include +#include "xcb_wm.h" + +typedef struct node node; +struct node { + node *next; + CARD32 key; + void *value; +}; + +struct Table { + node *head; +}; + +Table *AllocTable() +{ + return calloc(1, sizeof(Table)); +} + +void FreeTable(Table *table) +{ + free(table); +} + +int TablePut(Table *table, CARD32 key, void *value) +{ + node *record = malloc(sizeof(node)); + if(!record) + return 0; + record->next = table->head; + record->key = key; + record->value = value; + table->head = record; + return 1; +} + +void *TableGet(Table *table, CARD32 key) +{ + node *cur; + for(cur = table->head; cur; cur = cur->next) + if(cur->key == key) + return cur->value; + return 0; +} + +void *TableRemove(Table *table, CARD32 key) +{ + node **cur; + for(cur = &table->head; *cur; cur = &(*cur)->next) + if((*cur)->key == key) + { + node *tmp = *cur; + void *ret = tmp->value; + *cur = (*cur)->next; + free(tmp); + return ret; + } + return 0; +} diff --git a/wm/xcb-wm.pc.in b/wm/xcb-wm.pc.in new file mode 100644 index 0000000..07c840d --- /dev/null +++ b/wm/xcb-wm.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCBImage +Description: XCB image convenience library +Version: @PACKAGE_VERSION@ +Requires: xcb xcb-atom xcb-event xcb-property xcb-icccm +Libs: -L${libdir} -lXCBWM @LIBS@ +Cflags: -I${includedir} diff --git a/wm/xcb_wm.h b/wm/xcb_wm.h new file mode 100644 index 0000000..191392d --- /dev/null +++ b/wm/xcb_wm.h @@ -0,0 +1,45 @@ +#ifndef XCB_WM +#define XCB_WM + +#include +#include "xcb_atom.h" +#include "xcb_property.h" + +void reparentWindow(XCBConnection *c, XCBWINDOW child, + XCBVISUALID v, XCBWINDOW r, CARD8 d, + INT16 x, INT16 y, CARD16 width, CARD16 height); + +typedef struct { + XCBWINDOW child; + XCBWINDOW parent; + int name_len; + char *name; + XCBGCONTEXT titlegc; +} ClientWindow; + +typedef struct { + enum tag_t tag; + union { + XCBGetWindowAttributesCookie cookie; + BOOL override_redirect; + } u; +} WindowAttributes; + +void manageWindow(PropertyHandlers *prophs, XCBConnection *c, XCBWINDOW window, WindowAttributes wa); +int handleMapNotifyEvent(void *prophs, XCBConnection *c, XCBMapNotifyEvent *e); +int handleUnmapNotifyEvent(void *data, XCBConnection *c, XCBUnmapNotifyEvent *e); +void manageExistingWindows(XCBConnection *c, PropertyHandlers *prophs, XCBWINDOW root); + +typedef struct Table Table; + +Table *AllocTable(); +void FreeTable(Table *table); + +int TablePut(Table *table, CARD32 key, void *value); +void *TableGet(Table *table, CARD32 key); +void *TableRemove(Table *table, CARD32 key); + +extern Table *byChild; +extern Table *byParent; + +#endif /* XCB_WM */ diff --git a/wm/xcbwm-test.c b/wm/xcbwm-test.c new file mode 100644 index 0000000..1de4ac2 --- /dev/null +++ b/wm/xcbwm-test.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include + +#include +#include "reply_formats.h" +#include "xcb_aux.h" +#include "xcb_event.h" +#include "xcb_atom.h" +#include "xcb_icccm.h" +#include "xcb_wm.h" + +static const int TOP = 20; +static const int LEFT = 5; +static const int BOTTOM = 5; +static const int RIGHT = 5; + +static const int TEST_THREADS = 1; +static const int TEST_WATCH_ROOT = 1; + +static INT16 move_from_x = -1; +static INT16 move_from_y = -1; + +static int handleEvent(void *ignored, XCBConnection *c, XCBGenericEvent *e) +{ + return formatEvent(e); +} + +static int handleButtonPressEvent(void *data, XCBConnection *c, XCBButtonPressEvent *e) +{ + if(move_from_x != -1 && move_from_y != -1) + { + printf("Weird. Got ButtonPress after ButtonPress.\n"); + return 0; + } + move_from_x = e->root_x; + move_from_y = e->root_y; + return 1; +} + +static int handleButtonReleaseEvent(void *data, XCBConnection *c, XCBButtonReleaseEvent *e) +{ + CARD32 values[2]; + if(move_from_x == -1 && move_from_y == -1) + { + printf("Weird. Got ButtonRelease without ButtonPress.\n"); + return 0; + } + values[0] = /* x */ e->root_x; + values[1] = /* y */ e->root_y; + XCBConfigureWindow(c, e->event, CWX | CWY, values); + XCBFlush(c); + move_from_x = -1; + move_from_y = -1; + return 1; +} + +static int addClientWindow(XCBWINDOW child, XCBWINDOW parent, XCBGCONTEXT titlegc) +{ + int success; + ClientWindow *record = malloc(sizeof(ClientWindow)); + assert(record); + record->child = child; + record->parent = parent; + record->name_len = 0; + record->name = 0; + record->titlegc = titlegc; + success = TablePut(byParent, parent.xid, record) && + TablePut(byChild, child.xid, record); + assert(success); + return 1; +} + +void reparentWindow(XCBConnection *c, XCBWINDOW child, + XCBVISUALID v, XCBWINDOW r, CARD8 d, + INT16 x, INT16 y, CARD16 width, CARD16 height) +{ + XCBWINDOW w; + XCBDRAWABLE drawable; + CARD32 mask = 0; + CARD32 values[3]; + XCBSCREEN *root = XCBConnSetupSuccessRepRootsIter(XCBGetSetup(c)).data; + XCBGCONTEXT titlegc; + + w = XCBWINDOWNew(c); + + mask |= XCBCWBackPixel; + values[0] = root->white_pixel; + + mask |= XCBCWOverrideRedirect; + values[1] = 1; + + mask |= XCBCWEventMask; + values[2] = ButtonPressMask | ButtonReleaseMask + | ExposureMask /* | EnterWindowMask | LeaveWindowMask */; + + printf("Reparenting 0x%08lx under 0x%08lx.\n", child.xid, w.xid); + XCBCreateWindow(c, d, w, r, x, y, + width + LEFT + RIGHT, height + TOP + BOTTOM, + /* border_width */ 0, InputOutput, v, mask, values); + XCBChangeSaveSet(c, SetModeInsert, child); + XCBMapWindow(c, w); + + titlegc = XCBGCONTEXTNew(c); + + mask = GCForeground | GCBackground; + values[0] = root->black_pixel; + values[1] = root->white_pixel; + drawable.window = w; + XCBCreateGC(c, titlegc, drawable, mask, values); + addClientWindow(child, w, titlegc); + + XCBReparentWindow(c, child, w, LEFT - 1, TOP - 1); + + mask = XCBCWEventMask; + values[0] = PropertyChangeMask | StructureNotifyMask; + XCBChangeWindowAttributes(c, child, mask, values); + + XCBFlush(c); +} + +static void redrawWindow(XCBConnection *c, ClientWindow *client) +{ + XCBDRAWABLE d = { client->parent }; + if(!client->name_len) + return; + XCBClearArea(c, 0, d.window, 0, 0, 0, 0); + XCBImageText8(c, client->name_len, d, client->titlegc, + LEFT - 1, TOP - 4, client->name); + XCBFlush(c); +} + +static int handleExposeEvent(void *data, XCBConnection *c, XCBExposeEvent *e) +{ + ClientWindow *client = TableGet(byParent, e->window.xid); + if(!client || e->count != 0) + return 1; + redrawWindow(c, client); + return 1; +} + +static int handleWMNameChange(void *data, XCBConnection *c, BYTE state, XCBWINDOW window, XCBATOM atom, XCBGetPropertyRep *prop) +{ + ClientWindow *client = TableGet(byChild, window.xid); + printf("WM_NAME change: Window 0x%08lx ", window.xid); + if(!client) + { + printf("is not being managed.\n"); + return 0; + } + if(client->name) + { + printf("was named \"%.*s\"; now ", client->name_len, client->name); + free(client->name); + } + if(!prop) + { + client->name_len = 0; + client->name = 0; + printf("has no name.\n"); + return 1; + } + + client->name_len = XCBGetPropertyValueLength(prop); + client->name = malloc(client->name_len); + assert(client->name); + strncpy(client->name, XCBGetPropertyValue(prop), client->name_len); + printf("is named \"%.*s\".\n", client->name_len, client->name); + + redrawWindow(c, client); + return 1; +} + +int main(int argc, char **argv) +{ + XCBConnection *c; + EventHandlers *evenths; + PropertyHandlers *prophs; + XCBWINDOW root; + pthread_t event_thread; + int screen_nbr; + int i; + + byChild = AllocTable(); + byParent = AllocTable(); + + c = XCBConnect(NULL, &screen_nbr); + + evenths = allocEventHandlers(c); + + for(i = 2; i < 128; ++i) + setEventHandler(evenths, i, handleEvent, 0); + for(i = 0; i < 256; ++i) + setErrorHandler(evenths, i, (GenericErrorHandler) handleEvent, 0); + setButtonPressEventHandler(evenths, handleButtonPressEvent, 0); + setButtonReleaseEventHandler(evenths, handleButtonReleaseEvent, 0); + setUnmapNotifyEventHandler(evenths, handleUnmapNotifyEvent, 0); + setExposeEventHandler(evenths, handleExposeEvent, 0); + + prophs = AllocPropertyHandlers(evenths); + setMapNotifyEventHandler(evenths, handleMapNotifyEvent, prophs); + WatchWMName(prophs, 40, handleWMNameChange, 0); + + if(TEST_THREADS) + { + pthread_create(&event_thread, 0, (void *(*)(void *))eventLoop, evenths); + } + + root = XCBAuxGetScreen(c, screen_nbr)->root; + + { + CARD32 mask = XCBCWEventMask; + CARD32 values[] = { SubstructureNotifyMask | PropertyChangeMask }; + XCBChangeWindowAttributes(c, root, mask, values); + } + XCBFlush(c); + + manageExistingWindows(c, prophs, root); + + /* Terminate only when the event loop terminates */ + if(TEST_THREADS) + pthread_join(event_thread, 0); + else + eventLoop(evenths); + + exit(0); + /*NOTREACHED*/ +} diff --git a/xcb_util_intro.in b/xcb_util_intro.in new file mode 100644 index 0000000..482d658 --- /dev/null +++ b/xcb_util_intro.in @@ -0,0 +1,21 @@ +/** +@file +@brief XCB Utility functions + +These routines are used to facilitate the use of XCB in programs +*/ + +/** + +@mainpage XCB Utility Documentation +@version @PACKAGE_VERSION@ +@author Jamey Sharp +@author Vincent Torri +@date 2005 + + +@section intro What is available ? + +@todo Add more functions in XCBAux + +*/