parent
							
								
									525e4c0bea
								
							
						
					
					
						commit
						b2d71852fd
					
				@ -1,3 +1 @@ | 
				
			|||||||
SUBDIRS = wayland compositor clients data
 | 
					SUBDIRS = compositor clients data
 | 
				
			||||||
 | 
					 | 
				
			||||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,130 +1,6 @@ | 
				
			|||||||
What is Wayland | 
					Wayland Demos | 
				
			||||||
 | 
					
 | 
				
			||||||
Wayland is a project to define a protocol for a compositor to talk to | 
					This repository contains a few demos application for the Wayland | 
				
			||||||
its clients as well as a library implementation of the protocol.  The | 
					project.  There's a sample compositor that can run on KMS, under X11 | 
				
			||||||
compositor can be a standalone display server running on Linux kernel | 
					or under another Wayland compositor and there's a handful of simple | 
				
			||||||
modesetting and evdev input devices, an X applications, or a wayland | 
					clients that demonstrate various aspects of 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) | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -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 | 
					 | 
				
			||||||
@ -1,5 +0,0 @@ | 
				
			|||||||
libtool.m4 | 
					 | 
				
			||||||
ltoptions.m4 | 
					 | 
				
			||||||
ltsugar.m4 | 
					 | 
				
			||||||
ltversion.m4 | 
					 | 
				
			||||||
lt~obsolete.m4 | 
					 | 
				
			||||||
@ -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> | 
					 | 
				
			||||||
@ -1,3 +0,0 @@ | 
				
			|||||||
main.aux | 
					 | 
				
			||||||
main.log | 
					 | 
				
			||||||
main.pdf | 
					 | 
				
			||||||
@ -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} | 
					 | 
				
			||||||
@ -1,4 +0,0 @@ | 
				
			|||||||
scanner | 
					 | 
				
			||||||
wayland-client-protocol.h | 
					 | 
				
			||||||
wayland-protocol.c | 
					 | 
				
			||||||
wayland-server-protocol.h | 
					 | 
				
			||||||
@ -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)
 | 
					 | 
				
			||||||
@ -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) | 
					 | 
				
			||||||
{ | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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 < $< > $@
 | 
					 | 
				
			||||||
@ -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; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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++; | 
					 | 
				
			||||||
	} | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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; | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
@ -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); | 
					 | 
				
			||||||
} | 
					 | 
				
			||||||
@ -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 | 
					 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue