diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:13:33 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-02-14 22:13:33 -0500 |
commit | b2d71852fd2ace71722f73065dbccb09c8e9910e (patch) | |
tree | 8c092b846d4a66856ea84ca0ac8bca55718418d2 | |
parent | 525e4c0beae832afc2c098c1368a19ad164e1b2b (diff) |
Split into a demo repository that holds the demo compositor and clients
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | README | 134 | ||||
-rw-r--r-- | TODO | 246 | ||||
-rw-r--r-- | clients/Makefile.am | 18 | ||||
-rw-r--r-- | compositor/Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 35 | ||||
-rw-r--r-- | m4/.gitignore | 5 | ||||
-rw-r--r-- | protocol/wayland.xml | 483 | ||||
-rw-r--r-- | spec/.gitignore | 3 | ||||
-rw-r--r-- | spec/main.tex | 575 | ||||
-rw-r--r-- | wayland/.gitignore | 4 | ||||
-rw-r--r-- | wayland/Makefile.am | 52 | ||||
-rw-r--r-- | wayland/connection.c | 729 | ||||
-rw-r--r-- | wayland/connection.h | 68 | ||||
-rw-r--r-- | wayland/event-loop.c | 444 | ||||
-rw-r--r-- | wayland/scanner.c | 760 | ||||
-rw-r--r-- | wayland/scanner.mk | 8 | ||||
-rw-r--r-- | wayland/wayland-client.c | 565 | ||||
-rw-r--r-- | wayland/wayland-client.h | 75 | ||||
-rw-r--r-- | wayland/wayland-client.pc.in | 10 | ||||
-rw-r--r-- | wayland/wayland-egl.h | 82 | ||||
-rw-r--r-- | wayland/wayland-hash.c | 296 | ||||
-rw-r--r-- | wayland/wayland-server.c | 726 | ||||
-rw-r--r-- | wayland/wayland-server.h | 265 | ||||
-rw-r--r-- | wayland/wayland-server.pc.in | 10 | ||||
-rw-r--r-- | wayland/wayland-util.c | 123 | ||||
-rw-r--r-- | wayland/wayland-util.h | 157 |
27 files changed, 24 insertions, 5859 deletions
diff --git a/Makefile.am b/Makefile.am index 03d15db..b32051c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1 @@ -SUBDIRS = wayland compositor clients data - -ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} +SUBDIRS = compositor clients data @@ -1,130 +1,6 @@ -What is Wayland +Wayland Demos -Wayland is a project to define a protocol for a compositor to talk to -its clients as well as a library implementation of the protocol. The -compositor can be a standalone display server running on Linux kernel -modesetting and evdev input devices, an X applications, or a wayland -client itself. The clients can be traditional applications, X servers -(rootless or fullscreen) or other display servers. - -The wayland protocol is essentially only about input handling and -buffer management. The compositor receives input events and forwards -them to the relevant client. The clients creates buffers and renders -into them and notifies the compositor when it needs to redraw. The -protocol also handles drag and drop, selections, window management and -other interactions that must go throught the compositor. However, the -protocol does not handle rendering, which is one of the features that -makes wayland so simple. All clients are expected to handle rendering -themselves, typically through cairo or OpenGL. - -The wayland repository includes a compositor and a few clients, but -both the compositor and clients are essentially test cases. - - -Building Instructions - -The instructions below assume some familiarity with git and building -and running experimental software. And be prepared that this project -isn't at all useful right now, it's still very much a prototype. When -the instructions suggest to clone a git repo, you can of course just -add a remote and fetch instead, if you have a clone of that repo -around already. I usually install all software I'm working on into -$HOME/install, so that's what I'll use in the instructions below, but -you can use your favorite directory of course or install over your -system copy (pass --prefix=/usr --sysconfdir=/etc, generally). - - -Modesetting - -At this point, kernel modesetting is upstream for Intel, AMD and -nVidia chipsets. Most distributions ship with kernel modesetting -enabled by default and will work with Wayland out of the box. The -modesetting driver must also support the page flip ioctl, which only -the intel driver does at this point. - - -Building mesa - -Wayland uses the mesa EGL stack, and all extensions required to run -EGL on KMS are now upstream on the master branch. The 7.9 release of -mesa will have all these extensions, but for now you'll need to build -mesa master: - - $ git clone git://anongit.freedesktop.org/mesa/mesa - $ cd mesa - $ ./configure --prefix=$HOME/install --enable-egl --enable-gles2 - $ make && make install - -If you're using an intel chipset, it's best to also pass ---disable-gallium to ./configure, since otherwise libEGL will try to -load the gallium sw rasterizer before loading the Intel DRI driver. - - -libxkbcommon - -Wayland needs libxkbcommon for translating evdev keycodes to keysyms. -There's a couple of repos around, and we're trying to consolidate the -development, but for wayland you'll need the repo from my git -repository. For this you'll need development packages for xproto, -kbproto and libX11. - - $ git clone git://people.freedesktop.org/~krh/libxkbcommon.git - $ cd libxkbcommon/ - $ ./autogen.sh --prefix=$HOME/install - $ make && make install - - -cairo-gl - -The Wayland clients render using cairo-gl, which is an experimental -cairo backend. It has been available since cairo 1.10. Unless your -distribution ships cairo with the gl backend enabled, you'll need to -compile your own version of cairo: - - $ git clone git://anongit.freedesktop.org/cairo - $ cd cairo - $ ./autogen.sh --prefix=$HOME/install --enable-gl - $ make && make install - - -Wayland - -With mesa and libxkbcommon in place, we can checkout and build -Wayland. Aside from mesa, Wayland needs development packages for -gdk-pixbuf-2.0, libudev, libdrm, xcb-dri2, xcb-fixes (for X -compositor) cairo-gl, glib-2.0, gdk-2.0 (for poppler) and -poppler-glib: - - $ git clone git://people.freedesktop.org/~krh/wayland - $ ./autogen.sh --prefix=$HOME/install - $ make && make install - -Installing into a non-/usr prefix is fine, but the 70-wayland.rules -udev rule file has to be installed in /etc/udev/rules.d. Once -installed, either reboot or run - - $ sudo udevadm trigger --subsystem-match=drm --subsystem-match=input - -to make udev label the devices wayland will use. - -If DISPLAY is set, the wayland compositor will run under X in a window -and take input from X. Otherwise it will run on the KMS framebuffer -and take input from evdev devices. Pick a background image that you -like and copy it to the Wayland source directory as background.jpg or -use the -b command line option: - - $ ./wayland-system-compositor -b my-image.jpg - -To run clients, switch to a different VT and run the client from -there. Or run it under X and start up the clients from a terminal -window. There are a few demo clients available, but they are all -pretty simple and mostly for testing specific features in the wayland -protocol: 'terminal' is a simple terminal emulator, not very compliant -at all, but works well enough for bash - - 'flower' moves a flower around the screen, testing the frame protocol - 'gears' glxgears, but for wayland, currently broken - 'image' loads the image files passed on the command line and shows them - - 'view' does the same for pdf files, but needs file URIs - (file:///path/to/pdf) +This repository contains a few demos application for the Wayland +project. There's a sample compositor that can run on KMS, under X11 +or under another Wayland compositor and there's a handful of simple +clients that demonstrate various aspects of Wayland: @@ -1,246 +0,0 @@ -Core wayland protocol - - - surface.set_grab_mode(GRAB_OWNER_EVENTS vs GRAB_SURFACE_EVENTS), to - make menus work right: click and drag in a menubar grabs the - pointer to the menubar (which we need for detecting motion into - another menu item), but we need events for the popup menu surface - as well. - - - The message format has to include information about number of fds - in the message so we can skip a message correctly. Or we should - just give up on trying to recover from unknown messages. We need - to make sure you never get a message from an interface you don't - know about (using per-client id space and subscribe) or include - information on number of fds, so marshalling logic can skip. - - - generate pointer_focus (and drag focus) on raise/lower, move - windows, all kinds of changes in surface stacking. - - - glyph cache - - buffer = drm.create_buffer(); /* buffer with stuff in it */ - - cache.upload(buffer, x, y, width, height, int hash) - - drm.buffer: id, name, stride etc /* event to announce cache buffer */ - - cache.image: hash, buffer, x, y, stride /* event to announce - * location in cache */ - - cache.reject: hash /* no upload for you! */ - - cache.retire: buffer /* cache has stopped using buffer, please - * reupload whatever you had in that buffer */ - - - DnD issues: - - Root window must send NULL type (to decline drop) or - x-wayland/root-something type if the source offers that. But the - target deletes the drag_offer object when drag.pointer_focus leaves - the surface... - - How do we animate the drag icon back to the drag origin in case of - a failed drag? - - How to handle surfaces from clients that don't know about dnd or - don't care? Maybe the dnd object should have a - dnd.register_surface() method so clients can opt-in the surfaces - that will participate in dnd. Or just assume client is not - participating until we receive an accept request. - - - Selection/copy+paste issues: is it sufficient to only introduce the - selection offer when a client receives kb focus? Or maybe it is - actually a security feature? Clipboard manager in server for - retained selections? - - - Pointer image issue: - - - A direct touch input device (eg touch screen) doesn't have a - pointer; indicate that somehow. - - - Cursor themes, tie in with glyph/image cache. - - - Discard buffer, as in "wayland discarded your buffer, it's no - longer visible, you can stop updating it now.", reattach, as in "oh - hey, I'm about to show your buffer that I threw away, what was it - again?". for wayland system compositor vt switcing, for example, - to be able to throw away the surfaces in the session we're - switching away from. for minimized windows that we don't want live - thumb nails for. etc. - - - Import relevants bits from EWMH spec, stuff like window title, - window class, app groups, icons, lower window, need attention, - fullscreen (maybe different types of fullscreen). - - - Per client id space. Each client has an entire 32 bit id namespace - to itself. On the server side, each struct wl_client has an object - hash table. Object announcements use a server id space and clients - must respond with subscribe request with a client id for the - object. Part of wl_proxy_create_for_id(): - - wl_display_subscribe(display, id, new_id, my_version); - - or maybe - - wl_display_bind(display, id, new_id, my_version); - - Fixes a few things: - - - Maps the global object into the client id space, lets client - allocate the id. All ids are allocated by the client this way, - which fixes the range protocol problem. - - - Tells the server that the client is interested in events from - the object. Lets the server know that a client participates in a - certain protocol (like drag and drop), so the server can account - for whether or not the client is expected to reply - - - Server emits initial object state event(s) in reponse to - receiving the subscribe request. Introduces an extra round trip - at initialization time, but the server will still announces all - objects in one burst and the client can subscribe in a burst as - well. - - - Separates client resources, since each client will have it's own - hash table. It's not longer possible to guess the id of another - surface and access it. - - - Server must track the client id for each client an object is - exposed to. In some cases we know this (a surface is always - only owned by one client), in other cases it provides a way to - track who's interested in the object events. For input device - events, we can look up the client name when it receives pointer - focus or keyboard focus and cache it in the device. - - - Server must know which id to send when passing object references - in events. We could say that any object we're passing to a - client must have a server id, and each client has a server id -> - client id hash. - - - When a surface is the size of the screen and on top, we can set the - scanout buffer to that surface directly. Like compiz unredirect - top-level window feature. Except it won't have any protocol state - side-effects and the client that owns the surface won't know. We - lose control of updates. Should work well for X server root window - under wayland. Should be possible for yuv overlays as well. - - - what about cursors then? maybe use hw cursors if the cursor - satisfies hw limitations (64x64, only one cursor), switch to - composited cursors if not. - - - clients needs to allocate the surface to be suitable for - scanout, which they can do whenever they go fullscreen. - - - multihead, screen geometry and crtc layout protocol, hotplug, lcd - subpixel info - - - a wayland settings protocol to tell clients about themes (icons, - cursors, widget themes), fonts details (family, hinting - preferences) etc. Just send all settings at connect time, send - updates when a setting change. Getting a little close to gconf - here, but could be pretty simple: - - interface "settings": - event int_value(string name, int value) - event string_value(string name, string value) - - but maybe it's better to just require that clients get that from - somewhere else (gconf/dbus). - - - input device discovery, hotplug - - - Advertise axes as part of the discovery, use something like - "org.wayland.input.x" to identify the axes. - - - keyboard state, layout events at connect time and when it - changes, keyboard leds - - - relative events - - - multi touch? - - - synaptics, 3-button emulation, scim - - - drm bo access control, authentication, flink_to - - - Range protocol may not be sufficient... if a server cycles through - 2^32 object IDs we don't have a way to handle wrapping. And since - we hand out a range of 256 IDs to each new clients, we're just - talking about 2^24 clients. That's 31 years with a new client - every minute... Maybe just use bigger ranges, then it's feasible - to track and garbage collect them when a client dies. - - - Add protocol to let applications specify the effective/logical - surface rectangle, that is, the edge of the window, ignoring drop - shadows and other padding. The compositor needs this for snapping - and constraining window motion. Also, maybe communicate the opaque - region of the window (or just a conservative, simple estimate), to - let the compositor reduce overdraw. - - - multi gpu, needs queue and seqno to wait on in requests - -Clients and ports - - - port gtk+ - - - draw window decorations in gtkwindow.c - - - Details about pointer grabs. wayland doesn't have active grabs, - menus will behave subtly different. Under X, clicking a menu - open grabs the pointer and clicking outside the window pops down - the menu and swallows the click. without active grabs we can't - swallow the click. I'm sure there much more... - - - Port Qt? There's already talk about this on the list. - - - X on Wayland - - - move most of the code from xf86-video-intel into a Xorg wayland - module. - - - don't ask KMS for available output and modes, use the info from - the wayland server. then stop mooching off of drmmode.c. - - - map multiple wayland input devices to MPX in Xorg. - - - rootless; avoid allocating and setting the front buffer, draw - window decorations in the X server (!), how to map input? - - - gnome-shell as a wayland session compositor - - - runs as a client of the wayland session compositor, uses - clutter+egl on wayland - - - talks to an Xorg server as the compositing and window manager - for that server and renders the output to a wayland surface. - the Xorg server should be modified to take input from the system - compositor through gnome-shell, but not allocate a front buffer. - - - make gnome-shell itself a nested wayland server and allow native - wayland clients to connect and can native wayland windows with - the windows from the X server. - - - qemu as a wayland client; session surface as X case - - - qemu has too simple acceleration, so a Wayland backend like the - SDL/VNC ones it has now is trivial. - - - paravirt: forward wayland screen info as mmio, expose gem ioctls as mmio - - - mapping vmem is tricky, should try to only use ioctl (pwrite+pread) - - - not useful for Windows without a windows paravirt driver. - - - two approaches: 1) do a toplevel qemu window, or 2) expose a - wayland server in the guest that forwards to the host wayland - server, ie a "remote" compositor, but with the gem buffers - shared. could do a wl_connection directly on mmio memory, with - head and tail pointers. use an alloc_head register to indicate - desired data to write, if it overwrites tail, block guest. just - a socket would be easier. - - - moblin as a wayland compositor - - - clutter as a wayland compositors - - - argh, mutter diff --git a/clients/Makefile.am b/clients/Makefile.am index 6c92a1c..ee61efd 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -11,7 +11,7 @@ noinst_PROGRAMS = \ simple-client \ eventdemo -noinst_LTLIBRARIES = libtoytoolkit.la +noinst_LIBRARIES = libtoytoolkit.a AM_CFLAGS = $(GCC_CFLAGS) AM_CPPFLAGS = \ @@ -20,7 +20,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/wayland \ $(CLIENT_CFLAGS) -libtoytoolkit_la_SOURCES = \ +libtoytoolkit_a_SOURCES = \ window.c \ window.h \ wayland-glib.c \ @@ -28,10 +28,9 @@ libtoytoolkit_la_SOURCES = \ cairo-util.c \ cairo-util.h -toolkit_libs = \ - libtoytoolkit.la \ - $(top_builddir)/wayland/libwayland-client.la \ - $(CLIENT_LIBS) -lrt -lm -lwayland-egl +toolkit_libs = \ + libtoytoolkit.a \ + $(CLIENT_LIBS) -lrt -lm gears_SOURCES = gears.c gears_LDADD = $(toolkit_libs) @@ -58,10 +57,7 @@ resizor_SOURCES = resizor.c resizor_LDADD = $(toolkit_libs) simple_client_SOURCES = simple-client.c -simple_client_LDADD = \ - $(top_builddir)/wayland/libwayland-client.la -lm \ - $(GLES2_LIBS) \ - -lwayland-egl +simple_client_LDADD = $(SIMPLE_CLIENT_LIBS) -lm eventdemo_SOURCES = eventdemo.c eventdemo_LDADD = $(toolkit_libs) @@ -72,7 +68,7 @@ BUILT_SOURCES = \ CLEANFILES = $(BUILT_SOURCES) -include $(top_srcdir)/wayland/scanner.mk +@wayland_scanner_rules@ if HAVE_POPPLER poppler_programs = view diff --git a/compositor/Makefile.am b/compositor/Makefile.am index d2baa43..d2a3079 100644 --- a/compositor/Makefile.am +++ b/compositor/Makefile.am @@ -8,9 +8,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = $(GCC_CFLAGS) -compositor_LDADD = \ - $(top_builddir)/wayland/libwayland-server.la \ - $(top_builddir)/wayland/libwayland-client.la \ +compositor_LDADD = \ $(COMPOSITOR_LIBS) if ENABLE_DRM_COMPOSITOR @@ -52,4 +50,4 @@ BUILT_SOURCES = \ CLEANFILES = $(BUILT_SOURCES) -include $(top_srcdir)/wayland/scanner.mk +@wayland_scanner_rules@ diff --git a/configure.ac b/configure.ac index 48b9169..8b159dc 100644 --- a/configure.ac +++ b/configure.ac @@ -1,12 +1,11 @@ AC_PREREQ([2.64]) -AC_INIT([wayland], +AC_INIT([wayland-demos], [0.1], [https://bugs.freedesktop.org/enter_bug.cgi?product=wayland], - [wayland], + [wayland-demos], [http://wayland.freedesktop.org/]) AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.11 foreign dist-bzip2]) @@ -14,18 +13,14 @@ AM_SILENT_RULES([yes]) # Check for programs AC_PROG_CC - -# Initialize libtool -LT_PREREQ([2.2]) -LT_INIT +AC_PROG_RANLIB PKG_PROG_PKG_CONFIG() -PKG_CHECK_MODULES(FFI, [libffi]) PKG_CHECK_MODULES(COMPOSITOR, - [egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] pixman-1 xcb-dri2 xcb-xfixes) -PKG_CHECK_MODULES(GLES2, [egl >= 7.10 glesv2]) -PKG_CHECK_MODULES(CLIENT, [egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon]) + [wayland-server wayland-client egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] pixman-1 xcb-dri2 xcb-xfixes) +PKG_CHECK_MODULES(SIMPLE_CLIENT, [egl >= 7.10 glesv2 wayland-client wayland-egl]) +PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon]) PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0], [have_poppler=yes], [have_poppler=no]) AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes") @@ -69,26 +64,14 @@ if test "x$GCC" = "xyes"; then fi AC_SUBST(GCC_CFLAGS) -EXPAT_LIB="" -AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here], - [ expat=$withval - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" ] ) -AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)], - [AC_MSG_ERROR([Can't find expat.h. Please install expat.])]) -AC_CHECK_LIB(expat, XML_ParserCreate, [EXPAT_LIBS="-lexpat"], - [AC_MSG_ERROR([Can't find expat library. Please install expat.])]) -AC_SUBST(EXPAT_LIBS) - # workaround a bug in xcb-dri2 generated by xcb-proto 1.6 AC_CHECK_LIB(xcb-dri2, xcb_dri2_connect_alignment_pad, [], [AC_DEFINE([XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN], [1], [Define to 1 if xcb_dri2_connect_device_name is broken])]) -AC_CONFIG_FILES([wayland/wayland-server.pc - wayland/wayland-client.pc - Makefile - wayland/Makefile +WAYLAND_SCANNER_RULES(['$(top_srcdir)/protocol']) + +AC_CONFIG_FILES([Makefile compositor/Makefile clients/Makefile data/Makefile]) diff --git a/m4/.gitignore b/m4/.gitignore deleted file mode 100644 index 38066dd..0000000 --- a/m4/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -libtool.m4 -ltoptions.m4 -ltsugar.m4 -ltversion.m4 -lt~obsolete.m4 diff --git a/protocol/wayland.xml b/protocol/wayland.xml deleted file mode 100644 index a9f96b6..0000000 --- a/protocol/wayland.xml +++ /dev/null @@ -1,483 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="wayland"> - - <!-- The core global object. This is a special singleton object. - It is used for internal wayland protocol features. --> - <interface name="display" version="1"> - <!-- sync is an just an echo, which will reply with a sync event. - Since requests are handled in-order, this can be used as a - barrier to ensure all previous requests have ben handled. - The key argument can be used to correlate between multiple - sync invocations. --> - <request name="sync"> - <arg name="key" type="uint"/> - </request> - - <!-- Request notification when the next frame is displayed. - Useful for throttling redrawing operations, and driving - animations. The notification will only be posted for one - frame unless requested again. --> - <request name="frame"> - <arg name="key" type="uint"/> - </request> - - <!-- A request addressed a non-existent object id. This is - tyipcally a fatal error. --> - <event name="invalid_object"> - <arg name="object_id" type="uint"/> - </event> - - <!-- A request tried to invoke an opcode out of range. This is - typically a fatal error. --> - <event name="invalid_method"> - <arg name="object_id" type="uint"/> - <arg name="opcode" type="uint"/> - </event> - - <!-- A request has failed due to an out of memory error. --> - <event name="no_memory"/> - - <!-- Notify the client of global objects. These are objects that - are created by the server. Globals are published on the - initial client connection sequence, upon device hotplugs, - device disconnects, reconfiguration or other events. The - server will always announce an object before the object sends - out events. --> - <event name="global"> - <arg name="id" type="new_id" interface="object"/> - <arg name="name" type="string"/> - <arg name="version" type="uint"/> - </event> - - <!-- Internal, deprecated, and will be changed. This is an object - IDs range that is used by the client to allocate object IDs - in "new_id" type arguments. The server sends range - allocations to the client before the next range is about to - be depleted. --> - <event name="range"> - <arg name="base" type="uint"/> - </event> - - <!-- A reply to the frame or sync request. The key is the one - used in the request. time is in millisecond units, and - denotes the time when the frame was posted on the - display. time can be used to estimaate frame rate, determine - how much to advance animations and compensate for jitter. --> - <event name="key"> - <arg name="key" type="uint"/> - <arg name="time" type="uint"/> - </event> - </interface> - - - <!-- A compositor. This object is a global. The compositor is in - charge of combining the contents of multiple surfaces into one - displayable output. --> - <interface name="compositor" version="1"> - <!-- Factory request for a surface objects. A surface is akin to a - window. --> - <request name="create_surface"> - <arg name="id" type="new_id" interface="surface"/> - </request> - </interface> - - - <!-- drm support. This object is created by the server and published - using the display's global event. --> - <interface name="drm" version="1"> - <!-- Call this request with the magic received from drmGetMagic(). - It will be passed on to the drmAuthMagic() or - DRIAuthConnection() call. This authentication must be - completed before create_buffer could be used. --> - <request name="authenticate"> - <arg name="id" type="uint"/> - </request> - - <!-- Create a wayland buffer for the named DRM buffer. The DRM - surface must have a name using the flink ioctl --> - <request name="create_buffer"> - <arg name="id" type="new_id" interface="buffer"/> - <arg name="name" type="uint"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - <arg name="stride" type="uint"/> - <arg name="visual" type="object" interface="visual"/> - </request> - - <!-- Notification of the path of the drm device which is used by - the server. The client should use this device for creating - local buffers. Only buffers created from this device should - be be passed to the server using this drm object's - create_buffer request. --> - <event name="device"> - <arg name="name" type="string"/> - </event> - - <!-- Raised if the authenticate request succeeded --> - <event name="authenticated"/> - </interface> - - - <!-- Shared memory support --> - <interface name="shm" version="1"> - <!-- Transfer a shm buffer to the server. The allocated buffer - would include at least stride * height bytes starting at the - beginning of fd. The file descriptor is transferred over the - socket using AF_UNIX magical features. width, height, stride - and visual describe the respective properties of the pixel - data contained in the buffer. --> - <request name="create_buffer"> - <arg name="id" type="new_id" interface="buffer"/> - <arg name="fd" type="fd"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - <arg name="stride" type="uint"/> - <arg name="visual" type="object" interface="visual"/> - </request> - </interface> - - - <!-- A pixel buffer. Created using the drm, shm or similar objects. - It has a size, visual and contents, but not a location on the - screen --> - <interface name="buffer" version="1"> - <!-- Abandon a buffer. This will invalidate the object id. --> - <request name="destroy" type="destructor"/> - </interface> - - <interface name="shell" version="1"> - <request name="move"> - <arg name="surface" type="object" interface="surface"/> - <arg name="input_device" type="object" interface="input_device"/> - <arg name="time" type="uint"/> - </request> - - <enum name="resize"> - <entry name="none" value="0"/> - <entry name="top" value="1"/> - <entry name="bottom" value="2"/> - <entry name="left" value="4"/> - <entry name="top_left" value="5"/> - <entry name="bottom_left" value="6"/> - <entry name="right" value="8"/> - <entry name="top_right" value="9"/> - <entry name="bottom_right" value="10"/> - </enum> - - <request name="resize"> - <arg name="surface" type="object" interface="surface"/> - <arg name="input_device" type="object" interface="input_device"/> - <arg name="time" type="uint"/> - <!-- edges is an enum, need to get the values in here --> - <arg name="edges" type="uint"/> - </request> - - <request name="create_drag"> - <arg name="id" type="new_id" interface="drag"/> - </request> - - <request name="create_selection"> - <arg name="id" type="new_id" interface="selection"/> - </request> - - <!-- The configure event asks the client to resize its surface. - The size is a hint, in the sense that the client is free to - ignore it if it doesn't resize, pick a smaller size (to - satisfy aspect ration or resize in steps of NxM pixels). The - client is free to dismiss all but the last configure event it - received. --> - <event name="configure"> - <arg name="time" type="uint"/> - <arg name="edges" type="uint"/> - <arg name="surface" type="object" interface="surface"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - </event> - </interface> - - <interface name="selection" version="1"> - <!-- Add an offered mime type. Can be called several times to - offer multiple types, but must be called before 'activate'. --> - <request name="offer"> - <arg name="type" type="string"/> - </request> - - <!-- Can the selection be activated for multiple devices? --> - <request name="activate"> - <arg name="input_device" type="object" interface="input_device"/> - <arg name="time" type="uint"/> - </request> - - <!-- Destroy the selection. --> - <request name="destroy" type="destructor"/> - - <!-- Another client pasted the selection, send the mime-type over - the passed fd. --> - <event name="send"> - <arg name="mime_type" type="string"/> - <arg name="fd" type="fd"/> - </event> - - <!-- Another selection became active. --> - <event name="cancelled"/> - </interface> - - <interface name="selection_offer" version="1"> - <!-- Called to receive the selection data as the specified type. - Sends the pipe fd to the compositor, which forwards it to the - source in the 'send' event --> - <request name="receive"> - <arg name="mime_type" type="string"/> - <arg name="fd" type="fd"/> - </request> - - <!-- Sent before the keyboard_focus event to announce the types - offered. One event per offered mime type. A mime type of - NULL means the selection offer is going away. --> - <event name="offer"> - <arg name="type" type="string"/> - </event> - - <event name="keyboard_focus"> - <arg name="input_device" type="object" interface="input_device"/> - </event> - </interface> - - <interface name="drag" version="1"> - <!-- Add an offered mime type. Can be called several times to - offer multiple types, but must be called before 'activate'. --> - <request name="offer"> - <arg name="type" type="string"/> - </request> - - <request name="activate"> - <arg name="surface" type="object" interface="surface"/> - <arg name="input_device" type="object" interface="input_device"/> - <arg name="time" type="uint"/> - </request> - - <!-- Destroy the drag and cancel the session. --> - <request name="destroy" type="destructor"/> - - <!-- Sent when a target accepts pointer_focus or motion events. - If a target does not accept any of the offered types, type is - NULL --> - <event name="target"> - <arg name="mime_type" type="string"/> - </event> - - <!-- Sent when the drag is finished. The final mime type is that - of the last target event. If that was NULL, no drag target - was valid when the drag finished, fd is undefined and the - source should not send data. The event is also sent in case - a drag source tries to activate a drag after the grab was - released, in which case mime_type will also be NULL. --> - <event name="finish"> - <arg name="fd" type="fd"/> - </event> - - <event name="reject"/> - </interface> - - - <interface name="drag_offer" version="1"> - <!-- Call to accept the offer of the given type --> - <request name="accept"> - <arg name="time" type="uint"/> - <arg name="type" type="string"/> - </request> - - <!-- Called to initiate the drag finish sequence. Sends the pipe - fd to the compositor, which forwards it to the source in the - 'finish' event --> - <request name="receive"> - <arg name="fd" type="fd"/> - </request> - - <!-- Called to reject a drop --> - <request name="reject"/> - - <!-- Sent before the pointer_focus event to announce the types - offered. One event per offered mime type. --> - <event name="offer"> - <arg name="type" type="string"/> - </event> - - <!-- Similar to device::pointer_focus. Sent to potential target - surfaces to offer drag data. If the device leaves the - window, the drag stops or the originator cancels the drag, - this event is sent with the NULL surface, at which point the - drag object may no longer be valid. --> - <event name="pointer_focus"> - <arg name="time" type="uint"/> - <arg name="surface" type="object" interface="surface"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="surface_x" type="int"/> - <arg name="surface_y" type="int"/> - </event> - - <!-- Similar to device::motion. Sent to potential target surfaces - as the drag pointer moves around in the surface. --> - <event name="motion"> - <arg name="time" type="uint"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="surface_x" type="int"/> - <arg name="surface_y" type="int"/> - </event> - - <!-- Sent to indicate that the drag is finishing. The last - motion/pointer_focus event gives the location of the drop. - Target must respond with the 'receive' request, which sends - an fd to the source for writing the drag data. --> - <event name="drop"/> - </interface> - - - <!-- A surface. This is an image that is displayed on the screen. - It has a location, size and pixel contents. Similar to a window. --> - <interface name="surface" version="1"> - <!-- Deletes the surface and invalidates its object id. --> - <request name="destroy" type="destructor"/> - - <!-- Copy the contents of a buffer into this surface. The x and y - arguments specify the location of the new buffers upper left - corner, relative to the old buffers upper left corner. --> - <request name="attach"> - <arg name="buffer" type="object" interface="buffer"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - </request> - - <!-- Make the surface visible as a toplevel window. --> - <request name="map_toplevel"/> - - <!-- Map the surface relative to an existing surface. The x and y - arguments specify the locations of the upper left corner of - the surface relative to the upper left corner of the parent - surface. The flags argument controls overflow/clipping - behaviour when the surface would intersect a screen edge, - panel or such. And possibly whether the offset only - determines the initial position or if the surface is locked - to that relative position during moves. --> - <request name="map_transient"> - <arg name="parent" type="object" interface="surface"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="flags" type="uint"/> - </request> - - <!-- Map the surface as a fullscreen surface. There are a number - of options here: on which output? if the surface size doesn't - match the output size, do we scale, change resolution, or add - black borders? is that something the client controls? what - about transient surfaces, do they float on top of the - fullscreen? what if there's already a fullscreen surface on - the output, maybe you can only go fullscreen if you're - active? --> - <request name="map_fullscreen"/> - - <!-- Notify the server that the attached buffer's contents have - changed, and request a redraw. The arguments allow you to - damage only a part of the surface, but the server may ignore - it and redraw the entire contents of the surface. To - describe a more complicated area of damage, use this request - several times. --> - <request name="damage"> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - </request> - </interface> - - - <!-- A group of keyboards and pointer devices (mice, for - example). This object is published as a global during start up, - or when such a device is hot plugged. A input_device group - typically has a pointer and maintains a keyboard_focus and a - pointer_focus. --> - <interface name="input_device" version="1"> - <!-- Set the pointer's image. This request only takes effect if - the pointer focus for this device is one of the requesting - clients surfaces. --> - <request name="attach"> - <arg name="time" type="uint"/> - <arg name="buffer" type="object" interface="buffer"/> - <arg name="hotspot_x" type="int"/> - <arg name="hotspot_y" type="int"/> - </request> - - <!-- Notification of pointer location change. - x,y are the absolute location on the screen. - surface_[xy] are the location relative to the focused surface. --> - <event name="motion"> - <arg name="time" type="uint"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="surface_x" type="int"/> - <arg name="surface_y" type="int"/> - </event> - - <!-- Mouse button click and release notifications. The location - of the click is given by the last motion or pointer_focus - event. --> - <event name="button"> - <arg name="time" type="uint"/> - <arg name="button" type="uint"/> - <arg name="state" type="uint"/> - </event> - - <!-- Keyboard press. --> - <event name="key"> - <arg name="time" type="uint"/> - <arg name="key" type="uint"/> - <arg name="state" type="uint"/> - </event> - - <!-- Notification that this input device's pointer is focused on - certain surface. When an input_device enters a surface, the - pointer image is undefined and a client should respond to - this event by setting an apropriate pointer image. --> - <event name="pointer_focus"> - <arg name="time" type="uint"/> - <arg name="surface" type="object" interface="surface"/> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="surface_x" type="int"/> - <arg name="surface_y" type="int"/> - </event> - - <event name="keyboard_focus"> - <arg name="time" type="uint"/> - <arg name="surface" type="object" interface="surface"/> - <arg name="keys" type="array"/> - </event> - </interface> - - - <!-- An output describes part of the compositor geometry. The - compositor work in the 'compositor coordinate system' and an - output corresponds to rectangular area in that space that is - actually visible. This typically corresponds to a monitor that - displays part of the compositor space. This object is - published as global during start up, or when a screen is hot - plugged. --> - <interface name="output" version="1"> - <!-- Notification about the screen size. --> - <event name="geometry"> - <arg name="x" type="int"/> - <arg name="y" type="int"/> - <arg name="width" type="int"/> - <arg name="height" type="int"/> - </event> - </interface> - - - <!-- A visual is the pixel format. The different visuals are - currently only identified by the order they are advertised by - the 'global' events. We need something better. --> - <interface name="visual" version="1"/> - -</protocol> diff --git a/spec/.gitignore b/spec/.gitignore deleted file mode 100644 index 4962683..0000000 --- a/spec/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -main.aux -main.log -main.pdf diff --git a/spec/main.tex b/spec/main.tex deleted file mode 100644 index 1b17557..0000000 --- a/spec/main.tex +++ /dev/null @@ -1,575 +0,0 @@ -\documentclass{article} -\usepackage{palatino} - -\author{Kristian Høgsberg\\ -\texttt{krh@bitplanet.net} -} - -\title{The Wayland Display Server} - -\begin{document} - -\maketitle - -\section{Wayland Overview} - -\begin{itemize} -\item wayland is a protocol for a new display server. -\item wayland is an implementation -\end{itemize} - -\subsection{Replacing X11} - -Over time, a lot of functionality have slowly moved out of the X -server and into client-side libraries or kernel drivers. One of the -first components to move out was font rendering, with freetype and -fontconfig providing an alternative to the core X fonts. Direct -rendering OpenGL as a graphics driver in a client side library. Then -cairo came along and provided a modern 2D rendering library -independent of X and compositing managers took over control of the -rendering of the desktop. Recently with GEM and KMS in the Linux -kernel, we can do modesetting outside X and schedule several direct -rendering clients. The end result is a highly modular graphics stack. - -\subsection{Make the compositing manager the display server} - -Wayland is a new display server building on top of all those -components. We are trying to distill out the functionality in the X -server that is still used by the modern Linux desktop. This turns out -to be not a whole lot. Applications can allocate their own off-screen -buffers and render their window contents by themselves. In the end, -what’s needed is a way to present the resulting window surface to a -compositor and a way to receive input. This is what Wayland provides, -by piecing together the components already in the eco-system in a -slightly different way. - -X will always be relevant, in the same way Fortran compilers and VRML -browsers are, but it’s time that we think about moving it out of the -critical path and provide it as an optional component for legacy -applications. - - -\section{Wayland protocol} - -\subsection{Basic Principles} - -The wayland protocol is an asynchronous object oriented protocol. All -requests are method invocations on some object. The request include -an object id that uniquely identifies an object on the server. Each -object implements an interface and the requests include an opcode that -identifies which method in the interface to invoke. - -The server sends back events to the client, each event is emitted from -an object. Events can be error conditions. The event includes the -object id and the event opcode, from which the client can determine -the type of event. Events are generated both in response to a request -(in which case the request and the event constitutes a round trip) or -spontanously when the server state changes. - -\begin{itemize} -\item state is broadcast on connect, events sent out when state - change. client must listen for these changes and cache the state. - no need (or mechanism) to query server state. - -\item server will broadcast presence of a number of global objects, - which in turn will broadcast their current state. -\end{itemize} - -\subsection{Code generation} - -The interfaces, requests and events are defined in protocol/wayland.xml. -This xml is used to generate the function prototypes that can be used by -clients and compositors. - -The protocol entry points are generated as inline functions which just -wraps the \verb:wl_proxy_*: functions. The inline functions aren't -part of the library ABI and languange bindings should generate their -own stubs for the protocl entry points from the xml. - -\subsection{Wire format} - -The protocol is sent over a UNIX domain stream socket. Currently, the -endpoint is named \texttt{\textbackslash0wayland}, but it is subject -to change. The protocol is message-based. A message sent by a client -to the server is called \texttt{request}. A message from the server -to a client is called \texttt{event}. Every message is structured as -32-bit words, values are represented in the host's byte-order. - -The message header has 2 words in it: -\begin{itemize} -\item The first word is the sender's object id (32-bit). -\item The second has 2 parts of 16-bit. The upper 16-bits are the message - size in bytes, starting at the header (i.e. it has a minimum value of 8). - The lower is the request/event opcode. -\end{itemize} - -The payload describes the request/event arguments. Every argument is always -aligned to 32-bit. There is no prefix that describes the type, but it is -inferred implicitly from the xml specification. - -The representation of argument types are as follows: -\begin{itemize} -\item "int" or "uint": The value is the 32-bit value of the signed/unsigned - int. -\item "string": Starts with an unsigned 32-bit length, followed by the - string contents, including terminating NUL byte, then padding to a - 32-bit boundary. -\item "object": A 32-bit object ID. -\item "new\_id": the 32-bit object ID. On requests, the client - decides the ID. The only event with "new\_id" is advertisements of - globals, and the server will use IDs below 0x10000. -\item "array": Starts with 32-bit array size in bytes, followed by the array - contents verbatim, and finally padding to a 32-bit boundary. -\item "fd": the file descriptor is not stored in the message buffer, but in - the ancillary data of the UNIX domain socket message (msg\_control). -\end{itemize} - -\subsection{Connect Time} - -\begin{itemize} -\item no fixed format connect block, the server emits a bunch of - events at connect time -\item presence events for global objects: output, compositor, input - devices -\end{itemize} -\subsection{Security and Authentication} - -\begin{itemize} -\item mostly about access to underlying buffers, need new drm auth - mechanism (the grant-to ioctl idea), need to check the cmd stream? - -\item getting the server socket depends on the compositor type, could - be a system wide name, through fd passing on the session dbus. or - the client is forked by the compositor and the fd is already opened. -\end{itemize} - -\subsection{Creating Objects} - -\begin{itemize} -\item client allocates object ID, uses range protocol -\item server tracks how many IDs are left in current range, sends new - range when client is about to run out. -\end{itemize} - -\subsection{Compositor} - -The compositor is a global object, advertised at connect time. - -\begin{tabular}{l} - \hline - Interface \texttt{compositor} \\ \hline - Requests \\ \hline - \texttt{create\_surface(id)} \\ - \texttt{commit()} \\ \hline - Events \\ \hline - \texttt{device(device)} \\ - \texttt{acknowledge(key, frame)} \\ - \texttt{frame(frame, time)} \\ \hline -\end{tabular} - - -\begin{itemize} -\item a global object -\item broadcasts drm file name, or at least a string like drm:/dev/card0 -\item commit/ack/frame protocol -\end{itemize} - -\subsection{Surface} - -Created by the client. - -\begin{tabular}{l} - \hline - Interface \texttt{surface} \\ \hline - Requests \\ \hline - \texttt{destroy()} \\ - \texttt{attach()} \\ - \texttt{map()} \\ - \texttt{damage()} \\ \hline - Events \\ \hline - no events \\ \hline -\end{tabular} - -Needs a way to set input region, opaque region. - -\subsection{Input} - -Represents a group of input devices, including mice, keyboards. Has a -keyboard and pointer focus. Global object. Pointer events are -delivered in both screen coordinates and surface local coordinates. - -\begin{tabular}{l} - \hline - Interface \texttt{cache} \\ \hline - Requests \\ \hline - \texttt{attach(buffer, x, y)} \\ - Events \\ \hline - \texttt{motion(x, y, sx, sy)} \\ - \texttt{button(button, state, x, y, sx, sy)} \\ - \texttt{key(key, state)} \\ - \texttt{pointer\_focus(surface)} \\ - \texttt{keyboard\_focus(surface, keys)} \\ \hline -\end{tabular} - -Talk about: - -\begin{itemize} -\item keyboard map, change events -\item xkb on wayland -\item multi pointer wayland -\end{itemize} - -A surface can change the pointer image when the surface is the pointer -focus of the input device. Wayland doesn't automatically change the -pointer image when a pointer enters a surface, but expects the -application to set the cursor it wants in response the the pointer -focus and motion events. The rationale is that a client has to manage -changing pointer images for UI elements within the surface in response -to motion events anyway, so we'll make that the only mechanism for -setting changing the pointer image. If the server receives a request -to set the pointer image after the surface loses pointer focus, the -request is ignored. To the client this will look like it successfully -set the pointer image. - -The compositor will revert the pointer image back to a default image -when no surface has the pointer focus for that device. Clients can -revert the pointer image back to the default image by setting a NULL -image. - -What if the pointer moves from one window which has set a special -pointer image to a surface that doesn't set an image in response to -the motion event? The new surface will be stuck with the special -pointer image. We can't just revert the pointer image on leaving a -surface, since if we immediately enter a surface that sets a different -image, the image will flicker. Broken app, I suppose. - -\subsection{Output} - -A output is a global object, advertised at connect time or as they -come and go. - -\begin{tabular}{l} - \hline - Interface \texttt{output} \\ \hline - Requests \\ \hline - no requests \\ \hline - Events \\ \hline - \texttt{geometry(width, height)} \\ \hline -\end{tabular} - -\begin{itemize} -\item laid out in a big (compositor) coordinate system -\item basically xrandr over wayland -\item geometry needs position in compositor coordinate system\ -\item events to advertise available modes, requests to move and change - modes -\end{itemize} - -\subsection{Shared object cache} - -Cache for sharing glyphs, icons, cursors across clients. Lets clients -share identical objects. The cache is a global object, advertised at -connect time. - -\begin{tabular}{l} - \hline - Interface \texttt{cache} \\ \hline - Requests \\ \hline - \texttt{upload(key, visual, bo, stride, width, height)} \\ \hline - Events \\ \hline - \texttt{item(key, bo, x, y, stride)} \\ - \texttt{retire(bo)} \\ \hline -\end{tabular} - -\begin{itemize} - -\item Upload by passing a visual, bo, stride, width, height to the - cache. - -\item Upload returns a bo name, stride, and x, y location of object in - the buffer. Clients take a reference on the atlas bo. - -\item Shared objects are refcounted, freed by client (when purging - glyphs from the local cache) or when a client exits. - -\item Server can't delete individual items from an atlas, but it can - throw out an entire atlas bo if it becomes too sparse. The server - sends out an \texttt{retire} event when this happens, and clients - must throw away any objects from that bo and reupload. Between the - server dropping the atlas and the client receiving the retire event, - clients can still legally use the old atlas since they have a ref on - the bo. - -\item cairo needs to hook into the glyph cache, and maybe also a way - to create a read-only surface based on an object form the cache - (icons). - - \texttt{cairo\_wayland\_create\_cached\_surface(surface-data)}. - -\end{itemize} - - -\subsection{Drag and Drop} - -Multi-device aware. Orthogonal to rest of wayland, as it is its own -toplevel object. Since the compositor determines the drag target, it -works with transformed surfaces (dragging to a scaled down window in -expose mode, for example). - -Issues: - -\begin{itemize} -\item we can set the cursor image to the current cursor + dragged - object, which will last as long as the drag, but maybe an request to - attach an image to the cursor will be more convenient? - -\item Should drag.send() destroy the object? There's nothing to do - after the data has been transferred. - -\item How do we marshall several mime-types? We could make the drag - setup a multi-step operation: dnd.create, drag.offer(mime-type1), - drag.offer(mime-type2), drag.activate(). The drag object could send - multiple offer events on each motion event. Or we could just - implement an array type, but that's a pain to work with. - -\item Middle-click drag to pop up menu? Ctrl/Shift/Alt drag? - -\item Send a file descriptor over the protocol to let initiator and - source exchange data out of band? - -\item Action? Specify action when creating the drag object? Ask - action? -\end{itemize} - -New objects, requests and events: - -\begin{itemize} -\item New toplevel dnd global. One method, creates a drag object: - \texttt{dnd.start(new object id, surface, input device, mime - types)}. Starts drag for the device, if it's grabbed by the - surface. drag ends when button is released. Caller is responsible - for destroying the drag object. - -\item Drag object methods: - - \texttt{drag.destroy(id)}, destroy drag object. - - \texttt{drag.send(id, data)}, send drag data. - - \texttt{drag.accept(id, mime type)}, accept drag offer, called by - target surface. - -\item Drag object events: - - \texttt{drag.offer(id, mime-types)}, sent to potential destination - surfaces to offer drag data. If the device leaves the window or the - originator cancels the drag, this event is sent with mime-types = - NULL. - - \texttt{drag.target(id, mime-type)}, sent to drag originator when a - target surface has accepted the offer. if a previous target goes - away, this event is sent with mime-type = NULL. - - \texttt{drag.data(id, data)}, sent to target, contains dragged data. - ends transaction on the target side. -\end{itemize} - -Sequence of events: - -\begin{itemize} -\item The initiator surface receives a click (which grabs the input - device to that surface) and then enough motion to decide that a drag - is starting. Wayland has no subwindows, so it's entirely up to the - application to decide whether or not a draggable object within the - surface was clicked. - -\item The initiator creates a drag object by calling the - \texttt{create\_drag} method on the dnd global object. As for any - client created object, the client allocates the id. The - \texttt{create\_drag} method also takes the originating surface, the - device that's dragging and the mime-types supported. If the surface - has indeed grabbed the device passed in, the server will create an - active drag object for the device. If the grab was released in the - meantime, the drag object will be in-active, that is, the same state - as when the grab is released. In that case, the client will receive - a button up event, which will let it know that the drag finished. - To the client it will look like the drag was immediately cancelled - by the grab ending. - - The special mime-type application/x-root-target indicates that the - initiator is looking for drag events to the root window as well. - -\item To indicate the object being dragged, the initiator can replace - the pointer image with an larger image representing the data being - dragged with the cursor image overlaid. The pointer image will - remain in place as long as the grab is in effect, since the - initiating surface keeps pointer focus, and no other surface - receives enter events. - -\item As long as the grab is active (or until the initiator cancels - the drag by destroying the drag object), the drag object will send - \texttt{offer} events to surfaces it moves across. As for motion - events, these events contain the surface local coordinates of the - device as well as the list of mime-types offered. When a device - leaves a surface, it will send an \texttt{offer} event with an empty - list of mime-types to indicate that the device left the surface. - -\item If a surface receives an offer event and decides that it's in an - area that can accept a drag event, it should call the - \texttt{accept} method on the drag object in the event. The surface - passes a mime-type in the request, picked from the list in the offer - event, to indicate which of the types it wants. At this point, the - surface can update the appearance of the drop target to give - feedback to the user that the drag has a valid target. If the - \texttt{offer} event moves to a different drop target (the surface - decides the offer coordinates is outside the drop target) or leaves - the surface (the offer event has an empty list of mime-types) it - should revert the appearance of the drop target to the inactive - state. A surface can also decide to retract its drop target (if the - drop target disappears or moves, for example), by calling the accept - method with a NULL mime-type. - -\item When a target surface sends an \texttt{accept} request, the drag - object will send a \texttt{target} event to the initiator surface. - This tells the initiator that the drag currently has a potential - target and which of the offered mime-types the target wants. The - initiator can change the pointer image or drag source appearance to - reflect this new state. If the target surface retracts its drop - target of if the surface disappears, a \texttt{target} event with a - NULL mime-type will be sent. - - If the initiator listed application/x-root-target as a valid - mime-type, dragging into the root window will make the drag object - send a \texttt{target} event with the application/x-root-target - mime-type. - -\item When the grab is released (indicated by the button release - event), if the drag has an active target, the initiator calls the - \texttt{send} method on the drag object to send the data to be - transferred by the drag operation, in the format requested by the - target. The initiator can then destroy the drag object by calling - the \texttt{destroy} method. - -\item The drop target receives a \texttt{data} event from the drag - object with the requested data. -\end{itemize} - -MIME is defined in RFC's 2045-2049. A registry of MIME types is -maintained by the Internet Assigned Numbers Authority (IANA). - -ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/ - - -\section{Types of compositors} - -\subsection{System Compositor} - -\begin{itemize} -\item ties in with graphical boot -\item hosts different types of session compositors -\item lets us switch between multiple sessions (fast user switching, - secure/personal desktop switching) -\item multiseat -\item linux implementation using libudev, egl, kms, evdev, cairo -\item for fullscreen clients, the system compositor can reprogram the - video scanout address to source from the client provided buffer. -\end{itemize} - -\subsection{Session Compositor} - -\begin{itemize} -\item nested under the system compositor. nesting is feasible because - protocol is async, roundtrip would break nesting -\item gnome-shell -\item moblin -\item compiz? -\item kde compositor? -\item text mode using vte -\item rdp session -\item fullscreen X session under wayland -\item can run without system compositor, on the hw where it makes - sense -\item root window less X server, bridging X windows into a wayland - session compositor -\end{itemize} - -\subsection{Embbedding Compositor} - -X11 lets clients embed windows from other clients, or lets client copy -pixmap contents rendered by another client into their window. This is -often used for applets in a panel, browser plugins and similar. -Wayland doesn't directly allow this, but clients can communicate GEM -buffer names out-of-band, for example, using d-bus or as command line -arguments when the panel launches the applet. Another option is to -use a nested wayland instance. For this, the wayland server will have -to be a library that the host application links to. The host -application will then pass the wayland server socket name to the -embedded application, and will need to implement the wayland -compositor interface. The host application composites the client -surfaces as part of it's window, that is, in the web page or in the -panel. The benefit of nesting the wayland server is that it provides -the requests the embedded client needs to inform the host about buffer -updates and a mechanism for forwarding input events from the host -application. - -\begin{itemize} -\item firefox embedding flash by being a special purpose compositor to - the plugin -\end{itemize} - -\section{Implementation} - -what's currently implemented - -\subsection{Wayland Server Library} - -\texttt{libwayland-server.so} - -\begin{itemize} -\item implements protocol side of a compositor -\item minimal, doesn't include any rendering or input device handling -\item helpers for running on egl and evdev, and for nested wayland -\end{itemize} - -\subsection{Wayland Client Library} - -\texttt{libwayland.so} - -\begin{itemize} -\item minimal, designed to support integration with real toolkits such as - Qt, GTK+ or Clutter. - -\item doesn't cache state, but lets the toolkits cache server state in - native objects (GObject or QObject or whatever). -\end{itemize} - -\subsection{Wayland System Compositor} - -\begin{itemize} -\item implementation of the system compositor - -\item uses libudev, eagle (egl), evdev and drm - -\item integrates with ConsoleKit, can create new sessions - -\item allows multi seat setups - -\item configurable through udev rules and maybe /etc/wayland.d type thing -\end{itemize} - -\subsection{X Server Session} - -\begin{itemize} -\item xserver module and driver support - -\item uses wayland client library - -\item same X.org server as we normally run, the front buffer is a wayland - surface but all accel code, 3d and extensions are there - -\item when full screen the session compositor will scan out from the X - server wayland surface, at which point X is running pretty much as it - does natively. -\end{itemize} - -\end{document} diff --git a/wayland/.gitignore b/wayland/.gitignore deleted file mode 100644 index 0d28ba5..0000000 --- a/wayland/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -scanner -wayland-client-protocol.h -wayland-protocol.c -wayland-server-protocol.h diff --git a/wayland/Makefile.am b/wayland/Makefile.am deleted file mode 100644 index cf91c8d..0000000 --- a/wayland/Makefile.am +++ /dev/null @@ -1,52 +0,0 @@ -lib_LTLIBRARIES = libwayland-server.la libwayland-client.la -noinst_LTLIBRARIES = libwayland-util.la - -include_HEADERS = \ - wayland-util.h \ - wayland-server-protocol.h \ - wayland-server.h \ - wayland-client-protocol.h \ - wayland-client.h \ - wayland-egl.h - -libwayland_util_la_SOURCES = \ - connection.c \ - connection.h \ - wayland-util.c \ - wayland-util.h \ - wayland-hash.c - -libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -libwayland_server_la_SOURCES = \ - wayland-protocol.c \ - wayland-server.c \ - event-loop.c - -libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -libwayland_client_la_SOURCES = \ - wayland-protocol.c \ - wayland-client.c - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = wayland-client.pc wayland-server.pc - -AM_CPPFLAGS = $(FFI_CFLAGS) -AM_CFLAGS = $(GCC_CFLAGS) - -include $(top_srcdir)/wayland/scanner.mk - -noinst_PROGRAMS = scanner - -scanner_SOURCES = \ - scanner.c - -scanner_LDADD = $(EXPAT_LIBS) libwayland-util.la - -$(BUILT_SOURCES) : scanner - -BUILT_SOURCES = \ - wayland-server-protocol.h \ - wayland-client-protocol.h \ - wayland-protocol.c - -CLEANFILES = $(BUILT_SOURCES) diff --git a/wayland/connection.c b/wayland/connection.c deleted file mode 100644 index 4a00470..0000000 --- a/wayland/connection.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <sys/uio.h> -#include <ffi.h> -#include <assert.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include "wayland-util.h" -#include "connection.h" - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -struct wl_buffer { - char data[4096]; - int head, tail; -}; - -#define MASK(i) ((i) & 4095) - -struct wl_closure { - int count; - const struct wl_message *message; - ffi_type *types[20]; - ffi_cif cif; - void *args[20]; - uint32_t buffer[64]; - uint32_t *start; -}; - -struct wl_connection { - struct wl_buffer in, out; - struct wl_buffer fds_in, fds_out; - int fd; - void *data; - wl_connection_update_func_t update; - struct wl_closure receive_closure, send_closure; -}; - -union wl_value { - uint32_t uint32; - char *string; - struct wl_object *object; - uint32_t new_id; - struct wl_array *array; -}; - -static void -wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) -{ - int head, size; - - head = MASK(b->head); - if (head + count <= sizeof b->data) { - memcpy(b->data + head, data, count); - } else { - size = sizeof b->data - head; - memcpy(b->data + head, data, size); - memcpy(b->data, (const char *) data + size, count - size); - } - - b->head += count; -} - -static void -wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count) -{ - int head, tail; - - head = MASK(b->head); - tail = MASK(b->tail); - if (head < tail) { - iov[0].iov_base = b->data + head; - iov[0].iov_len = tail - head; - *count = 1; - } else if (tail == 0) { - iov[0].iov_base = b->data + head; - iov[0].iov_len = sizeof b->data - head; - *count = 1; - } else { - iov[0].iov_base = b->data + head; - iov[0].iov_len = sizeof b->data - head; - iov[1].iov_base = b->data; - iov[1].iov_len = tail; - *count = 2; - } -} - -static void -wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count) -{ - int head, tail; - - head = MASK(b->head); - tail = MASK(b->tail); - if (tail < head) { - iov[0].iov_base = b->data + tail; - iov[0].iov_len = head - tail; - *count = 1; - } else if (head == 0) { - iov[0].iov_base = b->data + tail; - iov[0].iov_len = sizeof b->data - tail; - *count = 1; - } else { - iov[0].iov_base = b->data + tail; - iov[0].iov_len = sizeof b->data - tail; - iov[1].iov_base = b->data; - iov[1].iov_len = head; - *count = 2; - } -} - -static void -wl_buffer_copy(struct wl_buffer *b, void *data, size_t count) -{ - int tail, size; - - tail = MASK(b->tail); - if (tail + count <= sizeof b->data) { - memcpy(data, b->data + tail, count); - } else { - size = sizeof b->data - tail; - memcpy(data, b->data + tail, size); - memcpy((char *) data + size, b->data, count - size); - } -} - -struct wl_connection * -wl_connection_create(int fd, - wl_connection_update_func_t update, - void *data) -{ - struct wl_connection *connection; - - connection = malloc(sizeof *connection); - memset(connection, 0, sizeof *connection); - connection->fd = fd; - connection->update = update; - connection->data = data; - - connection->update(connection, - WL_CONNECTION_READABLE, - connection->data); - - return connection; -} - -void -wl_connection_destroy(struct wl_connection *connection) -{ - close(connection->fd); - free(connection); -} - -void -wl_connection_copy(struct wl_connection *connection, void *data, size_t size) -{ - wl_buffer_copy(&connection->in, data, size); -} - -void -wl_connection_consume(struct wl_connection *connection, size_t size) -{ - connection->in.tail += size; -} - -static void -build_cmsg(struct wl_buffer *buffer, char *data, int *clen) -{ - struct cmsghdr *cmsg; - size_t size; - - size = buffer->head - buffer->tail; - if (size > 0) { - cmsg = (struct cmsghdr *) data; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(size); - wl_buffer_copy(buffer, CMSG_DATA(cmsg), size); - *clen = cmsg->cmsg_len; - } else { - *clen = 0; - } -} - -static void -close_fds(struct wl_buffer *buffer) -{ - int fds[32], i, count; - size_t size; - - size = buffer->head - buffer->tail; - if (size == 0) - return; - - wl_buffer_copy(buffer, fds, size); - count = size / sizeof fds[0]; - for (i = 0; i < count; i++) - close(fds[i]); - buffer->tail += size; -} - -static void -decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg) -{ - struct cmsghdr *cmsg; - size_t size; - - for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; - cmsg = CMSG_NXTHDR(msg, cmsg)) { - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) { - size = cmsg->cmsg_len - CMSG_LEN(0); - wl_buffer_put(buffer, CMSG_DATA(cmsg), size); - } - } -} - -int -wl_connection_data(struct wl_connection *connection, uint32_t mask) -{ - struct iovec iov[2]; - struct msghdr msg; - char cmsg[128]; - int len, count, clen; - - if (mask & WL_CONNECTION_WRITABLE) { - wl_buffer_get_iov(&connection->out, iov, &count); - - build_cmsg(&connection->fds_out, cmsg, &clen); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = count; - msg.msg_control = cmsg; - msg.msg_controllen = clen; - msg.msg_flags = 0; - - do { - len = sendmsg(connection->fd, &msg, MSG_NOSIGNAL); - } while (len < 0 && errno == EINTR); - - if (len == -1 && errno == EPIPE) { - return -1; - } else if (len < 0) { - fprintf(stderr, - "write error for connection %p, fd %d: %m\n", - connection, connection->fd); - return -1; - } - - close_fds(&connection->fds_out); - - connection->out.tail += len; - if (connection->out.tail == connection->out.head) - connection->update(connection, - WL_CONNECTION_READABLE, - connection->data); - } - - if (mask & WL_CONNECTION_READABLE) { - wl_buffer_put_iov(&connection->in, iov, &count); - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = count; - msg.msg_control = cmsg; - msg.msg_controllen = sizeof cmsg; - msg.msg_flags = 0; - - do { - len = recvmsg(connection->fd, &msg, 0); - } while (len < 0 && errno == EINTR); - - if (len < 0) { - fprintf(stderr, - "read error from connection %p: %m (%d)\n", - connection, errno); - return -1; - } else if (len == 0) { - /* FIXME: Handle this better? */ - return -1; - } - - decode_cmsg(&connection->fds_in, &msg); - - connection->in.head += len; - } - - return connection->in.head - connection->in.tail; -} - -void -wl_connection_write(struct wl_connection *connection, - const void *data, size_t count) -{ - wl_buffer_put(&connection->out, data, count); - - if (connection->out.head - connection->out.tail == count) - connection->update(connection, - WL_CONNECTION_READABLE | - WL_CONNECTION_WRITABLE, - connection->data); -} - -static int -wl_message_size_extra(const struct wl_message *message) -{ - int i, extra; - - for (i = 0, extra = 0; message->signature[i]; i++) { - - switch (message->signature[i]) { - case 's': - case 'o': - extra += sizeof (void *); - break; - case 'a': - extra += sizeof (void *) + sizeof (struct wl_array); - break; - case 'h': - extra += sizeof (uint32_t); - break; - default: - break; - } - } - - return extra; -} - -struct wl_closure * -wl_connection_vmarshal(struct wl_connection *connection, - struct wl_object *sender, - uint32_t opcode, va_list ap, - const struct wl_message *message) -{ - struct wl_closure *closure = &connection->send_closure; - struct wl_object **objectp, *object; - uint32_t length, *p, *start, size; - int dup_fd; - struct wl_array **arrayp, *array; - const char **sp, *s; - char *extra; - int i, count, fd, extra_size, *fd_ptr; - - extra_size = wl_message_size_extra(message); - count = strlen(message->signature) + 2; - extra = (char *) closure->buffer; - start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; - p = &start[2]; - for (i = 2; i < count; i++) { - switch (message->signature[i - 2]) { - case 'u': - closure->types[i] = &ffi_type_uint32; - closure->args[i] = p; - *p++ = va_arg(ap, uint32_t); - break; - case 'i': - closure->types[i] = &ffi_type_sint32; - closure->args[i] = p; - *p++ = va_arg(ap, int32_t); - break; - case 's': - closure->types[i] = &ffi_type_pointer; - closure->args[i] = extra; - sp = (const char **) extra; - extra += sizeof *sp; - - s = va_arg(ap, const char *); - length = s ? strlen(s) + 1: 0; - *p++ = length; - - if (length > 0) - *sp = (const char *) p; - else - *sp = NULL; - - memcpy(p, s, length); - p += DIV_ROUNDUP(length, sizeof *p); - break; - case 'o': - closure->types[i] = &ffi_type_pointer; - closure->args[i] = extra; - objectp = (struct wl_object **) extra; - extra += sizeof *objectp; - - object = va_arg(ap, struct wl_object *); - *objectp = object; - *p++ = object ? object->id : 0; - break; - - case 'n': - closure->types[i] = &ffi_type_uint32; - closure->args[i] = p; - object = va_arg(ap, struct wl_object *); - *p++ = object->id; - break; - - case 'a': - closure->types[i] = &ffi_type_pointer; - closure->args[i] = extra; - arrayp = (struct wl_array **) extra; - extra += sizeof *arrayp; - - *arrayp = (struct wl_array *) extra; - extra += sizeof **arrayp; - - array = va_arg(ap, struct wl_array *); - if (array == NULL || array->size == 0) { - *p++ = 0; - break; - } - *p++ = array->size; - memcpy(p, array->data, array->size); - - (*arrayp)->size = array->size; - (*arrayp)->alloc = array->alloc; - (*arrayp)->data = p; - - p += DIV_ROUNDUP(array->size, sizeof *p); - break; - - case 'h': - closure->types[i] = &ffi_type_sint; - closure->args[i] = extra; - fd_ptr = (int *) extra; - extra += sizeof *fd_ptr; - - fd = va_arg(ap, int); - dup_fd = dup(fd); - if (dup_fd < 0) { - fprintf(stderr, "dup failed: %m"); - abort(); - } - *fd_ptr = dup_fd; - wl_buffer_put(&connection->fds_out, - &dup_fd, sizeof dup_fd); - break; - default: - assert(0); - break; - } - } - - size = (p - start) * sizeof *p; - start[0] = sender->id; - start[1] = opcode | (size << 16); - - closure->start = start; - closure->message = message; - closure->count = count; - - return closure; -} - -struct wl_closure * -wl_connection_demarshal(struct wl_connection *connection, - uint32_t size, - struct wl_hash_table *objects, - const struct wl_message *message) -{ - uint32_t *p, *next, *end, length; - int *fd; - char *extra, **s; - int i, count, extra_space; - struct wl_object **object; - struct wl_array **array; - struct wl_closure *closure = &connection->receive_closure; - - count = strlen(message->signature) + 2; - if (count > ARRAY_LENGTH(closure->types)) { - printf("too many args (%d)\n", count); - assert(0); - } - - extra_space = wl_message_size_extra(message); - if (sizeof closure->buffer < size + extra_space) { - printf("request too big, should malloc tmp buffer here\n"); - assert(0); - } - - closure->message = message; - closure->types[0] = &ffi_type_pointer; - closure->types[1] = &ffi_type_pointer; - - wl_connection_copy(connection, closure->buffer, size); - p = &closure->buffer[2]; - end = (uint32_t *) ((char *) (p + size)); - extra = (char *) end; - for (i = 2; i < count; i++) { - if (p + 1 > end) { - printf("message too short, " - "object (%d), message %s(%s)\n", - *p, message->name, message->signature); - errno = EINVAL; - goto err; - } - - switch (message->signature[i - 2]) { - case 'u': - closure->types[i] = &ffi_type_uint32; - closure->args[i] = p++; - break; - case 'i': - closure->types[i] = &ffi_type_sint32; - closure->args[i] = p++; - break; - case 's': - closure->types[i] = &ffi_type_pointer; - length = *p++; - - next = p + DIV_ROUNDUP(length, sizeof *p); - if (next > end) { - printf("message too short, " - "object (%d), message %s(%s)\n", - *p, message->name, message->signature); - errno = EINVAL; - goto err; - } - - s = (char **) extra; - extra += sizeof *s; - closure->args[i] = s; - - if (length == 0) { - *s = NULL; - } else { - *s = (char *) p; - } - - if (length > 0 && (*s)[length - 1] != '\0') { - printf("string not nul-terminated, " - "message %s(%s)\n", - message->name, message->signature); - errno = EINVAL; - goto err; - } - p = next; - break; - case 'o': - closure->types[i] = &ffi_type_pointer; - object = (struct wl_object **) extra; - extra += sizeof *object; - closure->args[i] = object; - - *object = wl_hash_table_lookup(objects, *p); - if (*object == NULL && *p != 0) { - printf("unknown object (%d), message %s(%s)\n", - *p, message->name, message->signature); - errno = EINVAL; - goto err; - } - - p++; - break; - case 'n': - closure->types[i] = &ffi_type_uint32; - closure->args[i] = p; - object = wl_hash_table_lookup(objects, *p); - if (object != NULL) { - printf("not a new object (%d), " - "message %s(%s)\n", - *p, message->name, message->signature); - errno = EINVAL; - goto err; - } - p++; - break; - case 'a': - closure->types[i] = &ffi_type_pointer; - length = *p++; - - next = p + DIV_ROUNDUP(length, sizeof *p); - if (next > end) { - printf("message too short, " - "object (%d), message %s(%s)\n", - *p, message->name, message->signature); - errno = EINVAL; - goto err; - } - - array = (struct wl_array **) extra; - extra += sizeof *array; - closure->args[i] = array; - - *array = (struct wl_array *) extra; - extra += sizeof **array; - - (*array)->size = length; - (*array)->alloc = 0; - (*array)->data = p; - p = next; - break; - case 'h': - closure->types[i] = &ffi_type_sint; - - fd = (int *) extra; - extra += sizeof *fd; - closure->args[i] = fd; - - wl_buffer_copy(&connection->fds_in, fd, sizeof *fd); - connection->fds_in.tail += sizeof *fd; - break; - default: - printf("unknown type\n"); - assert(0); - break; - } - } - - closure->count = i; - ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI, - closure->count, &ffi_type_uint32, closure->types); - - wl_connection_consume(connection, size); - - return closure; - - err: - closure->count = i; - wl_closure_destroy(closure); - wl_connection_consume(connection, size); - - return NULL; -} - -void -wl_closure_invoke(struct wl_closure *closure, - struct wl_object *target, void (*func)(void), void *data) -{ - int result; - - closure->args[0] = &data; - closure->args[1] = ⌖ - - ffi_call(&closure->cif, func, &result, closure->args); -} - -void -wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) -{ - uint32_t size; - - size = closure->start[1] >> 16; - wl_connection_write(connection, closure->start, size); -} - -void -wl_closure_print(struct wl_closure *closure, struct wl_object *target) -{ - union wl_value *value; - int i; - - fprintf(stderr, "%s@%d.%s(", - target->interface->name, target->id, - closure->message->name); - - for (i = 2; i < closure->count; i++) { - if (i > 2) - fprintf(stderr, ", "); - - value = closure->args[i]; - switch (closure->message->signature[i - 2]) { - case 'u': - fprintf(stderr, "%u", value->uint32); - break; - case 'i': - fprintf(stderr, "%d", value->uint32); - break; - case 's': - fprintf(stderr, "\"%s\"", value->string); - break; - case 'o': - if (value->object) - fprintf(stderr, "%s@%u", - value->object->interface->name, - value->object->id); - else - fprintf(stderr, "nil"); - break; - case 'n': - fprintf(stderr, "new id %u", value->uint32); - break; - case 'a': - fprintf(stderr, "array"); - break; - case 'h': - fprintf(stderr, "fd %d", value->uint32); - break; - } - } - - fprintf(stderr, ")\n"); -} - -void -wl_closure_destroy(struct wl_closure *closure) -{ -} diff --git a/wayland/connection.h b/wayland/connection.h deleted file mode 100644 index 413977d..0000000 --- a/wayland/connection.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _CONNECTION_H_ -#define _CONNECTION_H_ - -#include <stdarg.h> -#include "wayland-util.h" - -struct wl_connection; -struct wl_closure; - -#define WL_CONNECTION_READABLE 0x01 -#define WL_CONNECTION_WRITABLE 0x02 - -typedef int (*wl_connection_update_func_t)(struct wl_connection *connection, - uint32_t mask, void *data); - -struct wl_connection *wl_connection_create(int fd, - wl_connection_update_func_t update, - void *data); -void wl_connection_destroy(struct wl_connection *connection); -void wl_connection_copy(struct wl_connection *connection, void *data, size_t size); -void wl_connection_consume(struct wl_connection *connection, size_t size); -int wl_connection_data(struct wl_connection *connection, uint32_t mask); -void wl_connection_write(struct wl_connection *connection, const void *data, size_t count); - -struct wl_closure * -wl_connection_vmarshal(struct wl_connection *connection, - struct wl_object *sender, - uint32_t opcode, va_list ap, - const struct wl_message *message); - -struct wl_closure * -wl_connection_demarshal(struct wl_connection *connection, - uint32_t size, - struct wl_hash_table *objects, - const struct wl_message *message); -void -wl_closure_invoke(struct wl_closure *closure, - struct wl_object *target, void (*func)(void), void *data); -void -wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); -void -wl_closure_print(struct wl_closure *closure, struct wl_object *target); -void -wl_closure_destroy(struct wl_closure *closure); - -#endif diff --git a/wayland/event-loop.c b/wayland/event-loop.c deleted file mode 100644 index bf2a9aa..0000000 --- a/wayland/event-loop.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include <stddef.h> -#include <stdio.h> -#include <errno.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/epoll.h> -#include <sys/signalfd.h> -#include <sys/timerfd.h> -#include <unistd.h> -#include <assert.h> -#include "wayland-server.h" - -struct wl_event_loop { - int epoll_fd; - struct wl_list idle_list; -}; - -struct wl_event_source_interface { - void (*dispatch)(struct wl_event_source *source, - struct epoll_event *ep); - int (*remove)(struct wl_event_source *source); -}; - -struct wl_event_source { - struct wl_event_source_interface *interface; - struct wl_event_loop *loop; -}; - -struct wl_event_source_fd { - struct wl_event_source base; - int fd; - wl_event_loop_fd_func_t func; - void *data; -}; - -static void -wl_event_source_fd_dispatch(struct wl_event_source *source, - struct epoll_event *ep) -{ - struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source; - uint32_t mask; - - mask = 0; - if (ep->events & EPOLLIN) - mask |= WL_EVENT_READABLE; - if (ep->events & EPOLLOUT) - mask |= WL_EVENT_WRITEABLE; - - fd_source->func(fd_source->fd, mask, fd_source->data); -} - -static int -wl_event_source_fd_remove(struct wl_event_source *source) -{ - struct wl_event_source_fd *fd_source = - (struct wl_event_source_fd *) source; - struct wl_event_loop *loop = source->loop; - int fd; - - fd = fd_source->fd; - free(source); - - return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); -} - -struct wl_event_source_interface fd_source_interface = { - wl_event_source_fd_dispatch, - wl_event_source_fd_remove -}; - -WL_EXPORT struct wl_event_source * -wl_event_loop_add_fd(struct wl_event_loop *loop, - int fd, uint32_t mask, - wl_event_loop_fd_func_t func, - void *data) -{ - struct wl_event_source_fd *source; - struct epoll_event ep; - - source = malloc(sizeof *source); - if (source == NULL) - return NULL; - - source->base.interface = &fd_source_interface; - source->base.loop = loop; - source->fd = fd; - source->func = func; - source->data = data; - - memset(&ep, 0, sizeof ep); - if (mask & WL_EVENT_READABLE) - ep.events |= EPOLLIN; - if (mask & WL_EVENT_WRITEABLE) - ep.events |= EPOLLOUT; - ep.data.ptr = source; - - if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { - free(source); - return NULL; - } - - return &source->base; -} - -WL_EXPORT int -wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask) -{ - struct wl_event_source_fd *fd_source = - (struct wl_event_source_fd *) source; - struct wl_event_loop *loop = source->loop; - struct epoll_event ep; - - memset(&ep, 0, sizeof ep); - if (mask & WL_EVENT_READABLE) - ep.events |= EPOLLIN; - if (mask & WL_EVENT_WRITEABLE) - ep.events |= EPOLLOUT; - ep.data.ptr = source; - - return epoll_ctl(loop->epoll_fd, - EPOLL_CTL_MOD, fd_source->fd, &ep); -} - -struct wl_event_source_timer { - struct wl_event_source base; - int fd; - wl_event_loop_timer_func_t func; - void *data; -}; - -static void -wl_event_source_timer_dispatch(struct wl_event_source *source, - struct epoll_event *ep) -{ - struct wl_event_source_timer *timer_source = - (struct wl_event_source_timer *) source; - uint64_t expires; - - read(timer_source->fd, &expires, sizeof expires); - - timer_source->func(timer_source->data); -} - -static int -wl_event_source_timer_remove(struct wl_event_source *source) -{ - struct wl_event_source_timer *timer_source = - (struct wl_event_source_timer *) source; - struct wl_event_loop *loop = source->loop; - int fd; - - fd = timer_source->fd; - free(source); - - return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); -} - -struct wl_event_source_interface timer_source_interface = { - wl_event_source_timer_dispatch, - wl_event_source_timer_remove -}; - -WL_EXPORT struct wl_event_source * -wl_event_loop_add_timer(struct wl_event_loop *loop, - wl_event_loop_timer_func_t func, - void *data) -{ - struct wl_event_source_timer *source; - struct epoll_event ep; - - source = malloc(sizeof *source); - if (source == NULL) - return NULL; - - source->base.interface = &timer_source_interface; - source->base.loop = loop; - - source->fd = timerfd_create(CLOCK_MONOTONIC, 0); - if (source->fd < 0) { - fprintf(stderr, "could not create timerfd\n: %m"); - free(source); - return NULL; - } - - source->func = func; - source->data = data; - - memset(&ep, 0, sizeof ep); - ep.events = EPOLLIN; - ep.data.ptr = source; - - if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) { - free(source); - return NULL; - } - - return &source->base; -} - -WL_EXPORT int -wl_event_source_timer_update(struct wl_event_source *source, int ms_delay) -{ - struct wl_event_source_timer *timer_source = - (struct wl_event_source_timer *) source; - struct itimerspec its; - - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - its.it_value.tv_sec = 0; - its.it_value.tv_nsec = ms_delay * 1000 * 1000; - if (timerfd_settime(timer_source->fd, 0, &its, NULL) < 0) { - fprintf(stderr, "could not set timerfd\n: %m"); - return -1; - } - - return 0; -} - -struct wl_event_source_signal { - struct wl_event_source base; - int fd; - int signal_number; - wl_event_loop_signal_func_t func; - void *data; -}; - -static void -wl_event_source_signal_dispatch(struct wl_event_source *source, - struct epoll_event *ep) -{ - struct wl_event_source_signal *signal_source = - (struct wl_event_source_signal *) source; - struct signalfd_siginfo signal_info; - - read(signal_source->fd, &signal_info, sizeof signal_info); - - signal_source->func(signal_source->signal_number, signal_source->data); -} - -static int -wl_event_source_signal_remove(struct wl_event_source *source) -{ - struct wl_event_source_signal *signal_source = - (struct wl_event_source_signal *) source; - struct wl_event_loop *loop = source->loop; - int fd; - - fd = signal_source->fd; - free(source); - - return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); -} - -struct wl_event_source_interface signal_source_interface = { - wl_event_source_signal_dispatch, - wl_event_source_signal_remove -}; - -WL_EXPORT struct wl_event_source * -wl_event_loop_add_signal(struct wl_event_loop *loop, - int signal_number, - wl_event_loop_signal_func_t func, - void *data) -{ - struct wl_event_source_signal *source; - struct epoll_event ep; - sigset_t mask; - - source = malloc(sizeof *source); - if (source == NULL) - return NULL; - - source->base.interface = &signal_source_interface; - source->base.loop = loop; - - sigemptyset(&mask); - sigaddset(&mask, signal_number); - source->fd = signalfd(-1, &mask, 0); - if (source->fd < 0) { - fprintf(stderr, "could not create fd to watch signal\n: %m"); - free(source); - return NULL; - } - sigprocmask(SIG_BLOCK, &mask, NULL); - - source->func = func; - source->data = data; - - memset(&ep, 0, sizeof ep); - ep.events = EPOLLIN; - ep.data.ptr = source; - - if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) { - free(source); - return NULL; - } - - return &source->base; -} - -struct wl_event_source_idle { - struct wl_event_source base; - struct wl_list link; - wl_event_loop_idle_func_t func; - void *data; -}; - -static void -wl_event_source_idle_dispatch(struct wl_event_source *source, - struct epoll_event *ep) -{ - assert(0); -} - -static int -wl_event_source_idle_remove(struct wl_event_source *source) -{ - struct wl_event_source_idle *idle_source = - (struct wl_event_source_idle *) source; - - wl_list_remove(&idle_source->link); - free(source); - - return 0; -} - -struct wl_event_source_interface idle_source_interface = { - wl_event_source_idle_dispatch, - wl_event_source_idle_remove -}; - -WL_EXPORT struct wl_event_source * -wl_event_loop_add_idle(struct wl_event_loop *loop, - wl_event_loop_idle_func_t func, - void *data) -{ - struct wl_event_source_idle *source; - - source = malloc(sizeof *source); - if (source == NULL) - return NULL; - - source->base.interface = &idle_source_interface; - source->base.loop = loop; - - source->func = func; - source->data = data; - wl_list_insert(loop->idle_list.prev, &source->link); - - return &source->base; -} - -WL_EXPORT int -wl_event_source_remove(struct wl_event_source *source) -{ - source->interface->remove(source); - - return 0; -} - -WL_EXPORT struct wl_event_loop * -wl_event_loop_create(void) -{ - struct wl_event_loop *loop; - - loop = malloc(sizeof *loop); - if (loop == NULL) - return NULL; - - loop->epoll_fd = epoll_create(16); - if (loop->epoll_fd < 0) { - free(loop); - return NULL; - } - wl_list_init(&loop->idle_list); - - return loop; -} - -WL_EXPORT void -wl_event_loop_destroy(struct wl_event_loop *loop) -{ - close(loop->epoll_fd); - free(loop); -} - -WL_EXPORT int -wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) -{ - struct epoll_event ep[32]; - struct wl_event_source *source; - struct wl_event_source_idle *idle; - int i, count; - - count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); - if (count < 0) - return -1; - - for (i = 0; i < count; i++) { - source = ep[i].data.ptr; - source->interface->dispatch(source, &ep[i]); - } - - while (!wl_list_empty(&loop->idle_list)) { - idle = container_of(loop->idle_list.next, - struct wl_event_source_idle, link); - wl_list_remove(&idle->link); - idle->func(idle->data); - free(idle); - } - - return 0; -} - -WL_EXPORT int -wl_event_loop_get_fd(struct wl_event_loop *loop) -{ - return loop->epoll_fd; -} diff --git a/wayland/scanner.c b/wayland/scanner.c deleted file mode 100644 index 43e6fa3..0000000 --- a/wayland/scanner.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#include <expat.h> - -#include "wayland-util.h" - -static const char copyright[] = - "/*\n" - " * Copyright © 2010 Kristian Høgsberg\n" - " *\n" - " * Permission to use, copy, modify, distribute, and sell this software and its\n" - " * documentation for any purpose is hereby granted without fee, provided that\n" - " * the above copyright notice appear in all copies and that both that copyright\n" - " * notice and this permission notice appear in supporting documentation, and\n" - " * that the name of the copyright holders not be used in advertising or\n" - " * publicity pertaining to distribution of the software without specific,\n" - " * written prior permission. The copyright holders make no representations\n" - " * about the suitability of this software for any purpose. It is provided \"as\n" - " * is\" without express or implied warranty.\n" - " *\n" - " * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,\n" - " * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO\n" - " * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR\n" - " * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,\n" - " * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n" - " * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE\n" - " * OF THIS SOFTWARE.\n" - " */\n"; - -static int -usage(int ret) -{ - fprintf(stderr, "usage: ./scanner [header|code]\n"); - exit(ret); -} - -#define XML_BUFFER_SIZE 4096 - -struct protocol { - char *name; - char *uppercase_name; - struct wl_list interface_list; -}; - -struct interface { - char *name; - char *uppercase_name; - int version; - struct wl_list request_list; - struct wl_list event_list; - struct wl_list enumeration_list; - struct wl_list link; -}; - -struct message { - char *name; - char *uppercase_name; - struct wl_list arg_list; - struct wl_list link; - int destructor; -}; - -enum arg_type { - NEW_ID, - INT, - UNSIGNED, - STRING, - OBJECT, - ARRAY, - FD -}; - -struct arg { - char *name; - enum arg_type type; - char *interface_name; - struct wl_list link; -}; - -struct enumeration { - char *name; - char *uppercase_name; - struct wl_list entry_list; - struct wl_list link; -}; - -struct entry { - char *name; - char *uppercase_name; - char *value; - struct wl_list link; -}; - -struct parse_context { - struct protocol *protocol; - struct interface *interface; - struct message *message; - struct enumeration *enumeration; -}; - -static char * -uppercase_dup(const char *src) -{ - char *u; - int i; - - u = strdup(src); - for (i = 0; u[i]; i++) - u[i] = toupper(u[i]); - u[i] = '\0'; - - return u; -} - -static void -start_element(void *data, const char *element_name, const char **atts) -{ - struct parse_context *ctx = data; - struct interface *interface; - struct message *message; - struct arg *arg; - struct enumeration *enumeration; - struct entry *entry; - const char *name, *type, *interface_name, *value; - int i, version; - - name = NULL; - type = NULL; - version = 0; - interface_name = NULL; - value = NULL; - for (i = 0; atts[i]; i += 2) { - if (strcmp(atts[i], "name") == 0) - name = atts[i + 1]; - if (strcmp(atts[i], "version") == 0) - version = atoi(atts[i + 1]); - if (strcmp(atts[i], "type") == 0) - type = atts[i + 1]; - if (strcmp(atts[i], "value") == 0) - value = atts[i + 1]; - if (strcmp(atts[i], "interface") == 0) - interface_name = atts[i + 1]; - } - - if (strcmp(element_name, "protocol") == 0) { - if (name == NULL) { - fprintf(stderr, "no protocol name given\n"); - exit(EXIT_FAILURE); - } - - ctx->protocol->name = strdup(name); - ctx->protocol->uppercase_name = uppercase_dup(name); - } else if (strcmp(element_name, "interface") == 0) { - if (name == NULL) { - fprintf(stderr, "no interface name given\n"); - exit(EXIT_FAILURE); - } - - if (version == 0) { - fprintf(stderr, "no interface version given\n"); - exit(EXIT_FAILURE); - } - - interface = malloc(sizeof *interface); - interface->name = strdup(name); - interface->uppercase_name = uppercase_dup(name); - interface->version = version; - wl_list_init(&interface->request_list); - wl_list_init(&interface->event_list); - wl_list_init(&interface->enumeration_list); - wl_list_insert(ctx->protocol->interface_list.prev, - &interface->link); - ctx->interface = interface; - } else if (strcmp(element_name, "request") == 0 || - strcmp(element_name, "event") == 0) { - if (name == NULL) { - fprintf(stderr, "no request name given\n"); - exit(EXIT_FAILURE); - } - - message = malloc(sizeof *message); - message->name = strdup(name); - message->uppercase_name = uppercase_dup(name); - wl_list_init(&message->arg_list); - - if (strcmp(element_name, "request") == 0) - wl_list_insert(ctx->interface->request_list.prev, - &message->link); - else - wl_list_insert(ctx->interface->event_list.prev, - &message->link); - - if (type != NULL && strcmp(type, "destructor") == 0) - message->destructor = 1; - else - message->destructor = 0; - - ctx->message = message; - } else if (strcmp(element_name, "arg") == 0) { - arg = malloc(sizeof *arg); - arg->name = strdup(name); - - if (strcmp(type, "int") == 0) - arg->type = INT; - else if (strcmp(type, "uint") == 0) - arg->type = UNSIGNED; - else if (strcmp(type, "string") == 0) - arg->type = STRING; - else if (strcmp(type, "array") == 0) - arg->type = ARRAY; - else if (strcmp(type, "fd") == 0) - arg->type = FD; - else if (strcmp(type, "new_id") == 0) { - if (interface_name == NULL) { - fprintf(stderr, "no interface name given\n"); - exit(EXIT_FAILURE); - } - arg->type = NEW_ID; - arg->interface_name = strdup(interface_name); - } else if (strcmp(type, "object") == 0) { - if (interface_name == NULL) { - fprintf(stderr, "no interface name given\n"); - exit(EXIT_FAILURE); - } - arg->type = OBJECT; - arg->interface_name = strdup(interface_name); - } else { - fprintf(stderr, "unknown type: %s\n", type); - exit(EXIT_FAILURE); - } - - wl_list_insert(ctx->message->arg_list.prev, &arg->link); - } else if (strcmp(element_name, "enum") == 0) { - if (name == NULL) { - fprintf(stderr, "no enum name given\n"); - exit(EXIT_FAILURE); - } - - enumeration = malloc(sizeof *enumeration); - enumeration->name = strdup(name); - enumeration->uppercase_name = uppercase_dup(name); - wl_list_init(&enumeration->entry_list); - - wl_list_insert(ctx->interface->enumeration_list.prev, - &enumeration->link); - - ctx->enumeration = enumeration; - } else if (strcmp(element_name, "entry") == 0) { - entry = malloc(sizeof *entry); - entry->name = strdup(name); - entry->uppercase_name = uppercase_dup(name); - entry->value = strdup(value); - wl_list_insert(ctx->enumeration->entry_list.prev, - &entry->link); - } -} - -static void -emit_opcodes(struct wl_list *message_list, struct interface *interface) -{ - struct message *m; - int opcode; - - if (wl_list_empty(message_list)) - return; - - opcode = 0; - wl_list_for_each(m, message_list, link) - printf("#define WL_%s_%s\t%d\n", - interface->uppercase_name, m->uppercase_name, opcode++); - - printf("\n"); -} - -static void -emit_type(struct arg *a) -{ - switch (a->type) { - default: - case INT: - case FD: - printf("int "); - break; - case NEW_ID: - case UNSIGNED: - printf("uint32_t "); - break; - case STRING: - printf("const char *"); - break; - case OBJECT: - printf("struct wl_%s *", a->interface_name); - break; - case ARRAY: - printf("struct wl_array *"); - break; - } -} - -static void -emit_stubs(struct wl_list *message_list, struct interface *interface) -{ - struct message *m; - struct arg *a, *ret; - int has_destructor, has_destroy; - - /* We provide a hand written constructor for the display object */ - if (strcmp(interface->name, "display") != 0) - printf("static inline struct wl_%s *\n" - "wl_%s_create(struct wl_display *display, uint32_t id)\n" - "{\n" - "\treturn (struct wl_%s *)\n" - "\t\twl_proxy_create_for_id(display, &wl_%s_interface, id);\n" - "}\n\n", - interface->name, - interface->name, - interface->name, - interface->name); - - printf("static inline void\n" - "wl_%s_set_user_data(struct wl_%s *%s, void *user_data)\n" - "{\n" - "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n" - "}\n\n", - interface->name, interface->name, interface->name, - interface->name); - - printf("static inline void *\n" - "wl_%s_get_user_data(struct wl_%s *%s)\n" - "{\n" - "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n" - "}\n\n", - interface->name, interface->name, interface->name, - interface->name); - - has_destructor = 0; - has_destroy = 0; - wl_list_for_each(m, message_list, link) { - if (m->destructor) - has_destructor = 1; - if (strcmp(m->name, "destroy)") == 0) - has_destroy = 1; - } - - if (!has_destructor && has_destroy) { - fprintf(stderr, - "interface %s has method named destroy but" - "no destructor", interface->name); - exit(EXIT_FAILURE); - } - - /* And we have a hand-written display destructor */ - if (!has_destructor && strcmp(interface->name, "display") != 0) - printf("static inline void\n" - "wl_%s_destroy(struct wl_%s *%s)\n" - "{\n" - "\twl_proxy_destroy(" - "(struct wl_proxy *) %s);\n" - "}\n\n", - interface->name, interface->name, interface->name, - interface->name); - - if (wl_list_empty(message_list)) - return; - - wl_list_for_each(m, message_list, link) { - ret = NULL; - wl_list_for_each(a, &m->arg_list, link) { - if (a->type == NEW_ID) - ret = a; - } - - if (ret) - printf("static inline struct wl_%s *\n", - ret->interface_name); - else - printf("static inline void\n"); - - printf("wl_%s_%s(struct wl_%s *%s", - interface->name, m->name, - interface->name, interface->name); - - wl_list_for_each(a, &m->arg_list, link) { - if (a->type == NEW_ID) - continue; - printf(", "); - emit_type(a); - printf("%s", a->name); - } - - printf(")\n" - "{\n"); - if (ret) - printf("\tstruct wl_proxy *%s;\n\n" - "\t%s = wl_proxy_create(" - "(struct wl_proxy *) %s,\n" - "\t\t\t &wl_%s_interface);\n" - "\tif (!%s)\n" - "\t\treturn NULL;\n\n", - ret->name, - ret->name, - interface->name, ret->interface_name, - ret->name); - - printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n" - "\t\t\t WL_%s_%s", - interface->name, - interface->uppercase_name, - m->uppercase_name); - - wl_list_for_each(a, &m->arg_list, link) { - printf(", "); - printf("%s", a->name); - } - printf(");\n"); - - if (m->destructor) - printf("\n\twl_proxy_destroy(" - "(struct wl_proxy *) %s);\n", - interface->name); - - if (ret) - printf("\n\treturn (struct wl_%s *) %s;\n", - ret->interface_name, ret->name); - - printf("}\n\n"); - } -} - -static const char *indent(int n) -{ - const char *whitespace[] = { - "\t\t\t\t\t\t\t\t\t\t\t\t", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t ", - "\t\t\t\t\t\t\t\t\t\t\t\t " - }; - - return whitespace[n % 8] + 12 - n / 8; -} - -static void -emit_enumerations(struct interface *interface) -{ - struct enumeration *e; - struct entry *entry; - - wl_list_for_each(e, &interface->enumeration_list, link) { - printf("#ifndef WL_%s_%s_ENUM\n", - interface->uppercase_name, e->uppercase_name); - printf("#define WL_%s_%s_ENUM\n", - interface->uppercase_name, e->uppercase_name); - printf("enum wl_%s_%s {\n", interface->name, e->name); - wl_list_for_each(entry, &e->entry_list, link) - printf("\tWL_%s_%s_%s = %s,\n", - interface->uppercase_name, - e->uppercase_name, - entry->uppercase_name, entry->value); - printf("};\n"); - printf("#endif /* WL_%s_%s_ENUM */\n\n", - interface->uppercase_name, e->uppercase_name); - } -} - -static void -emit_structs(struct wl_list *message_list, struct interface *interface) -{ - struct message *m; - struct arg *a; - int is_interface, n; - - if (wl_list_empty(message_list)) - return; - - is_interface = message_list == &interface->request_list; - printf("struct wl_%s_%s {\n", interface->name, - is_interface ? "interface" : "listener"); - - wl_list_for_each(m, message_list, link) { - printf("\tvoid (*%s)(", m->name); - - n = strlen(m->name) + 17; - if (is_interface) { - printf("struct wl_client *client,\n" - "%sstruct wl_%s *%s", - indent(n), - interface->name, interface->name); - } else { - printf("void *data,\n"), - printf("%sstruct wl_%s *%s", - indent(n), interface->name, interface->name); - } - - wl_list_for_each(a, &m->arg_list, link) { - printf(",\n%s", indent(n)); - - emit_type(a); - printf("%s", a->name); - } - - printf(");\n"); - } - - printf("};\n\n"); - - if (!is_interface) { - printf("static inline int\n" - "wl_%s_add_listener(struct wl_%s *%s,\n" - "%sconst struct wl_%s_listener *listener, void *data)\n" - "{\n" - "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n" - "%s(void (**)(void)) listener, data);\n" - "}\n\n", - interface->name, interface->name, interface->name, - indent(17 + strlen(interface->name)), - interface->name, - interface->name, - indent(37)); - } -} - -static const char client_prototypes[] = - "struct wl_proxy;\n\n" - - "extern void\n" - "wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);\n" - - "extern struct wl_proxy *\n" - "wl_proxy_create(struct wl_proxy *factory,\n" - "\t\tconst struct wl_interface *interface);\n" - - "extern struct wl_proxy *\n" - "wl_proxy_create_for_id(struct wl_display *display,\n" - "\t\t const struct wl_interface *interface, uint32_t id);\n" - - "extern void\n" - "wl_proxy_destroy(struct wl_proxy *proxy);\n\n" - - "extern int\n" - "wl_proxy_add_listener(struct wl_proxy *proxy,\n" - "\t\t void (**implementation)(void), void *data);\n\n" - - "extern void\n" - "wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);\n\n" - - "extern void *\n" - "wl_proxy_get_user_data(struct wl_proxy *proxy);\n\n"; - - -static void -emit_header(struct protocol *protocol, int server) -{ - struct interface *i; - const char *s = server ? "SERVER" : "CLIENT"; - - printf("%s\n\n" - "#ifndef %s_%s_PROTOCOL_H\n" - "#define %s_%s_PROTOCOL_H\n" - "\n" - "#ifdef __cplusplus\n" - "extern \"C\" {\n" - "#endif\n" - "\n" - "#include <stdint.h>\n" - "#include <stddef.h>\n" - "#include \"wayland-util.h\"\n\n" - "struct wl_client;\n\n", - copyright, - protocol->uppercase_name, s, - protocol->uppercase_name, s); - - wl_list_for_each(i, &protocol->interface_list, link) - printf("struct wl_%s;\n", i->name); - printf("\n"); - - if (!server) - printf(client_prototypes); - - wl_list_for_each(i, &protocol->interface_list, link) { - printf("extern const struct wl_interface " - "wl_%s_interface;\n", - i->name); - } - printf("\n"); - - wl_list_for_each(i, &protocol->interface_list, link) { - - emit_enumerations(i); - - if (server) { - emit_structs(&i->request_list, i); - emit_opcodes(&i->event_list, i); - } else { - emit_structs(&i->event_list, i); - emit_opcodes(&i->request_list, i); - emit_stubs(&i->request_list, i); - } - } - - printf("#ifdef __cplusplus\n" - "}\n" - "#endif\n" - "\n" - "#endif\n"); -} - -static void -emit_messages(struct wl_list *message_list, - struct interface *interface, const char *suffix) -{ - struct message *m; - struct arg *a; - - if (wl_list_empty(message_list)) - return; - - printf("static const struct wl_message " - "%s_%s[] = {\n", - interface->name, suffix); - - wl_list_for_each(m, message_list, link) { - printf("\t{ \"%s\", \"", m->name); - wl_list_for_each(a, &m->arg_list, link) { - switch (a->type) { - default: - case INT: - printf("i"); - break; - case NEW_ID: - printf("n"); - break; - case UNSIGNED: - printf("u"); - break; - case STRING: - printf("s"); - break; - case OBJECT: - printf("o"); - break; - case ARRAY: - printf("a"); - break; - case FD: - printf("h"); - break; - } - } - printf("\" },\n"); - } - - printf("};\n\n"); -} - -static void -emit_code(struct protocol *protocol) -{ - struct interface *i; - - printf("%s\n\n" - "#include <stdlib.h>\n" - "#include <stdint.h>\n" - "#include \"wayland-util.h\"\n\n", - copyright); - - wl_list_for_each(i, &protocol->interface_list, link) { - - emit_messages(&i->request_list, i, "requests"); - emit_messages(&i->event_list, i, "events"); - - printf("WL_EXPORT const struct wl_interface " - "wl_%s_interface = {\n" - "\t\"%s\", %d,\n", - i->name, i->name, i->version); - - if (!wl_list_empty(&i->request_list)) - printf("\tARRAY_LENGTH(%s_requests), %s_requests,\n", - i->name, i->name); - else - printf("\t0, NULL,\n"); - - if (!wl_list_empty(&i->event_list)) - printf("\tARRAY_LENGTH(%s_events), %s_events,\n", - i->name, i->name); - else - printf("\t0, NULL,\n"); - - printf("};\n\n"); - } -} - -int main(int argc, char *argv[]) -{ - struct parse_context ctx; - struct protocol protocol; - XML_Parser parser; - int len; - void *buf; - - if (argc != 2) - usage(EXIT_FAILURE); - - wl_list_init(&protocol.interface_list); - ctx.protocol = &protocol; - - parser = XML_ParserCreate(NULL); - XML_SetUserData(parser, &ctx); - if (parser == NULL) { - fprintf(stderr, "failed to create parser\n"); - exit(EXIT_FAILURE); - } - - XML_SetElementHandler(parser, start_element, NULL); - do { - buf = XML_GetBuffer(parser, XML_BUFFER_SIZE); - len = fread(buf, 1, XML_BUFFER_SIZE, stdin); - if (len < 0) { - fprintf(stderr, "fread: %s\n", strerror(errno)); - exit(EXIT_FAILURE); - } - XML_ParseBuffer(parser, len, len == 0); - - } while (len > 0); - - XML_ParserFree(parser); - - if (strcmp(argv[1], "client-header") == 0) { - emit_header(&protocol, 0); - } else if (strcmp(argv[1], "server-header") == 0) { - emit_header(&protocol, 1); - } else if (strcmp(argv[1], "code") == 0) { - emit_code(&protocol); - } - - return 0; -} diff --git a/wayland/scanner.mk b/wayland/scanner.mk deleted file mode 100644 index efdb42b..0000000 --- a/wayland/scanner.mk +++ /dev/null @@ -1,8 +0,0 @@ -%-protocol.c : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner code < $< > $@ - -%-server-protocol.h : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner server-header < $< > $@ - -%-client-protocol.h : $(top_srcdir)/protocol/%.xml - $(AM_V_GEN)$(top_builddir)/wayland/scanner client-header < $< > $@ diff --git a/wayland/wayland-client.c b/wayland/wayland-client.c deleted file mode 100644 index e3198c7..0000000 --- a/wayland/wayland-client.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <ctype.h> -#include <assert.h> -#include <sys/poll.h> - -#include "wayland-client-protocol.h" -#include "connection.h" -#include "wayland-util.h" -#include "wayland-client.h" - -struct wl_global_listener { - wl_display_global_func_t handler; - void *data; - struct wl_list link; -}; - -struct wl_listener { - void (**implementation)(void); - void *data; - struct wl_list link; -}; - -struct wl_proxy { - struct wl_object object; - struct wl_display *display; - struct wl_list listener_list; - void *user_data; -}; - -struct wl_sync_handler { - wl_display_sync_func_t func; - uint32_t key; - void *data; - struct wl_list link; -}; - -struct wl_frame_handler { - wl_display_frame_func_t func; - uint32_t key; - void *data; - struct wl_list link; -}; - -struct wl_display { - struct wl_proxy proxy; - struct wl_connection *connection; - int fd; - uint32_t id, id_count, next_range; - uint32_t mask; - struct wl_hash_table *objects; - struct wl_listener listener; - struct wl_list global_listener_list; - - struct wl_visual *argb_visual; - struct wl_visual *premultiplied_argb_visual; - struct wl_visual *rgb_visual; - - wl_display_update_func_t update; - void *update_data; - - wl_display_global_func_t global_handler; - void *global_handler_data; - - struct wl_list sync_list, frame_list; - uint32_t key; -}; - -static int wl_debug = 0; - -static int -connection_update(struct wl_connection *connection, - uint32_t mask, void *data) -{ - struct wl_display *display = data; - - display->mask = mask; - if (display->update) - return display->update(display->mask, - display->update_data); - - return 0; -} - -WL_EXPORT struct wl_global_listener * -wl_display_add_global_listener(struct wl_display *display, - wl_display_global_func_t handler, void *data) -{ - struct wl_global_listener *listener; - - listener = malloc(sizeof *listener); - if (listener == NULL) - return NULL; - - listener->handler = handler; - listener->data = data; - wl_list_insert(display->global_listener_list.prev, &listener->link); - - return listener; -} - -WL_EXPORT void -wl_display_remove_global_listener(struct wl_display *display, - struct wl_global_listener *listener) -{ - wl_list_remove(&listener->link); - free(listener); -} - -WL_EXPORT struct wl_proxy * -wl_proxy_create_for_id(struct wl_display *display, - const struct wl_interface *interface, uint32_t id) -{ - struct wl_proxy *proxy; - - proxy = malloc(sizeof *proxy); - if (proxy == NULL) - return NULL; - - proxy->object.interface = interface; - proxy->object.id = id; - proxy->display = display; - wl_list_init(&proxy->listener_list); - wl_hash_table_insert(display->objects, proxy->object.id, proxy); - - return proxy; -} - -WL_EXPORT struct wl_proxy * -wl_proxy_create(struct wl_proxy *factory, - const struct wl_interface *interface) -{ - return wl_proxy_create_for_id(factory->display, interface, - wl_display_allocate_id(factory->display)); -} - -WL_EXPORT void -wl_proxy_destroy(struct wl_proxy *proxy) -{ - struct wl_listener *listener, *next; - - wl_list_for_each_safe(listener, next, &proxy->listener_list, link) - free(listener); - - wl_hash_table_remove(proxy->display->objects, proxy->object.id); - free(proxy); -} - -WL_EXPORT int -wl_proxy_add_listener(struct wl_proxy *proxy, - void (**implementation)(void), void *data) -{ - struct wl_listener *listener; - - listener = malloc(sizeof *listener); - if (listener == NULL) - return -1; - - listener->implementation = (void (**)(void)) implementation; - listener->data = data; - wl_list_insert(proxy->listener_list.prev, &listener->link); - - return 0; -} - -WL_EXPORT void -wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) -{ - struct wl_closure *closure; - va_list ap; - - va_start(ap, opcode); - closure = wl_connection_vmarshal(proxy->display->connection, - &proxy->object, opcode, ap, - &proxy->object.interface->methods[opcode]); - va_end(ap); - - wl_closure_send(closure, proxy->display->connection); - - if (wl_debug) { - fprintf(stderr, " -> "); - wl_closure_print(closure, &proxy->object); - } - - wl_closure_destroy(closure); -} - -static void -add_visual(struct wl_display *display, uint32_t id) -{ - struct wl_visual *visual; - - visual = (struct wl_visual *) - wl_proxy_create_for_id(display, &wl_visual_interface, id); - if (display->argb_visual == NULL) - display->argb_visual = visual; - else if (display->premultiplied_argb_visual == NULL) - display->premultiplied_argb_visual = visual; - else - display->rgb_visual = visual; -} - -WL_EXPORT struct wl_visual * -wl_display_get_argb_visual(struct wl_display *display) -{ - return display->argb_visual; -} - -WL_EXPORT struct wl_visual * -wl_display_get_premultiplied_argb_visual(struct wl_display *display) -{ - return display->premultiplied_argb_visual; -} - -WL_EXPORT struct wl_visual * -wl_display_get_rgb_visual(struct wl_display *display) -{ - return display->rgb_visual; -} - -static void -display_handle_invalid_object(void *data, - struct wl_display *display, uint32_t id) -{ - fprintf(stderr, "sent request to invalid object\n"); - abort(); -} - -static void -display_handle_invalid_method(void *data, - struct wl_display *display, - uint32_t id, uint32_t opcode) -{ - fprintf(stderr, "sent invalid request opcode\n"); - abort(); -} - -static void -display_handle_no_memory(void *data, - struct wl_display *display) -{ - fprintf(stderr, "server out of memory\n"); - abort(); -} - -static void -display_handle_global(void *data, - struct wl_display *display, - uint32_t id, const char *interface, uint32_t version) -{ - struct wl_global_listener *listener; - - if (strcmp(interface, "display") == 0) - wl_hash_table_insert(display->objects, - id, &display->proxy.object); - else if (strcmp(interface, "visual") == 0) - add_visual(display, id); - - wl_list_for_each(listener, &display->global_listener_list, link) - (*listener->handler)(display, - id, interface, version, listener->data); -} - -static void -display_handle_range(void *data, - struct wl_display *display, uint32_t range) -{ - display->next_range = range; -} - -static void -display_handle_key(void *data, - struct wl_display *display, uint32_t key, uint32_t time) -{ - struct wl_sync_handler *sync_handler; - struct wl_frame_handler *frame_handler; - - sync_handler = container_of(display->sync_list.next, - struct wl_sync_handler, link); - if (!wl_list_empty(&display->sync_list) && sync_handler->key == key) { - wl_list_remove(&sync_handler->link); - sync_handler->func(sync_handler->data); - free(sync_handler); - return; - } - - frame_handler = container_of(display->frame_list. next, - struct wl_frame_handler, link); - if (!wl_list_empty(&display->frame_list) && - frame_handler->key == key) { - wl_list_remove(&frame_handler->link); - frame_handler->func(frame_handler->data, time); - free(frame_handler); - return; - } - - fprintf(stderr, "unsolicited sync event, client gone?\n"); -} - -static const struct wl_display_listener display_listener = { - display_handle_invalid_object, - display_handle_invalid_method, - display_handle_no_memory, - display_handle_global, - display_handle_range, - display_handle_key -}; - -WL_EXPORT struct wl_display * -wl_display_connect(const char *name) -{ - struct wl_display *display; - struct sockaddr_un addr; - socklen_t size; - const char *runtime_dir; - const char *debug; - size_t name_size; - - debug = getenv("WAYLAND_DEBUG"); - if (debug) - wl_debug = 1; - - display = malloc(sizeof *display); - if (display == NULL) - return NULL; - - memset(display, 0, sizeof *display); - display->fd = socket(PF_LOCAL, SOCK_STREAM, 0); - if (display->fd < 0) { - free(display); - return NULL; - } - - runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (runtime_dir == NULL) { - runtime_dir = "."; - fprintf(stderr, - "XDG_RUNTIME_DIR not set, falling back to %s\n", - runtime_dir); - } - - if (name == NULL) - name = getenv("WAYLAND_DISPLAY"); - if (name == NULL) - name = "wayland-0"; - - memset(&addr, 0, sizeof addr); - addr.sun_family = AF_LOCAL; - name_size = - snprintf(addr.sun_path, sizeof addr.sun_path, - "%s/%s", runtime_dir, name) + 1; - - size = offsetof (struct sockaddr_un, sun_path) + name_size; - - if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) { - close(display->fd); - free(display); - return NULL; - } - - display->objects = wl_hash_table_create(); - wl_list_init(&display->global_listener_list); - - display->proxy.object.interface = &wl_display_interface; - display->proxy.object.id = 1; - display->proxy.display = display; - wl_list_init(&display->proxy.listener_list); - - wl_list_init(&display->sync_list); - wl_list_init(&display->frame_list); - - display->listener.implementation = (void(**)(void)) &display_listener; - wl_list_insert(display->proxy.listener_list.prev, &display->listener.link); - - display->connection = wl_connection_create(display->fd, - connection_update, - display); - - return display; -} - -WL_EXPORT void -wl_display_destroy(struct wl_display *display) -{ - wl_connection_destroy(display->connection); - close(display->fd); - free(display); -} - -WL_EXPORT int -wl_display_get_fd(struct wl_display *display, - wl_display_update_func_t update, void *data) -{ - display->update = update; - display->update_data = data; - - display->update(display->mask, display->update_data); - - return display->fd; -} - -WL_EXPORT int -wl_display_sync_callback(struct wl_display *display, - wl_display_sync_func_t func, void *data) -{ - struct wl_sync_handler *handler; - - handler = malloc(sizeof *handler); - if (handler == NULL) - return -1; - - handler->func = func; - handler->key = display->key++; - handler->data = data; - - wl_list_insert(display->sync_list.prev, &handler->link); - wl_display_sync(display, handler->key); - - return 0; -} - -WL_EXPORT int -wl_display_frame_callback(struct wl_display *display, - wl_display_frame_func_t func, void *data) -{ - struct wl_frame_handler *handler; - - handler = malloc(sizeof *handler); - if (handler == NULL) - return -1; - - handler->func = func; - handler->key = display->key++; - handler->data = data; - - wl_list_insert(display->frame_list.prev, &handler->link); - wl_display_frame(display, handler->key); - - return 0; -} - -static void -handle_event(struct wl_display *display, - uint32_t id, uint32_t opcode, uint32_t size) -{ - uint32_t p[32]; - struct wl_listener *listener; - struct wl_proxy *proxy; - struct wl_closure *closure; - const struct wl_message *message; - - wl_connection_copy(display->connection, p, size); - if (id == 1) - proxy = &display->proxy; - else - proxy = wl_hash_table_lookup(display->objects, id); - - if (proxy == NULL) { - wl_connection_consume(display->connection, size); - return; - } - - message = &proxy->object.interface->events[opcode]; - closure = wl_connection_demarshal(display->connection, - size, display->objects, message); - - if (wl_debug) - wl_closure_print(closure, &proxy->object); - - wl_list_for_each(listener, &proxy->listener_list, link) - wl_closure_invoke(closure, &proxy->object, - listener->implementation[opcode], - listener->data); - - wl_closure_destroy(closure); -} - -WL_EXPORT void -wl_display_iterate(struct wl_display *display, uint32_t mask) -{ - uint32_t p[2], object, opcode, size; - int len; - - mask &= display->mask; - if (mask == 0) { - fprintf(stderr, - "wl_display_iterate called with unsolicited flags"); - return; - } - - len = wl_connection_data(display->connection, mask); - while (len > 0) { - if (len < sizeof p) - break; - - wl_connection_copy(display->connection, p, sizeof p); - object = p[0]; - opcode = p[1] & 0xffff; - size = p[1] >> 16; - if (len < size) - break; - - handle_event(display, object, opcode, size); - len -= size; - } - - if (len < 0) { - fprintf(stderr, "read error: %m\n"); - exit(EXIT_FAILURE); - } -} - -WL_EXPORT uint32_t -wl_display_allocate_id(struct wl_display *display) -{ - if (display->id_count == 0) { - display->id_count = 256; - display->id = display->next_range; - } - - display->id_count--; - - return display->id++; -} - -WL_EXPORT void -wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data) -{ - proxy->user_data = user_data; -} - -WL_EXPORT void * -wl_proxy_get_user_data(struct wl_proxy *proxy) -{ - return proxy->user_data; -} diff --git a/wayland/wayland-client.h b/wayland/wayland-client.h deleted file mode 100644 index d207b07..0000000 --- a/wayland/wayland-client.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _WAYLAND_CLIENT_H -#define _WAYLAND_CLIENT_H - -#include "wayland-util.h" -#include "wayland-client-protocol.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WL_DISPLAY_READABLE 0x01 -#define WL_DISPLAY_WRITABLE 0x02 - -typedef int (*wl_display_update_func_t)(uint32_t mask, void *data); -typedef void (*wl_display_sync_func_t)(void *data); -typedef void (*wl_display_frame_func_t)(void *data, uint32_t time); - -struct wl_display *wl_display_connect(const char *name); -void wl_display_destroy(struct wl_display *display); -int wl_display_get_fd(struct wl_display *display, - wl_display_update_func_t update, void *data); -uint32_t wl_display_allocate_id(struct wl_display *display); -void wl_display_iterate(struct wl_display *display, uint32_t mask); -int wl_display_sync_callback(struct wl_display *display, - wl_display_sync_func_t func, void *data); -int wl_display_frame_callback(struct wl_display *display, - wl_display_frame_func_t func, void *data); - -struct wl_global_listener; -typedef void (*wl_display_global_func_t)(struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, - void *data); -void -wl_display_remove_global_listener(struct wl_display *display, - struct wl_global_listener *listener); - -struct wl_global_listener * -wl_display_add_global_listener(struct wl_display *display, - wl_display_global_func_t handler, void *data); -struct wl_visual * -wl_display_get_argb_visual(struct wl_display *display); -struct wl_visual * -wl_display_get_premultiplied_argb_visual(struct wl_display *display); -struct wl_visual * -wl_display_get_rgb_visual(struct wl_display *display); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/wayland/wayland-client.pc.in b/wayland/wayland-client.pc.in deleted file mode 100644 index 59a925d..0000000 --- a/wayland/wayland-client.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: Wayland Client -Description: Wayland client side library -Version: 0.1 -Cflags: -I${includedir} -Libs: -L${libdir} -lwayland-client diff --git a/wayland/wayland-egl.h b/wayland/wayland-egl.h deleted file mode 100644 index d3de87c..0000000 --- a/wayland/wayland-egl.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * Copyright © 2011 Benjamin Franzke - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _WAYLAND_EGL_H -#define _WAYLAND_EGL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <wayland-client.h> - -#define WL_EGL_PLATFORM 1 - -struct wl_egl_display; -struct wl_egl_window; -struct wl_egl_pixmap; - -struct wl_egl_display * -wl_egl_display_create(struct wl_display *egl_display); - -void -wl_egl_display_destroy(struct wl_egl_display *egl_display); - -struct wl_egl_window * -wl_egl_window_create(struct wl_egl_display *egl_display, - struct wl_surface *surface, - int width, int height, - struct wl_visual *visual); - -void -wl_egl_window_destroy(struct wl_egl_window *egl_window); - -void -wl_egl_window_resize(struct wl_egl_window *egl_window, - int width, int height, - int dx, int dy); - -void -wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, - int *width, int *height); - -struct wl_egl_pixmap * -wl_egl_pixmap_create(struct wl_egl_display *egl_display, - int width, int height, - struct wl_visual *visual, uint32_t flags); -void -wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap); - -struct wl_buffer * -wl_egl_pixmap_create_buffer(struct wl_egl_display *egl_display, - struct wl_egl_pixmap *egl_pixmap); - -void -wl_egl_pixmap_flush(struct wl_egl_display *egl_display, - struct wl_egl_pixmap *egl_pixmap); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/wayland/wayland-hash.c b/wayland/wayland-hash.c deleted file mode 100644 index b299a33..0000000 --- a/wayland/wayland-hash.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * Copyright © 1988-2004 Keith Packard and Bart Massey. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Except as contained in this notice, the names of the authors - * or their institutions shall not be used in advertising or - * otherwise to promote the sale, use or other dealings in this - * Software without prior written authorization from the - * authors. - * - * Authors: - * Eric Anholt <eric@anholt.net> - * Keith Packard <keithp@keithp.com> - */ - -#include <stdlib.h> - -#include "wayland-util.h" - -struct hash_entry { - uint32_t hash; - void *data; -}; - -struct wl_hash_table { - struct hash_entry *table; - uint32_t size; - uint32_t rehash; - uint32_t max_entries; - uint32_t size_index; - uint32_t entries; - uint32_t deleted_entries; -}; - -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) - -/* - * From Knuth -- a good choice for hash/rehash values is p, p-2 where - * p and p-2 are both prime. These tables are sized to have an extra 10% - * free to avoid exponential performance degradation as the hash table fills - */ - -static const uint32_t deleted_data; - -static const struct { - uint32_t max_entries, size, rehash; -} hash_sizes[] = { - { 2, 5, 3 }, - { 4, 7, 5 }, - { 8, 13, 11 }, - { 16, 19, 17 }, - { 32, 43, 41 }, - { 64, 73, 71 }, - { 128, 151, 149 }, - { 256, 283, 281 }, - { 512, 571, 569 }, - { 1024, 1153, 1151 }, - { 2048, 2269, 2267 }, - { 4096, 4519, 4517 }, - { 8192, 9013, 9011 }, - { 16384, 18043, 18041 }, - { 32768, 36109, 36107 }, - { 65536, 72091, 72089 }, - { 131072, 144409, 144407 }, - { 262144, 288361, 288359 }, - { 524288, 576883, 576881 }, - { 1048576, 1153459, 1153457 }, - { 2097152, 2307163, 2307161 }, - { 4194304, 4613893, 4613891 }, - { 8388608, 9227641, 9227639 }, - { 16777216, 18455029, 18455027 }, - { 33554432, 36911011, 36911009 }, - { 67108864, 73819861, 73819859 }, - { 134217728, 147639589, 147639587 }, - { 268435456, 295279081, 295279079 }, - { 536870912, 590559793, 590559791 }, - { 1073741824, 1181116273, 1181116271}, - { 2147483648ul, 2362232233ul, 2362232231ul} -}; - -static int -entry_is_free(struct hash_entry *entry) -{ - return entry->data == NULL; -} - -static int -entry_is_deleted(struct hash_entry *entry) -{ - return entry->data == &deleted_data; -} - -static int -entry_is_present(struct hash_entry *entry) -{ - return entry->data != NULL && entry->data != &deleted_data; -} - -WL_EXPORT struct wl_hash_table * -wl_hash_table_create(void) -{ - struct wl_hash_table *ht; - - ht = malloc(sizeof(*ht)); - if (ht == NULL) - return NULL; - - ht->size_index = 0; - ht->size = hash_sizes[ht->size_index].size; - ht->rehash = hash_sizes[ht->size_index].rehash; - ht->max_entries = hash_sizes[ht->size_index].max_entries; - ht->table = calloc(ht->size, sizeof(*ht->table)); - ht->entries = 0; - ht->deleted_entries = 0; - - if (ht->table == NULL) { - free(ht); - return NULL; - } - - return ht; -} - -/** - * Frees the given hash table. - */ -WL_EXPORT void -wl_hash_table_destroy(struct wl_hash_table *ht) -{ - if (!ht) - return; - - free(ht->table); - free(ht); -} - -/** - * Finds a hash table entry with the given key and hash of that key. - * - * Returns NULL if no entry is found. Note that the data pointer may be - * modified by the user. - */ -static void * -hash_table_search(struct wl_hash_table *ht, uint32_t hash) -{ - uint32_t hash_address; - - hash_address = hash % ht->size; - do { - uint32_t double_hash; - - struct hash_entry *entry = ht->table + hash_address; - - if (entry_is_free(entry)) { - return NULL; - } else if (entry_is_present(entry) && entry->hash == hash) { - return entry; - } - - double_hash = hash % ht->rehash; - if (double_hash == 0) - double_hash = 1; - - hash_address = (hash_address + double_hash) % ht->size; - } while (hash_address != hash % ht->size); - - return NULL; -} - -WL_EXPORT void * -wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash) -{ - struct hash_entry *entry; - - entry = hash_table_search(ht, hash); - if (entry != NULL) - return entry->data; - - return NULL; -} - -static void -hash_table_rehash(struct wl_hash_table *ht, int new_size_index) -{ - struct wl_hash_table old_ht; - struct hash_entry *table, *entry; - - if (new_size_index >= ARRAY_SIZE(hash_sizes)) - return; - - table = calloc(hash_sizes[new_size_index].size, sizeof(*ht->table)); - if (table == NULL) - return; - - old_ht = *ht; - - ht->table = table; - ht->size_index = new_size_index; - ht->size = hash_sizes[ht->size_index].size; - ht->rehash = hash_sizes[ht->size_index].rehash; - ht->max_entries = hash_sizes[ht->size_index].max_entries; - ht->entries = 0; - ht->deleted_entries = 0; - - for (entry = old_ht.table; - entry != old_ht.table + old_ht.size; - entry++) { - if (entry_is_present(entry)) { - wl_hash_table_insert(ht, entry->hash, entry->data); - } - } - - free(old_ht.table); -} - -/** - * Inserts the data with the given hash into the table. - * - * Note that insertion may rearrange the table on a resize or rehash, - * so previously found hash_entries are no longer valid after this function. - */ -WL_EXPORT int -wl_hash_table_insert(struct wl_hash_table *ht, uint32_t hash, void *data) -{ - uint32_t hash_address; - - if (ht->entries >= ht->max_entries) { - hash_table_rehash(ht, ht->size_index + 1); - } else if (ht->deleted_entries + ht->entries >= ht->max_entries) { - hash_table_rehash(ht, ht->size_index); - } - - hash_address = hash % ht->size; - do { - struct hash_entry *entry = ht->table + hash_address; - uint32_t double_hash; - - if (!entry_is_present(entry)) { - if (entry_is_deleted(entry)) - ht->deleted_entries--; - entry->hash = hash; - entry->data = data; - ht->entries++; - return 0; - } - - double_hash = hash % ht->rehash; - if (double_hash == 0) - double_hash = 1; - - hash_address = (hash_address + double_hash) % ht->size; - } while (hash_address != hash % ht->size); - - /* We could hit here if a required resize failed. An unchecked-malloc - * application could ignore this result. - */ - return -1; -} - -/** - * This function deletes the given hash table entry. - * - * Note that deletion doesn't otherwise modify the table, so an iteration over - * the table deleting entries is safe. - */ -WL_EXPORT void -wl_hash_table_remove(struct wl_hash_table *ht, uint32_t hash) -{ - struct hash_entry *entry; - - entry = hash_table_search(ht, hash); - if (entry != NULL) { - entry->data = (void *) &deleted_data; - ht->entries--; - ht->deleted_entries++; - } -} diff --git a/wayland/wayland-server.c b/wayland/wayland-server.c deleted file mode 100644 index dece0d1..0000000 --- a/wayland/wayland-server.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stddef.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <dlfcn.h> -#include <assert.h> -#include <sys/time.h> -#include <ffi.h> - -#include "wayland-server.h" -#include "wayland-server-protocol.h" -#include "connection.h" - -struct wl_socket { - int fd; - struct sockaddr_un addr; - struct wl_list link; -}; - -struct wl_client { - struct wl_connection *connection; - struct wl_event_source *source; - struct wl_display *display; - struct wl_list resource_list; - uint32_t id_count; -}; - -struct wl_display { - struct wl_object object; - struct wl_event_loop *loop; - struct wl_hash_table *objects; - int run; - - struct wl_list frame_list; - uint32_t client_id_range; - uint32_t id; - - struct wl_list global_list; - struct wl_list socket_list; -}; - -struct wl_frame_listener { - struct wl_resource resource; - struct wl_client *client; - uint32_t key; - struct wl_list link; -}; - -struct wl_global { - struct wl_object *object; - wl_client_connect_func_t func; - struct wl_list link; -}; - -static int wl_debug = 0; - -WL_EXPORT void -wl_client_post_event(struct wl_client *client, struct wl_object *sender, - uint32_t opcode, ...) -{ - struct wl_closure *closure; - va_list ap; - - va_start(ap, opcode); - closure = wl_connection_vmarshal(client->connection, - sender, opcode, ap, - &sender->interface->events[opcode]); - va_end(ap); - - wl_closure_send(closure, client->connection); - - if (wl_debug) { - fprintf(stderr, " -> "); - wl_closure_print(closure, sender); - } - - wl_closure_destroy(closure); -} - -static void -wl_client_connection_data(int fd, uint32_t mask, void *data) -{ - struct wl_client *client = data; - struct wl_connection *connection = client->connection; - struct wl_object *object; - struct wl_closure *closure; - const struct wl_message *message; - uint32_t p[2], opcode, size; - uint32_t cmask = 0; - int len; - - if (mask & WL_EVENT_READABLE) - cmask |= WL_CONNECTION_READABLE; - if (mask & WL_EVENT_WRITEABLE) - cmask |= WL_CONNECTION_WRITABLE; - - len = wl_connection_data(connection, cmask); - if (len < 0) { - wl_client_destroy(client); - return; - } - - while (len >= sizeof p) { - wl_connection_copy(connection, p, sizeof p); - opcode = p[1] & 0xffff; - size = p[1] >> 16; - if (len < size) - break; - - object = wl_hash_table_lookup(client->display->objects, p[0]); - if (object == NULL) { - wl_client_post_event(client, &client->display->object, - WL_DISPLAY_INVALID_OBJECT, p[0]); - wl_connection_consume(connection, size); - len -= size; - continue; - } - - if (opcode >= object->interface->method_count) { - wl_client_post_event(client, &client->display->object, - WL_DISPLAY_INVALID_METHOD, p[0], opcode); - wl_connection_consume(connection, size); - len -= size; - continue; - } - - message = &object->interface->methods[opcode]; - closure = wl_connection_demarshal(client->connection, size, - client->display->objects, - message); - len -= size; - - if (closure == NULL && errno == EINVAL) { - wl_client_post_event(client, &client->display->object, - WL_DISPLAY_INVALID_METHOD, - p[0], opcode); - continue; - } else if (closure == NULL && errno == ENOMEM) { - wl_client_post_no_memory(client); - continue; - } - - - if (wl_debug) - wl_closure_print(closure, object); - - wl_closure_invoke(closure, object, - object->implementation[opcode], client); - - wl_closure_destroy(closure); - } -} - -static int -wl_client_connection_update(struct wl_connection *connection, - uint32_t mask, void *data) -{ - struct wl_client *client = data; - uint32_t emask = 0; - - if (mask & WL_CONNECTION_READABLE) - emask |= WL_EVENT_READABLE; - if (mask & WL_CONNECTION_WRITABLE) - emask |= WL_EVENT_WRITEABLE; - - return wl_event_source_fd_update(client->source, emask); -} - -WL_EXPORT struct wl_display * -wl_client_get_display(struct wl_client *client) -{ - return client->display; -} - -static void -wl_display_post_range(struct wl_display *display, struct wl_client *client) -{ - wl_client_post_event(client, &client->display->object, - WL_DISPLAY_RANGE, display->client_id_range); - display->client_id_range += 256; - client->id_count += 256; -} - -static struct wl_client * -wl_client_create(struct wl_display *display, int fd) -{ - struct wl_client *client; - struct wl_global *global; - - client = malloc(sizeof *client); - if (client == NULL) - return NULL; - - memset(client, 0, sizeof *client); - client->display = display; - client->source = wl_event_loop_add_fd(display->loop, fd, - WL_EVENT_READABLE, - wl_client_connection_data, client); - client->connection = - wl_connection_create(fd, wl_client_connection_update, client); - - wl_list_init(&client->resource_list); - - wl_display_post_range(display, client); - - wl_list_for_each(global, &display->global_list, link) - wl_client_post_event(client, &client->display->object, - WL_DISPLAY_GLOBAL, - global->object, - global->object->interface->name, - global->object->interface->version); - - wl_list_for_each(global, &display->global_list, link) - if (global->func) - global->func(client, global->object); - - return client; -} - -WL_EXPORT void -wl_client_add_resource(struct wl_client *client, - struct wl_resource *resource) -{ - struct wl_display *display = client->display; - - if (client->id_count-- < 64) - wl_display_post_range(display, client); - - wl_hash_table_insert(client->display->objects, - resource->object.id, resource); - wl_list_insert(client->resource_list.prev, &resource->link); -} - -WL_EXPORT void -wl_client_post_no_memory(struct wl_client *client) -{ - wl_client_post_event(client, - &client->display->object, - WL_DISPLAY_NO_MEMORY); -} - -WL_EXPORT void -wl_client_post_global(struct wl_client *client, struct wl_object *object) -{ - wl_client_post_event(client, - &client->display->object, - WL_DISPLAY_GLOBAL, - object, - object->interface->name, - object->interface->version); -} - -WL_EXPORT void -wl_resource_destroy(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_display *display = client->display; - - wl_list_remove(&resource->link); - if (resource->object.id > 0) - wl_hash_table_remove(display->objects, resource->object.id); - resource->destroy(resource, client); -} - -WL_EXPORT void -wl_client_destroy(struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - - printf("disconnect from client %p\n", client); - - wl_list_for_each_safe(resource, tmp, &client->resource_list, link) - wl_resource_destroy(resource, client); - - wl_event_source_remove(client->source); - wl_connection_destroy(client->connection); - free(client); -} - -static void -lose_pointer_focus(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wl_input_device *device = - container_of(listener, struct wl_input_device, - pointer_focus_listener); - - wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); -} - -static void -lose_keyboard_focus(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wl_input_device *device = - container_of(listener, struct wl_input_device, - keyboard_focus_listener); - - wl_input_device_set_keyboard_focus(device, NULL, time); -} - -WL_EXPORT void -wl_input_device_init(struct wl_input_device *device, - struct wl_compositor *compositor) -{ - wl_list_init(&device->pointer_focus_listener.link); - device->pointer_focus_listener.func = lose_pointer_focus; - wl_list_init(&device->keyboard_focus_listener.link); - device->keyboard_focus_listener.func = lose_keyboard_focus; - - device->x = 100; - device->y = 100; - device->compositor = compositor; -} - -WL_EXPORT void -wl_input_device_set_pointer_focus(struct wl_input_device *device, - struct wl_surface *surface, - uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy) -{ - if (device->pointer_focus == surface) - return; - - if (device->pointer_focus && - (!surface || device->pointer_focus->client != surface->client)) - wl_client_post_event(device->pointer_focus->client, - &device->object, - WL_INPUT_DEVICE_POINTER_FOCUS, - time, NULL, 0, 0, 0, 0); - if (surface) - wl_client_post_event(surface->client, - &device->object, - WL_INPUT_DEVICE_POINTER_FOCUS, - time, surface, x, y, sx, sy); - - device->pointer_focus = surface; - device->pointer_focus_time = time; - - wl_list_remove(&device->pointer_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &device->pointer_focus_listener.link); -} - -WL_EXPORT void -wl_input_device_set_keyboard_focus(struct wl_input_device *device, - struct wl_surface *surface, - uint32_t time) -{ - if (device->keyboard_focus == surface) - return; - - if (device->keyboard_focus && - (!surface || device->keyboard_focus->client != surface->client)) - wl_client_post_event(device->keyboard_focus->client, - &device->object, - WL_INPUT_DEVICE_KEYBOARD_FOCUS, - time, NULL, &device->keys); - - if (surface) - wl_client_post_event(surface->client, - &device->object, - WL_INPUT_DEVICE_KEYBOARD_FOCUS, - time, surface, &device->keys); - - device->keyboard_focus = surface; - device->keyboard_focus_time = time; - - wl_list_remove(&device->keyboard_focus_listener.link); - if (surface) - wl_list_insert(surface->destroy_listener_list.prev, - &device->keyboard_focus_listener.link); -} - -WL_EXPORT void -wl_input_device_end_grab(struct wl_input_device *device, uint32_t time) -{ - const struct wl_grab_interface *interface; - - interface = device->grab->interface; - interface->end(device->grab, time); - device->grab->input_device = NULL; - device->grab = NULL; - - wl_list_remove(&device->grab_listener.link); -} - -static void -lose_grab_surface(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time) -{ - struct wl_input_device *device = - container_of(listener, - struct wl_input_device, grab_listener); - - wl_input_device_end_grab(device, time); -} - -WL_EXPORT void -wl_input_device_start_grab(struct wl_input_device *device, - struct wl_grab *grab, - uint32_t button, uint32_t time) -{ - struct wl_surface *focus = device->pointer_focus; - - device->grab = grab; - device->grab_button = button; - device->grab_time = time; - device->grab_x = device->x; - device->grab_y = device->y; - - device->grab_listener.func = lose_grab_surface; - wl_list_insert(focus->destroy_listener_list.prev, - &device->grab_listener.link); - - grab->input_device = device; -} - -WL_EXPORT int -wl_input_device_update_grab(struct wl_input_device *device, - struct wl_grab *grab, - struct wl_surface *surface, uint32_t time) -{ - if (device->grab != &device->motion_grab || - device->grab_time != time || - device->pointer_focus != surface) - return -1; - - device->grab = grab; - grab->input_device = device; - - return 0; -} - -static void -display_sync(struct wl_client *client, - struct wl_display *display, uint32_t key) -{ - wl_client_post_event(client, &display->object, WL_DISPLAY_KEY, key, 0); -} - -static void -destroy_frame_listener(struct wl_resource *resource, struct wl_client *client) -{ - struct wl_frame_listener *listener = - container_of(resource, struct wl_frame_listener, resource); - - wl_list_remove(&listener->link); - free(listener); -} - -static void -display_frame(struct wl_client *client, - struct wl_display *display, uint32_t key) -{ - struct wl_frame_listener *listener; - - listener = malloc(sizeof *listener); - if (listener == NULL) { - wl_client_post_no_memory(client); - return; - } - - /* The listener is a resource so we destroy it when the client - * goes away. */ - listener->resource.destroy = destroy_frame_listener; - listener->resource.object.id = 0; - listener->client = client; - listener->key = key; - wl_list_insert(client->resource_list.prev, &listener->resource.link); - wl_list_insert(display->frame_list.prev, &listener->link); -} - -struct wl_display_interface display_interface = { - display_sync, - display_frame -}; - - -WL_EXPORT struct wl_display * -wl_display_create(void) -{ - struct wl_display *display; - const char *debug; - - debug = getenv("WAYLAND_DEBUG"); - if (debug) - wl_debug = 1; - - display = malloc(sizeof *display); - if (display == NULL) - return NULL; - - display->loop = wl_event_loop_create(); - if (display->loop == NULL) { - free(display); - return NULL; - } - - display->objects = wl_hash_table_create(); - if (display->objects == NULL) { - free(display); - return NULL; - } - - wl_list_init(&display->frame_list); - wl_list_init(&display->global_list); - wl_list_init(&display->socket_list); - - display->client_id_range = 256; /* Gah, arbitrary... */ - - display->id = 1; - display->object.interface = &wl_display_interface; - display->object.implementation = (void (**)(void)) &display_interface; - wl_display_add_object(display, &display->object); - if (wl_display_add_global(display, &display->object, NULL)) { - wl_event_loop_destroy(display->loop); - free(display); - return NULL; - } - - return display; -} - -WL_EXPORT void -wl_display_destroy(struct wl_display *display) -{ - struct wl_socket *s, *next; - - wl_event_loop_destroy(display->loop); - wl_hash_table_destroy(display->objects); - - wl_list_for_each_safe(s, next, &display->socket_list, link) { - close(s->fd); - unlink(s->addr.sun_path); - free(s); - } - - free(display); -} - -WL_EXPORT void -wl_display_add_object(struct wl_display *display, struct wl_object *object) -{ - object->id = display->id++; - wl_hash_table_insert(display->objects, object->id, object); -} - -WL_EXPORT int -wl_display_add_global(struct wl_display *display, - struct wl_object *object, wl_client_connect_func_t func) -{ - struct wl_global *global; - - global = malloc(sizeof *global); - if (global == NULL) - return -1; - - global->object = object; - global->func = func; - wl_list_insert(display->global_list.prev, &global->link); - - return 0; -} - -WL_EXPORT void -wl_display_post_frame(struct wl_display *display, uint32_t time) -{ - struct wl_frame_listener *listener, *next; - - wl_list_for_each_safe(listener, next, &display->frame_list, link) { - wl_client_post_event(listener->client, &display->object, - WL_DISPLAY_KEY, listener->key, time); - wl_resource_destroy(&listener->resource, listener->client); - } -} - -WL_EXPORT struct wl_event_loop * -wl_display_get_event_loop(struct wl_display *display) -{ - return display->loop; -} - -WL_EXPORT void -wl_display_terminate(struct wl_display *display) -{ - display->run = 0; -} - -WL_EXPORT void -wl_display_run(struct wl_display *display) -{ - display->run = 1; - - while (display->run) - wl_event_loop_dispatch(display->loop, -1); -} - -static void -socket_data(int fd, uint32_t mask, void *data) -{ - struct wl_display *display = data; - struct sockaddr_un name; - socklen_t length; - int client_fd; - - length = sizeof name; - client_fd = accept (fd, (struct sockaddr *) &name, &length); - if (client_fd < 0) - fprintf(stderr, "failed to accept\n"); - - wl_client_create(display, client_fd); -} - -WL_EXPORT int -wl_display_add_socket(struct wl_display *display, const char *name) -{ - struct wl_socket *s; - socklen_t size, name_size; - const char *runtime_dir; - - s = malloc(sizeof *s); - if (s == NULL) - return -1; - - s->fd = socket(PF_LOCAL, SOCK_STREAM, 0); - if (s->fd < 0) - return -1; - - runtime_dir = getenv("XDG_RUNTIME_DIR"); - if (runtime_dir == NULL) { - runtime_dir = "."; - fprintf(stderr, - "XDG_RUNTIME_DIR not set, falling back to %s\n", - runtime_dir); - } - - if (name == NULL) - name = getenv("WAYLAND_DISPLAY"); - if (name == NULL) - name = "wayland-0"; - - memset(&s->addr, 0, sizeof s->addr); - s->addr.sun_family = AF_LOCAL; - name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path, - "%s/%s", runtime_dir, name) + 1; - fprintf(stderr, "using socket %s\n", s->addr.sun_path); - - size = offsetof (struct sockaddr_un, sun_path) + name_size; - if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) - return -1; - - if (listen(s->fd, 1) < 0) - return -1; - - wl_event_loop_add_fd(display->loop, s->fd, - WL_EVENT_READABLE, - socket_data, display); - wl_list_insert(display->socket_list.prev, &s->link); - - return 0; -} - -WL_EXPORT int -wl_compositor_init(struct wl_compositor *compositor, - const struct wl_compositor_interface *interface, - struct wl_display *display) -{ - compositor->object.interface = &wl_compositor_interface; - compositor->object.implementation = (void (**)(void)) interface; - wl_display_add_object(display, &compositor->object); - if (wl_display_add_global(display, &compositor->object, NULL)) - return -1; - - compositor->argb_visual.object.interface = &wl_visual_interface; - compositor->argb_visual.object.implementation = NULL; - wl_display_add_object(display, &compositor->argb_visual.object); - wl_display_add_global(display, &compositor->argb_visual.object, NULL); - - compositor->premultiplied_argb_visual.object.interface = - &wl_visual_interface; - compositor->premultiplied_argb_visual.object.implementation = NULL; - wl_display_add_object(display, - &compositor->premultiplied_argb_visual.object); - wl_display_add_global(display, - &compositor->premultiplied_argb_visual.object, - NULL); - - compositor->rgb_visual.object.interface = &wl_visual_interface; - compositor->rgb_visual.object.implementation = NULL; - wl_display_add_object(display, - &compositor->rgb_visual.object); - wl_display_add_global(display, - &compositor->rgb_visual.object, NULL); - - return 0; -} diff --git a/wayland/wayland-server.h b/wayland/wayland-server.h deleted file mode 100644 index f74cbae..0000000 --- a/wayland/wayland-server.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef WAYLAND_H -#define WAYLAND_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdint.h> -#include "wayland-util.h" -#include "wayland-server-protocol.h" - -enum { - WL_EVENT_READABLE = 0x01, - WL_EVENT_WRITEABLE = 0x02 -}; - -struct wl_event_loop; -struct wl_event_source; -typedef void (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); -typedef void (*wl_event_loop_timer_func_t)(void *data); -typedef void (*wl_event_loop_signal_func_t)(int signal_number, void *data); -typedef void (*wl_event_loop_idle_func_t)(void *data); - -struct wl_event_loop *wl_event_loop_create(void); -void wl_event_loop_destroy(struct wl_event_loop *loop); -struct wl_event_source *wl_event_loop_add_fd(struct wl_event_loop *loop, - int fd, uint32_t mask, - wl_event_loop_fd_func_t func, - void *data); -int wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask); -struct wl_event_source *wl_event_loop_add_timer(struct wl_event_loop *loop, - wl_event_loop_timer_func_t func, - void *data); -struct wl_event_source * -wl_event_loop_add_signal(struct wl_event_loop *loop, - int signal_number, - wl_event_loop_signal_func_t func, - void *data); - -int wl_event_source_timer_update(struct wl_event_source *source, - int ms_delay); -int wl_event_source_remove(struct wl_event_source *source); - - -int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout); -struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop, - wl_event_loop_idle_func_t func, - void *data); -int wl_event_loop_get_fd(struct wl_event_loop *loop); - -struct wl_client; -struct wl_display; -struct wl_input_device; - -struct wl_display *wl_display_create(void); -void wl_display_destroy(struct wl_display *display); -struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); -int wl_display_add_socket(struct wl_display *display, const char *name); -void wl_display_terminate(struct wl_display *display); -void wl_display_run(struct wl_display *display); - -void wl_display_add_object(struct wl_display *display, struct wl_object *object); - -typedef void (*wl_client_connect_func_t)(struct wl_client *client, struct wl_object *global); - -int wl_display_add_global(struct wl_display *display, struct wl_object *object, wl_client_connect_func_t func); - -void wl_client_destroy(struct wl_client *client); -void wl_client_post_no_memory(struct wl_client *client); -void wl_client_post_global(struct wl_client *client, struct wl_object *object); - -struct wl_visual { - struct wl_object object; -}; - -struct wl_compositor { - struct wl_object object; - struct wl_visual argb_visual; - struct wl_visual premultiplied_argb_visual; - struct wl_visual rgb_visual; -}; - -struct wl_resource { - struct wl_object object; - void (*destroy)(struct wl_resource *resource, - struct wl_client *client); - struct wl_list link; -}; - -struct wl_buffer { - struct wl_resource resource; - struct wl_compositor *compositor; - struct wl_visual *visual; - int32_t width, height; - void (*attach)(struct wl_buffer *buffer, struct wl_surface *surface); - void (*damage)(struct wl_buffer *buffer, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height); -}; - -struct wl_listener { - struct wl_list link; - void (*func)(struct wl_listener *listener, - struct wl_surface *surface, uint32_t time); -}; - -struct wl_surface { - struct wl_resource resource; - struct wl_client *client; - struct wl_list destroy_listener_list; -}; - -struct wl_shell { - struct wl_object object; -}; - -struct wl_grab; -struct wl_grab_interface { - void (*motion)(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y); - void (*button)(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state); - void (*end)(struct wl_grab *grab, uint32_t time); -}; - -struct wl_grab { - const struct wl_grab_interface *interface; - struct wl_input_device *input_device; -}; - -struct wl_input_device { - struct wl_object object; - struct wl_compositor *compositor; - struct wl_surface *pointer_focus; - struct wl_surface *keyboard_focus; - struct wl_array keys; - uint32_t pointer_focus_time; - uint32_t keyboard_focus_time; - struct wl_listener pointer_focus_listener; - struct wl_listener keyboard_focus_listener; - - int32_t x, y; - struct wl_grab *grab; - struct wl_grab motion_grab; - uint32_t grab_time; - int32_t grab_x, grab_y; - uint32_t grab_button; - struct wl_listener grab_listener; -}; - -struct wl_drag_offer { - struct wl_object object; -}; - -struct wl_drag { - struct wl_resource resource; - struct wl_grab grab; - struct wl_drag_offer drag_offer; - struct wl_surface *source; - struct wl_surface *drag_focus; - struct wl_client *target; - int32_t x, y, sx, sy; - struct wl_array types; - const char *type; - uint32_t pointer_focus_time; - struct wl_listener drag_focus_listener; -}; - -struct wl_selection_offer { - struct wl_object object; -}; - -struct wl_selection { - struct wl_resource resource; - struct wl_client *client; - struct wl_input_device *input_device; - struct wl_selection_offer selection_offer; - struct wl_surface *selection_focus; - struct wl_client *target; - struct wl_array types; - struct wl_listener selection_focus_listener; -}; - -void -wl_client_post_event(struct wl_client *client, - struct wl_object *sender, - uint32_t event, ...); - -int -wl_display_set_compositor(struct wl_display *display, - struct wl_compositor *compositor, - const struct wl_compositor_interface *implementation); - -void -wl_display_post_frame(struct wl_display *display, uint32_t msecs); - -void -wl_client_add_resource(struct wl_client *client, - struct wl_resource *resource); - -struct wl_display * -wl_client_get_display(struct wl_client *client); - -void -wl_resource_destroy(struct wl_resource *resource, struct wl_client *client); - -void -wl_input_device_init(struct wl_input_device *device, - struct wl_compositor *compositor); - -void -wl_input_device_set_pointer_focus(struct wl_input_device *device, - struct wl_surface *surface, - uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy); - -void -wl_input_device_set_keyboard_focus(struct wl_input_device *device, - struct wl_surface *surface, - uint32_t time); - -void -wl_input_device_end_grab(struct wl_input_device *device, uint32_t time); -void -wl_input_device_start_grab(struct wl_input_device *device, - struct wl_grab *grab, - uint32_t button, uint32_t time); -int -wl_input_device_update_grab(struct wl_input_device *device, - struct wl_grab *grab, - struct wl_surface *surface, uint32_t time); - -int -wl_compositor_init(struct wl_compositor *compositor, - const struct wl_compositor_interface *interface, - struct wl_display *display); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/wayland/wayland-server.pc.in b/wayland/wayland-server.pc.in deleted file mode 100644 index b317461..0000000 --- a/wayland/wayland-server.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: Wayland Server -Description: Server side implementation of the Wayland protocol -Version: 0.1 -Cflags: -I${includedir} -Libs: -L${libdir} -lwayland-server diff --git a/wayland/wayland-util.c b/wayland/wayland-util.c deleted file mode 100644 index 3643274..0000000 --- a/wayland/wayland-util.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include "wayland-util.h" - -WL_EXPORT void -wl_list_init(struct wl_list *list) -{ - list->prev = list; - list->next = list; -} - -WL_EXPORT void -wl_list_insert(struct wl_list *list, struct wl_list *elm) -{ - elm->prev = list; - elm->next = list->next; - list->next = elm; - elm->next->prev = elm; -} - -WL_EXPORT void -wl_list_remove(struct wl_list *elm) -{ - elm->prev->next = elm->next; - elm->next->prev = elm->prev; -} - -WL_EXPORT int -wl_list_length(struct wl_list *list) -{ - struct wl_list *e; - int count; - - count = 0; - e = list->next; - while (e != list) { - e = e->next; - count++; - } - - return count; -} - -WL_EXPORT int -wl_list_empty(struct wl_list *list) -{ - return list->next == list; -} - -WL_EXPORT void -wl_array_init(struct wl_array *array) -{ - memset(array, 0, sizeof *array); -} - -WL_EXPORT void -wl_array_release(struct wl_array *array) -{ - free(array->data); -} - -WL_EXPORT void * -wl_array_add(struct wl_array *array, int size) -{ - int alloc; - void *data, *p; - - if (array->alloc > 0) - alloc = array->alloc; - else - alloc = 16; - - while (alloc < array->size + size) - alloc *= 2; - - if (array->alloc < alloc) { - if (array->alloc > 0) - data = realloc(array->data, alloc); - else - data = malloc(alloc); - - if (data == NULL) - return 0; - array->data = data; - array->alloc = alloc; - } - - p = array->data + array->size; - array->size += size; - - return p; -} - -WL_EXPORT void -wl_array_copy(struct wl_array *array, struct wl_array *source) -{ - array->size = 0; - wl_array_add(array, source->size); - memcpy(array->data, source->data, source->size); -} diff --git a/wayland/wayland-util.h b/wayland/wayland-util.h deleted file mode 100644 index 6c1231a..0000000 --- a/wayland/wayland-util.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef WAYLAND_UTIL_H -#define WAYLAND_UTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <inttypes.h> - -/* GCC visibility */ -#if defined(__GNUC__) && __GNUC__ >= 4 -#define WL_EXPORT __attribute__ ((visibility("default"))) -#else -#define WL_EXPORT -#endif - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) -#define ALIGN(n, a) ( ((n) + ((a) - 1)) & ~((a) - 1) ) -#define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) ) - -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -struct wl_argument { - uint32_t type; - void *data; -}; - -struct wl_message { - const char *name; - const char *signature; - const void **types; -}; - -struct wl_interface { - const char *name; - int version; - int method_count; - const struct wl_message *methods; - int event_count; - const struct wl_message *events; -}; - -struct wl_object { - const struct wl_interface *interface; - void (**implementation)(void); - uint32_t id; -}; - -struct wl_hash_table; -struct wl_hash_table *wl_hash_table_create(void); -void wl_hash_table_destroy(struct wl_hash_table *ht); -void *wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash); -int wl_hash_table_insert(struct wl_hash_table *ht, uint32_t hash, void *data); -void wl_hash_table_remove(struct wl_hash_table *ht, uint32_t hash); - -/** - * wl_list - linked list - * - * The list head is of "struct wl_list" type, and must be initialized - * using wl_list_init(). All entries in the list must be of the same - * type. The item type must have a "struct wl_list" member. This - * member will be initialized by wl_list_insert(). There is no need to - * call wl_list_init() on the individual item. To query if the list is - * empty in O(1), use wl_list_empty(). - * - * Let's call the list reference "struct wl_list foo_list", the item type as - * "item_t", and the item member as "struct wl_list link". The following code - * - * The following code will initialize a list: - * - * wl_list_init(foo_list); - * wl_list_insert(foo_list, item1); Pushes item1 at the head - * wl_list_insert(foo_list, item2); Pushes item2 at the head - * wl_list_insert(item2, item3); Pushes item3 after item2 - * - * The list now looks like [item2, item3, item1] - * - * Will iterate the list in ascending order: - * - * item_t *item; - * wl_list_for_each(item, foo_list, link) { - * Do_something_with_item(item); - * } - */ -struct wl_list { - struct wl_list *prev; - struct wl_list *next; -}; - -void wl_list_init(struct wl_list *list); -void wl_list_insert(struct wl_list *list, struct wl_list *elm); -void wl_list_remove(struct wl_list *elm); -int wl_list_length(struct wl_list *list); -int wl_list_empty(struct wl_list *list); - -#define __container_of(ptr, sample, member) \ - (void *)((char *)(ptr) - \ - ((char *)&(sample)->member - (char *)(sample))) - -#define wl_list_for_each(pos, head, member) \ - for (pos = 0, pos = __container_of((head)->next, pos, member); \ - &pos->member != (head); \ - pos = __container_of(pos->member.next, pos, member)) - -#define wl_list_for_each_safe(pos, tmp, head, member) \ - for (pos = 0, tmp = 0, \ - pos = __container_of((head)->next, pos, member), \ - tmp = __container_of((pos)->member.next, tmp, member); \ - &pos->member != (head); \ - pos = tmp, \ - tmp = __container_of(pos->member.next, tmp, member)) - -#define wl_list_for_each_reverse(pos, head, member) \ - for (pos = 0, pos = __container_of((head)->prev, pos, member); \ - &pos->member != (head); \ - pos = __container_of(pos->member.prev, pos, member)) - -struct wl_array { - uint32_t size; - uint32_t alloc; - void *data; -}; - -void wl_array_init(struct wl_array *array); -void wl_array_release(struct wl_array *array); -void *wl_array_add(struct wl_array *array, int size); -void wl_array_copy(struct wl_array *array, struct wl_array *source); - -#ifdef __cplusplus -} -#endif - -#endif |