Giter Site home page Giter Site logo

abooij / sudbury Goto Github PK

View Code? Open in Web Editor NEW
88.0 16.0 5.0 314 KB

Haskell implementation of the wayland protocol

License: MIT License

Haskell 75.78% C 24.10% Makefile 0.12%
haskell wayland-library wayland-client wayland-protocol wayland-compositor libwayland

sudbury's Introduction

Sudbury Build Status on Travis CI

A haskell implementation of the Wayland protocol. Any implementation of the Wayland protocol needs to support some C ABI calls if it wants to support EGL, so we just aim to implement the entire C ABI.

Sudbury architecture

FAQ: Where's the sample code of this Haskell library?

At this stage, most work has gone into preliminaries and supporting the C client ABI. That means that this is a piece of really elegant Haskell code that can only really be used by C wayland clients. In other words, this project is currently a drop-in replacement of libwayland-client.so (as of commit 24e5b89, all weston clients seem to run correctly).

However, the aim is to write a really nice Haskell interface so that you can write all your Wayland programs in elegant Haskell. See issue #2 for progress on the usability of this code in Haskell. See issue #3 for progress on the C ABI for compositors (making this a drop-in replacement of libwayland-server.so, thus a replacement of the original C wayland code).

FAQ: This won't work because the libwayland C library assumes it's in charge

This library builds its own dynamic object (see the foreign-library section in sudbury.cabal). If you have a piece of C code which calls into C libwayland code, and it doesn't do e.g. hacky pointer arithmetic, then it will work equally well with sudbury. If not, report a bug.

In other words, this project is supposed to be an ABI-compatible drop-in replacement to the C project.

