Compare commits

...

7 Commits

Author SHA1 Message Date
Carlos Garnacho
9115f6e796 workspace: Pass device to startDrag()
This is necessary to make DnD operations work from tablet devices on
wayland, as it's not the same onscreen pointer sprite than mice. Fixes
window DnD in the overview on tablet devices, no longer having them stick
to the wrong pointer.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/897
2019-12-13 17:53:41 +00:00
Bastien Nocera
0223d38602 shell-app: Add discrete GPU support for NVidia drivers
Use data from switcheroo-control to know which environment variables
to use to launch an application on the discrete GPU. switcheroo-control
version 2.0 or newer should be installed on Linux platforms.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1810
2019-12-13 00:44:28 +01:00
Bastien Nocera
33c10e9180 shell: Prime the GPUs property cache for switcheroo-control
See: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/781
2019-12-13 00:44:28 +01:00
Bastien Nocera
c7dec4130d shell: Add API to access switcheroo-control D-Bus proxy
See: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/781
2019-12-13 00:44:28 +01:00
Bastien Nocera
512130172c main: Add switcheroo-control generated code
See: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/781
2019-12-13 00:44:28 +01:00
Bastien Nocera
a849945bc4 data: Update switcheroo-control D-Bus interface
It's backwards compatible, so just new properties.

See: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/781
2019-12-13 00:44:24 +01:00
Bastien Nocera
4d16d2ceed appDisplay: Remove unimplemented 'activate-discrete-gpu'
It was added in commit 009d021 but not advertised, and likely not used
by an application since then.

See: https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/781
2019-12-12 17:19:41 +01:00
7 changed files with 217 additions and 6 deletions

View File

@@ -1,5 +1,46 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node> <node>
<!--
net.hadess.SwitcherooControl:
@short_description: D-Bus proxy to access dual-GPU controls.
After checking the availability of two switchable GPUs in the machine,
check the value of net.hadess.SwitcherooControl.HasDualGpu to see
if running applications on the discrete GPU should be offered.
The object path will be "/net/hadess/SwitcherooControl".
-->
<interface name="net.hadess.SwitcherooControl"> <interface name="net.hadess.SwitcherooControl">
<!--
HasDualGpu:
Whether two switchable GPUs are present on the system. This property
has been obsoleted in favour of the "NumGPUs" property.
-->
<property name="HasDualGpu" type="b" access="read"/> <property name="HasDualGpu" type="b" access="read"/>
<!--
NumGPUs:
The number of GPUs available on the system. Note that while having no
GPUs is unlikely, consumers of this API should probably not throw errors
if that were the case.
-->
<property name="NumGPUs" type="u" access="read"/>
<!--
GPUs:
An array of key-pair values representing each GPU. The key named "Name" (s)
will contain a user-facing name for the GPU, the "Environment" (as) key will
contain an array of even number of strings, each being an environment
variable to set to use the GPU, followed by its value, the "Default" (b) key
will tag the default (usually integrated) GPU.
-->
<property name="GPUs" type="aa{sv}" access="read"/>
</interface> </interface>
</node> </node>

View File

