Merge branch '0.3.x' of https://codeberg.org/river/river
This commit is contained in:
		| @ -5,7 +5,7 @@ | ||||
|     // When a release is tagged, the "-dev" suffix should be removed for the | ||||
|     // commit that gets tagged. Directly after the tagged commit, the version | ||||
|     // should be bumped and the "-dev" suffix added. | ||||
|     .version = "0.3.11-dev", | ||||
|     .version = "0.3.12-dev", | ||||
|     .paths = .{""}, | ||||
|     .dependencies = .{ | ||||
|         .pixman = .{ | ||||
| @ -17,8 +17,8 @@ | ||||
|             .hash = "wayland-0.3.0-lQa1kjPIAQDmhGYpY-zxiRzQJFHQ2VqhJkQLbKKdt5wl", | ||||
|         }, | ||||
|         .wlroots = .{ | ||||
|             .url = "https://codeberg.org/ifreund/zig-wlroots/archive/v0.19.1.tar.gz", | ||||
|             .hash = "wlroots-0.19.1-jmOlcs7dAwCajnVWlQZIc-ySYjRlbLxy0F5FvTQqYA3P", | ||||
|             .url = "https://codeberg.org/ifreund/zig-wlroots/archive/f92ba27133ecf702d85c9d3894f98a336389bbd9.tar.gz", | ||||
|             .hash = "wlroots-0.19.3-dev-jmOlcr7_AwClfjFwW8oOkWoqAbt9oPLqgdvfFYEXqlOF", | ||||
|         }, | ||||
|         .xkbcommon = .{ | ||||
|             .url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.3.0.tar.gz", | ||||
|  | ||||
| @ -160,7 +160,7 @@ pub fn reconfigureDevices(input_manager: *InputManager) void { | ||||
| fn handleNewInput(listener: *wl.Listener(*wlr.InputDevice), wlr_device: *wlr.InputDevice) void { | ||||
|     const input_manager: *InputManager = @fieldParentPtr("new_input", listener); | ||||
|  | ||||
|     input_manager.defaultSeat().addDevice(wlr_device); | ||||
|     input_manager.defaultSeat().addDevice(wlr_device, false); | ||||
| } | ||||
|  | ||||
| fn handleNewVirtualPointer( | ||||
| @ -178,17 +178,53 @@ fn handleNewVirtualPointer( | ||||
|         log.debug("Ignoring output suggestion from virtual pointer", .{}); | ||||
|     } | ||||
|  | ||||
|     input_manager.defaultSeat().addDevice(&event.new_pointer.pointer.base); | ||||
|     input_manager.defaultSeat().addDevice(&event.new_pointer.pointer.base, true); | ||||
| } | ||||
|  | ||||
| fn handleNewVirtualKeyboard( | ||||
|     _: *wl.Listener(*wlr.VirtualKeyboardV1), | ||||
|     virtual_keyboard: *wlr.VirtualKeyboardV1, | ||||
| ) void { | ||||
|     const seat: *Seat = @alignCast(@ptrCast(virtual_keyboard.seat.data)); | ||||
|     seat.addDevice(&virtual_keyboard.keyboard.base); | ||||
|     const no_keymap = util.gpa.create(NoKeymapVirtKeyboard) catch { | ||||
|         log.err("out of memory", .{}); | ||||
|         return; | ||||
|     }; | ||||
|     errdefer util.gpa.destroy(no_keymap); | ||||
|  | ||||
|     no_keymap.* = .{ | ||||
|         .virtual_keyboard = virtual_keyboard, | ||||
|     }; | ||||
|     virtual_keyboard.keyboard.base.events.destroy.add(&no_keymap.destroy); | ||||
|     virtual_keyboard.keyboard.events.keymap.add(&no_keymap.keymap); | ||||
| } | ||||
|  | ||||
| /// Ignore virtual keyboards completely until the client sets a keymap | ||||
| /// Yes, wlroots should probably do this for us. | ||||
| const NoKeymapVirtKeyboard = struct { | ||||
|     virtual_keyboard: *wlr.VirtualKeyboardV1, | ||||
|     destroy: wl.Listener(*wlr.InputDevice) = .init(handleDestroy), | ||||
|     keymap: wl.Listener(*wlr.Keyboard) = .init(handleKeymap), | ||||
|  | ||||
|     fn handleDestroy(listener: *wl.Listener(*wlr.InputDevice), _: *wlr.InputDevice) void { | ||||
|         const no_keymap: *NoKeymapVirtKeyboard = @fieldParentPtr("destroy", listener); | ||||
|  | ||||
|         no_keymap.destroy.link.remove(); | ||||
|         no_keymap.keymap.link.remove(); | ||||
|  | ||||
|         util.gpa.destroy(no_keymap); | ||||
|     } | ||||
|  | ||||
|     fn handleKeymap(listener: *wl.Listener(*wlr.Keyboard), _: *wlr.Keyboard) void { | ||||
|         const no_keymap: *NoKeymapVirtKeyboard = @fieldParentPtr("keymap", listener); | ||||
|         const virtual_keyboard = no_keymap.virtual_keyboard; | ||||
|  | ||||
|         handleDestroy(&no_keymap.destroy, &virtual_keyboard.keyboard.base); | ||||
|  | ||||
|         const seat: *Seat = @alignCast(@ptrCast(virtual_keyboard.seat.data)); | ||||
|         seat.addDevice(&virtual_keyboard.keyboard.base, true); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| fn handleNewConstraint( | ||||
|     _: *wl.Listener(*wlr.PointerConstraintV1), | ||||
|     wlr_constraint: *wlr.PointerConstraintV1, | ||||
|  | ||||
| @ -88,7 +88,7 @@ pressed: Pressed = .{}, | ||||
| key: wl.Listener(*wlr.Keyboard.event.Key) = wl.Listener(*wlr.Keyboard.event.Key).init(handleKey), | ||||
| modifiers: wl.Listener(*wlr.Keyboard) = wl.Listener(*wlr.Keyboard).init(handleModifiers), | ||||
|  | ||||
| pub fn init(keyboard: *Keyboard, seat: *Seat, wlr_device: *wlr.InputDevice) !void { | ||||
| pub fn init(keyboard: *Keyboard, seat: *Seat, wlr_device: *wlr.InputDevice, virtual: bool) !void { | ||||
|     keyboard.* = .{ | ||||
|         .device = undefined, | ||||
|     }; | ||||
| @ -98,12 +98,14 @@ pub fn init(keyboard: *Keyboard, seat: *Seat, wlr_device: *wlr.InputDevice) !voi | ||||
|     const wlr_keyboard = keyboard.device.wlr_device.toKeyboard(); | ||||
|     wlr_keyboard.data = keyboard; | ||||
|  | ||||
|     // wlroots will log a more detailed error if this fails. | ||||
|     if (!wlr_keyboard.setKeymap(server.config.keymap)) return error.OutOfMemory; | ||||
|     if (!virtual) { | ||||
|         // wlroots will log a more detailed error if this fails. | ||||
|         if (!wlr_keyboard.setKeymap(server.config.keymap)) return error.OutOfMemory; | ||||
|  | ||||
|     if (wlr.KeyboardGroup.fromKeyboard(wlr_keyboard) == null) { | ||||
|         // wlroots will log an error on failure | ||||
|         _ = seat.keyboard_group.addKeyboard(wlr_keyboard); | ||||
|         if (wlr.KeyboardGroup.fromKeyboard(wlr_keyboard) == null) { | ||||
|             // wlroots will log an error on failure | ||||
|             _ = seat.keyboard_group.addKeyboard(wlr_keyboard); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     wlr_keyboard.setRepeatInfo(server.config.repeat_rate, server.config.repeat_delay); | ||||
|  | ||||
| @ -127,7 +127,7 @@ pub fn init(seat: *Seat, name: [*:0]const u8) !void { | ||||
|     try seat.cursor.init(seat); | ||||
|     seat.relay.init(); | ||||
|  | ||||
|     try seat.tryAddDevice(&seat.keyboard_group.keyboard.base); | ||||
|     try seat.tryAddDevice(&seat.keyboard_group.keyboard.base, false); | ||||
|  | ||||
|     seat.wlr_seat.events.request_set_selection.add(&seat.request_set_selection); | ||||
|     seat.wlr_seat.events.request_start_drag.add(&seat.request_start_drag); | ||||
| @ -484,19 +484,19 @@ fn handleMappingRepeatTimeout(seat: *Seat) c_int { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| pub fn addDevice(seat: *Seat, wlr_device: *wlr.InputDevice) void { | ||||
|     seat.tryAddDevice(wlr_device) catch |err| switch (err) { | ||||
| pub fn addDevice(seat: *Seat, wlr_device: *wlr.InputDevice, virtual: bool) void { | ||||
|     seat.tryAddDevice(wlr_device, virtual) catch |err| switch (err) { | ||||
|         error.OutOfMemory => log.err("out of memory", .{}), | ||||
|     }; | ||||
| } | ||||
|  | ||||
| fn tryAddDevice(seat: *Seat, wlr_device: *wlr.InputDevice) !void { | ||||
| fn tryAddDevice(seat: *Seat, wlr_device: *wlr.InputDevice, virtual: bool) !void { | ||||
|     switch (wlr_device.type) { | ||||
|         .keyboard => { | ||||
|             const keyboard = try util.gpa.create(Keyboard); | ||||
|             errdefer util.gpa.destroy(keyboard); | ||||
|  | ||||
|             try keyboard.init(seat, wlr_device); | ||||
|             try keyboard.init(seat, wlr_device, virtual); | ||||
|  | ||||
|             seat.wlr_seat.setKeyboard(keyboard.device.wlr_device.toKeyboard()); | ||||
|             if (seat.wlr_seat.keyboard_state.focused_surface) |wlr_surface| { | ||||
|  | ||||
| @ -85,6 +85,8 @@ screencopy_manager: *wlr.ScreencopyManagerV1, | ||||
|  | ||||
| foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1, | ||||
|  | ||||
| foreign_toplevel_list: *wlr.ExtForeignToplevelListV1, | ||||
|  | ||||
| tearing_control_manager: *wlr.TearingControlManagerV1, | ||||
|  | ||||
| alpha_modifier: *wlr.AlphaModifierV1, | ||||
| @ -164,6 +166,8 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void { | ||||
|  | ||||
|         .foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server), | ||||
|  | ||||
|         .foreign_toplevel_list = try wlr.ExtForeignToplevelListV1.create(wl_server, 1), | ||||
|  | ||||
|         .tearing_control_manager = try wlr.TearingControlManagerV1.create(wl_server, 1), | ||||
|  | ||||
|         .alpha_modifier = try wlr.AlphaModifierV1.create(wl_server), | ||||
| @ -344,6 +348,7 @@ fn blocklist(server: *Server, global: *const wl.Global) bool { | ||||
|     return global == server.security_context_manager.global or | ||||
|         global == server.layer_shell.global or | ||||
|         global == server.foreign_toplevel_manager.global or | ||||
|         global == server.foreign_toplevel_list.global or | ||||
|         global == server.screencopy_manager.global or | ||||
|         global == server.export_dmabuf_manager.global or | ||||
|         global == server.data_control_manager.global or | ||||
|  | ||||
| @ -181,6 +181,8 @@ post_fullscreen_box: wlr.Box = undefined, | ||||
|  | ||||
| foreign_toplevel_handle: ForeignToplevelHandle = .{}, | ||||
|  | ||||
| ext_foreign_toplevel_handle: ?*wlr.ExtForeignToplevelHandleV1 = null, | ||||
|  | ||||
| /// Connector name of the output this view occupied before an evacuation. | ||||
| output_before_evac: ?[]const u8 = null, | ||||
|  | ||||
| @ -656,6 +658,15 @@ pub fn map(view: *View) !void { | ||||
|     assert(!view.mapped and !view.destroying); | ||||
|     view.mapped = true; | ||||
|  | ||||
|     if (wlr.ExtForeignToplevelHandleV1.create(server.foreign_toplevel_list, &.{ | ||||
|         .title = view.getTitle(), | ||||
|         .app_id = view.getAppId(), | ||||
|     })) |handle| { | ||||
|         view.ext_foreign_toplevel_handle = handle; | ||||
|     } else |_| { | ||||
|         log.err("failed to create ext foreign toplevel handle", .{}); | ||||
|     } | ||||
|  | ||||
|     view.foreign_toplevel_handle.map(); | ||||
|  | ||||
|     if (server.config.rules.float.match(view)) |float| { | ||||
| @ -755,6 +766,10 @@ pub fn unmap(view: *View) void { | ||||
|     assert(view.mapped and !view.destroying); | ||||
|     view.mapped = false; | ||||
|  | ||||
|     if (view.ext_foreign_toplevel_handle) |handle| { | ||||
|         handle.destroy(); | ||||
|         view.ext_foreign_toplevel_handle = null; | ||||
|     } | ||||
|     view.foreign_toplevel_handle.unmap(); | ||||
|  | ||||
|     server.root.applyPending(); | ||||
| @ -765,6 +780,12 @@ pub fn notifyState(view: *const View) void { | ||||
|         if (view.getTitle()) |title| wlr_handle.setTitle(title); | ||||
|     } | ||||
|     // Send title and tags to all status listeners attached to a seat which focuses this view | ||||
|     if (view.ext_foreign_toplevel_handle) |handle| { | ||||
|         handle.updateState(&.{ | ||||
|             .title = view.getTitle(), | ||||
|             .app_id = view.getAppId(), | ||||
|         }); | ||||
|     } | ||||
|     var seat_it = server.input_manager.seats.first; | ||||
|     while (seat_it) |seat_node| : (seat_it = seat_node.next) { | ||||
|         if (seat_node.data.focused == .view and seat_node.data.focused.view == view) { | ||||
| @ -780,4 +801,11 @@ pub fn notifyAppId(view: View) void { | ||||
|     if (view.foreign_toplevel_handle.wlr_handle) |wlr_handle| { | ||||
|         if (view.getAppId()) |app_id| wlr_handle.setAppId(app_id); | ||||
|     } | ||||
|  | ||||
|     if (view.ext_foreign_toplevel_handle) |handle| { | ||||
|         handle.updateState(&.{ | ||||
|             .title = view.getTitle(), | ||||
|             .app_id = view.getAppId(), | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user