parent
5ab6aefa49
commit
ee60060dc6
@ -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); |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -1,11 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <adwaita.h> |
||||
|
||||
G_BEGIN_DECLS |
||||
|
||||
G_DECLARE_FINAL_TYPE(GinputApplication, ginput_application, GINPUT, APPLICATION, AdwApplication) |
||||
|
||||
AdwApplication* ginput_application_new(void); |
||||
|
||||
G_END_DECLS |
@ -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 <gtk/gtk.h> |
||||
|
||||
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)); |
||||
} |
@ -1,14 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <adwaita.h> |
||||
#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 |
@ -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)); |
||||
} |
@ -1,44 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <adwaita.h> |
||||
|
||||
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 |
@ -0,0 +1,8 @@ |
||||
[GtkTemplate (ui="/v/ginput/panel-empty.ui")] |
||||
public class EmptyPanel : Panel |
||||
{ |
||||
public EmptyPanel() |
||||
{ |
||||
base(""); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
@ -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); |
@ -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); |
||||
} |
@ -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); |
||||
|
Loading…
Reference in new issue