abooij / sudbury Goto Github PK
View Code? Open in Web Editor NEWHaskell implementation of the wayland protocol
License: MIT License
Haskell implementation of the wayland protocol
License: MIT License
There are at least two reasons we are interested in implementing libwayland's ABI:
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.
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.
Apparently <enum>
<entry>
s support a since
field, which we are not parsing.
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.
As per the Pull Request Hack, we are proactively giving commit access to developers. Use this issue to introduce new developers.
What is needed to make this project more developer-friendly?
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,
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.
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.
This looks kinda neat.
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.
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.
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?
This has not been updated in years
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.
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?
In CABI.Client.hs
, we currently apply a convoluted TMVar
mechanism that takes and returns a Fd
to control access. This is probably better served by an STM lock.
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 WirePackage
s and file descriptors that get decoded into WireMessage
s 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 WirePackage
s, 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 WirePackage
s.
(names may change)
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.
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)
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
againOn 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
againWhen 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)
To do:
other-modules
somewhere, what's up with that?.cabal
fileWe 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.
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)
[]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.