diff --git a/ChangeLog b/ChangeLog index 0014b9d63..0e5c076e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,133 @@ +2002-12-16 Bill Haneman + + * 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 . + (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 * src/window-props.c (init_wm_name): argh, screwed that up. get diff --git a/configure.in b/configure.in index dc2967ae7..a08cfddc3 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 66440381a..94f3a39c3 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 000000000..03d31e343 --- /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 +#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 000000000..5da57ecbb --- /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 +#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 f88dce584..440b56cc6 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 e1b72daf1..2b20411d8 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 #include #ifdef HAVE_SOLARIS_XINERAMA @@ -42,6 +43,9 @@ #ifdef HAVE_XFREE_XINERAMA #include #endif +#ifdef HAVE_XKB +#include +#endif #include #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 2641af4d5..ef5144ce9 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 b981559e9..fe962eeb6 100644 --- a/src/frame.c +++ b/src/frame.c @@ -21,6 +21,7 @@ #include #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 20f946999..fff4db532 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 9216b4879..2444dc212 100644 --- a/src/metacity.schemas.in +++ b/src/metacity.schemas.in @@ -177,6 +177,57 @@ + + /apps/metacity/visual_bell + /apps/metacity/general/visual_bell + metacity + bool + false + + Enable Visual Bell + 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. + + + + + + /schemas/apps/metacity/general/audible_bell + /apps/metacity/general/audible_bell + metacity + bool + true + + System Bell is Audible + Determines whether applications or the system can generate audible + 'beeps'; may be used in conjunction with 'visual bell' to + allow silent 'beeps'. + + + + + + /schemas/apps/metacity/general/visual_bell_type + /apps/metacity/general/visual_bell_type + metacity + string + fullscreen + + Visual Bell Type + + 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. + + + + /schemas/apps/metacity/workspace_names/name /apps/metacity/workspace_names/name_1 diff --git a/src/prefs.c b/src/prefs.c index 2a88164ec..f888d0353 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 683bedba6..8e13ddcac 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 ef0627036..e006fe7dd 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 351f6b92a..dc98cd725 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 f1b6f41a0..b07d7cdd9 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;