2011-11-24 15:34:52 +00:00
/*
* Copyright © 2011 Red Hat , Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2014-01-23 12:57:27 +01:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2011-11-24 15:34:52 +00:00
*
* Authors : Peter Hutterer < peter . hutterer @ redhat . com >
* Bastien Nocera < hadess @ hadess . net >
*
*/
# include <config.h>
2013-04-04 12:05:24 +02:00
# ifdef FAKE_AREA
# include <gdk/gdk.h>
# endif /* FAKE_AREA */
2012-02-14 19:19:16 +00:00
# include <glib/gi18n-lib.h>
# include <gtk/gtk.h>
2016-06-06 14:49:13 +02:00
# include <gdesktop-enums.h>
2017-06-16 18:15:23 +02:00
# ifdef GDK_WINDOWING_X11
2021-11-18 15:51:43 -03:00
# include <gdk/x11/gdkx.h>
2017-06-16 18:15:23 +02:00
# endif
# ifdef GDK_WINDOWING_WAYLAND
2021-11-18 15:51:43 -03:00
# include <gdk/wayland/gdkwayland.h>
2017-06-16 18:15:23 +02:00
# endif
2012-02-14 19:19:16 +00:00
2023-03-27 19:22:34 +01:00
# include "cc-list-row.h"
2016-06-06 14:49:13 +02:00
# include "cc-wacom-device.h"
2013-07-23 12:45:20 +02:00
# include "cc-wacom-button-row.h"
2011-11-24 15:34:52 +00:00
# include "cc-wacom-page.h"
2012-01-16 17:18:32 +00:00
# include "cc-wacom-stylus-page.h"
2012-02-14 19:19:16 +00:00
# include "gsd-enums.h"
2013-04-08 18:44:12 +02:00
# include "calibrator-gui.h"
2017-06-16 18:15:23 +02:00
# include "gsd-input-helper.h"
2011-11-24 15:34:52 +00:00
# include <string.h>
2018-06-03 09:42:43 +04:00
# define MWID(x) (GtkWidget *) gtk_builder_get_object (page->mapping_builder, x)
2011-11-24 15:34:52 +00:00
2012-01-13 11:51:27 +00:00
# define THRESHOLD_MISCLICK 15
# define THRESHOLD_DOUBLECLICK 7
2018-06-03 09:42:43 +04:00
struct _CcWacomPage
2011-11-24 15:34:52 +00:00
{
2018-06-03 09:42:43 +04:00
GtkBox parent_instance ;
2012-01-26 17:49:56 +00:00
CcWacomPanel * panel ;
2016-06-06 14:49:13 +02:00
CcWacomDevice * stylus ;
2024-02-01 13:25:41 +01:00
CcWacomDevice * pad ;
2022-02-12 11:54:31 +01:00
CcCalibArea * area ;
2011-11-24 18:58:29 +00:00
GSettings * wacom_settings ;
2012-02-16 17:24:55 +01:00
2022-02-01 12:39:49 +01:00
GtkWidget * tablet_section ;
2022-01-29 17:17:40 +01:00
GtkWidget * tablet_icon ;
GtkWidget * tablet_display ;
GtkWidget * tablet_calibrate ;
GtkWidget * tablet_map_buttons ;
2024-01-16 19:57:27 -05:00
AdwSwitchRow * tablet_mode_row ;
AdwSwitchRow * tablet_left_handed_row ;
2024-02-27 03:53:00 -03:00
AdwSwitchRow * tablet_aspect_ratio_row ;
2022-01-29 17:17:40 +01:00
GtkWidget * display_section ;
GnomeRRScreen * rr_screen ;
2016-06-06 14:49:13 +02:00
2012-02-16 17:24:55 +01:00
/* Button mapping */
2012-02-14 19:19:16 +00:00
GtkBuilder * mapping_builder ;
2021-11-18 15:51:43 -03:00
GtkWindow * button_map ;
2012-06-26 11:06:07 +02:00
GtkListStore * action_store ;
2012-02-16 17:24:55 +01:00
2013-07-26 17:29:20 +02:00
GCancellable * cancellable ;
2019-12-05 14:17:17 +01:00
/* To reach other grouped devices */
GsdDeviceManager * manager ;
2011-11-24 15:34:52 +00:00
} ;
2018-06-03 09:42:43 +04:00
G_DEFINE_TYPE ( CcWacomPage , cc_wacom_page , GTK_TYPE_BOX )
2012-04-12 15:29:36 +02:00
/* Different types of layout for the tablet config */
enum {
LAYOUT_NORMAL , /* tracking mode, button mapping */
LAYOUT_REVERSIBLE , /* tracking mode, button mapping, left-hand orientation */
LAYOUT_SCREEN /* button mapping, calibration, display resolution */
} ;
static int
2016-06-06 14:49:13 +02:00
get_layout_type ( CcWacomDevice * device )
2012-04-12 15:29:36 +02:00
{
int layout ;
2016-06-06 14:49:13 +02:00
if ( cc_wacom_device_get_integration_flags ( device ) &
( WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM ) )
2012-04-12 15:29:36 +02:00
layout = LAYOUT_SCREEN ;
2016-06-06 14:49:13 +02:00
else if ( cc_wacom_device_is_reversible ( device ) )
2012-04-12 15:29:36 +02:00
layout = LAYOUT_REVERSIBLE ;
else
layout = LAYOUT_NORMAL ;
return layout ;
}
2012-01-09 16:01:14 -08:00
static void
2016-06-24 17:38:08 +02:00
set_calibration ( CcWacomDevice * device ,
gdouble * cal ,
2013-04-19 16:37:59 +02:00
gsize ncal ,
GSettings * settings )
2012-01-09 16:01:14 -08:00
{
GVariant * current ; /* current calibration */
GVariant * array ; /* new calibration */
2018-06-03 10:22:08 +04:00
g_autofree GVariant * * tmp = NULL ;
2012-01-09 16:01:14 -08:00
gsize nvalues ;
2013-04-19 16:37:59 +02:00
gint i ;
2012-01-09 16:01:14 -08:00
current = g_settings_get_value ( settings , " area " ) ;
2016-06-24 17:38:08 +02:00
g_variant_get_fixed_array ( current , & nvalues , sizeof ( gdouble ) ) ;
2012-01-12 18:57:55 +00:00
if ( ( ncal ! = 4 ) | | ( nvalues ! = 4 ) ) {
2020-07-20 10:38:09 +03:00
g_warning ( " Unable to set device calibration property. Got % " G_GSIZE_FORMAT " items to put in % " G_GSIZE_FORMAT " slots; expected %d items. \n " , ncal , nvalues , 4 ) ;
2012-01-09 16:01:14 -08:00
return ;
}
tmp = g_malloc ( nvalues * sizeof ( GVariant * ) ) ;
for ( i = 0 ; i < ncal ; i + + )
2016-06-24 17:38:08 +02:00
tmp [ i ] = g_variant_new_double ( cal [ i ] ) ;
2012-01-09 16:01:14 -08:00
2016-06-24 17:38:08 +02:00
array = g_variant_new_array ( G_VARIANT_TYPE_DOUBLE , tmp , nvalues ) ;
2012-01-09 16:01:14 -08:00
g_settings_set_value ( settings , " area " , array ) ;
2022-02-12 00:26:59 +01:00
g_debug ( " Setting area to %f, %f, %f, %f (left/right/top/bottom) " ,
cal [ 0 ] , cal [ 1 ] , cal [ 2 ] , cal [ 3 ] ) ;
2012-01-09 16:01:14 -08:00
}
2012-01-12 18:57:55 +00:00
static void
2022-02-12 11:54:31 +01:00
finish_calibration ( CcCalibArea * area ,
gpointer user_data )
2012-01-09 16:01:14 -08:00
{
2012-01-12 18:57:55 +00:00
CcWacomPage * page = ( CcWacomPage * ) user_data ;
2012-01-10 19:19:24 +00:00
XYinfo axis ;
2016-06-24 17:38:08 +02:00
gdouble cal [ 4 ] ;
2012-01-09 16:01:14 -08:00
2022-02-12 11:54:31 +01:00
if ( cc_calib_area_finish ( area ) ) {
cc_calib_area_get_padding ( area , & axis ) ;
2012-01-10 19:19:24 +00:00
cal [ 0 ] = axis . x_min ;
2017-06-20 15:55:26 -07:00
cal [ 1 ] = axis . x_max ;
cal [ 2 ] = axis . y_min ;
2012-01-10 19:19:24 +00:00
cal [ 3 ] = axis . y_max ;
2012-01-12 18:57:55 +00:00
2018-06-03 09:42:43 +04:00
set_calibration ( page - > stylus ,
cal , 4 , page - > wacom_settings ) ;
2013-10-08 08:46:41 +02:00
} else {
/* Reset the old values */
GVariant * old_calibration ;
old_calibration = g_object_get_data ( G_OBJECT ( page ) , " old-calibration " ) ;
2018-06-03 09:42:43 +04:00
g_settings_set_value ( page - > wacom_settings , " area " , old_calibration ) ;
2013-10-08 08:46:41 +02:00
g_object_set_data ( G_OBJECT ( page ) , " old-calibration " , NULL ) ;
2012-01-09 16:01:14 -08:00
}
2022-02-12 11:54:31 +01:00
cc_calib_area_free ( area ) ;
2018-06-03 09:42:43 +04:00
page - > area = NULL ;
2022-01-29 17:17:40 +01:00
gtk_widget_set_sensitive ( page - > tablet_calibrate , TRUE ) ;
2012-01-12 18:57:55 +00:00
}
static gboolean
run_calibration ( CcWacomPage * page ,
2013-10-08 08:46:41 +02:00
GVariant * old_calibration ,
2016-06-24 17:38:08 +02:00
gdouble * cal ,
2018-05-26 10:05:19 +02:00
GdkMonitor * monitor )
2012-01-12 18:57:55 +00:00
{
2018-06-03 09:42:43 +04:00
g_assert ( page - > area = = NULL ) ;
2012-07-18 14:23:29 +02:00
2022-02-12 11:54:31 +01:00
page - > area = cc_calib_area_new ( NULL ,
2024-02-08 16:17:29 +10:00
monitor ,
2024-02-08 16:18:47 +10:00
cc_wacom_device_get_device ( page - > stylus ) ,
2024-02-08 16:17:29 +10:00
finish_calibration ,
page ,
THRESHOLD_MISCLICK ,
THRESHOLD_DOUBLECLICK ) ;
2012-01-12 18:57:55 +00:00
2013-10-08 08:46:41 +02:00
g_object_set_data_full ( G_OBJECT ( page ) ,
" old-calibration " ,
old_calibration ,
( GDestroyNotify ) g_variant_unref ) ;
2012-01-10 20:16:33 +00:00
return FALSE ;
2012-01-09 16:01:14 -08:00
}
2022-09-01 13:58:18 +02:00
static GdkMonitor *
find_monitor_at_point ( GdkDisplay * display ,
gint x ,
gint y )
{
GListModel * monitors ;
int i ;
monitors = gdk_display_get_monitors ( display ) ;
for ( i = 0 ; i < g_list_model_get_n_items ( monitors ) ; i + + ) {
g_autoptr ( GdkMonitor ) m = g_list_model_get_item ( monitors , i ) ;
GdkRectangle geometry ;
gdk_monitor_get_geometry ( m , & geometry ) ;
if ( gdk_rectangle_contains_point ( & geometry , x , y ) )
return g_steal_pointer ( & m ) ;
}
return NULL ;
}
2012-01-09 16:01:14 -08:00
static void
2013-06-03 19:21:35 +02:00
calibrate ( CcWacomPage * page )
2012-01-09 16:01:14 -08:00
{
2016-06-24 17:38:08 +02:00
int i ;
2018-06-03 10:22:08 +04:00
GVariant * old_calibration , * array ;
g_autofree GVariant * * tmp = NULL ;
g_autofree gdouble * calibration = NULL ;
2012-01-12 15:26:16 +00:00
gsize ncal ;
2021-11-18 15:51:43 -03:00
GdkDisplay * display ;
2022-09-01 13:58:18 +02:00
g_autoptr ( GdkMonitor ) monitor = NULL ;
2018-06-03 10:22:08 +04:00
g_autoptr ( GnomeRRScreen ) rr_screen = NULL ;
2016-06-24 17:38:08 +02:00
GnomeRROutput * output ;
2018-06-03 10:22:08 +04:00
g_autoptr ( GError ) error = NULL ;
2022-09-01 13:58:18 +02:00
GDBusProxy * input_mapping_proxy ;
2016-06-24 17:38:08 +02:00
gint x , y ;
2012-01-12 13:02:22 -08:00
2021-11-18 15:51:43 -03:00
display = gdk_display_get_default ( ) ;
rr_screen = gnome_rr_screen_new ( display , & error ) ;
2016-06-24 17:38:08 +02:00
if ( error ) {
g_warning ( " Could not connect to display manager: %s " , error - > message ) ;
return ;
}
2018-06-03 09:42:43 +04:00
output = cc_wacom_device_get_output ( page - > stylus , rr_screen ) ;
2022-09-01 13:58:18 +02:00
input_mapping_proxy = cc_wacom_panel_get_input_mapping_bus_proxy ( page - > panel ) ;
if ( output ) {
gnome_rr_output_get_position ( output , & x , & y ) ;
monitor = find_monitor_at_point ( display , x , y ) ;
} else if ( input_mapping_proxy ) {
GsdDevice * gsd_device ;
GVariant * mapping ;
gsd_device = cc_wacom_device_get_device ( page - > stylus ) ;
if ( gsd_device ) {
mapping = g_dbus_proxy_call_sync ( input_mapping_proxy ,
" GetDeviceMapping " ,
g_variant_new ( " (o) " , gsd_device_get_device_file ( gsd_device ) ) ,
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
NULL ,
NULL ) ;
if ( mapping ) {
gint x , y , width , height ;
g_variant_get ( mapping , " ((iiii)) " , & x , & y , & width , & height ) ;
monitor = find_monitor_at_point ( display , x , y ) ;
}
}
}
2016-06-24 17:38:08 +02:00
2018-05-26 10:05:19 +02:00
if ( ! monitor ) {
2012-01-12 13:02:22 -08:00
/* The display the tablet should be mapped to could not be located.
* This shouldn ' t happen if the EDID data is good . . .
*/
2022-02-12 14:42:57 +01:00
g_critical ( " Output associated with the tablet is not connected. Calibration may appear in wrong monitor. " ) ;
2012-01-12 13:02:22 -08:00
}
2012-01-12 15:26:16 +00:00
2018-06-03 09:42:43 +04:00
old_calibration = g_settings_get_value ( page - > wacom_settings , " area " ) ;
2016-06-24 17:38:08 +02:00
g_variant_get_fixed_array ( old_calibration , & ncal , sizeof ( gdouble ) ) ;
2012-01-12 15:23:53 +00:00
2012-01-12 15:26:16 +00:00
if ( ncal ! = 4 ) {
g_warning ( " Device calibration property has wrong length. Got % " G_GSIZE_FORMAT " items; expected %d. \n " , ncal , 4 ) ;
2012-01-12 15:23:53 +00:00
return ;
}
2012-01-09 16:01:14 -08:00
2016-06-24 17:38:08 +02:00
calibration = g_new0 ( gdouble , ncal ) ;
2013-04-04 12:05:24 +02:00
2013-10-08 08:46:41 +02:00
/* Reset the current values, to avoid old calibrations
* from interfering with the calibration */
tmp = g_malloc ( ncal * sizeof ( GVariant * ) ) ;
2016-06-24 17:38:08 +02:00
for ( i = 0 ; i < ncal ; i + + ) {
calibration [ i ] = 0.0 ;
tmp [ i ] = g_variant_new_double ( calibration [ i ] ) ;
}
2013-10-08 08:46:41 +02:00
2016-06-24 17:38:08 +02:00
array = g_variant_new_array ( G_VARIANT_TYPE_DOUBLE , tmp , ncal ) ;
2018-06-03 09:42:43 +04:00
g_settings_set_value ( page - > wacom_settings , " area " , array ) ;
2012-01-12 15:23:53 +00:00
2013-10-08 08:46:41 +02:00
run_calibration ( page , old_calibration , calibration , monitor ) ;
2022-01-29 17:17:40 +01:00
gtk_widget_set_sensitive ( page - > tablet_calibrate , FALSE ) ;
2016-06-24 17:38:08 +02:00
}
2016-06-06 14:49:13 +02:00
2013-06-03 19:21:35 +02:00
static void
2022-01-29 17:17:40 +01:00
on_calibrate_activated ( CcWacomPage * self )
2013-06-03 19:21:35 +02:00
{
2022-01-29 17:17:40 +01:00
calibrate ( self ) ;
2012-01-12 15:23:53 +00:00
}
2012-01-09 16:01:14 -08:00
2012-12-20 12:07:00 +01:00
/* This avoids us crashing when a newer version of
* gnome - control - center has been used , and we load up an
* old one , as the action type if unknown to the old g - c - c */
static gboolean
2016-06-23 16:52:35 +02:00
action_type_is_valid ( GDesktopPadButtonAction action )
2012-12-20 12:07:00 +01:00
{
2016-06-23 16:52:35 +02:00
if ( action > = G_N_ELEMENTS ( action_table ) )
2012-12-20 12:07:00 +01:00
return FALSE ;
return TRUE ;
}
2012-02-14 19:19:16 +00:00
static void
2016-06-23 16:52:35 +02:00
create_row_from_button ( GtkWidget * list_box ,
guint button ,
GSettings * settings )
2012-02-14 19:19:16 +00:00
{
2021-11-18 15:51:43 -03:00
gtk_list_box_append ( GTK_LIST_BOX ( list_box ) ,
cc_wacom_button_row_new ( button , settings ) ) ;
2012-02-28 10:43:33 +00:00
}
static void
2013-07-23 12:45:20 +02:00
setup_button_mapping ( CcWacomPage * page )
2012-02-14 19:19:16 +00:00
{
2016-06-23 16:52:35 +02:00
GDesktopPadButtonAction action ;
2019-12-05 15:36:03 +01:00
CcWacomDevice * pad ;
2016-06-23 16:52:35 +02:00
GtkWidget * list_box ;
guint i , n_buttons ;
GSettings * settings ;
2012-02-14 19:19:16 +00:00
2013-07-23 12:45:20 +02:00
list_box = MWID ( " shortcuts_list " ) ;
2024-02-01 13:25:41 +01:00
pad = page - > pad ;
2019-12-05 15:36:03 +01:00
n_buttons = cc_wacom_device_get_num_buttons ( pad ) ;
2013-07-23 12:45:20 +02:00
2016-06-23 16:52:35 +02:00
for ( i = 0 ; i < n_buttons ; i + + ) {
2019-12-05 15:36:03 +01:00
settings = cc_wacom_device_get_button_settings ( pad , i ) ;
2016-06-23 16:52:35 +02:00
if ( ! settings )
2013-07-23 12:45:20 +02:00
continue ;
2012-06-26 11:06:07 +02:00
2016-06-23 16:52:35 +02:00
action = g_settings_get_enum ( settings , " action " ) ;
if ( ! action_type_is_valid ( action ) )
2013-07-23 12:45:20 +02:00
continue ;
2012-02-14 19:21:59 +00:00
2016-06-23 16:52:35 +02:00
create_row_from_button ( list_box , i , settings ) ;
2012-02-14 19:19:16 +00:00
}
}
2012-02-14 19:37:28 +00:00
static void
2019-11-22 15:54:43 +13:00
button_mapping_dialog_closed ( CcWacomPage * page )
2012-02-14 19:37:28 +00:00
{
2021-11-18 15:51:43 -03:00
gtk_window_destroy ( GTK_WINDOW ( MWID ( " button-mapping-dialog " ) ) ) ;
2018-06-03 10:22:08 +04:00
g_clear_object ( & page - > mapping_builder ) ;
2012-02-14 19:37:28 +00:00
}
2012-02-14 15:51:54 +00:00
static void
2013-07-26 17:29:20 +02:00
show_button_mapping_dialog ( CcWacomPage * page )
2012-02-14 15:51:54 +00:00
{
2013-07-26 17:29:20 +02:00
GtkWidget * toplevel ;
2018-06-03 10:22:08 +04:00
g_autoptr ( GError ) error = NULL ;
2013-07-26 17:29:20 +02:00
GtkWidget * dialog ;
2012-02-14 19:19:16 +00:00
2018-06-03 09:42:43 +04:00
g_assert ( page - > mapping_builder = = NULL ) ;
page - > mapping_builder = gtk_builder_new ( ) ;
gtk_builder_add_from_resource ( page - > mapping_builder ,
2013-01-04 16:36:56 +01:00
" /org/gnome/control-center/wacom/button-mapping.ui " ,
& error ) ;
2012-02-14 15:51:54 +00:00
if ( error ! = NULL ) {
g_warning ( " Error loading UI file: %s " , error - > message ) ;
2018-06-03 10:22:08 +04:00
g_clear_object ( & page - > mapping_builder ) ;
2012-02-14 15:51:54 +00:00
return ;
}
2013-07-23 12:45:20 +02:00
setup_button_mapping ( page ) ;
2012-02-14 19:19:16 +00:00
2012-02-14 15:51:54 +00:00
dialog = MWID ( " button-mapping-dialog " ) ;
2021-11-18 15:51:43 -03:00
toplevel = GTK_WIDGET ( gtk_widget_get_native ( GTK_WIDGET ( page ) ) ) ;
2012-02-19 16:05:27 +01:00
gtk_window_set_transient_for ( GTK_WINDOW ( dialog ) , GTK_WINDOW ( toplevel ) ) ;
2012-02-14 15:51:54 +00:00
gtk_window_set_modal ( GTK_WINDOW ( dialog ) , TRUE ) ;
2019-11-22 15:54:43 +13:00
g_signal_connect_object ( dialog , " response " ,
G_CALLBACK ( button_mapping_dialog_closed ) , page , G_CONNECT_SWAPPED ) ;
2012-02-14 19:37:28 +00:00
2023-01-17 00:18:31 +02:00
gtk_window_present ( GTK_WINDOW ( dialog ) ) ;
2012-05-25 11:19:37 +01:00
2021-11-18 15:51:43 -03:00
page - > button_map = GTK_WINDOW ( dialog ) ;
2018-06-03 09:42:43 +04:00
g_object_add_weak_pointer ( G_OBJECT ( dialog ) , ( gpointer * ) & page - > button_map ) ;
2012-02-14 15:51:54 +00:00
}
2013-07-26 17:29:20 +02:00
static void
set_osd_visibility_cb ( GObject * source_object ,
GAsyncResult * res ,
gpointer data )
{
2018-06-03 10:22:08 +04:00
g_autoptr ( GError ) error = NULL ;
2013-07-26 17:29:20 +02:00
GVariant * result ;
CcWacomPage * page ;
page = CC_WACOM_PAGE ( data ) ;
result = g_dbus_proxy_call_finish ( G_DBUS_PROXY ( source_object ) , res , & error ) ;
if ( result = = NULL ) {
if ( ! g_error_matches ( error , G_IO_ERROR , G_IO_ERROR_CANCELLED ) ) {
g_printerr ( " Error setting OSD's visibility: %s \n " , error - > message ) ;
show_button_mapping_dialog ( page ) ;
} else {
return ;
}
}
}
static void
2016-06-06 14:49:13 +02:00
set_osd_visibility ( CcWacomPage * page )
2013-07-26 17:29:20 +02:00
{
GDBusProxy * proxy ;
2016-06-06 14:49:13 +02:00
GsdDevice * gsd_device ;
const gchar * device_path ;
2013-07-26 17:29:20 +02:00
2018-06-03 09:42:43 +04:00
proxy = cc_wacom_panel_get_gsd_wacom_bus_proxy ( page - > panel ) ;
2019-12-05 15:36:03 +01:00
/* Pick the first device, the OSD may change later between them */
2024-02-01 13:25:41 +01:00
gsd_device = cc_wacom_device_get_device ( page - > pad ) ;
2016-06-06 14:49:13 +02:00
device_path = gsd_device_get_device_file ( gsd_device ) ;
2013-07-26 17:29:20 +02:00
if ( proxy = = NULL ) {
show_button_mapping_dialog ( page ) ;
return ;
}
g_dbus_proxy_call ( proxy ,
2016-06-23 16:55:29 +02:00
" Show " ,
g_variant_new ( " (ob) " , device_path , TRUE ) ,
2013-07-26 17:29:20 +02:00
G_DBUS_CALL_FLAGS_NONE ,
- 1 ,
2018-06-03 09:42:43 +04:00
page - > cancellable ,
2013-07-26 17:29:20 +02:00
set_osd_visibility_cb ,
page ) ;
}
static void
2022-01-29 17:17:40 +01:00
on_map_buttons_activated ( CcWacomPage * self )
2018-12-20 17:57:10 +01:00
{
2022-01-29 17:17:40 +01:00
set_osd_visibility ( self ) ;
2018-12-20 17:57:10 +01:00
}
static void
2023-05-26 12:31:41 +12:00
on_display_selected ( CcWacomPage * page )
2018-12-20 17:57:10 +01:00
{
2022-01-29 17:17:40 +01:00
GListModel * list ;
g_autoptr ( GObject ) obj = NULL ;
GVariant * variant ;
gint idx ;
2018-12-20 17:57:10 +01:00
2023-05-26 12:31:41 +12:00
list = adw_combo_row_get_model ( ADW_COMBO_ROW ( page - > tablet_display ) ) ;
idx = adw_combo_row_get_selected ( ADW_COMBO_ROW ( page - > tablet_display ) ) ;
2022-01-29 17:17:40 +01:00
obj = g_list_model_get_item ( list , idx ) ;
2018-12-20 17:57:10 +01:00
2022-01-29 17:17:40 +01:00
variant = g_object_get_data ( obj , " value-output " ) ;
2018-12-20 17:57:10 +01:00
2022-01-29 17:17:40 +01:00
if ( variant )
g_settings_set_value ( page - > wacom_settings , " output " , g_variant_ref ( variant ) ) ;
else
g_settings_reset ( page - > wacom_settings , " output " ) ;
2018-12-20 17:57:10 +01:00
2022-01-29 17:17:40 +01:00
gtk_widget_set_sensitive ( page - > tablet_calibrate , variant = = NULL ) ;
2018-12-20 17:57:10 +01:00
}
2011-11-24 15:34:52 +00:00
/* Boilerplate code goes below */
static void
cc_wacom_page_get_property ( GObject * object ,
guint property_id ,
GValue * value ,
GParamSpec * pspec )
{
switch ( property_id )
{
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , property_id , pspec ) ;
}
}
static void
cc_wacom_page_set_property ( GObject * object ,
guint property_id ,
const GValue * value ,
GParamSpec * pspec )
{
switch ( property_id )
{
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( object , property_id , pspec ) ;
}
}
static void
cc_wacom_page_dispose ( GObject * object )
{
2018-06-03 09:42:43 +04:00
CcWacomPage * self = CC_WACOM_PAGE ( object ) ;
2011-11-24 15:34:52 +00:00
2018-06-03 10:22:08 +04:00
g_cancellable_cancel ( self - > cancellable ) ;
g_clear_object ( & self - > cancellable ) ;
2022-02-12 11:54:31 +01:00
g_clear_pointer ( & self - > area , cc_calib_area_free ) ;
2021-11-18 15:51:43 -03:00
g_clear_pointer ( & self - > button_map , gtk_window_destroy ) ;
2024-02-01 13:25:41 +01:00
g_clear_object ( & self - > pad ) ;
2022-01-29 17:17:40 +01:00
g_clear_object ( & self - > rr_screen ) ;
2016-06-06 14:49:13 +02:00
2018-06-03 09:42:43 +04:00
self - > panel = NULL ;
2012-01-12 18:57:55 +00:00
2011-11-24 15:34:52 +00:00
G_OBJECT_CLASS ( cc_wacom_page_parent_class ) - > dispose ( object ) ;
}
static void
cc_wacom_page_class_init ( CcWacomPageClass * klass )
{
GObjectClass * object_class = G_OBJECT_CLASS ( klass ) ;
2022-01-29 17:17:40 +01:00
GtkWidgetClass * widget_class = GTK_WIDGET_CLASS ( klass ) ;
2011-11-24 15:34:52 +00:00
object_class - > get_property = cc_wacom_page_get_property ;
object_class - > set_property = cc_wacom_page_set_property ;
object_class - > dispose = cc_wacom_page_dispose ;
2023-03-27 19:22:34 +01:00
g_type_ensure ( CC_TYPE_LIST_ROW ) ;
2022-01-29 17:17:40 +01:00
gtk_widget_class_set_template_from_resource ( widget_class , " /org/gnome/control-center/wacom/cc-wacom-page.ui " ) ;
2022-02-01 12:39:49 +01:00
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_section ) ;
2022-01-29 17:17:40 +01:00
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_icon ) ;
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_display ) ;
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_calibrate ) ;
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_map_buttons ) ;
2024-01-16 19:57:27 -05:00
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_mode_row ) ;
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_left_handed_row ) ;
2024-02-27 03:53:00 -03:00
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , tablet_aspect_ratio_row ) ;
2022-01-29 17:17:40 +01:00
gtk_widget_class_bind_template_child ( widget_class , CcWacomPage , display_section ) ;
gtk_widget_class_bind_template_callback ( widget_class , on_map_buttons_activated ) ;
gtk_widget_class_bind_template_callback ( widget_class , on_calibrate_activated ) ;
gtk_widget_class_bind_template_callback ( widget_class , on_display_selected ) ;
}
static void
update_displays_model ( CcWacomPage * page )
{
g_autoptr ( GtkStringList ) list = NULL ;
GnomeRROutput * * outputs , * cur_output ;
int i , idx = 0 , cur = - 1 , automatic_item = - 1 ;
g_autoptr ( GObject ) obj = NULL ;
GVariant * variant ;
outputs = gnome_rr_screen_list_outputs ( page - > rr_screen ) ;
list = gtk_string_list_new ( NULL ) ;
cur_output = cc_wacom_device_get_output ( page - > stylus ,
page - > rr_screen ) ;
for ( i = 0 ; outputs [ i ] ! = NULL ; i + + ) {
GnomeRROutput * output = outputs [ i ] ;
GnomeRRCrtc * crtc = gnome_rr_output_get_crtc ( output ) ;
g_autofree gchar * text = NULL ;
g_autofree gchar * vendor = NULL ;
g_autofree gchar * product = NULL ;
g_autofree gchar * serial = NULL ;
const gchar * name , * disp_name ;
/* Output is turned on? */
if ( ! crtc | | gnome_rr_crtc_get_current_mode ( crtc ) = = NULL )
continue ;
2018-12-19 16:35:01 +01:00
2022-01-29 17:17:40 +01:00
if ( output = = cur_output )
cur = idx ;
name = gnome_rr_output_get_name ( output ) ;
disp_name = gnome_rr_output_get_display_name ( output ) ;
text = g_strdup_printf ( " %s (%s) " , name , disp_name ) ;
gnome_rr_output_get_ids_from_edid ( output ,
& vendor ,
& product ,
& serial ) ;
2024-02-05 11:06:38 +01:00
variant = g_variant_new_strv ( ( const gchar * [ ] ) { vendor , product , serial , name } , 4 ) ;
2022-01-29 17:17:40 +01:00
gtk_string_list_append ( list , text ) ;
obj = g_list_model_get_item ( G_LIST_MODEL ( list ) , idx ) ;
g_object_set_data_full ( G_OBJECT ( obj ) , " value-output " ,
variant , ( GDestroyNotify ) g_variant_unref ) ;
idx + + ;
2011-11-24 15:34:52 +00:00
}
2022-01-29 17:17:40 +01:00
/* All displays item */
gtk_string_list_append ( list , _ ( " All Displays " ) ) ;
variant = g_variant_new_strv ( ( const gchar * [ ] ) { " " , " " , " " } , 3 ) ;
obj = g_list_model_get_item ( G_LIST_MODEL ( list ) , idx ) ;
g_object_set_data_full ( G_OBJECT ( obj ) , " value-output " ,
variant , ( GDestroyNotify ) g_variant_unref ) ;
if ( cur_output = = NULL )
cur = idx ;
/* "Automatic" item */
if ( get_layout_type ( page - > stylus ) = = LAYOUT_SCREEN ) {
g_autoptr ( GVariant ) user_value = NULL ;
idx + + ;
gtk_string_list_append ( list , _ ( " Automatic " ) ) ;
automatic_item = idx ;
user_value = g_settings_get_user_value ( page - > wacom_settings , " output " ) ;
if ( ! user_value )
cur = idx ;
}
2011-11-24 15:34:52 +00:00
2022-01-29 17:17:40 +01:00
g_signal_handlers_block_by_func ( page - > tablet_display , on_display_selected , page ) ;
adw_combo_row_set_model ( ADW_COMBO_ROW ( page - > tablet_display ) , G_LIST_MODEL ( list ) ) ;
adw_combo_row_set_selected ( ADW_COMBO_ROW ( page - > tablet_display ) , cur ) ;
g_signal_handlers_unblock_by_func ( page - > tablet_display , on_display_selected , page ) ;
2011-11-25 15:05:34 +00:00
2022-01-29 17:17:40 +01:00
gtk_widget_set_sensitive ( page - > tablet_calibrate , cur = = automatic_item ) ;
2011-11-25 15:05:34 +00:00
}
2012-01-30 16:50:03 +00:00
static void
2022-01-29 17:17:40 +01:00
cc_wacom_page_init ( CcWacomPage * page )
2012-01-30 16:50:03 +00:00
{
2022-01-29 17:17:40 +01:00
g_autoptr ( GError ) error = NULL ;
2012-01-30 16:50:03 +00:00
2022-01-29 17:17:40 +01:00
gtk_widget_init_template ( GTK_WIDGET ( page ) ) ;
page - > rr_screen = gnome_rr_screen_new ( gdk_display_get_default ( ) , & error ) ;
2012-01-30 16:50:03 +00:00
2022-01-29 17:17:40 +01:00
if ( error )
g_warning ( " Could not get RR screen: %s " , error - > message ) ;
g_signal_connect_object ( page - > rr_screen , " changed " ,
G_CALLBACK ( update_displays_model ) ,
page , G_CONNECT_SWAPPED ) ;
2013-04-04 14:01:08 +02:00
}
2018-12-20 17:57:10 +01:00
static void
2022-01-29 17:17:40 +01:00
set_icon_name ( CcWacomPage * page ,
GtkWidget * widget ,
const char * icon_name )
2018-12-20 17:57:10 +01:00
{
2022-01-29 17:17:40 +01:00
g_autofree gchar * resource = NULL ;
resource = g_strdup_printf ( " /org/gnome/control-center/wacom/%s.svg " , icon_name ) ;
gtk_picture_set_resource ( GTK_PICTURE ( widget ) , resource ) ;
2018-12-20 17:57:10 +01:00
}
2013-06-03 19:21:35 +02:00
static gboolean
has_monitor ( CcWacomPage * page )
{
2016-06-06 14:49:13 +02:00
WacomIntegrationFlags integration_flags ;
2018-06-03 09:42:43 +04:00
integration_flags = cc_wacom_device_get_integration_flags ( page - > stylus ) ;
2016-06-06 14:49:13 +02:00
return ( ( integration_flags &
( WACOM_DEVICE_INTEGRATED_DISPLAY | WACOM_DEVICE_INTEGRATED_SYSTEM ) ) ! = 0 ) ;
2013-06-03 19:21:35 +02:00
}
2019-12-05 14:17:17 +01:00
static void
update_pad_availability ( CcWacomPage * page )
2012-04-12 15:29:36 +02:00
{
2024-02-01 13:25:41 +01:00
gtk_widget_set_visible ( page - > tablet_map_buttons , page - > pad ! = NULL ) ;
2019-12-05 14:17:17 +01:00
}
2012-04-12 15:29:36 +02:00
2019-12-05 14:17:17 +01:00
static void
check_add_pad ( CcWacomPage * page ,
GsdDevice * gsd_device )
{
g_autoptr ( CcWacomDevice ) wacom_device = NULL ;
2024-02-01 13:14:59 +01:00
const gchar * stylus_vendor , * stylus_product ;
const gchar * pad_vendor , * pad_product ;
GsdDevice * stylus_device ;
2012-04-12 15:29:36 +02:00
2019-12-05 14:17:17 +01:00
if ( ( gsd_device_get_device_type ( gsd_device ) & GSD_DEVICE_TYPE_PAD ) = = 0 )
return ;
2012-04-12 15:29:36 +02:00
2024-02-01 13:14:59 +01:00
stylus_device = cc_wacom_device_get_device ( page - > stylus ) ;
gsd_device_get_device_ids ( cc_wacom_device_get_device ( page - > stylus ) ,
& stylus_vendor , & stylus_product ) ;
gsd_device_get_device_ids ( gsd_device , & pad_vendor , & pad_product ) ;
if ( ! gsd_device_shares_group ( stylus_device , gsd_device ) | |
g_strcmp0 ( stylus_vendor , pad_vendor ) ! = 0 | |
g_strcmp0 ( stylus_product , pad_product ) ! = 0 )
2019-12-05 14:17:17 +01:00
return ;
2012-04-12 15:29:36 +02:00
2024-02-01 13:25:41 +01:00
page - > pad = cc_wacom_device_new ( gsd_device ) ;
if ( page - > pad )
update_pad_availability ( page ) ;
2019-12-05 14:17:17 +01:00
}
static void
check_remove_pad ( CcWacomPage * page ,
GsdDevice * gsd_device )
{
if ( ( gsd_device_get_device_type ( gsd_device ) & GSD_DEVICE_TYPE_PAD ) = = 0 )
return ;
2024-02-01 13:25:41 +01:00
if ( cc_wacom_device_get_device ( page - > pad ) = = gsd_device ) {
g_clear_object ( & page - > pad ) ;
update_pad_availability ( page ) ;
2019-12-05 15:36:03 +01:00
}
2012-04-12 15:29:36 +02:00
}
2022-01-29 17:17:40 +01:00
static GVariant *
tablet_mode_bind_set ( const GValue * value ,
const GVariantType * expected_type ,
gpointer user_data )
{
gboolean setting ;
setting = g_value_get_boolean ( value ) ;
return g_variant_new_string ( setting ? " absolute " : " relative " ) ;
}
static gboolean
tablet_mode_bind_get ( GValue * value ,
GVariant * variant ,
gpointer user_data )
{
g_value_set_boolean ( value ,
g_strcmp0 ( g_variant_get_string ( variant , NULL ) ,
" absolute " ) = = 0 ) ;
return TRUE ;
}
2011-11-24 15:34:52 +00:00
GtkWidget *
2016-06-06 14:49:13 +02:00
cc_wacom_page_new ( CcWacomPanel * panel ,
2019-12-05 14:17:17 +01:00
CcWacomDevice * stylus )
2011-11-24 15:34:52 +00:00
{
2019-12-05 14:17:17 +01:00
g_autoptr ( GList ) pads = NULL ;
2011-11-24 15:34:52 +00:00
CcWacomPage * page ;
2019-12-05 14:17:17 +01:00
GList * l ;
2011-11-24 15:34:52 +00:00
2016-06-06 14:49:13 +02:00
g_return_val_if_fail ( CC_IS_WACOM_DEVICE ( stylus ) , NULL ) ;
2012-02-14 18:30:34 +00:00
2011-11-24 15:34:52 +00:00
page = g_object_new ( CC_TYPE_WACOM_PAGE , NULL ) ;
2018-06-03 09:42:43 +04:00
page - > panel = panel ;
2019-12-05 14:17:17 +01:00
page - > stylus = stylus ;
2012-04-12 15:29:36 +02:00
2024-01-16 19:57:27 -05:00
gtk_widget_set_visible ( GTK_WIDGET ( page - > tablet_left_handed_row ) ,
2022-01-29 17:17:40 +01:00
get_layout_type ( stylus ) = = LAYOUT_REVERSIBLE ) ;
gtk_widget_set_visible ( page - > tablet_calibrate ,
get_layout_type ( stylus ) = = LAYOUT_SCREEN ) ;
2011-11-24 15:34:52 +00:00
/* FIXME move this to construct */
2018-06-03 09:42:43 +04:00
page - > wacom_settings = cc_wacom_device_get_settings ( stylus ) ;
2011-11-24 19:12:14 +00:00
2011-11-25 15:05:34 +00:00
/* Tablet name */
2022-02-01 12:39:49 +01:00
adw_preferences_group_set_title ( ADW_PREFERENCES_GROUP ( page - > tablet_section ) ,
cc_wacom_device_get_name ( stylus ) ) ;
adw_preferences_group_set_description ( ADW_PREFERENCES_GROUP ( page - > tablet_section ) ,
cc_wacom_device_get_description ( stylus ) ) ;
2022-01-29 17:17:40 +01:00
g_settings_bind_with_mapping ( page - > wacom_settings , " mapping " ,
2024-01-16 19:57:27 -05:00
page - > tablet_mode_row , " active " ,
2022-01-29 17:17:40 +01:00
G_SETTINGS_BIND_DEFAULT ,
tablet_mode_bind_get ,
tablet_mode_bind_set ,
NULL , NULL ) ;
g_settings_bind_with_mapping ( page - > wacom_settings , " mapping " ,
page - > display_section , " sensitive " ,
G_SETTINGS_BIND_DEFAULT ,
tablet_mode_bind_get ,
tablet_mode_bind_set ,
NULL , NULL ) ;
g_settings_bind ( page - > wacom_settings , " left-handed " ,
2024-01-16 19:57:27 -05:00
page - > tablet_left_handed_row , " active " ,
2022-01-29 17:17:40 +01:00
G_SETTINGS_BIND_DEFAULT ) ;
g_settings_bind ( page - > wacom_settings , " keep-aspect " ,
2024-02-27 03:53:00 -03:00
page - > tablet_aspect_ratio_row , " active " ,
2022-01-29 17:17:40 +01:00
G_SETTINGS_BIND_DEFAULT ) ;
2011-12-08 13:25:32 -08:00
2011-11-25 15:05:34 +00:00
/* Tablet icon */
2022-01-29 17:17:40 +01:00
set_icon_name ( page , page - > tablet_icon , cc_wacom_device_get_icon_name ( stylus ) ) ;
2012-02-20 16:50:44 +01:00
2019-12-05 14:17:17 +01:00
/* 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 ) ;
2022-01-29 17:17:40 +01:00
update_pad_availability ( page ) ;
update_displays_model ( page ) ;
2011-11-28 18:23:28 +00:00
2022-01-29 17:17:40 +01:00
return GTK_WIDGET ( page ) ;
2011-11-28 18:23:28 +00:00
}
2013-06-03 19:21:35 +02:00
void
cc_wacom_page_calibrate ( CcWacomPage * page )
{
g_return_if_fail ( CC_IS_WACOM_PAGE ( page ) ) ;
calibrate ( page ) ;
}
gboolean
cc_wacom_page_can_calibrate ( CcWacomPage * page )
{
g_return_val_if_fail ( CC_IS_WACOM_PAGE ( page ) ,
FALSE ) ;
return has_monitor ( page ) ;
}