summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog130
-rw-r--r--configure.in11
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bell.c250
-rw-r--r--src/bell.h34
-rw-r--r--src/common.h3
-rw-r--r--src/display.c24
-rw-r--r--src/display.h3
-rw-r--r--src/frame.c6
-rw-r--r--src/frame.h1
-rw-r--r--src/metacity.schemas.in51
-rw-r--r--src/prefs.c128
-rw-r--r--src/prefs.h17
-rw-r--r--src/screen.c1
-rw-r--r--src/screen.h2
-rw-r--r--src/theme.c6
16 files changed, 663 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 0014b9d..0e5c076 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,133 @@
+2002-12-16 Bill Haneman <bill.haneman@sun.com>
+
+ * configure.in:
+ Check for XKB extension.
+
+ * src/Makefile.am:
+ Added bell.c and bell.h to metacity sources.
+
+ * src/common.h:
+ (MetaFrameFlags):
+ Added META_FRAME_IS_FLASHING flag.
+
+ * src/frame.h:
+ (MetaFrame): Added is_flashing field.
+
+ * src/frame.c:
+ (meta_window_ensure_frame):
+ Initialize the is_flashing flag to FALSE.
+ (meta_frame_get_flags):
+ Handle the FRAME_IS_FLASHING flag.
+ (meta_window_destroy_frame):
+ Call meta_bell_notify_frame_destroy.
+
+ * src/prefs.h:
+ (MetaPreference):
+ Added META_PREF_VISUAL_BELL, META_PREF_AUDIBLE_BELL,
+ META_PREF_VISUAL_BELL_TYPE.
+ (MetaVisualBellType): New enum.
+ (meta_prefs_get_visual_bell, meta_prefs_bell_is_audible):
+ (meta_prefs_get_visual_bell_type):
+ New accessor declarations.
+
+ * src/prefs.c:
+ (#includes): Include "display.h", since we now call
+ meta_displays_list() in our update func.
+ (#defines):
+ Define KEY_VISUAL_BELL, KEY_AUDIBLE_BELL,
+ and KEY_VISUAL_BELL_TYPE.
+ (provide_visual_bell, bell_is_audible, visual_bell_type):
+ New static state variables.
+ (update_visual_bell): New method to update visual-bell
+ boolean settings from keys "visual_bell" and "audible_bell".
+ (update_visual_bell_type):
+ New method to update visual-bell type setting.
+ (visual_bell_type_from_string) :
+ New method to convert from gconf string to visual-bell
+ type enum. Only currently recognized values are "fullscreen"
+ and "frame_flash".
+ (change_notify):
+ Handle changes to visual and audible bell properties.
+ (meta_prefs_get_visual_bell, meta_prefs_bell_is_audible):
+ (meta_prefs_get_visual_bell_type):
+ New accessor definitions.
+ (meta_prefs_init): Added a second call to notify_add,
+ listens to "/desktop/gnome/interface" as well as "apps/metacity".
+ Also call the update funcs for the new visual-bell gconf keys.
+ (meta_preference_to_string):
+ Handle the visual/audible bell cases.
+
+ * src/bell.h:
+ (meta_bell_notify);
+ New method, calls a visual notifucation
+ method based on the visual-bell-type, or none if the type
+ is unrecognized or invalid.
+ (meta_bell_set_audible):
+ New public method for setting the audible bell setting,
+ used in updater for new gconf key "audible_bell".
+ (meta_bell_init):
+ Initialize the bell notification for a display.
+ (meta_bell_shutdown):
+ Shutdown the bell notification for a display.
+ (meta_bell_notify_frame_destroy):
+ Remove pending idle handlers on notification.
+
+ * src/bell.c:
+ Include "bell.h", and conditionally include <Xll/Xkblib.h>.
+ (meta_bell_set_audible):
+ If XKB is present, enable/disable the audible system
+ bell based on the gconf key /desktop/gnome/interface/audible_bell.
+ (meta_bell_init):
+ Query and initialize XKB if present, register for notification
+ on the bell, and set audible bell according to gconf settings.
+ (meta_bell_flash_screen):
+ Maps and unmaps a fullscreen X window (painted white, then
+ black), which causes a fullscreen 'flash' transient.
+ (meta_bell_flash_window_frame):
+ Flashes the titlebar of a specified window.
+ (meta_bell_flash_frame):
+ Calls meta_bell_flash_window_frame on the window which
+ was the source of the current bell event, or the currently
+ focussed window if the event source cannot be determined.
+ (meta_bell_unflash_frame):
+ Restore the frame's appearance to normal.
+ (meta_bell_flash_fullscreen):
+ Call meta_bell_flash_fullscreen for all screens.
+ (meta_bell_shutdown):
+ New method.
+ (meta_bell_notify_frame_destroy):
+ Remove pending idle handlers on notification,
+ testing for frame->is_flashing first.
+
+ * src/display.h:
+ (MetaDisplay): Added xkb_base_event_type field.
+
+ * src/display.c:
+ Check for XKB and include "X11/XKBlib.h" if present.
+ (meta_display_open): Call meta_bell_init.
+ (event_callback): Call meta_bell_notify
+ when event comes from XKB and is XkbBellNotify
+ (prefs_changed_callback):
+ Handle META_PREF_AUDIBLE_BELL notification.
+
+ * src/screen.h:
+ (MetaScreen): Add flash_window field.
+
+ * src/screen.c:
+ (meta_screen_new):
+ Initialize flash_window field.
+
+ * src/theme.c:
+ (theme_get_style):
+ New heuristic for focus-style, to invert sense of focus
+ flag when META_FRAME_IS_FLASHING flag is set.
+
+ * src/metacity.schemas.in:
+ Added scheme information for
+ /apps/metacity/general/visual_bell,
+ /apps/metacity/general/audible_bell, and
+ /apps/metacity/general/visual_bell_type.
+
2002-12-16 Havoc Pennington <hp@pobox.com>
* src/window-props.c (init_wm_name): argh, screwed that up. get
diff --git a/configure.in b/configure.in
index dc2967a..a08cfdd 100644
--- a/configure.in
+++ b/configure.in
@@ -221,6 +221,17 @@ if test "x$found_shape" = "xyes"; then
AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library])
fi
+found_xkb=no
+AC_CHECK_LIB(X11, XkbQueryExtension,
+ [AC_CHECK_HEADER(X11/XKBlib.h,
+ found_xkb=yes)],
+ , $ALL_X_LIBS)
+
+if test "x$found_xkb" = "xyes"; then
+ AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
+fi
+
+
RANDR_LIBS=
found_randr=no
AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
diff --git a/src/Makefile.am b/src/Makefile.am
index 6644038..94f3a39 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,8 @@ EGGFILES= \
metacity_SOURCES= \
async-getprop.c \
async-getprop.h \
+ bell.h \
+ bell.c \
common.h \
core.c \
core.h \
diff --git a/src/bell.c b/src/bell.c
new file mode 100644
index 0000000..03d31e3
--- /dev/null
+++ b/src/bell.c
@@ -0,0 +1,250 @@
+/* Metacity visual bell */
+
+/*
+ * Copyright (C) 2002 Sun Microsystems Inc.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <config.h>
+#include "bell.h"
+#include "screen.h"
+#include "prefs.h"
+
+static void
+meta_bell_flash_screen (MetaDisplay *display,
+ MetaScreen *screen)
+{
+ Window root = screen->xroot;
+ int width = screen->width;
+ int height = screen->height;
+
+ if (screen->flash_window == None)
+ {
+ Visual *visual = CopyFromParent;
+ XSetWindowAttributes xswa;
+ int depth = CopyFromParent;
+ xswa.save_under = True;
+ xswa.override_redirect = True;
+ /*
+ * TODO: use XGetVisualInfo and determine which is an
+ * overlay, if one is present, and use the Overlay visual
+ * for this window (for performance reasons).
+ * Not sure how to tell this yet...
+ */
+ screen->flash_window = XCreateWindow (display->xdisplay, root,
+ 0, 0, width, height,
+ 0, depth,
+ InputOutput,
+ visual,
+ /* note: XSun doesn't like SaveUnder here */
+ CWSaveUnder | CWOverrideRedirect,
+ &xswa);
+ XSelectInput (display->xdisplay, screen->flash_window, ExposureMask);
+ XMapWindow (display->xdisplay, screen->flash_window);
+ XSync (display->xdisplay, False);
+ XFlush (display->xdisplay);
+ XUnmapWindow (display->xdisplay, screen->flash_window);
+ }
+ else
+ {
+ /* just draw something in the window */
+ GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL);
+ XMapWindow (display->xdisplay, screen->flash_window);
+ XSetForeground (display->xdisplay, gc,
+ WhitePixel (display->xdisplay,
+ XScreenNumberOfScreen (screen->xscreen)));
+ XFillRectangle (display->xdisplay, screen->flash_window, gc,
+ 0, 0, width, height);
+ XSetForeground (display->xdisplay, gc,
+ BlackPixel (display->xdisplay,
+ XScreenNumberOfScreen (screen->xscreen)));
+ XFillRectangle (display->xdisplay, screen->flash_window, gc,
+ 0, 0, width, height);
+ XFlush (display->xdisplay);
+ XSync (display->xdisplay, False);
+ XUnmapWindow (display->xdisplay, screen->flash_window);
+ }
+ XFlush (display->xdisplay);
+}
+
+#ifdef HAVE_XKB
+static void
+meta_bell_flash_fullscreen (MetaDisplay *display,
+ XkbAnyEvent *xkb_ev)
+{
+ XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
+ MetaScreen *screen;
+
+ g_assert (xkb_ev->xkb_type == XkbBellNotify);
+ if (xkb_bell_ev->window != None)
+ {
+ screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
+ if (screen)
+ meta_bell_flash_screen (display, screen);
+ }
+ else
+ {
+ GSList *screen_list = display->screens;
+ while (screen_list)
+ {
+ screen = (MetaScreen *) screen_list->data;
+ meta_bell_flash_screen (display, screen);
+ screen_list = screen_list->next;
+ }
+ }
+}
+
+static gboolean
+meta_bell_unflash_frame (gpointer data)
+{
+ MetaFrame *frame = (MetaFrame *) data;
+ frame->is_flashing = 0;
+ meta_frame_queue_draw (frame);
+ return FALSE;
+}
+
+static void
+meta_bell_flash_window_frame (MetaWindow *window)
+{
+ g_assert (window->frame != NULL);
+ window->frame->is_flashing = 1;
+ meta_frame_queue_draw (window->frame);
+ g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 100,
+ meta_bell_unflash_frame, window->frame, NULL);
+}
+
+static void
+meta_bell_flash_frame (MetaDisplay *display,
+ XkbAnyEvent *xkb_ev)
+{
+ XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
+ MetaWindow *window;
+
+ g_assert (xkb_ev->xkb_type == XkbBellNotify);
+ window = meta_display_lookup_x_window (display, xkb_bell_event->window);
+ if (!window && (display->focus_window->frame))
+ {
+ window = display->focus_window;
+ }
+ if (window)
+ {
+ meta_bell_flash_window_frame (window);
+ }
+ else /* revert to fullscreen flash if there's no focussed window */
+ {
+ meta_bell_flash_fullscreen (display, xkb_ev);
+ }
+}
+
+static void
+meta_bell_visual_notify (MetaDisplay *display,
+ XkbAnyEvent *xkb_ev)
+{
+ switch (meta_prefs_get_visual_bell_type ())
+ {
+ case META_VISUAL_BELL_FULLSCREEN_FLASH:
+ meta_bell_flash_fullscreen (display, xkb_ev);
+ break;
+ case META_VISUAL_BELL_FRAME_FLASH:
+ meta_bell_flash_frame (display, xkb_ev); /* does nothing yet */
+ break;
+ case META_VISUAL_BELL_INVALID:
+ /* do nothing */
+ break;
+ }
+}
+
+void
+meta_bell_notify (MetaDisplay *display,
+ XkbAnyEvent *xkb_ev)
+{
+ /* flash something */
+ if (meta_prefs_get_visual_bell ())
+ meta_bell_visual_notify (display, xkb_ev);
+}
+#endif
+
+void
+meta_bell_set_audible (MetaDisplay *display, gboolean audible)
+{
+#ifdef HAVE_XKB
+ XkbChangeEnabledControls (display->xdisplay,
+ XkbUseCoreKbd,
+ XkbAudibleBellMask,
+ audible ? XkbAudibleBellMask : 0);
+#endif
+}
+
+gboolean
+meta_bell_init (MetaDisplay *display)
+{
+#ifdef HAVE_XKB
+ int xkb_base_error_type, xkb_opcode;
+
+ if (!XkbQueryExtension (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 (display->xdisplay,
+ XkbUseCoreKbd,
+ XkbBellNotifyMask,
+ XkbBellNotifyMask);
+ XkbChangeEnabledControls (display->xdisplay,
+ XkbUseCoreKbd,
+ XkbAudibleBellMask,
+ meta_prefs_bell_is_audible ()
+ ? XkbAudibleBellMask : 0);
+ if (visual_bell_auto_reset) {
+ XkbSetAutoResetControls (display->xdisplay,
+ XkbAudibleBellMask,
+ &mask,
+ &mask);
+ }
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+void
+meta_bell_shutdown (MetaDisplay *display)
+{
+#ifdef HAVE_XKB
+ /* TODO: persist initial bell state in display, reset here */
+ XkbChangeEnabledControls (display->xdisplay,
+ XkbUseCoreKbd,
+ XkbAudibleBellMask,
+ XkbAudibleBellMask);
+#endif
+}
+
+void
+meta_bell_notify_frame_destroy (MetaFrame *frame)
+{
+ if (frame->is_flashing)
+ g_idle_remove_by_data (frame);
+}
diff --git a/src/bell.h b/src/bell.h
new file mode 100644
index 0000000..5da57ec
--- /dev/null
+++ b/src/bell.h
@@ -0,0 +1,34 @@
+/* Metacity visual bell */
+
+/*
+ * Copyright (C) 2002 Sun Microsystems Inc.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
+#include "display.h"
+#include "frame.h"
+
+#ifdef HAVE_XKB
+void meta_bell_notify (MetaDisplay *display, XkbAnyEvent *xkb_ev);
+#endif
+void meta_bell_set_audible (MetaDisplay *display, gboolean audible);
+gboolean meta_bell_init (MetaDisplay *display);
+void meta_bell_shutdown (MetaDisplay *display);
+void meta_bell_notify_frame_destroy (MetaFrame *frame);
diff --git a/src/common.h b/src/common.h
index f88dce5..440b56c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -42,7 +42,8 @@ typedef enum
META_FRAME_MAXIMIZED = 1 << 9,
META_FRAME_ALLOWS_SHADE = 1 << 10,
META_FRAME_ALLOWS_MOVE = 1 << 11,
- META_FRAME_FULLSCREEN = 1 << 12
+ META_FRAME_FULLSCREEN = 1 << 12,
+ META_FRAME_IS_FLASHING = 1 << 13
} MetaFrameFlags;
typedef enum
diff --git a/src/display.c b/src/display.c
index e1b72da..2b20411 100644
--- a/src/display.c
+++ b/src/display.c
@@ -34,6 +34,7 @@
#include "prefs.h"
#include "resizepopup.h"
#include "workspace.h"
+#include "bell.h"
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#ifdef HAVE_SOLARIS_XINERAMA
@@ -42,6 +43,9 @@
#ifdef HAVE_XFREE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
+#ifdef HAVE_XKB
+#include <X11/XKBlib.h>
+#endif
#include <string.h>
#define USE_GDK_DISPLAY
@@ -305,6 +309,8 @@ meta_display_open (const char *name)
/* we have to go ahead and do this so error handlers work */
all_displays = g_slist_prepend (all_displays, display);
+ meta_bell_init (display);
+
meta_display_init_keys (display);
update_window_grab_modifiers (display);
@@ -1822,6 +1828,19 @@ event_callback (XEvent *event,
}
break;
default:
+#ifdef HAVE_XKB
+ if (event->type == display->xkb_base_event_type)
+ {
+ XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
+
+ switch (xkb_ev->xkb_type)
+ {
+ case XkbBellNotify:
+ meta_bell_notify (display, xkb_ev);
+ break;
+ }
+ }
+#endif
break;
}
@@ -3846,4 +3865,9 @@ prefs_changed_callback (MetaPreference pref,
g_slist_free (windows);
}
+ else if (pref == META_PREF_AUDIBLE_BELL)
+ {
+ MetaDisplay *display = data;
+ meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
+ }
}
diff --git a/src/display.h b/src/display.h
index 2641af4..ef5144c 100644
--- a/src/display.h
+++ b/src/display.h
@@ -245,6 +245,9 @@ struct _MetaDisplay
MetaRectangle grab_current_window_pos;
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time;
+#ifdef HAVE_XKB
+ int xkb_base_event_type;
+#endif
#ifdef HAVE_XSYNC
/* alarm monitoring client's _METACITY_UPDATE_COUNTER */
XSyncAlarm grab_update_alarm;
diff --git a/src/frame.c b/src/frame.c
index b981559..fe962ee 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -21,6 +21,7 @@
#include <config.h>
#include "frame.h"
+#include "bell.h"
#include "errors.h"
#include "keybindings.h"
@@ -58,6 +59,7 @@ meta_window_ensure_frame (MetaWindow *window)
frame->current_cursor = 0;
frame->mapped = FALSE;
+ frame->is_flashing = FALSE;
attrs.event_mask = EVENT_MASK;
@@ -159,6 +161,7 @@ meta_window_destroy_frame (MetaWindow *window)
frame = window->frame;
+ meta_bell_notify_frame_destroy (frame);
meta_ui_remove_frame (window->screen->ui, frame->xwindow);
/* Unparent the client window; it may be destroyed,
@@ -255,6 +258,9 @@ meta_frame_get_flags (MetaFrame *frame)
if (frame->window->fullscreen)
flags |= META_FRAME_FULLSCREEN;
+ if (frame->is_flashing)
+ flags |= META_FRAME_IS_FLASHING;
+
return flags;
}
diff --git a/src/frame.h b/src/frame.h
index 20f9469..fff4db5 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -57,6 +57,7 @@ struct _MetaFrame
int bottom_height;
guint mapped : 1;
+ guint is_flashing : 1; /* used by the visual bell flash */
};
void meta_window_ensure_frame (MetaWindow *window);
diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in
index 9216b48..2444dc2 100644
--- a/src/metacity.schemas.in
+++ b/src/metacity.schemas.in
@@ -178,6 +178,57 @@
</schema>
<schema>
+ <key>/apps/metacity/visual_bell</key>
+ <applyto>/apps/metacity/general/visual_bell</applyto>
+ <owner>metacity</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Enable Visual Bell</short>
+ <long>Turns on a visual indication when an application or the system
+ issues a 'bell' or 'beep'; useful for the hard-of-hearing and for use
+ in noisy environments, or when 'audible bell' is off.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/general/audible_bell</key>
+ <applyto>/apps/metacity/general/audible_bell</applyto>
+ <owner>metacity</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>System Bell is Audible</short>
+ <long>Determines whether applications or the system can generate audible
+ 'beeps'; may be used in conjunction with 'visual bell' to
+ allow silent 'beeps'.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/metacity/general/visual_bell_type</key>
+ <applyto>/apps/metacity/general/visual_bell_type</applyto>
+ <owner>metacity</owner>
+ <type>string</type>
+ <default>fullscreen</default>
+ <locale name="C">
+ <short>Visual Bell Type</short>
+ <long>
+ Tells Metacity how to implement the visual indication that
+ the system bell or another application 'bell' indicator has
+ been rung. Currently there are two valid values, "fullscreen",
+ which causes a fullscreen white-black flash, and "frame_flash" which
+ causes the titlebar of the application which sent the bell signal to
+ flash. If the application which sent the bell is unknown (as is
+ usually the case for the default "system beep"), the currently
+ focussed window's titlebar is flashed.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/metacity/workspace_names/name</key>
<applyto>/apps/metacity/workspace_names/name_1</applyto>
<applyto>/apps/metacity/workspace_names/name_2</applyto>
diff --git a/src/prefs.c b/src/prefs.c
index 2a88164..f888d03 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -54,6 +54,10 @@
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
+#define KEY_VISUAL_BELL "/apps/metacity/general/visual_bell"
+#define KEY_AUDIBLE_BELL "/apps/metacity/general/audible_bell"
+#define KEY_VISUAL_BELL_TYPE "/apps/metacity/general/visual_bell_type"
+
#ifdef HAVE_GCONF
static GConfClient *default_client = NULL;
static GList *changes = NULL;
@@ -73,6 +77,9 @@ static gboolean application_based = FALSE;
static gboolean disable_workarounds = FALSE;
static gboolean auto_raise = FALSE;
static gboolean auto_raise_delay = 500;
+static gboolean provide_visual_bell = TRUE;
+static gboolean bell_is_audible = TRUE;
+static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_INVALID;
static MetaButtonLayout button_layout = {
{
META_BUTTON_FUNCTION_MENU,
@@ -98,6 +105,8 @@ static gboolean update_titlebar_font (const char *value);
static gboolean update_mouse_button_mods (const char *value);
static gboolean update_focus_mode (const char *value);
static gboolean update_theme (const char *value);
+static gboolean update_visual_bell (gboolean v1, gboolean v2);
+static gboolean update_visual_bell_type (const char *value);
static gboolean update_num_workspaces (int value);
static gboolean update_application_based (gboolean value);
static gboolean update_disable_workarounds (gboolean value);
@@ -273,7 +282,7 @@ meta_prefs_init (void)
GError *err = NULL;
char *str_val;
int int_val;
- gboolean bool_val;
+ gboolean bool_val, bool_val_2;
if (default_client != NULL)
return;
@@ -360,6 +369,20 @@ meta_prefs_init (void)
g_free (str_val);
#endif /* HAVE_GCONF */
+ bool_val = gconf_client_get_bool (default_client, KEY_VISUAL_BELL,
+ &err);
+ cleanup_error (&err);
+ bool_val_2 = gconf_client_get_bool (default_client, KEY_AUDIBLE_BELL,
+ &err);
+ cleanup_error (&err);
+ update_visual_bell (bool_val, bool_val_2);
+
+ str_val = gconf_client_get_string (default_client, KEY_VISUAL_BELL_TYPE,
+ &err);
+ cleanup_error (&err);
+ update_visual_bell_type (str_val);
+ g_free (str_val);
+
/* Load keybindings prefs */
init_bindings ();
@@ -375,7 +398,7 @@ meta_prefs_init (void)
NULL,
NULL,
&err);
- cleanup_error (&err);
+ cleanup_error (&err);
#endif /* HAVE_GCONF */
}
@@ -674,6 +697,37 @@ change_notify (GConfClient *client,
if (update_button_layout (str))
queue_changed (META_PREF_BUTTON_LAYOUT);
}
+ else if (strcmp (key, KEY_VISUAL_BELL) == 0)
+ {
+ gboolean b;
+
+ b = value ? gconf_value_get_bool (value) : provide_visual_bell;
+ if (update_visual_bell (b, bell_is_audible))
+ queue_changed (META_PREF_VISUAL_BELL);
+ }
+ else if (strcmp (key, KEY_AUDIBLE_BELL) == 0)
+ {
+ gboolean b;
+
+ b = value ? gconf_value_get_bool (value) : bell_is_audible;
+ if (update_visual_bell (provide_visual_bell, b))
+ queue_changed (META_PREF_AUDIBLE_BELL);
+ }
+ else if (strcmp (key, KEY_VISUAL_BELL_TYPE) == 0)
+ {
+ const char * str;
+
+ if (value && value->type != GCONF_VALUE_STRING)
+ {
+ meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+ KEY_VISUAL_BELL_TYPE);
+ goto out;
+ }
+
+ str = value ? gconf_value_get_string (value) : NULL;
+ if (update_visual_bell_type (str))
+ queue_changed (META_PREF_VISUAL_BELL_TYPE);
+ }
else
{
meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n",
@@ -803,8 +857,48 @@ update_use_system_font (gboolean value)
return old != value;
}
+
+static MetaVisualBellType
+visual_bell_type_from_string (const char *value)
+{
+ if (!strcmp (value, "fullscreen"))
+ {
+ return META_VISUAL_BELL_FULLSCREEN_FLASH;
+ }
+ else if (!strcmp (value, "frame_flash"))
+ {
+ return META_VISUAL_BELL_FRAME_FLASH;
+ }
+ return META_VISUAL_BELL_FULLSCREEN_FLASH;
+}
+
+static gboolean
+update_visual_bell_type (const char *value)
+{
+ MetaVisualBellType old_bell_type;
+
+ old_bell_type = visual_bell_type;
+ visual_bell_type = visual_bell_type_from_string (value);
+
+ return (visual_bell_type != old_bell_type);
+}
#endif /* HAVE_GCONF */
+static gboolean
+update_visual_bell (gboolean visual_bell, gboolean audible_bell)
+{
+ gboolean old_visual = provide_visual_bell;
+ gboolean old_audible = bell_is_audible;
+ gboolean has_changed;
+
+ provide_visual_bell = visual_bell;
+ bell_is_audible = audible_bell;
+ has_changed = (old_visual != provide_visual_bell) ||
+ (old_audible != bell_is_audible);
+
+ return has_changed;
+}
+
#ifdef HAVE_GCONF
static gboolean
update_titlebar_font (const char *value)
@@ -1186,6 +1280,18 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_WORKSPACE_NAMES:
return "WORKSPACE_NAMES";
break;
+
+ case META_PREF_VISUAL_BELL:
+ return "VISUAL_BELL";
+ break;
+
+ case META_PREF_AUDIBLE_BELL:
+ return "AUDIBLE_BELL";
+ break;
+
+ case META_PREF_VISUAL_BELL_TYPE:
+ return "VISUAL_BELL_TYPE";
+ break;
}
return "(unknown)";
@@ -1750,6 +1856,24 @@ meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p)
*button_layout_p = button_layout;
}
+gboolean
+meta_prefs_get_visual_bell ()
+{
+ return provide_visual_bell;
+}
+
+gboolean
+meta_prefs_bell_is_audible ()
+{
+ return bell_is_audible;
+}
+
+MetaVisualBellType
+meta_prefs_get_visual_bell_type ()
+{
+ return visual_bell_type;
+}
+
void
meta_prefs_get_screen_bindings (const MetaKeyPref **bindings,
int *n_bindings)
diff --git a/src/prefs.h b/src/prefs.h
index 683bedb..8e13ddc 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -42,7 +42,10 @@ typedef enum
META_PREF_DISABLE_WORKAROUNDS,
META_PREF_COMMANDS,
META_PREF_BUTTON_LAYOUT,
- META_PREF_WORKSPACE_NAMES
+ META_PREF_WORKSPACE_NAMES,
+ META_PREF_VISUAL_BELL,
+ META_PREF_AUDIBLE_BELL,
+ META_PREF_VISUAL_BELL_TYPE
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -213,6 +216,18 @@ void meta_prefs_get_window_binding (const char *name,
unsigned int *keysym,
MetaVirtualModifier *modifiers);
+typedef enum
+{
+ META_VISUAL_BELL_INVALID = 0,
+ META_VISUAL_BELL_FULLSCREEN_FLASH,
+ META_VISUAL_BELL_FRAME_FLASH
+
+} MetaVisualBellType;
+
+gboolean meta_prefs_get_visual_bell (void);
+gboolean meta_prefs_bell_is_audible (void);
+MetaVisualBellType meta_prefs_get_visual_bell_type (void);
+
#endif
diff --git a/src/screen.c b/src/screen.c
index ef06270..e006fe7 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -523,6 +523,7 @@ meta_screen_new (MetaDisplay *display,
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
+ screen->flash_window = None;
screen->wm_sn_selection_window = new_wm_sn_owner;
screen->wm_sn_atom = wm_sn_atom;
diff --git a/src/screen.h b/src/screen.h
index 351f6b9..dc98cd7 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -70,6 +70,8 @@ struct _MetaScreen
MetaCursor current_cursor;
+ Window flash_window;
+
Window wm_sn_selection_window;
Atom wm_sn_atom;
Time wm_sn_timestamp;
diff --git a/src/theme.c b/src/theme.c
index f1b6f41..b07d7cd 100644
--- a/src/theme.c
+++ b/src/theme.c
@@ -4760,8 +4760,10 @@ theme_get_style (MetaTheme *theme,
resize = META_FRAME_RESIZE_LAST; /* compiler */
break;
}
-
- if (flags & META_FRAME_HAS_FOCUS)
+
+ /* re invert the styles used for focus/unfocussed while flashing a frame */
+ if (((flags & META_FRAME_HAS_FOCUS) && !(flags & META_FRAME_IS_FLASHING))
+ || (!(flags & META_FRAME_HAS_FOCUS) && (flags & META_FRAME_IS_FLASHING)))
focus = META_FRAME_FOCUS_YES;
else
focus = META_FRAME_FOCUS_NO;