diff --git a/ChangeLog b/ChangeLog index dc13ce858..b86431010 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2003-01-28 Bill Haneman + + * Re-instated visual-bell patch + (please see ChangeLog entry for 2002-12-16 for details). + + * src/prefs.c: + (visual_bell_type_from_string): + Accept a NULL string for 'visual-bell-type'. + 2003-01-25 Havoc Pennington * src/stack.c (window_is_fullscreen_size): When checking if a @@ -407,6 +416,136 @@ Tue Dec 17 17:50:19 2002 HideToshi Tajima * src/window-props.c (init_wm_name): argh, screwed that up. get WM_NAME as VALUE_TEXT_PROPERTY #101383 +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: use META_PROP_VALUE_STRING_AS_UTF8 so diff --git a/configure.in b/configure.in index 8988650d8..54b2c6c9f 100644 --- a/configure.in +++ b/configure.in @@ -235,6 +235,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 3571b85a8..6b1087574 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/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 a19e9e48e..36971cc9b 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 @@ -48,6 +49,9 @@ #ifdef HAVE_SHAPE #include #endif +#ifdef HAVE_XKB +#include +#endif #include #define USE_GDK_DISPLAY @@ -311,6 +315,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); @@ -1908,6 +1914,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; } @@ -3965,4 +3984,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 8bcf50d87..c5dae68aa 100644 --- a/src/display.h +++ b/src/display.h @@ -246,6 +246,9 @@ struct _MetaDisplay MetaResizePopup *grab_resize_popup; GTimeVal grab_last_moveresize_time; Time grab_motion_notify_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 10ae0a5e2..4d22cacc5 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" @@ -59,6 +60,7 @@ meta_window_ensure_frame (MetaWindow *window) frame->mapped = FALSE; frame->need_reapply_frame_shape = TRUE; + frame->is_flashing = FALSE; attrs.event_mask = EVENT_MASK; @@ -162,6 +164,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, @@ -258,6 +261,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 afa19557c..02de0abd5 100644 --- a/src/frame.h +++ b/src/frame.h @@ -58,6 +58,7 @@ struct _MetaFrame guint mapped : 1; guint need_reapply_frame_shape : 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 f37b20e68..0c0bb03a6 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 + focused 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 fede2e98e..512a555b5 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,51 @@ update_use_system_font (gboolean value) return old != value; } + +static MetaVisualBellType +visual_bell_type_from_string (const char *value) +{ + if (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) @@ -1191,6 +1288,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)"; @@ -1775,6 +1884,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 a7bef316c..45e9d7fe7 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, @@ -233,6 +236,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 2f65aa908..70549cef4 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 16e907073..dd47da95d 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;