Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

Commit

Permalink
feat: working on inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
RossComputerGuy committed Jun 7, 2024
1 parent 392f131 commit b8007c2
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 4 deletions.
22 changes: 20 additions & 2 deletions lib/logic/display.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:collection';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -259,14 +260,31 @@ class DisplayServerSurface extends ChangeNotifier {
int get monitor => _monitor;

Future<void> close() => sendRequest('close');
Future<void> enter() => sendRequest('enter');

Future<void> enter(Offset position) => sendRequest('enter', {
'position': {
'x': position.dx,
'y': position.dy,
},
});

Future<void> leave() => sendRequest('leave');

Future<void> sendRequest(String name) async {
Future<void> key(List<String> state, int logicalKey, int physicalKey, Duration timestamp) => sendRequest('key', {
'state': state,
'logicalKey': logicalKey,
'physicalKey': physicalKey,
'timestamp': timestamp.inMilliseconds,
});

Future<void> sendRequest(String name, [
Map<String, dynamic> data = const {},
]) async {
await DisplayManager.channel.invokeMethod('requestSurface', <String, dynamic>{
'name': _server.name,
'id': id,
'reqName': name,
...data,
});
}

Expand Down
53 changes: 51 additions & 2 deletions lib/widgets/surface.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:libtokyo_flutter/libtokyo.dart' hide ColorScheme;
import 'package:libtokyo/libtokyo.dart' hide TokyoApp;
import 'package:provider/provider.dart';
Expand Down Expand Up @@ -106,6 +110,7 @@ class SurfaceView extends StatefulWidget {

class _SurfaceViewState extends State<SurfaceView> {
GlobalKey key = GlobalKey();
FocusNode _node = FocusNode();

void _sendSize() {
if (key.currentContext != null && widget.surface.texture != null && widget.isSizable) {
Expand All @@ -123,6 +128,12 @@ class _SurfaceViewState extends State<SurfaceView> {
});
}

@override
void dispose() {
super.dispose();
_node.dispose();
}

@override
Widget _buildContent(BuildContext context, DisplayServerSurface surface) {
Widget content = surface.texture == null
Expand All @@ -135,11 +146,49 @@ class _SurfaceViewState extends State<SurfaceView> {
onFocusChange: (isFocused) {
surface.setActive(isFocused);
surface.setSuspended(!isFocused);

if (isFocused) _node.requestFocus();
else _node.unfocus();
},
child: MouseRegion(
onEnter: (_) => surface.enter(),
onEnter: (ev) => surface.enter(ev.localPosition),
onExit: (_) => surface.leave(),
child: content,
child: KeyboardListener(
focusNode: _node,
onKeyEvent: (ev) {
List<String> state = [];

if (ev is KeyUpEvent) state.add('up');
if (ev is KeyDownEvent) state.add('down');
if (ev is KeyRepeatEvent) state.add('repeat');

final kPlatformToLogicalKey = kIsWeb ? kWebToLogicalKey : switch (Platform.operatingSystem) {
"android" => kAndroidToLogicalKey,
"fuchsia" => kFuchsiaToLogicalKey,
"ios" => kIosToLogicalKey,
"linux" => kGtkToLogicalKey,
"macos" => kMacOsToLogicalKey,
"windows" => kWindowsToLogicalKey,
(_) => const {},
};

final kPlatformToPhysicalKey = kIsWeb ? kWebToPhysicalKey : switch (Platform.operatingSystem) {
"android" => kAndroidToPhysicalKey,
"fuchsia" => kFuchsiaToPhysicalKey,
"ios" => kIosToPhysicalKey,
"linux" => kLinuxToPhysicalKey,
"macos" => kMacOsToPhysicalKey,
"windows" => kWindowsToPhysicalKey,
(_) => const {},
};

final logicalKey = kPlatformToLogicalKey.map((key, value) => MapEntry(value, key))[ev.logicalKey];
final physicalKey = kPlatformToPhysicalKey.map((key, value) => MapEntry(value, key))[ev.physicalKey];

surface.key(state, logicalKey ?? 0, physicalKey ?? 0, ev.timeStamp);
},
child: content,
),
),
);
}
Expand Down
1 change: 1 addition & 0 deletions linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ add_executable(${BINARY_NAME}
"channels/auth.cc"
"channels/display/backend/dummy.c"
"channels/display/backend/wayland.c"
"channels/display/input/keyboard.c"
"channels/display/backend.c"
"channels/display/pixel-format.c"
"channels/display/texture.c"
Expand Down
40 changes: 40 additions & 0 deletions linux/channels/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ static void method_call_handler(FlMethodChannel* channel, FlMethodCall* method_c

disp->seat = wlr_seat_create(wl_display, session_name);
wlr_seat_set_capabilities(disp->seat, WL_SEAT_CAPABILITY_POINTER | WL_SEAT_CAPABILITY_KEYBOARD | WL_SEAT_CAPABILITY_TOUCH);

keyboard_init(&disp->keyboard);
wlr_seat_set_keyboard(disp->seat, &disp->keyboard);

disp->xdg_shell = wlr_xdg_shell_create(wl_display, 6);

disp->xdg_decor = wlr_xdg_decoration_manager_v1_create(wl_display);
Expand Down Expand Up @@ -355,12 +359,17 @@ static void method_call_handler(FlMethodChannel* channel, FlMethodCall* method_c
wlr_xdg_toplevel_send_close(surface->xdg);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(NULL));
} else if (strcmp(req_name, "enter") == 0) {
FlValue* pos = fl_value_lookup_string(args, "position");
double sx = fl_value_get_float(fl_value_lookup_string(pos, "x"));
double sy = fl_value_get_float(fl_value_lookup_string(pos, "y"));

struct wlr_output* output = g_list_nth_data(disp->outputs, surface->monitor);
if (output == NULL) {
fl_method_call_respond_error(method_call, "Linux", "Output does not exist", fl_value_new_int(surface->monitor), NULL);
return;
}

wlr_seat_pointer_notify_enter(disp->seat, surface->xdg->base->surface, sx, sy);
wlr_surface_send_enter(surface->xdg->base->surface, output);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(NULL));
} else if (strcmp(req_name, "leave") == 0) {
Expand All @@ -371,6 +380,37 @@ static void method_call_handler(FlMethodChannel* channel, FlMethodCall* method_c
}

wlr_surface_send_leave(surface->xdg->base->surface, output);
wlr_seat_pointer_notify_clear_focus(disp->seat);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(NULL));
} else if (strcmp(req_name, "key") == 0) {
FlValue* state = fl_value_lookup_string(args, "state");
int physical = fl_value_get_int(fl_value_lookup_string(args, "physicalKey"));
int logical = fl_value_get_int(fl_value_lookup_string(args, "logicalKey"));
int timestamp = fl_value_get_int(fl_value_lookup_string(args, "timestamp"));

uint32_t state_value = 0;

for (size_t i = 0; i < fl_value_get_length(state); i++) {
const char* state_item = fl_value_get_string(fl_value_get_list_value(state, i));
if (strcmp(state_item, "up") == 0) {
state_value |= WL_KEYBOARD_KEY_STATE_RELEASED;
} else if (strcmp(state_item, "down") == 0) {
state_value |= WL_KEYBOARD_KEY_STATE_PRESSED;
} else {
break;
}
}

if (state_value > 0) {
if (disp->seat->keyboard_state.focused_surface != surface->xdg->base->surface) {
wlr_seat_keyboard_enter(disp->seat, surface->xdg->base->surface, NULL, 0, NULL);
}

wlr_seat_keyboard_send_key(disp->seat, timestamp, logical, state_value);

g_message("%s %d %d %d", fl_value_to_string(state), physical, logical, timestamp);
}

response = FL_METHOD_RESPONSE(fl_method_success_response_new(NULL));
} else {
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
Expand Down
2 changes: 2 additions & 0 deletions linux/channels/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern "C" {
#include <wayland-client.h>

#include "display/backend.h"
#include "display/input/keyboard.h"

#ifdef __cplusplus
#undef static
Expand All @@ -40,6 +41,7 @@ typedef struct _DisplayChannelDisplay {
struct wlr_seat* seat;
struct wlr_xdg_shell* xdg_shell;
struct wlr_xdg_decoration_manager_v1* xdg_decor;
struct wlr_keyboard keyboard;

const gchar* prev_wl_disp;
const char* socket;
Expand Down
10 changes: 10 additions & 0 deletions linux/channels/display/input/keyboard.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "keyboard.h"
#include <wlr/interfaces/wlr_keyboard.h>

static const struct wlr_keyboard_impl keyboard_impl = {
.name = "keyboard",
};

void keyboard_init(struct wlr_keyboard* keyboard) {
wlr_keyboard_init(keyboard, &keyboard_impl, "keyboard");
}
5 changes: 5 additions & 0 deletions linux/channels/display/input/keyboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <wlr/types/wlr_keyboard.h>

void keyboard_init(struct wlr_keyboard* keyboard);

0 comments on commit b8007c2

Please sign in to comment.