diff --git a/ChangeLog b/ChangeLog index d0510fc101..7269be5710 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-02-24 Matthias Clasen + + * gdk/x11/gdkevents-x11.c: + * gdk/x11/gdkscreen-x11.[hc]: Another attempt at getting Xrandr + screen size changes right. Actually handle XRRScreenChangeNotify + events, and ignore root ConfigureNotify events if we are using + Xrandr. Only emit size-changed signals if the screen size changed, + and only emit monitor-changed signals if the monitors changed. + 2009-02-23 Matthias Clasen Bug 565199 – Ellipsize text in Places list diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index a335feefb6..096c17005c 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -2107,10 +2107,11 @@ gdk_event_translate (GdkDisplay *display, else #endif #ifdef HAVE_RANDR - if (xevent->type - display_x11->xrandr_event_base == RRNotify) + if (xevent->type - display_x11->xrandr_event_base == RRScreenChangeNotify || + xevent->type - display_x11->xrandr_event_base == RRNotify) { if (screen) - _gdk_x11_screen_process_monitors_change (screen); + _gdk_x11_screen_size_changed (screen, xevent); } else #endif diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index e6478006bf..0bcb2bcdab 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -1,4 +1,4 @@ -/* + /* * gdkscreen-x11.c * * Copyright 2001 Sun Microsystems Inc. @@ -856,34 +856,79 @@ init_xfree_xinerama (GdkScreen *screen) return FALSE; } +static void +free_monitors (GdkX11Monitor *monitors, + gint n_monitors) +{ + int i; + + for (i = 0; i < n_monitors; ++i) + { + g_free (monitors[i].output_name); + g_free (monitors[i].manufacturer); + } + + g_free (monitors); +} + static void deinit_multihead (GdkScreen *screen) { GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); - int i; - for (i = 0; i < screen_x11->n_monitors; ++i) - { - GdkX11Monitor *monitor = get_monitor (screen, i); - - g_free (monitor->output_name); - g_free (monitor->manufacturer); - } - - g_free (screen_x11->monitors); + free_monitors (screen_x11->monitors, screen_x11->n_monitors); screen_x11->n_monitors = 0; screen_x11->monitors = NULL; } +static gboolean +compare_monitor (GdkX11Monitor *m1, + GdkX11Monitor *m2) +{ + if (m1->geometry.x != m2->geometry.x || + m1->geometry.y != m2->geometry.y || + m1->geometry.width != m2->geometry.width || + m1->geometry.height != m2->geometry.height) + return FALSE; + + if (m1->width_mm != m2->width_mm || + m1->height_mm != m2->height_mm) + return FALSE; + + if (g_strcmp0 (m1->output_name, m2->output_name) != 0) + return FALSE; + + if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0) + return FALSE; + + return TRUE; +} + +static gboolean +compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1, + GdkX11Monitor *monitors2, gint n_monitors2) +{ + gint i; + + if (n_monitors1 != n_monitors2) + return FALSE; + + for (i = 0; i < n_monitors1; i++) + { + if (!compare_monitor (monitors1 + i, monitors2 + i)) + return FALSE; + } + + return TRUE; +} + static void init_multihead (GdkScreen *screen) { GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); int opcode, firstevent, firsterror; - deinit_multihead (screen); - /* There are four different implementations of multihead support: * * 1. Fake Xinerama for debugging purposes @@ -995,18 +1040,49 @@ init_randr_support (GdkScreen * screen) #endif } +static void +process_monitors_change (GdkScreen *screen) +{ + GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); + gint n_monitors; + GdkX11Monitor *monitors; + gboolean changed; + + n_monitors = screen_x11->n_monitors; + monitors = screen_x11->monitors; + + screen_x11->n_monitors = 0; + screen_x11->monitors = NULL; + + init_multihead (screen); + + changed = !compare_monitors (monitors, n_monitors, + screen_x11->monitors, screen_x11->n_monitors); + + free_monitors (monitors, n_monitors); + + if (changed) + g_signal_emit_by_name (screen, "monitors-changed"); +} + void _gdk_x11_screen_size_changed (GdkScreen *screen, XEvent *event) { gint width, height; + GdkDisplayX11 *display_x11; + gboolean monitors_changed; width = gdk_screen_get_width (screen); height = gdk_screen_get_height (screen); #ifdef HAVE_RANDR - if (!XRRUpdateConfiguration (event)) + display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen)); + + if (display_x11->have_randr13 && event->type == ConfigureNotify) return; + + XRRUpdateConfiguration (event); #else if (event->type == ConfigureNotify) { @@ -1020,21 +1096,11 @@ _gdk_x11_screen_size_changed (GdkScreen *screen, return; #endif - if (width == gdk_screen_get_width (screen) && - height == gdk_screen_get_height (screen)) - return; + process_monitors_change (screen); - _gdk_x11_screen_process_monitors_change (screen); - - g_signal_emit_by_name (screen, "size-changed"); -} - -void -_gdk_x11_screen_process_monitors_change (GdkScreen *screen) -{ - init_multihead (screen); - - g_signal_emit_by_name (screen, "monitors-changed"); + if (width != gdk_screen_get_width (screen) || + height != gdk_screen_get_height (screen)) + g_signal_emit_by_name (screen, "size-changed"); } void @@ -1061,7 +1127,7 @@ _gdk_x11_screen_process_owner_change (GdkScreen *screen, { screen_x11->is_composited = composited; - g_signal_emit_by_name (screen, "composited_changed"); + g_signal_emit_by_name (screen, "composited-changed"); } } #endif diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index 4ccc795f56..8a743f5d84 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -125,9 +125,8 @@ GdkScreen * _gdk_x11_screen_new (GdkDisplay *display, void _gdk_x11_screen_window_manager_changed (GdkScreen *screen); void _gdk_x11_screen_size_changed (GdkScreen *screen, XEvent *event); -void _gdk_x11_screen_process_owner_change (GdkScreen *screen, - XEvent *event); -void _gdk_x11_screen_process_monitors_change (GdkScreen *screen); +void _gdk_x11_screen_process_owner_change (GdkScreen *screen, + XEvent *event); G_END_DECLS