diff --git a/gdk/gdkscreen.h b/gdk/gdkscreen.h index 96ff8d44a2..4e3bb1c713 100644 --- a/gdk/gdkscreen.h +++ b/gdk/gdkscreen.h @@ -91,6 +91,7 @@ GList * gdk_screen_get_toplevel_windows (GdkScreen *screen); gchar * gdk_screen_make_display_name (GdkScreen *screen); gint gdk_screen_get_n_monitors (GdkScreen *screen); +gint gdk_screen_get_primary_monitor (GdkScreen *screen); void gdk_screen_get_monitor_geometry (GdkScreen *screen, gint monitor_num, GdkRectangle *dest); diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index 987bcfca7e..3e7b8b9067 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -354,6 +354,31 @@ gdk_screen_get_n_monitors (GdkScreen *screen) return GDK_SCREEN_X11 (screen)->n_monitors; } +/** + * gdk_screen_get_primary_monitor: + * @screen: a #GdkScreen. + * + * Gets the primary monitor for @screen. The primary monitor + * is considered the monitor where the 'main desktop' lives. + * While normal application windows typically allow the window + * manager to place the windows, specialized desktop applications + * such as panels should place themselves on the primary monitor. + * + * If no primary monitor is configured by the user, the return value + * will be 0, defaulting to the first monitor. + * + * Returns: An integer index for the primary monitor, or 0 if none is configured. + * + * Since: 2.20 + */ +gint +gdk_screen_get_primary_monitor (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), 0); + + return GDK_SCREEN_X11 (screen)->primary_monitor; +} + /** * gdk_screen_get_monitor_width_mm: * @screen: a #GdkScreen @@ -722,6 +747,7 @@ init_randr13 (GdkScreen *screen) GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); Display *dpy = GDK_SCREEN_XDISPLAY (screen); XRRScreenResources *resources; + RROutput primary_output; int i; GArray *monitors; gboolean randr12_compat = FALSE; @@ -733,15 +759,23 @@ init_randr13 (GdkScreen *screen) screen_x11->xroot_window); if (!resources) return FALSE; - + monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), resources->noutput); + primary_output = XRRGetOutputPrimary (screen_x11->xdisplay, + screen_x11->xroot_window); + for (i = 0; i < resources->noutput; ++i) { XRROutputInfo *output = XRRGetOutputInfo (dpy, resources, resources->outputs[i]); + if (resources->outputs[i] == primary_output) + { + screen_x11->primary_monitor = i; + } + /* Non RandR1.2 X driver have output name "default" */ randr12_compat |= !g_strcmp0(output->name, "default"); @@ -1110,7 +1144,10 @@ _gdk_x11_screen_size_changed (GdkScreen *screen, display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen)); if (display_x11->have_randr13 && event->type == ConfigureNotify) - return; + { + g_signal_emit_by_name (screen, "monitors-changed"); + return; + } XRRUpdateConfiguration (event); #else diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index 0d1548cdbb..3efee6ac9e 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -93,6 +93,7 @@ struct _GdkScreenX11 /* Xinerama/RandR 1.2 */ gint n_monitors; GdkX11Monitor *monitors; + gint primary_monitor; /* Pango renderer object singleton */ PangoRenderer *renderer; diff --git a/tests/testxinerama.c b/tests/testxinerama.c index 56dcde3f6e..d9d37a9f4e 100644 --- a/tests/testxinerama.c +++ b/tests/testxinerama.c @@ -23,13 +23,15 @@ #include static gint num_monitors; +static gint primary_monitor; static void request (GtkWidget *widget, gpointer user_data) { gchar *str; - gint i = gdk_screen_get_monitor_at_window (gtk_widget_get_screen (widget), + GdkScreen *screen = gtk_widget_get_screen (widget); + gint i = gdk_screen_get_monitor_at_window (screen, widget->window); if (i < 0) @@ -37,18 +39,35 @@ request (GtkWidget *widget, else { GdkRectangle monitor; - gdk_screen_get_monitor_geometry (gtk_widget_get_screen (widget), i, &monitor); + + gdk_screen_get_monitor_geometry (screen, + i, &monitor); + primary_monitor = gdk_screen_get_primary_monitor (screen); + str = g_strdup_printf ("" "Monitor %d of %d\n" "Width - Height : (%d,%d)\n" - "Top left coordinate : (%d,%d)",i+1, num_monitors, - monitor.width, monitor.height, monitor.x, monitor.y); + "Top left coordinate : (%d,%d)\n" + "Primary monitor: %d", + i + 1, num_monitors, + monitor.width, monitor.height, + monitor.x, monitor.y, + primary_monitor); } - + gtk_label_set_markup (GTK_LABEL (user_data), str); g_free (str); } +static void +monitors_changed_cb (GdkScreen *screen, + gpointer data) +{ + GtkWidget *label = (GtkWidget *)data; + + request (label, label); +} + int main (int argc, char *argv[]) { @@ -63,8 +82,10 @@ main (int argc, char *argv[]) num_monitors = gdk_screen_get_n_monitors (screen); if (num_monitors == 1) g_warning ("The default screen of the current display only has one monitor."); - - for (i=0; i" "Monitor %d of %d\n" "Width - Height : (%d,%d)\n" - "Top left coordinate : (%d,%d)",i+1, num_monitors, - monitor.width, monitor.height, monitor.x, monitor.y); + "Top left coordinate : (%d,%d)\n" + "Primary monitor: %d", + i + 1, num_monitors, + monitor.width, monitor.height, + monitor.x, monitor.y, + primary_monitor); gtk_label_set_markup (GTK_LABEL (label), str); g_free (str); vbox = gtk_vbox_new (TRUE, 1); @@ -94,8 +119,11 @@ main (int argc, char *argv[]) g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL); gtk_container_add (GTK_CONTAINER (vbox), button); gtk_widget_show_all (window); + + g_signal_connect (screen, "monitors-changed", + G_CALLBACK (monitors_changed_cb), label); } - + gtk_main (); return 0;