From c8c05c4a142f3de9c17a9ca83692dda364abccc8 Mon Sep 17 00:00:00 2001
From: Jan200101 <sentrycraft123@gmail.com>
Date: Thu, 15 Feb 2024 16:05:40 +0100
Subject: [PATCH] shell-app: Improve discrete GPU detection

---
 .../net.hadess.SwitcherooControl.xml          |  3 +-
 src/shell-app.c                               | 60 +++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/data/dbus-interfaces/net.hadess.SwitcherooControl.xml b/data/dbus-interfaces/net.hadess.SwitcherooControl.xml
index e52bc1a0d25..59a889654f4 100644
--- a/data/dbus-interfaces/net.hadess.SwitcherooControl.xml
+++ b/data/dbus-interfaces/net.hadess.SwitcherooControl.xml
@@ -38,7 +38,8 @@
         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.
+        will tag the default GPU, the "Discrete" (b) key tags if the GPU is a
+        dedicated component.
     -->
     <property name="GPUs" type="aa{sv}" access="read"/>
 
diff --git a/src/shell-app.c b/src/shell-app.c
index 371bc6cf762..39f220ba954 100644
--- a/src/shell-app.c
+++ b/src/shell-app.c
@@ -1300,6 +1300,66 @@ apply_discrete_gpu_env (GAppLaunchContext *context,
     }
 
   num_children = g_variant_n_children (variant);
+
+  // Check if the Default GPU is Discrete
+  for (i = 0; i < num_children; i++)
+    {
+      g_autoptr(GVariant) gpu = NULL;
+      g_autoptr(GVariant) env = NULL;
+      g_autoptr(GVariant) default_variant = NULL;
+      g_autoptr(GVariant) discrete_variant = NULL;
+      g_autofree const char **env_s = NULL;
+
+      gpu = g_variant_get_child_value (variant, i);
+      if (!gpu ||
+          !g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}")))
+        continue;
+
+      /* Skip over non-default GPUs */
+      default_variant = g_variant_lookup_value (gpu, "Default", NULL);
+      if (!default_variant || !g_variant_get_boolean (default_variant))
+        continue;
+
+      /* break out if default GPU is not discrete */
+      discrete_variant = g_variant_lookup_value (gpu, "Discrete", NULL);
+      if (!discrete_variant || !g_variant_get_boolean (discrete_variant))
+        break;
+
+      // Default GPU is discrete, no need to do anything
+      return;
+    }
+
+    // Find the first Discrete GPU
+  for (i = 0; i < num_children; i++)
+    {
+      g_autoptr(GVariant) gpu = NULL;
+      g_autoptr(GVariant) env = NULL;
+      g_autoptr(GVariant) discrete_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 non-discrete GPUs */
+      discrete_variant = g_variant_lookup_value (gpu, "Discrete", NULL);
+      if (!discrete_variant || !g_variant_get_boolean (discrete_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;
+    }
+
+  // fallback to old behavior
+  // find the first non-Default GPU
   for (i = 0; i < num_children; i++)
     {
       g_autoptr(GVariant) gpu = NULL;
-- 
GitLab