(Currently, it's client side only, because developer time is finite. But the server side should be doable as well.)

Philosophy

The Haskell bindings to the C wayland library are ugly and are not able to satisfy every need. Ultimately, this seems to be due to the nature of the libwayland API: it hides as many implementation details as it can, and only exposes a minimal API, for a specific use case (namely compositors and windowed clients).

Let's develop a more friendly and inviting library. Sudbury is an attempt to serve many usages of the wayland protocol: desktop applications, compositors, protocol dumpers, test utilities, ...

In addition, we would like to support many different programming paradigms - especially since in Haskell there are many different approaches to streaming IO (lazy IO, conduit, pipes, io-streams, ...) and event handling (polling, callbacks, FRP, ...).

While libwayland hides implementation details, sudbury exposes implementation details. To that end, as a rule of thumb, the haskell modules in this library expose all the (top-level) variables that they define. In particular, we minimize the amount of code that is considered "internal". Indeed, the philosophy is that we should not decide what API should be used, but merely offer users a safe API by making that component the most friendly and inviting API.

We intend to place unsafe code in self-contained modules, separated from the Haskell code we intend users to use directly.

Building and running

The package should be buildable using a development version (i.e. >=1.25) of cabal (development version as of 27 November 2016). As the moment, 27 November 2016, it does not seem to be buildable using stack.

To build with cabal, clone this repository and run

$ cabal sandbox init
$ cabal install

(It is installed locally in a subdirectory of the repository.)

If you installed the project with cabal, you can use it directly. Fire up your favorite wayland compositor, and use cabal exec to run existing executables with the sudbury implementation of the wayland client library:

$ cabal exec weston-flower
$ cabal exec weston-dnd

Portability: The wayland protocol works via unix domain sockets that support passing file descriptors. That means that even if this builds on non-Linux systems, it will likely not work.

(Planned) features

  • Implement the libwayland ABI to support running existing wayland applications without modification.
    • client-side (mostly done)
    • server-side (not started yet)
  • Write a flexible Haskell API.
    • We can use inspiration from the implementation of the ABI to see which components should be exposed and how.
    • The wayland objects all have a corresponding "interface" which is much like a type. Hence, we should use some fancy Haskell features to make the API more strongly typed than libwayland's.
  • Organise the code so that we can do extensive testing and benchmarking.
    • Because of the functional coding style, we will be able to test many more aspects of our code than libwayland.

Contributing

Most things that require attention should be documented somewhere: either in this readme file, or as an issue on github.

Any feedback on your experience using this library is welcome. Usage here encompasses:

  • simply building the library on system X with build system Y
  • running a wayland client using the instructions above:
    • are you able to make it use the sudbury implementation?
    • does the client connect?
    • does the client function as it does with libwayland?

For contributing code, you will probably want to get a bit more familiar with wayland. Some notes on understanding wayland are in NOTES.md. To work on:

  • work on any of the outstanding issues.
  • use sudbury to write tools to e.g. query wayland compositors, or to debug wayland connections. can we rewrite existing debug tools into haskell, using fewer lines of code? can we rewrite the weston client demos?

Related projects

sudbury's People

Contributors

abooij avatar anarchist666 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sudbury's Issues

Performance unclear

We should make sure that the library is sufficiently efficient for day-to-day use. I'm not sure how to evaluate this. Do the regular graphics 2D and 3D benchmarks (such as gtkperf, perhaps glxgears) give any useful information?

Implement object lifetime tracker

The (hopefully) final bug in #5 is the fact that we are not tracking object lifetime correctly. I think the elegant way to solve this is to restructure how we queue the packages for sending/receiving.

Currently, this send/receive queue is just that: a queue of WirePackages and file descriptors that get decoded into WireMessages somewhere along the way (this code is currently in Graphics.Sudbury.CABI.Client, but either this code or the solution I propose next should be available for the Haskell API as well, as a step towards solving #2). Probably the better way to set this up is to write some code that orders all packages coming in and going out, and depending on that, decides if objects should be considered alive or dead for certain operations. I'm imagining a pipeline roughly like this:

User code <-----------> MessageQueueManager <---------------> PackageQueueManager <--> domain socket
           WireMessage                       WirePackage, Fd

where MessageQueueManager sequences the incoming/outgoing packages, and makes object lifetime decisions atomically.

If users want to send/receive raw WirePackages, then this pattern still allows that: simply don't use the MessageQueueManager, or insert something between that and the PackageQueueManager.

The complicating factor here is that we'd need to teach MessageQueueManager about decoding WirePackages.

(names may change)

Extract the juices

This is slowly becoming a fairly serious project, so it probably contains several pieces of code that really should be generalised and released as standalone packages. I don't know what they are, but this issue highlights the efforts to find them.

Version checks infrastructure

We should compare versions of the protocol that our library implements, the user uses, and the person on the other side of the wire uses.

This has the potential to prevent bugs, see #5.

Rewrite singleton data types

Currently we have patterns as follows:

type family ArgProtData (t :: ArgumentType) where
  ArgProtData 'IntWAT = Maybe WLEnum
  ArgProtData 'UIntWAT = Maybe WLEnum
  ArgProtData 'FixedWAT = ()
  ArgProtData 'StringWAT = ()
  ArgProtData 'ObjectWAT = Maybe WLInterface
  ArgProtData 'NewIdWAT = Maybe WLInterface
  ArgProtData 'ArrayWAT = ()
  ArgProtData 'FdWAT = ()
data ArgProtDataBox = forall t. ArgProtDataBox (SArgumentType t) (ArgProtData t)
type family WireArgument (t :: ArgumentType) where
  WireArgument 'IntWAT = Int32
  WireArgument 'UIntWAT = Word32
  WireArgument 'FixedWAT = Fixed23_8
  WireArgument 'StringWAT = B.ByteString
  WireArgument 'ObjectWAT = Word32
  WireArgument 'NewIdWAT = Word32
  WireArgument 'ArrayWAT = B.ByteString
  WireArgument 'FdWAT = ()
data WireArgBox = forall t. WireArgBox (SArgumentType t) (WireArgument t)

First of all, the constructor names are a bit long. Secondly, we can replace the box type definitions by something like this:

data ArgBox (f :: ArgumentType -> *) = forall t . (SArgumentType t) :=> (f t)
infixr 1 :=>

(here, I'm stealing syntax from dependent-sum)
And now we could obtain the original types as:

type ArgProtDataBox = ArgBox ArgProtData
type WireArgBox = ArgBox WireArgument

This will make a bunch of code more concise.

TODO: care about strictness?

Setup ABI tracker

There are at least two reasons we are interested in implementing libwayland's ABI:

  1. It makes sudbury into a drop-in replacement of libwayland.
  2. If somebody wants to write a compositor with sudbury, then the (e.g.) EGL libraries that they'll want to use expect to be able to call back into libwayland.

Simply taking the relevant C header files and writing appropriate "foreign export" statements seems to work very well. But for correctness and completeness it would be useful to have a tool that constantly monitors the differences of the libwayland and sudbury ABI.

Google turns up "ABI Compliance Checker" and "abidiff" which look relevant, but I did not look into it much.

An added challenge here will be that sudbury's versions of the libraries will expose a lot of extra symbols that come with the Haskell runtime. These should be filtered out of the report.

Fix error handling

Our error handling is rather underdeveloped. In particular, we have several instances where we simply call error which should really be some kind of "abort and return -1" statement (for the C ABI).

For socket handling (reading and writing, as in Graphics.Sudbury.Socket.Wayland), we need to deal with sockets that close. (oh and when looking at this, please also compare the size limits for reads and writes with libwayland)

Efficient binary serialization

Currently we are serializing and deserializing using bytestring builders and attoparsec, respectively. But that seems like overkill, as our grammars are much simpler than what those libraries support.

Michael Snoyman has written an article and library for serialization in Haskell that might be relevant to our use case.

Build error when building against template-haskell-2.10.0.0

The type of DataD changed, causing the following build error.

[ 9 of 11] Compiling Graphics.Sudbury.Object ( Graphics/Sudbury/Object.hs, /home/auke/dev/sudbury/dist-newstyle/build/sudbury-0.1.0.0/build/Graphics/Sudbury/Object.o )

Graphics/Sudbury/Object.hs:30:3: error:
    • Couldn't match expected type ‘Dec’ with actual type ‘Cxt -> Dec’
    • Probable cause: ‘DataD’ is applied to too few arguments
      In the expression:
        DataD
          []
          (mkName $ capitalize name)
          []
          (map (flip NormalC [] . mkName . capitalize) constrs)
          []
      In an equation for ‘generatePlainType’:
          generatePlainType name constrs
            = DataD
                []
                (mkName $ capitalize name)
                []
                (map (flip NormalC [] . mkName . capitalize) constrs)
                []

Graphics/Sudbury/Object.hs:30:43: error:
    • Couldn't match expected type ‘Maybe Kind’
                  with actual type ‘[Con]’
    • In the fourth argument of ‘DataD’, namely
        ‘(map (flip NormalC [] . mkName . capitalize) constrs)’
      In the expression:
        DataD
          []
          (mkName $ capitalize name)
          []
          (map (flip NormalC [] . mkName . capitalize) constrs)
          []
      In an equation for ‘generatePlainType’:
          generatePlainType name constrs
            = DataD
                []
                (mkName $ capitalize name)
                []
                (map (flip NormalC [] . mkName . capitalize) constrs)
                []

No clear haskell API

Although the C client side is progressing steadily (reimplementing the C ABI), there is no clear API for haskellers to use.
The library should stay flexible, but that doesn't mean the API should be scattered around.
Perhaps writing example code will help steering the haskell API in the right direction.
Some of the code currently only existing for the C ABI (namely in the .CABI submodule) should be generalized for the entire Haskell API.

Add sudbury support to mesa?

It looks like mesa does some hackery to detect pointers to libwayland objects. In particular, in the function _eglNativePlatformDetectNativeDisplay in src/egl/main/egldisplay.c:

if (first_pointer == &wl_display_interface)
   return _EGL_PLATFORM_WAYLAND;

But as far as I know, mesa does not break encapsulation anywhere else. So fixing this instance might be sufficient.
I'm not sure what the impact of this is.

Test suite

It would be nice to have some unit testing and quickcheck-based property testing for our library. The libwayland developers are currently struggling to do anything in this direction, so this would be a big step forward from our side.

I'm not sure how to get started with this. WireMessage and WirePackage encode/decode tests seem obvious, but their API might change according to #6. And sudbury's Haskell API is still a bit in development, see #2. Suggestions are welcome.

Status of sudbury

I was looking to make a window manager in Haskell for Wayland. Is Sudbury at a stage that it would be good for being used in such a project? I can't seem to find any documentation anywhere that would be useful for using the project.

Example code for a client

Hello,

Thanks for sharing sudbury.

I am writing a wayland client to use EGL/OpenGL. Just want to check if you have any sample code.

I cannot figure out how the global_registry_handler and global_registry_remover callbacks translate to haskell.

Thanks again,

Building and using the shared library is difficult

This project consists of a bunch of Haskell modules (which can be used as normal), and a dynamic library that can be used to run existing C code. However, this library is hard to build and use.

  • The readme is missing build instructions.
  • Building this package as a plain cabal package will fail because of missing files: this package (confusingly) depends on libwayland, even though it claims to replace it.
  • The resulting package will not contain the actual C libraries in the correct location, hence will not install correctly.
  • It is unclear how to run existing binaries that were built against libwayland, such that they use this library instead of libwayland (the C library).

No support for server side libwayland ABI

The .CABI modules implement the C ABI. While the client side is progressing steadily, the server side has yet to be written. Writing a server side is useful because it means one can completely replace libwayland by sudbury. This allows for e.g. integration testing along the entire client-compositor connection.

Weston sample clients don't run

A number of sample clients included with the weston reference compositor do not run correctly when using sudbury client-side.

  • weston-simple-egl
has EGL_EXT_buffer_age and EGL_EXT_swap_buffers_with_damage
[1]    6970 segmentation fault (core dumped)

This might be caused by lack of dealing with null pointers in cArgToWireArg in Crap.Client.

  • weston-simple-dmabuf-intel
buffer allocated w 250, h 250, stride 1024, size 262144
buffer allocated w 250, h 250, stride 1024, size 262144
sudbury: IntMap.!: key 4278190080 is not an element of the map

We probably made a mistake in handling new_ids that are part of an event (ie a message from the server), in other words we can't deal with the case where the server decides to create an object.

  • weston-flower
sudbury: <<loop>>

I'm not sure where this originates, but I previously encountered such a loop via an STM deadlock. A number of clients have this error, and they all successfully open a window and then exit in this way. So they show a black rectangle on the screen for a split second.

  • weston-info
weston-info: symbol lookup error: weston-info: undefined symbol: wl_list_init

This is because we did not bake in support for wl_list. Should be an easy fix by just including some C code. (We are not planning to support wl_list on the Haskell side of things because it's not really necessary to do so: we can get away with just providing this C interface.)

  • weston-flower again

On mouseover:

sudbury: Message parse failed: not enough input
  • weston-subsurfaces
Chosen EGL config details:
        RGBA bits: 8 8 8 8
        swap interval range: 0 - 1
[1]    13663 segmentation fault (core dumped)
  • weston-dnd

When actually starting a drag:

[1]    5569 segmentation fault (core dumped)
  • weston-dnd again

When finishing the drag:

sudbury: IntMap.!: key 44 is not an element of the map

(we have to think about object lifetime, and do event handling accordingly)

  • others?

v0.1.0.0 release preparations

To do:

  • make the object lifetime tracker work similar to libwayland's id allocation to complete #11
  • write proof of concept haskell code that uses sudbury (probably requires progress with #2)
  • stack seems to be complaining about missing other-modules somewhere, what's up with that? fixed by not supporting stack for the moment
  • which ghc versions are supported by which build systems, and is everyone properly informed on this?
  • minimize imports
  • document the state of sudbury (i.e. what can you find in this project right now?)
  • document related projects in the readme file: hayland, sivert berg's wayland-wire, ismo puustinen's wayland-tracker, dlahoti's haskell-wlc
  • write a changelog or news file
  • write a release announcement for the haskell community
  • write a release announcement for the wayland community
  • evaluate the remaining TODOs and FIXMEs in the code
  • review the .cabal file
  • code linting
  • tag release
  • upload to hackage
  • announce sudbury on the relevant channels

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.