wacom: Let CcWacomPage track pad devices

This puts stylus/pad tracking on 2 separate levels. The CcWacomPanel
will look for styli, and treat them as "device leaders", adding a
CcWacomPage for them.

The CcWacomPage will then track the related pad, and update the
"Map buttons..." action visibility according to it.

This simplifies tablet page creation (eg. have it completed in one
step), and decouples the device grouping logic from CcWacomPanel,
which will be useful in future commits.
This commit is contained in:
Carlos Garnacho 2019-12-05 14:17:17 +01:00
parent e26139d499
commit e50f27a96b
5 changed files with 117 additions and 158 deletions

View file

@ -87,6 +87,9 @@ struct _CcWacomPage
GtkWidget *dialog;
GCancellable *cancellable;
/* To reach other grouped devices */
GsdDeviceManager *manager;
};
G_DEFINE_TYPE (CcWacomPage, cc_wacom_page, GTK_TYPE_BOX)
@ -119,8 +122,8 @@ enum {
};
static void
update_tablet_ui (CcWacomPage *page,
int layout);
set_page_layout (CcWacomPage *page,
int layout);
static int
get_layout_type (CcWacomDevice *device)
@ -498,7 +501,7 @@ display_mapping_dialog_closed (CcWacomPage *page)
page->dialog = NULL;
page->mapping = NULL;
layout = get_layout_type (page->stylus);
update_tablet_ui (page, layout);
set_page_layout (page, layout);
}
static void
@ -704,6 +707,7 @@ cc_wacom_page_dispose (GObject *object)
g_clear_pointer (&self->dialog, gtk_widget_destroy);
g_clear_object (&self->builder);
g_clear_object (&self->header_group);
g_clear_object (&self->pad);
self->panel = NULL;
@ -850,8 +854,8 @@ has_monitor (CcWacomPage *page)
}
static void
update_tablet_ui (CcWacomPage *page,
int layout)
set_page_layout (CcWacomPage *page,
int layout)
{
WacomIntegrationFlags integration_flags;
@ -863,9 +867,6 @@ update_tablet_ui (CcWacomPage *page,
remove_mouse_link (page);
}
/* Hide the pad buttons if no pad is present */
gtk_widget_set_visible (WID ("map-buttons-button"), page->pad != NULL);
switch (layout) {
case LAYOUT_NORMAL:
remove_left_handed (page);
@ -897,44 +898,61 @@ update_tablet_ui (CcWacomPage *page,
}
}
gboolean
cc_wacom_page_update_tools (CcWacomPage *page,
CcWacomDevice *stylus,
CcWacomDevice *pad)
static void
update_pad_availability (CcWacomPage *page)
{
int layout;
gboolean changed;
gtk_widget_set_visible (WID ("map-buttons-button"), page->pad != NULL);
}
/* Type of layout */
layout = get_layout_type (stylus);
static void
check_add_pad (CcWacomPage *page,
GsdDevice *gsd_device)
{
g_autoptr(CcWacomDevice) wacom_device = NULL;
changed = (page->stylus != stylus || page->pad != pad);
if (!changed)
return FALSE;
if ((gsd_device_get_device_type (gsd_device) & GSD_DEVICE_TYPE_PAD) == 0)
return;
page->stylus = stylus;
page->pad = pad;
wacom_device = cc_wacom_device_new (gsd_device);
if (!wacom_device)
return;
update_tablet_ui (CC_WACOM_PAGE (page), layout);
if (g_strcmp0 (cc_wacom_device_get_name (page->stylus),
cc_wacom_device_get_name (wacom_device)) != 0)
return;
return TRUE;
g_set_object (&page->pad, wacom_device);
update_pad_availability (page);
}
static void
check_remove_pad (CcWacomPage *page,
GsdDevice *gsd_device)
{
if ((gsd_device_get_device_type (gsd_device) & GSD_DEVICE_TYPE_PAD) == 0)
return;
if (page->pad && cc_wacom_device_get_device (page->pad) == gsd_device)
page->pad = NULL;
update_pad_availability (page);
}
GtkWidget *
cc_wacom_page_new (CcWacomPanel *panel,
CcWacomDevice *stylus,
CcWacomDevice *pad)
CcWacomDevice *stylus)
{
g_autoptr (GList) pads = NULL;
CcWacomPage *page;
GList *l;
g_return_val_if_fail (CC_IS_WACOM_DEVICE (stylus), NULL);
g_return_val_if_fail (!pad || CC_IS_WACOM_DEVICE (pad), NULL);
page = g_object_new (CC_TYPE_WACOM_PAGE, NULL);
page->panel = panel;
page->stylus = stylus;
cc_wacom_page_update_tools (page, stylus, pad);
set_page_layout (page, get_layout_type (stylus));
/* FIXME move this to construct */
page->wacom_settings = cc_wacom_device_get_settings (stylus);
@ -952,6 +970,19 @@ cc_wacom_page_new (CcWacomPanel *panel,
/* Tablet icon */
set_icon_name (page, "image-tablet", cc_wacom_device_get_icon_name (stylus));
/* Listen to changes in related/paired pads */
page->manager = gsd_device_manager_get ();
g_signal_connect_object (G_OBJECT (page->manager), "device-added",
G_CALLBACK (check_add_pad), page,
G_CONNECT_SWAPPED);
g_signal_connect_object (G_OBJECT (page->manager), "device-removed",
G_CALLBACK (check_remove_pad), page,
G_CONNECT_SWAPPED);
pads = gsd_device_manager_list_devices (page->manager, GSD_DEVICE_TYPE_PAD);
for (l = pads; l ; l = l->next)
check_add_pad (page, l->data);
return GTK_WIDGET (page);
}

View file

@ -30,12 +30,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CcWacomPage, cc_wacom_page, CC, WACOM_PAGE, GtkBox)
GtkWidget * cc_wacom_page_new (CcWacomPanel *panel,
CcWacomDevice *stylus,
CcWacomDevice *pad);
gboolean cc_wacom_page_update_tools (CcWacomPage *page,
CcWacomDevice *stylus,
CcWacomDevice *pad);
CcWacomDevice *stylus);
void cc_wacom_page_set_navigation (CcWacomPage *page,
GtkNotebook *notebook,

View file

@ -54,7 +54,7 @@ struct _CcWacomPanel
GtkWidget *test_draw_area;
GtkWidget *test_button;
GHashTable *devices; /* key=GsdDevice, value=CcWacomDevice */
GHashTable *pages; /* key=device name, value=GtkWidget */
GHashTable *pages; /* key=CcWacomDevice, value=GtkWidget */
GHashTable *stylus_pages; /* key=CcWacomTool, value=GtkWidget */
CcTabletToolMap *tablet_tool_map;
@ -116,23 +116,39 @@ cc_wacom_panel_static_init_func (void)
update_visibility (manager, NULL, NULL);
}
static CcWacomDevice *
lookup_wacom_device (CcWacomPanel *self,
const gchar *name)
{
GHashTableIter iter;
CcWacomDevice *wacom_device;
g_hash_table_iter_init (&iter, self->devices);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &wacom_device)) {
if (g_strcmp0 (cc_wacom_device_get_name (wacom_device), name) == 0)
return wacom_device;
}
return NULL;
}
static CcWacomPage *
set_device_page (CcWacomPanel *self, const gchar *device_name)
{
CcWacomPage *page;
CcWacomDevice *wacom_device;
gint current;
if (device_name == NULL)
return NULL;
/* Choose correct device */
page = g_hash_table_lookup (self->pages, device_name);
if (page == NULL) {
wacom_device = lookup_wacom_device (self, device_name);
if (!wacom_device) {
g_warning ("Failed to find device '%s', supplied in the command line.", device_name);
return page;
return NULL;
}
page = g_hash_table_lookup (self->pages, wacom_device);
current = gtk_notebook_page_num (GTK_NOTEBOOK (self->tablet_notebook), GTK_WIDGET (page));
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->tablet_notebook), current);
@ -482,107 +498,13 @@ cc_wacom_panel_class_init (CcWacomPanelClass *klass)
}
static void
remove_page (GtkNotebook *notebook,
GtkWidget *widget)
update_current_page (CcWacomPanel *self)
{
int num_pages, i;
int num_pages;
num_pages = gtk_notebook_get_n_pages (notebook);
g_return_if_fail (num_pages > 1);
for (i = 1; i < num_pages; i++) {
if (gtk_notebook_get_nth_page (notebook, i) == widget) {
gtk_notebook_remove_page (notebook, i);
return;
}
}
}
static void
update_current_page (CcWacomPanel *self,
CcWacomDevice *removed_device)
{
GHashTable *ht;
g_autoptr(GList) tablets = NULL;
GList *l;
gboolean changed;
GHashTableIter iter;
GsdDevice *gsd_device;
CcWacomDevice *device;
changed = FALSE;
ht = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
if (removed_device) {
Tablet *tablet = g_new0 (Tablet, 1);
tablet->name = cc_wacom_device_get_name (removed_device);
g_hash_table_insert (ht, (gpointer) tablet->name, tablet);
}
g_hash_table_iter_init (&iter, self->devices);
while (g_hash_table_iter_next (&iter, (gpointer*) &gsd_device,
(gpointer*) &device)) {
Tablet *tablet;
GsdDeviceType device_type;
device_type = gsd_device_get_device_type (gsd_device);
tablet = g_hash_table_lookup (ht, cc_wacom_device_get_name (device));
if (tablet == NULL) {
tablet = g_new0 (Tablet, 1);
tablet->name = cc_wacom_device_get_name (device);
g_hash_table_insert (ht, (gpointer) tablet->name, tablet);
}
if (device_type & GSD_DEVICE_TYPE_PAD) {
tablet->pad = device;
} else if (device_type & GSD_DEVICE_TYPE_TABLET) {
tablet->stylus = device;
}
}
/* We now have a list of Tablet structs,
* see which ones are full tablets */
tablets = g_hash_table_get_values (ht);
for (l = tablets; l; l = l->next) {
Tablet *tablet;
GtkWidget *page;
tablet = l->data;
if (tablet->stylus == NULL) {
page = g_hash_table_lookup (self->pages, tablet->name);
if (page != NULL) {
remove_page (GTK_NOTEBOOK (self->tablet_notebook), page);
g_hash_table_remove (self->pages, tablet->name);
changed = TRUE;
}
continue;
}
/* this code is called once the stylus is set up, but the pad does not exist yet */
page = g_hash_table_lookup (self->pages, tablet->name);
if (page == NULL) {
page = cc_wacom_page_new (self, tablet->stylus, tablet->pad);
cc_wacom_page_set_navigation (CC_WACOM_PAGE (page), GTK_NOTEBOOK (self->tablet_notebook), TRUE);
gtk_widget_show (page);
gtk_notebook_append_page (GTK_NOTEBOOK (self->tablet_notebook), page, NULL);
g_hash_table_insert (self->pages, g_strdup (tablet->name), page);
changed = TRUE;
} else {
cc_wacom_page_update_tools (CC_WACOM_PAGE (page), tablet->stylus, tablet->pad);
}
}
g_hash_table_destroy (ht);
if (changed == TRUE) {
int num_pages;
num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->tablet_notebook));
if (num_pages > 1)
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->tablet_notebook), 1);
}
num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (self->tablet_notebook));
if (num_pages > 1)
gtk_notebook_set_current_page (GTK_NOTEBOOK (self->tablet_notebook), 1);
update_test_button (self);
}
@ -593,6 +515,9 @@ add_known_device (CcWacomPanel *self,
{
CcWacomDevice *device;
GsdDeviceType device_type;
g_autoptr(GList) tools = NULL;
GtkWidget *page;
GList *l;
device_type = gsd_device_get_device_type (gsd_device);
@ -600,7 +525,9 @@ add_known_device (CcWacomPanel *self,
return;
if ((device_type &
(GSD_DEVICE_TYPE_TOUCHSCREEN | GSD_DEVICE_TYPE_TOUCHPAD)) != 0) {
(GSD_DEVICE_TYPE_PAD |
GSD_DEVICE_TYPE_TOUCHSCREEN |
GSD_DEVICE_TYPE_TOUCHPAD)) != 0) {
return;
}
@ -610,32 +537,39 @@ add_known_device (CcWacomPanel *self,
g_hash_table_insert (self->devices, gsd_device, device);
/* Only trigger tool lookup on pen devices */
if ((device_type & GSD_DEVICE_TYPE_TABLET) != 0) {
g_autoptr(GList) tools = NULL;
GList *l;
tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
for (l = tools; l != NULL; l = l->next) {
add_stylus (self, l->data);
}
for (l = tools; l != NULL; l = l->next) {
add_stylus (self, l->data);
}
page = cc_wacom_page_new (self, device);
cc_wacom_page_set_navigation (CC_WACOM_PAGE (page), GTK_NOTEBOOK (self->tablet_notebook), TRUE);
gtk_widget_show (page);
gtk_notebook_append_page (GTK_NOTEBOOK (self->tablet_notebook), page, NULL);
g_hash_table_insert (self->pages, device, page);
}
static void
device_removed_cb (CcWacomPanel *self,
GsdDevice *gsd_device)
{
g_autoptr(CcWacomDevice) device = NULL;
CcWacomDevice *device;
GtkWidget *page;
device = g_hash_table_lookup (self->devices, gsd_device);
if (!device)
return;
g_hash_table_steal (self->devices, gsd_device);
update_current_page (self, device);
page = g_hash_table_lookup (self->pages, device);
if (page) {
g_hash_table_remove (self->pages, device);
gtk_widget_destroy (page);
}
g_hash_table_remove (self->devices, gsd_device);
check_remove_stylus_pages (self);
update_current_page (self);
}
static void
@ -643,7 +577,7 @@ device_added_cb (CcWacomPanel *self,
GsdDevice *device)
{
add_known_device (self, device);
update_current_page (self, NULL);
update_current_page (self);
}
static gboolean
@ -807,7 +741,7 @@ cc_wacom_panel_init (CcWacomPanel *self)
G_CALLBACK (link_activated), self, G_CONNECT_SWAPPED);
self->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
self->pages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->pages = g_hash_table_new (NULL, NULL);
self->stylus_pages = g_hash_table_new (NULL, NULL);
device_manager = gsd_device_manager_get ();
@ -821,7 +755,7 @@ cc_wacom_panel_init (CcWacomPanel *self)
for (l = devices; l ; l = l->next)
add_known_device (self, l->data);
update_current_page (self, NULL);
update_current_page (self);
}
GDBusProxy *

View file

@ -308,7 +308,7 @@
<object class="GtkButton" id="map-buttons-button">
<property name="label" translatable="yes">Map Buttons…</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="visible">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>

View file

@ -26,19 +26,18 @@ add_page (GList *devices,
GtkWidget *notebook)
{
GtkWidget *widget;
CcWacomDevice *stylus, *eraser, *pad;
CcWacomDevice *stylus = NULL;
GList *l;
if (devices == NULL)
return;
stylus = eraser = pad = NULL;
for (l = devices; l ; l = l->next) {
stylus = l->data;
}
g_list_free (devices);
widget = cc_wacom_page_new (NULL, stylus, pad);
widget = cc_wacom_page_new (NULL, stylus);
cc_wacom_page_set_navigation (CC_WACOM_PAGE (widget), GTK_NOTEBOOK (notebook), FALSE);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, NULL);
gtk_widget_show (widget);