[Xcb-commit] win32port.mdwn
XCB site
xcb at freedesktop.org
Sat Mar 28 11:40:17 PDT 2009
win32port.mdwn | 450 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 450 insertions(+)
New commits:
commit 4c1d3dc3c5ded07c6d8dc5ae33c902679401ba58
Author: Jatin <Jatin at web>
Date: Sat Mar 28 11:40:16 2009 -0700
diff --git a/win32port.mdwn b/win32port.mdwn
new file mode 100644
index 0000000..e73d757
--- /dev/null
+++ b/win32port.mdwn
@@ -0,0 +1,450 @@
+# XCB out of Windows
+-jatin golani (aka jeetu aka topcat) <jeetu.golani at gmail.com>
+
+
+
+
+XCB has now been ported to the Win32 platform. This mess shall soon be unleashed on the world so here is the headsup on it :)
+
+## Background
+***
+
+The Windows operating system no longer includes the POSIX subsystem out of the box. Using POSIX/Unix applications under Windows therefore requires an additional layer such as Microsoft's Interix Posix/Unix subsystem or the Cygwin libraries. Cygwin consists of a library that implements the POSIX system call API in terms of Win32 system calls. Unfortunately, an additional translation layer causes performance degradation. While there are a few X Servers that have been ported to Windows, there has been no port of the X Client library (Xlib or XCB), thereby preventing writing native Windows based X clients. The Win32 XCB port aims at allowing native Windows X Clients to be developed. These native X applications would provide performance superior to applications using libraries such as Cygwin.
+
+
+## What's changed between the *nix and Windows ports?
+***
+
+Essentially the following:
+
+-- The following header files used under *nix development environments are absent or redundant in Windows.
+
+
+* sys/socket.h
+* netinet/in.h
+* sys/un.h
+* sys/select.h
+* sys/uio.h
+* netdb.h
+
+Our code has been changed to skip inclusion of these header files when compiled under WIN32.
+
+-- Source code files effected:
+
+* xcb_auth.c
+
+* xcb_conn.c
+ -- set_fd_flags() : Win32 doesn't have file descriptors and the fcntl function. Made changes that set the socket in non-blocking mode.
+ -- write_vec() : Win32 version using the send() function instead of writev.
+ -- xcb_disconnect() : Calls WSACleanup for Win32 build.
+
+* xcb_in.c
+ -- read_block() : Win32 version using the recv() function instead of read.
+ -- _xcb_in_read() : Win32 version using the recv() function instead of read.
+
+* xcb_util.c
+ -- _xcb_open_unix() : Preprocessor directives prevent this from being compiled while building for Win32.
+ -- _xcb_open() : Does not call _xcb_open_unix for Win32 build.
+ -- _xcb_open_tcp() : Calls initWSA to initialize the Windows Socket Architecture.
+ -- initWSA() : New function added to initialize the Win32 Sockets layer.
+
+* xcb.h
+ -- Declaration for the initWSA function added.
+
+* windefs.h (new header created specifically for the Win32 port)
+
+-- Windefs.h
+
+windefs.h defines all headers and other structures,datatypes,etc required for win32. A key point to note within this header file is the following:
+
+ #define WINVER 0x0501 since getaddrinfo/freeaddrinfo are defined only for WinXP and above. Without this linker complains of undefined references.
+
+Currently, therefore, the code may not compile (untested) on versions prior to XP.
+
+
+
+## Creating the XCB DLL
+***
+
+The following lists the process I used to compile XCB under MinGW on my Debian system :
+
+-- compiled and installed x11proto under standard linux ./autogen && make && make install....then copied the headers from /usr/local/include/X11 to /use/i586-mingw32msvc/include physically.
+
+-- Compiled the DLL version of libXau:
+* ./autogen.sh --host=i586-mingw32msvc
+* make
+* make install
+
+-- Compiled and installed the pthread-win32 library (http://sourceware.org/pthreads-win32/)
+
+ make CC=i586-mingw32msvc-gcc \
+ RC=i586-mingw32msvc-windres \
+ RANLIB=i586-mingw32msvc-ranlib \
+ DLLTOOL=i586-mingw32msvc-dlltool \
+ clean GC
+
+-- Made the following changes (thanks Vincent) -
+
+1. in configure.ac, before AC_PROG_LIBTOOL, add AC_LIBTOOL_WIN32_DLL
+
+2. add, in src/Makefile.am, the value -no-undefined to *_LDFLAGS:
+
+ libxcb_la_LDFLAGS = -no-undefined -version-info 1:0:0
+
+-- set the environment variable LIBS to include the ws2_32 and pthreadGC2 library - export LIBS = -lws2_32 -lpthreadGC2
+
+-- Configured and built using -
+./autogen.sh --host=i586-mingw32msvc
+make
+
+If all goes well the DLL is created within the src/.libs directory.
+
+## Using XCB within Windows
+***
+
+The XCB DLL has been tested predominantly under Windows XP (32 bit). The development environment has been Linux (Debian) using MinGW. However there is no reason you can't use Visual Studio or other IDEs. There are plenty of online resources that show how to create the required .def and .lib files and that speak of differences in name decoration of functions generated by MinGW as opposed to other compilers.
+
+Apart from the XCB DLL (e.g. libxcb-1.dll) you will also need the DLL for libXau (e.g. libXau-6.dll) and Pthreads (e.g. pthreadGC2.dll) to be in your path or along with your source code.
+
+The simplest way to use the DLL under MinGW is to include it during compiling your code. For e.g. :
+
+ i586-mingw32msvc-gcc xcbclient.c libxcb-1.dll -o xcbclient.exe
+
+## X Servers
+***
+
+For testing purposes I have used the following X Servers within Windows. My source code has been connecting locally to these X Servers. I have also connected remotely to my X.org server on Linux.
+
+* XMing <http://www.straightrunning.com/XmingNotes>
+* WinAxe <http://www.labf.com/winaxe/index.html>
+
+## Test Code
+***
+
+The following is a test code from the XCB tutorial. Copy all of the XCB headers within your source code directory or somewhere in your path. If all goes well this should work.
+
+
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
+
+ #include "xcb.h"
+
+ #define WIDTH 300
+ #define HEIGHT 150
+
+ static xcb_gc_t
+ getFontGC (xcb_connection_t *connection,
+ xcb_screen_t *screen,
+ xcb_window_t window,
+ const char *fontName );
+ static void
+ testCookie (xcb_void_cookie_t cookie,
+ xcb_connection_t *connection,
+ char *errMessage )
+ {
+ xcb_generic_error_t *error = xcb_request_check (connection, cookie);
+ if (error)
+ {
+ fprintf (stderr, "ERROR: %s : %d\n", errMessage , error->error_code);
+ xcb_disconnect (connection);
+ exit (-1);
+ }
+ }
+
+
+ static void
+ drawButton (xcb_connection_t *connection,
+ xcb_screen_t *screen,
+ xcb_window_t window,
+ int16_t x1,
+ int16_t y1,
+ const char *label )
+ {
+ uint8_t length = strlen (label);
+ int16_t inset = 2;
+ int16_t width = 7 * length + 2 * (inset + 1);
+ int16_t height = 13 + 2 * (inset + 1);
+
+ xcb_point_t points[5];
+ points[0].x = x1;
+ points[0].y = y1;
+ points[1].x = x1 + width;
+ points[1].y = y1;
+ points[2].x = x1 + width;
+ points[2].y = y1 - height;
+ points[3].x = x1;
+ points[3].y = y1 - height;
+ points[4].x = x1;
+ points[4].y = y1;
+
+
+ xcb_gcontext_t gc = getFontGC (connection, screen, window, "7x13");
+
+
+ xcb_void_cookie_t lineCookie = xcb_poly_line_checked (connection,
+ XCB_COORD_MODE_ORIGIN,
+ window,
+ gc,
+ 5,
+ points );
+ testCookie (lineCookie, connection, "can't draw lines");
+
+
+ xcb_void_cookie_t textCookie = xcb_image_text_8_checked (connection,
+ length,
+ window,
+ gc,
+ x1 + inset + 1,
+ y1 - inset - 1,
+ label );
+ testCookie (textCookie, connection, "can't paste text");
+
+
+ xcb_void_cookie_t gcCookie = xcb_free_gc (connection, gc);
+ testCookie (gcCookie, connection, "can't free gc");
+ }
+
+
+ static void
+ drawText (xcb_connection_t *connection,
+ xcb_screen_t *screen,
+ xcb_window_t window,
+ int16_t x1,
+ int16_t y1,
+ const char *label )
+ {
+
+ xcb_gcontext_t gc = getFontGC (connection, screen, window, "7x13");
+
+
+ xcb_void_cookie_t textCookie = xcb_image_text_8_checked (connection,
+ strlen (label),
+ window,
+ gc,
+ x1,
+ y1,
+ label );
+ testCookie(textCookie, connection, "can't paste text");
+
+
+ xcb_void_cookie_t gcCookie = xcb_free_gc (connection, gc);
+ testCookie (gcCookie, connection, "can't free gc");
+ }
+
+
+ static xcb_gc_t
+ getFontGC (xcb_connection_t *connection,
+ xcb_screen_t *screen,
+ xcb_window_t window,
+ const char *fontName )
+ {
+
+ xcb_font_t font = xcb_generate_id (connection);
+ xcb_void_cookie_t fontCookie = xcb_open_font_checked (connection,
+ font,
+ strlen (fontName),
+ fontName );
+ testCookie (fontCookie, connection, "can't open font");
+
+
+ xcb_gcontext_t gc = xcb_generate_id (connection);
+ uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
+ uint32_t value_list[3];
+ value_list[0] = screen->black_pixel;
+ value_list[1] = screen->white_pixel;
+ value_list[2] = font;
+
+
+ xcb_void_cookie_t gcCookie = xcb_create_gc_checked (connection,
+ gc,
+ window,
+ mask,
+ value_list );
+ testCookie (gcCookie, connection, "can't create gc");
+
+
+ fontCookie = xcb_close_font_checked (connection, font);
+ testCookie (fontCookie, connection, "can't close font");
+
+ return gc;
+ }
+
+
+ static void
+ setCursor (xcb_connection_t *connection,
+ xcb_screen_t *screen,
+ xcb_window_t window,
+ int cursorId )
+ {
+ uint32_t mask;
+ xcb_font_t font = xcb_generate_id (connection);
+ xcb_void_cookie_t fontCookie = xcb_open_font_checked (connection,
+ font,
+ strlen ("cursor"),
+ "cursor" );
+ testCookie (fontCookie, connection, "can't open font");
+
+
+ xcb_cursor_t cursor = xcb_generate_id (connection);
+ xcb_create_glyph_cursor (connection,
+ cursor,
+ font,
+ font,
+ cursorId,
+ cursorId + 1,
+ 0, 0, 0, 0, 0, 0 );
+
+
+ xcb_gcontext_t gc = xcb_generate_id (connection);
+
+ mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
+ uint32_t values_list[3];
+ values_list[0] = screen->black_pixel;
+ values_list[1] = screen->white_pixel;
+ values_list[2] = font;
+
+ xcb_void_cookie_t gcCookie = xcb_create_gc_checked (connection, gc, window, mask, values_list);
+ testCookie (gcCookie, connection, "can't create gc");
+
+
+ mask = XCB_CW_CURSOR;
+ uint32_t value_list = cursor;
+ xcb_change_window_attributes (connection, window, mask, &value_list);
+
+
+ xcb_free_cursor (connection, cursor);
+
+
+
+ fontCookie = xcb_close_font_checked (connection, font);
+ testCookie (fontCookie, connection, "can't close font");
+ }
+
+ int
+ main ()
+ {
+
+
+ int screenNum,i;
+ xcb_connection_t *connection = xcb_connect ("127.0.0.1:0.0", &screenNum);
+ if (!connection) {
+ fprintf (stderr, "ERROR: can't connect to an X server\n");
+ return -1;
+ }
+
+
+
+
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
+
+
+ for (i = 0; i < screenNum; ++i) {
+ xcb_screen_next (&iter);
+ }
+
+ xcb_screen_t *screen = iter.data;
+
+ if (!screen) {
+ fprintf (stderr, "ERROR: can't get the current screen\n");
+ xcb_disconnect (connection);
+ return -1;
+ }
+
+
+
+
+ xcb_window_t window = xcb_generate_id (connection);
+ uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+ uint32_t values[2];
+ values[0] = screen->white_pixel;
+ values[1] = XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_EXPOSURE |
+ XCB_EVENT_MASK_POINTER_MOTION;
+
+
+ xcb_void_cookie_t windowCookie = xcb_create_window_checked (connection,
+ screen->root_depth,
+ window,
+ screen->root,
+ 20, 200, WIDTH, HEIGHT,
+ 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ screen->root_visual,
+ mask, values );
+ testCookie (windowCookie, connection, "can't create window");
+
+
+ xcb_void_cookie_t mapCookie = xcb_map_window_checked (connection, window);
+ testCookie (mapCookie, connection, "can't map window");
+
+
+ setCursor (connection, screen, window, 68);
+
+ xcb_flush(connection);
+
+
+
+
+ uint8_t isHand = 0;
+
+ while (1) {
+ xcb_generic_event_t *event = xcb_poll_for_event (connection);
+ if (event) {
+ switch (event->response_type & ~0x80) {
+ case XCB_EXPOSE: {
+ char *text = "click here to change cursor";
+ drawButton (connection,
+ screen,
+ window,
+ (WIDTH - 7 * strlen(text)) / 2,
+ (HEIGHT - 16) / 2,
+ text );
+
+ text = "Press ESC key to exit...";
+ drawText (connection,
+ screen,
+ window,
+ 10,
+ HEIGHT - 10,
+ text );
+ break;
+ }
+ case XCB_BUTTON_PRESS: {
+ xcb_button_press_event_t *press = (xcb_button_press_event_t *)event;
+
+ int length = strlen ("click here to change cursor");
+ if ((press->event_x >= (WIDTH - 7 * length) / 2) &&
+ (press->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &&
+ (press->event_y >= (HEIGHT - 16) / 2 - 19) &&
+ (press->event_y <= ((HEIGHT - 16) / 2))) {
+ isHand = 1 - isHand;
+ }
+
+ if (isHand) {
+ setCursor (connection, screen, window, 58);
+ }
+ else {
+ setCursor (connection, screen, window, 68);
+ }
+ }
+ case XCB_KEY_RELEASE: {
+
+ xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event;
+
+ switch (kr->detail) {
+
+ case 8:
+ free (event);
+ xcb_disconnect (connection);
+ return 0;
+ }
+ }
+ }
+ free (event);
+ }
+ }
+
+ return 0;
+ }
More information about the xcb-commit
mailing list