@@ -2576,8 +2576,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
} }
if (discreteGpuAvailable && if (discreteGpuAvailable &&
this._source.app.state == Shell.AppState.STOPPED && this._source.app.state == Shell.AppState.STOPPED) {
!actions.includes('activate-discrete-gpu')) {
this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card")); this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
this._onDiscreteGpuMenuItem.connect('activate', () => { this._onDiscreteGpuMenuItem.connect('activate', () => {
this._source.animateLaunch(); this._source.animateLaunch();
@@ -2590,8 +2589,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
let action = actions[i]; let action = actions[i];
let item = this._appendMenuItem(appInfo.get_action_name(action)); let item = this._appendMenuItem(appInfo.get_action_name(action));
item.connect('activate', (emitter, event) => { item.connect('activate', (emitter, event) => {
if (action == 'new-window' || if (action == 'new-window')
action == 'activate-discrete-gpu')
this._source.animateLaunch(); this._source.animateLaunch();
this._source.app.launch_action(action, event.get_time(), -1); this._source.app.launch_action(action, event.get_time(), -1);

View File

@@ -431,7 +431,7 @@ var WindowClone = GObject.registerClass({
return; return;
let [x, y] = action.get_coords(); let [x, y] = action.get_coords();
action.release(); action.release();
this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence); this._draggable.startDrag(x, y, global.get_current_time(), this._dragTouchSequence, event.get_device());
}); });
} else { } else {
this.emit('show-chrome'); this.emit('show-chrome');

View File

@@ -188,6 +188,11 @@ dbus_generated = gnome.gdbus_codegen('org-gtk-application',
namespace: 'Shell' namespace: 'Shell'
) )
dbus_generated += gnome.gdbus_codegen('switcheroo-control',
'../data/dbus-interfaces/net.hadess.SwitcherooControl.xml',
namespace: 'Shell'
)
libshell_no_gir_sources += dbus_generated libshell_no_gir_sources += dbus_generated
libshell = library('gnome-shell', libshell = library('gnome-shell',

View File

@@ -19,6 +19,7 @@
#include "st.h" #include "st.h"
#include "gtkactionmuxer.h" #include "gtkactionmuxer.h"
#include "org-gtk-application.h" #include "org-gtk-application.h"
#include "switcheroo-control.h"
#ifdef HAVE_SYSTEMD #ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h> #include <systemd/sd-journal.h>
@@ -1255,6 +1256,60 @@ wait_pid (GDesktopAppInfo *appinfo,
g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL); g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
} }
static void
apply_discrete_gpu_env (GAppLaunchContext *context,
ShellGlobal *global)
{
GDBusProxy *proxy;
GVariant* variant;
guint num_children, i;
proxy = _shell_global_get_switcheroo_control (global);
if (!proxy)
{
g_warning ("Could not apply discrete GPU environment, switcheroo-control not available");
return;
}
variant = shell_net_hadess_switcheroo_control_get_gpus (SHELL_NET_HADESS_SWITCHEROO_CONTROL (proxy));
if (!variant)
{
g_warning ("Could not apply discrete GPU environment, no GPUs in list");
return;
}
num_children = g_variant_n_children (variant);
for (i = 0; i < num_children; i++)
{
g_autoptr(GVariant) gpu;
g_autoptr(GVariant) env = NULL;
g_autoptr(GVariant) default_variant = NULL;
g_autofree const char **env_s = NULL;
guint j;
gpu = g_variant_get_child_value (variant, i);
if (!gpu ||
!g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}")))
continue;
/* Skip over the default GPU */
default_variant = g_variant_lookup_value (gpu, "Default", NULL);
if (!default_variant || g_variant_get_boolean (default_variant))
continue;
env = g_variant_lookup_value (gpu, "Environment", NULL);
if (!env)
continue;
env_s = g_variant_get_strv (env, NULL);
for (j = 0; env_s[j] != NULL; j = j + 2)
g_app_launch_context_setenv (context, env_s[j], env_s[j+1]);
return;
}
g_warning ("Could not find discrete GPU data in switcheroo-control");
}
/** /**
* shell_app_launch: * shell_app_launch:
* @timestamp: Event timestamp, or 0 for current event timestamp * @timestamp: Event timestamp, or 0 for current event timestamp
@@ -1290,7 +1345,7 @@ shell_app_launch (ShellApp *app,
global = shell_global_get (); global = shell_global_get ();
context = shell_global_create_app_launch_context (global, timestamp, workspace); context = shell_global_create_app_launch_context (global, timestamp, workspace);
if (discrete_gpu) if (discrete_gpu)
g_app_launch_context_setenv (context, "DRI_PRIME", "1"); apply_discrete_gpu_env (context, global);
/* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn /* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn
* codepath. The shell's open file descriptors should be marked CLOEXEC * codepath. The shell's open file descriptors should be marked CLOEXEC

View File

@@ -48,6 +48,7 @@
#include "shell-wm.h" #include "shell-wm.h"
#include "shell-util.h" #include "shell-util.h"
#include "st.h" #include "st.h"
#include "switcheroo-control.h"
static ShellGlobal *the_object = NULL; static ShellGlobal *the_object = NULL;
@@ -85,6 +86,9 @@ struct _ShellGlobal {
gboolean has_modal; gboolean has_modal;
gboolean frame_timestamps; gboolean frame_timestamps;
gboolean frame_finish_timestamp; gboolean frame_finish_timestamp;
GDBusProxy *switcheroo_control;
GCancellable *switcheroo_cancellable;
}; };
enum { enum {
@@ -106,6 +110,7 @@ enum {
PROP_FOCUS_MANAGER, PROP_FOCUS_MANAGER,
PROP_FRAME_TIMESTAMPS, PROP_FRAME_TIMESTAMPS,
PROP_FRAME_FINISH_TIMESTAMP, PROP_FRAME_FINISH_TIMESTAMP,
PROP_SWITCHEROO_CONTROL,
}; };
/* Signals */ /* Signals */
@@ -120,6 +125,72 @@ G_DEFINE_TYPE(ShellGlobal, shell_global, G_TYPE_OBJECT);
static guint shell_global_signals [LAST_SIGNAL] = { 0 }; static guint shell_global_signals [LAST_SIGNAL] = { 0 };
static void
got_switcheroo_control_gpus_property_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
ShellGlobal *global;
GError *error = NULL;
GVariant *gpus;
gpus = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
res, &error);
if (!gpus)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_debug ("Could not get GPUs property from switcheroo-control: %s", error->message);
g_clear_error (&error);
return;
}
global = user_data;
g_dbus_proxy_set_cached_property (global->switcheroo_control, "GPUs", gpus);
}
static void
switcheroo_control_ready_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
ShellGlobal *global;
GError *error = NULL;
ShellNetHadessSwitcherooControl *control;
g_auto(GStrv) cached_props = NULL;
control = shell_net_hadess_switcheroo_control_proxy_new_for_bus_finish (res, &error);
if (!control)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_debug ("Could not get switcheroo-control GDBusProxy: %s", error->message);
g_clear_error (&error);
return;
}
global = user_data;
global->switcheroo_control = G_DBUS_PROXY (control);
g_debug ("Got switcheroo-control proxy successfully");
cached_props = g_dbus_proxy_get_cached_property_names (global->switcheroo_control);
if (cached_props != NULL && g_strv_contains ((const gchar * const *) cached_props, "GPUs"))
return;
g_dbus_connection_call (g_dbus_proxy_get_connection (global->switcheroo_control),
g_dbus_proxy_get_name (global->switcheroo_control),
g_dbus_proxy_get_object_path (global->switcheroo_control),
"org.freedesktop.DBus.Properties",
"Get",
g_variant_new ("(ss)",
g_dbus_proxy_get_interface_name (global->switcheroo_control),
"GPUs"),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
global->switcheroo_cancellable,
got_switcheroo_control_gpus_property_cb,
user_data);
}
static void static void
shell_global_set_property(GObject *object, shell_global_set_property(GObject *object,
guint prop_id, guint prop_id,
@@ -214,6 +285,9 @@ shell_global_get_property(GObject *object,
case PROP_FRAME_FINISH_TIMESTAMP: case PROP_FRAME_FINISH_TIMESTAMP:
g_value_set_boolean (value, global->frame_finish_timestamp); g_value_set_boolean (value, global->frame_finish_timestamp);
break; break;
case PROP_SWITCHEROO_CONTROL:
g_value_set_object (value, global->switcheroo_control);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -313,6 +387,15 @@ shell_global_init (ShellGlobal *global)
global->save_ops = g_hash_table_new_full (g_file_hash, global->save_ops = g_hash_table_new_full (g_file_hash,
(GEqualFunc) g_file_equal, (GEqualFunc) g_file_equal,
g_object_unref, g_object_unref); g_object_unref, g_object_unref);
global->switcheroo_cancellable = g_cancellable_new ();
shell_net_hadess_switcheroo_control_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
"net.hadess.SwitcherooControl",
"/net/hadess/SwitcherooControl",
global->switcheroo_cancellable,
switcheroo_control_ready_cb,
global);
} }
static void static void
@@ -325,6 +408,9 @@ shell_global_finalize (GObject *object)
the_object = NULL; the_object = NULL;
g_cancellable_cancel (global->switcheroo_cancellable);
g_clear_object (&global->switcheroo_cancellable);
g_clear_object (&global->userdatadir_path); g_clear_object (&global->userdatadir_path);
g_clear_object (&global->runtime_state_path); g_clear_object (&global->runtime_state_path);
@@ -481,6 +567,13 @@ shell_global_class_init (ShellGlobalClass *klass)
"Whether at the end of a frame to call glFinish and log paintCompletedTimestamp", "Whether at the end of a frame to call glFinish and log paintCompletedTimestamp",
FALSE, FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_SWITCHEROO_CONTROL,
g_param_spec_object ("switcheroo-control",
"switcheroo-control",
"D-Bus Proxy for switcheroo-control daemon",
G_TYPE_DBUS_PROXY,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
} }
/* /*
@@ -1264,6 +1357,22 @@ shell_global_sync_pointer (ShellGlobal *global)
clutter_event_put ((ClutterEvent *)&event); clutter_event_put ((ClutterEvent *)&event);
} }
/**
* _shell_global_get_switcheroo_control: (skip)
* @global: A #ShellGlobal
*
* Get the global #GDBusProxy instance for the switcheroo-control
* daemon.
*
* Return value: (transfer none): the #GDBusProxy for the daemon,
* or %NULL on error.
*/
GDBusProxy *
_shell_global_get_switcheroo_control (ShellGlobal *global)
{
return global->switcheroo_control;
}
/** /**
* shell_global_get_settings: * shell_global_get_settings:
* @global: A #ShellGlobal * @global: A #ShellGlobal

View File

@@ -66,6 +66,9 @@ void shell_global_run_at_leisure (ShellGlobal *global,
/* Misc utilities / Shell API */ /* Misc utilities / Shell API */
void shell_global_sync_pointer (ShellGlobal *global); void shell_global_sync_pointer (ShellGlobal *global);
GDBusProxy *
_shell_global_get_switcheroo_control (ShellGlobal *global);
GAppLaunchContext * GAppLaunchContext *
shell_global_create_app_launch_context (ShellGlobal *global, shell_global_create_app_launch_context (ShellGlobal *global,
guint32 timestamp, guint32 timestamp,