diff options
Diffstat (limited to 'src/core/bell.c')
-rw-r--r-- | src/core/bell.c | 363 |
1 files changed, 0 insertions, 363 deletions
diff --git a/src/core/bell.c b/src/core/bell.c deleted file mode 100644 index 1b6022c8..00000000 --- a/src/core/bell.c +++ /dev/null @@ -1,363 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -/** - * \file bell.c Ring the bell or flash the screen - * - * Sometimes, X programs "ring the bell", whatever that means. Metacity 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 focussed window - * using bell_flash_window_frame(), unless there is no such window, in - * which case it flashes the screen instead. bell_flash_window_frame() - * flashes the frame and calls bell_unflash_frame() as a timeout to - * remove the flash. - * - * 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 "bell.h" -#include "screen-private.h" -#include "prefs.h" - -/** - * Flashes one entire screen. This is done by making a window the size of the - * whole screen (or reusing the old one, if it's still around), mapping it, - * painting it white and then black, and then unmapping it. We set saveunder so - * that all the windows behind it come back immediately. - * - * Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather, - * we do them in one go, because we don't have to rely on the theme code - * redrawing the frame for us in order to do the flash. - * - * \param display The display which owns the screen (rather redundant) - * \param screen The screen to flash - * - * \bug The way I read it, this appears not to do the flash - * the first time we flash a particular display. Am I wrong? - * - * \bug This appears to destroy our current XSync status. - */ -static void -bell_flash_screen (MetaDisplay *display, - MetaScreen *screen) -{ - Window root = screen->xroot; - int width = screen->rect.width; - int height = screen->rect.height; - - if (screen->flash_window == None) - { - Visual *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); - XFreeGC (display->xdisplay, gc); - } - - if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK && - !display->mouse_mode) - meta_display_increment_focus_sentinel (display); - XFlush (display->xdisplay); -} - -/** - * 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. - * - * \param display The display the event came in on - * \param xkb_ev The bell event - */ -#ifdef HAVE_XKB -static void -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) - bell_flash_screen (display, screen); - } - else - { - GSList *screen_list = display->screens; - while (screen_list) - { - screen = (MetaScreen *) screen_list->data; - bell_flash_screen (display, screen); - screen_list = screen_list->next; - } - } -} - -/** - * Makes a frame be not flashed; this is the timeout half of - * bell_flash_window_frame(). This is done simply by clearing the - * flash flag and queuing a redraw of the frame. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param data The frame to unflash, cast to a gpointer so it can go into - * a callback function. - * \return Always FALSE, so we don't get called again. - * - * \bug This is the parallel to bell_flash_window_frame(), so it should - * really be called meta_bell_unflash_window_frame(). - */ -static gboolean -bell_unflash_frame (gpointer data) -{ - MetaFrame *frame = (MetaFrame *) data; - frame->is_flashing = 0; - meta_frame_queue_draw (frame); - return FALSE; -} - -/** - * Makes a frame flash and then return to normal shortly afterwards. - * This is done by setting a flag so that the theme - * code will temporarily draw the frame as focussed if it's unfocussed and - * vice versa, and then queueing a redraw. Lastly, we create a timeout so - * that the flag can be unset and the frame re-redrawn. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param window The window to flash - */ -static void -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, - bell_unflash_frame, window->frame, NULL); -} - -/** - * Flashes the frame of the focussed window. If there is no focussed window, - * flashes the screen. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - */ -static void -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) && (display->focus_window->frame)) - { - window = display->focus_window; - } - if (window) - { - bell_flash_window_frame (window); - } - else /* revert to fullscreen flash if there's no focussed window */ - { - bell_flash_fullscreen (display, xkb_ev); - } -} - -/** - * 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. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - * - * \bug This should be merged with meta_bell_notify(). - */ -static void -bell_visual_notify (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - switch (meta_prefs_get_visual_bell_type ()) - { - case META_VISUAL_BELL_FULLSCREEN_FLASH: - bell_flash_fullscreen (display, xkb_ev); - break; - case META_VISUAL_BELL_FRAME_FLASH: - 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 ()) - bell_visual_notify (display, xkb_ev); -} -#endif /* HAVE_XKB */ - -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 -} - -/** - * Deals with a frame being destroyed. This is important because if we're - * using a visual bell, we might be flashing the edges of the frame, and - * so we'd have a timeout function waiting ready to un-flash them. If the - * frame's going away, we can tell the timeout not to bother. - * - * \param frame The frame which is being destroyed - */ -void -meta_bell_notify_frame_destroy (MetaFrame *frame) -{ - if (frame->is_flashing) - g_source_remove_by_funcs_user_data (&g_timeout_funcs, frame); -} |