@@ -32,6 +32,8 @@ static void noop() {
32
32
33
33
static void xdg_wm_base_handle_ping (void * data ,
34
34
struct xdg_wm_base * xdg_wm_base , uint32_t serial ) {
35
+ // The compositor will send us a ping event to check that we're responsive.
36
+ // We need to send back a pong request immediately.
35
37
xdg_wm_base_pong (xdg_wm_base , serial );
36
38
}
37
39
@@ -41,12 +43,17 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = {
41
43
42
44
static void xdg_surface_handle_configure (void * data ,
43
45
struct xdg_surface * xdg_surface , uint32_t serial ) {
46
+ // The compositor configures our surface, acknowledge the configure event
44
47
xdg_surface_ack_configure (xdg_surface , serial );
48
+
45
49
if (configured ) {
50
+ // If this isn't the first configure event we've received, we already
51
+ // have a buffer attached, so no need to do anything. Commit the
52
+ // surface to apply the configure acknowledgement.
46
53
wl_surface_commit (surface );
47
- } else {
48
- configured = true;
49
54
}
55
+
56
+ configured = true;
50
57
}
51
58
52
59
static const struct xdg_surface_listener xdg_surface_listener = {
@@ -55,6 +62,7 @@ static const struct xdg_surface_listener xdg_surface_listener = {
55
62
56
63
static void xdg_toplevel_handle_close (void * data ,
57
64
struct xdg_toplevel * xdg_toplevel ) {
65
+ // Stop running if the user requests to close the toplevel
58
66
running = false;
59
67
}
60
68
@@ -67,6 +75,8 @@ static void pointer_handle_button(void *data, struct wl_pointer *pointer,
67
75
uint32_t serial , uint32_t time , uint32_t button , uint32_t state ) {
68
76
struct wl_seat * seat = data ;
69
77
78
+ // If the user presses the left pointer button, start an interactive move
79
+ // of the toplevel
70
80
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED ) {
71
81
xdg_toplevel_move (xdg_toplevel , seat , serial );
72
82
}
@@ -82,6 +92,8 @@ static const struct wl_pointer_listener pointer_listener = {
82
92
83
93
static void seat_handle_capabilities (void * data , struct wl_seat * seat ,
84
94
uint32_t capabilities ) {
95
+ // If the wl_seat has the pointer capability, start listening to pointer
96
+ // events
85
97
if (capabilities & WL_SEAT_CAPABILITY_POINTER ) {
86
98
struct wl_pointer * pointer = wl_seat_get_pointer (seat );
87
99
wl_pointer_add_listener (pointer , & pointer_listener , seat );
@@ -123,52 +135,59 @@ static struct wl_buffer *create_buffer(void) {
123
135
int stride = width * 4 ;
124
136
int size = stride * height ;
125
137
138
+ // Allocate a shared memory file with the right size
126
139
int fd = create_shm_file (size );
127
140
if (fd < 0 ) {
128
141
fprintf (stderr , "creating a buffer file for %d B failed: %m\n" , size );
129
142
return NULL ;
130
143
}
131
144
145
+ // Map the shared memory file
132
146
shm_data = mmap (NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 );
133
147
if (shm_data == MAP_FAILED ) {
134
148
fprintf (stderr , "mmap failed: %m\n" );
135
149
close (fd );
136
150
return NULL ;
137
151
}
138
152
153
+ // Create a wl_buffer from our shared memory file descriptor
139
154
struct wl_shm_pool * pool = wl_shm_create_pool (shm , fd , size );
140
155
struct wl_buffer * buffer = wl_shm_pool_create_buffer (pool , 0 , width , height ,
141
156
stride , WL_SHM_FORMAT_ARGB8888 );
142
157
wl_shm_pool_destroy (pool );
143
158
144
- // MagickImage is from cat.h
159
+ // Now that we've mapped the file and created the wl_buffer, we no longer
160
+ // need to keep file descriptor opened
161
+ close (fd );
162
+
163
+ // Copy pixels into our shared memory file (MagickImage is from cat.h)
145
164
memcpy (shm_data , MagickImage , size );
165
+
146
166
return buffer ;
147
167
}
148
168
149
169
int main (int argc , char * argv []) {
170
+ // Connect to the Wayland compositor
150
171
struct wl_display * display = wl_display_connect (NULL );
151
172
if (display == NULL ) {
152
173
fprintf (stderr , "failed to create display\n" );
153
174
return EXIT_FAILURE ;
154
175
}
155
176
177
+ // Obtain the wl_registry and fetch the list of globals
156
178
struct wl_registry * registry = wl_display_get_registry (display );
157
179
wl_registry_add_listener (registry , & registry_listener , NULL );
158
180
if (wl_display_roundtrip (display ) == -1 ) {
159
181
return EXIT_FAILURE ;
160
182
}
161
183
184
+ // Check that all globals we require are available
162
185
if (shm == NULL || compositor == NULL || xdg_wm_base == NULL ) {
163
186
fprintf (stderr , "no wl_shm, wl_compositor or xdg_wm_base support\n" );
164
187
return EXIT_FAILURE ;
165
188
}
166
189
167
- struct wl_buffer * buffer = create_buffer ();
168
- if (buffer == NULL ) {
169
- return EXIT_FAILURE ;
170
- }
171
-
190
+ // Create a wl_surface, a xdg_surface and a xdg_toplevel
172
191
surface = wl_compositor_create_surface (compositor );
173
192
struct xdg_surface * xdg_surface =
174
193
xdg_wm_base_get_xdg_surface (xdg_wm_base , surface );
@@ -177,14 +196,22 @@ int main(int argc, char *argv[]) {
177
196
xdg_surface_add_listener (xdg_surface , & xdg_surface_listener , NULL );
178
197
xdg_toplevel_add_listener (xdg_toplevel , & xdg_toplevel_listener , NULL );
179
198
199
+ // Perform the initial commit and wait for the first configure event
180
200
wl_surface_commit (surface );
181
201
while (wl_display_dispatch (display ) != -1 && !configured ) {
182
202
// This space intentionally left blank
183
203
}
184
204
205
+ // Create a wl_buffer, attach it to the surface and commit the surface
206
+ struct wl_buffer * buffer = create_buffer ();
207
+ if (buffer == NULL ) {
208
+ return EXIT_FAILURE ;
209
+ }
210
+
185
211
wl_surface_attach (surface , buffer , 0 , 0 );
186
212
wl_surface_commit (surface );
187
213
214
+ // Continue dispatching events until the user closes the toplevel
188
215
while (wl_display_dispatch (display ) != -1 && running ) {
189
216
// This space intentionally left blank
190
217
}
0 commit comments