1 /* 2 * This an unstable interface of wlroots. No guarantees are made regarding the 3 * future consistency of this API. 4 */ 5 #ifndef WLR_USE_UNSTABLE 6 #error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" 7 #endif 8 9 #ifndef WLR_XWAYLAND_H 10 #define WLR_XWAYLAND_H 11 12 #include <stdbool.h> 13 #include <time.h> 14 #include <wlr/config.h> 15 #include <wlr/types/wlr_compositor.h> 16 #include <wlr/types/wlr_seat.h> 17 #include <xcb/xcb.h> 18 19 struct wlr_xwm; 20 struct wlr_xwayland_cursor; 21 22 struct wlr_xwayland_server { 23 pid_t pid; 24 struct wl_client *client; 25 struct wl_event_source *sigusr1_source; 26 int wm_fd[2], wl_fd[2]; 27 28 time_t server_start; 29 30 int32_t scale; 31 32 /* Anything above display is reset on Xwayland restart, rest is conserved */ 33 34 int display; 35 char display_name[16]; 36 int x_fd[2]; 37 struct wl_event_source *x_fd_read_event[2]; 38 bool lazy; 39 bool enable_wm; 40 41 struct wl_display *wl_display; 42 43 struct { 44 struct wl_signal ready; 45 struct wl_signal destroy; 46 } events; 47 48 struct wl_listener client_destroy; 49 struct wl_listener display_destroy; 50 51 void *data; 52 }; 53 54 struct wlr_xwayland_server_options { 55 bool lazy; 56 bool enable_wm; 57 }; 58 59 struct wlr_xwayland_server_ready_event { 60 struct wlr_xwayland_server *server; 61 int wm_fd; 62 }; 63 64 struct wlr_xwayland { 65 struct wlr_xwayland_server *server; 66 struct wlr_xwm *xwm; 67 struct wlr_xwayland_cursor *cursor; 68 69 const char *display_name; 70 71 struct wl_display *wl_display; 72 struct wlr_compositor *compositor; 73 struct wlr_seat *seat; 74 75 struct { 76 struct wl_signal ready; 77 struct wl_signal new_surface; 78 } events; 79 80 /** 81 * Add a custom event handler to xwayland. Return 1 if the event was 82 * handled or 0 to use the default wlr-xwayland handler. wlr-xwayland will 83 * free the event. 84 */ 85 int (*user_event_handler)(struct wlr_xwm *xwm, xcb_generic_event_t *event); 86 87 struct wl_listener server_ready; 88 struct wl_listener server_destroy; 89 struct wl_listener seat_destroy; 90 91 void *data; 92 }; 93 94 enum wlr_xwayland_surface_decorations { 95 WLR_XWAYLAND_SURFACE_DECORATIONS_ALL = 0, 96 WLR_XWAYLAND_SURFACE_DECORATIONS_NO_BORDER = 1, 97 WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE = 2, 98 }; 99 100 struct wlr_xwayland_surface_hints { 101 uint32_t flags; 102 uint32_t input; 103 int32_t initial_state; 104 xcb_pixmap_t icon_pixmap; 105 xcb_window_t icon_window; 106 int32_t icon_x, icon_y; 107 xcb_pixmap_t icon_mask; 108 xcb_window_t window_group; 109 }; 110 111 struct wlr_xwayland_surface_size_hints { 112 uint32_t flags; 113 int32_t x, y; 114 int32_t width, height; 115 int32_t min_width, min_height; 116 int32_t max_width, max_height; 117 int32_t width_inc, height_inc; 118 int32_t base_width, base_height; 119 int32_t min_aspect_num, min_aspect_den; 120 int32_t max_aspect_num, max_aspect_den; 121 uint32_t win_gravity; 122 }; 123 124 /** 125 * An Xwayland user interface component. It has an absolute position in 126 * layout-local coordinates. 127 * 128 * When a surface is ready to be displayed, the `map` event is emitted. When a 129 * surface should no longer be displayed, the `unmap` event is emitted. The 130 * `unmap` event is guaranteed to be emitted before the `destroy` event if the 131 * view is destroyed when mapped. 132 */ 133 struct wlr_xwayland_surface { 134 xcb_window_t window_id; 135 struct wlr_xwm *xwm; 136 uint32_t surface_id; 137 138 struct wl_list link; 139 struct wl_list unpaired_link; 140 141 struct wlr_surface *surface; 142 int16_t x, y; 143 uint16_t width, height; 144 uint16_t saved_width, saved_height; 145 bool override_redirect; 146 bool mapped; 147 148 char *title; 149 char *class; 150 char *instance; 151 char *role; 152 pid_t pid; 153 bool has_utf8_title; 154 155 struct wl_list children; // wlr_xwayland_surface::parent_link 156 struct wlr_xwayland_surface *parent; 157 struct wl_list parent_link; // wlr_xwayland_surface::children 158 159 xcb_atom_t *window_type; 160 size_t window_type_len; 161 162 xcb_atom_t *protocols; 163 size_t protocols_len; 164 165 uint32_t decorations; 166 struct wlr_xwayland_surface_hints *hints; 167 uint32_t hints_urgency; 168 struct wlr_xwayland_surface_size_hints *size_hints; 169 170 bool pinging; 171 struct wl_event_source *ping_timer; 172 173 // _NET_WM_STATE 174 bool modal; 175 bool fullscreen; 176 bool maximized_vert, maximized_horz; 177 bool minimized; 178 179 bool has_alpha; 180 181 struct { 182 struct wl_signal destroy; 183 struct wl_signal request_configure; 184 struct wl_signal request_move; 185 struct wl_signal request_resize; 186 struct wl_signal request_minimize; 187 struct wl_signal request_maximize; 188 struct wl_signal request_fullscreen; 189 struct wl_signal request_activate; 190 191 struct wl_signal map; 192 struct wl_signal unmap; 193 struct wl_signal set_title; 194 struct wl_signal set_class; 195 struct wl_signal set_role; 196 struct wl_signal set_parent; 197 struct wl_signal set_pid; 198 struct wl_signal set_window_type; 199 struct wl_signal set_hints; 200 struct wl_signal set_decorations; 201 struct wl_signal set_override_redirect; 202 struct wl_signal set_geometry; 203 struct wl_signal ping_timeout; 204 } events; 205 206 struct wl_listener surface_destroy; 207 208 void *data; 209 }; 210 211 struct wlr_xwayland_surface_configure_event { 212 struct wlr_xwayland_surface *surface; 213 int16_t x, y; 214 uint16_t width, height; 215 uint16_t mask; // xcb_config_window_t 216 }; 217 218 // TODO: maybe add a seat to these 219 struct wlr_xwayland_move_event { 220 struct wlr_xwayland_surface *surface; 221 }; 222 223 struct wlr_xwayland_resize_event { 224 struct wlr_xwayland_surface *surface; 225 uint32_t edges; 226 }; 227 228 struct wlr_xwayland_minimize_event { 229 struct wlr_xwayland_surface *surface; 230 bool minimize; 231 }; 232 233 struct wlr_xwayland_server *wlr_xwayland_server_create( 234 struct wl_display *display, struct wlr_xwayland_server_options *options); 235 void wlr_xwayland_server_destroy(struct wlr_xwayland_server *server); 236 237 /** Create an Xwayland server and XWM. 238 * 239 * The server supports a lazy mode in which Xwayland is only started when a 240 * client tries to connect. 241 * 242 * Note: wlr_xwayland will setup a global SIGUSR1 handler on the compositor 243 * process. 244 */ 245 struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, 246 struct wlr_compositor *compositor, bool lazy); 247 248 void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland); 249 250 void wlr_xwayland_set_scale(struct wlr_xwayland *wlr_xwayland, int32_t scale); 251 252 void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland, 253 uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, 254 int32_t hotspot_x, int32_t hotspot_y); 255 256 void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *surface, 257 bool activated); 258 259 void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *surface, 260 int16_t x, int16_t y, uint16_t width, uint16_t height); 261 262 void wlr_xwayland_surface_close(struct wlr_xwayland_surface *surface); 263 264 void wlr_xwayland_surface_set_minimized(struct wlr_xwayland_surface *surface, 265 bool minimized); 266 267 void wlr_xwayland_surface_set_maximized(struct wlr_xwayland_surface *surface, 268 bool maximized); 269 270 void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface, 271 bool fullscreen); 272 273 void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, 274 struct wlr_seat *seat); 275 276 bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface); 277 278 struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( 279 struct wlr_surface *surface); 280 281 void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface); 282 283 /** Metric to guess if an OR window should "receive" focus 284 * 285 * In the pure X setups, window managers usually straight up ignore override 286 * redirect windows, and never touch them. (we have to handle them for mapping) 287 * 288 * When such a window wants to receive keyboard input (e.g. rofi/dzen) it will 289 * use mechanics we don't support (sniffing/grabbing input). 290 * [Sadly this is unrelated to xwayland-keyboard-grab] 291 * 292 * To still support these windows, while keeping general OR semantics as is, we 293 * need to hand a subset of windows focus. 294 * The dirty truth is, we need to hand focus to any Xwayland window, though 295 * pretending this window has focus makes it easier to handle unmap. 296 * 297 * This function provides a handy metric based on the window type to guess if 298 * the OR window wants focus. 299 * It's probably not perfect, nor exactly intended but works in practice. 300 * 301 * Returns: true if the window should receive focus 302 * false if it should be ignored 303 */ 304 bool wlr_xwayland_or_surface_wants_focus( 305 const struct wlr_xwayland_surface *surface); 306 307 308 #endif 309