Compare commits
	
		
			3 Commits
		
	
	
		
			wip/textur
			...
			wip/garnac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9f35b5816a | ||
|   | 63c91f9d4f | ||
|   | aaa02440be | 
| @@ -198,6 +198,8 @@ libmutter_la_SOURCES =				\ | ||||
| 	core/screen.c				\ | ||||
| 	core/screen-private.h			\ | ||||
| 	meta/screen.h				\ | ||||
| 	core/startup-notification.c		\ | ||||
| 	core/startup-notification-private.h	\ | ||||
| 	meta/types.h				\ | ||||
| 	core/restart.c				\ | ||||
| 	core/stack.c				\ | ||||
|   | ||||
| @@ -35,6 +35,7 @@ | ||||
| #include <meta/boxes.h> | ||||
| #include <meta/display.h> | ||||
| #include "keybindings-private.h" | ||||
| #include "startup-notification-private.h" | ||||
| #include "meta-gesture-tracker-private.h" | ||||
| #include <meta/prefs.h> | ||||
| #include <meta/barrier.h> | ||||
| @@ -276,9 +277,8 @@ struct _MetaDisplay | ||||
|   int xinput_event_base; | ||||
|   int xinput_opcode; | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   SnDisplay *sn_display; | ||||
| #endif | ||||
|   MetaStartupNotification *startup_notification; | ||||
|  | ||||
|   int xsync_event_base; | ||||
|   int xsync_error_base; | ||||
|   int shape_event_base; | ||||
|   | ||||
| @@ -400,28 +400,6 @@ meta_display_remove_pending_pings_for_window (MetaDisplay *display, | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| static void | ||||
| sn_error_trap_push (SnDisplay *sn_display, | ||||
|                     Display   *xdisplay) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|   display = meta_display_for_x_display (xdisplay); | ||||
|   if (display != NULL) | ||||
|     meta_error_trap_push (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sn_error_trap_pop (SnDisplay *sn_display, | ||||
|                    Display   *xdisplay) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|   display = meta_display_for_x_display (xdisplay); | ||||
|   if (display != NULL) | ||||
|     meta_error_trap_pop (display); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| enable_compositor (MetaDisplay *display) | ||||
| { | ||||
| @@ -527,6 +505,20 @@ gesture_tracker_state_changed (MetaGestureTracker   *tracker, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_startup_notification_changed (MetaStartupNotification *sn, | ||||
|                                  gpointer                 sequence, | ||||
|                                  MetaDisplay             *display) | ||||
| { | ||||
|   if (!display->screen) | ||||
|     return; | ||||
|  | ||||
|   g_slist_free (display->screen->startup_sequences); | ||||
|   display->screen->startup_sequences = | ||||
|     meta_startup_notification_get_sequences (display->startup_notification); | ||||
|   g_signal_emit_by_name (display->screen, "startup-sequence-changed", sequence); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_display_open: | ||||
|  * | ||||
| @@ -630,12 +622,6 @@ meta_display_open (void) | ||||
|  | ||||
|   display->screen = NULL; | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   display->sn_display = sn_display_new (display->xdisplay, | ||||
|                                         sn_error_trap_push, | ||||
|                                         sn_error_trap_pop); | ||||
| #endif | ||||
|  | ||||
|   /* Get events */ | ||||
|   meta_display_init_events (display); | ||||
|   meta_display_init_events_x11 (display); | ||||
| @@ -916,6 +902,10 @@ meta_display_open (void) | ||||
|  | ||||
|   display->screen = screen; | ||||
|  | ||||
|   display->startup_notification = meta_startup_notification_get (display); | ||||
|   g_signal_connect (display->startup_notification, "changed", | ||||
|                     G_CALLBACK (on_startup_notification_changed), display); | ||||
|  | ||||
|   meta_screen_init_workspaces (screen); | ||||
|  | ||||
|   enable_compositor (display); | ||||
| @@ -1100,6 +1090,7 @@ meta_display_close (MetaDisplay *display, | ||||
|  | ||||
|   meta_display_remove_autoraise_callback (display); | ||||
|  | ||||
|   g_clear_object (&display->startup_notification); | ||||
|   g_clear_object (&display->gesture_tracker); | ||||
|  | ||||
|   if (display->focus_timeout_id) | ||||
| @@ -1112,14 +1103,6 @@ meta_display_close (MetaDisplay *display, | ||||
|  | ||||
|   meta_screen_free (display->screen, timestamp); | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   if (display->sn_display) | ||||
|     { | ||||
|       sn_display_unref (display->sn_display); | ||||
|       display->sn_display = NULL; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   /* Must be after all calls to meta_window_unmanage() since they | ||||
|    * unregister windows | ||||
|    */ | ||||
|   | ||||
| @@ -85,11 +85,7 @@ struct _MetaScreen | ||||
|   /* Cache the current monitor */ | ||||
|   int last_monitor_index; | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   SnMonitorContext *sn_context; | ||||
|   GSList *startup_sequences; | ||||
|   guint startup_sequence_timeout; | ||||
| #endif | ||||
|  | ||||
|   Window wm_cm_selection_window; | ||||
|   guint work_area_later; | ||||
|   | ||||
| @@ -71,11 +71,6 @@ static void prefs_changed_callback (MetaPreference pref, | ||||
| static void set_desktop_geometry_hint (MetaScreen *screen); | ||||
| static void set_desktop_viewport_hint (MetaScreen *screen); | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| static void meta_screen_sn_event   (SnMonitorEvent *event, | ||||
|                                     void           *user_data); | ||||
| #endif | ||||
|  | ||||
| static void on_monitors_changed (MetaMonitorManager *manager, | ||||
|                                  MetaScreen         *screen); | ||||
|  | ||||
| @@ -730,17 +725,6 @@ meta_screen_new (MetaDisplay *display, | ||||
|  | ||||
|   meta_prefs_add_listener (prefs_changed_callback, screen); | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   screen->sn_context = | ||||
|     sn_monitor_context_new (screen->display->sn_display, | ||||
|                             screen->number, | ||||
|                             meta_screen_sn_event, | ||||
|                             screen, | ||||
|                             NULL); | ||||
|   screen->startup_sequences = NULL; | ||||
|   screen->startup_sequence_timeout = 0; | ||||
| #endif | ||||
|  | ||||
|   meta_verbose ("Added screen %d ('%s') root 0x%lx\n", | ||||
|                 screen->number, screen->screen_name, screen->xroot); | ||||
|  | ||||
| @@ -800,24 +784,6 @@ meta_screen_free (MetaScreen *screen, | ||||
|  | ||||
|   meta_screen_ungrab_keys (screen); | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   g_slist_foreach (screen->startup_sequences, | ||||
|                    (GFunc) sn_startup_sequence_unref, NULL); | ||||
|   g_slist_free (screen->startup_sequences); | ||||
|   screen->startup_sequences = NULL; | ||||
|  | ||||
|   if (screen->startup_sequence_timeout != 0) | ||||
|     { | ||||
|       g_source_remove (screen->startup_sequence_timeout); | ||||
|       screen->startup_sequence_timeout = 0; | ||||
|     } | ||||
|   if (screen->sn_context) | ||||
|     { | ||||
|       sn_monitor_context_unref (screen->sn_context); | ||||
|       screen->sn_context = NULL; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   meta_ui_free (screen->ui); | ||||
|  | ||||
|   meta_stack_free (screen->stack); | ||||
| @@ -2538,208 +2504,6 @@ meta_screen_unshow_desktop (MetaScreen *screen) | ||||
|   meta_screen_update_showing_desktop_hint (screen); | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| static gboolean startup_sequence_timeout (void *data); | ||||
|  | ||||
| static void | ||||
| update_startup_feedback (MetaScreen *screen) | ||||
| { | ||||
|   if (screen->startup_sequences != NULL) | ||||
|     { | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Setting busy cursor\n"); | ||||
|       meta_screen_set_cursor (screen, META_CURSOR_BUSY); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Setting default cursor\n"); | ||||
|       meta_screen_set_cursor (screen, META_CURSOR_DEFAULT); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| add_sequence (MetaScreen        *screen, | ||||
|               SnStartupSequence *sequence) | ||||
| { | ||||
|   meta_topic (META_DEBUG_STARTUP, | ||||
|               "Adding sequence %s\n", | ||||
|               sn_startup_sequence_get_id (sequence)); | ||||
|   sn_startup_sequence_ref (sequence); | ||||
|   screen->startup_sequences = g_slist_prepend (screen->startup_sequences, | ||||
|                                                sequence); | ||||
|  | ||||
|   /* our timeout just polls every second, instead of bothering | ||||
|    * to compute exactly when we may next time out | ||||
|    */ | ||||
|   if (screen->startup_sequence_timeout == 0) | ||||
|     { | ||||
|       screen->startup_sequence_timeout = g_timeout_add_seconds (1, | ||||
|                                                                 startup_sequence_timeout, | ||||
|                                                                 screen); | ||||
|       g_source_set_name_by_id (screen->startup_sequence_timeout, | ||||
|                                "[mutter] startup_sequence_timeout"); | ||||
|     } | ||||
|  | ||||
|   update_startup_feedback (screen); | ||||
| } | ||||
|  | ||||
| static void | ||||
| remove_sequence (MetaScreen        *screen, | ||||
|                  SnStartupSequence *sequence) | ||||
| { | ||||
|   meta_topic (META_DEBUG_STARTUP, | ||||
|               "Removing sequence %s\n", | ||||
|               sn_startup_sequence_get_id (sequence)); | ||||
|  | ||||
|   screen->startup_sequences = g_slist_remove (screen->startup_sequences, | ||||
|                                               sequence); | ||||
|  | ||||
|   if (screen->startup_sequences == NULL && | ||||
|       screen->startup_sequence_timeout != 0) | ||||
|     { | ||||
|       g_source_remove (screen->startup_sequence_timeout); | ||||
|       screen->startup_sequence_timeout = 0; | ||||
|     } | ||||
|  | ||||
|   update_startup_feedback (screen); | ||||
|  | ||||
|   sn_startup_sequence_unref (sequence); | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   GSList *list; | ||||
|   GTimeVal now; | ||||
| } CollectTimedOutData; | ||||
|  | ||||
| /* This should be fairly long, as it should never be required unless | ||||
|  * apps or .desktop files are buggy, and it's confusing if | ||||
|  * OpenOffice or whatever seems to stop launching - people | ||||
|  * might decide they need to launch it again. | ||||
|  */ | ||||
| #define STARTUP_TIMEOUT 15000 | ||||
|  | ||||
| static void | ||||
| collect_timed_out_foreach (void *element, | ||||
|                            void *data) | ||||
| { | ||||
|   CollectTimedOutData *ctod = data; | ||||
|   SnStartupSequence *sequence = element; | ||||
|   long tv_sec, tv_usec; | ||||
|   double elapsed; | ||||
|  | ||||
|   sn_startup_sequence_get_last_active_time (sequence, &tv_sec, &tv_usec); | ||||
|  | ||||
|   elapsed = | ||||
|     ((((double)ctod->now.tv_sec - tv_sec) * G_USEC_PER_SEC + | ||||
|       (ctod->now.tv_usec - tv_usec))) / 1000.0; | ||||
|  | ||||
|   meta_topic (META_DEBUG_STARTUP, | ||||
|               "Sequence used %g seconds vs. %g max: %s\n", | ||||
|               elapsed, (double) STARTUP_TIMEOUT, | ||||
|               sn_startup_sequence_get_id (sequence)); | ||||
|  | ||||
|   if (elapsed > STARTUP_TIMEOUT) | ||||
|     ctod->list = g_slist_prepend (ctod->list, sequence); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| startup_sequence_timeout (void *data) | ||||
| { | ||||
|   MetaScreen *screen = data; | ||||
|   CollectTimedOutData ctod; | ||||
|   GSList *l; | ||||
|  | ||||
|   ctod.list = NULL; | ||||
|   g_get_current_time (&ctod.now); | ||||
|   g_slist_foreach (screen->startup_sequences, | ||||
|                    collect_timed_out_foreach, | ||||
|                    &ctod); | ||||
|  | ||||
|   for (l = ctod.list; l != NULL; l = l->next) | ||||
|     { | ||||
|       SnStartupSequence *sequence = l->data; | ||||
|  | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Timed out sequence %s\n", | ||||
|                   sn_startup_sequence_get_id (sequence)); | ||||
|  | ||||
|       sn_startup_sequence_complete (sequence); | ||||
|     } | ||||
|  | ||||
|   g_slist_free (ctod.list); | ||||
|  | ||||
|   if (screen->startup_sequences != NULL) | ||||
|     { | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* remove */ | ||||
|       screen->startup_sequence_timeout = 0; | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_screen_sn_event (SnMonitorEvent *event, | ||||
|                       void           *user_data) | ||||
| { | ||||
|   MetaScreen *screen; | ||||
|   SnStartupSequence *sequence; | ||||
|  | ||||
|   screen = user_data; | ||||
|  | ||||
|   sequence = sn_monitor_event_get_startup_sequence (event); | ||||
|  | ||||
|   sn_startup_sequence_ref (sequence); | ||||
|  | ||||
|   switch (sn_monitor_event_get_type (event)) | ||||
|     { | ||||
|     case SN_MONITOR_EVENT_INITIATED: | ||||
|       { | ||||
|         const char *wmclass; | ||||
|  | ||||
|         wmclass = sn_startup_sequence_get_wmclass (sequence); | ||||
|  | ||||
|         meta_topic (META_DEBUG_STARTUP, | ||||
|                     "Received startup initiated for %s wmclass %s\n", | ||||
|                     sn_startup_sequence_get_id (sequence), | ||||
|                     wmclass ? wmclass : "(unset)"); | ||||
|         add_sequence (screen, sequence); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_COMPLETED: | ||||
|       { | ||||
|         meta_topic (META_DEBUG_STARTUP, | ||||
|                     "Received startup completed for %s\n", | ||||
|                     sn_startup_sequence_get_id (sequence)); | ||||
|         remove_sequence (screen, | ||||
|                          sn_monitor_event_get_startup_sequence (event)); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_CHANGED: | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Received startup changed for %s\n", | ||||
|                   sn_startup_sequence_get_id (sequence)); | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_CANCELED: | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Received startup canceled for %s\n", | ||||
|                   sn_startup_sequence_get_id (sequence)); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   g_signal_emit (G_OBJECT (screen), screen_signals[STARTUP_SEQUENCE_CHANGED], 0, sequence); | ||||
|  | ||||
|   sn_startup_sequence_unref (sequence); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_screen_get_startup_sequences: (skip) | ||||
|  * @screen: | ||||
| @@ -2751,7 +2515,6 @@ meta_screen_get_startup_sequences (MetaScreen *screen) | ||||
| { | ||||
|   return screen->startup_sequences; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Sets the initial_timestamp and initial_workspace properties | ||||
|  * of a window according to information given us by the | ||||
|   | ||||
							
								
								
									
										48
									
								
								src/core/startup-notification-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/core/startup-notification-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001, 2002 Havoc Pennington | ||||
|  * Copyright (C) 2002, 2003 Red Hat Inc. | ||||
|  * Some ICCCM manager selection code derived from fvwm2, | ||||
|  * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_STARTUP_NOTIFICATION_PRIVATE_H | ||||
| #define META_STARTUP_NOTIFICATION_PRIVATE_H | ||||
|  | ||||
| #include "display-private.h" | ||||
|  | ||||
| #define META_TYPE_STARTUP_NOTIFICATION (meta_startup_notification_get_type ()) | ||||
|  | ||||
| G_DECLARE_FINAL_TYPE (MetaStartupNotification, | ||||
|                       meta_startup_notification, | ||||
|                       META, STARTUP_NOTIFICATION, | ||||
|                       GObject) | ||||
|  | ||||
| MetaStartupNotification * | ||||
|          meta_startup_notification_get             (MetaDisplay             *display); | ||||
|  | ||||
| gboolean meta_startup_notification_handle_xevent   (MetaStartupNotification *sn, | ||||
|                                                     XEvent                  *xevent); | ||||
|  | ||||
| void     meta_startup_notification_remove_sequence (MetaStartupNotification *sn, | ||||
|                                                     const gchar             *id); | ||||
|  | ||||
| GSList * meta_startup_notification_get_sequences   (MetaStartupNotification *sn); | ||||
|  | ||||
| #endif /* META_STARTUP_NOTIFICATION_PRIVATE_H */ | ||||
							
								
								
									
										735
									
								
								src/core/startup-notification.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										735
									
								
								src/core/startup-notification.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,735 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001, 2002 Havoc Pennington | ||||
|  * Copyright (C) 2002, 2003 Red Hat Inc. | ||||
|  * Some ICCCM manager selection code derived from fvwm2, | ||||
|  * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include <meta/errors.h> | ||||
| #include "display-private.h" | ||||
| #include "screen-private.h" | ||||
| #include "startup-notification-private.h" | ||||
|  | ||||
| /* This should be fairly long, as it should never be required unless | ||||
|  * apps or .desktop files are buggy, and it's confusing if | ||||
|  * OpenOffice or whatever seems to stop launching - people | ||||
|  * might decide they need to launch it again. | ||||
|  */ | ||||
| #define STARTUP_TIMEOUT 15000000 | ||||
|  | ||||
| typedef struct _MetaStartupNotification MetaStartupNotification; | ||||
| typedef struct _MetaStartupNotificationSequence MetaStartupNotificationSequence; | ||||
| typedef struct _MetaStartupNotificationSequenceClass MetaStartupNotificationSequenceClass; | ||||
| typedef struct _MetaStartupNotificationSequenceX11 MetaStartupNotificationSequenceX11; | ||||
| typedef struct _MetaStartupNotificationSequenceX11Class MetaStartupNotificationSequenceX11Class; | ||||
|  | ||||
| enum { | ||||
|   PROP_SN_0, | ||||
|   PROP_SN_DISPLAY, | ||||
|   N_SN_PROPS | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|   PROP_SEQ_0, | ||||
|   PROP_SEQ_ID, | ||||
|   PROP_SEQ_TIMESTAMP, | ||||
|   N_SEQ_PROPS | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|   SN_CHANGED, | ||||
|   N_SN_SIGNALS | ||||
| }; | ||||
|  | ||||
| static guint sn_signals[N_SN_SIGNALS]; | ||||
| static GParamSpec *sn_props[N_SN_PROPS]; | ||||
| static GParamSpec *seq_props[N_SEQ_PROPS]; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   GSList *list; | ||||
|   gint64 now; | ||||
| } CollectTimedOutData; | ||||
|  | ||||
| struct _MetaStartupNotification | ||||
| { | ||||
|   GObject parent_instance; | ||||
|   MetaDisplay *display; | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   SnDisplay *sn_display; | ||||
|   SnMonitorContext *sn_context; | ||||
| #endif | ||||
|  | ||||
|   GSList *startup_sequences; | ||||
|   guint startup_sequence_timeout; | ||||
| }; | ||||
|  | ||||
| struct _MetaStartupNotificationSequence { | ||||
|   GObject parent_instance; | ||||
|   gchar *id; | ||||
|   time_t timestamp; | ||||
| }; | ||||
|  | ||||
| struct _MetaStartupNotificationSequenceClass { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (* complete) (MetaStartupNotificationSequence *sequence); | ||||
| }; | ||||
|  | ||||
| GType meta_startup_notification_get_type (void) G_GNUC_CONST; | ||||
| GType meta_startup_notification_sequence_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| #define META_TYPE_STARTUP_NOTIFICATION_SEQUENCE         (meta_startup_notification_sequence_get_type ()) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE, MetaStartupNotificationSequence)) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE, MetaStartupNotificationSequenceClass)) | ||||
| #define META_IS_STARTUP_NOTIFICATION_SEQUENCE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE)) | ||||
| #define META_IS_STARTUP_NOTIFICATION_SEQUENCE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE)) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE, MetaStartupNotificationSequenceClass)) | ||||
|  | ||||
| G_DEFINE_TYPE (MetaStartupNotification, | ||||
|                meta_startup_notification, | ||||
|                G_TYPE_OBJECT) | ||||
| G_DEFINE_TYPE (MetaStartupNotificationSequence, | ||||
|                meta_startup_notification_sequence, | ||||
|                G_TYPE_OBJECT) | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|  | ||||
| enum { | ||||
|   PROP_SEQ_X11_0, | ||||
|   PROP_SEQ_X11_SEQ, | ||||
|   N_SEQ_X11_PROPS | ||||
| }; | ||||
|  | ||||
| struct _MetaStartupNotificationSequenceX11 { | ||||
|   MetaStartupNotificationSequence parent_instance; | ||||
|   SnStartupSequence *seq; | ||||
| }; | ||||
|  | ||||
| struct _MetaStartupNotificationSequenceX11Class { | ||||
|   MetaStartupNotificationSequenceClass parent_class; | ||||
| }; | ||||
|  | ||||
| static GParamSpec *seq_x11_props[N_SEQ_X11_PROPS]; | ||||
|  | ||||
| GType meta_startup_notification_sequence_x11_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| #define META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11         (meta_startup_notification_sequence_x11_get_type ()) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE_X11(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11, MetaStartupNotificationSequenceX11)) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE_X11_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11, MetaStartupNotificationSequenceX11Class)) | ||||
| #define META_IS_STARTUP_NOTIFICATION_SEQUENCE_X11(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11)) | ||||
| #define META_IS_STARTUP_NOTIFICATION_SEQUENCE_X11_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11)) | ||||
| #define META_STARTUP_NOTIFICATION_SEQUENCE_X11_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), META_TYPE_STARTUP_NOTIFICATION_SEQUENCE_X11, MetaStartupNotificationSequenceX11Class)) | ||||
|  | ||||
| G_DEFINE_TYPE (MetaStartupNotificationSequenceX11, | ||||
|                meta_startup_notification_sequence_x11, | ||||
|                META_TYPE_STARTUP_NOTIFICATION_SEQUENCE) | ||||
|  | ||||
| static void meta_startup_notification_ensure_timeout  (MetaStartupNotification *sn); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_update_feedback (MetaStartupNotification *sn) | ||||
| { | ||||
|   MetaScreen *screen = sn->display->screen; | ||||
|  | ||||
|   if (sn->startup_sequences != NULL) | ||||
|     { | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Setting busy cursor\n"); | ||||
|       meta_screen_set_cursor (screen, META_CURSOR_BUSY); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Setting default cursor\n"); | ||||
|       meta_screen_set_cursor (screen, META_CURSOR_DEFAULT); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_init (MetaStartupNotificationSequence *seq) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_finalize (GObject *object) | ||||
| { | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE (object); | ||||
|   g_free (seq->id); | ||||
|   G_OBJECT_CLASS (meta_startup_notification_sequence_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_set_property (GObject      *object, | ||||
|                                                  guint         prop_id, | ||||
|                                                  const GValue *value, | ||||
|                                                  GParamSpec   *pspec) | ||||
| { | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SEQ_ID: | ||||
|       seq->id = g_value_dup_string (value); | ||||
|       break; | ||||
|     case PROP_SEQ_TIMESTAMP: | ||||
|       seq->timestamp = g_value_get_int64 (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_get_property (GObject    *object, | ||||
|                                                  guint       prop_id, | ||||
|                                                  GValue     *value, | ||||
|                                                  GParamSpec *pspec) | ||||
| { | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SEQ_ID: | ||||
|       g_value_set_string (value, seq->id); | ||||
|       break; | ||||
|     case PROP_SEQ_TIMESTAMP: | ||||
|       g_value_set_int64 (value, seq->timestamp); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_class_init (MetaStartupNotificationSequenceClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class; | ||||
|  | ||||
|   object_class = G_OBJECT_CLASS (klass); | ||||
|   object_class->finalize = meta_startup_notification_sequence_finalize; | ||||
|   object_class->set_property = meta_startup_notification_sequence_set_property; | ||||
|   object_class->get_property = meta_startup_notification_sequence_get_property; | ||||
|  | ||||
|   seq_props[PROP_SEQ_ID] = | ||||
|     g_param_spec_string ("id", | ||||
|                          "ID", | ||||
|                          "ID", | ||||
|                          NULL, | ||||
|                          G_PARAM_READWRITE | | ||||
|                          G_PARAM_CONSTRUCT_ONLY); | ||||
|   seq_props[PROP_SEQ_TIMESTAMP] = | ||||
|     g_param_spec_int64 ("timestamp", | ||||
|                         "Timestamp", | ||||
|                         "Timestamp", | ||||
|                         G_MININT64, G_MAXINT64, 0, | ||||
|                         G_PARAM_READWRITE | | ||||
|                         G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_properties (object_class, N_SEQ_PROPS, seq_props); | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| static void | ||||
| meta_startup_notification_sequence_complete (MetaStartupNotificationSequence *seq) | ||||
| { | ||||
|   MetaStartupNotificationSequenceClass *klass; | ||||
|  | ||||
|   klass = META_STARTUP_NOTIFICATION_SEQUENCE_GET_CLASS (seq); | ||||
|  | ||||
|   if (klass->complete) | ||||
|     klass->complete (seq); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_complete (MetaStartupNotificationSequence *seq) | ||||
| { | ||||
|   MetaStartupNotificationSequenceX11 *seq_x11; | ||||
|  | ||||
|   seq_x11 = META_STARTUP_NOTIFICATION_SEQUENCE_X11 (seq); | ||||
|   sn_startup_sequence_complete (seq_x11->seq); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_finalize (GObject *object) | ||||
| { | ||||
|   MetaStartupNotificationSequenceX11 *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE_X11 (object); | ||||
|   sn_startup_sequence_unref (seq->seq); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_startup_notification_sequence_x11_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_set_property (GObject      *object, | ||||
|                                                      guint         prop_id, | ||||
|                                                      const GValue *value, | ||||
|                                                      GParamSpec   *pspec) | ||||
| { | ||||
|   MetaStartupNotificationSequenceX11 *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE_X11 (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SEQ_X11_SEQ: | ||||
|       seq->seq = g_value_get_pointer (value); | ||||
|       sn_startup_sequence_ref (seq->seq); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_get_property (GObject    *object, | ||||
|                                                      guint       prop_id, | ||||
|                                                      GValue     *value, | ||||
|                                                      GParamSpec *pspec) | ||||
| { | ||||
|   MetaStartupNotificationSequenceX11 *seq; | ||||
|  | ||||
|   seq = META_STARTUP_NOTIFICATION_SEQUENCE_X11 (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SEQ_X11_SEQ: | ||||
|       g_value_set_pointer (value, seq->seq); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_init (MetaStartupNotificationSequenceX11 *seq) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sequence_x11_class_init (MetaStartupNotificationSequenceX11Class *klass) | ||||
| { | ||||
|   MetaStartupNotificationSequenceClass *seq_class; | ||||
|   GObjectClass *object_class; | ||||
|  | ||||
|   seq_class = META_STARTUP_NOTIFICATION_SEQUENCE_CLASS (klass); | ||||
|   seq_class->complete = meta_startup_notification_sequence_x11_complete; | ||||
|  | ||||
|   object_class = G_OBJECT_CLASS (klass); | ||||
|   object_class->finalize = meta_startup_notification_sequence_x11_finalize; | ||||
|   object_class->set_property = meta_startup_notification_sequence_x11_set_property; | ||||
|   object_class->get_property = meta_startup_notification_sequence_x11_get_property; | ||||
|  | ||||
|   seq_x11_props[PROP_SEQ_X11_SEQ] = | ||||
|     g_param_spec_pointer ("seq", | ||||
|                           "Sequence", | ||||
|                           "Sequence", | ||||
|                           G_PARAM_READWRITE | | ||||
|                           G_PARAM_CONSTRUCT_ONLY); | ||||
|  | ||||
|   g_object_class_install_properties (object_class, N_SEQ_X11_PROPS, | ||||
|                                      seq_x11_props); | ||||
| } | ||||
|  | ||||
| static MetaStartupNotificationSequence * | ||||
| meta_startup_notification_sequence_x11_new (SnStartupSequence *seq) | ||||
| { | ||||
|   return g_object_new (meta_startup_notification_sequence_x11_get_type (), | ||||
|                        "id", sn_startup_sequence_get_id (seq), | ||||
|                        "timestamp", sn_startup_sequence_get_timestamp (seq) * 1000, | ||||
|                        "seq", seq, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_add_sequence_internal (MetaStartupNotification         *sn, | ||||
|                                                  MetaStartupNotificationSequence *seq) | ||||
| { | ||||
|   sn->startup_sequences = g_slist_prepend (sn->startup_sequences, | ||||
|                                            g_object_ref (seq)); | ||||
|  | ||||
|   meta_startup_notification_ensure_timeout (sn); | ||||
|   meta_startup_notification_update_feedback (sn); | ||||
| } | ||||
|  | ||||
| static void | ||||
| collect_timed_out_foreach (void *element, | ||||
|                            void *data) | ||||
| { | ||||
|   MetaStartupNotificationSequence *sequence = element; | ||||
|   CollectTimedOutData *ctod = data; | ||||
|   gint64 elapsed; | ||||
|  | ||||
|   elapsed = ctod->now - sequence->timestamp; | ||||
|  | ||||
|   meta_topic (META_DEBUG_STARTUP, | ||||
|               "Sequence used %ld ms vs. %d max: %s\n", | ||||
|               elapsed, STARTUP_TIMEOUT, sequence->id); | ||||
|  | ||||
|   if (elapsed > STARTUP_TIMEOUT) | ||||
|     ctod->list = g_slist_prepend (ctod->list, sequence); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| startup_sequence_timeout (void *data) | ||||
| { | ||||
|   MetaStartupNotification *sn = data; | ||||
|   CollectTimedOutData ctod; | ||||
|   GSList *l; | ||||
|  | ||||
|   ctod.list = NULL; | ||||
|   ctod.now = g_get_monotonic_time (); | ||||
|   g_slist_foreach (sn->startup_sequences, | ||||
|                    collect_timed_out_foreach, | ||||
|                    &ctod); | ||||
|  | ||||
|   for (l = ctod.list; l != NULL; l = l->next) | ||||
|     { | ||||
|       MetaStartupNotificationSequence *sequence = l->data; | ||||
|  | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Timed out sequence %s\n", | ||||
|                   sequence->id); | ||||
|  | ||||
|       meta_startup_notification_sequence_complete (sequence); | ||||
|     } | ||||
|  | ||||
|   g_slist_free (ctod.list); | ||||
|  | ||||
|   if (sn->startup_sequences != NULL) | ||||
|     { | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* remove */ | ||||
|       sn->startup_sequence_timeout = 0; | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_ensure_timeout (MetaStartupNotification *sn) | ||||
| { | ||||
|   if (sn->startup_sequence_timeout != 0) | ||||
|     return; | ||||
|  | ||||
|   /* our timeout just polls every second, instead of bothering | ||||
|    * to compute exactly when we may next time out | ||||
|    */ | ||||
|   sn->startup_sequence_timeout = g_timeout_add_seconds (1, | ||||
|                                                         startup_sequence_timeout, | ||||
|                                                         sn); | ||||
|   g_source_set_name_by_id (sn->startup_sequence_timeout, | ||||
|                            "[mutter] startup_sequence_timeout"); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_remove_sequence_internal (MetaStartupNotification         *sn, | ||||
|                                                     MetaStartupNotificationSequence *seq) | ||||
| { | ||||
|   sn->startup_sequences = g_slist_remove (sn->startup_sequences, seq); | ||||
|   meta_startup_notification_update_feedback (sn); | ||||
|  | ||||
|   if (sn->startup_sequences == NULL && | ||||
|       sn->startup_sequence_timeout != 0) | ||||
|     { | ||||
|       g_source_remove (sn->startup_sequence_timeout); | ||||
|       sn->startup_sequence_timeout = 0; | ||||
|     } | ||||
|  | ||||
|   g_object_unref (seq); | ||||
| } | ||||
|  | ||||
| static MetaStartupNotificationSequence * | ||||
| meta_startup_notification_lookup_sequence (MetaStartupNotification *sn, | ||||
|                                            const gchar             *id) | ||||
| { | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|   GSList *l; | ||||
|  | ||||
|   for (l = sn->startup_sequences; l; l = l->next) | ||||
|     { | ||||
|       seq = l->data; | ||||
|  | ||||
|       if (g_str_equal (seq->id, id)) | ||||
|         return l->data; | ||||
|     } | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_init (MetaStartupNotification *sn) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_finalize (GObject *object) | ||||
| { | ||||
|   MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); | ||||
|  | ||||
|   sn_monitor_context_unref (sn->sn_context); | ||||
|   G_OBJECT_CLASS (meta_startup_notification_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_set_property (GObject      *object, | ||||
|                                         guint         prop_id, | ||||
|                                         const GValue *value, | ||||
|                                         GParamSpec   *pspec) | ||||
| { | ||||
|   MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SN_DISPLAY: | ||||
|       sn->display = g_value_get_object (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_get_property (GObject    *object, | ||||
|                                         guint       prop_id, | ||||
|                                         GValue     *value, | ||||
|                                         GParamSpec *pspec) | ||||
| { | ||||
|   MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_SN_DISPLAY: | ||||
|       g_value_set_object (value, sn->display); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| static void | ||||
| sn_error_trap_push (SnDisplay *sn_display, | ||||
|                     Display   *xdisplay) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|   display = meta_display_for_x_display (xdisplay); | ||||
|   if (display != NULL) | ||||
|     meta_error_trap_push (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sn_error_trap_pop (SnDisplay *sn_display, | ||||
|                    Display   *xdisplay) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|   display = meta_display_for_x_display (xdisplay); | ||||
|   if (display != NULL) | ||||
|     meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_sn_event (SnMonitorEvent *event, | ||||
|                                     void           *user_data) | ||||
| { | ||||
|   MetaStartupNotification *sn = user_data; | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|   SnStartupSequence *sequence; | ||||
|  | ||||
|   sequence = sn_monitor_event_get_startup_sequence (event); | ||||
|  | ||||
|   sn_startup_sequence_ref (sequence); | ||||
|  | ||||
|   switch (sn_monitor_event_get_type (event)) | ||||
|     { | ||||
|     case SN_MONITOR_EVENT_INITIATED: | ||||
|       { | ||||
|         const char *wmclass; | ||||
|  | ||||
|         wmclass = sn_startup_sequence_get_wmclass (sequence); | ||||
|  | ||||
|         meta_topic (META_DEBUG_STARTUP, | ||||
|                     "Received startup initiated for %s wmclass %s\n", | ||||
|                     sn_startup_sequence_get_id (sequence), | ||||
|                     wmclass ? wmclass : "(unset)"); | ||||
|  | ||||
|         seq = meta_startup_notification_sequence_x11_new (sequence); | ||||
|         meta_startup_notification_add_sequence_internal (sn, seq); | ||||
|         g_object_unref (seq); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_COMPLETED: | ||||
|       { | ||||
|         meta_topic (META_DEBUG_STARTUP, | ||||
|                     "Received startup completed for %s\n", | ||||
|                     sn_startup_sequence_get_id (sequence)); | ||||
|  | ||||
|         meta_startup_notification_remove_sequence (sn, sn_startup_sequence_get_id (sequence)); | ||||
|       } | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_CHANGED: | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Received startup changed for %s\n", | ||||
|                   sn_startup_sequence_get_id (sequence)); | ||||
|       break; | ||||
|  | ||||
|     case SN_MONITOR_EVENT_CANCELED: | ||||
|       meta_topic (META_DEBUG_STARTUP, | ||||
|                   "Received startup canceled for %s\n", | ||||
|                   sn_startup_sequence_get_id (sequence)); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   g_signal_emit (sn, sn_signals[SN_CHANGED], 0, sequence); | ||||
|  | ||||
|   sn_startup_sequence_unref (sequence); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_constructed (GObject *object) | ||||
| { | ||||
|   MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); | ||||
|  | ||||
|   g_assert (sn->display != NULL); | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   sn->sn_display = sn_display_new (sn->display->xdisplay, | ||||
|                                    sn_error_trap_push, | ||||
|                                    sn_error_trap_pop); | ||||
|   sn->sn_context = | ||||
|     sn_monitor_context_new (sn->sn_display, | ||||
|                             sn->display->screen->number, | ||||
|                             meta_startup_notification_sn_event, | ||||
|                             sn, | ||||
|                             NULL); | ||||
|   sn->startup_sequences = NULL; | ||||
|   sn->startup_sequence_timeout = 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_startup_notification_class_init (MetaStartupNotificationClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->constructed = meta_startup_notification_constructed; | ||||
|   object_class->finalize = meta_startup_notification_finalize; | ||||
|   object_class->set_property = meta_startup_notification_set_property; | ||||
|   object_class->get_property = meta_startup_notification_get_property; | ||||
|  | ||||
|   sn_props[PROP_SN_DISPLAY] = | ||||
|     g_param_spec_object ("display", | ||||
|                          "Display", | ||||
|                          "Display", | ||||
|                          META_TYPE_DISPLAY, | ||||
|                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | | ||||
|                          G_PARAM_STATIC_STRINGS); | ||||
|  | ||||
|   sn_signals[SN_CHANGED] = | ||||
|     g_signal_new ("changed", | ||||
|                   META_TYPE_STARTUP_NOTIFICATION, | ||||
|                   G_SIGNAL_RUN_LAST, | ||||
|                   0, NULL, NULL, NULL, | ||||
|                   G_TYPE_NONE, 1, G_TYPE_POINTER); | ||||
|  | ||||
|   g_object_class_install_properties (object_class, N_SN_PROPS, sn_props); | ||||
| } | ||||
|  | ||||
| MetaStartupNotification * | ||||
| meta_startup_notification_get (MetaDisplay *display) | ||||
| { | ||||
|   static MetaStartupNotification *notification = NULL; | ||||
|  | ||||
|   if (!notification) | ||||
|     notification = g_object_new (META_TYPE_STARTUP_NOTIFICATION, | ||||
|                                  "display", display, | ||||
|                                  NULL); | ||||
|  | ||||
|   return notification; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_startup_notification_remove_sequence (MetaStartupNotification *sn, | ||||
|                                            const gchar             *id) | ||||
| { | ||||
|   MetaStartupNotificationSequence *seq; | ||||
|  | ||||
|   seq = meta_startup_notification_lookup_sequence (sn, id); | ||||
|   if (seq) | ||||
|     meta_startup_notification_remove_sequence_internal (sn, seq); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_startup_notification_handle_xevent (MetaStartupNotification *sn, | ||||
|                                          XEvent                  *xevent) | ||||
| { | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   return sn_display_process_event (sn->sn_display, xevent); | ||||
| #endif | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| GSList * | ||||
| meta_startup_notification_get_sequences (MetaStartupNotification *sn) | ||||
| { | ||||
|   GSList *l, *sequences = NULL; | ||||
|  | ||||
|   /* We return a list of SnStartupSequences here */ | ||||
|   for (l = sn->startup_sequences; l; l = l->next) | ||||
|     { | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|       MetaStartupNotificationSequenceX11 *seq_x11; | ||||
|  | ||||
|       if (!META_IS_STARTUP_NOTIFICATION_SEQUENCE_X11 (l->data)) | ||||
|         continue; | ||||
|  | ||||
|       seq_x11 = META_STARTUP_NOTIFICATION_SEQUENCE_X11 (l->data); | ||||
|       sequences = g_slist_prepend (sequences, seq_x11->seq); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|   return sequences; | ||||
| } | ||||
| @@ -2029,8 +2029,21 @@ get_gtk_surface (struct wl_client *client, | ||||
|   wl_resource_set_implementation (surface->gtk_surface, &meta_wayland_gtk_surface_interface, surface, gtk_surface_destructor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_startup_id (struct wl_client   *client, | ||||
|                 struct wl_resource *resource, | ||||
|                 const char         *startup_id) | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|  | ||||
|   display = meta_get_display (); | ||||
|   meta_startup_notification_remove_sequence (display->startup_notification, | ||||
|                                              startup_id); | ||||
| } | ||||
|  | ||||
| static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = { | ||||
|   get_gtk_surface | ||||
|   get_gtk_surface, | ||||
|   set_startup_id | ||||
| }; | ||||
|  | ||||
| static void | ||||
| @@ -2044,7 +2057,7 @@ bind_gtk_shell (struct wl_client *client, | ||||
|  | ||||
|   resource = wl_resource_create (client, >k_shell_interface, version, id); | ||||
|  | ||||
|   if (version != META_GTK_SHELL_VERSION) | ||||
|   if (version < 2) | ||||
|     { | ||||
|       wl_resource_post_error (resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
|   | ||||
| @@ -42,7 +42,7 @@ | ||||
| #define META_WL_SEAT_VERSION                5 | ||||
| #define META_WL_OUTPUT_VERSION              2 | ||||
| #define META_XSERVER_VERSION                1 | ||||
| #define META_GTK_SHELL_VERSION              2 | ||||
| #define META_GTK_SHELL_VERSION              3 | ||||
| #define META_WL_SUBCOMPOSITOR_VERSION       1 | ||||
| #define META_ZWP_POINTER_GESTURES_V1_VERSION    1 | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <protocol name="gtk"> | ||||
|  | ||||
|   <interface name="gtk_shell" version="2"> | ||||
|   <interface name="gtk_shell" version="3"> | ||||
|     <description summary="gtk specific extensions"> | ||||
|       gtk_shell is a protocol extension providing additional features for | ||||
|       clients implementing it. It is not backward compatible, and a client must | ||||
| @@ -23,9 +23,13 @@ | ||||
|       <arg name="gtk_surface" type="new_id" interface="gtk_surface"/> | ||||
|       <arg name="surface" type="object" interface="wl_surface"/> | ||||
|     </request> | ||||
|  | ||||
|     <request name="set_startup_id" since="3"> | ||||
|       <arg name="startup_id" type="string" allow-null="true"/> | ||||
|     </request> | ||||
|   </interface> | ||||
|  | ||||
|   <interface name="gtk_surface" version="2"> | ||||
|   <interface name="gtk_surface" version="3"> | ||||
|     <request name="set_dbus_properties"> | ||||
|       <arg name="application_id" type="string" allow-null="true"/> | ||||
|       <arg name="app_menu_path" type="string" allow-null="true"/> | ||||
|   | ||||
| @@ -1671,13 +1671,12 @@ meta_display_handle_xevent (MetaDisplay *display, | ||||
|   meta_spew_event_print (display, event); | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
|   if (sn_display_process_event (display->sn_display, event)) | ||||
|   if (meta_startup_notification_handle_xevent (display->startup_notification, | ||||
|                                                event)) | ||||
|     { | ||||
|       bypass_gtk = bypass_compositor = TRUE; | ||||
|       goto out; | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
|   if (meta_is_wayland_compositor () && | ||||
|   | ||||
		Reference in New Issue
	
	Block a user