summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Krezović <krezovic.armin@gmail.com>2017-08-26 22:35:18 +0200
committerJonas Ådahl <jadahl@gmail.com>2018-07-06 19:47:16 +0200
commit9333a6da750a75367d1d6fa657c122f69c7add2f (patch)
tree4f02efaf1600f858ae437e0d0dc033f2e95b5788
parent8adab0275703b5a426a54d3112ce37b24345f356 (diff)
downloadmutter-9333a6da750a75367d1d6fa657c122f69c7add2f.tar.gz
Make bell and libstartup-notification bits work without X11
https://bugzilla.gnome.org/show_bug.cgi?id=759538
-rw-r--r--src/core/bell.c130
-rw-r--r--src/core/bell.h54
-rw-r--r--src/core/display-private.h6
-rw-r--r--src/core/display.c26
-rw-r--r--src/core/startup-notification.c57
-rw-r--r--src/x11/events.c18
-rw-r--r--src/x11/meta-x11-display-private.h3
-rw-r--r--src/x11/meta-x11-display.c101
8 files changed, 244 insertions, 151 deletions
diff --git a/src/core/bell.c b/src/core/bell.c
index 193be1c78..b4acf7aef 100644
--- a/src/core/bell.c
+++ b/src/core/bell.c
@@ -52,13 +52,73 @@
#include "window-private.h"
#include "util-private.h"
#include "compositor/compositor-private.h"
-#include "x11/meta-x11-display-private.h"
-#include <meta/prefs.h>
#include <meta/compositor.h>
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
+G_DEFINE_TYPE (MetaBell, meta_bell, G_TYPE_OBJECT)
+
+enum
+{
+ IS_AUDIBLE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint bell_signals [LAST_SIGNAL] = { 0 };
+
+static void
+prefs_changed_callback (MetaPreference pref,
+ gpointer data)
+{
+ MetaBell *bell = data;
+
+ if (pref == META_PREF_AUDIBLE_BELL)
+ {
+ g_signal_emit (bell, bell_signals[IS_AUDIBLE_CHANGED], 0,
+ meta_prefs_bell_is_audible ());
+ }
+}
+
+static void
+meta_bell_finalize (GObject *object)
+{
+ MetaBell *bell = META_BELL (object);
+
+ meta_prefs_remove_listener (prefs_changed_callback, bell);
+
+ G_OBJECT_CLASS (meta_bell_parent_class)->finalize (object);
+}
+
+static void
+meta_bell_class_init (MetaBellClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meta_bell_finalize;
+
+ bell_signals[IS_AUDIBLE_CHANGED] =
+ g_signal_new ("is-audible-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+}
+
+static void
+meta_bell_init (MetaBell *bell)
+{
+ meta_prefs_add_listener (prefs_changed_callback, bell);
+}
+
+MetaBell *
+meta_bell_new (MetaDisplay *display)
+{
+ return g_object_new (META_TYPE_BELL, NULL);
+}
+
/**
* bell_flash_fullscreen:
* @display: The display the event came in on
@@ -226,72 +286,6 @@ meta_bell_notify (MetaDisplay *display,
return TRUE;
}
-void
-meta_bell_set_audible (MetaDisplay *display, gboolean audible)
-{
- MetaX11Display *x11_display = display->x11_display;
-#ifdef HAVE_LIBCANBERRA
- /* When we are playing sounds using libcanberra support, we handle the
- * bell whether its an audible bell or a visible bell */
- gboolean enable_system_bell = FALSE;
-#else
- gboolean enable_system_bell = audible;
-#endif /* HAVE_LIBCANBERRA */
-
- XkbChangeEnabledControls (x11_display->xdisplay,
- XkbUseCoreKbd,
- XkbAudibleBellMask,
- enable_system_bell ? XkbAudibleBellMask : 0);
-}
-
-gboolean
-meta_bell_init (MetaDisplay *display)
-{
- int xkb_base_error_type, xkb_opcode;
- MetaX11Display *x11_display = display->x11_display;
-
- if (!XkbQueryExtension (x11_display->xdisplay, &xkb_opcode,
- &display->xkb_base_event_type,
- &xkb_base_error_type,
- NULL, NULL))
- {
- display->xkb_base_event_type = -1;
- g_message ("could not find XKB extension.");
- return FALSE;
- }
- else
- {
- unsigned int mask = XkbBellNotifyMask;
- gboolean visual_bell_auto_reset = FALSE;
- /* TRUE if and when non-broken version is available */
- XkbSelectEvents (x11_display->xdisplay,
- XkbUseCoreKbd,
- XkbBellNotifyMask,
- XkbBellNotifyMask);
- meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
- if (visual_bell_auto_reset) {
- XkbSetAutoResetControls (x11_display->xdisplay,
- XkbAudibleBellMask,
- &mask,
- &mask);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-void
-meta_bell_shutdown (MetaDisplay *display)
-{
- MetaX11Display *x11_display = display->x11_display;
-
- /* TODO: persist initial bell state in display, reset here */
- XkbChangeEnabledControls (x11_display->xdisplay,
- XkbUseCoreKbd,
- XkbAudibleBellMask,
- XkbAudibleBellMask);
-}
-
/**
* meta_bell_notify_frame_destroy:
* @frame: The frame which is being destroyed
diff --git a/src/core/bell.h b/src/core/bell.h
index 2e9cd3906..fbf132c7a 100644
--- a/src/core/bell.h
+++ b/src/core/bell.h
@@ -17,11 +17,19 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <X11/Xlib.h>
-#include <X11/XKBlib.h>
#include "display-private.h"
#include "frame.h"
+struct _MetaBell
+{
+ GObject parent;
+};
+
+#define META_TYPE_BELL (meta_bell_get_type ())
+G_DECLARE_FINAL_TYPE (MetaBell, meta_bell, META, BELL, GObject)
+
+MetaBell * meta_bell_new (MetaDisplay *display);
+
/**
* meta_bell_notify:
* @display: The display the bell event came in on
@@ -35,48 +43,6 @@ gboolean meta_bell_notify (MetaDisplay *display,
MetaWindow *window);
/**
- * meta_bell_set_audible:
- * @display: The display we're configuring
- * @audible: True for an audible bell, false for a visual bell
- *
- * Turns the bell to audible or visual. This tells X what to do, but
- * not Mutter; you will need to set the "visual bell" pref for that.
- *
- * If the configure script found we had no XKB, this is a no-op.
- */
-void meta_bell_set_audible (MetaDisplay *display, gboolean audible);
-
-/**
- * meta_bell_init:
- * @display: The display which is opening
- *
- * Initialises the bell subsystem. This involves intialising
- * XKB (which, despite being a keyboard extension, is the
- * place to look for bell notifications), then asking it
- * to send us bell notifications, and then also switching
- * off the audible bell if we're using a visual one ourselves.
- *
- * \bug There is a line of code that's never run that tells
- * XKB to reset the bell status after we quit. Bill H said
- * (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
- * that XFree86's implementation is broken so we shouldn't
- * call it, but that was in 2002. Is it working now?
- */
-gboolean meta_bell_init (MetaDisplay *display);
-
-/**
- * meta_bell_shutdown:
- * @display: The display which is closing
- *
- * Shuts down the bell subsystem.
- *
- * \bug This is never called! If we had XkbSetAutoResetControls
- * enabled in meta_bell_init(), this wouldn't be a problem, but
- * we don't.
- */
-void meta_bell_shutdown (MetaDisplay *display);
-
-/**
* meta_bell_notify_frame_destroy:
* @frame: The frame which is being destroyed
*
diff --git a/src/core/display-private.h b/src/core/display-private.h
index d73616022..122387c09 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -48,6 +48,7 @@
#include <X11/extensions/sync.h>
+typedef struct _MetaBell MetaBell;
typedef struct _MetaStack MetaStack;
typedef struct _MetaUISlave MetaUISlave;
@@ -205,9 +206,6 @@ struct _MetaDisplay
* to avoid some race conditions on EnterNotify events
*/
int sentinel_counter;
-
- int xkb_base_event_type;
- guint32 last_bell_time;
int grab_resize_timeout_id;
MetaKeyBindingManager key_binding_manager;
@@ -254,6 +252,8 @@ struct _MetaDisplay
MetaDisplayCorner starting_corner;
guint vertical_workspaces : 1;
guint workspace_layout_overridden : 1;
+
+ MetaBell *bell;
};
struct _MetaDisplayClass
diff --git a/src/core/display.c b/src/core/display.c
index 8e81f1fbd..4c7ce3998 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -765,7 +765,6 @@ meta_display_open (void)
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
- display->last_bell_time = 0;
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
@@ -804,7 +803,6 @@ meta_display_open (void)
meta_display_set_cursor (display, META_CURSOR_DEFAULT);
-
/* This is the default layout extracted from default
* variable values in update_num_workspaces ()
* This can be overriden using _NET_DESKTOP_LAYOUT in
@@ -824,6 +822,12 @@ meta_display_open (void)
reload_logical_monitors (display);
+ display->startup_notification = meta_startup_notification_get (display);
+ g_signal_connect (display->startup_notification, "changed",
+ G_CALLBACK (on_startup_notification_changed), display);
+
+ display->bell = meta_bell_new (display);
+
x11_display = meta_x11_display_new (display, &error);
g_assert (x11_display != NULL); /* Required, for now */
display->x11_display = x11_display;
@@ -834,8 +838,6 @@ meta_display_open (void)
display->stack = meta_stack_new (display);
display->stack_tracker = meta_stack_tracker_new (display);
- meta_bell_init (display);
-
display->last_focus_time = timestamp;
display->last_user_time = timestamp;
display->compositor = NULL;
@@ -846,10 +848,6 @@ meta_display_open (void)
display->x11_display->atom__NET_ACTIVE_WINDOW,
&old_active_xwindow);
- display->startup_notification = meta_startup_notification_get (display);
- g_signal_connect (display->startup_notification, "changed",
- G_CALLBACK (on_startup_notification_changed), display);
-
enable_compositor (display);
if (display->x11_display)
@@ -1015,7 +1013,6 @@ meta_display_close (MetaDisplay *display,
meta_display_remove_autoraise_callback (display);
- g_clear_object (&display->startup_notification);
g_clear_object (&display->gesture_tracker);
g_clear_pointer (&display->stack, (GDestroyNotify) meta_stack_free);
@@ -1056,6 +1053,9 @@ meta_display_close (MetaDisplay *display,
meta_display_shutdown_keys (display);
+ g_clear_object (&display->bell);
+ g_clear_object (&display->startup_notification);
+
g_object_unref (display);
the_display = NULL;
@@ -2564,12 +2564,8 @@ prefs_changed_callback (MetaPreference pref,
{
MetaDisplay *display = data;
- if (pref == META_PREF_AUDIBLE_BELL)
- {
- meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
- }
- else if (pref == META_PREF_CURSOR_THEME ||
- pref == META_PREF_CURSOR_SIZE)
+ if (pref == META_PREF_CURSOR_THEME ||
+ pref == META_PREF_CURSOR_SIZE)
{
meta_display_reload_cursor (display);
}
diff --git a/src/core/startup-notification.c b/src/core/startup-notification.c
index df1bc4e05..cde784573 100644
--- a/src/core/startup-notification.c
+++ b/src/core/startup-notification.c
@@ -528,11 +528,6 @@ meta_startup_notification_finalize (GObject *object)
{
MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
-#ifdef HAVE_STARTUP_NOTIFICATION
- sn_monitor_context_unref (sn->sn_context);
- sn_display_unref (sn->sn_display);
-#endif
-
if (sn->startup_sequence_timeout)
g_source_remove (sn->startup_sequence_timeout);
@@ -660,26 +655,59 @@ meta_startup_notification_sn_event (SnMonitorEvent *event,
sn_startup_sequence_unref (sequence);
}
-#endif
static void
-meta_startup_notification_constructed (GObject *object)
+on_x11_display_opened (MetaStartupNotification *sn)
{
- MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object);
+ MetaX11Display *x11_display = sn->display->x11_display;
- g_assert (sn->display != NULL);
-
-#ifdef HAVE_STARTUP_NOTIFICATION
- sn->sn_display = sn_display_new (sn->display->x11_display->xdisplay,
+ sn->sn_display = sn_display_new (x11_display->xdisplay,
sn_error_trap_push,
sn_error_trap_pop);
+
sn->sn_context =
sn_monitor_context_new (sn->sn_display,
- meta_ui_get_screen_number (),
+ meta_x11_display_get_screen_number (x11_display),
meta_startup_notification_sn_event,
sn,
NULL);
+}
+
+static void
+on_x11_display_closing (MetaStartupNotification *sn)
+{
+ sn_monitor_context_unref (sn->sn_context);
+ sn->sn_context = NULL;
+
+ sn_display_unref (sn->sn_display);
+ sn->sn_display = NULL;
+}
+#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 = NULL;
+ sn->sn_context = NULL;
+
+ g_signal_connect_object (sn->display,
+ "x11-display-opened",
+ G_CALLBACK (on_x11_display_opened),
+ sn,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (sn->display,
+ "x11-display-closing",
+ G_CALLBACK (on_x11_display_closing),
+ sn,
+ G_CONNECT_SWAPPED);
#endif
+
sn->startup_sequences = NULL;
sn->startup_sequence_timeout = 0;
}
@@ -753,6 +781,9 @@ meta_startup_notification_get_sequences (MetaStartupNotification *sn)
#ifdef HAVE_STARTUP_NOTIFICATION
GSList *l;
+ if (!sn->sn_display)
+ return sequences;
+
/* We return a list of SnStartupSequences here */
for (l = sn->startup_sequences; l; l = l->next)
{
diff --git a/src/x11/events.c b/src/x11/events.c
index 13c6faad8..c94f151e6 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -24,6 +24,7 @@
#include "x11/events.h"
#include <X11/Xatom.h>
+#include <X11/XKBlib.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/shape.h>
@@ -1166,23 +1167,24 @@ process_selection_clear (MetaX11Display *x11_display,
}
static void
-notify_bell (MetaDisplay *display,
- XkbAnyEvent *xkb_ev)
+notify_bell (MetaX11Display *x11_display,
+ XkbAnyEvent *xkb_ev)
{
+ MetaDisplay *display = x11_display->display;
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
MetaWindow *window;
- window = meta_x11_display_lookup_x_window (display->x11_display,
+ window = meta_x11_display_lookup_x_window (x11_display,
xkb_bell_event->window);
if (!window && display->focus_window && display->focus_window->frame)
window = display->focus_window;
- display->last_bell_time = xkb_ev->time;
+ x11_display->last_bell_time = xkb_ev->time;
if (!meta_bell_notify (display, window) &&
meta_prefs_bell_is_audible ())
{
/* Force a classic bell if the libcanberra bell failed. */
- XkbForceDeviceBell (display->x11_display->xdisplay,
+ XkbForceDeviceBell (x11_display->xdisplay,
xkb_bell_event->device,
xkb_bell_event->bell_class,
xkb_bell_event->bell_id,
@@ -1656,17 +1658,17 @@ handle_other_xevent (MetaX11Display *x11_display,
}
break;
default:
- if (event->type == display->xkb_base_event_type)
+ if (event->type == x11_display->xkb_base_event_type)
{
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
switch (xkb_ev->xkb_type)
{
case XkbBellNotify:
- if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
+ if (XSERVER_TIME_IS_BEFORE(x11_display->last_bell_time,
xkb_ev->time - 100))
{
- notify_bell (display, xkb_ev);
+ notify_bell (x11_display, xkb_ev);
}
break;
default:
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index a4af63ec0..41ad8d88c 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -110,6 +110,9 @@ struct _MetaX11Display
/* Managed by group-props.c */
MetaGroupPropHooks *group_prop_hooks;
+ int xkb_base_event_type;
+ guint32 last_bell_time;
+
MetaAlarmFilter alarm_filter;
gpointer alarm_filter_data;
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 605008573..47045896d 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -38,6 +38,7 @@
#include <unistd.h>
#include <X11/Xatom.h>
+#include <X11/XKBlib.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
@@ -402,6 +403,97 @@ query_xi_extension (MetaX11Display *x11_display)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
+/*
+ * Initialises the bell subsystem. This involves intialising
+ * XKB (which, despite being a keyboard extension, is the
+ * place to look for bell notifications), then asking it
+ * to send us bell notifications, and then also switching
+ * off the audible bell if we're using a visual one ourselves.
+ *
+ * \bug There is a line of code that's never run that tells
+ * XKB to reset the bell status after we quit. Bill H said
+ * (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
+ * that XFree86's implementation is broken so we shouldn't
+ * call it, but that was in 2002. Is it working now?
+ */
+static void
+init_x11_bell (MetaX11Display *x11_display)
+{
+ int xkb_base_error_type, xkb_opcode;
+
+ if (!XkbQueryExtension (x11_display->xdisplay, &xkb_opcode,
+ &x11_display->xkb_base_event_type,
+ &xkb_base_error_type,
+ NULL, NULL))
+ {
+ x11_display->xkb_base_event_type = -1;
+ meta_warning ("could not find XKB extension.");
+ }
+ else
+ {
+ unsigned int mask = XkbBellNotifyMask;
+ gboolean visual_bell_auto_reset = FALSE;
+ /* TRUE if and when non-broken version is available */
+ XkbSelectEvents (x11_display->xdisplay,
+ XkbUseCoreKbd,
+ XkbBellNotifyMask,
+ XkbBellNotifyMask);
+
+ if (visual_bell_auto_reset)
+ {
+ XkbSetAutoResetControls (x11_display->xdisplay,
+ XkbAudibleBellMask,
+ &mask,
+ &mask);
+ }
+ }
+}
+
+/*
+ * \bug This is never called! If we had XkbSetAutoResetControls
+ * enabled in meta_x11_bell_init(), this wouldn't be a problem,
+ * but we don't.
+ */
+G_GNUC_UNUSED static void
+shutdown_x11_bell (MetaX11Display *x11_display)
+{
+ /* TODO: persist initial bell state in display, reset here */
+ XkbChangeEnabledControls (x11_display->xdisplay,
+ XkbUseCoreKbd,
+ XkbAudibleBellMask,
+ XkbAudibleBellMask);
+}
+
+/*
+ * Turns the bell to audible or visual. This tells X what to do, but
+ * not Mutter; you will need to set the "visual bell" pref for that.
+ */
+static void
+set_x11_bell_is_audible (MetaX11Display *x11_display,
+ gboolean is_audible)
+{
+#ifdef HAVE_LIBCANBERRA
+ /* When we are playing sounds using libcanberra support, we handle the
+ * bell whether its an audible bell or a visible bell */
+ gboolean enable_system_bell = FALSE;
+#else
+ gboolean enable_system_bell = is_audible;
+#endif /* HAVE_LIBCANBERRA */
+
+ XkbChangeEnabledControls (x11_display->xdisplay,
+ XkbUseCoreKbd,
+ XkbAudibleBellMask,
+ enable_system_bell ? XkbAudibleBellMask : 0);
+}
+
+static void
+on_is_audible_changed (MetaBell *bell,
+ gboolean is_audible,
+ MetaX11Display *x11_display)
+{
+ set_x11_bell_is_audible (x11_display, is_audible);
+}
+
static void
set_desktop_geometry_hint (MetaX11Display *x11_display)
{
@@ -957,6 +1049,7 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
x11_display->timestamp_pinging_window = None;
x11_display->wm_sn_selection_window = None;
+ x11_display->last_bell_time = 0;
x11_display->focus_serial = 0;
x11_display->server_focus_window = None;
x11_display->server_focus_serial = 0;
@@ -1105,6 +1198,14 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
meta_prefs_add_listener (prefs_changed_callback, x11_display);
+ init_x11_bell (x11_display);
+
+ g_signal_connect_object (display->bell, "is-audible-changed",
+ G_CALLBACK (on_is_audible_changed),
+ x11_display, 0);
+
+ set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ());
+
return x11_display;
}