Fix handling of dynamic updates to colors/font/etc.

Since the introduction of frame sync in GTK+, updates to titlebar font and
colors haven't been working because GTK+ counts on the frame clock to
do style updates, and the frame clock doesn't run for an unmapped
GdkWindow. (It's possible that GtkStyleContext changes subsequent to
the introduction of the frame clock were also needed to fully break
things.)

We actually need to map the MetaFrames GdkWindow and let the
compositor code send out the frame sync messages in order to pick up
style changes.

Hopefully no bad side effects will occur from this - we make the window
override-redirect, 1x1, and outside the bounds of the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=725751
This commit is contained in:
Owen W. Taylor 2014-03-05 15:23:46 -05:00
parent bee59ec0e1
commit 365af53797
2 changed files with 23 additions and 27 deletions

View File

@ -44,8 +44,6 @@
static void meta_frames_destroy (GtkWidget *object); static void meta_frames_destroy (GtkWidget *object);
static void meta_frames_finalize (GObject *object); static void meta_frames_finalize (GObject *object);
static void meta_frames_style_updated (GtkWidget *widget); static void meta_frames_style_updated (GtkWidget *widget);
static void meta_frames_map (GtkWidget *widget);
static void meta_frames_unmap (GtkWidget *widget);
static void meta_frames_update_prelit_control (MetaFrames *frames, static void meta_frames_update_prelit_control (MetaFrames *frames,
MetaUIFrame *frame, MetaUIFrame *frame,
@ -134,9 +132,6 @@ meta_frames_class_init (MetaFramesClass *class)
widget_class->style_updated = meta_frames_style_updated; widget_class->style_updated = meta_frames_style_updated;
widget_class->map = meta_frames_map;
widget_class->unmap = meta_frames_unmap;
widget_class->draw = meta_frames_draw; widget_class->draw = meta_frames_draw;
widget_class->destroy_event = meta_frames_destroy_event; widget_class->destroy_event = meta_frames_destroy_event;
widget_class->button_press_event = meta_frames_button_press_event; widget_class->button_press_event = meta_frames_button_press_event;
@ -231,6 +226,7 @@ meta_frames_init (MetaFrames *frames)
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal, frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref); g_free, g_object_unref);
update_style_contexts (frames); update_style_contexts (frames);
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE); gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
@ -522,13 +518,26 @@ MetaFrames*
meta_frames_new (int screen_number) meta_frames_new (int screen_number)
{ {
GdkScreen *screen; GdkScreen *screen;
MetaFrames *frames;
screen = gdk_display_get_screen (gdk_display_get_default (), screen = gdk_display_get_screen (gdk_display_get_default (),
screen_number); screen_number);
return g_object_new (META_TYPE_FRAMES, frames = g_object_new (META_TYPE_FRAMES,
"screen", screen, "screen", screen,
NULL); "type", GTK_WINDOW_POPUP,
NULL);
/* Put the window at an arbitrary offscreen location; the one place
* it can't be is at -100x-100, since the meta_window_new() will
* mistake it for a window created via meta_create_offscreen_window()
* and ignore it, and we need this window to get frame-synchronization
* messages so that GTK+'s style change handling works.
*/
gtk_window_move (GTK_WINDOW (frames), -200, -200);
gtk_window_resize (GTK_WINDOW (frames), 1, 1);
return frames;
} }
/* In order to use a style with a window it has to be attached to that /* In order to use a style with a window it has to be attached to that
@ -635,22 +644,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow); meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
} }
static void
meta_frames_map (GtkWidget *widget)
{
/* We override the parent map function to a no-op because we don't
* want to actually show the GDK window. But GTK needs to think that
* the widget is mapped or it won't deliver the events we care about.
*/
gtk_widget_set_mapped (widget, TRUE);
}
static void
meta_frames_unmap (GtkWidget *widget)
{
gtk_widget_set_mapped (widget, FALSE);
}
static MetaUIFrame* static MetaUIFrame*
meta_frames_lookup_window (MetaFrames *frames, meta_frames_lookup_window (MetaFrames *frames,
Window xwindow) Window xwindow)

View File

@ -295,9 +295,12 @@ meta_ui_new (Display *xdisplay,
g_assert (gdisplay == gdk_display_get_default ()); g_assert (gdisplay == gdk_display_get_default ());
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen)); ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
/* This does not actually show any widget. MetaFrames has been hacked so /* GTK+ needs the frame-sync protocol to work in order to properly
* that showing it doesn't actually do anything. But we need the flags * handle style changes. This means that the dummy widget we create
* set for GTK to deliver events properly. */ * to get the style for title bars actually needs to be mapped
* and fully tracked as a MetaWindow. Horrible, but mostly harmless -
* the window is a 1x1 overide redirect window positioned offscreen.
*/
gtk_widget_show (GTK_WIDGET (ui->frames)); gtk_widget_show (GTK_WIDGET (ui->frames));
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui); g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);