Giter Club home page Giter Club logo

Comments (5)

abooij avatar abooij commented on July 28, 2024

Thanks for your question.

I'm not quite sure which callbacks you are referring to here. But presumably you are expecting an API similar to the one in libwayland, for which the wayland-{client,server}-core.h header files contain the main methods for speaking the wayland protocol.

These methods translate message data (e.g. the mouse's updated x,y positions) into binary messages that are subsequently sent on the UNIX domain socket (or vice versa, translate binary socket data into callbacks with x,y positions), and also track which wayland objects are alive and which are not. sudbury implements this for the C ABI.

However, there is not yet an equivalent API for haskell itself. This relates to #2. That means that although sudbury is able to send and receive binary messages, and be called by C and call back into C, if you want to write a program in Haskell, right now you'll have to construct the message you want to send pretty much "manually". There is no Haskell API that links the protocol specification (wayland.xml) to message sending/receiving. There is only a data type for messages on the socket that parses their binary data into the appropriate fields.

That does not mean you can't write programs with sudbury, but for "practical" purposes it'll be a bit tedious. And indeed it would be nice to have such a Haskell API.

Personally, I'm rather unsure what this Haskell API should look like. So if you have any ideas on what would be nice from an API user's point of view, they are most welcome. If you can write a program the way you would like the API to look, that'd be very welcome. Personally I'd favour something as strongly typed as reasonably possible.

from sudbury.

joe9 avatar joe9 commented on July 28, 2024

Hello,


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>

struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct wl_egl_window *egl_window;
struct wl_region *region;
struct wl_shell *shell;
struct wl_shell_surface *shell_surface;

EGLDisplay egl_display;
EGLConfig egl_conf;
EGLSurface egl_surface;
EGLContext egl_context;

static void
global_registry_handler(void *data, struct wl_registry *registry, uint32_t id,
            const char *interface, uint32_t version)
{
   printf("Got a registry event for %s id %d\n", interface, id);
   if (strcmp(interface, "wl_compositor") == 0) {
      compositor = wl_registry_bind(registry,
                    id,
                    &wl_compositor_interface,
                    1);
   } else if (strcmp(interface, "wl_shell") == 0) {
      shell = wl_registry_bind(registry, id,
                   &wl_shell_interface, 1);

   }
}

static void
global_registry_remover(void *data, struct wl_registry *registry, uint32_t id)
{
   printf("Got a registry losing event for %d\n", id);
}

static const struct wl_registry_listener registry_listener = {
   global_registry_handler,
   global_registry_remover
};

static void
create_opaque_region() {
   region = wl_compositor_create_region(compositor);
   wl_region_add(region, 0, 0,
         480,
         360);
   wl_surface_set_opaque_region(surface, region);
}

static void
create_window() {

   egl_window = wl_egl_window_create(surface,
                     480, 360);
   if (egl_window == EGL_NO_SURFACE) {
      fprintf(stderr, "Can't create egl window\n");
      exit(1);
   } else {
      fprintf(stderr, "Created egl window\n");
   }

   egl_surface =
     eglCreateWindowSurface(egl_display,
                egl_conf,
                egl_window, NULL);

   if (eglMakeCurrent(egl_display, egl_surface,
              egl_surface, egl_context)) {
      fprintf(stderr, "Made current\n");
   } else {
      fprintf(stderr, "Made current failed\n");
   }

   glClearColor(1.0, 1.0, 0.0, 1.0);
   glClear(GL_COLOR_BUFFER_BIT);
   glFlush();

   if (eglSwapBuffers(egl_display, egl_surface)) {
      fprintf(stderr, "Swapped buffers\n");
   } else {
      fprintf(stderr, "Swapped buffers failed\n");
   }
}

static void
init_egl() {
   EGLint major, minor, count, n, size;
   EGLConfig *configs;
   int i;
   EGLint config_attribs[] = {
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
      EGL_NONE
   };

   static const EGLint context_attribs[] = {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };


   egl_display = eglGetDisplay((EGLNativeDisplayType) display);
   if (egl_display == EGL_NO_DISPLAY) {
      fprintf(stderr, "Can't create egl display\n");
      exit(1);
   } else {
      fprintf(stderr, "Created egl display\n");
   }

   if (eglInitialize(egl_display, &major, &minor) != EGL_TRUE) {
      fprintf(stderr, "Can't initialise egl display\n");
      exit(1);
   }
   printf("EGL major: %d, minor %d\n", major, minor);

   eglGetConfigs(egl_display, NULL, 0, &count);
   printf("EGL has %d configs\n", count);

   configs = calloc(count, sizeof *configs);

   eglChooseConfig(egl_display, config_attribs,
           configs, count, &n);

   for (i = 0; i < n; i++) {
      eglGetConfigAttrib(egl_display,
             configs[i], EGL_BUFFER_SIZE, &size);
      printf("Buffer size for config %d is %d\n", i, size);
      eglGetConfigAttrib(egl_display,
             configs[i], EGL_RED_SIZE, &size);
      printf("Red size for config %d is %d\n", i, size);

      // just choose the first one
      egl_conf = configs[i];
      break;
   }

   egl_context =
     eglCreateContext(egl_display,
              egl_conf,
              EGL_NO_CONTEXT, context_attribs);

}

static void
get_server_references(void) {

   display = wl_display_connect(NULL);
   if (display == NULL) {
      fprintf(stderr, "Can't connect to display\n");
      exit(1);
   }
   printf("connected to display\n");

   struct wl_registry *registry = wl_display_get_registry(display);
   wl_registry_add_listener(registry, &registry_listener, NULL);

   wl_display_dispatch(display);
   wl_display_roundtrip(display);

   if (compositor == NULL || shell == NULL) {
      fprintf(stderr, "Can't find compositor or shell\n");
      exit(1);
   } else {
      fprintf(stderr, "Found compositor and shell\n");
   }
}

int main(int argc, char **argv) {

   get_server_references();

   surface = wl_compositor_create_surface(compositor);
   if (surface == NULL) {
      fprintf(stderr, "Can't create surface\n");
      exit(1);
   } else {
      fprintf(stderr, "Created surface\n");
   }

   shell_surface = wl_shell_get_shell_surface(shell, surface);
   wl_shell_surface_set_toplevel(shell_surface);

   create_opaque_region();
   init_egl();
   create_window();

   while (wl_display_dispatch(display) != -1) {
      ;
   }

   wl_display_disconnect(display);
   printf("disconnected from display\n");

   exit(0);
}

This is sample code to render something in a window. I cannot figure out how the struct wl_registry_listener would translate to haskell land. Any thoughts, please?

Thanks

from sudbury.

abooij avatar abooij commented on July 28, 2024

I'm not quite sure what you're asking. sudbury has no practical solution for sending and receiving wayland messages in Haskell yet, except for the ABI that is used by compiled C programs. Now, what we would like to have here can consist of several solutions: calls and callbacks like in C (in other words, a translation of wl_registry_listener and other parts of the callback mechanism), or a streaming model, or functional reactive programming, or polling-based...

from sudbury.

joe9 avatar joe9 commented on July 28, 2024

Thanks for the quick response. Do you hang out in any irc channels? It might be quicker if I can discuss it with you there.

from sudbury.

abooij avatar abooij commented on July 28, 2024

We have now discussed this via IRC. I think my responses here are adequate, but feel free to open a new issue if there are any remaining questions about the status of sudbury.

from sudbury.

Related Issues (20)

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.