Finding a Way(land)

Thu, 14 Mar 2013 13:32:01 +0000

In the next round we shall be sending it the messages we have so lovingly composed from whole cloth and see if it reacts the same way as it did when the same bytes were sent from weston-info

And the answer is … yes, pretty much. We had to fix up our string parsing to make sense of the replies, but watch:

psadan.core> (def connection (conn/open-connection "/home/dan/private/wayland-0"))
#'psadan.core/connection
psadan.core> (defn test-send-message []
  (let [registry
        (conn/remember-object
         connection
         {:id 2 :interface (proto/find-interface-by-name :wl_registry)})
        done-cb
        (conn/remember-object
         connection
         {:id 3 :interface (proto/find-interface-by-name :wl_callback)})
        ]
    (conn/write-buffer connection
                       (buf/pack-message connection (:display connection)
                                         :requests :get_registry [registry]))
    (conn/write-buffer connection
                       (buf/pack-message connection (:display connection)
                                         :requests :sync [done-cb]))
    registry))

#'psadan.core/test-send-message
psadan.core> (test-send-message)
{:id 2, :interface {:index 1, :name :wl_registry, :requests ({:index 0, :name :bind, :summary "bind an object to the display", :args ({:name "name", :type :uint, :interface nil} {:name "id", :type :new_id, :interface nil})}), :events ({:index 0, :name :global, :summary "announce global object", :args ({:name "name", :type :uint, :interface nil} {:name "interface", :type :string, :interface nil} {:name "version", :type :uint, :interface nil})} {:index 1, :name :global_remove, :summary "announce removal of global object", :args ({:name "name", :type :uint, :interface nil})}), :enums ()}}
psadan.core> (def received (read-buffer connection))
#'psadan.core/received
psadan.core> (pprint (map (fn [x] [(:object-id x) (:message x) (:args x)]) (buf/parse-messages received connection :events)))
nil
([2 :global (1 "wl_display" 1)]
 [2 :global (2 "wl_compositor" 2)]
 [2 :global (3 "screenshooter" 1)]
 [2 :global (4 "text_cursor_position" 1)]
 [2 :global (5 "text_model_factory" 1)]
 [2 :global (6 "wl_data_device_manager" 1)]
 [2 :global (7 "wl_shm" 1)]
 [2 :global (8 "wl_seat" 1)]
 [2 :global (9 "input_method" 1)]
 [2 :global (10 "wl_output" 1)]
 [2 :global (11 "wl_drm" 1)]
 [2 :global (12 "wl_shell" 1)]
 [2 :global (13 "desktop_shell" 1)]
 [2 :global (14 "screensaver" 1)]
 [2 :global (15 "input_panel" 1)]
 [2 :global (16 "workspace_manager" 1)]
 [3 :done (58)]
 [1 :delete_id (3)])

My interpretation of what’s happening here is that we’re sending to the server a ‘tell object 2 about all your global objects’ message, followed by a ‘tell object 3 done when you’re finished doing stuff’ message, and as you can see from the output, the reply is a bunch of ids for global objects sent to object 2, a done event sent to object 3, and then a delete_id event for object 3 sent to object 1. I’m actually not sure why that last one triggers, as I don’t think I asked it to. Perhaps it’s just tidying up for me.

I’m also handwaving – if not actually handdrowning – a litle bit, because really … are these :global messages sent to object 2 or from object 2? For the moment, I am using the two directions interchangeably, which is probably not a recipe for an easier future life, but in the meantime I can continue to tread water.

It’s instructive, or at least reassuring, to compare this stuff with what weston-info says:

interface: 'wl_display', version: 1, name: 1
interface: 'wl_compositor', version: 2, name: 2
interface: 'screenshooter', version: 1, name: 3
interface: 'text_cursor_position', version: 1, name: 4
interface: 'text_model_factory', version: 1, name: 5
interface: 'wl_data_device_manager', version: 1, name: 6
interface: 'wl_shm', version: 1, name: 7
	formats: XRGB8888 ARGB8888
interface: 'wl_seat', version: 1, name: 8
	capabilities: pointer keyboard
interface: 'input_method', version: 1, name: 9
interface: 'wl_output', version: 1, name: 10
	x: 0, y: 0,
	physical_width: 1024 mm, physical_height: 640 mm,
	make: 'xwayland', model: 'none',
	subpixel_orientation: unknown, output_tranform: normal,
	mode:
		width: 1024 px, height: 640 px, refresh: 60 Hz,
		flags: current preferred
interface: 'wl_drm', version: 1, name: 11
interface: 'wl_shell', version: 1, name: 12
interface: 'desktop_shell', version: 1, name: 13
interface: 'screensaver', version: 1, name: 14
interface: 'input_panel', version: 1, name: 15
interface: 'workspace_manager', version: 1, name: 16

Top Wayland tip for today: it appears to be the case that you can make the C library clients log protocol exchanges to stderr by putting WAYLAND_DEBUG=client in the environment. When doing that it’s clear to see that weston-info is making a couple of additional requests that we’re not. We could add them, but I think the more pressing concern is to make it do something with the events we’re getting already – if it’s sending us details of global objects that we might need to know about, we should at a minimum be storing those details somewhere instead of throwing them away …