Bug Summary

File:core/bell.c
Warning:line 405, column 10
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bell.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I ./include -D CROMA_LIBEXECDIR="/usr/libexec" -D HOST_ALIAS="" -D CROMA_LOCALEDIR="/usr/share/locale" -D CROMA_PKGDATADIR="/usr/share/croma" -D CROMA_DATADIR="/usr/share" -D G_LOG_DOMAIN="croma" -D SN_API_NOT_YET_FROZEN=1 -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _REENTRANT -D _REENTRANT -I /usr/include/startup-notification-1.0 -I /usr/include/libgtop-2.0 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-14-231308-31150-1 -x c core/bell.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3/* Croma visual bell */
4
5/*
6 * Copyright (C) 2002 Sun Microsystems Inc.
7 * Copyright (C) 2005, 2006 Elijah Newren
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25/**
26 * \file bell.c Ring the bell or flash the screen
27 *
28 * Sometimes, X programs "ring the bell", whatever that means. Croma lets
29 * the user configure the bell to be audible or visible (aka visual), and
30 * if it's visual it can be configured to be frame-flash or fullscreen-flash.
31 * We never get told about audible bells; X handles them just fine by itself.
32 *
33 * Visual bells come in at meta_bell_notify(), which checks we are actually
34 * in visual mode and calls through to bell_visual_notify(). That
35 * function then checks what kind of visual flash you like, and calls either
36 * bell_flash_fullscreen()-- which calls bell_flash_screen() to do
37 * its work-- or bell_flash_frame(), which flashes the focussed window
38 * using bell_flash_window_frame(), unless there is no such window, in
39 * which case it flashes the screen instead. bell_flash_window_frame()
40 * flashes the frame and calls bell_unflash_frame() as a timeout to
41 * remove the flash.
42 *
43 * The visual bell was the result of a discussion in Bugzilla here:
44 * <http://bugzilla.gnome.org/show_bug.cgi?id=99886>.
45 *
46 * Several of the functions in this file are ifdeffed out entirely if we are
47 * found not to have the XKB extension, which is required to do these clever
48 * things with bells; some others are entirely no-ops in that case.
49 */
50
51#include <config.h>
52#include "bell.h"
53#include "screen-private.h"
54#include "prefs.h"
55#include <kanberra-ctk.h>
56
57/**
58 * Flashes one entire screen. This is done by making a window the size of the
59 * whole screen (or reusing the old one, if it's still around), mapping it,
60 * painting it white and then black, and then unmapping it. We set saveunder so
61 * that all the windows behind it come back immediately.
62 *
63 * Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather,
64 * we do them in one go, because we don't have to rely on the theme code
65 * redrawing the frame for us in order to do the flash.
66 *
67 * \param display The display which owns the screen (rather redundant)
68 * \param screen The screen to flash
69 *
70 * \bug The way I read it, this appears not to do the flash
71 * the first time we flash a particular display. Am I wrong?
72 *
73 * \bug This appears to destroy our current XSync status.
74 */
75static void
76bell_flash_screen (MetaDisplay *display,
77 MetaScreen *screen)
78{
79 Window root = screen->xroot;
80 int width = screen->rect.width;
81 int height = screen->rect.height;
82
83 if (screen->flash_window == None0L)
84 {
85 Visual *visual = (Visual *)CopyFromParent0L;
86 XSetWindowAttributes xswa;
87 int depth = CopyFromParent0L;
88 xswa.save_under = True1;
89 xswa.override_redirect = True1;
90 /*
91 * TODO: use XGetVisualInfo and determine which is an
92 * overlay, if one is present, and use the Overlay visual
93 * for this window (for performance reasons).
94 * Not sure how to tell this yet...
95 */
96 screen->flash_window = XCreateWindow (display->xdisplay, root,
97 0, 0, width, height,
98 0, depth,
99 InputOutput1,
100 visual,
101 /* note: XSun doesn't like SaveUnder here */
102 CWSaveUnder(1L<<10) | CWOverrideRedirect(1L<<9),
103 &xswa);
104 XSelectInput (display->xdisplay, screen->flash_window, ExposureMask(1L<<15));
105 XMapWindow (display->xdisplay, screen->flash_window);
106 XSync (display->xdisplay, False0);
107 XFlush (display->xdisplay);
108 XUnmapWindow (display->xdisplay, screen->flash_window);
109 }
110 else
111 {
112 /* just draw something in the window */
113 GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL((void*)0));
114 XMapWindow (display->xdisplay, screen->flash_window);
115 XSetForeground (display->xdisplay, gc,
116 WhitePixel (display->xdisplay,((&((_XPrivDisplay)(display->xdisplay))->screens[XScreenNumberOfScreen
(screen->xscreen)])->white_pixel)
117 XScreenNumberOfScreen (screen->xscreen))((&((_XPrivDisplay)(display->xdisplay))->screens[XScreenNumberOfScreen
(screen->xscreen)])->white_pixel)
);
118 XFillRectangle (display->xdisplay, screen->flash_window, gc,
119 0, 0, width, height);
120 XSetForeground (display->xdisplay, gc,
121 BlackPixel (display->xdisplay,((&((_XPrivDisplay)(display->xdisplay))->screens[XScreenNumberOfScreen
(screen->xscreen)])->black_pixel)
122 XScreenNumberOfScreen (screen->xscreen))((&((_XPrivDisplay)(display->xdisplay))->screens[XScreenNumberOfScreen
(screen->xscreen)])->black_pixel)
);
123 XFillRectangle (display->xdisplay, screen->flash_window, gc,
124 0, 0, width, height);
125 XFlush (display->xdisplay);
126 XSync (display->xdisplay, False0);
127 XUnmapWindow (display->xdisplay, screen->flash_window);
128 XFreeGC (display->xdisplay, gc);
129 }
130
131 if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK &&
132 !display->mouse_mode)
133 meta_display_increment_focus_sentinel (display);
134 XFlush (display->xdisplay);
135}
136
137/**
138 * Flashes one screen, or all screens, in response to a bell event.
139 * If the event is on a particular window, flash the screen that
140 * window is on. Otherwise, flash every screen on this display.
141 *
142 * If the configure script found we had no XKB, this does not exist.
143 *
144 * \param display The display the event came in on
145 * \param xkb_ev The bell event
146 */
147#ifdef HAVE_XKB
148static void
149bell_flash_fullscreen (MetaDisplay *display,
150 XkbAnyEvent *xkb_ev)
151{
152 XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
153 MetaScreen *screen;
154
155 g_assert (xkb_ev->xkb_type == XkbBellNotify)do { if (xkb_ev->xkb_type == 8) ; else g_assertion_message_expr
("croma", "core/bell.c", 155, ((const char*) (__func__)), "xkb_ev->xkb_type == XkbBellNotify"
); } while (0)
;
156 if (xkb_bell_ev->window != None0L)
157 {
158 screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
159 if (screen)
160 bell_flash_screen (display, screen);
161 }
162 else
163 {
164 GSList *screen_list = display->screens;
165 while (screen_list)
166 {
167 screen = (MetaScreen *) screen_list->data;
168 bell_flash_screen (display, screen);
169 screen_list = screen_list->next;
170 }
171 }
172}
173
174/**
175 * Makes a frame be not flashed; this is the timeout half of
176 * bell_flash_window_frame(). This is done simply by clearing the
177 * flash flag and queuing a redraw of the frame.
178 *
179 * If the configure script found we had no XKB, this does not exist.
180 *
181 * \param data The frame to unflash, cast to a gpointer so it can go into
182 * a callback function.
183 * \return Always FALSE, so we don't get called again.
184 *
185 * \bug This is the parallel to bell_flash_window_frame(), so it should
186 * really be called meta_bell_unflash_window_frame().
187 */
188static gboolean
189bell_unflash_frame (gpointer data)
190{
191 MetaFrame *frame = (MetaFrame *) data;
192 frame->is_flashing = 0;
193 meta_frame_queue_draw (frame);
194 return FALSE(0);
195}
196
197/**
198 * Makes a frame flash and then return to normal shortly afterwards.
199 * This is done by setting a flag so that the theme
200 * code will temporarily draw the frame as focussed if it's unfocussed and
201 * vice versa, and then queueing a redraw. Lastly, we create a timeout so
202 * that the flag can be unset and the frame re-redrawn.
203 *
204 * If the configure script found we had no XKB, this does not exist.
205 *
206 * \param window The window to flash
207 */
208static void
209bell_flash_window_frame (MetaWindow *window)
210{
211 g_assert (window->frame != NULL)do { if (window->frame != ((void*)0)) ; else g_assertion_message_expr
("croma", "core/bell.c", 211, ((const char*) (__func__)), "window->frame != NULL"
); } while (0)
;
212 window->frame->is_flashing = 1;
213 meta_frame_queue_draw (window->frame);
214 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE200, 100,
215 bell_unflash_frame, window->frame, NULL((void*)0));
216}
217
218/**
219 * Flashes the frame of the focussed window. If there is no focussed window,
220 * flashes the screen.
221 *
222 * \param display The display the bell event came in on
223 * \param xkb_ev The bell event we just received
224 */
225static void
226bell_flash_frame (MetaDisplay *display,
227 XkbAnyEvent *xkb_ev)
228{
229 XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
230 MetaWindow *window;
231
232 g_assert (xkb_ev->xkb_type == XkbBellNotify)do { if (xkb_ev->xkb_type == 8) ; else g_assertion_message_expr
("croma", "core/bell.c", 232, ((const char*) (__func__)), "xkb_ev->xkb_type == XkbBellNotify"
); } while (0)
;
233 window = meta_display_lookup_x_window (display, xkb_bell_event->window);
234 if (!window && (display->focus_window))
235 {
236 window = display->focus_window;
237 }
238 if (window && window->frame)
239 {
240 bell_flash_window_frame (window);
241 }
242 else /* revert to fullscreen flash if there's no focussed window */
243 {
244 bell_flash_fullscreen (display, xkb_ev);
245 }
246}
247
248/**
249 * Gives the user some kind of visual bell substitute, in response to a
250 * bell event. What this is depends on the "visual bell type" pref.
251 *
252 * If the configure script found we had no XKB, this does not exist.
253 *
254 * \param display The display the bell event came in on
255 * \param xkb_ev The bell event we just received
256 *
257 * \bug This should be merged with meta_bell_notify().
258 */
259static void
260bell_visual_notify (MetaDisplay *display,
261 XkbAnyEvent *xkb_ev)
262{
263 switch (meta_prefs_get_visual_bell_type ())
264 {
265 case META_VISUAL_BELL_FULLSCREEN_FLASH:
266 bell_flash_fullscreen (display, xkb_ev);
267 break;
268 case META_VISUAL_BELL_FRAME_FLASH:
269 bell_flash_frame (display, xkb_ev); /* does nothing yet */
270 break;
271 case META_VISUAL_BELL_INVALID:
272 /* do nothing */
273 break;
274 }
275}
276
277void
278meta_bell_notify (MetaDisplay *display,
279 XkbAnyEvent *xkb_ev)
280{
281 /* flash something */
282 if (meta_prefs_get_visual_bell ())
283 bell_visual_notify (display, xkb_ev);
284
285 if (meta_prefs_bell_is_audible ())
286 {
287 ka_proplist *p;
288 XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
289 MetaWindow *window;
290 int res;
291
292 ka_proplist_create (&p);
293 ka_proplist_sets (p, KA_PROP_EVENT_ID"event.id", "bell-window-system");
294 ka_proplist_sets (p, KA_PROP_EVENT_DESCRIPTION"event.description", _("Bell event")dgettext ("croma", "Bell event"));
295 ka_proplist_sets (p, KA_PROP_KANBERRA_CACHE_CONTROL"kanberra.cache-control", "permanent");
296
297 window = meta_display_lookup_x_window (display, xkb_bell_event->window);
298 if (!window && (display->focus_window) && (display->focus_window->frame))
299 window = display->focus_window;
300
301 if (window)
302 {
303 int x=-1, y=-1, width=-1, height=-1, screen_width=-1, screen_height=-1;
304 MetaScreen *screen;
305
306 screen = meta_window_get_screen (window);
307
308 ka_proplist_sets (p, KA_PROP_WINDOW_NAME"window.name", window->title);
309 ka_proplist_setf (p, KA_PROP_WINDOW_X11_XID"window.x11.xid", "%lu", (unsigned long)window->xwindow);
310 ka_proplist_setf (p, KA_PROP_WINDOW_X11_SCREEN"window.x11.screen", "%i", meta_screen_get_screen_number(screen));
311 ka_proplist_sets (p, KA_PROP_APPLICATION_NAME"application.name", window->res_name);
312 ka_proplist_setf (p, KA_PROP_APPLICATION_PROCESS_ID"application.process.id", "%d", window->net_wm_pid);
313
314 /* properties for positional sound based on window placement */
315 meta_window_get_geometry (window, &x, &y, &width, &height);
316 ka_proplist_setf (p, KA_PROP_WINDOW_X"window.x", "%i", x);
317 ka_proplist_setf (p, KA_PROP_WINDOW_Y"window.y", "%i", y);
318 ka_proplist_setf (p, KA_PROP_WINDOW_WIDTH"window.width", "%i", width);
319 ka_proplist_setf (p, KA_PROP_WINDOW_HEIGHT"window.height", "%i", height);
320
321 meta_screen_get_size (screen, &screen_width, &screen_height);
322 if (screen_width > 1)
323 {
324 x += width/2;
325 x = CLAMP(x, 0, screen_width-1)(((x) > (screen_width-1)) ? (screen_width-1) : (((x) < (
0)) ? (0) : (x)))
;
326
327 /* From libkanberra-ctk.
328 * We use these strange format strings here to avoid that libc
329 * applies locale information on the formatting of floating
330 * numbers. */
331
332 ka_proplist_setf (p, KA_PROP_WINDOW_HPOS"window.hpos", "%i.%03i",
333 (int) (x/(screen_width-1)), (int) (1000.0*x/(screen_width-1)) % 1000);
334 }
335 if (screen_height > 1)
336 {
337 y += height/2;
338 y = CLAMP(y, 0, screen_height-1)(((y) > (screen_height-1)) ? (screen_height-1) : (((y) <
(0)) ? (0) : (y)))
;
339
340 ka_proplist_setf (p, KA_PROP_WINDOW_VPOS"window.vpos", "%i.%03i",
341 (int) (y/(screen_height-1)), (int) (1000.0*y/(screen_height-1)) % 1000);
342 }
343 }
344
345 /* First, we try to play a real sound ... */
346 res = ka_context_play_full (ka_ctk_context_get (), 1, p, NULL((void*)0), NULL((void*)0));
347
348 ka_proplist_destroy (p);
349
350 if (res != KA_SUCCESS && res != KA_ERROR_DISABLED)
351 {
352 /* ...and in case that failed we use the classic X11 bell. */
353 XkbForceDeviceBell (display->xdisplay,
354 xkb_bell_event->device,
355 xkb_bell_event->bell_class,
356 xkb_bell_event->bell_id,
357 xkb_bell_event->percent);
358 }
359 }
360}
361#endif /* HAVE_XKB */
362
363void
364meta_bell_set_audible (MetaDisplay *display, gboolean audible)
365{
366}
367
368gboolean
369meta_bell_init (MetaDisplay *display)
370{
371#ifdef HAVE_XKB
372 int xkb_base_error_type, xkb_opcode;
373
374 if (!XkbQueryExtension (display->xdisplay, &xkb_opcode,
375 &display->xkb_base_event_type,
376 &xkb_base_error_type,
377 NULL((void*)0), NULL((void*)0)))
378 {
379 display->xkb_base_event_type = -1;
380 g_message ("could not find XKB extension.");
381 return FALSE(0);
382 }
383 else
384 {
385 unsigned int mask = XkbBellNotifyMask(1L << 8);
386 gboolean visual_bell_auto_reset = FALSE(0);
387 /* TRUE if and when non-broken version is available */
388 XkbSelectEvents (display->xdisplay,
389 XkbUseCoreKbd0x0100,
390 XkbBellNotifyMask(1L << 8),
391 XkbBellNotifyMask(1L << 8));
392 XkbChangeEnabledControls (display->xdisplay,
393 XkbUseCoreKbd0x0100,
394 XkbAudibleBellMask(1L << 9),
395 0);
396 if (visual_bell_auto_reset) {
397 XkbSetAutoResetControls (display->xdisplay,
398 XkbAudibleBellMask(1L << 9),
399 &mask,
400 &mask);
401 }
402 return TRUE(!(0));
403 }
404#endif
405 return FALSE(0);
This statement is never executed
406}
407
408void
409meta_bell_shutdown (MetaDisplay *display)
410{
411#ifdef HAVE_XKB
412 /* TODO: persist initial bell state in display, reset here */
413 XkbChangeEnabledControls (display->xdisplay,
414 XkbUseCoreKbd0x0100,
415 XkbAudibleBellMask(1L << 9),
416 XkbAudibleBellMask(1L << 9));
417#endif
418}
419
420/**
421 * Deals with a frame being destroyed. This is important because if we're
422 * using a visual bell, we might be flashing the edges of the frame, and
423 * so we'd have a timeout function waiting ready to un-flash them. If the
424 * frame's going away, we can tell the timeout not to bother.
425 *
426 * \param frame The frame which is being destroyed
427 */
428void
429meta_bell_notify_frame_destroy (MetaFrame *frame)
430{
431 if (frame->is_flashing)
432 g_source_remove_by_funcs_user_data (&g_timeout_funcs, frame);
433}