I'm not sure if a answer regarding Gtk is helpful, the question is tagged with gtk
and the author seem to use it. With GNOME I can apply different scaling factors per monitor on Wayland, X11 uses on scaling factor for all monitors. The following code reports the scaling factors:
#include <gtk/gtk.h>
#include <stdio.h>
static void activate(GtkApplication *app, gpointer user_data) {
GtkWidget *window;
window = gtk_application_window_new(app); // creates GtkApplicationWindow, returns a GtkWidget*
gtk_window_set_title(GTK_WINDOW (window), "Window"); // macro, checks types and does function style cast
gtk_window_set_default_size(GTK_WINDOW (window), 200, 200);
gtk_widget_show_all(window);
GdkWindow* gdk_window = gtk_widget_get_window(window);
GdkDisplay* gdk_display = gdk_display_get_default();
// prints sadly always '1' on my system
GdkMonitor* gdk_monitor = gdk_display_get_monitor_at_window(gdk_display, gdk_window);
int scale = gdk_monitor_get_scale_factor(gdk_monitor);
printf("scale is %d\n", scale);
// seems to work fine
int n = gdk_display_get_n_monitors(gdk_display);
for (int i = 0; i < n; ++i) {
GdkMonitor* monitor = gdk_display_get_monitor(gdk_display, i);
int scale = gdk_monitor_get_scale_factor(monitor);
printf("monitor %d, scale %d\n", i, scale);
}
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run(G_APPLICATION (app), argc, argv);
g_object_unref(app); // free memory of GtkApplication
return status;
}
Compile
gcc `pkg-config --cflags gtk+-3.0` -o gtk_scale gtk_scale.c `pkg-config --libs gtk+-3.0`
When I'm running the application on Wayland, with the left monitor (primary) set to scale factor 1 and the right monitor is set to scale factor 2:
./gtk_scale
scale is 1 # wrong, application windows resides on right screen with scale factor 2
monitor 0, scale 2 # correct
monitor 1, scale 1 # correct
The more convenient function gdk_display_get_monitor_at_window() seem to always return the scale factor of the primary monitor instead of the actual scale factor used by the application window.
Gets the monitor in which the largest area of window resides, or a
monitor close to window if it is outside of all monitors.
Therefore I recommend instead currently gdk_monitor_get_scale_factor() which provides the correct results. If multiple displays are conneted - like in my example - you will need to figure out now on which one your application window is shown.
Gets the internal scale factor that maps from monitor coordinates to
the actual device pixels. On traditional systems this is 1, but on
very high density outputs this can be a higher value (often 2).
This can be used if you want to create pixel based data for a
particular monitor, but most of the time you’re drawing to a window
where it is better to use gdk_window_get_scale_factor() instead.
The other function mentioned there is the one Andreas has investigated initially, for me it returns always 2.