2002-12-16 20:08:29 -05:00
|
|
|
/* Metacity visual bell */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2002 Sun Microsystems Inc.
|
2005-10-08 15:38:54 -04:00
|
|
|
* Copyright (C) 2005 Elijah Newren
|
2002-12-16 20:08:29 -05:00
|
|
|
*
|
|
|
|
* 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)
|
|
|
|
{
|
A load of fixes of issues reported by sparse. Closes bug #152849
2004-09-17 Kjartan Maraas <kmaraas@gnome.org>
* src/bell.c: (meta_bell_flash_screen):
* src/compositor.c:
* src/effects.c: (meta_effects_draw_box_animation):
* src/fixedtip.c: (meta_fixed_tip_show):
* src/frame.c: (find_argb_visual):
* src/frames.c: (unsigned_long_hash), (meta_frames_manage_window),
(meta_frames_apply_shapes):
* src/iconcache.c: (find_largest_sizes), (find_best_size):
* src/keybindings.c: (meta_spawn_command_line_async_on_screen):
* src/main.c: (main):
* src/menu.c: (meta_window_menu_new):
* src/prefs.c: (meta_prefs_get_visual_bell),
(meta_prefs_bell_is_audible), (meta_prefs_get_visual_bell_type),
(meta_prefs_get_action_double_click_titlebar),
(meta_prefs_get_auto_raise), (meta_prefs_get_auto_raise_delay),
(meta_prefs_get_reduced_resources):
* src/screen.c: (meta_create_offscreen_window):
* src/tabpopup.c: (meta_ui_tab_popup_get_selected):
* src/theme-parser.c: (meta_theme_load):
* src/theme.c: (meta_gtk_widget_get_font_desc):
* src/tools/metacity-mag.c: (mouse_press), (begin_area_grab):
* src/util.c: (meta_unsigned_long_hash): A load of fixes of issues
reported by sparse. Closes bug #152849
2004-09-16 19:18:22 -04:00
|
|
|
Visual *visual = (Visual *)CopyFromParent;
|
2002-12-16 20:08:29 -05:00
|
|
|
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);
|
2005-10-03 15:22:40 -04:00
|
|
|
XFreeGC (display->xdisplay, gc);
|
2002-12-16 20:08:29 -05:00
|
|
|
}
|
2005-02-25 15:14:08 -05:00
|
|
|
|
|
|
|
if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK &&
|
|
|
|
!display->mouse_mode)
|
|
|
|
meta_display_increment_focus_sentinel (display);
|
2002-12-16 20:08:29 -05:00
|
|
|
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);
|
2003-06-11 13:55:28 -04:00
|
|
|
if (!window && (display->focus_window) && (display->focus_window->frame))
|
2002-12-16 20:08:29 -05:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|