From ee60060dc69b177c052b6cb12bddcd69197cc84f Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Wed, 22 Nov 2023 11:37:04 +0100 Subject: [PATCH] Moved UI from C to Vala Multiple changes coming with that Massive cleanup --- Makefile | 25 ++- README.md | 7 + drivers/g-wolves/g-wolves.c | 71 ++++---- src/device/device.c | 54 +++++- src/device/device.h | 4 +- src/device/driver_interface.h | 46 +++-- src/main.c | 3 +- src/ui/Device.vapi | 65 +++++++ src/ui/GinputApplication.vala | 11 ++ src/ui/MainWindow.vala | 80 +++++++++ src/ui/Panel.vala | 38 ++++ src/ui/ginput-application.c | 87 ---------- src/ui/ginput-application.h | 11 -- src/ui/main-window.c | 315 ---------------------------------- src/ui/main-window.h | 14 -- src/ui/panel.c | 206 ---------------------- src/ui/panel.h | 44 ----- src/ui/panels/EmptyPanel.vala | 8 + src/ui/panels/MousePanel.vala | 122 +++++++++++++ src/ui/panels/empty-panel.c | 28 --- src/ui/panels/empty-panel.h | 11 -- src/ui/panels/mouse-panel.c | 156 ----------------- src/ui/panels/mouse-panel.h | 15 -- ui/main-window.ui | 111 ++++++------ 24 files changed, 519 insertions(+), 1013 deletions(-) create mode 100644 src/ui/Device.vapi create mode 100644 src/ui/GinputApplication.vala create mode 100644 src/ui/MainWindow.vala create mode 100644 src/ui/Panel.vala delete mode 100644 src/ui/ginput-application.c delete mode 100644 src/ui/ginput-application.h delete mode 100644 src/ui/main-window.c delete mode 100644 src/ui/main-window.h delete mode 100644 src/ui/panel.c delete mode 100644 src/ui/panel.h create mode 100644 src/ui/panels/EmptyPanel.vala create mode 100644 src/ui/panels/MousePanel.vala delete mode 100644 src/ui/panels/empty-panel.c delete mode 100644 src/ui/panels/empty-panel.h delete mode 100644 src/ui/panels/mouse-panel.c delete mode 100644 src/ui/panels/mouse-panel.h diff --git a/Makefile b/Makefile index e094dae..cac24bf 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,39 @@ NAME=ginput -CC=gcc -CFLAGS=$(shell pkg-config --cflags gtk4 libadwaita-1 libusb-1.0) -O3 -Wall -I src -LDFLAGS=$(shell pkg-config --libs gtk4 libadwaita-1 libusb-1.0) BUILD_DIR=build +CC=gcc +VALAC=valac +VALA_FLAGS=--pkg libadwaita-1 --gresources ui/ginput.gresource.xml +CFLAGS=$(shell pkg-config --cflags gtk4 libadwaita-1 libusb-1.0 glib-2.0) -O3 -Wall -I src -I $(BUILD_DIR)/vala +LDFLAGS=$(shell pkg-config --libs gtk4 libadwaita-1 libusb-1.0 glib-2.0) -lm + UI := $(shell find ui/ -name '*.ui') C_FILES := $(shell find src/ -name '*.c') +VALA_FILES := $(shell find src/ -name '*.vala') +VAPI_FILES := $(shell find src/ -name '*.vapi') +VALA_OBJECTS := $(VALA_FILES) +VALA_OBJECTS := $(patsubst %.vala,%.c,$(VALA_OBJECTS)) +VALA_OBJECTS := $(VALA_OBJECTS:%=$(BUILD_DIR)/vala/%) all: resources $(BUILD_DIR)/$(NAME) $(BUILD_DIR)/drivers # Top-level targets resources: $(BUILD_DIR)/glib-2.0/schemas/gschemas.compiled -$(BUILD_DIR)/$(NAME): $(BUILD_DIR)/resource.c $(C_FILES) | $(BUILD_DIR) +$(VALA_OBJECTS): $(VALA_FILES) $(VAPI_FILES) | $(BUILD_DIR)/vala + rm -rf $(BUILD_DIR)/vala + $(VALAC) -d $(BUILD_DIR)/vala $(VALA_FLAGS) --header=$(BUILD_DIR)/vala/vala.h -C $^ $(VALA_PKG) + +$(BUILD_DIR)/$(NAME): $(BUILD_DIR)/resource.c $(C_FILES) $(VALA_OBJECTS) | $(BUILD_DIR) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) # Build directory $(BUILD_DIR): mkdir -p $(BUILD_DIR) +$(BUILD_DIR)/vala: | $(BUILD_DIR) + mkdir -p $(BUILD_DIR)/vala + # Resources $(BUILD_DIR)/resource.c: ui/ginput.gresource.xml ui/style.css $(UI) cp ui/style.css $(BUILD_DIR)/ @@ -44,7 +59,7 @@ clean: run: all XDG_DATA_DIRS=./$(BUILD_DIR) ./$(BUILD_DIR)/$(NAME) -$(BUILD_DIR)/$(NAME).dbg: $(BUILD_DIR)/resource.c $(C_FILES) | $(BUILD_DIR) +$(BUILD_DIR)/$(NAME).dbg: $(BUILD_DIR)/resource.c $(C_FILES) $(VALA_OBJECTS) | $(BUILD_DIR) $(CC) $(CFLAGS) -g -o $@ $^ $(LDFLAGS) debug: $(BUILD_DIR)/$(NAME).dbg $(BUILD_DIR)/drivers resources diff --git a/README.md b/README.md index 10363b6..702b3a9 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,13 @@ struct MOUSE_DPI_LEVELS int driver_mouse_dpi_get(void* handle, struct MOUSE_DPI_LEVELS* output); int driver_mouse_motion_sync_get(void* handle, bool* output); int driver_mouse_angle_snap_get(void* handle, bool* output); +struct MOUSE_POLLING_RATES +{ + unsigned int polling_rate_count; + unsigned int polling_rate_current; + unsigned int polling_rate_values[]; +}; +int driver_mouse_polling_rate_get(void* handle, struct MOUSE_POLLING_RATES* output); /* * Wireless driver diff --git a/drivers/g-wolves/g-wolves.c b/drivers/g-wolves/g-wolves.c index fcfe121..51ec8a4 100644 --- a/drivers/g-wolves/g-wolves.c +++ b/drivers/g-wolves/g-wolves.c @@ -168,16 +168,8 @@ static bool is_connection_wireless(void* handle) return false; } -int driver_mouse_dpi_get(void* handle, struct MOUSE_DPI_LEVELS* output) +int driver_mouse_dpi_get(void* handle, libusb_device_handle* hand, struct MOUSE* output) { - libusb_device* dev = handle; - - // Prepare usb device for transfer - libusb_device_handle* hand; - int openres = libusb_open(dev, &hand); - if(openres) return -1; - libusb_detach_kernel_driver(hand, 0x2); - // Send command struct REPORT_DPI_SETTINGS report = {0}; int res = send_command(hand, COMMAND_DPI_SETTINGS, REPORT_DPI_SETTINGS_SIZE, &report, DEVICE_WIRELESS(handle)); @@ -191,28 +183,18 @@ int driver_mouse_dpi_get(void* handle, struct MOUSE_DPI_LEVELS* output) output->xy_available = false; for(size_t i = 0; i < report.level_count; i++) { - output->level[i].dpi_x = report.levels[i].dpi_x_high << 8 | report.levels[i].dpi_x_low; - output->level[i].dpi_y = report.levels[i].dpi_y_high << 8 | report.levels[i].dpi_y_low; - output->level[i].r = report.levels[i].led_r; - output->level[i].g = report.levels[i].led_g; - output->level[i].b = report.levels[i].led_b; + output->dpi_x[i] = report.levels[i].dpi_x_high << 8 | report.levels[i].dpi_x_low; + output->dpi_y[i] = report.levels[i].dpi_y_high << 8 | report.levels[i].dpi_y_low; + output->r[i] = report.levels[i].led_r; + output->g[i] = report.levels[i].led_g; + output->b[i] = report.levels[i].led_b; } - libusb_attach_kernel_driver(hand, 0x2); - libusb_close(hand); return 0; } -int driver_mouse_motion_sync_get(void* handle, bool* output) +int driver_mouse_motion_sync_get(void* handle, libusb_device_handle* hand, bool* output) { - libusb_device* dev = handle; - - // Prepare usb device for transfer - libusb_device_handle* hand; - int openres = libusb_open(dev, &hand); - if(openres) return -1; - libusb_detach_kernel_driver(hand, 0x2); - // Send command struct REPORT_MOTION_SYNC report = {0}; int res = send_command(hand, COMMAND_MOTION_SYNC, REPORT_MOTION_SYNC_SIZE, &report, DEVICE_WIRELESS(handle)); @@ -220,23 +202,11 @@ int driver_mouse_motion_sync_get(void* handle, bool* output) // Format output boolean *output = report.motion_sync; - - // Close and return - libusb_attach_kernel_driver(hand, 0x2); - libusb_close(hand); return 0; } -int driver_mouse_angle_snap_get(void* handle, bool* output) +int driver_mouse_angle_snap_get(void* handle, libusb_device_handle* hand, bool* output) { - libusb_device* dev = handle; - - // Prepare usb device for transfer - libusb_device_handle* hand; - int openres = libusb_open(dev, &hand); - if(openres) return -1; - libusb_detach_kernel_driver(hand, 0x2); - // Send command struct REPORT_ANGLE_SNAP report = {0}; int res = send_command(hand, COMMAND_ANGLE_SNAP, REPORT_ANGLE_SNAP_SIZE, &report, DEVICE_WIRELESS(handle)); @@ -244,8 +214,29 @@ int driver_mouse_angle_snap_get(void* handle, bool* output) // Format output boolean *output = report.angle_snap; - - // Close and return + return 0; +} + +int driver_mouse_polling_rate_get(void* handle, libusb_device_handle* hand, struct MOUSE* output) +{ + output->polling_rate_count = 0; + return 0; +} + +int driver_mouse_get(void* handle, struct MOUSE* output) +{ + // Prepare usb device for transfer + libusb_device_handle* hand; + int openres = libusb_open((libusb_device*) handle, &hand); + if(openres) return -1; + libusb_detach_kernel_driver(hand, 0x2); + + // TODO : handle errors + driver_mouse_dpi_get(handle, hand, output); + driver_mouse_polling_rate_get(handle, hand, output); + driver_mouse_motion_sync_get(handle, hand, output); + driver_mouse_angle_snap_get(handle, hand, output); + libusb_attach_kernel_driver(hand, 0x2); libusb_close(hand); return 0; diff --git a/src/device/device.c b/src/device/device.c index eb956c1..65b597a 100644 --- a/src/device/device.c +++ b/src/device/device.c @@ -3,6 +3,7 @@ #include "usb/usb.h" #include #include +#include struct DEVICE { @@ -40,6 +41,14 @@ device_t* device_register(void* driver, void* handle) char* device_get_image(device_t* device) { char* (*getimage_fn)(void*) = dlsym(device->driver, "driver_get_image"); + if(!getimage_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_get_image`\n"); + char* tr = malloc(1); + *tr = 0; + return tr; + } + char* image = getimage_fn(device->handle); size_t image_len = strlen(image); @@ -58,21 +67,58 @@ char* device_get_image(device_t* device) char* device_get_name(device_t* device) { char* (*getname_fn)(void*) = dlsym(device->driver, "driver_get_name"); + if(!getname_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_get_name`\n"); + return ""; + } + return getname_fn(device->handle); } device_capacity_t device_get_capacity(device_t* device) { device_capacity_t (*getcapacity_fn)(void*) = dlsym(device->driver, "driver_get_capacity"); + if(!getcapacity_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_get_capacity`\n"); + return 0; + } + return getcapacity_fn(device->handle); } -void* device_handle(device_t* device) +char* device_get_manufacturer(device_t* device) +{ + char* (*getmanufacturer_fn)(void*) = dlsym(device->driver, "driver_get_manufacturer"); + if(!getmanufacturer_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_get_manufacturer`\n"); + return ""; + } + return getmanufacturer_fn(device->handle); +} + +int device_mouse_get(device_t* device, struct MOUSE* output) { - return device->handle; + int (*mouseget_fn)(void*, struct MOUSE*) = dlsym(device->driver, "driver_mouse_get"); + if(!mouseget_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_mouse_get`\n"); + return -1; + } + + return mouseget_fn(device->handle, output); } -void* device_driver(device_t* device) +int device_wireless_get(device_t* device, struct WIRELESS* output) { - return device->driver; + int (*wirelessget_fn)(void*, struct WIRELESS*) = dlsym(device->driver, "driver_wireless_get"); + if(!wirelessget_fn) + { + fprintf(stderr, "Warning: driver does not implement `driver_wireless_get`\n"); + return -1; + } + + return wirelessget_fn(device->handle, output); } diff --git a/src/device/device.h b/src/device/device.h index fe1fd72..630c355 100644 --- a/src/device/device.h +++ b/src/device/device.h @@ -15,11 +15,11 @@ void device_init(); array_t* device_get_array(); // Handling a single device -void* device_handle(device_t* device); -void* device_driver(device_t* device); device_t* device_register(void* driver, void* handle); char* device_get_image(device_t* device); char* device_get_name(device_t* device); device_capacity_t device_get_capacity(device_t* device); +char* device_get_manufacturer(device_t* device); +int device_mouse_get(device_t* device, struct MOUSE* output); #endif \ No newline at end of file diff --git a/src/device/driver_interface.h b/src/device/driver_interface.h index f3edc06..21573cb 100644 --- a/src/device/driver_interface.h +++ b/src/device/driver_interface.h @@ -6,8 +6,9 @@ typedef enum DEVICE_CAPACITY { - DEVICE_CAPACITY_MOUSE, - DEVICE_CAPACITY_WIRELESS, + DEVICE_CAPACITY_MOUSE = (1 << 0), + DEVICE_CAPACITY_KEYBOARD = (1 << 1), + DEVICE_CAPACITY_WIRELESS = (1 << 10), } device_capacity_t; void driver_init(); // Initialization @@ -19,30 +20,39 @@ char* driver_get_manufacturer(void* handle); // Returns peripheral manufacturer char* driver_get_image(void* handle); // Returns peripheral image /* Mouse drivers */ -#define MAX_DPI_LEVELS 10 -struct MOUSE_DPI_LEVELS +struct MOUSE { + // DPI unsigned int max_level_count; unsigned int level_count; unsigned int level_current; bool led_available; bool xy_available; - struct MOUSE_DPI_LEVEL - { - unsigned int dpi_x; - unsigned int dpi_y; - unsigned char r; - unsigned char g; - unsigned char b; - } level[MAX_DPI_LEVELS]; + unsigned int dpi_x[8]; + unsigned int dpi_y[8]; + unsigned char r[8]; + unsigned char g[8]; + unsigned char b[8]; + + // Polling rate + unsigned int polling_rate_count; + unsigned int polling_rate_current; + unsigned int polling_rates[8]; + + // Features + bool angle_snap; + bool motion_sync; }; -int driver_mouse_dpi_get(void* handle, struct MOUSE_DPI_LEVELS* output); - -int driver_mouse_motion_sync_get(void* handle, bool* output); -int driver_mouse_angle_snap_get(void* handle, bool* output); +int driver_mouse_get(void* handle, struct MOUSE* output); +int driver_mouse_set(void* handle, struct MOUSE* input); /* Wireless drivers */ -int driver_wireless_battery_state_get(void* handle, int* battery_level, bool* charging); -int driver_wireless_connection_type_get(void* handle, bool* output); +struct WIRELESS +{ + int battery_level; + bool charging; + bool connection_wireless; +}; +int driver_wireless_get(void* handle, struct WIRELESS* output); #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 469ced2..5cd6991 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ -#include "ui/ginput-application.h" +#include +#include "vala.h" #include "device/device.h" int main(gint argc, gchar** argv) diff --git a/src/ui/Device.vapi b/src/ui/Device.vapi new file mode 100644 index 0000000..2733a10 --- /dev/null +++ b/src/ui/Device.vapi @@ -0,0 +1,65 @@ +[CCode (cheader_filename = "utils/array.h")] +namespace Array +{ + void* get(void* array, size_t index); + size_t count(void* array); +} + +[CCode (cheader_filename = "device/device.h")] +namespace Device +{ + // Obtain device array + void* get_array(); + + [CCode (cname = "device_capacity_t", cprefix = "DEVICE_CAPACITY_", has_type_id = false)] + public enum Capacity + { + MOUSE = (1 << 0), + KEYBOARD = (1 << 1), + WIRELESS = (1 << 10) + } + + // Handle a specific device + unowned string get_name(void* device); + string get_image(void* device); + int get_capacity(void* device); + unowned string get_manufacturer(void* device); + + [CCode (cname = "struct MOUSE", free_function = "", has_type_id = false)] + public struct Mouse + { + // DPI + uint max_level_count; + uint level_count; + uint level_current; + bool led_available; + bool xy_available; + uint dpi_x[8]; + uchar r[8]; + uchar g[8]; + uchar b[8]; + + // Polling rate + uint polling_rate_count; + uint polling_rate_current; + uint polling_rates[8]; + + // Features + bool angle_snap; + bool motion_sync; + } + + public int mouse_get(void* device, Mouse* output); + public int mouse_set(void* device, Mouse* input); + + [CCode (cname = "struct WIRELESS", free_function = "", has_type_id = false)] + public struct Wireless + { + int battery_level; + bool charging; + bool connection_wireless; + } + + public int wireless_get(void* device, Wireless* output); + public int wireless_set(void* device, Wireless* input); +} diff --git a/src/ui/GinputApplication.vala b/src/ui/GinputApplication.vala new file mode 100644 index 0000000..b4099e1 --- /dev/null +++ b/src/ui/GinputApplication.vala @@ -0,0 +1,11 @@ +public class GinputApplication : Adw.Application { + + public GinputApplication() { + Object(application_id: "v.ginput", flags:ApplicationFlags.DEFAULT_FLAGS); + } + + public override void activate() { + var win = new MainWindow(this); + win.present(); + } +} diff --git a/src/ui/MainWindow.vala b/src/ui/MainWindow.vala new file mode 100644 index 0000000..cb57985 --- /dev/null +++ b/src/ui/MainWindow.vala @@ -0,0 +1,80 @@ +using Device; + +[GtkTemplate (ui="/v/ginput/main-window.ui")] +public class MainWindow : Adw.ApplicationWindow +{ + [GtkChild] + protected unowned Gtk.ListBox device_list; + [GtkChild] + protected unowned Gtk.Stack stack; + + protected Panel active_panel; + + public MainWindow(Adw.Application app) + { + Object(application:app, resizable:true, title:"Input devices", icon_name:"ginput-icon", show_menubar:false); + } + + construct + { + init_template(); + set_default_size(1024, 768); + device_list.row_selected.connect(select_device); + } + + void activate_panel(Panel panel) + { + var pname = panel.get_name(); + if(stack.get_child_by_name(pname) == null) + stack.add_named(panel, pname); + stack.set_visible_child_name(pname); + active_panel = panel; + } + + void select_device(Gtk.ListBox list, Gtk.ListBoxRow? row) + { + if(row == null) + return; + + void* device = row.get_data("ginput_device"); + var name = Device.get_name(device); + + Panel devpane; + var capacity = Device.get_capacity(device); + if((capacity & Device.Capacity.MOUSE) != 0) + devpane = new MousePanel(name, device); + else + { + stderr.printf("Warning: selected device with unsupported capacity\n"); + return; + } + + activate_panel(devpane); + } + + public void add_device(void* device) + { + Gtk.ListBoxRow row = new Gtk.ListBoxRow(); + Gtk.Label label = new Gtk.Label(Device.get_name(device)); + label.add_css_class("body"); + label.set_margin_top(7); + label.set_margin_bottom(7); + row.set_child(label); + row.set_data("ginput_device", device); + + device_list.append(row); + } + + public override void constructed() + { + // Add all devices to the window + var devices = Device.get_array(); + for(size_t i = 0; i < Array.count(devices); i++) + add_device(Array.get(devices, i)); + + // Activate empty panel by default + activate_panel(new EmptyPanel()); + + base.constructed(); + } +} diff --git a/src/ui/Panel.vala b/src/ui/Panel.vala new file mode 100644 index 0000000..544d209 --- /dev/null +++ b/src/ui/Panel.vala @@ -0,0 +1,38 @@ +[GtkTemplate (ui="/v/ginput/panel.ui")] +public abstract class Panel : Adw.Bin, Gtk.Buildable +{ + [GtkChild] + protected unowned Adw.Bin content_bin; + [GtkChild] + protected unowned Gtk.Box main_box; + [GtkChild] + protected unowned Adw.Bin titlebar_bin; + [GtkChild] + protected unowned Adw.HeaderBar titlebar; + + protected Adw.WindowTitle titlebar_title; + + protected Panel(string name) + { + this.name = name; + + titlebar_title = new Adw.WindowTitle(this.name, ""); + titlebar.set_title_widget(titlebar_title); + } + + construct + { + init_template(); + } + + void add_child(Gtk.Builder builder, Object child, string? type) + { + if(type != null && type == "content") + { + content_bin.set_child(((Gtk.Widget) child)); + return; + } + + base.add_child(builder, child, type); + } +} diff --git a/src/ui/ginput-application.c b/src/ui/ginput-application.c deleted file mode 100644 index d37eba1..0000000 --- a/src/ui/ginput-application.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "ginput-application.h" -#include "ui/main-window.h" - -struct _GinputApplication -{ - AdwApplication parent; - - MainWindow* window; -}; - -G_DEFINE_TYPE(GinputApplication, ginput_application, ADW_TYPE_APPLICATION) - -/* - * Special 'activate' trigger of the application, called when the application is launched - * This shows the main window - */ -static void -ginput_application_activate(GApplication* application) -{ - GinputApplication* self = GINPUT_APPLICATION(application); - gtk_window_present(GTK_WINDOW(self->window)); -} - -static void -ginput_application_startup(GApplication* application) -{ - GinputApplication* self = GINPUT_APPLICATION(application); - - G_APPLICATION_CLASS(ginput_application_parent_class)->startup(application); - - self->window = main_window_new(ADW_APPLICATION(application)); - - GtkCssProvider* provider = gtk_css_provider_new(); - gtk_css_provider_load_from_resource(provider, "/v/ginput/style.css"); - gtk_style_context_add_provider_for_display(gdk_display_get_default(), - GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); -} - -static void -ginput_application_finalize(GObject* object) -{ - G_OBJECT_CLASS(ginput_application_parent_class)->finalize(object); -} - -static GObject* -ginput_application_constructor(GType type, guint n_construct_params, GObjectConstructParam* construct_params) -{ - static GObject* self = NULL; - - if(self == NULL) - { - self = G_OBJECT_CLASS(ginput_application_parent_class)->constructor(type, n_construct_params, construct_params); - g_object_add_weak_pointer(self, (gpointer) &self); - return self; - } - - return g_object_ref(self); -} - -static void -ginput_application_class_init(GinputApplicationClass* klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS(klass); - GApplicationClass* application_class = G_APPLICATION_CLASS(klass); - - object_class->finalize = ginput_application_finalize; - object_class->constructor = ginput_application_constructor; - application_class->activate = ginput_application_activate; - application_class->startup = ginput_application_startup; - // application_class->command_line = ginput_application_command_line; - // application_class->handle_local_options = ginput_application_handle_local_options; -} - -static void -ginput_application_init(GinputApplication* self) -{ -} - -AdwApplication* -ginput_application_new(void) -{ - return g_object_new(ginput_application_get_type(), - "application-id", "v.ginput", - "flags", G_APPLICATION_DEFAULT_FLAGS, - NULL); -} diff --git a/src/ui/ginput-application.h b/src/ui/ginput-application.h deleted file mode 100644 index cd3f98a..0000000 --- a/src/ui/ginput-application.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(GinputApplication, ginput_application, GINPUT, APPLICATION, AdwApplication) - -AdwApplication* ginput_application_new(void); - -G_END_DECLS diff --git a/src/ui/main-window.c b/src/ui/main-window.c deleted file mode 100644 index b494beb..0000000 --- a/src/ui/main-window.c +++ /dev/null @@ -1,315 +0,0 @@ -#define G_LOG_DOMAIN "main-window" - -#include "main-window.h" -#include "panels/empty-panel.h" -#include "panels/mouse-panel.h" -#include "device/device.h" - -#include - -struct _MainWindow -{ - AdwApplicationWindow parent; - - AdwHeaderBar* header; - AdwLeaflet* main_leaflet; - GtkListBox *device_list; - GtkBox* sidebar_box; - AdwWindowTitle* sidebar_title_widget; - GtkStack* stack; - - GtkWidget* current_panel; - char* current_panel_id; - - GtkWidget* custom_titlebar; - - // CcShellModel *store; - - Panel *active_panel; - GSettings* settings; - - gboolean folded; - - // CcPanelListView previous_list_view; -}; - -G_DEFINE_TYPE(MainWindow, main_window, ADW_TYPE_APPLICATION_WINDOW) -enum -{ - PROP_0, - PROP_ACTIVE_PANEL, - PROP_MODEL, - PROP_FOLDED, -}; - -static gboolean activate_panel(MainWindow* self, Panel* panel, const gchar* id) -{ - self->current_panel = GTK_WIDGET(panel); - self->active_panel = panel; - gtk_stack_add_named(self->stack, self->current_panel, id); - gtk_stack_set_visible_child_name (self->stack, id); - return true; -} - -/* - * @Override from GtkWidget - */ -static void -main_window_map(GtkWidget* widget) -{ - // MainWindow* self = (MainWindow*) widget; - GTK_WIDGET_CLASS(main_window_parent_class)->map(widget); -} - -/* - * @Override from GtkWidget - */ -static void -main_window_unmap(GtkWidget* widget) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(widget); - gboolean maximized; - gint height; - gint width; - - maximized = gtk_window_is_maximized(GTK_WINDOW(self)); - gtk_window_get_default_size(GTK_WINDOW(self), &width, &height); - - g_settings_set(self->settings, - "window-state", - "(iib)", - width, - height, - maximized); - - GTK_WIDGET_CLASS(main_window_parent_class)->unmap(widget); -} - -static void -main_window_get_property(GObject* object, guint property_id, GValue* value, GParamSpec* pspec) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(object); - - switch(property_id) - { - case PROP_ACTIVE_PANEL: - g_value_set_object (value, self->active_panel); - break; - - // case PROP_MODEL: - // g_value_set_object (value, self->store); - // break; - - case PROP_FOLDED: - g_value_set_boolean(value, self->folded); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } -} - -static void -main_window_set_property(GObject* object, - guint property_id, - const GValue* value, - GParamSpec* pspec) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(object); - - switch(property_id) - { - // case PROP_ACTIVE_PANEL: - // set_active_panel(self, g_value_get_object(value)); - // break; - - // case PROP_MODEL: - // g_assert(self->store == NULL); - // self->store = g_value_dup_object(value); - // break; - - case PROP_FOLDED: - self->folded = g_value_get_boolean(value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - } -} - -static void -load_window_state(MainWindow* self) -{ - gint current_width = -1; - gint current_height = -1; - gboolean maximized = FALSE; - - g_settings_get(self->settings, - "window-state", - "(iib)", - ¤t_width, - ¤t_height, - &maximized); - - if(current_width != -1 && current_height != -1) - gtk_window_set_default_size(GTK_WINDOW(self), current_width, current_height); - if(maximized) - gtk_window_maximize(GTK_WINDOW(self)); -} - -void main_window_add_all_devices(MainWindow* self) -{ - // Obtain devices, and iterate over the array to add them - array_t* devices = device_get_array(); - for(size_t i = 0; i < array_count(devices); i++) - main_window_add_device_to_list(self, array_get(devices, i)); -} - -void main_window_device_selected(GtkListBox* self, GtkListBoxRow* row, gpointer user_data) -{ - MainWindow* main_window = (MainWindow*) gtk_widget_get_root(GTK_WIDGET(self)); - - // Selection cleared - if(!row) - { - // TODO: set to empty panel ? - return; - } - - device_t* device = (device_t*) g_object_get_data(G_OBJECT(row), "ginput_device"); - MousePanel* mp = (MousePanel*) mouse_panel_new(); - mouse_panel_set_device(mp, device); - - // TODO : change and use already added child if possible - activate_panel(main_window, GINPUT_PANEL(mp), device_get_name(device)); -} - -static void -main_window_constructed(GObject* object) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(object); - - load_window_state(self); - - main_window_add_all_devices(self); - - /* Add the panels */ - // setup_model (self); - - /* After everything is loaded, select the last used panel, if any, - * or the first visible panel. We do that in an idle handler so we - * have a chance to skip it when another panel has been explicitly - * activated from commandline parameter or from DBus method */ - // g_idle_add_once ((GSourceOnceFunc) maybe_load_last_panel, self); - - // g_signal_connect_swapped (self->panel_list, - // "notify::view", - // G_CALLBACK (update_headerbar_buttons), - // self); - - // update_headerbar_buttons (self); - // adw_leaflet_set_visible_child (self->main_leaflet, - // GTK_WIDGET (self->sidebar_box)); - - G_OBJECT_CLASS(main_window_parent_class)->constructed(object); -} - -static void -main_window_dispose(GObject* object) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(object); - - g_clear_pointer(&self->current_panel_id, g_free); - // g_clear_object (&self->store); - // g_clear_object (&self->active_panel); - - G_OBJECT_CLASS(main_window_parent_class)->dispose(object); -} - -static void -main_window_finalize(GObject* object) -{ - MainWindow* self = GINPUT_MAIN_WINDOW(object); - - g_clear_object(&self->settings); - - G_OBJECT_CLASS(main_window_parent_class)->finalize(object); -} - -static void -main_window_class_init(MainWindowClass* klass) -{ - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); - GObjectClass* object_class = G_OBJECT_CLASS(klass); - - object_class->get_property = main_window_get_property; - object_class->set_property = main_window_set_property; - object_class->constructed = main_window_constructed; - object_class->dispose = main_window_dispose; - object_class->finalize = main_window_finalize; - - widget_class->map = main_window_map; - widget_class->unmap = main_window_unmap; - - g_object_class_install_property(object_class, PROP_FOLDED, - g_param_spec_boolean("folded", "Folded", "Whether the window is foled", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gtk_widget_class_set_template_from_resource(widget_class, "/v/ginput/main-window.ui"); - - gtk_widget_class_bind_template_child(widget_class, MainWindow, header); - gtk_widget_class_bind_template_child(widget_class, MainWindow, main_leaflet); - gtk_widget_class_bind_template_child(widget_class, MainWindow, device_list); - gtk_widget_class_bind_template_child(widget_class, MainWindow, sidebar_box); - gtk_widget_class_bind_template_child(widget_class, MainWindow, sidebar_title_widget); - gtk_widget_class_bind_template_child(widget_class, MainWindow, stack); -} - -static void -main_window_init(MainWindow* self) -{ - gtk_widget_init_template(GTK_WIDGET(self)); - - self->settings = g_settings_new("v.ginput"); - - g_object_bind_property(self->main_leaflet, - "folded", - self, - "folded", - G_BINDING_SYNC_CREATE); - - activate_panel(self, empty_panel_new(), "empty"); - - g_signal_connect(self->device_list, "row_selected", G_CALLBACK(main_window_device_selected), NULL); -} - -// TODO use translation -#define _(x) x - -MainWindow* -main_window_new(AdwApplication* application) -{ - g_return_val_if_fail(GTK_IS_APPLICATION(application), NULL); - - return g_object_new(main_window_get_type(), - "application", application, - "resizable", TRUE, - "title", _("Input devices"), - "icon-name", "input-devices", - "show-menubar", FALSE, - NULL); -} - -void main_window_add_device_to_list(MainWindow* self, device_t* device) -{ - // Setup row - GtkListBoxRow* row = (GtkListBoxRow*) gtk_list_box_row_new(); - GtkLabel* label = (GtkLabel*) gtk_label_new(device_get_name(device)); - gtk_widget_add_css_class(GTK_WIDGET(label), "body"); - gtk_widget_set_margin_top(GTK_WIDGET(label), 7); - gtk_widget_set_margin_bottom(GTK_WIDGET(label), 7); - gtk_list_box_row_set_child(row, GTK_WIDGET(label)); - g_object_set_data(G_OBJECT(row), "ginput_device", device); - - // Add row to listbox - gtk_list_box_append(GTK_LIST_BOX(self->device_list), GTK_WIDGET(row)); -} diff --git a/src/ui/main-window.h b/src/ui/main-window.h deleted file mode 100644 index 669b72c..0000000 --- a/src/ui/main-window.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include "device/device.h" - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(MainWindow, main_window, GINPUT, MAIN_WINDOW, AdwApplicationWindow) - -MainWindow* main_window_new(AdwApplication* application); - -void main_window_add_device_to_list(MainWindow* self, device_t* device); - -G_END_DECLS diff --git a/src/ui/panel.c b/src/ui/panel.c deleted file mode 100644 index a72eb5d..0000000 --- a/src/ui/panel.c +++ /dev/null @@ -1,206 +0,0 @@ -#include "panel.h" - -/* - * Abstract class representing a panel - */ - -typedef struct -{ - AdwBin* content_bin; - GtkBox* main_box; - AdwBin* titlebar_bin; - AdwHeaderBar* titlebar; - - GCancellable* cancellable; - gboolean folded; - gchar* title; -} PanelPrivate; - -static void panel_buildable_init(GtkBuildableIface* iface); - -G_DEFINE_ABSTRACT_TYPE_WITH_CODE(Panel, panel, ADW_TYPE_BIN, - G_ADD_PRIVATE(Panel) - G_IMPLEMENT_INTERFACE(GTK_TYPE_BUILDABLE, panel_buildable_init)) - -static GtkBuildableIface* parent_buildable_iface; - -enum -{ - PROP_0, - PROP_PARAMETERS, - PROP_FOLDED, - PROP_TITLE, - N_PROPS -}; - -static GParamSpec* properties[N_PROPS]; - -static void -panel_buildable_add_child(GtkBuildable* buildable, GtkBuilder* builder, GObject* child, const char* type) -{ - PanelPrivate* priv = panel_get_instance_private(GINPUT_PANEL(buildable)); - - if(GTK_IS_WIDGET(child) && !priv->main_box) - { - adw_bin_set_child(ADW_BIN(buildable), GTK_WIDGET(child)); - return; - } - - if(g_strcmp0(type, "content") == 0) - adw_bin_set_child(priv->content_bin, GTK_WIDGET(child)); - else if(g_strcmp0(type, "titlebar-start") == 0) - adw_header_bar_pack_start(priv->titlebar, GTK_WIDGET(child)); - else if(g_strcmp0(type, "titlebar-end") == 0) - adw_header_bar_pack_end(priv->titlebar, GTK_WIDGET(child)); - else if(g_strcmp0(type, "titlebar") == 0) - adw_bin_set_child(priv->titlebar_bin, GTK_WIDGET(child)); - else - parent_buildable_iface->add_child(buildable, builder, child, type); -} - -/* - * @Override from GtkBuildableIface - */ -static void -panel_buildable_init(GtkBuildableIface* iface) -{ - parent_buildable_iface = g_type_interface_peek_parent(iface); - iface->add_child = panel_buildable_add_child; -} - -/* - * @Override from GObject - */ -static void -panel_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) -{ - PanelPrivate* priv = panel_get_instance_private(GINPUT_PANEL(object)); - - switch(prop_id) - { - case PROP_PARAMETERS: - { - g_autoptr(GVariant) v = NULL; - GVariant* parameters; - gsize n_parameters; - - parameters = g_value_get_variant(value); - - if(parameters == NULL) - return; - - n_parameters = g_variant_n_children(parameters); - if(n_parameters == 0) - return; - - g_variant_get_child(parameters, 0, "v", &v); - - if(!g_variant_is_of_type(v, G_VARIANT_TYPE_DICTIONARY)) - g_warning("Wrong type for the first argument GVariant, expected 'a{sv}' but got '%s'", - (gchar*) g_variant_get_type(v)); - else if(g_variant_n_children(v) > 0) - g_warning("Ignoring additional flags"); - - if(n_parameters > 1) - g_warning("Ignoring additional parameters"); - - break; - } - - case PROP_TITLE: - priv->title = g_value_dup_string(value); - break; - - case PROP_FOLDED: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/* - * @Override from GObject - */ -static void -panel_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) -{ - PanelPrivate* priv = panel_get_instance_private(GINPUT_PANEL(object)); - - switch(prop_id) - { - case PROP_FOLDED: - g_value_set_boolean(value, priv->folded); - break; - - case PROP_TITLE: - g_value_set_string(value, priv->title); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/* - * @Override from GObject - */ -static void -panel_finalize(GObject* object) -{ - PanelPrivate* priv = panel_get_instance_private(GINPUT_PANEL(object)); - - g_cancellable_cancel(priv->cancellable); - g_clear_object(&priv->cancellable); - - g_clear_pointer(&priv->title, g_free); - - G_OBJECT_CLASS(panel_parent_class)->finalize(object); -} - -static void -panel_class_init(PanelClass* klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS(klass); - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); - - object_class->get_property = panel_get_property; - object_class->set_property = panel_set_property; - object_class->finalize = panel_finalize; - - // signals[SIDEBAR_ACTIVATED] = g_signal_new ("sidebar-activated", - // G_TYPE_FROM_CLASS (object_class), - // G_SIGNAL_RUN_LAST, - // 0, NULL, NULL, - // g_cclosure_marshal_VOID__VOID, - // G_TYPE_NONE, 0); - - properties[PROP_FOLDED] = g_param_spec_boolean("folded", NULL, NULL, - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - properties[PROP_PARAMETERS] = g_param_spec_variant("parameters", - "Structured parameters", - "Additional parameters passed externally (ie. command line, D-Bus activation)", - G_VARIANT_TYPE("av"), - NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); - - properties[PROP_TITLE] = g_param_spec_string("title", NULL, NULL, NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, N_PROPS, properties); - - gtk_widget_class_set_template_from_resource(widget_class, "/v/ginput/panel.ui"); - - gtk_widget_class_bind_template_child_private(widget_class, Panel, content_bin); - gtk_widget_class_bind_template_child_private(widget_class, Panel, main_box); - gtk_widget_class_bind_template_child_private(widget_class, Panel, titlebar_bin); - gtk_widget_class_bind_template_child_private(widget_class, Panel, titlebar); -} - -static void -panel_init(Panel* panel) -{ - gtk_widget_init_template(GTK_WIDGET(panel)); -} diff --git a/src/ui/panel.h b/src/ui/panel.h deleted file mode 100644 index b29572d..0000000 --- a/src/ui/panel.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include - -G_DECLARE_DERIVABLE_TYPE(Panel, panel, GINPUT, PANEL, AdwBin) - -G_BEGIN_DECLS - -/** - * PanelClass: - * - * The contents of this struct are private and should not be accessed directly. - */ -struct _PanelClass -{ - /*< private >*/ - AdwBinClass parent_class; - - const gchar* (*get_help_uri)(Panel* panel); - - GtkWidget* (*get_sidebar_widget)(Panel* panel); -}; - -GPermission* panel_get_permission(Panel* panel); - -const gchar* panel_get_help_uri(Panel* panel); - -GtkWidget* panel_get_sidebar_widget(Panel* panel); - -GCancellable* panel_get_cancellable(Panel* panel); - -gboolean panel_get_folded(Panel* panel); - -GtkWidget* panel_get_content(Panel* panel); - -void panel_set_content(Panel* panel, GtkWidget* content); - -GtkWidget* panel_get_titlebar(Panel* panel); - -void panel_set_titlebar(Panel* panel, GtkWidget* titlebar); - -void panel_deactivate(Panel* panel); - -G_END_DECLS diff --git a/src/ui/panels/EmptyPanel.vala b/src/ui/panels/EmptyPanel.vala new file mode 100644 index 0000000..0bc9597 --- /dev/null +++ b/src/ui/panels/EmptyPanel.vala @@ -0,0 +1,8 @@ +[GtkTemplate (ui="/v/ginput/panel-empty.ui")] +public class EmptyPanel : Panel +{ + public EmptyPanel() + { + base(""); + } +} diff --git a/src/ui/panels/MousePanel.vala b/src/ui/panels/MousePanel.vala new file mode 100644 index 0000000..180ff71 --- /dev/null +++ b/src/ui/panels/MousePanel.vala @@ -0,0 +1,122 @@ +using Device; + +[GtkTemplate (ui="/v/ginput/panel-mouse.ui")] +public class MousePanel : Panel +{ + // Mouse presentation + [GtkChild] + private unowned Gtk.Image mouse_image; + [GtkChild] + private unowned Gtk.Label mouse_manufacturer; + [GtkChild] + private unowned Gtk.Label mouse_name; + + // Wireless informations + [GtkChild] + private unowned Adw.PreferencesGroup wireless; + [GtkChild] + private unowned Gtk.LevelBar battery_level; + [GtkChild] + private unowned Gtk.Label battery_level_label; + [GtkChild] + private unowned Gtk.Label charging_state; + + // DPI + [GtkChild] + private unowned Adw.PreferencesGroup dpi_preference_group; + [GtkChild] + private unowned Adw.ButtonContent dpi_stage_add_button; + + // Features + [GtkChild] + private unowned Adw.SwitchRow motion_sync_switchrow; + [GtkChild] + private unowned Adw.SwitchRow angle_snap_switchrow; + + // Polling rate + [GtkChild] + private unowned Adw.ComboRow polling_rate_comborow; + + private void* device; + + public MousePanel(string name, void* device) + { + base(name); + this.device = device; + + refresh_device(); + } + + public void refresh_device() + { + // Obtain and fill basic information + mouse_image.set_from_file(Device.get_image(this.device)); + mouse_name.set_label(name); + mouse_manufacturer.set_label(Device.get_manufacturer(this.device)); + + // Obtain mouse information + Mouse mouse = Mouse(); + Device.mouse_get(this.device, &mouse); + + /* Fill information */ + + // DPI stages + string dpi_used_max = "%u/%u".printf(mouse.level_count, mouse.max_level_count); + dpi_stage_add_button.set_label(dpi_used_max); + + // All dpi levels + Gtk.CheckButton? group = null; + for(size_t i = 0; i < mouse.level_count; i++) + { + Adw.ActionRow row = new Adw.ActionRow(); + + // Add radiobutton + if(mouse.level_count > 1) + { + Gtk.CheckButton radio_button = new Gtk.CheckButton(); + if(group == null) group = radio_button; + else radio_button.set_group(group); + + if(mouse.level_current == i) + radio_button.set_active(true); + + row.add_prefix(radio_button); + } + + row.set_title("%u DPI".printf(mouse.dpi_x[i])); + + dpi_preference_group.add(row); + } + + // Features + motion_sync_switchrow.set_active(mouse.motion_sync); + angle_snap_switchrow.set_active(mouse.angle_snap); + + // Polling rate + var model = new Gtk.StringList(null); + for(size_t i = 0; i < mouse.polling_rate_count; i++) + { + model.append("%u Hz".printf(mouse.polling_rates[i])); + } + polling_rate_comborow.set_model(model); + polling_rate_comborow.set_selected(mouse.polling_rate_current); + + // Wireless + if((Device.get_capacity(this.device) & Device.Capacity.WIRELESS) != 0) + { + Wireless wireless = Wireless(); + Device.wireless_get(this.device, &wireless); + + battery_level.set_value(wireless.battery_level); + battery_level_label.set_label("%u %%".printf(wireless.battery_level)); + if(wireless.charging) + charging_state.set_label("Charging"); + else + charging_state.set_label("Not charging"); + } + else + { + wireless.hide(); + } + } +} diff --git a/src/ui/panels/empty-panel.c b/src/ui/panels/empty-panel.c deleted file mode 100644 index b8e8732..0000000 --- a/src/ui/panels/empty-panel.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "empty-panel.h" - -struct _EmptyPanel -{ - Panel parent_instance; -}; - -G_DEFINE_TYPE (EmptyPanel, empty_panel, panel_get_type()) - -static void -empty_panel_class_init(EmptyPanelClass* klass) -{ - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); - - gtk_widget_class_set_template_from_resource(widget_class, "/v/ginput/panel-empty.ui"); -} - -static void -empty_panel_init(EmptyPanel* self) -{ - gtk_widget_init_template(GTK_WIDGET(self)); -} - -Panel* -empty_panel_new(void) -{ - return g_object_new(empty_panel_get_type(), NULL); -} diff --git a/src/ui/panels/empty-panel.h b/src/ui/panels/empty-panel.h deleted file mode 100644 index b32b973..0000000 --- a/src/ui/panels/empty-panel.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "ui/panel.h" - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(EmptyPanel, empty_panel, GINPUT, EMPTY_PANEL, Panel) - -G_END_DECLS - -Panel* empty_panel_new(void); diff --git a/src/ui/panels/mouse-panel.c b/src/ui/panels/mouse-panel.c deleted file mode 100644 index 9d4c401..0000000 --- a/src/ui/panels/mouse-panel.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "mouse-panel.h" - -struct _MousePanel -{ - Panel parent_instance; - - // Mouse presentation - GtkImage* mouse_image; - GtkLabel* mouse_manufacturer; - GtkLabel* mouse_name; - - // Wireless informations - AdwPreferencesGroup* wireless; - GtkLevelBar* battery_level; - GtkLabel* battery_level_label; - GtkLabel* charging_state; - - // DPI - AdwPreferencesGroup* dpi_preference_group; - AdwButtonContent* dpi_stage_add_button; - - // Features - AdwSwitchRow* motion_sync_switchrow; - AdwSwitchRow* angle_snap_switchrow; -}; - -G_DEFINE_TYPE (MousePanel, mouse_panel, panel_get_type()) - -static void -mouse_panel_class_init(MousePanelClass* klass) -{ - GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); - - gtk_widget_class_set_template_from_resource(widget_class, "/v/ginput/panel-mouse.ui"); - - gtk_widget_class_bind_template_child(widget_class, MousePanel, mouse_image); - gtk_widget_class_bind_template_child(widget_class, MousePanel, mouse_manufacturer); - gtk_widget_class_bind_template_child(widget_class, MousePanel, mouse_name); - gtk_widget_class_bind_template_child(widget_class, MousePanel, wireless); - gtk_widget_class_bind_template_child(widget_class, MousePanel, battery_level); - gtk_widget_class_bind_template_child(widget_class, MousePanel, battery_level_label); - gtk_widget_class_bind_template_child(widget_class, MousePanel, charging_state); - gtk_widget_class_bind_template_child(widget_class, MousePanel, dpi_preference_group); - gtk_widget_class_bind_template_child(widget_class, MousePanel, dpi_stage_add_button); - gtk_widget_class_bind_template_child(widget_class, MousePanel, motion_sync_switchrow); - gtk_widget_class_bind_template_child(widget_class, MousePanel, angle_snap_switchrow); -} - -static void -mouse_panel_init(MousePanel* self) -{ - gtk_widget_init_template(GTK_WIDGET(self)); -} - -Panel* -mouse_panel_new(void) -{ - return g_object_new(mouse_panel_get_type(), NULL); -} - -void mouse_panel_set_device(MousePanel* self, device_t* device) -{ - // Set device image - char* image = device_get_image(device); - gtk_image_set_from_file(self->mouse_image, image); - free(image); - - // Set device manufacturer - char* (*getmanufacturer_fn)(void*) = dlsym(device_driver(device), "driver_get_manufacturer"); - gtk_label_set_label(self->mouse_manufacturer, getmanufacturer_fn(device_handle(device))); - - // Set device name - // TODO inner window title - char* device_name = device_get_name(device); - gtk_label_set_label(self->mouse_name, device_name); - - // Set mouse wireless status - if(device_get_capacity(device) & DEVICE_CAPACITY_WIRELESS) - { - int (*driver_wireless_battery_state_get)(void*, int*, bool*) = dlsym(device_driver(device), "driver_wireless_battery_state_get"); - int battery_level; - bool charging; - int battery_res = driver_wireless_battery_state_get(device_handle(device), &battery_level, &charging); - - if(!battery_res) - { - // Set battery level - gtk_level_bar_set_value(self->battery_level, (double) battery_level); - char battery_level_str[10]; - sprintf(battery_level_str, "%u %%", battery_level); - gtk_label_set_label(self->battery_level_label, battery_level_str); - - // Set battery status - if(charging) - gtk_label_set_label(self->charging_state, "Charging"); - else - gtk_label_set_label(self->charging_state, "Not charging"); - } - } - else gtk_widget_set_visible(GTK_WIDGET(self->wireless), false); - - // Set mouse dpi - struct MOUSE_DPI_LEVELS dpi; - int (*driver_mouse_dpi_get)(void*, void*) = dlsym(device_driver(device), "driver_mouse_dpi_get"); - int dpi_res = driver_mouse_dpi_get(device_handle(device), &dpi); - if(!dpi_res) - { - // Set dpi used/max label in add button - char dpi_used_max[10]; - sprintf(dpi_used_max, "%u/%u", dpi.level_count, dpi.max_level_count); - adw_button_content_set_label(self->dpi_stage_add_button, dpi_used_max); - - GtkCheckButton* group = 0; - // Set dpi list - for(size_t i = 0; i < dpi.level_count; i++) - { - AdwActionRow* row = ADW_ACTION_ROW(adw_action_row_new()); - - // Add radiobutton - if(dpi.level_count > 1) - { - GtkCheckButton* radio_button = GTK_CHECK_BUTTON(gtk_check_button_new()); - if(!group) group = radio_button; - else gtk_check_button_set_group(radio_button, group); - - if(dpi.level_current == i) - gtk_check_button_set_active(radio_button, true); - - adw_action_row_add_prefix(row, GTK_WIDGET(radio_button)); - } - - // Convert dpi int to string, and set it as title - char dpi_str[15]; - sprintf(dpi_str, "%u DPI", dpi.level[i].dpi_x); - adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row), dpi_str); - - //gtk_list_box_row_set_activatable(GTK_LIST_BOX_ROW(row), false); - - adw_preferences_group_add(self->dpi_preference_group, GTK_WIDGET(row)); - } - } - - // Set mouse 'motion sync' feature - bool motion_sync = false; - int (*driver_mouse_motion_sync_get)(void*, bool*) = dlsym(device_driver(device), "driver_mouse_motion_sync_get"); - int motionsync_res = driver_mouse_motion_sync_get(device_handle(device), &motion_sync); - if(!motionsync_res) - adw_switch_row_set_active(self->motion_sync_switchrow, motion_sync); - - // Set mouse 'angle snap' feature - bool angle_snap = false; - int (*driver_mouse_angle_snap_get)(void*, bool*) = dlsym(device_driver(device), "driver_mouse_angle_snap_get"); - int anglesnap_res = driver_mouse_angle_snap_get(device_handle(device), &angle_snap); - if(!anglesnap_res) - adw_switch_row_set_active(self->angle_snap_switchrow, angle_snap); -} diff --git a/src/ui/panels/mouse-panel.h b/src/ui/panels/mouse-panel.h deleted file mode 100644 index 8ab0ec1..0000000 --- a/src/ui/panels/mouse-panel.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "ui/panel.h" -#include "device/device.h" - -G_BEGIN_DECLS - -G_DECLARE_FINAL_TYPE(MousePanel, mouse_panel, GINPUT, MOUSE_PANEL, Panel) - -G_END_DECLS - -Panel* mouse_panel_new(void); - -void mouse_panel_set_device(MousePanel* self, device_t* device); - diff --git a/ui/main-window.ui b/ui/main-window.ui index d13bbc3..79a328b 100644 --- a/ui/main-window.ui +++ b/ui/main-window.ui @@ -8,86 +8,85 @@ 640 - - - - vertical + + + + + Input devices - - False - - - Input devices - - - - - open-menu-symbolic - True - - primary_menu + + vertical + + + False + + + Input devices + + + + + open-menu-symbolic + True + + primary_menu + + - - - - - + - + + + + + + + never + True + 200 - never - True - 200 - - - - - - - vertical - - - - False - - - - - True - vertical - True + + + + + Empty - + True - crossfade + vertical True - 360 - + + + True + crossfade + True + 360 + + + - + - +