Compare commits
7 Commits
3.35.2
...
wip/carlos
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9115f6e796 | ||
![]() |
0223d38602 | ||
![]() |
33c10e9180 | ||
![]() |
c7dec4130d | ||
![]() |
512130172c | ||
![]() |
a849945bc4 | ||
![]() |
4d16d2ceed |
@@ -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>
|
||||||
|
@@ -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);
|
||||||
|
@@ -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');
|
||||||
|
@@ -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',
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user