From b299f173490f5c51476ad3c8436b19bb091c1b00 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 10 May 2022 09:32:59 +0800 Subject: [PATCH] Update alpha frame parameter when the window manager changes it * src/xfns.c (x_set_alpha): New function. Set `alpha_identical_p' flag. (x_frame_parm_handlers): Use it to handle `alpha' instead. * src/xterm.c (x_set_frame_alpha): Make tests against current alpha safer. (handle_one_xevent): Set frame alpha when alpha property changes. * src/xterm.h (struct x_output): New flag `alpha_identical_p'. --- src/xfns.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/xterm.c | 48 +++++++++++++++++++++++++++++++++++++++++-- src/xterm.h | 4 ++++ 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index dc8f02780ce..7dbf1e16c3a 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2372,6 +2372,63 @@ x_set_scroll_bar_default_height (struct frame *f) #endif } +static void +x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + double alpha = 1.0; + double newval[2]; + int i; + Lisp_Object item; + bool alpha_identical_p; + + alpha_identical_p = true; + + for (i = 0; i < 2; i++) + { + newval[i] = 1.0; + if (CONSP (arg)) + { + item = CAR (arg); + arg = CDR (arg); + + alpha_identical_p = false; + } + else + item = arg; + + if (NILP (item)) + alpha = - 1.0; + else if (FLOATP (item)) + { + alpha = XFLOAT_DATA (item); + if (! (0 <= alpha && alpha <= 1.0)) + args_out_of_range (make_float (0.0), make_float (1.0)); + } + else if (FIXNUMP (item)) + { + EMACS_INT ialpha = XFIXNUM (item); + if (! (0 <= ialpha && ialpha <= 100)) + args_out_of_range (make_fixnum (0), make_fixnum (100)); + alpha = ialpha / 100.0; + } + else + wrong_type_argument (Qnumberp, item); + newval[i] = alpha; + } + + for (i = 0; i < 2; i++) + f->alpha[i] = newval[i]; + + FRAME_X_OUTPUT (f)->alpha_identical_p = alpha_identical_p; + + if (FRAME_TERMINAL (f)->set_frame_alpha_hook) + { + block_input (); + FRAME_TERMINAL (f)->set_frame_alpha_hook (f); + unblock_input (); + } +} + /* Record in frame F the specified or default value according to ALIST of the parameter named PROP (a Lisp symbol). If no value is @@ -9368,7 +9425,7 @@ frame_parm_handler x_frame_parm_handlers[] = x_set_wait_for_wm, gui_set_fullscreen, gui_set_font_backend, - gui_set_alpha, + x_set_alpha, x_set_sticky, x_set_tool_bar_position, #ifdef HAVE_XDBE diff --git a/src/xterm.c b/src/xterm.c index 10d268dc93f..de3129fd87c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5358,9 +5358,16 @@ x_set_frame_alpha (struct frame *f) &actual, &format, &n, &left, &data); - if (rc == Success && actual != None && data) + if (rc == Success && actual != None + && n && format == XA_CARDINAL && data) { unsigned long value = *(unsigned long *) data; + + /* Xlib sign-extends values greater than 0x7fffffff on 64-bit + machines. Get the low bits by ourself. */ + + value &= 0xffffffff; + if (value == opac) { x_uncatch_errors (); @@ -14746,7 +14753,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, unsigned long nitems, bytesafter; unsigned char *data = NULL; - if (event->xproperty.state == PropertyDelete) { if (!last) @@ -14835,6 +14841,44 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } + if (f && FRAME_X_OUTPUT (f)->alpha_identical_p + && (event->xproperty.atom + == dpyinfo->Xatom_net_wm_window_opacity)) + { + int rc, actual_format; + Atom actual; + unsigned char *tmp_data; + unsigned long n, left, opacity; + + tmp_data = NULL; + + if (event->xproperty.state == PropertyDelete) + { + f->alpha[0] = 1.0; + f->alpha[1] = 1.0; + } + else + { + rc = XGetWindowProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f), + dpyinfo->Xatom_net_wm_window_opacity, + 0, 1, False, XA_CARDINAL, &actual, + &actual_format, &n, &left, &tmp_data); + + if (rc == Success && actual_format == 32 + && actual == XA_CARDINAL && n) + { + opacity = *(unsigned long *) tmp_data & OPAQUE; + f->alpha[0] = (double) opacity / (double) OPAQUE; + f->alpha[1] = (double) opacity / (double) OPAQUE; + + store_frame_param (f, Qalpha, make_float (f->alpha[0])); + } + } + + if (tmp_data) + XFree (tmp_data); + } + if (event->xproperty.window == dpyinfo->root_window && (event->xproperty.atom == dpyinfo->Xatom_net_client_list_stacking || event->xproperty.atom == dpyinfo->Xatom_net_current_desktop) diff --git a/src/xterm.h b/src/xterm.h index 16635053be4..98c4c5f01c6 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -932,6 +932,10 @@ struct x_output false, tell Xt not to wait. */ bool_bf wait_for_wm : 1; + /* True if this frame's alpha value is the same for both the active + and inactive states. */ + bool_bf alpha_identical_p : 1; + #ifdef HAVE_X_I18N /* Input context (currently, this means Compose key handler setup). */ XIC xic; -- 2.39.2