209 lines
5.8 KiB
C
209 lines
5.8 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/* Mutter visual bell */
|
|
|
|
/*
|
|
* Copyright (C) 2002 Sun Microsystems Inc.
|
|
* Copyright (C) 2005, 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/>.
|
|
*/
|
|
|
|
/*
|
|
* SECTION:bell
|
|
* @short_description: Ring the bell or flash the screen
|
|
*
|
|
* Sometimes, X programs "ring the bell", whatever that means. Mutter lets
|
|
* the user configure the bell to be audible or visible (aka visual), and
|
|
* if it's visual it can be configured to be frame-flash or fullscreen-flash.
|
|
* We never get told about audible bells; X handles them just fine by itself.
|
|
*
|
|
* Visual bells come in at meta_bell_notify(), which checks we are actually
|
|
* in visual mode and calls through to bell_visual_notify(). That
|
|
* function then checks what kind of visual flash you like, and calls either
|
|
* bell_flash_fullscreen()-- which calls bell_flash_screen() to do
|
|
* its work-- or bell_flash_frame(), which flashes the focused window
|
|
* using bell_flash_window(), unless there is no such window, in
|
|
* which case it flashes the screen instead.
|
|
*
|
|
* The visual bell was the result of a discussion in Bugzilla here:
|
|
* <http://bugzilla.gnome.org/show_bug.cgi?id=99886>.
|
|
*
|
|
* Several of the functions in this file are ifdeffed out entirely if we are
|
|
* found not to have the XKB extension, which is required to do these clever
|
|
* things with bells; some others are entirely no-ops in that case.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "core/bell.h"
|
|
|
|
#include "compositor/compositor-private.h"
|
|
#include "core/util-private.h"
|
|
#include "core/window-private.h"
|
|
#include "meta/compositor.h"
|
|
|
|
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
|
|
* @xkb_ev: The bell event
|
|
*
|
|
* Flashes one screen, or all screens, in response to a bell event.
|
|
* If the event is on a particular window, flash the screen that
|
|
* window is on. Otherwise, flash every screen on this display.
|
|
*
|
|
* If the configure script found we had no XKB, this does not exist.
|
|
*/
|
|
static void
|
|
bell_flash_fullscreen (MetaDisplay *display)
|
|
{
|
|
meta_compositor_flash_display (display->compositor, display);
|
|
}
|
|
|
|
static void
|
|
bell_flash_window (MetaWindow *window)
|
|
{
|
|
meta_compositor_flash_window (window->display->compositor, window);
|
|
}
|
|
|
|
/**
|
|
* bell_flash_frame:
|
|
* @display: The display the bell event came in on
|
|
* @xkb_ev: The bell event we just received
|
|
*
|
|
* Flashes the frame of the focused window. If there is no focused window,
|
|
* flashes the screen.
|
|
*/
|
|
static void
|
|
bell_flash_frame (MetaDisplay *display,
|
|
MetaWindow *window)
|
|
{
|
|
if (window)
|
|
bell_flash_window (window);
|
|
else
|
|
bell_flash_fullscreen (display);
|
|
}
|
|
|
|
/**
|
|
* bell_visual_notify:
|
|
* @display: The display the bell event came in on
|
|
* @xkb_ev: The bell event we just received
|
|
*
|
|
* Gives the user some kind of visual bell substitute, in response to a
|
|
* bell event. What this is depends on the "visual bell type" pref.
|
|
*/
|
|
static void
|
|
bell_visual_notify (MetaDisplay *display,
|
|
MetaWindow *window)
|
|
{
|
|
switch (meta_prefs_get_visual_bell_type ())
|
|
{
|
|
case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH:
|
|
bell_flash_fullscreen (display);
|
|
break;
|
|
case G_DESKTOP_VISUAL_BELL_FRAME_FLASH:
|
|
bell_flash_frame (display, window);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
bell_audible_notify (MetaDisplay *display,
|
|
MetaWindow *window)
|
|
{
|
|
MetaSoundPlayer *player;
|
|
|
|
player = meta_display_get_sound_player (display);
|
|
meta_sound_player_play_from_theme (player,
|
|
"bell-window-system",
|
|
_("Bell event"),
|
|
NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
meta_bell_notify (MetaDisplay *display,
|
|
MetaWindow *window)
|
|
{
|
|
/* flash something */
|
|
if (meta_prefs_get_visual_bell ())
|
|
bell_visual_notify (display, window);
|
|
|
|
if (meta_prefs_bell_is_audible ())
|
|
return bell_audible_notify (display, window);
|
|
|
|
return TRUE;
|
|
}
|