commit 579d7c20da5406575e087e4e8cb0a5621d28037b (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Sun Dec 19 09:43:26 2021 +0800 Add missing implementation of `pgtk-menu-bar-open' * lisp/term/pgtk-win.el (pgtk-menu-bar-open): New function. (bug#52604) diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 689a5e595a..bd925a0129 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -497,6 +497,18 @@ This uses `icon-map-list' to map icon file names to stock icon names." (and value (cdr value)))) x-gtk-stock-cache)))) +(declare-function accelerate-menu "pgtkmenu.c" (&optional frame) t) + +(defun pgtk-menu-bar-open (&optional frame) + "Open the menu bar if it is shown. +`popup-menu' is used if it is off." + (interactive "i") + (cond + ((and (not (zerop (or (frame-parameter nil 'menu-bar-lines) 0))) + (fboundp 'accelerate-menu)) + (accelerate-menu frame)) + (t + (popup-menu (mouse-menu-bar-map) last-nonmenu-event)))) (provide 'pgtk-win) (provide 'term/pgtk-win) commit 1fce1d99d4f0b37481dce19bebaf93ccffde4cff Author: Po Lu Date: Sun Dec 19 09:18:20 2021 +0800 * src/gtkutil.c: Remove obsolete fixme. diff --git a/src/gtkutil.c b/src/gtkutil.c index c10b362370..62a9c05a97 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -17,13 +17,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . */ -/* FIXME: This code is problematic; it misuses GTK, so the GTK - developers don't think they should fix the resulting problems in GTK - itself. The right way to fix this is by rewriting the code in Emacs - to use GTK3 properly. As of 2020, there is a project to do this. - Talk with Yuuki Harano if you are interested - in doing substantial work on this. */ - #include #ifdef USE_GTK commit 1758db1bd86d2ee358824a51d82dc5f711406fec Author: Po Lu Date: Sun Dec 19 08:48:15 2021 +0800 * etc/NEWS: Add news entry for pgtk. diff --git a/etc/NEWS b/etc/NEWS index e3665b918a..b50e7e5db0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -64,6 +64,13 @@ this support. The named feature 'xinput2' can be used to test for the presence of XInput 2 support from Lisp programs. +** Emacs now supports being built with pure GTK. +To use this option, make sure the GTK 3 and Cairo development files +are installed, and configure Emacs with the option '--with-pgtk'. +Unlike the default X and GTK build, the resulting Emacs binary will +work on any underlying window system supported by GDK, such as +Wayland and Broadway. + * Startup Changes in Emacs 29.1 commit f05a93e8232e6f56458ac16d733b03e96a63e930 Author: Paul Eggert Date: Sat Dec 18 16:12:38 2021 -0800 Update from gnulib Make the following changes by hand, and run ‘admin/merge-gnulib’. * configure.ac (AM_CONDITIONAL): Adjust to new Gnulib convention. diff --git a/build-aux/config.guess b/build-aux/config.guess index e81d3ae7c2..1105a74983 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -4,7 +4,7 @@ # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2021-06-03' +timestamp='2021-11-30' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -437,7 +437,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 @@ -1522,6 +1522,9 @@ EOF i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; + i*86:Fiwix:*:*) + GUESS=$UNAME_MACHINE-pc-fiwix + ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; diff --git a/build-aux/config.sub b/build-aux/config.sub index d74fb6deac..38f3d037a7 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -4,7 +4,7 @@ # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2021-08-14' +timestamp='2021-10-27' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -1304,7 +1304,7 @@ esac if test x$basic_os != x then -# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) @@ -1748,7 +1748,8 @@ case $os in | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ - | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*) + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ + | fiwix* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) diff --git a/configure.ac b/configure.ac index c00233edec..2e7ea2bd6f 100644 --- a/configure.ac +++ b/configure.ac @@ -1198,8 +1198,8 @@ fi) dnl Automake replacements. AC_DEFUN([AM_CONDITIONAL], - [$2 && $1=1 || $1= - AC_SUBST([$1])]) + [$2 && $1_CONDITION=1 || $1_CONDITION= + AC_SUBST([$1_CONDITION])]) dnl Prefer silent make output. For verbose output, use dnl 'configure --disable-silent-rules' or 'make V=1' . diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index e48383defc..6e19429894 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2021-04-25.21} +\def\texinfoversion{2021-11-01.16} % % Copyright 1985, 1986, 1988, 1990-2021 Free Software Foundation, Inc. % @@ -3614,6 +3614,9 @@ \def\quotedblbase{{\ecfont \char"12}} \def\quotesinglbase{{\ecfont \char"0D}} % +\def\L{{\ecfont \char"8A}} % L with stroke +\def\l{{\ecfont \char"AA}} % l with stroke +% % This positioning is not perfect (see the ogonek LaTeX package), but % we have the precomposed glyphs for the most common cases. We put the % tests to use those glyphs in the single \ogonek macro so we have fewer @@ -7592,6 +7595,7 @@ % \def\printdefunline#1#2{% \begingroup + \plainfrenchspacing % call \deffnheader: #1#2 \endheader % common ending: @@ -9402,7 +9406,7 @@ \fi\fi % \ifimagevmode - \nobreak\medskip + \medskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. @@ -11599,11 +11603,9 @@ @setregularquotes @c Local variables: -@c eval: (add-hook 'before-save-hook 'time-stamp) +@c eval: (add-hook 'before-save-hook 'time-stamp nil t) +@c time-stamp-pattern: "texinfoversion{%Y-%02m-%02d.%02H}" @c page-delimiter: "^\\\\message\\|emacs-page" -@c time-stamp-start: "def\\\\texinfoversion{" -@c time-stamp-format: "%:y-%02m-%02d.%02H" -@c time-stamp-end: "}" @c End: @c vim:sw=2: diff --git a/lib/cdefs.h b/lib/cdefs.h index 4dac9d264d..a05b538579 100644 --- a/lib/cdefs.h +++ b/lib/cdefs.h @@ -1,4 +1,5 @@ /* Copyright (C) 1992-2021 Free Software Foundation, Inc. + Copyright The GNU Toolchain Authors. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -150,6 +151,53 @@ # define __glibc_objsize(__o) __bos (__o) #endif +/* Compile time conditions to choose between the regular, _chk and _chk_warn + variants. These conditions should get evaluated to constant and optimized + away. */ + +#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s)) +#define __glibc_unsigned_or_positive(__l) \ + ((__typeof (__l)) 0 < (__typeof (__l)) -1 \ + || (__builtin_constant_p (__l) && (__l) > 0)) + +/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ + condition can be folded to a constant and if it is true. The -1 check is + redundant because since it implies that __glibc_safe_len_cond is true. */ +#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ + (__glibc_unsigned_or_positive (__l) \ + && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ + __s, __osz)) \ + && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) + +/* Conversely, we know at compile time that the length is unsafe if the + __L * __S <= __OBJSZ condition can be folded to a constant and if it is + false. */ +#define __glibc_unsafe_len(__l, __s, __osz) \ + (__glibc_unsigned_or_positive (__l) \ + && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ + __s, __osz)) \ + && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) + +/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be + declared. */ + +#define __glibc_fortify(f, __l, __s, __osz, ...) \ + (__glibc_safe_or_unknown_len (__l, __s, __osz) \ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ + : __ ## f ## _chk (__VA_ARGS__, __osz))) \ + +/* Fortify function f, where object size argument passed to f is the number of + elements and not total size. */ + +#define __glibc_fortify_n(f, __l, __s, __osz, ...) \ + (__glibc_safe_or_unknown_len (__l, __s, __osz) \ + ? __ ## f ## _alias (__VA_ARGS__) \ + : (__glibc_unsafe_len (__l, __s, __osz) \ + ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ + : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \ + #if __GNUC_PREREQ (4,3) # define __warnattr(msg) __attribute__((__warning__ (msg))) # define __errordecl(name, msg) \ @@ -243,6 +291,15 @@ # define __attribute_alloc_size__(params) /* Ignore. */ #endif +/* Tell the compiler which argument to an allocation function + indicates the alignment of the allocation. */ +#if __GNUC_PREREQ (4, 9) || __glibc_has_attribute (__alloc_align__) +# define __attribute_alloc_align__(param) \ + __attribute__ ((__alloc_align__ param)) +#else +# define __attribute_alloc_align__(param) /* Ignore. */ +#endif + /* At some point during the gcc 2.96 development the `pure' attribute for functions was introduced. We don't want to use it unconditionally (although this would be possible) since it generates warnings. */ @@ -605,12 +662,22 @@ _Static_assert (0, "IEEE 128-bits long double requires redirection on this platf size-index is not provided: access (access-mode, [, ]) */ # define __attr_access(x) __attribute__ ((__access__ x)) +/* For _FORTIFY_SOURCE == 3 we use __builtin_dynamic_object_size, which may + use the access attribute to get object sizes from function definition + arguments, so we can't use them on functions we fortify. Drop the object + size hints for such functions. */ +# if __USE_FORTIFY_LEVEL == 3 +# define __fortified_attr_access(a, o, s) __attribute__ ((__access__ (a, o))) +# else +# define __fortified_attr_access(a, o, s) __attr_access ((a, o, s)) +# endif # if __GNUC_PREREQ (11, 0) # define __attr_access_none(argno) __attribute__ ((__access__ (__none__, argno))) # else # define __attr_access_none(argno) # endif #else +# define __fortified_attr_access(a, o, s) # define __attr_access(x) # define __attr_access_none(argno) #endif diff --git a/lib/gettext.h b/lib/gettext.h index f1c7a24075..a573da3546 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -138,7 +138,7 @@ #define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) -#ifdef __GNUC__ +#if defined __GNUC__ || defined __clang__ __inline #else #ifdef __cplusplus @@ -157,7 +157,7 @@ pgettext_aux (const char *domain, return translation; } -#ifdef __GNUC__ +#if defined __GNUC__ || defined __clang__ __inline #else #ifdef __cplusplus @@ -191,9 +191,8 @@ npgettext_aux (const char *domain, or may have security implications due to non-deterministic stack usage. */ #if (!defined GNULIB_NO_VLA \ - && (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \ - /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc) - || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ )) + && defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \ + && !defined __STDC_NO_VLA__) # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1 #else # define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0 @@ -208,7 +207,7 @@ npgettext_aux (const char *domain, #define dpgettext_expr(Domainname, Msgctxt, Msgid) \ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) -#ifdef __GNUC__ +#if defined __GNUC__ || defined __clang__ __inline #else #ifdef __cplusplus @@ -255,7 +254,7 @@ dcpgettext_expr (const char *domain, #define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) -#ifdef __GNUC__ +#if defined __GNUC__ || defined __clang__ __inline #else #ifdef __cplusplus diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index c7c7eb455b..fbec70c135 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -202,6 +202,9 @@ COM_ERRLIB = @COM_ERRLIB@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CRYPTOLIB = @CRYPTOLIB@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ CYGWIN_OBJ = @CYGWIN_OBJ@ C_SWITCH_MACHINE = @C_SWITCH_MACHINE@ C_SWITCH_SYSTEM = @C_SWITCH_SYSTEM@ @@ -244,18 +247,22 @@ GETOPT_CDEFS_H = @GETOPT_CDEFS_H@ GETOPT_H = @GETOPT_H@ GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@ GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@ -GL_COND_LIBTOOL = @GL_COND_LIBTOOL@ -GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@ -GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@ -GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@ -GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@ -GL_GENERATE_GMP_GMP_H = @GL_GENERATE_GMP_GMP_H@ -GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@ -GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@ -GL_GENERATE_MINI_GMP_H = @GL_GENERATE_MINI_GMP_H@ -GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@ -GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@ -GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@ +GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@ +GL_COND_LIBTOOL_CONDITION = @GL_COND_LIBTOOL_CONDITION@ +GL_GENERATE_ALLOCA_H_CONDITION = @GL_GENERATE_ALLOCA_H_CONDITION@ +GL_GENERATE_BYTESWAP_H_CONDITION = @GL_GENERATE_BYTESWAP_H_CONDITION@ +GL_GENERATE_ERRNO_H_CONDITION = @GL_GENERATE_ERRNO_H_CONDITION@ +GL_GENERATE_EXECINFO_H_CONDITION = @GL_GENERATE_EXECINFO_H_CONDITION@ +GL_GENERATE_GETOPT_CDEFS_H_CONDITION = @GL_GENERATE_GETOPT_CDEFS_H_CONDITION@ +GL_GENERATE_GETOPT_H_CONDITION = @GL_GENERATE_GETOPT_H_CONDITION@ +GL_GENERATE_GMP_GMP_H_CONDITION = @GL_GENERATE_GMP_GMP_H_CONDITION@ +GL_GENERATE_GMP_H_CONDITION = @GL_GENERATE_GMP_H_CONDITION@ +GL_GENERATE_IEEE754_H_CONDITION = @GL_GENERATE_IEEE754_H_CONDITION@ +GL_GENERATE_LIMITS_H_CONDITION = @GL_GENERATE_LIMITS_H_CONDITION@ +GL_GENERATE_MINI_GMP_H_CONDITION = @GL_GENERATE_MINI_GMP_H_CONDITION@ +GL_GENERATE_STDALIGN_H_CONDITION = @GL_GENERATE_STDALIGN_H_CONDITION@ +GL_GENERATE_STDDEF_H_CONDITION = @GL_GENERATE_STDDEF_H_CONDITION@ +GL_GENERATE_STDINT_H_CONDITION = @GL_GENERATE_STDINT_H_CONDITION@ GL_GNULIB_ACCESS = @GL_GNULIB_ACCESS@ GL_GNULIB_ALIGNED_ALLOC = @GL_GNULIB_ALIGNED_ALLOC@ GL_GNULIB_ALPHASORT = @GL_GNULIB_ALPHASORT@ @@ -556,17 +563,24 @@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GREP = @GREP@ GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@ +GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@ GSETTINGS_LIBS = @GSETTINGS_LIBS@ +GSETTINGS_RULES = @GSETTINGS_RULES@ GTK_CFLAGS = @GTK_CFLAGS@ GTK_LIBS = @GTK_LIBS@ GTK_OBJ = @GTK_OBJ@ GZIP_PROG = @GZIP_PROG@ +HAIKU_CFLAGS = @HAIKU_CFLAGS@ +HAIKU_CXX_OBJ = @HAIKU_CXX_OBJ@ +HAIKU_LIBS = @HAIKU_LIBS@ +HAIKU_OBJ = @HAIKU_OBJ@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@ HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ HAVE_ALPHASORT = @HAVE_ALPHASORT@ HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BE_APP = @HAVE_BE_APP@ HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ HAVE_CHOWN = @HAVE_CHOWN@ @@ -600,6 +614,7 @@ HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_POSIX_SPAWN_SETSID = @HAVE_DECL_POSIX_SPAWN_SETSID@ HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@ @@ -690,6 +705,10 @@ HAVE_POPEN = @HAVE_POPEN@ HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@ HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@ +HAVE_POSIX_SPAWNATTR_SETFLAGS = @HAVE_POSIX_SPAWNATTR_SETFLAGS@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@ +HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP = @HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP@ HAVE_PREAD = @HAVE_PREAD@ HAVE_PSELECT = @HAVE_PSELECT@ HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ @@ -726,6 +745,7 @@ HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ HAVE_SIGSET_T = @HAVE_SIGSET_T@ HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_SPAWN_H = @HAVE_SPAWN_H@ HAVE_STDINT_H = @HAVE_STDINT_H@ HAVE_STPCPY = @HAVE_STPCPY@ HAVE_STPNCPY = @HAVE_STPNCPY@ @@ -923,6 +943,8 @@ PATH_SEPARATOR = @PATH_SEPARATOR@ PAXCTL = @PAXCTL@ PAXCTL_dumped = @PAXCTL_dumped@ PAXCTL_notdumped = @PAXCTL_notdumped@ +PGTK_LIBS = @PGTK_LIBS@ +PGTK_OBJ = @PGTK_OBJ@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -1104,6 +1126,7 @@ SETTINGS_LIBS = @SETTINGS_LIBS@ SHELL = @SHELL@ SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SQLITE3_LIBS = @SQLITE3_LIBS@ STDALIGN_H = @STDALIGN_H@ STDDEF_H = @STDDEF_H@ STDINT_H = @STDINT_H@ @@ -1132,6 +1155,8 @@ WARN_CFLAGS = @WARN_CFLAGS@ WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ WERROR_CFLAGS = @WERROR_CFLAGS@ WIDGET_OBJ = @WIDGET_OBJ@ WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ @@ -1153,6 +1178,8 @@ XFT_LIBS = @XFT_LIBS@ XGSELOBJ = @XGSELOBJ@ XINERAMA_CFLAGS = @XINERAMA_CFLAGS@ XINERAMA_LIBS = @XINERAMA_LIBS@ +XINPUT_CFLAGS = @XINPUT_CFLAGS@ +XINPUT_LIBS = @XINPUT_LIBS@ XMENU_OBJ = @XMENU_OBJ@ XMKMF = @XMKMF@ XOBJ = @XOBJ@ @@ -1162,6 +1189,7 @@ XRENDER_LIBS = @XRENDER_LIBS@ XWIDGETS_OBJ = @XWIDGETS_OBJ@ X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@ ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ ac_ct_OBJC = @ac_ct_OBJC@ archlibdir = @archlibdir@ bindir = @bindir@ @@ -1188,34 +1216,35 @@ exec_prefix = @exec_prefix@ gamedir = @gamedir@ gamegroup = @gamegroup@ gameuser = @gameuser@ -gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7 = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7@ -gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b@ -gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31 = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31@ -gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c@ -gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4 = @gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4@ -gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec@ -gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c = @gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c@ -gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1@ -gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@ -gl_GNULIB_ENABLED_cloexec = @gl_GNULIB_ENABLED_cloexec@ -gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b = @gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b@ -gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@ -gl_GNULIB_ENABLED_dynarray = @gl_GNULIB_ENABLED_dynarray@ -gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866 = @gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866@ -gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@ -gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@ -gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@ -gl_GNULIB_ENABLED_lchmod = @gl_GNULIB_ENABLED_lchmod@ -gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@ -gl_GNULIB_ENABLED_rawmemchr = @gl_GNULIB_ENABLED_rawmemchr@ -gl_GNULIB_ENABLED_scratch_buffer = @gl_GNULIB_ENABLED_scratch_buffer@ -gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@ -gl_GNULIB_ENABLED_utimens = @gl_GNULIB_ENABLED_utimens@ +gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION = @gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION@ +gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION = @gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION@ +gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION@ +gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION@ +gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION = @gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION@ +gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION@ +gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION = @gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION@ +gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION@ +gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION@ +gl_GNULIB_ENABLED_cloexec_CONDITION = @gl_GNULIB_ENABLED_cloexec_CONDITION@ +gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION = @gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION@ +gl_GNULIB_ENABLED_dirfd_CONDITION = @gl_GNULIB_ENABLED_dirfd_CONDITION@ +gl_GNULIB_ENABLED_dynarray_CONDITION = @gl_GNULIB_ENABLED_dynarray_CONDITION@ +gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION = @gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION@ +gl_GNULIB_ENABLED_euidaccess_CONDITION = @gl_GNULIB_ENABLED_euidaccess_CONDITION@ +gl_GNULIB_ENABLED_getdtablesize_CONDITION = @gl_GNULIB_ENABLED_getdtablesize_CONDITION@ +gl_GNULIB_ENABLED_getgroups_CONDITION = @gl_GNULIB_ENABLED_getgroups_CONDITION@ +gl_GNULIB_ENABLED_lchmod_CONDITION = @gl_GNULIB_ENABLED_lchmod_CONDITION@ +gl_GNULIB_ENABLED_open_CONDITION = @gl_GNULIB_ENABLED_open_CONDITION@ +gl_GNULIB_ENABLED_rawmemchr_CONDITION = @gl_GNULIB_ENABLED_rawmemchr_CONDITION@ +gl_GNULIB_ENABLED_scratch_buffer_CONDITION = @gl_GNULIB_ENABLED_scratch_buffer_CONDITION@ +gl_GNULIB_ENABLED_strtoll_CONDITION = @gl_GNULIB_ENABLED_strtoll_CONDITION@ +gl_GNULIB_ENABLED_utimens_CONDITION = @gl_GNULIB_ENABLED_utimens_CONDITION@ gl_LIBOBJS = @gl_LIBOBJS@ gl_LTLIBOBJS = @gl_LTLIBOBJS@ gltests_LIBOBJS = @gltests_LIBOBJS@ gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ gltests_WITNESS = @gltests_WITNESS@ +gsettingsschemadir = @gsettingsschemadir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -1296,9 +1325,10 @@ BUILT_SOURCES += $(ALLOCA_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. -ifneq (,$(GL_GENERATE_ALLOCA_H)) +ifneq (,$(GL_GENERATE_ALLOCA_H_CONDITION)) alloca.h: alloca.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''HAVE_ALLOCA_H''@|$(HAVE_ALLOCA_H)|g' < $(srcdir)/alloca.in.h; \ } > $@-t && \ @@ -1327,7 +1357,7 @@ endif ## begin gnulib module at-internal ifeq (,$(OMIT_GNULIB_MODULE_at-internal)) -ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b)) +ifneq (,$(gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION)) libgnu_a_SOURCES += openat-priv.h openat-proc.c endif @@ -1358,9 +1388,10 @@ BUILT_SOURCES += $(BYTESWAP_H) # We need the following in order to create when the system # doesn't have one. -ifneq (,$(GL_GENERATE_BYTESWAP_H)) +ifneq (,$(GL_GENERATE_BYTESWAP_H_CONDITION)) byteswap.h: byteswap.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ cat $(srcdir)/byteswap.in.h; \ } > $@-t && \ @@ -1416,7 +1447,7 @@ endif ## begin gnulib module cloexec ifeq (,$(OMIT_GNULIB_MODULE_cloexec)) -ifneq (,$(gl_GNULIB_ENABLED_cloexec)) +ifneq (,$(gl_GNULIB_ENABLED_cloexec_CONDITION)) libgnu_a_SOURCES += cloexec.c endif @@ -1541,6 +1572,7 @@ BUILT_SOURCES += dirent.h # doesn't have one that works with the given compiler. dirent.h: dirent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''HAVE_DIRENT_H''@|$(HAVE_DIRENT_H)|g' \ @@ -1585,7 +1617,7 @@ endif ## begin gnulib module dirfd ifeq (,$(OMIT_GNULIB_MODULE_dirfd)) -ifneq (,$(gl_GNULIB_ENABLED_dirfd)) +ifneq (,$(gl_GNULIB_ENABLED_dirfd_CONDITION)) endif EXTRA_DIST += dirfd.c @@ -1629,11 +1661,11 @@ endif ## begin gnulib module dynarray ifeq (,$(OMIT_GNULIB_MODULE_dynarray)) -ifneq (,$(gl_GNULIB_ENABLED_dynarray)) +ifneq (,$(gl_GNULIB_ENABLED_dynarray_CONDITION)) BUILT_SOURCES += malloc/dynarray.gl.h malloc/dynarray-skeleton.gl.h malloc/dynarray.gl.h: malloc/dynarray.h - $(AM_V_at)$(MKDIR_P) malloc + $(AM_V_at)$(MKDIR_P) 'malloc' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e '/libc_hidden_proto/d' < $(srcdir)/malloc/dynarray.h; \ @@ -1642,7 +1674,7 @@ malloc/dynarray.gl.h: malloc/dynarray.h MOSTLYCLEANFILES += malloc/dynarray.gl.h malloc/dynarray.gl.h-t malloc/dynarray-skeleton.gl.h: malloc/dynarray-skeleton.c - $(AM_V_at)$(MKDIR_P) malloc + $(AM_V_at)$(MKDIR_P) 'malloc' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|||g' \ @@ -1669,7 +1701,7 @@ endif ## begin gnulib module eloop-threshold ifeq (,$(OMIT_GNULIB_MODULE_eloop-threshold)) -ifneq (,$(gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c)) +ifneq (,$(gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION)) endif EXTRA_DIST += eloop-threshold.h @@ -1684,9 +1716,10 @@ BUILT_SOURCES += $(ERRNO_H) # We need the following in order to create when the system # doesn't have one that is POSIX compliant. -ifneq (,$(GL_GENERATE_ERRNO_H)) +ifneq (,$(GL_GENERATE_ERRNO_H_CONDITION)) errno.h: errno.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -1716,7 +1749,7 @@ endif ## begin gnulib module euidaccess ifeq (,$(OMIT_GNULIB_MODULE_euidaccess)) -ifneq (,$(gl_GNULIB_ENABLED_euidaccess)) +ifneq (,$(gl_GNULIB_ENABLED_euidaccess_CONDITION)) endif EXTRA_DIST += euidaccess.c @@ -1733,9 +1766,10 @@ BUILT_SOURCES += $(EXECINFO_H) # We need the following in order to create when the system # doesn't have one that works. -ifneq (,$(GL_GENERATE_EXECINFO_H)) +ifneq (,$(GL_GENERATE_EXECINFO_H_CONDITION)) execinfo.h: execinfo.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ cat $(srcdir)/execinfo.in.h; \ } > $@-t && \ @@ -1806,6 +1840,7 @@ BUILT_SOURCES += fcntl.h # doesn't have one that works with the given compiler. fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -1966,7 +2001,7 @@ endif ## begin gnulib module getdtablesize ifeq (,$(OMIT_GNULIB_MODULE_getdtablesize)) -ifneq (,$(gl_GNULIB_ENABLED_getdtablesize)) +ifneq (,$(gl_GNULIB_ENABLED_getdtablesize_CONDITION)) endif EXTRA_DIST += getdtablesize.c @@ -1979,7 +2014,7 @@ endif ## begin gnulib module getgroups ifeq (,$(OMIT_GNULIB_MODULE_getgroups)) -ifneq (,$(gl_GNULIB_ENABLED_getgroups)) +ifneq (,$(gl_GNULIB_ENABLED_getgroups_CONDITION)) endif EXTRA_DIST += getgroups.c @@ -2007,8 +2042,10 @@ BUILT_SOURCES += $(GETOPT_H) $(GETOPT_CDEFS_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. +ifneq (,$(GL_GENERATE_GETOPT_H_CONDITION)) getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ @@ -2020,7 +2057,12 @@ getopt.h: getopt.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) < $(srcdir)/getopt.in.h; \ } > $@-t && \ mv -f $@-t $@ +else +getopt.h: $(top_builddir)/config.status + rm -f $@ +endif +ifneq (,$(GL_GENERATE_GETOPT_CDEFS_H_CONDITION)) getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ @@ -2028,6 +2070,10 @@ getopt-cdefs.h: getopt-cdefs.in.h $(top_builddir)/config.status < $(srcdir)/getopt-cdefs.in.h; \ } > $@-t && \ mv -f $@-t $@ +else +getopt-cdefs.h: $(top_builddir)/config.status + rm -f $@ +endif MOSTLYCLEANFILES += getopt.h getopt.h-t getopt-cdefs.h getopt-cdefs.h-t @@ -2052,7 +2098,7 @@ endif ## begin gnulib module gettext-h ifeq (,$(OMIT_GNULIB_MODULE_gettext-h)) -ifneq (,$(gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36)) +ifneq (,$(gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION)) libgnu_a_SOURCES += gettext.h endif @@ -2090,7 +2136,7 @@ endif ## begin gnulib module group-member ifeq (,$(OMIT_GNULIB_MODULE_group-member)) -ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1)) +ifneq (,$(gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION)) endif EXTRA_DIST += group-member.c @@ -2115,9 +2161,10 @@ BUILT_SOURCES += $(IEEE754_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. -ifneq (,$(GL_GENERATE_IEEE754_H)) +ifneq (,$(GL_GENERATE_IEEE754_H_CONDITION)) ieee754.h: ieee754.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \ $(srcdir)/ieee754.in.h; \ @@ -2161,6 +2208,7 @@ BUILT_SOURCES += inttypes.h # doesn't have one that works with the given compiler. inttypes.h: inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -2200,7 +2248,7 @@ endif ## begin gnulib module lchmod ifeq (,$(OMIT_GNULIB_MODULE_lchmod)) -ifneq (,$(gl_GNULIB_ENABLED_lchmod)) +ifneq (,$(gl_GNULIB_ENABLED_lchmod_CONDITION)) endif EXTRA_DIST += lchmod.c @@ -2224,22 +2272,25 @@ ifeq (,$(OMIT_GNULIB_MODULE_libgmp)) BUILT_SOURCES += $(GMP_H) -ifneq (,$(GL_GENERATE_MINI_GMP_H)) +ifneq (,$(GL_GENERATE_GMP_H_CONDITION)) +ifneq (,$(GL_GENERATE_MINI_GMP_H_CONDITION)) # Build gmp.h as a wrapper for mini-gmp.h when using mini-gmp. gmp.h: $(top_builddir)/config.status - echo '#include "mini-gmp.h"' >$@-t + $(MKDIR_P) '.' + echo '#include "mini-gmp.h"' > $@-t mv $@-t $@ -else -ifneq (,$(GL_GENERATE_GMP_GMP_H)) +endif +ifneq (,$(GL_GENERATE_GMP_GMP_H_CONDITION)) # Build gmp.h as a wrapper for gmp/gmp.h. gmp.h: $(top_builddir)/config.status - echo '#include ' >$@-t + $(MKDIR_P) '.' + echo '#include ' > $@-t mv $@-t $@ +endif else gmp.h: $(top_builddir)/config.status rm -f $@ endif -endif MOSTLYCLEANFILES += gmp.h gmp.h-t EXTRA_DIST += mini-gmp-gnulib.c mini-gmp.c mini-gmp.h @@ -2256,9 +2307,10 @@ BUILT_SOURCES += $(LIMITS_H) # We need the following in order to create when the system # doesn't have one that is compatible with GNU. -ifneq (,$(GL_GENERATE_LIMITS_H)) +ifneq (,$(GL_GENERATE_LIMITS_H_CONDITION)) limits.h: limits.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -2293,7 +2345,7 @@ endif ## begin gnulib module malloc-posix ifeq (,$(OMIT_GNULIB_MODULE_malloc-posix)) -ifneq (,$(gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866)) +ifneq (,$(gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION)) endif EXTRA_DIST += malloc.c @@ -2369,7 +2421,7 @@ endif ## begin gnulib module mktime-internal ifeq (,$(OMIT_GNULIB_MODULE_mktime-internal)) -ifneq (,$(gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31)) +ifneq (,$(gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION)) endif EXTRA_DIST += mktime-internal.h mktime.c @@ -2402,7 +2454,7 @@ endif ## begin gnulib module open ifeq (,$(OMIT_GNULIB_MODULE_open)) -ifneq (,$(gl_GNULIB_ENABLED_open)) +ifneq (,$(gl_GNULIB_ENABLED_open_CONDITION)) endif EXTRA_DIST += open.c @@ -2415,7 +2467,7 @@ endif ## begin gnulib module openat-h ifeq (,$(OMIT_GNULIB_MODULE_openat-h)) -ifneq (,$(gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7)) +ifneq (,$(gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7_CONDITION)) endif EXTRA_DIST += openat.h @@ -2473,7 +2525,7 @@ endif ## begin gnulib module rawmemchr ifeq (,$(OMIT_GNULIB_MODULE_rawmemchr)) -ifneq (,$(gl_GNULIB_ENABLED_rawmemchr)) +ifneq (,$(gl_GNULIB_ENABLED_rawmemchr_CONDITION)) endif EXTRA_DIST += rawmemchr.c rawmemchr.valgrind @@ -2508,7 +2560,7 @@ endif ## begin gnulib module realloc-gnu ifeq (,$(OMIT_GNULIB_MODULE_realloc-gnu)) -ifneq (,$(gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b)) +ifneq (,$(gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION)) endif EXTRA_DIST += realloc.c @@ -2521,7 +2573,7 @@ endif ## begin gnulib module realloc-posix ifeq (,$(OMIT_GNULIB_MODULE_realloc-posix)) -ifneq (,$(gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4)) +ifneq (,$(gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION)) endif EXTRA_DIST += realloc.c @@ -2545,7 +2597,7 @@ endif ## begin gnulib module root-uid ifeq (,$(OMIT_GNULIB_MODULE_root-uid)) -ifneq (,$(gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c)) +ifneq (,$(gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION)) endif EXTRA_DIST += root-uid.h @@ -2556,11 +2608,11 @@ endif ## begin gnulib module scratch_buffer ifeq (,$(OMIT_GNULIB_MODULE_scratch_buffer)) -ifneq (,$(gl_GNULIB_ENABLED_scratch_buffer)) +ifneq (,$(gl_GNULIB_ENABLED_scratch_buffer_CONDITION)) BUILT_SOURCES += malloc/scratch_buffer.gl.h malloc/scratch_buffer.gl.h: malloc/scratch_buffer.h - $(AM_V_at)$(MKDIR_P) malloc + $(AM_V_at)$(MKDIR_P) 'malloc' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|__always_inline|inline _GL_ATTRIBUTE_ALWAYS_INLINE|g' \ @@ -2611,6 +2663,7 @@ BUILT_SOURCES += signal.h # doesn't have a complete one. signal.h: signal.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -2719,9 +2772,10 @@ BUILT_SOURCES += $(STDALIGN_H) # We need the following in order to create when the system # doesn't have one that works. -ifneq (,$(GL_GENERATE_STDALIGN_H)) +ifneq (,$(GL_GENERATE_STDALIGN_H_CONDITION)) stdalign.h: stdalign.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ cat $(srcdir)/stdalign.in.h; \ } > $@-t && \ @@ -2744,9 +2798,10 @@ BUILT_SOURCES += $(STDDEF_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. -ifneq (,$(GL_GENERATE_STDDEF_H)) +ifneq (,$(GL_GENERATE_STDDEF_H_CONDITION)) stddef.h: stddef.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -2777,9 +2832,10 @@ BUILT_SOURCES += $(STDINT_H) # We need the following in order to create when the system # doesn't have one that works with the given compiler. -ifneq (,$(GL_GENERATE_STDINT_H)) +ifneq (,$(GL_GENERATE_STDINT_H_CONDITION)) stdint.h: stdint.in.h $(top_builddir)/config.status $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ @@ -2831,6 +2887,7 @@ BUILT_SOURCES += stdio.h # doesn't have one that works with the given compiler. stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -2969,6 +3026,7 @@ BUILT_SOURCES += stdlib.h stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -3125,6 +3183,7 @@ BUILT_SOURCES += string.h # doesn't have one that works with the given compiler. string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -3256,7 +3315,7 @@ endif ## begin gnulib module strtoll ifeq (,$(OMIT_GNULIB_MODULE_strtoll)) -ifneq (,$(gl_GNULIB_ENABLED_strtoll)) +ifneq (,$(gl_GNULIB_ENABLED_strtoll_CONDITION)) endif EXTRA_DIST += strtol.c strtoll.c @@ -3285,7 +3344,7 @@ BUILT_SOURCES += sys/random.h # We need the following in order to create when the system # doesn't have one. sys/random.h: sys_random.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_at)$(MKDIR_P) sys + $(AM_V_at)$(MKDIR_P) 'sys' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -3319,7 +3378,7 @@ BUILT_SOURCES += sys/select.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. sys/select.h: sys_select.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) - $(AM_V_at)$(MKDIR_P) sys + $(AM_V_at)$(MKDIR_P) 'sys' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -3355,7 +3414,7 @@ BUILT_SOURCES += sys/stat.h # We need the following in order to create when the system # has one that is incomplete. sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_at)$(MKDIR_P) sys + $(AM_V_at)$(MKDIR_P) 'sys' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -3430,7 +3489,7 @@ BUILT_SOURCES += sys/time.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. sys/time.h: sys_time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_at)$(MKDIR_P) sys + $(AM_V_at)$(MKDIR_P) 'sys' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -3466,7 +3525,7 @@ BUILT_SOURCES += sys/types.h # We need the following in order to create when the system # doesn't have one that works with the given compiler. sys/types.h: sys_types.in.h $(top_builddir)/config.status - $(AM_V_at)$(MKDIR_P) sys + $(AM_V_at)$(MKDIR_P) 'sys' $(AM_V_GEN)rm -f $@-t $@ && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ @@ -3505,6 +3564,7 @@ BUILT_SOURCES += time.h # doesn't have one that works with the given compiler. time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ @@ -3635,6 +3695,7 @@ libgnu_a_SOURCES += unistd.c # when the system doesn't have one. unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) $(AM_V_GEN)rm -f $@-t $@ && \ + $(MKDIR_P) '.' && \ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ sed -e 's|@''GUARD_PREFIX''@|GL|g' \ -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ @@ -3853,7 +3914,7 @@ endif ## begin gnulib module utimens ifeq (,$(OMIT_GNULIB_MODULE_utimens)) -ifneq (,$(gl_GNULIB_ENABLED_utimens)) +ifneq (,$(gl_GNULIB_ENABLED_utimens_CONDITION)) libgnu_a_SOURCES += utimens.c endif @@ -3894,7 +3955,7 @@ endif ## begin gnulib module xalloc-oversized ifeq (,$(OMIT_GNULIB_MODULE_xalloc-oversized)) -ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec)) +ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION)) endif EXTRA_DIST += xalloc-oversized.h diff --git a/lib/intprops.h b/lib/intprops.h index 3fe64e82e9..7f20f09fa0 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -229,18 +229,18 @@ /* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow (A, B, P) work when P is non-null. */ +#if defined __has_builtin +# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow) /* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x, see . */ -#if 7 <= __GNUC__ && !defined __ICC +#elif 7 <= __GNUC__ && !defined __EDG__ # define _GL_HAS_BUILTIN_ADD_OVERFLOW 1 -#elif defined __has_builtin -# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow) #else # define _GL_HAS_BUILTIN_ADD_OVERFLOW 0 #endif /* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */ -#ifdef __clang__ +#if defined __clang_major_ && __clang_major__ < 14 /* Work around Clang bug . */ # define _GL_HAS_BUILTIN_MUL_OVERFLOW 0 #else @@ -249,9 +249,8 @@ /* True if __builtin_add_overflow_p (A, B, C) works, and similarly for __builtin_sub_overflow_p and __builtin_mul_overflow_p. */ -#if defined __clang__ || defined __ICC -/* Clang 11 lacks __builtin_mul_overflow_p, and even if it did it - would presumably run afoul of Clang bug 16404. ICC 2021.1's +#ifdef __EDG__ +/* In EDG-based compilers like ICC 2021.3 and earlier, __builtin_add_overflow_p etc. are not treated as integral constant expressions even when all arguments are. */ # define _GL_HAS_BUILTIN_OVERFLOW_P 0 @@ -400,7 +399,7 @@ #if _GL_HAS_BUILTIN_MUL_OVERFLOW # if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \ || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \ - && !defined __ICC) + && !defined __EDG__) # define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r) # else /* Work around GCC bug 91450. */ diff --git a/lib/nproc.c b/lib/nproc.c index a9e369dd3f..1af989d6dd 100644 --- a/lib/nproc.c +++ b/lib/nproc.c @@ -307,10 +307,11 @@ num_processors_ignoring_omp (enum nproc_query query) NPROC_CURRENT and NPROC_ALL. */ #if HAVE_SYSCTL && ! defined __GLIBC__ && defined HW_NCPU - { /* This works on Mac OS X, FreeBSD, NetBSD, OpenBSD. */ + { /* This works on macOS, FreeBSD, NetBSD, OpenBSD. + macOS 10.14 does not allow mib to be const. */ int nprocs; size_t len = sizeof (nprocs); - static int const mib[][2] = { + static int mib[][2] = { # ifdef HW_NCPUONLINE { CTL_HW, HW_NCPUONLINE }, # endif diff --git a/lib/nstrftime.c b/lib/nstrftime.c index 7f258e8727..25baf76c60 100644 --- a/lib/nstrftime.c +++ b/lib/nstrftime.c @@ -22,7 +22,7 @@ # define HAVE_TZNAME 1 # include "../locale/localeinfo.h" #else -# include +# include # if FPRINTFTIME # include "fprintftime.h" # else @@ -367,10 +367,7 @@ tm_diff (const struct tm *a, const struct tm *b) #define ISO_WEEK1_WDAY 4 /* Thursday */ #define YDAY_MINIMUM (-366) static int iso_week_days (int, int); -#if defined __GNUC__ || defined __clang__ -__inline__ -#endif -static int +static __inline int iso_week_days (int yday, int wday) { /* Add enough to the first operand of % to make it nonnegative. */ @@ -428,9 +425,7 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) return __strftime_internal (s, STRFTIME_ARG (maxsize) format, tp, false, 0, -1, &tzset_called extra_args LOCALE_ARG); } -#if defined _LIBC && ! FPRINTFTIME libc_hidden_def (my_strftime) -#endif /* Just like my_strftime, above, but with more parameters. UPCASE indicates that the result should be converted to upper case. diff --git a/lib/regcomp.c b/lib/regcomp.c index 887e5b5068..6a97fdee47 100644 --- a/lib/regcomp.c +++ b/lib/regcomp.c @@ -27,14 +27,10 @@ static void re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, char *fastmap); static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -#ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset); -#endif /* RE_ENABLE_I18N */ static void free_workarea_compile (regex_t *preg); static reg_errcode_t create_initial_state (re_dfa_t *dfa); -#ifdef RE_ENABLE_I18N static void optimize_utf8 (re_dfa_t *dfa); -#endif static reg_errcode_t analyze (regex_t *preg); static reg_errcode_t preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), @@ -89,7 +85,6 @@ static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token); -#ifdef RE_ENABLE_I18N static reg_errcode_t build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, Idx *equiv_class_alloc, @@ -100,14 +95,6 @@ static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, Idx *char_class_alloc, const char *class_name, reg_syntax_t syntax); -#else /* not RE_ENABLE_I18N */ -static reg_errcode_t build_equiv_class (bitset_t sbcset, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - const char *class_name, - reg_syntax_t syntax); -#endif /* not RE_ENABLE_I18N */ static bin_tree_t *build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, const char *class_name, @@ -279,8 +266,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp) } weak_alias (__re_compile_fastmap, re_compile_fastmap) -static inline void -__attribute__ ((always_inline)) +static __always_inline void re_set_fastmap (char *fastmap, bool icase, int ch) { fastmap[ch] = 1; @@ -306,7 +292,6 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, if (type == CHARACTER) { re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); -#ifdef RE_ENABLE_I18N if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) { unsigned char buf[MB_LEN_MAX]; @@ -327,7 +312,6 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, != (size_t) -1)) re_set_fastmap (fastmap, false, buf[0]); } -#endif } else if (type == SIMPLE_BRACKET) { @@ -341,13 +325,12 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, re_set_fastmap (fastmap, icase, ch); } } -#ifdef RE_ENABLE_I18N else if (type == COMPLEX_BRACKET) { re_charset_t *cset = dfa->nodes[node].opr.mbcset; Idx i; -# ifdef _LIBC +#ifdef _LIBC /* See if we have to try all bytes which start multiple collation elements. e.g. In da_DK, we want to catch 'a' since "aa" is a valid @@ -363,7 +346,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, if (table[i] < 0) re_set_fastmap (fastmap, icase, i); } -# endif /* _LIBC */ +#endif /* _LIBC */ /* See if we have to start the match at all multibyte characters, i.e. where we would not find an invalid sequence. This only @@ -371,9 +354,9 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, sets, the SIMPLE_BRACKET again suffices. */ if (dfa->mb_cur_max > 1 && (cset->nchar_classes || cset->non_match || cset->nranges -# ifdef _LIBC +#ifdef _LIBC || cset->nequiv_classes -# endif /* _LIBC */ +#endif /* _LIBC */ )) { unsigned char c = 0; @@ -406,12 +389,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, } } } -#endif /* RE_ENABLE_I18N */ - else if (type == OP_PERIOD -#ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -#endif /* RE_ENABLE_I18N */ - || type == END_OF_RE) + else if (type == OP_PERIOD || type == OP_UTF8_PERIOD || type == END_OF_RE) { memset (fastmap, '\1', sizeof (char) * SBC_MAX); if (type == END_OF_RE) @@ -550,7 +528,6 @@ regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf, weak_alias (__regerror, regerror) -#ifdef RE_ENABLE_I18N /* This static array is used for the map to single-byte characters when UTF-8 is used. Otherwise we would allocate memory just to initialize it the same all the time. UTF-8 is the preferred encoding so this is @@ -558,25 +535,24 @@ weak_alias (__regerror, regerror) static const bitset_t utf8_sb_map = { /* Set the first 128 bits. */ -# if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__ +#if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__ [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX -# else -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS +#else +# if 4 * BITSET_WORD_BITS < ASCII_CHARS +# error "bitset_word_t is narrower than 32 bits" +# elif 3 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS +# elif 2 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS +# elif 1 * BITSET_WORD_BITS < ASCII_CHARS BITSET_WORD_MAX, -# endif +# endif (BITSET_WORD_MAX >> (SBC_MAX % BITSET_WORD_BITS == 0 ? 0 : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) -# endif -}; #endif +}; static void @@ -614,10 +590,8 @@ free_dfa_content (re_dfa_t *dfa) re_free (entry->array); } re_free (dfa->state_table); -#ifdef RE_ENABLE_I18N if (dfa->sb_char != utf8_sb_map) re_free (dfa->sb_char); -#endif re_free (dfa->subexp_map); #ifdef DEBUG re_free (dfa->re_str); @@ -796,11 +770,9 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, if (__glibc_unlikely (err != REG_NOERROR)) goto re_compile_internal_free_return; -#ifdef RE_ENABLE_I18N /* If possible, do searching in single byte encoding to speed things up. */ if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) optimize_utf8 (dfa); -#endif /* Then create the initial state of the dfa. */ err = create_initial_state (dfa); @@ -830,11 +802,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) #ifndef _LIBC const char *codeset_name; #endif -#ifdef RE_ENABLE_I18N size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); -#else - size_t max_i18n_object_size = 0; -#endif size_t max_object_size = MAX (sizeof (struct re_state_table_entry), MAX (sizeof (re_token_t), @@ -886,7 +854,6 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) dfa->map_notascii = 0; #endif -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { if (dfa->is_utf8) @@ -906,14 +873,13 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) wint_t wch = __btowc (ch); if (wch != WEOF) dfa->sb_char[i] |= (bitset_word_t) 1 << j; -# ifndef _LIBC +#ifndef _LIBC if (isascii (ch) && wch != ch) dfa->map_notascii = 1; -# endif +#endif } } } -#endif if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL)) return REG_ESPACE; @@ -933,8 +899,6 @@ init_word_char (re_dfa_t *dfa) dfa->word_ops_used = 1; if (__glibc_likely (dfa->map_notascii == 0)) { - /* Avoid uint32_t and uint64_t as some non-GCC platforms lack - them, an issue when this code is used in Gnulib. */ bitset_word_t bits0 = 0x00000000; bitset_word_t bits1 = 0x03ff0000; bitset_word_t bits2 = 0x87fffffe; @@ -1074,7 +1038,6 @@ create_initial_state (re_dfa_t *dfa) return REG_NOERROR; } -#ifdef RE_ENABLE_I18N /* If it is possible to do searching in single byte encoding instead of UTF-8 to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change DFA nodes where needed. */ @@ -1154,7 +1117,6 @@ optimize_utf8 (re_dfa_t *dfa) dfa->is_utf8 = 0; dfa->has_mb_node = dfa->nbackref > 0 || has_period; } -#endif /* Analyze the structure tree, and calculate "first", "next", "edest", "eclosure", and "inveclosure". */ @@ -1792,7 +1754,6 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) token->opr.c = c; token->word_char = 0; -#ifdef RE_ENABLE_I18N token->mb_partial = 0; if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) @@ -1801,7 +1762,6 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) token->mb_partial = 1; return 1; } -#endif if (c == '\\') { unsigned char c2; @@ -1814,7 +1774,6 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) c2 = re_string_peek_byte_case (input, 1); token->opr.c = c2; token->type = CHARACTER; -#ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, @@ -1822,7 +1781,6 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else -#endif token->word_char = IS_WORD_CHAR (c2) != 0; switch (c2) @@ -1928,14 +1886,12 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) } token->type = CHARACTER; -#ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; } else -#endif token->word_char = IS_WORD_CHAR (token->opr.c); switch (c) @@ -2027,14 +1983,12 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) c = re_string_peek_byte (input, 0); token->opr.c = c; -#ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1 && !re_string_first_byte (input, re_string_cur_idx (input))) { token->type = CHARACTER; return 1; } -#endif /* RE_ENABLE_I18N */ if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && re_string_cur_idx (input) + 1 < re_string_length (input)) @@ -2256,7 +2210,6 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, *err = REG_ESPACE; return NULL; } -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (!re_string_eoi (regexp) @@ -2273,7 +2226,6 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, } } } -#endif break; case OP_OPEN_SUBEXP: @@ -2666,40 +2618,30 @@ parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, #ifndef _LIBC -# ifdef RE_ENABLE_I18N /* Convert the byte B to the corresponding wide character. In a unibyte locale, treat B as itself. In a multibyte locale, return WEOF if B is an encoding error. */ static wint_t -parse_byte (unsigned char b, re_charset_t *mbcset) +parse_byte (unsigned char b, re_dfa_t const *dfa) { - return mbcset == NULL ? b : __btowc (b); + return dfa->mb_cur_max > 1 ? __btowc (b) : b; } -# endif - /* Local function for parse_bracket_exp only used in case of NOT _LIBC. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument since we may - update it. */ +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ static reg_errcode_t -# ifdef RE_ENABLE_I18N -build_range_exp (const reg_syntax_t syntax, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *range_alloc, - const bracket_elem_t *start_elem, - const bracket_elem_t *end_elem) -# else /* not RE_ENABLE_I18N */ -build_range_exp (const reg_syntax_t syntax, - bitset_t sbcset, - const bracket_elem_t *start_elem, - const bracket_elem_t *end_elem) -# endif /* not RE_ENABLE_I18N */ +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem, + re_dfa_t *dfa, reg_syntax_t syntax, uint_fast32_t nrules, + const unsigned char *collseqmb, const char *collseqwc, + int_fast32_t table_size, const void *symb_table, + const unsigned char *extra) { - unsigned int start_ch, end_ch; /* Equivalence Classes and Character Classes can't be a range start/end. */ if (__glibc_unlikely (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS @@ -2715,110 +2657,88 @@ build_range_exp (const reg_syntax_t syntax, && strlen ((char *) end_elem->opr.name) > 1))) return REG_ECOLLATE; -# ifdef RE_ENABLE_I18N - { - wchar_t wc; - wint_t start_wc; - wint_t end_wc; - + unsigned int start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); + : 0)), end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] : 0)); + wint_t start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? parse_byte (start_ch, mbcset) : start_elem->opr.wch); + ? parse_byte (start_ch, dfa) : start_elem->opr.wch), end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? parse_byte (end_ch, mbcset) : end_elem->opr.wch); - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) - && start_wc > end_wc)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ - if (__glibc_unlikely (*range_alloc == mbcset->nranges)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); + ? parse_byte (end_ch, dfa) : end_elem->opr.wch); - if (__glibc_unlikely (new_array_start == NULL - || new_array_end == NULL)) - { - re_free (new_array_start); - re_free (new_array_end); - return REG_ESPACE; - } + if (start_wc == WEOF || end_wc == WEOF) + return REG_ECOLLATE; + else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_wc > end_wc)) + return REG_ERANGE; - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } + /* Got valid collation sequence values, add them as a new entry. + However, for !_LIBC we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes + no MBCSET if dfa->mb_cur_max == 1. */ + if (dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) + { + /* There is not enough space, need realloc. */ + wchar_t *new_array_start, *new_array_end; + Idx new_nranges; - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + /* Use realloc since mbcset->range_starts and mbcset->range_ends + are NULL if *range_alloc == 0. */ + new_array_start = re_realloc (mbcset->range_starts, wchar_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, wchar_t, + new_nranges); + + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + { + re_free (new_array_start); + re_free (new_array_end); + return REG_ESPACE; + } + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_wc; + mbcset->range_ends[mbcset->nranges++] = end_wc; + } + + /* Build the table for single byte characters. */ + for (wchar_t wc = 0; wc < SBC_MAX; ++wc) + { + if (start_wc <= wc && wc <= end_wc) + bitset_set (sbcset, wc); + } - /* Build the table for single byte characters. */ - for (wc = 0; wc < SBC_MAX; ++wc) - { - if (start_wc <= wc && wc <= end_wc) - bitset_set (sbcset, wc); - } - } -# else /* not RE_ENABLE_I18N */ - { - unsigned int ch; - start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - if (start_ch > end_ch) - return REG_ERANGE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ++ch) - if (start_ch <= ch && ch <= end_ch) - bitset_set (sbcset, ch); - } -# endif /* not RE_ENABLE_I18N */ return REG_NOERROR; } #endif /* not _LIBC */ #ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. +/* Helper function for parse_bracket_exp only used in case of NOT _LIBC. Build the collating element which is represented by NAME. The result are written to MBCSET and SBCSET. COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a pointer argument since we may update it. */ static reg_errcode_t -# ifdef RE_ENABLE_I18N build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, - Idx *coll_sym_alloc, const unsigned char *name) -# else /* not RE_ENABLE_I18N */ -build_collating_symbol (bitset_t sbcset, const unsigned char *name) -# endif /* not RE_ENABLE_I18N */ + Idx *coll_sym_alloc, const unsigned char *name, + uint_fast32_t nrules, int_fast32_t table_size, + const void *symb_table, const unsigned char *extra) { size_t name_len = strlen ((const char *) name); if (__glibc_unlikely (name_len != 1)) @@ -2831,271 +2751,280 @@ build_collating_symbol (bitset_t sbcset, const unsigned char *name) } #endif /* not _LIBC */ -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ #ifdef _LIBC - const unsigned char *collseqmb; - const char *collseqwc; - uint32_t nrules; - int32_t table_size; - const int32_t *symb_table; - const unsigned char *extra; - - /* Local function for parse_bracket_exp used in _LIBC environment. - Seek the collating symbol entry corresponding to NAME. - Return the index of the symbol in the SYMB_TABLE, - or -1 if not found. */ - - auto inline int32_t - __attribute__ ((always_inline)) - seek_collating_symbol_entry (const unsigned char *name, size_t name_len) - { - int32_t elem; - - for (elem = 0; elem < table_size; elem++) - if (symb_table[2 * elem] != 0) - { - int32_t idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - if (/* Compare the length of the name. */ - name_len == extra[idx] - /* Compare the name. */ - && memcmp (name, &extra[idx + 1], name_len) == 0) - /* Yep, this is the entry. */ - return elem; - } - return -1; - } +/* Local function for parse_bracket_exp used in _LIBC environment. + Seek the collating symbol entry corresponding to NAME. + Return the index of the symbol in the SYMB_TABLE, + or -1 if not found. */ + +static __always_inline int32_t +seek_collating_symbol_entry (const unsigned char *name, size_t name_len, + const int32_t *symb_table, + int_fast32_t table_size, + const unsigned char *extra) +{ + int_fast32_t elem; - /* Local function for parse_bracket_exp used in _LIBC environment. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + int32_t idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + if (/* Compare the length of the name. */ + name_len == extra[idx] + /* Compare the name. */ + && memcmp (name, &extra[idx + 1], name_len) == 0) + /* Yep, this is the entry. */ + return elem; + } + return -1; +} - auto inline unsigned int - __attribute__ ((always_inline)) - lookup_collation_sequence_value (bracket_elem_t *br_elem) +/* Local function for parse_bracket_exp used in _LIBC environment. + Look up the collation sequence value of BR_ELEM. + Return the value if succeeded, UINT_MAX otherwise. */ + +static __always_inline unsigned int +lookup_collation_sequence_value (bracket_elem_t *br_elem, uint32_t nrules, + const unsigned char *collseqmb, + const char *collseqwc, + int_fast32_t table_size, + const int32_t *symb_table, + const unsigned char *extra) +{ + if (br_elem->type == SB_CHAR) { - if (br_elem->type == SB_CHAR) - { - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) + /* if (MB_CUR_MAX == 1) */ + if (nrules == 0) + return collseqmb[br_elem->opr.ch]; + else { - if (nrules != 0) - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); } - else if (br_elem->type == COLL_SYM) + } + else if (br_elem->type == MB_CHAR) + { + if (nrules != 0) + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); + if (nrules != 0) { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len, + symb_table, table_size, + extra); + if (elem != -1) { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len); - if (elem != -1) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + /* Skip the byte sequence of the collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the multibyte collation sequence value. */ + idx += sizeof (unsigned int); + /* Skip the wide char sequence of the collating element. */ + idx += sizeof (unsigned int) * + (1 + *(unsigned int *) (extra + idx)); + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); } else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; + { + /* No valid character. Match it as a single byte + character. */ + return collseqmb[br_elem->opr.name[0]]; + } } - return UINT_MAX; + else if (sym_name_len == 1) + return collseqmb[br_elem->opr.name[0]]; } + return UINT_MAX; +} - /* Local function for parse_bracket_exp used in _LIBC environment. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument since we may - update it. */ +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument since we may + update it. */ + +static __always_inline reg_errcode_t +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem, + re_dfa_t *dfa, reg_syntax_t syntax, uint32_t nrules, + const unsigned char *collseqmb, const char *collseqwc, + int_fast32_t table_size, const int32_t *symb_table, + const unsigned char *extra) +{ + unsigned int ch; + uint32_t start_collseq; + uint32_t end_collseq; - auto inline reg_errcode_t - __attribute__ ((always_inline)) - build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem) - { - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (__glibc_unlikely (start_elem->type == EQUIV_CLASS - || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS - || end_elem->type == CHAR_CLASS)) - return REG_ERANGE; + /* Equivalence Classes and Character Classes can't be a range + start/end. */ + if (__glibc_unlikely (start_elem->type == EQUIV_CLASS + || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS + || end_elem->type == CHAR_CLASS)) + return REG_ERANGE; - /* FIXME: Implement rational ranges here, too. */ - start_collseq = lookup_collation_sequence_value (start_elem); - end_collseq = lookup_collation_sequence_value (end_elem); - /* Check start/end collation sequence values. */ - if (__glibc_unlikely (start_collseq == UINT_MAX - || end_collseq == UINT_MAX)) - return REG_ECOLLATE; - if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) - && start_collseq > end_collseq)) - return REG_ERANGE; + /* FIXME: Implement rational ranges here, too. */ + start_collseq = lookup_collation_sequence_value (start_elem, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); + end_collseq = lookup_collation_sequence_value (end_elem, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); + /* Check start/end collation sequence values. */ + if (__glibc_unlikely (start_collseq == UINT_MAX + || end_collseq == UINT_MAX)) + return REG_ECOLLATE; + if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) + && start_collseq > end_collseq)) + return REG_ERANGE; - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) + /* Got valid collation sequence values, add them as a new entry. + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ + if (nrules > 0 || dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (__glibc_unlikely (*range_alloc == mbcset->nranges)) { - /* Check the space of the arrays. */ - if (__glibc_unlikely (*range_alloc == mbcset->nranges)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (__glibc_unlikely (new_array_start == NULL - || new_array_end == NULL)) - return REG_ESPACE; + /* There is not enough space, need realloc. */ + uint32_t *new_array_start; + uint32_t *new_array_end; + int new_nranges; - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + new_array_start = re_realloc (mbcset->range_starts, uint32_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, uint32_t, + new_nranges); - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } + if (__glibc_unlikely (new_array_start == NULL + || new_array_end == NULL)) + return REG_ESPACE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; } - return REG_NOERROR; + + mbcset->range_starts[mbcset->nranges] = start_collseq; + mbcset->range_ends[mbcset->nranges++] = end_collseq; } - /* Local function for parse_bracket_exp used in _LIBC environment. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ch++) + { + uint32_t ch_collseq; + /* if (MB_CUR_MAX == 1) */ + if (nrules == 0) + ch_collseq = collseqmb[ch]; + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) + bitset_set (sbcset, ch); + } + return REG_NOERROR; +} - auto inline reg_errcode_t - __attribute__ ((always_inline)) - build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, - Idx *coll_sym_alloc, const unsigned char *name) +/* Local function for parse_bracket_exp used in _LIBC environment. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static __always_inline reg_errcode_t +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + Idx *coll_sym_alloc, const unsigned char *name, + uint_fast32_t nrules, int_fast32_t table_size, + const int32_t *symb_table, const unsigned char *extra) +{ + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) { - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) + elem = seek_collating_symbol_entry (name, name_len, symb_table, + table_size, extra); + if (elem != -1) { - elem = seek_collating_symbol_entry (name, name_len); - if (elem != -1) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (__glibc_unlikely (new_coll_syms == NULL)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } + else if (name_len == 1) + { + /* No valid character, treat it as a normal + character. */ + bitset_set (sbcset, name[0]); return REG_NOERROR; } else + return REG_ECOLLATE; + + /* Got valid collation sequence, add it as a new entry. */ + /* Check the space of the arrays. */ + if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms)) { - if (__glibc_unlikely (name_len != 1)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } + /* Not enough, realloc it. */ + /* +1 in case of mbcset->ncoll_syms is 0. */ + int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + /* Use realloc since mbcset->coll_syms is NULL + if *alloc == 0. */ + int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, + new_coll_sym_alloc); + if (__glibc_unlikely (new_coll_syms == NULL)) + return REG_ESPACE; + mbcset->coll_syms = new_coll_syms; + *coll_sym_alloc = new_coll_sym_alloc; } + mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + return REG_NOERROR; } -#endif + else + { + if (__glibc_unlikely (name_len != 1)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + } +} +#endif /* _LIBC */ + +/* This function parse bracket expression like "[abc]", "[a-c]", + "[[.a-a.]]" etc. */ + +static bin_tree_t * +parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) +{ + const unsigned char *collseqmb = NULL; + const char *collseqwc = NULL; + uint_fast32_t nrules = 0; + int_fast32_t table_size = 0; + const void *symb_table = NULL; + const unsigned char *extra = NULL; re_token_t br_token; re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N re_charset_t *mbcset; Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; Idx equiv_class_alloc = 0, char_class_alloc = 0; -#endif /* not RE_ENABLE_I18N */ bool non_match = false; bin_tree_t *work_tree; int token_len; @@ -3111,26 +3040,17 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, */ collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); + symb_table = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); } #endif sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ -#ifdef RE_ENABLE_I18N if (__glibc_unlikely (sbcset == NULL || mbcset == NULL)) -#else - if (__glibc_unlikely (sbcset == NULL)) -#endif /* RE_ENABLE_I18N */ { re_free (sbcset); -#ifdef RE_ENABLE_I18N re_free (mbcset); -#endif *err = REG_ESPACE; return NULL; } @@ -3143,9 +3063,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, } if (token->type == OP_NON_MATCH_LIST) { -#ifdef RE_ENABLE_I18N mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ non_match = true; if (syntax & RE_HAT_LISTS_NOT_NEWLINE) bitset_set (sbcset, '\n'); @@ -3228,18 +3146,10 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, token_len = peek_token_bracket (token, regexp, syntax); -#ifdef _LIBC *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem); -#else -# ifdef RE_ENABLE_I18N - *err = build_range_exp (syntax, sbcset, - dfa->mb_cur_max > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); -# else - *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem); -# endif -#endif /* RE_ENABLE_I18N */ + &start_elem, &end_elem, + dfa, syntax, nrules, collseqmb, collseqwc, + table_size, symb_table, extra); if (__glibc_unlikely (*err != REG_NOERROR)) goto parse_bracket_exp_free_return; } @@ -3250,7 +3160,6 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, case SB_CHAR: bitset_set (sbcset, start_elem.opr.ch); break; -#ifdef RE_ENABLE_I18N case MB_CHAR: /* Check whether the array has enough space. */ if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars)) @@ -3268,30 +3177,24 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, } mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; break; -#endif /* RE_ENABLE_I18N */ case EQUIV_CLASS: *err = build_equiv_class (sbcset, -#ifdef RE_ENABLE_I18N mbcset, &equiv_class_alloc, -#endif /* RE_ENABLE_I18N */ start_elem.opr.name); if (__glibc_unlikely (*err != REG_NOERROR)) goto parse_bracket_exp_free_return; break; case COLL_SYM: *err = build_collating_symbol (sbcset, -#ifdef RE_ENABLE_I18N mbcset, &coll_sym_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); + start_elem.opr.name, + nrules, table_size, symb_table, extra); if (__glibc_unlikely (*err != REG_NOERROR)) goto parse_bracket_exp_free_return; break; case CHAR_CLASS: *err = build_charclass (regexp->trans, sbcset, -#ifdef RE_ENABLE_I18N mbcset, &char_class_alloc, -#endif /* RE_ENABLE_I18N */ (const char *) start_elem.opr.name, syntax); if (__glibc_unlikely (*err != REG_NOERROR)) @@ -3317,7 +3220,6 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, if (non_match) bitset_not (sbcset); -#ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); @@ -3361,11 +3263,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, } } else -#endif /* not RE_ENABLE_I18N */ { -#ifdef RE_ENABLE_I18N free_charset (mbcset); -#endif /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; @@ -3379,9 +3278,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, *err = REG_ESPACE; parse_bracket_exp_free_return: re_free (sbcset); -#ifdef RE_ENABLE_I18N free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ return NULL; } @@ -3392,7 +3289,6 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_token_t *token, int token_len, re_dfa_t *dfa, reg_syntax_t syntax, bool accept_hyphen) { -#ifdef RE_ENABLE_I18N int cur_char_size; cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); if (cur_char_size > 1) @@ -3402,7 +3298,6 @@ parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, re_string_skip_bytes (regexp, cur_char_size); return REG_NOERROR; } -#endif /* RE_ENABLE_I18N */ re_string_skip_bytes (regexp, token_len); /* Skip a token. */ if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS || token->type == OP_OPEN_EQUIV_CLASS) @@ -3475,12 +3370,8 @@ parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, is a pointer argument since we may update it. */ static reg_errcode_t -#ifdef RE_ENABLE_I18N build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, Idx *equiv_class_alloc, const unsigned char *name) -#else /* not RE_ENABLE_I18N */ -build_equiv_class (bitset_t sbcset, const unsigned char *name) -#endif /* not RE_ENABLE_I18N */ { #ifdef _LIBC uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); @@ -3560,14 +3451,9 @@ build_equiv_class (bitset_t sbcset, const unsigned char *name) is a pointer argument since we may update it. */ static reg_errcode_t -#ifdef RE_ENABLE_I18N build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, re_charset_t *mbcset, Idx *char_class_alloc, const char *class_name, reg_syntax_t syntax) -#else /* not RE_ENABLE_I18N */ -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const char *class_name, reg_syntax_t syntax) -#endif /* not RE_ENABLE_I18N */ { int i; const char *name = class_name; @@ -3578,7 +3464,6 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) name = "alpha"; -#ifdef RE_ENABLE_I18N /* Check the space of the arrays. */ if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes)) { @@ -3594,7 +3479,6 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, *char_class_alloc = new_char_class_alloc; } mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); -#endif /* RE_ENABLE_I18N */ #define BUILD_CHARCLASS_LOOP(ctype_func) \ do { \ @@ -3649,10 +3533,8 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, reg_errcode_t *err) { re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N re_charset_t *mbcset; Idx alloc = 0; -#endif /* not RE_ENABLE_I18N */ reg_errcode_t ret; bin_tree_t *tree; @@ -3662,7 +3544,6 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, *err = REG_ESPACE; return NULL; } -#ifdef RE_ENABLE_I18N mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); if (__glibc_unlikely (mbcset == NULL)) { @@ -3671,21 +3552,14 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, return NULL; } mbcset->non_match = non_match; -#endif /* RE_ENABLE_I18N */ /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &alloc, -#endif /* RE_ENABLE_I18N */ - class_name, 0); + ret = build_charclass (trans, sbcset, mbcset, &alloc, class_name, 0); if (__glibc_unlikely (ret != REG_NOERROR)) { re_free (sbcset); -#ifdef RE_ENABLE_I18N free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ *err = ret; return NULL; } @@ -3697,11 +3571,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, if (non_match) bitset_not (sbcset); -#ifdef RE_ENABLE_I18N /* Ensure only single byte characters are set. */ if (dfa->mb_cur_max > 1) bitset_mask (sbcset, dfa->sb_char); -#endif /* Build a tree for simple bracket. */ re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset }; @@ -3709,7 +3581,6 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, if (__glibc_unlikely (tree == NULL)) goto build_word_op_espace; -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { bin_tree_t *mbc_tree; @@ -3730,15 +3601,10 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, free_charset (mbcset); return tree; } -#else /* not RE_ENABLE_I18N */ - return tree; -#endif /* not RE_ENABLE_I18N */ build_word_op_espace: re_free (sbcset); -#ifdef RE_ENABLE_I18N free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ *err = REG_ESPACE; return NULL; } @@ -3771,21 +3637,19 @@ fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) return num; } -#ifdef RE_ENABLE_I18N static void free_charset (re_charset_t *cset) { re_free (cset->mbchars); -# ifdef _LIBC +#ifdef _LIBC re_free (cset->coll_syms); re_free (cset->equiv_classes); -# endif +#endif re_free (cset->range_starts); re_free (cset->range_ends); re_free (cset->char_classes); re_free (cset); } -#endif /* RE_ENABLE_I18N */ /* Functions for binary tree operation. */ @@ -3851,13 +3715,10 @@ mark_opt_subexp (void *extra, bin_tree_t *node) static void free_token (re_token_t *node) { -#ifdef RE_ENABLE_I18N if (node->type == COMPLEX_BRACKET && node->duplicated == 0) free_charset (node->opr.mbcset); - else -#endif /* RE_ENABLE_I18N */ - if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); + else if (node->type == SIMPLE_BRACKET && node->duplicated == 0) + re_free (node->opr.sbcset); } /* Worker function for tree walking. Free the allocated memory inside NODE diff --git a/lib/regex_internal.c b/lib/regex_internal.c index aefcfa2f52..9767cd0d07 100644 --- a/lib/regex_internal.c +++ b/lib/regex_internal.c @@ -30,10 +30,8 @@ static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, re_hashval_t hash); static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len); -#ifdef RE_ENABLE_I18N static void build_wcs_buffer (re_string_t *pstr); static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr); -#endif /* RE_ENABLE_I18N */ static void build_upper_buffer (re_string_t *pstr); static void re_string_translate_buffer (re_string_t *pstr); static unsigned int re_string_context_at (const re_string_t *input, Idx idx, @@ -91,7 +89,6 @@ re_string_construct (re_string_t *pstr, const char *str, Idx len, if (icase) { -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) { while (1) @@ -109,16 +106,13 @@ re_string_construct (re_string_t *pstr, const char *str, Idx len, } } else -#endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) build_wcs_buffer (pstr); else -#endif /* RE_ENABLE_I18N */ { if (trans != NULL) re_string_translate_buffer (pstr); @@ -139,7 +133,6 @@ static reg_errcode_t __attribute_warn_unused_result__ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) { -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { wint_t *new_wcs; @@ -162,7 +155,6 @@ re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) pstr->offsets = new_offsets; } } -#endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) { unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, @@ -194,7 +186,6 @@ re_string_construct_common (const char *str, Idx len, re_string_t *pstr, pstr->raw_stop = pstr->stop; } -#ifdef RE_ENABLE_I18N /* Build wide character buffer PSTR->WCS. If the byte sequence of the string are: @@ -530,7 +521,6 @@ re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) *last_wc = wc; return rawbuf_idx; } -#endif /* RE_ENABLE_I18N */ /* Build the buffer PSTR->MBS, and apply the translation if we need. This function is used in case of REG_ICASE. */ @@ -585,10 +575,8 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) else { /* Reset buffer. */ -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); -#endif /* RE_ENABLE_I18N */ pstr->len = pstr->raw_len; pstr->stop = pstr->raw_stop; pstr->valid_len = 0; @@ -608,7 +596,6 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) if (__glibc_likely (offset < pstr->valid_raw_len)) { /* Yes, move them to the front of the buffer. */ -#ifdef RE_ENABLE_I18N if (__glibc_unlikely (pstr->offsets_needed)) { Idx low = 0, high = pstr->valid_len, mid; @@ -672,15 +659,12 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) } } else -#endif { pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) memmove (pstr->wcs, pstr->wcs + offset, (pstr->valid_len - offset) * sizeof (wint_t)); -#endif /* RE_ENABLE_I18N */ if (__glibc_unlikely (pstr->mbs_allocated)) memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); @@ -691,7 +675,6 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) } else { -#ifdef RE_ENABLE_I18N /* No, skip all characters until IDX. */ Idx prev_valid_len = pstr->valid_len; @@ -701,9 +684,7 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) pstr->stop = pstr->raw_stop - idx + offset; pstr->offsets_needed = 0; } -#endif pstr->valid_len = 0; -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { Idx wcs_idx; @@ -787,7 +768,6 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) pstr->valid_raw_len = pstr->valid_len; } else -#endif /* RE_ENABLE_I18N */ { int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; pstr->valid_raw_len = 0; @@ -807,7 +787,6 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) pstr->stop -= offset; /* Then build the buffers. */ -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { if (pstr->icase) @@ -820,7 +799,6 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) build_wcs_buffer (pstr); } else -#endif /* RE_ENABLE_I18N */ if (__glibc_unlikely (pstr->mbs_allocated)) { if (pstr->icase) @@ -846,28 +824,22 @@ re_string_peek_byte_case (const re_string_t *pstr, Idx idx) if (__glibc_likely (!pstr->mbs_allocated)) return re_string_peek_byte (pstr, idx); -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1 && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) return re_string_peek_byte (pstr, idx); -#endif off = pstr->cur_idx + idx; -#ifdef RE_ENABLE_I18N if (pstr->offsets_needed) off = pstr->offsets[off]; -#endif ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; -#ifdef RE_ENABLE_I18N /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I this function returns CAPITAL LETTER I instead of first byte of DOTLESS SMALL LETTER I. The latter would confuse the parser, since peek_byte_case doesn't advance cur_idx in any way. */ if (pstr->offsets_needed && !isascii (ch)) return re_string_peek_byte (pstr, idx); -#endif return ch; } @@ -878,7 +850,6 @@ re_string_fetch_byte_case (re_string_t *pstr) if (__glibc_likely (!pstr->mbs_allocated)) return re_string_fetch_byte (pstr); -#ifdef RE_ENABLE_I18N if (pstr->offsets_needed) { Idx off; @@ -904,7 +875,6 @@ re_string_fetch_byte_case (re_string_t *pstr) re_string_char_size_at (pstr, pstr->cur_idx)); return ch; } -#endif return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; } @@ -912,10 +882,8 @@ re_string_fetch_byte_case (re_string_t *pstr) static void re_string_destruct (re_string_t *pstr) { -#ifdef RE_ENABLE_I18N re_free (pstr->wcs); re_free (pstr->offsets); -#endif /* RE_ENABLE_I18N */ if (pstr->mbs_allocated) re_free (pstr->mbs); } @@ -933,7 +901,6 @@ re_string_context_at (const re_string_t *input, Idx idx, int eflags) if (__glibc_unlikely (idx == input->len)) return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF : CONTEXT_NEWLINE | CONTEXT_ENDBUF); -#ifdef RE_ENABLE_I18N if (input->mb_cur_max > 1) { wint_t wc; @@ -953,7 +920,6 @@ re_string_context_at (const re_string_t *input, Idx idx, int eflags) ? CONTEXT_NEWLINE : 0); } else -#endif { c = re_string_byte_at (input, idx); if (bitset_contain (input->word_char, c)) @@ -1451,11 +1417,9 @@ re_dfa_add_node (re_dfa_t *dfa, re_token_t token) } dfa->nodes[dfa->nodes_len] = token; dfa->nodes[dfa->nodes_len].constraint = 0; -#ifdef RE_ENABLE_I18N dfa->nodes[dfa->nodes_len].accept_mb = ((token.type == OP_PERIOD && dfa->mb_cur_max > 1) || token.type == COMPLEX_BRACKET); -#endif dfa->nexts[dfa->nodes_len] = -1; re_node_set_init_empty (dfa->edests + dfa->nodes_len); re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); @@ -1651,9 +1615,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, re_token_type_t type = node->type; if (type == CHARACTER && !node->constraint) continue; -#ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) @@ -1705,9 +1667,7 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, if (type == CHARACTER && !constraint) continue; -#ifdef RE_ENABLE_I18N newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ /* If the state has the halt node, the state is a halt state. */ if (type == END_OF_RE) diff --git a/lib/regex_internal.h b/lib/regex_internal.h index 1245e782ff..8493db2701 100644 --- a/lib/regex_internal.h +++ b/lib/regex_internal.h @@ -116,10 +116,6 @@ # define gettext_noop(String) String #endif -#if (defined MB_CUR_MAX && HAVE_WCTYPE_H && HAVE_ISWCTYPE) || _LIBC -# define RE_ENABLE_I18N -#endif - /* Number of ASCII characters. */ #define ASCII_CHARS 0x80 @@ -150,6 +146,11 @@ # define __regfree regfree #endif /* not _LIBC */ +/* Types related to integers. Unless protected by #ifdef _LIBC, the + regex code should avoid exact-width types like int32_t and uint64_t + as some non-GCC platforms lack them, an issue when this code is + used in Gnulib. */ + #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif @@ -246,10 +247,8 @@ typedef enum SIMPLE_BRACKET = 3, OP_BACK_REF = 4, OP_PERIOD = 5, -#ifdef RE_ENABLE_I18N COMPLEX_BRACKET = 6, OP_UTF8_PERIOD = 7, -#endif /* RE_ENABLE_I18N */ /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used when the debugger shows values of this enum type. */ @@ -287,30 +286,29 @@ typedef enum } re_token_type_t; -#ifdef RE_ENABLE_I18N typedef struct { /* Multibyte characters. */ wchar_t *mbchars; +#ifdef _LIBC /* Collating symbols. */ -# ifdef _LIBC int32_t *coll_syms; -# endif +#endif +#ifdef _LIBC /* Equivalence classes. */ -# ifdef _LIBC int32_t *equiv_classes; -# endif +#endif /* Range expressions. */ -# ifdef _LIBC +#ifdef _LIBC uint32_t *range_starts; uint32_t *range_ends; -# else /* not _LIBC */ +#else wchar_t *range_starts; wchar_t *range_ends; -# endif /* not _LIBC */ +#endif /* Character classes. */ wctype_t *char_classes; @@ -333,7 +331,6 @@ typedef struct /* # of character classes. */ Idx nchar_classes; } re_charset_t; -#endif /* RE_ENABLE_I18N */ typedef struct { @@ -341,9 +338,7 @@ typedef struct { unsigned char c; /* for CHARACTER */ re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ -#ifdef RE_ENABLE_I18N re_charset_t *mbcset; /* for COMPLEX_BRACKET */ -#endif /* RE_ENABLE_I18N */ Idx idx; /* for BACK_REF */ re_context_type ctx_type; /* for ANCHOR */ } opr; @@ -355,12 +350,10 @@ typedef struct unsigned int constraint : 10; /* context constraint */ unsigned int duplicated : 1; unsigned int opt_subexp : 1; -#ifdef RE_ENABLE_I18N unsigned int accept_mb : 1; /* These 2 bits can be moved into the union if needed (e.g. if running out of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ unsigned int mb_partial : 1; -#endif unsigned int word_char : 1; } re_token_t; @@ -375,12 +368,10 @@ struct re_string_t REG_ICASE, upper cases of the string are stored, otherwise MBS points the same address that RAW_MBS points. */ unsigned char *mbs; -#ifdef RE_ENABLE_I18N /* Store the wide character string which is corresponding to MBS. */ wint_t *wcs; Idx *offsets; mbstate_t cur_state; -#endif /* Index in RAW_MBS. Each character mbs[i] corresponds to raw_mbs[raw_mbs_idx + i]. */ Idx raw_mbs_idx; @@ -779,7 +770,6 @@ bitset_mask (bitset_t dest, const bitset_t src) dest[bitset_i] &= src[bitset_i]; } -#ifdef RE_ENABLE_I18N /* Functions for re_string. */ static int __attribute__ ((pure, unused)) @@ -803,15 +793,15 @@ re_string_wchar_at (const re_string_t *pstr, Idx idx) return (wint_t) pstr->wcs[idx]; } -# ifdef _LIBC -# include -# endif +#ifdef _LIBC +# include +#endif static int __attribute__ ((pure, unused)) re_string_elem_size_at (const re_string_t *pstr, Idx idx) { -# ifdef _LIBC +#ifdef _LIBC const unsigned char *p, *extra; const int32_t *table, *indirect; uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); @@ -827,11 +817,10 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx) findidx (table, indirect, extra, &p, pstr->len - idx); return p - pstr->mbs - idx; } - else -# endif /* _LIBC */ - return 1; +#endif /* _LIBC */ + + return 1; } -#endif /* RE_ENABLE_I18N */ #ifdef _LIBC # if __GNUC__ >= 7 diff --git a/lib/regexec.c b/lib/regexec.c index 83e9aaf8ca..3196708373 100644 --- a/lib/regexec.c +++ b/lib/regexec.c @@ -67,11 +67,9 @@ static reg_errcode_t set_regs (const regex_t *preg, bool fl_backtrack); static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs); -#ifdef RE_ENABLE_I18N static int sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, Idx node_idx, Idx str_idx, Idx max_str_idx); -#endif /* RE_ENABLE_I18N */ static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx); static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, @@ -123,10 +121,8 @@ static re_dfastate_t *transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t *pstate); #endif -#ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate); -#endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes); static reg_errcode_t get_subexp (re_match_context_t *mctx, @@ -156,14 +152,12 @@ static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, Idx cur_str, Idx subexp_num, int type); static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state); -#ifdef RE_ENABLE_I18N static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, const re_string_t *input, Idx idx); -# ifdef _LIBC +#ifdef _LIBC static unsigned int find_collation_sequence_value (const unsigned char *mbs, size_t name_len); -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ +#endif static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, re_node_set *states_node, @@ -758,10 +752,9 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, offset = match_first - mctx.input.raw_mbs_idx; } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = (match_first >= length - ? 0 : re_string_byte_at (&mctx.input, offset)); + /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */ + ch = (offset < mctx.input.valid_len + ? re_string_byte_at (&mctx.input, offset) : 0); if (fastmap[ch]) break; match_first += incr; @@ -780,12 +773,10 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, if (__glibc_unlikely (err != REG_NOERROR)) goto free_return; -#ifdef RE_ENABLE_I18N - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ if (!sb && !re_string_first_byte (&mctx.input, 0)) continue; -#endif /* It seems to be appropriate one, then use the matcher. */ /* We assume that the matching starts from 0. */ @@ -859,7 +850,6 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) if (pmatch[reg_idx].rm_so != -1) { -#ifdef RE_ENABLE_I18N if (__glibc_unlikely (mctx.input.offsets_needed != 0)) { pmatch[reg_idx].rm_so = @@ -871,9 +861,6 @@ re_search_internal (const regex_t *preg, const char *string, Idx length, ? mctx.input.valid_raw_len : mctx.input.offsets[pmatch[reg_idx].rm_eo]); } -#else - DEBUG_ASSERT (mctx.input.offsets_needed == 0); -#endif pmatch[reg_idx].rm_so += match_first; pmatch[reg_idx].rm_eo += match_first; } @@ -997,8 +984,7 @@ prune_impossible_nodes (re_match_context_t *mctx) We must select appropriate initial state depending on the context, since initial states may have constraints like "\<", "^", etc.. */ -static inline re_dfastate_t * -__attribute__ ((always_inline)) +static __always_inline re_dfastate_t * acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, Idx idx) { @@ -1262,12 +1248,9 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, Idx naccepted = 0; re_token_type_t type = dfa->nodes[node].type; -#ifdef RE_ENABLE_I18N if (dfa->nodes[node].accept_mb) naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else -#endif /* RE_ENABLE_I18N */ - if (type == OP_BACK_REF) + else if (type == OP_BACK_REF) { Idx subexp_idx = dfa->nodes[node].opr.idx + 1; if (subexp_idx < nregs) @@ -1635,12 +1618,10 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, bool ok; DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type)); -#ifdef RE_ENABLE_I18N /* If the node may accept "multi byte". */ if (dfa->nodes[prev_node].accept_mb) naccepted = sift_states_iter_mb (mctx, sctx, prev_node, str_idx, sctx->last_str_idx); -#endif /* RE_ENABLE_I18N */ /* We don't check backreferences here. See update_cur_sifted_state(). */ @@ -1689,6 +1670,7 @@ clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) if (top < next_state_log_idx) { + DEBUG_ASSERT (mctx->state_log != NULL); memset (mctx->state_log + top + 1, '\0', sizeof (re_dfastate_t *) * (next_state_log_idx - top)); mctx->state_log_top = next_state_log_idx; @@ -2177,7 +2159,6 @@ sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, } -#ifdef RE_ENABLE_I18N static int sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, Idx node_idx, Idx str_idx, Idx max_str_idx) @@ -2197,8 +2178,6 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, 'naccepted' bytes input. */ return naccepted; } -#endif /* RE_ENABLE_I18N */ - /* Functions for state transition. */ @@ -2216,7 +2195,6 @@ transit_state (reg_errcode_t *err, re_match_context_t *mctx, re_dfastate_t **trtable; unsigned char ch; -#ifdef RE_ENABLE_I18N /* If the current state can accept multibyte. */ if (__glibc_unlikely (state->accept_mb)) { @@ -2224,7 +2202,6 @@ transit_state (reg_errcode_t *err, re_match_context_t *mctx, if (__glibc_unlikely (*err != REG_NOERROR)) return NULL; } -#endif /* RE_ENABLE_I18N */ /* Then decide the next state with the single byte. */ #if 0 @@ -2445,7 +2422,6 @@ transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, } #endif -#ifdef RE_ENABLE_I18N static reg_errcode_t transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) { @@ -2513,7 +2489,6 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) } return REG_NOERROR; } -#endif /* RE_ENABLE_I18N */ static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) @@ -3003,9 +2978,7 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, const re_dfa_t *const dfa = mctx->dfa; bool ok; Idx cur_idx; -#ifdef RE_ENABLE_I18N reg_errcode_t err = REG_NOERROR; -#endif re_node_set union_set; re_node_set_init_empty (&union_set); for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) @@ -3014,7 +2987,6 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, Idx cur_node = cur_nodes->elems[cur_idx]; DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type)); -#ifdef RE_ENABLE_I18N /* If the node may accept "multi byte". */ if (dfa->nodes[cur_node].accept_mb) { @@ -3052,7 +3024,7 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, } } } -#endif /* RE_ENABLE_I18N */ + if (naccepted || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) { @@ -3476,18 +3448,15 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, } else if (type == OP_PERIOD) { -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) bitset_merge (accepts, dfa->sb_char); else -#endif bitset_set_all (accepts); if (!(dfa->syntax & RE_DOT_NEWLINE)) bitset_clear (accepts, '\n'); if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } -#ifdef RE_ENABLE_I18N else if (type == OP_UTF8_PERIOD) { if (ASCII_CHARS % BITSET_WORD_BITS == 0) @@ -3499,7 +3468,6 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, if (dfa->syntax & RE_DOT_NOT_NULL) bitset_clear (accepts, '\0'); } -#endif else continue; @@ -3530,12 +3498,10 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, bitset_empty (accepts); continue; } -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); else -#endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= dfa->word_char[j]); if (!any_set) @@ -3549,12 +3515,10 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, bitset_empty (accepts); continue; } -#ifdef RE_ENABLE_I18N if (dfa->mb_cur_max > 1) for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); else -#endif for (j = 0; j < BITSET_WORDS; ++j) any_set |= (accepts[j] &= ~dfa->word_char[j]); if (!any_set) @@ -3631,7 +3595,6 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, return -1; } -#ifdef RE_ENABLE_I18N /* Check how many bytes the node 'dfa->nodes[node_idx]' accepts. Return the number of the bytes the node accepts. STR_IDX is the current index of the input string. @@ -3640,9 +3603,9 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, one collating element like '.', '[a-z]', opposite to the other nodes can only accept one byte. */ -# ifdef _LIBC -# include -# endif +#ifdef _LIBC +# include +#endif static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, @@ -3726,12 +3689,12 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, if (node->type == COMPLEX_BRACKET) { const re_charset_t *cset = node->opr.mbcset; -# ifdef _LIBC +#ifdef _LIBC const unsigned char *pin = ((const unsigned char *) re_string_get_buffer (input) + str_idx); Idx j; uint32_t nrules; -# endif /* _LIBC */ +#endif int match_len = 0; wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) ? re_string_wchar_at (input, str_idx) : 0); @@ -3754,7 +3717,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, } } -# ifdef _LIBC +#ifdef _LIBC nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); if (nrules != 0) { @@ -3843,7 +3806,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, } } else -# endif /* _LIBC */ +#endif /* _LIBC */ { /* match with range expression? */ for (i = 0; i < cset->nranges; ++i) @@ -3869,7 +3832,7 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, return 0; } -# ifdef _LIBC +#ifdef _LIBC static unsigned int find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) { @@ -3927,8 +3890,7 @@ find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) return UINT_MAX; } } -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ +#endif /* _LIBC */ /* Check whether the node accepts the byte which is IDX-th byte of the INPUT. */ @@ -3951,12 +3913,10 @@ check_node_accept (const re_match_context_t *mctx, const re_token_t *node, return false; break; -#ifdef RE_ENABLE_I18N case OP_UTF8_PERIOD: if (ch >= ASCII_CHARS) return false; FALLTHROUGH; -#endif case OP_PERIOD: if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) @@ -4017,7 +3977,6 @@ extend_buffers (re_match_context_t *mctx, int min_len) /* Then reconstruct the buffers. */ if (pstr->icase) { -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) { ret = build_wcs_upper_buffer (pstr); @@ -4025,16 +3984,13 @@ extend_buffers (re_match_context_t *mctx, int min_len) return ret; } else -#endif /* RE_ENABLE_I18N */ build_upper_buffer (pstr); } else { -#ifdef RE_ENABLE_I18N if (pstr->mb_cur_max > 1) build_wcs_buffer (pstr); else -#endif /* RE_ENABLE_I18N */ { if (pstr->trans != NULL) re_string_translate_buffer (pstr); diff --git a/lib/string.in.h b/lib/string.in.h index 8d77ae3800..afe7350867 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -67,6 +67,35 @@ # include #endif +/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers + that can be freed by passing them as the Ith argument to the + function F. */ +#ifndef _GL_ATTRIBUTE_DEALLOC +# if __GNUC__ >= 11 +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i))) +# else +# define _GL_ATTRIBUTE_DEALLOC(f, i) +# endif +#endif + +/* _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that + can be freed via 'free'; it can be used only after declaring 'free'. */ +/* Applies to: functions. Cannot be used on inline functions. */ +#ifndef _GL_ATTRIBUTE_DEALLOC_FREE +# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) +#endif + +/* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly + allocated memory. */ +/* Applies to: functions. */ +#ifndef _GL_ATTRIBUTE_MALLOC +# if __GNUC__ >= 3 || defined __clang__ +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define _GL_ATTRIBUTE_MALLOC +# endif +#endif + /* The __attribute__ feature is available in gcc versions 2.5 and later. The attribute __pure__ was added in gcc 2.96. */ #ifndef _GL_ATTRIBUTE_PURE diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h index 1abd6c544e..8b4b934a1e 100644 --- a/lib/sys_random.in.h +++ b/lib/sys_random.in.h @@ -23,8 +23,10 @@ #if @HAVE_SYS_RANDOM_H@ -/* On uClibc, assumes prior inclusion of . */ -# if defined __UCLIBC__ +/* On uClibc < 1.0.35, assumes prior inclusion of . + Do not use __UCLIBC__ here, as it might not be defined yet. + But avoid namespace pollution on glibc systems. */ +# ifndef __GLIBC__ # include # endif /* On Mac OS X 10.5, assumes prior inclusion of . diff --git a/m4/alloca.m4 b/m4/alloca.m4 index ba2f679d8e..7e474aa681 100644 --- a/m4/alloca.m4 +++ b/m4/alloca.m4 @@ -1,4 +1,4 @@ -# alloca.m4 serial 20 +# alloca.m4 serial 21 dnl Copyright (C) 2002-2004, 2006-2007, 2009-2021 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -26,17 +26,15 @@ AC_DEFUN([gl_FUNC_ALLOCA], AC_DEFINE([HAVE_ALLOCA], [1], [Define to 1 if you have 'alloca' after including , a header that may be supplied by this distribution.]) - ALLOCA_H=alloca.h + GL_GENERATE_ALLOCA_H=true else dnl alloca exists as a library function, i.e. it is slow and probably dnl a memory leak. Don't define HAVE_ALLOCA in this case. - ALLOCA_H= + GL_GENERATE_ALLOCA_H=false fi else - ALLOCA_H=alloca.h + GL_GENERATE_ALLOCA_H=true fi - AC_SUBST([ALLOCA_H]) - AM_CONDITIONAL([GL_GENERATE_ALLOCA_H], [test -n "$ALLOCA_H"]) if test $ac_cv_working_alloca_h = yes; then HAVE_ALLOCA_H=1 diff --git a/m4/byteswap.m4 b/m4/byteswap.m4 index 1083b4c9e2..db35b527a6 100644 --- a/m4/byteswap.m4 +++ b/m4/byteswap.m4 @@ -1,4 +1,4 @@ -# byteswap.m4 serial 4 +# byteswap.m4 serial 5 dnl Copyright (C) 2005, 2007, 2009-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,10 +10,8 @@ AC_DEFUN([gl_BYTESWAP], [ dnl Prerequisites of lib/byteswap.in.h. AC_CHECK_HEADERS([byteswap.h], [ - BYTESWAP_H='' + GL_GENERATE_BYTESWAP_H=false ], [ - BYTESWAP_H='byteswap.h' + GL_GENERATE_BYTESWAP_H=true ]) - AC_SUBST([BYTESWAP_H]) - AM_CONDITIONAL([GL_GENERATE_BYTESWAP_H], [test -n "$BYTESWAP_H"]) ]) diff --git a/m4/errno_h.m4 b/m4/errno_h.m4 index 51dfe92938..7f5feabb2b 100644 --- a/m4/errno_h.m4 +++ b/m4/errno_h.m4 @@ -1,4 +1,4 @@ -# errno_h.m4 serial 13 +# errno_h.m4 serial 14 dnl Copyright (C) 2004, 2006, 2008-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -68,13 +68,11 @@ booboo [gl_cv_header_errno_h_complete=yes]) ]) if test $gl_cv_header_errno_h_complete = yes; then - ERRNO_H='' + GL_GENERATE_ERRNO_H=false else gl_NEXT_HEADERS([errno.h]) - ERRNO_H='errno.h' + GL_GENERATE_ERRNO_H=true fi - AC_SUBST([ERRNO_H]) - AM_CONDITIONAL([GL_GENERATE_ERRNO_H], [test -n "$ERRNO_H"]) gl_REPLACE_ERRNO_VALUE([EMULTIHOP]) gl_REPLACE_ERRNO_VALUE([ENOLINK]) gl_REPLACE_ERRNO_VALUE([EOVERFLOW]) @@ -88,7 +86,7 @@ booboo # Set the variables EOVERFLOW_HIDDEN and EOVERFLOW_VALUE. AC_DEFUN([gl_REPLACE_ERRNO_VALUE], [ - if test -n "$ERRNO_H"; then + if $GL_GENERATE_ERRNO_H; then AC_CACHE_CHECK([for ]$1[ value], [gl_cv_header_errno_h_]$1, [ AC_EGREP_CPP([yes],[ #include diff --git a/m4/execinfo.m4 b/m4/execinfo.m4 index 75ab44beee..581b173a23 100644 --- a/m4/execinfo.m4 +++ b/m4/execinfo.m4 @@ -10,7 +10,7 @@ AC_DEFUN([gl_EXECINFO_H], AC_CHECK_HEADERS_ONCE([execinfo.h]) LIB_EXECINFO='' - EXECINFO_H='execinfo.h' + GL_GENERATE_EXECINFO_H=true if test $ac_cv_header_execinfo_h = yes; then gl_saved_libs=$LIBS @@ -18,14 +18,10 @@ AC_DEFUN([gl_EXECINFO_H], [test "$ac_cv_search_backtrace_symbols_fd" = "none required" || LIB_EXECINFO=$ac_cv_search_backtrace_symbols_fd]) LIBS=$gl_saved_libs - test "$ac_cv_search_backtrace_symbols_fd" = no || EXECINFO_H='' + if test "$ac_cv_search_backtrace_symbols_fd" != no; then + GL_GENERATE_EXECINFO_H=false + fi fi - if test -n "$EXECINFO_H"; then - AC_LIBOBJ([execinfo]) - fi - - AC_SUBST([EXECINFO_H]) AC_SUBST([LIB_EXECINFO]) - AM_CONDITIONAL([GL_GENERATE_EXECINFO_H], [test -n "$EXECINFO_H"]) ]) diff --git a/m4/getopt.m4 b/m4/getopt.m4 index bb95c5ea28..9b71159bc5 100644 --- a/m4/getopt.m4 +++ b/m4/getopt.m4 @@ -1,4 +1,4 @@ -# getopt.m4 serial 47 +# getopt.m4 serial 48 dnl Copyright (C) 2002-2006, 2008-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -21,6 +21,8 @@ AC_DEFUN([gl_FUNC_GETOPT_POSIX], REPLACE_GETOPT=1 fi ]) + GL_GENERATE_GETOPT_H=false + GL_GENERATE_GETOPT_CDEFS_H=false if test $REPLACE_GETOPT = 1; then dnl Arrange for getopt.h to be created. gl_GETOPT_SUBSTITUTE_HEADER @@ -374,8 +376,6 @@ AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER], AC_DEFINE([__GETOPT_PREFIX], [[rpl_]], [Define to rpl_ if the getopt replacement functions and variables should be used.]) - GETOPT_H=getopt.h - GETOPT_CDEFS_H=getopt-cdefs.h - AC_SUBST([GETOPT_H]) - AC_SUBST([GETOPT_CDEFS_H]) + GL_GENERATE_GETOPT_H=true + GL_GENERATE_GETOPT_CDEFS_H=true ]) diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index 12b19dbcb4..f70ef4ea96 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,4 +1,4 @@ -# gnulib-common.m4 serial 67 +# gnulib-common.m4 serial 69 dnl Copyright (C) 2007-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -879,6 +879,36 @@ AC_DEFUN([gl_CXX_ALLOW_WARNINGS], AC_SUBST([GL_CXXFLAG_ALLOW_WARNINGS]) ]) +dnl gl_CONDITIONAL_HEADER([foo.h]) +dnl takes a shell variable GL_GENERATE_FOO_H (with value true or false) as input +dnl and produces +dnl - an AC_SUBSTed variable FOO_H that is either a file name or empty, based +dnl on whether GL_GENERATE_FOO_H is true or false, +dnl - an Automake conditional GL_GENERATE_FOO_H that evaluates to the value of +dnl the shell variable GL_GENERATE_FOO_H. +AC_DEFUN([gl_CONDITIONAL_HEADER], +[ + m4_pushdef([gl_header_name], AS_TR_SH(m4_toupper($1))) + m4_pushdef([gl_generate_var], [GL_GENERATE_]AS_TR_SH(m4_toupper($1))) + m4_pushdef([gl_generate_cond], [GL_GENERATE_]AS_TR_SH(m4_toupper($1))) + case "$gl_generate_var" in + false) gl_header_name='' ;; + true) + dnl It is OK to use a .h file in lib/ from within tests/, but not vice + dnl versa. + if test -z "$gl_header_name"; then + gl_header_name="${gl_source_base_prefix}$1" + fi + ;; + *) echo "*** gl_generate_var is not set correctly" 1>&2; exit 1 ;; + esac + AC_SUBST(gl_header_name) + AM_CONDITIONAL(gl_generate_cond, [$gl_generate_var]) + m4_popdef([gl_generate_cond]) + m4_popdef([gl_generate_var]) + m4_popdef([gl_header_name]) +]) + dnl Expands to some code for use in .c programs that, on native Windows, defines dnl the Microsoft deprecated alias function names to the underscore-prefixed dnl actual function names. With this macro, these function names are available diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index e314edcfb5..a6810523ec 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -224,10 +224,15 @@ AC_DEFUN([gl_INIT], m4_pushdef([GL_MODULE_INDICATOR_PREFIX], [GL]) gl_COMMON gl_source_base='lib' + gl_source_base_prefix= gl_FUNC_ACL gl_FUNC_ALLOCA + gl_CONDITIONAL_HEADER([alloca.h]) + AC_PROG_MKDIR_P gl___BUILTIN_EXPECT gl_BYTESWAP + gl_CONDITIONAL_HEADER([byteswap.h]) + AC_PROG_MKDIR_P gl_CANONICALIZE_LGPL if test $HAVE_CANONICALIZE_FILE_NAME = 0 || test $REPLACE_CANONICALIZE_FILE_NAME = 1; then AC_LIBOBJ([canonicalize-lgpl]) @@ -255,6 +260,7 @@ AC_DEFUN([gl_INIT], gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE gl_DIRENT_H gl_DIRENT_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_DOUBLE_SLASH_ROOT gl_FUNC_DUP2 if test $REPLACE_DUP2 = 1; then @@ -265,7 +271,14 @@ AC_DEFUN([gl_INIT], gl_ENVIRON gl_UNISTD_MODULE_INDICATOR([environ]) gl_HEADER_ERRNO_H + gl_CONDITIONAL_HEADER([errno.h]) + AC_PROG_MKDIR_P gl_EXECINFO_H + gl_CONDITIONAL_HEADER([execinfo.h]) + AC_PROG_MKDIR_P + if $GL_GENERATE_EXECINFO_H; then + AC_LIBOBJ([execinfo]) + fi gl_FUNC_EXPLICIT_BZERO if test $HAVE_EXPLICIT_BZERO = 0; then AC_LIBOBJ([explicit_bzero]) @@ -293,6 +306,7 @@ AC_DEFUN([gl_INIT], gl_FCNTL_MODULE_INDICATOR([fcntl]) gl_FCNTL_H gl_FCNTL_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_FUNC_FDOPENDIR if test $HAVE_FDOPENDIR = 0 || test $REPLACE_FDOPENDIR = 1; then AC_LIBOBJ([fdopendir]) @@ -345,6 +359,9 @@ AC_DEFUN([gl_INIT], dnl mechanism), there is no need to do any AC_LIBOBJ or AC_SUBST here; they are dnl done in the getopt-posix module. gl_FUNC_GETOPT_POSIX + gl_CONDITIONAL_HEADER([getopt.h]) + gl_CONDITIONAL_HEADER([getopt-cdefs.h]) + AC_PROG_MKDIR_P if test $REPLACE_GETOPT = 1; then AC_LIBOBJ([getopt]) AC_LIBOBJ([getopt1]) @@ -367,15 +384,22 @@ AC_DEFUN([gl_INIT], fi gl_SYS_TIME_MODULE_INDICATOR([gettimeofday]) gl_IEEE754_H + gl_CONDITIONAL_HEADER([ieee754.h]) + AC_PROG_MKDIR_P gl_INTTYPES_INCOMPLETE gl_INTTYPES_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P AC_REQUIRE([gl_LARGEFILE]) gl___INLINE gl_LIBGMP + gl_CONDITIONAL_HEADER([gmp.h]) + AC_PROG_MKDIR_P if test $HAVE_LIBGMP != yes; then AC_LIBOBJ([mini-gmp-gnulib]) fi gl_LIMITS_H + gl_CONDITIONAL_HEADER([limits.h]) + AC_PROG_MKDIR_P gl_FUNC_LSTAT if test $REPLACE_LSTAT = 1; then AC_LIBOBJ([lstat]) @@ -458,16 +482,26 @@ AC_DEFUN([gl_INIT], gl_STRING_MODULE_INDICATOR([sigdescr_np]) gl_SIGNAL_H gl_SIGNAL_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_TYPE_SOCKLEN_T gt_TYPE_SSIZE_T gl_STAT_TIME gl_STAT_BIRTHTIME gl_STDALIGN_H + gl_CONDITIONAL_HEADER([stdalign.h]) + AC_PROG_MKDIR_P gl_STDDEF_H gl_STDDEF_H_REQUIRE_DEFAULTS + gl_CONDITIONAL_HEADER([stddef.h]) + AC_PROG_MKDIR_P gl_STDINT_H + gl_CONDITIONAL_HEADER([stdint.h]) + dnl Because of gl_REPLACE_LIMITS_H: + gl_CONDITIONAL_HEADER([limits.h]) + AC_PROG_MKDIR_P gl_STDIO_H gl_STDIO_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P dnl No need to create extra modules for these functions. Everyone who uses dnl likely needs them. gl_STDIO_MODULE_INDICATOR([fscanf]) @@ -493,6 +527,7 @@ AC_DEFUN([gl_INIT], gl_STDIO_MODULE_INDICATOR([fwrite]) gl_STDLIB_H gl_STDLIB_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_FUNC_STPCPY if test $HAVE_STPCPY = 0; then AC_LIBOBJ([stpcpy]) @@ -501,6 +536,7 @@ AC_DEFUN([gl_INIT], gl_STRING_MODULE_INDICATOR([stpcpy]) gl_STRING_H gl_STRING_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_FUNC_STRNLEN if test $HAVE_DECL_STRNLEN = 0 || test $REPLACE_STRNLEN = 1; then AC_LIBOBJ([strnlen]) @@ -537,6 +573,7 @@ AC_DEFUN([gl_INIT], gl_MODULE_INDICATOR([tempname]) gl_TIME_H gl_TIME_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P gl_TIME_R if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then AC_LIBOBJ([time_r]) @@ -558,6 +595,7 @@ AC_DEFUN([gl_INIT], gl_TIMESPEC gl_UNISTD_H gl_UNISTD_H_REQUIRE_DEFAULTS + AC_PROG_MKDIR_P AC_DEFINE([GNULIB_STDIO_SINGLE_THREAD], [1], [Define to 1 if you want the FILE stream functions getc, putc, etc. to use unlocked I/O if available, throughout the package. @@ -993,6 +1031,7 @@ AC_DEFUN([gl_INIT], m4_pushdef([GL_MODULE_INDICATOR_PREFIX], [GL]) gl_COMMON gl_source_base='tests' + gl_source_base_prefix= changequote(,)dnl gltests_WITNESS=IN_`echo "${PACKAGE-$PACKAGE_TARNAME}" | LC_ALL=C tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | LC_ALL=C sed -e 's/[^A-Z0-9_]/_/g'`_GNULIB_TESTS changequote([, ])dnl diff --git a/m4/ieee754-h.m4 b/m4/ieee754-h.m4 index 68af3bd7eb..0712613b6f 100644 --- a/m4/ieee754-h.m4 +++ b/m4/ieee754-h.m4 @@ -10,12 +10,10 @@ AC_DEFUN([gl_IEEE754_H], AC_REQUIRE([AC_C_BIGENDIAN]) AC_CHECK_HEADERS_ONCE([ieee754.h]) if test $ac_cv_header_ieee754_h = yes; then - IEEE754_H= + GL_GENERATE_IEEE754_H=false else - IEEE754_H=ieee754.h + GL_GENERATE_IEEE754_H=true AC_DEFINE([_GL_REPLACE_IEEE754_H], 1, [Define to 1 if is missing.]) fi - AC_SUBST([IEEE754_H]) - AM_CONDITIONAL([GL_GENERATE_IEEE754_H], [test -n "$IEEE754_H"]) ]) diff --git a/m4/include_next.m4 b/m4/include_next.m4 index bdd542bc64..7dcd1cef0b 100644 --- a/m4/include_next.m4 +++ b/m4/include_next.m4 @@ -193,9 +193,9 @@ AC_DEFUN([gl_NEXT_HEADERS_INTERNAL], if test AS_VAR_GET([gl_header_exists]) = yes; then AS_VAR_POPDEF([gl_header_exists]) ]) - gl_ABSOLUTE_HEADER_ONE(gl_HEADER_NAME) - AS_VAR_COPY([gl_header], [gl_cv_absolute_]AS_TR_SH(gl_HEADER_NAME)) - AS_VAR_SET([gl_next_header], ['"'$gl_header'"']) + gl_ABSOLUTE_HEADER_ONE(gl_HEADER_NAME) + AS_VAR_COPY([gl_header], [gl_cv_absolute_]AS_TR_SH(gl_HEADER_NAME)) + AS_VAR_SET([gl_next_header], ['"'$gl_header'"']) m4_if([$2], [check], [else AS_VAR_SET([gl_next_header], ['<'gl_HEADER_NAME'>']) diff --git a/m4/inttypes.m4 b/m4/inttypes.m4 index 64b1de5c42..c446aa8277 100644 --- a/m4/inttypes.m4 +++ b/m4/inttypes.m4 @@ -1,4 +1,4 @@ -# inttypes.m4 serial 35 +# inttypes.m4 serial 36 dnl Copyright (C) 2006-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -36,7 +36,7 @@ AC_DEFUN_ONCE([gl_INTTYPES_INCOMPLETE], AC_DEFUN([gl_INTTYPES_PRI_SCN], [ PRIPTR_PREFIX= - if test -n "$STDINT_H"; then + if $GL_GENERATE_STDINT_H; then dnl Using the gnulib . It defines intptr_t to 'long' or dnl 'long long', depending on _WIN64. AC_COMPILE_IFELSE( diff --git a/m4/libgmp.m4 b/m4/libgmp.m4 index c630a19e64..a2103dde88 100644 --- a/m4/libgmp.m4 +++ b/m4/libgmp.m4 @@ -1,4 +1,4 @@ -# libgmp.m4 serial 5 +# libgmp.m4 serial 6 # Configure the GMP library or a replacement. dnl Copyright 2020-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation @@ -59,11 +59,10 @@ AC_DEFUN([gl_LIBGMP], [ Try specifying --with-libgmp-prefix=DIR.])]) fi]) if test $HAVE_LIBGMP = yes && test "$ac_cv_header_gmp_h" = yes; then - GMP_H= + GL_GENERATE_GMP_H=false else - GMP_H=gmp.h + GL_GENERATE_GMP_H=true fi - AC_SUBST([GMP_H]) AM_CONDITIONAL([GL_GENERATE_MINI_GMP_H], [test $HAVE_LIBGMP != yes]) AM_CONDITIONAL([GL_GENERATE_GMP_GMP_H], diff --git a/m4/limits-h.m4 b/m4/limits-h.m4 index 00c9fe9e50..c82f6c6781 100644 --- a/m4/limits-h.m4 +++ b/m4/limits-h.m4 @@ -27,18 +27,15 @@ AC_DEFUN_ONCE([gl_LIMITS_H], [gl_cv_header_limits_width=yes], [gl_cv_header_limits_width=no])]) if test "$gl_cv_header_limits_width" = yes; then - LIMITS_H= + GL_GENERATE_LIMITS_H=false else - LIMITS_H=limits.h + GL_GENERATE_LIMITS_H=true fi - AC_SUBST([LIMITS_H]) - AM_CONDITIONAL([GL_GENERATE_LIMITS_H], [test -n "$LIMITS_H"]) ]) dnl Unconditionally enables the replacement of . AC_DEFUN([gl_REPLACE_LIMITS_H], [ AC_REQUIRE([gl_LIMITS_H]) - LIMITS_H='limits.h' - AM_CONDITIONAL([GL_GENERATE_LIMITS_H], [test -n "$LIMITS_H"]) + GL_GENERATE_LIMITS_H=true ]) diff --git a/m4/stdalign.m4 b/m4/stdalign.m4 index e22d7f78c0..fd57cdd47f 100644 --- a/m4/stdalign.m4 +++ b/m4/stdalign.m4 @@ -49,11 +49,8 @@ AC_DEFUN([gl_STDALIGN_H], [gl_cv_header_working_stdalign_h=no])]) if test $gl_cv_header_working_stdalign_h = yes; then - STDALIGN_H='' + GL_GENERATE_STDALIGN_H=false else - STDALIGN_H='stdalign.h' + GL_GENERATE_STDALIGN_H=true fi - - AC_SUBST([STDALIGN_H]) - AM_CONDITIONAL([GL_GENERATE_STDALIGN_H], [test -n "$STDALIGN_H"]) ]) diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4 index 1303d2e06c..0b160cde08 100644 --- a/m4/stddef_h.m4 +++ b/m4/stddef_h.m4 @@ -1,4 +1,4 @@ -# stddef_h.m4 serial 11 +# stddef_h.m4 serial 12 dnl Copyright (C) 2009-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -14,7 +14,7 @@ AC_DEFUN_ONCE([gl_STDDEF_H], dnl Persuade OpenBSD to declare max_align_t. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) - STDDEF_H= + GL_GENERATE_STDDEF_H=false dnl Test whether the type max_align_t exists and whether its alignment dnl "is as great as is supported by the implementation in all contexts". @@ -41,12 +41,12 @@ AC_DEFUN_ONCE([gl_STDDEF_H], ]) if test $gl_cv_type_max_align_t = no; then HAVE_MAX_ALIGN_T=0 - STDDEF_H=stddef.h + GL_GENERATE_STDDEF_H=true fi if test $gt_cv_c_wchar_t = no; then HAVE_WCHAR_T=0 - STDDEF_H=stddef.h + GL_GENERATE_STDDEF_H=true fi AC_CACHE_CHECK([whether NULL can be used in arbitrary expressions], @@ -58,12 +58,10 @@ AC_DEFUN_ONCE([gl_STDDEF_H], [gl_cv_decl_null_works=no])]) if test $gl_cv_decl_null_works = no; then REPLACE_NULL=1 - STDDEF_H=stddef.h + GL_GENERATE_STDDEF_H=true fi - AC_SUBST([STDDEF_H]) - AM_CONDITIONAL([GL_GENERATE_STDDEF_H], [test -n "$STDDEF_H"]) - if test -n "$STDDEF_H"; then + if $GL_GENERATE_STDDEF_H; then gl_NEXT_HEADERS([stddef.h]) fi ]) diff --git a/m4/stdint.m4 b/m4/stdint.m4 index 2eb1652d8e..61fb8ca696 100644 --- a/m4/stdint.m4 +++ b/m4/stdint.m4 @@ -1,4 +1,4 @@ -# stdint.m4 serial 60 +# stdint.m4 serial 61 dnl Copyright (C) 2001-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -296,7 +296,7 @@ static const char *macro_values[] = HAVE_C99_STDINT_H=0 HAVE_SYS_BITYPES_H=0 HAVE_SYS_INTTYPES_H=0 - STDINT_H=stdint.h + GL_GENERATE_STDINT_H=true case "$gl_cv_header_working_stdint_h" in *yes) HAVE_C99_STDINT_H=1 @@ -341,7 +341,7 @@ int32_t i32 = INT32_C (0x7fffffff); ]])], [gl_cv_header_stdint_width=yes])]) if test "$gl_cv_header_stdint_width" = yes; then - STDINT_H= + GL_GENERATE_STDINT_H=false fi ;; *) @@ -364,8 +364,6 @@ int32_t i32 = INT32_C (0x7fffffff); AC_SUBST([HAVE_C99_STDINT_H]) AC_SUBST([HAVE_SYS_BITYPES_H]) AC_SUBST([HAVE_SYS_INTTYPES_H]) - AC_SUBST([STDINT_H]) - AM_CONDITIONAL([GL_GENERATE_STDINT_H], [test -n "$STDINT_H"]) ]) dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES) diff --git a/m4/sys_socket_h.m4 b/m4/sys_socket_h.m4 index 5676a0d217..1f9a06f09c 100644 --- a/m4/sys_socket_h.m4 +++ b/m4/sys_socket_h.m4 @@ -1,4 +1,4 @@ -# sys_socket_h.m4 serial 28 +# sys_socket_h.m4 serial 29 dnl Copyright (C) 2005-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -22,6 +22,7 @@ AC_DEFUN_ONCE([gl_SYS_SOCKET_H], ;; esac + GL_GENERATE_SYS_SOCKET_H=false AC_CACHE_CHECK([whether is self-contained], [gl_cv_header_sys_socket_h_selfcontained], [ @@ -44,7 +45,7 @@ AC_DEFUN_ONCE([gl_SYS_SOCKET_H], [gl_cv_header_sys_socket_h_shut=no]) ]) if test $gl_cv_header_sys_socket_h_shut = no; then - SYS_SOCKET_H='sys/socket.h' + GL_GENERATE_SYS_SOCKET_H=true fi fi fi @@ -83,7 +84,7 @@ AC_DEFUN_ONCE([gl_SYS_SOCKET_H], fi if test $HAVE_STRUCT_SOCKADDR_STORAGE = 0 || test $HAVE_SA_FAMILY_T = 0 \ || test $HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = 0; then - SYS_SOCKET_H='sys/socket.h' + GL_GENERATE_SYS_SOCKET_H=true fi gl_PREREQ_SYS_H_WINSOCK2 commit 35da3ed05212e0222841becf614c109011f9ad80 Author: Andrew G Cohen Date: Sun Dec 19 06:11:50 2021 +0800 Fix gnus search by message-id * lisp/gnus/gnus-search.el (gnus-search-run-search): Continue iterating until a match is found. * lisp/gnus/nnselect.el (nnselect-request-article): Use new gnus-search query format. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 46dc1cf6c1..d64c0cb90c 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -1060,7 +1060,7 @@ Responsible for handling and, or, and parenthetical expressions.") q-string))) (while (and (setq group (pop grouplist)) - (or (null single-search) (null artlist))) + (or (null single-search) (= 0 (length artlist)))) (when (nnimap-change-group (gnus-group-short-name group) server) (with-current-buffer (nnimap-buffer) diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el index 252e9f6683..0130f68999 100644 --- a/lisp/gnus/nnselect.el +++ b/lisp/gnus/nnselect.el @@ -395,8 +395,7 @@ If this variable is nil, or if the provided function returns nil, (gnus-search-run-query (list (cons 'search-query-spec - (list (cons 'query `((id . ,article))) - (cons 'criteria "") (cons 'shortcut t))) + (list (cons 'query (format "id:%s" article)))) (cons 'search-group-spec servers)))) (unless (zerop (nnselect-artlist-length artlist)) (setq @@ -905,7 +904,7 @@ article came from is also searched." ;; make sure (setq list (sort (map-merge - 'list list + 'alist list (alist-get type (gnus-info-marks group-info))) (lambda (elt1 elt2) (< (car elt1) (car elt2)))))) commit f315d3121654ba5a752efbae3835af3e8b964f9f Merge: 7a886aab90 941d15558f Author: Eli Zaretskii Date: Sat Dec 18 21:56:20 2021 +0200 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 7a886aab9082ca31d948bf957998ce972b9c3c42 Author: Eli Zaretskii Date: Sat Dec 18 21:54:39 2021 +0200 Improve doc strings in emoji.el * lisp/international/emoji.el (emoji-insert, emoji-recent) (emoji-search, emoji-list, emoji-describe, emoji-list-help): Improve and clarify the doc strings. diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index a4dec973fb..1202571b32 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -66,8 +66,9 @@ ;;;###autoload (defun emoji-insert (&optional text) "Choose and insert an emoji glyph. -If TEXT (interactively, the prefix), use a textual search instead -of a visual interface." +If TEXT (interactively, the prefix argument), choose the emoji +by typing its Unicode Standard name (with completion), instead +of selecting from emoji display." (interactive "*P") (emoji--init) (if text @@ -78,7 +79,7 @@ of a visual interface." ;;;###autoload (defun emoji-recent () - "Choose and insert a recently used emoji glyph." + "Choose and insert one of the recently-used emoji glyphs." (interactive "*") (emoji--init) (unless (fboundp 'emoji--command-Emoji) @@ -88,7 +89,9 @@ of a visual interface." ;;;###autoload (defun emoji-search () - "Choose and insert an emoji glyph by searching for an emoji name." + "Choose and insert an emoji glyph by typing its Unicode name. +This command prompts for an emoji name, with completion, and inserts it. +It recognizes the Unicode Standard names of emoji." (interactive "*") (emoji--init) (emoji--choose-emoji)) @@ -96,8 +99,9 @@ of a visual interface." ;;;###autoload (defun emoji-list () "List emojis and insert the one that's selected. -The character will be inserted into the buffer that was selected -when the command was issued." +Select the emoji by typing \\\\[emoji-list-select] on its picture. +The glyph will be inserted into the buffer that was current +when the command was invoked." (interactive "*") (let ((buf (current-buffer))) (emoji--init) @@ -113,11 +117,13 @@ when the command was issued." ;;;###autoload (defun emoji-describe (glyph &optional interactive) - "Say what the name of the composed grapheme cluster GLYPH is. -If it's not known, this function returns nil. + "Display the name of the grapheme cluster composed from GLYPH. +GLYPH should be a string of one or more characters which together +produce an emoji. Interactively, GLYPH is the emoji at point (it +could also be any character, not just emoji). -Interactively, it will message what the name of the emoji (or -character) under point is." +If called from Lisp, return the name as a string; return nil if +the name is not known." (interactive (list (if (eobp) (error "No glyph under point") @@ -224,14 +230,14 @@ character) under point is." nil end-func))))))) (defun emoji-list-help () - "Say what the emoji under point is." + "Display the name of the emoji at point." (interactive nil emoji-list-mode) (let ((glyph (get-text-property (point) 'emoji-glyph))) (unless glyph - (error "No emoji under point")) + (error "No emoji here")) (let ((name (emoji--name glyph))) (if (not name) - (error "Unknown name") + (error "Emoji name is unknown") (message "%s" name))))) (defun emoji--init (&optional force inhibit-adjust) commit 941d15558f013612689afe9fd2501ce6119a5120 Author: Mattias Engdegård Date: Sat Dec 18 19:45:38 2021 +0100 Remove incorrect byte-hunk-handler for `eval` This optimisation is of very limited utility and miscompiles top-level code having the form (eval 'CODE t) by replacing it with CODE which will then, as things currently stand, be evaluated with dynamic binding. * lisp/emacs-lisp/bytecomp.el (byte-compile-file-form-eval): Remove. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 644d9f1a47..a98c9197a0 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2677,15 +2677,6 @@ list that represents a doc string reference. (prog1 (byte-compile-keep-pending form) (apply 'make-obsolete (mapcar 'eval (cdr form))))) -;; This handler is not necessary, but it makes the output from dont-compile -;; and similar macros cleaner. -(put 'eval 'byte-hunk-handler 'byte-compile-file-form-eval) -(defun byte-compile-file-form-eval (form) - (if (and (eq (car-safe (nth 1 form)) 'quote) - (equal (nth 2 form) lexical-binding)) - (nth 1 (nth 1 form)) - (byte-compile-keep-pending form))) - (defun byte-compile-file-form-defmumble (name macro arglist body rest) "Process a `defalias' for NAME. If MACRO is non-nil, the definition is known to be a macro. commit 55f652c856837b903b28917c8f5c6834b1483197 Author: Michael Albinus Date: Sat Dec 18 18:43:18 2021 +0100 Make generation of JUnit test reports more robust. * lisp/emacs-lisp/ert.el (ert-load-file-name): New defvar. (ert-write-junit-test-report): Use it. Make detection of selector more robust. Protect calls of `xml-escape-string' with 'noerror. * test/infra/Makefile.in (subdir_template): Use "make -k ...". * test/infra/gitlab-ci.yml (test-filenotify-gio): Adapt make_params in order to get a JUnit test report. (test-native-comp-speed0): Use "make -k ...". * test/infra/test-jobs.yml: Regenerate. * test/lisp/progmodes/perl-mode-tests.el (top): Set `ert-load-file-name'. diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 019916e617..cc464a0f81 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -1527,13 +1527,20 @@ the tests)." (backtrace)) (kill-emacs 2)))) +(defvar ert-load-file-name nil + "The name of the loaded ERT test file, a string. +Usually, it is not needed to be defined, but if different ERT +test packages depend on each other, it might be helpful.") + (defun ert-write-junit-test-report (stats) "Write a JUnit test report, generated from STATS." ;; https://www.ibm.com/docs/en/developer-for-zos/14.1.0?topic=formats-junit-xml-format ;; https://llg.cubic.org/docs/junit/ (when-let ((symbol (car (apropos-internal "" #'ert-test-boundp))) (test-file (symbol-file symbol 'ert--test)) - (test-report (file-name-with-extension test-file "xml"))) + (test-report + (file-name-with-extension + (or ert-load-file-name test-file) "xml"))) (with-temp-file test-report (insert "\n") (insert (format "\n" @@ -1557,15 +1564,19 @@ the tests)." (ert--stats-end-time stats) (ert--stats-start-time stats))) (ert--format-time-iso8601 (ert--stats-end-time stats)))) - (insert " \n" - (format " \n" - (ert--stats-selector stats)) - " \n") + ;; If the test has aborted, `ert--stats-selector' might return + ;; huge junk. Skip this. + (when (< (length (format "%s" (ert--stats-selector stats))) 1024) + (insert " \n" + (format " \n" + (xml-escape-string + (format "%s" (ert--stats-selector stats)) 'noerror)) + " \n")) (cl-loop for test across (ert--stats-tests stats) for result = (ert-test-most-recent-result test) do (insert (format " \n" (xml-escape-string (string-trim - (ert-reason-for-test-result result))) + (ert-reason-for-test-result result)) + 'noerror) (ert-string-for-test-result result (ert-test-result-expected-p test result))) (xml-escape-string (string-trim - (ert-reason-for-test-result result))) + (ert-reason-for-test-result result)) + 'noerror) "\n" " \n")) ((ert-test-aborted-with-non-local-exit-p result) @@ -1600,27 +1613,29 @@ the tests)." test result))) (format "Test %s aborted with non-local exit\n" (xml-escape-string - (symbol-name (ert-test-name test)))) + (symbol-name (ert-test-name test)) 'noerror)) " \n")) ((not (ert-test-result-type-p result (ert-test-expected-result-type test))) (insert (format " \n" (xml-escape-string (string-trim - (ert-reason-for-test-result result))) + (ert-reason-for-test-result result)) + 'noerror) (ert-string-for-test-result result (ert-test-result-expected-p test result))) (xml-escape-string (string-trim - (ert-reason-for-test-result result))) + (ert-reason-for-test-result result)) + 'noerror) "\n" " \n"))) (unless (zerop (length (ert-test-result-messages result))) (insert " \n" (xml-escape-string - (ert-test-result-messages result)) + (ert-test-result-messages result) 'noerror) " \n")) (insert " \n"))) (insert " \n") @@ -1653,7 +1668,7 @@ the tests)." (insert (format " \n" (file-name-nondirectory test-report))) (when logfile-contents - (insert (xml-escape-string logfile-contents))) + (insert (xml-escape-string logfile-contents 'noerror))) (insert " \n" " \n" " \n") diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in index e4f99743e0..368be7392b 100644 --- a/test/infra/Makefile.in +++ b/test/infra/Makefile.in @@ -84,7 +84,7 @@ define subdir_template @echo ' - test/$(1)/*resources/**' >>$(FILE) @echo ' variables:' >>$(FILE) @echo ' target: emacs-inotify' >>$(FILE) - @echo ' make_params: "-C test $(target)"' >>$(FILE) + @echo ' make_params: "-k -C test $(target)"' >>$(FILE) endef $(foreach subdir, $(SUBDIRS), $(eval $(call subdir_template,$(subdir)))) diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml index 3903642c79..dd3f517e74 100644 --- a/test/infra/gitlab-ci.yml +++ b/test/infra/gitlab-ci.yml @@ -226,7 +226,8 @@ test-filenotify-gio: optional: true variables: target: emacs-filenotify-gio - make_params: "-k -C test autorevert-tests.log filenotify-tests.log" + # This is needed in order to get a JUnit test report. + make_params: '-k -C test check-expensive LOGFILES="lisp/autorevert-tests.log lisp/filenotify-tests.log"' build-image-gnustep: stage: platform-images @@ -271,7 +272,7 @@ test-native-comp-speed0: optional: true variables: target: emacs-native-comp-speed0 - make_params: "-C test check SELECTOR='(not (tag :unstable))'" + make_params: "-k -C test check SELECTOR='(not (tag :unstable))'" # Local Variables: # add-log-current-defun-header-regexp: "^\\([-_.[:alnum:]]+\\)[ \t]*:" diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml index 63b052bf8c..51707c181b 100644 --- a/test/infra/test-jobs.yml +++ b/test/infra/test-jobs.yml @@ -15,7 +15,7 @@ test-lib-src-inotify: - test/lib-src/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lib-src" + make_params: "-k -C test check-lib-src" test-lisp-inotify: stage: normal @@ -32,7 +32,7 @@ test-lisp-inotify: - test/lisp/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp" + make_params: "-k -C test check-lisp" test-lisp-calc-inotify: stage: normal @@ -49,7 +49,7 @@ test-lisp-calc-inotify: - test/lisp/calc/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-calc" + make_params: "-k -C test check-lisp-calc" test-lisp-calendar-inotify: stage: normal @@ -66,7 +66,7 @@ test-lisp-calendar-inotify: - test/lisp/calendar/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-calendar" + make_params: "-k -C test check-lisp-calendar" test-lisp-cedet-inotify: stage: normal @@ -83,7 +83,7 @@ test-lisp-cedet-inotify: - test/lisp/cedet/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-cedet" + make_params: "-k -C test check-lisp-cedet" test-lisp-cedet-semantic-inotify: stage: normal @@ -100,7 +100,7 @@ test-lisp-cedet-semantic-inotify: - test/lisp/cedet/semantic/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-cedet-semantic" + make_params: "-k -C test check-lisp-cedet-semantic" test-lisp-cedet-semantic-bovine-inotify: stage: normal @@ -117,7 +117,7 @@ test-lisp-cedet-semantic-bovine-inotify: - test/lisp/cedet/semantic/bovine/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-cedet-semantic-bovine" + make_params: "-k -C test check-lisp-cedet-semantic-bovine" test-lisp-cedet-srecode-inotify: stage: normal @@ -134,7 +134,7 @@ test-lisp-cedet-srecode-inotify: - test/lisp/cedet/srecode/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-cedet-srecode" + make_params: "-k -C test check-lisp-cedet-srecode" test-lisp-emacs-lisp-inotify: stage: normal @@ -151,7 +151,7 @@ test-lisp-emacs-lisp-inotify: - test/lisp/emacs-lisp/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-emacs-lisp" + make_params: "-k -C test check-lisp-emacs-lisp" test-lisp-emacs-lisp-eieio-tests-inotify: stage: normal @@ -168,7 +168,7 @@ test-lisp-emacs-lisp-eieio-tests-inotify: - test/lisp/emacs-lisp/eieio-tests/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-emacs-lisp-eieio-tests" + make_params: "-k -C test check-lisp-emacs-lisp-eieio-tests" test-lisp-emacs-lisp-faceup-tests-inotify: stage: normal @@ -185,7 +185,7 @@ test-lisp-emacs-lisp-faceup-tests-inotify: - test/lisp/emacs-lisp/faceup-tests/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-emacs-lisp-faceup-tests" + make_params: "-k -C test check-lisp-emacs-lisp-faceup-tests" test-lisp-emulation-inotify: stage: normal @@ -202,7 +202,7 @@ test-lisp-emulation-inotify: - test/lisp/emulation/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-emulation" + make_params: "-k -C test check-lisp-emulation" test-lisp-erc-inotify: stage: normal @@ -219,7 +219,7 @@ test-lisp-erc-inotify: - test/lisp/erc/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-erc" + make_params: "-k -C test check-lisp-erc" test-lisp-eshell-inotify: stage: normal @@ -236,7 +236,7 @@ test-lisp-eshell-inotify: - test/lisp/eshell/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-eshell" + make_params: "-k -C test check-lisp-eshell" test-lisp-gnus-inotify: stage: normal @@ -253,7 +253,7 @@ test-lisp-gnus-inotify: - test/lisp/gnus/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-gnus" + make_params: "-k -C test check-lisp-gnus" test-lisp-image-inotify: stage: normal @@ -270,7 +270,7 @@ test-lisp-image-inotify: - test/lisp/image/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-image" + make_params: "-k -C test check-lisp-image" test-lisp-international-inotify: stage: normal @@ -287,7 +287,7 @@ test-lisp-international-inotify: - test/lisp/international/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-international" + make_params: "-k -C test check-lisp-international" test-lisp-mail-inotify: stage: normal @@ -304,7 +304,7 @@ test-lisp-mail-inotify: - test/lisp/mail/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-mail" + make_params: "-k -C test check-lisp-mail" test-lisp-mh-e-inotify: stage: normal @@ -321,7 +321,7 @@ test-lisp-mh-e-inotify: - test/lisp/mh-e/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-mh-e" + make_params: "-k -C test check-lisp-mh-e" test-lisp-net-inotify: stage: normal @@ -338,7 +338,7 @@ test-lisp-net-inotify: - test/lisp/net/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-net" + make_params: "-k -C test check-lisp-net" test-lisp-nxml-inotify: stage: normal @@ -355,7 +355,7 @@ test-lisp-nxml-inotify: - test/lisp/nxml/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-nxml" + make_params: "-k -C test check-lisp-nxml" test-lisp-obsolete-inotify: stage: normal @@ -372,7 +372,7 @@ test-lisp-obsolete-inotify: - test/lisp/obsolete/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-obsolete" + make_params: "-k -C test check-lisp-obsolete" test-lisp-org-inotify: stage: normal @@ -389,7 +389,7 @@ test-lisp-org-inotify: - test/lisp/org/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-org" + make_params: "-k -C test check-lisp-org" test-lisp-play-inotify: stage: normal @@ -406,7 +406,7 @@ test-lisp-play-inotify: - test/lisp/play/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-play" + make_params: "-k -C test check-lisp-play" test-lisp-progmodes-inotify: stage: normal @@ -423,7 +423,7 @@ test-lisp-progmodes-inotify: - test/lisp/progmodes/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-progmodes" + make_params: "-k -C test check-lisp-progmodes" test-lisp-so-long-tests-inotify: stage: normal @@ -440,7 +440,7 @@ test-lisp-so-long-tests-inotify: - test/lisp/so-long-tests/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-so-long-tests" + make_params: "-k -C test check-lisp-so-long-tests" test-lisp-term-inotify: stage: normal @@ -457,7 +457,7 @@ test-lisp-term-inotify: - test/lisp/term/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-term" + make_params: "-k -C test check-lisp-term" test-lisp-textmodes-inotify: stage: normal @@ -474,7 +474,7 @@ test-lisp-textmodes-inotify: - test/lisp/textmodes/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-textmodes" + make_params: "-k -C test check-lisp-textmodes" test-lisp-url-inotify: stage: normal @@ -491,7 +491,7 @@ test-lisp-url-inotify: - test/lisp/url/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-url" + make_params: "-k -C test check-lisp-url" test-lisp-vc-inotify: stage: normal @@ -508,7 +508,7 @@ test-lisp-vc-inotify: - test/lisp/vc/*resources/** variables: target: emacs-inotify - make_params: "-C test check-lisp-vc" + make_params: "-k -C test check-lisp-vc" test-misc-inotify: stage: normal @@ -525,7 +525,7 @@ test-misc-inotify: - test/misc/*resources/** variables: target: emacs-inotify - make_params: "-C test check-misc" + make_params: "-k -C test check-misc" test-src-inotify: stage: normal @@ -542,4 +542,4 @@ test-src-inotify: - test/src/*resources/** variables: target: emacs-inotify - make_params: "-C test check-src" + make_params: "-k -C test check-src" diff --git a/test/lisp/progmodes/perl-mode-tests.el b/test/lisp/progmodes/perl-mode-tests.el index 3f4af5e1f6..b059f53915 100644 --- a/test/lisp/progmodes/perl-mode-tests.el +++ b/test/lisp/progmodes/perl-mode-tests.el @@ -37,4 +37,6 @@ (file-name-directory (or load-file-name buffer-file-name))))) +(setq ert-load-file-name load-file-name) + ;;; perl-mode-tests.el ends here commit 21ef1740f0fe9424f2a079440d070f725b2ca558 Author: Stefan Kangas Date: Sat Dec 18 15:53:00 2021 +0100 * lisp/dired.el (dired-mode-map): Use defvar-keymap. diff --git a/lisp/dired.el b/lisp/dired.el index b964fd9c18..a884121415 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1920,154 +1920,152 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." ;;; Dired mode key bindings and menus -(defvar dired-mode-map +(defvar-keymap dired-mode-map + :doc "Local keymap for Dired mode buffers." + :full t + :parent special-mode-map ;; This looks ugly when substitute-command-keys uses C-d instead d: - ;; (define-key dired-mode-map "\C-d" 'dired-flag-file-deletion) - (let ((map (make-keymap))) - (set-keymap-parent map special-mode-map) - (define-key map [mouse-2] 'dired-mouse-find-file-other-window) - (define-key map [follow-link] 'mouse-face) - ;; Commands to mark or flag certain categories of files - (define-key map "#" 'dired-flag-auto-save-files) - (define-key map "." 'dired-clean-directory) - (define-key map "~" 'dired-flag-backup-files) - ;; Upper case keys (except !) for operating on the marked files - (define-key map "A" 'dired-do-find-regexp) - (define-key map "C" 'dired-do-copy) - (define-key map "B" 'dired-do-byte-compile) - (define-key map "D" 'dired-do-delete) - (define-key map "G" 'dired-do-chgrp) - (define-key map "H" 'dired-do-hardlink) - (define-key map "L" 'dired-do-load) - (define-key map "M" 'dired-do-chmod) - (define-key map "O" 'dired-do-chown) - (define-key map "P" 'dired-do-print) - (define-key map "Q" 'dired-do-find-regexp-and-replace) - (define-key map "R" 'dired-do-rename) - (define-key map "S" 'dired-do-symlink) - (define-key map "T" 'dired-do-touch) - (define-key map "X" 'dired-do-shell-command) - (define-key map "Z" 'dired-do-compress) - (define-key map "c" 'dired-do-compress-to) - (define-key map "!" 'dired-do-shell-command) - (define-key map "&" 'dired-do-async-shell-command) - ;; Comparison commands - (define-key map "=" 'dired-diff) - ;; Tree Dired commands - (define-key map "\M-\C-?" 'dired-unmark-all-files) - (define-key map "\M-\C-d" 'dired-tree-down) - (define-key map "\M-\C-u" 'dired-tree-up) - (define-key map "\M-\C-n" 'dired-next-subdir) - (define-key map "\M-\C-p" 'dired-prev-subdir) - ;; move to marked files - (define-key map "\M-{" 'dired-prev-marked-file) - (define-key map "\M-}" 'dired-next-marked-file) - ;; Make all regexp commands share a `%' prefix: - ;; We used to get to the submap via a symbol dired-regexp-prefix, - ;; but that seems to serve little purpose, and copy-keymap - ;; does a better job without it. - (define-key map "%" nil) - (define-key map "%u" 'dired-upcase) - (define-key map "%l" 'dired-downcase) - (define-key map "%d" 'dired-flag-files-regexp) - (define-key map "%g" 'dired-mark-files-containing-regexp) - (define-key map "%m" 'dired-mark-files-regexp) - (define-key map "%r" 'dired-do-rename-regexp) - (define-key map "%C" 'dired-do-copy-regexp) - (define-key map "%H" 'dired-do-hardlink-regexp) - (define-key map "%R" 'dired-do-rename-regexp) - (define-key map "%S" 'dired-do-symlink-regexp) - (define-key map "%&" 'dired-flag-garbage-files) - ;; Commands for marking and unmarking. - (define-key map "*" nil) - (define-key map "**" 'dired-mark-executables) - (define-key map "*/" 'dired-mark-directories) - (define-key map "*@" 'dired-mark-symlinks) - (define-key map "*%" 'dired-mark-files-regexp) - (define-key map "*N" 'dired-number-of-marked-files) - (define-key map "*c" 'dired-change-marks) - (define-key map "*s" 'dired-mark-subdir-files) - (define-key map "*m" 'dired-mark) - (define-key map "*u" 'dired-unmark) - (define-key map "*?" 'dired-unmark-all-files) - (define-key map "*!" 'dired-unmark-all-marks) - (define-key map "U" 'dired-unmark-all-marks) - (define-key map "*\177" 'dired-unmark-backward) - (define-key map "*\C-n" 'dired-next-marked-file) - (define-key map "*\C-p" 'dired-prev-marked-file) - (define-key map "*t" 'dired-toggle-marks) - ;; Lower keys for commands not operating on all the marked files - (define-key map "a" 'dired-find-alternate-file) - (define-key map "d" 'dired-flag-file-deletion) - (define-key map "e" 'dired-find-file) - (define-key map "f" 'dired-find-file) - (define-key map "\C-m" 'dired-find-file) - (put 'dired-find-file :advertised-binding "\C-m") - (define-key map "g" 'revert-buffer) - (define-key map "i" 'dired-maybe-insert-subdir) - (define-key map "j" 'dired-goto-file) - (define-key map "k" 'dired-do-kill-lines) - (define-key map "l" 'dired-do-redisplay) - (define-key map "m" 'dired-mark) - (define-key map "n" 'dired-next-line) - (define-key map "o" 'dired-find-file-other-window) - (define-key map "\C-o" 'dired-display-file) - (define-key map "p" 'dired-previous-line) - (define-key map "s" 'dired-sort-toggle-or-edit) - (define-key map "t" 'dired-toggle-marks) - (define-key map "u" 'dired-unmark) - (define-key map "v" 'dired-view-file) - (define-key map "w" 'dired-copy-filename-as-kill) - (define-key map "W" 'browse-url-of-dired-file) - (define-key map "x" 'dired-do-flagged-delete) - (define-key map "y" 'dired-show-file-type) - (define-key map "+" 'dired-create-directory) - ;; moving - (define-key map "<" 'dired-prev-dirline) - (define-key map ">" 'dired-next-dirline) - (define-key map "^" 'dired-up-directory) - (define-key map " " 'dired-next-line) - (define-key map [?\S-\ ] 'dired-previous-line) - (define-key map [remap next-line] 'dired-next-line) - (define-key map [remap previous-line] 'dired-previous-line) - ;; hiding - (define-key map "$" 'dired-hide-subdir) - (define-key map "\M-$" 'dired-hide-all) - (define-key map "(" 'dired-hide-details-mode) - ;; isearch - (define-key map (kbd "M-s a C-s") 'dired-do-isearch) - (define-key map (kbd "M-s a M-C-s") 'dired-do-isearch-regexp) - (define-key map (kbd "M-s f C-s") 'dired-isearch-filenames) - (define-key map (kbd "M-s f M-C-s") 'dired-isearch-filenames-regexp) - ;; misc - (define-key map [remap read-only-mode] 'dired-toggle-read-only) - ;; `toggle-read-only' is an obsolete alias for `read-only-mode' - (define-key map [remap toggle-read-only] 'dired-toggle-read-only) - (define-key map "?" 'dired-summary) - (define-key map "\177" 'dired-unmark-backward) - (define-key map [remap undo] 'dired-undo) - (define-key map [remap advertised-undo] 'dired-undo) - (define-key map [remap vc-next-action] 'dired-vc-next-action) - ;; thumbnail manipulation (image-dired) - (define-key map "\C-td" 'image-dired-display-thumbs) - (define-key map "\C-tt" 'image-dired-tag-files) - (define-key map "\C-tr" 'image-dired-delete-tag) - (define-key map "\C-tj" 'image-dired-jump-thumbnail-buffer) - (define-key map "\C-ti" 'image-dired-dired-display-image) - (define-key map "\C-tx" 'image-dired-dired-display-external) - (define-key map "\C-ta" 'image-dired-display-thumbs-append) - (define-key map "\C-t." 'image-dired-display-thumb) - (define-key map "\C-tc" 'image-dired-dired-comment-files) - (define-key map "\C-tf" 'image-dired-mark-tagged-files) - (define-key map "\C-t\C-t" 'image-dired-dired-toggle-marked-thumbs) - (define-key map "\C-te" 'image-dired-dired-edit-comment-and-tags) - ;; encryption and decryption (epa-dired) - (define-key map ":d" 'epa-dired-do-decrypt) - (define-key map ":v" 'epa-dired-do-verify) - (define-key map ":s" 'epa-dired-do-sign) - (define-key map ":e" 'epa-dired-do-encrypt) - map) - "Local keymap for Dired mode buffers.") + ;; "C-d" #'dired-flag-file-deletion + "" #'dired-mouse-find-file-other-window + "" 'mouse-face + ;; Commands to mark or flag certain categories of files + "#" #'dired-flag-auto-save-files + "." #'dired-clean-directory + "~" #'dired-flag-backup-files + ;; Upper case keys (except !) for operating on the marked files + "A" #'dired-do-find-regexp + "C" #'dired-do-copy + "B" #'dired-do-byte-compile + "D" #'dired-do-delete + "G" #'dired-do-chgrp + "H" #'dired-do-hardlink + "L" #'dired-do-load + "M" #'dired-do-chmod + "O" #'dired-do-chown + "P" #'dired-do-print + "Q" #'dired-do-find-regexp-and-replace + "R" #'dired-do-rename + "S" #'dired-do-symlink + "T" #'dired-do-touch + "X" #'dired-do-shell-command + "Z" #'dired-do-compress + "c" #'dired-do-compress-to + "!" #'dired-do-shell-command + "&" #'dired-do-async-shell-command + ;; Comparison commands + "=" #'dired-diff + ;; Tree Dired commands + "M-DEL" #'dired-unmark-all-files + "C-M-d" #'dired-tree-down + "C-M-u" #'dired-tree-up + "C-M-n" #'dired-next-subdir + "C-M-p" #'dired-prev-subdir + ;; move to marked files + "M-{" #'dired-prev-marked-file + "M-}" #'dired-next-marked-file + ;; Make all regexp commands share a `%' prefix: + ;; We used to get to the submap via a symbol dired-regexp-prefix, + ;; but that seems to serve little purpose, and copy-keymap + ;; does a better job without it. + "% u" #'dired-upcase + "% l" #'dired-downcase + "% d" #'dired-flag-files-regexp + "% g" #'dired-mark-files-containing-regexp + "% m" #'dired-mark-files-regexp + "% r" #'dired-do-rename-regexp + "% C" #'dired-do-copy-regexp + "% H" #'dired-do-hardlink-regexp + "% R" #'dired-do-rename-regexp + "% S" #'dired-do-symlink-regexp + "% &" #'dired-flag-garbage-files + ;; Commands for marking and unmarking. + "* *" #'dired-mark-executables + "* /" #'dired-mark-directories + "* @" #'dired-mark-symlinks + "* %" #'dired-mark-files-regexp + "* N" #'dired-number-of-marked-files + "* c" #'dired-change-marks + "* s" #'dired-mark-subdir-files + "* m" #'dired-mark + "* u" #'dired-unmark + "* ?" #'dired-unmark-all-files + "* !" #'dired-unmark-all-marks + "U" #'dired-unmark-all-marks + "* DEL" #'dired-unmark-backward + "* C-n" #'dired-next-marked-file + "* C-p" #'dired-prev-marked-file + "* t" #'dired-toggle-marks + ;; Lower keys for commands not operating on all the marked files + "a" #'dired-find-alternate-file + "d" #'dired-flag-file-deletion + "e" #'dired-find-file + "f" #'dired-find-file + "C-m" #'dired-find-file + "g" #'revert-buffer + "i" #'dired-maybe-insert-subdir + "j" #'dired-goto-file + "k" #'dired-do-kill-lines + "l" #'dired-do-redisplay + "m" #'dired-mark + "n" #'dired-next-line + "o" #'dired-find-file-other-window + "C-o" #'dired-display-file + "p" #'dired-previous-line + "s" #'dired-sort-toggle-or-edit + "t" #'dired-toggle-marks + "u" #'dired-unmark + "v" #'dired-view-file + "w" #'dired-copy-filename-as-kill + "W" #'browse-url-of-dired-file + "x" #'dired-do-flagged-delete + "y" #'dired-show-file-type + "+" #'dired-create-directory + ;; moving + "<" #'dired-prev-dirline + ">" #'dired-next-dirline + "^" #'dired-up-directory + "SPC" #'dired-next-line + "S-SPC" #'dired-previous-line + " " #'dired-next-line + " " #'dired-previous-line + ;; hiding + "$" #'dired-hide-subdir + "M-$" #'dired-hide-all + "(" #'dired-hide-details-mode + ;; isearch + "M-s a C-s" #'dired-do-isearch + "M-s a C-M-s" #'dired-do-isearch-regexp + "M-s f C-s" #'dired-isearch-filenames + "M-s f C-M-s" #'dired-isearch-filenames-regexp + ;; misc + " " #'dired-toggle-read-only + ;; `toggle-read-only' is an obsolete alias for `read-only-mode' + " " #'dired-toggle-read-only + "?" #'dired-summary + "DEL" #'dired-unmark-backward + " " #'dired-undo + " " #'dired-undo + " " #'dired-vc-next-action + ;; thumbnail manipulation (image-dired) + "C-t d" #'image-dired-display-thumbs + "C-t t" #'image-dired-tag-files + "C-t r" #'image-dired-delete-tag + "C-t j" #'image-dired-jump-thumbnail-buffer + "C-t i" #'image-dired-dired-display-image + "C-t x" #'image-dired-dired-display-external + "C-t a" #'image-dired-display-thumbs-append + "C-t ." #'image-dired-display-thumb + "C-t c" #'image-dired-dired-comment-files + "C-t f" #'image-dired-mark-tagged-files + "C-t C-t" #'image-dired-dired-toggle-marked-thumbs + "C-t e" #'image-dired-dired-edit-comment-and-tags + ;; encryption and decryption (epa-dired) + ": d" #'epa-dired-do-decrypt + ": v" #'epa-dired-do-verify + ": s" #'epa-dired-do-sign + ": e" #'epa-dired-do-encrypt) + +(put 'dired-find-file :advertised-binding (kbd "RET")) (easy-menu-define dired-mode-subdir-menu dired-mode-map "Subdir menu for Dired mode." commit cb10eed97cfe5c1bee2bee7b7c09b0dcbdf92e18 Author: Stefan Kangas Date: Sat Dec 18 15:14:23 2021 +0100 Silence byte-compiler in multisession-tests.el * test/lisp/emacs-lisp/multisession-tests.el (multi-test-sqlite-simple, multi-test-sqlite-busy) (multi-test-files-simple, multi-test-files-busy) (multi-test-files-some-values): Silence byte-compiler. diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el index 41fcde04f2..1bf0a533a7 100644 --- a/test/lisp/emacs-lisp/multisession-tests.el +++ b/test/lisp/emacs-lisp/multisession-tests.el @@ -35,12 +35,12 @@ (multisession-directory dir)) (unwind-protect (progn - (define-multisession-variable foo 0 + (define-multisession-variable multisession--foo 0 "" :synchronized t) - (should (= (multisession-value foo) 0)) - (cl-incf (multisession-value foo)) - (should (= (multisession-value foo) 1)) + (should (= (multisession-value multisession--foo) 0)) + (cl-incf (multisession-value multisession--foo)) + (should (= (multisession-value multisession--foo) 1)) (call-process (concat invocation-directory invocation-name) nil t nil @@ -51,11 +51,11 @@ (let ((multisession-directory ,dir) (multisession-storage 'sqlite) (user-init-file "/tmp/foo.el")) - (define-multisession-variable foo 0 + (define-multisession-variable multisession--foo 0 "" :synchronized t) - (cl-incf (multisession-value foo)))))) - (should (= (multisession-value foo) 2))) + (cl-incf (multisession-value multisession--foo)))))) + (should (= (multisession-value multisession--foo) 2))) (sqlite-close multisession--db) (setq multisession--db nil))))) @@ -69,12 +69,12 @@ proc) (unwind-protect (progn - (define-multisession-variable bar 0 + (define-multisession-variable multisession--bar 0 "" :synchronized t) - (should (= (multisession-value bar) 0)) - (cl-incf (multisession-value bar)) - (should (= (multisession-value bar) 1)) + (should (= (multisession-value multisession--bar) 0)) + (cl-incf (multisession-value multisession--bar)) + (should (= (multisession-value multisession--bar) 1)) (setq proc (start-process "other-emacs" @@ -87,18 +87,18 @@ (let ((multisession-directory ,dir) (multisession-storage 'sqlite) (user-init-file "/tmp/bar.el")) - (define-multisession-variable bar 0 + (define-multisession-variable multisession--bar 0 "" :synchronized t) (dotimes (i 100) - (cl-incf (multisession-value bar)))))))) + (cl-incf (multisession-value multisession--bar)))))))) (while (process-live-p proc) (ignore-error 'sqlite-locked-error - (message "bar %s" (multisession-value bar)) - ;;(cl-incf (multisession-value bar)) + (message "multisession--bar %s" (multisession-value multisession--bar)) + ;;(cl-incf (multisession-value multisession--bar)) ) (sleep-for 0.1)) - (message "bar ends up as %s" (multisession-value bar)) - (should (< (multisession-value bar) 1003))) + (message "multisession--bar ends up as %s" (multisession-value multisession--bar)) + (should (< (multisession-value multisession--bar) 1003))) (sqlite-close multisession--db) (setq multisession--db nil))))) @@ -108,12 +108,12 @@ (let ((user-init-file "/tmp/sfoo.el") (multisession-storage 'files) (multisession-directory dir)) - (define-multisession-variable sfoo 0 + (define-multisession-variable multisession--sfoo 0 "" :synchronized t) - (should (= (multisession-value sfoo) 0)) - (cl-incf (multisession-value sfoo)) - (should (= (multisession-value sfoo) 1)) + (should (= (multisession-value multisession--sfoo) 0)) + (cl-incf (multisession-value multisession--sfoo)) + (should (= (multisession-value multisession--sfoo) 1)) (call-process (concat invocation-directory invocation-name) nil t nil @@ -124,11 +124,11 @@ (let ((multisession-directory ,dir) (multisession-storage 'files) (user-init-file "/tmp/sfoo.el")) - (define-multisession-variable sfoo 0 + (define-multisession-variable multisession--sfoo 0 "" :synchronized t) - (cl-incf (multisession-value sfoo)))))) - (should (= (multisession-value sfoo) 2))))) + (cl-incf (multisession-value multisession--sfoo)))))) + (should (= (multisession-value multisession--sfoo) 2))))) (ert-deftest multi-test-files-busy () (skip-unless (and t (sqlite-available-p))) @@ -138,12 +138,12 @@ (multisession-storage 'files) (multisession-directory dir) proc) - (define-multisession-variable sbar 0 + (define-multisession-variable multisession--sbar 0 "" :synchronized t) - (should (= (multisession-value sbar) 0)) - (cl-incf (multisession-value sbar)) - (should (= (multisession-value sbar) 1)) + (should (= (multisession-value multisession--sbar) 0)) + (cl-incf (multisession-value multisession--sbar)) + (should (= (multisession-value multisession--sbar) 1)) (setq proc (start-process "other-emacs" @@ -156,16 +156,16 @@ (let ((multisession-directory ,dir) (multisession-storage 'files) (user-init-file "/tmp/sbar.el")) - (define-multisession-variable sbar 0 + (define-multisession-variable multisession--sbar 0 "" :synchronized t) (dotimes (i 1000) - (cl-incf (multisession-value sbar)))))))) + (cl-incf (multisession-value multisession--sbar)))))))) (while (process-live-p proc) - (message "sbar %s" (multisession-value sbar)) - ;;(cl-incf (multisession-value sbar)) + (message "multisession--sbar %s" (multisession-value multisession--sbar)) + ;;(cl-incf (multisession-value multisession--sbar)) (sleep-for 0.1)) - (message "sbar ends up as %s" (multisession-value sbar)) - (should (< (multisession-value sbar) 2000))))) + (message "multisession--sbar ends up as %s" (multisession-value multisession--sbar)) + (should (< (multisession-value multisession--sbar) 2000))))) (ert-deftest multi-test-files-some-values () (ert-with-temp-file dir @@ -173,29 +173,29 @@ (let ((user-init-file "/tmp/sfoo.el") (multisession-storage 'files) (multisession-directory dir)) - (define-multisession-variable foo1 nil) - (should (eq (multisession-value foo1) nil)) - (setf (multisession-value foo1) nil) - (should (eq (multisession-value foo1) nil)) - (setf (multisession-value foo1) t) - (should (eq (multisession-value foo1) t)) - - (define-multisession-variable foo2 t) - (setf (multisession-value foo2) nil) - (should (eq (multisession-value foo2) nil)) - (setf (multisession-value foo2) t) - (should (eq (multisession-value foo2) t)) - - (define-multisession-variable foo3 t) - (should-error (setf (multisession-value foo3) (make-marker))) + (define-multisession-variable multisession--foo1 nil) + (should (eq (multisession-value multisession--foo1) nil)) + (setf (multisession-value multisession--foo1) nil) + (should (eq (multisession-value multisession--foo1) nil)) + (setf (multisession-value multisession--foo1) t) + (should (eq (multisession-value multisession--foo1) t)) + + (define-multisession-variable multisession--foo2 t) + (setf (multisession-value multisession--foo2) nil) + (should (eq (multisession-value multisession--foo2) nil)) + (setf (multisession-value multisession--foo2) t) + (should (eq (multisession-value multisession--foo2) t)) + + (define-multisession-variable multisession--foo3 t) + (should-error (setf (multisession-value multisession--foo3) (make-marker))) (let ((string (with-temp-buffer (set-buffer-multibyte nil) (insert 0 1 2) (buffer-string)))) (should-not (multibyte-string-p string)) - (define-multisession-variable foo4 nil) - (setf (multisession-value foo4) string) - (should (equal (multisession-value foo4) string)))))) + (define-multisession-variable multisession--foo4 nil) + (setf (multisession-value multisession--foo4) string) + (should (equal (multisession-value multisession--foo4) string)))))) ;;; multisession-tests.el ends here commit b7338d870a1fcc155449e54150658eb82df18f63 Author: YugaEgo Date: Fri Dec 10 23:29:51 2021 +0200 Cleanup append-to-buffer section in ELisp Intro * doc/lispintro/emacs-lisp-intro.texi (append-to-buffer, Buffer Related Review, fwd-para let): Finalize shifting focus of the 'let*' introduction to the 'append-to-buffer' section. Improve wording, fix typos, remove redundant comments (Bug#8275). diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 9f1f10e8d6..43f1c2ddd5 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -4896,25 +4896,6 @@ result of this, point is placed at the beginning of the buffer and mark is set at the end of the buffer. The whole buffer is, therefore, the region. -@c FIXME: the definition of append-to-buffer has been changed (in -@c 2010-03-30). -@c In Bug#8275, Stefan Monner writes: -@c >> Do you want to fix this, or shall I try? The problem is that -@c >> append-to-buffer now uses let* and with-current-buffer, so this might -@c >> break the flow of the text. At this point in the book, let* and -@c >> with-current-buffer are not yet introduced. -@c > -@c > Here are some thoughts: -@c > - I don't think it's of any importance that the example code be -@c > identical to the currently used code. -@c > - append-to-buffer might not be the best example since AFAICT copying -@c > text from one buffer to another is not a common operation and in most -@c > cases this is done via buffer-substring + insert (often with some -@c > processing on the string between the two) rather than with -@c > insert-buffer-substring which is a rarely used function. -@c > - yes, I think the text would benefit from some rethink to try and present -@c > with-current-buffer in preference to set-buffer, but it's not -@c > a simple fix. @node append-to-buffer @section The Definition of @code{append-to-buffer} @findex append-to-buffer @@ -4949,8 +4930,9 @@ buffer to which the text will go, the window it comes from and goes to, and the region that will be copied. @need 1250 -Here is the complete text of the function: +Here is a possible implementation of the function: +@c GNU Emacs 22 @smallexample @group (defun append-to-buffer (buffer start end) @@ -5017,7 +4999,9 @@ name. (The function can handle either.) Since the @code{append-to-buffer} function will be used interactively, the function must have an @code{interactive} expression. (For a review of @code{interactive}, see @ref{Interactive, , Making a -Function Interactive}.) The expression reads as follows: +Function Interactive}.) + +The expression reads as follows: @smallexample @group @@ -5046,7 +5030,7 @@ for true. The first argument to @code{other-buffer}, the exception, is yet another function, @code{current-buffer}. That is not going to be -returned. The second argument is the symbol for true, @code{t}. that +returned. The second argument is the symbol for true, @code{t}. That tells @code{other-buffer} that it may show visible buffers (except in this case, it will not show the current buffer, which makes sense). @@ -5082,33 +5066,6 @@ point and mark. That argument worked fine.) @node append-to-buffer body @subsection The Body of @code{append-to-buffer} -@ignore -in GNU Emacs 22 in /usr/local/src/emacs/lisp/simple.el - -(defun append-to-buffer (buffer start end) - "Append to specified buffer the text of the region. -It is inserted into that buffer before its point. - -When calling from a program, give three arguments: -BUFFER (or buffer name), START and END. -START and END specify the portion of the current buffer to be copied." - (interactive - (list (read-buffer "Append to buffer: " (other-buffer (current-buffer) t)) - (region-beginning) (region-end))) - (let ((oldbuf (current-buffer))) - (save-excursion - (let* ((append-to (get-buffer-create buffer)) - (windows (get-buffer-window-list append-to t t)) - point) - (set-buffer append-to) - (setq point (point)) - (barf-if-buffer-read-only) - (insert-buffer-substring oldbuf start end) - (dolist (window windows) - (when (= (window-point window) point) - (set-window-point window (point)))))))) -@end ignore - The body of the @code{append-to-buffer} function begins with @code{let}. As we have seen before (@pxref{let, , @code{let}}), the purpose of a @@ -5127,7 +5084,7 @@ whole by showing a template for @code{append-to-buffer} with the "@var{documentation}@dots{}" (interactive @dots{}) (let ((@var{variable} @var{value})) - @var{body}@dots{}) + @var{body}@dots{})) @end group @end smallexample @@ -5247,19 +5204,39 @@ of filling in the slots of a template: @need 1200 @noindent +@anchor{let* introduced} +@findex let* In this function, the body of the @code{save-excursion} contains only one expression, the @code{let*} expression. You know about a -@code{let} function. The @code{let*} function is different. It has a -@samp{*} in its name. It enables Emacs to set each variable in its -varlist in sequence, one after another. +@code{let} function. The @code{let*} function is different. It +enables Emacs to set each variable in its varlist in sequence, one +after another; such that variables in the latter part of the varlist +can make use of the values to which Emacs set variables earlier in the +varlist. -Its critical feature is that variables later in the varlist can make -use of the values to which Emacs set variables earlier in the varlist. -@xref{fwd-para let, , The @code{let*} expression}. +Looking at the @code{let*} expression in @code{append-to-buffer}: -We will skip functions like @code{let*} and focus on two: the -@code{set-buffer} function and the @code{insert-buffer-substring} -function. +@smallexample +@group +(let* ((append-to (get-buffer-create buffer)) + (windows (get-buffer-window-list append-to t t)) + point) + BODY...) +@end group +@end smallexample + +@noindent +we see that @code{append-to} is bound to the value returned by the +@w{@code{(get-buffer-create buffer)}}. On the next line, +@code{append-to} is used as an argument to +@code{get-buffer-window-list}; this would not be possible with the +@code{let} expression. Note that @code{point} is automatically bound +to @code{nil}, the same way as it would be done in the @code{let} +statement. + +Now let's focus on the functions @code{set-buffer} and +@code{insert-buffer-substring} in the body of the @code{let*} +expression. @need 1250 In the old days, the @code{set-buffer} expression was simply @@ -5277,27 +5254,8 @@ but now it is @end smallexample @noindent -@code{append-to} is bound to @code{(get-buffer-create buffer)} earlier -on in the @code{let*} expression. That extra binding would not be -necessary except for that @code{append-to} is used later in the -varlist as an argument to @code{get-buffer-window-list}. - -@ignore -in GNU Emacs 22 - - (let ((oldbuf (current-buffer))) - (save-excursion - (let* ((append-to (get-buffer-create buffer)) - (windows (get-buffer-window-list append-to t t)) - point) - (set-buffer append-to) - (setq point (point)) - (barf-if-buffer-read-only) - (insert-buffer-substring oldbuf start end) - (dolist (window windows) - (when (= (window-point window) point) - (set-window-point window (point)))))))) -@end ignore +This is because @code{append-to} was bound to @code{(get-buffer-create +buffer)} earlier on in the @code{let*} expression. The @code{append-to-buffer} function definition inserts text from the buffer in which you are currently to a named buffer. It happens that @@ -5394,6 +5352,12 @@ an argument and insert the region into the current buffer. @item mark-whole-buffer Mark the whole buffer as a region. Normally bound to @kbd{C-x h}. +@item let* +Declare a list of variables and give them an initial value; then +evaluate the rest of the expressions in the body of @code{let*}. The +values of the variables can be used to bind ensuing variables in the +list. + @item set-buffer Switch the attention of Emacs to another buffer, but do not change the window being displayed. Used when the program rather than a human is @@ -12896,25 +12860,12 @@ familiar part of this function. @node fwd-para let @unnumberedsubsec The @code{let*} expression -The next line of the @code{forward-paragraph} function begins a -@code{let*} expression. This is different from @code{let}. The -symbol is @code{let*} not @code{let}. - @findex let* -The @code{let*} special form is like @code{let} except that Emacs sets -each variable in sequence, one after another, and variables in the -latter part of the varlist can make use of the values to which Emacs -set variables in the earlier part of the varlist. - -@ignore -( refappend save-excursion, , code save-excursion in code append-to-buffer .) -@end ignore - -(@ref{append save-excursion, , @code{save-excursion} in @code{append-to-buffer}}.) - -In the @code{let*} expression in this function, Emacs binds a total of -seven variables: @code{opoint}, @code{fill-prefix-regexp}, -@code{parstart}, @code{parsep}, @code{sp-parstart}, @code{start}, and +The next line of the @code{forward-paragraph} function begins a +@code{let*} expression (@pxref{let* introduced,,@code{let*} +introduced}), in which Emacs binds a total of seven variables: +@code{opoint}, @code{fill-prefix-regexp}, @code{parstart}, +@code{parsep}, @code{sp-parstart}, @code{start}, and @code{found-start}. The variable @code{parsep} appears twice, first, to remove instances commit f60265e73f1d31425f35d334410441986ae3aa77 Author: Eli Zaretskii Date: Sat Dec 18 16:12:23 2021 +0200 Clean up some of PGTK code * src/pgtkgui.h: Fix comments. * src/image.c (DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) (is_wayland_display, check_x_display_info) (pgtk_get_string_resource): Reformat comments. * src/gtkutil.c (xg_show_tooltip): Add comments to large #ifdef's. diff --git a/src/gtkutil.c b/src/gtkutil.c index 5271ccfba6..c10b362370 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -921,7 +921,7 @@ xg_hide_tooltip (struct frame *f) return FALSE; } -#else +#else /* HAVE_PGTK */ void xg_show_tooltip (struct frame *f, @@ -943,7 +943,7 @@ xg_hide_tooltip (struct frame *f) return TRUE; } -#endif +#endif /* HAVE_PGTK */ /*********************************************************************** diff --git a/src/image.c b/src/image.c index 55f5f5549e..dd5ea19fc1 100644 --- a/src/image.c +++ b/src/image.c @@ -102,13 +102,11 @@ static unsigned long image_alloc_image_color (struct frame *, struct image *, #endif /* USE_CAIRO */ #if defined HAVE_PGTK && defined HAVE_IMAGEMAGICK -/* On pgtk, we don't want to create scaled image. - * If we create scaled image on scale=2.0 environment, - * the created image is half size and Gdk scales it back, - * and the result is blurry. - * To avoid this, we hold original size image as far as - * we can, and let Gdk to scale it when it is shown. - */ +/* In pgtk, we don't want to create scaled image. If we create scaled + * image on scale=2.0 environment, the created image is half size and + * Gdk scales it back, and the result is blurry. To avoid this, we + * hold original size image as far as we can, and let Gdk to scale it + * when it is shown. */ # define DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE #endif diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 21f31848a5..44e3d2a37e 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -41,8 +41,6 @@ along with GNU Emacs. If not, see . */ #ifdef HAVE_PGTK -//static EmacsTooltip *pgtk_tooltip = nil; - /* Static variables to handle applescript execution. */ static Lisp_Object as_script, *as_result; static int as_status; @@ -55,7 +53,7 @@ static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); static const char *pgtk_app_name = "Emacs"; -/* scale factor manually set per monitor */ +/* Scale factor manually set per monitor. */ static Lisp_Object monitor_scale_factor_alist; /* ========================================================================== @@ -78,13 +76,9 @@ pgtk_get_monitor_scale_factor (const char *model) if (NILP (cdr)) return 0; if (FIXNUMP (cdr)) - { - return XFIXNUM (cdr); - } + return XFIXNUM (cdr); else if (FLOATP (cdr)) - { - return XFLOAT_DATA (cdr); - } + return XFLOAT_DATA (cdr); else error ("unknown type of scale-factor"); } @@ -125,15 +119,12 @@ check_pgtk_display_info (Lisp_Object object) return dpyinfo; } -/* On Wayland, - * even if without WAYLAND_DISPLAY, --display DISPLAY works, but - * gdk_display_get_name() always return "wayland-0", which may be - * different from DISPLAY. - * If with WAYLAND_DISPLAY, then it always returns WAYLAND_DISPLAY. - * So pgtk emacs is confused and enter multi display environment. - * To workaround this situation, treat all the wayland-* as the same - * display. - */ +/* On Wayland, even if without WAYLAND_DISPLAY, --display DISPLAY + works, but gdk_display_get_name always return "wayland-0", which + may be different from DISPLAY. If with WAYLAND_DISPLAY, then it + always returns WAYLAND_DISPLAY. So pgtk Emacs is confused and + enters multi display environment. To workaround this situation, + treat all the wayland-* as the same display. */ static Lisp_Object is_wayland_display (Lisp_Object dpyname) { @@ -204,7 +195,6 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (FRAME_GTK_WIDGET (f)) { update_face_from_frame_parameter (f, Qforeground_color, arg); - /*recompute_basic_faces (f); */ if (FRAME_VISIBLE_P (f)) SET_FRAME_GARBAGED (f); } @@ -219,7 +209,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f)); FRAME_BACKGROUND_PIXEL (f) = bg; - /* clear the frame */ + /* Clear the frame. */ if (FRAME_VISIBLE_P (f)) pgtk_clear_frame (f); @@ -405,7 +395,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) return; if (TYPE_RANGED_FIXNUMP (int, value)) - nlines = XFIXNUM (value); + nlines = XFIXNUM (value); else nlines = 0; @@ -530,8 +520,7 @@ x_change_tool_bar_height (struct frame *f, int height) } } - -/* toolbar support */ +/* Toolbar support. */ static void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { @@ -569,7 +558,6 @@ x_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object ol } - static void x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) @@ -588,7 +576,6 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, } } - static void x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -619,7 +606,6 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) unblock_input (); } - static void x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { @@ -1239,9 +1225,7 @@ scale factor. */ ) monitor_scale_factor_alist); } else - { - Fsetcdr (tem, scale_factor); - } + Fsetcdr (tem, scale_factor); return scale_factor; } @@ -2382,7 +2366,7 @@ font descriptor. If string contains `fontset' and not ========================================================================== */ -/* called from frame.c */ +/* Called from frame.c. */ struct pgtk_display_info * check_x_display_info (Lisp_Object frame) { @@ -2410,7 +2394,7 @@ pgtk_set_scroll_bar_default_height (struct frame *f) FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height; } -/* terms impl this instead of x-get-resource directly */ +/* Terminals implement this instead of x-get-resource directly. */ const char * pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class) @@ -3888,7 +3872,7 @@ value of DIR as in previous invocations; this is standard MS Windows behavior. } DEFUN ("pgtk-backend-display-class", Fpgtk_backend_display_class, Spgtk_backend_display_class, 0, 1, "", - doc: /* Returns the name of the Gdk backend display class of the TERMINAL. + doc: /* Return the name of the Gdk backend display class of TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) diff --git a/src/pgtkgui.h b/src/pgtkgui.h index 7342dacc5b..035e0179f6 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -53,15 +53,15 @@ typedef struct _GdkDisplay Display; typedef void *XrmDatabase; -/* some sort of attempt to normalize rectangle handling.. seems a bit much - for what is accomplished */ +/* Some sort of attempt to normalize rectangle handling.. seems a bit much + for what is accomplished. */ typedef struct { int x, y; unsigned width, height; } XRectangle; -/* This stuff needed by frame.c. */ +/* This stuff is needed by frame.c. */ #define ForgetGravity 0 #define NorthWestGravity 1 #define NorthGravity 2 diff --git a/src/pgtkim.c b/src/pgtkim.c index ba69a27501..c0104ebc0a 100644 --- a/src/pgtkim.c +++ b/src/pgtkim.c @@ -1,4 +1,4 @@ -/* Pure Gtk+-3 communication module. -*- coding: utf-8 -*- +/* Pure Gtk+-3 communication module. Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2020 Free Software Foundation, Inc. commit 120de8f9cbef44a0c26d767ca67f5457c3d7f8a0 Author: Po Lu Date: Sat Dec 18 13:59:49 2021 +0000 ; * configure.ac: Add missing object to Haiku cairo build diff --git a/configure.ac b/configure.ac index df9bde6f20..c00233edec 100644 --- a/configure.ac +++ b/configure.ac @@ -5855,7 +5855,7 @@ fi if test "${HAVE_BE_APP}" = "yes" ; then if test "${HAVE_CAIRO}" = "yes"; then - FONT_OBJ="$FONT_OBJ ftcrfont.o" + FONT_OBJ="$FONT_OBJ ftfont.o ftcrfont.o" fi fi commit a1eb71413d107196490425de9b3929d001d775cb Author: Po Lu Date: Sat Dec 18 13:47:54 2021 +0000 Fix cairo build on haiku * configure.ac: Move pgtk cairo detection to the correct location. diff --git a/configure.ac b/configure.ac index 9a74c52c68..df9bde6f20 100644 --- a/configure.ac +++ b/configure.ac @@ -3474,6 +3474,23 @@ if test "${HAVE_X11}" = "yes"; then fi fi fi + +if test "$window_system" = "pgtk"; then + CAIRO_REQUIRED=1.12.0 + CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" + EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) + if test $HAVE_CAIRO = yes; then + AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) + else + AC_MSG_ERROR([cairo required but not found.]) + fi + + CFLAGS="$CFLAGS $CAIRO_CFLAGS" + LIBS="$LIBS $CAIRO_LIBS" + AC_SUBST(CAIRO_CFLAGS) + AC_SUBST(CAIRO_LIBS) +fi + if test "${HAVE_BE_APP}" = "yes"; then if test "${with_be_cairo}" != "no"; then CAIRO_REQUIRED=1.8.0 @@ -3729,25 +3746,6 @@ AC_SUBST(LIBOTF_LIBS) AC_SUBST(M17N_FLT_CFLAGS) AC_SUBST(M17N_FLT_LIBS) -HAVE_CAIRO=no -if test "${HAVE_X11}" = "yes" -o "$window_system" = pgtk; then - if test "${with_cairo}" != "no"; then - CAIRO_REQUIRED=1.12.0 - CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" - EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) - if test $HAVE_CAIRO = yes; then - AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) - else - AC_MSG_ERROR([cairo requested but not found.]) - fi - - CFLAGS="$CFLAGS $CAIRO_CFLAGS" - LIBS="$LIBS $CAIRO_LIBS" - AC_SUBST(CAIRO_CFLAGS) - AC_SUBST(CAIRO_LIBS) - fi -fi - if test "${HAVE_X11}" = "yes"; then AC_CHECK_HEADER(X11/Xlib-xcb.h, AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes)) @@ -5850,15 +5848,12 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then FONT_OBJ="$FONT_OBJ ftfont.o" fi fi + if test "${window_system}" = "pgtk"; then FONT_OBJ="ftfont.o ftcrfont.o" fi if test "${HAVE_BE_APP}" = "yes" ; then - if test "${HAVE_FREETYPE}" = "yes" || \ - test "${HAVE_CAIRO}" = "yes"; then - FONT_OBJ="$FONT_OBJ ftfont.o" - fi if test "${HAVE_CAIRO}" = "yes"; then FONT_OBJ="$FONT_OBJ ftcrfont.o" fi commit a7794c6dd52a7daf67ed22384a7e70b695c65df8 Author: Eli Zaretskii Date: Sat Dec 18 15:39:57 2021 +0200 ; * lisp/net/browse-url.el (pgtk-backend-display-class): Declare. diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 0273478cac..b7840f0589 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -787,6 +787,8 @@ See `browse-url' for details." ;; A generic command to call the current browse-url-browser-function +(declare-function pgtk-backend-display-class "pgtkfns.c" (&optional terminal)) + ;;;###autoload (defun browse-url (url &rest args) "Open URL using a configurable method. commit 97b6907563ae9c96ebb97876ce0662c7f9d47535 Author: Po Lu Date: Sat Dec 18 20:59:11 2021 +0800 * src/pgtkfns.c (Fx_show_tip): Adjust call for new signature. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 5fc5bb4bf2..21f31848a5 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3490,7 +3490,8 @@ Text larger than the specified size is clipped. */) try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); commit 4ff3a70153ac1716bf0767fbbf92b04fdb3b1c80 Merge: 7ab1b71c0d 4544651b3f Author: Po Lu Date: Sat Dec 18 20:58:44 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 4544651b3f62ce4a104a058e8c6aee42c23b76bc Author: Po Lu Date: Sat Dec 18 20:45:11 2021 +0800 Work around some mysterious touch ownership race on GNOME Shell * src/xterm.c (x_unlink_touch_point): Return if touchpoint was actually unlinked. (handle_one_xevent): Catch and ignore errors during touch sequence grabbing. diff --git a/src/xterm.c b/src/xterm.c index 03f509ba86..7456b3b6be 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -579,7 +579,7 @@ xi_link_touch_point (struct xi_device_t *device, device->touchpoints = touchpoint; } -static void +static bool xi_unlink_touch_point (int detail, struct xi_device_t *device) { @@ -596,9 +596,11 @@ xi_unlink_touch_point (int detail, last->next = tem->next; xfree (tem); - return; + return true; } } + + return false; } static struct xi_touch_point_t * @@ -10887,37 +10889,45 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (f && device->direct_p) { - xi_link_touch_point (device, xev->detail, xev->event_x, - xev->event_y); + x_catch_errors (dpyinfo->display); + XIAllowTouchEvents (dpyinfo->display, xev->deviceid, + xev->detail, xev->event, XIAcceptTouch); + if (!x_had_errors_p (dpyinfo->display)) + { + xi_link_touch_point (device, xev->detail, xev->event_x, + xev->event_y); #ifdef HAVE_GTK3 - if (FRAME_X_OUTPUT (f)->menubar_widget - && xg_event_is_for_menubar (f, event)) - { - bool was_waiting_for_input = waiting_for_input; - /* This hack was adopted from the NS port. Whether - or not it is actually safe is a different story - altogether. */ - if (waiting_for_input) - waiting_for_input = 0; - set_frame_menubar (f, true); - waiting_for_input = was_waiting_for_input; - } + if (FRAME_X_OUTPUT (f)->menubar_widget + && xg_event_is_for_menubar (f, event)) + { + bool was_waiting_for_input = waiting_for_input; + /* This hack was adopted from the NS port. Whether + or not it is actually safe is a different story + altogether. */ + if (waiting_for_input) + waiting_for_input = 0; + set_frame_menubar (f, true); + waiting_for_input = was_waiting_for_input; + } #endif - inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT; - inev.ie.timestamp = xev->time; - XSETFRAME (inev.ie.frame_or_window, f); - XSETINT (inev.ie.x, lrint (xev->event_x)); - XSETINT (inev.ie.y, lrint (xev->event_y)); - XSETINT (inev.ie.arg, xev->detail); - - XIAllowTouchEvents (dpyinfo->display, xev->deviceid, - xev->detail, xev->event, XIAcceptTouch); + inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT; + inev.ie.timestamp = xev->time; + XSETFRAME (inev.ie.frame_or_window, f); + XSETINT (inev.ie.x, lrint (xev->event_x)); + XSETINT (inev.ie.y, lrint (xev->event_y)); + XSETINT (inev.ie.arg, xev->detail); + } + x_uncatch_errors_after_check (); } else - XIAllowTouchEvents (dpyinfo->display, xev->deviceid, - xev->detail, xev->event, XIRejectTouch); + { + x_catch_errors (dpyinfo->display); + XIAllowTouchEvents (dpyinfo->display, xev->deviceid, + xev->detail, xev->event, XIRejectTouch); + x_uncatch_errors (); + } goto XI_OTHER; } @@ -10965,24 +10975,28 @@ handle_one_xevent (struct x_display_info *dpyinfo, case XI_TouchEnd: { struct xi_device_t *device; + bool unlinked_p; device = xi_device_from_id (dpyinfo, xev->deviceid); if (!device) goto XI_OTHER; - xi_unlink_touch_point (xev->detail, device); - - f = x_any_window_to_frame (dpyinfo, xev->event); + unlinked_p = xi_unlink_touch_point (xev->detail, device); - if (f && device->direct_p) + if (unlinked_p) { - inev.ie.kind = TOUCHSCREEN_END_EVENT; - inev.ie.timestamp = xev->time; - XSETFRAME (inev.ie.frame_or_window, f); - XSETINT (inev.ie.x, lrint (xev->event_x)); - XSETINT (inev.ie.y, lrint (xev->event_y)); - XSETINT (inev.ie.arg, xev->detail); + f = x_any_window_to_frame (dpyinfo, xev->event); + + if (f && device->direct_p) + { + inev.ie.kind = TOUCHSCREEN_END_EVENT; + inev.ie.timestamp = xev->time; + XSETFRAME (inev.ie.frame_or_window, f); + XSETINT (inev.ie.x, lrint (xev->event_x)); + XSETINT (inev.ie.y, lrint (xev->event_y)); + XSETINT (inev.ie.arg, xev->detail); + } } goto XI_OTHER; commit d99aa9461b1348741ee2df7b6c7a197005191716 Author: Eli Zaretskii Date: Sat Dec 18 13:56:10 2021 +0200 ; Fix last change * src/xdisp.c (window_text_pixel_size): Fix whitespace and braces. * src/xdisp.c (Fwindow_text_pixel_size): * etc/NEWS: * doc/lispref/display.texi (Size of Displayed Text): Improve wording of the documentation of the new argument of 'window-text-pixel-size'. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 92bfd2fea1..1460e070a0 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2138,7 +2138,9 @@ height of all of these lines, if present, in the return value. The optional argument @var{ignore-line-at-end} controls whether or not to count the height of text in @var{to}'s screen line as part of -the returned pixel-height. +the returned pixel-height. This is useful if your Lisp program is +only interested in the dimensions of text up to and excluding the +visual beginning of @var{to}'s screen line. @code{window-text-pixel-size} treats the text displayed in a window as a whole and does not care about the size of individual lines. The diff --git a/etc/NEWS b/etc/NEWS index 20056b30c5..e3665b918a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -985,9 +985,10 @@ This can be used to check whether a specific font has a glyph for a character. +++ -** 'window-text-pixel-size' now accepts a new argument `ignore-line-at-end'. -This controls whether or not the screen line at the end of the -measured area will be counted during the height calculation. +** 'window-text-pixel-size' now accepts a new argument 'ignore-line-at-end'. +This controls whether or not the last screen line of the text being +measured will be counted for the purpose of calculating the text +dimensions. ** XDG support diff --git a/src/xdisp.c b/src/xdisp.c index 473c9f3f14..6dcfe3573a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10832,8 +10832,9 @@ in_display_vector_p (struct it *it) set WINDOW's buffer to the buffer specified by its BUFFER_OR_NAME argument. */ static Lisp_Object -window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, - Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end) +window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, + Lisp_Object x_limit, Lisp_Object y_limit, + Lisp_Object mode_lines, Lisp_Object ignore_line_at_end) { struct window *w = decode_live_window (window); struct it it; @@ -10973,10 +10974,8 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li /* DTRT if ignore_line_at_end is t. */ if (!NILP (ignore_line_at_end)) - { - doff = (max (it.max_ascent, it.ascent) - + max (it.max_descent, it.descent)); - } + doff = (max (it.max_ascent, it.ascent) + + max (it.max_descent, it.descent)); else { it.max_ascent = max (it.max_ascent, it.ascent); @@ -11105,8 +11104,8 @@ If it is the symbol `mode-line', 'tab-line' or `header-line', include only the height of that line, if present, in the return value. If t, include the height of any of these, if present, in the return value. -IGNORE-LINE-AT-END means to not add the height of the screen line at -TO to the returned height. */) +IGNORE-LINE-AT-END, if non-nil, means to not add the height of the +screen line that includes TO to the returned height of the text. */) (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end) { commit 43c4cc2ea29fa93de17d35e9cce4949eae171c45 Author: Po Lu Date: Sat Dec 18 18:48:11 2021 +0800 Add new argument `ignore-line-at-end' to `window-text-pixel-size' * doc/lispref/display.texi (Size of Displayed Text): Update documentation. * etc/NEWS: Announce new argument. * src/xdisp.c (window_text_pixel_size): Allow controlling if the iterator's ascent and descent will be appended to the pixel height returned. All callers changed. (Fwindow_text_pixel_size): New argument `ignore-line-at-end'. All callers changed. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index b82473f9c2..92bfd2fea1 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2086,7 +2086,7 @@ displayed in a given window. This function is used by (@pxref{Resizing Windows}) to make a window exactly as large as the text it contains. -@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines +@defun window-text-pixel-size &optional window from to x-limit y-limit mode-lines ignore-line-at-end This function returns the size of the text of @var{window}'s buffer in pixels. @var{window} must be a live window and defaults to the selected one. The return value is a cons of the maximum pixel-width @@ -2136,6 +2136,10 @@ line, if present, in the return value. If it is @code{t}, include the height of all of these lines, if present, in the return value. @end defun +The optional argument @var{ignore-line-at-end} controls whether or +not to count the height of text in @var{to}'s screen line as part of +the returned pixel-height. + @code{window-text-pixel-size} treats the text displayed in a window as a whole and does not care about the size of individual lines. The following function does. diff --git a/etc/NEWS b/etc/NEWS index bd1ed4da00..20056b30c5 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -984,6 +984,11 @@ when they have changed. This can be used to check whether a specific font has a glyph for a character. ++++ +** 'window-text-pixel-size' now accepts a new argument `ignore-line-at-end'. +This controls whether or not the screen line at the end of the +measured area will be counted during the height calculation. + ** XDG support *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. diff --git a/src/haikufns.c b/src/haikufns.c index 868fc71f97..737b033899 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -1970,7 +1970,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); diff --git a/src/w32fns.c b/src/w32fns.c index 65463b5261..02a6d78b51 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -7525,7 +7525,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); diff --git a/src/xdisp.c b/src/xdisp.c index e74411c817..473c9f3f14 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10833,7 +10833,7 @@ in_display_vector_p (struct it *it) argument. */ static Lisp_Object window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, - Lisp_Object y_limit, Lisp_Object mode_lines) + Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end) { struct window *w = decode_live_window (window); struct it it; @@ -10841,6 +10841,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li struct text_pos startp; void *itdata = NULL; int c, max_x = 0, max_y = 0, x = 0, y = 0; + int doff = 0; if (NILP (from)) { @@ -10969,8 +10970,18 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li if (IT_CHARPOS (it) == end) { x += it.pixel_width; - it.max_ascent = max (it.max_ascent, it.ascent); - it.max_descent = max (it.max_descent, it.descent); + + /* DTRT if ignore_line_at_end is t. */ + if (!NILP (ignore_line_at_end)) + { + doff = (max (it.max_ascent, it.ascent) + + max (it.max_descent, it.descent)); + } + else + { + it.max_ascent = max (it.max_ascent, it.ascent); + it.max_descent = max (it.max_descent, it.descent); + } } } else @@ -10991,8 +11002,14 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li /* Subtract height of header-line and tab-line which was counted automatically by start_display. */ - y = it.current_y + it.max_ascent + it.max_descent - - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w); + if (!NILP (ignore_line_at_end)) + y = (it.current_y + doff + - WINDOW_TAB_LINE_HEIGHT (w) + - WINDOW_HEADER_LINE_HEIGHT (w)); + else + y = (it.current_y + it.max_ascent + it.max_descent + doff + - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w)); + /* Don't return more than Y-LIMIT. */ if (y > max_y) y = max_y; @@ -11039,7 +11056,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, Li return Fcons (make_fixnum (x - start_x), make_fixnum (y)); } -DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0, +DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0, doc: /* Return the size of the text of WINDOW's buffer in pixels. WINDOW must be a live window and defaults to the selected one. The return value is a cons of the maximum pixel-width of any text line @@ -11086,9 +11103,12 @@ Optional argument MODE-LINES nil or omitted means do not include the height of the mode-, tab- or header-line of WINDOW in the return value. If it is the symbol `mode-line', 'tab-line' or `header-line', include only the height of that line, if present, in the return value. If t, -include the height of any of these, if present, in the return value. */) +include the height of any of these, if present, in the return value. + +IGNORE-LINE-AT-END means to not add the height of the screen line at +TO to the returned height. */) (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, - Lisp_Object y_limit, Lisp_Object mode_lines) + Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end) { struct window *w = decode_live_window (window); struct buffer *b = XBUFFER (w->contents); @@ -11101,7 +11121,8 @@ include the height of any of these, if present, in the return value. */) set_buffer_internal_1 (b); } - value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines); + value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines, + ignore_line_at_end); if (old_b) set_buffer_internal_1 (old_b); @@ -11151,7 +11172,8 @@ WINDOW. */) set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE); } - value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil); + value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil, + Qnil); unbind_to (count, Qnil); diff --git a/src/xfns.c b/src/xfns.c index dc25d7bfca..30ed358fb2 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7169,7 +7169,8 @@ Text larger than the specified size is clipped. */) try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); /* Calculate size of tooltip window. */ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, - make_fixnum (w->pixel_height), Qnil); + make_fixnum (w->pixel_height), Qnil, + Qnil); /* Add the frame's internal border to calculated size. */ width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); commit 3fea95b79f7a80fc84f0aee38e1f31234ed7c657 Author: Eli Zaretskii Date: Sat Dec 18 11:03:48 2021 +0200 Fix display of window-specific overlays with 'display' property * src/xdisp.c (handle_display_prop): Pass the window to 'get_char_property_and_overlay', not the buffer. (Bug#52385) The assignment of the buffer to OBJECT was moved to before the call to 'get_char_property_and_overlay', for unknown reasons, as part of installing the support for the 'min-width' space spec. diff --git a/src/xdisp.c b/src/xdisp.c index 5e549c9c63..e74411c817 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5361,9 +5361,6 @@ handle_display_prop (struct it *it) if (!it->string_from_display_prop_p) it->area = TEXT_AREA; - if (!STRINGP (it->string)) - object = it->w->contents; - propval = get_char_property_and_overlay (make_fixnum (position->charpos), Qdisplay, object, &overlay); @@ -5377,6 +5374,9 @@ handle_display_prop (struct it *it) /* Now OVERLAY is the overlay that gave us this property, or nil if it was a text property. */ + if (!STRINGP (it->string)) + object = it->w->contents; + display_replaced = handle_display_spec (it, propval, object, overlay, position, bufpos, FRAME_WINDOW_P (it->f)); commit e5a74c20c399cdcab6115197da4b96eec8d3a345 Author: Lars Ingebrigtsen Date: Sat Dec 18 09:24:17 2021 +0100 Make multisession file reading more resilient on Windows * lisp/emacs-lisp/multisession.el (multisession--read-file-value): Rename and try harder on file errors on Windows. diff --git a/lisp/emacs-lisp/multisession.el b/lisp/emacs-lisp/multisession.el index bce888acc6..6ef0da10f7 100644 --- a/lisp/emacs-lisp/multisession.el +++ b/lisp/emacs-lisp/multisession.el @@ -250,23 +250,30 @@ DOC should be a doc string, and ARGS are keywords as applicable to (defun multisession--encode-file-name (name) (url-hexify-string name)) -(defun multisession--update-file-value (file object) - (condition-case nil - (with-temp-buffer - (let* ((time (file-attribute-modification-time - (file-attributes file))) - (coding-system-for-read 'utf-8)) - (insert-file-contents file) - (let ((stored (read (current-buffer)))) - (setf (multisession--cached-value object) stored - (multisession--cached-sequence object) time) - stored))) - ;; If the file is contended (could happen with file locking in - ;; Windws) or unreadable, just return the current value. - (error - (if (eq (multisession--cached-value object) multisession--unbound) - (multisession--initial-value object) - (multisession--cached-value object))))) +(defun multisession--read-file-value (file object) + (catch 'done + (let ((i 0) + last-error) + (while (< i 10) + (condition-case err + (throw 'done + (with-temp-buffer + (let* ((time (file-attribute-modification-time + (file-attributes file))) + (coding-system-for-read 'utf-8)) + (insert-file-contents file) + (let ((stored (read (current-buffer)))) + (setf (multisession--cached-value object) stored + (multisession--cached-sequence object) time) + stored)))) + ;; Windows uses OS-level file locking that may preclude + ;; reading the file in some circumstances. So when that + ;; happens, wait a bit and try again. + (file-error + (setq i (1+ i) + last-error err) + (sleep-for (+ 0.1 (/ (float (random 10)) 10)))))) + (signal (car last-error) (cdr last-error))))) (defun multisession--object-file-name (object) (expand-file-name @@ -283,7 +290,7 @@ DOC should be a doc string, and ARGS are keywords as applicable to ;; We have no value yet; see whether it's stored. ((eq (multisession--cached-value object) multisession--unbound) (if (file-exists-p file) - (multisession--update-file-value file object) + (multisession--read-file-value file object) ;; Nope; return the initial value. (multisession--initial-value object))) ;; We have a value, but we want to update in case some other @@ -293,7 +300,7 @@ DOC should be a doc string, and ARGS are keywords as applicable to (time-less-p (multisession--cached-sequence object) (file-attribute-modification-time (file-attributes file)))) - (multisession--update-file-value file object) + (multisession--read-file-value file object) ;; Nothing, return the cached value. (multisession--cached-value object))) ;; Just return the cached value. commit 7ab1b71c0dd878daa6806ce3a01d429dc5af646c Author: Po Lu Date: Sat Dec 18 15:45:42 2021 +0800 Coding style fixes * src/gtkutil.c (xg_frame_set_char_size): Fix coding style. diff --git a/src/gtkutil.c b/src/gtkutil.c index 0164d873bb..5271ccfba6 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1100,15 +1100,18 @@ xg_frame_set_char_size (struct frame *f, int width, int height) gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), &gwidth, &gheight); #else - if (FRAME_GTK_OUTER_WIDGET (f)) { - gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - &gwidth, &gheight); - } else { - GtkAllocation alloc; - gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); - gwidth = alloc.width; - gheight = alloc.height; - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + &gwidth, &gheight); + } + else + { + GtkAllocation alloc; + gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); + gwidth = alloc.width; + gheight = alloc.height; + } #endif /* Do this before resize, as we don't know yet if we will be resized. */ @@ -1182,13 +1185,16 @@ xg_frame_set_char_size (struct frame *f, int width, int height) gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), outer_width, outer_height); #else - if (FRAME_GTK_OUTER_WIDGET (f)) { - gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - outer_width, outer_height); - } else { - gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), - outer_width, outer_height); - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + outer_width, outer_height); + } + else + { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + outer_width, outer_height); + } #endif if (hide_child_frame) @@ -1211,13 +1217,16 @@ xg_frame_set_char_size (struct frame *f, int width, int height) gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), outer_width, outer_height); #else - if (FRAME_GTK_OUTER_WIDGET (f)) { - gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - outer_width, outer_height); - } else { - gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), - outer_width, outer_height); - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + outer_width, outer_height); + } + else + { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + outer_width, outer_height); + } #endif fullscreen = Qnil; } commit 6ad5ff4496085a74015a03d8bc0e891dbd4c3914 Merge: 5e5cde55e5 0c240e4235 Author: Po Lu Date: Sat Dec 18 15:30:43 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 5e5cde55e5be6e2d388252c3ccb0d019aee6b89e Merge: 32b9b22f66 f6339412ee Author: Po Lu Date: Fri Dec 17 14:23:07 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 32b9b22f66b1afcc614d5f76860d56d5630c5bc4 Merge: 81d2e846a8 0b43e7a493 Author: Po Lu Date: Thu Dec 16 17:57:56 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 81d2e846a801a45befe911146469a983af8438c6 Merge: 30ac6fbbed 92ed2fe688 Author: Po Lu Date: Wed Dec 15 18:39:06 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 30ac6fbbed95b3e9db530a35be7d04c257076423 Merge: da2c0e8f7d 8c0f9be0d1 Author: Po Lu Date: Tue Dec 14 17:43:16 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit da2c0e8f7d7ce7a7a45a5b1425821426dc291d9f Merge: 13edadb492 9ce0fe5ef4 Author: Po Lu Date: Mon Dec 13 13:32:53 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 13edadb4927c4f5bf130d602d60d29099e50a166 Author: Po Lu Date: Sun Dec 12 21:44:02 2021 +0800 Fix overline display when there is a box on PGTK * src/pgtkterm.c (pgtk_draw_glyph_string): Draw box before any text decorations. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index ed9d086273..bd61c65edd 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2503,6 +2503,10 @@ pgtk_draw_glyph_string (struct glyph_string *s) if (!s->for_overlaps) { + /* Draw relief if not yet drawn. */ + if (!relief_drawn_p && s->face->box != FACE_NO_BOX) + x_draw_glyph_string_box (s); + /* Draw underline. */ if (s->face->underline) { @@ -2617,10 +2621,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) } } - /* Draw relief if not yet drawn. */ - if (!relief_drawn_p && s->face->box != FACE_NO_BOX) - x_draw_glyph_string_box (s); - if (s->prev) { struct glyph_string *prev; commit 2de147e93c69a3ae2c74b5264ab5c6e46598ac31 Merge: 87cdc6369a 0ee1a46e6c Author: Po Lu Date: Sun Dec 12 21:40:17 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 87cdc6369acc7ae8537d9156e8231821e3378c9a Author: Po Lu Date: Sun Dec 12 11:26:04 2021 +0800 Fix coding style * src/pgtkmenu.c (popup_widget_loop): (popup_deactivate_callback): (show_help_event): (menu_highlight_callback): (menubar_selection_callback): (popup_selection_callback): (dialog_selection_callback): (create_and_show_dialog): Fix coding style. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 40adfa55ea..fd2c53a1b8 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -107,7 +107,7 @@ DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_i Used for popup menus and dialogs. */ static void -popup_widget_loop (bool do_timers, GtkWidget * widget) +popup_widget_loop (bool do_timers, GtkWidget *widget) { ++popup_activated_flag; @@ -130,7 +130,7 @@ pgtk_activate_menubar (struct frame *f) used and has been unposted. */ static void -popup_deactivate_callback (GtkWidget * widget, gpointer client_data) +popup_deactivate_callback (GtkWidget *widget, gpointer client_data) { popup_activated_flag = 0; } @@ -139,7 +139,7 @@ popup_deactivate_callback (GtkWidget * widget, gpointer client_data) for that widget. F is the frame if known, or NULL if not known. */ static void -show_help_event (struct frame *f, GtkWidget * widget, Lisp_Object help) +show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help) { /* Don't show this tooltip. * Tooltips are always tied to main widget, so stacking order @@ -175,7 +175,7 @@ show_help_event (struct frame *f, GtkWidget * widget, Lisp_Object help) unhighlighting. */ static void -menu_highlight_callback (GtkWidget * widget, gpointer call_data) +menu_highlight_callback (GtkWidget *widget, gpointer call_data) { xg_menu_item_cb_data *cb_data; Lisp_Object help; @@ -207,7 +207,7 @@ static bool xg_crazy_callback_abort; Figure out what the user chose and put the appropriate events into the keyboard buffer. */ static void -menubar_selection_callback (GtkWidget * widget, gpointer client_data) +menubar_selection_callback (GtkWidget *widget, gpointer client_data) { xg_menu_item_cb_data *cb_data = client_data; @@ -531,7 +531,7 @@ initialize_frame_menubar (struct frame *f) static Lisp_Object *volatile menu_item_selection; static void -popup_selection_callback (GtkWidget * widget, gpointer client_data) +popup_selection_callback (GtkWidget *widget, gpointer client_data) { xg_menu_item_cb_data *cb_data = client_data; @@ -876,7 +876,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, } static void -dialog_selection_callback (GtkWidget * widget, gpointer client_data) +dialog_selection_callback (GtkWidget *widget, gpointer client_data) { /* Treat the pointer as an integer. There's no problem as long as pointers have enough bits to hold small integers. */ @@ -890,7 +890,7 @@ dialog_selection_callback (GtkWidget * widget, gpointer client_data) dialog pops down. menu_item_selection will be set to the selection. */ static void -create_and_show_dialog (struct frame *f, widget_value * first_wv) +create_and_show_dialog (struct frame *f, widget_value *first_wv) { GtkWidget *menu; commit ae0f52b7b4bc3fa5c12db8d5ecf5d6fac917493d Author: Po Lu Date: Sun Dec 12 11:24:29 2021 +0800 Prevent hangs when displaying a context menu on pgtk * src/pgtkmenu.c (pgtk_menu_wait_for_event, popup_widget_loop): Remove unnecessary workarounds. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 6f8f8720de..40adfa55ea 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -68,24 +68,6 @@ pgtk_menu_set_in_use (bool in_use) } } -/* Wait for an X event to arrive or for a timer to expire. */ - -static void -pgtk_menu_wait_for_event (void *data) -{ - struct timespec next_time = timer_check (), *ntp; - - if (!timespec_valid_p (next_time)) - ntp = 0; - else - ntp = &next_time; - - /* Gtk3 have arrows on menus when they don't fit. When the - pointer is over an arrow, a timeout scrolls it a bit. Use - xg_select so that timeout gets triggered. */ - xg_select (0, NULL, NULL, NULL, ntp, NULL); -} - DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", doc: /* Start key navigation of the menu bar in FRAME. This initially opens the first menu bar item and you can then navigate with the @@ -131,11 +113,7 @@ popup_widget_loop (bool do_timers, GtkWidget * widget) /* Process events in the Gtk event loop until done. */ while (popup_activated_flag) - { - if (do_timers) - pgtk_menu_wait_for_event (0); - gtk_main_iteration (); - } + gtk_main_iteration (); } void commit 0e69753ac142ef0f45ec14c8281ec4f76aea723b Merge: b9c1e1d73b ff9360f4da Author: Po Lu Date: Sun Dec 12 11:15:00 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit b9c1e1d73bbaf9228867dad2885ca6de53a3175f Author: Yuuki Harano Date: Sat Dec 11 22:03:01 2021 +0900 Implement pgtk_frame_raise_lower * src/pgtkterm.c (pgtk_raise_frame): New function. (pgtk_lower_frame): New function. (pgtk_frame_raise_lower): New function to call one of those. (pgtk_create_terminal): Set frame_raise_lower_hook. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index c502905926..ed9d086273 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -195,6 +195,42 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { } +/* Raise frame F. */ + +static void +pgtk_raise_frame (struct frame *f) +{ + /* This works only for non-child frames on X. + It does not work for child frames on X, and it does not work + on Wayland too. */ + block_input (); + if (FRAME_VISIBLE_P (f)) + gdk_window_raise (gtk_widget_get_window (FRAME_WIDGET (f))); + unblock_input (); +} + +/* Lower frame F. */ + +static void +pgtk_lower_frame (struct frame *f) +{ + if (FRAME_VISIBLE_P (f)) + { + block_input (); + gdk_window_lower (gtk_widget_get_window (FRAME_WIDGET (f))); + unblock_input (); + } +} + +static void +pgtk_frame_raise_lower (struct frame *f, bool raise_flag) +{ + if (raise_flag) + pgtk_raise_frame (f); + else + pgtk_lower_frame (f); +} + /* Free X resources of frame F. */ void @@ -4671,7 +4707,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->mouse_position_hook = pgtk_mouse_position; terminal->frame_rehighlight_hook = XTframe_rehighlight; terminal->buffer_flipping_unblocked_hook = pgtk_buffer_flipping_unblocked_hook; - /* terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; */ + terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; terminal->fullscreen_hook = pgtk_fullscreen_hook; terminal->menu_show_hook = pgtk_menu_show; commit 9be1a841e59e7975195cb3e2f52855172bb46608 Author: Po Lu Date: Sat Dec 11 18:45:35 2021 +0800 Coding style fixes * src/pgtkterm.c (button_event): Fix coding style. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1e8d49c1d1..c502905926 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5947,10 +5947,9 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { block_input (); gtk_widget_grab_focus (FRAME_GTK_WIDGET (f)); + if (FRAME_GTK_OUTER_WIDGET (f)) - { - gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); - } + gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); unblock_input (); } } commit 8c29dbd3a81e6f0c9b9a76d4fd617f05ae2ea235 Author: Po Lu Date: Sat Dec 11 18:44:53 2021 +0800 Fix tooltips in PGTK child frames * src/gtkutil.c (xg_show_tooltip, xg_hide_tooltip): Make safe for child frames. diff --git a/src/gtkutil.c b/src/gtkutil.c index 225984af41..0164d873bb 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -928,15 +928,18 @@ xg_show_tooltip (struct frame *f, Lisp_Object string) { Lisp_Object encoded_string = ENCODE_UTF_8 (string); - gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f), SSDATA (encoded_string)); + gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f) + ? FRAME_GTK_OUTER_WIDGET (f) + : FRAME_GTK_WIDGET (f), + SSDATA (encoded_string)); } bool xg_hide_tooltip (struct frame *f) { - if (gtk_widget_get_tooltip_text (FRAME_GTK_OUTER_WIDGET (f)) == NULL) - return FALSE; - gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f), NULL); + if (FRAME_GTK_OUTER_WIDGET (f)) + gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f), NULL); + gtk_widget_set_tooltip_text (FRAME_GTK_WIDGET (f), NULL); return TRUE; } commit 25084b1e953ebe036e275a2cf5a6bb4de64a4008 Merge: ea8bb59c1b d90be27995 Author: Po Lu Date: Sat Dec 11 18:34:05 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit ea8bb59c1b393e57046fec698fbb498f08bc70cc Merge: cc0f147180 c9cb59bc4f Author: Po Lu Date: Sat Dec 11 11:00:39 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit cc0f147180300b672894de931bee76b2a3a719e9 Merge: 6919d5a7c0 6e865a7171 Author: Po Lu Date: Fri Dec 10 14:50:21 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 6919d5a7c0a23c14ae77f7c708ea6d0ef2478108 Merge: 47cd820d93 c0b9041ebd Author: Po Lu Date: Fri Dec 10 08:54:56 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 47cd820d93d282da484ae91e68021736ed7994bc Merge: 41b1d223c6 63f07ea22f Author: Po Lu Date: Thu Dec 9 10:30:18 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 41b1d223c6ab7bca1b626a4c07a4f2dda2855feb Merge: bdeb189cf2 bf79dad3f2 Author: Po Lu Date: Wed Dec 8 14:18:09 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit bdeb189cf202f9661f783aebd4852b401858958b Merge: d9b3f665bc 176c63287f Author: Po Lu Date: Wed Dec 8 09:03:14 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit d9b3f665bc57bc78716f4c9d5efebf283f7e1964 Merge: 0b6a632f99 e17aea73a5 Author: Po Lu Date: Tue Dec 7 09:32:13 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 0b6a632f99214e2d1e9e1d72b8f8b3a7f054d552 Merge: f68a0314e3 9eba6b966e Author: Yuuki Harano Date: Tue Dec 7 00:46:39 2021 +0900 Merge branch 'feature/pgtk' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit f68a0314e3ca522d1a86eae6cc909c1a5381ac3b Author: Yuuki Harano Date: Tue Dec 7 00:35:54 2021 +0900 * src/pgtkterm.c (x_set_parent_frame): Fix coding style diff --git a/src/pgtkterm.c b/src/pgtkterm.c index ed7a4a45c2..4bfe2efbdc 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -860,12 +860,13 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, g_object_unref (fixed); - if (FRAME_GTK_OUTER_WIDGET (f)) { - if (EQ (x_gtk_resize_child_frames, Qresize_mode)) - gtk_container_set_resize_mode - (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), - p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE); - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + if (EQ (x_gtk_resize_child_frames, Qresize_mode)) + gtk_container_set_resize_mode + (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), + p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE); + } unblock_input (); commit 42d4ffad5ad3c381a5495c7ce059ff1526a22a28 Author: Yuuki Harano Date: Tue Dec 7 00:20:30 2021 +0900 Fix SEGV crash by unref css provider too much I Got css provider from F, and was going to remove it from style context. But between them, unhighlight was called when gtk_container_remove was called, and the css provider was already freed, so I can't use the css provider to remove it from style context. As a fix, I call gtk_container_remove after remove it. Also, I free a css provider set by unhighlight. * src/pgtkterm.c (x_set_parent_frame): diff --git a/src/pgtkterm.c b/src/pgtkterm.c index bf863c8474..ed7a4a45c2 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -798,15 +798,19 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, gtk_widget_get_allocation (fixed, &alloc); g_object_ref (fixed); + /* Remember the css provider, and restore it later. */ GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider; + FRAME_X_OUTPUT (f)->border_color_css_provider = NULL; + { + GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider)); + } { GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed); + /* Here, unhighlight can be called and may change border_color_css_provider. */ gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed); - GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); - gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider)); - if (FRAME_GTK_OUTER_WIDGET (f)) { gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); @@ -842,9 +846,17 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, gtk_widget_show_all (fixed); } + /* Restore css provider. */ GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); + GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; + FRAME_X_OUTPUT (f)->border_color_css_provider = provider; gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + if (old != NULL) + { + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + g_object_unref(old); + } g_object_unref (fixed); commit 9eba6b966e330a38bdc3fef5e36b8a2904e72785 Merge: 7314c12e64 c1145c31ad Author: Po Lu Date: Mon Dec 6 17:24:28 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 7314c12e64ef5b185e3fd52d8dc1111eb730bdad Author: Po Lu Date: Mon Dec 6 13:43:23 2021 +0800 Fix child frame crash on pgtk * src/gtkutil.c (xg_check_special_colors): Use `FRAME_WIDGET' on PGTK. diff --git a/src/gtkutil.c b/src/gtkutil.c index d872d393ca..225984af41 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -684,8 +684,13 @@ xg_check_special_colors (struct frame *f, block_input (); { #ifdef HAVE_GTK3 +#ifndef HAVE_PGTK GtkStyleContext *gsty = gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); +#else + GtkStyleContext *gsty + = gtk_widget_get_style_context (FRAME_WIDGET (f)); +#endif GdkRGBA col; char buf[sizeof "rgb://rrrr/gggg/bbbb"]; int state = GTK_STATE_FLAG_SELECTED|GTK_STATE_FLAG_FOCUSED; commit c83dc91579ba992ea0964c1eac68d4334b888a21 Author: Po Lu Date: Mon Dec 6 13:08:28 2021 +0800 Fix coding style * src/pgtkfns.c (frame_geometry): * src/pgtkterm.c (x_set_parent_frame): (pgtk_text_icon): (key_release_event): (configure_event): (map_event): (window_state_event): (delete_event): (enter_notify_event): Fix coding style. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 74591452fb..5fc5bb4bf2 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3551,17 +3551,23 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) /* Get these here because they can't be got in configure_event(). */ int left_pos, top_pos; - if (FRAME_GTK_OUTER_WIDGET (f)) { - gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - &left_pos, &top_pos); - } else { - if (FRAME_GTK_WIDGET (f) == NULL) - return Qnil; /* This can occur while creating a frame. */ - GtkAllocation alloc; - gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); - left_pos = alloc.x; - top_pos = alloc.y; - } + + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + &left_pos, &top_pos); + } + else + { + GtkAllocation alloc; + + if (FRAME_GTK_WIDGET (f) == NULL) + return Qnil; /* This can occur while creating a frame. */ + + gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); + left_pos = alloc.x; + top_pos = alloc.y; + } int native_left = left_pos + border; int native_top = top_pos + border + title_height; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index bf863c8474..7af4e3783a 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -805,7 +805,8 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed); GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); - gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider)); + if (provider) + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider)); if (FRAME_GTK_OUTER_WIDGET (f)) { @@ -843,17 +844,19 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, } GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); - gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); + if (provider) + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); g_object_unref (fixed); - if (FRAME_GTK_OUTER_WIDGET (f)) { - if (EQ (x_gtk_resize_child_frames, Qresize_mode)) - gtk_container_set_resize_mode - (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), - p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE); - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + if (EQ (x_gtk_resize_child_frames, Qresize_mode)) + gtk_container_set_resize_mode + (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), + p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE); + } unblock_input (); @@ -3037,10 +3040,11 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file) bool pgtk_text_icon (struct frame *f, const char *icon_name) { - if (FRAME_GTK_OUTER_WIDGET (f)) { - gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); - gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); + } return false; } @@ -5366,13 +5370,17 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } static gboolean -key_release_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) +key_release_event (GtkWidget *widget, + GdkEvent *event, + gpointer *user_data) { return TRUE; } static gboolean -configure_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) +configure_event (GtkWidget *widget, + GdkEvent *event, + gpointer *user_data) { struct frame *f = pgtk_any_window_to_frame (event->configure.window); if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) @@ -5392,7 +5400,9 @@ configure_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } static gboolean -map_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) +map_event (GtkWidget *widget, + GdkEvent *event, + gpointer *user_data) { struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; @@ -5439,8 +5449,9 @@ map_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } static gboolean -window_state_event (GtkWidget * widget, GdkEvent * event, - gpointer * user_data) +window_state_event (GtkWidget *widget, + GdkEvent *event, + gpointer *user_data) { struct frame *f = pgtk_any_window_to_frame (event->window_state.window); union buffered_input_event inev; @@ -5473,7 +5484,8 @@ window_state_event (GtkWidget * widget, GdkEvent * event, } static gboolean -delete_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) +delete_event (GtkWidget *widget, + GdkEvent *event, gpointer *user_data) { struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; @@ -5548,8 +5560,8 @@ x_focus_changed (gboolean is_enter, int state, } static gboolean -enter_notify_event (GtkWidget * widget, GdkEvent * event, - gpointer * user_data) +enter_notify_event (GtkWidget *widget, GdkEvent *event, + gpointer *user_data) { union buffered_input_event inev; struct frame *frame = commit 8f2d0450ad23681bb6fc26ca46c7eb1c615128de Merge: f99745c78e 77de40aed3 Author: Po Lu Date: Mon Dec 6 08:57:17 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit f99745c78ec13c02817dbd10eb1c4c041add7c21 Author: Yuuki Harano Date: Mon Dec 6 00:39:36 2021 +0900 * src/frame.c (gui_set_border_width): Revert confused changes diff --git a/src/frame.c b/src/frame.c index 98f1b80e42..2b06bc821d 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4788,17 +4788,10 @@ gui_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (border_width == f->border_width) return; -#ifndef HAVE_PGTK if (FRAME_NATIVE_WINDOW (f) != 0) error ("Cannot change the border width of a frame"); -#endif f->border_width = border_width; - -#ifdef HAVE_PGTK - if (FRAME_TERMINAL (f)->frame_rehighlight_hook) - (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f); -#endif } void commit aacc371ac5edb8c4b48bbf7d03891e483f5ef79d Merge: e5f74cecf1 1710fca446 Author: Yuuki Harano Date: Mon Dec 6 00:37:31 2021 +0900 Merge branch 'feature/pgtk' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit e5f74cecf132eb266abbaf7483bd793f45cc370f Merge: 6d7a1123b4 622550f718 Author: Yuuki Harano Date: Mon Dec 6 00:37:01 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 1710fca446650b25c9656f2a6131785581afa22e Merge: 360d2d3a33 8bdea76720 Author: Po Lu Date: Sun Dec 5 11:30:14 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 360d2d3a3328799ed8fea27bc7c13873f84b65fa Merge: f851e725b3 b3505e31d6 Author: Po Lu Date: Sun Dec 5 08:36:40 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit f851e725b35d2ebd51b829059761a232d2ca1fbb Merge: 44ed098153 aa6681a51a Author: Po Lu Date: Sat Dec 4 20:34:08 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 44ed0981535e1baf994b55ede7a975a03a69c960 Author: Po Lu Date: Sat Dec 4 20:31:58 2021 +0800 Fix double buffering on pgtk * src/pgtkterm.c (pgtk_update_end): Stop flipping buffers here. (pgtk_frame_up_to_date) (pgtk_buffer_flipping_unblocked_hook): New function. (pgtk_create_terminal): Attach new hooks. (leave_notify_event): Clear mouse face. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 4c953fa92b..bf863c8474 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3144,12 +3144,21 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) static void pgtk_update_end (struct frame *f) { - GtkWidget *widget = FRAME_GTK_WIDGET (f); /* Mouse highlight may be displayed again. */ MOUSE_HL_INFO (f)->mouse_face_defer = false; +} - gtk_widget_queue_draw (widget); - flip_cr_context (f); +static void +pgtk_frame_up_to_date (struct frame *f) +{ + block_input (); + FRAME_MOUSE_UPDATE (f); + if (!buffer_flipping_blocked_p ()) + { + flip_cr_context (f); + gtk_widget_queue_draw (FRAME_GTK_WIDGET (f)); + } + unblock_input (); } /* Return the current position of the mouse. @@ -4612,6 +4621,15 @@ x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) pgtk_frame_rehighlight (dpyinfo); } +static void +pgtk_buffer_flipping_unblocked_hook (struct frame *f) +{ + block_input (); + flip_cr_context (f); + gtk_widget_queue_draw (FRAME_GTK_WIDGET (f)); + unblock_input (); +} + static struct terminal * pgtk_create_terminal (struct pgtk_display_info *dpyinfo) /* -------------------------------------------------------------------------- @@ -4631,9 +4649,10 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->update_begin_hook = pgtk_update_begin; terminal->update_end_hook = pgtk_update_end; terminal->read_socket_hook = pgtk_read_socket; - /* terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; */ + terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; terminal->mouse_position_hook = pgtk_mouse_position; terminal->frame_rehighlight_hook = XTframe_rehighlight; + terminal->buffer_flipping_unblocked_hook = pgtk_buffer_flipping_unblocked_hook; /* terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; */ terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; terminal->fullscreen_hook = pgtk_fullscreen_hook; @@ -5555,8 +5574,8 @@ enter_notify_event (GtkWidget * widget, GdkEvent * event, } static gboolean -leave_notify_event (GtkWidget * widget, GdkEvent * event, - gpointer * user_data) +leave_notify_event (GtkWidget *widget, GdkEvent *event, + gpointer *user_data) { union buffered_input_event inev; struct frame *frame = @@ -5567,6 +5586,15 @@ leave_notify_event (GtkWidget * widget, GdkEvent * event, struct frame *focus_frame = dpyinfo->x_focus_frame; int focus_state = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0; + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (frame); + + if (frame == hlinfo->mouse_face_mouse_frame) + { + /* If we move outside the frame, then we're + certainly no longer on any text in the frame. */ + clear_mouse_face (hlinfo); + hlinfo->mouse_face_mouse_frame = 0; + } EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; commit 3925fd777f93481932abbba45d6f139746fd3231 Author: Po Lu Date: Sat Dec 4 19:45:12 2021 +0800 Fix coding style of a recent change * src/pgtkfns.c (update_watched_scale_factor): Fix coding style. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index febc90ad4e..74591452fb 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1180,11 +1180,12 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) RES_TYPE_STRING); } -static void update_watched_scale_factor(struct atimer *timer) +static void +update_watched_scale_factor (struct atimer *timer) { struct frame *f = timer->client_data; - double scale_factor = FRAME_SCALE_FACTOR (f); + if (scale_factor != FRAME_X_OUTPUT (f)->watched_scale_factor) { FRAME_X_OUTPUT (f)->watched_scale_factor = scale_factor; commit 6d7a1123b44ecc4b0f5f356df1eaea0b74e1e855 Merge: d44d6ae016 84c9369fd7 Author: Yuuki Harano Date: Sat Dec 4 16:31:14 2021 +0900 Merge branch 'feature/pgtk' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit d44d6ae016ef9245737550a03ebf25cf49d7fe65 Merge: 729311c22b fba17b0747 Author: Yuuki Harano Date: Sat Dec 4 16:06:16 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 729311c22b230faab9f8714ca2b6cb8f73ac0737 Author: Yuuki Harano Date: Sat Dec 4 15:54:37 2021 +0900 Keep track of scale factor by atimer and recreate cairo_surface_t Otherwise texts become blurry when a frame moved from 1x monitor to 2x monitor. I need GTK's such signal, but there isn't. Instead I watch frame's monitor's scale factor periodically. We can see blurriness for a short time, but it is gone soon. * src/pgtkfns.c (update_watched_scale_factor): New function to check scale factor and recreate cairo_surface_t if changed. * src/pgtkfns.c (Fx_create_frame): Initialize atimer. (Fx_show_tip): Add an argument. * src/pgtkterm.c (FRAME_CR_SURFACE_DESIRED_WIDTH): Move macros to pgtkterm.h (x_free_frame_resources): Free atimer. (size_allocate): Add an argument. (pgtk_cr_update_surface_desired_size): Add an argument. Recreate if it is true. * src/pgtkterm.h (struct pgtk_output): New members. (FRAME_CR_SURFACE_DESIRED_HEIGHT): Move macros from pgtkterm.c diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4f1f9faa2c..febc90ad4e 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see . */ #include "fontset.h" #include "font.h" #include "xsettings.h" +#include "atimer.h" #ifdef HAVE_PGTK @@ -1179,6 +1180,21 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) RES_TYPE_STRING); } +static void update_watched_scale_factor(struct atimer *timer) +{ + struct frame *f = timer->client_data; + + double scale_factor = FRAME_SCALE_FACTOR (f); + if (scale_factor != FRAME_X_OUTPUT (f)->watched_scale_factor) + { + FRAME_X_OUTPUT (f)->watched_scale_factor = scale_factor; + pgtk_cr_update_surface_desired_size (f, + FRAME_CR_SURFACE_DESIRED_WIDTH (f), + FRAME_CR_SURFACE_DESIRED_HEIGHT (f), + true); + } +} + /* ========================================================================== Lisp definitions @@ -1773,6 +1789,12 @@ This function is an internal primitive--use `make-frame' instead. */ ) FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL; FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; + FRAME_X_OUTPUT (f)->watched_scale_factor = 1.0; + struct timespec ts = make_timespec (1, 0); + FRAME_X_OUTPUT (f)->scale_factor_atimer = start_atimer(ATIMER_CONTINUOUS, + ts, + update_watched_scale_factor, + f); /* Make sure windows on this frame appear in calls to next-window and similar functions. */ @@ -3481,7 +3503,7 @@ Text larger than the specified size is clipped. */) gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (tip_f)), root_x, root_y); unblock_input (); - pgtk_cr_update_surface_desired_size (tip_f, width, height); + pgtk_cr_update_surface_desired_size (tip_f, width, height, false); w->must_be_updated_p = true; update_single_window (w); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1fc8fa98a4..4c953fa92b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -72,10 +72,6 @@ along with GNU Emacs. If not, see . */ #define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) #define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active) #define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f))) -#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ - ((f)->output_data.pgtk->cr_surface_desired_width) -#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ - ((f)->output_data.pgtk->cr_surface_desired_height) /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ @@ -215,6 +211,12 @@ x_free_frame_resources (struct frame *f) free_frame_faces (f); + if (FRAME_X_OUTPUT (f)->scale_factor_atimer != NULL) + { + cancel_atimer (FRAME_X_OUTPUT (f)->scale_factor_atimer); + FRAME_X_OUTPUT (f)->scale_factor_atimer = NULL; + } + #define CLEAR_IF_EQ(FIELD) \ do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false) @@ -4845,7 +4847,7 @@ size_allocate (GtkWidget * widget, GtkAllocation * alloc, if (f) { xg_frame_resized (f, alloc->width, alloc->height); - pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height); + pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height, false); } } @@ -6820,10 +6822,11 @@ If set to a non-float value, there will be no wait at all. */); * until a redrawn frame is completed. */ void -pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) +pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height, bool force) { if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width - || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) + || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height + || force) { pgtk_cr_destroy_frame_context (f); FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c16221da83..e76411cf02 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -398,6 +398,13 @@ struct pgtk_output frame, or IMPLICIT if we received an EnterNotify. FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ int focus_state; + + /* Keep track of scale factor. If monitor's scale factor is changed, or + monitor is switched and scale factor is changed, then recreate cairo_t + and cairo_surface_t. I need GTK's such signal, but there isn't, so + I watch it periodically with atimer. */ + double watched_scale_factor; + struct atimer *scale_factor_atimer; }; /* this dummy decl needed to support TTYs */ @@ -521,6 +528,10 @@ enum (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ : FRAME_SCROLL_BAR_COLS (f)) +#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ + ((f)->output_data.pgtk->cr_surface_desired_width) +#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ + ((f)->output_data.pgtk->cr_surface_desired_height) /* Display init/shutdown functions implemented in pgtkterm.c */ extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, @@ -575,7 +586,7 @@ extern void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); /* Cairo related functions implemented in pgtkterm.c */ -extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int); +extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int, bool); extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, commit 84c9369fd74df11198553c6cd5bdd238bcf54a6f Merge: 39c466b195 fba17b0747 Author: Po Lu Date: Sat Dec 4 14:06:32 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 39c466b19587e024964189458c44d079d1fc0588 Merge: f638541785 352c737dce Author: Po Lu Date: Sat Dec 4 08:40:23 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit f638541785f0641f3010fa9c4393a4c32710d47e Author: Koen van Greevenbroek Date: Fri Dec 3 18:12:07 2021 +0100 Fix a compilation warning in pgtkterm.c * src/pgtkterm.c (set_fullscreen_state): Fix a compilation warning (bug#52260). Copyright-paperwork-exempt: yes diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 278316268f..1fc8fa98a4 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4277,6 +4277,7 @@ set_fullscreen_state (struct frame *f) case FULLSCREEN_WIDTH: case FULLSCREEN_HEIGHT: /* Not supported by gtk. Ignore them. */ + break; } f->want_fullscreen = FULLSCREEN_NONE; commit 57a9bf8d4186878a59750e2f0bef3ca3b526e8ef Merge: f17d0dfb3e 1afa295aed Author: Po Lu Date: Fri Dec 3 14:07:40 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit f17d0dfb3e61b2b271e012b9b17aac657f6ee09f Author: Po Lu Date: Fri Dec 3 10:29:41 2021 +0800 Generate touch-end events on pgtk * src/pgtkterm.c (scroll_event): Generate touch end events. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 15d5fda105..278316268f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6008,6 +6008,13 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) XSETFRAME (inev.ie.frame_or_window, f); inev.ie.arg = Qnil; + if (gdk_event_is_scroll_stop_event (event)) + { + inev.ie.kind = TOUCH_END_EVENT; + evq_enqueue (&inev); + return TRUE; + } + if (gdk_event_get_scroll_direction (event, &dir)) { switch (dir) commit 054319e9fde42f211c23f6e3885f7e1fc6217caa Merge: 15d5af8cb0 67191f7eee Author: Po Lu Date: Fri Dec 3 10:26:50 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 15d5af8cb0969e43ead40e632126764c62a7317d Merge: 105c7562dc f5f5297a92 Author: Po Lu Date: Fri Dec 3 08:36:48 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 105c7562dc38de31cda6dfed00a1c260a6e72ea2 Author: Po Lu Date: Thu Dec 2 18:18:00 2021 +0800 Get rid of duplicate pgtk function * src/pgtkfns.c (Fpgtk_popup_font_panel): Remove function. (syms_of_pgtkfns): Get rid of removed subr. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index caf1cc65fb..4f1f9faa2c 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1840,44 +1840,6 @@ Some window managers may refuse to restack windows. */) return Qt; } -DEFUN ("pgtk-popup-font-panel", Fpgtk_popup_font_panel, Spgtk_popup_font_panel, - 0, 1, "", - doc: /* Pop up the font panel. */) - (Lisp_Object frame) -{ - struct frame *f = decode_window_system_frame (frame); - - Lisp_Object font; - Lisp_Object font_param; - char *default_name = NULL; - ptrdiff_t count = SPECPDL_INDEX (); - - block_input (); - - XSETFONT (font, FRAME_FONT (f)); - font_param = Ffont_get (font, QCname); - if (STRINGP (font_param)) - default_name = xlispstrdup (font_param); - else - { - font_param = Fframe_parameter (frame, Qfont_parameter); - if (STRINGP (font_param)) - default_name = xlispstrdup (font_param); - } - - font = xg_get_font (f, default_name); - xfree (default_name); - - unblock_input (); - - if (NILP (font)) - quit (); - - return unbind_to (count, font); -} - - - #ifdef HAVE_GSETTINGS #define RESOURCE_KEY_MAX_LEN 128 @@ -4047,7 +4009,6 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_frame_geometry); defsubr (&Spgtk_frame_edges); defsubr (&Spgtk_frame_restack); - defsubr (&Spgtk_popup_font_panel); defsubr (&Spgtk_set_mouse_absolute_pixel_position); defsubr (&Spgtk_mouse_absolute_pixel_position); defsubr (&Sx_display_mm_width); commit 4844aaac199de9af8da0a62b5ae92b1f5a7abb2c Author: Po Lu Date: Thu Dec 2 18:15:23 2021 +0800 Documentation fixes for pgtk port * doc/lispref/display.texi (Defining Faces): * doc/lispref/frames.texi (Multiple Terminals): Add references to the `pgtk' terminal type. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 80ef24b270..33e8f2f37e 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2785,8 +2785,8 @@ apply to. Here are the possible values of @var{characteristic}: The kind of window system the terminal uses---either @code{graphic} (any graphics-capable display), @code{x}, @code{pc} (for the MS-DOS console), @code{w32} (for MS Windows 9X/NT/2K/XP), @code{haiku} (for -Haiku), or @code{tty} (a non-graphics-capable display). -@xref{Window Systems, window-system}. +Haiku), @code{pgtk} (for GTK), or @code{tty} (a non-graphics-capable +display). @xref{Window Systems, window-system}. @item class What kinds of colors the terminal supports---either @code{color}, diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 923ff19997..1dfd0d4bfa 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -214,7 +214,7 @@ The terminal and keyboard coding systems used on the terminal. @item The kind of display associated with the terminal. This is the symbol returned by the function @code{terminal-live-p} (i.e., @code{x}, -@code{t}, @code{w32}, @code{ns}, @code{pc}, or @code{haiku}). +@code{t}, @code{w32}, @code{ns}, @code{pc}, @code{haiku}, or @code{pgtk}). @xref{Frames}. @item commit 7fa11be2fae2b9fa5981e01da05cb618859d77ca Author: Po Lu Date: Thu Dec 2 18:03:51 2021 +0800 Fix `menu-set-font' on pgtk * src/pgtkfns.c (Fx_select_font): New function. (syms_of_pgtkfns): Define new subr. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index afcb44f122..caf1cc65fb 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3908,6 +3908,52 @@ If omitted or nil, that stands for the selected frame's display. */) return build_string (type_name); } +DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0, + doc: /* Read a font using a GTK dialog and return a font spec. + +FRAME is the frame on which to pop up the font chooser. If omitted or +nil, it defaults to the selected frame. */) + (Lisp_Object frame, Lisp_Object ignored) +{ + struct frame *f = decode_window_system_frame (frame); + Lisp_Object font; + Lisp_Object font_param; + char *default_name = NULL; + ptrdiff_t count = SPECPDL_INDEX (); + + if (popup_activated ()) + error ("Trying to use a menu from within a menu-entry"); + else + pgtk_menu_set_in_use (true); + + /* Prevent redisplay. */ + specbind (Qinhibit_redisplay, Qt); + record_unwind_protect_void (clean_up_dialog); + + block_input (); + + XSETFONT (font, FRAME_FONT (f)); + font_param = Ffont_get (font, QCname); + if (STRINGP (font_param)) + default_name = xlispstrdup (font_param); + else + { + font_param = Fframe_parameter (frame, Qfont_parameter); + if (STRINGP (font_param)) + default_name = xlispstrdup (font_param); + } + + font = xg_get_font (f, default_name); + xfree (default_name); + + unblock_input (); + + if (NILP (font)) + quit (); + + return unbind_to (count, font); +} + /* ========================================================================== Lisp interface declaration @@ -4032,6 +4078,7 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_set_monitor_scale_factor); defsubr (&Sx_file_dialog); + defsubr (&Sx_select_font); as_status = 0; as_script = Qnil; commit 2f6b519eaeb3be4ee6a912b40a21686be12d4d88 Merge: 78a3933b62 3f98188b86 Author: Po Lu Date: Thu Dec 2 17:53:58 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 78a3933b62c1c83a6a4d54c9bc65faf069aa83dc Merge: 6e5c2fb468 01a6c0b409 Author: Po Lu Date: Thu Dec 2 09:21:11 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 6e5c2fb468de23649c6df8710ec483e712894d8f Author: Po Lu Date: Wed Dec 1 21:50:43 2021 +0800 Stop relying on `x_coalesce_scroll_events' in pgtk code * src/pgtkterm.c (scroll_event): Use `mwheel_coalesce_scroll_events'. (x_coalesce_scroll_events): Remove variable. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 190436a82d..15d5fda105 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6037,7 +6037,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) dpyinfo->scroll.acc_x += delta_x; dpyinfo->scroll.acc_y += delta_y; if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line - || !x_coalesce_scroll_events) + || !mwheel_coalesce_scroll_events) { int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; @@ -6045,7 +6045,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.arg = list3 (make_fixnum (nlines), make_float (-dpyinfo->scroll.acc_x * 100), make_float (-dpyinfo->scroll.acc_y * 100)); - if (!x_coalesce_scroll_events) + if (!mwheel_coalesce_scroll_events) { dpyinfo->scroll.acc_y = 0; dpyinfo->scroll.acc_x = 0; @@ -6056,7 +6056,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } } else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line - || !x_coalesce_scroll_events) + || !mwheel_coalesce_scroll_events) { int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; @@ -6065,7 +6065,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) make_float (-dpyinfo->scroll.acc_x * 100), make_float (-dpyinfo->scroll.acc_y * 100)); - if (!x_coalesce_scroll_events) + if (!mwheel_coalesce_scroll_events) { dpyinfo->scroll.acc_y = 0; dpyinfo->scroll.acc_x = 0; @@ -6074,7 +6074,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines; } else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char - || !x_coalesce_scroll_events) + || !mwheel_coalesce_scroll_events) { int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; @@ -6083,7 +6083,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) make_float (-dpyinfo->scroll.acc_x * 100), make_float (-dpyinfo->scroll.acc_y * 100)); - if (x_coalesce_scroll_events) + if (mwheel_coalesce_scroll_events) dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; else { @@ -6100,7 +6100,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) make_float (-dpyinfo->scroll.acc_x * 100), make_float (-dpyinfo->scroll.acc_y * 100)); - if (x_coalesce_scroll_events) + if (mwheel_coalesce_scroll_events) dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; else { @@ -6799,10 +6799,6 @@ If set to a non-float value, there will be no wait at all. */); window_being_scrolled = Qnil; staticpro (&window_being_scrolled); - DEFVAR_BOOL ("x-coalesce-scroll-events", x_coalesce_scroll_events, - doc: /* SKIP: real doc in xterm.c. */); - x_coalesce_scroll_events = true; - /* Tell Emacs about this window system. */ Fprovide (Qpgtk, Qnil); } commit 658085d0699a3e4402d3ad8513a5fa02a5138963 Merge: 5477b929da 3bc0768e9b Author: Po Lu Date: Wed Dec 1 21:50:02 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 5477b929da886c1aea70e1b2ac17b80df8d0015b Merge: b463dc8921 9fa15463bd Author: Po Lu Date: Wed Dec 1 15:20:08 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit b463dc8921aaebb429192fcb5b54743660483505 Author: Po Lu Date: Wed Dec 1 09:20:07 2021 +0800 Synchronize pgtk tab bar code with xterm * src/pgtkterm.c (x_draw_image_relief): (button_event): Synchronize code with xterm. (Bug#50779) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0e98c8a587..190436a82d 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1978,7 +1978,8 @@ x_draw_image_relief (struct glyph_string *s) /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p && s->slice.x == 0) + && s->first_glyph->left_box_line_p + && s->slice.x == 0) x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position @@ -1988,13 +1989,17 @@ x_draw_image_relief (struct glyph_string *s) if (s->slice.y == 0) y += s->img->vmargin; - if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) + if (s->hl == DRAW_IMAGE_SUNKEN + || s->hl == DRAW_IMAGE_RAISED) { - thick = (tab_bar_button_relief < 0 - ? DEFAULT_TAB_BAR_BUTTON_RELIEF - : (tool_bar_button_relief < 0 - ? DEFAULT_TOOL_BAR_BUTTON_RELIEF - : min (tool_bar_button_relief, 1000000))); + if (s->face->id == TAB_BAR_FACE_ID) + thick = (tab_bar_button_relief < 0 + ? DEFAULT_TAB_BAR_BUTTON_RELIEF + : min (tab_bar_button_relief, 1000000)); + else + thick = (tool_bar_button_relief < 0 + ? DEFAULT_TOOL_BAR_BUTTON_RELIEF + : min (tool_bar_button_relief, 1000000)); raised_p = s->hl == DRAW_IMAGE_RAISED; } else @@ -2013,23 +2018,23 @@ x_draw_image_relief (struct glyph_string *s) && FIXNUMP (XCAR (Vtab_bar_button_margin)) && FIXNUMP (XCDR (Vtab_bar_button_margin))) { - extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)); - extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)); + extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)) - thick; + extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)) - thick; } else if (FIXNUMP (Vtab_bar_button_margin)) - extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin); + extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin) - thick; } if (s->face->id == TOOL_BAR_FACE_ID) { if (CONSP (Vtool_bar_button_margin) - && INTEGERP (XCAR (Vtool_bar_button_margin)) - && INTEGERP (XCDR (Vtool_bar_button_margin))) + && FIXNUMP (XCAR (Vtool_bar_button_margin)) + && FIXNUMP (XCDR (Vtool_bar_button_margin))) { extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin)); extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin)); } - else if (INTEGERP (Vtool_bar_button_margin)) + else if (FIXNUMP (Vtool_bar_button_margin)) extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin); } @@ -5848,6 +5853,7 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) by the rest of Emacs, we put it here. */ bool tab_bar_p = false; bool tool_bar_p = false; + Lisp_Object tab_bar_arg = Qnil; EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; @@ -5914,8 +5920,8 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) window = window_from_coordinates (f, x, y, 0, true, true); tab_bar_p = EQ (window, f->tab_bar_window); - if (tab_bar_p && event->button.button < 4) - handle_tab_bar_click + if (tab_bar_p) + tab_bar_arg = handle_tab_bar_click (f, x, y, event->type == GDK_BUTTON_PRESS, pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state)); } @@ -5923,7 +5929,7 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) if (f) { - if (!tab_bar_p && !tool_bar_p) + if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p) { if (ignore_next_mouse_click_timeout) { @@ -5938,6 +5944,9 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } else construct_mouse_click (&inev.ie, &event->button, f); + + if (!NILP (tab_bar_arg)) + inev.ie.arg = tab_bar_arg; } #if 0 if (FRAME_X_EMBEDDED_P (f)) commit 3005c00b13e45feb387cc9ab71a68d6c301fe63e Merge: c3a440e520 aa0162ddfa Author: Po Lu Date: Wed Dec 1 09:05:07 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit c3a440e520d661e0296a7ac2d97abc5e9cd65712 Author: Po Lu Date: Tue Nov 30 19:35:36 2021 +0800 Calculate pixel deltas correctly * src/pgtkterm.c (scroll_event): Fix scroll delta factor. (bug#52195) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 98143585cf..0e98c8a587 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6034,8 +6034,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= down_modifier; inev.ie.arg = list3 (make_fixnum (nlines), - make_float (-dpyinfo->scroll.acc_x * 10), - make_float (-dpyinfo->scroll.acc_y * 10)); + make_float (-dpyinfo->scroll.acc_x * 100), + make_float (-dpyinfo->scroll.acc_y * 100)); if (!x_coalesce_scroll_events) { dpyinfo->scroll.acc_y = 0; @@ -6053,8 +6053,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= up_modifier; inev.ie.arg = list3 (make_fixnum (nlines), - make_float (-dpyinfo->scroll.acc_x * 10), - make_float (-dpyinfo->scroll.acc_y * 10)); + make_float (-dpyinfo->scroll.acc_x * 100), + make_float (-dpyinfo->scroll.acc_y * 100)); if (!x_coalesce_scroll_events) { @@ -6071,8 +6071,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= up_modifier; inev.ie.arg = list3 (make_fixnum (nchars), - make_float (-dpyinfo->scroll.acc_x * 10), - make_float (-dpyinfo->scroll.acc_y * 10)); + make_float (-dpyinfo->scroll.acc_x * 100), + make_float (-dpyinfo->scroll.acc_y * 100)); if (x_coalesce_scroll_events) dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; @@ -6088,8 +6088,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= down_modifier; inev.ie.arg = list3 (make_fixnum (nchars), - make_float (-dpyinfo->scroll.acc_x * 10), - make_float (-dpyinfo->scroll.acc_y * 10)); + make_float (-dpyinfo->scroll.acc_x * 100), + make_float (-dpyinfo->scroll.acc_y * 100)); if (x_coalesce_scroll_events) dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; commit 9fe993371ba696d2ec3cdfd152b433ffbee79565 Merge: fe5baf0a10 f633116c09 Author: Po Lu Date: Tue Nov 30 19:31:38 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit fe5baf0a101fc880ef253a302d584f240cde51b7 Merge: 4beecd8e8c 4e2fa4c34b Author: Po Lu Date: Tue Nov 30 15:57:33 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 4beecd8e8cadc70b72f77d4ab202734f1d99eeb0 Merge: 72d223a544 f3bb2b80b4 Author: Po Lu Date: Tue Nov 30 13:56:32 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 72d223a5445831d681a1fbc6f23370cef5252cd3 Author: Po Lu Date: Tue Nov 30 13:55:16 2021 +0800 Enable shallow menu bar updates on PGTK * src/gtkutil.c (menu_bar_button_pressed_cb): New function. (create_menus): Connect button press event signal. * src/pgtkmenu.c (set_frame_menubar): Allow shallow updates. diff --git a/src/gtkutil.c b/src/gtkutil.c index c2b33912ef..d872d393ca 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -3141,6 +3141,20 @@ xg_create_one_menuitem (widget_value *item, return w; } +#ifdef HAVE_PGTK +static gboolean +menu_bar_button_pressed_cb (GtkWidget *widget, GdkEvent *event, + gpointer user_data) +{ + struct frame *f = user_data; + + if (event->button.button < 4) + set_frame_menubar (f, true); + + return false; +} +#endif + /* Create a full menu tree specified by DATA. F is the frame the created menu belongs to. SELECT_CB is the callback to use when a menu item is selected. @@ -3198,6 +3212,10 @@ create_menus (widget_value *data, else { wmenu = gtk_menu_bar_new (); +#ifdef HAVE_PGTK + g_signal_connect (G_OBJECT (wmenu), "button-press-event", + G_CALLBACK (menu_bar_button_pressed_cb), f); +#endif /* Set width of menu bar to a small value so it doesn't enlarge a small initial frame size. The width will be set to the width of the frame later on when it is added to a container. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 88020c3044..6f8f8720de 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -297,10 +297,6 @@ set_frame_menubar (struct frame *f, bool deep_p) if (!menubar_widget) deep_p = true; - /* Since button_event handler in pgtk emacs doesn't handle mouse - * events in menubars, the menu needs to be built now. */ - deep_p = true; - if (deep_p) { struct buffer *prev = current_buffer; commit b3277883f35c5ac9980b4ef05dc99fa8b5ce6792 Author: Po Lu Date: Tue Nov 30 09:34:24 2021 +0800 Make interrupt input optionally work on PGTK * src/pgtkterm.c (pgtk_delete_terminal): Close display fd if it exists. (pgtk_term_init): Set up interrupt handling for display fd if available. * src/pgtkterm.h (struct pgtk_display_info): Add `connection' field. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d9b2e385fc..98143585cf 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -63,6 +63,10 @@ along with GNU Emacs. If not, see . */ #include "pgtkselect.h" #include "emacsgtkfixed.h" +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) #define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) @@ -4320,6 +4324,11 @@ pgtk_delete_terminal (struct terminal *terminal) dpyinfo->gdpy = NULL; } + if (dpyinfo->connection >= 0) + emacs_close (dpyinfo->connection); + + dpyinfo->connection = -1; + delete_keyboard_wait_descriptor (0); pgtk_delete_display (dpyinfo); @@ -6285,6 +6294,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) static int x_initialized = 0; static unsigned x_display_id = 0; static char *initial_display = NULL; + static dynlib_handle_ptr *handle = NULL; char *dpy_name; Lisp_Object lisp_dpy_name = Qnil; @@ -6456,6 +6466,49 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->scroll.x_per_char = 2; dpyinfo->scroll.y_per_line = 2; + dpyinfo->connection = -1; + + if (!handle) + handle = dynlib_open (NULL); + +#ifdef GDK_WINDOWING_X11 + if (!strcmp (G_OBJECT_TYPE_NAME (dpy), "GdkX11Display") && handle) + { + void *(*gdk_x11_display_get_xdisplay) (GdkDisplay *) + = dynlib_sym (handle, "gdk_x11_display_get_xdisplay"); + int (*x_connection_number) (void *) + = dynlib_sym (handle, "XConnectionNumber"); + + if (x_connection_number + && gdk_x11_display_get_xdisplay) + dpyinfo->connection + = x_connection_number (gdk_x11_display_get_xdisplay (dpy)); + } +#endif + +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (dpy) && handle) + { + struct wl_display *wl_dpy = gdk_wayland_display_get_wl_display (dpy); + int (*display_get_fd) (struct wl_display *) + = dynlib_sym (handle, "wl_display_get_fd"); + + if (display_get_fd) + dpyinfo->connection = display_get_fd (wl_dpy); + } +#endif + + if (dpyinfo->connection >= 0) + { + add_keyboard_wait_descriptor (dpyinfo->connection); +#ifdef F_SETOWN + fcntl (dpyinfo->connection, F_SETOWN, getpid ()); +#endif /* ! defined (F_SETOWN) */ + + if (interrupt_input) + init_sigio (dpyinfo->connection); + } + x_setup_pointer_blanking (dpyinfo); xsettings_initialize (dpyinfo); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 231c8e8706..c16221da83 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -238,6 +238,8 @@ struct pgtk_display_info double acc_x, acc_y; double x_per_char, y_per_line; } scroll; + + int connection; }; /* This is a chain of structures for all the PGTK displays currently in use. */ commit d15dafeefb58fc521186385a1a703f7f660f2f6b Author: Po Lu Date: Tue Nov 30 09:11:42 2021 +0800 Stop setting mouse face GC manually, as it is no longer required * src/pgtkterm.c (x_set_mouse_face_gc): Remove obsolete code. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 8353a9ca4d..d9b2e385fc 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1007,20 +1007,6 @@ x_set_cursor_gc (struct glyph_string *s) static void x_set_mouse_face_gc (struct glyph_string *s) { - int face_id; - struct face *face; - - /* What face has to be used last for the mouse face? */ - face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id; - face = FACE_FROM_ID_OR_NULL (s->f, face_id); - if (face == NULL) - face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); - - if (s->first_glyph->type == CHAR_GLYPH) - face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil); - else - face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); - s->face = FACE_FROM_ID (s->f, face_id); prepare_face_for_display (s->f, s->face); if (s->font == s->face->font) commit afff603778ba17ca13d4cc7b95fee54569d4c640 Author: Po Lu Date: Tue Nov 30 09:03:31 2021 +0800 Add missing function declarations to pgtk-win.el * lisp/term/pgtk-win.el: Add missing IM context related declarations. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 3df450070c..689a5e595a 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -51,6 +51,9 @@ ;; pgtkterm.c. (defvar pgtk-input-file) +(declare-function pgtk-use-im-context "pgtkim.c") +(defvar pgtk-use-im-context-on-new-connection) + (defun pgtk-handle-nxopen (_switch &optional temp) (setq unread-command-events (append unread-command-events (if temp '(pgtk-open-temp-file) commit faa593ac5dde459c48116c167a938f5e7af602df Author: Po Lu Date: Tue Nov 30 09:01:26 2021 +0800 Enable pixel-precision scrolling on pgtk port * src/pgtkterm.c (scroll_event): Generate enhanced wheel events. (x_coalesce_scroll_events): New variable. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f7aadec321..8353a9ca4d 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6032,37 +6032,77 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { dpyinfo->scroll.acc_x += delta_x; dpyinfo->scroll.acc_y += delta_y; - if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line) + if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line + || !x_coalesce_scroll_events) { int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= down_modifier; - inev.ie.arg = make_fixnum (nlines); - dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines; + inev.ie.arg = list3 (make_fixnum (nlines), + make_float (-dpyinfo->scroll.acc_x * 10), + make_float (-dpyinfo->scroll.acc_y * 10)); + if (!x_coalesce_scroll_events) + { + dpyinfo->scroll.acc_y = 0; + dpyinfo->scroll.acc_x = 0; + } + else + { + dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines; + } } - else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line) + else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line + || !x_coalesce_scroll_events) { int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - inev.ie.arg = make_fixnum (nlines); - dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines; + inev.ie.arg = list3 (make_fixnum (nlines), + make_float (-dpyinfo->scroll.acc_x * 10), + make_float (-dpyinfo->scroll.acc_y * 10)); + + if (!x_coalesce_scroll_events) + { + dpyinfo->scroll.acc_y = 0; + dpyinfo->scroll.acc_x = 0; + } + else + dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines; } - else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char) + else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char + || !x_coalesce_scroll_events) { int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - inev.ie.arg = make_fixnum (nchars); - dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; + inev.ie.arg = list3 (make_fixnum (nchars), + make_float (-dpyinfo->scroll.acc_x * 10), + make_float (-dpyinfo->scroll.acc_y * 10)); + + if (x_coalesce_scroll_events) + dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; + else + { + dpyinfo->scroll.acc_x = 0; + dpyinfo->scroll.acc_y = 0; + } } else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char) { int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= down_modifier; - inev.ie.arg = make_fixnum (nchars); - dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; + inev.ie.arg = list3 (make_fixnum (nchars), + make_float (-dpyinfo->scroll.acc_x * 10), + make_float (-dpyinfo->scroll.acc_y * 10)); + + if (x_coalesce_scroll_events) + dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; + else + { + dpyinfo->scroll.acc_x = 0; + dpyinfo->scroll.acc_y = 0; + } } } @@ -6711,6 +6751,10 @@ If set to a non-float value, there will be no wait at all. */); window_being_scrolled = Qnil; staticpro (&window_being_scrolled); + DEFVAR_BOOL ("x-coalesce-scroll-events", x_coalesce_scroll_events, + doc: /* SKIP: real doc in xterm.c. */); + x_coalesce_scroll_events = true; + /* Tell Emacs about this window system. */ Fprovide (Qpgtk, Qnil); } commit 105205c86bc082eb73b15d6329745e3629ab9431 Author: Po Lu Date: Tue Nov 30 08:52:00 2021 +0800 Get rid of pgtk_select and use xg_select instead * src/pgtkmenu.c (pgtk_menu_wait_for_event): Get rid of pgtk_select. * src/pgtkterm.h (pgtk_select): * src/pgtkterm.c (pgtk_select): Delete function. * src/process.c (wait_reading_process_output): Stop using pgtk_select. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index b8f4619d7d..88020c3044 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -37,6 +37,7 @@ along with GNU Emacs. If not, see . */ #include "keyboard.h" #include "menu.h" #include "pdumper.h" +#include "xgselect.h" #include "gtkutil.h" #include @@ -82,7 +83,7 @@ pgtk_menu_wait_for_event (void *data) /* Gtk3 have arrows on menus when they don't fit. When the pointer is over an arrow, a timeout scrolls it a bit. Use xg_select so that timeout gets triggered. */ - pgtk_select (0, NULL, NULL, NULL, ntp, NULL); + xg_select (0, NULL, NULL, NULL, ntp, NULL); } DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 27b7ccabb4..f7aadec321 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3700,173 +3700,6 @@ pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) return 0; } -int -pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, - struct timespec *timeout, sigset_t * sigmask) -{ - fd_set all_rfds, all_wfds; - struct timespec tmo; - struct timespec *tmop = timeout; - - GMainContext *context; - bool have_wfds = wfds != NULL; - GPollFD gfds_buf[128]; - GPollFD *gfds = gfds_buf; - int gfds_size = ARRAYELTS (gfds_buf); - int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; - bool context_acquired = false; - int i, nfds, tmo_in_millisec, must_free = 0; - bool need_to_dispatch; - - if (event_q.nr >= 1) - { - raise (SIGIO); - errno = EINTR; - return -1; - } - - context = g_main_context_default (); - context_acquired = g_main_context_acquire (context); - /* FIXME: If we couldn't acquire the context, we just silently proceed - because this function handles more than just glib file descriptors. - Note that, as implemented, this failure is completely silent: there is - no feedback to the caller. */ - - /* Before sleep, dispatch draw events. - * Don't do this after g_main_context_query(), because fd may be closed - * in dispatch. - */ - if (context_acquired) - { - int pselect_errno = errno; - block_input (); - while (g_main_context_pending (context)) - g_main_context_dispatch (context); - unblock_input (); - errno = pselect_errno; - } - - if (rfds) - all_rfds = *rfds; - else - FD_ZERO (&all_rfds); - if (wfds) - all_wfds = *wfds; - else - FD_ZERO (&all_wfds); - - n_gfds = (context_acquired - ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, - gfds, gfds_size) : -1); - - if (gfds_size < n_gfds) - { - /* Avoid using SAFE_NALLOCA, as that implicitly refers to the - current thread. Using xnmalloc avoids thread-switching - problems here. */ - gfds = xnmalloc (n_gfds, sizeof *gfds); - must_free = 1; - gfds_size = n_gfds; - n_gfds = - g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, - gfds_size); - } - - for (i = 0; i < n_gfds; ++i) - { - if (gfds[i].events & G_IO_IN) - { - FD_SET (gfds[i].fd, &all_rfds); - if (gfds[i].fd > max_fds) - max_fds = gfds[i].fd; - } - if (gfds[i].events & G_IO_OUT) - { - FD_SET (gfds[i].fd, &all_wfds); - if (gfds[i].fd > max_fds) - max_fds = gfds[i].fd; - have_wfds = true; - } - } - - if (must_free) - xfree (gfds); - - if (n_gfds >= 0 && tmo_in_millisec >= 0) - { - tmo = make_timespec (tmo_in_millisec / 1000, - 1000 * 1000 * (tmo_in_millisec % 1000)); - if (!timeout || timespec_cmp (tmo, *timeout) < 0) - tmop = &tmo; - } - - fds_lim = max_fds + 1; - nfds = thread_select (pselect, fds_lim, - &all_rfds, have_wfds ? &all_wfds : NULL, efds, - tmop, sigmask); - if (nfds < 0) - retval = nfds; - else if (nfds > 0) - { - for (i = 0; i < fds_lim; ++i) - { - if (FD_ISSET (i, &all_rfds)) - { - if (rfds && FD_ISSET (i, rfds)) - ++retval; - else - ++our_fds; - } - else if (rfds) - FD_CLR (i, rfds); - - if (have_wfds && FD_ISSET (i, &all_wfds)) - { - if (wfds && FD_ISSET (i, wfds)) - ++retval; - else - ++our_fds; - } - else if (wfds) - FD_CLR (i, wfds); - - if (efds && FD_ISSET (i, efds)) - ++retval; - } - } - - /* If Gtk+ is in use eventually gtk_main_iteration will be called, - unless retval is zero. */ - need_to_dispatch = retval == 0; - if (need_to_dispatch && context_acquired) - { - int pselect_errno = errno; - /* Prevent g_main_dispatch recursion, that would occur without - block_input wrapper, because event handlers call - unblock_input. Event loop recursion was causing Bug#15801. */ - block_input (); - while (g_main_context_pending (context)) - { - g_main_context_dispatch (context); - } - unblock_input (); - errno = pselect_errno; - } - - if (context_acquired) - g_main_context_release (context); - - /* To not have to recalculate timeout, return like this. */ - if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) - { - retval = -1; - errno = EINTR; - } - - return retval; -} - - /* Lisp window being scrolled. Set when starting to interact with a toolkit scroll bar, reset to nil when ending the interaction. */ diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 635c5e6a61..231c8e8706 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -571,9 +571,6 @@ extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); extern void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); -extern int pgtk_select (int nfds, fd_set * readfds, fd_set * writefds, - fd_set * exceptfds, struct timespec *timeout, - sigset_t * sigmask); /* Cairo related functions implemented in pgtkterm.c */ extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int); diff --git a/src/process.c b/src/process.c index eb27ddef45..241ffe9a8d 100644 --- a/src/process.c +++ b/src/process.c @@ -5588,19 +5588,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, timeout = make_timespec (0, 0); #endif -#if defined HAVE_PGTK - nfds = pgtk_select (max_desc + 1, - &Available, (check_write ? &Writeok : 0), - NULL, &timeout, NULL); -#elif !defined USABLE_SIGIO && !defined WINDOWSNT +#if !defined USABLE_SIGIO && !defined WINDOWSNT /* If we're polling for input, don't get stuck in select for more than 25 msec. */ struct timespec short_timeout = make_timespec (0, 25000000); if ((read_kbd || !NILP (wait_for_cell)) && timespec_cmp (short_timeout, timeout) < 0) timeout = short_timeout; -#elif defined HAVE_GLIB && !defined HAVE_NS +#endif + /* Non-macOS HAVE_GLIB builds call thread_select in xgselect.c. */ +#if defined HAVE_GLIB && !defined HAVE_NS nfds = xg_select (max_desc + 1, &Available, (check_write ? &Writeok : 0), NULL, &timeout, NULL); commit 127be1e8b3916279fb402f18aa63eeefb432f539 Author: Po Lu Date: Tue Nov 30 08:46:23 2021 +0800 * lisp/frame.el (display-graphic-p): Fix typo. diff --git a/lisp/frame.el b/lisp/frame.el index c9306ec46d..f790fa13ab 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2119,7 +2119,7 @@ frames and several different fonts at once. This is true for displays that use a window system such as X, and false for text-only terminals. DISPLAY can be a display name, a frame, or nil (meaning the selected frame's display)." - (not (null (memq (framep-on-display display) '(x w32 ns haiku haiku))))) + (not (null (memq (framep-on-display display) '(x w32 ns pgtk haiku))))) (defun display-images-p (&optional display) "Return non-nil if DISPLAY can display images. commit 66b5f5a87263030dd4a8d13080dea68afdb6c3e4 Author: Po Lu Date: Tue Nov 30 08:33:24 2021 +0800 Fix build after merge * lisp/mwheel.el (mouse-wheel-up-event): * src/gtkutil.c (xg_event_is_for_scrollbar): * src/termhooks.h (enum output_method): Fix trivial typos. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index d04139d148..3458fb6d84 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -77,7 +77,7 @@ (defcustom mouse-wheel-up-event (if (or (featurep 'w32-win) (featurep 'ns-win) - (featurep 'haiku-win) (feautrep 'pgtk-win)) + (featurep 'haiku-win) (featurep 'pgtk-win)) 'wheel-down 'mouse-5) "Event used for scrolling up." diff --git a/src/gtkutil.c b/src/gtkutil.c index 0574d5691b..c2b33912ef 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -4793,7 +4793,6 @@ xg_event_is_for_scrollbar (struct frame *f, const EVENT *event) || event->type == GDK_MOTION_NOTIFY) #endif ) - || event->type == MotionNotify)) #endif /* HAVE_XINPUT2 */ { /* If we are releasing or moving the scroll bar, it has the grab. */ diff --git a/src/termhooks.h b/src/termhooks.h index f0c3ffd57b..649a4236d2 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -61,7 +61,7 @@ enum output_method output_msdos_raw, output_w32, output_ns, - output_pgtk + output_pgtk, output_haiku }; commit 194c299470e087aeeff5c496c7dfc6400e1185a7 Merge: 8f5d2a3181 7d8f0c0586 Author: Po Lu Date: Tue Nov 30 08:19:46 2021 +0800 Merge remote-tracking branch 'origin/feature/pgtk' into feature/pgtk commit 8f5d2a3181d22f858ede3fb6a1452f99272901fe Merge: 901938109f d8dd705e9d Author: Po Lu Date: Tue Nov 30 08:16:50 2021 +0800 Merge remote-tracking branch 'origin/master' into feature/pgtk commit 7d8f0c0586dbbf630ee6e683c1fe5d8d4ab8d1bb Author: Yuuki Harano Date: Tue Nov 30 00:23:39 2021 +0900 * src/xdisp.c (mouse_face_from_buffer_pos): Revert whitespace only change diff --git a/src/xdisp.c b/src/xdisp.c index 690cace6e5..e40e605d52 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -32953,7 +32953,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, hlinfo->mouse_face_face_id = face_at_buffer_position (w, mouse_charpos, &ignore, mouse_charpos + 1, - !hlinfo->mouse_face_hidden, -1, 0); + !hlinfo->mouse_face_hidden, -1, 0); show_mouse_face (hlinfo, DRAW_MOUSE_FACE); } commit 92cd274ba82b142271d7884795b5f6e9033ab4f9 Author: Yuuki Harano Date: Tue Nov 30 00:19:22 2021 +0900 Remove draw_glyphs_debug It is left-over from debugging, and not needed any more. * src/xdisp.c (draw_glyphs_debug): (draw_glyphs): diff --git a/src/xdisp.c b/src/xdisp.c index 5b67bcf5dc..690cace6e5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -29341,16 +29341,6 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, return x_reached; } -static int draw_glyphs_debug (const char *file, int lineno, - struct window *w, int x, struct glyph_row *row, - enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end, - enum draw_glyphs_face hl, int overlaps) -{ - return draw_glyphs(w, x, row, area, start, end, hl, overlaps); -} -#define draw_glyphs(w, x, r, a, s, e, h, o) \ - draw_glyphs_debug (__FILE__, __LINE__, w, x, r, a, s, e, h, o) - /* Find the first glyph in the run of underlined glyphs preceding the beginning of glyph string S, and return its font (which could be NULL). This is needed because that font determines the underline commit 073111cc7755bc5ac685936f5e738a4dbae7ef61 Author: Yuuki Harano Date: Tue Nov 30 00:14:42 2021 +0900 Replace XFillRectangle with cairo_rectangle and cairo_fill * src/pgtkterm.c (pgtk_flash): diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d6103d4f15..27b7ccabb4 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3578,9 +3578,6 @@ pgtk_flash (struct frame *f) cairo_set_source_rgb (cr, 1, 1, 1); cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); -#define XFillRectangle(d, win, gc, x, y, w, h) \ - ( cairo_rectangle (cr, x, y, w, h), cairo_fill (cr) ) - { /* Get the height not including a menu bar widget. */ int height = FRAME_PIXEL_HEIGHT (f); @@ -3595,23 +3592,28 @@ pgtk_flash (struct frame *f) /* If window is tall, flash top and bottom line. */ if (height > 3 * FRAME_LINE_HEIGHT (f)) { - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, - flash_left, - (FRAME_INTERNAL_BORDER_WIDTH (f) - + FRAME_TOP_MARGIN_HEIGHT (f)), - width, flash_height); - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, - flash_left, - (height - flash_height - - FRAME_INTERNAL_BORDER_WIDTH (f)), - width, flash_height); + cairo_rectangle (cr, + flash_left, + (FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_TOP_MARGIN_HEIGHT (f)), + width, flash_height); + cairo_fill (cr); + cairo_rectangle (cr, + flash_left, + (height - flash_height + - FRAME_INTERNAL_BORDER_WIDTH (f)), + width, flash_height); + cairo_fill (cr); } else - /* If it is short, flash it all. */ - XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, - flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), - width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + { + /* If it is short, flash it all. */ + cairo_rectangle (cr, + flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), + width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + cairo_fill (cr); + } FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface; { @@ -3625,7 +3627,6 @@ pgtk_flash (struct frame *f) start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f); } -#undef XFillRectangle } cairo_destroy (cr); commit 3b8e122bc7afc0830c6bb353e81a0face0d10746 Author: Yuuki Harano Date: Tue Nov 30 00:07:18 2021 +0900 Use /* */ comment style instead of // * src/gtkutil.c (xg_create_frame_widgets): * src/pgtkfns.c (Fx_create_frame): (frame_geometry): * src/pgtkterm.c (pgtk_mouse_position): (pgtk_redisplay_interface): (pgtk_clear_frame): (pgtk_create_terminal): (struct pgtk_window_is_of_frame_recursive_t): (key_press_event): (syms_of_pgtkterm): diff --git a/src/gtkutil.c b/src/gtkutil.c index d4823f813b..d15caf044f 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1407,7 +1407,7 @@ xg_create_frame_widgets (struct frame *f) block_input (); -#ifndef HAVE_PGTK // gtk_plug not found. +#ifndef HAVE_PGTK /* gtk_plug not found. */ if (FRAME_X_EMBEDDED_P (f)) { GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 339d6dd45a..afcb44f122 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1602,7 +1602,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) #endif /* Create the X widget or window. */ - // x_window (f); + /* x_window (f); */ xg_create_frame_widgets (f); pgtk_set_event_handler (f); @@ -3591,7 +3591,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) tab_bar_height = FRAME_TAB_BAR_HEIGHT (f); tab_bar_width = (tab_bar_height ? native_width - 2 * internal_border_width : 0); - // inner_top += tab_bar_height; + /* inner_top += tab_bar_height; */ /* Construct list. */ if (EQ (attribute, Qouter_edges)) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0c286ca151..d6103d4f15 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3218,7 +3218,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, f1 = pgtk_any_window_to_frame (win); else { - // crossing display server? + /* crossing display server? */ f1 = SELECTED_FRAME (); } } @@ -3488,8 +3488,8 @@ static struct redisplay_interface pgtk_redisplay_interface = { gui_clear_end_of_line, pgtk_scroll_run, pgtk_after_update_window_line, - NULL, // gui_update_window_begin, - NULL, // gui_update_window_end, + NULL, /* gui_update_window_begin, */ + NULL, /* gui_update_window_end, */ pgtk_flush_display, gui_clear_window_mouse_face, gui_get_glyph_overhangs, @@ -3505,7 +3505,7 @@ static struct redisplay_interface pgtk_redisplay_interface = { pgtk_draw_window_cursor, pgtk_draw_vertical_window_border, pgtk_draw_window_divider, - NULL, // pgtk_shift_glyphs_for_insert, + NULL, /* pgtk_shift_glyphs_for_insert, */ pgtk_show_hourglass, pgtk_hide_hourglass, pgtk_default_font_parameter, @@ -3527,7 +3527,7 @@ pgtk_clear_frame (struct frame *f) if (!FRAME_DEFAULT_FACE (f)) return; - // mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); + /* mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); */ block_input (); @@ -4794,10 +4794,10 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->update_begin_hook = pgtk_update_begin; terminal->update_end_hook = pgtk_update_end; terminal->read_socket_hook = pgtk_read_socket; - // terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; + /* terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; */ terminal->mouse_position_hook = pgtk_mouse_position; terminal->frame_rehighlight_hook = XTframe_rehighlight; - // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; + /* terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; */ terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; terminal->fullscreen_hook = pgtk_fullscreen_hook; terminal->menu_show_hook = pgtk_menu_show; @@ -4838,7 +4838,7 @@ struct pgtk_window_is_of_frame_recursive_t { GdkWindow *window; bool result; - GtkWidget *emacs_gtk_fixed; // stop on emacsgtkfixed other than this. + GtkWidget *emacs_gtk_fixed; /* stop on emacsgtkfixed other than this. */ }; static void @@ -5487,7 +5487,7 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) evq_enqueue (&inev); } - // count += nchars; + /* count += nchars; */ inev.ie.kind = NO_EVENT; /* Already stored above. */ @@ -5501,7 +5501,7 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { XSETFRAME (inev.ie.frame_or_window, f); evq_enqueue (&inev); - // count++; + /* count++; */ } SAFE_FREE (); @@ -6831,7 +6831,7 @@ A value of nil means Emacs doesn't use toolkit scroll bars. With the X Window system, the value is a symbol describing the X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. With MS Windows or Nextstep, the value is t. */ ); - // Vx_toolkit_scroll_bars = Qt; + /* Vx_toolkit_scroll_bars = Qt; */ Vx_toolkit_scroll_bars = intern_c_string ("gtk"); DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties, commit 901938109f7b5574e97e787bee10441086680de8 Author: Yuuki Harano Date: Wed Nov 24 00:32:57 2021 +0900 Remove PGTK_DEBUG stuff * src/gtkutil.c: (xg_create_frame_widgets): (xg_create_frame_outer_widgets): (x_wm_set_size_hint): (xg_set_toolkit_scroll_bar_thumb): * src/pgtkfns.c (x_set_background_color): (pgtk_set_name): (x_explicitly_set_name): (pgtk_implicitly_set_name): (x_set_title): (Fx_create_frame): (Fpgtk_set_mouse_absolute_pixel_position): (pgtk_log): (pgtk_backtrace): * src/pgtkselect.c (get_func): (clear_func): (pgtk_selection_lost): (Fpgtk_own_selection_internal): (Fpgtk_disown_selection_internal): (Fpgtk_selection_exists_p): (Fpgtk_selection_owner_p): (nxatoms_of_pgtkselect): (syms_of_pgtkselect): * src/pgtkterm.c (flip_cr_context): (get_keysym_name): (frame_set_mouse_pixel_position): (x_free_frame_resources): (x_destroy_window): (x_set_offset): (pgtk_set_window_size): (pgtk_iconify_frame): (pgtk_make_frame_visible): (pgtk_make_frame_invisible): (pgtk_new_font): (x_display_pixel_height): (x_display_pixel_width): (x_set_no_focus_on_map): (x_set_no_accept_focus): (x_set_z_group): (x_set_cursor_gc): (x_set_glyph_string_gc): (x_set_glyph_string_clipping): (x_draw_glyph_string_background): (pgtk_draw_glyph_string): (pgtk_after_update_window_line): (pgtk_clear_frame_area): (pgtk_draw_window_cursor): (pgtk_copy_bits): (pgtk_cr_draw_image): (pgtk_draw_fringe_bitmap): (pgtk_redraw_scroll_bars): (pgtk_clear_frame): (pgtk_read_socket): (pgtk_select): (xg_scroll_callback): (xg_end_scroll_callback): (pgtk_set_vertical_scroll_bar): (set_fullscreen_state): (pgtk_fullscreen_hook): (pgtk_handle_event): (pgtk_fill_rectangle): (pgtk_clear_under_internal_border): (print_widget_tree_recursive): (print_widget_tree): (pgtk_handle_draw): (size_allocate): (key_press_event): (key_release_event): (map_event): (delete_event): (enter_notify_event): (leave_notify_event): (focus_in_event): (focus_out_event): (motion_notify_event): (button_event): (scroll_event): (drag_data_received): (pgtk_xlfd_to_fontname): (pgtk_defined_color): (pgtk_parse_color): (pgtk_query_colors): (pgtk_query_color): (pgtk_clear_area): (pgtk_cr_update_surface_desired_size): (pgtk_begin_cr_clip): (pgtk_end_cr_clip): (pgtk_set_cr_source_with_gc_foreground): (pgtk_set_cr_source_with_gc_background): (pgtk_set_cr_source_with_color): (pgtk_cr_draw_frame): (pgtk_cr_destroy_frame_context): * src/pgtkterm.h: diff --git a/src/gtkutil.c b/src/gtkutil.c index cb33474711..d4823f813b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -51,9 +51,6 @@ typedef struct pgtk_output xp_output; #include "termhooks.h" #include "keyboard.h" #include "coding.h" -#ifndef PGTK_TRACE -#define PGTK_TRACE(fmt, ...) ((void) 0) -#endif #include @@ -1408,7 +1405,6 @@ xg_create_frame_widgets (struct frame *f) GtkWindowType type = GTK_WINDOW_TOPLEVEL; char *title = 0; - PGTK_TRACE ("xg_create_frame_widgets."); block_input (); #ifndef HAVE_PGTK // gtk_plug not found. @@ -1622,7 +1618,6 @@ xg_create_frame_outer_widgets (struct frame *f) GtkWindowType type = GTK_WINDOW_TOPLEVEL; char *title = 0; - PGTK_TRACE ("xg_create_frame_outer_widgets."); block_input (); wtop = gtk_window_new (type); @@ -1814,7 +1809,6 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 1) + FRAME_TOOLBAR_WIDTH (f); base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); - PGTK_TRACE ("base: %dx%d\n", base_width, base_height); size_hints.base_width = base_width; size_hints.base_height = base_height; @@ -4569,8 +4563,6 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: ----------------------------------"); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: %p, %d, %d, %d.", bar, portion, position, whole); if (wscroll && bar->dragging == -1) { GtkAdjustment *adj; @@ -4602,26 +4594,17 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, top = (gdouble) position / whole; shown = (gdouble) portion / whole; } - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: position=%d, portion=%d, whole=%d", position, portion, whole); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: top=%f, shown=%f", top, shown); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: shown*range=%f", shown * XG_SB_RANGE); size = clip_to_bounds (1, shown * XG_SB_RANGE, XG_SB_RANGE); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: size=%d.", size); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: top*range=%f.", top * XG_SB_RANGE); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: max-size=%d.", XG_SB_MAX - size); value = clip_to_bounds (XG_SB_MIN, top * XG_SB_RANGE, XG_SB_MAX - size); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: value=%d.", value); /* Assume all lines are of equal size. */ new_step = size / max (1, FRAME_LINES (f)); old_size = gtk_adjustment_get_page_size (adj); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: old_size=%d, size=%d", old_size, size); if (old_size != size) { int old_step = gtk_adjustment_get_step_increment (adj); - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: old_step=%d, new_step=%d", old_step, new_step); if (old_step != new_step) { gtk_adjustment_set_page_size (adj, size); @@ -4632,8 +4615,6 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, } } - PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: changed=%d, old=%d, value=%d.", - changed, int_gtk_range_get_value (GTK_RANGE (wscroll)), value); if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value) { block_input (); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 3c2ea02831..339d6dd45a 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -222,13 +222,11 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (FRAME_VISIBLE_P (f)) pgtk_clear_frame (f); - PGTK_TRACE ("x_set_background_color: col.pixel=%08lx.", bg); FRAME_X_OUTPUT (f)->background_color = bg; xg_set_background_color (f, bg); update_face_from_frame_parameter (f, Qbackground_color, arg); - PGTK_TRACE ("visible_p=%d.", FRAME_VISIBLE_P (f)); if (FRAME_VISIBLE_P (f)) SET_FRAME_GARBAGED (f); } @@ -311,8 +309,6 @@ pgtk_set_name_internal (struct frame *f, Lisp_Object name) static void pgtk_set_name (struct frame *f, Lisp_Object name, int explicit) { - PGTK_TRACE ("pgtk_set_name"); - /* Make sure that requests from lisp code override requests from Emacs redisplay code. */ if (explicit) @@ -352,7 +348,6 @@ pgtk_set_name (struct frame *f, Lisp_Object name, int explicit) static void x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - PGTK_TRACE ("x_explicitly_set_name"); pgtk_set_name (f, arg, true); } @@ -364,7 +359,6 @@ void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - PGTK_TRACE ("x_implicitly_set_name"); pgtk_set_name (f, arg, false); } @@ -375,7 +369,6 @@ pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, static void x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) { - PGTK_TRACE ("x_set_title"); /* Don't change the title if it's already NAME. */ if (EQ (name, f->title)) return; @@ -1670,7 +1663,6 @@ This function is an internal primitive--use `make-frame' instead. */ ) block_input (); - PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); GtkWidget *fixed = FRAME_GTK_WIDGET (f); GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p); GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed); @@ -3726,7 +3718,6 @@ The coordinates X and Y are interpreted in pixels relative to a position GdkSeat *seat = gdk_display_get_default_seat (gdpy); GdkDevice *device = gdk_seat_get_pointer (seat); - PGTK_TRACE ("pgtk-set-mouse-absolute-pixel-position:"); gdk_device_warp (device, gscr, XFIXNUM (x), XFIXNUM (y)); /* No effect on wayland. */ return Qnil; @@ -4128,66 +4119,4 @@ eliminated in future versions of Emacs. */); DEFSYM (Qreverse_landscape, "reverse-landscape"); } - -#ifdef PGTK_DEBUG -#include -#include -void -pgtk_log (const char *file, int lineno, const char *fmt, ...) -{ - struct timespec ts; - struct tm tm; - char timestr[32]; - va_list ap; - - clock_gettime (CLOCK_REALTIME, &ts); - - localtime_r (&ts.tv_sec, &tm); - strftime (timestr, sizeof timestr, "%H:%M:%S", &tm); - - fprintf (stderr, "%s.%06ld %.10s:%04d ", timestr, ts.tv_nsec / 1000, file, - lineno); - va_start (ap, fmt); - vfprintf (stderr, fmt, ap); - va_end (ap); - fputc ('\n', stderr); -} - -void -pgtk_backtrace (const char *file, int lineno) -{ - Lisp_Object bt = make_uninit_vector (10); - for (int i = 0; i < 10; i++) - ASET (bt, i, Qnil); - - struct timespec ts; - struct tm tm; - char timestr[32]; - - clock_gettime (CLOCK_REALTIME, &ts); - - localtime_r (&ts.tv_sec, &tm); - strftime (timestr, sizeof timestr, "%H:%M:%S", &tm); - - fprintf (stderr, "%s.%06ld %.10s:%04d ********\n", timestr, - ts.tv_nsec / 1000, file, lineno); - - get_backtrace (bt); - for (int i = 0; i < 10; i++) - { - Lisp_Object stk = AREF (bt, i); - if (!NILP (stk)) - { - Lisp_Object args[2] = { build_string ("%S"), stk }; - Lisp_Object str = Fformat (2, args); - fprintf (stderr, "%s %.10s:%04d %s\n", timestr, file, lineno, - SSDATA (str)); - } - } - - fprintf (stderr, "%s %.10s:%04d ********\n", timestr, file, lineno); -} - -#endif - #endif diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 58a2b0d05e..77a563dc3f 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -165,7 +165,6 @@ static void get_func (GtkClipboard * cb, GtkSelectionData * data, guint info, gpointer user_data_or_owner) { - PGTK_TRACE ("get_func:"); GObject *obj = G_OBJECT (user_data_or_owner); const char *str; int size; @@ -176,14 +175,12 @@ get_func (GtkClipboard * cb, GtkSelectionData * data, guint info, str = g_object_get_qdata (obj, quark_data); size = GPOINTER_TO_SIZE (g_object_get_qdata (obj, quark_size)); - PGTK_TRACE ("get_func: str: %s", str); gtk_selection_data_set_text (data, str, size); } static void clear_func (GtkClipboard * cb, gpointer user_data_or_owner) { - PGTK_TRACE ("clear_func:"); GObject *obj = G_OBJECT (user_data_or_owner); GQuark quark_data, quark_size; @@ -224,7 +221,6 @@ pgtk_selection_lost (GtkWidget * widget, GdkEventSelection * event, gpointer user_data) { GQuark quark_data, quark_size; - PGTK_TRACE ("pgtk_selection_lost:"); selection_type_to_quarks (event->selection, &quark_data, &quark_size); @@ -340,7 +336,6 @@ FRAME should be a frame that should own the selection. If omitted or nil, it defaults to the selected frame. */) (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) { - PGTK_TRACE ("pgtk-own-selection-internal."); Lisp_Object successful_p = Qnil; Lisp_Object target_symbol, rest; GtkClipboard *cb; @@ -392,19 +387,13 @@ nil, it defaults to the selected frame. */) g_object_set_qdata_full (G_OBJECT (widget), quark_size, GSIZE_TO_POINTER (size), NULL); - PGTK_TRACE ("set_with_owner: owner=%p", FRAME_GTK_WIDGET (f)); if (gtk_clipboard_set_with_owner (cb, targets, n_targets, get_func, clear_func, G_OBJECT (FRAME_GTK_WIDGET (f)))) { - PGTK_TRACE ("set_with_owner succeeded.."); successful_p = Qt; } - else - { - PGTK_TRACE ("set_with_owner failed."); - } gtk_clipboard_set_can_store (cb, NULL, 0); gtk_target_table_free (targets, n_targets); @@ -439,8 +428,6 @@ On MS-DOS, all this does is return non-nil if we own the selection. On PGTK, the TIME-OBJECT is unused. */) (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) { - PGTK_TRACE ("pgtk-disown-selection-internal."); - struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; @@ -472,7 +459,6 @@ frame's display, or the first available X display. On Nextstep, TERMINAL is unused. */) (Lisp_Object selection, Lisp_Object terminal) { - PGTK_TRACE ("pgtk-selection-exists-p."); struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; @@ -503,7 +489,6 @@ frame's display, or the first available X display. On Nextstep, TERMINAL is unused. */) (Lisp_Object selection, Lisp_Object terminal) { - PGTK_TRACE ("pgtk-selection-owner-p."); struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; GObject *obj; @@ -598,14 +583,11 @@ On PGTK, TIME-STAMP is unused. */) void nxatoms_of_pgtkselect (void) { - PGTK_TRACE ("nxatoms_of_pgtkselect"); } void syms_of_pgtkselect (void) { - PGTK_TRACE ("syms_of_pgtkselect"); - DEFSYM (QCLIPBOARD, "CLIPBOARD"); DEFSYM (QSECONDARY, "SECONDARY"); DEFSYM (QTEXT, "TEXT"); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f306b9c414..0c286ca151 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -116,7 +116,6 @@ static struct frame *pgtk_any_window_to_frame (GdkWindow * window); static void flip_cr_context (struct frame *f) { - PGTK_TRACE ("flip_cr_context"); cairo_t *cr = FRAME_CR_ACTIVE_CONTEXT (f); block_input (); @@ -183,7 +182,6 @@ get_keysym_name (int keysym) that it be unique. -------------------------------------------------------------------------- */ { - PGTK_TRACE ("x_get_ksysym_name"); static char value[16]; sprintf (value, "%d", keysym); return value; @@ -195,7 +193,6 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) Programmatically reposition mouse pointer in pixel coordinates -------------------------------------------------------------------------- */ { - PGTK_TRACE ("frame_set_mouse_pixel_position"); } /* Free X resources of frame F. */ @@ -206,7 +203,6 @@ x_free_frame_resources (struct frame *f) struct pgtk_display_info *dpyinfo; Mouse_HLInfo *hlinfo; - PGTK_TRACE ("x_free_frame_resources"); check_window_system (f); dpyinfo = FRAME_DISPLAY_INFO (f); hlinfo = MOUSE_HL_INFO (f); @@ -300,7 +296,6 @@ x_destroy_window (struct frame *f) -------------------------------------------------------------------------- */ { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - PGTK_TRACE ("x_destroy_window"); check_window_system (f); if (dpyinfo->gdpy != NULL) @@ -395,8 +390,6 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) External: Position the window -------------------------------------------------------------------------- */ { - PGTK_TRACE ("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); - int modified_top, modified_left; if (change_gravity > 0) @@ -465,7 +458,6 @@ pgtk_set_window_size (struct frame *f, bool change_gravity, internal clipping. -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_set_window_size(%dx%d)", width, height); int pixelwidth, pixelheight; block_input (); @@ -521,8 +513,6 @@ pgtk_iconify_frame (struct frame *f) External: Iconify window -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_iconify_frame"); - /* Don't keep the highlight on an invisible frame. */ if (FRAME_DISPLAY_INFO (f)->highlight_frame == f) FRAME_DISPLAY_INFO (f)->highlight_frame = 0; @@ -631,8 +621,6 @@ pgtk_make_frame_visible (struct frame *f) External: Show the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_make_frame_visible"); - GtkWidget *win = FRAME_GTK_OUTER_WIDGET (f); if (!FRAME_VISIBLE_P (f)) @@ -652,8 +640,6 @@ pgtk_make_frame_invisible (struct frame *f) External: Hide the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_make_frame_invisible"); - gtk_widget_hide (FRAME_WIDGET (f)); /* Map events are emitted many times, and @@ -679,7 +665,6 @@ pgtk_make_frame_visible_invisible (struct frame *f, bool visible) static Lisp_Object pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) { - PGTK_TRACE ("pgtk_new_font"); struct font *font = XFONT_OBJECT (font_object); int font_ascent, font_descent; @@ -691,28 +676,10 @@ pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) { /* This font is already set in frame F. There's nothing more to do. */ - PGTK_TRACE ("already set."); return font_object; } FRAME_FONT (f) = font; - PGTK_TRACE ("font:"); - PGTK_TRACE (" %p", font); - PGTK_TRACE (" name: %s", SSDATA (font_get_name (font_object))); - PGTK_TRACE (" width: %d..%d", font->min_width, font->max_width); - PGTK_TRACE (" pixel_size: %d", font->pixel_size); - PGTK_TRACE (" height: %d", font->height); - PGTK_TRACE (" space_width: %d", font->space_width); - PGTK_TRACE (" average_width: %d", font->average_width); - PGTK_TRACE (" asc/desc: %d,%d", font->ascent, font->descent); - PGTK_TRACE (" ul thickness: %d", font->underline_thickness); - PGTK_TRACE (" ul position: %d", font->underline_position); - PGTK_TRACE (" vertical_centering: %d", font->vertical_centering); - PGTK_TRACE (" baseline_offset: %d", font->baseline_offset); - PGTK_TRACE (" relative_compose: %d", font->relative_compose); - PGTK_TRACE (" default_ascent: %d", font->default_ascent); - PGTK_TRACE (" encoding_charset: %d", font->encoding_charset); - PGTK_TRACE (" repertory_charset: %d", font->repertory_charset); FRAME_BASELINE_OFFSET (f) = font->baseline_offset; FRAME_COLUMN_WIDTH (f) = font->average_width; @@ -754,29 +721,22 @@ pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); - PGTK_TRACE ("set new."); return font_object; } int x_display_pixel_height (struct pgtk_display_info *dpyinfo) { - PGTK_TRACE ("x_display_pixel_height"); - GdkDisplay *gdpy = dpyinfo->gdpy; GdkScreen *gscr = gdk_display_get_default_screen (gdpy); - PGTK_TRACE (" = %d", gdk_screen_get_height (gscr)); return gdk_screen_get_height (gscr); } int x_display_pixel_width (struct pgtk_display_info *dpyinfo) { - PGTK_TRACE ("x_display_pixel_width"); - GdkDisplay *gdpy = dpyinfo->gdpy; GdkScreen *gscr = gdk_display_get_default_screen (gdpy); - PGTK_TRACE (" = %d", gdk_screen_get_width (gscr)); return gdk_screen_get_width (gscr); } @@ -907,7 +867,6 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, * * Some window managers may not honor this parameter. */ { - PGTK_TRACE ("x_set_no_accept_focus_on_map"); /* doesn't work on wayland. */ if (!EQ (new_value, old_value)) @@ -930,7 +889,6 @@ x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, * Some window managers may not honor this parameter. */ { /* doesn't work on wayland. */ - PGTK_TRACE ("x_set_no_accept_focus"); xg_set_no_accept_focus (f, new_value); FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value); @@ -948,7 +906,6 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) Some window managers may not honor this parameter. */ { /* doesn't work on wayland. */ - PGTK_TRACE ("x_set_z_group"); if (!FRAME_GTK_OUTER_WIDGET (f)) return; @@ -1012,34 +969,25 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) static void x_set_cursor_gc (struct glyph_string *s) { - PGTK_TRACE ("x_set_cursor_gc."); if (s->font == FRAME_FONT (s->f) && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) && !s->cmp) - PGTK_TRACE ("x_set_cursor_gc: 1."), s->xgcv = FRAME_X_OUTPUT (s->f)->cursor_xgcv; else { /* Cursor on non-default face: must merge. */ Emacs_GC xgcv; - PGTK_TRACE ("x_set_cursor_gc: 2."); xgcv.background = FRAME_X_OUTPUT (s->f)->cursor_color; xgcv.foreground = s->face->background; - PGTK_TRACE ("x_set_cursor_gc: 3. %08lx, %08lx.", xgcv.background, - xgcv.foreground); /* If the glyph would be invisible, try a different foreground. */ if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; - PGTK_TRACE ("x_set_cursor_gc: 4. %08lx, %08lx.", xgcv.background, - xgcv.foreground); if (xgcv.foreground == xgcv.background) xgcv.foreground = FRAME_X_OUTPUT (s->f)->cursor_foreground_color; if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; - PGTK_TRACE ("x_set_cursor_gc: 5. %08lx, %08lx.", xgcv.background, - xgcv.foreground); /* Make sure the cursor is distinct from text in this face. */ if (xgcv.background == s->face->background @@ -1048,8 +996,6 @@ x_set_cursor_gc (struct glyph_string *s) xgcv.background = s->face->foreground; xgcv.foreground = s->face->background; } - PGTK_TRACE ("x_set_cursor_gc: 6. %08lx, %08lx.", xgcv.background, - xgcv.foreground); s->xgcv = xgcv; } @@ -1116,50 +1062,34 @@ x_set_mode_line_face_gc (struct glyph_string *s) static void x_set_glyph_string_gc (struct glyph_string *s) { - PGTK_TRACE ("x_set_glyph_string_gc: s->f: %08lx, %08lx", - s->f->background_pixel, s->f->foreground_pixel); - PGTK_TRACE ("x_set_glyph_string_gc: s->face: %08lx, %08lx", - s->face->background, s->face->foreground); prepare_face_for_display (s->f, s->face); - PGTK_TRACE ("x_set_glyph_string_gc: s->face: %08lx, %08lx", - s->face->background, s->face->foreground); if (s->hl == DRAW_NORMAL_TEXT) { s->xgcv.foreground = s->face->foreground; s->xgcv.background = s->face->background; s->stippled_p = s->face->stipple != 0; - PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, - s->xgcv.foreground); } else if (s->hl == DRAW_INVERSE_VIDEO) { x_set_mode_line_face_gc (s); s->stippled_p = s->face->stipple != 0; - PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, - s->xgcv.foreground); } else if (s->hl == DRAW_CURSOR) { x_set_cursor_gc (s); s->stippled_p = false; - PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, - s->xgcv.foreground); } else if (s->hl == DRAW_MOUSE_FACE) { x_set_mouse_face_gc (s); s->stippled_p = s->face->stipple != 0; - PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, - s->xgcv.foreground); } else if (s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) { s->xgcv.foreground = s->face->foreground; s->xgcv.background = s->face->background; s->stippled_p = s->face->stipple != 0; - PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, - s->xgcv.foreground); } else emacs_abort (); @@ -1174,29 +1104,15 @@ x_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr) { XRectangle r[2]; int n = get_glyph_string_clip_rects (s, r, 2); - PGTK_TRACE ("x_set_glyph_string_clipping: n=%d.", n); if (n > 0) { for (int i = 0; i < n; i++) { - PGTK_TRACE ("x_set_glyph_string_clipping: r[%d]: %ux%u+%d+%d.", - i, r[i].width, r[i].height, r[i].x, r[i].y); cairo_rectangle (cr, r[i].x, r[i].y, r[i].width, r[i].height); } cairo_clip (cr); } - PGTK_TRACE ("clip result:"); - cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list (cr); - for (int i = 0; i < rects->num_rectangles; i++) - { - PGTK_TRACE (" rect[%d]: %dx%d+%d+%d.", - i, - (int) rects->rectangles[i].width, - (int) rects->rectangles[i].height, - (int) rects->rectangles[i].x, (int) rects->rectangles[i].y); - } - cairo_rectangle_list_destroy (rects); } @@ -1314,24 +1230,12 @@ fill_background (struct glyph_string *s, int x, int y, int width, int height) static void x_draw_glyph_string_background (struct glyph_string *s, bool force_p) { - PGTK_TRACE ("x_draw_glyph_string_background: 0."); /* Nothing to do if background has already been drawn or if it shouldn't be drawn in the first place. */ if (!s->background_filled_p) { - PGTK_TRACE ("x_draw_glyph_string_background: 1."); int box_line_width = max (s->face->box_horizontal_line_width, 0); - PGTK_TRACE ("x_draw_glyph_string_background: 2. %d, %d.", - FONT_HEIGHT (s->font), s->height - 2 * box_line_width); - PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", - FONT_TOO_HIGH (s->font)); - PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", - s->font_not_found_p); - PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", - s->extends_to_end_of_line_p); - PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", force_p); - if (s->stippled_p) { /* Fill background with a stipple pattern. */ @@ -1351,7 +1255,6 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) || s->font_not_found_p || s->extends_to_end_of_line_p || force_p) { - PGTK_TRACE ("x_draw_glyph_string_background: 3."); x_clear_glyph_string_rect (s, s->x, s->y + box_line_width, s->background_width, s->height - 2 * box_line_width); @@ -2448,10 +2351,6 @@ x_draw_stretch_glyph_string (struct glyph_string *s) static void pgtk_draw_glyph_string (struct glyph_string *s) { - PGTK_TRACE ("draw_glyph_string."); - PGTK_TRACE ("draw_glyph_string: x=%d, y=%d, width=%d, height=%d.", - s->x, s->y, s->width, s->height); - bool relief_drawn_p = false; /* If S draws into the background of its successors, draw the @@ -2468,7 +2367,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) if (next->first_glyph->type != IMAGE_GLYPH) { cairo_t *cr = pgtk_begin_cr_clip (next->f); - PGTK_TRACE ("pgtk_draw_glyph_string: 1."); x_set_glyph_string_gc (next); x_set_glyph_string_clipping (next, cr); if (next->first_glyph->type == STRETCH_GLYPH) @@ -2481,7 +2379,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) } /* Set up S->gc, set clipping and draw S. */ - PGTK_TRACE ("pgtk_draw_glyph_string: 2."); x_set_glyph_string_gc (s); cairo_t *cr = pgtk_begin_cr_clip (s->f); @@ -2494,7 +2391,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) || s->first_glyph->type == COMPOSITE_GLYPH)) { - PGTK_TRACE ("pgtk_draw_glyph_string: 2.1."); x_set_glyph_string_clipping (s, cr); x_draw_glyph_string_background (s, true); x_draw_glyph_string_box (s); @@ -2508,31 +2404,25 @@ pgtk_draw_glyph_string (struct glyph_string *s) /* We must clip just this glyph. left_overhang part has already drawn when s->prev was drawn, and right_overhang part will be drawn later when s->next is drawn. */ - PGTK_TRACE ("pgtk_draw_glyph_string: 2.2."), x_set_glyph_string_clipping_exactly (s, s, cr); else - PGTK_TRACE ("pgtk_draw_glyph_string: 2.3."), x_set_glyph_string_clipping (s, cr); switch (s->first_glyph->type) { case IMAGE_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.4."); x_draw_image_glyph_string (s); break; case XWIDGET_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.5."); x_draw_xwidget_glyph_string (s); break; case STRETCH_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.6."); x_draw_stretch_glyph_string (s); break; case CHAR_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.7."); if (s->for_overlaps) s->background_filled_p = true; else @@ -2541,7 +2431,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) break; case COMPOSITE_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.8."); if (s->for_overlaps || (s->cmp_from > 0 && !s->first_glyph->u.cmp.automatic)) s->background_filled_p = true; @@ -2551,7 +2440,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) break; case GLYPHLESS_GLYPH: - PGTK_TRACE ("pgtk_draw_glyph_string: 2.9."); if (s->for_overlaps) s->background_filled_p = true; else @@ -2696,7 +2584,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) enum draw_glyphs_face save = prev->hl; prev->hl = s->hl; - PGTK_TRACE ("pgtk_draw_glyph_string: 3."); x_set_glyph_string_gc (prev); cairo_save (cr); x_set_glyph_string_clipping_exactly (s, prev, cr); @@ -2723,7 +2610,6 @@ pgtk_draw_glyph_string (struct glyph_string *s) enum draw_glyphs_face save = next->hl; next->hl = s->hl; - PGTK_TRACE ("pgtk_draw_glyph_string: 4."); x_set_glyph_string_gc (next); cairo_save (cr); x_set_glyph_string_clipping_exactly (s, next, cr); @@ -2759,8 +2645,6 @@ static void pgtk_after_update_window_line (struct window *w, struct glyph_row *desired_row) { - PGTK_TRACE ("after_update_window_line."); - struct frame *f; int width, height; @@ -2791,7 +2675,6 @@ pgtk_after_update_window_line (struct window *w, static void pgtk_clear_frame_area (struct frame *f, int x, int y, int width, int height) { - PGTK_TRACE ("clear_frame_area."); pgtk_clear_area (f, x, y, width, height); } @@ -2941,8 +2824,6 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int cursor_width, bool on_p, bool active_p) { struct frame *f = XFRAME (w->frame); - PGTK_TRACE ("draw_window_cursor: %d, %d, %d, %d, %d, %d.", - x, y, cursor_type, cursor_width, on_p, active_p); if (on_p) { w->phys_cursor_type = cursor_type; @@ -3002,14 +2883,6 @@ static void pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect, cairo_rectangle_t * dst_rect) { - PGTK_TRACE ("pgtk_copy_bits: %dx%d+%d+%d -> %dx%d+%d+%d", - (int) src_rect->width, - (int) src_rect->height, - (int) src_rect->x, - (int) src_rect->y, - (int) dst_rect->width, - (int) dst_rect->height, (int) dst_rect->x, (int) dst_rect->y); - cairo_t *cr; cairo_surface_t *surface; /* temporary surface */ @@ -3470,9 +3343,6 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC * gc, cairo_pattern_t * image, { cairo_t *cr = pgtk_begin_cr_clip (f); - PGTK_TRACE ("pgtk_cr_draw_image: 0: %d,%d,%d,%d,%d,%d,%d.", src_x, src_y, - width, height, dest_x, dest_y, overlay_p); - if (overlay_p) cairo_rectangle (cr, dest_x, dest_y, width, height); else @@ -3505,8 +3375,6 @@ static void pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p) { - PGTK_TRACE ("draw_fringe_bitmap."); - struct frame *f = XFRAME (WINDOW_FRAME (w)); struct face *face = p->face; @@ -3533,16 +3401,10 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, } } - PGTK_TRACE ("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); if (p->which && p->which < max_fringe_bmp) { Emacs_GC gcv; - PGTK_TRACE ("cursor_p=%d.", p->cursor_p); - PGTK_TRACE ("overlay_p_p=%d.", p->overlay_p); - PGTK_TRACE ("background=%08lx.", face->background); - PGTK_TRACE ("cursor_color=%08lx.", FRAME_X_OUTPUT (f)->cursor_color); - PGTK_TRACE ("foreground=%08lx.", face->foreground); gcv.foreground = (p->cursor_p ? (p->overlay_p ? face->background : FRAME_X_OUTPUT (f)->cursor_color) @@ -3652,7 +3514,6 @@ static struct redisplay_interface pgtk_redisplay_interface = { static void pgtk_redraw_scroll_bars (struct frame *f) { - PGTK_TRACE ("pgtk_redraw_scroll_bars"); } void @@ -3661,7 +3522,6 @@ pgtk_clear_frame (struct frame *f) External (hook): Erase the entire frame -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_clear_frame"); /* comes on initial frame because we have after-make-frame-functions = select-frame */ if (!FRAME_DEFAULT_FACE (f)) @@ -3802,7 +3662,6 @@ pgtk_ring_bell (struct frame *f) static int pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) { - PGTK_TRACE ("pgtk_read_socket: enter."); GMainContext *context; bool context_acquired = false; int count; @@ -3810,7 +3669,6 @@ pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) count = evq_flush (hold_quit); if (count > 0) { - PGTK_TRACE ("pgtk_read_socket: leave(1)."); return count; } @@ -3818,20 +3676,15 @@ pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) context_acquired = g_main_context_acquire (context); block_input (); - PGTK_TRACE ("pgtk_read_socket: 3: errno=%d.", errno); if (context_acquired) { - PGTK_TRACE ("pgtk_read_socket: 4.1: acquired."); while (g_main_context_pending (context)) { - PGTK_TRACE ("pgtk_read_socket: 4: dispatch..."); g_main_context_dispatch (context); - PGTK_TRACE ("pgtk_read_socket: 5: dispatch... done."); } } - PGTK_TRACE ("pgtk_read_socket: 7: errno=%d.", errno); unblock_input (); if (context_acquired) @@ -3840,11 +3693,9 @@ pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) count = evq_flush (hold_quit); if (count > 0) { - PGTK_TRACE ("pgtk_read_socket: leave(2)."); return count; } - PGTK_TRACE ("pgtk_read_socket: leave(3)."); return 0; } @@ -3866,11 +3717,8 @@ pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, int i, nfds, tmo_in_millisec, must_free = 0; bool need_to_dispatch; - PGTK_TRACE ("pgtk_select: enter."); - if (event_q.nr >= 1) { - PGTK_TRACE ("pgtk_select: raise."); raise (SIGIO); errno = EINTR; return -1; @@ -3992,19 +3840,13 @@ pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, if (need_to_dispatch && context_acquired) { int pselect_errno = errno; - PGTK_TRACE ("retval=%d.", retval); - PGTK_TRACE ("need_to_dispatch=%d.", need_to_dispatch); - PGTK_TRACE ("context_acquired=%d.", context_acquired); - PGTK_TRACE ("pselect_errno=%d.", pselect_errno); /* Prevent g_main_dispatch recursion, that would occur without block_input wrapper, because event handlers call unblock_input. Event loop recursion was causing Bug#15801. */ block_input (); while (g_main_context_pending (context)) { - PGTK_TRACE ("dispatch..."); g_main_context_dispatch (context); - PGTK_TRACE ("dispatch... done."); } unblock_input (); errno = pselect_errno; @@ -4020,7 +3862,6 @@ pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, errno = EINTR; } - PGTK_TRACE ("pgtk_select: leave."); return retval; } @@ -4064,13 +3905,10 @@ xg_scroll_callback (GtkRange * range, struct scroll_bar *bar = user_data; enum scroll_bar_part part = scroll_bar_nowhere; GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range)); - PGTK_TRACE ("xg_scroll_callback:"); if (xg_ignore_gtk_scrollbar) return false; - PGTK_TRACE ("xg_scroll_callback: not ignored."); - PGTK_TRACE ("xg_scroll_callback: scroll=%u.", scroll); switch (scroll) { case GTK_SCROLL_JUMP: @@ -4121,8 +3959,6 @@ xg_scroll_callback (GtkRange * range, break; } - PGTK_TRACE ("xg_scroll_callback: part=%u, scroll_bar_nowhere=%d.", part, - scroll_bar_nowhere); if (part != scroll_bar_nowhere) { window_being_scrolled = bar->window; @@ -4140,7 +3976,6 @@ xg_end_scroll_callback (GtkWidget * widget, GdkEventButton * event, gpointer user_data) { struct scroll_bar *bar = user_data; - PGTK_TRACE ("xg_end_scroll_callback:"); bar->dragging = -1; if (WINDOWP (window_being_scrolled)) { @@ -4297,16 +4132,6 @@ pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, height = window_height; left = WINDOW_SCROLL_BAR_AREA_X (w); width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); - PGTK_TRACE ("pgtk_set_vertical_scroll_bar: has_vertical_scroll_bar: %d", - WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); - PGTK_TRACE ("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", - WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)); - PGTK_TRACE ("pgtk_set_vertical_scroll_bar: scroll_bar_width: %d", - w->scroll_bar_width); - PGTK_TRACE ("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", - FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w))); - PGTK_TRACE ("pgtk_set_vertical_scroll_bar: %dx%d+%d+%d", width, height, - left, top); /* Does the scroll bar exist yet? */ if (NILP (w->vertical_scroll_bar)) @@ -4603,21 +4428,18 @@ set_fullscreen_state (struct frame *f) switch (f->want_fullscreen) { case FULLSCREEN_NONE: - PGTK_TRACE ("pgtk_fullscreen_hook: none."); gtk_window_unfullscreen (widget); gtk_window_unmaximize (widget); store_frame_param (f, Qfullscreen, Qnil); break; case FULLSCREEN_BOTH: - PGTK_TRACE ("pgtk_fullscreen_hook: both."); gtk_window_unmaximize (widget); gtk_window_fullscreen (widget); store_frame_param (f, Qfullscreen, Qfullboth); break; case FULLSCREEN_MAXIMIZED: - PGTK_TRACE ("pgtk_fullscreen_hook: maximized."); gtk_window_unfullscreen (widget); gtk_window_maximize (widget); store_frame_param (f, Qfullscreen, Qmaximized); @@ -4625,7 +4447,6 @@ set_fullscreen_state (struct frame *f) case FULLSCREEN_WIDTH: case FULLSCREEN_HEIGHT: - PGTK_TRACE ("pgtk_fullscreen_hook: width or height."); /* Not supported by gtk. Ignore them. */ } @@ -4635,7 +4456,6 @@ set_fullscreen_state (struct frame *f) static void pgtk_fullscreen_hook (struct frame *f) { - PGTK_TRACE ("pgtk_fullscreen_hook:"); if (FRAME_VISIBLE_P (f)) { block_input (); @@ -5084,159 +4904,6 @@ pgtk_any_window_to_frame (GdkWindow * window) static gboolean pgtk_handle_event (GtkWidget * widget, GdkEvent * event, gpointer * data) { -#ifdef PGTK_DEBUG - const char *type_name = G_OBJECT_TYPE_NAME (widget); - switch (event->type) - { - case GDK_NOTHING: - PGTK_TRACE ("GDK_NOTHING"); - break; - case GDK_DELETE: - PGTK_TRACE ("GDK_DELETE"); - break; - case GDK_DESTROY: - PGTK_TRACE ("GDK_DESTROY"); - break; - case GDK_EXPOSE: - PGTK_TRACE ("GDK_EXPOSE"); - break; - case GDK_MOTION_NOTIFY: - PGTK_TRACE ("GDK_MOTION_NOTIFY"); - break; - case GDK_BUTTON_PRESS: - PGTK_TRACE ("GDK_BUTTON_PRESS"); - break; - case GDK_2BUTTON_PRESS: - PGTK_TRACE ("GDK_2BUTTON_PRESS"); - break; - case GDK_3BUTTON_PRESS: - PGTK_TRACE ("GDK_3BUTTON_PRESS"); - break; - case GDK_BUTTON_RELEASE: - PGTK_TRACE ("GDK_BUTTON_RELEASE"); - break; - case GDK_KEY_PRESS: - PGTK_TRACE ("GDK_KEY_PRESS"); - break; - case GDK_KEY_RELEASE: - PGTK_TRACE ("GDK_KEY_RELEASE"); - break; - case GDK_ENTER_NOTIFY: - PGTK_TRACE ("GDK_ENTER_NOTIFY"); - break; - case GDK_LEAVE_NOTIFY: - PGTK_TRACE ("GDK_LEAVE_NOTIFY"); - break; - case GDK_FOCUS_CHANGE: - PGTK_TRACE ("GDK_FOCUS_CHANGE"); - break; - case GDK_CONFIGURE: - PGTK_TRACE ("GDK_CONFIGURE"); - break; - case GDK_MAP: - PGTK_TRACE ("GDK_MAP"); - break; - case GDK_UNMAP: - PGTK_TRACE ("GDK_UNMAP"); - break; - case GDK_PROPERTY_NOTIFY: - PGTK_TRACE ("GDK_PROPERTY_NOTIFY"); - break; - case GDK_SELECTION_CLEAR: - PGTK_TRACE ("GDK_SELECTION_CLEAR"); - break; - case GDK_SELECTION_REQUEST: - PGTK_TRACE ("GDK_SELECTION_REQUEST"); - break; - case GDK_SELECTION_NOTIFY: - PGTK_TRACE ("GDK_SELECTION_NOTIFY"); - break; - case GDK_PROXIMITY_IN: - PGTK_TRACE ("GDK_PROXIMITY_IN"); - break; - case GDK_PROXIMITY_OUT: - PGTK_TRACE ("GDK_PROXIMITY_OUT"); - break; - case GDK_DRAG_ENTER: - PGTK_TRACE ("GDK_DRAG_ENTER"); - break; - case GDK_DRAG_LEAVE: - PGTK_TRACE ("GDK_DRAG_LEAVE"); - break; - case GDK_DRAG_MOTION: - PGTK_TRACE ("GDK_DRAG_MOTION"); - break; - case GDK_DRAG_STATUS: - PGTK_TRACE ("GDK_DRAG_STATUS"); - break; - case GDK_DROP_START: - PGTK_TRACE ("GDK_DROP_START"); - break; - case GDK_DROP_FINISHED: - PGTK_TRACE ("GDK_DROP_FINISHED"); - break; - case GDK_CLIENT_EVENT: - PGTK_TRACE ("GDK_CLIENT_EVENT"); - break; - case GDK_VISIBILITY_NOTIFY: - PGTK_TRACE ("GDK_VISIBILITY_NOTIFY"); - break; - case GDK_SCROLL: - PGTK_TRACE ("GDK_SCROLL"); - break; - case GDK_WINDOW_STATE: - PGTK_TRACE ("GDK_WINDOW_STATE"); - break; - case GDK_SETTING: - PGTK_TRACE ("GDK_SETTING"); - break; - case GDK_OWNER_CHANGE: - PGTK_TRACE ("GDK_OWNER_CHANGE"); - break; - case GDK_GRAB_BROKEN: - PGTK_TRACE ("GDK_GRAB_BROKEN"); - break; - case GDK_DAMAGE: - PGTK_TRACE ("GDK_DAMAGE"); - break; - case GDK_TOUCH_BEGIN: - PGTK_TRACE ("GDK_TOUCH_BEGIN"); - break; - case GDK_TOUCH_UPDATE: - PGTK_TRACE ("GDK_TOUCH_UPDATE"); - break; - case GDK_TOUCH_END: - PGTK_TRACE ("GDK_TOUCH_END"); - break; - case GDK_TOUCH_CANCEL: - PGTK_TRACE ("GDK_TOUCH_CANCEL"); - break; - case GDK_TOUCHPAD_SWIPE: - PGTK_TRACE ("GDK_TOUCHPAD_SWIPE"); - break; - case GDK_TOUCHPAD_PINCH: - PGTK_TRACE ("GDK_TOUCHPAD_PINCH"); - break; - case GDK_PAD_BUTTON_PRESS: - PGTK_TRACE ("GDK_PAD_BUTTON_PRESS"); - break; - case GDK_PAD_BUTTON_RELEASE: - PGTK_TRACE ("GDK_PAD_BUTTON_RELEASE"); - break; - case GDK_PAD_RING: - PGTK_TRACE ("GDK_PAD_RING"); - break; - case GDK_PAD_STRIP: - PGTK_TRACE ("GDK_PAD_STRIP"); - break; - case GDK_PAD_GROUP_MODE: - PGTK_TRACE ("GDK_PAD_GROUP_MODE"); - break; - default: - PGTK_TRACE ("GDK_EVENT %d", event->type); - } - PGTK_TRACE (" Widget is %s", type_name); -#endif return FALSE; } @@ -5244,7 +4911,6 @@ static void pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y, int width, int height) { - PGTK_TRACE ("pgtk_fill_rectangle"); cairo_t *cr; cr = pgtk_begin_cr_clip (f); pgtk_set_cr_source_with_color (f, color); @@ -5256,7 +4922,6 @@ pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y, void pgtk_clear_under_internal_border (struct frame *f) { - PGTK_TRACE ("pgtk_clear_under_internal_border"); if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) { int border = FRAME_INTERNAL_BORDER_WIDTH (f); @@ -5299,85 +4964,25 @@ pgtk_clear_under_internal_border (struct frame *f) } } -#ifdef HAVE_PGTK - -static void -print_widget_tree_recursive (GtkWidget * w, gpointer user_data) -{ - const char *indent = user_data; - char buf[1024] = ""; - int len = 0; - len += sprintf (buf + len, "%s", indent); - len += - sprintf (buf + len, "%p %s mapped:%d visible:%d", w, - G_OBJECT_TYPE_NAME (w), gtk_widget_get_mapped (w), - gtk_widget_get_visible (w)); - gint wd, hi; - gtk_widget_get_size_request (w, &wd, &hi); - len += sprintf (buf + len, " size_req:%dx%d", wd, hi); - GtkAllocation alloc; - gtk_widget_get_allocation (w, &alloc); - len += - sprintf (buf + len, " alloc:%dx%d+%d+%d", alloc.width, alloc.height, - alloc.x, alloc.y); - len += sprintf (buf + len, " haswin:%d", gtk_widget_get_has_window (w)); - len += sprintf (buf + len, " gdkwin:%p", gtk_widget_get_window (w)); - PGTK_TRACE ("%s", buf); - - if (GTK_IS_CONTAINER (w)) - { - strcpy (buf, indent); - strcat (buf, " "); - gtk_container_foreach (GTK_CONTAINER (w), print_widget_tree_recursive, - buf); - } -} - -static void -print_widget_tree (GtkWidget * w) -{ - char indent[1] = ""; - w = gtk_widget_get_toplevel (w); - print_widget_tree_recursive (w, indent); -} - -#endif - static gboolean pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) { struct frame *f; - PGTK_TRACE ("pgtk_handle_draw"); - -#ifdef HAVE_PGTK - print_widget_tree (widget); -#endif - GdkWindow *win = gtk_widget_get_window (widget); - PGTK_TRACE (" win=%p", win); if (win != NULL) { cairo_surface_t *src = NULL; f = pgtk_any_window_to_frame (win); - PGTK_TRACE (" f=%p", f); if (f != NULL) { src = FRAME_X_OUTPUT (f)->cr_surface_visible_bell; if (src == NULL && FRAME_CR_ACTIVE_CONTEXT (f) != NULL) src = cairo_get_target (FRAME_CR_ACTIVE_CONTEXT (f)); } - PGTK_TRACE (" surface=%p", src); if (src != NULL) { - PGTK_TRACE (" resized_p=%d", f->resized_p); - PGTK_TRACE (" garbaged=%d", f->garbaged); - PGTK_TRACE (" scroll_bar_width=%f", - (double) PGTK_SCROLL_BAR_WIDTH (f)); - // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST (f)); - PGTK_TRACE (" scroll_bar_cols=%d", FRAME_SCROLL_BAR_COLS (f)); - PGTK_TRACE (" column_width=%d", FRAME_COLUMN_WIDTH (f)); cairo_set_source_surface (cr, src, 0, 0); cairo_paint (cr); } @@ -5389,9 +4994,6 @@ static void size_allocate (GtkWidget * widget, GtkAllocation * alloc, gpointer user_data) { - PGTK_TRACE ("size-alloc: %dx%d+%d+%d.", alloc->width, alloc->height, - alloc->x, alloc->y); - struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); /* Between a frame is created and not shown, size is allocated and @@ -5407,7 +5009,6 @@ size_allocate (GtkWidget * widget, GtkAllocation * alloc, if (f) { - PGTK_TRACE ("%dx%d", alloc->width, alloc->height); xg_frame_resized (f, alloc->width, alloc->height); pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height); } @@ -5641,8 +5242,6 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) USE_SAFE_ALLOCA; - PGTK_TRACE ("key_press_event"); - EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; @@ -5913,7 +5512,6 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) static gboolean key_release_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("key_release_event"); return TRUE; } @@ -5943,8 +5541,6 @@ map_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; - PGTK_TRACE ("map_event"); - EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; @@ -6026,8 +5622,6 @@ delete_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; - PGTK_TRACE ("delete_event"); - EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; @@ -6101,7 +5695,6 @@ static gboolean enter_notify_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("enter_notify_event"); union buffered_input_event inev; struct frame *frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); @@ -6128,7 +5721,6 @@ static gboolean leave_notify_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("leave_notify_event"); union buffered_input_event inev; struct frame *frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); @@ -6166,7 +5758,6 @@ leave_notify_event (GtkWidget * widget, GdkEvent * event, static gboolean focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("focus_in_event"); union buffered_input_event inev; struct frame *frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); @@ -6191,7 +5782,6 @@ focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) static gboolean focus_out_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("focus_out_event"); union buffered_input_event inev; struct frame *frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); @@ -6268,7 +5858,6 @@ static gboolean motion_notify_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("motion_notify_event"); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -6422,8 +6011,6 @@ construct_mouse_click (struct input_event *result, static gboolean button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("button_event: type=%d, button=%u.", event->button.type, - event->button.button); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -6556,7 +6143,6 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) static gboolean scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE ("scroll_event"); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -6657,7 +6243,6 @@ drag_data_received (GtkWidget * widget, GdkDragContext * context, GtkSelectionData * data, guint info, guint time, gpointer user_data) { - PGTK_TRACE ("drag_data_received:"); struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); gchar **uris = gtk_selection_data_get_uris (data); @@ -6668,8 +6253,6 @@ drag_data_received (GtkWidget * widget, GdkDragContext * context, union buffered_input_event inev; Lisp_Object arg = Qnil; - PGTK_TRACE ("drag_data_received: uri: %s", uris[i]); - EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; @@ -6687,7 +6270,6 @@ drag_data_received (GtkWidget * widget, GdkDragContext * context, evq_enqueue (&inev); } } - PGTK_TRACE ("drag_data_received: that's all."); gtk_drag_finish (context, TRUE, FALSE, time); } @@ -7066,7 +6648,6 @@ pgtk_xlfd_to_fontname (const char *xlfd) The string returned is temporarily allocated. -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_xlfd_to_fontname"); char *name = xmalloc (180); if (!strncmp (xlfd, "--", 2)) @@ -7084,7 +6665,6 @@ pgtk_xlfd_to_fontname (const char *xlfd) if (strlen (name) == 0) strcpy (name, "Monospace"); - PGTK_TRACE ("converted '%s' to '%s'", xlfd, name); return name; } @@ -7100,7 +6680,6 @@ pgtk_defined_color (struct frame *f, Return false if not found -------------------------------------------------------------------------- */ { - // PGTK_TRACE("pgtk_defined_color(%s)", name); int r; block_input (); @@ -7123,8 +6702,6 @@ int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color * color) { - PGTK_TRACE ("pgtk_parse_color: %s", color_name); - GdkRGBA rgba; if (gdk_rgba_parse (&rgba, color_name)) { @@ -7146,7 +6723,6 @@ pgtk_parse_color (struct frame *f, const char *color_name, void pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors) { - PGTK_TRACE ("pgtk_query_colors"); int i; for (i = 0; i < ncolors; i++) @@ -7159,29 +6735,23 @@ pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors) colors[i].red = GetRValue (pixel) * 257; colors[i].green = GetGValue (pixel) * 257; colors[i].blue = GetBValue (pixel) * 257; - PGTK_TRACE ("pixel: %lx, red: %d, blue %d, green %d", colors[i].pixel, - colors[i].red, colors[i].blue, colors[i].green); } } void pgtk_query_color (struct frame *f, Emacs_Color * color) { - PGTK_TRACE ("pgtk_query_color"); pgtk_query_colors (f, color, 1); } void pgtk_clear_area (struct frame *f, int x, int y, int width, int height) { - PGTK_TRACE ("pgtk_clear_area: %dx%d+%d+%d.", width, height, x, y); cairo_t *cr; eassert (width > 0 && height > 0); cr = pgtk_begin_cr_clip (f); - PGTK_TRACE ("back color %08lx.", - (unsigned long) FRAME_X_OUTPUT (f)->background_color); pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); @@ -7322,8 +6892,6 @@ If set to a non-float value, there will be no wait at all. */); void pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) { - PGTK_TRACE ("pgtk_cr_update_surface_desired_size"); - if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) { @@ -7340,7 +6908,6 @@ pgtk_begin_cr_clip (struct frame *f) { cairo_t *cr = FRAME_CR_CONTEXT (f); - PGTK_TRACE ("pgtk_begin_cr_clip"); if (!cr) { cairo_surface_t *surface = @@ -7363,28 +6930,24 @@ pgtk_begin_cr_clip (struct frame *f) void pgtk_end_cr_clip (struct frame *f) { - PGTK_TRACE ("pgtk_end_cr_clip"); cairo_restore (FRAME_CR_CONTEXT (f)); } void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC * gc) { - PGTK_TRACE ("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); pgtk_set_cr_source_with_color (f, gc->foreground); } void pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC * gc) { - PGTK_TRACE ("pgtk_set_cr_source_with_gc_background: %08lx", gc->background); pgtk_set_cr_source_with_color (f, gc->background); } void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) { - PGTK_TRACE ("pgtk_set_cr_source_with_color: %08lx.", color); Emacs_Color col; col.pixel = color; pgtk_query_color (f, &col); @@ -7395,7 +6958,6 @@ pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f) { - PGTK_TRACE ("pgtk_cr_draw_frame"); cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0); cairo_paint (cr); } @@ -7414,7 +6976,6 @@ pgtk_cr_accumulate_data (void *closure, const unsigned char *data, void pgtk_cr_destroy_frame_context (struct frame *f) { - PGTK_TRACE ("pgtk_cr_destroy_frame_context"); if (FRAME_CR_CONTEXT (f) != NULL) { cairo_destroy (FRAME_CR_CONTEXT (f)); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 46266fdfd9..635c5e6a61 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -38,20 +38,6 @@ along with GNU Emacs. If not, see . */ #include #endif -// #define PGTK_DEBUG 1 - -#ifdef PGTK_DEBUG -extern void -pgtk_log (const char *file, int lineno, const char *fmt, ...) -ATTRIBUTE_FORMAT_PRINTF (3, 4); -#define PGTK_TRACE(fmt, ...) pgtk_log (__FILE__, __LINE__, fmt, ## __VA_ARGS__) - extern void pgtk_backtrace (const char *file, int lineno); -#define PGTK_BACKTRACE() pgtk_backtrace (__FILE__, __LINE__) -#else -#define PGTK_TRACE(fmt, ...) ((void) 0) -#define PGTK_BACKTRACE() ((void) 0) -#endif - /* could use list to store these, but rest of emacs has a big infrastructure for managing a table of bitmap "records" */ struct pgtk_bitmap_record commit 209662c0bda0234ae10c22d3e10a29286d0ed933 Author: Yuuki Harano Date: Wed Nov 24 00:13:29 2021 +0900 * src/ftcrfont.c (ftcrfont_open): Revert redundant brace change. diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 42f5f9eab0..6a0411ff6d 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -136,9 +136,7 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) filename = XCAR (val); size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) - { size = pixel_size; - } block_input (); commit 4a5aa814ba7dc25ff87a94f640b3b675265766bd Author: Yuuki Harano Date: Wed Nov 24 00:07:42 2021 +0900 * src/frame.c (syms_of_frame): Revert frame_resize_pixelwise defaults to false It was just a workaround of mutter's bug, which is already fixed, so we can revert it. diff --git a/src/frame.c b/src/frame.c index 8044c16372..585be79bf2 100644 --- a/src/frame.c +++ b/src/frame.c @@ -6391,12 +6391,7 @@ With some window managers you may have to set this to non-nil in order to set the size of a frame in pixels, to maximize frames or to make them fullscreen. To resize your initial frame pixelwise, set this option to a non-nil value in your init file. */); -#ifndef HAVE_PGTK frame_resize_pixelwise = 0; -#else - /* https://gitlab.gnome.org/GNOME/mutter/-/issues/396 */ - frame_resize_pixelwise = true; -#endif DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize, doc: /* Whether frames should be resized implicitly. commit 1fd3b57a92788fcc5ce673d806e7615c60870344 Author: Yuuki Harano Date: Tue Nov 23 23:10:28 2021 +0900 * src/frame.c (Fframep): Fix comment diff --git a/src/frame.c b/src/frame.c index bb5d46f4ee..8044c16372 100644 --- a/src/frame.c +++ b/src/frame.c @@ -226,7 +226,7 @@ Value is: `w32' for an Emacs frame that is a window on MS-Windows display, `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display, `pc' for a direct-write MS-DOS frame, - `pgtk' for an Emacs frame running entirely in GTK. + `pgtk' for an Emacs frame running on pure GTK. See also `frame-live-p'. */) (Lisp_Object object) { commit b80a24b221e039995dfa82604a74b27e481604c4 Author: Yuuki Harano Date: Tue Nov 23 23:05:17 2021 +0900 * src/font.h: Remove redundant condition It is redundant because pgtk build always defines HAVE_FREETYPE. diff --git a/src/font.h b/src/font.h index a847f232f6..1da72cca07 100644 --- a/src/font.h +++ b/src/font.h @@ -822,7 +822,7 @@ extern Lisp_Object merge_font_spec (Lisp_Object, Lisp_Object); extern Lisp_Object font_make_entity (void); extern Lisp_Object font_make_object (int, Lisp_Object, int); -#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) || defined (HAVE_PGTK) +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) extern Lisp_Object font_build_object (int, Lisp_Object, Lisp_Object, double); #endif commit a68575a8146277bd08b4d09b7ca4329c0e5212e0 Author: Yuuki Harano Date: Tue Nov 23 22:59:18 2021 +0900 Enclose pgtk changes within #ifdef * src/emacsgtkfixed.c: * src/emacsgtkfixed.h: diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index 49c3dab921..78c952f805 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -51,6 +51,9 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); +#ifndef HAVE_PGTK +static GType emacs_fixed_get_type (void); +#endif G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) static EmacsFixed * diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h index 9b69bbb99d..4f7a4eb3f7 100644 --- a/src/emacsgtkfixed.h +++ b/src/emacsgtkfixed.h @@ -27,8 +27,10 @@ struct frame; G_BEGIN_DECLS +#ifdef HAVE_PGTK #define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) #define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) +#endif struct frame; @@ -47,7 +49,9 @@ struct _EmacsFixedClass GtkFixedClass parent_class; }; +#ifdef HAVE_PGTK extern GType emacs_fixed_get_type (void); +#endif extern GtkWidget *emacs_fixed_new (struct frame *f); commit bc53310aaf1a2b71c1476ae1fffb1b137fb8d617 Author: Yuuki Harano Date: Tue Nov 23 22:49:03 2021 +0900 * src/emacs.c (main): Combine two conditions to one diff --git a/src/emacs.c b/src/emacs.c index 790740deb1..adac8fc38a 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2287,10 +2287,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #ifdef HAVE_DBUS init_dbusbind (); #endif -#ifdef USE_GTK -#ifndef HAVE_PGTK +#if defined(USE_GTK) && !defined(HAVE_PGTK) init_xterm (); -#endif #endif /* This can create a thread that may call getenv, so it must follow commit b22323c3b66feb3c9c0f3086cc784fab9578ff7b Author: Yuuki Harano Date: Wed Nov 17 00:49:20 2021 +0900 Support xterm-mouse-mode mouse-4/5 When I opened both pgtk frame and terminal frame using daemon mode, I get mouse-4 on terminal frame and wheel-up on pgtk frame. I support both events as mwheel events at the same time. (Bug#50321) * lisp/mwheel.el (mouse-wheel-down-event): It is both mouse-4 and wheel-up. (mouse-wheel-up-event): mouse-5 and wheel-down. (mouse-wheel-left-event): mouse-6 and wheel-left. (mouse-wheel-right-event): mouse-7 and wheel-right. (mouse-wheel--button-eq): New function to test a button is included in a list. (mouse-wheel--button-flatten): New function to make flatten list of events. (mwheel-scroll): Use mouse-wheel--button-eq instead of eq. (mouse-wheel-text-scale): Use mouse-wheel--button-eq instead of eq. (mouse-wheel--setup-bindings): Make it flatten. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index cb1997801b..4627142757 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -55,18 +55,24 @@ (mouse-wheel-mode 1))) (defcustom mouse-wheel-down-event - (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) - 'wheel-up - 'mouse-4) + (cond ((or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-up) + ((featurep 'pgtk-win) + '(mouse-4 wheel-up)) + (t + 'mouse-4)) "Event used for scrolling down." :group 'mouse :type 'symbol :set 'mouse-wheel-change-button) (defcustom mouse-wheel-up-event - (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) - 'wheel-down - 'mouse-5) + (cond ((or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-down) + ((featurep 'pgtk-win) + '(mouse-5 wheel-down)) + (t + 'mouse-5)) "Event used for scrolling up." :group 'mouse :type 'symbol @@ -221,15 +227,21 @@ Also see `mouse-wheel-tilt-scroll'." "Function that does the job of scrolling right.") (defvar mouse-wheel-left-event - (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) - 'wheel-left - 'mouse-6) + (cond ((or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-left) + ((featurep 'pgtk-win) + '(mouse-6 wheel-left)) + (t + 'mouse-6)) "Event used for scrolling left.") (defvar mouse-wheel-right-event - (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) - 'wheel-right - 'mouse-7) + (cond ((or (featurep 'w32-win) (featurep 'ns-win)) + 'wheel-right) + ((featurep 'pgtk-win) + '(mouse-7 wheel-right)) + (t + 'mouse-7)) "Event used for scrolling right.") (defun mouse-wheel--get-scroll-window (event) @@ -259,6 +271,18 @@ active window." frame nil t))))) (mwheel-event-window event))) +(defun mouse-wheel--button-eq (btn lst) + "Test whether BTN is included in LST." + (cond ((listp lst) + (memq btn lst)) + (t + (eq lst btn)) + )) + +(defun mouse-wheel--button-flatten (&rest arg) + "Flatten ARG." + (flatten-list arg)) + (defun mwheel-scroll (event &optional arg) "Scroll up or down according to the EVENT. This should be bound only to mouse buttons 4, 5, 6, and 7 on @@ -296,14 +320,14 @@ value of ARG, and the command uses it in subsequent scrolls." (condition-case nil (unwind-protect (let ((button (mwheel-event-button event))) - (cond ((and (eq amt 'hscroll) (eq button mouse-wheel-down-event)) + (cond ((and (eq amt 'hscroll) (mouse-wheel--button-eq button mouse-wheel-down-event)) (when (and (natnump arg) (> arg 0)) (setq mouse-wheel-scroll-amount-horizontal arg)) (funcall (if mouse-wheel-flip-direction mwheel-scroll-left-function mwheel-scroll-right-function) mouse-wheel-scroll-amount-horizontal)) - ((eq button mouse-wheel-down-event) + ((mouse-wheel--button-eq button mouse-wheel-down-event) (condition-case nil (funcall mwheel-scroll-down-function amt) ;; Make sure we do indeed scroll to the beginning of ;; the buffer. @@ -318,14 +342,14 @@ value of ARG, and the command uses it in subsequent scrolls." ;; for a reason that escapes me. This problem seems ;; to only affect scroll-down. --Stef (set-window-start (selected-window) (point-min)))))) - ((and (eq amt 'hscroll) (eq button mouse-wheel-up-event)) + ((and (eq amt 'hscroll) (mouse-wheel--button-eq button mouse-wheel-up-event)) (when (and (natnump arg) (> arg 0)) (setq mouse-wheel-scroll-amount-horizontal arg)) (funcall (if mouse-wheel-flip-direction mwheel-scroll-right-function mwheel-scroll-left-function) mouse-wheel-scroll-amount-horizontal)) - ((eq button mouse-wheel-up-event) + ((mouse-wheel--button-eq button mouse-wheel-up-event) (condition-case nil (funcall mwheel-scroll-up-function amt) ;; Make sure we do indeed scroll to the end of the buffer. (end-of-buffer (while t (funcall mwheel-scroll-up-function))))) @@ -378,9 +402,9 @@ value of ARG, and the command uses it in subsequent scrolls." (button (mwheel-event-button event))) (select-window scroll-window 'mark-for-redisplay) (unwind-protect - (cond ((eq button mouse-wheel-down-event) + (cond ((mouse-wheel--button-eq button mouse-wheel-down-event) (text-scale-increase 1)) - ((eq button mouse-wheel-up-event) + ((mouse-wheel--button-eq button mouse-wheel-up-event) (text-scale-decrease 1))) (select-window selected-window)))) @@ -432,13 +456,16 @@ an event used for scrolling, such as `mouse-wheel-down-event'." (cond ;; Bindings for changing font size. ((and (consp binding) (eq (cdr binding) 'text-scale)) - (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event)) + (dolist (event (mouse-wheel--button-flatten mouse-wheel-down-event + mouse-wheel-up-event)) (mouse-wheel--add-binding `[,(list (caar binding) event)] 'mouse-wheel-text-scale))) ;; Bindings for scrolling. (t - (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event - mouse-wheel-left-event mouse-wheel-right-event)) + (dolist (event (mouse-wheel--button-flatten mouse-wheel-down-event + mouse-wheel-up-event + mouse-wheel-left-event + mouse-wheel-right-event)) (dolist (key (mouse-wheel--create-scroll-keys binding event)) (mouse-wheel--add-binding key 'mwheel-scroll))))))) commit 47d0f6b5ecbf2a2b81364f9923ffe2b88ff19452 Author: Yuuki Harano Date: Wed Nov 17 00:28:34 2021 +0900 Remove garbage #ifndef Maybe it was left by git merge miss. It prevented feature/pgtk from successful X-build with xwidget. * src/xwidget.c (Fxwidget_resize): diff --git a/src/xwidget.c b/src/xwidget.c index 66a905d3f0..b58fe76a95 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1976,7 +1976,6 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, #ifdef USE_GTK if (xw->widget_osr) { -#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, xw->height); gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, commit 42ea8c21b48a49d52d1d6ea6e4a9af5abc19afdd Author: Yuuki Harano Date: Tue Nov 16 01:31:19 2021 +0900 ; * src/pgtkterm.c (pgtk_mouse_position): Add bug ID to the comment diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5d39276a88..f306b9c414 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3350,7 +3350,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, } } - /* f1 can be a terminal frame. */ + /* f1 can be a terminal frame. Bug#50322 */ if (f1 == NULL || !FRAME_PGTK_P (f1)) { unblock_input (); commit 20dd24c3a058d85f5e92311038fe4f561f00bf8f Author: Yuuki Harano Date: Tue Nov 16 01:19:12 2021 +0900 Avoid handle terminal frames in pgtk_mouse_position. Just above, f1 can become a selected frame, which may be a terminal frame. We can't call gtk_widget_get_window() for a terminal frame. * src/pgtkterm.c (pgtk_mouse_position): Return if it is not a pgtk frame. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0d258584c5..5d39276a88 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3350,6 +3350,13 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, } } + /* f1 can be a terminal frame. */ + if (f1 == NULL || !FRAME_PGTK_P (f1)) + { + unblock_input (); + return; + } + /* 2. get the display and the device. */ win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1)); GdkDisplay *gdpy = gdk_window_get_display (win); commit 37738c32aca5b6cf0811e957ced7e1d7385ef620 Author: Yuuki Harano Date: Mon Nov 15 21:11:26 2021 +0900 Fix coding style * src/gtkutil.c (xg_set_no_accept_focus): * src/pgtkterm.c (pgtk_focus_frame): (button_event): diff --git a/src/gtkutil.c b/src/gtkutil.c index 3e4d6e076f..cb33474711 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -2000,8 +2000,8 @@ xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus) #ifdef HAVE_PGTK if (!FRAME_GTK_OUTER_WIDGET (f)) { - if (FRAME_WIDGET(f)) - gtk_widget_set_can_focus (FRAME_WIDGET(f), g_no_accept_focus); + if (FRAME_WIDGET (f)) + gtk_widget_set_can_focus (FRAME_WIDGET (f), g_no_accept_focus); return; } #endif diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 978d4798d5..0d258584c5 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4707,7 +4707,7 @@ pgtk_focus_frame (struct frame *f, bool noactivate) if (dpyinfo->x_focus_frame != f && wid != NULL) { block_input (); - gtk_widget_grab_focus(wid); + gtk_widget_grab_focus (wid); unblock_input (); } } @@ -6460,7 +6460,7 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) { block_input (); - gtk_widget_grab_focus(FRAME_GTK_WIDGET(f)); + gtk_widget_grab_focus (FRAME_GTK_WIDGET (f)); if (FRAME_GTK_OUTER_WIDGET (f)) { gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); commit 6c1f0dd709a77a2fade006b5957553fc5abd7631 Author: Jeff Walsh Date: Mon Sep 27 00:20:57 2021 +1000 pgtk: Handle (child) frame focusing better child frames on pgtk are gtk widgets inside the parent surface, rather than subsurfaces (in wayland ters), and the edit widget is handled separately from the parent window, so we need to handle signals more correctly, rather than squinting and assuming an event for the window is just an event for the edit widget. * src/gtkutil.c (xg_set_no_accept_focus): set focus on widget rather than request it on window * src/pgtkterm.c (pgtk_focus_frame): focus frame on edit_widget instead (button_event): Implement focus calls to replace dead X calls diff --git a/src/gtkutil.c b/src/gtkutil.c index 6822aeb4e3..3e4d6e076f 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1996,16 +1996,19 @@ xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map) void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus) { + gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE; #ifdef HAVE_PGTK if (!FRAME_GTK_OUTER_WIDGET (f)) - return; + { + if (FRAME_WIDGET(f)) + gtk_widget_set_can_focus (FRAME_WIDGET(f), g_no_accept_focus); + return; + } #endif block_input (); if (FRAME_GTK_WIDGET (f)) { GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); - gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE; - gtk_window_set_accept_focus (gwin, g_no_accept_focus); } unblock_input (); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 75386ee6c3..978d4798d5 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4702,12 +4702,12 @@ pgtk_focus_frame (struct frame *f, bool noactivate) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - GtkWidget *wid = FRAME_GTK_OUTER_WIDGET (f); + GtkWidget *wid = FRAME_WIDGET (f); if (dpyinfo->x_focus_frame != f && wid != NULL) { block_input (); - gtk_window_present (GTK_WINDOW (wid)); + gtk_widget_grab_focus(wid); unblock_input (); } } @@ -6460,12 +6460,11 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) { block_input (); -#if 0 - XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - RevertToParent, CurrentTime); - if (FRAME_PARENT_FRAME (f)) - XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); -#endif + gtk_widget_grab_focus(FRAME_GTK_WIDGET(f)); + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_present (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); + } unblock_input (); } } commit f1a60225152af1f87d8580db0785cf5a0a9c7544 Author: Yuuki Harano Date: Sun Nov 14 23:43:15 2021 +0900 Add WAYLAND_DISPLAY description to cmdargs.texi * doc/emacs/cmdargs.texi (Misc Variables): Add WAYLAND_DISPLAY description. diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index 86c04c84a2..b1e471f6d6 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -756,6 +756,10 @@ On MS-Windows, if you set this variable, Emacs will load and initialize the network library at startup, instead of waiting until the first time it is required. +@item WAYLAND_DISPLAY +Pgtk Emacs (built with @option{--with-pgtk}) can run on Wayland natively. +@env{WAYLAND_DISPLAY} specifies the connection to the compositor. + @item emacs_dir On MS-Windows, @env{emacs_dir} is a special environment variable, which indicates the full path of the directory in which Emacs is installed. commit 11e4fd11bd6ef69e430a624910e990e9535c44d5 Author: Jeff Walsh Date: Sat Oct 2 00:28:19 2021 +1000 pgtk: Set correct face color for stretched glyphs * src/pgtkterm.c (x_draw_stretch_glyph_string): s/foreground/background (Bug#50579) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d81517a5d8..75386ee6c3 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2391,7 +2391,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s) color = s->xgcv.foreground; } else - color = s->face->foreground; + color = s->face->background; cairo_t *cr = pgtk_begin_cr_clip (s->f); commit 8b98aafe35033062921399ecb3bdca949a7e4a72 Author: Jeff Walsh Date: Sat Oct 2 00:50:08 2021 +1000 configure.ac (PGTK_LIBS): remove pgtk dl dependency (Bug#50494) diff --git a/configure.ac b/configure.ac index 3748bbcf07..d68cf42145 100644 --- a/configure.ac +++ b/configure.ac @@ -2856,7 +2856,7 @@ PGTK_OBJ= PGTK_LIBS= if test "$window_system" = "pgtk"; then PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o pgtkim.o xsettings.o" - PGTK_LIBS="$GTK_LIBS -ldl" + PGTK_LIBS="$GTK_LIBS" HAVE_PGTK=yes AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) fi commit 30a00f14c824e5e4005a1cb6ccf2f26def19d80b Author: Yuuki Harano Date: Sun Nov 14 20:27:31 2021 +0900 Fix coding style Especially, insert a space between function name and paren. * src/alloc.c (garbage_collect): * src/font.h: * src/frame.h: * src/fringe.c: * src/gtkutil.c (xg_set_screen): (xg_create_frame_widgets): (xg_create_frame_outer_widgets): (xg_get_file_name): (xg_get_font): (xg_update_scrollbar_pos): * src/image.c (image_create_bitmap_from_file): (xpm_load_image): * src/pgtkfns.c (pgtk_get_monitor_scale_factor): (is_wayland_display): (pgtk_display_info_for_name): (INSTALL_CURSOR): (Fx_create_frame): (Fx_display_mm_height): (Fx_display_mm_width): (Fx_display_pixel_width): (Fx_display_pixel_height): * src/pgtkselect.c (pgtk_selection_usable): (Fpgtk_own_selection_internal): (Fpgtk_get_selection_internal): * src/pgtkterm.c: (x_set_parent_frame): (pgtk_draw_fringe_bitmap): (pgtk_handle_draw): (scroll_event): (pgtk_text_scaling_factor): (pgtk_term_init): * src/pgtkterm.h: * src/window.h: * src/xdisp.c (redisplay_internal): (draw_glyphs_debug): (draw_glyphs): (note_mouse_highlight): diff --git a/src/alloc.c b/src/alloc.c index 9388cf1d08..22e3e8e2a1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -6145,7 +6145,7 @@ garbage_collect (void) mark_kboards (); mark_threads (); #ifdef HAVE_PGTK - mark_pgtkterm(); + mark_pgtkterm (); #endif #ifdef USE_GTK diff --git a/src/font.h b/src/font.h index 6ee7bcafff..a847f232f6 100644 --- a/src/font.h +++ b/src/font.h @@ -822,7 +822,7 @@ extern Lisp_Object merge_font_spec (Lisp_Object, Lisp_Object); extern Lisp_Object font_make_entity (void); extern Lisp_Object font_make_object (int, Lisp_Object, int); -#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) || defined(HAVE_PGTK) +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) || defined (HAVE_PGTK) extern Lisp_Object font_build_object (int, Lisp_Object, Lisp_Object, double); #endif diff --git a/src/frame.h b/src/frame.h index 3960776604..fa6cc4a561 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1684,7 +1684,7 @@ extern const char *x_get_resource_string (const char *, const char *); extern void x_sync (struct frame *); #endif /* HAVE_X_WINDOWS */ -#if !defined(HAVE_NS) && !defined(HAVE_PGTK) +#if !defined (HAVE_NS) && !defined (HAVE_PGTK) /* Set F's bitmap icon, if specified among F's parameters. */ diff --git a/src/fringe.c b/src/fringe.c index f22d095698..441146d135 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -1410,7 +1410,7 @@ If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. On W32 and MAC (little endian), there's no need to do this. */ -#if defined (HAVE_X_WINDOWS) || defined(HAVE_PGTK) +#if defined (HAVE_X_WINDOWS) || defined (HAVE_PGTK) static const unsigned char swap_nibble[16] = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ diff --git a/src/gtkutil.c b/src/gtkutil.c index 7f8a33c01d..6822aeb4e3 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -151,9 +151,9 @@ xg_set_screen (GtkWidget *w, struct frame *f) gtk_window_set_screen (GTK_WINDOW (w), gscreen); } #else - if (FRAME_X_DISPLAY(f) != DEFAULT_GDK_DISPLAY ()) + if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ()) { - GdkScreen *gscreen = gdk_display_get_default_screen (FRAME_X_DISPLAY(f)); + GdkScreen *gscreen = gdk_display_get_default_screen (FRAME_X_DISPLAY (f)); if (GTK_IS_MENU (w)) gtk_menu_set_screen (GTK_MENU (w), gscreen); @@ -1425,7 +1425,7 @@ xg_create_frame_widgets (struct frame *f) type = GTK_WINDOW_POPUP; } wtop = gtk_window_new (type); - gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK); #endif /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu @@ -1626,7 +1626,7 @@ xg_create_frame_outer_widgets (struct frame *f) block_input (); wtop = gtk_window_new (type); - gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + gtk_widget_add_events (wtop, GDK_ALL_EVENTS_MASK); xg_set_screen (wtop, f); @@ -2582,7 +2582,7 @@ xg_get_file_name (struct frame *f, #ifdef HAVE_PGTK if (!FRAME_GTK_OUTER_WIDGET (f)) - error("Can't open dialog from child frames"); + error ("Can't open dialog from child frames"); #endif #ifdef HAVE_GTK_FILE_SELECTION_NEW @@ -2684,7 +2684,7 @@ xg_get_font (struct frame *f, const char *default_name) #ifdef HAVE_PGTK if (!FRAME_GTK_OUTER_WIDGET (f)) - error("Can't open dialog from child frames"); + error ("Can't open dialog from child frames"); #endif w = gtk_font_chooser_dialog_new @@ -4437,7 +4437,7 @@ xg_update_scrollbar_pos (struct frame *f, /* Don't obscure any child frames. */ XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox)); #else - gdk_window_lower (gtk_widget_get_window(webox)); + gdk_window_lower (gtk_widget_get_window (webox)); #endif } diff --git a/src/image.c b/src/image.c index d03e16e5c8..a41a2a16a6 100644 --- a/src/image.c +++ b/src/image.c @@ -585,15 +585,15 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) #ifdef HAVE_PGTK GError *err = NULL; ptrdiff_t id; - void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); + void * bitmap = gdk_pixbuf_new_from_file (SSDATA (file), &err); if (!bitmap) { - g_error_free(err); + g_error_free (err); return -1; } - id = image_allocate_bitmap_record(f); + id = image_allocate_bitmap_record (f); dpyinfo->bitmaps[id - 1].img = bitmap; dpyinfo->bitmaps[id - 1].refcount = 1; @@ -5034,7 +5034,7 @@ xpm_load_image (struct frame *f, Lisp_Object (*get_color_table) (Lisp_Object, const char *, int); Lisp_Object frame, color_symbols, color_table; int best_key; -#if !defined(HAVE_NS) +#if !defined (HAVE_NS) bool have_mask = false; #endif Emacs_Pix_Container ximg = NULL, mask_img = NULL; diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 0f9f2e4c83..3c2ea02831 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -70,7 +70,7 @@ pgtk_get_monitor_scale_factor (const char *model) return 0.0; Lisp_Object mdl = build_string (model); - Lisp_Object tem = Fassoc(mdl, monitor_scale_factor_alist, Qnil); + Lisp_Object tem = Fassoc (mdl, monitor_scale_factor_alist, Qnil); if (NILP (tem)) return 0; Lisp_Object cdr = Fcdr (tem); @@ -134,10 +134,10 @@ check_pgtk_display_info (Lisp_Object object) * display. */ static Lisp_Object -is_wayland_display(Lisp_Object dpyname) +is_wayland_display (Lisp_Object dpyname) { const char *p = SSDATA (dpyname); - if (strncmp(p, "wayland-", 8) != 0) + if (strncmp (p, "wayland-", 8) != 0) return Qnil; p += 8; do { @@ -156,7 +156,7 @@ pgtk_display_info_for_name (Lisp_Object name) CHECK_STRING (name); - if (!NILP (is_wayland_display(name))) + if (!NILP (is_wayland_display (name))) { for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) if (!NILP (is_wayland_display (XCAR (dpyinfo->name_list_element)))) @@ -1615,7 +1615,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) #define INSTALL_CURSOR(FIELD, NAME) \ - FRAME_X_OUTPUT(f)->FIELD = gdk_cursor_new_for_display(FRAME_X_DISPLAY(f), GDK_ ## NAME) + FRAME_X_OUTPUT (f)->FIELD = gdk_cursor_new_for_display (FRAME_X_DISPLAY (f), GDK_ ## NAME) INSTALL_CURSOR (text_cursor, XTERM); INSTALL_CURSOR (nontext_cursor, LEFT_PTR); @@ -1693,13 +1693,12 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) { - GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); - for (; w != NULL; w = w->next) - { - gtk_widget_show_all (GTK_WIDGET(w->data)); - } - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + GList *w = gtk_container_get_children (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f))); + for (; w != NULL; w = w->next) + gtk_widget_show_all (GTK_WIDGET (w->data)); + } gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); @@ -2204,7 +2203,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */) int mm = gdk_monitor_get_height_mm (monitor); if (rec.y == 0) - height_mm_at_0 = max(height_mm_at_0, mm); + height_mm_at_0 = max (height_mm_at_0, mm); else height_mm_at_other += mm; } @@ -2245,7 +2244,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */) int mm = gdk_monitor_get_width_mm (monitor); if (rec.x == 0) - width_mm_at_0 = max(width_mm_at_0, mm); + width_mm_at_0 = max (width_mm_at_0, mm); else width_mm_at_other += mm; } @@ -2572,7 +2571,7 @@ each physical monitor, use `display-monitor-attributes-list'. */) rec.width = rec.width * scale + 0.5; rec.height = rec.height * scale + 0.5; - width = max(width, rec.x + rec.width); + width = max (width, rec.x + rec.width); } unblock_input (); @@ -2618,7 +2617,7 @@ each physical monitor, use `display-monitor-attributes-list'. */) rec.width = rec.width * scale + 0.5; rec.height = rec.height * scale + 0.5; - height = max(height, rec.y + rec.height); + height = max (height, rec.y + rec.height); } unblock_input (); diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 447c839f45..58a2b0d05e 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -249,48 +249,48 @@ pgtk_selection_usable (void) * * static GtkWidget *top1, *top2; * - * int main(int argc, char **argv) + * int main (int argc, char **argv) * { * GtkWidget *w; * GtkTextBuffer *buf; * - * gtk_init(&argc, &argv); + * gtk_init (&argc, &argv); * * static char *text = "\ * It is fine today.\n\ * It will be fine tomorrow too.\n\ * It is too hot."; * - * top1 = gtk_window_new(GTK_WINDOW_TOPLEVEL); - * gtk_window_set_title(GTK_WINDOW(top1), "default"); - * gtk_widget_show(top1); - * w = gtk_text_view_new(); - * gtk_container_add(GTK_CONTAINER(top1), w); - * gtk_widget_show(w); - * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); - * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text)); - * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY)); + * top1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + * gtk_window_set_title (GTK_WINDOW (top1), "default"); + * gtk_widget_show (top1); + * w = gtk_text_view_new (); + * gtk_container_add (GTK_CONTAINER (top1), w); + * gtk_widget_show (w); + * buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w)); + * gtk_text_buffer_insert_at_cursor (buf, text, strlen (text)); + * gtk_text_buffer_add_selection_clipboard (buf, gtk_widget_get_clipboard (w, GDK_SELECTION_PRIMARY)); * - * unsetenv("GDK_BACKEND"); + * unsetenv ("GDK_BACKEND"); * GdkDisplay *gdpy; * const char *dpyname2; - * if (strcmp(G_OBJECT_TYPE_NAME(gtk_widget_get_window(top1)), "GdkWaylandWindow") == 0) + * if (strcmp (G_OBJECT_TYPE_NAME (gtk_widget_get_window (top1)), "GdkWaylandWindow") == 0) * dpyname2 = ":0"; * else * dpyname2 = "wayland-0"; * gdpy = gdk_display_open (dpyname2); * top2 = gtk_window_new (GTK_WINDOW_TOPLEVEL); - * gtk_window_set_title(GTK_WINDOW(top2), dpyname2); - * gtk_window_set_screen (GTK_WINDOW (top2), gdk_display_get_default_screen(gdpy)); + * gtk_window_set_title (GTK_WINDOW (top2), dpyname2); + * gtk_window_set_screen (GTK_WINDOW (top2), gdk_display_get_default_screen (gdpy)); * gtk_widget_show (top2); - * w = gtk_text_view_new(); - * gtk_container_add(GTK_CONTAINER(top2), w); - * gtk_widget_show(w); - * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); - * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text)); - * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY)); + * w = gtk_text_view_new (); + * gtk_container_add (GTK_CONTAINER (top2), w); + * gtk_widget_show (w); + * buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w)); + * gtk_text_buffer_insert_at_cursor (buf, text, strlen (text)); + * gtk_text_buffer_add_selection_clipboard (buf, gtk_widget_get_clipboard (w, GDK_SELECTION_PRIMARY)); * - * gtk_main(); + * gtk_main (); * * return 0; * } @@ -376,8 +376,8 @@ nil, it defaults to the selected frame. */) { /* text/plain: Strings encoded by Gtk are not correctly decoded by Chromium(Wayland). */ - GdkAtom atom_text_plain = gdk_atom_intern("text/plain", false); - gtk_target_list_remove(list, atom_text_plain); + GdkAtom atom_text_plain = gdk_atom_intern ("text/plain", false); + gtk_target_list_remove (list, atom_text_plain); } targets = gtk_target_table_new_from_list (list, &n_targets); @@ -575,11 +575,11 @@ On PGTK, TIME-STAMP is unused. */) property `foreign-selection' so that the caller of x-get-selection-internal (usually x-get-selection) can know that the string must be decode. */ - if (sd_type == gdk_atom_intern("COMPOUND_TEXT", false)) + if (sd_type == gdk_atom_intern ("COMPOUND_TEXT", false)) lispy_type = QCOMPOUND_TEXT; - else if (sd_type == gdk_atom_intern("UTF8_STRING", false)) + else if (sd_type == gdk_atom_intern ("UTF8_STRING", false)) lispy_type = QUTF8_STRING; - else if (sd_type == gdk_atom_intern("text/plain;charset=utf-8", false)) + else if (sd_type == gdk_atom_intern ("text/plain;charset=utf-8", false)) lispy_type = Qtext_plain_charset_utf_8; else lispy_type = QSTRING; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 40489c0c6b..d81517a5d8 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -67,7 +67,7 @@ along with GNU Emacs. If not, see . */ #define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) #define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active) -#define FRAME_CR_SURFACE(f) (cairo_get_target(FRAME_CR_CONTEXT(f))) +#define FRAME_CR_SURFACE(f) (cairo_get_target (FRAME_CR_CONTEXT (f))) #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ ((f)->output_data.pgtk->cr_surface_desired_width) #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ @@ -829,7 +829,7 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, GtkWidget *fixed = FRAME_GTK_WIDGET (f); GtkAllocation alloc; - gtk_widget_get_allocation(fixed, &alloc); + gtk_widget_get_allocation (fixed, &alloc); g_object_ref (fixed); GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider; @@ -3545,7 +3545,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, p->wd, p->h, p->x, p->y, p->overlay_p); } - pgtk_end_cr_clip(f); + pgtk_end_cr_clip (f); } static struct atimer *hourglass_atimer = NULL; @@ -5368,7 +5368,7 @@ pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) PGTK_TRACE (" garbaged=%d", f->garbaged); PGTK_TRACE (" scroll_bar_width=%f", (double) PGTK_SCROLL_BAR_WIDTH (f)); - // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); + // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST (f)); PGTK_TRACE (" scroll_bar_cols=%d", FRAME_SCROLL_BAR_COLS (f)); PGTK_TRACE (" column_width=%d", FRAME_COLUMN_WIDTH (f)); cairo_set_source_surface (cr, src, 0, 0); @@ -6611,7 +6611,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= down_modifier; - inev.ie.arg = make_fixnum(nlines); + inev.ie.arg = make_fixnum (nlines); dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines; } else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line) @@ -6619,7 +6619,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - inev.ie.arg = make_fixnum(nlines); + inev.ie.arg = make_fixnum (nlines); dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines; } else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char) @@ -6627,7 +6627,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - inev.ie.arg = make_fixnum(nchars); + inev.ie.arg = make_fixnum (nchars); dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; } else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char) @@ -6635,7 +6635,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= down_modifier; - inev.ie.arg = make_fixnum(nchars); + inev.ie.arg = make_fixnum (nchars); dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; } } @@ -6806,7 +6806,7 @@ same_x_server (const char *name1, const char *name2) #define GNOME_INTERFACE_SCHEMA "org.gnome.desktop.interface" -static gdouble pgtk_text_scaling_factor(void) +static gdouble pgtk_text_scaling_factor (void) { GSettingsSchemaSource *schema_source = g_settings_schema_source_get_default (); if (schema_source != NULL) @@ -6999,7 +6999,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) if (dpi < 0) dpi = 96.0; - dpi *= pgtk_text_scaling_factor(); + dpi *= pgtk_text_scaling_factor (); dpyinfo->resx = dpi; dpyinfo->resy = dpi; } diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c87a5e13ec..46266fdfd9 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -44,9 +44,9 @@ along with GNU Emacs. If not, see . */ extern void pgtk_log (const char *file, int lineno, const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF (3, 4); -#define PGTK_TRACE(fmt, ...) pgtk_log(__FILE__, __LINE__, fmt, ## __VA_ARGS__) +#define PGTK_TRACE(fmt, ...) pgtk_log (__FILE__, __LINE__, fmt, ## __VA_ARGS__) extern void pgtk_backtrace (const char *file, int lineno); -#define PGTK_BACKTRACE() pgtk_backtrace(__FILE__, __LINE__) +#define PGTK_BACKTRACE() pgtk_backtrace (__FILE__, __LINE__) #else #define PGTK_TRACE(fmt, ...) ((void) 0) #define PGTK_BACKTRACE() ((void) 0) @@ -434,26 +434,26 @@ enum #define FRAME_X_OUTPUT(f) ((f)->output_data.pgtk) #define FRAME_OUTPUT_DATA(f) FRAME_X_OUTPUT (f) -#define FRAME_DISPLAY_INFO(f) (FRAME_X_OUTPUT(f)->display_info) -#define FRAME_FOREGROUND_COLOR(f) (FRAME_X_OUTPUT(f)->foreground_color) -#define FRAME_BACKGROUND_COLOR(f) (FRAME_X_OUTPUT(f)->background_color) -#define FRAME_CURSOR_COLOR(f) (FRAME_X_OUTPUT(f)->cursor_color) -#define FRAME_POINTER_TYPE(f) (FRAME_X_OUTPUT(f)->current_pointer) -#define FRAME_FONT(f) (FRAME_X_OUTPUT(f)->font) -#define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT(f)->widget) -#define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT(f)->edit_widget) -#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET(f) ? \ - FRAME_GTK_OUTER_WIDGET(f) : \ - FRAME_GTK_WIDGET(f)) +#define FRAME_DISPLAY_INFO(f) (FRAME_X_OUTPUT (f)->display_info) +#define FRAME_FOREGROUND_COLOR(f) (FRAME_X_OUTPUT (f)->foreground_color) +#define FRAME_BACKGROUND_COLOR(f) (FRAME_X_OUTPUT (f)->background_color) +#define FRAME_CURSOR_COLOR(f) (FRAME_X_OUTPUT (f)->cursor_color) +#define FRAME_POINTER_TYPE(f) (FRAME_X_OUTPUT (f)->current_pointer) +#define FRAME_FONT(f) (FRAME_X_OUTPUT (f)->font) +#define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT (f)->widget) +#define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT (f)->edit_widget) +#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET (f) ? \ + FRAME_GTK_OUTER_WIDGET (f) : \ + FRAME_GTK_WIDGET (f)) /* aliases */ -#define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET(f) -#define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET(f) -#define FRAME_NATIVE_WINDOW(f) GTK_WINDOW(FRAME_X_WINDOW(f)) +#define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET (f) +#define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET (f) +#define FRAME_NATIVE_WINDOW(f) GTK_WINDOW (FRAME_X_WINDOW (f)) -#define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO(f)->gdpy) +#define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO (f)->gdpy) -#define DEFAULT_GDK_DISPLAY() gdk_display_get_default() +#define DEFAULT_GDK_DISPLAY() gdk_display_get_default () /* Turning a lisp vector value into a pointer to a struct scroll_bar. */ #define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec)) @@ -495,7 +495,7 @@ enum (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \ - PGTK_SCROLL_BAR_HEIGHT (f)) : 0) -#define FRAME_MENUBAR_HEIGHT(f) (FRAME_X_OUTPUT(f)->menubar_height) +#define FRAME_MENUBAR_HEIGHT(f) (FRAME_X_OUTPUT (f)->menubar_height) /* Calculate system coordinates of the left and top of the parent window or, if there is no parent window, the screen. */ @@ -521,9 +521,9 @@ enum #define FRAME_TOOLBAR_WIDTH(f) \ (FRAME_TOOLBAR_LEFT_WIDTH (f) + FRAME_TOOLBAR_RIGHT_WIDTH (f)) -#define FRAME_FONTSET(f) (FRAME_X_OUTPUT(f)->fontset) +#define FRAME_FONTSET(f) (FRAME_X_OUTPUT (f)->fontset) -#define FRAME_BASELINE_OFFSET(f) (FRAME_X_OUTPUT(f)->baseline_offset) +#define FRAME_BASELINE_OFFSET(f) (FRAME_X_OUTPUT (f)->baseline_offset) #define BLACK_PIX_DEFAULT(f) 0x000000 #define WHITE_PIX_DEFAULT(f) 0xFFFFFF diff --git a/src/window.h b/src/window.h index 3a75c99813..8e9a2eb317 100644 --- a/src/window.h +++ b/src/window.h @@ -756,7 +756,7 @@ wset_next_buffers (struct window *w, Lisp_Object val) #endif /* True if W is a tab bar window. */ -#if defined (HAVE_WINDOW_SYSTEM) && !defined(HAVE_PGTK) +#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_PGTK) # define WINDOW_TAB_BAR_P(W) \ (WINDOWP (WINDOW_XFRAME (W)->tab_bar_window) \ && (W) == XWINDOW (WINDOW_XFRAME (W)->tab_bar_window)) diff --git a/src/xdisp.c b/src/xdisp.c index 1ecc6aa9cf..5b67bcf5dc 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -15650,7 +15650,7 @@ redisplay_internal (void) if (!fr->glyphs_initialized_p) return; -#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) +#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined (HAVE_PGTK)) || defined (HAVE_NS) if (popup_activated ()) { return; @@ -29341,7 +29341,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, return x_reached; } -static int draw_glyphs_debug(const char *file, int lineno, +static int draw_glyphs_debug (const char *file, int lineno, struct window *w, int x, struct glyph_row *row, enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end, enum draw_glyphs_face hl, int overlaps) @@ -29349,7 +29349,7 @@ static int draw_glyphs_debug(const char *file, int lineno, return draw_glyphs(w, x, row, area, start, end, hl, overlaps); } #define draw_glyphs(w, x, r, a, s, e, h, o) \ - draw_glyphs_debug(__FILE__, __LINE__, w, x, r, a, s, e, h, o) + draw_glyphs_debug (__FILE__, __LINE__, w, x, r, a, s, e, h, o) /* Find the first glyph in the run of underlined glyphs preceding the beginning of glyph string S, and return its font (which could be @@ -33708,7 +33708,7 @@ note_mouse_highlight (struct frame *f, int x, int y) struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ -#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) || defined (MSDOS) +#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined (HAVE_PGTK)) || defined (HAVE_NS) || defined (MSDOS) if (popup_activated ()) return; #endif commit 3e20d50fc5a8fc94b571e140a696ccd65040e6c1 Author: Yuuki Harano Date: Sat Nov 13 16:41:29 2021 +0900 Revert #if changes I changed some "#ifdef"s to "#if defined"s by mistake, so I reverted them. * src/alloc.c: Reverted. (garbage_collect): Reverted. * src/emacs.c (main): Reverted. * src/image.c (xpm_load_image): Reverted. (image_disable_image): Reverted. (image_build_heuristic_mask): Reverted. diff --git a/src/alloc.c b/src/alloc.c index 2d25f8205a..9388cf1d08 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -96,7 +96,7 @@ along with GNU Emacs. If not, see . */ #include #include -#if defined(USE_GTK) +#ifdef USE_GTK # include "gtkutil.h" #endif #ifdef WINDOWSNT @@ -6148,7 +6148,7 @@ garbage_collect (void) mark_pgtkterm(); #endif -#if defined(USE_GTK) +#ifdef USE_GTK xg_mark_data (); #endif diff --git a/src/emacs.c b/src/emacs.c index 925f167d5f..790740deb1 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2287,7 +2287,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #ifdef HAVE_DBUS init_dbusbind (); #endif -#if defined(USE_GTK) +#ifdef USE_GTK #ifndef HAVE_PGTK init_xterm (); #endif diff --git a/src/image.c b/src/image.c index f911da51ea..d03e16e5c8 100644 --- a/src/image.c +++ b/src/image.c @@ -5088,7 +5088,7 @@ xpm_load_image (struct frame *f, } if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0) -#if !defined(HAVE_NS) +#ifndef HAVE_NS || !image_create_x_image_and_pixmap (f, img, width, height, 1, &mask_img, 1) #endif @@ -5216,7 +5216,7 @@ xpm_load_image (struct frame *f, PUT_PIXEL (ximg, x, y, FIXNUMP (color_val) ? XFIXNUM (color_val) : frame_fg); -#if !defined(HAVE_NS) +#ifndef HAVE_NS PUT_PIXEL (mask_img, x, y, (!EQ (color_val, Qt) ? PIX_MASK_DRAW : (have_mask = true, PIX_MASK_RETAIN))); @@ -5237,7 +5237,7 @@ xpm_load_image (struct frame *f, IMAGE_BACKGROUND (img, f, ximg); image_put_x_image (f, img, ximg, 0); -#if !defined(HAVE_NS) +#ifndef HAVE_NS if (have_mask) { /* Fill in the background_transparent field while we have the @@ -5968,7 +5968,7 @@ image_disable_image (struct frame *f, struct image *img) if (n_planes < 2 || cross_disabled_images) { #ifndef HAVE_NTGUI -#if !defined(HAVE_NS) /* TODO: NS support, however this not needed for toolbars */ +#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ #ifndef USE_CAIRO #define CrossForeground(f) BLACK_PIX_DEFAULT (f) @@ -6046,7 +6046,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, image_clear_image_1 (f, img, CLEAR_IMAGE_MASK); #ifndef HAVE_NTGUI -#if !defined HAVE_NS +#ifndef HAVE_NS /* Create an image and pixmap serving as mask. */ if (! image_create_x_image_and_pixmap (f, img, img->width, img->height, 1, &mask_img, 1)) @@ -6108,7 +6108,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, if (XGetPixel (ximg, x, y) == bg) ns_set_alpha (ximg, x, y, 0); #endif /* HAVE_NS */ -#if !defined HAVE_NS +#ifndef HAVE_NS /* Fill in the background_transparent field while we have the mask handy. */ image_background_transparent (img, f, mask_img); commit c31d3dacf7f153589b6e7a5f5204937c64e7fd24 Merge: c3377ae3b7 b4c6ab8cb6 Author: Yuuki Harano Date: Sat Nov 13 16:25:48 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit c3377ae3b7fdb8714e03586589d1b2804cf08e17 Author: Yuuki Harano Date: Sat Nov 13 16:02:46 2021 +0900 Revert atimer changes They seem to be not needed any more. * src/atimer.c (set_alarm): Revert (turn_on_atimers): Revert (have_buggy_timerfd): Revert diff --git a/src/atimer.c b/src/atimer.c index 197b504bf5..490c21bff1 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -310,13 +310,10 @@ set_alarm (void) ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; # ifdef HAVE_TIMERFD - if (timerfd >= 0) + if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) { - if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) - { - add_timer_wait_descriptor (timerfd); - exit = true; - } + add_timer_wait_descriptor (timerfd); + exit = true; } # endif if (alarm_timer_ok @@ -467,8 +464,7 @@ turn_on_atimers (bool on) if (alarm_timer_ok) timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0); # ifdef HAVE_TIMERFD - if (timerfd >= 0) - timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); + timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); # endif #endif alarm (0); @@ -575,9 +571,6 @@ have_buggy_timerfd (void) # ifdef CYGWIN struct utsname name; return uname (&name) < 0 || strverscmp (name.release, "3.0.2") < 0; -# elif defined HAVE_PGTK - /* pgtk emacs does not want timerfd. */ - return true; # else return false; # endif commit 60623aceed5486939c28fecf2790acd7e4ac6318 Merge: 4dd1f56f29 b4204bdae8 Author: Yuuki Harano Date: Fri Nov 12 00:21:12 2021 +0900 Merge branch 'feature/pgtk' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 4dd1f56f29fc598a8339a345c2f8945250600602 Merge: 4c49ec7f86 810fa21d26 Author: Yuuki Harano Date: Thu Nov 11 00:39:53 2021 +0900 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs into feature/pgtk commit b4204bdae83695089a27141602a955339df78b7a Author: Sharaf Zaman Date: Sat Oct 23 14:01:55 2021 +0000 Fix a memory leak in pgtk_draw_fringe_bitmap * src/pgtkterm.c (pgtk_draw_fringe_bitmap): we had an unbalanced cairo_save/restore. Copyright-paperwork-exempt: yes diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 86074d010d..40489c0c6b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3504,7 +3504,6 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct face *face = p->face; cairo_t *cr = pgtk_begin_cr_clip (f); - cairo_save (cr); /* Must clip because of partially visible lines. */ pgtk_clip_to_row (w, row, ANY_AREA, cr); @@ -3546,7 +3545,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, p->wd, p->h, p->x, p->y, p->overlay_p); } - cairo_restore (cr); + pgtk_end_cr_clip(f); } static struct atimer *hourglass_atimer = NULL; commit 4c49ec7f865bdad1629d2f125f71f4e506b258f2 Author: Yuuki Harano Date: Mon Aug 16 23:01:11 2021 +0900 Make PGTK's additions conditioinal * src/.gdbinit: Make them enclosed in condition. * src/alloc.c: Define defined_HAVE_PGTK and make it externally visible. diff --git a/src/.gdbinit b/src/.gdbinit index 53e17df636..68db1ff3ea 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -42,7 +42,9 @@ handle SIGUSR2 noprint pass handle SIGALRM ignore # On selection send failed. -handle SIGPIPE nostop noprint +if defined_HAVE_PGTK + handle SIGPIPE nostop noprint +end # Use $bugfix so that the value isn't a constant. # Using a constant runs into GDB bugs sometimes. @@ -1227,7 +1229,9 @@ set print pretty on set print sevenbit-strings show environment DISPLAY -show environment WAYLAND_DISPLAY +if defined_HAVE_PGTK + show environment WAYLAND_DISPLAY +end show environment TERM # When debugging, it is handy to be able to "return" from diff --git a/src/alloc.c b/src/alloc.c index a17488ee1d..ff3670eeb1 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -7709,6 +7709,12 @@ enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = true }; enum defined_HAVE_X_WINDOWS { defined_HAVE_X_WINDOWS = false }; #endif +#ifdef HAVE_PGTK +enum defined_HAVE_PGTK { defined_HAVE_PGTK = true }; +#else +enum defined_HAVE_PGTK { defined_HAVE_PGTK = false }; +#endif + /* When compiled with GCC, GDB might say "No enum type named pvec_type" if we don't have at least one symbol with that type, and then xbacktrace could fail. Similarly for the other enums and @@ -7728,5 +7734,6 @@ union enum More_Lisp_Bits More_Lisp_Bits; enum pvec_type pvec_type; enum defined_HAVE_X_WINDOWS defined_HAVE_X_WINDOWS; + enum defined_HAVE_PGTK defined_HAVE_PGTK; } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; #endif /* __GNUC__ */ commit 2e561ab2276820896e6c1dd13406bfe9047bd1dc Author: Yuuki Harano Date: Mon Aug 16 21:50:32 2021 +0900 * lisp/term/pgtk-win.el (pgtk-preedit-text): Write doc string diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index f4247b030b..3df450070c 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -319,7 +319,11 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (defvar pgtk-preedit-overlay nil) -(defun pgtk-preedit-text (e) +(defun pgtk-preedit-text (event) + "An internal function to display preedit text from input method. + +EVENT is an event of PGTK_PREEDIT_TEXT_EVENT. +It contains colors and texts." (interactive "e") (when pgtk-preedit-overlay (delete-overlay pgtk-preedit-overlay)) @@ -328,7 +332,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (let ((ovstr "") (idx 0) atts ov str color face-name) - (dolist (part (nth 1 e)) + (dolist (part (nth 1 event)) (setq str (car part)) (setq face-name (intern (format "pgtk-im-%d" idx))) (eval commit a925e6b2b571dec8e17fba73dba69503674cc49e Author: Yuuki Harano Date: Mon Aug 16 21:48:56 2021 +0900 * lisp/term/pgtk-win.el (pgtk-face-at-pos): Remove unused function diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 57e8d14dcf..f4247b030b 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -226,43 +226,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (insert (gui-get-selection 'SECONDARY))) -;;;; Color support. - -;; Functions for color panel + drag -(defun pgtk-face-at-pos (pos) - (let* ((frame (car pos)) - (frame-pos (cons (cadr pos) (cddr pos))) - (window (window-at (car frame-pos) (cdr frame-pos) frame)) - (window-pos (coordinates-in-window-p frame-pos window)) - (buffer (window-buffer window)) - (edges (window-edges window))) - (cond - ((not window-pos) - nil) - ((eq window-pos 'mode-line) - 'mode-line) - ((eq window-pos 'vertical-line) - 'default) - ((consp window-pos) - (with-current-buffer buffer - (let ((p (car (compute-motion (window-start window) - (cons (nth 0 edges) (nth 1 edges)) - (window-end window) - frame-pos - (- (window-width window) 1) - nil - window)))) - (cond - ((eq p (window-point window)) - 'cursor) - ((and mark-active (< (region-beginning) p) (< p (region-end))) - 'region) - (t - (let ((faces (get-char-property p 'face window))) - (if (consp faces) (car faces) faces))))))) - (t - nil)))) - (defun pgtk-suspend-error () ;; Don't allow suspending if any of the frames are PGTK frames. (if (memq 'pgtk (mapcar 'window-system (frame-list))) commit 4ed859359c7f6771f43b08a4dc2e35e60638d07e Author: Yuuki Harano Date: Sun Aug 15 18:30:47 2021 +0900 * lisp/term/pgtk-win.el: Remove some font stuff pgtk-popup-font-panel does not exist. pgtk-respond-to-change-font is not used. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 3b046cc61a..57e8d14dcf 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -195,28 +195,6 @@ the last file dropped is selected." ;; Needed for font listing functions under both backend and normal (setq scalable-fonts-allowed t) -;; Set to use font panel instead -(declare-function pgtk-popup-font-panel "pgtkfns.c" (&optional frame)) -(defalias 'x-select-font 'pgtk-popup-font-panel "Pop up the font panel. -This function has been overloaded in Nextstep.") -(defalias 'mouse-set-font 'pgtk-popup-font-panel "Pop up the font panel. -This function has been overloaded in Nextstep.") - -;; pgtkterm.c -(defvar pgtk-input-font) -(defvar pgtk-input-fontsize) - -(defun pgtk-respond-to-change-font () - "Respond to changeFont: event, expecting `pgtk-input-font' and\n\ -`pgtk-input-fontsize' of new font." - (interactive) - (modify-frame-parameters (selected-frame) - (list (cons 'fontsize pgtk-input-fontsize))) - (modify-frame-parameters (selected-frame) - (list (cons 'font pgtk-input-font))) - (set-frame-font pgtk-input-font)) - - ;; Default fontset. This is mainly here to show how a fontset ;; can be set up manually. Ordinarily, fontsets are auto-created whenever ;; a font is chosen by @@ -225,9 +203,7 @@ This function has been overloaded in Nextstep.") ;; "-pgtk-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai" (mapconcat 'identity '("-*-Monospace-*-*-*-*-10-*-*-*-*-*-fontset-standard" - "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1" - "han:-*-Kai-*-*-*-*-10-*-*-*-*-*-iso10646-1" - "cyrillic:-*-Trebuchet$MS-*-*-*-*-10-*-*-*-*-*-iso10646-1") + "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1") ",") "String of fontset spec of the standard fontset. This defines a fontset consisting of the Courier and other fonts. commit 35906d60e6aa92de487fdc88a575a4c04d7d314a Author: Yuuki Harano Date: Sun Aug 15 18:28:45 2021 +0900 * lisp/term/pgtk-win.el (pgtk-pop-up-frames): Remove since it is not used diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 4f1810c1de..3b046cc61a 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -65,16 +65,6 @@ ;;;; File handling. -(defcustom pgtk-pop-up-frames 'fresh - "Non-nil means open files upon request from the Workspace in a new frame. -If t, always do so. Any other non-nil value means open a new frame -unless the current buffer is a scratch buffer." - :type '(choice (const :tag "Never" nil) - (const :tag "Always" t) - (other :tag "Except for scratch buffer" fresh)) - :version "23.1" - :group 'pgtk) - (declare-function pgtk-hide-emacs "pgtkfns.c" (on)) commit 299cfb413f1f374420a2a24007d8a98e39123f52 Author: Yuuki Harano Date: Sun Aug 15 17:15:54 2021 +0900 * configure.ac: Add a notice to --with-pgtk diff --git a/configure.ac b/configure.ac index b1ce80c6f0..6ebb966700 100644 --- a/configure.ac +++ b/configure.ac @@ -468,7 +468,7 @@ AC_ARG_WITH([ns],[AS_HELP_STRING([--with-ns], [use Nextstep (macOS Cocoa or GNUstep) windowing system. On by default on macOS.])],[],[with_ns=maybe]) OPTION_DEFAULT_OFF([w32], [use native MS Windows GUI in a Cygwin build]) -OPTION_DEFAULT_OFF([pgtk], [use pure GTK build without reliance on X libs (Wayland support) - Experimental]) +OPTION_DEFAULT_OFF([pgtk], [use pure GTK build without reliance on X libs (Wayland support) (requires cairo) - Experimental]) OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console]) OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support]) commit c76d5ff2430fe49d2e498bf75214145fb6620255 Author: Yuuki Harano Date: Sun Aug 15 17:07:56 2021 +0900 * configure.ac: Remove imagemagick special support code for pgtk When emacs did not support imagemagick 7 and I had imagemagick both 6 and 7, I wanted to use imagemagick 6. The code is not needed any more. diff --git a/configure.ac b/configure.ac index 50bbf89d3d..b1ce80c6f0 100644 --- a/configure.ac +++ b/configure.ac @@ -2613,11 +2613,6 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${window_sys EMACS_CHECK_MODULES([IMAGEMAGICK], [Wand >= 6.3.5 Wand != 6.8.2]) fi - if test $HAVE_IMAGEMAGICK != yes; then - IMAGEMAGICK_MODULE="MagickWand-6.Q16HDRI >= 6.3.5 MagickWand-6.Q16HDRI != 6.8.2 MagickWand-6.Q16HDRI < 7 MagickCore-6.Q16HDRI >= 6.9.9 MagickCore-6.Q16HDRI < 7" - EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE]) - fi - if test $HAVE_IMAGEMAGICK = yes; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS commit 13a9a5e836cbe6e64aadaba40fe1f7eb83320d08 Merge: b242394f24 41a55a330f Author: Yuuki Harano Date: Sun Jul 25 23:34:55 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit b242394f24b154f8e20f5abf4b2f826629e99ea6 Merge: 492a0ae592 6b802a08ca Author: Yuuki Harano Date: Sun Jul 18 18:44:54 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 492a0ae5927eda83b65dd08d3e1655a62fc2c43d Merge: 01b0a909b5 2f2afa0b31 Author: Yuuki Harano Date: Sun Jul 4 22:37:03 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 01b0a909b5ca858a09484821cc866127652f4153 Merge: 11c835ea48 a17f40911e Author: Yuuki Harano Date: Sun Jun 20 18:17:23 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 11c835ea48b971faf21dd94e40721e9ed0a8265a Author: Yuuki Harano Date: Fri Jun 18 23:08:54 2021 +0900 Fix a frame created without scroll/menu/toolbar is empty * src/pgtkterm.c (size_allocate): Get frame pointer through user_data. (pgtk_set_event_handler): Pass it. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 13bd442ad9..86074d010d 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5381,12 +5381,24 @@ pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) static void size_allocate (GtkWidget * widget, GtkAllocation * alloc, - gpointer * user_data) + gpointer user_data) { PGTK_TRACE ("size-alloc: %dx%d+%d+%d.", alloc->width, alloc->height, alloc->x, alloc->y); struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + + /* Between a frame is created and not shown, size is allocated and + * this handler is called. When that, since the widget's window is + * NULL, we can't get f, pgtk_cr_update_surface_desired_size is not + * called, and its size is 0x0. That causes empty frame. + * + * Fortunately since we know f in pgtk_set_event_handler, we can get + * it through user_data; + */ + if (!f) + f = user_data; + if (f) { PGTK_TRACE ("%dx%d", alloc->width, alloc->height); @@ -6705,7 +6717,7 @@ pgtk_set_event_handler (struct frame *f) g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event", G_CALLBACK (map_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate", - G_CALLBACK (size_allocate), NULL); + G_CALLBACK (size_allocate), f); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event", G_CALLBACK (key_press_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-release-event", commit 3dbd3a87a1a81b7c70a1131563d9e5aee1d974d3 Author: Yuuki Harano Date: Fri Jun 18 22:59:36 2021 +0900 Revert "Revert "* src/pgtkfns.c: Do not show an empty frame prematurely"" This reverts commit b0d688673b0be774c3735eef304f69568bd59bcf. The commit 83c35b8 causes the empty frame bug, so I reverted. Now, I debugged so re-apply the commit. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index ceff279ad0..0f9f2e4c83 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1693,8 +1693,13 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) - gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + if (FRAME_GTK_OUTER_WIDGET (f)) { + GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); + for (; w != NULL; w = w->next) + { + gtk_widget_show_all (GTK_WIDGET(w->data)); + } + } gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); commit b0d688673b0be774c3735eef304f69568bd59bcf Author: Yuuki Harano Date: Mon Jun 14 00:07:48 2021 +0900 Revert "* src/pgtkfns.c: Do not show an empty frame prematurely" This reverts commit 83c35b86da233870231e30d114ffa4640eb10081. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 0f9f2e4c83..ceff279ad0 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1693,13 +1693,8 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) { - GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); - for (; w != NULL; w = w->next) - { - gtk_widget_show_all (GTK_WIDGET(w->data)); - } - } + if (FRAME_GTK_OUTER_WIDGET (f)) + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); commit beb4e9f828af4fd8ed9b553ee9516744c2e69ad3 Author: Yuuki Harano Date: Mon Jun 14 00:07:34 2021 +0900 Revert "; * src/pgtkfns.c (Fx_create_frame): Fix coding style" This reverts commit 4b91168c657e3476b8a0a3f539ee6bcb1b71e3d5. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index ce6775d93d..0f9f2e4c83 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1693,14 +1693,13 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) - { - GList *w = gtk_container_get_children (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f))); - for (; w != NULL; w = w->next) - { - gtk_widget_show_all (GTK_WIDGET (w->data)); - } - } + if (FRAME_GTK_OUTER_WIDGET (f)) { + GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); + for (; w != NULL; w = w->next) + { + gtk_widget_show_all (GTK_WIDGET(w->data)); + } + } gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); commit 4b91168c657e3476b8a0a3f539ee6bcb1b71e3d5 Author: Yuuki Harano Date: Sun Jun 13 18:26:43 2021 +0900 ; * src/pgtkfns.c (Fx_create_frame): Fix coding style diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 0f9f2e4c83..ce6775d93d 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1693,13 +1693,14 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) { - GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); - for (; w != NULL; w = w->next) - { - gtk_widget_show_all (GTK_WIDGET(w->data)); - } - } + if (FRAME_GTK_OUTER_WIDGET (f)) + { + GList *w = gtk_container_get_children (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f))); + for (; w != NULL; w = w->next) + { + gtk_widget_show_all (GTK_WIDGET (w->data)); + } + } gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); commit 83c35b86da233870231e30d114ffa4640eb10081 Author: Jindřich Makovička Date: Sat May 29 14:53:20 2021 +0200 * src/pgtkfns.c: Do not show an empty frame prematurely Set only the child widgets visible, leave the outer window to pgtk_make_frame_visible . diff --git a/src/pgtkfns.c b/src/pgtkfns.c index ceff279ad0..0f9f2e4c83 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1693,8 +1693,13 @@ This function is an internal primitive--use `make-frame' instead. */ ) unblock_input (); } - if (FRAME_GTK_OUTER_WIDGET (f)) - gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + if (FRAME_GTK_OUTER_WIDGET (f)) { + GList *w = gtk_container_get_children(GTK_CONTAINER(FRAME_GTK_OUTER_WIDGET (f))); + for (; w != NULL; w = w->next) + { + gtk_widget_show_all (GTK_WIDGET(w->data)); + } + } gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); commit 7d5e94bada09e642a8bfc4f66804f7948bad40bc Merge: 7673b6b9eb dc471feee3 Author: Yuuki Harano Date: Sun Jun 13 17:34:06 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 7673b6b9eb0af3add73e1614a466f142092b00aa Author: Jindřich Makovička Date: Sun May 30 11:40:45 2021 +0200 * src/pgtkselect.c: Avoid Glib assertion warnings Do not call g_object_get_qdata, when the clipboard has no owner, and obj is NULL. Just return Qnil immediately. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 8ab74744f3..447c839f45 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -518,7 +518,7 @@ On Nextstep, TERMINAL is unused. */) obj = gtk_clipboard_get_owner (cb); - return g_object_get_qdata (obj, quark_data) != NULL ? Qt : Qnil; + return obj && g_object_get_qdata (obj, quark_data) != NULL ? Qt : Qnil; } commit ce7a78d0a8e033f04978b0c0762378ba13d3fa64 Author: Yuuki Harano Date: Sat Jun 5 20:53:31 2021 +0900 Support frame-scale-factor on pgtk frames * src/pgtkfns.c (pgtk_frame_scale_factor): New function to get frame scale factor. * src/frame.h: Call it when a pgtk frame. * src/pgtkterm.h: Add the declaration. diff --git a/src/frame.h b/src/frame.h index 1aba1e3bc4..b1ad525779 100644 --- a/src/frame.h +++ b/src/frame.h @@ -920,6 +920,8 @@ default_pixels_per_inch_y (void) /* Scale factor of frame F. */ #if defined HAVE_NS # define FRAME_SCALE_FACTOR(f) (FRAME_NS_P (f) ? ns_frame_scale_factor (f) : 1) +#elif defined HAVE_PGTK +# define FRAME_SCALE_FACTOR(f) (FRAME_PGTK_P (f) ? pgtk_frame_scale_factor (f) : 1) #else # define FRAME_SCALE_FACTOR(f) 1 #endif diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 5f114515c9..ceff279ad0 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2728,6 +2728,26 @@ Internal use only, use `display-monitor-attributes-list' instead. */) return attributes_list; } +double +pgtk_frame_scale_factor (struct frame *f) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + GdkDisplay *gdpy = dpyinfo->gdpy; + + block_input (); + + GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + GdkMonitor *gmon = gdk_display_get_monitor_at_window (gdpy, gwin); + + /* GTK returns scaled sizes for the workareas. */ + double scale = pgtk_get_monitor_scale_factor (gdk_monitor_get_model (gmon)); + if (scale == 0.0) + scale = gdk_monitor_get_scale_factor (gmon); + + unblock_input (); + + return scale; +} DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, 0, 1, 0, doc: /* Return the number of bitplanes of the display TERMINAL. diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 07d7fc10c6..c87a5e13ec 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -663,4 +663,6 @@ extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); extern bool pgtk_text_icon (struct frame *f, const char *icon_name); +extern double pgtk_frame_scale_factor (struct frame *); + #endif /* HAVE_PGTK */ commit c6ada6e9f1f82d36a05ecc49844e9400e0da8fdd Author: Jindřich Makovička Date: Sat May 29 09:44:39 2021 +0200 * src/pgtkterm.c: Honor system DPI settings diff --git a/src/pgtkterm.c b/src/pgtkterm.c index e4bf7ba6bd..13bd442ad9 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6984,8 +6984,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) { GdkScreen *gscr = gdk_display_get_default_screen (dpyinfo->gdpy); - gdouble dpi = 96.0 * pgtk_text_scaling_factor(); - gdk_screen_set_resolution (gscr, dpi); + gdouble dpi = gdk_screen_get_resolution (gscr); + if (dpi < 0) + dpi = 96.0; + + dpi *= pgtk_text_scaling_factor(); dpyinfo->resx = dpi; dpyinfo->resy = dpi; } commit 7085fecf53d9506b1f626e3cab1dd90e33aa9ed0 Author: Yuuki Harano Date: Sat May 29 23:56:04 2021 +0900 Disable hyper key when super and hyper conflict * src/pgtkterm.c (x_find_modifier_meanings): If super_mod_mask and hyper_mod_mask are equal, then disable hyper. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f79329f7dd..e4bf7ba6bd 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5462,6 +5462,16 @@ x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) { dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; } + + /* If xmodmap says: + * $ xmodmap | grep mod4 + * mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf) + * then, when mod4 is pressed, both of super and hyper are recognized ON. + * Maybe many people have such configuration, and they don't like such behavior, + * so I disable hyper if such configuration is detected. + */ + if (dpyinfo->hyper_mod_mask == dpyinfo->super_mod_mask) + dpyinfo->hyper_mod_mask = 0; } static void commit 67ae4b6271233559271f7a7158ba0e059b643ba5 Merge: 67a4c8b5ad e3fc16fd71 Author: Yuuki Harano Date: Sat May 29 18:00:13 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 67a4c8b5ad9ebfb3fa2c7fae433aa6b6b5e92154 Author: Colin Woodbury Date: Sat May 22 18:41:42 2021 +0900 * src/frame.c (Fframep): Update framep docstring diff --git a/src/frame.c b/src/frame.c index 40b8d2b06c..f8479f63f1 100644 --- a/src/frame.c +++ b/src/frame.c @@ -225,7 +225,8 @@ Value is: `x' for an Emacs frame that is really an X window, `w32' for an Emacs frame that is a window on MS-Windows display, `ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display, - `pc' for a direct-write MS-DOS frame. + `pc' for a direct-write MS-DOS frame, + `pgtk' for an Emacs frame running entirely in GTK. See also `frame-live-p'. */) (Lisp_Object object) { commit 1f82c85bffaaa901dc4626bf47073d1d0fb29d2d Author: Yuuki Harano Date: Wed May 19 23:34:16 2021 +0900 Fix compile error when PGTK_DEBUG is enabled * src/pgtkterm.c (pgtk_set_window_size): Remove "pixelwise" arg, which is already non-existent. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 533b9ea894..f79329f7dd 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -465,8 +465,7 @@ pgtk_set_window_size (struct frame *f, bool change_gravity, internal clipping. -------------------------------------------------------------------------- */ { - PGTK_TRACE ("pgtk_set_window_size(%dx%d, %s)", width, height, - pixelwise ? "pixel" : "char"); + PGTK_TRACE ("pgtk_set_window_size(%dx%d)", width, height); int pixelwidth, pixelheight; block_input (); commit 82b4ea2fe820e3e49fb500cb220df60186f298c6 Author: Yuuki Harano Date: Wed May 19 23:06:56 2021 +0900 * src/image.c: Fix compile error related xpm in image.c Use the same code as NS. diff --git a/src/image.c b/src/image.c index 67c55ea9ea..9b8b7d97bd 100644 --- a/src/image.c +++ b/src/image.c @@ -4191,7 +4191,7 @@ enum xpm_keyword_index XPM_LAST }; -#if defined HAVE_XPM || defined HAVE_NS +#if defined HAVE_XPM || defined HAVE_NS || defined HAVE_PGTK /* Vector of image_keyword structures describing the format of valid XPM image specifications. */ @@ -4433,7 +4433,7 @@ init_xpm_functions (void) #endif /* WINDOWSNT */ -#if defined HAVE_XPM || defined HAVE_NS +#if defined HAVE_XPM || defined HAVE_NS || defined HAVE_PGTK /* Value is true if COLOR_SYMBOLS is a valid color symbols list for XPM images. Such a list must consist of conses whose car and cdr are strings. */ @@ -4840,7 +4840,7 @@ xpm_load (struct frame *f, struct image *img) #endif /* HAVE_XPM && !USE_CAIRO */ #if (defined USE_CAIRO && defined HAVE_XPM) \ - || (defined HAVE_NS && !defined HAVE_XPM) + || ((defined HAVE_NS || defined HAVE_PGTK) && !defined HAVE_XPM) /* XPM support functions for NS where libxpm is not available, and for Cairo. Only XPM version 3 (without any extensions) is supported. */ commit e48372f8e5722643e37185b004469acd174663f7 Merge: d0fa569b73 61291e06cc Author: Yuuki Harano Date: Wed May 19 22:02:06 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit d0fa569b7303c2d893b54d0a7af7a521308a5ed4 Author: Yuuki Harano Date: Sat May 15 23:39:35 2021 +0900 Revert "Update texts while busy" This reverts commit 8a649cba44cc637b5326cee9fe3febc55c653719. Because the position of the initial frame is not desired, unless initial-frame-alist is set. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 194a2551c9..533b9ea894 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3551,31 +3551,12 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, } static struct atimer *hourglass_atimer = NULL; +static int hourglass_enter_count = 0; static void hourglass_cb (struct atimer *timer) { - /*NOP*/ -} - -static void -start_timer (void) -{ - static bool hourglass_inited = false; - - /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ - /* This is useful for drawing text while busy, and C-g takes effect while busy. */ - if (!hourglass_inited) - { - struct timespec ts = make_timespec (0, 50 * 1000 * 1000); - if (hourglass_atimer != NULL) - cancel_atimer (hourglass_atimer); - hourglass_atimer = - start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); - - hourglass_inited = true; - } -} + /*NOP*/} static void pgtk_show_hourglass (struct frame *f) @@ -3591,13 +3572,32 @@ pgtk_show_hourglass (struct frame *f) gdk_window_raise (gtk_widget_get_window (x->hourglass_widget)); gdk_window_set_cursor (gtk_widget_get_window (x->hourglass_widget), x->hourglass_cursor); + + /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ + if (hourglass_enter_count++ == 0) + { + struct timespec ts = make_timespec (0, 50 * 1000 * 1000); + if (hourglass_atimer != NULL) + cancel_atimer (hourglass_atimer); + hourglass_atimer = + start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); + } + + /* Cursor frequently stops animation. gtk's bug? */ } static void pgtk_hide_hourglass (struct frame *f) { struct pgtk_output *x = FRAME_X_OUTPUT (f); - + if (--hourglass_enter_count == 0) + { + if (hourglass_atimer != NULL) + { + cancel_atimer (hourglass_atimer); + hourglass_atimer = NULL; + } + } if (x->hourglass_widget != NULL) { gtk_widget_destroy (x->hourglass_widget); @@ -6995,8 +6995,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) unblock_input (); - start_timer(); - return dpyinfo; } commit 8a649cba44cc637b5326cee9fe3febc55c653719 Author: Yuuki Harano Date: Sat May 15 22:50:06 2021 +0900 Update texts while busy Pgtk didn't update text and C-g didn't take effect while it is busy. By timer interrupts, we can call pgtk_read_socket, and update texts and handle C-g. * src/pgtkterm.c (start_timer): New function to start timer. (pgtk_show_hourglass): Remove code to start timer. (pgtk_hide_hourglass): Remove code to stop timer. (pgtk_term_init): Call start_timer(). diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 533b9ea894..194a2551c9 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3551,12 +3551,31 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, } static struct atimer *hourglass_atimer = NULL; -static int hourglass_enter_count = 0; static void hourglass_cb (struct atimer *timer) { - /*NOP*/} + /*NOP*/ +} + +static void +start_timer (void) +{ + static bool hourglass_inited = false; + + /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ + /* This is useful for drawing text while busy, and C-g takes effect while busy. */ + if (!hourglass_inited) + { + struct timespec ts = make_timespec (0, 50 * 1000 * 1000); + if (hourglass_atimer != NULL) + cancel_atimer (hourglass_atimer); + hourglass_atimer = + start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); + + hourglass_inited = true; + } +} static void pgtk_show_hourglass (struct frame *f) @@ -3572,32 +3591,13 @@ pgtk_show_hourglass (struct frame *f) gdk_window_raise (gtk_widget_get_window (x->hourglass_widget)); gdk_window_set_cursor (gtk_widget_get_window (x->hourglass_widget), x->hourglass_cursor); - - /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ - if (hourglass_enter_count++ == 0) - { - struct timespec ts = make_timespec (0, 50 * 1000 * 1000); - if (hourglass_atimer != NULL) - cancel_atimer (hourglass_atimer); - hourglass_atimer = - start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); - } - - /* Cursor frequently stops animation. gtk's bug? */ } static void pgtk_hide_hourglass (struct frame *f) { struct pgtk_output *x = FRAME_X_OUTPUT (f); - if (--hourglass_enter_count == 0) - { - if (hourglass_atimer != NULL) - { - cancel_atimer (hourglass_atimer); - hourglass_atimer = NULL; - } - } + if (x->hourglass_widget != NULL) { gtk_widget_destroy (x->hourglass_widget); @@ -6995,6 +6995,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) unblock_input (); + start_timer(); + return dpyinfo; } commit 3f8f3a9027a1de28899725f0fecdc4f1f33c1479 Author: Yuuki Harano Date: Sat May 15 01:24:50 2021 +0900 Create a variable to enable selection on multi display * src/pgtkselect.c (pgtk_selection_usable): If it is true, always returns true. (syms_of_pgtkselect): New bool variable. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 7b7bc69df7..8ab74744f3 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -235,6 +235,9 @@ pgtk_selection_lost (GtkWidget * widget, GdkEventSelection * event, static bool pgtk_selection_usable (void) { + if (pgtk_enable_selection_on_multi_display) + return true; + /* * https://github.com/GNOME/gtk/blob/gtk-3-24/gdk/wayland/gdkselection-wayland.c#L1033 * @@ -639,4 +642,9 @@ to convert into a type that we don't know about or that is inappropriate.\n\ This hook doesn't let you change the behavior of Emacs's selection replies,\n\ it merely informs you that they have happened."); Vpgtk_sent_selection_hooks = Qnil; + + DEFVAR_BOOL ("pgtk-enable-selection-on-multi-display", pgtk_enable_selection_on_multi_display, + doc: /* Enable selection on multi display environment. +This may cause crash. */); + pgtk_enable_selection_on_multi_display = false; } commit 9a64cc1468486c7668b329c859b43c728ded123e Author: Yuuki Harano Date: Fri May 14 01:32:53 2021 +0900 Treat all the wayland connection as the same display On Wayland, even if without WAYLAND_DISPLAY, --display DISPLAY works, but gdk_display_get_name() always return "wayland-0", which may be different from DISPLAY. If with WAYLAND_DISPLAY, then it always returns WAYLAND_DISPLAY. So pgtk emacs is confused and enter multi display environment. To workaround this situation, treat all the wayland-* as the same display. * src/pgtkfns.c (is_wayland_display): New function to decide it is a wayland connection. (pgtk_display_info_for_name): If both are wayland connection, then they are the same display. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 73681c66f7..5f114515c9 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -124,6 +124,29 @@ check_pgtk_display_info (Lisp_Object object) return dpyinfo; } +/* On Wayland, + * even if without WAYLAND_DISPLAY, --display DISPLAY works, but + * gdk_display_get_name() always return "wayland-0", which may be + * different from DISPLAY. + * If with WAYLAND_DISPLAY, then it always returns WAYLAND_DISPLAY. + * So pgtk emacs is confused and enter multi display environment. + * To workaround this situation, treat all the wayland-* as the same + * display. + */ +static Lisp_Object +is_wayland_display(Lisp_Object dpyname) +{ + const char *p = SSDATA (dpyname); + if (strncmp(p, "wayland-", 8) != 0) + return Qnil; + p += 8; + do { + if (*p < '0' || *p > '9') + return Qnil; + } while (*++p != '\0'); + return Qt; +} + /* Return the X display structure for the display named NAME. Open a new connection if necessary. */ static struct pgtk_display_info * @@ -133,9 +156,18 @@ pgtk_display_info_for_name (Lisp_Object name) CHECK_STRING (name); - for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) - if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) - return dpyinfo; + if (!NILP (is_wayland_display(name))) + { + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (!NILP (is_wayland_display (XCAR (dpyinfo->name_list_element)))) + return dpyinfo; + } + else + { + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + return dpyinfo; + } /* Use this general default value to start with. */ Vx_resource_name = Vinvocation_name; commit bfd6ab9dc936d16d7b550d878385431077b8c9a7 Author: Jeff Walsh Date: Wed May 12 21:27:59 2021 +1000 * src/pgtkterm.c remove duplicated code * src/pgtkterm.c (pgtk_update_window_begin): (pgtk_update_window_end): (pgtk_redisplay_interface): Remove duplicate code and default to the generic gui_update_window_begin/end implementations diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0b0af16aca..533b9ea894 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3192,33 +3192,6 @@ pgtk_update_begin (struct frame *f) pgtk_clear_under_internal_border (f); } -/* Start update of window W. */ - -static void -pgtk_update_window_begin (struct window *w) -{ - struct frame *f = XFRAME (WINDOW_FRAME (w)); - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - - w->output_cursor = w->cursor; - - block_input (); - - if (f == hlinfo->mouse_face_mouse_frame) - { - /* Don't do highlighting for mouse motion during the update. */ - hlinfo->mouse_face_defer = true; - - /* If F needs to be redrawn, simply forget about any prior mouse - highlighting. */ - if (FRAME_GARBAGED_P (f)) - hlinfo->mouse_face_window = Qnil; - } - - unblock_input (); -} - - /* Draw a vertical window border from (x,y0) to (x,y1) */ static void @@ -3296,55 +3269,6 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) pgtk_end_cr_clip (f); } -/* End update of window W. - - Draw vertical borders between horizontally adjacent windows, and - display W's cursor if CURSOR_ON_P is non-zero. - - MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing - glyphs in mouse-face were overwritten. In that case we have to - make sure that the mouse-highlight is properly redrawn. - - W may be a menu bar pseudo-window in case we don't have X toolkit - support. Such windows don't have a cursor, so don't display it - here. */ - -static void -pgtk_update_window_end (struct window *w, bool cursor_on_p, - bool mouse_face_overwritten_p) -{ - if (!w->pseudo_window_p) - { - block_input (); - - if (cursor_on_p) - display_and_set_cursor (w, true, - w->output_cursor.hpos, w->output_cursor.vpos, - w->output_cursor.x, w->output_cursor.y); - - if (draw_window_fringes (w, true)) - { - if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) - gui_draw_right_divider (w); - else - gui_draw_vertical_border (w); - } - - unblock_input (); - } - - /* If a row with mouse-face was overwritten, arrange for - XTframe_up_to_date to redisplay the mouse highlight. */ - if (mouse_face_overwritten_p) - { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); - - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - } -} - /* End update of frame F. This function is installed as a hook in update_end. */ @@ -3697,8 +3621,8 @@ static struct redisplay_interface pgtk_redisplay_interface = { gui_clear_end_of_line, pgtk_scroll_run, pgtk_after_update_window_line, - pgtk_update_window_begin, - pgtk_update_window_end, + NULL, // gui_update_window_begin, + NULL, // gui_update_window_end, pgtk_flush_display, gui_clear_window_mouse_face, gui_get_glyph_overhangs, commit 486e77befd2ea7fd750b1f24eb5dfaf2b91d70b3 Author: Yuuki Harano Date: Tue May 11 00:09:04 2021 +0900 Fix frame size shrinking when turning fringe/scrollbars on/off In 66a36f1, I keeped passing text size by mistake. * src/pgtkterm.c (pgtk_set_window_size): Don't use FRAME_PIXEL_TO_TEXT_WIDTH/HEIGHT to pass pixel size. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5331b67e33..0b0af16aca 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -510,8 +510,7 @@ pgtk_set_window_size (struct frame *f, bool change_gravity, f->output_data.pgtk->preferred_width = pixelwidth; f->output_data.pgtk->preferred_height = pixelheight; x_wm_set_size_hint (f, 0, 0); - xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth), - FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)); + xg_frame_set_char_size (f, pixelwidth, pixelheight); gtk_widget_queue_resize (FRAME_WIDGET (f)); unblock_input (); commit ca0b1b9fe5a9eb225d4cfd1fd52f9e6e56d5fa5f Author: Yuuki Harano Date: Sun May 9 17:53:20 2021 +0900 Fix pgtk_make_frame_visible doesn't work * src/pgtkterm.c (pgtk_wait_for_map_event): New function to wait for map events. The content is moved from pgtk_make_frame_visible. (pgtk_make_frame_visible): Call pgtk_wait_for_map_event, instead of process here directly. (pgtk_make_frame_invisible): Call pgtk_wait_for_map_event to wait for multiple map events. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 3839b2b3fc..5331b67e33 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -591,6 +591,42 @@ pgtk_make_frame_visible_wait_for_map_event_timeout (gpointer user_data) return FALSE; } +static void +pgtk_wait_for_map_event (struct frame *f, bool multiple_times) +{ + if (FLOATP (Vpgtk_wait_for_event_timeout)) + { + guint msec = + (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000); + int found = 0; + int timed_out = 0; + gulong id = + g_signal_connect (FRAME_WIDGET (f), "map-event", + G_CALLBACK + (pgtk_make_frame_visible_wait_for_map_event_cb), + &found); + guint src = + g_timeout_add (msec, + pgtk_make_frame_visible_wait_for_map_event_timeout, + &timed_out); + + if (!multiple_times) + { + while (!found && !timed_out) + gtk_main_iteration (); + } + else + { + while (!timed_out) + gtk_main_iteration (); + } + + g_signal_handler_disconnect (FRAME_WIDGET (f), id); + if (!timed_out) + g_source_remove (src); + } +} + void pgtk_make_frame_visible (struct frame *f) /* -------------------------------------------------------------------------- @@ -607,27 +643,7 @@ pgtk_make_frame_visible (struct frame *f) if (win) gtk_window_deiconify (GTK_WINDOW (win)); - if (FLOATP (Vpgtk_wait_for_event_timeout)) - { - guint msec = - (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000); - int found = 0; - int timed_out = 0; - gulong id = - g_signal_connect (FRAME_WIDGET (f), "map-event", - G_CALLBACK - (pgtk_make_frame_visible_wait_for_map_event_cb), - &found); - guint src = - g_timeout_add (msec, - pgtk_make_frame_visible_wait_for_map_event_timeout, - &timed_out); - while (!found && !timed_out) - gtk_main_iteration (); - g_signal_handler_disconnect (FRAME_WIDGET (f), id); - if (!timed_out) - g_source_remove (src); - } + pgtk_wait_for_map_event (f, false); } } @@ -642,6 +658,13 @@ pgtk_make_frame_invisible (struct frame *f) gtk_widget_hide (FRAME_WIDGET (f)); + /* Map events are emitted many times, and + * map_event() do SET_FRAME_VISIBLE(f, 1). + * I expect visible = 0, so process those map events here and + * SET_FRAME_VISIBLE(f, 0) after that. + */ + pgtk_wait_for_map_event (f, true); + SET_FRAME_VISIBLE (f, 0); SET_FRAME_ICONIFIED (f, false); } commit 647e4a92bbb771e248c640b9ea4737f928ba187e Author: Yuuki Harano Date: Sat May 8 23:43:19 2021 +0900 * src/pgtkmenu.c (show_help_event): Let emacs not show menu tooltips diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 59cc9c25dc..b8f4619d7d 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -162,6 +162,21 @@ popup_deactivate_callback (GtkWidget * widget, gpointer client_data) static void show_help_event (struct frame *f, GtkWidget * widget, Lisp_Object help) { + /* Don't show this tooltip. + * Tooltips are always tied to main widget, so stacking order + * on Wayland is: + * (above) + * - menu + * - tooltip + * - main widget + * (below) + * This is applicable to tooltips for menu, and menu tooltips + * are shown below menus. + * As a workaround, I entrust Gtk with menu tooltips, and + * let emacs not to show menu tooltips. + */ + +#if 0 Lisp_Object frame; if (f) @@ -171,6 +186,7 @@ show_help_event (struct frame *f, GtkWidget * widget, Lisp_Object help) } else show_help_echo (help, Qnil, Qnil, Qnil); +#endif } /* Callback called when menu items are highlighted/unhighlighted commit 639d94fe14ce4d6036296c4b548ecbe4910ad7fa Author: Yuuki Harano Date: Wed May 5 01:21:02 2021 +0900 Entrust Gtk with handling tooltips Previously, tooltips for menu items are below the menu. To solve it, set tooltip text on menu items in advance, and entrust gtk with handling tooltips. * src/gtkutil.c (xg_show_tooltip): New function for pgtk to set tooltip text on the widget. (xg_hide_tooltip): New function for pgtk to clear tooltip text on the widget. (xg_create_frame_widgets): Don't set initial tooltips text, and don't use qttip_cb. (xg_create_frame_outer_widgets): Ditto. (make_menu_item): Set tooltip text on the menu item. * src/gtkutil.h: New declaration of xg_show_tooltip for pgtk. * src/pgtkfns.c (Fx_show_tip): Calls xg_show_tooltip, and always ok. diff --git a/src/gtkutil.c b/src/gtkutil.c index 7760c8ed0a..ee8b925920 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -738,6 +738,9 @@ xg_check_special_colors (struct frame *f, /*********************************************************************** Tooltips ***********************************************************************/ + +#ifndef HAVE_PGTK + /* Gtk+ calls this callback when the parent of our tooltip dummy changes. We use that to pop down the tooltip. This happens if Gtk+ for some reason wants to change or hide the tooltip. */ @@ -912,6 +915,27 @@ xg_hide_tooltip (struct frame *f) return FALSE; } +#else + +void +xg_show_tooltip (struct frame *f, + Lisp_Object string) +{ + Lisp_Object encoded_string = ENCODE_UTF_8 (string); + gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f), SSDATA (encoded_string)); +} + +bool +xg_hide_tooltip (struct frame *f) +{ + if (gtk_widget_get_tooltip_text (FRAME_GTK_OUTER_WIDGET (f)) == NULL) + return FALSE; + gtk_widget_set_tooltip_text (FRAME_GTK_OUTER_WIDGET (f), NULL); + return TRUE; +} + +#endif + /*********************************************************************** General functions for creating widgets, resizing, events, e.t.c. @@ -1563,8 +1587,10 @@ xg_create_frame_widgets (struct frame *f) f->output_data.xp->ttip_widget = 0; f->output_data.xp->ttip_lbl = 0; f->output_data.xp->ttip_window = 0; +#ifndef HAVE_PGTK gtk_widget_set_tooltip_text (wtop, "Dummy text"); g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f); +#endif { GdkScreen *screen = gtk_widget_get_screen (wtop); @@ -1665,8 +1691,10 @@ xg_create_frame_outer_widgets (struct frame *f) f->output_data.xp->ttip_widget = 0; f->output_data.xp->ttip_lbl = 0; f->output_data.xp->ttip_window = 0; +#ifndef HAVE_PGTK gtk_widget_set_tooltip_text (wtop, "Dummy text"); g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f); +#endif { GdkScreen *screen = gtk_widget_get_screen (wtop); @@ -3006,6 +3034,11 @@ make_menu_item (const char *utf8_label, if (wtoadd) gtk_container_add (GTK_CONTAINER (w), wtoadd); if (! item->enabled) gtk_widget_set_sensitive (w, FALSE); +#ifdef HAVE_PGTK + if (!NILP (item->help)) + gtk_widget_set_tooltip_text (w, SSDATA (item->help)); +#endif + return w; } diff --git a/src/gtkutil.h b/src/gtkutil.h index a421cee6ca..4afdfe7405 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -200,7 +200,11 @@ extern bool xg_prepare_tooltip (struct frame *f, Lisp_Object string, int *width, int *height); +#ifndef HAVE_PGTK extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); +#else +extern void xg_show_tooltip (struct frame *f, Lisp_Object string); +#endif extern bool xg_hide_tooltip (struct frame *f); #ifdef USE_CAIRO diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 65c81f7438..73681c66f7 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3287,13 +3287,10 @@ Text larger than the specified size is clipped. */) Fx_hide_tip (); block_input (); - ok = xg_prepare_tooltip (f, string, &width, &height); - if (ok) - { - compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); - xg_show_tooltip (f, root_x, root_y); - tip_last_frame = frame; - } + + ok = true; + xg_show_tooltip (f, string); + tip_last_frame = frame; unblock_input (); if (ok) goto start_timer; commit ff3d7190bbaebf196c0ac7f84d4869fa9362276f Merge: 5b97b98daa 896384b542 Author: Yuuki Harano Date: Thu May 6 21:47:23 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 5b97b98daa7f61311c3662beecbeca7037505992 Merge: 704b765eaa 58b0bcd16d Author: Yuuki Harano Date: Wed May 5 19:00:37 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 704b765eaaee82176e26ab084c26d65311fd46d3 Merge: 66a36f1e5a 1dafab8936 Author: Yuuki Harano Date: Mon May 3 21:33:53 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 66a36f1e5a323aed3d39db1044a1b71373123832 Merge: b302a551ab 6fb80c9ad8 Author: Yuuki Harano Date: Tue Apr 27 21:12:21 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit b302a551ab50a3d961f438380e9d095870c11a6c Merge: de46c7796e 86d1b4d88f Author: Yuuki Harano Date: Sun Apr 25 15:30:05 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit de46c7796e635faf8647a7c6a5ae34fda9adae3b Merge: fb5f3e694b 5c07cd0f15 Author: Yuuki Harano Date: Sun Apr 18 15:30:29 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit fb5f3e694b0f6e2bccfc2124555c986fdc409cd0 Author: Yuuki Harano Date: Tue Apr 13 21:23:48 2021 +0900 Workaround touchscreen events are ignored on sway On sway, gdk_device_get_window_at_position() in xg_event_is_for_scrollbar always returns NULL, and all the touchscreen press events are mishandled as on scrollbar. We don't need to call xg_event_is_for_scrollbar, so removed the call. * src/pgtkterm.c (button_event): Don't call xg_event_is_for_scrollbar. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 10a3999f70..55c139fb7c 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6496,8 +6496,13 @@ button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) } } + /* xg_event_is_for_scrollbar() doesn't work correctly on sway, and + * we shouldn't need it. + */ +#if 0 if (f && xg_event_is_for_scrollbar (f, event)) f = 0; +#endif if (f) { commit 8c7453632e8f45ed65ce814eafc0a1af637774c1 Merge: 5d2f319eec 0342354c15 Author: Yuuki Harano Date: Tue Apr 6 00:11:36 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 5d2f319eec33fea2cb29a02210952ee590b4b21b Merge: 7a7bc15242 e9e691093a Author: Yuuki Harano Date: Sun Mar 21 15:54:46 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 7a7bc15242896b20c7af49f77f0e22c3d78e4d88 Merge: 56297c0f42 f9b737fb9d Author: Yuuki Harano Date: Sun Mar 14 23:24:49 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 56297c0f426314dde66614a5c4e459c285af939a Author: Yuuki Harano Date: Thu Mar 11 21:13:23 2021 +0900 Fix some leaks * src/pgtkterm.c (x_free_frame_resources): Free cursors. (pgtk_delete_terminal): Free cursors and events. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index b965879a1c..10a3999f70 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -231,6 +231,23 @@ x_free_frame_resources (struct frame *f) if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); + g_clear_object (&FRAME_X_OUTPUT (f)->text_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->nontext_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->modeline_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->hand_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->hourglass_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->horizontal_drag_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->vertical_drag_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->left_edge_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->right_edge_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->top_edge_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->bottom_edge_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->top_left_corner_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->top_right_corner_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->bottom_right_corner_cursor); + g_clear_object (&FRAME_X_OUTPUT (f)->bottom_left_corner_cursor); + + if (FRAME_X_OUTPUT (f)->border_color_css_provider != NULL) { GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); @@ -4687,6 +4704,15 @@ pgtk_delete_terminal (struct terminal *terminal) { image_destroy_all_bitmaps (dpyinfo); + g_clear_object (&dpyinfo->xg_cursor); + g_clear_object (&dpyinfo->vertical_scroll_bar_cursor); + g_clear_object (&dpyinfo->horizontal_scroll_bar_cursor); + g_clear_object (&dpyinfo->invisible_cursor); + if (dpyinfo->last_click_event != NULL) { + gdk_event_free (dpyinfo->last_click_event); + dpyinfo->last_click_event = NULL; + } + xg_display_close (dpyinfo->gdpy); /* Do not close the connection here because it's already closed commit 4dda6db3abf4a67455a007d28e14d62a9909f665 Merge: 565995d408 432c1aaa80 Author: Yuuki Harano Date: Mon Mar 8 21:20:54 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 565995d408ca65ec9f981f175cca29d2164a5fd0 Author: Yuuki Harano Date: Tue Mar 2 22:44:42 2021 +0900 Fix unicode strings can't be pasted correctly * lisp/select.el (x-select-request-type): Use text/plain;charset=utf-8 instead. (gui--selection-value-internal): same. (gui-get-selection): Treat text/plain;charset=utf-8 as utf-8. * src/pgtkselect.c (Fpgtk_get_selection_internal): Support text/plain;charset=utf-8 as foreign-selection. (syms_of_pgtkselect): Add new symbol. diff --git a/lisp/select.el b/lisp/select.el index 5e8a364023..72f03e76c4 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -140,26 +140,27 @@ MS-Windows does not have a \"primary\" selection." (defcustom x-select-request-type nil "Data type request for X selection. The value is one of the following data types, a list of them, or nil: - `COMPOUND_TEXT', `UTF8_STRING', `STRING', `TEXT', `text/plain' + `COMPOUND_TEXT', `UTF8_STRING', `STRING', `TEXT', `text/plain\\;charset=utf-8' If the value is one of the above symbols, try only the specified type. If the value is a list of them, try each of them in the specified order until succeed. -The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING text/plain)." +The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING +text/plain\\;charset=utf-8)." :type '(choice (const :tag "Default" nil) (const COMPOUND_TEXT) (const UTF8_STRING) (const STRING) (const TEXT) - (const text/plain) + (const text/plain\;charset=utf-8) (set :tag "List of values" (const COMPOUND_TEXT) (const UTF8_STRING) (const STRING) (const TEXT) - (const text/plain))) + (const text/plain\;charset=utf-8))) :group 'killing) (defun gui--selection-value-internal (type) @@ -169,7 +170,7 @@ decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." (let ((request-type (if (memq window-system '(x pgtk)) (or x-select-request-type - '(UTF8_STRING COMPOUND_TEXT STRING text/plain)) + '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)) 'STRING)) text) (with-demoted-errors "gui-get-selection: %S" @@ -305,6 +306,7 @@ the formats available in the clipboard if TYPE is `CLIPBOARD'." selection-coding-system (pcase data-type ('UTF8_STRING 'utf-8) + ('text/plain\;charset=utf-8 'utf-8) ('COMPOUND_TEXT 'compound-text-with-extensions) ('C_STRING nil) ('STRING 'iso-8859-1) diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 469e42f816..7b7bc69df7 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -576,6 +576,8 @@ On PGTK, TIME-STAMP is unused. */) lispy_type = QCOMPOUND_TEXT; else if (sd_type == gdk_atom_intern("UTF8_STRING", false)) lispy_type = QUTF8_STRING; + else if (sd_type == gdk_atom_intern("text/plain;charset=utf-8", false)) + lispy_type = Qtext_plain_charset_utf_8; else lispy_type = QSTRING; Fput_text_property (make_fixnum (0), make_fixnum (sd_len), @@ -611,6 +613,7 @@ syms_of_pgtkselect (void) DEFSYM (QUTF8_STRING, "UTF8_STRING"); DEFSYM (QSTRING, "STRING"); DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT"); + DEFSYM (Qtext_plain_charset_utf_8, "text/plain;charset=utf-8"); defsubr (&Spgtk_disown_selection_internal); defsubr (&Spgtk_get_selection_internal); commit 436f21eda127882a8408bdc8ae0d398c2cf5aff2 Author: Yuuki Harano Date: Tue Mar 2 21:08:50 2021 +0900 Support selection type text/plain on wayland Apps on XWayland need this. * lisp/select.el (x-select-request-type): Add choice `text/plain'. (gui--selection-value-internal): Add text/plain to the default list. diff --git a/lisp/select.el b/lisp/select.el index 897b66a028..5e8a364023 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -140,24 +140,26 @@ MS-Windows does not have a \"primary\" selection." (defcustom x-select-request-type nil "Data type request for X selection. The value is one of the following data types, a list of them, or nil: - `COMPOUND_TEXT', `UTF8_STRING', `STRING', `TEXT' + `COMPOUND_TEXT', `UTF8_STRING', `STRING', `TEXT', `text/plain' If the value is one of the above symbols, try only the specified type. If the value is a list of them, try each of them in the specified order until succeed. -The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING)." +The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING text/plain)." :type '(choice (const :tag "Default" nil) (const COMPOUND_TEXT) (const UTF8_STRING) (const STRING) (const TEXT) + (const text/plain) (set :tag "List of values" (const COMPOUND_TEXT) (const UTF8_STRING) (const STRING) - (const TEXT))) + (const TEXT) + (const text/plain))) :group 'killing) (defun gui--selection-value-internal (type) @@ -167,7 +169,7 @@ decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." (let ((request-type (if (memq window-system '(x pgtk)) (or x-select-request-type - '(UTF8_STRING COMPOUND_TEXT STRING)) + '(UTF8_STRING COMPOUND_TEXT STRING text/plain)) 'STRING)) text) (with-demoted-errors "gui-get-selection: %S" commit 9f7fde8dc9cae395605b4923324895fbe7c1c8d0 Author: Yuuki Harano Date: Tue Feb 23 17:53:07 2021 +0900 Make scrollbars ignore scroll-bar-fore/background. * src/pgtkfns.c (pgtk_set_scroll_bar_foreground): Handle frame parameters but actually ignore it. (pgtk_set_scroll_bar_background): The same. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 07636a25ca..e9ee2ba13f 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -853,6 +853,7 @@ pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, if (NILP (new_value)) { gtk_css_provider_load_from_data (css_provider, "", -1, NULL); + update_face_from_frame_parameter (f, Qscroll_bar_foreground, new_value); } else if (STRINGP (new_value)) { @@ -861,10 +862,14 @@ pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) error ("Unknown color."); + /* On pgtk, this frame parameter should be ignored, and honor gtk theme. */ +#if 0 char css[64]; sprintf (css, "scrollbar slider { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); gtk_css_provider_load_from_data (css_provider, css, -1, NULL); +#endif + update_face_from_frame_parameter (f, Qscroll_bar_foreground, new_value); } else @@ -881,6 +886,7 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, if (NILP (new_value)) { gtk_css_provider_load_from_data (css_provider, "", -1, NULL); + update_face_from_frame_parameter (f, Qscroll_bar_background, new_value); } else if (STRINGP (new_value)) { @@ -889,10 +895,14 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) error ("Unknown color."); + /* On pgtk, this frame parameter should be ignored, and honor gtk theme. */ +#if 0 char css[64]; sprintf (css, "scrollbar trough { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); gtk_css_provider_load_from_data (css_provider, css, -1, NULL); +#endif + update_face_from_frame_parameter (f, Qscroll_bar_background, new_value); } else commit be2e47362b0f933dbc8e300e3d168296b7e2aac4 Merge: 949d3e50ec c85c8e7d42 Author: Yuuki Harano Date: Sat Feb 20 18:00:36 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 949d3e50ec4ea7723bf14b93b66ad0b72f96f163 Author: Yuuki Harano Date: Sat Feb 20 17:48:11 2021 +0900 Work around I can't copy and paste unicode string to wayland chromium * src/pgtkselect.c (Fpgtk_own_selection_internal): Remove text/plain, since unicode strings are not correctly encoded/decoded between Gtk and chromium(wayland) with it. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 2d81d1274c..469e42f816 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -371,6 +371,12 @@ nil, it defaults to the selected frame. */) list = gtk_target_list_new (NULL, 0); gtk_target_list_add_text_targets (list, 0); + { + /* text/plain: Strings encoded by Gtk are not correctly decoded by Chromium(Wayland). */ + GdkAtom atom_text_plain = gdk_atom_intern("text/plain", false); + gtk_target_list_remove(list, atom_text_plain); + } + targets = gtk_target_table_new_from_list (list, &n_targets); int size = SBYTES (value); commit f094806ffb78487f9d11773134dfbebea2bd95dd Author: Yuuki Harano Date: Tue Feb 16 23:41:33 2021 +0900 Fix I can't paste international text from clipboard * lisp/select.el (gui--selection-value-internal): Try UTF8_STRING when pgtk as well as x. diff --git a/lisp/select.el b/lisp/select.el index c39bc93dea..897b66a028 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -165,7 +165,7 @@ The value nil is the same as the list (UTF8_STRING COMPOUND_TEXT STRING)." Call `gui-get-selection' with an appropriate DATA-TYPE argument decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." - (let ((request-type (if (eq window-system 'x) + (let ((request-type (if (memq window-system '(x pgtk)) (or x-select-request-type '(UTF8_STRING COMPOUND_TEXT STRING)) 'STRING)) commit c4cc80e1fbbfb50486c6ce360f2d68e96fc45887 Author: Basil L. Contovounesios Date: Sat Feb 13 14:51:48 2021 +0000 Fix unused macro build warning in image.c * src/image.c [HAVE_PGTK] (DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE): Define only if HAVE_IMAGEMAGICK is also defined, as it is otherwise unused (bug#46491). (image_set_transform): Reduce nesting of preprocessor conditionals. diff --git a/src/image.c b/src/image.c index cc97ca4d7c..09370fa833 100644 --- a/src/image.c +++ b/src/image.c @@ -99,7 +99,7 @@ static unsigned long image_alloc_image_color (struct frame *, struct image *, Lisp_Object, unsigned long); #endif /* USE_CAIRO */ -#ifdef HAVE_PGTK +#if defined HAVE_PGTK && defined HAVE_IMAGEMAGICK /* On pgtk, we don't want to create scaled image. * If we create scaled image on scale=2.0 environment, * the created image is half size and Gdk scales it back, @@ -2307,12 +2307,11 @@ compute_image_rotation (struct image *img, double *rotation) static void image_set_transform (struct frame *f, struct image *img) { -# ifdef HAVE_IMAGEMAGICK -# ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE +# if (defined HAVE_IMAGEMAGICK \ + && !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) /* ImageMagick images already have the correct transform. */ if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick)) return; -# endif # endif # if !defined USE_CAIRO && defined HAVE_XRENDER commit 175ebb010477ff0e174fe5145154397f43dee2d2 Author: Robert Pluim Date: Thu Feb 11 16:53:13 2021 +0100 Don't crash if we can't find a monitor model name This can happen when running emacs over a forwarded X11 connection. * src/pgtkfns.c (pgtk_get_monitor_scale_factor): Return 0 if we're passed a NULL model name. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index cee24c1ad1..07636a25ca 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -66,6 +66,9 @@ static Lisp_Object monitor_scale_factor_alist; static double pgtk_get_monitor_scale_factor (const char *model) { + if (model == NULL) + return 0.0; + Lisp_Object mdl = build_string (model); Lisp_Object tem = Fassoc(mdl, monitor_scale_factor_alist, Qnil); if (NILP (tem)) commit ef76e64427bb980cca23c338df2526766431ea52 Author: Yuuki Harano Date: Thu Feb 11 19:30:01 2021 +0900 Support getting a image from clipboard * src/pgtkselect.c (Fpgtk_get_selection_internal): Reimplement referring selection_data_to_lisp_data in xselect.c (syms_of_pgtkselect): Add symbols. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 3e57fc7526..2d81d1274c 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -546,14 +546,41 @@ On PGTK, TIME-STAMP is unused. */) cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection_symbol); - gchar *s = gtk_clipboard_wait_for_text (cb); - if (s == NULL) + GdkAtom target_atom = gdk_atom_intern (SSDATA (SYMBOL_NAME (target_type)), false); + GtkSelectionData *seldata = gtk_clipboard_wait_for_contents (cb, target_atom); + + if (seldata == NULL) return Qnil; - int size = strlen (s); - Lisp_Object str = make_unibyte_string (s, size); - Fput_text_property (make_fixnum (0), make_fixnum (size), - Qforeign_selection, QUTF8_STRING, str); - return str; + + const guchar *sd_data = gtk_selection_data_get_data (seldata); + int sd_len = gtk_selection_data_get_length (seldata); + int sd_format = gtk_selection_data_get_format (seldata); + GdkAtom sd_type = gtk_selection_data_get_data_type (seldata); + + if (sd_format == 8) + { + Lisp_Object str, lispy_type; + + str = make_unibyte_string ((char *) sd_data, sd_len); + /* Indicate that this string is from foreign selection by a text + property `foreign-selection' so that the caller of + x-get-selection-internal (usually x-get-selection) can know + that the string must be decode. */ + if (sd_type == gdk_atom_intern("COMPOUND_TEXT", false)) + lispy_type = QCOMPOUND_TEXT; + else if (sd_type == gdk_atom_intern("UTF8_STRING", false)) + lispy_type = QUTF8_STRING; + else + lispy_type = QSTRING; + Fput_text_property (make_fixnum (0), make_fixnum (sd_len), + Qforeign_selection, lispy_type, str); + + gtk_selection_data_free (seldata); + return str; + } + + gtk_selection_data_free (seldata); + return Qnil; } @@ -576,6 +603,8 @@ syms_of_pgtkselect (void) DEFSYM (Qforeign_selection, "foreign-selection"); DEFSYM (QUTF8_STRING, "UTF8_STRING"); + DEFSYM (QSTRING, "STRING"); + DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT"); defsubr (&Spgtk_disown_selection_internal); defsubr (&Spgtk_get_selection_internal); commit ed2205a288a7c38f8614fa134f27be41baad00dc Author: Yuuki Harano Date: Sat Feb 6 19:19:03 2021 +0900 Remove unused arg as xmenu.c * src/pgtkmenu.c (Fx_menu_bar_open_internal): Remove unused arg. (pgtk_activate_menubar): Remove unused arg. (set_frame_menubar): Remove unused arg. (initialize_frame_menubar): Remove unused arg. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index be68e29ca2..59cc9c25dc 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -101,7 +101,7 @@ DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_i f = decode_window_system_frame (frame); if (FRAME_EXTERNAL_MENU_BAR (f)) - set_frame_menubar (f, false, true); + set_frame_menubar (f, true); menubar = FRAME_X_OUTPUT (f)->menubar_widget; if (menubar) @@ -140,7 +140,7 @@ popup_widget_loop (bool do_timers, GtkWidget * widget) void pgtk_activate_menubar (struct frame *f) { - set_frame_menubar (f, false, true); + set_frame_menubar (f, true); popup_activated_flag = 1; @@ -262,7 +262,7 @@ update_frame_menubar (struct frame *f) it is set the first time this is called, from initialize_frame_menubar. */ void -set_frame_menubar (struct frame *f, bool first_time, bool deep_p) +set_frame_menubar (struct frame *f, bool deep_p) { GtkWidget *menubar_widget; Lisp_Object items; @@ -515,7 +515,7 @@ initialize_frame_menubar (struct frame *f) /* This function is called before the first chance to redisplay the frame. It has to be, so the frame will have the right size. */ fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); - set_frame_menubar (f, true, true); + set_frame_menubar (f, true); } commit afcd13783e501f7de345d683e68ec4dff73e8015 Merge: 7646793acd b84b8dff70 Author: Yuuki Harano Date: Sat Feb 6 19:11:51 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 7646793acd8af4644270f5cda4f9a15ef85b68a2 Author: Misha Gusarov Date: Sat Feb 6 18:54:27 2021 +0900 Make reading GNOME settings optional. * src/pgtkterm.c (pgtk_term_init): Make reading GNOME settings optional. (pgtk_text_scaling_factor): New function to read text scaling factor. Copyright-paperwork-exempt: yes diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 437249abeb..b965879a1c 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6798,6 +6798,26 @@ same_x_server (const char *name1, const char *name2) && (*name2 == '.' || *name2 == '\0')); } +#define GNOME_INTERFACE_SCHEMA "org.gnome.desktop.interface" + +static gdouble pgtk_text_scaling_factor(void) +{ + GSettingsSchemaSource *schema_source = g_settings_schema_source_get_default (); + if (schema_source != NULL) + { + GSettingsSchema *schema = g_settings_schema_source_lookup (schema_source, + GNOME_INTERFACE_SCHEMA, true); + if (schema != NULL) + { + g_settings_schema_unref (schema); + GSettings *set = g_settings_new (GNOME_INTERFACE_SCHEMA); + return g_settings_get_double (set, "text-scaling-factor"); + } + } + return 1; +} + + /* Open a connection to X display DISPLAY_NAME, and return the structure that describes the open display. If we cannot contact the display, return null. */ @@ -6969,11 +6989,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) { GdkScreen *gscr = gdk_display_get_default_screen (dpyinfo->gdpy); - GSettings *set = g_settings_new ("org.gnome.desktop.interface"); - gdouble x = g_settings_get_double (set, "text-scaling-factor"); - gdouble dpi = 0; - - dpi = 96.0 * x; + gdouble dpi = 96.0 * pgtk_text_scaling_factor(); gdk_screen_set_resolution (gscr, dpi); dpyinfo->resx = dpi; dpyinfo->resy = dpi; commit ae18c8ec4f0ef37c8c9cda473770ff47e41291e2 Author: Yuuki Harano Date: Sun Jan 31 00:49:56 2021 +0900 Support child frame border width * src/pgtkfns.c (x_set_child_frame_border_width): Port code for X. (pgtk_frame_parm_handlers): Add hook. (Fx_create_frame): Get default parameter. * src/pgtkterm.c (x_draw_stretch_glyph_string): Re-port code for X. (pgtk_clear_under_internal_border): Re-port code for X. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 620680fbda..cee24c1ad1 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -534,6 +534,24 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } +static void +x_set_child_frame_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int border = check_int_nonnegative (arg); + + if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f)) + { + f->child_frame_border_width = border; + + if (FRAME_X_WINDOW (f)) + { + adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width); + pgtk_clear_under_internal_border (f); + } + } + +} + static void x_set_internal_border_width (struct frame *f, Lisp_Object arg, @@ -963,6 +981,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = { x_set_foreground_color, x_set_icon_name, x_set_icon_type, + x_set_child_frame_border_width, x_set_internal_border_width, /* generic OK */ gui_set_right_divider_width, gui_set_bottom_divider_width, @@ -1422,6 +1441,25 @@ This function is an internal primitive--use `make-frame' instead. */ ) if (!EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } + + /* Same for child frames. */ + if (NILP (Fassq (Qchild_frame_border_width, parms))) + { + Lisp_Object value; + + value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, + "childFrameBorderWidth", "childFrameBorderWidth", + RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qchild_frame_border_width, value), + parms); + + } + + gui_default_parameter (f, parms, Qchild_frame_border_width, + make_fixnum (0), + "childFrameBorderWidth", "childFrameBorderWidth", + RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (0), "internalBorderWidth", "internalBorderWidth", diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5d1716adcb..437249abeb 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2367,14 +2367,29 @@ x_draw_stretch_glyph_string (struct glyph_string *s) else if (!s->background_filled_p) { int background_width = s->background_width; - int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + int x = s->x, text_left_x = window_box_left_offset (s->w, TEXT_AREA); - /* Don't draw into left margin, fringe or scrollbar area - except for header line and mode line. */ - if (x < left_x && !s->row->mode_line_p) + /* Don't draw into left fringe or scrollbar area except for + header line and mode line. */ + if (x < text_left_x && !s->row->mode_line_p) { - background_width -= left_x - x; - x = left_x; + int left_x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (s->w); + int right_x = text_left_x; + + if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w)) + left_x += WINDOW_LEFT_FRINGE_WIDTH (s->w); + else + right_x -= WINDOW_LEFT_FRINGE_WIDTH (s->w); + + /* Adjust X and BACKGROUND_WIDTH to fit inside the space + between LEFT_X and RIGHT_X. */ + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + if (x + background_width > right_x) + background_width = right_x - x; } if (background_width > 0) x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); @@ -5261,37 +5276,37 @@ pgtk_clear_under_internal_border (struct frame *f) int border = FRAME_INTERNAL_BORDER_WIDTH (f); int width = FRAME_PIXEL_WIDTH (f); int height = FRAME_PIXEL_HEIGHT (f); - int margin = 0; - struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID); + int margin = FRAME_TOP_MARGIN_HEIGHT (f); + int face_id = + (FRAME_PARENT_FRAME (f) + ? (!NILP (Vface_remapping_alist) + ? lookup_basic_face (NULL, f, CHILD_FRAME_BORDER_FACE_ID) + : CHILD_FRAME_BORDER_FACE_ID) + : (!NILP (Vface_remapping_alist) + ? lookup_basic_face (NULL, f, INTERNAL_BORDER_FACE_ID) + : INTERNAL_BORDER_FACE_ID)); + struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); block_input (); - struct - { - int x, y, w, h; - } rects[] = { - {0, margin, width, border}, - {0, 0, border, height}, - {width - border, 0, border, height}, - {0, height - border, width, border}, - }; - if (face) { - for (int i = 0; i < 4; i++) - { - int x = rects[i].x; - int y = rects[i].y; - int w = rects[i].w; - int h = rects[i].h; - fill_background_by_face (f, face, x, y, w, h); - } +#define x_fill_rectangle(f, gc, x, y, w, h) \ + fill_background_by_face (f, face, x, y, w, h) + x_fill_rectangle (f, gc, 0, margin, width, border); + x_fill_rectangle (f, gc, 0, 0, border, height); + x_fill_rectangle (f, gc, width - border, 0, border, height); + x_fill_rectangle (f, gc, 0, height - border, width, border); +#undef x_fill_rectangle } else { - for (int i = 0; i < 4; i++) - pgtk_clear_area (f, rects[i].x, rects[i].y, rects[i].w, - rects[i].h); +#define x_clear_area(f, x, y, w, h) pgtk_clear_area (f, x, y, w, h) + x_clear_area (f, 0, 0, border, height); + x_clear_area (f, 0, margin, width, border); + x_clear_area (f, width - border, 0, border, height); + x_clear_area (f, 0, height - border, width, border); +#undef x_clear_area } unblock_input (); commit 50c76b844bc79309b4f5d9e28a2386b9a6f735b7 Merge: 563a0d94c3 96f20120c9 Author: Yuuki Harano Date: Sat Jan 30 23:37:19 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 563a0d94c379292bd88e83f18560ed21c497cea9 Author: Yichao Yu Date: Sat Jan 30 23:20:08 2021 +0900 Add support for setting cursor location using Gtk IM Context The existing XIC implementation doesn't work when using Gtk IM Context. Instead, `gtk_im_context_set_cursor_location` should be used to update the cursor information for the input method. * src/pgtkim.c (pgtk_im_set_cursor_location): New function to tell gtk cursor location. * src/pgtkterm.c (pgtk_draw_window_cursor): Remove invalid code and add new code to call the function. * src/pgtkterm.h: Add the function declaration. diff --git a/src/pgtkim.c b/src/pgtkim.c index 68f83d2c6e..ba69a27501 100644 --- a/src/pgtkim.c +++ b/src/pgtkim.c @@ -210,6 +210,18 @@ pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev) return false; } +void +pgtk_im_set_cursor_location (struct frame *f, int x, int y, int width, + int height) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->im.context != NULL && dpyinfo->im.focused_frame == f) + { + GdkRectangle area = { x, y, width, height }; + gtk_im_context_set_cursor_location (dpyinfo->im.context, &area); + } +} + static void pgtk_im_use_context (struct pgtk_display_info *dpyinfo, bool use_p) { diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 44e1f3e296..5d1716adcb 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2878,6 +2878,7 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, enum text_cursor_kinds cursor_type, int cursor_width, bool on_p, bool active_p) { + struct frame *f = XFRAME (w->frame); PGTK_TRACE ("draw_window_cursor: %d, %d, %d, %d, %d, %d.", x, y, cursor_type, cursor_width, on_p, active_p); if (on_p) @@ -2922,11 +2923,15 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, } } -#ifdef HAVE_X_I18N if (w == XWINDOW (f->selected_window)) - if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition)) - xic_set_preeditarea (w, x, y); -#endif + { + int frame_x = + WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w); + int frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, y); + pgtk_im_set_cursor_location (f, frame_x, frame_y, + w->phys_cursor_width, + w->phys_cursor_height); + } } } diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 5e71f93998..07d7fc10c6 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -653,6 +653,8 @@ extern void pgtk_enqueue_preedit (struct frame *f, Lisp_Object image_data); extern void pgtk_im_focus_in (struct frame *f); extern void pgtk_im_focus_out (struct frame *f); extern bool pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev); +extern void pgtk_im_set_cursor_location (struct frame *f, int x, int y, + int width, int height); extern void pgtk_im_init (struct pgtk_display_info *dpyinfo); extern void pgtk_im_finish (struct pgtk_display_info *dpyinfo); commit e9608601e5d5f45be36a8f833a98230086e628a8 Author: Yuuki Harano Date: Sun Jan 24 00:47:50 2021 +0900 Add scale factor in display-monitor-attributes-list. * lisp/frame.el (display-monitor-attributes-list): Add the comment. * src/frame.c (make_monitor_attribute_list): Include the scale factor value. (syms_of_frame): Declare intern'ed scale-factor. * src/frame.h (struct MonitorInfo): Add scale_factor member. * src/pgtkfns.c (Fpgtk_display_monitor_attributes_list): Set the value. diff --git a/lisp/frame.el b/lisp/frame.el index 010bab41d2..0aae87b9f4 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2253,6 +2253,7 @@ of attribute keys and values as follows: mm-size -- Width and height in millimeters in the form of (WIDTH HEIGHT) frames -- List of frames dominated by the physical monitor + scale-factor (*) -- Scale factor (float) name (*) -- Name of the physical monitor as a string source (*) -- Source of multi-monitor information as a string diff --git a/src/frame.c b/src/frame.c index daaba2abfe..998ddaabb3 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5826,6 +5826,10 @@ make_monitor_attribute_list (struct MonitorInfo *monitors, attributes); attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)), attributes); +#ifdef HAVE_PGTK + attributes = Fcons (Fcons (Qscale_factor, make_float (mi->scale_factor)), + attributes); +#endif attributes = Fcons (Fcons (Qmm_size, list2i (mi->mm_width, mi->mm_height)), attributes); @@ -5938,6 +5942,9 @@ syms_of_frame (void) DEFSYM (Qworkarea, "workarea"); DEFSYM (Qmm_size, "mm-size"); +#ifdef HAVE_PGTK + DEFSYM (Qscale_factor, "scale-factor"); +#endif DEFSYM (Qframes, "frames"); DEFSYM (Qsource, "source"); diff --git a/src/frame.h b/src/frame.h index 10cb3f52e5..7372e74cfe 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1746,6 +1746,9 @@ struct MonitorInfo { Emacs_Rectangle geom, work; int mm_width, mm_height; char *name; +#ifdef HAVE_PGTK + double scale_factor; +#endif }; extern void free_monitors (struct MonitorInfo *monitors, int n_monitors); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 63e121f118..620680fbda 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2647,6 +2647,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) mi->work.height = work.height; mi->mm_width = width_mm; mi->mm_height = height_mm; + mi->scale_factor = scale; dupstring (&mi->name, (gdk_monitor_get_model (monitor))); } commit f7fa39fbda29d80930d6be97a4ad2f2818b590ff Author: Yuuki Harano Date: Thu Jan 21 00:57:10 2021 +0900 Make imagemagick images less blurry. * src/image.c: New macro to specify non-scaled mode. (image_set_transform): Don't skip even if imagemagick. (imagemagick_load_image): Don't calculate desired size. diff --git a/src/image.c b/src/image.c index 8e74a7ab9a..cc97ca4d7c 100644 --- a/src/image.c +++ b/src/image.c @@ -99,6 +99,17 @@ static unsigned long image_alloc_image_color (struct frame *, struct image *, Lisp_Object, unsigned long); #endif /* USE_CAIRO */ +#ifdef HAVE_PGTK +/* On pgtk, we don't want to create scaled image. + * If we create scaled image on scale=2.0 environment, + * the created image is half size and Gdk scales it back, + * and the result is blurry. + * To avoid this, we hold original size image as far as + * we can, and let Gdk to scale it when it is shown. + */ +# define DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE +#endif + #ifdef HAVE_NTGUI /* We need (or want) w32.h only when we're _not_ compiling for Cygwin. */ @@ -2297,9 +2308,11 @@ static void image_set_transform (struct frame *f, struct image *img) { # ifdef HAVE_IMAGEMAGICK +# ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE /* ImageMagick images already have the correct transform. */ if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick)) return; +# endif # endif # if !defined USE_CAIRO && defined HAVE_XRENDER @@ -9189,11 +9202,15 @@ imagemagick_load_image (struct frame *f, struct image *img, PixelWand **pixels, *bg_wand = NULL; MagickPixelPacket pixel; Lisp_Object image; +#ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE Lisp_Object value; +#endif Lisp_Object crop; EMACS_INT ino; int desired_width, desired_height; +#ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE double rotation; +#endif char hint_buffer[MaxTextExtent]; char *filename_hint = NULL; imagemagick_initialize (); @@ -9310,9 +9327,13 @@ imagemagick_load_image (struct frame *f, struct image *img, PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535); } +#ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE compute_image_size (MagickGetImageWidth (image_wand), MagickGetImageHeight (image_wand), img->spec, &desired_width, &desired_height); +#else + desired_width = desired_height = -1; +#endif if (desired_width != -1 && desired_height != -1) { @@ -9356,6 +9377,7 @@ imagemagick_load_image (struct frame *f, struct image *img, } } +#ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE /* Furthermore :rotation. we need background color and angle for rotation. */ /* @@ -9374,6 +9396,7 @@ imagemagick_load_image (struct frame *f, struct image *img, goto imagemagick_error; } } +#endif /* Set the canvas background color to the frame or specified background, and flatten the image. Note: as of ImageMagick commit bebc657aad7c9b448a8e0cafd9d09d7774097975 Merge: 7326982d28 8b33b76eb9 Author: Yuuki Harano Date: Wed Jan 20 21:46:03 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 7326982d283abe7545d5f5742ea2b57e513fd285 Author: Yuuki Harano Date: Mon Jan 11 19:56:32 2021 +0900 Fix visual-bell on X * src/pgtkterm.c (pgtk_flash): Change size source. On X, surface_orig is not an image surface but xlib surface, so I cannot get its size with cairo_image_surface_get_{width,height}. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 00381671f2..44e1f3e296 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3706,8 +3706,8 @@ pgtk_flash (struct frame *f) { cairo_surface_t *surface_orig = FRAME_CR_SURFACE (f); - int width = cairo_image_surface_get_width (surface_orig); - int height = cairo_image_surface_get_height (surface_orig); + int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f); + int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f); cairo_surface_t *surface = cairo_surface_create_similar (surface_orig, CAIRO_CONTENT_COLOR_ALPHA, width, height); commit cd72fba0437ab5fcd6bf17a2b85ed1aedd3739d4 Author: Yuuki Harano Date: Mon Jan 11 19:55:40 2021 +0900 Free unneeded context * src/pgtkterm.c (pgtk_flash): Free unneeded cairo_t. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f67d5098da..00381671f2 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3770,6 +3770,8 @@ pgtk_flash (struct frame *f) #undef XFillRectangle } + + cairo_destroy (cr); } unblock_input (); commit aac33a8074c41354ffdb1236a342da16dca4a1bc Merge: 78fd106653 690cf6b8d8 Author: Yuuki Harano Date: Sun Jan 10 18:49:51 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 78fd106653a9e4fa7c9c3c9788540e2e15552254 Author: Yuuki Harano Date: Sun Jan 10 18:41:07 2021 +0900 Fix gtk icon theme does not reflect * lisp/term/pgtk-win.el (x-gtk-stock-map): Port from X. (icon-map-list): Port from X. (x-gtk-stock-cache): Port from X. (x-gtk-map-stock): Port from X. * src/pgtkterm.c (syms_of_pgtkterm): Remove duplicated definition. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 6e970c45d8..4f1810c1de 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -428,6 +428,140 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (pgtk-use-im-context pgtk-use-im-context-on-new-connection))))) +;;; + +(defcustom x-gtk-stock-map + (mapcar (lambda (arg) + (cons (purecopy (car arg)) (purecopy (cdr arg)))) + '( + ("etc/images/new" . ("document-new" "gtk-new")) + ("etc/images/open" . ("document-open" "gtk-open")) + ("etc/images/diropen" . "n:system-file-manager") + ("etc/images/close" . ("window-close" "gtk-close")) + ("etc/images/save" . ("document-save" "gtk-save")) + ("etc/images/saveas" . ("document-save-as" "gtk-save-as")) + ("etc/images/undo" . ("edit-undo" "gtk-undo")) + ("etc/images/cut" . ("edit-cut" "gtk-cut")) + ("etc/images/copy" . ("edit-copy" "gtk-copy")) + ("etc/images/paste" . ("edit-paste" "gtk-paste")) + ("etc/images/search" . ("edit-find" "gtk-find")) + ("etc/images/print" . ("document-print" "gtk-print")) + ("etc/images/preferences" . ("preferences-system" "gtk-preferences")) + ("etc/images/help" . ("help-browser" "gtk-help")) + ("etc/images/left-arrow" . ("go-previous" "gtk-go-back")) + ("etc/images/right-arrow" . ("go-next" "gtk-go-forward")) + ("etc/images/home" . ("go-home" "gtk-home")) + ("etc/images/jump-to" . ("go-jump" "gtk-jump-to")) + ("etc/images/index" . ("gtk-search" "gtk-index")) + ("etc/images/exit" . ("application-exit" "gtk-quit")) + ("etc/images/cancel" . "gtk-cancel") + ("etc/images/info" . ("dialog-information" "gtk-info")) + ("etc/images/bookmark_add" . "n:bookmark_add") + ;; Used in Gnus and/or MH-E: + ("etc/images/attach" . ("mail-attachment" "gtk-attach")) + ("etc/images/connect" . "gtk-connect") + ("etc/images/contact" . "gtk-contact") + ("etc/images/delete" . ("edit-delete" "gtk-delete")) + ("etc/images/describe" . ("document-properties" "gtk-properties")) + ("etc/images/disconnect" . "gtk-disconnect") + ;; ("etc/images/exit" . "gtk-exit") + ("etc/images/lock-broken" . "gtk-lock_broken") + ("etc/images/lock-ok" . "gtk-lock_ok") + ("etc/images/lock" . "gtk-lock") + ("etc/images/next-page" . "gtk-next-page") + ("etc/images/refresh" . ("view-refresh" "gtk-refresh")) + ("etc/images/search-replace" . "edit-find-replace") + ("etc/images/sort-ascending" . ("view-sort-ascending" "gtk-sort-ascending")) + ("etc/images/sort-column-ascending" . "gtk-sort-column-ascending") + ("etc/images/sort-criteria" . "gtk-sort-criteria") + ("etc/images/sort-descending" . ("view-sort-descending" + "gtk-sort-descending")) + ("etc/images/sort-row-ascending" . "gtk-sort-row-ascending") + ("etc/images/spell" . ("tools-check-spelling" "gtk-spell-check")) + ("images/gnus/toggle-subscription" . "gtk-task-recurring") + ("images/mail/compose" . ("mail-message-new" "gtk-mail-compose")) + ("images/mail/copy" . "gtk-mail-copy") + ("images/mail/forward" . "gtk-mail-forward") + ("images/mail/inbox" . "gtk-inbox") + ("images/mail/move" . "gtk-mail-move") + ("images/mail/not-spam" . "gtk-not-spam") + ("images/mail/outbox" . "gtk-outbox") + ("images/mail/reply-all" . "gtk-mail-reply-to-all") + ("images/mail/reply" . "gtk-mail-reply") + ("images/mail/save-draft" . "gtk-mail-handling") + ("images/mail/send" . ("mail-send" "gtk-mail-send")) + ("images/mail/spam" . "gtk-spam") + ;; Used for GDB Graphical Interface + ("images/gud/break" . "gtk-no") + ("images/gud/recstart" . ("media-record" "gtk-media-record")) + ("images/gud/recstop" . ("media-playback-stop" "gtk-media-stop")) + ;; No themed versions available: + ;; mail/preview (combining stock_mail and stock_zoom) + ;; mail/save (combining stock_mail, stock_save and stock_convert) + )) + "How icons for tool bars are mapped to Gtk+ stock items. +Emacs must be compiled with the Gtk+ toolkit for this to have any effect. +A value that begins with n: denotes a named icon instead of a stock icon." + :version "22.2" + :type '(choice (repeat + (choice symbol + (cons (string :tag "Emacs icon") + (choice (group (string :tag "Named") + (string :tag "Stock")) + (string :tag "Stock/named")))))) + :group 'pgtk) + +(defcustom icon-map-list '(x-gtk-stock-map) + "A list of alists that map icon file names to stock/named icons. +The alists are searched in the order they appear. The first match is used. +The keys in the alists are file names without extension and with two directory +components. For example, to map /usr/share/emacs/22.1.1/etc/images/open.xpm +to stock item gtk-open, use: + + (\"etc/images/open\" . \"gtk-open\") + +Themes also have named icons. To map to one of those, use n: before the name: + + (\"etc/images/diropen\" . \"n:system-file-manager\") + +The list elements are either the symbol name for the alist or the +alist itself. + +If you don't want stock icons, set the variable to nil." + :version "22.2" + :type '(choice (const :tag "Don't use stock icons" nil) + (repeat (choice symbol + (cons (string :tag "Emacs icon") + (string :tag "Stock/named"))))) + :group 'pgtk) + +(defconst x-gtk-stock-cache (make-hash-table :weakness t :test 'equal)) + +(defun x-gtk-map-stock (file) + "Map icon with file name FILE to a Gtk+ stock name. +This uses `icon-map-list' to map icon file names to stock icon names." + (when (stringp file) + (or (gethash file x-gtk-stock-cache) + (puthash + file + (save-match-data + (let* ((file-sans (file-name-sans-extension file)) + (key (and (string-match "/\\([^/]+/[^/]+/[^/]+$\\)" + file-sans) + (match-string 1 file-sans))) + (icon-map icon-map-list) + elem value) + (while (and (null value) icon-map) + (setq elem (car icon-map) + value (assoc-string (or key file-sans) + (if (symbolp elem) + (symbol-value elem) + elem)) + icon-map (cdr icon-map))) + (and value (cdr value)))) + x-gtk-stock-cache)))) + + (provide 'pgtk-win) (provide 'term/pgtk-win) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 568de7ca8d..f67d5098da 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -7233,7 +7233,6 @@ consuming frame position adjustments. In newer versions of GTK, Emacs always uses gtk_window_move and ignores the value of this variable. */); x_gtk_use_window_move = true; - DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout, doc: /* How long to wait for X events. commit bcb74798ed3068e324cffd8856f5a70f2c6c7687 Author: Yuuki Harano Date: Mon Jan 4 04:13:33 2021 +0900 Add a function to set monitor scale factor manually * src/pgtkfns.c (pgtk_get_monitor_scale_factor): New function to get manual scale factor from alist. (Fpgtk_set_monitor_scale_factor): New function to set manual scale factor into alist. (Fx_display_pixel_width): Use manual scale factor first, if not set, use gdk's one. (Fx_display_pixel_height): Use manual scale factor first, if not set, use gdk's one. (Fpgtk_display_monitor_attributes_list): Use manual scale factor first, if not set, use gdk's one. (syms_of_pgtkfns): initialize alist. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 7d2183d2a0..63e121f118 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -54,12 +54,37 @@ static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); static const char *pgtk_app_name = "Emacs"; +/* scale factor manually set per monitor */ +static Lisp_Object monitor_scale_factor_alist; + /* ========================================================================== Internal utility functions ========================================================================== */ +static double +pgtk_get_monitor_scale_factor (const char *model) +{ + Lisp_Object mdl = build_string (model); + Lisp_Object tem = Fassoc(mdl, monitor_scale_factor_alist, Qnil); + if (NILP (tem)) + return 0; + Lisp_Object cdr = Fcdr (tem); + if (NILP (cdr)) + return 0; + if (FIXNUMP (cdr)) + { + return XFIXNUM (cdr); + } + else if (FLOATP (cdr)) + { + return XFLOAT_DATA (cdr); + } + else + error ("unknown type of scale-factor"); +} + struct pgtk_display_info * check_pgtk_display_info (Lisp_Object object) { @@ -1115,6 +1140,50 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) ========================================================================== */ +DEFUN ("pgtk-set-monitor-scale-factor", Fpgtk_set_monitor_scale_factor, + Spgtk_set_monitor_scale_factor, 2, 2, 0, + doc: /* Set monitor MONITOR-MODEL's scale factor to SCALE-FACTOR. +Since Gdk's scale factor is integer, physical pixel width/height is +incorrect when you specify fractional scale factor in compositor. +If you set scale factor by this function, it is used instead of Gdk's one. + +Pass nil as SCALE-FACTOR if you want to reset the specified monitor's +scale factor. */ ) + (Lisp_Object monitor_model, Lisp_Object scale_factor) +{ + CHECK_STRING (monitor_model); + if (!NILP (scale_factor)) + { + CHECK_NUMBER (scale_factor); + if (FIXNUMP (scale_factor)) + { + if (XFIXNUM (scale_factor) <= 0) + error ("scale factor must be > 0."); + } + else if (FLOATP (scale_factor)) + { + if (XFLOAT_DATA (scale_factor) <= 0.0) + error ("scale factor must be > 0."); + } + else + error ("unknown type of scale-factor"); + } + + Lisp_Object tem = Fassoc (monitor_model, monitor_scale_factor_alist, Qnil); + if (NILP (tem)) + { + if (!NILP (scale_factor)) + monitor_scale_factor_alist = Fcons (Fcons (monitor_model, scale_factor), + monitor_scale_factor_alist); + } + else + { + Fsetcdr (tem, scale_factor); + } + + return scale_factor; +} + DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 1, 1, 0, doc: /* Make a new X window, which is called a "frame" in Emacs terms. Return an Emacs frame object. PARMS is an alist of frame parameters. @@ -2419,17 +2488,19 @@ each physical monitor, use `display-monitor-attributes-list'. */) for (i = 0; i < n_monitors; ++i) { GdkRectangle rec; - int scale = 1; + double scale = 1; GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); gdk_monitor_get_geometry (monitor, &rec); /* GTK returns scaled sizes for the workareas. */ - scale = gdk_monitor_get_scale_factor (monitor); - rec.x *= scale; - rec.y *= scale; - rec.width *= scale; - rec.height *= scale; + scale = pgtk_get_monitor_scale_factor (gdk_monitor_get_model (monitor)); + if (scale == 0.0) + scale = gdk_monitor_get_scale_factor (monitor); + rec.x = rec.x * scale + 0.5; + rec.y = rec.y * scale + 0.5; + rec.width = rec.width * scale + 0.5; + rec.height = rec.height * scale + 0.5; width = max(width, rec.x + rec.width); } @@ -2463,17 +2534,19 @@ each physical monitor, use `display-monitor-attributes-list'. */) for (i = 0; i < n_monitors; ++i) { GdkRectangle rec; - int scale = 1; + double scale = 1; GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); gdk_monitor_get_geometry (monitor, &rec); /* GTK returns scaled sizes for the workareas. */ - scale = gdk_monitor_get_scale_factor (monitor); - rec.x *= scale; - rec.y *= scale; - rec.width *= scale; - rec.height *= scale; + scale = pgtk_get_monitor_scale_factor (gdk_monitor_get_model (monitor)); + if (scale == 0.0) + scale = gdk_monitor_get_scale_factor (monitor); + rec.x = rec.x * scale + 0.5; + rec.y = rec.y * scale + 0.5; + rec.width = rec.width * scale + 0.5; + rec.height = rec.height * scale + 0.5; height = max(height, rec.y + rec.height); } @@ -2540,7 +2613,7 @@ Internal use only, use `display-monitor-attributes-list' instead. */) gint width_mm, height_mm; GdkRectangle rec, work; struct MonitorInfo *mi = &monitors[i]; - int scale = 1; + double scale = 1; GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); if (gdk_monitor_is_primary (monitor)) @@ -2552,15 +2625,17 @@ Internal use only, use `display-monitor-attributes-list' instead. */) gdk_monitor_get_workarea (monitor, &work); /* GTK returns scaled sizes for the workareas. */ - scale = gdk_monitor_get_scale_factor (monitor); - rec.x *= scale; - rec.y *= scale; - rec.width *= scale; - rec.height *= scale; - work.x *= scale; - work.y *= scale; - work.width *= scale; - work.height *= scale; + scale = pgtk_get_monitor_scale_factor (gdk_monitor_get_model (monitor)); + if (scale == 0.0) + scale = gdk_monitor_get_scale_factor (monitor); + rec.x = rec.x * scale + 0.5; + rec.y = rec.y * scale + 0.5; + rec.width = rec.width * scale + 0.5; + rec.height = rec.height * scale + 0.5; + work.x = work.x * scale + 0.5; + work.y = work.y * scale + 0.5; + work.width = work.width * scale + 0.5; + work.height = work.height * scale + 0.5; mi->geom.x = rec.x; mi->geom.y = rec.y; @@ -3885,12 +3960,17 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_print_frames_dialog); defsubr (&Spgtk_backend_display_class); + defsubr (&Spgtk_set_monitor_scale_factor); + defsubr (&Sx_file_dialog); as_status = 0; as_script = Qnil; as_result = 0; + monitor_scale_factor_alist = Qnil; + staticpro (&monitor_scale_factor_alist); + tip_timer = Qnil; staticpro (&tip_timer); tip_frame = Qnil; commit 44f7f57c6833149799539c5e0abcadf4d7d61d43 Merge: 0af4e7587e 825b4ec338 Author: Yuuki Harano Date: Sun Jan 3 16:33:29 2021 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 0af4e7587e1b5ac9066e17b875952cb5a16e63c0 Author: Yuuki Harano Date: Sun Jan 3 16:26:25 2021 +0900 Fix display-pixel-width/height to return physical pixel size. * src/pgtkfns.c (Fx_display_pixel_width): (Fx_display_pixel_height): Return bottom/right-most of all the monitors. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 3e55b83872..7d2183d2a0 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2408,8 +2408,35 @@ each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy; + gint n_monitors, i; + int width = 0; + + block_input (); + gdpy = dpyinfo->gdpy; + n_monitors = gdk_display_get_n_monitors (gdpy); + + for (i = 0; i < n_monitors; ++i) + { + GdkRectangle rec; + int scale = 1; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + gdk_monitor_get_geometry (monitor, &rec); + + /* GTK returns scaled sizes for the workareas. */ + scale = gdk_monitor_get_scale_factor (monitor); + rec.x *= scale; + rec.y *= scale; + rec.width *= scale; + rec.height *= scale; + + width = max(width, rec.x + rec.width); + } + + unblock_input (); - return make_fixnum (x_display_pixel_width (dpyinfo)); + return make_fixnum (width); } @@ -2425,8 +2452,35 @@ each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy; + gint n_monitors, i; + int height = 0; + + block_input (); + gdpy = dpyinfo->gdpy; + n_monitors = gdk_display_get_n_monitors (gdpy); + + for (i = 0; i < n_monitors; ++i) + { + GdkRectangle rec; + int scale = 1; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + gdk_monitor_get_geometry (monitor, &rec); + + /* GTK returns scaled sizes for the workareas. */ + scale = gdk_monitor_get_scale_factor (monitor); + rec.x *= scale; + rec.y *= scale; + rec.width *= scale; + rec.height *= scale; + + height = max(height, rec.y + rec.height); + } + + unblock_input (); - return make_fixnum (x_display_pixel_height (dpyinfo)); + return make_fixnum (height); } DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, commit 78801c6e211b966d4730759e56ae65f94ef8bc8a Author: Yuuki Harano Date: Sun Jan 3 16:22:34 2021 +0900 Make display-mm-width/height consider multi-monitor. * src/pgtkfns.c (Fx_display_mm_height): (Fx_display_mm_width): Calculate width/height mm assuming monitor other than origin does not overlap. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index f52dab6dbe..3e55b83872 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2047,9 +2047,32 @@ for each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor *gmon = gdk_display_get_monitor_at_point (gdpy, 0, 0); - return make_fixnum (gdk_monitor_get_height_mm (gmon)); + GdkDisplay *gdpy; + gint n_monitors, i; + int height_mm_at_0 = 0, height_mm_at_other = 0; + + block_input (); + gdpy = dpyinfo->gdpy; + n_monitors = gdk_display_get_n_monitors (gdpy); + + for (i = 0; i < n_monitors; ++i) + { + GdkRectangle rec; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + gdk_monitor_get_geometry (monitor, &rec); + + int mm = gdk_monitor_get_height_mm (monitor); + + if (rec.y == 0) + height_mm_at_0 = max(height_mm_at_0, mm); + else + height_mm_at_other += mm; + } + + unblock_input (); + + return make_fixnum (height_mm_at_0 + height_mm_at_other); } @@ -2065,9 +2088,32 @@ for each physical monitor, use `display-monitor-attributes-list'. */) (Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor *gmon = gdk_display_get_monitor_at_point (gdpy, 0, 0); - return make_fixnum (gdk_monitor_get_width_mm (gmon)); + GdkDisplay *gdpy; + gint n_monitors, i; + int width_mm_at_0 = 0, width_mm_at_other = 0; + + block_input (); + gdpy = dpyinfo->gdpy; + n_monitors = gdk_display_get_n_monitors (gdpy); + + for (i = 0; i < n_monitors; ++i) + { + GdkRectangle rec; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + gdk_monitor_get_geometry (monitor, &rec); + + int mm = gdk_monitor_get_width_mm (monitor); + + if (rec.x == 0) + width_mm_at_0 = max(width_mm_at_0, mm); + else + width_mm_at_other += mm; + } + + unblock_input (); + + return make_fixnum (width_mm_at_0 + width_mm_at_other); } commit 91d450d1fbe78717f34f4c28789d3f4c6ecd6061 Author: Yuuki Harano Date: Sun Jan 3 15:07:37 2021 +0900 Fix pgtk-display-monitor-attributes-list to return physical pixel sizes. * src/pgtkfns.c (Fpgtk_display_monitor_attributes_list): Re-port it. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index cf84163fee..f52dab6dbe 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2383,109 +2383,108 @@ each physical monitor, use `display-monitor-attributes-list'. */) return make_fixnum (x_display_pixel_height (dpyinfo)); } -DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, Spgtk_display_monitor_attributes_list, 0, 1, 0, +DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, + Spgtk_display_monitor_attributes_list, + 0, 1, 0, doc: /* Return a list of physical monitor attributes on the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. +In addition to the standard attribute keys listed in +`display-monitor-attributes-list', the following keys are contained in +the attributes: + + source -- String describing the source from which multi-monitor + information is obtained, \"Gdk\" + Internal use only, use `display-monitor-attributes-list' instead. */) (Lisp_Object terminal) { - struct terminal *term = decode_live_terminal (terminal); struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor **gmons; - int i, n_monitors, primary_index; - struct MonitorInfo *monitors; - Lisp_Object monitor_frames = Qnil; - Lisp_Object frame = Qnil, rest = Qnil; - Lisp_Object rv = Qnil; + Lisp_Object attributes_list = Qnil; - if (term->type != output_pgtk) - return Qnil; + GdkDisplay *gdpy; + gint primary_monitor = 0, n_monitors, i; + Lisp_Object monitor_frames, rest, frame; + static const char *source = "Gdk"; + struct MonitorInfo *monitors; + block_input (); + gdpy = dpyinfo->gdpy; n_monitors = gdk_display_get_n_monitors (gdpy); - if (n_monitors == 0) - return Qnil; - - gmons = xmalloc (sizeof *gmons * n_monitors); - for (i = 0; i < n_monitors; i++) - gmons[i] = gdk_display_get_monitor (gdpy, i); - + monitor_frames = make_nil_vector (n_monitors); monitors = xzalloc (n_monitors * sizeof *monitors); - for (i = 0; i < n_monitors; i++) - { - struct MonitorInfo *mon = &monitors[i]; - GdkMonitor *gmon = gmons[i]; - if (gmon != NULL) - { - GdkRectangle geom; - gdk_monitor_get_geometry (gmon, &geom); - mon->geom.x = geom.x; - mon->geom.y = geom.y; - mon->geom.width = geom.width; - mon->geom.height = geom.height; - - gdk_monitor_get_workarea (gmon, &geom); - mon->work.x = geom.x; - mon->work.y = geom.y; - mon->work.width = geom.width; - mon->work.height = geom.height; - - mon->mm_width = gdk_monitor_get_width_mm (gmon); - mon->mm_height = gdk_monitor_get_height_mm (gmon); - - mon->name = xstrdup (gdk_monitor_get_model (gmon)); - } - } - monitor_frames = Fmake_vector (make_fixnum (n_monitors), Qnil); FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); - - if (FRAME_PGTK_P (f)) - { - GtkWidget *widget = FRAME_GTK_WIDGET (f); - GdkMonitor *gmon = - gdk_display_get_monitor_at_window (gdpy, - gtk_widget_get_window (widget)); - - if (gmon != NULL) - { - for (i = 0; i < n_monitors; i++) - { - if (gmons[i] == gmon) - { - ASET (monitor_frames, i, - Fcons (frame, AREF (monitor_frames, i))); - break; - } - } - } - } - } - - primary_index = -1; - for (i = 0; i < n_monitors; i++) { - if (gmons[i] != NULL && gdk_monitor_is_primary (gmons[i])) + struct frame *f = XFRAME (frame); + + if (FRAME_PGTK_P (f) + && FRAME_DISPLAY_INFO (f) == dpyinfo + && !FRAME_TOOLTIP_P (f)) { - primary_index = i; - break; + GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + + for (i = 0; i < n_monitors; i++) + if (gdk_display_get_monitor_at_window (gdpy, gwin) + == gdk_display_get_monitor (gdpy, i)) + break; + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); } } - rv = - make_monitor_attribute_list (monitors, n_monitors, primary_index, - monitor_frames, "Gdk"); - + for (i = 0; i < n_monitors; ++i) + { + gint width_mm, height_mm; + GdkRectangle rec, work; + struct MonitorInfo *mi = &monitors[i]; + int scale = 1; + + GdkMonitor *monitor = gdk_display_get_monitor (gdpy, i); + if (gdk_monitor_is_primary (monitor)) + primary_monitor = i; + gdk_monitor_get_geometry (monitor, &rec); + + width_mm = gdk_monitor_get_width_mm (monitor); + height_mm = gdk_monitor_get_height_mm (monitor); + gdk_monitor_get_workarea (monitor, &work); + + /* GTK returns scaled sizes for the workareas. */ + scale = gdk_monitor_get_scale_factor (monitor); + rec.x *= scale; + rec.y *= scale; + rec.width *= scale; + rec.height *= scale; + work.x *= scale; + work.y *= scale; + work.width *= scale; + work.height *= scale; + + mi->geom.x = rec.x; + mi->geom.y = rec.y; + mi->geom.width = rec.width; + mi->geom.height = rec.height; + mi->work.x = work.x; + mi->work.y = work.y; + mi->work.width = work.width; + mi->work.height = work.height; + mi->mm_width = width_mm; + mi->mm_height = height_mm; + + dupstring (&mi->name, (gdk_monitor_get_model (monitor))); + } + + attributes_list = make_monitor_attribute_list (monitors, + n_monitors, + primary_monitor, + monitor_frames, + source); free_monitors (monitors, n_monitors); - xfree (gmons); + unblock_input (); - return rv; + return attributes_list; } commit ce14970f0268a5f27156aaf3612973c9d7b43780 Author: Yuuki Harano Date: Sun Dec 27 03:25:22 2020 +0900 Follow get-buffer-create change * src/pgtkfns.c (Fx_show_tip): Pass nil to get-buffer-create. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 1bf1c612ff..cf84163fee 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3208,7 +3208,7 @@ Text larger than the specified size is clipped. */) tip_f = XFRAME (tip_frame); window = FRAME_ROOT_WINDOW (tip_f); - tip_buf = Fget_buffer_create (tip); + tip_buf = Fget_buffer_create (tip, Qnil); /* We will mark the tip window a "pseudo-window" below, and such windows cannot have display margins. */ bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0)); commit b64089c37b4305a511e5ddbf02746862c7c7575e Merge: 565d8f57d3 4b2ca6bfc0 Author: Yuuki Harano Date: Sun Dec 27 03:13:00 2020 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit 565d8f57d349c19d9bbb5d5d5fdacf3c70b85d42 Merge: a44cd7c881 87b82a1969 Author: Yuuki Harano Date: Mon Dec 21 01:53:07 2020 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit a44cd7c88121bb0e04bdf13d73e15f085cf3b085 Author: Yuuki Harano Date: Mon Dec 14 02:05:29 2020 +0900 * src/pgtkterm.c (map_event): Remove record_asynch_buffer_change call. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f59bc85288..568de7ca8d 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5949,10 +5949,6 @@ map_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = DEICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } - else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list))) - /* Force a redisplay sooner or later to update the - frame titles in case this is the second frame. */ - record_asynch_buffer_change (); } if (inev.ie.kind != NO_EVENT) commit 3e30047ce3a81dd0879973012abbf570d3215dfd Merge: aea5dbec25 fe50a8b9ba Author: Yuuki Harano Date: Mon Dec 14 01:52:10 2020 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit aea5dbec2514811fb2e1cc44b2347a976a5b7de8 Author: Yuuki Harano Date: Tue Dec 8 21:46:26 2020 +0900 Fix DEL key behavior * lisp/simple.el (normal-erase-is-backspace-setup-frame): Include pgtk in window-system group. diff --git a/lisp/simple.el b/lisp/simple.el index d73bc6b068..1f90db3dea 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9180,7 +9180,7 @@ call `normal-erase-is-backspace-mode' (which see) instead." (if (if (eq normal-erase-is-backspace 'maybe) (and (not noninteractive) (or (memq system-type '(ms-dos windows-nt)) - (memq window-system '(w32 ns)) + (memq window-system '(w32 ns pgtk)) (and (eq window-system 'x) (fboundp 'x-backspace-delete-keys-p) (x-backspace-delete-keys-p)) commit da92d5700eff8f628b6306202635a2514eb8b387 Merge: d46a223d85 dc39c66d3b Author: Yuuki Harano Date: Sat Dec 5 20:30:42 2020 +0900 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk commit d46a223d8595e8edb67c6361033625797503cacf Merge: 62abc05404 769dc33df7 Author: Yuuki Harano Date: Sun Nov 29 02:12:15 2020 +0900 Merge branch 'master' into feature/pgtk commit 62abc054041a592ca617ab228d61469dd7923a3f Author: Yuuki Harano Date: Sun Nov 29 01:04:29 2020 +0900 * src/pgtkterm.c (scroll_event): Shut up warnings diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f3675b49fb..f59bc85288 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6574,6 +6574,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= down_modifier; break; + case GDK_SCROLL_SMOOTH: /* shut up warning */ + break; } } else if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y)) commit fc68127ce8b273834bed951510d5bb39d12e5615 Author: Yuuki Harano Date: Sat Nov 28 21:55:18 2020 +0900 Improve smooth scroll * src/pgtkterm.c (scroll_event): Accumulate deltas and calculate the number of lines. (pgtk_term_init): Set smooth scroll parameters. * src/pgtkterm.h (scroll): New members to store parameters. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0cf9bb84e7..f3675b49fb 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6530,6 +6530,8 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; + GdkScrollDirection dir; + double delta_x, delta_y; EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; @@ -6543,7 +6545,7 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) else f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); - inev.ie.kind = WHEEL_EVENT; + inev.ie.kind = NO_EVENT; inev.ie.timestamp = event->scroll.time; inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state); @@ -6552,50 +6554,64 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) XSETFRAME (inev.ie.frame_or_window, f); inev.ie.arg = Qnil; - switch (event->scroll.direction) + if (gdk_event_get_scroll_direction (event, &dir)) { - case GDK_SCROLL_UP: - inev.ie.kind = WHEEL_EVENT; - inev.ie.modifiers |= up_modifier; - break; - case GDK_SCROLL_DOWN: - inev.ie.kind = WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; - break; - case GDK_SCROLL_LEFT: - inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= up_modifier; - break; - case GDK_SCROLL_RIGHT: - inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; - break; - case GDK_SCROLL_SMOOTH: - if (event->scroll.delta_y >= 0.5) + switch (dir) { + case GDK_SCROLL_UP: + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + break; + case GDK_SCROLL_DOWN: inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= down_modifier; + break; + case GDK_SCROLL_LEFT: + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + break; + case GDK_SCROLL_RIGHT: + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + break; } - else if (event->scroll.delta_y <= -0.5) + } + else if (gdk_event_get_scroll_deltas (event, &delta_x, &delta_y)) + { + dpyinfo->scroll.acc_x += delta_x; + dpyinfo->scroll.acc_y += delta_y; + if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line) { + int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + inev.ie.arg = make_fixnum(nlines); + dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines; + } + else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line) + { + int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line; inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= up_modifier; + inev.ie.arg = make_fixnum(nlines); + dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines; } - else if (event->scroll.delta_x >= 0.5) + else if (dpyinfo->scroll.acc_x >= dpyinfo->scroll.x_per_char) { + int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; + inev.ie.modifiers |= up_modifier; + inev.ie.arg = make_fixnum(nchars); + dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars; } - else if (event->scroll.delta_x <= -0.5) + else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char) { + int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char; inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= up_modifier; + inev.ie.modifiers |= down_modifier; + inev.ie.arg = make_fixnum(nchars); + dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars; } - else - return TRUE; - break; - default: - return TRUE; } if (inev.ie.kind != NO_EVENT) @@ -6943,6 +6959,10 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->resy = dpi; } + /* smooth scroll setting */ + dpyinfo->scroll.x_per_char = 2; + dpyinfo->scroll.y_per_line = 2; + x_setup_pointer_blanking (dpyinfo); xsettings_initialize (dpyinfo); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 09b3b21b17..5e71f93998 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -246,6 +246,12 @@ struct pgtk_display_info GtkIMContext *context; struct frame *focused_frame; } im; + + struct + { + double acc_x, acc_y; + double x_per_char, y_per_line; + } scroll; }; /* This is a chain of structures for all the PGTK displays currently in use. */ commit 197b37c7689578bf3b08fd690c97df122e8d3547 Author: Yuuki Harano Date: Sat Nov 28 00:14:23 2020 +0900 Enable harfbuzz * src/pgtkfns.c (Fx_create_frame): Register ftcrhb font driver if enabled. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index e280bb33d2..1bf1c612ff 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1314,6 +1314,9 @@ This function is an internal primitive--use `make-frame' instead. */ ) } register_font_driver (&ftcrfont_driver, f); +#ifdef HAVE_HARFBUZZ + register_font_driver (&ftcrhbfont_driver, f); +#endif /* HAVE_HARFBUZZ */ image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; commit db169f81346f3a642b645937218dc3d1dae3301f Author: Yuuki Harano Date: Thu Nov 26 23:44:29 2020 +0900 Add support for hyper modifier key * src/pgtkterm.c (x_find_modifier_meanings): Autodetect key mask. (pgtk_gtk_to_emacs_modifiers): Use autodetected mask instead of GDK's. (pgtk_emacs_to_gtk_modifiers): Use autodetected mask instead of GDK's. (key_press_event): Ignore hyper as well as super. * src/pgtkterm.h (struct pgtk_display_info): New member for hyper. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 6f2bb2898b..0cf9bb84e7 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5441,6 +5441,25 @@ x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) { dpyinfo->super_mod_mask = GDK_MOD4_MASK; } + + state = GDK_HYPER_MASK; + r = gdk_keymap_map_virtual_modifiers (keymap, &state); + if (r) + { + /* Hyper key exists. */ + if (state == GDK_HYPER_MASK) + { + dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; /* maybe this is hyper. */ + } + else + { + dpyinfo->hyper_mod_mask = state & ~GDK_HYPER_MASK; + } + } + else + { + dpyinfo->hyper_mod_mask = GDK_MOD3_MASK; + } } static void @@ -5497,7 +5516,7 @@ pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state) mod |= mod_alt; if (state & dpyinfo->super_mod_mask) mod |= mod_super; - if (state & GDK_HYPER_MASK) + if (state & dpyinfo->hyper_mod_mask) mod |= mod_hyper; return mod; } @@ -5521,7 +5540,7 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) if (state & mod_super) mask |= dpyinfo->super_mod_mask; if (state & mod_hyper) - mask |= GDK_HYPER_MASK; + mask |= dpyinfo->hyper_mod_mask; if (state & shift_modifier) mask |= GDK_SHIFT_MASK; if (state & mod_ctrl) @@ -5613,10 +5632,10 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { /* While super is pressed, gtk_im_context_filter_keypress() always process the * key events ignoring super. - * As a work around, don't call it while super is pressed... + * As a work around, don't call it while super or hyper are pressed... */ struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - if (!(event->key.state & dpyinfo->super_mod_mask)) + if (!(event->key.state & (dpyinfo->super_mod_mask | dpyinfo->hyper_mod_mask))) { if (pgtk_im_filter_keypress (f, &event->key)) return TRUE; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index a777885518..09b3b21b17 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -235,7 +235,7 @@ struct pgtk_display_info struct frame *last_mouse_glyph_frame; /* Modifier masks in gdk */ - int meta_mod_mask, alt_mod_mask, super_mod_mask; + int meta_mod_mask, alt_mod_mask, super_mod_mask, hyper_mod_mask; /* The last click event. */ GdkEvent *last_click_event; commit 68b8acc405f2f7f7cfca6fe88820dfa13161a3c6 Author: Yuuki Harano Date: Wed Nov 25 20:40:10 2020 +0900 Fix compilation issue when --enable-checking=glyphs * src/pgtkfns.c (Fx_create_frame): Remove code surrounded by GLYPH_DEBUG. (x_create_tip_frame): Remove code surrounded by GLYPH_DEBUG. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 494cbc7282..e280bb33d2 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1317,11 +1317,6 @@ This function is an internal primitive--use `make-frame' instead. */ ) image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; -#if 0 -#ifdef GLYPH_DEBUG - dpyinfo_refcount = dpyinfo->reference_count; -#endif /* GLYPH_DEBUG */ -#endif gui_default_parameter (f, parms, Qfont_backend, Qnil, "fontBackend", "FontBackend", RES_TYPE_STRING); @@ -2657,9 +2652,6 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct image_cache_refcount = FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; -#ifdef GLYPH_DEBUG - dpyinfo_refcount = dpyinfo->reference_count; -#endif /* GLYPH_DEBUG */ gui_default_parameter (f, parms, Qfont_backend, Qnil, "fontBackend", "FontBackend", RES_TYPE_STRING); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index ab61283e06..6f2bb2898b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1004,8 +1004,6 @@ x_set_cursor_gc (struct glyph_string *s) PGTK_TRACE ("x_set_cursor_gc: 6. %08lx, %08lx.", xgcv.background, xgcv.foreground); - IF_DEBUG (x_check_font (s->f, s->font)); - s->xgcv = xgcv; } } commit d6ef9af82eafef33e117dd61aa3bd51a2464fcc6 Author: Yuuki Harano Date: Sat Nov 21 17:18:49 2020 +0900 Fix crash when .schema.xml is not installed * src/pgtkfns.c (parse_resource_key): Check return value. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index f1ad9ca272..494cbc7282 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1861,10 +1861,13 @@ parse_resource_key (const char *res_key, char *setting_key) /* check existence of setting_key */ GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default (); GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, FALSE); - if (!g_settings_schema_has_key (scm, setting_key)) { - g_settings_schema_unref (scm); - return NULL; - } + if (!scm) + return NULL; /* *.schema.xml is not installed. */ + if (!g_settings_schema_has_key (scm, setting_key)) + { + g_settings_schema_unref (scm); + return NULL; + } /* create GSettings, and return it */ GSettings *gs = g_settings_new_full (scm, NULL, path); commit 731b5e8e318cf09d18d9821e9b0e24633e9204da Author: Yuuki Harano Date: Fri Nov 20 21:17:41 2020 +0900 Add copyright line * etc/org.gnu.emacs.defaults.gschema.xml: Add copyright line. diff --git a/etc/org.gnu.emacs.defaults.gschema.xml b/etc/org.gnu.emacs.defaults.gschema.xml index 2d206e63a0..7c700ac0b6 100644 --- a/etc/org.gnu.emacs.defaults.gschema.xml +++ b/etc/org.gnu.emacs.defaults.gschema.xml @@ -1,4 +1,5 @@ + commit b1b744057f4605cf7165a2041d2979a7decdacff Author: Yuuki Harano Date: Thu Nov 19 01:20:06 2020 +0900 Work around gtk_im_context_filter_keypress() issue with super key * src/pgtkterm.c (x_find_modifier_meanings): Convert virtual super to non-virtual one. (pgtk_gtk_to_emacs_modifiers): Use non-virtual one. (pgtk_emacs_to_gtk_modifiers): Use non-virtual one. (key_press_event): Don't call pgtk_im_context_filter_keypress while super is pressed. * src/pgtkterm.h (struct pgtk_display_info): New member. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d7bbfe1511..ab61283e06 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5424,6 +5424,25 @@ x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) dpyinfo->meta_mod_mask = GDK_MOD1_MASK; dpyinfo->alt_mod_mask = 0; } + + state = GDK_SUPER_MASK; + r = gdk_keymap_map_virtual_modifiers (keymap, &state); + if (r) + { + /* Super key exists. */ + if (state == GDK_SUPER_MASK) + { + dpyinfo->super_mod_mask = GDK_MOD4_MASK; /* maybe this is super. */ + } + else + { + dpyinfo->super_mod_mask = state & ~GDK_SUPER_MASK; + } + } + else + { + dpyinfo->super_mod_mask = GDK_MOD4_MASK; + } } static void @@ -5478,7 +5497,7 @@ pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state) mod |= mod_meta; if (state & dpyinfo->alt_mod_mask) mod |= mod_alt; - if (state & GDK_SUPER_MASK) + if (state & dpyinfo->super_mod_mask) mod |= mod_super; if (state & GDK_HYPER_MASK) mod |= mod_hyper; @@ -5502,7 +5521,7 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) if (state & mod_alt) mask |= dpyinfo->alt_mod_mask; if (state & mod_super) - mask |= GDK_SUPER_MASK; + mask |= dpyinfo->super_mod_mask; if (state & mod_hyper) mask |= GDK_HYPER_MASK; if (state & shift_modifier) @@ -5594,8 +5613,16 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) if (f != 0) { - if (pgtk_im_filter_keypress (f, &event->key)) - return TRUE; + /* While super is pressed, gtk_im_context_filter_keypress() always process the + * key events ignoring super. + * As a work around, don't call it while super is pressed... + */ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (!(event->key.state & dpyinfo->super_mod_mask)) + { + if (pgtk_im_filter_keypress (f, &event->key)) + return TRUE; + } } if (f != 0) diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 641509bb4e..a777885518 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -235,7 +235,7 @@ struct pgtk_display_info struct frame *last_mouse_glyph_frame; /* Modifier masks in gdk */ - int meta_mod_mask, alt_mod_mask; + int meta_mod_mask, alt_mod_mask, super_mod_mask; /* The last click event. */ GdkEvent *last_click_event; commit 8fa5427130c67a9710838672a61eaf2db0eb16ba Author: Jeff Walsh Date: Wed Nov 18 13:46:17 2020 +1100 lisp/term/pgtk-win.el: Add copyright file header diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index e84fbf9168..6e970c45d8 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -1,4 +1,26 @@ -;;; +;;; xterm.el --- define function key sequences and standard colors for xterm -*- lexical-binding: t -*- + +;; Copyright (C) 1995, 2001-2020 Free Software Foundation, Inc. + +;; Author: FSF +;; Keywords: terminals + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs 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 GNU Emacs. If not, see . + +;;; Commentary: ;;; Code: (eval-when-compile (require 'cl-lib)) commit 886fcb237d4db5ab14e8f3e599c5a4dbd0c9ff79 Author: Jeff Walsh Date: Wed Nov 18 11:18:07 2020 +1100 Update copyright dates for PGTK files * src/pgtkfns.c: * src/pgtkgui.h: * src/pgtkim.c: * src/pgtkmenu.c: * src/pgtkselect.c: * src/pgtkselect.h: * src/pgtkterm.c: * src/pgtkterm.h: Update copyright dates - No Funtional Changes diff --git a/src/pgtkfns.c b/src/pgtkfns.c index ece63517b2..f1ad9ca272 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1,6 +1,6 @@ /* Functions for the pure Gtk+-3. -Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2017 Free Software +Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkgui.h b/src/pgtkgui.h index 08559207d4..7342dacc5b 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -1,5 +1,5 @@ /* Definitions and headers for communication on the pure Gtk+3. - Copyright (C) 1995, 2005, 2008-2017 Free Software Foundation, Inc. + Copyright (C) 1995, 2005, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkim.c b/src/pgtkim.c index 0ec931c4b1..68f83d2c6e 100644 --- a/src/pgtkim.c +++ b/src/pgtkim.c @@ -1,6 +1,6 @@ /* Pure Gtk+-3 communication module. -*- coding: utf-8 -*- -Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2018 Free Software +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 79f562e2ab..be68e29ca2 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -1,5 +1,5 @@ /* Pure GTK3 menu and toolbar module. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 491c50b336..3e57fc7526 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -1,5 +1,5 @@ /* Gtk selection processing for emacs. - Copyright (C) 1993-1994, 2005-2006, 2008-2017 Free Software + Copyright (C) 1993-1994, 2005-2006, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkselect.h b/src/pgtkselect.h index 9dad58017d..7ad04c217a 100644 --- a/src/pgtkselect.h +++ b/src/pgtkselect.h @@ -1,5 +1,5 @@ /* Definitions and headers for selection of pure Gtk+3. - Copyright (C) 1989, 1993, 2005, 2008-2017 Free Software Foundation, + Copyright (C) 1989, 1993, 2005, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5527b7fc2a..d7bbfe1511 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1,6 +1,6 @@ /* Pure Gtk+-3 communication module. -*- coding: utf-8 -*- -Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2017 Free Software +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. diff --git a/src/pgtkterm.h b/src/pgtkterm.h index a2714a3afe..641509bb4e 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -1,5 +1,5 @@ /* Definitions and headers for communication with pure Gtk+3. - Copyright (C) 1989, 1993, 2005, 2008-2017 Free Software Foundation, + Copyright (C) 1989, 1993, 2005, 2008-2020 Free Software Foundation, Inc. This file is part of GNU Emacs. commit e405404d10ef5b24e06d02f626c4bf27a3ae525d Author: Yuuki Harano Date: Mon Oct 26 22:05:55 2020 +0900 Fix startup failure on svg-unsupported environments * src/pgtkterm.c (pgtk_bitmap_icon): Re-port X-code. (pgtk_term_init): Add member initialization. * src/pgtkterm.h (struct pgtk_display_info): Add member. (struct pgtk_output): Add member. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 6e2c87f821..5527b7fc2a 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -52,6 +52,7 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "termopts.h" #include "termchar.h" +#include "emacs-icon.h" #include "menu.h" #include "window.h" #include "keyboard.h" @@ -3029,25 +3030,69 @@ pgtk_scroll_run (struct window *w, struct run *run) static bool pgtk_bitmap_icon (struct frame *f, Lisp_Object file) { + ptrdiff_t bitmap_id; + if (FRAME_GTK_WIDGET (f) == 0) return true; + /* Free up our existing icon bitmap and mask if any. */ + if (f->output_data.pgtk->icon_bitmap > 0) + image_destroy_bitmap (f, f->output_data.pgtk->icon_bitmap); + f->output_data.pgtk->icon_bitmap = 0; + if (STRINGP (file)) { /* Use gtk_window_set_icon_from_file () if available, - It's not restricted to bitmaps */ + It's not restricted to bitmaps */ if (xg_set_icon (f, file)) return false; + bitmap_id = image_create_bitmap_from_file (f, file); + } + else + { + /* Create the GNU bitmap and mask if necessary. */ + if (FRAME_DISPLAY_INFO (f)->icon_bitmap_id < 0) + { + ptrdiff_t rc = -1; - return true; + if (xg_set_icon (f, xg_default_icon_file) + || xg_set_icon_from_xpm_data (f, gnu_xpm_bits)) + { + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = -2; + return false; + } + + /* If all else fails, use the (black and white) xbm image. */ + if (rc == -1) + { + rc = image_create_bitmap_from_data (f, + (char *) gnu_xbm_bits, + gnu_xbm_width, + gnu_xbm_height); + if (rc == -1) + return true; + + FRAME_DISPLAY_INFO (f)->icon_bitmap_id = rc; + } + } + + /* The first time we create the GNU bitmap and mask, + this increments the ref-count one extra time. + As a result, the GNU bitmap and mask are never freed. + That way, we don't have to worry about allocating it again. */ + image_reference_bitmap (f, FRAME_DISPLAY_INFO (f)->icon_bitmap_id); + + bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id; } - if (xg_set_icon (f, xg_default_icon_file)) + if (FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img != NULL) { - return false; + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img); } + f->output_data.pgtk->icon_bitmap = bitmap_id; - return true; + return false; } @@ -6837,6 +6882,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->horizontal_scroll_bar_cursor = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW); + dpyinfo->icon_bitmap_id = -1; + reset_mouse_highlight (&dpyinfo->mouse_highlight); { diff --git a/src/pgtkterm.h b/src/pgtkterm.h index ad66039648..a2714a3afe 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -172,6 +172,10 @@ struct pgtk_display_info int color_p; + /* Emacs bitmap-id of the default icon bitmap for this frame. + Or -1 if none has been allocated yet. */ + ptrdiff_t icon_bitmap_id; + Window root_window; /* Xism */ @@ -296,6 +300,10 @@ struct pgtk_output Window window_desc, parent_desc; char explicit_parent; + /* If >=0, a bitmap index. The indicated bitmap is used for the + icon. */ + ptrdiff_t icon_bitmap; + struct font *font; int baseline_offset; commit 948e2fa582ff33b58d25186ea35f41adaa9d6cbe Author: Yuuki Harano Date: Sun Oct 18 20:14:52 2020 +0900 Avoid weird behavior when resizing with top-left corner * src/frame.c (syms_of_frame): Defaults frame_resize_pixelwise to true. diff --git a/src/frame.c b/src/frame.c index 191b0268c5..2a55755bba 100644 --- a/src/frame.c +++ b/src/frame.c @@ -6260,7 +6260,12 @@ With some window managers you may have to set this to non-nil in order to set the size of a frame in pixels, to maximize frames or to make them fullscreen. To resize your initial frame pixelwise, set this option to a non-nil value in your init file. */); +#ifndef HAVE_PGTK frame_resize_pixelwise = 0; +#else + /* https://gitlab.gnome.org/GNOME/mutter/-/issues/396 */ + frame_resize_pixelwise = true; +#endif DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize, doc: /* Whether frames should be resized implicitly. commit c1fbfb3fe04e3185fa64df2ed69cd97b0a6bbb40 Author: Yuuki Harano Date: Sat Oct 17 03:47:03 2020 +0900 Don't use gtk_window_resize to resize offscreen window * src/xwidget.c (Fmake_xwidget): Use gtk_container_check_resize instead. (Fxwidget_resize): Use gtk_container_check_resize instead. ; Gtk+3 document says: ; > Applications should not use any API specific to GtkWindow ; > to operate on this object. It should be treated as a GtkBin ; > that has no parent widget. diff --git a/src/xwidget.c b/src/xwidget.c index c9fc706663..893292cf5a 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -122,8 +122,12 @@ Returns the newly constructed xwidget, or nil if construction fails. */) # endif xw->widgetwindow_osr = gtk_offscreen_window_new (); +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, xw->height); +#else + gtk_container_check_resize (GTK_CONTAINER (xw->widgetwindow_osr)); +#endif if (EQ (xw->type, Qwebkit)) { @@ -966,8 +970,12 @@ DEFUN ("xwidget-resize", Fxwidget_resize, Sxwidget_resize, 3, 3, 0, #ifdef USE_GTK if (xw->widget_osr) { +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (xw->widgetwindow_osr), xw->width, xw->height); +#else + gtk_container_check_resize (GTK_CONTAINER (xw->widgetwindow_osr)); +#endif gtk_container_resize_children (GTK_CONTAINER (xw->widgetwindow_osr)); gtk_widget_set_size_request (GTK_WIDGET (xw->widget_osr), xw->width, xw->height); commit d437aabe4da94dd1a19c318a6c1f88c2df94ed1a Author: Yuuki Harano Date: Sat Oct 17 03:51:15 2020 +0900 Avoid gtk warnings on X * src/xwidget.c (xwidget_osr_draw_cb): Call it to avoid alloc_needes. diff --git a/src/xwidget.c b/src/xwidget.c index e929df0a49..c9fc706663 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -510,6 +510,10 @@ xwidget_osr_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data) cairo_rectangle (cr, 0, 0, xv->clip_right, xv->clip_bottom); cairo_clip (cr); +#ifdef HAVE_PGTK + gtk_container_check_resize (GTK_CONTAINER (xw->widgetwindow_osr)); +#endif + gtk_widget_draw (xw->widget_osr, cr); return FALSE; } commit 7b6fea821ad040f7e8358b2afd9c0eaead967c2c Author: Kira Bruneau Date: Thu Oct 15 14:46:44 2020 -0400 Avoid mutating invocation-name (tiny change) * lisp/term/pgtk-win.el (window-system-initialization): copy invocation-name. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index a41d3a3951..e84fbf9168 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -303,7 +303,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") ;; Make sure we have a valid resource name. (or (stringp x-resource-name) (let (i) - (setq x-resource-name invocation-name) + (setq x-resource-name (copy-sequence invocation-name)) ;; Change any . or * characters in x-resource-name to hyphens, ;; so as not to choke when we use it in X resource queries. commit 4dbea5be1758788d9f6177ca3f7eaedc9e01ad56 Author: Yuuki Harano Date: Mon Oct 5 21:18:06 2020 +0900 Fix Gtk warnings * src/gtkutil.c (xg_frame_set_char_size): Call appropriate function (xg_set_undecorated): Do nothing if child frame. (xg_set_no_focus_on_map): Do nothing if child frame. (xg_set_no_accept_focus): Do nothing if child frame. (xg_set_frame_icon): Do nothing if child frame. (xg_get_file_name): Do nothing if child frame. (xg_get_font): * src/pgtkterm.c (pgtk_focus_frame): Do nothing if child frames. (x_set_frame_alpha): Select correct widget. (x_new_focus_frame): Focus only when non-child frames. (pgtk_set_event_handler): Don't set for child frames. * src/pgtkfns.c (xg_set_icon): Do nothing if child frames. (xg_set_icon_from_xpm_data): Do nothing if child frames. (pgtk_set_sticky): Do nothing if child frames. (Fx_show_tip): Do nothing if child frames. (Fpgtk_set_mouse_absolute_pixel_position): Select correct widget. (Fpgtk_mouse_absolute_pixel_position): Select correct widget. * src/pgtkmenu.c (pgtk_menu_show): (pgtk_dialog_show): diff --git a/src/gtkutil.c b/src/gtkutil.c index 56d415887d..a62616bbfc 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1098,8 +1098,21 @@ xg_frame_set_char_size (struct frame *f, int width, int height) (f, Qxg_frame_set_char_size_1, width, height, list2i (gheight, totalheight)); +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gwidth, totalheight); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + gwidth, totalheight); + } + else + { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + gwidth, totalheight); + } +#endif } else if (EQ (fullscreen, Qfullheight) && height == FRAME_TEXT_HEIGHT (f)) { @@ -1107,8 +1120,21 @@ xg_frame_set_char_size (struct frame *f, int width, int height) (f, Qxg_frame_set_char_size_2, width, height, list2i (gwidth, totalwidth)); +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), totalwidth, gheight); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + totalwidth, gheight); + } + else + { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + totalwidth, gheight); + } +#endif } else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)) { @@ -1880,6 +1906,10 @@ xg_set_background_color (struct frame *f, unsigned long bg) void xg_set_undecorated (struct frame *f, Lisp_Object undecorated) { +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; +#endif if (FRAME_GTK_WIDGET (f)) { block_input (); @@ -1940,6 +1970,10 @@ xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar) void xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map) { +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; +#endif block_input (); if (FRAME_GTK_WIDGET (f)) { @@ -1955,14 +1989,12 @@ xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map) void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus) { - block_input (); - if ( -#ifndef HAVE_PGTK - FRAME_GTK_WIDGET (f) -#else - FRAME_GTK_OUTER_WIDGET (f) +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; #endif - ) + block_input (); + if (FRAME_GTK_WIDGET (f)) { GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE; @@ -1994,6 +2026,10 @@ xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect) void xg_set_frame_icon (struct frame *f, Pixmap icon_pixmap, Pixmap icon_mask) { +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; +#endif GdkPixbuf *gp = xg_get_pixbuf_from_pix_and_mask (f, icon_pixmap, icon_mask); @@ -2537,6 +2573,11 @@ xg_get_file_name (struct frame *f, int filesel_done = 0; xg_get_file_func func; +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + error("Can't open dialog from child frames"); +#endif + #ifdef HAVE_GTK_FILE_SELECTION_NEW if (xg_uses_old_file_dialog ()) @@ -2620,6 +2661,11 @@ xg_get_font (struct frame *f, const char *default_name) int done = 0; Lisp_Object font = Qnil; +#ifdef HAVE_PGTK + if (!FRAME_GTK_OUTER_WIDGET (f)) + error("Can't open dialog from child frames"); +#endif + w = gtk_font_chooser_dialog_new ("Pick a font", GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4ecb03b91c..ece63517b2 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -719,6 +719,9 @@ xg_set_icon (struct frame *f, Lisp_Object file) bool result = false; Lisp_Object found; + if (!FRAME_GTK_OUTER_WIDGET (f)) + return false; + found = image_find_image_file (file); if (!NILP (found)) @@ -755,6 +758,9 @@ xg_set_icon_from_xpm_data (struct frame *f, const char **data) if (!pixbuf) return false; + if (!FRAME_GTK_OUTER_WIDGET (f)) + return false; + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); g_object_unref (pixbuf); return true; @@ -764,6 +770,9 @@ static void pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; + if (!NILP (new_value)) gtk_window_stick (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); else @@ -3055,6 +3064,9 @@ Text larger than the specified size is clipped. */) frame = selected_frame; f = decode_window_system_frame (frame); + if (!FRAME_GTK_OUTER_WIDGET (f)) + return unbind_to (count, Qnil); + if (NILP (timeout)) timeout = make_fixnum (5); else @@ -3457,7 +3469,7 @@ The coordinates X and Y are interpreted in pixels relative to a position (Lisp_Object x, Lisp_Object y) { struct frame *f = SELECTED_FRAME (); - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + GtkWidget *widget = gtk_widget_get_toplevel (FRAME_WIDGET (f)); GdkWindow *window = gtk_widget_get_window (widget); GdkDisplay *gdpy = gdk_window_get_display (window); GdkScreen *gscr = gdk_window_get_screen (window); @@ -3478,7 +3490,7 @@ position (0, 0) of the selected frame's terminal. */) (void) { struct frame *f = SELECTED_FRAME (); - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + GtkWidget *widget = gtk_widget_get_toplevel (FRAME_WIDGET (f)); GdkWindow *window = gtk_widget_get_window (widget); GdkDisplay *gdpy = gdk_window_get_display (window); GdkScreen *gscr; diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 7d15340b6b..79f562e2ab 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -640,6 +640,11 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, *error_name = NULL; + if (!FRAME_GTK_OUTER_WIDGET (f)) { + *error_name = "Can't popup from child frames."; + return Qnil; + } + if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) { *error_name = "Empty menu"; @@ -944,6 +949,11 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, *error_name = NULL; + if (!FRAME_GTK_OUTER_WIDGET (f)) { + *error_name = "Can't popup from child frames."; + return Qnil; + } + if (menu_items_n_panes > 1) { *error_name = "Multiple panes in dialog box"; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index c66379e6e4..6e2c87f821 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4660,7 +4660,7 @@ pgtk_focus_frame (struct frame *f, bool noactivate) GtkWidget *wid = FRAME_GTK_OUTER_WIDGET (f); - if (dpyinfo->x_focus_frame != f) + if (dpyinfo->x_focus_frame != f && wid != NULL) { block_input (); gtk_window_present (GTK_WINDOW (wid)); @@ -4718,9 +4718,9 @@ x_set_frame_alpha (struct frame *f) } #endif - set_opacity_recursively (FRAME_GTK_OUTER_WIDGET (f), &alpha); + set_opacity_recursively (FRAME_WIDGET (f), &alpha); /* without this, blending mode is strange on wayland. */ - gtk_widget_queue_resize_no_redraw (FRAME_GTK_OUTER_WIDGET (f)); + gtk_widget_queue_resize_no_redraw (FRAME_WIDGET (f)); } static void @@ -4891,12 +4891,14 @@ x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) dpyinfo->x_focus_frame = frame; if (old_focus && old_focus->auto_lower) - gdk_window_lower (gtk_widget_get_window - (FRAME_GTK_OUTER_WIDGET (old_focus))); + if (FRAME_GTK_OUTER_WIDGET (old_focus)) + gdk_window_lower (gtk_widget_get_window + (FRAME_GTK_OUTER_WIDGET (old_focus))); if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) - gdk_window_raise (gtk_widget_get_window - (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); + if (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame)) + gdk_window_raise (gtk_widget_get_window + (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); } pgtk_frame_rehighlight (dpyinfo); @@ -6567,15 +6569,18 @@ pgtk_set_event_handler (struct frame *f) GDK_ACTION_COPY); gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f)); - g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), - "window-state-event", G_CALLBACK (window_state_event), - NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event", - G_CALLBACK (delete_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event", - G_CALLBACK (pgtk_handle_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "configure-event", - G_CALLBACK (configure_event), NULL); + if (FRAME_GTK_OUTER_WIDGET (f)) + { + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), + "window-state-event", G_CALLBACK (window_state_event), + NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event", + G_CALLBACK (delete_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event", + G_CALLBACK (pgtk_handle_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "configure-event", + G_CALLBACK (configure_event), NULL); + } g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event", G_CALLBACK (map_event), NULL); commit bb6862df1beddeaa4802af58b94332ba48afbb4f Author: Yuuki Harano Date: Sat Oct 3 20:09:07 2020 +0900 Fix crash on drag and drop * src/pgtkterm.c (pgtk_select): Move dispatch before g_main_context_query. (drag_drop): Remove drag_drop. (drag_data_received): Rename arg. (pgtk_set_event_handler): Remove drag-drop callback. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index a5cf0a8159..c66379e6e4 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3841,6 +3841,20 @@ pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, Note that, as implemented, this failure is completely silent: there is no feedback to the caller. */ + /* Before sleep, dispatch draw events. + * Don't do this after g_main_context_query(), because fd may be closed + * in dispatch. + */ + if (context_acquired) + { + int pselect_errno = errno; + block_input (); + while (g_main_context_pending (context)) + g_main_context_dispatch (context); + unblock_input (); + errno = pselect_errno; + } + if (rfds) all_rfds = *rfds; else @@ -3895,17 +3909,6 @@ pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, tmop = &tmo; } - /* Before sleep, dispatch draw events. */ - if (context_acquired) - { - int pselect_errno = errno; - block_input (); - while (g_main_context_pending (context)) - g_main_context_dispatch (context); - unblock_input (); - errno = pselect_errno; - } - fds_lim = max_fds + 1; nfds = thread_select (pselect, fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, @@ -6509,31 +6512,11 @@ scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) return TRUE; } -static gboolean -drag_drop (GtkWidget * widget, - GdkDragContext * context, - gint x, gint y, guint time_, gpointer user_data) -{ - PGTK_TRACE ("drag_drop"); - GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL); - PGTK_TRACE ("drag_drop: target: %p", (void *) target); - - if (target == GDK_NONE) - { - gtk_drag_finish (context, TRUE, FALSE, time_); - return FALSE; - } - - gtk_drag_get_data (widget, context, target, time_); - - return TRUE; -} - static void drag_data_received (GtkWidget * widget, GdkDragContext * context, gint x, gint y, GtkSelectionData * data, - guint info, guint time_, gpointer user_data) + guint info, guint time, gpointer user_data) { PGTK_TRACE ("drag_data_received:"); struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); @@ -6567,7 +6550,7 @@ drag_data_received (GtkWidget * widget, GdkDragContext * context, } PGTK_TRACE ("drag_data_received: that's all."); - gtk_drag_finish (context, TRUE, FALSE, time_); + gtk_drag_finish (context, TRUE, FALSE, time); } void @@ -6622,8 +6605,6 @@ pgtk_set_event_handler (struct frame *f) G_CALLBACK (pgtk_selection_lost), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", G_CALLBACK (configure_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop", - G_CALLBACK (drag_drop), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", G_CALLBACK (drag_data_received), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", commit 640f770b79b3c646fab8cad63076a7d58acdc44a Author: Yuuki Harano Date: Tue Sep 29 23:09:22 2020 +0900 Fix mouse cursor doesn't appear on motion events on xwidgets * src/xwidget.c (xwidget_osr_event_forward): Propagate motion notify. diff --git a/src/xwidget.c b/src/xwidget.c index e078a28a35..e929df0a49 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -527,6 +527,11 @@ xwidget_osr_event_forward (GtkWidget *widget, GdkEvent *event, perhaps in xwgir_event_cb. */ gtk_main_do_event (eventcopy); +#ifdef HAVE_PGTK + /* Pgtk code needs this event */ + if (event->type == GDK_MOTION_NOTIFY) + return FALSE; +#endif /* Don't propagate this event further. */ return TRUE; } commit d899fc11f6a5f55fdb215ad88b183a75123218ae Author: Yuuki Harano Date: Mon Sep 28 22:49:38 2020 +0900 Fix tooltips don't hide on events * src/pgtkterm.c: New variable to indicate whether any event occurs. (configure_event): Clear help string on a event. (leave_notify_event): Clear help string on a event. (motion_notify_event): Use gen_help_event. (pgtk_set_event_handler): Hook configure-event for outer widgets. (pgtk_term_init): Clear the flag. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 224c01551b..a5cf0a8159 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -72,6 +72,10 @@ along with GNU Emacs. If not, see . */ #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ ((f)->output_data.pgtk->cr_surface_desired_height) +/* Non-zero means that a HELP_EVENT has been generated since Emacs + start. */ + +static bool any_help_event_p; struct pgtk_display_info *x_display_list; /* Chain of existing displays */ extern Lisp_Object tip_frame; @@ -5795,12 +5799,18 @@ configure_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) struct frame *f = pgtk_any_window_to_frame (event->configure.window); if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) { - PGTK_TRACE ("%dx%d", event->configure.width, event->configure.height); - xg_frame_resized (f, event->configure.width, event->configure.height); - pgtk_cr_update_surface_desired_size (f, event->configure.width, - event->configure.height); + if (any_help_event_p) + { + Lisp_Object frame; + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + help_echo_string = Qnil; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } } - return TRUE; + return FALSE; } static gboolean @@ -6016,6 +6026,18 @@ leave_notify_event (GtkWidget * widget, GdkEvent * event, if (event->crossing.detail != GDK_NOTIFY_INFERIOR && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT)) x_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev); + + if (frame) + { + if (any_help_event_p) + { + Lisp_Object frame_obj; + XSETFRAME (frame_obj, frame); + help_echo_string = Qnil; + gen_help_event (Qnil, frame_obj, Qnil, Qnil, 0); + } + } + if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; @@ -6218,20 +6240,15 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event, if (do_help > 0) { Lisp_Object frame; - union buffered_input_event inev; if (f) XSETFRAME (frame, f); else frame = Qnil; - inev.ie.kind = HELP_EVENT; - inev.ie.frame_or_window = frame; - inev.ie.arg = help_echo_object; - inev.ie.x = help_echo_window; - inev.ie.y = help_echo_string; - inev.ie.timestamp = help_echo_pos; - evq_enqueue (&inev); + any_help_event_p = true; + gen_help_event (help_echo_string, frame, help_echo_window, + help_echo_object, help_echo_pos); } return TRUE; @@ -6574,6 +6591,8 @@ pgtk_set_event_handler (struct frame *f) G_CALLBACK (delete_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event", G_CALLBACK (pgtk_handle_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "configure-event", + G_CALLBACK (configure_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event", G_CALLBACK (map_event), NULL); @@ -6688,6 +6707,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) if (!x_initialized) { + any_help_event_p = false; + Fset_input_interrupt_mode (Qt); baud_rate = 19200; commit b60d4c9db018bf64ea2eb1ecf434708a7ee82c67 Author: Yuuki Harano Date: Tue Sep 29 17:20:59 2020 +0900 Fix crash on creating child frames. * src/pgtkfns.c (frame_geometry): Returns nil when no widget. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index c6909ba3d6..4ecb03b91c 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3316,6 +3316,8 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), &left_pos, &top_pos); } else { + if (FRAME_GTK_WIDGET (f) == NULL) + return Qnil; /* This can occur while creating a frame. */ GtkAllocation alloc; gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); left_pos = alloc.x; commit 0b69b73baa1e6fb2380e86aa5fab89d5f3a5b061 Author: Yuuki Harano Date: Tue Sep 29 18:38:41 2020 +0900 Fix crash when child frame updates toolbar * src/gtkutil.c (update_frame_tool_bar): Do nothing when child frame. diff --git a/src/gtkutil.c b/src/gtkutil.c index 0f1a51fbbb..56d415887d 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -5348,6 +5348,11 @@ update_frame_tool_bar (struct frame *f) if (! FRAME_GTK_WIDGET (f)) return; +#ifdef HAVE_PGTK + if (! FRAME_GTK_OUTER_WIDGET (f)) + return; +#endif + block_input (); if (RANGED_FIXNUMP (1, Vtool_bar_button_margin, INT_MAX)) commit 7c8da336138eb799bcba8583cb18fc8b3cfe7347 Author: Yuuki Harano Date: Tue Sep 22 00:14:34 2020 +0900 Exclude Xlib's modifier keys * src/pgtkterm.c (IsModifierKey): New macro. (key_press_event): Exclude Xlib's modifier keys. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d62e2a3b16..224c01551b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5464,6 +5464,12 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) #define IsMiscFunctionKey(keysym) (0xff60 <= (keysym) && (keysym) < 0xff6c) #define IsKeypadKey(keysym) (0xff80 <= (keysym) && (keysym) < 0xffbe) #define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1) +#define IsModifierKey(keysym) \ + ((((keysym) >= GDK_KEY_Shift_L) && ((keysym) <= GDK_KEY_Hyper_R)) \ + || (((keysym) >= GDK_KEY_ISO_Lock) && ((keysym) <= GDK_KEY_ISO_Level5_Lock)) \ + || ((keysym) == GDK_KEY_Mode_switch) \ + || ((keysym) == GDK_KEY_Num_Lock)) + void pgtk_enqueue_string (struct frame *f, gchar * str) @@ -5680,6 +5686,10 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) || (orig_keysym & (1 << 28)) || (keysym != GDK_KEY_VoidSymbol && nbytes == 0)) && !(event->key.is_modifier + /* Gtk's modifier keys are different from Xlib's ones. + * I need to exclude them. + */ + || IsModifierKey (orig_keysym) /* The symbols from GDK_KEY_ISO_Lock to GDK_KEY_ISO_Last_Group_Lock don't have real modifiers but commit 28073ba59bbabec1194977d654b471800ce63f45 Author: Yuuki Harano Date: Sun Sep 6 23:27:45 2020 +0900 Re-implement childframe with emacsgtkfixed * src/emacsgtkfixed.c (G_DEFINE_TYPE): Make emacs_fixed_get_type public. * src/emacsgtkfixed.h (EMACS_TYPE_FIXED): Make emacs_fixed_get_type public. * src/gtkutil.c (xg_frame_set_char_size): Call appropriate functions by whether the frame is a child frame or not. (xg_create_frame_widgets): Use GTK_WINDOW_TOPLEVEL when creating child frame. (xg_create_frame_outer_widgets): New function. (xg_set_skip_taskbar): Call only when top-level frame. (xg_set_no_accept_focus): See appropriate widget. * src/gtkutil.h: New declaration. * src/pgtkfns.c (pgtk_set_name_internal): Do only when top-level frame. (Fx_create_frame): Reparent the frame. (frame_geometry): Call appropriate functions (syms_of_pgtkfns): Port from X code. * src/pgtkterm.c (x_free_frame_resources): Destroy appropriate widget. (x_calc_absolute_position): Port from X code. (x_set_offset): Re-port from X code. (pgtk_set_window_size): Use appropriate widget. (pgtk_make_frame_visible): Use appropriate widget. (pgtk_make_frame_invisible): Use appropriate widget. (x_set_parent_frame): Reparent the frame. (x_set_z_group): Process only when top-level frame. (pgtk_text_icon): Process only when top-level frame. (set_fullscreen_state): Process only when top-level frame. (frame_highlight): Hold ref. (frame_unhighlight): Hold ref. (pgtk_window_is_of_frame_recursive): Prune child frames. (pgtk_window_is_of_frame): Prune child frames. (print_widget_tree_recursive): Don't call this when not debugging. (pgtk_handle_draw): Don't call this when not debugging. (pgtk_set_event_handler): expect map-event for edit_widget not outer widget. * src/pgtkterm.h (FRAME_WIDGET): New macro. diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index 4128f81cce..d2a7fcbbc1 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -51,7 +51,6 @@ static void emacs_fixed_get_preferred_width (GtkWidget *widget, static void emacs_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); -static GType emacs_fixed_get_type (void); G_DEFINE_TYPE (EmacsFixed, emacs_fixed, GTK_TYPE_FIXED) static EmacsFixed * diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h index b230a4d4d8..f2fb1f269a 100644 --- a/src/emacsgtkfixed.h +++ b/src/emacsgtkfixed.h @@ -27,6 +27,9 @@ struct frame; G_BEGIN_DECLS +#define EMACS_TYPE_FIXED (emacs_fixed_get_type ()) +#define EMACS_IS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMACS_TYPE_FIXED)) + struct frame; typedef struct _EmacsFixedPrivate EmacsFixedPrivate; @@ -44,6 +47,8 @@ struct _EmacsFixedClass GtkFixedClass parent_class; }; +extern GType emacs_fixed_get_type (void); + extern GtkWidget *emacs_fixed_new (struct frame *f); G_END_DECLS diff --git a/src/gtkutil.c b/src/gtkutil.c index 3956c581d9..0f1a51fbbb 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1060,8 +1060,20 @@ xg_frame_set_char_size (struct frame *f, int width, int height) if (FRAME_PIXEL_HEIGHT (f) == 0) return; +#ifndef HAVE_PGTK gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), &gwidth, &gheight); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) { + gtk_window_get_size (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + &gwidth, &gheight); + } else { + GtkAllocation alloc; + gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); + gwidth = alloc.width; + gheight = alloc.height; + } +#endif /* Do this before resize, as we don't know yet if we will be resized. */ FRAME_RIF (f)->clear_under_internal_border (f); @@ -1101,11 +1113,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height) else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)) { was_visible = true; -#ifndef HAVE_PGTK hide_child_frame = EQ (x_gtk_resize_child_frames, Qhide); -#else - hide_child_frame = true; -#endif // !HAVE_PGTK if (totalwidth != gwidth || totalheight != gheight) { @@ -1116,17 +1124,35 @@ xg_frame_set_char_size (struct frame *f, int width, int height) if (hide_child_frame) { block_input (); +#ifndef HAVE_PGTK gtk_widget_hide (FRAME_GTK_OUTER_WIDGET (f)); +#else + gtk_widget_hide (FRAME_WIDGET (f)); +#endif unblock_input (); } +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), totalwidth, totalheight); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + totalwidth, totalheight); + } else { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + totalwidth, totalheight); + } +#endif if (hide_child_frame) { block_input (); +#ifndef HAVE_PGTK gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); +#else + gtk_widget_show_all (FRAME_WIDGET (f)); +#endif unblock_input (); } @@ -1138,8 +1164,18 @@ xg_frame_set_char_size (struct frame *f, int width, int height) frame_size_history_add (f, Qxg_frame_set_char_size_3, width, height, list2i (totalwidth, totalheight)); +#ifndef HAVE_PGTK gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), totalwidth, totalheight); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) { + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + totalwidth, totalheight); + } else { + gtk_widget_set_size_request (FRAME_GTK_WIDGET (f), + totalwidth, totalheight); + } +#endif fullscreen = Qnil; } @@ -1355,7 +1391,7 @@ xg_create_frame_widgets (struct frame *f) else wtop = gtk_window_new (type); #else - if (!NILP(f->parent_frame) || f->tooltip) + if (f->tooltip) { type = GTK_WINDOW_POPUP; } @@ -1546,6 +1582,107 @@ xg_create_frame_widgets (struct frame *f) return 1; } +#ifdef HAVE_PGTK +void +xg_create_frame_outer_widgets (struct frame *f) +{ + GtkWidget *wtop; + GtkWidget *wvbox, *whbox; + GtkWindowType type = GTK_WINDOW_TOPLEVEL; + char *title = 0; + + PGTK_TRACE ("xg_create_frame_outer_widgets."); + block_input (); + + wtop = gtk_window_new (type); + gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + + xg_set_screen (wtop, f); + + wvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + whbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_set_homogeneous (GTK_BOX (wvbox), FALSE); + gtk_box_set_homogeneous (GTK_BOX (whbox), FALSE); + + /* Use same names as the Xt port does. I.e. Emacs.pane.emacs by default */ + gtk_widget_set_name (wtop, EMACS_CLASS); + gtk_widget_set_name (wvbox, "pane"); + + /* If this frame has a title or name, set it in the title bar. */ + if (! NILP (f->title)) + title = SSDATA (ENCODE_UTF_8 (f->title)); + else if (! NILP (f->name)) + title = SSDATA (ENCODE_UTF_8 (f->name)); + + if (title) + gtk_window_set_title (GTK_WINDOW (wtop), title); + + if (FRAME_UNDECORATED (f)) + { + gtk_window_set_decorated (GTK_WINDOW (wtop), FALSE); + store_frame_param (f, Qundecorated, Qt); + } + + FRAME_GTK_OUTER_WIDGET (f) = wtop; + f->output_data.xp->vbox_widget = wvbox; + f->output_data.xp->hbox_widget = whbox; + + gtk_container_add (GTK_CONTAINER (wtop), wvbox); + gtk_box_pack_start (GTK_BOX (wvbox), whbox, TRUE, TRUE, 0); + + if (FRAME_EXTERNAL_TOOL_BAR (f)) + update_frame_tool_bar (f); + +#if ! GTK_CHECK_VERSION (3, 22, 0) + gtk_window_set_wmclass (GTK_WINDOW (wtop), + SSDATA (Vx_resource_name), + SSDATA (Vx_resource_class)); +#endif + + /* Convert our geometry parameters into a geometry string + and specify it. + GTK will itself handle calculating the real position this way. */ + xg_set_geometry (f); + f->win_gravity + = gtk_window_get_gravity (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); + + gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); + + if (FRAME_OVERRIDE_REDIRECT (f)) + { + GdkWindow *gwin = gtk_widget_get_window (wtop); + + if (gwin) + gdk_window_set_override_redirect (gwin, TRUE); + } + + /* Steal a tool tip window we can move ourselves. */ + f->output_data.xp->ttip_widget = 0; + f->output_data.xp->ttip_lbl = 0; + f->output_data.xp->ttip_window = 0; + gtk_widget_set_tooltip_text (wtop, "Dummy text"); + g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f); + + { + GdkScreen *screen = gtk_widget_get_screen (wtop); + GtkSettings *gs = gtk_settings_get_for_screen (screen); + /* Only connect this signal once per screen. */ + if (! g_signal_handler_find (G_OBJECT (gs), + G_SIGNAL_MATCH_FUNC, + 0, 0, 0, + (gpointer) G_CALLBACK (style_changed_cb), + 0)) + { + g_signal_connect (G_OBJECT (gs), "notify::gtk-theme-name", + G_CALLBACK (style_changed_cb), + gdk_screen_get_display (screen)); + } + } + + unblock_input (); +} +#endif + void xg_free_frame_widgets (struct frame *f) { @@ -1784,10 +1921,17 @@ void xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar) { block_input (); +#ifndef HAVE_PGTK if (FRAME_GTK_WIDGET (f)) gdk_window_set_skip_taskbar_hint (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)), NILP (skip_taskbar) ? FALSE : TRUE); +#else + if (FRAME_GTK_OUTER_WIDGET (f)) + gdk_window_set_skip_taskbar_hint + (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)), + NILP (skip_taskbar) ? FALSE : TRUE); +#endif unblock_input (); } @@ -1812,7 +1956,13 @@ void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus) { block_input (); - if (FRAME_GTK_WIDGET (f)) + if ( +#ifndef HAVE_PGTK + FRAME_GTK_WIDGET (f) +#else + FRAME_GTK_OUTER_WIDGET (f) +#endif + ) { GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE; diff --git a/src/gtkutil.h b/src/gtkutil.h index b7f67ba928..04007343f2 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -179,6 +179,9 @@ extern void xg_set_background_color (struct frame *f, unsigned long bg); extern bool xg_check_special_colors (struct frame *f, const char *color_name, Emacs_Color *color); +#ifdef HAVE_PGTK +extern void xg_create_frame_outer_widgets (struct frame *f); +#endif #ifndef HAVE_PGTK extern void xg_set_frame_icon (struct frame *f, diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 06fb4e206f..c6909ba3d6 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -231,7 +231,7 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) static void pgtk_set_name_internal (struct frame *f, Lisp_Object name) { - if (FRAME_GTK_WIDGET (f)) + if (FRAME_GTK_OUTER_WIDGET (f)) { block_input (); { @@ -1523,18 +1523,32 @@ This function is an internal primitive--use `make-frame' instead. */ ) struct frame *p = XFRAME (parent_frame); block_input (); + PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); - gtk_window_set_transient_for (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (p))); - gtk_window_set_attached_to (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - FRAME_GTK_WIDGET (p)); - gtk_window_set_destroy_with_parent (GTK_WINDOW - (FRAME_GTK_OUTER_WIDGET (f)), TRUE); - gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + GtkWidget *fixed = FRAME_GTK_WIDGET (f); + GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p); + GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed); + g_object_ref (fixed); + gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed); + gtk_fixed_put (GTK_FIXED (fixed_of_p), fixed, f->left_pos, f->top_pos); + gtk_widget_show_all (fixed); + g_object_unref (fixed); + + gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); + FRAME_GTK_OUTER_WIDGET (f) = NULL; + FRAME_OUTPUT_DATA (f)->vbox_widget = NULL; + FRAME_OUTPUT_DATA (f)->hbox_widget = NULL; + FRAME_OUTPUT_DATA (f)->menubar_widget = NULL; + FRAME_OUTPUT_DATA (f)->toolbar_widget = NULL; + FRAME_OUTPUT_DATA (f)->ttip_widget = NULL; + FRAME_OUTPUT_DATA (f)->ttip_lbl = NULL; + FRAME_OUTPUT_DATA (f)->ttip_window = NULL; + unblock_input (); } - gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + if (FRAME_GTK_OUTER_WIDGET (f)) + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); @@ -3298,8 +3312,15 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) /* Get these here because they can't be got in configure_event(). */ int left_pos, top_pos; - gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - &left_pos, &top_pos); + if (FRAME_GTK_OUTER_WIDGET (f)) { + gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + &left_pos, &top_pos); + } else { + GtkAllocation alloc; + gtk_widget_get_allocation (FRAME_GTK_WIDGET (f), &alloc); + left_pos = alloc.x; + top_pos = alloc.y; + } int native_left = left_pos + border; int native_top = top_pos + border + title_height; @@ -3647,6 +3668,8 @@ syms_of_pgtkfns (void) DEFSYM (Qframe_title_format, "frame-title-format"); DEFSYM (Qicon_title_format, "icon-title-format"); DEFSYM (Qdark, "dark"); + DEFSYM (Qhide, "hide"); + DEFSYM (Qresize_mode, "resize-mode"); DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, doc: /* A string indicating the foreground color of the cursor box. */); @@ -3799,6 +3822,28 @@ When using Gtk+ tooltips, the tooltip face is not used. */); Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */); Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40)); + DEFVAR_LISP ("x-gtk-resize-child-frames", x_gtk_resize_child_frames, + doc: /* If non-nil, resize child frames specially with GTK builds. +If this is nil, resize child frames like any other frames. This is the +default and usually works with most desktops. Some desktop environments +(GNOME shell in particular when using the mutter window manager), +however, may refuse to resize a child frame when Emacs is built with +GTK3. For those environments, the two settings below are provided. + +If this equals the symbol 'hide', Emacs temporarily hides the child +frame during resizing. This approach seems to work reliably, may +however induce some flicker when the frame is made visible again. + +If this equals the symbol 'resize-mode', Emacs uses GTK's resize mode to +always trigger an immediate resize of the child frame. This method is +deprecated by GTK and may not work in future versions of that toolkit. +It also may freeze Emacs when used with other desktop environments. It +avoids, however, the unpleasant flicker induced by the hiding approach. + +This variable is considered a temporary workaround and will be hopefully +eliminated in future versions of Emacs. */); + x_gtk_resize_child_frames = Qnil; + DEFSYM (Qmono, "mono"); DEFSYM (Qassq_delete_all, "assq-delete-all"); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 6d8b1ece87..d62e2a3b16 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -60,6 +60,7 @@ along with GNU Emacs. If not, see . */ #include "font.h" #include "xsettings.h" #include "pgtkselect.h" +#include "emacsgtkfixed.h" #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) @@ -227,10 +228,10 @@ x_free_frame_resources (struct frame *f) if (FRAME_X_OUTPUT (f)->border_color_css_provider != NULL) { - GtkStyleContext *ctxt = - gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + g_object_unref (old); FRAME_X_OUTPUT (f)->border_color_css_provider = NULL; } @@ -250,7 +251,7 @@ x_free_frame_resources (struct frame *f) FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL; } - gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); + gtk_widget_destroy (FRAME_WIDGET (f)); if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL) { @@ -286,6 +287,80 @@ x_destroy_window (struct frame *f) dpyinfo->reference_count--; } +/* Calculate the absolute position in frame F + from its current recorded position values and gravity. */ + +static void +x_calc_absolute_position (struct frame *f) +{ + int flags = f->size_hint_flags; + struct frame *p = FRAME_PARENT_FRAME (f); + + /* We have nothing to do if the current position + is already for the top-left corner. */ + if (! ((flags & XNegative) || (flags & YNegative))) + return; + + /* Treat negative positions as relative to the leftmost bottommost + position that fits on the screen. */ + if ((flags & XNegative) && (f->left_pos <= 0)) + { + int width = FRAME_PIXEL_WIDTH (f); + + /* A frame that has been visible at least once should have outer + edges. */ + if (f->output_data.pgtk->has_been_visible && !p) + { + Lisp_Object frame; + Lisp_Object edges = Qnil; + + XSETFRAME (frame, f); + edges = Fpgtk_frame_edges (frame, Qouter_edges); + if (!NILP (edges)) + width = (XFIXNUM (Fnth (make_fixnum (2), edges)) + - XFIXNUM (Fnth (make_fixnum (0), edges))); + } + + if (p) + f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width + + f->left_pos); + else + f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) + - width + f->left_pos); + + } + + if ((flags & YNegative) && (f->top_pos <= 0)) + { + int height = FRAME_PIXEL_HEIGHT (f); + + if (f->output_data.pgtk->has_been_visible && !p) + { + Lisp_Object frame; + Lisp_Object edges = Qnil; + + XSETFRAME (frame, f); + if (NILP (edges)) + edges = Fpgtk_frame_edges (frame, Qouter_edges); + if (!NILP (edges)) + height = (XFIXNUM (Fnth (make_fixnum (3), edges)) + - XFIXNUM (Fnth (make_fixnum (1), edges))); + } + + if (p) + f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width + + f->top_pos); + else + f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) + - height + f->top_pos); + } + + /* The left_pos and top_pos + are now relative to the top and left screen edges, + so the flags should correspond. */ + f->size_hint_flags &= ~ (XNegative | YNegative); +} + /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, to really change the position, and 0 when calling from x_make_frame_visible (in that case, XOFF and YOFF are the current @@ -300,48 +375,60 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) { PGTK_TRACE ("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); - struct frame *parent = FRAME_PARENT_FRAME (f); - GtkAllocation a = { 0 }; - int surface_pos_x = 0; - int surface_pos_y = 0; - - if (parent) - { - /* determing the "height" of the titlebar, by finding the - location of the "emacsfixed" widget on the surface/window */ - GtkWidget *w = FRAME_GTK_WIDGET (parent); - gtk_widget_get_allocation (w, &a); - } + int modified_top, modified_left; if (change_gravity > 0) { - f->size_hint_flags &= ~(XNegative | YNegative); - f->left_pos = xoff; f->top_pos = yoff; - + f->left_pos = xoff; + f->size_hint_flags &= ~ (XNegative | YNegative); if (xoff < 0) - { - f->size_hint_flags |= XNegative; - } + f->size_hint_flags |= XNegative; if (yoff < 0) - { - f->size_hint_flags |= YNegative; - } + f->size_hint_flags |= YNegative; f->win_gravity = NorthWestGravity; } + x_calc_absolute_position (f); + block_input (); - surface_pos_y = f->top_pos + a.y; - surface_pos_x = f->left_pos + a.x; + x_wm_set_size_hint (f, 0, false); - /* When a position change was requested and the outer GTK widget - has been realized already, leave it to gtk_window_move to DTRT - and return. Used for Bug#25851 and Bug#25943. */ - if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) + if (x_gtk_use_window_move) + { + if (change_gravity != 0) + { + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + } + else + { + GtkWidget *fixed = FRAME_GTK_WIDGET (f); + GtkWidget *parent = gtk_widget_get_parent (fixed); + gtk_fixed_move (GTK_FIXED (parent), fixed, + f->left_pos, f->top_pos); + } + } + unblock_input (); + return; + } + + modified_left = f->left_pos; + modified_top = f->top_pos; + + if (FRAME_GTK_OUTER_WIDGET (f)) { - PGTK_TRACE ("x_set_offset: move to %d,%d.", surface_pos_x, surface_pos_y); gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - surface_pos_x, surface_pos_y); + modified_left, modified_top); + } + else + { + GtkWidget *fixed = FRAME_GTK_WIDGET (f); + GtkWidget *parent = gtk_widget_get_parent (fixed); + gtk_fixed_move (GTK_FIXED (parent), fixed, + modified_left, modified_top); } unblock_input (); @@ -397,7 +484,7 @@ pgtk_set_window_size (struct frame *f, x_wm_set_size_hint (f, 0, 0); xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth), FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)); - gtk_widget_queue_resize (FRAME_GTK_OUTER_WIDGET (f)); + gtk_widget_queue_resize (FRAME_WIDGET (f)); unblock_input (); } @@ -488,8 +575,9 @@ pgtk_make_frame_visible (struct frame *f) if (!FRAME_VISIBLE_P (f)) { - gtk_widget_show (win); - gtk_window_deiconify (GTK_WINDOW (win)); + gtk_widget_show (FRAME_WIDGET (f)); + if (win) + gtk_window_deiconify (GTK_WINDOW (win)); if (FLOATP (Vpgtk_wait_for_event_timeout)) { @@ -498,7 +586,7 @@ pgtk_make_frame_visible (struct frame *f) int found = 0; int timed_out = 0; gulong id = - g_signal_connect (win, "map-event", + g_signal_connect (FRAME_WIDGET (f), "map-event", G_CALLBACK (pgtk_make_frame_visible_wait_for_map_event_cb), &found); @@ -508,7 +596,7 @@ pgtk_make_frame_visible (struct frame *f) &timed_out); while (!found && !timed_out) gtk_main_iteration (); - g_signal_handler_disconnect (win, id); + g_signal_handler_disconnect (FRAME_WIDGET (f), id); if (!timed_out) g_source_remove (src); } @@ -524,9 +612,7 @@ pgtk_make_frame_invisible (struct frame *f) { PGTK_TRACE ("pgtk_make_frame_invisible"); - GtkWidget *win = FRAME_OUTPUT_DATA (f)->widget; - - gtk_widget_hide (win); + gtk_widget_hide (FRAME_WIDGET (f)); SET_FRAME_VISIBLE (f, 0); SET_FRAME_ICONIFIED (f, false); @@ -668,25 +754,89 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, -------------------------------------------------------------------------- */ { struct frame *p = NULL; - PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); if (!NILP (new_value) && (!FRAMEP (new_value) - || !FRAME_LIVE_P (p = XFRAME (new_value)) || !FRAME_PGTK_P (p))) + || !FRAME_LIVE_P (p = XFRAME (new_value)) + || !FRAME_PGTK_P (p))) { store_frame_param (f, Qparent_frame, old_value); error ("Invalid specification of `parent-frame'"); } - if (p != FRAME_PARENT_FRAME (f) && (p != NULL)) + if (p != FRAME_PARENT_FRAME (f)) { block_input (); - gtk_window_set_transient_for (FRAME_NATIVE_WINDOW (f), - FRAME_NATIVE_WINDOW (p)); - gtk_window_set_attached_to (FRAME_NATIVE_WINDOW (f), - FRAME_GTK_WIDGET (p)); - gtk_window_move (FRAME_NATIVE_WINDOW (f), f->left_pos, f->top_pos); - gtk_window_set_keep_above (FRAME_NATIVE_WINDOW (f), true); + + if (p != NULL) + { + if (FRAME_DISPLAY_INFO (f) != FRAME_DISPLAY_INFO (p)) + error ("Cross display reparent."); + } + + GtkWidget *fixed = FRAME_GTK_WIDGET (f); + + GtkAllocation alloc; + gtk_widget_get_allocation(fixed, &alloc); + g_object_ref (fixed); + + GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider; + + { + GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed); + gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed); + + GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider)); + + if (FRAME_GTK_OUTER_WIDGET (f)) + { + gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); + FRAME_GTK_OUTER_WIDGET (f) = NULL; + FRAME_OUTPUT_DATA (f)->vbox_widget = NULL; + FRAME_OUTPUT_DATA (f)->hbox_widget = NULL; + FRAME_OUTPUT_DATA (f)->menubar_widget = NULL; + FRAME_OUTPUT_DATA (f)->toolbar_widget = NULL; + FRAME_OUTPUT_DATA (f)->ttip_widget = NULL; + FRAME_OUTPUT_DATA (f)->ttip_lbl = NULL; + FRAME_OUTPUT_DATA (f)->ttip_window = NULL; + } + } + + if (p == NULL) + { + xg_create_frame_outer_widgets (f); + pgtk_set_event_handler (f); + gtk_box_pack_start (GTK_BOX (f->output_data.pgtk->hbox_widget), fixed, TRUE, TRUE, 0); + f->output_data.pgtk->preferred_width = alloc.width; + f->output_data.pgtk->preferred_height = alloc.height; + x_wm_set_size_hint (f, 0, 0); + xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, alloc.width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, alloc.height)); + gtk_widget_queue_resize (FRAME_WIDGET (f)); + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + } + else + { + GtkWidget *fixed_of_p = FRAME_GTK_WIDGET (p); + gtk_fixed_put (GTK_FIXED (fixed_of_p), fixed, f->left_pos, f->top_pos); + gtk_widget_set_size_request (fixed, alloc.width, alloc.height); + gtk_widget_show_all (fixed); + } + + GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f)); + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + + g_object_unref (fixed); + + if (FRAME_GTK_OUTER_WIDGET (f)) { + if (EQ (x_gtk_resize_child_frames, Qresize_mode)) + gtk_container_set_resize_mode + (GTK_CONTAINER (FRAME_GTK_OUTER_WIDGET (f)), + p ? GTK_RESIZE_IMMEDIATE : GTK_RESIZE_QUEUE); + } + unblock_input (); fset_parent_frame (f, new_value); @@ -748,6 +898,9 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) /* doesn't work on wayland. */ PGTK_TRACE ("x_set_z_group"); + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; + if (NILP (new_value)) { gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), @@ -2900,8 +3053,10 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file) bool pgtk_text_icon (struct frame *f, const char *icon_name) { - gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); - gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); + if (FRAME_GTK_OUTER_WIDGET (f)) { + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); + } return false; } @@ -4392,6 +4547,9 @@ pgtk_judge_scroll_bars (struct frame *f) static void set_fullscreen_state (struct frame *f) { + if (!FRAME_GTK_OUTER_WIDGET (f)) + return; + GtkWindow *widget = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); switch (f->want_fullscreen) { @@ -4571,24 +4729,27 @@ frame_highlight (struct frame *f) using that same window-manager binary for ever. Let's not crash just because of this (bug#9310). */ + GtkWidget *w = FRAME_WIDGET (f); + char *css = g_strdup_printf ("decoration { border: solid %dpx #%06x; }", f->border_width, - (unsigned int) FRAME_X_OUTPUT (f)-> - border_pixel & 0x00ffffff); - GtkStyleContext *ctxt = - gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + (unsigned int) FRAME_X_OUTPUT (f)->border_pixel & 0x00ffffff); + + GtkStyleContext *ctxt = gtk_widget_get_style_context (w); GtkCssProvider *css_provider = gtk_css_provider_new (); gtk_css_provider_load_from_data (css_provider, css, -1, NULL); gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - g_object_unref (css_provider); g_free (css); GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider; if (old != NULL) - gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + { + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + g_object_unref (old); + } unblock_input (); gui_update_cursor (f, true); @@ -4605,22 +4766,26 @@ frame_unhighlight (struct frame *f) block_input (); /* Same as above for XSetWindowBorder (bug#9310). */ + GtkWidget *w = FRAME_WIDGET (f); + char *css = g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }", f->border_width); - GtkStyleContext *ctxt = - gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + + GtkStyleContext *ctxt = gtk_widget_get_style_context (w); GtkCssProvider *css_provider = gtk_css_provider_new (); gtk_css_provider_load_from_data (css_provider, css, -1, NULL); gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - g_object_unref (css_provider); g_free (css); GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider; if (old != NULL) - gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + { + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + g_object_unref (old); + } unblock_input (); gui_update_cursor (f, true); @@ -4793,6 +4958,7 @@ struct pgtk_window_is_of_frame_recursive_t { GdkWindow *window; bool result; + GtkWidget *emacs_gtk_fixed; // stop on emacsgtkfixed other than this. }; static void @@ -4803,15 +4969,19 @@ pgtk_window_is_of_frame_recursive (GtkWidget * widget, gpointer data) if (datap->result) return; + if (EMACS_IS_FIXED (widget) && widget != datap->emacs_gtk_fixed) + return; + if (gtk_widget_get_window (widget) == datap->window) { datap->result = true; return; } - if (GTK_IS_CONTAINER (widget)) + if (GTK_IS_CONTAINER (widget)) { gtk_container_foreach (GTK_CONTAINER (widget), pgtk_window_is_of_frame_recursive, datap); + } } static bool @@ -4820,7 +4990,8 @@ pgtk_window_is_of_frame (struct frame *f, GdkWindow * window) struct pgtk_window_is_of_frame_recursive_t data; data.window = window; data.result = false; - pgtk_window_is_of_frame_recursive (FRAME_GTK_OUTER_WIDGET (f), &data); + data.emacs_gtk_fixed = FRAME_GTK_WIDGET (f); + pgtk_window_is_of_frame_recursive (FRAME_WIDGET (f), &data); return data.result; } @@ -5068,6 +5239,8 @@ pgtk_clear_under_internal_border (struct frame *f) } } +#ifdef HAVE_PGTK + static void print_widget_tree_recursive (GtkWidget * w, gpointer user_data) { @@ -5108,6 +5281,8 @@ print_widget_tree (GtkWidget * w) print_widget_tree_recursive (w, indent); } +#endif + static gboolean pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) { @@ -5115,7 +5290,9 @@ pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) PGTK_TRACE ("pgtk_handle_draw"); +#ifdef HAVE_PGTK print_widget_tree (widget); +#endif GdkWindow *win = gtk_widget_get_window (widget); @@ -6385,11 +6562,11 @@ pgtk_set_event_handler (struct frame *f) NULL); g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event", G_CALLBACK (delete_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "map-event", - G_CALLBACK (map_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event", G_CALLBACK (pgtk_handle_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "map-event", + G_CALLBACK (map_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate", G_CALLBACK (size_allocate), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event", diff --git a/src/pgtkterm.h b/src/pgtkterm.h index cff1633292..ad66039648 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -428,6 +428,9 @@ enum #define FRAME_FONT(f) (FRAME_X_OUTPUT(f)->font) #define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT(f)->widget) #define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT(f)->edit_widget) +#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET(f) ? \ + FRAME_GTK_OUTER_WIDGET(f) : \ + FRAME_GTK_WIDGET(f)) /* aliases */ #define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET(f) commit e75ce0302d4c907c8ff56fb15fc7dd12b48e7370 Author: Jeff Walsh Date: Thu Aug 27 22:05:15 2020 +1000 Add support for x-support-frames * src/pgtkfns.c (Fx_export_frames): (syms_of_pgtkfns): port from X11 version * src/pgtkterm.c (pgtk_cr_accumulate_data): (pgtk_cr_destroy): (pgtk_cr_export_frames): port from X11 * src/pgtkterm.h: add defs diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 53da9b756a..06fb4e206f 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -844,6 +844,78 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, error ("Invalid scroll-bar-background."); } + +/*********************************************************************** + Printing + ***********************************************************************/ + + +DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0, + doc: /* Return image data of FRAMES in TYPE format. +FRAMES should be nil (the selected frame), a frame, or a list of +frames (each of which corresponds to one page). Each frame should be +visible. Optional arg TYPE should be either `pdf' (default), `png', +`postscript', or `svg'. Supported types are determined by the +compile-time configuration of cairo. + +Note: Text drawn with the `x' font backend is shown with hollow boxes +unless TYPE is `png'. */) + (Lisp_Object frames, Lisp_Object type) +{ + Lisp_Object rest, tmp; + cairo_surface_type_t surface_type; + + if (!CONSP (frames)) + frames = list1 (frames); + + tmp = Qnil; + for (rest = frames; CONSP (rest); rest = XCDR (rest)) + { + struct frame *f = decode_window_system_frame (XCAR (rest)); + Lisp_Object frame; + + XSETFRAME (frame, f); + if (!FRAME_VISIBLE_P (f)) + error ("Frames to be exported must be visible."); + tmp = Fcons (frame, tmp); + } + frames = Fnreverse (tmp); + +#ifdef CAIRO_HAS_PDF_SURFACE + if (NILP (type) || EQ (type, Qpdf)) + surface_type = CAIRO_SURFACE_TYPE_PDF; + else +#endif +#ifdef CAIRO_HAS_PNG_FUNCTIONS + if (EQ (type, Qpng)) + { + if (!NILP (XCDR (frames))) + error ("PNG export cannot handle multiple frames."); + surface_type = CAIRO_SURFACE_TYPE_IMAGE; + } + else +#endif +#ifdef CAIRO_HAS_PS_SURFACE + if (EQ (type, Qpostscript)) + surface_type = CAIRO_SURFACE_TYPE_PS; + else +#endif +#ifdef CAIRO_HAS_SVG_SURFACE + if (EQ (type, Qsvg)) + { + /* For now, we stick to SVG 1.1. */ + if (!NILP (XCDR (frames))) + error ("SVG export cannot handle multiple frames."); + surface_type = CAIRO_SURFACE_TYPE_SVG; + } + else +#endif + error ("Unsupported export type"); + + return pgtk_cr_export_frames (frames, surface_type); +} + + /* Note: see frame.c for template, also where generic functions are impl */ frame_parm_handler pgtk_frame_parm_handlers[] = { gui_set_autoraise, /* generic OK */ @@ -3673,7 +3745,7 @@ be used as the image of the icon representing the frame. */); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - // defsubr (&Spgtk_export_frames); + defsubr (&Sx_export_frames); defsubr (&Spgtk_page_setup_dialog); defsubr (&Spgtk_get_page_setup); defsubr (&Spgtk_print_frames_dialog); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 544436e6e4..6d8b1ece87 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -7045,6 +7045,17 @@ pgtk_cr_draw_frame (cairo_t * cr, struct frame *f) cairo_paint (cr); } +static cairo_status_t +pgtk_cr_accumulate_data (void *closure, const unsigned char *data, + unsigned int length) +{ + Lisp_Object *acc = (Lisp_Object *) closure; + + *acc = Fcons (make_unibyte_string ((char const *) data, length), *acc); + + return CAIRO_STATUS_SUCCESS; +} + void pgtk_cr_destroy_frame_context (struct frame *f) { @@ -7056,6 +7067,110 @@ pgtk_cr_destroy_frame_context (struct frame *f) } } +static void +pgtk_cr_destroy (void *cr) +{ + block_input (); + cairo_destroy (cr); + unblock_input (); +} + + + +Lisp_Object +pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type) +{ + struct frame *f; + cairo_surface_t *surface; + cairo_t *cr; + int width, height; + void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL; + Lisp_Object acc = Qnil; + ptrdiff_t count = SPECPDL_INDEX (); + + specbind (Qredisplay_dont_pause, Qt); + redisplay_preserve_echo_area (31); + + f = XFRAME (XCAR (frames)); + frames = XCDR (frames); + width = FRAME_PIXEL_WIDTH (f); + height = FRAME_PIXEL_HEIGHT (f); + + block_input (); +#ifdef CAIRO_HAS_PDF_SURFACE + if (surface_type == CAIRO_SURFACE_TYPE_PDF) + { + surface = cairo_pdf_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, + width, height); + surface_set_size_func = cairo_pdf_surface_set_size; + } + else +#endif +#ifdef CAIRO_HAS_PNG_FUNCTIONS + if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) + surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); + else +#endif +#ifdef CAIRO_HAS_PS_SURFACE + if (surface_type == CAIRO_SURFACE_TYPE_PS) + { + surface = cairo_ps_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, + width, height); + surface_set_size_func = cairo_ps_surface_set_size; + } + else +#endif +#ifdef CAIRO_HAS_SVG_SURFACE + if (surface_type == CAIRO_SURFACE_TYPE_SVG) + surface = cairo_svg_surface_create_for_stream (pgtk_cr_accumulate_data, &acc, + width, height); + else +#endif + abort (); + + cr = cairo_create (surface); + cairo_surface_destroy (surface); + record_unwind_protect_ptr (pgtk_cr_destroy, cr); + + while (1) + { + cairo_t *saved_cr = FRAME_CR_CONTEXT (f); + FRAME_CR_CONTEXT (f) = cr; + pgtk_clear_area (f, 0, 0, width, height); + expose_frame (f, 0, 0, width, height); + FRAME_CR_CONTEXT (f) = saved_cr; + + if (NILP (frames)) + break; + + cairo_surface_show_page (surface); + f = XFRAME (XCAR (frames)); + frames = XCDR (frames); + width = FRAME_PIXEL_WIDTH (f); + height = FRAME_PIXEL_HEIGHT (f); + if (surface_set_size_func) + (*surface_set_size_func) (surface, width, height); + + unblock_input (); + maybe_quit (); + block_input (); + } + +#ifdef CAIRO_HAS_PNG_FUNCTIONS + if (surface_type == CAIRO_SURFACE_TYPE_IMAGE) + { + cairo_surface_flush (surface); + cairo_surface_write_to_png_stream (surface, pgtk_cr_accumulate_data, &acc); + } +#endif + unblock_input (); + + unbind_to (count, Qnil); + + return CALLN (Fapply, intern ("concat"), Fnreverse (acc)); +} + + void init_pgtkterm (void) { diff --git a/src/pgtkterm.h b/src/pgtkterm.h index f4d6ee035f..cff1633292 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -28,6 +28,16 @@ along with GNU Emacs. If not, see . */ #include +#ifdef CAIRO_HAS_PDF_SURFACE +#include +#endif +#ifdef CAIRO_HAS_PS_SURFACE +#include +#endif +#ifdef CAIRO_HAS_SVG_SURFACE +#include +#endif + // #define PGTK_DEBUG 1 #ifdef PGTK_DEBUG @@ -574,6 +584,7 @@ extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color); extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); extern void pgtk_cr_destroy_frame_context (struct frame *f); +extern Lisp_Object pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type); /* Defined in pgtkmenu.c */ extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, commit 9704e23f4c2cd56bc8091e2024c7b972a3254bb7 Author: Yuuki Harano Date: Sat Aug 22 19:17:04 2020 +0900 Enable GtkIMContext by default * lisp/term/pgtk-win.el: Call pgtk-use-im-context after init. * src/pgtkim.c (pgtk_im_use_context): New function. (pgtk_im_init): Call pgtk_im_use_context. (Fpgtk_use_im_context): Call pgtk_im_use_context. (syms_of_pgtkim): New variable Vpgtk_use_im_context_on_new_connection. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 4598ba007b..a41d3a3951 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -398,6 +398,14 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (overlay-put ov 'before-string ovstr) (setq pgtk-preedit-overlay ov))) + +(add-hook 'after-init-hook + (function + (lambda () + (when (eq window-system 'pgtk) + (pgtk-use-im-context pgtk-use-im-context-on-new-connection))))) + + (provide 'pgtk-win) (provide 'term/pgtk-win) diff --git a/src/pgtkim.c b/src/pgtkim.c index 15088bc64d..0ec931c4b1 100644 --- a/src/pgtkim.c +++ b/src/pgtkim.c @@ -210,27 +210,10 @@ pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev) return false; } -void -pgtk_im_init (struct pgtk_display_info *dpyinfo) -{ - dpyinfo->im.context = NULL; -} - -void -pgtk_im_finish (struct pgtk_display_info *dpyinfo) -{ - if (dpyinfo->im.context != NULL) - g_object_unref (dpyinfo->im.context); - dpyinfo->im.context = NULL; -} - -DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, 1, 2, 0, - doc: /* Set whether use Gtk's im context. */) - (Lisp_Object use_p, Lisp_Object terminal) +static void +pgtk_im_use_context (struct pgtk_display_info *dpyinfo, bool use_p) { - struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - - if (NILP (use_p)) + if (!use_p) { if (dpyinfo->im.context != NULL) { @@ -269,6 +252,31 @@ DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, 1, 2, pgtk_im_focus_in (dpyinfo->im.focused_frame); } } +} + +void +pgtk_im_init (struct pgtk_display_info *dpyinfo) +{ + dpyinfo->im.context = NULL; + + pgtk_im_use_context (dpyinfo, !NILP (Vpgtk_use_im_context_on_new_connection)); +} + +void +pgtk_im_finish (struct pgtk_display_info *dpyinfo) +{ + if (dpyinfo->im.context != NULL) + g_object_unref (dpyinfo->im.context); + dpyinfo->im.context = NULL; +} + +DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, 1, 2, 0, + doc: /* Set whether to use GtkIMContext. */) + (Lisp_Object use_p, Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + + pgtk_im_use_context (dpyinfo, !NILP (use_p)); return Qnil; } @@ -282,4 +290,10 @@ syms_of_pgtkim (void) DEFSYM (Qul, "ul"); DEFSYM (Qfg, "fg"); DEFSYM (Qbg, "bg"); + + DEFVAR_LISP ("pgtk-use-im-context-on-new-connection", Vpgtk_use_im_context_on_new_connection, + doc: /* Whether to use GtkIMContext on a new connection. +If you want to change it after connection, use the `pgtk-use-im-context' +function. */ ); + Vpgtk_use_im_context_on_new_connection = Qt; } commit 6df8556ab71ef8ae38e52d770d56510da65a614e Author: Yuuki Harano Date: Sun Aug 16 21:37:59 2020 +0900 Remove duplicated syms_of_xwidget call * src/emacs.c (main): Remove duplicated syms_of_xwidget() call. diff --git a/src/emacs.c b/src/emacs.c index f833184863..253f5f7ba1 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1917,6 +1917,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_nsselect (); syms_of_fontset (); #endif /* HAVE_NS */ + #ifdef HAVE_PGTK syms_of_pgtkterm (); syms_of_pgtkfns (); @@ -1925,7 +1926,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_pgtkim (); syms_of_fontset (); syms_of_xsettings (); - syms_of_xwidget (); #endif syms_of_gnutls (); commit 2dd20b2d7595877b7c733fa52695905c920a9d2a Author: Yuuki Harano Date: Sat Aug 15 01:13:52 2020 +0900 Self-implement tooltip * src/gtkutil.c (xg_create_frame_widgets): Use popup for tooltip. * src/pgtkfns.c (unwind_create_tip_frame): Port X code. (x_create_tip_frame): Re-port X code. (x_hide_tip): Re-port X code. (Fx_show_tip): Re-port X code. (frame_geometry): Get left_pos and top_pos here. (syms_of_pgtkfns): Add variables for tooltip. * src/pgtkterm.c (pgtk_set_event_handler): Set event handler for tooltip. diff --git a/src/gtkutil.c b/src/gtkutil.c index 97a8e4a5c1..3956c581d9 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1355,9 +1355,10 @@ xg_create_frame_widgets (struct frame *f) else wtop = gtk_window_new (type); #else - if (!NILP(f->parent_frame)) { - type = GTK_WINDOW_POPUP; - } + if (!NILP(f->parent_frame) || f->tooltip) + { + type = GTK_WINDOW_POPUP; + } wtop = gtk_window_new (type); gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); #endif diff --git a/src/pgtkfns.c b/src/pgtkfns.c index a4da3302ef..53da9b756a 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2421,15 +2421,311 @@ If omitted or nil, that stands for the selected frame's display. */) Tool tips ***********************************************************************/ -/* The frame of a currently visible tooltip. */ +/* The frame of the currently visible tooltip. */ +static Lisp_Object tip_frame; -Lisp_Object tip_frame; +/* The window-system window corresponding to the frame of the + currently visible tooltip. */ +GtkWidget *tip_window; -/* If non-nil, a timer started that hides the last tooltip when it +/* A timer that hides or deletes the currently visible tooltip when it fires. */ - static Lisp_Object tip_timer; +/* STRING argument of last `x-show-tip' call. */ +static Lisp_Object tip_last_string; + +/* Normalized FRAME argument of last `x-show-tip' call. */ +static Lisp_Object tip_last_frame; + +/* PARMS argument of last `x-show-tip' call. */ +static Lisp_Object tip_last_parms; + + +static void +unwind_create_tip_frame (Lisp_Object frame) +{ + Lisp_Object deleted; + + deleted = unwind_create_frame (frame); + if (EQ (deleted, Qt)) + { + tip_window = NULL; + tip_frame = Qnil; + } +} + + +/* Create a frame for a tooltip on the display described by DPYINFO. + PARMS is a list of frame parameters. TEXT is the string to + display in the tip frame. Value is the frame. + + Note that functions called here, esp. gui_default_parameter can + signal errors, for instance when a specified color name is + undefined. We have to make sure that we're in a consistent state + when this happens. */ + +static Lisp_Object +x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct frame *p) +{ + struct frame *f; + Lisp_Object frame; + Lisp_Object name; + int width, height; + ptrdiff_t count = SPECPDL_INDEX (); + bool face_change_before = face_change; + int x_width = 0, x_height = 0; + + if (!dpyinfo->terminal->name) + error ("Terminal is not live, can't create new frames on it"); + + parms = Fcopy_alist (parms); + + /* Get the name of the frame to use for resource lookup. */ + name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", + RES_TYPE_STRING); + if (!STRINGP (name) + && !EQ (name, Qunbound) + && !NILP (name)) + error ("Invalid frame name--not a string or nil"); + + frame = Qnil; + f = make_frame (false); + f->wants_modeline = false; + XSETFRAME (frame, f); + record_unwind_protect (unwind_create_tip_frame, frame); + + f->terminal = dpyinfo->terminal; + + /* By setting the output method, we're essentially saying that + the frame is live, as per FRAME_LIVE_P. If we get a signal + from this point on, x_destroy_window might screw up reference + counts etc. */ + f->output_method = output_pgtk; + f->output_data.pgtk = xzalloc (sizeof *f->output_data.pgtk); +#if 0 + f->output_data.pgtk->icon_bitmap = -1; +#endif + FRAME_FONTSET (f) = -1; + f->output_data.pgtk->white_relief.pixel = -1; + f->output_data.pgtk->black_relief.pixel = -1; + + f->tooltip = true; + fset_icon_name (f, Qnil); + FRAME_DISPLAY_INFO (f) = dpyinfo; + f->output_data.pgtk->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; + f->output_data.pgtk->explicit_parent = false; + + /* These colors will be set anyway later, but it's important + to get the color reference counts right, so initialize them! */ + { + Lisp_Object black; + + /* Function x_decode_color can signal an error. Make + sure to initialize color slots so that we won't try + to free colors we haven't allocated. */ + FRAME_FOREGROUND_PIXEL (f) = -1; + FRAME_BACKGROUND_PIXEL (f) = -1; + f->output_data.pgtk->border_pixel = -1; + + black = build_string ("black"); + FRAME_FOREGROUND_PIXEL (f) + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + FRAME_BACKGROUND_PIXEL (f) + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + f->output_data.pgtk->border_pixel + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + } + + /* Set the name; the functions to which we pass f expect the name to + be set. */ + if (EQ (name, Qunbound) || NILP (name)) + { + fset_name (f, build_string (dpyinfo->x_id_name)); + f->explicit_name = false; + } + else + { + fset_name (f, name); + f->explicit_name = true; + /* use the frame's title when getting resources for this frame. */ + specbind (Qx_resource_name, name); + } + + register_font_driver (&ftcrfont_driver, f); +#ifdef HAVE_HARFBUZZ + register_font_driver (&ftcrhbfont_driver, f); +#endif /* HAVE_HARFBUZZ */ + + image_cache_refcount = + FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; +#ifdef GLYPH_DEBUG + dpyinfo_refcount = dpyinfo->reference_count; +#endif /* GLYPH_DEBUG */ + + gui_default_parameter (f, parms, Qfont_backend, Qnil, + "fontBackend", "FontBackend", RES_TYPE_STRING); + + /* Extract the window parameters from the supplied values that are + needed to determine window geometry. */ + pgtk_default_font_parameter (f, parms); + + gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), + "borderWidth", "BorderWidth", RES_TYPE_NUMBER); + + /* This defaults to 2 in order to match xterm. We recognize either + internalBorderWidth or internalBorder (which is what xterm calls + it). */ + if (NILP (Fassq (Qinternal_border_width, parms))) + { + Lisp_Object value; + + value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, + "internalBorder", "internalBorder", + RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qinternal_border_width, value), + parms); + } + + gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (1), + "internalBorderWidth", "internalBorderWidth", + RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + + /* Also do the stuff which must be set before the window exists. */ + gui_default_parameter (f, parms, Qforeground_color, build_string ("black"), + "foreground", "Foreground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), + "background", "Background", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), + "pointerColor", "Foreground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), + "cursorColor", "Foreground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qborder_color, build_string ("black"), + "borderColor", "BorderColor", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + + /* Init faces before gui_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ + init_frame_faces (f); + + f->output_data.pgtk->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; + + gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, + "inhibitDoubleBuffering", "InhibitDoubleBuffering", + RES_TYPE_BOOLEAN); + + gui_figure_window_size (f, parms, false, false, &x_width, &x_height); + + xg_create_frame_widgets (f); + pgtk_set_event_handler (f); + tip_window = FRAME_GTK_OUTER_WIDGET (f); + gtk_window_set_transient_for (GTK_WINDOW (tip_window), + GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (p))); + gtk_window_set_attached_to (GTK_WINDOW (tip_window), FRAME_GTK_WIDGET (p)); + gtk_window_set_destroy_with_parent (GTK_WINDOW (tip_window), TRUE); + gtk_window_set_decorated (GTK_WINDOW (tip_window), FALSE); + gtk_window_set_type_hint (GTK_WINDOW (tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP); + f->output_data.pgtk->current_cursor = f->output_data.pgtk->text_cursor; + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)), + f->output_data.pgtk->current_cursor); + +#if 0 + x_make_gc (f); +#endif + + gui_default_parameter (f, parms, Qauto_raise, Qnil, + "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qauto_lower, Qnil, + "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); + gui_default_parameter (f, parms, Qcursor_type, Qbox, + "cursorType", "CursorType", RES_TYPE_SYMBOL); + gui_default_parameter (f, parms, Qalpha, Qnil, + "alpha", "Alpha", RES_TYPE_NUMBER); + + /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size. + Change will not be effected unless different from the current + FRAME_LINES (f). */ + width = FRAME_COLS (f); + height = FRAME_LINES (f); + SET_FRAME_COLS (f, 0); + SET_FRAME_LINES (f, 0); + change_frame_size (f, width, height, true, false, false, false); + + /* Add `tooltip' frame parameter's default value. */ + if (NILP (Fframe_parameter (frame, Qtooltip))) + { + AUTO_FRAME_ARG (arg, Qtooltip, Qt); + Fmodify_frame_parameters (frame, arg); + } + + /* FIXME - can this be done in a similar way to normal frames? + https://lists.gnu.org/r/emacs-devel/2007-10/msg00641.html */ + + /* Set the `display-type' frame parameter before setting up faces. */ + { + Lisp_Object disptype; + + disptype = intern ("color"); + + if (NILP (Fframe_parameter (frame, Qdisplay_type))) + { + AUTO_FRAME_ARG (arg, Qdisplay_type, disptype); + Fmodify_frame_parameters (frame, arg); + } + } + + /* Set up faces after all frame parameters are known. This call + also merges in face attributes specified for new frames. + + Frame parameters may be changed if .Xdefaults contains + specifications for the default font. For example, if there is an + `Emacs.default.attributeBackground: pink', the `background-color' + attribute of the frame get's set, which let's the internal border + of the tooltip frame appear in pink. Prevent this. */ + { + Lisp_Object bg = Fframe_parameter (frame, Qbackground_color); + + call2 (Qface_set_after_frame_default, frame, Qnil); + + if (!EQ (bg, Fframe_parameter (frame, Qbackground_color))) + { + AUTO_FRAME_ARG (arg, Qbackground_color, bg); + Fmodify_frame_parameters (frame, arg); + } + } + + f->no_split = true; + + /* Now that the frame will be official, it counts as a reference to + its display and terminal. */ + FRAME_DISPLAY_INFO (f)->reference_count++; + f->terminal->reference_count++; + + /* It is now ok to make the frame official even if we get an error + below. And the frame needs to be on Vframe_list or making it + visible won't work. */ + Vframe_list = Fcons (frame, Vframe_list); + f->can_set_window_size = true; + + /* Setting attributes of faces of the tooltip frame from resources + and similar will set face_change, which leads to the clearing of + all current matrices. Since this isn't necessary here, avoid it + by resetting face_change to the value it had before we created + the tip frame. */ + face_change = face_change_before; + + /* Discard the unwind_protect. */ + return unbind_to (count, frame); +} + /* Compute where to display tip frame F. PARMS is the list of frame parameters for F. DX and DY are specified offsets from the current location of the mouse. WIDTH and HEIGHT are the width and height @@ -2546,9 +2842,20 @@ x_hide_tip (bool delete) tip_timer = Qnil; } - if (NILP (tip_frame) - || (!delete && FRAMEP (tip_frame) + /* Any GTK+ system tooltip can be found via the x_output structure of + tip_last_frame, provided that frame is still live. Any Emacs + tooltip is found via the tip_frame variable. Note that the current + value of x_gtk_use_system_tooltips might not be the same as used + for the tooltip we have to hide, see Bug#30399. */ + if ((NILP (tip_last_frame) && NILP (tip_frame)) + || (!x_gtk_use_system_tooltips + && !delete + && FRAMEP (tip_frame) + && FRAME_LIVE_P (XFRAME (tip_frame)) && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + /* Either there's no tooltip to hide or it's an already invisible + Emacs tooltip and we don't want to change its type. Return + quickly. */ return Qnil; else { @@ -2559,29 +2866,46 @@ x_hide_tip (bool delete) specbind (Qinhibit_redisplay, Qt); specbind (Qinhibit_quit, Qt); - { - /* When using system tooltip, tip_frame is the Emacs frame on - which the tip is shown. */ - struct frame *f = XFRAME (tip_frame); + /* Try to hide the GTK+ system tip first. */ + if (FRAMEP (tip_last_frame)) + { + struct frame *f = XFRAME (tip_last_frame); - if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) - { - tip_frame = Qnil; - was_open = Qt; - } - } + if (FRAME_LIVE_P (f)) + { + if (xg_hide_tooltip (f)) + was_open = Qt; + } + } + /* When using GTK+ system tooltips (compare Bug#41200) reset + tip_last_frame. It will be reassigned when showing the next + GTK+ system tooltip. */ + if (x_gtk_use_system_tooltips) + tip_last_frame = Qnil; + + /* Now look whether there's an Emacs tip around. */ if (FRAMEP (tip_frame)) { - if (delete) + struct frame *f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (f)) { - delete_frame (tip_frame, Qnil); - tip_frame = Qnil; + if (delete || x_gtk_use_system_tooltips) + { + /* Delete the Emacs tooltip frame when DELETE is true + or we change the tooltip type from an Emacs one to + a GTK+ system one. */ + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } + else + pgtk_make_frame_invisible (f); + + was_open = Qt; } else - pgtk_make_frame_invisible (XFRAME (tip_frame)); - - was_open = Qt; + tip_frame = Qnil; } else tip_frame = Qnil; @@ -2623,10 +2947,17 @@ Text larger than the specified size is clipped. */) (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { - struct frame *f; + struct frame *f, *tip_f; + struct window *w; int root_x, root_y; + struct buffer *old_buffer; + struct text_pos pos; int width, height; + int old_windows_or_buffers_changed = windows_or_buffers_changed; ptrdiff_t count = SPECPDL_INDEX (); + ptrdiff_t count_1; + Lisp_Object window, size, tip_buf; + AUTO_STRING (tip, " *tip*"); specbind (Qinhibit_redisplay, Qt); @@ -2634,7 +2965,10 @@ Text larger than the specified size is clipped. */) if (SCHARS (string) == 0) string = make_unibyte_string (" ", 1); + if (NILP (frame)) + frame = selected_frame; f = decode_window_system_frame (frame); + if (NILP (timeout)) timeout = make_fixnum (5); else @@ -2643,34 +2977,218 @@ Text larger than the specified size is clipped. */) if (NILP (dx)) dx = make_fixnum (5); else - CHECK_NUMBER (dx); + CHECK_FIXNUM (dx); if (NILP (dy)) dy = make_fixnum (-10); else - CHECK_NUMBER (dy); + CHECK_FIXNUM (dy); - { - bool ok; + if (x_gtk_use_system_tooltips) + { + bool ok; - /* Hide a previous tip, if any. */ - Fx_hide_tip (); + /* Hide a previous tip, if any. */ + Fx_hide_tip (); - block_input (); - ok = xg_prepare_tooltip (f, string, &width, &height); - if (ok) - { - compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); - xg_show_tooltip (f, root_x, root_y); - /* This is used in Fx_hide_tip. */ - XSETFRAME (tip_frame, f); - } - unblock_input (); - if (ok) - goto start_timer; - } + block_input (); + ok = xg_prepare_tooltip (f, string, &width, &height); + if (ok) + { + compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); + xg_show_tooltip (f, root_x, root_y); + tip_last_frame = frame; + } + + unblock_input (); + if (ok) goto start_timer; + } + + if (FRAMEP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame))) + { + if (FRAME_VISIBLE_P (XFRAME (tip_frame)) + && EQ (frame, tip_last_frame) + && !NILP (Fequal_including_properties (tip_last_string, string)) + && !NILP (Fequal (tip_last_parms, parms))) + { + /* Only DX and DY have changed. */ + tip_f = XFRAME (tip_frame); + if (!NILP (tip_timer)) + { + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } + + block_input (); + compute_tip_xy (tip_f, parms, dx, dy, FRAME_PIXEL_WIDTH (tip_f), + FRAME_PIXEL_HEIGHT (tip_f), &root_x, &root_y); + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (tip_f)), root_x, root_y); + unblock_input (); + + goto start_timer; + } + else if (tooltip_reuse_hidden_frame && EQ (frame, tip_last_frame)) + { + bool delete = false; + Lisp_Object tail, elt, parm, last; + + /* Check if every parameter in PARMS has the same value in + tip_last_parms. This may destruct tip_last_parms which, + however, will be recreated below. */ + for (tail = parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + /* The left, top, right and bottom parameters are handled + by compute_tip_xy so they can be ignored here. */ + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) + && !EQ (parm, Qright) && !EQ (parm, Qbottom)) + { + last = Fassq (parm, tip_last_parms); + if (NILP (Fequal (Fcdr (elt), Fcdr (last)))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + else + tip_last_parms = + call2 (Qassq_delete_all, parm, tip_last_parms); + } + else + tip_last_parms = + call2 (Qassq_delete_all, parm, tip_last_parms); + } + + /* Now check if every parameter in what is left of + tip_last_parms with a non-nil value has an association in + PARMS. */ + for (tail = tip_last_parms; CONSP (tail); tail = XCDR (tail)) + { + elt = XCAR (tail); + parm = Fcar (elt); + if (!EQ (parm, Qleft) && !EQ (parm, Qtop) && !EQ (parm, Qright) + && !EQ (parm, Qbottom) && !NILP (Fcdr (elt))) + { + /* We lost, delete the old tooltip. */ + delete = true; + break; + } + } + + x_hide_tip (delete); + } + else + x_hide_tip (true); + } + else + x_hide_tip (true); + + tip_last_frame = frame; + tip_last_string = string; + tip_last_parms = parms; -start_timer: + if (!FRAMEP (tip_frame) || !FRAME_LIVE_P (XFRAME (tip_frame))) + { + /* Add default values to frame parameters. */ + if (NILP (Fassq (Qname, parms))) + parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms); + if (NILP (Fassq (Qinternal_border_width, parms))) + parms = Fcons (Fcons (Qinternal_border_width, make_fixnum (3)), parms); + if (NILP (Fassq (Qborder_width, parms))) + parms = Fcons (Fcons (Qborder_width, make_fixnum (1)), parms); + if (NILP (Fassq (Qborder_color, parms))) + parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms); + if (NILP (Fassq (Qbackground_color, parms))) + parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")), + parms); + + /* Create a frame for the tooltip, and record it in the global + variable tip_frame. */ + if (NILP (tip_frame = x_create_tip_frame (FRAME_DISPLAY_INFO (f), parms, f))) + /* Creating the tip frame failed. */ + return unbind_to (count, Qnil); + } + + tip_f = XFRAME (tip_frame); + window = FRAME_ROOT_WINDOW (tip_f); + tip_buf = Fget_buffer_create (tip); + /* We will mark the tip window a "pseudo-window" below, and such + windows cannot have display margins. */ + bset_left_margin_cols (XBUFFER (tip_buf), make_fixnum (0)); + bset_right_margin_cols (XBUFFER (tip_buf), make_fixnum (0)); + set_window_buffer (window, tip_buf, false, false); + w = XWINDOW (window); + w->pseudo_window_p = true; + + /* Set up the frame's root window. Note: The following code does not + try to size the window or its frame correctly. Its only purpose is + to make the subsequent text size calculations work. The right + sizes should get installed when the toolkit gets back to us. */ + w->left_col = 0; + w->top_line = 0; + w->pixel_left = 0; + w->pixel_top = 0; + + if (CONSP (Vx_max_tooltip_size) + && RANGED_FIXNUMP (1, XCAR (Vx_max_tooltip_size), INT_MAX) + && RANGED_FIXNUMP (1, XCDR (Vx_max_tooltip_size), INT_MAX)) + { + w->total_cols = XFIXNAT (XCAR (Vx_max_tooltip_size)); + w->total_lines = XFIXNAT (XCDR (Vx_max_tooltip_size)); + } + else + { + w->total_cols = 80; + w->total_lines = 40; + } + + w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (tip_f); + w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (tip_f); + FRAME_TOTAL_COLS (tip_f) = w->total_cols; + adjust_frame_glyphs (tip_f); + + /* Insert STRING into root window's buffer and fit the frame to the + buffer. */ + count_1 = SPECPDL_INDEX (); + old_buffer = current_buffer; + set_buffer_internal_1 (XBUFFER (w->contents)); + bset_truncate_lines (current_buffer, Qnil); + specbind (Qinhibit_read_only, Qt); + specbind (Qinhibit_modification_hooks, Qt); + specbind (Qinhibit_point_motion_hooks, Qt); + Ferase_buffer (); + Finsert (1, &string); + clear_glyph_matrix (w->desired_matrix); + clear_glyph_matrix (w->current_matrix); + SET_TEXT_POS (pos, BEGV, BEGV_BYTE); + try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE); + /* Calculate size of tooltip window. */ + size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil, + make_fixnum (w->pixel_height), Qnil); + /* Add the frame's internal border to calculated size. */ + width = XFIXNUM (Fcar (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + height = XFIXNUM (Fcdr (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f); + + /* Calculate position of tooltip frame. */ + compute_tip_xy (tip_f, parms, dx, dy, width, height, &root_x, &root_y); + + /* Show tooltip frame. */ + block_input (); + gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (tip_f)), width, height); + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (tip_f)), root_x, root_y); + unblock_input (); + + pgtk_cr_update_surface_desired_size (tip_f, width, height); + + w->must_be_updated_p = true; + update_single_window (w); + flush_frame (tip_f); + set_buffer_internal_1 (old_buffer); + unbind_to (count_1, Qnil); + windows_or_buffers_changed = old_windows_or_buffers_changed; + + start_timer: /* Let the tip disappear after timeout seconds. */ tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, intern ("x-hide-tip")); @@ -2705,10 +3223,16 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) int native_height = FRAME_PIXEL_HEIGHT (f); int outer_width = native_width + 2 * border; int outer_height = native_height + 2 * border + title_height; - int native_left = f->left_pos + border; - int native_top = f->top_pos + border + title_height; - int native_right = f->left_pos + outer_width - border; - int native_bottom = f->top_pos + outer_height - border; + + /* Get these here because they can't be got in configure_event(). */ + int left_pos, top_pos; + gtk_window_get_position (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + &left_pos, &top_pos); + + int native_left = left_pos + border; + int native_top = top_pos + border + title_height; + int native_right = left_pos + outer_width - border; + int native_bottom = top_pos + outer_height - border; int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f); int tab_bar_height = 0, tab_bar_width = 0; int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f); @@ -2722,9 +3246,9 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) /* Construct list. */ if (EQ (attribute, Qouter_edges)) - return list4 (make_fixnum (f->left_pos), make_fixnum (f->top_pos), - make_fixnum (f->left_pos + outer_width), - make_fixnum (f->top_pos + outer_height)); + return list4 (make_fixnum (left_pos), make_fixnum (top_pos), + make_fixnum (left_pos + outer_width), + make_fixnum (top_pos + outer_height)); else if (EQ (attribute, Qnative_edges)) return list4 (make_fixnum (native_left), make_fixnum (native_top), make_fixnum (native_right), make_fixnum (native_bottom)); @@ -2738,8 +3262,8 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) else return list (Fcons (Qouter_position, - Fcons (make_fixnum (f->left_pos), - make_fixnum (f->top_pos))), + Fcons (make_fixnum (left_pos), + make_fixnum (top_pos))), Fcons (Qouter_size, Fcons (make_fixnum (outer_width), make_fixnum (outer_height))), @@ -3161,10 +3685,16 @@ be used as the image of the icon representing the frame. */); as_script = Qnil; as_result = 0; - tip_frame = Qnil; - staticpro (&tip_frame); tip_timer = Qnil; staticpro (&tip_timer); + tip_frame = Qnil; + staticpro (&tip_frame); + tip_last_frame = Qnil; + staticpro (&tip_last_frame); + tip_last_string = Qnil; + staticpro (&tip_last_string); + tip_last_parms = Qnil; + staticpro (&tip_last_parms); /* This is not ifdef:ed, so other builds than GTK can customize it. */ DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog, @@ -3192,8 +3722,14 @@ Otherwise use Emacs own tooltip implementation. When using Gtk+ tooltips, the tooltip face is not used. */); x_gtk_use_system_tooltips = true; + DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, + doc: /* Maximum size for tooltips. +Value is a pair (COLUMNS . ROWS). Text larger than this is clipped. */); + Vx_max_tooltip_size = Fcons (make_fixnum (80), make_fixnum (40)); + DEFSYM (Qmono, "mono"); + DEFSYM (Qassq_delete_all, "assq-delete-all"); DEFSYM (Qpdf, "pdf"); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index aeec3f589f..544436e6e4 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6369,6 +6369,13 @@ drag_data_received (GtkWidget * widget, GdkDragContext * context, void pgtk_set_event_handler (struct frame *f) { + if (f->tooltip) + { + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", + G_CALLBACK (pgtk_handle_draw), NULL); + return; + } + gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f)); commit 51462ce2ccae6461384b44ef7dfbc11d27465be8 Author: Yuuki Harano Date: Thu Aug 13 14:26:43 2020 +0900 Add PGTK to system-configuration-features * configure.ac: Set HAVE_PGTK when configuring for PGTK, and add PGTK for iteration. diff --git a/configure.ac b/configure.ac index 66f9b7e8ce..7e04fb6908 100644 --- a/configure.ac +++ b/configure.ac @@ -2837,6 +2837,7 @@ PGTK_LIBS= if test "$window_system" = "pgtk"; then PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o pgtkim.o xsettings.o" PGTK_LIBS="$GTK_LIBS -ldl" + HAVE_PGTK=yes AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) fi AC_SUBST(PGTK_OBJ) @@ -5736,7 +5737,7 @@ optsep= emacs_config_features= for opt in XAW3D XPM JPEG TIFF GIF PNG RSVG CAIRO IMAGEMAGICK SOUND GPM DBUS \ GCONF GSETTINGS GLIB NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE HARFBUZZ M17N_FLT \ - LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT OLDXMENU X11 XDBE XIM \ + LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS X_TOOLKIT OLDXMENU PGTK X11 XDBE XIM \ NS MODULES THREADS XWIDGETS LIBSYSTEMD JSON PDUMPER UNEXEC LCMS2 GMP; do case $opt in commit be47e34e40d4a330e59c8dfabdf8b44a57905973 Author: Yuuki Harano Date: Mon Aug 10 19:06:40 2020 +0900 Re-port image drawing code from X * src/pgtkterm.c (x_cr_draw_image): Re-port X code. (x_draw_image_foreground): Re-port X code. (x_draw_image_glyph_string): Re-port X code. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index dc36f38a5c..aeec3f589f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1971,6 +1971,42 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, x_clear_glyph_string_rect (s, x, y, w, h); } +static void +x_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, + int src_x, int src_y, int width, int height, + int dest_x, int dest_y, bool overlay_p) +{ + cairo_t *cr = pgtk_begin_cr_clip (f); + + if (overlay_p) + cairo_rectangle (cr, dest_x, dest_y, width, height); + else + { + pgtk_set_cr_source_with_gc_background (f, gc); + cairo_rectangle (cr, dest_x, dest_y, width, height); + cairo_fill_preserve (cr); + } + + cairo_translate (cr, dest_x - src_x, dest_y - src_y); + + cairo_surface_t *surface; + cairo_pattern_get_surface (image, &surface); + cairo_format_t format = cairo_image_surface_get_format (surface); + if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1) + { + cairo_set_source (cr, image); + cairo_fill (cr); + } + else + { + pgtk_set_cr_source_with_gc_foreground (f, gc); + cairo_clip (cr); + cairo_mask (cr, image); + } + + pgtk_end_cr_clip (f); +} + /* Draw foreground of image glyph string S. */ static void @@ -1982,7 +2018,8 @@ x_draw_image_foreground (struct glyph_string *s) /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p && s->slice.x == 0) + && s->first_glyph->left_box_line_p + && s->slice.x == 0) x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position @@ -1992,9 +2029,35 @@ x_draw_image_foreground (struct glyph_string *s) if (s->slice.y == 0) y += s->img->vmargin; - /* Draw a rectangle if image could not be loaded. */ - pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y, - s->slice.width - 1, s->slice.height - 1); + if (s->img->cr_data) + { + cairo_t *cr = pgtk_begin_cr_clip (s->f); + x_set_glyph_string_clipping (s, cr); + x_cr_draw_image (s->f, &s->xgcv, s->img->cr_data, + s->slice.x, s->slice.y, s->slice.width, s->slice.height, + x, y, true); + if (!s->img->mask) + { + /* When the image has a mask, we can expect that at + least part of a mouse highlight or a block cursor will + be visible. If the image doesn't have a mask, make + a block cursor visible by drawing a rectangle around + the image. I believe it's looking better if we do + nothing here for mouse-face. */ + if (s->hl == DRAW_CURSOR) + { + int relief = eabs (s->img->relief); + pgtk_draw_rectangle (s->f, s->xgcv.foreground, x - relief, y - relief, + s->slice.width + relief*2 - 1, + s->slice.height + relief*2 - 1); + } + } + pgtk_end_cr_clip (s->f); + } + else + /* Draw a rectangle if image could not be loaded. */ + pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y, + s->slice.width - 1, s->slice.height - 1); } /* Draw image glyph string S. @@ -2033,19 +2096,15 @@ x_draw_image_glyph_string (struct glyph_string *s) || s->img->vmargin || s->img->mask || s->img->pixmap == 0 - || s->stippled_p || s->width != s->background_width) + || s->width != s->background_width) { - if (s->img->mask) - { - fill_background (s, s->x, s->y, s->background_width, s->height); - } - else { int x = s->x; int y = s->y; int width = s->background_width; - if (s->first_glyph->left_box_line_p && s->slice.x == 0) + if (s->first_glyph->left_box_line_p + && s->slice.x == 0) { x += box_line_hwidth; width -= box_line_hwidth; @@ -2054,33 +2113,19 @@ x_draw_image_glyph_string (struct glyph_string *s) if (s->slice.y == 0) y += box_line_vwidth; - fill_background (s, x, y, width, height); + x_draw_glyph_string_bg_rect (s, x, y, width, height); } s->background_filled_p = true; } /* Draw the foreground. */ - if (s->img->cr_data) - { - cairo_t *cr = pgtk_begin_cr_clip (s->f); - - int x = s->x + s->img->hmargin; - int y = s->y + s->img->vmargin; - int width = s->background_width; - - cairo_translate (cr, x - s->slice.x, y - s->slice.y); - cairo_set_source (cr, s->img->cr_data); - cairo_rectangle (cr, 0, 0, width, height); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - } - else - x_draw_image_foreground (s); + x_draw_image_foreground (s); /* If we must draw a relief around the image, do it. */ if (s->img->relief - || s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) + || s->hl == DRAW_IMAGE_RAISED + || s->hl == DRAW_IMAGE_SUNKEN) x_draw_image_relief (s); } commit 2d5ffa5595e2f83977cfe391bcaca0aba9f1f5b6 Author: Yuuki Harano Date: Fri Aug 7 00:47:38 2020 +0900 Make pointer visible when motion notify event * src/pgtkterm.c (motion_notify_event): set pending_signals to true. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index f49bcac294..dc36f38a5c 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5900,6 +5900,9 @@ motion_notify_event (GtkWidget * widget, GdkEvent * event, struct pgtk_display_info *dpyinfo; Mouse_HLInfo *hlinfo; + /* This is needed to make pointer visible when motion_notify event */ + pending_signals = true; + EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; commit e7190d8bb251afd11ac91a3b3c64243a0e8a0cd0 Author: Yuuki Harano Date: Mon Jul 20 21:35:21 2020 +0900 Fix non-English layout does not work * src/pgtkterm.c (key_press_event): Use Vlocale_coding_system. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 6b193bae3e..f49bcac294 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5492,9 +5492,9 @@ key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { /* Decode the input data. */ - /* The input should be decoded with `coding_system' - which depends on which X*LookupString function - we used just above and the locale. */ + /* The input should be decoded with locale `coding_system'. */ + if (!NILP (Vlocale_coding_system)) + coding_system = Vlocale_coding_system; setup_coding_system (coding_system, &coding); coding.src_multibyte = false; coding.dst_multibyte = true; commit 6c4349601c852e16ae34815a36d7032de054e809 Author: Yuuki Harano Date: Mon Jul 13 23:38:07 2020 +0900 Fix font lock is not applied on continued lines * src/pgtkterm.c (pgtk_parse_color): Remove alpha bits. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5318d66917..6b193bae3e 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6721,9 +6721,9 @@ pgtk_parse_color (struct frame *f, const char *color_name, color->green = rgba.green * 65535; color->blue = rgba.blue * 65535; color->pixel = - (unsigned long) 0xff << 24 | (color->red >> 8) << 16 | - (color->green >> 8) << 8 | (color->blue >> 8) << 0; + (color->green >> 8) << 8 | + (color->blue >> 8) << 0; return 1; } return 0; commit af1e279c1530a2df76136a466bccddadcdd9bc7b Author: Jeff Walsh Date: Thu Jul 2 16:27:30 2020 +1000 Restore support for terminal only emacs in PGTK (add --with-pgtk) * configure.ac: add "--with-pgtk" switch for building pgtk terminal support. Adjust X11 window system tests to no clobber pgtk preferences diff --git a/configure.ac b/configure.ac index 16f7ef0e7b..66f9b7e8ce 100644 --- a/configure.ac +++ b/configure.ac @@ -468,6 +468,7 @@ AC_ARG_WITH([ns],[AS_HELP_STRING([--with-ns], [use Nextstep (macOS Cocoa or GNUstep) windowing system. On by default on macOS.])],[],[with_ns=maybe]) OPTION_DEFAULT_OFF([w32], [use native MS Windows GUI in a Cygwin build]) +OPTION_DEFAULT_OFF([pgtk], [use pure GTK build without reliance on X libs (Wayland support) - Experimental]) OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console]) OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support]) @@ -1830,11 +1831,15 @@ AC_SUBST(AUTO_DEPEND) ## window-system-specific substs. window_system=none + +if test "${with_pgtk}" = "yes"; then + window_system=pgtk +fi + + AC_PATH_X -if test "$no_x" != yes; then +if test "$no_x" != yes && test "${with_pgtk}" != "yes"; then window_system=x11 -else - window_system=pgtk fi LD_SWITCH_X_SITE_RPATH= commit 27a92f7b1541f172182e4b3308259ba37d3d5e1f Author: Jeff Walsh Date: Mon Jun 29 22:54:57 2020 +1000 Add font chooser functionality * src/pgtkfns.c (Fpgtk_popup_font_panel): repurpose X/gtk font chooser code (syms_of_pgtkfns): add new symbol diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 900a899445..a4da3302ef 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1617,6 +1617,44 @@ Some window managers may refuse to restack windows. */) return Qt; } +DEFUN ("pgtk-popup-font-panel", Fpgtk_popup_font_panel, Spgtk_popup_font_panel, + 0, 1, "", + doc: /* Pop up the font panel. */) + (Lisp_Object frame) +{ + struct frame *f = decode_window_system_frame (frame); + + Lisp_Object font; + Lisp_Object font_param; + char *default_name = NULL; + ptrdiff_t count = SPECPDL_INDEX (); + + block_input (); + + XSETFONT (font, FRAME_FONT (f)); + font_param = Ffont_get (font, QCname); + if (STRINGP (font_param)) + default_name = xlispstrdup (font_param); + else + { + font_param = Fframe_parameter (frame, Qfont_parameter); + if (STRINGP (font_param)) + default_name = xlispstrdup (font_param); + } + + font = xg_get_font (f, default_name); + xfree (default_name); + + unblock_input (); + + if (NILP (font)) + quit (); + + return unbind_to (count, font); +} + + + #ifdef HAVE_GSETTINGS #define RESOURCE_KEY_MAX_LEN 128 @@ -3089,6 +3127,7 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_frame_geometry); defsubr (&Spgtk_frame_edges); defsubr (&Spgtk_frame_restack); + defsubr (&Spgtk_popup_font_panel); defsubr (&Spgtk_set_mouse_absolute_pixel_position); defsubr (&Spgtk_mouse_absolute_pixel_position); defsubr (&Sx_display_mm_width); commit 383ced7aee884c44d7422b085fe0d2a036e51724 Author: Jeff Walsh Date: Thu Jun 25 16:17:37 2020 +1000 Fix migrating Child frames * src/pgtkterm.c: (x_calc_absolute_position): Remove Function that has no effect (x_set_offset): titlebar off should not be stored as an offset, only used to calculate final move locations diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 413d421fa4..5318d66917 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -286,80 +286,6 @@ x_destroy_window (struct frame *f) dpyinfo->reference_count--; } -/* Calculate the absolute position in frame F - from its current recorded position values and gravity. */ - -static void -x_calc_absolute_position (struct frame *f) -{ - int flags = f->size_hint_flags; - struct frame *p = FRAME_PARENT_FRAME (f); - - /* We have nothing to do if the current position - is already for the top-left corner. */ - if (!((flags & XNegative) || (flags & YNegative))) - return; - - /* Treat negative positions as relative to the leftmost bottommost - position that fits on the screen. */ - if ((flags & XNegative) && (f->left_pos <= 0)) - { - int width = FRAME_PIXEL_WIDTH (f); - - /* A frame that has been visible at least once should have outer - edges. */ - if (FRAME_X_OUTPUT (f)->has_been_visible && !p) - { - Lisp_Object frame; - Lisp_Object edges = Qnil; - - XSETFRAME (frame, f); - edges = Fpgtk_frame_edges (frame, Qouter_edges); - if (!NILP (edges)) - width = (XFIXNUM (Fnth (make_fixnum (2), edges)) - - XFIXNUM (Fnth (make_fixnum (0), edges))); - } - - if (p) - f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width - + f->left_pos); - else - f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) - - width + f->left_pos); - - } - - if ((flags & YNegative) && (f->top_pos <= 0)) - { - int height = FRAME_PIXEL_HEIGHT (f); - - if (FRAME_X_OUTPUT (f)->has_been_visible && !p) - { - Lisp_Object frame; - Lisp_Object edges = Qnil; - - XSETFRAME (frame, f); - if (NILP (edges)) - edges = Fpgtk_frame_edges (frame, Qouter_edges); - if (!NILP (edges)) - height = (XFIXNUM (Fnth (make_fixnum (3), edges)) - - XFIXNUM (Fnth (make_fixnum (1), edges))); - } - - if (p) - f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width - + f->top_pos); - else - f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - - height + f->top_pos); - } - - /* The left_pos and top_pos - are now relative to the top and left screen edges, - so the flags should correspond. */ - f->size_hint_flags &= ~(XNegative | YNegative); -} - /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, to really change the position, and 0 when calling from x_make_frame_visible (in that case, XOFF and YOFF are the current @@ -376,53 +302,46 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) struct frame *parent = FRAME_PARENT_FRAME (f); GtkAllocation a = { 0 }; - if (change_gravity > 0) + int surface_pos_x = 0; + int surface_pos_y = 0; + + if (parent) { - if (parent) - { - /* determing the "height" of the titlebar, by finding the - location of the "emacsfixed" widget on the surface/window */ - GtkWidget *w = FRAME_GTK_WIDGET (parent); - gtk_widget_get_allocation (w, &a); - } + /* determing the "height" of the titlebar, by finding the + location of the "emacsfixed" widget on the surface/window */ + GtkWidget *w = FRAME_GTK_WIDGET (parent); + gtk_widget_get_allocation (w, &a); + } + if (change_gravity > 0) + { f->size_hint_flags &= ~(XNegative | YNegative); - /* if the value is negative, don't include the titlebar offset */ + f->left_pos = xoff; + f->top_pos = yoff; + if (xoff < 0) { f->size_hint_flags |= XNegative; - f->left_pos = xoff; - } - else - { - f->left_pos = xoff + a.x; //~25 } - if (yoff < 0) { f->size_hint_flags |= YNegative; - f->top_pos = yoff; - } - else - { - f->top_pos = yoff + a.y; //~60 } f->win_gravity = NorthWestGravity; } - x_calc_absolute_position (f); - block_input (); - x_wm_set_size_hint (f, 0, false); + surface_pos_y = f->top_pos + a.y; + surface_pos_x = f->left_pos + a.x; /* When a position change was requested and the outer GTK widget has been realized already, leave it to gtk_window_move to DTRT and return. Used for Bug#25851 and Bug#25943. */ if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) { - PGTK_TRACE ("x_set_offset: move to %d,%d.", f->left_pos, f->top_pos); + PGTK_TRACE ("x_set_offset: move to %d,%d.", surface_pos_x, surface_pos_y); gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - f->left_pos, f->top_pos); + surface_pos_x, surface_pos_y); } unblock_input (); commit 89cbe3756c373ca3d1c83055498291f724ca8aa6 Author: Yuuki Harano Date: Tue May 26 20:41:09 2020 +0900 * src/keyboard.c (make_lispy_event): Fix coding style diff --git a/src/keyboard.c b/src/keyboard.c index f6c44a11fb..6605419c5c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -6052,7 +6052,7 @@ make_lispy_event (struct input_event *event) #ifdef HAVE_PGTK case PGTK_PREEDIT_TEXT_EVENT: - return list2 (intern("pgtk-preedit-text"), event->arg); + return list2 (intern ("pgtk-preedit-text"), event->arg); #endif /* The 'kind' field of the event is something we don't recognize. */ commit 20dbd4e283229c98e8bbf1a60da66dde00036d77 Author: Yuuki Harano Date: Tue May 26 20:38:38 2020 +0900 Change coding style * src/gtkutil.c (xg_display_open): (xg_get_image_for_pixmap): (xg_frame_resized): (xg_create_frame_widgets): (x_wm_set_size_hint): (xg_frame_restack): (xg_finish_scroll_bar_creation): (xg_update_scrollbar_pos): (xg_update_horizontal_scrollbar_pos): (xg_set_toolkit_scroll_bar_thumb): (xg_event_is_for_scrollbar): diff --git a/src/gtkutil.c b/src/gtkutil.c index ce08ffec37..97a8e4a5c1 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -186,7 +186,7 @@ xg_display_open (char *display_name, GdkDisplay **dpy) #ifndef HAVE_PGTK gdpy = gdk_display_open (display_name); #else - gdpy = gdk_display_open (strlen(display_name) == 0 ? NULL : display_name); + gdpy = gdk_display_open (strlen (display_name) == 0 ? NULL : display_name); #endif request_sigio (); if (!gdpy_def && gdpy) @@ -1020,15 +1020,15 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth); height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight); - PGTK_TRACE("xg_frame_resized: pixel: %dx%d, text: %dx%d", pixelwidth, pixelheight, width, height); + PGTK_TRACE ("xg_frame_resized: pixel: %dx%d, text: %dx%d", pixelwidth, pixelheight, width, height); frame_size_history_add (f, Qxg_frame_resized, width, height, Qnil); - PGTK_TRACE("width: %d -> %d.", FRAME_TEXT_WIDTH(f), width); - PGTK_TRACE("height: %d -> %d.", FRAME_TEXT_HEIGHT(f), height); - PGTK_TRACE("pixelwidth: %d -> %d.", FRAME_PIXEL_WIDTH(f), pixelwidth); - PGTK_TRACE("pixelheight: %d -> %d.", FRAME_PIXEL_HEIGHT(f), pixelheight); + PGTK_TRACE ("width: %d -> %d.", FRAME_TEXT_WIDTH (f), width); + PGTK_TRACE ("height: %d -> %d.", FRAME_TEXT_HEIGHT (f), height); + PGTK_TRACE ("pixelwidth: %d -> %d.", FRAME_PIXEL_WIDTH (f), pixelwidth); + PGTK_TRACE ("pixelheight: %d -> %d.", FRAME_PIXEL_HEIGHT (f), pixelheight); if (width != FRAME_TEXT_WIDTH (f) || height != FRAME_TEXT_HEIGHT (f) @@ -1343,7 +1343,7 @@ xg_create_frame_widgets (struct frame *f) GtkWindowType type = GTK_WINDOW_TOPLEVEL; char *title = 0; - PGTK_TRACE("xg_create_frame_widgets."); + PGTK_TRACE ("xg_create_frame_widgets."); block_input (); #ifndef HAVE_PGTK // gtk_plug not found. @@ -1504,7 +1504,7 @@ xg_create_frame_widgets (struct frame *f) #else gtk_widget_set_can_focus (wfixed, TRUE); #ifdef HAVE_PGTK - gtk_widget_grab_focus(wfixed); + gtk_widget_grab_focus (wfixed); #endif gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); #endif @@ -1643,7 +1643,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 1) + FRAME_TOOLBAR_WIDTH (f); base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); - PGTK_TRACE("base: %dx%d\n", base_width, base_height); + PGTK_TRACE ("base: %dx%d\n", base_width, base_height); size_hints.base_width = base_width; size_hints.base_height = base_height; @@ -1771,7 +1771,7 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) #ifndef HAVE_PGTK x_sync (f1); #else - gdk_flush(); + gdk_flush (); #endif } unblock_input (); @@ -4039,7 +4039,7 @@ xg_finish_scroll_bar_creation (struct frame *f, Emacs main window, which we draw over using Xlib. */ gtk_widget_realize (webox); #ifdef HAVE_PGTK - gtk_widget_show_all(webox); + gtk_widget_show_all (webox); #endif #ifndef HAVE_PGTK GTK_WIDGET_TO_X_WIN (webox); @@ -4049,11 +4049,15 @@ xg_finish_scroll_bar_creation (struct frame *f, xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); #ifdef HAVE_PGTK - GtkStyleContext *ctxt = gtk_widget_get_style_context(wscroll); - gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); - gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider), - GTK_STYLE_PROVIDER_PRIORITY_USER); + GtkStyleContext *ctxt = gtk_widget_get_style_context (wscroll); + gtk_style_context_add_provider (ctxt, + GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)-> + scrollbar_foreground_css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + gtk_style_context_add_provider (ctxt, + GTK_STYLE_PROVIDER (FRAME_OUTPUT_DATA (f)-> + scrollbar_background_css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); #endif bar->x_window = scroll_id; @@ -4212,7 +4216,7 @@ xg_update_scrollbar_pos (struct frame *f, /* Don't obscure any child frames. */ XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox)); #else - gdk_window_lower(gtk_widget_get_window(webox)); + gdk_window_lower (gtk_widget_get_window(webox)); #endif } @@ -4223,7 +4227,7 @@ xg_update_scrollbar_pos (struct frame *f, #ifndef HAVE_PGTK x_sync (f); #else - gdk_flush(); + gdk_flush (); #endif SET_FRAME_GARBAGED (f); cancel_mouse_face (f); @@ -4304,14 +4308,14 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, /* Don't obscure any child frames. */ XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox)); #else - gdk_window_lower(gtk_widget_get_window(webox)); + gdk_window_lower (gtk_widget_get_window (webox)); #endif } #ifndef HAVE_PGTK x_sync (f); #else - gdk_flush(); + gdk_flush (); #endif SET_FRAME_GARBAGED (f); cancel_mouse_face (f); @@ -4341,8 +4345,8 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: ----------------------------------"); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: %p, %d, %d, %d.", bar, portion, position, whole); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: ----------------------------------"); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: %p, %d, %d, %d.", bar, portion, position, whole); if (wscroll && bar->dragging == -1) { GtkAdjustment *adj; @@ -4374,16 +4378,16 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, top = (gdouble) position / whole; shown = (gdouble) portion / whole; } - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: position=%d, portion=%d, whole=%d", position, portion, whole); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: top=%f, shown=%f", top, shown); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: position=%d, portion=%d, whole=%d", position, portion, whole); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: top=%f, shown=%f", top, shown); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: shown*range=%f", shown * XG_SB_RANGE); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: shown*range=%f", shown * XG_SB_RANGE); size = clip_to_bounds (1, shown * XG_SB_RANGE, XG_SB_RANGE); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: size=%d.", size); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: top*range=%f.", top * XG_SB_RANGE); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: max-size=%d.", XG_SB_MAX - size); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: size=%d.", size); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: top*range=%f.", top * XG_SB_RANGE); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: max-size=%d.", XG_SB_MAX - size); value = clip_to_bounds (XG_SB_MIN, top * XG_SB_RANGE, XG_SB_MAX - size); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: value=%d.", value); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: value=%d.", value); /* Assume all lines are of equal size. */ new_step = size / max (1, FRAME_LINES (f)); @@ -4393,7 +4397,7 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, if (old_size != size) { int old_step = gtk_adjustment_get_step_increment (adj); - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: old_step=%d, new_step=%d", old_step, new_step); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: old_step=%d, new_step=%d", old_step, new_step); if (old_step != new_step) { gtk_adjustment_set_page_size (adj, size); @@ -4404,8 +4408,8 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, } } - PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: changed=%d, old=%d, value=%d.", - changed, int_gtk_range_get_value (GTK_RANGE (wscroll)), value); + PGTK_TRACE ("xg_set_toolkit_scroll_bar_thumb: changed=%d, old=%d, value=%d.", + changed, int_gtk_range_get_value (GTK_RANGE (wscroll)), value); if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value) { block_input (); @@ -4485,7 +4489,7 @@ xg_event_is_for_scrollbar (struct frame *f, const EVENT *event) #ifndef HAVE_PGTK GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); #else - GdkDisplay *gdpy = FRAME_X_DISPLAY(f); + GdkDisplay *gdpy = FRAME_X_DISPLAY (f); #endif GdkWindow *gwin; #ifdef HAVE_GTK3 commit 1fe7caf3a6779f36d8dc6e0a32ccc7d5df8f3121 Author: Yuuki Harano Date: Tue May 26 20:25:28 2020 +0900 Fix coding style * src/emacs.c (main): Fix coding style diff --git a/src/emacs.c b/src/emacs.c index ba5c64a152..f833184863 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1918,8 +1918,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_fontset (); #endif /* HAVE_NS */ #ifdef HAVE_PGTK - syms_of_pgtkterm(); - syms_of_pgtkfns(); + syms_of_pgtkterm (); + syms_of_pgtkfns (); syms_of_pgtkselect (); syms_of_pgtkmenu (); syms_of_pgtkim (); commit 25cf59203e3e2787f8085462989ecaabb6292f75 Author: Yuuki Harano Date: Tue May 26 20:22:20 2020 +0900 Change coding style * src/image.c (image_create_pattern_from_pixbuf): Change coding style (image_create_bitmap_from_data): Change coding style (image_create_bitmap_from_file): Change coding style diff --git a/src/image.c b/src/image.c index c7ae3b9944..e2d142ed32 100644 --- a/src/image.c +++ b/src/image.c @@ -402,14 +402,15 @@ image_reference_bitmap (struct frame *f, ptrdiff_t id) #ifdef HAVE_PGTK static cairo_pattern_t * -image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf *pixbuf) +image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf * pixbuf) { GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); - cairo_surface_t *surface = cairo_surface_create_similar_image (cairo_get_target( - f->output_data.pgtk->cr_context), - CAIRO_FORMAT_A1, - gdk_pixbuf_get_width (pb), - gdk_pixbuf_get_height (pb)); + cairo_surface_t *surface = + cairo_surface_create_similar_image (cairo_get_target + (f->output_data.pgtk->cr_context), + CAIRO_FORMAT_A1, + gdk_pixbuf_get_width (pb), + gdk_pixbuf_get_height (pb)); cairo_t *cr = cairo_create (surface); gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); @@ -462,38 +463,45 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #endif #ifdef HAVE_PGTK - GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - FALSE, - 8, - width, - height); + GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, + 8, + width, + height); { char *sp = bits; int mask = 0x01; unsigned char *buf = gdk_pixbuf_get_pixels (pixbuf); int rowstride = gdk_pixbuf_get_rowstride (pixbuf); - for (int y = 0; y < height; y++) { - unsigned char *dp = buf + rowstride * y; - for (int x = 0; x < width; x++) { - if (*sp & mask) { - *dp++ = 0xff; - *dp++ = 0xff; - *dp++ = 0xff; - } else { - *dp++ = 0x00; - *dp++ = 0x00; - *dp++ = 0x00; - } - if ((mask <<= 1) >= 0x100) { - mask = 0x01; - sp++; - } - } - if (mask != 0x01) { - mask = 0x01; - sp++; + for (int y = 0; y < height; y++) + { + unsigned char *dp = buf + rowstride * y; + for (int x = 0; x < width; x++) + { + if (*sp & mask) + { + *dp++ = 0xff; + *dp++ = 0xff; + *dp++ = 0xff; + } + else + { + *dp++ = 0x00; + *dp++ = 0x00; + *dp++ = 0x00; + } + if ((mask <<= 1) >= 0x100) + { + mask = 0x01; + sp++; + } + } + if (mask != 0x01) + { + mask = 0x01; + sp++; + } } - } } #endif @@ -507,7 +515,8 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #ifdef HAVE_PGTK dpyinfo->bitmaps[id - 1].img = pixbuf; dpyinfo->bitmaps[id - 1].depth = 1; - dpyinfo->bitmaps[id - 1].pattern = image_create_pattern_from_pixbuf (f, pixbuf); + dpyinfo->bitmaps[id - 1].pattern = + image_create_pattern_from_pixbuf (f, pixbuf); #endif dpyinfo->bitmaps[id - 1].file = NULL; @@ -567,10 +576,11 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) ptrdiff_t id; void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); - if (!bitmap) { - g_error_free(err); - return -1; - } + if (!bitmap) + { + g_error_free(err); + return -1; + } id = image_allocate_bitmap_record(f); @@ -580,7 +590,8 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) //dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); - dpyinfo->bitmaps[id - 1].pattern = image_create_pattern_from_pixbuf (f, bitmap); + dpyinfo->bitmaps[id - 1].pattern + = image_create_pattern_from_pixbuf (f, bitmap); return id; #endif commit 3b161dd3c8a9440024bacb7fe26cdb7eff289361 Author: Yuuki Harano Date: Sun May 24 19:45:35 2020 +0900 * src/pgtkselect.h: Change coding style diff --git a/src/pgtkselect.h b/src/pgtkselect.h index a67b2218e4..9dad58017d 100644 --- a/src/pgtkselect.h +++ b/src/pgtkselect.h @@ -25,7 +25,9 @@ along with GNU Emacs. If not, see . */ #include -extern void pgtk_selection_init(void); -void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer user_data); +extern void pgtk_selection_init (void); +extern void pgtk_selection_lost (GtkWidget * widget, + GdkEventSelection * event, + gpointer user_data); -#endif /* HAVE_PGTK */ +#endif /* HAVE_PGTK */ commit f761a09c98c98c27f4621f77edc1fe4ca60e6fcf Author: Yuuki Harano Date: Sun May 24 19:41:51 2020 +0900 * src/pgtkim.c: Change coding style diff --git a/src/pgtkim.c b/src/pgtkim.c index d9bba7e590..15088bc64d 100644 --- a/src/pgtkim.c +++ b/src/pgtkim.c @@ -24,7 +24,8 @@ along with GNU Emacs. If not, see . */ #include "pgtkterm.h" -static void im_context_commit_cb(GtkIMContext *imc, gchar *str, gpointer user_data) +static void +im_context_commit_cb (GtkIMContext * imc, gchar * str, gpointer user_data) { struct pgtk_display_info *dpyinfo = user_data; struct frame *f = dpyinfo->im.focused_frame; @@ -34,31 +35,34 @@ static void im_context_commit_cb(GtkIMContext *imc, gchar *str, gpointer user_da if (f == NULL) return; - pgtk_enqueue_string(f, str); + pgtk_enqueue_string (f, str); } -static gboolean im_context_retrieve_surrounding_cb(GtkIMContext *imc, gpointer user_data) +static gboolean +im_context_retrieve_surrounding_cb (GtkIMContext * imc, gpointer user_data) { - gtk_im_context_set_surrounding(imc, "", -1, 0); + gtk_im_context_set_surrounding (imc, "", -1, 0); return TRUE; } -static gboolean im_context_delete_surrounding_cb(GtkIMContext *imc, int offset, int n_chars, gpointer user_data) +static gboolean +im_context_delete_surrounding_cb (GtkIMContext * imc, int offset, int n_chars, + gpointer user_data) { return TRUE; } -static Lisp_Object make_color_string(PangoAttrColor *pac) +static Lisp_Object +make_color_string (PangoAttrColor * pac) { char buf[256]; - sprintf(buf, "#%02x%02x%02x", - pac->color.red >> 8, - pac->color.green >> 8, - pac->color.blue >> 8); - return build_string(buf); + sprintf (buf, "#%02x%02x%02x", + pac->color.red >> 8, pac->color.green >> 8, pac->color.blue >> 8); + return build_string (buf); } -static void im_context_preedit_changed_cb(GtkIMContext *imc, gpointer user_data) +static void +im_context_preedit_changed_cb (GtkIMContext * imc, gpointer user_data) { struct pgtk_display_info *dpyinfo = user_data; struct frame *f = dpyinfo->im.focused_frame; @@ -71,7 +75,7 @@ static void im_context_preedit_changed_cb(GtkIMContext *imc, gpointer user_data) if (f == NULL) return; - gtk_im_context_get_preedit_string(imc, &str, &attrs, &pos); + gtk_im_context_get_preedit_string (imc, &str, &attrs, &pos); /* @@ -82,58 +86,70 @@ static void im_context_preedit_changed_cb(GtkIMContext *imc, gpointer user_data) */ Lisp_Object list = Qnil; - PangoAttrIterator* iter; - iter = pango_attr_list_get_iterator(attrs); - do { - int st, ed; - int has_underline = 0; - Lisp_Object part = Qnil; - - pango_attr_iterator_range(iter, &st, &ed); - - if (ed > strlen(str)) - ed = strlen(str); - if (st >= ed) - continue; - - Lisp_Object text = make_string(str + st, ed - st); - part = Fcons(text, part); - - PangoAttrInt *ul = (PangoAttrInt *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE); - if (ul != NULL) { - if (ul->value != PANGO_UNDERLINE_NONE) - has_underline = 1; - } - - PangoAttrColor *pac; - if (has_underline) { - pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE_COLOR); + PangoAttrIterator *iter; + iter = pango_attr_list_get_iterator (attrs); + do + { + int st, ed; + int has_underline = 0; + Lisp_Object part = Qnil; + + pango_attr_iterator_range (iter, &st, &ed); + + if (ed > strlen (str)) + ed = strlen (str); + if (st >= ed) + continue; + + Lisp_Object text = make_string (str + st, ed - st); + part = Fcons (text, part); + + PangoAttrInt *ul = + (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE); + if (ul != NULL) + { + if (ul->value != PANGO_UNDERLINE_NONE) + has_underline = 1; + } + + PangoAttrColor *pac; + if (has_underline) + { + pac = + (PangoAttrColor *) pango_attr_iterator_get (iter, + PANGO_ATTR_UNDERLINE_COLOR); + if (pac != NULL) + part = Fcons (Fcons (Qul, make_color_string (pac)), part); + else + part = Fcons (Fcons (Qul, Qt), part); + } + + pac = + (PangoAttrColor *) pango_attr_iterator_get (iter, + PANGO_ATTR_FOREGROUND); if (pac != NULL) - part = Fcons(Fcons(Qul, make_color_string(pac)), part); - else - part = Fcons(Fcons(Qul, Qt), part); - } - - pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_FOREGROUND); - if (pac != NULL) - part = Fcons(Fcons(Qfg, make_color_string(pac)), part); + part = Fcons (Fcons (Qfg, make_color_string (pac)), part); - pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_BACKGROUND); - if (pac != NULL) - part = Fcons(Fcons(Qbg, make_color_string(pac)), part); + pac = + (PangoAttrColor *) pango_attr_iterator_get (iter, + PANGO_ATTR_BACKGROUND); + if (pac != NULL) + part = Fcons (Fcons (Qbg, make_color_string (pac)), part); - part = Fnreverse(part); - list = Fcons(part, list); - } while (pango_attr_iterator_next(iter)); + part = Fnreverse (part); + list = Fcons (part, list); + } + while (pango_attr_iterator_next (iter)); - list = Fnreverse(list); - pgtk_enqueue_preedit(f, list); + list = Fnreverse (list); + pgtk_enqueue_preedit (f, list); - g_free(str); - pango_attr_list_unref(attrs); + g_free (str); + pango_attr_list_unref (attrs); } -static void im_context_preedit_end_cb(GtkIMContext *imc, gpointer user_data) +static void +im_context_preedit_end_cb (GtkIMContext * imc, gpointer user_data) { struct pgtk_display_info *dpyinfo = user_data; struct frame *f = dpyinfo->im.focused_frame; @@ -143,90 +159,116 @@ static void im_context_preedit_end_cb(GtkIMContext *imc, gpointer user_data) if (f == NULL) return; - pgtk_enqueue_preedit(f, Qnil); + pgtk_enqueue_preedit (f, Qnil); } -static void im_context_preedit_start_cb(GtkIMContext *imc, gpointer user_data) +static void +im_context_preedit_start_cb (GtkIMContext * imc, gpointer user_data) { } -void pgtk_im_focus_in(struct frame *f) +void +pgtk_im_focus_in (struct frame *f) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - if (dpyinfo->im.context != NULL) { - gtk_im_context_reset (dpyinfo->im.context); - gtk_im_context_set_client_window (dpyinfo->im.context, gtk_widget_get_window (FRAME_GTK_WIDGET (f))); - gtk_im_context_focus_in (dpyinfo->im.context); - } + if (dpyinfo->im.context != NULL) + { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, + gtk_widget_get_window + (FRAME_GTK_WIDGET (f))); + gtk_im_context_focus_in (dpyinfo->im.context); + } dpyinfo->im.focused_frame = f; } -void pgtk_im_focus_out(struct frame *f) +void +pgtk_im_focus_out (struct frame *f) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - if (dpyinfo->im.focused_frame == f) { - if (dpyinfo->im.context != NULL) { - gtk_im_context_reset (dpyinfo->im.context); - gtk_im_context_focus_out (dpyinfo->im.context); - gtk_im_context_set_client_window (dpyinfo->im.context, NULL); + if (dpyinfo->im.focused_frame == f) + { + if (dpyinfo->im.context != NULL) + { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_focus_out (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, NULL); + } + dpyinfo->im.focused_frame = NULL; } - dpyinfo->im.focused_frame = NULL; - } } -bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev) +bool +pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - if (dpyinfo->im.context != NULL) { - if (gtk_im_context_filter_keypress (dpyinfo->im.context, ev)) - return true; - } + if (dpyinfo->im.context != NULL) + { + if (gtk_im_context_filter_keypress (dpyinfo->im.context, ev)) + return true; + } return false; } -void pgtk_im_init(struct pgtk_display_info *dpyinfo) +void +pgtk_im_init (struct pgtk_display_info *dpyinfo) { dpyinfo->im.context = NULL; } -void pgtk_im_finish(struct pgtk_display_info *dpyinfo) +void +pgtk_im_finish (struct pgtk_display_info *dpyinfo) { if (dpyinfo->im.context != NULL) - g_object_unref(dpyinfo->im.context); + g_object_unref (dpyinfo->im.context); dpyinfo->im.context = NULL; } -DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, - 1, 2, 0, +DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, 1, 2, 0, doc: /* Set whether use Gtk's im context. */) (Lisp_Object use_p, Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); - if (NILP(use_p)) { - if (dpyinfo->im.context != NULL) { - gtk_im_context_reset (dpyinfo->im.context); - gtk_im_context_focus_out (dpyinfo->im.context); - gtk_im_context_set_client_window (dpyinfo->im.context, NULL); - - g_object_unref(dpyinfo->im.context); - dpyinfo->im.context = NULL; + if (NILP (use_p)) + { + if (dpyinfo->im.context != NULL) + { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_focus_out (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, NULL); + + g_object_unref (dpyinfo->im.context); + dpyinfo->im.context = NULL; + } } - } else { - if (dpyinfo->im.context == NULL) { - dpyinfo->im.context = gtk_im_multicontext_new(); - g_signal_connect(dpyinfo->im.context, "commit", G_CALLBACK(im_context_commit_cb), dpyinfo); - g_signal_connect(dpyinfo->im.context, "retrieve-surrounding", G_CALLBACK(im_context_retrieve_surrounding_cb), dpyinfo); - g_signal_connect(dpyinfo->im.context, "delete-surrounding", G_CALLBACK(im_context_delete_surrounding_cb), dpyinfo); - g_signal_connect(dpyinfo->im.context, "preedit-changed", G_CALLBACK(im_context_preedit_changed_cb), dpyinfo); - g_signal_connect(dpyinfo->im.context, "preedit-end", G_CALLBACK(im_context_preedit_end_cb), dpyinfo); - g_signal_connect(dpyinfo->im.context, "preedit-start", G_CALLBACK(im_context_preedit_start_cb), dpyinfo); - gtk_im_context_set_use_preedit (dpyinfo->im.context, TRUE); - - if (dpyinfo->im.focused_frame) - pgtk_im_focus_in(dpyinfo->im.focused_frame); + else + { + if (dpyinfo->im.context == NULL) + { + dpyinfo->im.context = gtk_im_multicontext_new (); + g_signal_connect (dpyinfo->im.context, "commit", + G_CALLBACK (im_context_commit_cb), dpyinfo); + g_signal_connect (dpyinfo->im.context, "retrieve-surrounding", + G_CALLBACK (im_context_retrieve_surrounding_cb), + dpyinfo); + g_signal_connect (dpyinfo->im.context, "delete-surrounding", + G_CALLBACK (im_context_delete_surrounding_cb), + dpyinfo); + g_signal_connect (dpyinfo->im.context, "preedit-changed", + G_CALLBACK (im_context_preedit_changed_cb), + dpyinfo); + g_signal_connect (dpyinfo->im.context, "preedit-end", + G_CALLBACK (im_context_preedit_end_cb), dpyinfo); + g_signal_connect (dpyinfo->im.context, "preedit-start", + G_CALLBACK (im_context_preedit_start_cb), + dpyinfo); + gtk_im_context_set_use_preedit (dpyinfo->im.context, TRUE); + + if (dpyinfo->im.focused_frame) + pgtk_im_focus_in (dpyinfo->im.focused_frame); + } } - } return Qnil; } commit 0056ca2d06ce47b0a272d2b1e3650a28dee91cf3 Author: Yuuki Harano Date: Sun May 24 19:39:44 2020 +0900 * src/pgtkterm.h: Change coding style diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 4ba00e0dbd..f4d6ee035f 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -31,10 +31,11 @@ along with GNU Emacs. If not, see . */ // #define PGTK_DEBUG 1 #ifdef PGTK_DEBUG -extern void pgtk_log(const char *file, int lineno, const char *fmt, ...) - ATTRIBUTE_FORMAT_PRINTF (3, 4); +extern void +pgtk_log (const char *file, int lineno, const char *fmt, ...) +ATTRIBUTE_FORMAT_PRINTF (3, 4); #define PGTK_TRACE(fmt, ...) pgtk_log(__FILE__, __LINE__, fmt, ## __VA_ARGS__) -extern void pgtk_backtrace(const char *file, int lineno); + extern void pgtk_backtrace (const char *file, int lineno); #define PGTK_BACKTRACE() pgtk_backtrace(__FILE__, __LINE__) #else #define PGTK_TRACE(fmt, ...) ((void) 0) @@ -226,7 +227,8 @@ struct pgtk_display_info GdkEvent *last_click_event; /* input method */ - struct { + struct + { GtkIMContext *context; struct frame *focused_frame; } im; @@ -289,7 +291,7 @@ struct pgtk_output /* If a fontset is specified for this frame instead of font, this value contains an ID of the fontset, else -1. */ - int fontset; /* only used with font_backend */ + int fontset; /* only used with font_backend */ unsigned long mouse_color; unsigned long cursor_color; @@ -336,8 +338,8 @@ struct pgtk_output /* The tool bar in this frame */ GtkWidget *toolbar_widget; /* True if tool bar is packed into the hbox widget (i.e. vertical). */ - bool_bf toolbar_in_hbox : 1; - bool_bf toolbar_is_packed : 1; + bool_bf toolbar_in_hbox:1; + bool_bf toolbar_is_packed:1; GtkTooltip *ttip_widget; GtkWidget *ttip_lbl; @@ -399,7 +401,7 @@ enum the focus. IMPLICIT means we received an EnterNotify and the frame may have the focus if no window manager is running. FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ - FOCUS_NONE = 0, + FOCUS_NONE = 0, FOCUS_IMPLICIT = 1, FOCUS_EXPLICIT = 2 }; @@ -506,7 +508,8 @@ enum /* Display init/shutdown functions implemented in pgtkterm.c */ -extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, char *resource_name); +extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, + char *resource_name); extern void pgtk_term_shutdown (int sig); /* Implemented in pgtkterm, published in or needed from pgtkfns. */ @@ -516,23 +519,30 @@ extern char *pgtk_xlfd_to_fontname (const char *xlfd); /* Implemented in pgtkfns. */ extern void pgtk_set_doc_edited (void); extern const char *pgtk_get_defaults_value (const char *key); -extern const char *pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class); -extern void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval); +extern const char *pgtk_get_string_resource (XrmDatabase rdb, + const char *name, + const char *class); +extern void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, + Lisp_Object oldval); /* Color management implemented in pgtkterm. */ extern bool pgtk_defined_color (struct frame *f, const char *name, - Emacs_Color *color_def, bool alloc, + Emacs_Color * color_def, bool alloc, bool makeIndex); -extern void pgtk_query_color (struct frame *f, Emacs_Color *color); -extern void pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors); -extern int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color *color); +extern void pgtk_query_color (struct frame *f, Emacs_Color * color); +extern void pgtk_query_colors (struct frame *f, Emacs_Color * colors, + int ncolors); +extern int pgtk_parse_color (struct frame *f, const char *color_name, + Emacs_Color * color); /* Implemented in pgtkterm.c */ -extern void pgtk_clear_area (struct frame *f, int x, int y, int width, int height); -extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state); +extern void pgtk_clear_area (struct frame *f, int x, int y, int width, + int height); +extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, + int state); extern void pgtk_clear_under_internal_border (struct frame *f); -extern void pgtk_set_event_handler(struct frame *f); +extern void pgtk_set_event_handler (struct frame *f); /* Implemented in pgtkterm.c */ extern int x_display_pixel_height (struct pgtk_display_info *); @@ -541,30 +551,36 @@ extern int x_display_pixel_width (struct pgtk_display_info *); /* Implemented in pgtkterm.c */ extern void x_destroy_window (struct frame *f); extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value, - Lisp_Object old_value); + Lisp_Object old_value); extern void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, - Lisp_Object old_value); + Lisp_Object old_value); extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, - Lisp_Object old_value); + Lisp_Object old_value); extern void x_set_z_group (struct frame *f, Lisp_Object new_value, - Lisp_Object old_value); -extern int pgtk_select (int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timespec *timeout, - sigset_t *sigmask); + Lisp_Object old_value); +extern int pgtk_select (int nfds, fd_set * readfds, fd_set * writefds, + fd_set * exceptfds, struct timespec *timeout, + sigset_t * sigmask); /* Cairo related functions implemented in pgtkterm.c */ extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int); extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); -extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc); -extern void pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc); -extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color); -extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); -extern void pgtk_cr_destroy_frame_context(struct frame *f); +extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, + Emacs_GC * gc); +extern void pgtk_set_cr_source_with_gc_background (struct frame *f, + Emacs_GC * gc); +extern void pgtk_set_cr_source_with_color (struct frame *f, + unsigned long color); +extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); +extern void pgtk_cr_destroy_frame_context (struct frame *f); /* Defined in pgtkmenu.c */ -extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents); -extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object header, const char **error_name); +extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, + Lisp_Object contents); +extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, + const char **error_name); extern void initialize_frame_menubar (struct frame *); @@ -580,7 +596,7 @@ extern void nxatoms_of_pgtkselect (void); /* Initialization and marking implemented in pgtkterm.c */ extern void init_pgtkterm (void); -extern void mark_pgtkterm(void); +extern void mark_pgtkterm (void); extern void pgtk_delete_terminal (struct terminal *terminal); extern void pgtk_make_frame_visible (struct frame *f); @@ -604,17 +620,17 @@ extern void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms); extern void pgtk_menu_set_in_use (bool in_use); -extern void pgtk_enqueue_string(struct frame *f, gchar *str); -extern void pgtk_enqueue_preedit(struct frame *f, Lisp_Object image_data); -extern void pgtk_im_focus_in(struct frame *f); -extern void pgtk_im_focus_out(struct frame *f); -extern bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev); -extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); -extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); +extern void pgtk_enqueue_string (struct frame *f, gchar * str); +extern void pgtk_enqueue_preedit (struct frame *f, Lisp_Object image_data); +extern void pgtk_im_focus_in (struct frame *f); +extern void pgtk_im_focus_out (struct frame *f); +extern bool pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev); +extern void pgtk_im_init (struct pgtk_display_info *dpyinfo); +extern void pgtk_im_finish (struct pgtk_display_info *dpyinfo); extern bool xg_set_icon (struct frame *, Lisp_Object); extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); extern bool pgtk_text_icon (struct frame *f, const char *icon_name); -#endif /* HAVE_PGTK */ +#endif /* HAVE_PGTK */ commit 209c611ae908e4c0be1382c46040e184422f62cc Author: Yuuki Harano Date: Sun May 24 19:37:24 2020 +0900 * src/pgtkterm.h: Remove unused code diff --git a/src/pgtkterm.h b/src/pgtkterm.h index b92a2cd1d1..4ba00e0dbd 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -435,14 +435,6 @@ enum /* Compute pixel height of the frame's titlebar. */ #define FRAME_PGTK_TITLEBAR_HEIGHT(f) 0 -#if 0 - (PGTKHeight([FRAME_PGTK_VIEW (f) frame]) == 0 ? \ - 0 \ - : (int)(PGTKHeight([FRAME_PGTK_VIEW (f) window].frame) \ - - PGTKHeight([PGTKWindow contentRectForFrameRect: \ - [[FRAME_PGTK_VIEW (f) window] frame] \ - styleMask:[[FRAME_PGTK_VIEW (f) window] styleMask]]))) -#endif /* Compute pixel size for vertical scroll bars */ #define PGTK_SCROLL_BAR_WIDTH(f) \ commit 964dfcf46222d9d834da936f5cef7aa3c3c29bd9 Author: Yuuki Harano Date: Sun May 24 19:33:43 2020 +0900 * src/pgtkgui.h: change coding style diff --git a/src/pgtkgui.h b/src/pgtkgui.h index be9fb25bfe..08559207d4 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -45,7 +45,7 @@ typedef unichar XChar2b; typedef struct _GdkCursor *Emacs_Cursor; -typedef void * Color; +typedef void *Color; typedef int Window; typedef struct _GdkDisplay Display; @@ -55,31 +55,12 @@ typedef void *XrmDatabase; /* some sort of attempt to normalize rectangle handling.. seems a bit much for what is accomplished */ -typedef struct { - int x, y; - unsigned width, height; +typedef struct +{ + int x, y; + unsigned width, height; } XRectangle; -#define NativeRectangle XRectangle - -#define CONVERT_TO_EMACS_RECT(xr, nr) \ - ((xr).x = (nr).origin.x, \ - (xr).y = (nr).origin.y, \ - (xr).width = (nr).size.width, \ - (xr).height = (nr).size.height) - -#define CONVERT_FROM_EMACS_RECT(xr, nr) \ - ((nr).x = (xr).x, \ - (nr).y = (xr).y, \ - (nr).width = (xr).width, \ - (nr).height = (xr).height) - -#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \ - ((nr).x = (px), \ - (nr).y = (py), \ - (nr).width = (pwidth), \ - (nr).height = (pheight)) - /* This stuff needed by frame.c. */ #define ForgetGravity 0 #define NorthWestGravity 1 @@ -102,16 +83,37 @@ typedef struct { #define XNegative 0x0010 #define YNegative 0x0020 -#define USPosition (1L << 0) /* user specified x, y */ -#define USSize (1L << 1) /* user specified width, height */ +#define USPosition (1L << 0) /* user specified x, y */ +#define USSize (1L << 1) /* user specified width, height */ -#define PPosition (1L << 2) /* program specified position */ -#define PSize (1L << 3) /* program specified size */ -#define PMinSize (1L << 4) /* program specified minimum size */ -#define PMaxSize (1L << 5) /* program specified maximum size */ -#define PResizeInc (1L << 6) /* program specified resize increments */ -#define PAspect (1L << 7) /* program specified min, max aspect ratios */ -#define PBaseSize (1L << 8) /* program specified base for incrementing */ -#define PWinGravity (1L << 9) /* program specified window gravity */ +#define PPosition (1L << 2) /* program specified position */ +#define PSize (1L << 3) /* program specified size */ +#define PMinSize (1L << 4) /* program specified minimum size */ +#define PMaxSize (1L << 5) /* program specified maximum size */ +#define PResizeInc (1L << 6) /* program specified resize increments */ +#define PAspect (1L << 7) /* program specified min, max aspect ratios */ +#define PBaseSize (1L << 8) /* program specified base for incrementing */ +#define PWinGravity (1L << 9) /* program specified window gravity */ + + +#define NativeRectangle XRectangle + +#define CONVERT_TO_EMACS_RECT(xr, nr) \ + ((xr).x = (nr).x, \ + (xr).y = (nr).y, \ + (xr).width = (nr).width, \ + (xr).height = (nr).height) + +#define CONVERT_FROM_EMACS_RECT(xr, nr) \ + ((nr).x = (xr).x, \ + (nr).y = (xr).y, \ + (nr).width = (xr).width, \ + (nr).height = (xr).height) + +#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \ + ((nr).x = (px), \ + (nr).y = (py), \ + (nr).width = (pwidth), \ + (nr).height = (pheight)) -#endif /* __PGTKGUI_H__ */ +#endif /* __PGTKGUI_H__ */ commit af5b72575c13b4b3f6ad96d7b24b20c67faf5ba4 Author: Yuuki Harano Date: Sun May 24 19:31:06 2020 +0900 * src/pgtkmenu.c: change coding style diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index d86612e13f..7d15340b6b 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -57,14 +57,14 @@ pgtk_menu_set_in_use (bool in_use) /* Don't let frames in `above' z-group obscure popups. */ FOR_EACH_FRAME (frames, frame) - { - struct frame *f = XFRAME (frame); + { + struct frame *f = XFRAME (frame); - if (in_use && FRAME_Z_GROUP_ABOVE (f)) - x_set_z_group (f, Qabove_suspended, Qabove); - else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f)) - x_set_z_group (f, Qabove, Qabove_suspended); - } + if (in_use && FRAME_Z_GROUP_ABOVE (f)) + x_set_z_group (f, Qabove_suspended, Qabove); + else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f)) + x_set_z_group (f, Qabove, Qabove_suspended); + } } /* Wait for an X event to arrive or for a timer to expire. */ @@ -74,7 +74,7 @@ pgtk_menu_wait_for_event (void *data) { struct timespec next_time = timer_check (), *ntp; - if (! timespec_valid_p (next_time)) + if (!timespec_valid_p (next_time)) ntp = 0; else ntp = &next_time; @@ -87,11 +87,11 @@ pgtk_menu_wait_for_event (void *data) DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", doc: /* Start key navigation of the menu bar in FRAME. -This initially opens the first menu bar item and you can then navigate with the -arrow keys, select a menu entry with the return key or cancel with the -escape key. If FRAME has no menu bar this function does nothing. + This initially opens the first menu bar item and you can then navigate with the + arrow keys, select a menu entry with the return key or cancel with the + escape key. If FRAME has no menu bar this function does nothing. -If FRAME is nil or not given, use the selected frame. */) + If FRAME is nil or not given, use the selected frame. */) (Lisp_Object frame) { GtkWidget *menubar; @@ -110,10 +110,10 @@ If FRAME is nil or not given, use the selected frame. */) GList *children = gtk_container_get_children (GTK_CONTAINER (menubar)); if (children) - { - g_signal_emit_by_name (children->data, "activate_item"); - g_list_free (children); - } + { + g_signal_emit_by_name (children->data, "activate_item"); + g_list_free (children); + } } unblock_input (); @@ -124,21 +124,23 @@ If FRAME is nil or not given, use the selected frame. */) Used for popup menus and dialogs. */ static void -popup_widget_loop (bool do_timers, GtkWidget *widget) +popup_widget_loop (bool do_timers, GtkWidget * widget) { ++popup_activated_flag; /* Process events in the Gtk event loop until done. */ while (popup_activated_flag) { - if (do_timers) pgtk_menu_wait_for_event (0); + if (do_timers) + pgtk_menu_wait_for_event (0); gtk_main_iteration (); } } -void pgtk_activate_menubar (struct frame *f) +void +pgtk_activate_menubar (struct frame *f) { - set_frame_menubar(f, false, true); + set_frame_menubar (f, false, true); popup_activated_flag = 1; @@ -149,7 +151,7 @@ void pgtk_activate_menubar (struct frame *f) used and has been unposted. */ static void -popup_deactivate_callback (GtkWidget *widget, gpointer client_data) +popup_deactivate_callback (GtkWidget * widget, gpointer client_data) { popup_activated_flag = 0; } @@ -158,7 +160,7 @@ popup_deactivate_callback (GtkWidget *widget, gpointer client_data) for that widget. F is the frame if known, or NULL if not known. */ static void -show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help) +show_help_event (struct frame *f, GtkWidget * widget, Lisp_Object help) { Lisp_Object frame; @@ -178,13 +180,14 @@ show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help) unhighlighting. */ static void -menu_highlight_callback (GtkWidget *widget, gpointer call_data) +menu_highlight_callback (GtkWidget * widget, gpointer call_data) { xg_menu_item_cb_data *cb_data; Lisp_Object help; cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA); - if (! cb_data) return; + if (!cb_data) + return; help = call_data ? cb_data->help : Qnil; @@ -195,7 +198,7 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data) directly without using an Emacs event. This is what the Lucid code does below. */ show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL, - widget, help); + widget, help); } /* Gtk calls callbacks just because we tell it what item should be @@ -209,14 +212,14 @@ static bool xg_crazy_callback_abort; Figure out what the user chose and put the appropriate events into the keyboard buffer. */ static void -menubar_selection_callback (GtkWidget *widget, gpointer client_data) +menubar_selection_callback (GtkWidget * widget, gpointer client_data) { xg_menu_item_cb_data *cb_data = client_data; if (xg_crazy_callback_abort) return; - if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f) + if (!cb_data || !cb_data->cl_data || !cb_data->cl_data->f) return; /* For a group of radio buttons, GTK calls the selection callback first @@ -225,7 +228,7 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data) the deselected item and then the selected item is executed. Prevent that by ignoring the non-active item. */ if (GTK_IS_RADIO_MENU_ITEM (widget) - && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) + && !gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) return; /* When a menu is popped down, X generates a focus event (i.e. focus @@ -240,9 +243,9 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data) unblock_input (); find_and_call_menu_selection (cb_data->cl_data->f, - cb_data->cl_data->menu_bar_items_used, - cb_data->cl_data->menu_bar_vector, - cb_data->call_data); + cb_data->cl_data->menu_bar_items_used, + cb_data->cl_data->menu_bar_vector, + cb_data->call_data); } /* Recompute all the widgets of frame F, when the menu bar has been @@ -261,7 +264,7 @@ update_frame_menubar (struct frame *f) void set_frame_menubar (struct frame *f, bool first_time, bool deep_p) { - GtkWidget * menubar_widget; + GtkWidget *menubar_widget; Lisp_Object items; widget_value *wv, *first_wv, *prev_wv = 0; int i; @@ -272,9 +275,9 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) menubar_widget = f->output_data.pgtk->menubar_widget; - XSETFRAME(Vmenu_updating_frame, f); + XSETFRAME (Vmenu_updating_frame, f); - if (! menubar_widget) + if (!menubar_widget) deep_p = true; /* Since button_event handler in pgtk emacs doesn't handle mouse @@ -292,14 +295,14 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) int subitems; /* If we are making a new widget, its contents are empty, - do always reinitialize them. */ - if (! menubar_widget) + do always reinitialize them. */ + if (!menubar_widget) previous_menu_items_used = 0; buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents; specbind (Qinhibit_quit, Qt); /* Don't let the debugger step into this code - because it is not reentrant. */ + because it is not reentrant. */ specbind (Qdebug_on_next_call, Qnil); record_unwind_save_match_data (); @@ -315,8 +318,8 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) safe_run_hooks (Qactivate_menubar_hook); /* If it has changed current-menubar from previous value, - really recompute the menubar from the value. */ - if (! NILP (Vlucid_menu_bar_dirty_flag)) + really recompute the menubar from the value. */ + if (!NILP (Vlucid_menu_bar_dirty_flag)) call0 (Qrecompute_lucid_menubar); safe_run_hooks (Qmenu_bar_update_hook); fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); @@ -329,7 +332,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) previous_menu_items_used * word_size); /* Fill in menu_items with the current menu bar contents. - This can evaluate Lisp code. */ + This can evaluate Lisp code. */ save_menu_items (); menu_items = f->menu_bar_vector; @@ -365,7 +368,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) finish_menu_items (); /* Convert menu_items into widget_value trees - to display the menu. This cannot evaluate Lisp code. */ + to display the menu. This cannot evaluate Lisp code. */ wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; @@ -389,7 +392,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) set_buffer_internal_1 (prev); /* If there has been no change in the Lisp-level contents - of the menu bar, skip redisplaying it. Just exit. */ + of the menu bar, skip redisplaying it. Just exit. */ /* Compare the new menu items with the ones computed last time. */ for (i = 0; i < previous_menu_items_used; i++) @@ -414,24 +417,24 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) unbind_to (specpdl_count, Qnil); /* Now GC cannot happen during the lifetime of the widget_value, - so it's safe to store data from a Lisp_String. */ + so it's safe to store data from a Lisp_String. */ wv = first_wv->contents; for (i = 0; i < ASIZE (items); i += 4) { Lisp_Object string; string = AREF (items, i + 1); if (NILP (string)) - break; - wv->name = SSDATA (string); - update_submenu_strings (wv->contents); - wv = wv->next; + break; + wv->name = SSDATA (string); + update_submenu_strings (wv->contents); + wv = wv->next; } } else { /* Make a widget-value tree containing - just the top level menu bar strings. */ + just the top level menu bar strings. */ wv = make_widget_value ("menubar", NULL, true, Qnil); wv->button_type = BUTTON_TYPE_NONE; @@ -462,33 +465,33 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) } /* Forget what we thought we knew about what is in the - detailed contents of the menu bar menus. - Changing the top level always destroys the contents. */ + detailed contents of the menu bar menus. + Changing the top level always destroys the contents. */ f->menu_bar_items_used = 0; } - block_input(); + block_input (); xg_crazy_callback_abort = true; if (menubar_widget) { /* The fourth arg is DEEP_P, which says to consider the entire - menu trees we supply, rather than just the menu bar item names. */ + menu trees we supply, rather than just the menu bar item names. */ xg_modify_menubar_widgets (menubar_widget, - f, - first_wv, - deep_p, - G_CALLBACK (menubar_selection_callback), - G_CALLBACK (popup_deactivate_callback), - G_CALLBACK (menu_highlight_callback)); + f, + first_wv, + deep_p, + G_CALLBACK (menubar_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); } else { menubar_widget - = xg_create_widget ("menubar", "menubar", f, first_wv, - G_CALLBACK (menubar_selection_callback), - G_CALLBACK (popup_deactivate_callback), - G_CALLBACK (menu_highlight_callback)); + = xg_create_widget ("menubar", "menubar", f, first_wv, + G_CALLBACK (menubar_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); f->output_data.pgtk->menubar_widget = menubar_widget; } @@ -537,12 +540,14 @@ initialize_frame_menubar (struct frame *f) static Lisp_Object *volatile menu_item_selection; static void -popup_selection_callback (GtkWidget *widget, gpointer client_data) +popup_selection_callback (GtkWidget * widget, gpointer client_data) { xg_menu_item_cb_data *cb_data = client_data; - if (xg_crazy_callback_abort) return; - if (cb_data) menu_item_selection = cb_data->call_data; + if (xg_crazy_callback_abort) + return; + if (cb_data) + menu_item_selection = cb_data->call_data; } static void @@ -558,7 +563,7 @@ pop_down_menu (void *arg) menu pops down. menu_item_selection will be set to the selection. */ static void -create_and_show_popup_menu (struct frame *f, widget_value *first_wv, +create_and_show_popup_menu (struct frame *f, widget_value * first_wv, int x, int y, bool for_click) { GtkWidget *menu; @@ -568,28 +573,30 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, xg_crazy_callback_abort = true; menu = xg_create_widget ("popup", first_wv->name, f, first_wv, - G_CALLBACK (popup_selection_callback), - G_CALLBACK (popup_deactivate_callback), - G_CALLBACK (menu_highlight_callback)); + G_CALLBACK (popup_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); xg_crazy_callback_abort = false; /* Display the menu. */ gtk_widget_show_all (menu); if (for_click) - gtk_menu_popup_at_pointer (GTK_MENU (menu), FRAME_DISPLAY_INFO(f)->last_click_event); - else { - GdkRectangle rect; - rect.x = x; - rect.y = y; - rect.width = 1; - rect.height = 1; - gtk_menu_popup_at_rect (GTK_MENU (menu), - gtk_widget_get_window(FRAME_GTK_WIDGET(f)), - &rect, - GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, - FRAME_DISPLAY_INFO(f)->last_click_event); - } + gtk_menu_popup_at_pointer (GTK_MENU (menu), + FRAME_DISPLAY_INFO (f)->last_click_event); + else + { + GdkRectangle rect; + rect.x = x; + rect.y = y; + rect.width = 1; + rect.height = 1; + gtk_menu_popup_at_rect (GTK_MENU (menu), + gtk_widget_get_window (FRAME_GTK_WIDGET (f)), + &rect, + GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, + FRAME_DISPLAY_INFO (f)->last_click_event); + } record_unwind_protect_ptr (pop_down_menu, menu); @@ -617,7 +624,7 @@ cleanup_widget_value_tree (void *arg) Lisp_Object pgtk_menu_show (struct frame *f, int x, int y, int menuflags, - Lisp_Object title, const char **error_name) + Lisp_Object title, const char **error_name) { int i; widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; @@ -667,11 +674,10 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, first_pane = false; i++; } - else if (EQ (AREF (menu_items, i), Qt) - && submenu_depth != 0) + else if (EQ (AREF (menu_items, i), Qt) && submenu_depth != 0) i += MENU_ITEMS_PANE_LENGTH; /* Ignore a nil in the item list. - It's meaningful only for dialog boxes. */ + It's meaningful only for dialog boxes. */ else if (EQ (AREF (menu_items, i), Qquote)) i += 1; else if (EQ (AREF (menu_items, i), Qt)) @@ -690,8 +696,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); } #endif - pane_string = (NILP (pane_name) - ? "" : SSDATA (pane_name)); + pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); /* If there is just one top-level pane, put all its items directly under the top-level menu. */ if (menu_items_n_panes == 1) @@ -734,13 +739,13 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); #ifndef HAVE_MULTILINGUAL_MENU - if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) + if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) { item_name = ENCODE_MENU_STRING (item_name); ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); } - if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) + if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) { descrip = ENCODE_MENU_STRING (descrip); ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); @@ -806,8 +811,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv); /* Actually create and show the menu until popped down. */ - create_and_show_popup_menu (f, first_wv, x, y, - menuflags & MENU_FOR_CLICK); + create_and_show_popup_menu (f, first_wv, x, y, menuflags & MENU_FOR_CLICK); unbind_to (specpdl_count, Qnil); @@ -834,8 +838,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, } else if (EQ (AREF (menu_items, i), Qt)) { - prefix - = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); + prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); i += MENU_ITEMS_PANE_LENGTH; } /* Ignore a nil in the item list. @@ -844,8 +847,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, i += 1; else { - entry - = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) { if (menuflags & MENU_KEYMAPS) @@ -878,7 +880,7 @@ pgtk_menu_show (struct frame *f, int x, int y, int menuflags, } static void -dialog_selection_callback (GtkWidget *widget, gpointer client_data) +dialog_selection_callback (GtkWidget * widget, gpointer client_data) { /* Treat the pointer as an integer. There's no problem as long as pointers have enough bits to hold small integers. */ @@ -892,16 +894,15 @@ dialog_selection_callback (GtkWidget *widget, gpointer client_data) dialog pops down. menu_item_selection will be set to the selection. */ static void -create_and_show_dialog (struct frame *f, widget_value *first_wv) +create_and_show_dialog (struct frame *f, widget_value * first_wv) { GtkWidget *menu; eassert (FRAME_PGTK_P (f)); menu = xg_create_widget ("dialog", first_wv->name, f, first_wv, - G_CALLBACK (dialog_selection_callback), - G_CALLBACK (popup_deactivate_callback), - 0); + G_CALLBACK (dialog_selection_callback), + G_CALLBACK (popup_deactivate_callback), 0); if (menu) { @@ -918,15 +919,16 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) } } -static const char * button_names [] = { +static const char *button_names[] = { "button1", "button2", "button3", "button4", "button5", - "button6", "button7", "button8", "button9", "button10" }; + "button6", "button7", "button8", "button9", "button10" +}; Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, - Lisp_Object header, const char **error_name) + Lisp_Object header, const char **error_name) { - int i, nb_buttons=0; + int i, nb_buttons = 0; char dialog_name[6]; widget_value *wv, *first_wv = 0, *prev_wv = 0; @@ -954,8 +956,7 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object pane_name; const char *pane_string; pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); - pane_string = (NILP (pane_name) - ? "" : SSDATA (pane_name)); + pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name)); prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil); first_wv = prev_wv; @@ -968,8 +969,7 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object item_name, enable, descrip; item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); - descrip - = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); + descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); if (NILP (item_name)) { @@ -993,15 +993,14 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, } wv = make_widget_value (button_names[nb_buttons], - SSDATA (item_name), - !NILP (enable), Qnil); + SSDATA (item_name), !NILP (enable), Qnil); prev_wv->next = wv; if (!NILP (descrip)) wv->key = SSDATA (descrip); wv->call_data = aref_addr (menu_items, i); prev_wv = wv; - if (! boundary_seen) + if (!boundary_seen) left_count++; nb_buttons++; @@ -1010,14 +1009,14 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, /* If the boundary was not specified, by default put half on the left and half on the right. */ - if (! boundary_seen) + if (!boundary_seen) left_count = nb_buttons - nb_buttons / 2; wv = make_widget_value (dialog_name, NULL, false, Qnil); /* Frame title: 'Q' = Question, 'I' = Information. - Can also have 'E' = Error if, one day, we want - a popup for errors. */ + Can also have 'E' = Error if, one day, we want + a popup for errors. */ if (NILP (header)) dialog_name[0] = 'Q'; else @@ -1062,13 +1061,12 @@ pgtk_dialog_show (struct frame *f, Lisp_Object title, else if (EQ (AREF (menu_items, i), Qquote)) { /* This is the boundary between left-side elts and - right-side elts. */ + right-side elts. */ ++i; } else { - entry - = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); if (menu_item_selection == aref_addr (menu_items, i)) return entry; i += MENU_ITEMS_ITEM_LENGTH; @@ -1113,7 +1111,8 @@ pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) unbind_to (specpdl_count, Qnil); discard_menu_items (); - if (error_name) error ("%s", error_name); + if (error_name) + error ("%s", error_name); return selection; } @@ -1133,7 +1132,7 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ \(On MS Windows, this refers to the selected frame.) */) (void) { - return (popup_activated ()) ? Qt : Qnil; + return (popup_activated ())? Qt : Qnil; } static void syms_of_pgtkmenu_for_pdumper (void); commit 72f79d820df2eff19d1127ab687fac11ffd1c379 Author: Yuuki Harano Date: Sun May 24 18:16:03 2020 +0900 * src/pgtkselect.c: change coding style diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 4f4a43da8b..491c50b336 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -72,11 +72,11 @@ frame_for_pgtk_selection (Lisp_Object object) return f; FOR_EACH_FRAME (tail, frame) - { - f = XFRAME (frame); - if (FRAME_PGTK_P (f) && FRAME_LIVE_P (f)) - return f; - } + { + f = XFRAME (frame); + if (FRAME_PGTK_P (f) && FRAME_LIVE_P (f)) + return f; + } } else if (TERMINALP (object)) { @@ -84,11 +84,11 @@ frame_for_pgtk_selection (Lisp_Object object) if (t->type == output_pgtk) FOR_EACH_FRAME (tail, frame) - { - f = XFRAME (frame); - if (FRAME_LIVE_P (f) && f->terminal == t) - return f; - } + { + f = XFRAME (frame); + if (FRAME_LIVE_P (f) && f->terminal == t) + return f; + } } else if (FRAMEP (object)) { @@ -100,74 +100,98 @@ frame_for_pgtk_selection (Lisp_Object object) return NULL; } -static GtkClipboard *symbol_to_gtk_clipboard(GtkWidget *widget, Lisp_Object symbol) +static GtkClipboard * +symbol_to_gtk_clipboard (GtkWidget * widget, Lisp_Object symbol) { GdkAtom atom; CHECK_SYMBOL (symbol); - if (NILP(symbol)) { - atom = GDK_SELECTION_PRIMARY; - } else if (EQ(symbol, QCLIPBOARD)) { - atom = GDK_SELECTION_CLIPBOARD; - } else if (EQ(symbol, QPRIMARY)) { - atom = GDK_SELECTION_PRIMARY; - } else if (EQ(symbol, QSECONDARY)) { - atom = GDK_SELECTION_SECONDARY; - } else if (EQ(symbol, Qt)) { - atom = GDK_SELECTION_SECONDARY; - } else { - atom = 0; - error ("Bad selection"); - } - - return gtk_widget_get_clipboard(widget, atom); + if (NILP (symbol)) + { + atom = GDK_SELECTION_PRIMARY; + } + else if (EQ (symbol, QCLIPBOARD)) + { + atom = GDK_SELECTION_CLIPBOARD; + } + else if (EQ (symbol, QPRIMARY)) + { + atom = GDK_SELECTION_PRIMARY; + } + else if (EQ (symbol, QSECONDARY)) + { + atom = GDK_SELECTION_SECONDARY; + } + else if (EQ (symbol, Qt)) + { + atom = GDK_SELECTION_SECONDARY; + } + else + { + atom = 0; + error ("Bad selection"); + } + + return gtk_widget_get_clipboard (widget, atom); } -static void selection_type_to_quarks(GdkAtom type, GQuark *quark_data, GQuark *quark_size) +static void +selection_type_to_quarks (GdkAtom type, GQuark * quark_data, + GQuark * quark_size) { - if (type == GDK_SELECTION_PRIMARY) { - *quark_data = quark_primary_data; - *quark_size = quark_primary_size; - } else if (type == GDK_SELECTION_SECONDARY) { - *quark_data = quark_secondary_data; - *quark_size = quark_secondary_size; - } else if (type == GDK_SELECTION_CLIPBOARD) { - *quark_data = quark_clipboard_data; - *quark_size = quark_clipboard_size; - } else { - /* fixme: Is it safe to use 'error' here? */ - error("Unknown selection type."); - } + if (type == GDK_SELECTION_PRIMARY) + { + *quark_data = quark_primary_data; + *quark_size = quark_primary_size; + } + else if (type == GDK_SELECTION_SECONDARY) + { + *quark_data = quark_secondary_data; + *quark_size = quark_secondary_size; + } + else if (type == GDK_SELECTION_CLIPBOARD) + { + *quark_data = quark_clipboard_data; + *quark_size = quark_clipboard_size; + } + else + { + /* fixme: Is it safe to use 'error' here? */ + error ("Unknown selection type."); + } } static void -get_func(GtkClipboard *cb, GtkSelectionData *data, guint info, gpointer user_data_or_owner) +get_func (GtkClipboard * cb, GtkSelectionData * data, guint info, + gpointer user_data_or_owner) { - PGTK_TRACE("get_func:"); - GObject *obj = G_OBJECT(user_data_or_owner); + PGTK_TRACE ("get_func:"); + GObject *obj = G_OBJECT (user_data_or_owner); const char *str; int size; GQuark quark_data, quark_size; - selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, + &quark_size); - str = g_object_get_qdata(obj, quark_data); - size = GPOINTER_TO_SIZE(g_object_get_qdata(obj, quark_size)); - PGTK_TRACE("get_func: str: %s", str); - gtk_selection_data_set_text(data, str, size); + str = g_object_get_qdata (obj, quark_data); + size = GPOINTER_TO_SIZE (g_object_get_qdata (obj, quark_size)); + PGTK_TRACE ("get_func: str: %s", str); + gtk_selection_data_set_text (data, str, size); } static void -clear_func(GtkClipboard *cb, gpointer user_data_or_owner) +clear_func (GtkClipboard * cb, gpointer user_data_or_owner) { - PGTK_TRACE("clear_func:"); - GObject *obj = G_OBJECT(user_data_or_owner); + PGTK_TRACE ("clear_func:"); + GObject *obj = G_OBJECT (user_data_or_owner); GQuark quark_data, quark_size; - selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, + &quark_size); - g_object_set_qdata(obj, quark_data, NULL); - g_object_set_qdata(obj, quark_size, 0); + g_object_set_qdata (obj, quark_data, NULL); + g_object_set_qdata (obj, quark_size, 0); } @@ -177,27 +201,35 @@ clear_func(GtkClipboard *cb, gpointer user_data_or_owner) ========================================================================== */ -void pgtk_selection_init(void) +void +pgtk_selection_init (void) { - if (quark_primary_data == 0) { - quark_primary_data = g_quark_from_static_string("pgtk-primary-data"); - quark_primary_size = g_quark_from_static_string("pgtk-primary-size"); - quark_secondary_data = g_quark_from_static_string("pgtk-secondary-data"); - quark_secondary_size = g_quark_from_static_string("pgtk-secondary-size"); - quark_clipboard_data = g_quark_from_static_string("pgtk-clipboard-data"); - quark_clipboard_size = g_quark_from_static_string("pgtk-clipboard-size"); - } + if (quark_primary_data == 0) + { + quark_primary_data = g_quark_from_static_string ("pgtk-primary-data"); + quark_primary_size = g_quark_from_static_string ("pgtk-primary-size"); + quark_secondary_data = + g_quark_from_static_string ("pgtk-secondary-data"); + quark_secondary_size = + g_quark_from_static_string ("pgtk-secondary-size"); + quark_clipboard_data = + g_quark_from_static_string ("pgtk-clipboard-data"); + quark_clipboard_size = + g_quark_from_static_string ("pgtk-clipboard-size"); + } } -void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer user_data) +void +pgtk_selection_lost (GtkWidget * widget, GdkEventSelection * event, + gpointer user_data) { GQuark quark_data, quark_size; - PGTK_TRACE("pgtk_selection_lost:"); + PGTK_TRACE ("pgtk_selection_lost:"); - selection_type_to_quarks(event->selection, &quark_data, &quark_size); + selection_type_to_quarks (event->selection, &quark_data, &quark_size); - g_object_set_qdata(G_OBJECT(widget), quark_data, NULL); - g_object_set_qdata(G_OBJECT(widget), quark_size, 0); + g_object_set_qdata (G_OBJECT (widget), quark_data, NULL); + g_object_set_qdata (G_OBJECT (widget), quark_size, 0); } static bool @@ -294,8 +326,7 @@ pgtk_selection_usable (void) ========================================================================== */ -DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, - Spgtk_own_selection_internal, 2, 3, 0, +DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, Spgtk_own_selection_internal, 2, 3, 0, doc: /* Assert an X selection of type SELECTION and value VALUE. SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. \(Those are literal upper-case symbol names, since that's what X expects.) @@ -303,10 +334,10 @@ VALUE is typically a string, or a cons of two markers, but may be anything that the functions on `selection-converter-alist' know about. FRAME should be a frame that should own the selection. If omitted or -nil, it defaults to the selected frame.*/) - (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) +nil, it defaults to the selected frame. */) + (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) { - PGTK_TRACE("pgtk-own-selection-internal."); + PGTK_TRACE ("pgtk-own-selection-internal."); Lisp_Object successful_p = Qnil; Lisp_Object target_symbol, rest; GtkClipboard *cb; @@ -318,13 +349,15 @@ nil, it defaults to the selected frame.*/) if (!pgtk_selection_usable ()) return Qnil; - if (NILP (frame)) frame = selected_frame; + if (NILP (frame)) + frame = selected_frame; if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) error ("pgtk selection unavailable for this frame"); - f = XFRAME(frame); + f = XFRAME (frame); - cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); - selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); + selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, + &quark_size); /* We only support copy of text. */ target_symbol = QTEXT; @@ -340,25 +373,29 @@ nil, it defaults to the selected frame.*/) targets = gtk_target_table_new_from_list (list, &n_targets); - int size = SBYTES(value); - gchar *str = xmalloc(size + 1); - memcpy(str, SSDATA(value), size); + int size = SBYTES (value); + gchar *str = xmalloc (size + 1); + memcpy (str, SSDATA (value), size); str[size] = '\0'; - widget = FRAME_GTK_WIDGET(f); - g_object_set_qdata_full(G_OBJECT(widget), quark_data, str, xfree); - g_object_set_qdata_full(G_OBJECT(widget), quark_size, GSIZE_TO_POINTER(size), NULL); + widget = FRAME_GTK_WIDGET (f); + g_object_set_qdata_full (G_OBJECT (widget), quark_data, str, xfree); + g_object_set_qdata_full (G_OBJECT (widget), quark_size, + GSIZE_TO_POINTER (size), NULL); - PGTK_TRACE("set_with_owner: owner=%p", FRAME_GTK_WIDGET(f)); + PGTK_TRACE ("set_with_owner: owner=%p", FRAME_GTK_WIDGET (f)); if (gtk_clipboard_set_with_owner (cb, targets, n_targets, get_func, clear_func, - G_OBJECT(FRAME_GTK_WIDGET(f)))) { - PGTK_TRACE("set_with_owner succeeded.."); - successful_p = Qt; - } else { - PGTK_TRACE("set_with_owner failed."); - } + G_OBJECT (FRAME_GTK_WIDGET (f)))) + { + PGTK_TRACE ("set_with_owner succeeded.."); + successful_p = Qt; + } + else + { + PGTK_TRACE ("set_with_owner failed."); + } gtk_clipboard_set_can_store (cb, NULL, 0); gtk_target_table_free (targets, n_targets); @@ -368,16 +405,16 @@ nil, it defaults to the selected frame.*/) if (!EQ (Vpgtk_sent_selection_hooks, Qunbound)) { /* FIXME: Use run-hook-with-args! */ - for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); rest = Fcdr (rest)) - call3 (Fcar (rest), selection, target_symbol, successful_p); + for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); + rest = Fcdr (rest)) + call3 (Fcar (rest), selection, target_symbol, successful_p); } return value; } -DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, - Spgtk_disown_selection_internal, 1, 3, 0, +DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, Spgtk_disown_selection_internal, 1, 3, 0, doc: /* If we own the selection SELECTION, disown it. Disowning it means there is no such selection. @@ -393,7 +430,7 @@ On MS-DOS, all this does is return non-nil if we own the selection. On PGTK, the TIME-OBJECT is unused. */) (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) { - PGTK_TRACE("pgtk-disown-selection-internal."); + PGTK_TRACE ("pgtk-disown-selection-internal."); struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; @@ -404,16 +441,16 @@ On PGTK, the TIME-OBJECT is unused. */) if (!f) return Qnil; - cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); - gtk_clipboard_clear(cb); + gtk_clipboard_clear (cb); return Qt; } -DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, - 0, 2, 0, doc: /* Whether there is an owner for the given X selection. +DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, 0, 2, 0, + doc: /* Whether there is an owner for the given X selection. SELECTION should be the name of the selection in question, typically one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects these literal upper-case names.) The symbol nil is the same as @@ -424,9 +461,9 @@ server to query. If omitted or nil, that stands for the selected frame's display, or the first available X display. On Nextstep, TERMINAL is unused. */) - (Lisp_Object selection, Lisp_Object terminal) + (Lisp_Object selection, Lisp_Object terminal) { - PGTK_TRACE("pgtk-selection-exists-p."); + PGTK_TRACE ("pgtk-selection-exists-p."); struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; @@ -436,14 +473,13 @@ On Nextstep, TERMINAL is unused. */) if (!f) return Qnil; - cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); - return gtk_clipboard_wait_is_text_available(cb) ? Qt : Qnil; + return gtk_clipboard_wait_is_text_available (cb) ? Qt : Qnil; } -DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, - 0, 2, 0, +DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, 0, 2, 0, doc: /* Whether the current Emacs process owns the given X Selection. The arg should be the name of the selection in question, typically one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. @@ -456,9 +492,9 @@ server to query. If omitted or nil, that stands for the selected frame's display, or the first available X display. On Nextstep, TERMINAL is unused. */) - (Lisp_Object selection, Lisp_Object terminal) + (Lisp_Object selection, Lisp_Object terminal) { - PGTK_TRACE("pgtk-selection-owner-p."); + PGTK_TRACE ("pgtk-selection-owner-p."); struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; GObject *obj; @@ -467,17 +503,17 @@ On Nextstep, TERMINAL is unused. */) if (!pgtk_selection_usable ()) return Qnil; - cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); - selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); + selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, + &quark_size); - obj = gtk_clipboard_get_owner(cb); + obj = gtk_clipboard_get_owner (cb); - return g_object_get_qdata(obj, quark_data) != NULL ? Qt : Qnil; + return g_object_get_qdata (obj, quark_data) != NULL ? Qt : Qnil; } -DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, - Spgtk_get_selection_internal, 2, 4, 0, +DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, Spgtk_get_selection_internal, 2, 4, 0, doc: /* Return text selected from some X window. SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. \(Those are literal upper-case symbol names, since that's what X expects.) @@ -508,12 +544,12 @@ On PGTK, TIME-STAMP is unused. */) if (!pgtk_selection_usable ()) return Qnil; - cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol); + cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection_symbol); - gchar *s = gtk_clipboard_wait_for_text(cb); + gchar *s = gtk_clipboard_wait_for_text (cb); if (s == NULL) return Qnil; - int size = strlen(s); + int size = strlen (s); Lisp_Object str = make_unibyte_string (s, size); Fput_text_property (make_fixnum (0), make_fixnum (size), Qforeign_selection, QUTF8_STRING, str); @@ -524,13 +560,13 @@ On PGTK, TIME-STAMP is unused. */) void nxatoms_of_pgtkselect (void) { - PGTK_TRACE("nxatoms_of_pgtkselect"); + PGTK_TRACE ("nxatoms_of_pgtkselect"); } void syms_of_pgtkselect (void) { - PGTK_TRACE("syms_of_pgtkselect"); + PGTK_TRACE ("syms_of_pgtkselect"); DEFSYM (QCLIPBOARD, "CLIPBOARD"); DEFSYM (QSECONDARY, "SECONDARY"); @@ -553,7 +589,7 @@ syms_of_pgtkselect (void) #endif DEFVAR_LISP ("pgtk-sent-selection-hooks", Vpgtk_sent_selection_hooks, - "A list of functions to be called when Emacs answers a selection request.\n\ + "A list of functions to be called when Emacs answers a selection request.\n\ The functions are called with four arguments:\n\ - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\ - the selection-type which Emacs was asked to convert the\n\ commit d109dabbc53c9d8e5a5dedf3d82f70692875c908 Author: Yuuki Harano Date: Sun May 24 18:11:22 2020 +0900 * src/pgtkfns.c: change coding style diff --git a/src/pgtkfns.c b/src/pgtkfns.c index feda093384..900a899445 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -48,7 +48,8 @@ static int as_status; static ptrdiff_t image_cache_refcount; -static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); +static int x_decode_color (struct frame *f, Lisp_Object color_name, + int mono_color); static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); static const char *pgtk_app_name = "Emacs"; @@ -73,14 +74,14 @@ check_pgtk_display_info (Lisp_Object object) else if (x_display_list != 0) dpyinfo = x_display_list; else - error ("Frames are not in use or not initialized"); + error ("Frames are not in use or not initialized"); } else if (TERMINALP (object)) { struct terminal *t = decode_live_terminal (object); if (t->type != output_pgtk) - error ("Terminal %d is not a display", t->id); + error ("Terminal %d is not a display", t->id); dpyinfo = t->display_info.pgtk; } @@ -137,14 +138,14 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); FRAME_FOREGROUND_PIXEL (f) = fg; - FRAME_X_OUTPUT(f)->foreground_color = fg; + FRAME_X_OUTPUT (f)->foreground_color = fg; if (FRAME_GTK_WIDGET (f)) { update_face_from_frame_parameter (f, Qforeground_color, arg); /*recompute_basic_faces (f); */ if (FRAME_VISIBLE_P (f)) - SET_FRAME_GARBAGED (f); + SET_FRAME_GARBAGED (f); } } @@ -161,13 +162,13 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (FRAME_VISIBLE_P (f)) pgtk_clear_frame (f); - PGTK_TRACE("x_set_background_color: col.pixel=%08lx.", bg); - FRAME_X_OUTPUT(f)->background_color = bg; + PGTK_TRACE ("x_set_background_color: col.pixel=%08lx.", bg); + FRAME_X_OUTPUT (f)->background_color = bg; - xg_set_background_color(f, bg); + xg_set_background_color (f, bg); update_face_from_frame_parameter (f, Qbackground_color, arg); - PGTK_TRACE("visible_p=%d.", FRAME_VISIBLE_P(f)); + PGTK_TRACE ("visible_p=%d.", FRAME_VISIBLE_P (f)); if (FRAME_VISIBLE_P (f)) SET_FRAME_GARBAGED (f); } @@ -179,7 +180,7 @@ x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) CHECK_STRING (arg); pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->border_pixel = pix; + FRAME_X_OUTPUT (f)->border_pixel = pix; pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (f)); } @@ -240,8 +241,8 @@ pgtk_set_name_internal (struct frame *f, Lisp_Object name) we use it before x_encode_text that may return string data. */ encoded_name = ENCODE_UTF_8 (name); - gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - SSDATA (encoded_name)); + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + SSDATA (encoded_name)); } unblock_input (); } @@ -259,9 +260,9 @@ pgtk_set_name (struct frame *f, Lisp_Object name, int explicit) /* If we're switching from explicit to implicit, we had better update the mode lines and thereby update the title. */ if (f->explicit_name && NILP (name)) - update_mode_lines = 12; + update_mode_lines = 12; - f->explicit_name = ! NILP (name); + f->explicit_name = !NILP (name); } else if (f->explicit_name) return; @@ -272,13 +273,13 @@ pgtk_set_name (struct frame *f, Lisp_Object name, int explicit) CHECK_STRING (name); /* Don't change the name if it's already NAME. */ - if (! NILP (Fstring_equal (name, f->name))) + if (!NILP (Fstring_equal (name, f->name))) return; fset_name (f, name); /* Title overrides explicit name. */ - if (! NILP (f->title)) + if (!NILP (f->title)) name = f->title; pgtk_set_name_internal (f, name); @@ -300,7 +301,8 @@ x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) name; names set this way will never override names set by the user's lisp code. */ void -pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, + Lisp_Object oldval) { PGTK_TRACE ("x_implicitly_set_name"); pgtk_set_name (f, arg, false); @@ -349,7 +351,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) return; if (TYPE_RANGED_FIXNUMP (int, value)) - nlines = XFIXNUM (value); + nlines = XFIXNUM (value); else nlines = 0; @@ -442,7 +444,8 @@ x_change_tab_bar_height (struct frame *f, int height) && (!f->after_make_frame || NILP (frame_inhibit_implied_resize) || (CONSP (frame_inhibit_implied_resize) - && NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize))))) + && + NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize))))) f->tab_bar_redisplayed = f->tab_bar_resized = false; adjust_frame_size (f, -1, -1, @@ -451,8 +454,7 @@ x_change_tab_bar_height (struct frame *f, int height) get_frame_param (f, Qfullscreen)) || EQ (fullscreen, Qfullwidth))) ? 1 : (old_height == 0 || height == 0) ? 2 - : 4), - false, Qtab_bar_lines); + : 4), false, Qtab_bar_lines); f->tab_bar_resized = f->tab_bar_redisplayed; @@ -481,7 +483,7 @@ x_change_tool_bar_height (struct frame *f, int height) else { if (FRAME_EXTERNAL_TOOL_BAR (f)) - free_frame_tool_bar (f); + free_frame_tool_bar (f); FRAME_EXTERNAL_TOOL_BAR (f) = false; } } @@ -509,7 +511,8 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) static void -x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +x_set_internal_border_width (struct frame *f, Lisp_Object arg, + Lisp_Object oldval) { int border = check_int_nonnegative (arg); @@ -542,9 +545,8 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) block_input (); if (NILP (arg)) result = pgtk_text_icon (f, - SSDATA ((!NILP (f->icon_name) - ? f->icon_name - : f->name))); + SSDATA ((!NILP (f->icon_name) + ? f->icon_name : f->name))); else result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg); @@ -579,8 +581,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) SSDATA ((!NILP (f->icon_name) ? f->icon_name : !NILP (f->title) - ? f->title - : f->name))); + ? f->title : f->name))); if (result) { @@ -619,18 +620,20 @@ x_icon (struct frame *f, Lisp_Object parms) Lisp_Object icon_x, icon_y; struct pgtk_display_info *dpyinfo = check_pgtk_display_info (Qnil); - FRAME_X_OUTPUT(f)->icon_top = -1; - FRAME_X_OUTPUT(f)->icon_left = -1; + FRAME_X_OUTPUT (f)->icon_top = -1; + FRAME_X_OUTPUT (f)->icon_left = -1; /* Set the position of the icon. */ - icon_x = gui_display_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); - icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); + icon_x = + gui_display_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); + icon_y = + gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) { CHECK_NUMBER (icon_x); CHECK_NUMBER (icon_y); - FRAME_X_OUTPUT(f)->icon_top = XFIXNUM (icon_y); - FRAME_X_OUTPUT(f)->icon_left = XFIXNUM (icon_x); + FRAME_X_OUTPUT (f)->icon_top = XFIXNUM (icon_y); + FRAME_X_OUTPUT (f)->icon_left = XFIXNUM (icon_x); } else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) error ("Both left and top icon corners of icon must be specified"); @@ -650,7 +653,8 @@ x_icon (struct frame *f, Lisp_Object parms) * Some window managers may not honor this parameter. */ static void -x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_undecorated (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { if (!EQ (new_value, old_value)) { @@ -670,7 +674,8 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value * Some window managers may not honor this parameter. */ static void -x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { if (!EQ (new_value, old_value)) { @@ -689,12 +694,13 @@ x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu * Some window managers may not honor this parameter. */ static void -x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_override_redirect (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { if (!EQ (new_value, old_value)) { /* Here (xfwm) override_redirect can be changed for invisible - frames only. */ + frames only. */ pgtk_make_frame_invisible (f); xg_set_override_redirect (f, new_value); @@ -715,7 +721,7 @@ xg_set_icon (struct frame *f, Lisp_Object file) found = image_find_image_file (file); - if (! NILP (found)) + if (!NILP (found)) { GdkPixbuf *pixbuf; GError *err = NULL; @@ -755,7 +761,8 @@ xg_set_icon_from_xpm_data (struct frame *f, const char **data) } static void -pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +pgtk_set_sticky (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { if (!NILP (new_value)) gtk_window_stick (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); @@ -765,8 +772,7 @@ pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) static void pgtk_set_tool_bar_position (struct frame *f, - Lisp_Object new_value, - Lisp_Object old_value) + Lisp_Object new_value, Lisp_Object old_value) { Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom); @@ -783,89 +789,102 @@ pgtk_set_tool_bar_position (struct frame *f, } static void -pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { - GtkCssProvider *css_provider = FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider; + GtkCssProvider *css_provider = + FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider; - if (NILP (new_value)) { - gtk_css_provider_load_from_data(css_provider, "", -1, NULL); - } else if (STRINGP (new_value)) { - Emacs_Color rgb; + if (NILP (new_value)) + { + gtk_css_provider_load_from_data (css_provider, "", -1, NULL); + } + else if (STRINGP (new_value)) + { + Emacs_Color rgb; - if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) - error ("Unknown color."); + if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) + error ("Unknown color."); - char css[64]; - sprintf(css, "scrollbar slider { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); - gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + char css[64]; + sprintf (css, "scrollbar slider { background-color: #%06x; }", + (unsigned int) rgb.pixel & 0xffffff); + gtk_css_provider_load_from_data (css_provider, css, -1, NULL); - } else + } + else error ("Invalid scroll-bar-foreground."); } static void -pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) { - GtkCssProvider *css_provider = FRAME_X_OUTPUT (f)->scrollbar_background_css_provider; + GtkCssProvider *css_provider = + FRAME_X_OUTPUT (f)->scrollbar_background_css_provider; - if (NILP (new_value)) { - gtk_css_provider_load_from_data(css_provider, "", -1, NULL); - } else if (STRINGP (new_value)) { - Emacs_Color rgb; + if (NILP (new_value)) + { + gtk_css_provider_load_from_data (css_provider, "", -1, NULL); + } + else if (STRINGP (new_value)) + { + Emacs_Color rgb; - if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) - error ("Unknown color."); + if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) + error ("Unknown color."); - char css[64]; - sprintf(css, "scrollbar trough { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); - gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + char css[64]; + sprintf (css, "scrollbar trough { background-color: #%06x; }", + (unsigned int) rgb.pixel & 0xffffff); + gtk_css_provider_load_from_data (css_provider, css, -1, NULL); - } else + } + else error ("Invalid scroll-bar-background."); } /* Note: see frame.c for template, also where generic functions are impl */ -frame_parm_handler pgtk_frame_parm_handlers[] = -{ - gui_set_autoraise, /* generic OK */ - gui_set_autolower, /* generic OK */ +frame_parm_handler pgtk_frame_parm_handlers[] = { + gui_set_autoraise, /* generic OK */ + gui_set_autolower, /* generic OK */ x_set_background_color, x_set_border_color, gui_set_border_width, x_set_cursor_color, x_set_cursor_type, - gui_set_font, /* generic OK */ + gui_set_font, /* generic OK */ x_set_foreground_color, x_set_icon_name, x_set_icon_type, - x_set_internal_border_width, /* generic OK */ + x_set_internal_border_width, /* generic OK */ gui_set_right_divider_width, gui_set_bottom_divider_width, x_set_menu_bar_lines, x_set_mouse_color, x_explicitly_set_name, - gui_set_scroll_bar_width, /* generic OK */ - gui_set_scroll_bar_height, /* generic OK */ + gui_set_scroll_bar_width, /* generic OK */ + gui_set_scroll_bar_height, /* generic OK */ x_set_title, - gui_set_unsplittable, /* generic OK */ - gui_set_vertical_scroll_bars, /* generic OK */ - gui_set_horizontal_scroll_bars, /* generic OK */ - gui_set_visibility, /* generic OK */ + gui_set_unsplittable, /* generic OK */ + gui_set_vertical_scroll_bars, /* generic OK */ + gui_set_horizontal_scroll_bars, /* generic OK */ + gui_set_visibility, /* generic OK */ x_set_tab_bar_lines, x_set_tool_bar_lines, pgtk_set_scroll_bar_foreground, pgtk_set_scroll_bar_background, - gui_set_screen_gamma, /* generic OK */ - gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ - gui_set_left_fringe, /* generic OK */ - gui_set_right_fringe, /* generic OK */ - 0, /* x_set_wait_for_wm */ - gui_set_fullscreen, /* generic OK */ - gui_set_font_backend, /* generic OK */ + gui_set_screen_gamma, /* generic OK */ + gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ + gui_set_left_fringe, /* generic OK */ + gui_set_right_fringe, /* generic OK */ + 0, /* x_set_wait_for_wm */ + gui_set_fullscreen, /* generic OK */ + gui_set_font_backend, /* generic OK */ gui_set_alpha, pgtk_set_sticky, pgtk_set_tool_bar_position, - 0, /* x_set_inhibit_double_buffering */ + 0, /* x_set_inhibit_double_buffering */ x_set_undecorated, x_set_parent_frame, x_set_skip_taskbar, @@ -896,12 +915,12 @@ unwind_create_frame (Lisp_Object frame) if (NILP (Fmemq (frame, Vframe_list))) { /* If the frame's image cache refcount is still the same as our - private shadow variable, it means we are unwinding a frame - for which we didn't yet call init_frame_faces, where the - refcount is incremented. Therefore, we increment it here, so - that free_frame_faces, called in x_free_frame_resources - below, will not mistakenly decrement the counter that was not - incremented yet to account for this new frame. */ + private shadow variable, it means we are unwinding a frame + for which we didn't yet call init_frame_faces, where the + refcount is incremented. Therefore, we increment it here, so + that free_frame_faces, called in x_free_frame_resources + below, will not mistakenly decrement the counter that was not + incremented yet to account for this new frame. */ if (FRAME_IMAGE_CACHE (f) != NULL && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount) FRAME_IMAGE_CACHE (f)->refcount++; @@ -947,8 +966,9 @@ void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, - RES_TYPE_STRING); + Lisp_Object font_param = + gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, + RES_TYPE_STRING); Lisp_Object font = Qnil; if (EQ (font_param, Qunbound)) font_param = Qnil; @@ -964,31 +984,32 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) } if (NILP (font)) - font = !NILP (font_param) ? font_param - : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING); + font = !NILP (font_param) ? font_param + : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", + RES_TYPE_STRING); - if (! FONTP (font) && ! STRINGP (font)) + if (!FONTP (font) && !STRINGP (font)) { - const char *names[] - = { - "monospace-10", - "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1", - "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", - "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", - /* This was formerly the first thing tried, but it finds - too many fonts and takes too long. */ - "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1", - /* If those didn't work, look for something which will - at least work. */ - "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1", - "fixed", - NULL }; + const char *names[] = { + "monospace-10", + "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1", + "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", + "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", + /* This was formerly the first thing tried, but it finds + too many fonts and takes too long. */ + "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1", + /* If those didn't work, look for something which will + at least work. */ + "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1", + "fixed", + NULL + }; int i; for (i = 0; names[i]; i++) { font = font_open_by_name (f, build_unibyte_string (names[i])); - if (! NILP (font)) + if (!NILP (font)) break; } if (NILP (font)) @@ -997,13 +1018,14 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) else if (!NILP (font_param)) { /* Remember the explicit font parameter, so we can re-apply it after - we've applied the `default' face settings. */ + we've applied the `default' face settings. */ AUTO_FRAME_ARG (arg, Qfont_parameter, font_param); gui_set_frame_parameters (f, arg); } /* This call will make X resources override any system font setting. */ - gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qfont, font, "font", "Font", + RES_TYPE_STRING); } /* ========================================================================== @@ -1012,8 +1034,7 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) ========================================================================== */ -DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, - 1, 1, 0, +DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, 1, 1, 0, doc: /* Make a new X window, which is called a "frame" in Emacs terms. Return an Emacs frame object. PARMS is an alist of frame parameters. If the parameters specify that the frame should not have a minibuffer, @@ -1021,7 +1042,7 @@ and do not specify a specific minibuffer window to use, then `default-minibuffer-frame' must be a frame whose minibuffer can be shared by the new frame. -This function is an internal primitive--use `make-frame' instead. */) +This function is an internal primitive--use `make-frame' instead. */ ) (Lisp_Object parms) { struct frame *f; @@ -1043,9 +1064,11 @@ This function is an internal primitive--use `make-frame' instead. */) until we know if this frame has a specified name. */ Vx_resource_name = Vinvocation_name; - display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); + display = + gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); if (EQ (display, Qunbound)) - display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); + display = + gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); if (EQ (display, Qunbound)) display = Qnil; dpyinfo = check_pgtk_display_info (display); @@ -1054,25 +1077,28 @@ This function is an internal primitive--use `make-frame' instead. */) if (!dpyinfo->terminal->name) error ("Terminal is not live, can't create new frames on it"); - name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); - if (!STRINGP (name) - && ! EQ (name, Qunbound) - && ! NILP (name)) + name = + gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", + RES_TYPE_STRING); + if (!STRINGP (name) && !EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); if (STRINGP (name)) Vx_resource_name = name; /* See if parent window is specified. */ - parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); + parent = + gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, + RES_TYPE_NUMBER); if (EQ (parent, Qunbound)) parent = Qnil; - if (! NILP (parent)) + if (!NILP (parent)) CHECK_NUMBER (parent); frame = Qnil; - tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer", - RES_TYPE_SYMBOL); + tem = + gui_display_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", + "Minibuffer", RES_TYPE_SYMBOL); if (EQ (tem, Qnone) || NILP (tem)) f = make_frame_without_minibuffer (Qnil, kb, display); else if (EQ (tem, Qonly)) @@ -1085,8 +1111,9 @@ This function is an internal primitive--use `make-frame' instead. */) else f = make_frame (true); - parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, - RES_TYPE_SYMBOL); + parent_frame = + gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, + RES_TYPE_SYMBOL); /* Accept parent-frame iff parent-id was not specified. */ if (!NILP (parent) || EQ (parent_frame, Qunbound) @@ -1099,16 +1126,20 @@ This function is an internal primitive--use `make-frame' instead. */) fset_parent_frame (f, parent_frame); store_frame_param (f, Qparent_frame, parent_frame); - if (!NILP (tem = (gui_display_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, - RES_TYPE_BOOLEAN))) + if (!NILP + (tem = + (gui_display_get_arg + (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN))) && !(EQ (tem, Qunbound))) undecorated = true; FRAME_UNDECORATED (f) = undecorated; store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil); - if (!NILP (tem = (gui_display_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL, - RES_TYPE_BOOLEAN))) + if (!NILP + (tem = + (gui_display_get_arg + (dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN))) && !(EQ (tem, Qunbound))) override_redirect = true; @@ -1120,21 +1151,23 @@ This function is an internal primitive--use `make-frame' instead. */) f->terminal = dpyinfo->terminal; f->output_method = output_pgtk; - FRAME_X_OUTPUT(f) = xzalloc (sizeof *FRAME_X_OUTPUT(f)); + FRAME_X_OUTPUT (f) = xzalloc (sizeof *FRAME_X_OUTPUT (f)); #if 0 - FRAME_X_OUTPUT(f)->icon_bitmap = -1; + FRAME_X_OUTPUT (f)->icon_bitmap = -1; #endif FRAME_FONTSET (f) = -1; - FRAME_X_OUTPUT(f)->white_relief.pixel = -1; - FRAME_X_OUTPUT(f)->black_relief.pixel = -1; + FRAME_X_OUTPUT (f)->white_relief.pixel = -1; + FRAME_X_OUTPUT (f)->black_relief.pixel = -1; - FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider = gtk_css_provider_new(); - FRAME_X_OUTPUT(f)->scrollbar_background_css_provider = gtk_css_provider_new(); + FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider = + gtk_css_provider_new (); + FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = + gtk_css_provider_new (); fset_icon_name (f, - gui_display_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", - RES_TYPE_STRING)); - if (! STRINGP (f->icon_name)) + gui_display_get_arg (dpyinfo, parms, Qicon_name, "iconName", + "Title", RES_TYPE_STRING)); + if (!STRINGP (f->icon_name)) fset_icon_name (f, Qnil); FRAME_DISPLAY_INFO (f) = dpyinfo; @@ -1152,36 +1185,36 @@ This function is an internal primitive--use `make-frame' instead. */) to free colors we haven't allocated. */ FRAME_FOREGROUND_PIXEL (f) = -1; FRAME_BACKGROUND_PIXEL (f) = -1; - FRAME_X_OUTPUT(f)->cursor_color = -1; - FRAME_X_OUTPUT(f)->cursor_foreground_color = -1; - FRAME_X_OUTPUT(f)->border_pixel = -1; - FRAME_X_OUTPUT(f)->mouse_color = -1; + FRAME_X_OUTPUT (f)->cursor_color = -1; + FRAME_X_OUTPUT (f)->cursor_foreground_color = -1; + FRAME_X_OUTPUT (f)->border_pixel = -1; + FRAME_X_OUTPUT (f)->mouse_color = -1; black = build_string ("black"); FRAME_FOREGROUND_PIXEL (f) = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); FRAME_BACKGROUND_PIXEL (f) = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->cursor_color + FRAME_X_OUTPUT (f)->cursor_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->cursor_foreground_color + FRAME_X_OUTPUT (f)->cursor_foreground_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->border_pixel + FRAME_X_OUTPUT (f)->border_pixel = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->mouse_color + FRAME_X_OUTPUT (f)->mouse_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); } /* Specify the parent under which to make this X window. */ if (!NILP (parent)) { - FRAME_X_OUTPUT(f)->parent_desc = (Window) XFIXNAT (parent); - FRAME_X_OUTPUT(f)->explicit_parent = true; + FRAME_X_OUTPUT (f)->parent_desc = (Window) XFIXNAT (parent); + FRAME_X_OUTPUT (f)->explicit_parent = true; } else { - FRAME_X_OUTPUT(f)->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; - FRAME_X_OUTPUT(f)->explicit_parent = false; + FRAME_X_OUTPUT (f)->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; + FRAME_X_OUTPUT (f)->explicit_parent = false; } /* Set the name; the functions to which we pass f expect the name to @@ -1210,7 +1243,7 @@ This function is an internal primitive--use `make-frame' instead. */) #endif gui_default_parameter (f, parms, Qfont_backend, Qnil, - "fontBackend", "FontBackend", RES_TYPE_STRING); + "fontBackend", "FontBackend", RES_TYPE_STRING); /* Extract the window parameters from the supplied values that are needed to determine window geometry. */ @@ -1223,10 +1256,10 @@ This function is an internal primitive--use `make-frame' instead. */) /* Frame contents get displaced if an embedded X window has a border. */ #if 0 - if (! FRAME_X_EMBEDDED_P (f)) + if (!FRAME_X_EMBEDDED_P (f)) #endif gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), - "borderWidth", "BorderWidth", RES_TYPE_NUMBER); + "borderWidth", "BorderWidth", RES_TYPE_NUMBER); /* This defaults to 1 in order to match xterm. We recognize either internalBorderWidth or internalBorder (which is what xterm calls @@ -1236,50 +1269,51 @@ This function is an internal primitive--use `make-frame' instead. */) Lisp_Object value; value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, - "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) - parms = Fcons (Fcons (Qinternal_border_width, value), - parms); + "internalBorder", "internalBorder", + RES_TYPE_NUMBER); + if (!EQ (value, Qunbound)) + parms = Fcons (Fcons (Qinternal_border_width, value), parms); } gui_default_parameter (f, parms, Qinternal_border_width, - make_fixnum (0), - "internalBorderWidth", "internalBorderWidth", - RES_TYPE_NUMBER); + make_fixnum (0), + "internalBorderWidth", "internalBorderWidth", + RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), - NULL, NULL, RES_TYPE_NUMBER); + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), - NULL, NULL, RES_TYPE_NUMBER); + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qvertical_scroll_bars, - Qright, - "verticalScrollBars", "ScrollBars", - RES_TYPE_SYMBOL); + Qright, + "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, - "horizontalScrollBars", "ScrollBars", - RES_TYPE_SYMBOL); + "horizontalScrollBars", "ScrollBars", + RES_TYPE_SYMBOL); /* Also do the stuff which must be set before the window exists. */ gui_default_parameter (f, parms, Qforeground_color, build_string ("black"), - "foreground", "Foreground", RES_TYPE_STRING); + "foreground", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), - "background", "Background", RES_TYPE_STRING); + "background", "Background", RES_TYPE_STRING); gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), - "pointerColor", "Foreground", RES_TYPE_STRING); + "pointerColor", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qborder_color, build_string ("black"), - "borderColor", "BorderColor", RES_TYPE_STRING); + "borderColor", "BorderColor", RES_TYPE_STRING); gui_default_parameter (f, parms, Qscreen_gamma, Qnil, - "screenGamma", "ScreenGamma", RES_TYPE_FLOAT); + "screenGamma", "ScreenGamma", RES_TYPE_FLOAT); gui_default_parameter (f, parms, Qline_spacing, Qnil, - "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); + "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qleft_fringe, Qnil, - "leftFringe", "LeftFringe", RES_TYPE_NUMBER); + "leftFringe", "LeftFringe", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qright_fringe, Qnil, - "rightFringe", "RightFringe", RES_TYPE_NUMBER); + "rightFringe", "RightFringe", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); + NULL, NULL, RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qscroll_bar_foreground, Qnil, - "scrollBarForeground", "ScrollBarForeground", RES_TYPE_STRING); + "scrollBarForeground", "ScrollBarForeground", + RES_TYPE_STRING); gui_default_parameter (f, parms, Qscroll_bar_background, Qnil, - "scrollBarBackground", "ScrollBarBackground", RES_TYPE_STRING); + "scrollBarBackground", "ScrollBarBackground", + RES_TYPE_STRING); /* Init faces before gui_default_parameter is called for the scroll-bar-width parameter because otherwise we end up in @@ -1298,10 +1332,14 @@ This function is an internal primitive--use `make-frame' instead. */) Also process `min-width' and `min-height' parameters right here because `frame-windows-min-size' needs them. */ - tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER); + tem = + gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, + RES_TYPE_NUMBER); if (NUMBERP (tem)) store_frame_param (f, Qmin_width, tem); - tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER); + tem = + gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, + RES_TYPE_NUMBER); if (NUMBERP (tem)) store_frame_param (f, Qmin_height, tem); adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), @@ -1314,35 +1352,38 @@ This function is an internal primitive--use `make-frame' instead. */) the values of the mode variables. */ gui_default_parameter (f, parms, Qmenu_bar_lines, - NILP (Vmenu_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); + NILP (Vmenu_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qtab_bar_lines, - NILP (Vtab_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); + NILP (Vtab_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qtool_bar_lines, - NILP (Vtool_bar_mode) - ? make_fixnum (0) : make_fixnum (1), - NULL, NULL, RES_TYPE_NUMBER); + NILP (Vtool_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, - "bufferPredicate", "BufferPredicate", - RES_TYPE_SYMBOL); + "bufferPredicate", "BufferPredicate", + RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qtitle, Qnil, - "title", "Title", RES_TYPE_STRING); + "title", "Title", RES_TYPE_STRING); gui_default_parameter (f, parms, Qwait_for_wm, Qt, - "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); + "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qtool_bar_position, - FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); + FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, - "inhibitDoubleBuffering", "InhibitDoubleBuffering", - RES_TYPE_BOOLEAN); + "inhibitDoubleBuffering", "InhibitDoubleBuffering", + RES_TYPE_BOOLEAN); /* Compute the size of the X window. */ - window_prompting = gui_figure_window_size (f, parms, true, true, &x_width, &x_height); + window_prompting = + gui_figure_window_size (f, parms, true, true, &x_width, &x_height); - tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); + tem = + gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, + RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || EQ (tem, Qt); #if 0 @@ -1352,27 +1393,27 @@ This function is an internal primitive--use `make-frame' instead. */) /* Create the X widget or window. */ // x_window (f); xg_create_frame_widgets (f); - pgtk_set_event_handler(f); + pgtk_set_event_handler (f); #define INSTALL_CURSOR(FIELD, NAME) \ FRAME_X_OUTPUT(f)->FIELD = gdk_cursor_new_for_display(FRAME_X_DISPLAY(f), GDK_ ## NAME) - INSTALL_CURSOR(text_cursor, XTERM); - INSTALL_CURSOR(nontext_cursor, LEFT_PTR); - INSTALL_CURSOR(modeline_cursor, XTERM); - INSTALL_CURSOR(hand_cursor, HAND2); - INSTALL_CURSOR(hourglass_cursor, WATCH); - INSTALL_CURSOR(horizontal_drag_cursor, SB_H_DOUBLE_ARROW); - INSTALL_CURSOR(vertical_drag_cursor, SB_V_DOUBLE_ARROW); - INSTALL_CURSOR(left_edge_cursor, LEFT_SIDE); - INSTALL_CURSOR(right_edge_cursor, RIGHT_SIDE); - INSTALL_CURSOR(top_edge_cursor, TOP_SIDE); - INSTALL_CURSOR(bottom_edge_cursor, BOTTOM_SIDE); - INSTALL_CURSOR(top_left_corner_cursor, TOP_LEFT_CORNER); - INSTALL_CURSOR(top_right_corner_cursor, TOP_RIGHT_CORNER); - INSTALL_CURSOR(bottom_right_corner_cursor, BOTTOM_RIGHT_CORNER); - INSTALL_CURSOR(bottom_left_corner_cursor, BOTTOM_LEFT_CORNER); + INSTALL_CURSOR (text_cursor, XTERM); + INSTALL_CURSOR (nontext_cursor, LEFT_PTR); + INSTALL_CURSOR (modeline_cursor, XTERM); + INSTALL_CURSOR (hand_cursor, HAND2); + INSTALL_CURSOR (hourglass_cursor, WATCH); + INSTALL_CURSOR (horizontal_drag_cursor, SB_H_DOUBLE_ARROW); + INSTALL_CURSOR (vertical_drag_cursor, SB_V_DOUBLE_ARROW); + INSTALL_CURSOR (left_edge_cursor, LEFT_SIDE); + INSTALL_CURSOR (right_edge_cursor, RIGHT_SIDE); + INSTALL_CURSOR (top_edge_cursor, TOP_SIDE); + INSTALL_CURSOR (bottom_edge_cursor, BOTTOM_SIDE); + INSTALL_CURSOR (top_left_corner_cursor, TOP_LEFT_CORNER); + INSTALL_CURSOR (top_right_corner_cursor, TOP_RIGHT_CORNER); + INSTALL_CURSOR (bottom_right_corner_cursor, BOTTOM_RIGHT_CORNER); + INSTALL_CURSOR (bottom_left_corner_cursor, BOTTOM_LEFT_CORNER); #undef INSTALL_CURSOR @@ -1389,22 +1430,21 @@ This function is an internal primitive--use `make-frame' instead. */) /* We need to do this after creating the X window, so that the icon-creation functions can say whose icon they're describing. */ gui_default_parameter (f, parms, Qicon_type, Qt, - "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN); + "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qauto_raise, Qnil, - "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); + "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qauto_lower, Qnil, - "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); + "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qcursor_type, Qbox, - "cursorType", "CursorType", RES_TYPE_SYMBOL); + "cursorType", "CursorType", RES_TYPE_SYMBOL); gui_default_parameter (f, parms, Qscroll_bar_width, Qnil, - "scrollBarWidth", "ScrollBarWidth", - RES_TYPE_NUMBER); + "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qscroll_bar_height, Qnil, - "scrollBarHeight", "ScrollBarHeight", - RES_TYPE_NUMBER); + "scrollBarHeight", "ScrollBarHeight", + RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qalpha, Qnil, - "alpha", "Alpha", RES_TYPE_NUMBER); + "alpha", "Alpha", RES_TYPE_NUMBER); if (!NILP (parent_frame)) { @@ -1412,28 +1452,28 @@ This function is an internal primitive--use `make-frame' instead. */) block_input (); PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); - gtk_window_set_transient_for(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), - GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(p))); - gtk_window_set_attached_to(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), - FRAME_GTK_WIDGET(p)); - gtk_window_set_destroy_with_parent(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), - TRUE); - gtk_widget_show_all(FRAME_GTK_OUTER_WIDGET(f)); + gtk_window_set_transient_for (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (p))); + gtk_window_set_attached_to (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FRAME_GTK_WIDGET (p)); + gtk_window_set_destroy_with_parent (GTK_WINDOW + (FRAME_GTK_OUTER_WIDGET (f)), TRUE); + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); unblock_input (); } - gtk_widget_show_all(FRAME_GTK_OUTER_WIDGET(f)); + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); + NULL, NULL, RES_TYPE_BOOLEAN); gui_default_parameter (f, parms, Qno_accept_focus, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); + NULL, NULL, RES_TYPE_BOOLEAN); /* Create the menu bar. */ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) { /* If this signals an error, we haven't set size hints for the - frame and we didn't make it visible. */ + frame and we didn't make it visible. */ initialize_frame_menubar (f); } @@ -1460,15 +1500,17 @@ This function is an internal primitive--use `make-frame' instead. */) fullheight/fullwidth frame will produce the size set by the last adjust_frame_size call. */ gui_default_parameter (f, parms, Qfullscreen, Qnil, - "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); /* Make the window appear on the frame and enable display, unless the caller says not to. However, with explicit parent, Emacs cannot control visibility, so don't try. */ - if (!FRAME_X_OUTPUT(f)->explicit_parent) + if (!FRAME_X_OUTPUT (f)->explicit_parent) { Lisp_Object visibility - = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); + = + gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, + RES_TYPE_SYMBOL); if (EQ (visibility, Qicon)) pgtk_iconify_frame (f); @@ -1486,16 +1528,16 @@ This function is an internal primitive--use `make-frame' instead. */) /* Works iff frame has been already mapped. */ gui_default_parameter (f, parms, Qskip_taskbar, Qnil, - NULL, NULL, RES_TYPE_BOOLEAN); + NULL, NULL, RES_TYPE_BOOLEAN); /* The `z-group' parameter works only for visible frames. */ gui_default_parameter (f, parms, Qz_group, Qnil, - NULL, NULL, RES_TYPE_SYMBOL); + NULL, NULL, RES_TYPE_SYMBOL); /* Initialize `default-minibuffer-frame' in case this is the first frame on this terminal. */ if (FRAME_HAS_MINIBUF_P (f) && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) - || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) + || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) kset_default_minibuffer_frame (kb, frame); /* All remaining specified parameters, which have not been "used" @@ -1504,22 +1546,22 @@ This function is an internal primitive--use `make-frame' instead. */) if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) fset_param_alist (f, Fcons (XCAR (tem), f->param_alist)); - FRAME_X_OUTPUT(f)->border_color_css_provider = NULL; + FRAME_X_OUTPUT (f)->border_color_css_provider = NULL; - FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; - FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL; + FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; /* Make sure windows on this frame appear in calls to next-window and similar functions. */ Vwindow_list = Qnil; - return unbind_to (count, frame); + return unbind_to (count, frame); } #if 0 static int -pgtk_window_is_ancestor (PGTKWindow *win, PGTKWindow *candidate) +pgtk_window_is_ancestor (PGTKWindow * win, PGTKWindow * candidate) /* Test whether CANDIDATE is an ancestor window of WIN. */ { if (candidate == NULL) @@ -1527,7 +1569,7 @@ pgtk_window_is_ancestor (PGTKWindow *win, PGTKWindow *candidate) else if (win == candidate) return 1; else - return pgtk_window_is_ancestor(win, [candidate parentWindow]); + return pgtk_window_is_ancestor (win,[candidate parentWindow]); } #endif @@ -1564,12 +1606,12 @@ that of FRAME2. Hence the position of FRAME2 in its display's Z unaltered. Some window managers may refuse to restack windows. */) - (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above) + (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above) { struct frame *f1 = decode_live_frame (frame1); struct frame *f2 = decode_live_frame (frame2); - if (! (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))) + if (!(FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))) error ("Cannot restack frames"); pgtk_frame_restack (f1, f2, !NILP (above)); return Qt; @@ -1620,59 +1662,67 @@ parse_resource_key (const char *res_key, char *setting_key) */ /* generate path */ - if (pgtk_is_upper_char(*sp)) { - /* First letter is upper case. It should be "Emacs", - * but don't care. - */ - strcpy (path, PATH_FOR_CLASS_TYPE); - while (*sp != '\0') { - if (*sp == '.') - break; - sp++; + if (pgtk_is_upper_char (*sp)) + { + /* First letter is upper case. It should be "Emacs", + * but don't care. + */ + strcpy (path, PATH_FOR_CLASS_TYPE); + while (*sp != '\0') + { + if (*sp == '.') + break; + sp++; + } + } + else + { + strcpy (path, PATH_PREFIX_FOR_NAME_TYPE); + dp = path + strlen (path); + while (*sp != '\0') + { + int c = *sp; + if (c == '.') + break; + if (pgtk_is_lower_char (c)) + (void) 0; /* lower -> NOP */ + else if (pgtk_is_upper_char (c)) + c = c - 'A' + 'a'; /* upper -> lower */ + else if (pgtk_is_numeric_char (c)) + (void) 0; /* numeric -> NOP */ + else + return NULL; /* invalid */ + *dp++ = c; + sp++; + } + *dp++ = '/'; /* must ends with '/' */ + *dp = '\0'; } - } else { - strcpy (path, PATH_PREFIX_FOR_NAME_TYPE); - dp = path + strlen (path); - while (*sp != '\0') { + + if (*sp++ != '.') + return NULL; + + /* generate setting_key */ + dp = setting_key; + while (*sp != '\0') + { int c = *sp; - if (c == '.') - break; if (pgtk_is_lower_char (c)) (void) 0; /* lower -> NOP */ else if (pgtk_is_upper_char (c)) - c = c - 'A' + 'a'; /* upper -> lower */ + { + c = c - 'A' + 'a'; /* upper -> lower */ + if (dp != setting_key) + *dp++ = '-'; /* store '-' unless first char */ + } else if (pgtk_is_numeric_char (c)) (void) 0; /* numeric -> NOP */ else return NULL; /* invalid */ + *dp++ = c; sp++; } - *dp++ = '/'; /* must ends with '/' */ - *dp = '\0'; - } - - if (*sp++ != '.') - return NULL; - - /* generate setting_key */ - dp = setting_key; - while (*sp != '\0') { - int c = *sp; - if (pgtk_is_lower_char (c)) - (void) 0; /* lower -> NOP */ - else if (pgtk_is_upper_char (c)) { - c = c - 'A' + 'a'; /* upper -> lower */ - if (dp != setting_key) - *dp++ = '-'; /* store '-' unless first char */ - } else if (pgtk_is_numeric_char (c)) - (void) 0; /* numeric -> NOP */ - else - return NULL; /* invalid */ - - *dp++ = c; - sp++; - } *dp = '\0'; /* check existence of setting_key */ @@ -1698,10 +1748,11 @@ pgtk_get_defaults_value (const char *key) if (strlen (key) >= RESOURCE_KEY_MAX_LEN) error ("resource key too long."); - GSettings *gs = parse_resource_key(key, skey); - if (gs == NULL) { - return NULL; - } + GSettings *gs = parse_resource_key (key, skey); + if (gs == NULL) + { + return NULL; + } gchar *str = g_settings_get_string (gs, skey); @@ -1727,15 +1778,18 @@ pgtk_set_defaults_value (const char *key, const char *value) if (strlen (key) >= RESOURCE_KEY_MAX_LEN) error ("resource key too long."); - GSettings *gs = parse_resource_key(key, skey); - if (gs == NULL) { + GSettings *gs = parse_resource_key (key, skey); + if (gs == NULL) error ("unknown resource key."); - } - if (value != NULL) { - g_settings_set_string (gs, skey, value); - } else { - g_settings_reset (gs, skey); - } + + if (value != NULL) + { + g_settings_set_string (gs, skey, value); + } + else + { + g_settings_reset (gs, skey); + } g_object_unref (gs); } @@ -1763,8 +1817,8 @@ pgtk_set_defaults_value (const char *key, const char *value) DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 2, 2, 0, - doc: /* Set the value of ATTRIBUTE, of class CLASS, as VALUE, into defaults database. */) - (Lisp_Object attribute, Lisp_Object value) + doc: /* Set the value of ATTRIBUTE, of class CLASS, as VALUE, into defaults database. */ ) + (Lisp_Object attribute, Lisp_Object value) { check_window_system (NULL); @@ -1777,19 +1831,17 @@ DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 2, 2, 0, if (attr[0] >= 'A' && attr[0] <= 'Z') res = SSDATA (Vx_resource_class); - char *key = g_strdup_printf("%s.%s", res, attr); + char *key = g_strdup_printf ("%s.%s", res, attr); - pgtk_set_defaults_value(key, NILP (value) ? NULL : SSDATA (value)); + pgtk_set_defaults_value (key, NILP (value) ? NULL : SSDATA (value)); return Qnil; } -DEFUN ("x-server-max-request-size", Fx_server_max_request_size, - Sx_server_max_request_size, - 0, 1, 0, - doc: /* This function is a no-op. It is only present for completeness. */) - (Lisp_Object terminal) +DEFUN ("x-server-max-request-size", Fx_server_max_request_size, Sx_server_max_request_size, 0, 1, 0, + doc: /* This function is a no-op. It is only present for completeness. */ ) + (Lisp_Object terminal) { check_pgtk_display_info (terminal); /* This function has no real equivalent under PGTK. Return nil to @@ -1820,16 +1872,16 @@ number. See also the function `x-server-vendor'. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). -If omitted or nil, that stands for the selected frame's display. */) +If omitted or nil, that stands for the selected frame's display. */ ) (Lisp_Object terminal) { check_pgtk_display_info (terminal); /*NOTE: it is unclear what would best correspond with "protocol"; - we return 10.3, meaning Panther, since this is roughly the - level that GNUstep's APIs correspond to. - The last number is where we distinguish between the Apple - and GNUstep implementations ("distributor-specific release - number") and give int'ized versions of major.minor. */ + we return 10.3, meaning Panther, since this is roughly the + level that GNUstep's APIs correspond to. + The last number is where we distinguish between the Apple + and GNUstep implementations ("distributor-specific release + number") and give int'ized versions of major.minor. */ return list3i (0, 0, 0); } @@ -1841,7 +1893,7 @@ TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. Note: "screen" here is not in X11's. For the number of physical monitors, - use `(length \(display-monitor-attributes-list TERMINAL))' instead. */) +use `(length \(display-monitor-attributes-list TERMINAL))' instead. */) (Lisp_Object terminal) { check_pgtk_display_info (terminal); @@ -1862,8 +1914,8 @@ for each physical monitor, use `display-monitor-attributes-list'. */) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor *gmon = gdk_display_get_monitor_at_point(gdpy, 0, 0); - return make_fixnum (gdk_monitor_get_height_mm(gmon)); + GdkMonitor *gmon = gdk_display_get_monitor_at_point (gdpy, 0, 0); + return make_fixnum (gdk_monitor_get_height_mm (gmon)); } @@ -1880,13 +1932,12 @@ for each physical monitor, use `display-monitor-attributes-list'. */) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); GdkDisplay *gdpy = dpyinfo->gdpy; - GdkMonitor *gmon = gdk_display_get_monitor_at_point(gdpy, 0, 0); - return make_fixnum (gdk_monitor_get_width_mm(gmon)); + GdkMonitor *gmon = gdk_display_get_monitor_at_point (gdpy, 0, 0); + return make_fixnum (gdk_monitor_get_width_mm (gmon)); } -DEFUN ("x-display-backing-store", Fx_display_backing_store, - Sx_display_backing_store, 0, 1, 0, +DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store, 0, 1, 0, doc: /* Return an indication of whether the the display TERMINAL does backing store. The value may be `buffered', `retained', or `non-retained'. The optional argument TERMINAL specifies which display to ask about. @@ -1899,8 +1950,7 @@ If omitted or nil, that stands for the selected frame's display. */) } -DEFUN ("x-display-visual-class", Fx_display_visual_class, - Sx_display_visual_class, 0, 1, 0, +DEFUN ("x-display-visual-class", Fx_display_visual_class, Sx_display_visual_class, 0, 1, 0, doc: /* Return the visual class of the the display TERMINAL. The value is one of the symbols `static-gray', `gray-scale', `static-color', `pseudo-color', `true-color', or `direct-color'. @@ -1916,8 +1966,7 @@ On PGTK, always return true-color. */) } -DEFUN ("x-display-save-under", Fx_display_save_under, - Sx_display_save_under, 0, 1, 0, +DEFUN ("x-display-save-under", Fx_display_save_under, Sx_display_save_under, 0, 1, 0, doc: /* Return t if TERMINAL supports the save-under feature. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -1929,45 +1978,41 @@ If omitted or nil, that stands for the selected frame's display. */) } -DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, - 1, 3, 0, +DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, 1, 3, 0, doc: /* Open a connection to a display server. DISPLAY is the name of the display to connect to. Optional second arg XRM-STRING is a string of resources in xrdb format. If the optional third arg MUST-SUCCEED is non-nil, terminate Emacs if we can't open the connection. */) - (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed) + (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed) { struct pgtk_display_info *dpyinfo; - if (NILP(display)) - display = build_string(""); + if (NILP (display)) + display = build_string (""); CHECK_STRING (display); nxatoms_of_pgtkselect (); - dpyinfo = pgtk_term_init (display, SSDATA(Vx_resource_name)); + dpyinfo = pgtk_term_init (display, SSDATA (Vx_resource_name)); if (dpyinfo == 0) { if (!NILP (must_succeed)) - fatal ("Display on %s not responding.\n", - SSDATA (display)); + fatal ("Display on %s not responding.\n", SSDATA (display)); else - error ("Display on %s not responding.\n", - SSDATA (display)); + error ("Display on %s not responding.\n", SSDATA (display)); } return Qnil; } -DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, - 1, 1, 0, +DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, 1, 1, 0, doc: /* Close the connection to TERMINAL's display server. For TERMINAL, specify a terminal object, a frame or a display name (a string). If TERMINAL is nil, that stands for the selected frame's terminal. */) - (Lisp_Object terminal) + (Lisp_Object terminal) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); @@ -1982,7 +2027,7 @@ terminal. */) DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, doc: /* Return the list of display names that Emacs has connections to. */) - (void) + (void) { Lisp_Object result = Qnil; struct pgtk_display_info *ndi; @@ -1994,22 +2039,20 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, } -DEFUN ("pgtk-hide-others", Fpgtk_hide_others, Spgtk_hide_others, - 0, 0, 0, +DEFUN ("pgtk-hide-others", Fpgtk_hide_others, Spgtk_hide_others, 0, 0, 0, doc: /* Hides all applications other than Emacs. */) - (void) + (void) { check_window_system (NULL); return Qnil; } -DEFUN ("pgtk-hide-emacs", Fpgtk_hide_emacs, Spgtk_hide_emacs, - 1, 1, 0, +DEFUN ("pgtk-hide-emacs", Fpgtk_hide_emacs, Spgtk_hide_emacs, 1, 1, 0, doc: /* If ON is non-nil, the entire Emacs application is hidden. Otherwise if Emacs is hidden, it is unhidden. If ON is equal to `activate', Emacs is unhidden and becomes the active application. */) - (Lisp_Object on) + (Lisp_Object on) { check_window_system (NULL); return Qnil; @@ -2021,7 +2064,7 @@ DEFUN ("pgtk-font-name", Fpgtk_font_name, Spgtk_font_name, 1, 1, 0, NAME should be a string containing either the font name or an XLFD font descriptor. If string contains `fontset' and not `fontset-startup', it is left alone. */) - (Lisp_Object name) + (Lisp_Object name) { char *nm; CHECK_STRING (name); @@ -2034,7 +2077,7 @@ font descriptor. If string contains `fontset' and not char *str = pgtk_xlfd_to_fontname (SSDATA (name)); name = build_string (str); - xfree(str); + xfree (str); return name; } @@ -2074,7 +2117,8 @@ pgtk_set_scroll_bar_default_height (struct frame *f) /* terms impl this instead of x-get-resource directly */ const char * -pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class) +pgtk_get_string_resource (XrmDatabase rdb, const char *name, + const char *class) { check_window_system (NULL); @@ -2121,7 +2165,7 @@ x_get_focus_frame (struct frame *frame) DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, doc: /* Internal function called by `color-defined-p', which see. */) - (Lisp_Object color, Lisp_Object frame) + (Lisp_Object color, Lisp_Object frame) { Emacs_Color col; struct frame *f = decode_window_system_frame (frame); @@ -2137,7 +2181,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, doc: /* Internal function called by `color-values', which see. */) - (Lisp_Object color, Lisp_Object frame) + (Lisp_Object color, Lisp_Object frame) { Emacs_Color col; struct frame *f = decode_window_system_frame (frame); @@ -2153,15 +2197,14 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, doc: /* Internal function called by `display-color-p', which see. */) - (Lisp_Object terminal) + (Lisp_Object terminal) { check_pgtk_display_info (terminal); return Qt; } -DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, - 0, 1, 0, +DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, 0, 1, 0, doc: /* Return t if the display supports shades of gray. Note that color displays do support shades of gray. The optional argument TERMINAL specifies which display to ask about. @@ -2173,8 +2216,7 @@ If omitted or nil, that stands for the selected frame's display. */) } -DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, - 0, 1, 0, +DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, 0, 1, 0, doc: /* Return the width in pixels of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2191,8 +2233,7 @@ each physical monitor, use `display-monitor-attributes-list'. */) } -DEFUN ("x-display-pixel-height", Fx_display_pixel_height, - Sx_display_pixel_height, 0, 1, 0, +DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_height, 0, 1, 0, doc: /* Return the height in pixels of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2208,10 +2249,7 @@ each physical monitor, use `display-monitor-attributes-list'. */) return make_fixnum (x_display_pixel_height (dpyinfo)); } -DEFUN ("pgtk-display-monitor-attributes-list", - Fpgtk_display_monitor_attributes_list, - Spgtk_display_monitor_attributes_list, - 0, 1, 0, +DEFUN ("pgtk-display-monitor-attributes-list", Fpgtk_display_monitor_attributes_list, Spgtk_display_monitor_attributes_list, 0, 1, 0, doc: /* Return a list of physical monitor attributes on the X display TERMINAL. The optional argument TERMINAL specifies which display to ask about. @@ -2234,79 +2272,90 @@ Internal use only, use `display-monitor-attributes-list' instead. */) if (term->type != output_pgtk) return Qnil; - n_monitors = gdk_display_get_n_monitors(gdpy); + n_monitors = gdk_display_get_n_monitors (gdpy); if (n_monitors == 0) return Qnil; - gmons = xmalloc(sizeof *gmons * n_monitors); + gmons = xmalloc (sizeof *gmons * n_monitors); for (i = 0; i < n_monitors; i++) - gmons[i] = gdk_display_get_monitor(gdpy, i); + gmons[i] = gdk_display_get_monitor (gdpy, i); monitors = xzalloc (n_monitors * sizeof *monitors); - for (i = 0; i < n_monitors; i++) { - struct MonitorInfo *mon = &monitors[i]; - GdkMonitor *gmon = gmons[i]; - if (gmon != NULL) { - GdkRectangle geom; - gdk_monitor_get_geometry(gmon, &geom); - mon->geom.x = geom.x; - mon->geom.y = geom.y; - mon->geom.width = geom.width; - mon->geom.height = geom.height; - - gdk_monitor_get_workarea(gmon, &geom); - mon->work.x = geom.x; - mon->work.y = geom.y; - mon->work.width = geom.width; - mon->work.height = geom.height; - - mon->mm_width = gdk_monitor_get_width_mm(gmon); - mon->mm_height = gdk_monitor_get_height_mm(gmon); - - mon->name = xstrdup(gdk_monitor_get_model(gmon)); + for (i = 0; i < n_monitors; i++) + { + struct MonitorInfo *mon = &monitors[i]; + GdkMonitor *gmon = gmons[i]; + if (gmon != NULL) + { + GdkRectangle geom; + gdk_monitor_get_geometry (gmon, &geom); + mon->geom.x = geom.x; + mon->geom.y = geom.y; + mon->geom.width = geom.width; + mon->geom.height = geom.height; + + gdk_monitor_get_workarea (gmon, &geom); + mon->work.x = geom.x; + mon->work.y = geom.y; + mon->work.width = geom.width; + mon->work.height = geom.height; + + mon->mm_width = gdk_monitor_get_width_mm (gmon); + mon->mm_height = gdk_monitor_get_height_mm (gmon); + + mon->name = xstrdup (gdk_monitor_get_model (gmon)); + } } - } monitor_frames = Fmake_vector (make_fixnum (n_monitors), Qnil); FOR_EACH_FRAME (rest, frame) - { - struct frame *f = XFRAME (frame); + { + struct frame *f = XFRAME (frame); - if (FRAME_PGTK_P (f)) - { - GtkWidget *widget = FRAME_GTK_WIDGET(f); - GdkMonitor *gmon = gdk_display_get_monitor_at_window(gdpy, gtk_widget_get_window(widget)); - - if (gmon != NULL) { - for (i = 0; i < n_monitors; i++) { - if (gmons[i] == gmon) { - ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); - break; + if (FRAME_PGTK_P (f)) + { + GtkWidget *widget = FRAME_GTK_WIDGET (f); + GdkMonitor *gmon = + gdk_display_get_monitor_at_window (gdpy, + gtk_widget_get_window (widget)); + + if (gmon != NULL) + { + for (i = 0; i < n_monitors; i++) + { + if (gmons[i] == gmon) + { + ASET (monitor_frames, i, + Fcons (frame, AREF (monitor_frames, i))); + break; + } } - } } - } - } + } + } primary_index = -1; - for (i = 0; i < n_monitors; i++) { - if (gmons[i] != NULL && gdk_monitor_is_primary(gmons[i])) { - primary_index = i; - break; + for (i = 0; i < n_monitors; i++) + { + if (gmons[i] != NULL && gdk_monitor_is_primary (gmons[i])) + { + primary_index = i; + break; + } } - } - rv = make_monitor_attribute_list(monitors, n_monitors, primary_index, monitor_frames, "Gdk"); + rv = + make_monitor_attribute_list (monitors, n_monitors, primary_index, + monitor_frames, "Gdk"); - free_monitors(monitors, n_monitors); - xfree(gmons); + free_monitors (monitors, n_monitors); + xfree (gmons); return rv; } -DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, - 0, 1, 0, +DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, 0, 1, 0, doc: /* Return the number of bitplanes of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2314,12 +2363,11 @@ If omitted or nil, that stands for the selected frame's display. */) (Lisp_Object terminal) { check_pgtk_display_info (terminal); - return make_fixnum(32); + return make_fixnum (32); } -DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, - 0, 1, 0, +DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, 0, 1, 0, doc: /* Returns the number of color cells of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2351,14 +2399,16 @@ static Lisp_Object tip_timer; the display in *ROOT_X, and *ROOT_Y. */ static void -compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y) +compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, + Lisp_Object dy, int width, int height, int *root_x, + int *root_y) { Lisp_Object left, top, right, bottom; int min_x, min_y, max_x, max_y = -1; /* User-specified position? */ left = Fcdr (Fassq (Qleft, parms)); - top = Fcdr (Fassq (Qtop, parms)); + top = Fcdr (Fassq (Qtop, parms)); right = Fcdr (Fassq (Qright, parms)); bottom = Fcdr (Fassq (Qbottom, parms)); @@ -2368,44 +2418,45 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object || (!INTEGERP (top) && !INTEGERP (bottom))) { Lisp_Object frame, attributes, monitor, geometry; - GdkSeat *seat = gdk_display_get_default_seat(FRAME_DISPLAY_INFO(f)->gdpy); - GdkDevice *dev = gdk_seat_get_pointer(seat); + GdkSeat *seat = + gdk_display_get_default_seat (FRAME_DISPLAY_INFO (f)->gdpy); + GdkDevice *dev = gdk_seat_get_pointer (seat); GdkScreen *scr; block_input (); - gdk_device_get_position(dev, &scr, root_x, root_y); + gdk_device_get_position (dev, &scr, root_x, root_y); unblock_input (); - XSETFRAME(frame, f); + XSETFRAME (frame, f); attributes = Fpgtk_display_monitor_attributes_list (frame); /* Try to determine the monitor where the mouse pointer is and its geometry. See bug#22549. */ while (CONSP (attributes)) { - monitor = XCAR (attributes); - geometry = Fassq (Qgeometry, monitor); - if (CONSP (geometry)) - { - min_x = XFIXNUM (Fnth (make_fixnum (1), geometry)); - min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); - max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); - max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); - if (min_x <= *root_x && *root_x < max_x - && min_y <= *root_y && *root_y < max_y) - { - break; - } - max_y = -1; - } - - attributes = XCDR (attributes); + monitor = XCAR (attributes); + geometry = Fassq (Qgeometry, monitor); + if (CONSP (geometry)) + { + min_x = XFIXNUM (Fnth (make_fixnum (1), geometry)); + min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); + max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); + max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); + if (min_x <= *root_x && *root_x < max_x + && min_y <= *root_y && *root_y < max_y) + { + break; + } + max_y = -1; + } + + attributes = XCDR (attributes); } } /* It was not possible to determine the monitor's geometry, so we assign some sane defaults here: */ - if ( max_y < 0 ) + if (max_y < 0) { min_x = 0; min_y = 0; @@ -2418,7 +2469,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object else if (INTEGERP (bottom)) *root_y = XFIXNUM (bottom) - height; else if (*root_y + XFIXNUM (dy) <= min_y) - *root_y = min_y; /* Can happen for negative dy */ + *root_y = min_y; /* Can happen for negative dy */ else if (*root_y + XFIXNUM (dy) + height <= max_y) /* It fits below the pointer */ *root_y += XFIXNUM (dy); @@ -2434,7 +2485,7 @@ compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object else if (INTEGERP (right)) *root_x = XFIXNUM (right) - width; else if (*root_x + XFIXNUM (dx) <= min_x) - *root_x = 0; /* Can happen for negative dx */ + *root_x = 0; /* Can happen for negative dx */ else if (*root_x + XFIXNUM (dx) + width <= max_x) /* It fits to the right of the pointer. */ *root_x += XFIXNUM (dx); @@ -2531,7 +2582,8 @@ with offset DY added (default is -10). A tooltip's maximum size is specified by `x-max-tooltip-size'. Text larger than the specified size is clipped. */) - (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, + Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) { struct frame *f; int root_x, root_y; @@ -2576,10 +2628,11 @@ Text larger than the specified size is clipped. */) XSETFRAME (tip_frame, f); } unblock_input (); - if (ok) goto start_timer; + if (ok) + goto start_timer; } - start_timer: +start_timer: /* Let the tip disappear after timeout seconds. */ tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, intern ("x-hide-tip")); @@ -2622,13 +2675,11 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) int tab_bar_height = 0, tab_bar_width = 0; int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f); int tool_bar_width = (tool_bar_height - ? outer_width - 2 * internal_border_width - : 0); + ? outer_width - 2 * internal_border_width : 0); tab_bar_height = FRAME_TAB_BAR_HEIGHT (f); tab_bar_width = (tab_bar_height - ? native_width - 2 * internal_border_width - : 0); + ? native_width - 2 * internal_border_width : 0); // inner_top += tab_bar_height; /* Construct list. */ @@ -2682,38 +2733,38 @@ value is an association list of the attributes listed below. All height and width values are in pixels. `outer-position' is a cons of the outer left and top edges of FRAME - relative to the origin - the position (0, 0) - of FRAME's display. +relative to the origin - the position (0, 0) - of FRAME's display. `outer-size' is a cons of the outer width and height of FRAME. The - outer size includes the title bar and the external borders as well as - any menu and/or tool bar of frame. +outer size includes the title bar and the external borders as well as +any menu and/or tool bar of frame. `external-border-size' is a cons of the horizontal and vertical width of - FRAME's external borders as supplied by the window manager. +FRAME's external borders as supplied by the window manager. `title-bar-size' is a cons of the width and height of the title bar of - FRAME as supplied by the window manager. If both of them are zero, - FRAME has no title bar. If only the width is zero, Emacs was not - able to retrieve the width information. +FRAME as supplied by the window manager. If both of them are zero, +FRAME has no title bar. If only the width is zero, Emacs was not +able to retrieve the width information. `menu-bar-external', if non-nil, means the menu bar is external (never - included in the inner edges of FRAME). +included in the inner edges of FRAME). `menu-bar-size' is a cons of the width and height of the menu bar of - FRAME. +FRAME. `tool-bar-external', if non-nil, means the tool bar is external (never - included in the inner edges of FRAME). +included in the inner edges of FRAME). `tool-bar-position' tells on which side the tool bar on FRAME is and can - be one of `left', `top', `right' or `bottom'. If this is nil, FRAME - has no tool bar. +be one of `left', `top', `right' or `bottom'. If this is nil, FRAME +has no tool bar. `tool-bar-size' is a cons of the width and height of the tool bar of - FRAME. +FRAME. `internal-border-width' is the width of the internal border of - FRAME. */) +FRAME. */) (Lisp_Object frame) { return frame_geometry (frame, Qnil); @@ -2739,60 +2790,55 @@ menu bar or tool bar of FRAME. */) { return frame_geometry (frame, ((EQ (type, Qouter_edges) || EQ (type, Qinner_edges)) - ? type - : Qnative_edges)); + ? type : Qnative_edges)); } -DEFUN ("pgtk-set-mouse-absolute-pixel-position", - Fpgtk_set_mouse_absolute_pixel_position, - Spgtk_set_mouse_absolute_pixel_position, 2, 2, 0, +DEFUN ("pgtk-set-mouse-absolute-pixel-position", Fpgtk_set_mouse_absolute_pixel_position, Spgtk_set_mouse_absolute_pixel_position, 2, 2, 0, doc: /* Move mouse pointer to absolute pixel position (X, Y). The coordinates X and Y are interpreted in pixels relative to a position \(0, 0) of the selected frame's display. */) - (Lisp_Object x, Lisp_Object y) + (Lisp_Object x, Lisp_Object y) { struct frame *f = SELECTED_FRAME (); - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); - GdkWindow *window = gtk_widget_get_window(widget); - GdkDisplay *gdpy = gdk_window_get_display(window); - GdkScreen *gscr = gdk_window_get_screen(window); - GdkSeat *seat = gdk_display_get_default_seat(gdpy); - GdkDevice *device = gdk_seat_get_pointer(seat); + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + GdkWindow *window = gtk_widget_get_window (widget); + GdkDisplay *gdpy = gdk_window_get_display (window); + GdkScreen *gscr = gdk_window_get_screen (window); + GdkSeat *seat = gdk_display_get_default_seat (gdpy); + GdkDevice *device = gdk_seat_get_pointer (seat); - PGTK_TRACE("pgtk-set-mouse-absolute-pixel-position:"); - gdk_device_warp(device, gscr, XFIXNUM(x), XFIXNUM(y)); /* No effect on wayland. */ + PGTK_TRACE ("pgtk-set-mouse-absolute-pixel-position:"); + gdk_device_warp (device, gscr, XFIXNUM (x), XFIXNUM (y)); /* No effect on wayland. */ return Qnil; } -DEFUN ("pgtk-mouse-absolute-pixel-position", - Fpgtk_mouse_absolute_pixel_position, - Spgtk_mouse_absolute_pixel_position, 0, 0, 0, +DEFUN ("pgtk-mouse-absolute-pixel-position", Fpgtk_mouse_absolute_pixel_position, Spgtk_mouse_absolute_pixel_position, 0, 0, 0, doc: /* Return absolute position of mouse cursor in pixels. The position is returned as a cons cell (X . Y) of the coordinates of the mouse cursor position in pixels relative to a position (0, 0) of the selected frame's terminal. */) - (void) + (void) { struct frame *f = SELECTED_FRAME (); - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); - GdkWindow *window = gtk_widget_get_window(widget); - GdkDisplay *gdpy = gdk_window_get_display(window); + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + GdkWindow *window = gtk_widget_get_window (widget); + GdkDisplay *gdpy = gdk_window_get_display (window); GdkScreen *gscr; - GdkSeat *seat = gdk_display_get_default_seat(gdpy); - GdkDevice *device = gdk_seat_get_pointer(seat); + GdkSeat *seat = gdk_display_get_default_seat (gdpy); + GdkDevice *device = gdk_seat_get_pointer (seat); int x = 0, y = 0; - gdk_device_get_position(device, &gscr, &x, &y); /* can't get on wayland? */ + gdk_device_get_position (device, &gscr, &x, &y); /* can't get on wayland? */ - return Fcons(make_fixnum(x), make_fixnum(y)); + return Fcons (make_fixnum (x), make_fixnum (y)); } DEFUN ("pgtk-page-setup-dialog", Fpgtk_page_setup_dialog, Spgtk_page_setup_dialog, 0, 0, 0, doc: /* Pop up a page setup dialog. The current page setup can be obtained using `x-get-page-setup'. */) - (void) + (void) { block_input (); xg_page_setup_dialog (); @@ -2805,12 +2851,12 @@ DEFUN ("pgtk-get-page-setup", Fpgtk_get_page_setup, Spgtk_get_page_setup, 0, 0, doc: /* Return the value of the current page setup. The return value is an alist containing the following keys: - orientation: page orientation (symbol `portrait', `landscape', - `reverse-portrait', or `reverse-landscape'). - width, height: page width/height in points not including margins. - left-margin, right-margin, top-margin, bottom-margin: print margins, - which is the parts of the page that the printer cannot print - on, in points. +orientation: page orientation (symbol `portrait', `landscape', +`reverse-portrait', or `reverse-landscape'). +width, height: page width/height in points not including margins. +left-margin, right-margin, top-margin, bottom-margin: print margins, +which is the parts of the page that the printer cannot print +on, in points. The paper width can be obtained as the sum of width, left-margin, and right-margin values if the page orientation is `portrait' or @@ -2819,7 +2865,7 @@ and bottom-margin values. Likewise, the paper height is the sum of height, top-margin, and bottom-margin values if the page orientation is `portrait' or `reverse-portrait'. Otherwise, it is the sum of height, left-margin, and right-margin values. */) - (void) + (void) { Lisp_Object result; @@ -2835,7 +2881,7 @@ DEFUN ("pgtk-print-frames-dialog", Fpgtk_print_frames_dialog, Spgtk_print_frames FRAMES should be nil (the selected frame), a frame, or a list of frames (each of which corresponds to one page). Each frame should be visible. */) - (Lisp_Object frames) + (Lisp_Object frames) { Lisp_Object rest, tmp; int count; @@ -2888,7 +2934,8 @@ On MS Windows 7 and later, the file selection dialog "remembers" the last directory where the user selected a file, and will open that directory instead of DIR on subsequent invocations of this function with the same value of DIR as in previous invocations; this is standard MS Windows behavior. */) - (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p) + (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, + Lisp_Object mustmatch, Lisp_Object only_dir_p) { struct frame *f = SELECTED_FRAME (); char *fn; @@ -2919,8 +2966,7 @@ value of DIR as in previous invocations; this is standard MS Windows behavior. cdef_file = SSDATA (dir); fn = xg_get_file_name (f, SSDATA (prompt), cdef_file, - ! NILP (mustmatch), - ! NILP (only_dir_p)); + !NILP (mustmatch), !NILP (only_dir_p)); if (fn) { @@ -2939,8 +2985,7 @@ value of DIR as in previous invocations; this is standard MS Windows behavior. return unbind_to (count, decoded_file); } -DEFUN ("pgtk-backend-display-class", Fpgtk_backend_display_class, Spgtk_backend_display_class, - 0, 1, "", +DEFUN ("pgtk-backend-display-class", Fpgtk_backend_display_class, Spgtk_backend_display_class, 0, 1, "", doc: /* Returns the name of the Gdk backend display class of the TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2949,8 +2994,8 @@ If omitted or nil, that stands for the selected frame's display. */) { struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); GdkDisplay *gdpy = dpyinfo->gdpy; - const gchar *type_name = G_OBJECT_TYPE_NAME(G_OBJECT(gdpy)); - return build_string(type_name); + const gchar *type_name = G_OBJECT_TYPE_NAME (G_OBJECT (gdpy)); + return build_string (type_name); } /* ========================================================================== @@ -2970,11 +3015,11 @@ syms_of_pgtkfns (void) DEFSYM (Qdark, "dark"); DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, - doc: /* A string indicating the foreground color of the cursor box. */); + doc: /* A string indicating the foreground color of the cursor box. */); Vx_cursor_fore_pixel = Qnil; DEFVAR_LISP ("pgtk-icon-type-alist", Vpgtk_icon_type_alist, - doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames. + doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames. If the title of a frame matches REGEXP, then IMAGE.tiff is selected as the image of the icon representing the frame when it's miniaturized. If an element is t, then Emacs tries to select an icon @@ -2985,10 +3030,10 @@ Emacs folder. You have to restart Emacs after installing new icons. Example: Install an icon Gnus.tiff and execute the following code - (setq pgtk-icon-type-alist - (append pgtk-icon-type-alist - \\='((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\" - . \"Gnus\")))) +(setq pgtk-icon-type-alist +(append pgtk-icon-type-alist +\\='((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\" +. \"Gnus\")))) When you miniaturize a Group, Summary or Article frame, Gnus.tiff will be used as the image of the icon representing the frame. */); @@ -3004,32 +3049,33 @@ be used as the image of the icon representing the frame. */); Fprovide (intern_c_string ("move-toolbar"), Qnil); DEFVAR_LISP ("gtk-version-string", Vgtk_version_string, - doc: /* Version info for GTK+. */); + doc: /* Version info for GTK+. */); { - char *ver = g_strdup_printf("%d.%d.%d", - GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); - int len = strlen(ver); + char *ver = g_strdup_printf ("%d.%d.%d", + GTK_MAJOR_VERSION, GTK_MINOR_VERSION, + GTK_MICRO_VERSION); + int len = strlen (ver); Vgtk_version_string = make_pure_string (ver, len, len, false); - g_free(ver); + g_free (ver); } Fprovide (intern_c_string ("cairo"), Qnil); DEFVAR_LISP ("cairo-version-string", Vcairo_version_string, - doc: /* Version info for cairo. */); + doc: /* Version info for cairo. */); { - char *ver = g_strdup_printf("%d.%d.%d", - CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR, - CAIRO_VERSION_MICRO); - int len = strlen(ver); + char *ver = g_strdup_printf ("%d.%d.%d", + CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR, + CAIRO_VERSION_MICRO); + int len = strlen (ver); Vcairo_version_string = make_pure_string (ver, len, len, false); - g_free(ver); + g_free (ver); } defsubr (&Spgtk_set_resource); - defsubr (&Sxw_display_color_p); /* this and next called directly by C code */ + defsubr (&Sxw_display_color_p); /* this and next called directly by C code */ defsubr (&Sx_display_grayscale_p); defsubr (&Spgtk_font_name); defsubr (&Sxw_color_defined_p); @@ -3077,32 +3123,32 @@ be used as the image of the icon representing the frame. */); as_result = 0; tip_frame = Qnil; - staticpro(&tip_frame); + staticpro (&tip_frame); tip_timer = Qnil; - staticpro(&tip_timer); + staticpro (&tip_timer); -/* This is not ifdef:ed, so other builds than GTK can customize it. */ + /* This is not ifdef:ed, so other builds than GTK can customize it. */ DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog, - doc: /* Non-nil means prompt with the old GTK file selection dialog. + doc: /* Non-nil means prompt with the old GTK file selection dialog. If nil or if the file selection dialog is not available, the new GTK file chooser is used instead. To turn off all file dialogs set the variable `use-file-dialog'. */); x_gtk_use_old_file_dialog = false; DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files, - doc: /* If non-nil, the GTK file chooser will by default show hidden files. + doc: /* If non-nil, the GTK file chooser will by default show hidden files. Note that this is just the default, there is a toggle button on the file chooser to show or not show hidden files on a case by case basis. */); x_gtk_show_hidden_files = false; DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text, - doc: /* If non-nil, the GTK file chooser will show additional help text. + doc: /* If non-nil, the GTK file chooser will show additional help text. If more space for files in the file chooser dialog is wanted, set this to nil to turn the additional text off. */); x_gtk_file_dialog_help_text = true; DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips, - doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. + doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. Otherwise use Emacs own tooltip implementation. When using Gtk+ tooltips, the tooltip face is not used. */); x_gtk_use_system_tooltips = true; @@ -3125,53 +3171,60 @@ When using Gtk+ tooltips, the tooltip face is not used. */); #ifdef PGTK_DEBUG #include #include -void pgtk_log(const char *file, int lineno, const char *fmt, ...) +void +pgtk_log (const char *file, int lineno, const char *fmt, ...) { struct timespec ts; struct tm tm; char timestr[32]; va_list ap; - clock_gettime(CLOCK_REALTIME, &ts); + clock_gettime (CLOCK_REALTIME, &ts); - localtime_r(&ts.tv_sec, &tm); - strftime(timestr, sizeof timestr, "%H:%M:%S", &tm); + localtime_r (&ts.tv_sec, &tm); + strftime (timestr, sizeof timestr, "%H:%M:%S", &tm); - fprintf(stderr, "%s.%06ld %.10s:%04d ", timestr, ts.tv_nsec / 1000, file, lineno); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); + fprintf (stderr, "%s.%06ld %.10s:%04d ", timestr, ts.tv_nsec / 1000, file, + lineno); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fputc ('\n', stderr); } -void pgtk_backtrace(const char *file, int lineno) +void +pgtk_backtrace (const char *file, int lineno) { - Lisp_Object bt = make_uninit_vector(10); + Lisp_Object bt = make_uninit_vector (10); for (int i = 0; i < 10; i++) - ASET(bt, i, Qnil); + ASET (bt, i, Qnil); struct timespec ts; struct tm tm; char timestr[32]; - clock_gettime(CLOCK_REALTIME, &ts); + clock_gettime (CLOCK_REALTIME, &ts); - localtime_r(&ts.tv_sec, &tm); - strftime(timestr, sizeof timestr, "%H:%M:%S", &tm); + localtime_r (&ts.tv_sec, &tm); + strftime (timestr, sizeof timestr, "%H:%M:%S", &tm); - fprintf(stderr, "%s.%06ld %.10s:%04d ********\n", timestr, ts.tv_nsec / 1000, file, lineno); + fprintf (stderr, "%s.%06ld %.10s:%04d ********\n", timestr, + ts.tv_nsec / 1000, file, lineno); - get_backtrace(bt); - for (int i = 0; i < 10; i++) { - Lisp_Object stk = AREF(bt, i); - if (!NILP(stk)) { - Lisp_Object args[2] = { build_string("%S"), stk }; - Lisp_Object str = Fformat(2, args); - fprintf(stderr, "%s %.10s:%04d %s\n", timestr, file, lineno, SSDATA(str)); + get_backtrace (bt); + for (int i = 0; i < 10; i++) + { + Lisp_Object stk = AREF (bt, i); + if (!NILP (stk)) + { + Lisp_Object args[2] = { build_string ("%S"), stk }; + Lisp_Object str = Fformat (2, args); + fprintf (stderr, "%s %.10s:%04d %s\n", timestr, file, lineno, + SSDATA (str)); + } } - } - fprintf(stderr, "%s %.10s:%04d ********\n", timestr, file, lineno); + fprintf (stderr, "%s %.10s:%04d ********\n", timestr, file, lineno); } #endif commit e649275a0cb3bdd38711b7a4ef35b85e95a811a4 Author: Yuuki Harano Date: Sun May 24 00:08:00 2020 +0900 * src/pgtkterm.c: change coding style diff --git a/src/pgtkterm.c b/src/pgtkterm.c index ef8daba720..413d421fa4 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -72,10 +72,11 @@ along with GNU Emacs. If not, see . */ ((f)->output_data.pgtk->cr_surface_desired_height) -struct pgtk_display_info *x_display_list; /* Chain of existing displays */ +struct pgtk_display_info *x_display_list; /* Chain of existing displays */ extern Lisp_Object tip_frame; -static struct event_queue_t { +static struct event_queue_t +{ union buffered_input_event *q; int nr, cap; } event_q = { @@ -91,12 +92,13 @@ static Time ignore_next_mouse_click_timeout; static Lisp_Object xg_default_icon_file; static void pgtk_delete_display (struct pgtk_display_info *dpyinfo); -static void pgtk_clear_frame_area(struct frame *f, int x, int y, int width, int height); -static void pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int width, int height); +static void pgtk_clear_frame_area (struct frame *f, int x, int y, int width, + int height); +static void pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, + int y, int width, int height); static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, - enum glyph_row_area area, cairo_t *cr); -static struct frame * -pgtk_any_window_to_frame (GdkWindow *window); + enum glyph_row_area area, cairo_t * cr); +static struct frame *pgtk_any_window_to_frame (GdkWindow * window); /* * This is not a flip context in the same sense as gpu rendering @@ -105,40 +107,45 @@ pgtk_any_window_to_frame (GdkWindow *window); * context's surface has completed drawing */ -static void flip_cr_context(struct frame *f) +static void +flip_cr_context (struct frame *f) { - PGTK_TRACE("flip_cr_context"); - cairo_t * cr = FRAME_CR_ACTIVE_CONTEXT(f); + PGTK_TRACE ("flip_cr_context"); + cairo_t *cr = FRAME_CR_ACTIVE_CONTEXT (f); - block_input(); - if ( cr != FRAME_CR_CONTEXT(f)) + block_input (); + if (cr != FRAME_CR_CONTEXT (f)) { - cairo_destroy(cr); - FRAME_CR_ACTIVE_CONTEXT(f) = cairo_reference(FRAME_CR_CONTEXT(f)); + cairo_destroy (cr); + FRAME_CR_ACTIVE_CONTEXT (f) = cairo_reference (FRAME_CR_CONTEXT (f)); } - unblock_input(); + unblock_input (); } -static void evq_enqueue(union buffered_input_event *ev) +static void +evq_enqueue (union buffered_input_event *ev) { struct event_queue_t *evq = &event_q; - if (evq->cap == 0) { - evq->cap = 4; - evq->q = xmalloc(sizeof *evq->q * evq->cap); - } + if (evq->cap == 0) + { + evq->cap = 4; + evq->q = xmalloc (sizeof *evq->q * evq->cap); + } - if (evq->nr >= evq->cap) { - evq->cap += evq->cap / 2; - evq->q = xrealloc(evq->q, sizeof *evq->q * evq->cap); - } + if (evq->nr >= evq->cap) + { + evq->cap += evq->cap / 2; + evq->q = xrealloc (evq->q, sizeof *evq->q * evq->cap); + } evq->q[evq->nr++] = *ev; - raise(SIGIO); + raise (SIGIO); } -static int evq_flush(struct input_event *hold_quit) +static int +evq_flush (struct input_event *hold_quit) { struct event_queue_t *evq = &event_q; int i, n = evq->nr; @@ -149,17 +156,18 @@ static int evq_flush(struct input_event *hold_quit) } void -mark_pgtkterm(void) +mark_pgtkterm (void) { struct event_queue_t *evq = &event_q; int i, n = evq->nr; - for (i = 0; i < n; i++) { - union buffered_input_event *ev = &evq->q[i]; - mark_object (ev->ie.x); - mark_object (ev->ie.y); - mark_object (ev->ie.frame_or_window); - mark_object (ev->ie.arg); - } + for (i = 0; i < n; i++) + { + union buffered_input_event *ev = &evq->q[i]; + mark_object (ev->ie.x); + mark_object (ev->ie.y); + mark_object (ev->ie.frame_or_window); + mark_object (ev->ie.arg); + } } char * @@ -169,7 +177,7 @@ get_keysym_name (int keysym) that it be unique. -------------------------------------------------------------------------- */ { - PGTK_TRACE("x_get_ksysym_name"); + PGTK_TRACE ("x_get_ksysym_name"); static char value[16]; sprintf (value, "%d", keysym); return value; @@ -181,7 +189,7 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) Programmatically reposition mouse pointer in pixel coordinates -------------------------------------------------------------------------- */ { - PGTK_TRACE("frame_set_mouse_pixel_position"); + PGTK_TRACE ("frame_set_mouse_pixel_position"); } /* Free X resources of frame F. */ @@ -204,49 +212,57 @@ x_free_frame_resources (struct frame *f) #define CLEAR_IF_EQ(FIELD) \ do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false) - CLEAR_IF_EQ(x_focus_frame); - CLEAR_IF_EQ(highlight_frame); - CLEAR_IF_EQ(x_focus_event_frame); - CLEAR_IF_EQ(last_mouse_frame); - CLEAR_IF_EQ(last_mouse_motion_frame); - CLEAR_IF_EQ(last_mouse_glyph_frame); - CLEAR_IF_EQ(im.focused_frame); + CLEAR_IF_EQ (x_focus_frame); + CLEAR_IF_EQ (highlight_frame); + CLEAR_IF_EQ (x_focus_event_frame); + CLEAR_IF_EQ (last_mouse_frame); + CLEAR_IF_EQ (last_mouse_motion_frame); + CLEAR_IF_EQ (last_mouse_glyph_frame); + CLEAR_IF_EQ (im.focused_frame); #undef CLEAR_IF_EQ if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); - if (FRAME_X_OUTPUT(f)->border_color_css_provider != NULL) { - GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); - GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; - gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); - FRAME_X_OUTPUT(f)->border_color_css_provider = NULL; - } + if (FRAME_X_OUTPUT (f)->border_color_css_provider != NULL) + { + GtkStyleContext *ctxt = + gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); + FRAME_X_OUTPUT (f)->border_color_css_provider = NULL; + } - if (FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider != NULL) { - GtkCssProvider *old = FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider; - g_object_unref (old); - FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider = NULL; - } + if (FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider != NULL) + { + GtkCssProvider *old = + FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider; + g_object_unref (old); + FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider = NULL; + } - if (FRAME_X_OUTPUT(f)->scrollbar_background_css_provider != NULL) { - GtkCssProvider *old = FRAME_X_OUTPUT(f)->scrollbar_background_css_provider; - g_object_unref (old); - FRAME_X_OUTPUT(f)->scrollbar_background_css_provider = NULL; - } + if (FRAME_X_OUTPUT (f)->scrollbar_background_css_provider != NULL) + { + GtkCssProvider *old = + FRAME_X_OUTPUT (f)->scrollbar_background_css_provider; + g_object_unref (old); + FRAME_X_OUTPUT (f)->scrollbar_background_css_provider = NULL; + } - gtk_widget_destroy(FRAME_GTK_OUTER_WIDGET(f)); + gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); - if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { - cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); - FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; - } + if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL) + { + cairo_surface_destroy (FRAME_X_OUTPUT (f)->cr_surface_visible_bell); + FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL; + } - if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) { - cancel_atimer(FRAME_X_OUTPUT(f)->atimer_visible_bell); - FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; - } + if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL) + { + cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell); + FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; + } xfree (f->output_data.pgtk); f->output_data.pgtk = NULL; @@ -281,7 +297,7 @@ x_calc_absolute_position (struct frame *f) /* We have nothing to do if the current position is already for the top-left corner. */ - if (! ((flags & XNegative) || (flags & YNegative))) + if (!((flags & XNegative) || (flags & YNegative))) return; /* Treat negative positions as relative to the leftmost bottommost @@ -291,8 +307,8 @@ x_calc_absolute_position (struct frame *f) int width = FRAME_PIXEL_WIDTH (f); /* A frame that has been visible at least once should have outer - edges. */ - if (FRAME_X_OUTPUT(f)->has_been_visible && !p) + edges. */ + if (FRAME_X_OUTPUT (f)->has_been_visible && !p) { Lisp_Object frame; Lisp_Object edges = Qnil; @@ -317,7 +333,7 @@ x_calc_absolute_position (struct frame *f) { int height = FRAME_PIXEL_HEIGHT (f); - if (FRAME_X_OUTPUT(f)->has_been_visible && !p) + if (FRAME_X_OUTPUT (f)->has_been_visible && !p) { Lisp_Object frame; Lisp_Object edges = Qnil; @@ -332,16 +348,16 @@ x_calc_absolute_position (struct frame *f) if (p) f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width - + f->top_pos); + + f->top_pos); else f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height + f->top_pos); - } + } /* The left_pos and top_pos are now relative to the top and left screen edges, so the flags should correspond. */ - f->size_hint_flags &= ~ (XNegative | YNegative); + f->size_hint_flags &= ~(XNegative | YNegative); } /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, @@ -356,35 +372,43 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) External: Position the window -------------------------------------------------------------------------- */ { - PGTK_TRACE("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); + PGTK_TRACE ("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); - struct frame *parent = FRAME_PARENT_FRAME(f); - GtkAllocation a = {0}; - if (change_gravity > 0) { - if (parent) { - /* determing the "height" of the titlebar, by finding the - location of the "emacsfixed" widget on the surface/window */ - GtkWidget *w = FRAME_GTK_WIDGET(parent); - gtk_widget_get_allocation(w, &a); - } + struct frame *parent = FRAME_PARENT_FRAME (f); + GtkAllocation a = { 0 }; + if (change_gravity > 0) + { + if (parent) + { + /* determing the "height" of the titlebar, by finding the + location of the "emacsfixed" widget on the surface/window */ + GtkWidget *w = FRAME_GTK_WIDGET (parent); + gtk_widget_get_allocation (w, &a); + } - f->size_hint_flags &= ~ (XNegative | YNegative); - /* if the value is negative, don't include the titlebar offset */ - if (xoff < 0) { - f->size_hint_flags |= XNegative; - f->left_pos = xoff; - } else { - f->left_pos = xoff + a.x; //~25 - } + f->size_hint_flags &= ~(XNegative | YNegative); + /* if the value is negative, don't include the titlebar offset */ + if (xoff < 0) + { + f->size_hint_flags |= XNegative; + f->left_pos = xoff; + } + else + { + f->left_pos = xoff + a.x; //~25 + } - if (yoff < 0){ - f->size_hint_flags |= YNegative; - f->top_pos = yoff; - } else { - f->top_pos = yoff + a.y; //~60 + if (yoff < 0) + { + f->size_hint_flags |= YNegative; + f->top_pos = yoff; + } + else + { + f->top_pos = yoff + a.y; //~60 + } + f->win_gravity = NorthWestGravity; } - f->win_gravity = NorthWestGravity; - } x_calc_absolute_position (f); @@ -394,33 +418,34 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) /* When a position change was requested and the outer GTK widget has been realized already, leave it to gtk_window_move to DTRT and return. Used for Bug#25851 and Bug#25943. */ - if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) { - PGTK_TRACE("x_set_offset: move to %d,%d.", f->left_pos, f->top_pos); - gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - f->left_pos, f->top_pos); - } + if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) + { + PGTK_TRACE ("x_set_offset: move to %d,%d.", f->left_pos, f->top_pos); + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + } unblock_input (); } static void pgtk_set_window_size (struct frame *f, - bool change_gravity, - int width, - int height, - bool pixelwise) + bool change_gravity, + int width, int height, bool pixelwise) /* -------------------------------------------------------------------------- Adjust window pixel size based on given character grid size Impl is a bit more complex than other terms, need to do some internal clipping. -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_set_window_size(%dx%d, %s)", width, height, pixelwise ? "pixel" : "char"); + PGTK_TRACE ("pgtk_set_window_size(%dx%d, %s)", width, height, + pixelwise ? "pixel" : "char"); int pixelwidth, pixelheight; block_input (); - gtk_widget_get_size_request(FRAME_GTK_WIDGET(f), &pixelwidth, &pixelheight); + gtk_widget_get_size_request (FRAME_GTK_WIDGET (f), &pixelwidth, + &pixelheight); if (pixelwise) { @@ -429,7 +454,7 @@ pgtk_set_window_size (struct frame *f, } else { - pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); } @@ -441,15 +466,18 @@ pgtk_set_window_size (struct frame *f, make_fixnum (FRAME_PGTK_TITLEBAR_HEIGHT (f)), make_fixnum (FRAME_TOOLBAR_HEIGHT (f)))); - for (GtkWidget *w = FRAME_GTK_WIDGET(f); w != NULL; w = gtk_widget_get_parent(w)) { - gint wd, hi; - gtk_widget_get_size_request(w, &wd, &hi); - } + for (GtkWidget * w = FRAME_GTK_WIDGET (f); w != NULL; + w = gtk_widget_get_parent (w)) + { + gint wd, hi; + gtk_widget_get_size_request (w, &wd, &hi); + } f->output_data.pgtk->preferred_width = pixelwidth; f->output_data.pgtk->preferred_height = pixelheight; - x_wm_set_size_hint(f, 0, 0); - xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH(f, pixelwidth), FRAME_PIXEL_TO_TEXT_HEIGHT(f, pixelheight)); + x_wm_set_size_hint (f, 0, 0); + xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight)); gtk_widget_queue_resize (FRAME_GTK_OUTER_WIDGET (f)); unblock_input (); @@ -461,7 +489,7 @@ pgtk_iconify_frame (struct frame *f) External: Iconify window -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_iconify_frame"); + PGTK_TRACE ("pgtk_iconify_frame"); /* Don't keep the highlight on an invisible frame. */ if (FRAME_DISPLAY_INFO (f)->highlight_frame == f) @@ -478,8 +506,8 @@ pgtk_iconify_frame (struct frame *f) if (FRAME_GTK_OUTER_WIDGET (f)) { - if (! FRAME_VISIBLE_P (f)) - gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + if (!FRAME_VISIBLE_P (f)) + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); SET_FRAME_VISIBLE (f, 0); @@ -490,12 +518,11 @@ pgtk_iconify_frame (struct frame *f) /* Make sure the X server knows where the window should be positioned, in case the user deiconifies with the window manager. */ - if (! FRAME_VISIBLE_P (f) - && ! FRAME_ICONIFIED_P (f) + if (!FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f) #if 0 - && ! FRAME_X_EMBEDDED_P (f) + && !FRAME_X_EMBEDDED_P (f) #endif - ) + ) x_set_offset (f, f->left_pos, f->top_pos, 0); #if 0 @@ -513,7 +540,9 @@ pgtk_iconify_frame (struct frame *f) } static gboolean -pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer user_data) +pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget * widget, + GdkEventAny * event, + gpointer user_data) { int *foundptr = user_data; *foundptr = 1; @@ -534,27 +563,36 @@ pgtk_make_frame_visible (struct frame *f) External: Show the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_make_frame_visible"); + PGTK_TRACE ("pgtk_make_frame_visible"); GtkWidget *win = FRAME_GTK_OUTER_WIDGET (f); - if (! FRAME_VISIBLE_P (f)) - { - gtk_widget_show(win); - gtk_window_deiconify(GTK_WINDOW(win)); - - if (FLOATP (Vpgtk_wait_for_event_timeout)) { - guint msec = (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000); - int found = 0; - int timed_out = 0; - gulong id = g_signal_connect(win, "map-event", G_CALLBACK(pgtk_make_frame_visible_wait_for_map_event_cb), &found); - guint src = g_timeout_add(msec, pgtk_make_frame_visible_wait_for_map_event_timeout, &timed_out); - while (!found && !timed_out) - gtk_main_iteration(); - g_signal_handler_disconnect (win, id); - if (!timed_out) - g_source_remove(src); - } + if (!FRAME_VISIBLE_P (f)) + { + gtk_widget_show (win); + gtk_window_deiconify (GTK_WINDOW (win)); + + if (FLOATP (Vpgtk_wait_for_event_timeout)) + { + guint msec = + (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000); + int found = 0; + int timed_out = 0; + gulong id = + g_signal_connect (win, "map-event", + G_CALLBACK + (pgtk_make_frame_visible_wait_for_map_event_cb), + &found); + guint src = + g_timeout_add (msec, + pgtk_make_frame_visible_wait_for_map_event_timeout, + &timed_out); + while (!found && !timed_out) + gtk_main_iteration (); + g_signal_handler_disconnect (win, id); + if (!timed_out) + g_source_remove (src); + } } } @@ -565,11 +603,11 @@ pgtk_make_frame_invisible (struct frame *f) External: Hide the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_make_frame_invisible"); + PGTK_TRACE ("pgtk_make_frame_invisible"); - GtkWidget *win = FRAME_OUTPUT_DATA(f)->widget; + GtkWidget *win = FRAME_OUTPUT_DATA (f)->widget; - gtk_widget_hide(win); + gtk_widget_hide (win); SET_FRAME_VISIBLE (f, 0); SET_FRAME_ICONIFIED (f, false); @@ -587,7 +625,7 @@ pgtk_make_frame_visible_invisible (struct frame *f, bool visible) static Lisp_Object pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) { - PGTK_TRACE("pgtk_new_font"); + PGTK_TRACE ("pgtk_new_font"); struct font *font = XFONT_OBJECT (font_object); int font_ascent, font_descent; @@ -595,31 +633,32 @@ pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) fontset = fontset_from_font (font_object); FRAME_FONTSET (f) = fontset; - if (FRAME_FONT (f) == font) { - /* This font is already set in frame F. There's nothing more to - do. */ - PGTK_TRACE("already set."); - return font_object; - } + if (FRAME_FONT (f) == font) + { + /* This font is already set in frame F. There's nothing more to + do. */ + PGTK_TRACE ("already set."); + return font_object; + } FRAME_FONT (f) = font; - PGTK_TRACE("font:"); - PGTK_TRACE(" %p", font); - PGTK_TRACE(" name: %s", SSDATA(font_get_name(font_object))); - PGTK_TRACE(" width: %d..%d", font->min_width, font->max_width); - PGTK_TRACE(" pixel_size: %d", font->pixel_size); - PGTK_TRACE(" height: %d", font->height); - PGTK_TRACE(" space_width: %d", font->space_width); - PGTK_TRACE(" average_width: %d", font->average_width); - PGTK_TRACE(" asc/desc: %d,%d", font->ascent, font->descent); - PGTK_TRACE(" ul thickness: %d", font->underline_thickness); - PGTK_TRACE(" ul position: %d", font->underline_position); - PGTK_TRACE(" vertical_centering: %d", font->vertical_centering); - PGTK_TRACE(" baseline_offset: %d", font->baseline_offset); - PGTK_TRACE(" relative_compose: %d", font->relative_compose); - PGTK_TRACE(" default_ascent: %d", font->default_ascent); - PGTK_TRACE(" encoding_charset: %d", font->encoding_charset); - PGTK_TRACE(" repertory_charset: %d", font->repertory_charset); + PGTK_TRACE ("font:"); + PGTK_TRACE (" %p", font); + PGTK_TRACE (" name: %s", SSDATA (font_get_name (font_object))); + PGTK_TRACE (" width: %d..%d", font->min_width, font->max_width); + PGTK_TRACE (" pixel_size: %d", font->pixel_size); + PGTK_TRACE (" height: %d", font->height); + PGTK_TRACE (" space_width: %d", font->space_width); + PGTK_TRACE (" average_width: %d", font->average_width); + PGTK_TRACE (" asc/desc: %d,%d", font->ascent, font->descent); + PGTK_TRACE (" ul thickness: %d", font->underline_thickness); + PGTK_TRACE (" ul position: %d", font->underline_position); + PGTK_TRACE (" vertical_centering: %d", font->vertical_centering); + PGTK_TRACE (" baseline_offset: %d", font->baseline_offset); + PGTK_TRACE (" relative_compose: %d", font->relative_compose); + PGTK_TRACE (" default_ascent: %d", font->default_ascent); + PGTK_TRACE (" encoding_charset: %d", font->encoding_charset); + PGTK_TRACE (" repertory_charset: %d", font->repertory_charset); FRAME_BASELINE_OFFSET (f) = font->baseline_offset; FRAME_COLUMN_WIDTH (f) = font->average_width; @@ -658,34 +697,35 @@ pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, false, Qfont); - PGTK_TRACE("set new."); + PGTK_TRACE ("set new."); return font_object; } int x_display_pixel_height (struct pgtk_display_info *dpyinfo) { - PGTK_TRACE("x_display_pixel_height"); + PGTK_TRACE ("x_display_pixel_height"); GdkDisplay *gdpy = dpyinfo->gdpy; - GdkScreen *gscr = gdk_display_get_default_screen(gdpy); - PGTK_TRACE(" = %d", gdk_screen_get_height(gscr)); - return gdk_screen_get_height(gscr); + GdkScreen *gscr = gdk_display_get_default_screen (gdpy); + PGTK_TRACE (" = %d", gdk_screen_get_height (gscr)); + return gdk_screen_get_height (gscr); } int x_display_pixel_width (struct pgtk_display_info *dpyinfo) { - PGTK_TRACE("x_display_pixel_width"); + PGTK_TRACE ("x_display_pixel_width"); GdkDisplay *gdpy = dpyinfo->gdpy; - GdkScreen *gscr = gdk_display_get_default_screen(gdpy); - PGTK_TRACE(" = %d", gdk_screen_get_width(gscr)); - return gdk_screen_get_width(gscr); + GdkScreen *gscr = gdk_display_get_default_screen (gdpy); + PGTK_TRACE (" = %d", gdk_screen_get_width (gscr)); + return gdk_screen_get_width (gscr); } void -x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_parent_frame (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) /* -------------------------------------------------------------------------- Set frame F's `parent-frame' parameter. If non-nil, make F a child frame of the frame specified by that parameter. Technically, this @@ -713,21 +753,21 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu if (!NILP (new_value) && (!FRAMEP (new_value) - || !FRAME_LIVE_P (p = XFRAME (new_value)) - || !FRAME_PGTK_P (p))) + || !FRAME_LIVE_P (p = XFRAME (new_value)) || !FRAME_PGTK_P (p))) { store_frame_param (f, Qparent_frame, old_value); error ("Invalid specification of `parent-frame'"); } - if (p != FRAME_PARENT_FRAME (f) - && (p != NULL)) + if (p != FRAME_PARENT_FRAME (f) && (p != NULL)) { block_input (); - gtk_window_set_transient_for(FRAME_NATIVE_WINDOW(f), FRAME_NATIVE_WINDOW(p)); - gtk_window_set_attached_to(FRAME_NATIVE_WINDOW(f), FRAME_GTK_WIDGET(p)); - gtk_window_move(FRAME_NATIVE_WINDOW(f), f->left_pos, f->top_pos); - gtk_window_set_keep_above(FRAME_NATIVE_WINDOW(f), true); + gtk_window_set_transient_for (FRAME_NATIVE_WINDOW (f), + FRAME_NATIVE_WINDOW (p)); + gtk_window_set_attached_to (FRAME_NATIVE_WINDOW (f), + FRAME_GTK_WIDGET (p)); + gtk_window_move (FRAME_NATIVE_WINDOW (f), f->left_pos, f->top_pos); + gtk_window_set_keep_above (FRAME_NATIVE_WINDOW (f), true); unblock_input (); fset_parent_frame (f, new_value); @@ -736,7 +776,8 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu void -x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) /* Set frame F's `no-focus-on-map' parameter which, if non-nil, means * that F's window-system window does not want to receive input focus * when it is mapped. (A frame's window is mapped when the frame is @@ -745,7 +786,7 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_v * * Some window managers may not honor this parameter. */ { - PGTK_TRACE("x_set_no_accept_focus_on_map"); + PGTK_TRACE ("x_set_no_accept_focus_on_map"); /* doesn't work on wayland. */ if (!EQ (new_value, old_value)) @@ -756,7 +797,8 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_v } void -x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value) /* Set frame F's `no-accept-focus' parameter which, if non-nil, hints * that F's window-system window does not want to receive input focus * via mouse clicks or by moving the mouse into it. @@ -767,7 +809,7 @@ x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_v * Some window managers may not honor this parameter. */ { /* doesn't work on wayland. */ - PGTK_TRACE("x_set_no_accept_focus"); + PGTK_TRACE ("x_set_no_accept_focus"); xg_set_no_accept_focus (f, new_value); FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value); @@ -785,29 +827,36 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) Some window managers may not honor this parameter. */ { /* doesn't work on wayland. */ - PGTK_TRACE("x_set_z_group"); + PGTK_TRACE ("x_set_z_group"); if (NILP (new_value)) { - gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); - gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FALSE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FALSE); FRAME_Z_GROUP (f) = z_group_none; } else if (EQ (new_value, Qabove)) { - gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), TRUE); - gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + TRUE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FALSE); FRAME_Z_GROUP (f) = z_group_above; } else if (EQ (new_value, Qabove_suspended)) { - gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FALSE); FRAME_Z_GROUP (f) = z_group_above_suspended; } else if (EQ (new_value, Qbelow)) { - gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); - gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), TRUE); + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + FALSE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + TRUE); FRAME_Z_GROUP (f) = z_group_below; } else @@ -820,17 +869,17 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) Initialize global info and storage for display. -------------------------------------------------------------------------- */ { - dpyinfo->resx = 96; - dpyinfo->resy = 96; - dpyinfo->color_p = 1; - dpyinfo->n_planes = 32; - dpyinfo->root_window = 42; /* a placeholder.. */ - dpyinfo->highlight_frame = dpyinfo->x_focus_frame = NULL; - dpyinfo->n_fonts = 0; - dpyinfo->smallest_font_height = 1; - dpyinfo->smallest_char_width = 1; + dpyinfo->resx = 96; + dpyinfo->resy = 96; + dpyinfo->color_p = 1; + dpyinfo->n_planes = 32; + dpyinfo->root_window = 42; /* a placeholder.. */ + dpyinfo->highlight_frame = dpyinfo->x_focus_frame = NULL; + dpyinfo->n_fonts = 0; + dpyinfo->smallest_font_height = 1; + dpyinfo->smallest_char_width = 1; - reset_mouse_highlight (&dpyinfo->mouse_highlight); + reset_mouse_highlight (&dpyinfo->mouse_highlight); } /* Set S->gc to a suitable GC for drawing glyph string S in cursor @@ -839,32 +888,34 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) static void x_set_cursor_gc (struct glyph_string *s) { - PGTK_TRACE("x_set_cursor_gc."); + PGTK_TRACE ("x_set_cursor_gc."); if (s->font == FRAME_FONT (s->f) && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) - && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) - && !s->cmp) - PGTK_TRACE("x_set_cursor_gc: 1."), - s->xgcv = FRAME_X_OUTPUT(s->f)->cursor_xgcv; + && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) && !s->cmp) + PGTK_TRACE ("x_set_cursor_gc: 1."), + s->xgcv = FRAME_X_OUTPUT (s->f)->cursor_xgcv; else { /* Cursor on non-default face: must merge. */ Emacs_GC xgcv; - PGTK_TRACE("x_set_cursor_gc: 2."); - xgcv.background = FRAME_X_OUTPUT(s->f)->cursor_color; + PGTK_TRACE ("x_set_cursor_gc: 2."); + xgcv.background = FRAME_X_OUTPUT (s->f)->cursor_color; xgcv.foreground = s->face->background; - PGTK_TRACE("x_set_cursor_gc: 3. %08lx, %08lx.", xgcv.background, xgcv.foreground); + PGTK_TRACE ("x_set_cursor_gc: 3. %08lx, %08lx.", xgcv.background, + xgcv.foreground); /* If the glyph would be invisible, try a different foreground. */ if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; - PGTK_TRACE("x_set_cursor_gc: 4. %08lx, %08lx.", xgcv.background, xgcv.foreground); + PGTK_TRACE ("x_set_cursor_gc: 4. %08lx, %08lx.", xgcv.background, + xgcv.foreground); if (xgcv.foreground == xgcv.background) - xgcv.foreground = FRAME_X_OUTPUT(s->f)->cursor_foreground_color; + xgcv.foreground = FRAME_X_OUTPUT (s->f)->cursor_foreground_color; if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; - PGTK_TRACE("x_set_cursor_gc: 5. %08lx, %08lx.", xgcv.background, xgcv.foreground); + PGTK_TRACE ("x_set_cursor_gc: 5. %08lx, %08lx.", xgcv.background, + xgcv.foreground); /* Make sure the cursor is distinct from text in this face. */ if (xgcv.background == s->face->background @@ -873,7 +924,8 @@ x_set_cursor_gc (struct glyph_string *s) xgcv.background = s->face->foreground; xgcv.foreground = s->face->background; } - PGTK_TRACE("x_set_cursor_gc: 6. %08lx, %08lx.", xgcv.background, xgcv.foreground); + PGTK_TRACE ("x_set_cursor_gc: 6. %08lx, %08lx.", xgcv.background, + xgcv.foreground); IF_DEBUG (x_check_font (s->f, s->font)); @@ -903,13 +955,15 @@ x_set_mouse_face_gc (struct glyph_string *s) s->face = FACE_FROM_ID (s->f, face_id); prepare_face_for_display (s->f, s->face); - if (s->font == s->face->font) { - s->xgcv.foreground = s->face->foreground; - s->xgcv.background = s->face->background; - } else + if (s->font == s->face->font) + { + s->xgcv.foreground = s->face->foreground; + s->xgcv.background = s->face->background; + } + else { /* Otherwise construct scratch_cursor_gc with values from FACE - except for FONT. */ + except for FONT. */ Emacs_GC xgcv; xgcv.background = s->face->background; @@ -940,43 +994,50 @@ x_set_mode_line_face_gc (struct glyph_string *s) static void x_set_glyph_string_gc (struct glyph_string *s) { - PGTK_TRACE("x_set_glyph_string_gc: s->f: %08lx, %08lx", s->f->background_pixel, s->f->foreground_pixel); - PGTK_TRACE("x_set_glyph_string_gc: s->face: %08lx, %08lx", s->face->background, s->face->foreground); + PGTK_TRACE ("x_set_glyph_string_gc: s->f: %08lx, %08lx", + s->f->background_pixel, s->f->foreground_pixel); + PGTK_TRACE ("x_set_glyph_string_gc: s->face: %08lx, %08lx", + s->face->background, s->face->foreground); prepare_face_for_display (s->f, s->face); - PGTK_TRACE("x_set_glyph_string_gc: s->face: %08lx, %08lx", s->face->background, s->face->foreground); + PGTK_TRACE ("x_set_glyph_string_gc: s->face: %08lx, %08lx", + s->face->background, s->face->foreground); if (s->hl == DRAW_NORMAL_TEXT) { s->xgcv.foreground = s->face->foreground; s->xgcv.background = s->face->background; s->stippled_p = s->face->stipple != 0; - PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, + s->xgcv.foreground); } else if (s->hl == DRAW_INVERSE_VIDEO) { x_set_mode_line_face_gc (s); s->stippled_p = s->face->stipple != 0; - PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, + s->xgcv.foreground); } else if (s->hl == DRAW_CURSOR) { x_set_cursor_gc (s); s->stippled_p = false; - PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, + s->xgcv.foreground); } else if (s->hl == DRAW_MOUSE_FACE) { x_set_mouse_face_gc (s); s->stippled_p = s->face->stipple != 0; - PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, + s->xgcv.foreground); } - else if (s->hl == DRAW_IMAGE_RAISED - || s->hl == DRAW_IMAGE_SUNKEN) + else if (s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) { s->xgcv.foreground = s->face->foreground; s->xgcv.background = s->face->background; s->stippled_p = s->face->stipple != 0; - PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + PGTK_TRACE ("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, + s->xgcv.foreground); } else emacs_abort (); @@ -987,31 +1048,33 @@ x_set_glyph_string_gc (struct glyph_string *s) line or menu if we don't have X toolkit support. */ static void -x_set_glyph_string_clipping (struct glyph_string *s, cairo_t *cr) +x_set_glyph_string_clipping (struct glyph_string *s, cairo_t * cr) { XRectangle r[2]; int n = get_glyph_string_clip_rects (s, r, 2); - PGTK_TRACE("x_set_glyph_string_clipping: n=%d.", n); + PGTK_TRACE ("x_set_glyph_string_clipping: n=%d.", n); - if (n > 0) { - for (int i = 0; i < n; i++) { - PGTK_TRACE("x_set_glyph_string_clipping: r[%d]: %ux%u+%d+%d.", - i, r[i].width, r[i].height, r[i].x, r[i].y); - cairo_rectangle(cr, r[i].x, r[i].y, r[i].width, r[i].height); + if (n > 0) + { + for (int i = 0; i < n; i++) + { + PGTK_TRACE ("x_set_glyph_string_clipping: r[%d]: %ux%u+%d+%d.", + i, r[i].width, r[i].height, r[i].x, r[i].y); + cairo_rectangle (cr, r[i].x, r[i].y, r[i].width, r[i].height); + } + cairo_clip (cr); } - cairo_clip(cr); - } - PGTK_TRACE("clip result:"); - cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr); - for (int i = 0; i < rects->num_rectangles; i++) { - PGTK_TRACE(" rect[%d]: %dx%d+%d+%d.", - i, - (int) rects->rectangles[i].width, - (int) rects->rectangles[i].height, - (int) rects->rectangles[i].x, - (int) rects->rectangles[i].y); - } - cairo_rectangle_list_destroy(rects); + PGTK_TRACE ("clip result:"); + cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list (cr); + for (int i = 0; i < rects->num_rectangles; i++) + { + PGTK_TRACE (" rect[%d]: %dx%d+%d+%d.", + i, + (int) rects->rectangles[i].width, + (int) rects->rectangles[i].height, + (int) rects->rectangles[i].x, (int) rects->rectangles[i].y); + } + cairo_rectangle_list_destroy (rects); } @@ -1020,7 +1083,8 @@ x_set_glyph_string_clipping (struct glyph_string *s, cairo_t *cr) the area of SRC. */ static void -x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst, cairo_t *cr) +x_set_glyph_string_clipping_exactly (struct glyph_string *src, + struct glyph_string *dst, cairo_t * cr) { dst->clip[0].x = src->x; dst->clip[0].y = src->y; @@ -1028,8 +1092,8 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_stri dst->clip[0].height = src->height; dst->num_clips = 1; - cairo_rectangle(cr, src->x, src->y, src->width, src->height); - cairo_clip(cr); + cairo_rectangle (cr, src->x, src->y, src->width, src->height); + cairo_clip (cr); } @@ -1059,16 +1123,17 @@ pgtk_compute_glyph_string_overhangs (struct glyph_string *s) { Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); - composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics); + composition_gstring_width (gstring, s->cmp_from, s->cmp_to, + &metrics); } s->right_overhang = (metrics.rbearing > metrics.width ? metrics.rbearing - metrics.width : 0); - s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0; + s->left_overhang = metrics.lbearing < 0 ? -metrics.lbearing : 0; } else if (s->cmp) { s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; - s->left_overhang = - s->cmp->lbearing; + s->left_overhang = -s->cmp->lbearing; } } @@ -1078,33 +1143,36 @@ pgtk_compute_glyph_string_overhangs (struct glyph_string *s) static void x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) { - pgtk_fill_rectangle(s->f, s->xgcv.background, x, y, w, h); + pgtk_fill_rectangle (s->f, s->xgcv.background, x, y, w, h); } static void -fill_background_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) +fill_background_by_face (struct frame *f, struct face *face, int x, int y, + int width, int height) { - cairo_t *cr = pgtk_begin_cr_clip(f); + cairo_t *cr = pgtk_begin_cr_clip (f); cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); double r = ((face->background >> 16) & 0xff) / 255.0; - double g = ((face->background >> 8) & 0xff) / 255.0; - double b = ((face->background >> 0) & 0xff) / 255.0; + double g = ((face->background >> 8) & 0xff) / 255.0; + double b = ((face->background >> 0) & 0xff) / 255.0; cairo_set_source_rgb (cr, r, g, b); cairo_paint (cr); - if (face->stipple != 0) { - cairo_pattern_t *mask = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern; + if (face->stipple != 0) + { + cairo_pattern_t *mask = + FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern; - double r = ((face->foreground >> 16) & 0xff) / 255.0; - double g = ((face->foreground >> 8) & 0xff) / 255.0; - double b = ((face->foreground >> 0) & 0xff) / 255.0; - cairo_set_source_rgb (cr, r, g, b); - cairo_mask (cr, mask); - } + double r = ((face->foreground >> 16) & 0xff) / 255.0; + double g = ((face->foreground >> 8) & 0xff) / 255.0; + double b = ((face->foreground >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_mask (cr, mask); + } pgtk_end_cr_clip (f); } @@ -1124,20 +1192,23 @@ fill_background (struct glyph_string *s, int x, int y, int width, int height) static void x_draw_glyph_string_background (struct glyph_string *s, bool force_p) { - PGTK_TRACE("x_draw_glyph_string_background: 0."); + PGTK_TRACE ("x_draw_glyph_string_background: 0."); /* Nothing to do if background has already been drawn or if it shouldn't be drawn in the first place. */ if (!s->background_filled_p) { - PGTK_TRACE("x_draw_glyph_string_background: 1."); + PGTK_TRACE ("x_draw_glyph_string_background: 1."); int box_line_width = max (s->face->box_horizontal_line_width, 0); - PGTK_TRACE("x_draw_glyph_string_background: 2. %d, %d.", - FONT_HEIGHT (s->font), s->height - 2 * box_line_width); - PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", FONT_TOO_HIGH(s->font)); - PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); - PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); - PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); + PGTK_TRACE ("x_draw_glyph_string_background: 2. %d, %d.", + FONT_HEIGHT (s->font), s->height - 2 * box_line_width); + PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", + FONT_TOO_HIGH (s->font)); + PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", + s->font_not_found_p); + PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", + s->extends_to_end_of_line_p); + PGTK_TRACE ("x_draw_glyph_string_background: 2. %d.", force_p); if (s->stippled_p) { @@ -1145,21 +1216,20 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) fill_background (s, s->x, s->y + box_line_width, - s->background_width, s->height - 2 * box_line_width); + s->background_width, + s->height - 2 * box_line_width); s->background_filled_p = true; } - else - if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width + else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width /* When xdisp.c ignores FONT_HEIGHT, we cannot trust - font dimensions, since the actual glyphs might be - much smaller. So in that case we always clear the - rectangle with background color. */ + font dimensions, since the actual glyphs might be + much smaller. So in that case we always clear the + rectangle with background color. */ || FONT_TOO_HIGH (s->font) || s->font_not_found_p - || s->extends_to_end_of_line_p - || force_p) + || s->extends_to_end_of_line_p || force_p) { - PGTK_TRACE("x_draw_glyph_string_background: 3."); + PGTK_TRACE ("x_draw_glyph_string_background: 3."); x_clear_glyph_string_rect (s, s->x, s->y + box_line_width, s->background_width, s->height - 2 * box_line_width); @@ -1170,7 +1240,8 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) static void -pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y, int width, int height) +pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y, + int width, int height) { cairo_t *cr; @@ -1191,8 +1262,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s) /* If first glyph of S has a left box line, start drawing the text of S to the right of that box line. */ - if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p) + if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) x = s->x + max (s->face->box_vertical_line_width, 0); else x = s->x; @@ -1205,8 +1275,8 @@ x_draw_glyph_string_foreground (struct glyph_string *s) { struct glyph *g = s->first_glyph + i; pgtk_draw_rectangle (s->f, - s->face->foreground, x, s->y, g->pixel_width - 1, - s->height - 1); + s->face->foreground, x, s->y, + g->pixel_width - 1, s->height - 1); x += g->pixel_width; } } @@ -1220,8 +1290,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s) boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff; y = s->ybase - boff; - if (s->for_overlaps - || (s->background_filled_p && s->hl != DRAW_CURSOR)) + if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR)) font->driver->draw (s, 0, s->nchars, x, y, false); else font->driver->draw (s, 0, s->nchars, x, y, true); @@ -1257,9 +1326,9 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s) { if (s->cmp_from == 0) pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y, - s->width - 1, s->height - 1); + s->width - 1, s->height - 1); } - else if (! s->first_glyph->u.cmp.automatic) + else if (!s->first_glyph->u.cmp.automatic) { int y = s->ybase; @@ -1343,9 +1412,11 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) for (i = 0; i < s->nchars; i++, glyph++) { #ifdef GCC_LINT - enum { PACIFY_GCC_BUG_81401 = 1 }; + enum + { PACIFY_GCC_BUG_81401 = 1 }; #else - enum { PACIFY_GCC_BUG_81401 = 0 }; + enum + { PACIFY_GCC_BUG_81401 = 0 }; #endif char buf[7 + PACIFY_GCC_BUG_81401]; char *str = NULL; @@ -1355,11 +1426,12 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) { if (len > 0 && CHAR_TABLE_P (Vglyphless_char_display) - && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) - >= 1)) + && + (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) + >= 1)) { Lisp_Object acronym - = (! glyph->u.glyphless.for_no_font + = (!glyph->u.glyphless.for_no_font ? CHAR_TABLE_REF (Vglyphless_char_display, glyph->u.glyphless.ch) : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); @@ -1381,7 +1453,8 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) /* It is assured that all LEN characters in STR is ASCII. */ for (j = 0; j < len; j++) - char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF; + char2b[j] = + s->font->driver->encode_char (s->font, str[j]) & 0xFFFF; s->font->driver->draw (s, 0, upper_len, x + glyph->slice.glyphless.upper_xoff, s->ybase + glyph->slice.glyphless.upper_yoff, @@ -1393,11 +1466,11 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) } if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE) pgtk_draw_rectangle (s->f, s->face->foreground, - x, s->ybase - glyph->ascent, - glyph->pixel_width - 1, - glyph->ascent + glyph->descent - 1); + x, s->ybase - glyph->ascent, + glyph->pixel_width - 1, + glyph->ascent + glyph->descent - 1); x += glyph->pixel_width; - } + } } /* Brightness beyond which a color won't have its highlight brightness @@ -1422,7 +1495,8 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) Value is non-zero if successful. */ static bool -x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, int delta) +x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, + int delta) { Emacs_Color color, new; long bright; @@ -1448,21 +1522,21 @@ x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, int that scaling by FACTOR alone isn't enough. */ { /* How far below the limit this color is (0 - 1, 1 being darker). */ - double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT; + double dimness = 1 - (double) bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT; /* The additive adjustment. */ int min_delta = delta * dimness * factor / 2; if (factor < 1) { - new.red = max (0, new.red - min_delta); + new.red = max (0, new.red - min_delta); new.green = max (0, new.green - min_delta); - new.blue = max (0, new.blue - min_delta); + new.blue = max (0, new.blue - min_delta); } else { - new.red = min (0xffff, min_delta + new.red); + new.red = min (0xffff, min_delta + new.red); new.green = min (0xffff, min_delta + new.green); - new.blue = min (0xffff, min_delta + new.blue); + new.blue = min (0xffff, min_delta + new.blue); } } @@ -1478,7 +1552,8 @@ x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, int new.red = min (0xffff, delta + color.red); new.green = min (0xffff, delta + color.green); new.blue = min (0xffff, delta + color.blue); - new.pixel = new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8; + new.pixel = + new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8; success_p = true; } else @@ -1490,8 +1565,8 @@ x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, int } static void -x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x, int y, - int width, int height, int top_p) +x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x, + int y, int width, int height, int top_p) { cairo_t *cr; @@ -1506,18 +1581,18 @@ x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x, int y, } enum corners - { - CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */ - CORNER_BOTTOM_LEFT, /* pi/2 -> pi */ - CORNER_TOP_LEFT, /* pi -> 3pi/2 */ - CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */ - CORNER_LAST - }; +{ + CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */ + CORNER_BOTTOM_LEFT, /* pi/2 -> pi */ + CORNER_TOP_LEFT, /* pi -> 3pi/2 */ + CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */ + CORNER_LAST +}; static void -x_erase_corners_for_relief (struct frame *f, unsigned long color, int x, int y, - int width, int height, - double radius, double margin, int corners) +x_erase_corners_for_relief (struct frame *f, unsigned long color, int x, + int y, int width, int height, double radius, + double margin, int corners) { cairo_t *cr; int i; @@ -1559,7 +1634,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, unsigned long default_pixel) { Emacs_GC xgcv; - struct pgtk_output *di = FRAME_X_OUTPUT(f); + struct pgtk_output *di = FRAME_X_OUTPUT (f); unsigned long pixel; unsigned long background = di->relief_background; @@ -1577,7 +1652,7 @@ x_setup_relief_color (struct frame *f, struct relief *relief, double factor, static void x_setup_relief_colors (struct glyph_string *s) { - struct pgtk_output *di = FRAME_X_OUTPUT(s->f); + struct pgtk_output *di = FRAME_X_OUTPUT (s->f); unsigned long color; if (s->face->use_box_color_for_shadows_p) @@ -1604,18 +1679,20 @@ x_setup_relief_colors (struct glyph_string *s) static void -x_set_clip_rectangles (struct frame *f, cairo_t *cr, XRectangle *rectangles, int n) +x_set_clip_rectangles (struct frame *f, cairo_t * cr, XRectangle * rectangles, + int n) { - if (n > 0) { - for (int i = 0; i < n; i++) { - cairo_rectangle(cr, - rectangles[i].x, - rectangles[i].y, - rectangles[i].width, - rectangles[i].height); + if (n > 0) + { + for (int i = 0; i < n; i++) + { + cairo_rectangle (cr, + rectangles[i].x, + rectangles[i].y, + rectangles[i].width, rectangles[i].height); + } + cairo_clip (cr); } - cairo_clip(cr); - } } /* Draw a relief on frame F inside the rectangle given by LEFT_X, @@ -1629,24 +1706,24 @@ x_set_clip_rectangles (struct frame *f, cairo_t *cr, XRectangle *rectangles, int static void x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x, int bottom_y, - int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p, - bool left_p, bool right_p, - XRectangle *clip_rect) + int hwidth, int vwidth, bool raised_p, bool top_p, + bool bot_p, bool left_p, bool right_p, + XRectangle * clip_rect) { unsigned long top_left_color, bottom_right_color; int corners = 0; - cairo_t *cr = pgtk_begin_cr_clip(f); + cairo_t *cr = pgtk_begin_cr_clip (f); if (raised_p) { - top_left_color = FRAME_X_OUTPUT(f)->white_relief.xgcv.foreground; - bottom_right_color = FRAME_X_OUTPUT(f)->black_relief.xgcv.foreground; + top_left_color = FRAME_X_OUTPUT (f)->white_relief.xgcv.foreground; + bottom_right_color = FRAME_X_OUTPUT (f)->black_relief.xgcv.foreground; } else { - top_left_color = FRAME_X_OUTPUT(f)->black_relief.xgcv.foreground; - bottom_right_color = FRAME_X_OUTPUT(f)->white_relief.xgcv.foreground; + top_left_color = FRAME_X_OUTPUT (f)->black_relief.xgcv.foreground; + bottom_right_color = FRAME_X_OUTPUT (f)->white_relief.xgcv.foreground; } x_set_clip_rectangles (f, cr, clip_rect, 1); @@ -1654,7 +1731,7 @@ x_draw_relief_rect (struct frame *f, if (left_p) { pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - vwidth, bottom_y + 1 - top_y); + vwidth, bottom_y + 1 - top_y); if (top_p) corners |= 1 << CORNER_TOP_LEFT; if (bot_p) @@ -1663,7 +1740,7 @@ x_draw_relief_rect (struct frame *f, if (right_p) { pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - vwidth, top_y, - vwidth, bottom_y + 1 - top_y); + vwidth, bottom_y + 1 - top_y); if (top_p) corners |= 1 << CORNER_TOP_RIGHT; if (bot_p) @@ -1673,7 +1750,7 @@ x_draw_relief_rect (struct frame *f, { if (!right_p) pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - right_x + 1 - left_x, hwidth); + right_x + 1 - left_x, hwidth); else x_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y, right_x + 1 - left_x, hwidth, 1); @@ -1681,8 +1758,9 @@ x_draw_relief_rect (struct frame *f, if (bot_p) { if (!left_p) - pgtk_fill_rectangle (f, bottom_right_color, left_x, bottom_y + 1 - hwidth, - right_x + 1 - left_x, hwidth); + pgtk_fill_rectangle (f, bottom_right_color, left_x, + bottom_y + 1 - hwidth, right_x + 1 - left_x, + hwidth); else x_fill_trapezoid_for_relief (f, bottom_right_color, left_x, bottom_y + 1 - hwidth, @@ -1690,18 +1768,18 @@ x_draw_relief_rect (struct frame *f, } if (left_p && vwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, - 1, bottom_y + 1 - top_y); + 1, bottom_y + 1 - top_y); if (top_p && hwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, - right_x + 1 - left_x, 1); + right_x + 1 - left_x, 1); if (corners) { - x_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x, top_y, - right_x - left_x + 1, bottom_y - top_y + 1, - 6, 1, corners); + x_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x, + top_y, right_x - left_x + 1, + bottom_y - top_y + 1, 6, 1, corners); } - pgtk_end_cr_clip(f); + pgtk_end_cr_clip (f); } /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y, @@ -1714,11 +1792,12 @@ x_draw_relief_rect (struct frame *f, static void x_draw_box_rect (struct glyph_string *s, int left_x, int top_y, int right_x, int bottom_y, int hwidth, - int vwidth, bool left_p, bool right_p, XRectangle *clip_rect) + int vwidth, bool left_p, bool right_p, + XRectangle * clip_rect) { unsigned long foreground_backup; - cairo_t *cr = pgtk_begin_cr_clip(s->f); + cairo_t *cr = pgtk_begin_cr_clip (s->f); foreground_backup = s->xgcv.foreground; s->xgcv.foreground = s->face->box_color; @@ -1727,25 +1806,27 @@ x_draw_box_rect (struct glyph_string *s, /* Top. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, right_x - left_x + 1, hwidth); + left_x, top_y, right_x - left_x + 1, hwidth); /* Left. */ if (left_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, vwidth, bottom_y - top_y + 1); + left_x, top_y, vwidth, bottom_y - top_y + 1); /* Bottom. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth); + left_x, bottom_y - hwidth + 1, right_x - left_x + 1, + hwidth); /* Right. */ if (right_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1); + right_x - vwidth + 1, top_y, vwidth, + bottom_y - top_y + 1); s->xgcv.foreground = foreground_backup; - pgtk_end_cr_clip(s->f); + pgtk_end_cr_clip (s->f); } @@ -1760,32 +1841,27 @@ x_draw_glyph_string_box (struct glyph_string *s) XRectangle clip_rect; last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) - ? WINDOW_RIGHT_EDGE_X (s->w) - : window_box_right (s->w, s->area)); + ? WINDOW_RIGHT_EDGE_X (s->w) : window_box_right (s->w, s->area)); /* The glyph that may have a right box line. */ last_glyph = (s->cmp || s->img - ? s->first_glyph - : s->first_glyph + s->nchars - 1); + ? s->first_glyph : s->first_glyph + s->nchars - 1); vwidth = eabs (s->face->box_vertical_line_width); hwidth = eabs (s->face->box_horizontal_line_width); raised_p = s->face->box == FACE_RAISED_BOX; left_x = s->x; right_x = (s->row->full_width_p && s->extends_to_end_of_line_p - ? last_x - 1 - : min (last_x, s->x + s->background_width) - 1); + ? last_x - 1 : min (last_x, s->x + s->background_width) - 1); top_y = s->y; bottom_y = top_y + s->height - 1; left_p = (s->first_glyph->left_box_line_p || (s->hl == DRAW_MOUSE_FACE - && (s->prev == NULL - || s->prev->hl != s->hl))); + && (s->prev == NULL || s->prev->hl != s->hl))); right_p = (last_glyph->right_box_line_p || (s->hl == DRAW_MOUSE_FACE - && (s->next == NULL - || s->next->hl != s->hl))); + && (s->next == NULL || s->next->hl != s->hl))); get_glyph_string_clip_rect (s, &clip_rect); @@ -1802,7 +1878,7 @@ x_draw_glyph_string_box (struct glyph_string *s) } static void -x_get_scale_factor(int *scale_x, int *scale_y) +x_get_scale_factor (int *scale_x, int *scale_y) { *scale_x = *scale_y = 1; } @@ -1887,8 +1963,7 @@ x_draw_image_relief (struct glyph_string *s) /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p - && s->slice.x == 0) + && s->first_glyph->left_box_line_p && s->slice.x == 0) x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position @@ -1898,8 +1973,7 @@ x_draw_image_relief (struct glyph_string *s) if (s->slice.y == 0) y += s->img->vmargin; - if (s->hl == DRAW_IMAGE_SUNKEN - || s->hl == DRAW_IMAGE_RAISED) + if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) { thick = (tab_bar_button_relief < 0 ? DEFAULT_TAB_BAR_BUTTON_RELIEF @@ -1965,7 +2039,8 @@ x_draw_image_relief (struct glyph_string *s) give the rectangle to draw. */ static void -x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) +x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, + int h) { if (s->stippled_p) { @@ -1988,8 +2063,7 @@ x_draw_image_foreground (struct glyph_string *s) /* If first glyph of S has a left box line, start drawing it to the right of that line. */ if (s->face->box != FACE_NO_BOX - && s->first_glyph->left_box_line_p - && s->slice.x == 0) + && s->first_glyph->left_box_line_p && s->slice.x == 0) x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position @@ -2040,8 +2114,7 @@ x_draw_image_glyph_string (struct glyph_string *s) || s->img->vmargin || s->img->mask || s->img->pixmap == 0 - || s->stippled_p - || s->width != s->background_width) + || s->stippled_p || s->width != s->background_width) { if (s->img->mask) { @@ -2053,8 +2126,7 @@ x_draw_image_glyph_string (struct glyph_string *s) int y = s->y; int width = s->background_width; - if (s->first_glyph->left_box_line_p - && s->slice.x == 0) + if (s->first_glyph->left_box_line_p && s->slice.x == 0) { x += box_line_hwidth; width -= box_line_hwidth; @@ -2089,8 +2161,7 @@ x_draw_image_glyph_string (struct glyph_string *s) /* If we must draw a relief around the image, do it. */ if (s->img->relief - || s->hl == DRAW_IMAGE_RAISED - || s->hl == DRAW_IMAGE_SUNKEN) + || s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) x_draw_image_relief (s); } @@ -2101,11 +2172,10 @@ x_draw_stretch_glyph_string (struct glyph_string *s) { eassert (s->first_glyph->type == STRETCH_GLYPH); - if (s->hl == DRAW_CURSOR - && !x_stretch_cursor_p) + if (s->hl == DRAW_CURSOR && !x_stretch_cursor_p) { /* If `x-stretch-cursor' is nil, don't draw a block cursor as - wide as the stretch glyph. */ + wide as the stretch glyph. */ int width, background_width = s->background_width; int x = s->x; @@ -2148,8 +2218,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s) x += width; else x = s->x; - if (s->row->mouse_face_p - && cursor_in_mouse_face_p (s->w)) + if (s->row->mouse_face_p && cursor_in_mouse_face_p (s->w)) { x_set_mouse_face_gc (s); color = s->xgcv.foreground; @@ -2157,7 +2226,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s) else color = s->face->foreground; - cairo_t *cr = pgtk_begin_cr_clip(s->f); + cairo_t *cr = pgtk_begin_cr_clip (s->f); get_glyph_string_clip_rect (s, &r); x_set_clip_rectangles (s->f, cr, &r, 1); @@ -2169,10 +2238,10 @@ x_draw_stretch_glyph_string (struct glyph_string *s) } else { - pgtk_fill_rectangle(s->f, color, x, y, w, h); + pgtk_fill_rectangle (s->f, color, x, y, w, h); } - pgtk_end_cr_clip(s->f); + pgtk_end_cr_clip (s->f); } } else if (!s->background_filled_p) @@ -2194,11 +2263,12 @@ x_draw_stretch_glyph_string (struct glyph_string *s) s->background_filled_p = true; } -static void pgtk_draw_glyph_string(struct glyph_string *s) +static void +pgtk_draw_glyph_string (struct glyph_string *s) { - PGTK_TRACE("draw_glyph_string."); - PGTK_TRACE("draw_glyph_string: x=%d, y=%d, width=%d, height=%d.", - s->x, s->y, s->width, s->height); + PGTK_TRACE ("draw_glyph_string."); + PGTK_TRACE ("draw_glyph_string: x=%d, y=%d, width=%d, height=%d.", + s->x, s->y, s->width, s->height); bool relief_drawn_p = false; @@ -2215,8 +2285,8 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) width += next->width, next = next->next) if (next->first_glyph->type != IMAGE_GLYPH) { - cairo_t *cr = pgtk_begin_cr_clip(next->f); - PGTK_TRACE("pgtk_draw_glyph_string: 1."); + cairo_t *cr = pgtk_begin_cr_clip (next->f); + PGTK_TRACE ("pgtk_draw_glyph_string: 1."); x_set_glyph_string_gc (next); x_set_glyph_string_clipping (next, cr); if (next->first_glyph->type == STRETCH_GLYPH) @@ -2224,15 +2294,15 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) else x_draw_glyph_string_background (next, true); next->num_clips = 0; - pgtk_end_cr_clip(next->f); + pgtk_end_cr_clip (next->f); } } /* Set up S->gc, set clipping and draw S. */ - PGTK_TRACE("pgtk_draw_glyph_string: 2."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2."); x_set_glyph_string_gc (s); - cairo_t *cr = pgtk_begin_cr_clip(s->f); + cairo_t *cr = pgtk_begin_cr_clip (s->f); /* Draw relief (if any) in advance for char/composition so that the glyph string can be drawn over it. */ @@ -2242,45 +2312,45 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) || s->first_glyph->type == COMPOSITE_GLYPH)) { - PGTK_TRACE("pgtk_draw_glyph_string: 2.1."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.1."); x_set_glyph_string_clipping (s, cr); x_draw_glyph_string_background (s, true); x_draw_glyph_string_box (s); x_set_glyph_string_clipping (s, cr); relief_drawn_p = true; } - else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ + else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ && !s->clip_tail && ((s->prev && s->prev->hl != s->hl && s->left_overhang) || (s->next && s->next->hl != s->hl && s->right_overhang))) /* We must clip just this glyph. left_overhang part has already drawn when s->prev was drawn, and right_overhang part will be drawn later when s->next is drawn. */ - PGTK_TRACE("pgtk_draw_glyph_string: 2.2."), - x_set_glyph_string_clipping_exactly (s, s, cr); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.2."), + x_set_glyph_string_clipping_exactly (s, s, cr); else - PGTK_TRACE("pgtk_draw_glyph_string: 2.3."), - x_set_glyph_string_clipping (s, cr); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.3."), + x_set_glyph_string_clipping (s, cr); switch (s->first_glyph->type) { case IMAGE_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.4."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.4."); x_draw_image_glyph_string (s); break; case XWIDGET_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.5."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.5."); x_draw_xwidget_glyph_string (s); break; case STRETCH_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.6."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.6."); x_draw_stretch_glyph_string (s); break; case CHAR_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.7."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.7."); if (s->for_overlaps) s->background_filled_p = true; else @@ -2289,9 +2359,9 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) break; case COMPOSITE_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.8."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.8."); if (s->for_overlaps || (s->cmp_from > 0 - && ! s->first_glyph->u.cmp.automatic)) + && !s->first_glyph->u.cmp.automatic)) s->background_filled_p = true; else x_draw_glyph_string_background (s, true); @@ -2299,7 +2369,7 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) break; case GLYPHLESS_GLYPH: - PGTK_TRACE("pgtk_draw_glyph_string: 2.9."); + PGTK_TRACE ("pgtk_draw_glyph_string: 2.9."); if (s->for_overlaps) s->background_filled_p = true; else @@ -2341,52 +2411,52 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) { struct font *font = font_for_underline_metrics (s); - /* Get the underline thickness. Default is 1 pixel. */ - if (font && font->underline_thickness > 0) - thickness = font->underline_thickness; - else - thickness = 1; - if (x_underline_at_descent_line) - position = (s->height - thickness) - (s->ybase - s->y); - else - { - /* Get the underline position. This is the recommended - vertical offset in pixels from the baseline to the top of - the underline. This is a signed value according to the - specs, and its default is - - ROUND ((maximum descent) / 2), with - ROUND(x) = floor (x + 0.5) */ - - if (x_use_underline_position_properties - && font && font->underline_position >= 0) - position = font->underline_position; - else if (font) - position = (font->descent + 1) / 2; - else - position = underline_minimum_offset; - } - position = max (position, underline_minimum_offset); - } - /* Check the sanity of thickness and position. We should - avoid drawing underline out of the current line area. */ - if (s->y + s->height <= s->ybase + position) - position = (s->height - 1) - (s->ybase - s->y); - if (s->y + s->height < s->ybase + position + thickness) - thickness = (s->y + s->height) - (s->ybase + position); - s->underline_thickness = thickness; - s->underline_position = position; - y = s->ybase + position; - if (s->face->underline_defaulted_p) - pgtk_fill_rectangle (s->f, s->xgcv.foreground, + /* Get the underline thickness. Default is 1 pixel. */ + if (font && font->underline_thickness > 0) + thickness = font->underline_thickness; + else + thickness = 1; + if (x_underline_at_descent_line) + position = (s->height - thickness) - (s->ybase - s->y); + else + { + /* Get the underline position. This is the recommended + vertical offset in pixels from the baseline to the top of + the underline. This is a signed value according to the + specs, and its default is + + ROUND ((maximum descent) / 2), with + ROUND(x) = floor (x + 0.5) */ + + if (x_use_underline_position_properties + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = (font->descent + 1) / 2; + else + position = underline_minimum_offset; + } + position = max (position, underline_minimum_offset); + } + /* Check the sanity of thickness and position. We should + avoid drawing underline out of the current line area. */ + if (s->y + s->height <= s->ybase + position) + position = (s->height - 1) - (s->ybase - s->y); + if (s->y + s->height < s->ybase + position + thickness) + thickness = (s->y + s->height) - (s->ybase + position); + s->underline_thickness = thickness; + s->underline_position = position; + y = s->ybase + position; + if (s->face->underline_defaulted_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + s->x, y, s->width, thickness); + else + { + pgtk_fill_rectangle (s->f, s->face->underline_color, s->x, y, s->width, thickness); - else - { - pgtk_fill_rectangle (s->f, s->face->underline_color, - s->x, y, s->width, thickness); - } - } - } + } + } + } /* Draw overline. */ if (s->face->overline_p) { @@ -2394,11 +2464,11 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) if (s->face->overline_color_defaulted_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, s->y + dy, - s->width, h); + s->width, h); else { - pgtk_fill_rectangle (s->f, s->face->overline_color, s->x, s->y + dy, - s->width, h); + pgtk_fill_rectangle (s->f, s->face->overline_color, s->x, + s->y + dy, s->width, h); } } @@ -2419,11 +2489,11 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) if (s->face->strike_through_color_defaulted_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, glyph_y + dy, - s->width, h); + s->width, h); else { - pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x, glyph_y + dy, - s->width, h); + pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x, + glyph_y + dy, s->width, h); } } @@ -2444,9 +2514,9 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) enum draw_glyphs_face save = prev->hl; prev->hl = s->hl; - PGTK_TRACE("pgtk_draw_glyph_string: 3."); + PGTK_TRACE ("pgtk_draw_glyph_string: 3."); x_set_glyph_string_gc (prev); - cairo_save(cr); + cairo_save (cr); x_set_glyph_string_clipping_exactly (s, prev, cr); if (prev->first_glyph->type == CHAR_GLYPH) x_draw_glyph_string_foreground (prev); @@ -2454,7 +2524,7 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) x_draw_composite_glyph_string_foreground (prev); prev->hl = save; prev->num_clips = 0; - cairo_restore(cr); + cairo_restore (cr); } } @@ -2471,15 +2541,15 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) enum draw_glyphs_face save = next->hl; next->hl = s->hl; - PGTK_TRACE("pgtk_draw_glyph_string: 4."); + PGTK_TRACE ("pgtk_draw_glyph_string: 4."); x_set_glyph_string_gc (next); - cairo_save(cr); + cairo_save (cr); x_set_glyph_string_clipping_exactly (s, next, cr); if (next->first_glyph->type == CHAR_GLYPH) x_draw_glyph_string_foreground (next); else x_draw_composite_glyph_string_foreground (next); - cairo_restore(cr); + cairo_restore (cr); next->hl = save; next->num_clips = 0; next->clip_head = s->next; @@ -2488,7 +2558,7 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) } /* Reset clipping. */ - pgtk_end_cr_clip(s->f); + pgtk_end_cr_clip (s->f); s->num_clips = 0; } @@ -2497,15 +2567,17 @@ static void pgtk_draw_glyph_string(struct glyph_string *s) static void pgtk_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) { - if (!f->pointer_invisible - && FRAME_X_OUTPUT(f)->current_cursor != cursor) - gdk_window_set_cursor(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), cursor); - FRAME_X_OUTPUT(f)->current_cursor = cursor; + if (!f->pointer_invisible && FRAME_X_OUTPUT (f)->current_cursor != cursor) + gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)), + cursor); + FRAME_X_OUTPUT (f)->current_cursor = cursor; } -static void pgtk_after_update_window_line(struct window *w, struct glyph_row *desired_row) +static void +pgtk_after_update_window_line (struct window *w, + struct glyph_row *desired_row) { - PGTK_TRACE("after_update_window_line."); + PGTK_TRACE ("after_update_window_line."); struct frame *f; int width, height; @@ -2522,24 +2594,22 @@ static void pgtk_after_update_window_line(struct window *w, struct glyph_row *de && desired_row->full_width_p && (f = XFRAME (w->frame), width = FRAME_INTERNAL_BORDER_WIDTH (f), - width != 0) - && (height = desired_row->visible_height, - height > 0)) + width != 0) && (height = desired_row->visible_height, height > 0)) { int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); block_input (); pgtk_clear_frame_area (f, 0, y, width, height); pgtk_clear_frame_area (f, - FRAME_PIXEL_WIDTH (f) - width, - y, width, height); + FRAME_PIXEL_WIDTH (f) - width, y, width, height); unblock_input (); } } -static void pgtk_clear_frame_area(struct frame *f, int x, int y, int width, int height) +static void +pgtk_clear_frame_area (struct frame *f, int x, int y, int width, int height) { - PGTK_TRACE("clear_frame_area."); + PGTK_TRACE ("clear_frame_area."); pgtk_clear_area (f, x, y, width, height); } @@ -2564,8 +2634,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ - cairo_t *cr = pgtk_begin_cr_clip(f); - pgtk_set_cr_source_with_color(f, FRAME_X_OUTPUT(f)->cursor_color); + cairo_t *cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->cursor_color); /* When on R2L character, show cursor at the right edge of the glyph, unless the cursor box is as wide as the glyph or wider @@ -2579,8 +2649,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) } /* Set clipping, draw the rectangle, and reset clipping again. */ pgtk_clip_to_row (w, row, TEXT_AREA, cr); - pgtk_draw_rectangle (f, FRAME_X_OUTPUT(f)->cursor_color, x, y, wd, h - 1); - pgtk_end_cr_clip(f); + pgtk_draw_rectangle (f, FRAME_X_OUTPUT (f)->cursor_color, x, y, wd, h - 1); + pgtk_end_cr_clip (f); } /* Draw a bar cursor on window W in glyph row ROW. @@ -2591,7 +2661,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row) --gerd. */ static void -x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind) +x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, + enum text_cursor_kinds kind) { struct frame *f = XFRAME (w->frame); struct glyph *cursor_glyph; @@ -2621,17 +2692,17 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); unsigned long color; - cairo_t *cr = pgtk_begin_cr_clip(f); + cairo_t *cr = pgtk_begin_cr_clip (f); /* If the glyph's background equals the color we normally draw - the bars cursor in, the bar cursor in its normal color is - invisible. Use the glyph's foreground color instead in this - case, on the assumption that the glyph's colors are chosen so - that the glyph is legible. */ - if (face->background == FRAME_X_OUTPUT(f)->cursor_color) + the bars cursor in, the bar cursor in its normal color is + invisible. Use the glyph's foreground color instead in this + case, on the assumption that the glyph's colors are chosen so + that the glyph is legible. */ + if (face->background == FRAME_X_OUTPUT (f)->cursor_color) color = face->foreground; else - color = FRAME_X_OUTPUT(f)->cursor_color; + color = FRAME_X_OUTPUT (f)->cursor_color; pgtk_clip_to_row (w, row, TEXT_AREA, cr); @@ -2651,10 +2722,10 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text x += cursor_glyph->pixel_width - width; pgtk_fill_rectangle (f, color, x, - WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), - width, row->height); + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), + width, row->height); } - else /* HBAR_CURSOR */ + else /* HBAR_CURSOR */ { int dummy_x, dummy_y, dummy_h; int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); @@ -2671,12 +2742,12 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text && cursor_glyph->pixel_width > w->phys_cursor_width - 1) x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; pgtk_fill_rectangle (f, color, x, - WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + - row->height - width), - w->phys_cursor_width - 1, width); + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + + row->height - width), + w->phys_cursor_width - 1, width); } - pgtk_end_cr_clip(f); + pgtk_end_cr_clip (f); } } @@ -2684,11 +2755,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text static void pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, - int y, enum text_cursor_kinds cursor_type, - int cursor_width, bool on_p, bool active_p) + int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) { - PGTK_TRACE("draw_window_cursor: %d, %d, %d, %d, %d, %d.", - x, y, cursor_type, cursor_width, on_p, active_p); + PGTK_TRACE ("draw_window_cursor: %d, %d, %d, %d, %d, %d.", + x, y, cursor_type, cursor_width, on_p, active_p); if (on_p) { w->phys_cursor_type = cursor_type; @@ -2741,7 +2812,8 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, } static void -pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, cairo_rectangle_t *dst_rect) +pgtk_copy_bits (struct frame *f, cairo_rectangle_t * src_rect, + cairo_rectangle_t * dst_rect) { PGTK_TRACE ("pgtk_copy_bits: %dx%d+%d+%d -> %dx%d+%d+%d", (int) src_rect->width, @@ -2749,32 +2821,34 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, cairo_rectangle_t (int) src_rect->x, (int) src_rect->y, (int) dst_rect->width, - (int) dst_rect->height, - (int) dst_rect->x, - (int) dst_rect->y); + (int) dst_rect->height, (int) dst_rect->x, (int) dst_rect->y); cairo_t *cr; - cairo_surface_t *surface; /* temporary surface */ - - surface = cairo_surface_create_similar(FRAME_CR_SURFACE(f), CAIRO_CONTENT_COLOR_ALPHA, - (int) src_rect->width, - (int) src_rect->height); - - cr = cairo_create(surface); - cairo_set_source_surface(cr, FRAME_CR_SURFACE(f), -src_rect->x, -src_rect->y); - cairo_rectangle(cr, 0, 0, src_rect->width, src_rect->height); - cairo_clip(cr); - cairo_paint(cr); - cairo_destroy(cr); + cairo_surface_t *surface; /* temporary surface */ + + surface = + cairo_surface_create_similar (FRAME_CR_SURFACE (f), + CAIRO_CONTENT_COLOR_ALPHA, + (int) src_rect->width, + (int) src_rect->height); + + cr = cairo_create (surface); + cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x, + -src_rect->y); + cairo_rectangle (cr, 0, 0, src_rect->width, src_rect->height); + cairo_clip (cr); + cairo_paint (cr); + cairo_destroy (cr); - cr = pgtk_begin_cr_clip(f); - cairo_set_source_surface(cr, surface, dst_rect->x, dst_rect->y); - cairo_rectangle(cr, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height); - cairo_clip(cr); - cairo_paint(cr); - pgtk_end_cr_clip(f); + cr = pgtk_begin_cr_clip (f); + cairo_set_source_surface (cr, surface, dst_rect->x, dst_rect->y); + cairo_rectangle (cr, dst_rect->x, dst_rect->y, dst_rect->width, + dst_rect->height); + cairo_clip (cr); + cairo_paint (cr); + pgtk_end_cr_clip (f); - cairo_surface_destroy(surface); + cairo_surface_destroy (surface); } /* Scroll part of the display as described by RUN. */ @@ -2797,7 +2871,7 @@ pgtk_scroll_run (struct window *w, struct run *run) if (to_y < from_y) { /* Scrolling up. Make sure we don't copy part of the mode - line at the bottom. */ + line at the bottom. */ if (from_y + run->height > bottom_y) height = bottom_y - from_y; else @@ -2806,7 +2880,7 @@ pgtk_scroll_run (struct window *w, struct run *run) else { /* Scrolling down. Make sure we don't copy over the mode line. - at the bottom. */ + at the bottom. */ if (to_y + run->height > bottom_y) height = bottom_y - to_y; else @@ -2821,7 +2895,7 @@ pgtk_scroll_run (struct window *w, struct run *run) { cairo_rectangle_t src_rect = { x, from_y, width, height }; cairo_rectangle_t dst_rect = { x, to_y, width, height }; - pgtk_copy_bits (f, &src_rect , &dst_rect); + pgtk_copy_bits (f, &src_rect, &dst_rect); } unblock_input (); @@ -2840,7 +2914,7 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file) if (STRINGP (file)) { /* Use gtk_window_set_icon_from_file () if available, - It's not restricted to bitmaps */ + It's not restricted to bitmaps */ if (xg_set_icon (f, file)) return false; @@ -2902,7 +2976,7 @@ pgtk_update_window_begin (struct window *w) hlinfo->mouse_face_defer = true; /* If F needs to be redrawn, simply forget about any prior mouse - highlighting. */ + highlighting. */ if (FRAME_GARBAGED_P (f)) hlinfo->mouse_face_window = Qnil; } @@ -2957,32 +3031,32 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) { pgtk_set_cr_source_with_color (f, color_first); cairo_rectangle (cr, x0, y0, 1, y1 - y0); - cairo_fill(cr); + cairo_fill (cr); pgtk_set_cr_source_with_color (f, color); cairo_rectangle (cr, x0 + 1, y0, x1 - x0 - 2, y1 - y0); - cairo_fill(cr); + cairo_fill (cr); pgtk_set_cr_source_with_color (f, color_last); cairo_rectangle (cr, x1 - 1, y0, 1, y1 - y0); - cairo_fill(cr); + cairo_fill (cr); } else if (x1 - x0 > y1 - y0 && y1 - y0 > 3) /* Horizontal. */ { pgtk_set_cr_source_with_color (f, color_first); cairo_rectangle (cr, x0, y0, x1 - x0, 1); - cairo_fill(cr); + cairo_fill (cr); pgtk_set_cr_source_with_color (f, color); cairo_rectangle (cr, x0, y0 + 1, x1 - x0, y1 - y0 - 2); - cairo_fill(cr); + cairo_fill (cr); pgtk_set_cr_source_with_color (f, color_last); cairo_rectangle (cr, x0, y1 - 1, x1 - x0, 1); - cairo_fill(cr); + cairo_fill (cr); } else { pgtk_set_cr_source_with_color (f, color); cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0); - cairo_fill(cr); + cairo_fill (cr); } pgtk_end_cr_clip (f); @@ -3003,7 +3077,7 @@ pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) static void pgtk_update_window_end (struct window *w, bool cursor_on_p, - bool mouse_face_overwritten_p) + bool mouse_face_overwritten_p) { if (!w->pseudo_window_p) { @@ -3043,12 +3117,12 @@ pgtk_update_window_end (struct window *w, bool cursor_on_p, static void pgtk_update_end (struct frame *f) { - GtkWidget *widget = FRAME_GTK_WIDGET(f); + GtkWidget *widget = FRAME_GTK_WIDGET (f); /* Mouse highlight may be displayed again. */ MOUSE_HL_INFO (f)->mouse_face_defer = false; gtk_widget_queue_draw (widget); - flip_cr_context(f); + flip_cr_context (f); } /* Return the current position of the mouse. @@ -3072,9 +3146,9 @@ pgtk_update_end (struct frame *f) movement. */ static void -pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, - enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - Time *timestamp) +pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object * bar_window, + enum scroll_bar_part *part, Lisp_Object * x, + Lisp_Object * y, Time * timestamp) { struct frame *f1; struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); @@ -3092,49 +3166,55 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, FOR_EACH_FRAME (tail, frame) if (FRAME_PGTK_P (XFRAME (frame)) && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp)) - XFRAME (frame)->mouse_moved = false; + XFRAME (frame)->mouse_moved = false; dpyinfo->last_mouse_scroll_bar = NULL; - if (gui_mouse_grabbed (dpyinfo)) { - /* 1.1. use last_mouse_frame as frame where the pointer is on. */ - f1 = dpyinfo->last_mouse_frame; - } else { - f1 = *fp; - /* 1.2. get frame where the pointer is on. */ - win = gtk_widget_get_window(FRAME_GTK_WIDGET(*fp)); - seat = gdk_display_get_default_seat(dpyinfo->gdpy); - device = gdk_seat_get_pointer(seat); - win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); - if (win != NULL) - f1 = pgtk_any_window_to_frame(win); - else { - // crossing display server? - f1 = SELECTED_FRAME(); + if (gui_mouse_grabbed (dpyinfo)) + { + /* 1.1. use last_mouse_frame as frame where the pointer is on. */ + f1 = dpyinfo->last_mouse_frame; + } + else + { + f1 = *fp; + /* 1.2. get frame where the pointer is on. */ + win = gtk_widget_get_window (FRAME_GTK_WIDGET (*fp)); + seat = gdk_display_get_default_seat (dpyinfo->gdpy); + device = gdk_seat_get_pointer (seat); + win = + gdk_window_get_device_position (win, device, &win_x, &win_y, &mask); + if (win != NULL) + f1 = pgtk_any_window_to_frame (win); + else + { + // crossing display server? + f1 = SELECTED_FRAME (); + } } - } /* 2. get the display and the device. */ - win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); + win = gtk_widget_get_window (FRAME_GTK_WIDGET (f1)); GdkDisplay *gdpy = gdk_window_get_display (win); - seat = gdk_display_get_default_seat(gdpy); - device = gdk_seat_get_pointer(seat); + seat = gdk_display_get_default_seat (gdpy); + device = gdk_seat_get_pointer (seat); /* 3. get x, y relative to edit window of the frame. */ - win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); - - if (f1 != NULL) { - dpyinfo = FRAME_DISPLAY_INFO (f1); - remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); - dpyinfo->last_mouse_glyph_frame = f1; - - *bar_window = Qnil; - *part = 0; - *fp = f1; - XSETINT (*x, win_x); - XSETINT (*y, win_y); - *timestamp = dpyinfo->last_mouse_movement_time; - } + win = gdk_window_get_device_position (win, device, &win_x, &win_y, &mask); + + if (f1 != NULL) + { + dpyinfo = FRAME_DISPLAY_INFO (f1); + remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); + dpyinfo->last_mouse_glyph_frame = f1; + + *bar_window = Qnil; + *part = 0; + *fp = f1; + XSETINT (*x, win_x); + XSETINT (*y, win_y); + *timestamp = dpyinfo->last_mouse_movement_time; + } unblock_input (); } @@ -3156,7 +3236,10 @@ pgtk_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd) { i = max_fringe_bmp; max_fringe_bmp = which + 20; - fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *)); + fringe_bmp = + (cairo_pattern_t **) xrealloc (fringe_bmp, + max_fringe_bmp * + sizeof (cairo_pattern_t *)); while (i < max_fringe_bmp) fringe_bmp[i++] = 0; } @@ -3199,7 +3282,7 @@ pgtk_destroy_fringe_bitmap (int which) static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, - enum glyph_row_area area, cairo_t *cr) + enum glyph_row_area area, cairo_t * cr) { int window_x, window_y, window_width; cairo_rectangle_int_t rect; @@ -3212,18 +3295,19 @@ pgtk_clip_to_row (struct window *w, struct glyph_row *row, rect.width = window_width; rect.height = row->visible_height; - cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height); - cairo_clip(cr); + cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height); + cairo_clip (cr); } static void -pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, - int src_x, int src_y, int width, int height, - int dest_x, int dest_y, bool overlay_p) +pgtk_cr_draw_image (struct frame *f, Emacs_GC * gc, cairo_pattern_t * image, + int src_x, int src_y, int width, int height, + int dest_x, int dest_y, bool overlay_p) { cairo_t *cr = pgtk_begin_cr_clip (f); - PGTK_TRACE("pgtk_cr_draw_image: 0: %d,%d,%d,%d,%d,%d,%d.", src_x, src_y, width, height, dest_x, dest_y, overlay_p); + PGTK_TRACE ("pgtk_cr_draw_image: 0: %d,%d,%d,%d,%d,%d,%d.", src_x, src_y, + width, height, dest_x, dest_y, overlay_p); if (overlay_p) cairo_rectangle (cr, dest_x, dest_y, width, height); @@ -3254,15 +3338,16 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, } static void -pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p) +pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, + struct draw_fringe_bitmap_params *p) { - PGTK_TRACE("draw_fringe_bitmap."); + PGTK_TRACE ("draw_fringe_bitmap."); struct frame *f = XFRAME (WINDOW_FRAME (w)); struct face *face = p->face; - cairo_t *cr = pgtk_begin_cr_clip(f); - cairo_save(cr); + cairo_t *cr = pgtk_begin_cr_clip (f); + cairo_save (cr); /* Must clip because of partially visible lines. */ pgtk_clip_to_row (w, row, ANY_AREA, cr); @@ -3270,87 +3355,96 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr if (p->bx >= 0 && !p->overlay_p) { /* In case the same realized face is used for fringes and - for something displayed in the text (e.g. face `region' on - mono-displays, the fill style may have been changed to - FillSolid in x_draw_glyph_string_background. */ - if (face->stipple) { - fill_background_by_face(f, face, p->bx, p->by, p->nx, p->ny); - } else { - pgtk_set_cr_source_with_color(f, face->background); - cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); - cairo_fill(cr); - } + for something displayed in the text (e.g. face `region' on + mono-displays, the fill style may have been changed to + FillSolid in x_draw_glyph_string_background. */ + if (face->stipple) + { + fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny); + } + else + { + pgtk_set_cr_source_with_color (f, face->background); + cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); + cairo_fill (cr); + } } - PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); + PGTK_TRACE ("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); if (p->which && p->which < max_fringe_bmp) { Emacs_GC gcv; - PGTK_TRACE("cursor_p=%d.", p->cursor_p); - PGTK_TRACE("overlay_p_p=%d.", p->overlay_p); - PGTK_TRACE("background=%08lx.", face->background); - PGTK_TRACE("cursor_color=%08lx.", FRAME_X_OUTPUT(f)->cursor_color); - PGTK_TRACE("foreground=%08lx.", face->foreground); + PGTK_TRACE ("cursor_p=%d.", p->cursor_p); + PGTK_TRACE ("overlay_p_p=%d.", p->overlay_p); + PGTK_TRACE ("background=%08lx.", face->background); + PGTK_TRACE ("cursor_color=%08lx.", FRAME_X_OUTPUT (f)->cursor_color); + PGTK_TRACE ("foreground=%08lx.", face->foreground); gcv.foreground = (p->cursor_p - ? (p->overlay_p ? face->background - : FRAME_X_OUTPUT(f)->cursor_color) - : face->foreground); + ? (p->overlay_p ? face->background + : FRAME_X_OUTPUT (f)->cursor_color) + : face->foreground); gcv.background = face->background; pgtk_cr_draw_image (f, &gcv, fringe_bmp[p->which], 0, p->dh, - p->wd, p->h, p->x, p->y, p->overlay_p); + p->wd, p->h, p->x, p->y, p->overlay_p); } - cairo_restore(cr); + cairo_restore (cr); } static struct atimer *hourglass_atimer = NULL; static int hourglass_enter_count = 0; -static void hourglass_cb(struct atimer *timer) +static void +hourglass_cb (struct atimer *timer) { - /*NOP*/ -} + /*NOP*/} static void -pgtk_show_hourglass(struct frame *f) +pgtk_show_hourglass (struct frame *f) { - struct pgtk_output *x = FRAME_X_OUTPUT(f); + struct pgtk_output *x = FRAME_X_OUTPUT (f); if (x->hourglass_widget != NULL) - gtk_widget_destroy(x->hourglass_widget); - x->hourglass_widget = gtk_event_box_new(); /* gtk_event_box is GDK_INPUT_ONLY. */ - gtk_widget_set_has_window(x->hourglass_widget, true); - gtk_fixed_put(GTK_FIXED(FRAME_GTK_WIDGET(f)), x->hourglass_widget, 0, 0); - gtk_widget_show(x->hourglass_widget); - gtk_widget_set_size_request(x->hourglass_widget, 30000, 30000); - gdk_window_raise(gtk_widget_get_window(x->hourglass_widget)); - gdk_window_set_cursor(gtk_widget_get_window(x->hourglass_widget), x->hourglass_cursor); + gtk_widget_destroy (x->hourglass_widget); + x->hourglass_widget = gtk_event_box_new (); /* gtk_event_box is GDK_INPUT_ONLY. */ + gtk_widget_set_has_window (x->hourglass_widget, true); + gtk_fixed_put (GTK_FIXED (FRAME_GTK_WIDGET (f)), x->hourglass_widget, 0, 0); + gtk_widget_show (x->hourglass_widget); + gtk_widget_set_size_request (x->hourglass_widget, 30000, 30000); + gdk_window_raise (gtk_widget_get_window (x->hourglass_widget)); + gdk_window_set_cursor (gtk_widget_get_window (x->hourglass_widget), + x->hourglass_cursor); /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ - if (hourglass_enter_count++ == 0) { - struct timespec ts = make_timespec(0, 50 * 1000 * 1000); - if (hourglass_atimer != NULL) - cancel_atimer(hourglass_atimer); - hourglass_atimer = start_atimer(ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); - } + if (hourglass_enter_count++ == 0) + { + struct timespec ts = make_timespec (0, 50 * 1000 * 1000); + if (hourglass_atimer != NULL) + cancel_atimer (hourglass_atimer); + hourglass_atimer = + start_atimer (ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); + } /* Cursor frequently stops animation. gtk's bug? */ } static void -pgtk_hide_hourglass(struct frame *f) +pgtk_hide_hourglass (struct frame *f) { - struct pgtk_output *x = FRAME_X_OUTPUT(f); - if (--hourglass_enter_count == 0) { - if (hourglass_atimer != NULL) { - cancel_atimer(hourglass_atimer); - hourglass_atimer = NULL; + struct pgtk_output *x = FRAME_X_OUTPUT (f); + if (--hourglass_enter_count == 0) + { + if (hourglass_atimer != NULL) + { + cancel_atimer (hourglass_atimer); + hourglass_atimer = NULL; + } + } + if (x->hourglass_widget != NULL) + { + gtk_widget_destroy (x->hourglass_widget); + x->hourglass_widget = NULL; } - } - if (x->hourglass_widget != NULL) { - gtk_widget_destroy(x->hourglass_widget); - x->hourglass_widget = NULL; - } } /* Flushes changes to display. */ @@ -3361,8 +3455,7 @@ pgtk_flush_display (struct frame *f) extern frame_parm_handler pgtk_frame_parm_handlers[]; -static struct redisplay_interface pgtk_redisplay_interface = -{ +static struct redisplay_interface pgtk_redisplay_interface = { pgtk_frame_parm_handlers, gui_produce_glyphs, gui_write_glyphs, @@ -3387,7 +3480,7 @@ static struct redisplay_interface pgtk_redisplay_interface = pgtk_draw_window_cursor, pgtk_draw_vertical_window_border, pgtk_draw_window_divider, - NULL, // pgtk_shift_glyphs_for_insert, + NULL, // pgtk_shift_glyphs_for_insert, pgtk_show_hourglass, pgtk_hide_hourglass, pgtk_default_font_parameter, @@ -3396,7 +3489,7 @@ static struct redisplay_interface pgtk_redisplay_interface = static void pgtk_redraw_scroll_bars (struct frame *f) { - PGTK_TRACE("pgtk_redraw_scroll_bars"); + PGTK_TRACE ("pgtk_redraw_scroll_bars"); } void @@ -3405,9 +3498,9 @@ pgtk_clear_frame (struct frame *f) External (hook): Erase the entire frame -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_clear_frame"); - /* comes on initial frame because we have - after-make-frame-functions = select-frame */ + PGTK_TRACE ("pgtk_clear_frame"); + /* comes on initial frame because we have + after-make-frame-functions = select-frame */ if (!FRAME_DEFAULT_FACE (f)) return; @@ -3415,7 +3508,7 @@ pgtk_clear_frame (struct frame *f) block_input (); - pgtk_clear_area(f, 0, 0, FRAME_PIXEL_WIDTH(f), FRAME_PIXEL_HEIGHT(f)); + pgtk_clear_area (f, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); /* as of 2006/11 or so this is now needed */ pgtk_redraw_scroll_bars (f); @@ -3425,17 +3518,18 @@ pgtk_clear_frame (struct frame *f) /* Invert the middle quarter of the frame for .15 sec. */ static void -recover_from_visible_bell(struct atimer *timer) +recover_from_visible_bell (struct atimer *timer) { struct frame *f = timer->client_data; - if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { - cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); - FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; - } + if (FRAME_X_OUTPUT (f)->cr_surface_visible_bell != NULL) + { + cairo_surface_destroy (FRAME_X_OUTPUT (f)->cr_surface_visible_bell); + FRAME_X_OUTPUT (f)->cr_surface_visible_bell = NULL; + } - if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) - FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL) + FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; } static void @@ -3444,18 +3538,19 @@ pgtk_flash (struct frame *f) block_input (); { - cairo_surface_t *surface_orig = FRAME_CR_SURFACE(f); + cairo_surface_t *surface_orig = FRAME_CR_SURFACE (f); - int width = cairo_image_surface_get_width(surface_orig); - int height = cairo_image_surface_get_height(surface_orig); - cairo_surface_t *surface = cairo_surface_create_similar(surface_orig, CAIRO_CONTENT_COLOR_ALPHA, - width, height); + int width = cairo_image_surface_get_width (surface_orig); + int height = cairo_image_surface_get_height (surface_orig); + cairo_surface_t *surface = + cairo_surface_create_similar (surface_orig, CAIRO_CONTENT_COLOR_ALPHA, + width, height); - cairo_t *cr = cairo_create(surface); - cairo_set_source_surface(cr, surface_orig, 0, 0); - cairo_rectangle(cr, 0, 0, width, height); - cairo_clip(cr); - cairo_paint(cr); + cairo_t *cr = cairo_create (surface); + cairo_set_source_surface (cr, surface_orig, 0, 0); + cairo_rectangle (cr, 0, 0, width, height); + cairo_clip (cr); + cairo_paint (cr); cairo_set_source_rgb (cr, 1, 1, 1); cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); @@ -3470,7 +3565,8 @@ pgtk_flash (struct frame *f) int flash_height = FRAME_LINE_HEIGHT (f); /* These will be the left and right margins of the rectangles. */ int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); - int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); + int flash_right = + FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); int width = flash_right - flash_left; /* If window is tall, flash top and bottom line. */ @@ -3494,14 +3590,16 @@ pgtk_flash (struct frame *f) flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); - FRAME_X_OUTPUT(f)->cr_surface_visible_bell = surface; + FRAME_X_OUTPUT (f)->cr_surface_visible_bell = surface; { struct timespec delay = make_timespec (0, 50 * 1000 * 1000); - if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) { - cancel_atimer(FRAME_X_OUTPUT(f)->atimer_visible_bell); - FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; - } - FRAME_X_OUTPUT(f)->atimer_visible_bell = start_atimer(ATIMER_RELATIVE, delay, recover_from_visible_bell, f); + if (FRAME_X_OUTPUT (f)->atimer_visible_bell != NULL) + { + cancel_atimer (FRAME_X_OUTPUT (f)->atimer_visible_bell); + FRAME_X_OUTPUT (f)->atimer_visible_bell = NULL; + } + FRAME_X_OUTPUT (f)->atimer_visible_bell = + start_atimer (ATIMER_RELATIVE, delay, recover_from_visible_bell, f); } #undef XFillRectangle @@ -3518,12 +3616,12 @@ pgtk_ring_bell (struct frame *f) { if (visible_bell) { - pgtk_flash(f); + pgtk_flash (f); } else { block_input (); - gtk_widget_error_bell(FRAME_GTK_WIDGET(f)); + gtk_widget_error_bell (FRAME_GTK_WIDGET (f)); unblock_input (); } } @@ -3539,51 +3637,55 @@ pgtk_ring_bell (struct frame *f) static int pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) { - PGTK_TRACE("pgtk_read_socket: enter."); + PGTK_TRACE ("pgtk_read_socket: enter."); GMainContext *context; bool context_acquired = false; int count; - count = evq_flush(hold_quit); - if (count > 0) { - PGTK_TRACE("pgtk_read_socket: leave(1)."); - return count; - } + count = evq_flush (hold_quit); + if (count > 0) + { + PGTK_TRACE ("pgtk_read_socket: leave(1)."); + return count; + } context = g_main_context_default (); context_acquired = g_main_context_acquire (context); block_input (); - PGTK_TRACE("pgtk_read_socket: 3: errno=%d.", errno); + PGTK_TRACE ("pgtk_read_socket: 3: errno=%d.", errno); - if (context_acquired) { - PGTK_TRACE("pgtk_read_socket: 4.1: acquired."); - while (g_main_context_pending (context)) { - PGTK_TRACE("pgtk_read_socket: 4: dispatch..."); - g_main_context_dispatch (context); - PGTK_TRACE("pgtk_read_socket: 5: dispatch... done."); + if (context_acquired) + { + PGTK_TRACE ("pgtk_read_socket: 4.1: acquired."); + while (g_main_context_pending (context)) + { + PGTK_TRACE ("pgtk_read_socket: 4: dispatch..."); + g_main_context_dispatch (context); + PGTK_TRACE ("pgtk_read_socket: 5: dispatch... done."); + } } - } - PGTK_TRACE("pgtk_read_socket: 7: errno=%d.", errno); + PGTK_TRACE ("pgtk_read_socket: 7: errno=%d.", errno); unblock_input (); if (context_acquired) g_main_context_release (context); - count = evq_flush(hold_quit); - if (count > 0) { - PGTK_TRACE("pgtk_read_socket: leave(2)."); - return count; - } + count = evq_flush (hold_quit); + if (count > 0) + { + PGTK_TRACE ("pgtk_read_socket: leave(2)."); + return count; + } - PGTK_TRACE("pgtk_read_socket: leave(3)."); + PGTK_TRACE ("pgtk_read_socket: leave(3)."); return 0; } int -pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, - struct timespec *timeout, sigset_t *sigmask) +pgtk_select (int fds_lim, fd_set * rfds, fd_set * wfds, fd_set * efds, + struct timespec *timeout, sigset_t * sigmask) { fd_set all_rfds, all_wfds; struct timespec tmo; @@ -3599,14 +3701,15 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, int i, nfds, tmo_in_millisec, must_free = 0; bool need_to_dispatch; - PGTK_TRACE("pgtk_select: enter."); + PGTK_TRACE ("pgtk_select: enter."); - if (event_q.nr >= 1) { - PGTK_TRACE("pgtk_select: raise."); - raise(SIGIO); - errno = EINTR; - return -1; - } + if (event_q.nr >= 1) + { + PGTK_TRACE ("pgtk_select: raise."); + raise (SIGIO); + errno = EINTR; + return -1; + } context = g_main_context_default (); context_acquired = g_main_context_acquire (context); @@ -3615,41 +3718,47 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, Note that, as implemented, this failure is completely silent: there is no feedback to the caller. */ - if (rfds) all_rfds = *rfds; - else FD_ZERO (&all_rfds); - if (wfds) all_wfds = *wfds; - else FD_ZERO (&all_wfds); + if (rfds) + all_rfds = *rfds; + else + FD_ZERO (&all_rfds); + if (wfds) + all_wfds = *wfds; + else + FD_ZERO (&all_wfds); n_gfds = (context_acquired ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, - gfds, gfds_size) - : -1); + gfds, gfds_size) : -1); if (gfds_size < n_gfds) { /* Avoid using SAFE_NALLOCA, as that implicitly refers to the - current thread. Using xnmalloc avoids thread-switching - problems here. */ + current thread. Using xnmalloc avoids thread-switching + problems here. */ gfds = xnmalloc (n_gfds, sizeof *gfds); must_free = 1; gfds_size = n_gfds; - n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, - gfds, gfds_size); + n_gfds = + g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, + gfds_size); } for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) - { - FD_SET (gfds[i].fd, &all_rfds); - if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; - } + { + FD_SET (gfds[i].fd, &all_rfds); + if (gfds[i].fd > max_fds) + max_fds = gfds[i].fd; + } if (gfds[i].events & G_IO_OUT) - { - FD_SET (gfds[i].fd, &all_wfds); - if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; - have_wfds = true; - } + { + FD_SET (gfds[i].fd, &all_wfds); + if (gfds[i].fd > max_fds) + max_fds = gfds[i].fd; + have_wfds = true; + } } if (must_free) @@ -3683,26 +3792,30 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, else if (nfds > 0) { for (i = 0; i < fds_lim; ++i) - { - if (FD_ISSET (i, &all_rfds)) - { - if (rfds && FD_ISSET (i, rfds)) ++retval; - else ++our_fds; - } - else if (rfds) - FD_CLR (i, rfds); - - if (have_wfds && FD_ISSET (i, &all_wfds)) - { - if (wfds && FD_ISSET (i, wfds)) ++retval; - else ++our_fds; - } - else if (wfds) - FD_CLR (i, wfds); - - if (efds && FD_ISSET (i, efds)) - ++retval; - } + { + if (FD_ISSET (i, &all_rfds)) + { + if (rfds && FD_ISSET (i, rfds)) + ++retval; + else + ++our_fds; + } + else if (rfds) + FD_CLR (i, rfds); + + if (have_wfds && FD_ISSET (i, &all_wfds)) + { + if (wfds && FD_ISSET (i, wfds)) + ++retval; + else + ++our_fds; + } + else if (wfds) + FD_CLR (i, wfds); + + if (efds && FD_ISSET (i, efds)) + ++retval; + } } /* If Gtk+ is in use eventually gtk_main_iteration will be called, @@ -3711,19 +3824,20 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, if (need_to_dispatch && context_acquired) { int pselect_errno = errno; - PGTK_TRACE("retval=%d.", retval); - PGTK_TRACE("need_to_dispatch=%d.", need_to_dispatch); - PGTK_TRACE("context_acquired=%d.", context_acquired); - PGTK_TRACE("pselect_errno=%d.", pselect_errno); + PGTK_TRACE ("retval=%d.", retval); + PGTK_TRACE ("need_to_dispatch=%d.", need_to_dispatch); + PGTK_TRACE ("context_acquired=%d.", context_acquired); + PGTK_TRACE ("pselect_errno=%d.", pselect_errno); /* Prevent g_main_dispatch recursion, that would occur without block_input wrapper, because event handlers call unblock_input. Event loop recursion was causing Bug#15801. */ block_input (); - while (g_main_context_pending (context)) { - PGTK_TRACE("dispatch..."); - g_main_context_dispatch (context); - PGTK_TRACE("dispatch... done."); - } + while (g_main_context_pending (context)) + { + PGTK_TRACE ("dispatch..."); + g_main_context_dispatch (context); + PGTK_TRACE ("dispatch... done."); + } unblock_input (); errno = pselect_errno; } @@ -3738,7 +3852,7 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, errno = EINTR; } - PGTK_TRACE("pgtk_select: leave."); + PGTK_TRACE ("pgtk_select: leave."); return retval; } @@ -3756,17 +3870,18 @@ pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part, EVENT_INIT (inev.ie); - inev.ie.kind = horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : SCROLL_BAR_CLICK_EVENT; + inev.ie.kind = + horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : SCROLL_BAR_CLICK_EVENT; inev.ie.frame_or_window = window; inev.ie.arg = Qnil; inev.ie.timestamp = 0; inev.ie.code = 0; inev.ie.part = part; - inev.ie.x = make_fixnum(portion); - inev.ie.y = make_fixnum(whole); + inev.ie.x = make_fixnum (portion); + inev.ie.y = make_fixnum (whole); inev.ie.modifiers = 0; - evq_enqueue(&inev); + evq_enqueue (&inev); } @@ -3774,21 +3889,20 @@ pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part, bar widget. DATA is a pointer to the scroll_bar structure. */ static gboolean -xg_scroll_callback (GtkRange *range, - GtkScrollType scroll, - gdouble value, - gpointer user_data) +xg_scroll_callback (GtkRange * range, + GtkScrollType scroll, gdouble value, gpointer user_data) { int whole = 0, portion = 0; struct scroll_bar *bar = user_data; enum scroll_bar_part part = scroll_bar_nowhere; GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range)); - PGTK_TRACE("xg_scroll_callback:"); + PGTK_TRACE ("xg_scroll_callback:"); - if (xg_ignore_gtk_scrollbar) return false; - PGTK_TRACE("xg_scroll_callback: not ignored."); + if (xg_ignore_gtk_scrollbar) + return false; + PGTK_TRACE ("xg_scroll_callback: not ignored."); - PGTK_TRACE("xg_scroll_callback: scroll=%u.", scroll); + PGTK_TRACE ("xg_scroll_callback: scroll=%u.", scroll); switch (scroll) { case GTK_SCROLL_JUMP: @@ -3801,9 +3915,9 @@ xg_scroll_callback (GtkRange *range, if (bar->horizontal) { part = scroll_bar_horizontal_handle; - whole = (int)(gtk_adjustment_get_upper (adj) - - gtk_adjustment_get_page_size (adj)); - portion = min ((int)value, whole); + whole = (int) (gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj)); + portion = min ((int) value, whole); bar->dragging = portion; } else @@ -3811,14 +3925,13 @@ xg_scroll_callback (GtkRange *range, part = scroll_bar_handle; whole = gtk_adjustment_get_upper (adj) - gtk_adjustment_get_page_size (adj); - portion = min ((int)value, whole); + portion = min ((int) value, whole); bar->dragging = portion; } } break; case GTK_SCROLL_STEP_BACKWARD: - part = (bar->horizontal - ? scroll_bar_left_arrow : scroll_bar_up_arrow); + part = (bar->horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow); bar->dragging = -1; break; case GTK_SCROLL_STEP_FORWARD: @@ -3840,7 +3953,8 @@ xg_scroll_callback (GtkRange *range, break; } - PGTK_TRACE("xg_scroll_callback: part=%u, scroll_bar_nowhere=%d.", part, scroll_bar_nowhere); + PGTK_TRACE ("xg_scroll_callback: part=%u, scroll_bar_nowhere=%d.", part, + scroll_bar_nowhere); if (part != scroll_bar_nowhere) { window_being_scrolled = bar->window; @@ -3854,17 +3968,17 @@ xg_scroll_callback (GtkRange *range, /* Callback for button release. Sets dragging to -1 when dragging is done. */ static gboolean -xg_end_scroll_callback (GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) +xg_end_scroll_callback (GtkWidget * widget, + GdkEventButton * event, gpointer user_data) { struct scroll_bar *bar = user_data; - PGTK_TRACE("xg_end_scroll_callback:"); + PGTK_TRACE ("xg_end_scroll_callback:"); bar->dragging = -1; if (WINDOWP (window_being_scrolled)) { pgtk_send_scroll_bar_event (window_being_scrolled, - scroll_bar_end_scroll, 0, 0, bar->horizontal); + scroll_bar_end_scroll, 0, 0, + bar->horizontal); window_being_scrolled = Qnil; } @@ -3884,13 +3998,13 @@ x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) block_input (); xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback), - G_CALLBACK (xg_end_scroll_callback), - scroll_bar_name); + G_CALLBACK (xg_end_scroll_callback), scroll_bar_name); unblock_input (); } static void -x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) +x_create_horizontal_toolkit_scroll_bar (struct frame *f, + struct scroll_bar *bar) { const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME; @@ -3905,13 +4019,16 @@ x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) displaying PORTION out of a whole WHOLE, and our position POSITION. */ static void -x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) +x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, + int position, int whole) { xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); } static void -x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) +x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, + int portion, int position, + int whole) { xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole); } @@ -3965,7 +4082,7 @@ x_scroll_bar_create (struct window *w, int top, int left, else xg_update_scrollbar_pos (f, bar->x_window, top, left, width, max (height, 1)); - } + } unblock_input (); return bar; @@ -3997,7 +4114,8 @@ x_scroll_bar_remove (struct scroll_bar *bar) create one. */ static void -pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position) +pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, + int position) { struct frame *f = XFRAME (w->frame); Lisp_Object barobj; @@ -4011,11 +4129,16 @@ pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, int posi height = window_height; left = WINDOW_SCROLL_BAR_AREA_X (w); width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); - PGTK_TRACE("pgtk_set_vertical_scroll_bar: has_vertical_scroll_bar: %d", WINDOW_HAS_VERTICAL_SCROLL_BAR(w)); - PGTK_TRACE("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", WINDOW_CONFIG_SCROLL_BAR_WIDTH(w)); - PGTK_TRACE("pgtk_set_vertical_scroll_bar: scroll_bar_width: %d", w->scroll_bar_width); - PGTK_TRACE("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w))); - PGTK_TRACE("pgtk_set_vertical_scroll_bar: %dx%d+%d+%d", width, height, left, top); + PGTK_TRACE ("pgtk_set_vertical_scroll_bar: has_vertical_scroll_bar: %d", + WINDOW_HAS_VERTICAL_SCROLL_BAR (w)); + PGTK_TRACE ("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", + WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)); + PGTK_TRACE ("pgtk_set_vertical_scroll_bar: scroll_bar_width: %d", + w->scroll_bar_width); + PGTK_TRACE ("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", + FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w))); + PGTK_TRACE ("pgtk_set_vertical_scroll_bar: %dx%d+%d+%d", width, height, + left, top); /* Does the scroll bar exist yet? */ if (NILP (w->vertical_scroll_bar)) @@ -4075,7 +4198,8 @@ pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, int posi static void -pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) +pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole, + int position) { struct frame *f = XFRAME (w->frame); Lisp_Object barobj; @@ -4131,9 +4255,10 @@ pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int po for them on the frame, we have to clear "under" them. */ if (width > 0 && height > 0) pgtk_clear_area (f, - WINDOW_LEFT_EDGE_X (w), top, - pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); - xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left, + WINDOW_LEFT_EDGE_X (w), top, + pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), + height); + xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left, width, height); } @@ -4224,19 +4349,20 @@ pgtk_redeem_scroll_bar (struct window *w) else XSCROLL_BAR (bar->prev)->next = bar->next; - if (! NILP (bar->next)) + if (!NILP (bar->next)) XSCROLL_BAR (bar->next)->prev = bar->prev; bar->next = FRAME_SCROLL_BARS (f); bar->prev = Qnil; XSETVECTOR (barobj, bar); fset_scroll_bars (f, barobj); - if (! NILP (bar->next)) + if (!NILP (bar->next)) XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); } - horizontal: - if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) +horizontal: + if (!NILP (w->horizontal_scroll_bar) + && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) { bar = XSCROLL_BAR (w->horizontal_scroll_bar); /* Unlink it from the condemned list. */ @@ -4259,14 +4385,14 @@ pgtk_redeem_scroll_bar (struct window *w) else XSCROLL_BAR (bar->prev)->next = bar->next; - if (! NILP (bar->next)) + if (!NILP (bar->next)) XSCROLL_BAR (bar->next)->prev = bar->prev; bar->next = FRAME_SCROLL_BARS (f); bar->prev = Qnil; XSETVECTOR (barobj, bar); fset_scroll_bars (f, barobj); - if (! NILP (bar->next)) + if (!NILP (bar->next)) XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); } } @@ -4285,7 +4411,7 @@ pgtk_judge_scroll_bars (struct frame *f) more events on the hapless scroll bars. */ fset_condemned_scroll_bars (f, Qnil); - for (; ! NILP (bar); bar = next) + for (; !NILP (bar); bar = next) { struct scroll_bar *b = XSCROLL_BAR (bar); @@ -4299,36 +4425,38 @@ pgtk_judge_scroll_bars (struct frame *f) and they should get garbage-collected. */ } -static void set_fullscreen_state(struct frame *f) -{ - GtkWindow *widget = GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)); - switch (f->want_fullscreen) { - case FULLSCREEN_NONE: - PGTK_TRACE("pgtk_fullscreen_hook: none."); - gtk_window_unfullscreen(widget); - gtk_window_unmaximize(widget); - store_frame_param(f, Qfullscreen, Qnil); - break; - - case FULLSCREEN_BOTH: - PGTK_TRACE("pgtk_fullscreen_hook: both."); - gtk_window_unmaximize(widget); - gtk_window_fullscreen(widget); - store_frame_param(f, Qfullscreen, Qfullboth); - break; - - case FULLSCREEN_MAXIMIZED: - PGTK_TRACE("pgtk_fullscreen_hook: maximized."); - gtk_window_unfullscreen(widget); - gtk_window_maximize(widget); - store_frame_param(f, Qfullscreen, Qmaximized); - break; - - case FULLSCREEN_WIDTH: - case FULLSCREEN_HEIGHT: - PGTK_TRACE("pgtk_fullscreen_hook: width or height."); - /* Not supported by gtk. Ignore them.*/ - } +static void +set_fullscreen_state (struct frame *f) +{ + GtkWindow *widget = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)); + switch (f->want_fullscreen) + { + case FULLSCREEN_NONE: + PGTK_TRACE ("pgtk_fullscreen_hook: none."); + gtk_window_unfullscreen (widget); + gtk_window_unmaximize (widget); + store_frame_param (f, Qfullscreen, Qnil); + break; + + case FULLSCREEN_BOTH: + PGTK_TRACE ("pgtk_fullscreen_hook: both."); + gtk_window_unmaximize (widget); + gtk_window_fullscreen (widget); + store_frame_param (f, Qfullscreen, Qfullboth); + break; + + case FULLSCREEN_MAXIMIZED: + PGTK_TRACE ("pgtk_fullscreen_hook: maximized."); + gtk_window_unfullscreen (widget); + gtk_window_maximize (widget); + store_frame_param (f, Qfullscreen, Qmaximized); + break; + + case FULLSCREEN_WIDTH: + case FULLSCREEN_HEIGHT: + PGTK_TRACE ("pgtk_fullscreen_hook: width or height."); + /* Not supported by gtk. Ignore them. */ + } f->want_fullscreen = FULLSCREEN_NONE; } @@ -4336,11 +4464,11 @@ static void set_fullscreen_state(struct frame *f) static void pgtk_fullscreen_hook (struct frame *f) { - PGTK_TRACE("pgtk_fullscreen_hook:"); + PGTK_TRACE ("pgtk_fullscreen_hook:"); if (FRAME_VISIBLE_P (f)) { block_input (); - set_fullscreen_state(f); + set_fullscreen_state (f); unblock_input (); } } @@ -4368,17 +4496,19 @@ pgtk_delete_terminal (struct terminal *terminal) xg_display_close (dpyinfo->gdpy); /* Do not close the connection here because it's already closed - by X(t)CloseDisplay (Bug#18403). */ + by X(t)CloseDisplay (Bug#18403). */ dpyinfo->gdpy = NULL; } + delete_keyboard_wait_descriptor (0); + pgtk_delete_display (dpyinfo); unblock_input (); } /* Store F's background color into *BGCOLOR. */ static void -pgtk_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor) +pgtk_query_frame_background_color (struct frame *f, Emacs_Color * bgcolor) { bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f); pgtk_query_color (f, bgcolor); @@ -4399,7 +4529,7 @@ pgtk_focus_frame (struct frame *f, bool noactivate) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); + GtkWidget *wid = FRAME_GTK_OUTER_WIDGET (f); if (dpyinfo->x_focus_frame != f) { @@ -4410,7 +4540,8 @@ pgtk_focus_frame (struct frame *f, bool noactivate) } -static void set_opacity_recursively (GtkWidget *w, gpointer data) +static void +set_opacity_recursively (GtkWidget * w, gpointer data) { gtk_widget_set_opacity (w, *(double *) data); if (GTK_IS_CONTAINER (w)) @@ -4476,18 +4607,24 @@ frame_highlight (struct frame *f) using that same window-manager binary for ever. Let's not crash just because of this (bug#9310). */ - char *css = g_strdup_printf("decoration { border: solid %dpx #%06x; }", f->border_width, (unsigned int) FRAME_X_OUTPUT(f)->border_pixel & 0x00ffffff); - GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); - GtkCssProvider *css_provider = gtk_css_provider_new(); - gtk_css_provider_load_from_data(css_provider, css, -1, NULL); - gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - g_object_unref(css_provider); - g_free(css); - - GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; - FRAME_X_OUTPUT(f)->border_color_css_provider = css_provider; + char *css = + g_strdup_printf ("decoration { border: solid %dpx #%06x; }", + f->border_width, + (unsigned int) FRAME_X_OUTPUT (f)-> + border_pixel & 0x00ffffff); + GtkStyleContext *ctxt = + gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + GtkCssProvider *css_provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (css_provider, css, -1, NULL); + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + g_object_unref (css_provider); + g_free (css); + + GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; + FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider; if (old != NULL) - gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); unblock_input (); gui_update_cursor (f, true); @@ -4504,18 +4641,22 @@ frame_unhighlight (struct frame *f) block_input (); /* Same as above for XSetWindowBorder (bug#9310). */ - char *css = g_strdup_printf("decoration { border: dotted %dpx #ffffff; }", f->border_width); - GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); - GtkCssProvider *css_provider = gtk_css_provider_new(); - gtk_css_provider_load_from_data(css_provider, css, -1, NULL); - gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); - g_object_unref(css_provider); - g_free(css); - - GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; - FRAME_X_OUTPUT(f)->border_color_css_provider = css_provider; + char *css = + g_strdup_printf ("decoration { border: dotted %dpx #ffffff; }", + f->border_width); + GtkStyleContext *ctxt = + gtk_widget_get_style_context (FRAME_GTK_OUTER_WIDGET (f)); + GtkCssProvider *css_provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (css_provider, css, -1, NULL); + gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + g_object_unref (css_provider); + g_free (css); + + GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider; + FRAME_X_OUTPUT (f)->border_color_css_provider = css_provider; if (old != NULL) - gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); + gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old)); unblock_input (); gui_update_cursor (f, true); @@ -4534,7 +4675,7 @@ pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo) = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) : dpyinfo->x_focus_frame); - if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) + if (!FRAME_LIVE_P (dpyinfo->highlight_frame)) { fset_focus_frame (dpyinfo->x_focus_frame, Qnil); dpyinfo->highlight_frame = dpyinfo->x_focus_frame; @@ -4574,7 +4715,8 @@ x_toggle_visible_pointer (struct frame *f, bool invisible) cursor = FRAME_DISPLAY_INFO (f)->invisible_cursor; else cursor = f->output_data.pgtk->current_cursor; - gdk_window_set_cursor(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), cursor); + gdk_window_set_cursor (gtk_widget_get_window (FRAME_GTK_WIDGET (f)), + cursor); f->pointer_invisible = invisible; } @@ -4582,7 +4724,8 @@ static void x_setup_pointer_blanking (struct pgtk_display_info *dpyinfo) { dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer; - dpyinfo->invisible_cursor = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_BLANK_CURSOR); + dpyinfo->invisible_cursor = + gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_BLANK_CURSOR); } static void @@ -4608,14 +4751,16 @@ x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) if (frame != dpyinfo->x_focus_frame) { /* Set this before calling other routines, so that they see - the correct value of x_focus_frame. */ + the correct value of x_focus_frame. */ dpyinfo->x_focus_frame = frame; if (old_focus && old_focus->auto_lower) - gdk_window_lower (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (old_focus))); + gdk_window_lower (gtk_widget_get_window + (FRAME_GTK_OUTER_WIDGET (old_focus))); if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) - gdk_window_raise (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); + gdk_window_raise (gtk_widget_get_window + (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); } pgtk_frame_rehighlight (dpyinfo); @@ -4664,8 +4809,10 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->set_bitmap_icon_hook = pgtk_bitmap_icon; terminal->implicit_set_name_hook = pgtk_implicitly_set_name; terminal->iconify_frame_hook = pgtk_iconify_frame; - terminal->set_scroll_bar_default_width_hook = pgtk_set_scroll_bar_default_width; - terminal->set_scroll_bar_default_height_hook = pgtk_set_scroll_bar_default_height; + terminal->set_scroll_bar_default_width_hook = + pgtk_set_scroll_bar_default_width; + terminal->set_scroll_bar_default_height_hook = + pgtk_set_scroll_bar_default_height; terminal->set_window_size_hook = pgtk_set_window_size; terminal->query_colors = pgtk_query_colors; terminal->get_focus_frame = x_get_focus_frame; @@ -4678,42 +4825,45 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) return terminal; } -struct pgtk_window_is_of_frame_recursive_t { +struct pgtk_window_is_of_frame_recursive_t +{ GdkWindow *window; bool result; }; static void -pgtk_window_is_of_frame_recursive(GtkWidget *widget, gpointer data) +pgtk_window_is_of_frame_recursive (GtkWidget * widget, gpointer data) { struct pgtk_window_is_of_frame_recursive_t *datap = data; if (datap->result) return; - if (gtk_widget_get_window(widget) == datap->window) { - datap->result = true; - return; - } + if (gtk_widget_get_window (widget) == datap->window) + { + datap->result = true; + return; + } - if (GTK_IS_CONTAINER(widget)) - gtk_container_foreach(GTK_CONTAINER(widget), pgtk_window_is_of_frame_recursive, datap); + if (GTK_IS_CONTAINER (widget)) + gtk_container_foreach (GTK_CONTAINER (widget), + pgtk_window_is_of_frame_recursive, datap); } static bool -pgtk_window_is_of_frame(struct frame *f, GdkWindow *window) +pgtk_window_is_of_frame (struct frame *f, GdkWindow * window) { struct pgtk_window_is_of_frame_recursive_t data; data.window = window; data.result = false; - pgtk_window_is_of_frame_recursive(FRAME_GTK_OUTER_WIDGET(f), &data); + pgtk_window_is_of_frame_recursive (FRAME_GTK_OUTER_WIDGET (f), &data); return data.result; } /* Like x_window_to_frame but also compares the window with the widget's windows. */ static struct frame * -pgtk_any_window_to_frame (GdkWindow *window) +pgtk_any_window_to_frame (GdkWindow * window) { Lisp_Object tail, frame; struct frame *f, *found = NULL; @@ -4722,85 +4872,184 @@ pgtk_any_window_to_frame (GdkWindow *window) return NULL; FOR_EACH_FRAME (tail, frame) - { - if (found) - break; - f = XFRAME (frame); - if (FRAME_PGTK_P (f)) - { - if (pgtk_window_is_of_frame(f, window)) - found = f; - } - } + { + if (found) + break; + f = XFRAME (frame); + if (FRAME_PGTK_P (f)) + { + if (pgtk_window_is_of_frame (f, window)) + found = f; + } + } return found; } static gboolean -pgtk_handle_event(GtkWidget *widget, GdkEvent *event, gpointer *data) +pgtk_handle_event (GtkWidget * widget, GdkEvent * event, gpointer * data) { #ifdef PGTK_DEBUG - const char *type_name = G_OBJECT_TYPE_NAME(widget); - switch (event->type) { - case GDK_NOTHING: PGTK_TRACE("GDK_NOTHING"); break; - case GDK_DELETE: PGTK_TRACE("GDK_DELETE"); break; - case GDK_DESTROY: PGTK_TRACE("GDK_DESTROY"); break; - case GDK_EXPOSE: PGTK_TRACE("GDK_EXPOSE"); break; - case GDK_MOTION_NOTIFY: PGTK_TRACE("GDK_MOTION_NOTIFY"); break; - case GDK_BUTTON_PRESS: PGTK_TRACE("GDK_BUTTON_PRESS"); break; - case GDK_2BUTTON_PRESS: PGTK_TRACE("GDK_2BUTTON_PRESS"); break; - case GDK_3BUTTON_PRESS: PGTK_TRACE("GDK_3BUTTON_PRESS"); break; - case GDK_BUTTON_RELEASE: PGTK_TRACE("GDK_BUTTON_RELEASE"); break; - case GDK_KEY_PRESS: PGTK_TRACE("GDK_KEY_PRESS"); break; - case GDK_KEY_RELEASE: PGTK_TRACE("GDK_KEY_RELEASE"); break; - case GDK_ENTER_NOTIFY: PGTK_TRACE("GDK_ENTER_NOTIFY"); break; - case GDK_LEAVE_NOTIFY: PGTK_TRACE("GDK_LEAVE_NOTIFY"); break; - case GDK_FOCUS_CHANGE: PGTK_TRACE("GDK_FOCUS_CHANGE"); break; - case GDK_CONFIGURE: PGTK_TRACE("GDK_CONFIGURE"); break; - case GDK_MAP: PGTK_TRACE("GDK_MAP"); break; - case GDK_UNMAP: PGTK_TRACE("GDK_UNMAP"); break; - case GDK_PROPERTY_NOTIFY: PGTK_TRACE("GDK_PROPERTY_NOTIFY"); break; - case GDK_SELECTION_CLEAR: PGTK_TRACE("GDK_SELECTION_CLEAR"); break; - case GDK_SELECTION_REQUEST: PGTK_TRACE("GDK_SELECTION_REQUEST"); break; - case GDK_SELECTION_NOTIFY: PGTK_TRACE("GDK_SELECTION_NOTIFY"); break; - case GDK_PROXIMITY_IN: PGTK_TRACE("GDK_PROXIMITY_IN"); break; - case GDK_PROXIMITY_OUT: PGTK_TRACE("GDK_PROXIMITY_OUT"); break; - case GDK_DRAG_ENTER: PGTK_TRACE("GDK_DRAG_ENTER"); break; - case GDK_DRAG_LEAVE: PGTK_TRACE("GDK_DRAG_LEAVE"); break; - case GDK_DRAG_MOTION: PGTK_TRACE("GDK_DRAG_MOTION"); break; - case GDK_DRAG_STATUS: PGTK_TRACE("GDK_DRAG_STATUS"); break; - case GDK_DROP_START: PGTK_TRACE("GDK_DROP_START"); break; - case GDK_DROP_FINISHED: PGTK_TRACE("GDK_DROP_FINISHED"); break; - case GDK_CLIENT_EVENT: PGTK_TRACE("GDK_CLIENT_EVENT"); break; - case GDK_VISIBILITY_NOTIFY: PGTK_TRACE("GDK_VISIBILITY_NOTIFY"); break; - case GDK_SCROLL: PGTK_TRACE("GDK_SCROLL"); break; - case GDK_WINDOW_STATE: PGTK_TRACE("GDK_WINDOW_STATE"); break; - case GDK_SETTING: PGTK_TRACE("GDK_SETTING"); break; - case GDK_OWNER_CHANGE: PGTK_TRACE("GDK_OWNER_CHANGE"); break; - case GDK_GRAB_BROKEN: PGTK_TRACE("GDK_GRAB_BROKEN"); break; - case GDK_DAMAGE: PGTK_TRACE("GDK_DAMAGE"); break; - case GDK_TOUCH_BEGIN: PGTK_TRACE("GDK_TOUCH_BEGIN"); break; - case GDK_TOUCH_UPDATE: PGTK_TRACE("GDK_TOUCH_UPDATE"); break; - case GDK_TOUCH_END: PGTK_TRACE("GDK_TOUCH_END"); break; - case GDK_TOUCH_CANCEL: PGTK_TRACE("GDK_TOUCH_CANCEL"); break; - case GDK_TOUCHPAD_SWIPE: PGTK_TRACE("GDK_TOUCHPAD_SWIPE"); break; - case GDK_TOUCHPAD_PINCH: PGTK_TRACE("GDK_TOUCHPAD_PINCH"); break; - case GDK_PAD_BUTTON_PRESS: PGTK_TRACE("GDK_PAD_BUTTON_PRESS"); break; - case GDK_PAD_BUTTON_RELEASE: PGTK_TRACE("GDK_PAD_BUTTON_RELEASE"); break; - case GDK_PAD_RING: PGTK_TRACE("GDK_PAD_RING"); break; - case GDK_PAD_STRIP: PGTK_TRACE("GDK_PAD_STRIP"); break; - case GDK_PAD_GROUP_MODE: PGTK_TRACE("GDK_PAD_GROUP_MODE"); break; - default: PGTK_TRACE("GDK_EVENT %d", event->type); - } - PGTK_TRACE(" Widget is %s", type_name); + const char *type_name = G_OBJECT_TYPE_NAME (widget); + switch (event->type) + { + case GDK_NOTHING: + PGTK_TRACE ("GDK_NOTHING"); + break; + case GDK_DELETE: + PGTK_TRACE ("GDK_DELETE"); + break; + case GDK_DESTROY: + PGTK_TRACE ("GDK_DESTROY"); + break; + case GDK_EXPOSE: + PGTK_TRACE ("GDK_EXPOSE"); + break; + case GDK_MOTION_NOTIFY: + PGTK_TRACE ("GDK_MOTION_NOTIFY"); + break; + case GDK_BUTTON_PRESS: + PGTK_TRACE ("GDK_BUTTON_PRESS"); + break; + case GDK_2BUTTON_PRESS: + PGTK_TRACE ("GDK_2BUTTON_PRESS"); + break; + case GDK_3BUTTON_PRESS: + PGTK_TRACE ("GDK_3BUTTON_PRESS"); + break; + case GDK_BUTTON_RELEASE: + PGTK_TRACE ("GDK_BUTTON_RELEASE"); + break; + case GDK_KEY_PRESS: + PGTK_TRACE ("GDK_KEY_PRESS"); + break; + case GDK_KEY_RELEASE: + PGTK_TRACE ("GDK_KEY_RELEASE"); + break; + case GDK_ENTER_NOTIFY: + PGTK_TRACE ("GDK_ENTER_NOTIFY"); + break; + case GDK_LEAVE_NOTIFY: + PGTK_TRACE ("GDK_LEAVE_NOTIFY"); + break; + case GDK_FOCUS_CHANGE: + PGTK_TRACE ("GDK_FOCUS_CHANGE"); + break; + case GDK_CONFIGURE: + PGTK_TRACE ("GDK_CONFIGURE"); + break; + case GDK_MAP: + PGTK_TRACE ("GDK_MAP"); + break; + case GDK_UNMAP: + PGTK_TRACE ("GDK_UNMAP"); + break; + case GDK_PROPERTY_NOTIFY: + PGTK_TRACE ("GDK_PROPERTY_NOTIFY"); + break; + case GDK_SELECTION_CLEAR: + PGTK_TRACE ("GDK_SELECTION_CLEAR"); + break; + case GDK_SELECTION_REQUEST: + PGTK_TRACE ("GDK_SELECTION_REQUEST"); + break; + case GDK_SELECTION_NOTIFY: + PGTK_TRACE ("GDK_SELECTION_NOTIFY"); + break; + case GDK_PROXIMITY_IN: + PGTK_TRACE ("GDK_PROXIMITY_IN"); + break; + case GDK_PROXIMITY_OUT: + PGTK_TRACE ("GDK_PROXIMITY_OUT"); + break; + case GDK_DRAG_ENTER: + PGTK_TRACE ("GDK_DRAG_ENTER"); + break; + case GDK_DRAG_LEAVE: + PGTK_TRACE ("GDK_DRAG_LEAVE"); + break; + case GDK_DRAG_MOTION: + PGTK_TRACE ("GDK_DRAG_MOTION"); + break; + case GDK_DRAG_STATUS: + PGTK_TRACE ("GDK_DRAG_STATUS"); + break; + case GDK_DROP_START: + PGTK_TRACE ("GDK_DROP_START"); + break; + case GDK_DROP_FINISHED: + PGTK_TRACE ("GDK_DROP_FINISHED"); + break; + case GDK_CLIENT_EVENT: + PGTK_TRACE ("GDK_CLIENT_EVENT"); + break; + case GDK_VISIBILITY_NOTIFY: + PGTK_TRACE ("GDK_VISIBILITY_NOTIFY"); + break; + case GDK_SCROLL: + PGTK_TRACE ("GDK_SCROLL"); + break; + case GDK_WINDOW_STATE: + PGTK_TRACE ("GDK_WINDOW_STATE"); + break; + case GDK_SETTING: + PGTK_TRACE ("GDK_SETTING"); + break; + case GDK_OWNER_CHANGE: + PGTK_TRACE ("GDK_OWNER_CHANGE"); + break; + case GDK_GRAB_BROKEN: + PGTK_TRACE ("GDK_GRAB_BROKEN"); + break; + case GDK_DAMAGE: + PGTK_TRACE ("GDK_DAMAGE"); + break; + case GDK_TOUCH_BEGIN: + PGTK_TRACE ("GDK_TOUCH_BEGIN"); + break; + case GDK_TOUCH_UPDATE: + PGTK_TRACE ("GDK_TOUCH_UPDATE"); + break; + case GDK_TOUCH_END: + PGTK_TRACE ("GDK_TOUCH_END"); + break; + case GDK_TOUCH_CANCEL: + PGTK_TRACE ("GDK_TOUCH_CANCEL"); + break; + case GDK_TOUCHPAD_SWIPE: + PGTK_TRACE ("GDK_TOUCHPAD_SWIPE"); + break; + case GDK_TOUCHPAD_PINCH: + PGTK_TRACE ("GDK_TOUCHPAD_PINCH"); + break; + case GDK_PAD_BUTTON_PRESS: + PGTK_TRACE ("GDK_PAD_BUTTON_PRESS"); + break; + case GDK_PAD_BUTTON_RELEASE: + PGTK_TRACE ("GDK_PAD_BUTTON_RELEASE"); + break; + case GDK_PAD_RING: + PGTK_TRACE ("GDK_PAD_RING"); + break; + case GDK_PAD_STRIP: + PGTK_TRACE ("GDK_PAD_STRIP"); + break; + case GDK_PAD_GROUP_MODE: + PGTK_TRACE ("GDK_PAD_GROUP_MODE"); + break; + default: + PGTK_TRACE ("GDK_EVENT %d", event->type); + } + PGTK_TRACE (" Widget is %s", type_name); #endif return FALSE; } static void -pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int width, int height) +pgtk_fill_rectangle (struct frame *f, unsigned long color, int x, int y, + int width, int height) { - PGTK_TRACE("pgtk_fill_rectangle"); + PGTK_TRACE ("pgtk_fill_rectangle"); cairo_t *cr; cr = pgtk_begin_cr_clip (f); pgtk_set_cr_source_with_color (f, color); @@ -4812,7 +5061,7 @@ pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int widt void pgtk_clear_under_internal_border (struct frame *f) { - PGTK_TRACE("pgtk_clear_under_internal_border"); + PGTK_TRACE ("pgtk_clear_under_internal_border"); if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) { int border = FRAME_INTERNAL_BORDER_WIDTH (f); @@ -4823,112 +5072,132 @@ pgtk_clear_under_internal_border (struct frame *f) block_input (); - struct { + struct + { int x, y, w, h; } rects[] = { - { 0, margin, width, border }, - { 0, 0, border, height }, - { width - border, 0, border, height }, - { 0, height - border, width, border }, + {0, margin, width, border}, + {0, 0, border, height}, + {width - border, 0, border, height}, + {0, height - border, width, border}, }; if (face) { - for (int i = 0; i < 4; i++) { - int x = rects[i].x; - int y = rects[i].y; - int w = rects[i].w; - int h = rects[i].h; - fill_background_by_face (f, face, x, y, w, h); - } + for (int i = 0; i < 4; i++) + { + int x = rects[i].x; + int y = rects[i].y; + int w = rects[i].w; + int h = rects[i].h; + fill_background_by_face (f, face, x, y, w, h); + } } else { for (int i = 0; i < 4; i++) - pgtk_clear_area (f, rects[i].x, rects[i].y, rects[i].w, rects[i].h); + pgtk_clear_area (f, rects[i].x, rects[i].y, rects[i].w, + rects[i].h); } unblock_input (); } } -static void print_widget_tree_recursive(GtkWidget *w, gpointer user_data) +static void +print_widget_tree_recursive (GtkWidget * w, gpointer user_data) { const char *indent = user_data; char buf[1024] = ""; int len = 0; - len += sprintf(buf + len, "%s", indent); - len += sprintf(buf + len, "%p %s mapped:%d visible:%d", w, G_OBJECT_TYPE_NAME(w), gtk_widget_get_mapped(w), gtk_widget_get_visible(w)); + len += sprintf (buf + len, "%s", indent); + len += + sprintf (buf + len, "%p %s mapped:%d visible:%d", w, + G_OBJECT_TYPE_NAME (w), gtk_widget_get_mapped (w), + gtk_widget_get_visible (w)); gint wd, hi; - gtk_widget_get_size_request(w, &wd, &hi); - len += sprintf(buf + len, " size_req:%dx%d", wd, hi); + gtk_widget_get_size_request (w, &wd, &hi); + len += sprintf (buf + len, " size_req:%dx%d", wd, hi); GtkAllocation alloc; - gtk_widget_get_allocation(w, &alloc); - len += sprintf(buf + len, " alloc:%dx%d+%d+%d", alloc.width, alloc.height, alloc.x, alloc.y); - len += sprintf(buf + len, " haswin:%d", gtk_widget_get_has_window(w)); - len += sprintf(buf + len, " gdkwin:%p", gtk_widget_get_window(w)); - PGTK_TRACE("%s", buf); - - if (GTK_IS_CONTAINER(w)) { - strcpy(buf, indent); - strcat(buf, " "); - gtk_container_foreach(GTK_CONTAINER(w), print_widget_tree_recursive, buf); - } + gtk_widget_get_allocation (w, &alloc); + len += + sprintf (buf + len, " alloc:%dx%d+%d+%d", alloc.width, alloc.height, + alloc.x, alloc.y); + len += sprintf (buf + len, " haswin:%d", gtk_widget_get_has_window (w)); + len += sprintf (buf + len, " gdkwin:%p", gtk_widget_get_window (w)); + PGTK_TRACE ("%s", buf); + + if (GTK_IS_CONTAINER (w)) + { + strcpy (buf, indent); + strcat (buf, " "); + gtk_container_foreach (GTK_CONTAINER (w), print_widget_tree_recursive, + buf); + } } -static void print_widget_tree(GtkWidget *w) +static void +print_widget_tree (GtkWidget * w) { char indent[1] = ""; - w = gtk_widget_get_toplevel(w); - print_widget_tree_recursive(w, indent); + w = gtk_widget_get_toplevel (w); + print_widget_tree_recursive (w, indent); } static gboolean -pgtk_handle_draw(GtkWidget *widget, cairo_t *cr, gpointer *data) +pgtk_handle_draw (GtkWidget * widget, cairo_t * cr, gpointer * data) { struct frame *f; - PGTK_TRACE("pgtk_handle_draw"); - - print_widget_tree(widget); - - GdkWindow *win = gtk_widget_get_window(widget); - - PGTK_TRACE(" win=%p", win); - if (win != NULL) { - cairo_surface_t *src = NULL; - f = pgtk_any_window_to_frame(win); - PGTK_TRACE(" f=%p", f); - if (f != NULL) { - src = FRAME_X_OUTPUT(f)->cr_surface_visible_bell; - if (src == NULL && FRAME_CR_ACTIVE_CONTEXT(f) != NULL) - src = cairo_get_target(FRAME_CR_ACTIVE_CONTEXT(f)); - } - PGTK_TRACE(" surface=%p", src); - if (src != NULL) { - PGTK_TRACE(" resized_p=%d", f->resized_p); - PGTK_TRACE(" garbaged=%d", f->garbaged); - PGTK_TRACE(" scroll_bar_width=%f", (double) PGTK_SCROLL_BAR_WIDTH(f)); - // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); - PGTK_TRACE(" scroll_bar_cols=%d", FRAME_SCROLL_BAR_COLS(f)); - PGTK_TRACE(" column_width=%d", FRAME_COLUMN_WIDTH(f)); - cairo_set_source_surface(cr, src, 0, 0); - cairo_paint(cr); + PGTK_TRACE ("pgtk_handle_draw"); + + print_widget_tree (widget); + + GdkWindow *win = gtk_widget_get_window (widget); + + PGTK_TRACE (" win=%p", win); + if (win != NULL) + { + cairo_surface_t *src = NULL; + f = pgtk_any_window_to_frame (win); + PGTK_TRACE (" f=%p", f); + if (f != NULL) + { + src = FRAME_X_OUTPUT (f)->cr_surface_visible_bell; + if (src == NULL && FRAME_CR_ACTIVE_CONTEXT (f) != NULL) + src = cairo_get_target (FRAME_CR_ACTIVE_CONTEXT (f)); + } + PGTK_TRACE (" surface=%p", src); + if (src != NULL) + { + PGTK_TRACE (" resized_p=%d", f->resized_p); + PGTK_TRACE (" garbaged=%d", f->garbaged); + PGTK_TRACE (" scroll_bar_width=%f", + (double) PGTK_SCROLL_BAR_WIDTH (f)); + // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); + PGTK_TRACE (" scroll_bar_cols=%d", FRAME_SCROLL_BAR_COLS (f)); + PGTK_TRACE (" column_width=%d", FRAME_COLUMN_WIDTH (f)); + cairo_set_source_surface (cr, src, 0, 0); + cairo_paint (cr); + } } - } return FALSE; } -static void size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer *user_data) +static void +size_allocate (GtkWidget * widget, GtkAllocation * alloc, + gpointer * user_data) { - PGTK_TRACE("size-alloc: %dx%d+%d+%d.", alloc->width, alloc->height, alloc->x, alloc->y); + PGTK_TRACE ("size-alloc: %dx%d+%d+%d.", alloc->width, alloc->height, + alloc->x, alloc->y); - struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window(widget)); - if (f) { - PGTK_TRACE("%dx%d", alloc->width, alloc->height); - xg_frame_resized(f, alloc->width, alloc->height); - pgtk_cr_update_surface_desired_size(f, alloc->width, alloc->height); - } + struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + if (f) + { + PGTK_TRACE ("%dx%d", alloc->width, alloc->height); + xg_frame_resized (f, alloc->width, alloc->height); + pgtk_cr_update_surface_desired_size (f, alloc->width, alloc->height); + } } static void @@ -4938,49 +5207,58 @@ x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) GdkKeymap *keymap = gdk_keymap_get_for_display (gdpy); GdkModifierType state = GDK_META_MASK; gboolean r = gdk_keymap_map_virtual_modifiers (keymap, &state); - if (r) { - /* Meta key exists. */ - if (state == GDK_META_MASK) { - dpyinfo->meta_mod_mask = GDK_MOD1_MASK; /* maybe this is meta. */ - dpyinfo->alt_mod_mask = 0; - } else { - dpyinfo->meta_mod_mask = state & ~GDK_META_MASK; - if (dpyinfo->meta_mod_mask == GDK_MOD1_MASK) - dpyinfo->alt_mod_mask = 0; + if (r) + { + /* Meta key exists. */ + if (state == GDK_META_MASK) + { + dpyinfo->meta_mod_mask = GDK_MOD1_MASK; /* maybe this is meta. */ + dpyinfo->alt_mod_mask = 0; + } else - dpyinfo->alt_mod_mask = GDK_MOD1_MASK; + { + dpyinfo->meta_mod_mask = state & ~GDK_META_MASK; + if (dpyinfo->meta_mod_mask == GDK_MOD1_MASK) + dpyinfo->alt_mod_mask = 0; + else + dpyinfo->alt_mod_mask = GDK_MOD1_MASK; + } + } + else + { + dpyinfo->meta_mod_mask = GDK_MOD1_MASK; + dpyinfo->alt_mod_mask = 0; } - } else { - dpyinfo->meta_mod_mask = GDK_MOD1_MASK; - dpyinfo->alt_mod_mask = 0; - } } -static void get_modifier_values( - int *mod_ctrl, - int *mod_meta, - int *mod_alt, - int *mod_hyper, - int *mod_super) +static void +get_modifier_values (int *mod_ctrl, + int *mod_meta, + int *mod_alt, int *mod_hyper, int *mod_super) { Lisp_Object tem; *mod_ctrl = ctrl_modifier; *mod_meta = meta_modifier; - *mod_alt = alt_modifier; + *mod_alt = alt_modifier; *mod_hyper = hyper_modifier; *mod_super = super_modifier; tem = Fget (Vx_ctrl_keysym, Qmodifier_value); - if (INTEGERP (tem)) *mod_ctrl = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) + *mod_ctrl = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_alt_keysym, Qmodifier_value); - if (INTEGERP (tem)) *mod_alt = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) + *mod_alt = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_meta_keysym, Qmodifier_value); - if (INTEGERP (tem)) *mod_meta = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) + *mod_meta = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_hyper_keysym, Qmodifier_value); - if (INTEGERP (tem)) *mod_hyper = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) + *mod_hyper = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_super_keysym, Qmodifier_value); - if (INTEGERP (tem)) *mod_super = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) + *mod_super = XFIXNUM (tem) & INT_MAX; } int @@ -4993,15 +5271,22 @@ pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state) int mod_super; int mod; - get_modifier_values(&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, &mod_super); + get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, + &mod_super); mod = 0; - if (state & GDK_SHIFT_MASK) mod |= shift_modifier; - if (state & GDK_CONTROL_MASK) mod |= mod_ctrl; - if (state & dpyinfo->meta_mod_mask) mod |= mod_meta; - if (state & dpyinfo->alt_mod_mask) mod |= mod_alt; - if (state & GDK_SUPER_MASK) mod |= mod_super; - if (state & GDK_HYPER_MASK) mod |= mod_hyper; + if (state & GDK_SHIFT_MASK) + mod |= shift_modifier; + if (state & GDK_CONTROL_MASK) + mod |= mod_ctrl; + if (state & dpyinfo->meta_mod_mask) + mod |= mod_meta; + if (state & dpyinfo->alt_mod_mask) + mod |= mod_alt; + if (state & GDK_SUPER_MASK) + mod |= mod_super; + if (state & GDK_HYPER_MASK) + mod |= mod_hyper; return mod; } @@ -5015,15 +5300,22 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) int mod_super; int mask; - get_modifier_values(&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, &mod_super); + get_modifier_values (&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, + &mod_super); mask = 0; - if (state & mod_alt) mask |= dpyinfo->alt_mod_mask; - if (state & mod_super) mask |= GDK_SUPER_MASK; - if (state & mod_hyper) mask |= GDK_HYPER_MASK; - if (state & shift_modifier) mask |= GDK_SHIFT_MASK; - if (state & mod_ctrl) mask |= GDK_CONTROL_MASK; - if (state & mod_meta) mask |= dpyinfo->meta_mod_mask; + if (state & mod_alt) + mask |= dpyinfo->alt_mod_mask; + if (state & mod_super) + mask |= GDK_SUPER_MASK; + if (state & mod_hyper) + mask |= GDK_HYPER_MASK; + if (state & shift_modifier) + mask |= GDK_SHIFT_MASK; + if (state & mod_ctrl) + mask |= GDK_CONTROL_MASK; + if (state & mod_meta) + mask |= dpyinfo->meta_mod_mask; return mask; } @@ -5033,32 +5325,33 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) #define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1) void -pgtk_enqueue_string(struct frame *f, gchar *str) +pgtk_enqueue_string (struct frame *f, gchar * str) { gunichar *ustr; ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL); if (ustr == NULL) return; - for ( ; *ustr != 0; ustr++) { - union buffered_input_event inev; - Lisp_Object c = make_fixnum (*ustr); - EVENT_INIT (inev.ie); - inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c)) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.ie.arg = Qnil; - inev.ie.code = XFIXNAT (c); - XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.modifiers = 0; - inev.ie.timestamp = 0; - evq_enqueue (&inev); - } + for (; *ustr != 0; ustr++) + { + union buffered_input_event inev; + Lisp_Object c = make_fixnum (*ustr); + EVENT_INIT (inev.ie); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c)) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.arg = Qnil; + inev.ie.code = XFIXNAT (c); + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers = 0; + inev.ie.timestamp = 0; + evq_enqueue (&inev); + } } void -pgtk_enqueue_preedit(struct frame *f, Lisp_Object preedit) +pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit) { union buffered_input_event inev; EVENT_INIT (inev.ie); @@ -5071,7 +5364,8 @@ pgtk_enqueue_preedit(struct frame *f, Lisp_Object preedit) evq_enqueue (&inev); } -static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +key_press_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { struct coding_system coding; union buffered_input_event inev; @@ -5080,14 +5374,14 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us USE_SAFE_ALLOCA; - PGTK_TRACE("key_press_event"); + PGTK_TRACE ("key_press_event"); EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - struct frame *f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); - hlinfo = MOUSE_HL_INFO(f); + struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + hlinfo = MOUSE_HL_INFO (f); /* If mouse-highlight is an integer, input clears out mouse highlighting. */ @@ -5097,25 +5391,26 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us hlinfo->mouse_face_hidden = true; } - if (f != 0) { - if (pgtk_im_filter_keypress (f, &event->key)) - return TRUE; - } + if (f != 0) + { + if (pgtk_im_filter_keypress (f, &event->key)) + return TRUE; + } if (f != 0) { guint keysym, orig_keysym; /* al%imercury@uunet.uu.net says that making this 81 - instead of 80 fixed a bug whereby meta chars made - his Emacs hang. - - It seems that some version of XmbLookupString has - a bug of not returning XBufferOverflow in - status_return even if the input is too long to - fit in 81 bytes. So, we must prepare sufficient - bytes for copy_buffer. 513 bytes (256 chars for - two-byte character set) seems to be a fairly good - approximation. -- 2000.8.10 handa@etl.go.jp */ + instead of 80 fixed a bug whereby meta chars made + his Emacs hang. + + It seems that some version of XmbLookupString has + a bug of not returning XBufferOverflow in + status_return even if the input is too long to + fit in 81 bytes. So, we must prepare sufficient + bytes for copy_buffer. 513 bytes (256 chars for + two-byte character set) seems to be a fairly good + approximation. -- 2000.8.10 handa@etl.go.jp */ unsigned char copy_buffer[513]; unsigned char *copy_bufptr = copy_buffer; int copy_bufsiz = sizeof (copy_buffer); @@ -5124,34 +5419,35 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us Lisp_Object c; guint state = event->key.state; - state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f), extra_keyboard_modifiers); + state |= + pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f), + extra_keyboard_modifiers); modifiers = state; /* This will have to go some day... */ /* make_lispy_event turns chars into control chars. - Don't do it here because XLookupString is too eager. */ + Don't do it here because XLookupString is too eager. */ state &= ~GDK_CONTROL_MASK; state &= ~(GDK_META_MASK - | GDK_SUPER_MASK - | GDK_HYPER_MASK - | GDK_MOD1_MASK); + | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_MOD1_MASK); nbytes = event->key.length; if (nbytes > copy_bufsiz) nbytes = copy_bufsiz; - memcpy(copy_bufptr, event->key.string, nbytes); + memcpy (copy_bufptr, event->key.string, nbytes); keysym = event->key.keyval; orig_keysym = keysym; /* Common for all keysym input events. */ XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers); + inev.ie.modifiers = + pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers); inev.ie.timestamp = event->key.time; /* First deal with keysyms which have defined - translations to characters. */ + translations to characters. */ if (keysym >= 32 && keysym < 128) /* Avoid explicitly decoding each ASCII character. */ { @@ -5174,9 +5470,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us /* Now non-ASCII. */ if (HASH_TABLE_P (Vpgtk_keysym_table) && (c = Fgethash (make_fixnum (keysym), - Vpgtk_keysym_table, - Qnil), - FIXNATP (c))) + Vpgtk_keysym_table, Qnil), FIXNATP (c))) { inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c)) ? ASCII_KEYSTROKE_EVENT @@ -5189,11 +5483,10 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us if (((keysym >= GDK_KEY_BackSpace && keysym <= GDK_KEY_Escape) || keysym == GDK_KEY_Delete #ifdef GDK_KEY_ISO_Left_Tab - || (keysym >= GDK_KEY_ISO_Left_Tab - && keysym <= GDK_KEY_ISO_Enter) + || (keysym >= GDK_KEY_ISO_Left_Tab && keysym <= GDK_KEY_ISO_Enter) #endif - || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */ - || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */ + || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */ + || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */ #ifdef HPUX /* This recognizes the "extended function keys". It seems there's no cleaner way. @@ -5240,22 +5533,22 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us #ifdef GDK_KEY_dead_abovedot || orig_keysym == GDK_KEY_dead_abovedot #endif - || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ - || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ + || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ + || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ /* Any "vendor-specific" key is ok. */ || (orig_keysym & (1 << 28)) || (keysym != GDK_KEY_VoidSymbol && nbytes == 0)) - && ! (event->key.is_modifier - /* The symbols from GDK_KEY_ISO_Lock - to GDK_KEY_ISO_Last_Group_Lock - don't have real modifiers but - should be treated similarly to - Mode_switch by Emacs. */ + && !(event->key.is_modifier + /* The symbols from GDK_KEY_ISO_Lock + to GDK_KEY_ISO_Last_Group_Lock + don't have real modifiers but + should be treated similarly to + Mode_switch by Emacs. */ #if defined GDK_KEY_ISO_Lock && defined GDK_KEY_ISO_Last_Group_Lock - || (GDK_KEY_ISO_Lock <= orig_keysym - && orig_keysym <= GDK_KEY_ISO_Last_Group_Lock) + || (GDK_KEY_ISO_Lock <= orig_keysym + && orig_keysym <= GDK_KEY_ISO_Last_Group_Lock) #endif - )) + )) { STORE_KEYSYM_FOR_DEBUG (keysym); /* make_lispy_event will convert this to a symbolic @@ -5265,7 +5558,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us goto done; } - { /* Raw bytes, not keysym. */ + { /* Raw bytes, not keysym. */ ptrdiff_t i; int nchars, len; @@ -5291,8 +5584,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us gives us composition information. */ coding.common_flags &= ~CODING_ANNOTATION_MASK; - SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, - nbytes); + SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, nbytes); coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes; coding.mode |= CODING_MODE_LAST_BLOCK; decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); @@ -5319,14 +5611,14 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us // count += nchars; - inev.ie.kind = NO_EVENT; /* Already stored above. */ + inev.ie.kind = NO_EVENT; /* Already stored above. */ if (keysym == GDK_KEY_VoidSymbol) goto done; } } - done: +done: if (inev.ie.kind != NO_EVENT) { XSETFRAME (inev.ie.frame_or_window, f); @@ -5334,34 +5626,39 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us // count++; } - SAFE_FREE(); + SAFE_FREE (); return TRUE; } -static gboolean key_release_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +key_release_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE("key_release_event"); + PGTK_TRACE ("key_release_event"); return TRUE; } -static gboolean configure_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +configure_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { struct frame *f = pgtk_any_window_to_frame (event->configure.window); - if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) { - PGTK_TRACE("%dx%d", event->configure.width, event->configure.height); - xg_frame_resized(f, event->configure.width, event->configure.height); - pgtk_cr_update_surface_desired_size(f, event->configure.width, event->configure.height); - } + if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) + { + PGTK_TRACE ("%dx%d", event->configure.width, event->configure.height); + xg_frame_resized (f, event->configure.width, event->configure.height); + pgtk_cr_update_surface_desired_size (f, event->configure.width, + event->configure.height); + } return TRUE; } -static gboolean map_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +map_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; - PGTK_TRACE("map_event"); + PGTK_TRACE ("map_event"); EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; @@ -5372,10 +5669,10 @@ static gboolean map_event(GtkWidget *widget, GdkEvent *event, gpointer *user_dat bool iconified = FRAME_ICONIFIED_P (f); /* Check if fullscreen was specified before we where mapped the - first time, i.e. from the command line. */ - if (!FRAME_X_OUTPUT(f)->has_been_visible) + first time, i.e. from the command line. */ + if (!FRAME_X_OUTPUT (f)->has_been_visible) { - set_fullscreen_state(f); + set_fullscreen_state (f); } if (!iconified) @@ -5390,25 +5687,27 @@ static gboolean map_event(GtkWidget *widget, GdkEvent *event, gpointer *user_dat SET_FRAME_VISIBLE (f, 1); SET_FRAME_ICONIFIED (f, false); - FRAME_X_OUTPUT(f)->has_been_visible = true; + FRAME_X_OUTPUT (f)->has_been_visible = true; if (iconified) { inev.ie.kind = DEICONIFY_EVENT; XSETFRAME (inev.ie.frame_or_window, f); } - else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) + else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list))) /* Force a redisplay sooner or later to update the frame titles in case this is the second frame. */ record_asynch_buffer_change (); } if (inev.ie.kind != NO_EVENT) - evq_enqueue(&inev); + evq_enqueue (&inev); return FALSE; } -static gboolean window_state_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +window_state_event (GtkWidget * widget, GdkEvent * event, + gpointer * user_data) { struct frame *f = pgtk_any_window_to_frame (event->window_state.window); union buffered_input_event inev; @@ -5417,46 +5716,49 @@ static gboolean window_state_event(GtkWidget *widget, GdkEvent *event, gpointer inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (f) { - if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) - { - if (FRAME_ICONIFIED_P (f)) - { - /* Gnome shell does not iconify us when C-z is pressed. - It hides the frame. So if our state says we aren't - hidden anymore, treat it as deiconified. */ - SET_FRAME_VISIBLE (f, 1); - SET_FRAME_ICONIFIED (f, false); - FRAME_X_OUTPUT(f)->has_been_visible = true; - inev.ie.kind = DEICONIFY_EVENT; - XSETFRAME (inev.ie.frame_or_window, f); - } - } - } + if (f) + { + if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) + { + if (FRAME_ICONIFIED_P (f)) + { + /* Gnome shell does not iconify us when C-z is pressed. + It hides the frame. So if our state says we aren't + hidden anymore, treat it as deiconified. */ + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + FRAME_X_OUTPUT (f)->has_been_visible = true; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + } + } if (inev.ie.kind != NO_EVENT) - evq_enqueue(&inev); + evq_enqueue (&inev); return FALSE; } -static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +static gboolean +delete_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { struct frame *f = pgtk_any_window_to_frame (event->any.window); union buffered_input_event inev; - PGTK_TRACE("delete_event"); + PGTK_TRACE ("delete_event"); EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (f) { - inev.ie.kind = DELETE_WINDOW_EVENT; - XSETFRAME (inev.ie.frame_or_window, f); - } + if (f) + { + inev.ie.kind = DELETE_WINDOW_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } if (inev.ie.kind != NO_EVENT) - evq_enqueue(&inev); + evq_enqueue (&inev); return TRUE; } @@ -5470,27 +5772,28 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_ a FOCUS_IN_EVENT into *BUFP. */ static void -x_focus_changed (gboolean is_enter, int state, struct pgtk_display_info *dpyinfo, struct frame *frame, union buffered_input_event *bufp) +x_focus_changed (gboolean is_enter, int state, + struct pgtk_display_info *dpyinfo, struct frame *frame, + union buffered_input_event *bufp) { if (is_enter) { if (dpyinfo->x_focus_event_frame != frame) - { - x_new_focus_frame (dpyinfo, frame); - dpyinfo->x_focus_event_frame = frame; - - /* Don't stop displaying the initial startup message - for a switch-frame event we don't need. */ - /* When run as a daemon, Vterminal_frame is always NIL. */ - bufp->ie.arg = (((NILP (Vterminal_frame) - || ! FRAME_PGTK_P (XFRAME (Vterminal_frame)) - || EQ (Fdaemonp (), Qt)) - && CONSP (Vframe_list) - && !NILP (XCDR (Vframe_list))) - ? Qt : Qnil); - bufp->ie.kind = FOCUS_IN_EVENT; - XSETFRAME (bufp->ie.frame_or_window, frame); - } + { + x_new_focus_frame (dpyinfo, frame); + dpyinfo->x_focus_event_frame = frame; + + /* Don't stop displaying the initial startup message + for a switch-frame event we don't need. */ + /* When run as a daemon, Vterminal_frame is always NIL. */ + bufp->ie.arg = (((NILP (Vterminal_frame) + || !FRAME_PGTK_P (XFRAME (Vterminal_frame)) + || EQ (Fdaemonp (), Qt)) + && CONSP (Vframe_list) + && !NILP (XCDR (Vframe_list))) ? Qt : Qnil); + bufp->ie.kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->ie.frame_or_window, frame); + } frame->output_data.pgtk->focus_state |= state; @@ -5514,11 +5817,13 @@ x_focus_changed (gboolean is_enter, int state, struct pgtk_display_info *dpyinfo } static gboolean -enter_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +enter_notify_event (GtkWidget * widget, GdkEvent * event, + gpointer * user_data) { - PGTK_TRACE("enter_notify_event"); + PGTK_TRACE ("enter_notify_event"); union buffered_input_event inev; - struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = + pgtk_any_window_to_frame (gtk_widget_get_window (widget)); if (frame == NULL) return FALSE; struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); @@ -5531,22 +5836,21 @@ enter_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.arg = Qnil; if (event->crossing.detail != GDK_NOTIFY_INFERIOR - && event->crossing.focus - && ! (focus_state & FOCUS_EXPLICIT)) - x_focus_changed (TRUE, - FOCUS_IMPLICIT, - dpyinfo, frame, &inev); + && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT)) + x_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; } static gboolean -leave_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +leave_notify_event (GtkWidget * widget, GdkEvent * event, + gpointer * user_data) { - PGTK_TRACE("leave_notify_event"); + PGTK_TRACE ("leave_notify_event"); union buffered_input_event inev; - struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = + pgtk_any_window_to_frame (gtk_widget_get_window (widget)); if (frame == NULL) return FALSE; struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); @@ -5559,22 +5863,20 @@ leave_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.arg = Qnil; if (event->crossing.detail != GDK_NOTIFY_INFERIOR - && event->crossing.focus - && ! (focus_state & FOCUS_EXPLICIT)) - x_focus_changed (FALSE, - FOCUS_IMPLICIT, - dpyinfo, frame, &inev); + && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT)) + x_focus_changed (FALSE, FOCUS_IMPLICIT, dpyinfo, frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; } static gboolean -focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +focus_in_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE("focus_in_event"); + PGTK_TRACE ("focus_in_event"); union buffered_input_event inev; - struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = + pgtk_any_window_to_frame (gtk_widget_get_window (widget)); if (frame == NULL) return TRUE; @@ -5584,7 +5886,7 @@ focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.arg = Qnil; x_focus_changed (TRUE, FOCUS_EXPLICIT, - FRAME_DISPLAY_INFO(frame), frame, &inev); + FRAME_DISPLAY_INFO (frame), frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); @@ -5594,11 +5896,12 @@ focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) } static gboolean -focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +focus_out_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE("focus_out_event"); + PGTK_TRACE ("focus_out_event"); union buffered_input_event inev; - struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = + pgtk_any_window_to_frame (gtk_widget_get_window (widget)); if (frame == NULL) return TRUE; @@ -5608,9 +5911,9 @@ focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.arg = Qnil; x_focus_changed (FALSE, FOCUS_EXPLICIT, - FRAME_DISPLAY_INFO(frame), frame, &inev); + FRAME_DISPLAY_INFO (frame), frame, &inev); if (inev.ie.kind != NO_EVENT) - evq_enqueue(&inev); + evq_enqueue (&inev); pgtk_im_focus_out (frame); @@ -5626,7 +5929,7 @@ focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) another motion event, so we can check again the next time it moves. */ static bool -note_mouse_movement (struct frame *frame, const GdkEventMotion *event) +note_mouse_movement (struct frame *frame, const GdkEventMotion * event) { XRectangle *r; struct pgtk_display_info *dpyinfo; @@ -5640,7 +5943,7 @@ note_mouse_movement (struct frame *frame, const GdkEventMotion *event) dpyinfo->last_mouse_motion_x = event->x; dpyinfo->last_mouse_motion_y = event->y; - if (event->window != gtk_widget_get_window(FRAME_GTK_WIDGET (frame))) + if (event->window != gtk_widget_get_window (FRAME_GTK_WIDGET (frame))) { frame->mouse_moved = true; dpyinfo->last_mouse_scroll_bar = NULL; @@ -5669,9 +5972,10 @@ note_mouse_movement (struct frame *frame, const GdkEventMotion *event) } static gboolean -motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +motion_notify_event (GtkWidget * widget, GdkEvent * event, + gpointer * user_data) { - PGTK_TRACE("motion_notify_event"); + PGTK_TRACE ("motion_notify_event"); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -5684,10 +5988,10 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) previous_help_echo_string = help_echo_string; help_echo_string = Qnil; - frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); dpyinfo = FRAME_DISPLAY_INFO (frame); f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame - : pgtk_any_window_to_frame(gtk_widget_get_window(widget))); + : pgtk_any_window_to_frame (gtk_widget_get_window (widget))); hlinfo = MOUSE_HL_INFO (f); if (hlinfo->mouse_face_hidden) @@ -5701,8 +6005,8 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) if (f) { /* Maybe generate a SELECT_WINDOW_EVENT for - `mouse-autoselect-window' but don't let popup menus - interfere with this (Bug#1261). */ + `mouse-autoselect-window' but don't let popup menus + interfere with this (Bug#1261). */ if (!NILP (Vmouse_autoselect_window) /* Don't switch if we're currently in the minibuffer. This tries to work around problems where the @@ -5712,8 +6016,7 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) && !MINI_WINDOW_P (XWINDOW (selected_window)) /* With `focus-follows-mouse' non-nil create an event also when the target window is on another frame. */ - && (f == XFRAME (selected_frame) - || !NILP (focus_follows_mouse))) + && (f == XFRAME (selected_frame) || !NILP (focus_follows_mouse))) { static Lisp_Object last_mouse_window; Lisp_Object window = window_from_coordinates @@ -5745,37 +6048,37 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) else { /* If we move outside the frame, then we're - certainly no longer on any text in the frame. */ + certainly no longer on any text in the frame. */ clear_mouse_face (hlinfo); } /* If the contents of the global variable help_echo_string has changed, generate a HELP_EVENT. */ int do_help = 0; - if (!NILP (help_echo_string) - || !NILP (previous_help_echo_string)) + if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) do_help = 1; if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); - if (do_help > 0) { - Lisp_Object frame; - union buffered_input_event inev; + if (do_help > 0) + { + Lisp_Object frame; + union buffered_input_event inev; - if (f) - XSETFRAME (frame, f); - else - frame = Qnil; - - inev.ie.kind = HELP_EVENT; - inev.ie.frame_or_window = frame; - inev.ie.arg = help_echo_object; - inev.ie.x = help_echo_window; - inev.ie.y = help_echo_string; - inev.ie.timestamp = help_echo_pos; - evq_enqueue(&inev); - } + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + + inev.ie.kind = HELP_EVENT; + inev.ie.frame_or_window = frame; + inev.ie.arg = help_echo_object; + inev.ie.x = help_echo_window; + inev.ie.y = help_echo_string; + inev.ie.timestamp = help_echo_pos; + evq_enqueue (&inev); + } return TRUE; } @@ -5807,18 +6110,16 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) static Lisp_Object construct_mouse_click (struct input_event *result, - const GdkEventButton *event, - struct frame *f) + const GdkEventButton * event, struct frame *f) { /* Make the event type NO_EVENT; we'll change that when we decide otherwise. */ result->kind = MOUSE_CLICK_EVENT; result->code = event->button - 1; result->timestamp = event->time; - result->modifiers = (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->state) - | (event->type == GDK_BUTTON_RELEASE - ? up_modifier - : down_modifier)); + result->modifiers = + (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->state) | + (event->type == GDK_BUTTON_RELEASE ? up_modifier : down_modifier)); XSETINT (result->x, event->x); XSETINT (result->y, event->y); @@ -5828,9 +6129,10 @@ construct_mouse_click (struct input_event *result, } static gboolean -button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +button_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE("button_event: type=%d, button=%u.", event->button.type, event->button.button); + PGTK_TRACE ("button_event: type=%d, button=%u.", event->button.type, + event->button.button); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -5848,7 +6150,7 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) return TRUE; - frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); dpyinfo = FRAME_DISPLAY_INFO (frame); dpyinfo->last_mouse_glyph_frame = NULL; @@ -5860,7 +6162,7 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) f = dpyinfo->last_mouse_frame; else { - f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); if (f && event->button.type == GDK_BUTTON_PRESS && !FRAME_NO_ACCEPT_FOCUS (f)) @@ -5939,8 +6241,8 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) dpyinfo->last_mouse_frame = f; if (dpyinfo->last_click_event != NULL) - gdk_event_free(dpyinfo->last_click_event); - dpyinfo->last_click_event = gdk_event_copy(event); + gdk_event_free (dpyinfo->last_click_event); + dpyinfo->last_click_event = gdk_event_copy (event); } else dpyinfo->grabbed &= ~(1 << event->button.button); @@ -5957,9 +6259,9 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) } static gboolean -scroll_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +scroll_event (GtkWidget * widget, GdkEvent * event, gpointer * user_data) { - PGTK_TRACE("scroll_event"); + PGTK_TRACE ("scroll_event"); union buffered_input_event inev; struct frame *f, *frame; struct pgtk_display_info *dpyinfo; @@ -5968,159 +6270,194 @@ scroll_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); dpyinfo = FRAME_DISPLAY_INFO (frame); if (gui_mouse_grabbed (dpyinfo)) f = dpyinfo->last_mouse_frame; else - f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); inev.ie.kind = WHEEL_EVENT; inev.ie.timestamp = event->scroll.time; - inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state); + inev.ie.modifiers = + pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state); XSETINT (inev.ie.x, event->scroll.x); XSETINT (inev.ie.y, event->scroll.y); XSETFRAME (inev.ie.frame_or_window, f); inev.ie.arg = Qnil; - switch (event->scroll.direction) { - case GDK_SCROLL_UP: - inev.ie.kind = WHEEL_EVENT; - inev.ie.modifiers |= up_modifier; - break; - case GDK_SCROLL_DOWN: - inev.ie.kind = WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; - break; - case GDK_SCROLL_LEFT: - inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= up_modifier; - break; - case GDK_SCROLL_RIGHT: - inev.ie.kind = HORIZ_WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; - break; - case GDK_SCROLL_SMOOTH: - if (event->scroll.delta_y >= 0.5) { - inev.ie.kind = WHEEL_EVENT; - inev.ie.modifiers |= down_modifier; - } else if (event->scroll.delta_y <= -0.5) { + switch (event->scroll.direction) + { + case GDK_SCROLL_UP: inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - } else if (event->scroll.delta_x >= 0.5) { - inev.ie.kind = HORIZ_WHEEL_EVENT; + break; + case GDK_SCROLL_DOWN: + inev.ie.kind = WHEEL_EVENT; inev.ie.modifiers |= down_modifier; - } else if (event->scroll.delta_x <= -0.5) { + break; + case GDK_SCROLL_LEFT: inev.ie.kind = HORIZ_WHEEL_EVENT; inev.ie.modifiers |= up_modifier; - } else + break; + case GDK_SCROLL_RIGHT: + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + break; + case GDK_SCROLL_SMOOTH: + if (event->scroll.delta_y >= 0.5) + { + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + } + else if (event->scroll.delta_y <= -0.5) + { + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + } + else if (event->scroll.delta_x >= 0.5) + { + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + } + else if (event->scroll.delta_x <= -0.5) + { + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + } + else + return TRUE; + break; + default: return TRUE; - break; - default: - return TRUE; - } + } if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; } -static gboolean drag_drop(GtkWidget *widget, - GdkDragContext *context, - gint x, gint y, - guint time_, - gpointer user_data) +static gboolean +drag_drop (GtkWidget * widget, + GdkDragContext * context, + gint x, gint y, guint time_, gpointer user_data) { - PGTK_TRACE("drag_drop"); - GdkAtom target = gtk_drag_dest_find_target(widget, context, NULL); - PGTK_TRACE("drag_drop: target: %p", (void *) target); + PGTK_TRACE ("drag_drop"); + GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL); + PGTK_TRACE ("drag_drop: target: %p", (void *) target); - if (target == GDK_NONE) { - gtk_drag_finish(context, TRUE, FALSE, time_); - return FALSE; - } + if (target == GDK_NONE) + { + gtk_drag_finish (context, TRUE, FALSE, time_); + return FALSE; + } - gtk_drag_get_data(widget, context, target, time_); + gtk_drag_get_data (widget, context, target, time_); return TRUE; } -static void drag_data_received(GtkWidget *widget, GdkDragContext *context, - gint x, gint y, - GtkSelectionData *data, - guint info, guint time_, - gpointer user_data) +static void +drag_data_received (GtkWidget * widget, GdkDragContext * context, + gint x, gint y, + GtkSelectionData * data, + guint info, guint time_, gpointer user_data) { - PGTK_TRACE("drag_data_received:"); - struct frame *f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); - gchar **uris = gtk_selection_data_get_uris(data); + PGTK_TRACE ("drag_data_received:"); + struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + gchar **uris = gtk_selection_data_get_uris (data); - if (uris != NULL) { - for (int i = 0; uris[i] != NULL; i++) { - union buffered_input_event inev; - Lisp_Object arg = Qnil; + if (uris != NULL) + { + for (int i = 0; uris[i] != NULL; i++) + { + union buffered_input_event inev; + Lisp_Object arg = Qnil; - PGTK_TRACE("drag_data_received: uri: %s", uris[i]); + PGTK_TRACE ("drag_data_received: uri: %s", uris[i]); - EVENT_INIT (inev.ie); - inev.ie.kind = NO_EVENT; - inev.ie.arg = Qnil; + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; - arg = list2(Qurl, build_string(uris[i])); + arg = list2 (Qurl, build_string (uris[i])); - inev.ie.kind = DRAG_N_DROP_EVENT; - inev.ie.modifiers = 0; - XSETINT(inev.ie.x, x); - XSETINT(inev.ie.y, y); - XSETFRAME(inev.ie.frame_or_window, f); - inev.ie.arg = arg; - inev.ie.timestamp = 0; + inev.ie.kind = DRAG_N_DROP_EVENT; + inev.ie.modifiers = 0; + XSETINT (inev.ie.x, x); + XSETINT (inev.ie.y, y); + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.arg = arg; + inev.ie.timestamp = 0; - evq_enqueue (&inev); + evq_enqueue (&inev); + } } - } - PGTK_TRACE("drag_data_received: that's all."); + PGTK_TRACE ("drag_data_received: that's all."); - gtk_drag_finish(context, TRUE, FALSE, time_); + gtk_drag_finish (context, TRUE, FALSE, time_); } void -pgtk_set_event_handler(struct frame *f) -{ - gtk_drag_dest_set(FRAME_GTK_WIDGET(f), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); - gtk_drag_dest_add_uri_targets(FRAME_GTK_WIDGET(f)); - - g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "window-state-event", G_CALLBACK(window_state_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "delete-event", G_CALLBACK(delete_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "map-event", G_CALLBACK(map_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "event", G_CALLBACK(pgtk_handle_event), NULL); - - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "size-allocate", G_CALLBACK(size_allocate), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "key-press-event", G_CALLBACK(key_press_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "key-release-event", G_CALLBACK(key_release_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "focus-in-event", G_CALLBACK(focus_in_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "focus-out-event", G_CALLBACK(focus_out_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "enter-notify-event", G_CALLBACK(enter_notify_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "leave-notify-event", G_CALLBACK(leave_notify_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "motion-notify-event", G_CALLBACK(motion_notify_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "button-press-event", G_CALLBACK(button_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "button-release-event", G_CALLBACK(button_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "scroll-event", G_CALLBACK(scroll_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "selection-clear-event", G_CALLBACK(pgtk_selection_lost), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "configure-event", G_CALLBACK(configure_event), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "drag-drop", G_CALLBACK(drag_drop), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "drag-data-received", G_CALLBACK(drag_data_received), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "draw", G_CALLBACK(pgtk_handle_draw), NULL); - g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "event", G_CALLBACK(pgtk_handle_event), NULL); +pgtk_set_event_handler (struct frame *f) +{ + gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0, + GDK_ACTION_COPY); + gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f)); + + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), + "window-state-event", G_CALLBACK (window_state_event), + NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "delete-event", + G_CALLBACK (delete_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "map-event", + G_CALLBACK (map_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), "event", + G_CALLBACK (pgtk_handle_event), NULL); + + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "size-allocate", + G_CALLBACK (size_allocate), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-press-event", + G_CALLBACK (key_press_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "key-release-event", + G_CALLBACK (key_release_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-in-event", + G_CALLBACK (focus_in_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "focus-out-event", + G_CALLBACK (focus_out_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "enter-notify-event", + G_CALLBACK (enter_notify_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "leave-notify-event", + G_CALLBACK (leave_notify_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "motion-notify-event", + G_CALLBACK (motion_notify_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-press-event", + G_CALLBACK (button_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "button-release-event", + G_CALLBACK (button_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event", + G_CALLBACK (scroll_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event", + G_CALLBACK (pgtk_selection_lost), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", + G_CALLBACK (configure_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop", + G_CALLBACK (drag_drop), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", + G_CALLBACK (drag_data_received), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", + G_CALLBACK (pgtk_handle_draw), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event", + G_CALLBACK (pgtk_handle_event), NULL); } static void -my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, - const gchar *msg, gpointer user_data) +my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, + const gchar * msg, gpointer user_data) { if (!strstr (msg, "g_set_prgname")) - fprintf (stderr, "%s-WARNING **: %s", log_domain, msg); + fprintf (stderr, "%s-WARNING **: %s", log_domain, msg); } /* Test whether two display-name strings agree up to the dot that separates @@ -6139,22 +6476,22 @@ same_x_server (const char *name1, const char *name2) length_until_period++; /* Treat `unix' like an empty host name. */ - if (! strncmp (name1, "unix:", 5)) + if (!strncmp (name1, "unix:", 5)) name1 += 4; - if (! strncmp (name2, "unix:", 5)) + if (!strncmp (name2, "unix:", 5)) name2 += 4; /* Treat this host's name like an empty host name. */ - if (! strncmp (name1, system_name, system_name_length) + if (!strncmp (name1, system_name, system_name_length) && name1[system_name_length] == ':') name1 += system_name_length; - if (! strncmp (name2, system_name, system_name_length) + if (!strncmp (name2, system_name, system_name_length) && name2[system_name_length] == ':') name2 += system_name_length; /* Treat this host's domainless name like an empty host name. */ - if (! strncmp (name1, system_name, length_until_period) + if (!strncmp (name1, system_name, length_until_period) && name1[length_until_period] == ':') name1 += length_until_period; - if (! strncmp (name2, system_name, length_until_period) + if (!strncmp (name2, system_name, length_until_period) && name2[length_until_period] == ':') name2 += length_until_period; @@ -6201,7 +6538,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) } dpy_name = SSDATA (display_name); - if (strlen(dpy_name) == 0 && initial_display != NULL) + if (strlen (dpy_name) == 0 && initial_display != NULL) dpy_name = initial_display; lisp_dpy_name = build_string (dpy_name); @@ -6227,11 +6564,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) argc = 0; argv[argc++] = initial_argv[0]; - if (strlen(dpy_name) != 0) - { - argv[argc++] = display_opt; - argv[argc++] = dpy_name; - } + if (strlen (dpy_name) != 0) + { + argv[argc++] = display_opt; + argv[argc++] = dpy_name; + } argv[argc++] = name_opt; argv[argc++] = resource_name; @@ -6239,11 +6576,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) /* Work around GLib bug that outputs a faulty warning. See https://bugzilla.gnome.org/show_bug.cgi?id=563627. */ id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL - | G_LOG_FLAG_RECURSION, my_log_handler, NULL); + | G_LOG_FLAG_RECURSION, my_log_handler, NULL); /* gtk_init does set_locale. Fix locale before and after. */ fixup_locale (); - unrequest_sigio (); /* See comment in x_display_ok. */ + unrequest_sigio (); /* See comment in x_display_ok. */ gtk_init (&argc, &argv2); request_sigio (); fixup_locale (); @@ -6255,9 +6592,9 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpy = DEFAULT_GDK_DISPLAY (); - initial_display = g_strdup (gdk_display_get_name(dpy)); + initial_display = g_strdup (gdk_display_get_name (dpy)); dpy_name = initial_display; - lisp_dpy_name = build_string(dpy_name); + lisp_dpy_name = build_string (dpy_name); } } @@ -6327,22 +6664,22 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy); dpyinfo->vertical_scroll_bar_cursor - = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_SB_V_DOUBLE_ARROW); + = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_V_DOUBLE_ARROW); dpyinfo->horizontal_scroll_bar_cursor - = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW); + = gdk_cursor_new_for_display (dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW); reset_mouse_highlight (&dpyinfo->mouse_highlight); { - GdkScreen *gscr = gdk_display_get_default_screen(dpyinfo->gdpy); + GdkScreen *gscr = gdk_display_get_default_screen (dpyinfo->gdpy); - GSettings *set = g_settings_new("org.gnome.desktop.interface"); - gdouble x = g_settings_get_double(set,"text-scaling-factor"); + GSettings *set = g_settings_new ("org.gnome.desktop.interface"); + gdouble x = g_settings_get_double (set, "text-scaling-factor"); gdouble dpi = 0; - dpi = 96.0 * x; - gdk_screen_set_resolution(gscr, dpi); + dpi = 96.0 * x; + gdk_screen_set_resolution (gscr, dpi); dpyinfo->resx = dpi; dpyinfo->resy = dpi; } @@ -6351,7 +6688,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) xsettings_initialize (dpyinfo); - pgtk_selection_init(); + pgtk_selection_init (); pgtk_im_init (dpyinfo); @@ -6399,31 +6736,32 @@ pgtk_xlfd_to_fontname (const char *xlfd) The string returned is temporarily allocated. -------------------------------------------------------------------------- */ { - PGTK_TRACE("pgtk_xlfd_to_fontname"); + PGTK_TRACE ("pgtk_xlfd_to_fontname"); char *name = xmalloc (180); - if (!strncmp (xlfd, "--", 2)) { - if (sscanf (xlfd, "--%179[^-]-", name) != 1) - name[0] = '\0'; - } else { - if (sscanf (xlfd, "-%*[^-]-%179[^-]-", name) != 1) - name[0] = '\0'; - } + if (!strncmp (xlfd, "--", 2)) + { + if (sscanf (xlfd, "--%179[^-]-", name) != 1) + name[0] = '\0'; + } + else + { + if (sscanf (xlfd, "-%*[^-]-%179[^-]-", name) != 1) + name[0] = '\0'; + } /* stopgap for malformed XLFD input */ if (strlen (name) == 0) strcpy (name, "Monospace"); - PGTK_TRACE("converted '%s' to '%s'", xlfd, name); + PGTK_TRACE ("converted '%s' to '%s'", xlfd, name); return name; } bool pgtk_defined_color (struct frame *f, - const char *name, - Emacs_Color *color_def, - bool alloc, - bool makeIndex) + const char *name, + Emacs_Color * color_def, bool alloc, bool makeIndex) /* -------------------------------------------------------------------------- Return true if named color found, and set color_def rgb accordingly. If makeIndex and alloc are nonzero put the color in the color_table, @@ -6436,7 +6774,7 @@ pgtk_defined_color (struct frame *f, int r; block_input (); - r = xg_check_special_colors(f, name, color_def); + r = xg_check_special_colors (f, name, color_def); if (!r) r = pgtk_parse_color (f, name, color_def); unblock_input (); @@ -6451,22 +6789,24 @@ pgtk_defined_color (struct frame *f, and names we've actually looked up; list-colors-display is probably the most color-intensive case we're likely to hit. */ -int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color *color) +int +pgtk_parse_color (struct frame *f, const char *color_name, + Emacs_Color * color) { - PGTK_TRACE("pgtk_parse_color: %s", color_name); + PGTK_TRACE ("pgtk_parse_color: %s", color_name); GdkRGBA rgba; - if (gdk_rgba_parse(&rgba, color_name)) { - color->red = rgba.red * 65535; - color->green = rgba.green * 65535; - color->blue = rgba.blue * 65535; - color->pixel = - (unsigned long) 0xff << 24 | - (color->red >> 8) << 16 | - (color->green >> 8) << 8 | - (color->blue >> 8) << 0; - return 1; - } + if (gdk_rgba_parse (&rgba, color_name)) + { + color->red = rgba.red * 65535; + color->green = rgba.green * 65535; + color->blue = rgba.blue * 65535; + color->pixel = + (unsigned long) 0xff << 24 | + (color->red >> 8) << 16 | + (color->green >> 8) << 8 | (color->blue >> 8) << 0; + return 1; + } return 0; } @@ -6474,9 +6814,9 @@ int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color *colo colors in COLORS. On W32, we no longer try to map colors to a palette. */ void -pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors) +pgtk_query_colors (struct frame *f, Emacs_Color * colors, int ncolors) { - PGTK_TRACE("pgtk_query_colors"); + PGTK_TRACE ("pgtk_query_colors"); int i; for (i = 0; i < ncolors; i++) @@ -6489,28 +6829,30 @@ pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors) colors[i].red = GetRValue (pixel) * 257; colors[i].green = GetGValue (pixel) * 257; colors[i].blue = GetBValue (pixel) * 257; - PGTK_TRACE("pixel: %lx, red: %d, blue %d, green %d", colors[i].pixel, colors[i].red, colors[i].blue, colors[i].green); + PGTK_TRACE ("pixel: %lx, red: %d, blue %d, green %d", colors[i].pixel, + colors[i].red, colors[i].blue, colors[i].green); } } void -pgtk_query_color (struct frame *f, Emacs_Color *color) +pgtk_query_color (struct frame *f, Emacs_Color * color) { - PGTK_TRACE("pgtk_query_color"); + PGTK_TRACE ("pgtk_query_color"); pgtk_query_colors (f, color, 1); } void pgtk_clear_area (struct frame *f, int x, int y, int width, int height) { - PGTK_TRACE("pgtk_clear_area: %dx%d+%d+%d.", width, height, x, y); + PGTK_TRACE ("pgtk_clear_area: %dx%d+%d+%d.", width, height, x, y); cairo_t *cr; eassert (width > 0 && height > 0); cr = pgtk_begin_cr_clip (f); - PGTK_TRACE("back color %08lx.", (unsigned long) FRAME_X_OUTPUT(f)->background_color); - pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT(f)->background_color); + PGTK_TRACE ("back color %08lx.", + (unsigned long) FRAME_X_OUTPUT (f)->background_color); + pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT (f)->background_color); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); pgtk_end_cr_clip (f); @@ -6534,7 +6876,8 @@ syms_of_pgtkterm (void) DEFSYM (Qlatin_1, "latin-1"); - xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); + xg_default_icon_file = + build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); staticpro (&xg_default_icon_file); DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); @@ -6547,38 +6890,38 @@ syms_of_pgtkterm (void) Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier)); DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, - doc: /* Which keys Emacs uses for the ctrl modifier. + doc: /* Which keys Emacs uses for the ctrl modifier. This should be one of the symbols `ctrl', `alt', `hyper', `meta', `super'. For example, `ctrl' means use the Ctrl_L and Ctrl_R keysyms. -The default is nil, which is the same as `ctrl'. */); +The default is nil, which is the same as `ctrl'. */ ); Vx_ctrl_keysym = Qnil; DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym, - doc: /* Which keys Emacs uses for the alt modifier. + doc: /* Which keys Emacs uses for the alt modifier. This should be one of the symbols `ctrl', `alt', `hyper', `meta', `super'. For example, `alt' means use the Alt_L and Alt_R keysyms. -The default is nil, which is the same as `alt'. */); +The default is nil, which is the same as `alt'. */ ); Vx_alt_keysym = Qnil; DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym, - doc: /* Which keys Emacs uses for the hyper modifier. + doc: /* Which keys Emacs uses for the hyper modifier. This should be one of the symbols `ctrl', `alt', `hyper', `meta', `super'. For example, `hyper' means use the Hyper_L and Hyper_R -keysyms. The default is nil, which is the same as `hyper'. */); +keysyms. The default is nil, which is the same as `hyper'. */ ); Vx_hyper_keysym = Qnil; DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym, - doc: /* Which keys Emacs uses for the meta modifier. + doc: /* Which keys Emacs uses for the meta modifier. This should be one of the symbols `ctrl', `alt', `hyper', `meta', `super'. For example, `meta' means use the Meta_L and Meta_R keysyms. -The default is nil, which is the same as `meta'. */); +The default is nil, which is the same as `meta'. */ ); Vx_meta_keysym = Qnil; DEFVAR_LISP ("x-super-keysym", Vx_super_keysym, - doc: /* Which keys Emacs uses for the super modifier. + doc: /* Which keys Emacs uses for the super modifier. This should be one of the symbols `ctrl', `alt', `hyper', `meta', `super'. For example, `super' means use the Super_L and Super_R -keysyms. The default is nil, which is the same as `super'. */); +keysyms. The default is nil, which is the same as `super'. */ ); Vx_super_keysym = Qnil; /* TODO: move to common code */ @@ -6587,28 +6930,26 @@ keysyms. The default is nil, which is the same as `super'. */); A value of nil means Emacs doesn't use toolkit scroll bars. With the X Window system, the value is a symbol describing the X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. -With MS Windows or Nextstep, the value is t. */); +With MS Windows or Nextstep, the value is t. */ ); // Vx_toolkit_scroll_bars = Qt; Vx_toolkit_scroll_bars = intern_c_string ("gtk"); - DEFVAR_BOOL ("x-use-underline-position-properties", - x_use_underline_position_properties, - doc: /*Non-nil means make use of UNDERLINE_POSITION font properties. + DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties, + doc: /*Non-nil means make use of UNDERLINE_POSITION font properties. A value of nil means ignore them. If you encounter fonts with bogus UNDERLINE_POSITION font properties, for example 7x13 on XFree prior to 4.1, set this to nil. */); x_use_underline_position_properties = 0; - DEFVAR_BOOL ("x-underline-at-descent-line", - x_underline_at_descent_line, - doc: /* Non-nil means to draw the underline at the same place as the descent line. + DEFVAR_BOOL ("x-underline-at-descent-line", x_underline_at_descent_line, + doc: /* Non-nil means to draw the underline at the same place as the descent line. A value of nil means to draw the underline according to the value of the variable `x-use-underline-position-properties', which is usually at the baseline level. The default value is nil. */); x_underline_at_descent_line = 0; DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move, - doc: /* Non-nil means rely on gtk_window_move to set frame positions. + doc: /* Non-nil means rely on gtk_window_move to set frame positions. If this variable is t (the default), the GTK build uses the function gtk_window_move to set or store frame positions and disables some time consuming frame position adjustments. In newer versions of GTK, Emacs @@ -6618,7 +6959,7 @@ always uses gtk_window_move and ignores the value of this variable. */); DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout, - doc: /* How long to wait for X events. + doc: /* How long to wait for X events. Emacs will wait up to this many seconds to receive X events after making changes which affect the state of the graphical interface. @@ -6629,14 +6970,13 @@ If set to a non-float value, there will be no wait at all. */); Vpgtk_wait_for_event_timeout = make_float (0.1); DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table, - doc: /* Hash table of character codes indexed by X keysym codes. */); - Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, - DEFAULT_REHASH_SIZE, - DEFAULT_REHASH_THRESHOLD, - Qnil, false); + doc: /* Hash table of character codes indexed by X keysym codes. */); + Vpgtk_keysym_table = + make_hash_table (hashtest_eql, 900, DEFAULT_REHASH_SIZE, + DEFAULT_REHASH_THRESHOLD, Qnil, false); window_being_scrolled = Qnil; - staticpro(&window_being_scrolled); + staticpro (&window_being_scrolled); /* Tell Emacs about this window system. */ Fprovide (Qpgtk, Qnil); @@ -6653,15 +6993,15 @@ If set to a non-float value, there will be no wait at all. */); void pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) { - PGTK_TRACE("pgtk_cr_update_surface_desired_size"); + PGTK_TRACE ("pgtk_cr_update_surface_desired_size"); if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) { - pgtk_cr_destroy_frame_context(f); + pgtk_cr_destroy_frame_context (f); FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width; FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height; - SET_FRAME_GARBAGED(f); + SET_FRAME_GARBAGED (f); } } @@ -6671,14 +7011,16 @@ pgtk_begin_cr_clip (struct frame *f) { cairo_t *cr = FRAME_CR_CONTEXT (f); - PGTK_TRACE("pgtk_begin_cr_clip"); + PGTK_TRACE ("pgtk_begin_cr_clip"); if (!cr) { cairo_surface_t *surface = - gdk_window_create_similar_surface(gtk_widget_get_window (FRAME_GTK_WIDGET (f)), - CAIRO_CONTENT_COLOR_ALPHA, - FRAME_CR_SURFACE_DESIRED_WIDTH (f), - FRAME_CR_SURFACE_DESIRED_HEIGHT (f)); + gdk_window_create_similar_surface (gtk_widget_get_window + (FRAME_GTK_WIDGET (f)), + CAIRO_CONTENT_COLOR_ALPHA, + FRAME_CR_SURFACE_DESIRED_WIDTH (f), + FRAME_CR_SURFACE_DESIRED_HEIGHT + (f)); cr = FRAME_CR_CONTEXT (f) = cairo_create (surface); cairo_surface_destroy (surface); @@ -6692,51 +7034,52 @@ pgtk_begin_cr_clip (struct frame *f) void pgtk_end_cr_clip (struct frame *f) { - PGTK_TRACE("pgtk_end_cr_clip"); + PGTK_TRACE ("pgtk_end_cr_clip"); cairo_restore (FRAME_CR_CONTEXT (f)); } void -pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc) +pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC * gc) { PGTK_TRACE ("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); - pgtk_set_cr_source_with_color(f, gc->foreground); + pgtk_set_cr_source_with_color (f, gc->foreground); } void -pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc) +pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC * gc) { - PGTK_TRACE("pgtk_set_cr_source_with_gc_background: %08lx", gc->background); - pgtk_set_cr_source_with_color(f, gc->background); + PGTK_TRACE ("pgtk_set_cr_source_with_gc_background: %08lx", gc->background); + pgtk_set_cr_source_with_color (f, gc->background); } void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) { - PGTK_TRACE("pgtk_set_cr_source_with_color: %08lx.", color); + PGTK_TRACE ("pgtk_set_cr_source_with_color: %08lx.", color); Emacs_Color col; col.pixel = color; - pgtk_query_color(f, &col); + pgtk_query_color (f, &col); cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0, col.green / 65535.0, col.blue / 65535.0); } void -pgtk_cr_draw_frame (cairo_t *cr, struct frame *f) +pgtk_cr_draw_frame (cairo_t * cr, struct frame *f) { - PGTK_TRACE("pgtk_cr_draw_frame"); - cairo_set_source_surface(cr, FRAME_CR_SURFACE(f), 0, 0); - cairo_paint(cr); + PGTK_TRACE ("pgtk_cr_draw_frame"); + cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0); + cairo_paint (cr); } void -pgtk_cr_destroy_frame_context(struct frame *f) +pgtk_cr_destroy_frame_context (struct frame *f) { - PGTK_TRACE("pgtk_cr_destroy_frame_context"); - if (FRAME_CR_CONTEXT(f) != NULL) { - cairo_destroy(FRAME_CR_CONTEXT(f)); - FRAME_CR_CONTEXT(f) = NULL; - } + PGTK_TRACE ("pgtk_cr_destroy_frame_context"); + if (FRAME_CR_CONTEXT (f) != NULL) + { + cairo_destroy (FRAME_CR_CONTEXT (f)); + FRAME_CR_CONTEXT (f) = NULL; + } } void commit a167e23560b6de6eddb149f9332377c41f455b30 Author: Yuuki Harano Date: Sun May 17 20:04:18 2020 +0900 * src/pgtkmenu.c (set_frame_menubar): Suppress gcc warning diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index acc9ab3827..d86612e13f 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -325,7 +325,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) /* Save the frame's previous menu bar contents data. */ if (previous_menu_items_used) - memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents, + memcpy (previous_items, xvector_contents (f->menu_bar_vector), previous_menu_items_used * word_size); /* Fill in menu_items with the current menu bar contents. commit d68633bfa1124e32f6aa6a288a9c7b2098a39bd8 Author: Yuuki Harano Date: Tue May 12 22:39:15 2020 +0900 * src/pgtkterm.c (pgtk_defined_color): support gtk special colors Color functions take the frame * src/gtkutil.c (xg_check_special_colors): pass frame as argument. * src/pgtkfns.c (x_set_foreground_color, x_set_background_color, x_set_cursor_color, pgtk_set_scroll_bar_foreground, pgtk_set_scroll_bar_background, Fxw_color_defined_p, Fxw_color_values): pass frame as argument. * src/pgtkterm.c (pgtk_parse_color): take frame as argument. (pgtk_lisp_to_color): take frame as argument, and pass it. Remove pgtk_lisp_to_color * src/pgtkfns.c (x_set_foreground_color, x_set_background_color, x_set_cursor_color): use x_decode_color instead of pgtk_lisp_to_color. (Fxw_color_defined_p, Fxw_color_values): use pgtk_defined_color instead of pgtk_lisp_to_color. * src/pgtkterm.c (pgtk_lisp_to_color): remove. * src/gtkutil.c (xg_check_special_colors): change color format * src/pgtkterm.h: remove pgtk_lisp_to_color declaration diff --git a/src/gtkutil.c b/src/gtkutil.c index 16fac6cc08..ce08ffec37 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -710,11 +710,12 @@ xg_check_special_colors (struct frame *f, r = col.red * 65535, g = col.green * 65535, b = col.blue * 65535; - sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b); #ifndef HAVE_PGTK + sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b); success_p = x_parse_color (f, buf, color) != 0; #else - success_p = pgtk_parse_color (buf, color) != 0; + sprintf (buf, "#%04x%04x%04x", r, g, b); + success_p = pgtk_parse_color (f, buf, color) != 0; #endif #else GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 79c9aab1a2..feda093384 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -133,22 +133,11 @@ pgtk_display_info_for_name (Lisp_Object name) static void x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - Emacs_Color col; - - /* Must block_input, because pgtk_lisp_to_color does block/unblock_input - which means that col may be deallocated in its unblock_input if there - is user input, unless we also block_input. */ - block_input (); - if (pgtk_lisp_to_color (arg, &col)) - { - store_frame_param (f, Qforeground_color, oldval); - unblock_input (); - error ("Unknown color"); - } + unsigned long fg; - FRAME_X_OUTPUT(f)->foreground_color = col.pixel; - - FRAME_FOREGROUND_PIXEL (f) = col.pixel; + fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + FRAME_FOREGROUND_PIXEL (f) = fg; + FRAME_X_OUTPUT(f)->foreground_color = fg; if (FRAME_GTK_WIDGET (f)) { @@ -157,40 +146,30 @@ x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (FRAME_VISIBLE_P (f)) SET_FRAME_GARBAGED (f); } - unblock_input (); } static void x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - Emacs_Color col; + unsigned long bg; - block_input (); - if (pgtk_lisp_to_color (arg, &col)) - { - store_frame_param (f, Qbackground_color, oldval); - unblock_input (); - error ("Unknown color"); - } + bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f)); + FRAME_BACKGROUND_PIXEL (f) = bg; /* clear the frame */ if (FRAME_VISIBLE_P (f)) pgtk_clear_frame (f); - PGTK_TRACE("x_set_background_color: col.pixel=%08lx.", col.pixel); - FRAME_X_OUTPUT(f)->background_color = col.pixel; - FRAME_BACKGROUND_PIXEL (f) = - ARGB_TO_ULONG ((unsigned int)(0xff), (unsigned int)(col.red>>8), (unsigned int)(col.green>>8), (unsigned int)(col.blue>>8)); + PGTK_TRACE("x_set_background_color: col.pixel=%08lx.", bg); + FRAME_X_OUTPUT(f)->background_color = bg; - xg_set_background_color(f, col.pixel); + xg_set_background_color(f, bg); update_face_from_frame_parameter (f, Qbackground_color, arg); PGTK_TRACE("visible_p=%d.", FRAME_VISIBLE_P(f)); if (FRAME_VISIBLE_P (f)) SET_FRAME_GARBAGED (f); - - unblock_input (); } static void @@ -209,20 +188,16 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { unsigned long fore_pixel, pixel; struct pgtk_output *x = f->output_data.pgtk; - Emacs_Color col; if (!NILP (Vx_cursor_fore_pixel)) { - if (pgtk_lisp_to_color(Vx_cursor_fore_pixel, &col)) - signal_error ("Undefined color", Vx_cursor_fore_pixel); - fore_pixel = col.pixel; + fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel, + WHITE_PIX_DEFAULT (f)); } else fore_pixel = FRAME_BACKGROUND_PIXEL (f); - if (pgtk_lisp_to_color(arg, &col)) - signal_error ("Undefined color", arg); - pixel = col.pixel; + pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); /* Make sure that the cursor color differs from the background color. */ if (pixel == FRAME_BACKGROUND_PIXEL (f)) @@ -817,7 +792,7 @@ pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, Lisp_Obj } else if (STRINGP (new_value)) { Emacs_Color rgb; - if (!pgtk_parse_color (SSDATA (new_value), &rgb)) + if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) error ("Unknown color."); char css[64]; @@ -838,7 +813,7 @@ pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, Lisp_Obj } else if (STRINGP (new_value)) { Emacs_Color rgb; - if (!pgtk_parse_color (SSDATA (new_value), &rgb)) + if (!pgtk_parse_color (f, SSDATA (new_value), &rgb)) error ("Unknown color."); char css[64]; @@ -2149,7 +2124,14 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { Emacs_Color col; - return pgtk_lisp_to_color (color, &col) ? Qnil : Qt; + struct frame *f = decode_window_system_frame (frame); + + CHECK_STRING (color); + + if (pgtk_defined_color (f, SSDATA (color), &col, false, false)) + return Qt; + else + return Qnil; } @@ -2158,20 +2140,14 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { Emacs_Color col; + struct frame *f = decode_window_system_frame (frame); CHECK_STRING (color); - block_input (); - - if (pgtk_lisp_to_color (color, &col)) - { - unblock_input (); - return Qnil; - } - - unblock_input (); - - return list3i (col.red, col.green, col.blue); + if (pgtk_defined_color (f, SSDATA (color), &col, false, false)) + return list3i (col.red, col.green, col.blue); + else + return Qnil; } diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 2d1a990483..ef8daba720 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6436,7 +6436,9 @@ pgtk_defined_color (struct frame *f, int r; block_input (); - r = pgtk_parse_color (name, color_def); + r = xg_check_special_colors(f, name, color_def); + if (!r) + r = pgtk_parse_color (f, name, color_def); unblock_input (); return r; } @@ -6449,7 +6451,7 @@ pgtk_defined_color (struct frame *f, and names we've actually looked up; list-colors-display is probably the most color-intensive case we're likely to hit. */ -int pgtk_parse_color (const char *color_name, Emacs_Color *color) +int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color *color) { PGTK_TRACE("pgtk_parse_color: %s", color_name); @@ -6468,20 +6470,6 @@ int pgtk_parse_color (const char *color_name, Emacs_Color *color) return 0; } -int -pgtk_lisp_to_color (Lisp_Object color, Emacs_Color *col) -/* -------------------------------------------------------------------------- - Convert a Lisp string object to a NS color - -------------------------------------------------------------------------- */ -{ - PGTK_TRACE("pgtk_lisp_to_color"); - if (STRINGP (color)) - return !pgtk_parse_color (SSDATA (color), col); - else if (SYMBOLP (color)) - return !pgtk_parse_color (SSDATA (SYMBOL_NAME (color)), col); - return 1; -} - /* On frame F, translate pixel colors to RGB values for the NCOLORS colors in COLORS. On W32, we no longer try to map colors to a palette. */ diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 706198aa8a..b92a2cd1d1 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -534,8 +534,7 @@ extern bool pgtk_defined_color (struct frame *f, bool makeIndex); extern void pgtk_query_color (struct frame *f, Emacs_Color *color); extern void pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors); -extern int pgtk_parse_color (const char *color_name, Emacs_Color *color); -extern int pgtk_lisp_to_color (Lisp_Object color, Emacs_Color *col); +extern int pgtk_parse_color (struct frame *f, const char *color_name, Emacs_Color *color); /* Implemented in pgtkterm.c */ extern void pgtk_clear_area (struct frame *f, int x, int y, int width, int height); commit fe2297ce7aa0e400f4a80484e2872dcee0de1391 Author: Yuuki Harano Date: Wed May 6 19:04:23 2020 +0900 * pgtkmenu.c (set_frame_menubar): fix empty menu. diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 6f4195d6d8..acc9ab3827 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -277,6 +277,10 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) if (! menubar_widget) deep_p = true; + /* Since button_event handler in pgtk emacs doesn't handle mouse + * events in menubars, the menu needs to be built now. */ + deep_p = true; + if (deep_p) { struct buffer *prev = current_buffer; commit 8669feb0c5c1b8fe3a9bf8489420e786c3367b2a Author: Yuuki Harano Date: Wed May 6 12:55:04 2020 +0900 Make icons and titles work like on X * pgtk-win.el (frame-title-format, icon-title-format): remove. * pgtkfns.c (pgtk_set_name_as_filename): remove. * pgtkfns.c (pgtk_set_name_internal): remove gtk_window_set_icon_name call. * pgtkfns.c (pgtk_set_name): change value of update_mode_lines. * pgtkfns.c (pgtk_explicitly_set_name): prefer the symbol to an immediate value. * pgtkfns.c (pgtk_implicitly_set_name): remove pgtk_set_name_as_filename call. * pgtkfns.c (x_set_icon_type, x_set_icon_name): re-port from X code. * pgtkfns.c (xg_set_icon, xg_set_icon_from_xpm_data): port from X code. * pgtkterm.c (pgtk_bitmap_icon, pgtk_text_icon, pgtk_create_terminal): port from X code. * pgtkterm.h: add function declarations. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index f3239c6c1a..4598ba007b 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -281,10 +281,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (error "Cannot suspend Emacs while a PGTK GUI frame exists"))) -;; Set some options to be as Nextstep-like as possible. -(setq frame-title-format t - icon-title-format t) - (defvar pgtk-initialized nil "Non-nil if pure-GTK windowing has been initialized.") diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 9078a78e06..79c9aab1a2 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -50,7 +50,6 @@ static ptrdiff_t image_cache_refcount; static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); -static void pgtk_set_name_as_filename (struct frame *); static const char *pgtk_app_name = "Emacs"; @@ -253,58 +252,24 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) update_face_from_frame_parameter (f, Qcursor_color, arg); } - static void -x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +pgtk_set_name_internal (struct frame *f, Lisp_Object name) { - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); - PGTK_TRACE ("x_set_icon_name"); - - /* see if it's changed */ - if (STRINGP (arg)) + if (FRAME_GTK_WIDGET (f)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) - return; - } - else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) - return; + block_input (); + { + Lisp_Object encoded_name; - fset_icon_name (f, arg); + /* As ENCODE_UTF_8 may cause GC and relocation of string data, + we use it before x_encode_text that may return string data. */ + encoded_name = ENCODE_UTF_8 (name); - if (NILP (arg)) - { - if (!NILP (f->title)) - arg = f->title; - else - /* Explicit name and no icon-name -> explicit_name. */ - if (f->explicit_name) - arg = f->name; - else - { - /* No explicit name and no icon-name -> - name has to be rebuild from icon_title_format. */ - windows_or_buffers_changed = 67; - return; - } + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + SSDATA (encoded_name)); + } + unblock_input (); } - - gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA(arg)); -} - -static void -pgtk_set_name_internal (struct frame *f, Lisp_Object name) -{ - Lisp_Object encoded_name, encoded_icon_name; - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); - - encoded_name = ENCODE_UTF_8 (name); - gtk_window_set_title(GTK_WINDOW(widget), SSDATA (encoded_name)); - - if (!STRINGP (f->icon_name)) - encoded_icon_name = encoded_name; - else - encoded_icon_name = ENCODE_UTF_8 (f->icon_name); - gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA (encoded_icon_name)); } static void @@ -352,7 +317,7 @@ static void x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { PGTK_TRACE ("x_explicitly_set_name"); - pgtk_set_name (f, arg, 1); + pgtk_set_name (f, arg, true); } @@ -363,17 +328,7 @@ void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { PGTK_TRACE ("x_implicitly_set_name"); - - Lisp_Object frame_title = buffer_local_value - (Qframe_title_format, XWINDOW (f->selected_window)->contents); - Lisp_Object icon_title = buffer_local_value - (Qicon_title_format, XWINDOW (f->selected_window)->contents); - - if (FRAME_PGTK_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (icon_title, Qt)) - || EQ (frame_title, Qt))) - pgtk_set_name_as_filename (f); - else - pgtk_set_name (f, arg, 0); + pgtk_set_name (f, arg, false); } @@ -401,72 +356,6 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) } -static void -pgtk_set_name_as_filename (struct frame *f) -{ - GtkWidget *widget; - Lisp_Object name, filename; - Lisp_Object buf = XWINDOW (f->selected_window)->contents; - const char *title; - Lisp_Object encoded_name, encoded_filename; - const char *str; - PGTK_TRACE ("pgtk_set_name_as_filename"); - - if (f->explicit_name || ! NILP (f->title)) - return; - - block_input (); - filename = BVAR (XBUFFER (buf), filename); - name = BVAR (XBUFFER (buf), name); - - if (NILP (name)) - { - if (! NILP (filename)) - name = Ffile_name_nondirectory (filename); - else - name = build_string (pgtk_app_name); - } - - encoded_name = ENCODE_UTF_8 (name); - - widget = FRAME_GTK_OUTER_WIDGET (f); - - title = FRAME_ICONIFIED_P (f) ? gtk_window_get_icon_name(GTK_WINDOW(widget)) - : gtk_window_get_title(GTK_WINDOW(widget)); - - if (title && (! strcmp (title, SSDATA (encoded_name)))) - { - unblock_input (); - return; - } - - str = SSDATA (encoded_name); - if (str == NULL) str = "Bad coding"; - - if (FRAME_ICONIFIED_P (f)) - gtk_window_set_icon_name(GTK_WINDOW(widget), str); - else - { - const char *fstr; - - if (! NILP (filename)) - { - encoded_filename = ENCODE_UTF_8 (filename); - - fstr = SSDATA (encoded_filename); - if (fstr == NULL) fstr = ""; - } - else - fstr = ""; - - gtk_window_set_title(GTK_WINDOW(widget), str); - fset_name (f, name); - } - - unblock_input (); -} - - void pgtk_set_doc_edited (void) { @@ -665,26 +554,66 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva static void x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - /* This does not work if on Wayland, or if icon is defined in emacs.desktop - * even if on X11. - */ - GdkPixbuf *pixbuf; - if (NILP (arg) || EQ (arg, Qt)) - pixbuf = NULL; - else { - GError *err = NULL; - CHECK_STRING (arg); - pixbuf = gdk_pixbuf_new_from_file (SSDATA (arg), &err); - if (pixbuf == NULL) { - Lisp_Object msg = build_string (err->message); - g_error_free (err); - error ("%s", SSDATA (msg)); + bool result; + + if (STRINGP (arg)) + { + if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + return; } - } + else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) + return; - gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); - if (pixbuf != NULL) - g_object_unref (pixbuf); + block_input (); + if (NILP (arg)) + result = pgtk_text_icon (f, + SSDATA ((!NILP (f->icon_name) + ? f->icon_name + : f->name))); + else + result = FRAME_TERMINAL (f)->set_bitmap_icon_hook (f, arg); + + if (result) + { + unblock_input (); + error ("No icon window available"); + } + + unblock_input (); +} + + +static void +x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + bool result; + + if (STRINGP (arg)) + { + if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + return; + } + else if (!NILP (arg) || NILP (oldval)) + return; + + fset_icon_name (f, arg); + + block_input (); + + result = pgtk_text_icon (f, + SSDATA ((!NILP (f->icon_name) + ? f->icon_name + : !NILP (f->title) + ? f->title + : f->name))); + + if (result) + { + unblock_input (); + error ("No icon window available"); + } + + unblock_input (); } /* This is the same as the xfns.c definition. */ @@ -800,6 +729,56 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old } } +/* Set icon from FILE for frame F. By using GTK functions the icon + may be any format that GdkPixbuf knows about, i.e. not just bitmaps. */ + +bool +xg_set_icon (struct frame *f, Lisp_Object file) +{ + bool result = false; + Lisp_Object found; + + found = image_find_image_file (file); + + if (! NILP (found)) + { + GdkPixbuf *pixbuf; + GError *err = NULL; + char *filename = SSDATA (ENCODE_FILE (found)); + block_input (); + + pixbuf = gdk_pixbuf_new_from_file (filename, &err); + + if (pixbuf) + { + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + pixbuf); + g_object_unref (pixbuf); + + result = true; + } + else + g_error_free (err); + + unblock_input (); + } + + return result; +} + +bool +xg_set_icon_from_xpm_data (struct frame *f, const char **data) +{ + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data); + + if (!pixbuf) + return false; + + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); + g_object_unref (pixbuf); + return true; +} + static void pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) { diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 65d250b6de..2d1a990483 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2827,6 +2827,47 @@ pgtk_scroll_run (struct window *w, struct run *run) unblock_input (); } +/* Icons. */ + +/* Make the x-window of frame F use the gnu icon bitmap. */ + +static bool +pgtk_bitmap_icon (struct frame *f, Lisp_Object file) +{ + if (FRAME_GTK_WIDGET (f) == 0) + return true; + + if (STRINGP (file)) + { + /* Use gtk_window_set_icon_from_file () if available, + It's not restricted to bitmaps */ + if (xg_set_icon (f, file)) + return false; + + return true; + } + + if (xg_set_icon (f, xg_default_icon_file)) + { + return false; + } + + return true; +} + + +/* Make the x-window of frame F use a rectangle with text. + Use ICON_NAME as the text. */ + +bool +pgtk_text_icon (struct frame *f, const char *icon_name) +{ + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL); + gtk_window_set_title (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), icon_name); + + return false; +} + /*********************************************************************** Starting and ending an update ***********************************************************************/ @@ -4620,6 +4661,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->query_frame_background_color = pgtk_query_frame_background_color; terminal->defined_color_hook = pgtk_defined_color; terminal->set_new_font_hook = pgtk_new_font; + terminal->set_bitmap_icon_hook = pgtk_bitmap_icon; terminal->implicit_set_name_hook = pgtk_implicitly_set_name; terminal->iconify_frame_hook = pgtk_iconify_frame; terminal->set_scroll_bar_default_width_hook = pgtk_set_scroll_bar_default_width; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index e740318439..706198aa8a 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -621,4 +621,9 @@ extern bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev); extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); +extern bool xg_set_icon (struct frame *, Lisp_Object); +extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); + +extern bool pgtk_text_icon (struct frame *f, const char *icon_name); + #endif /* HAVE_PGTK */ commit 5a72a07fa5bcec2ad5265284dfb2a5dec7485e7f Author: Yuuki Harano Date: Sat May 2 00:21:03 2020 +0900 * pgtk-win.el: fix compile-time warnings. diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 2205ad662b..f3239c6c1a 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -4,7 +4,7 @@ (eval-when-compile (require 'cl-lib)) (or (featurep 'pgtk) (error "%s: Loading pgtk-win.el but not compiled for pure Gtk+-3." - (invocation-name))) + invocation-name)) ;; Documentation-purposes only: actually loaded in loadup.el. (require 'term/common-win) @@ -108,8 +108,9 @@ the last file dropped is selected." (defvar pgtk-right-control-modifier) ;; You say tomAYto, I say tomAHto.. -(defvaralias 'pgtk-option-modifier 'pgtk-alternate-modifier) -(defvaralias 'pgtk-right-option-modifier 'pgtk-right-alternate-modifier) +(with-no-warnings + (defvaralias 'pgtk-option-modifier 'pgtk-alternate-modifier) + (defvaralias 'pgtk-right-option-modifier 'pgtk-right-alternate-modifier)) (defun pgtk-do-hide-emacs () (interactive) @@ -306,7 +307,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") ;; Make sure we have a valid resource name. (or (stringp x-resource-name) (let (i) - (setq x-resource-name (invocation-name)) + (setq x-resource-name invocation-name) ;; Change any . or * characters in x-resource-name to hyphens, ;; so as not to choke when we use it in X resource queries. commit 014d56fa134f8f4810a716e0e076309c692edaba Author: Yuuki Harano Date: Mon Apr 27 23:51:01 2020 +0900 * src/pgtkterm.c: Remove incorrect mark_object call. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index e5f89cf742..65d250b6de 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -160,14 +160,6 @@ mark_pgtkterm(void) mark_object (ev->ie.frame_or_window); mark_object (ev->ie.arg); } - - struct pgtk_display_info *dpyinfo; - for (dpyinfo = x_display_list; dpyinfo != NULL; dpyinfo = dpyinfo->next) { -#if false /* marked in alloc.c:compact_font_caches() */ - mark_object (dpyinfo->name_list_element); -#endif - mark_object (dpyinfo->rdb); - } } char * commit 4de4d9ee7eeb0407346546f21cd0911a8cda337b Author: Yuuki Harano Date: Sat Apr 11 23:36:36 2020 +0900 follow x_set_internal_border_width change. * ../src/pgtkfns.c (x_set_internal_border_width): diff --git a/src/pgtkfns.c b/src/pgtkfns.c index b7d34d5680..9078a78e06 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -647,20 +647,18 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) static void x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - int old_width = FRAME_INTERNAL_BORDER_WIDTH (f); + int border = check_int_nonnegative (arg); - CHECK_TYPE_RANGED_INTEGER (int, arg); - f->internal_border_width = XFIXNUM (arg); - if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0) - f->internal_border_width = 0; - - if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width) - return; - - if (FRAME_X_WINDOW (f) != 0) - adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width); + if (border != FRAME_INTERNAL_BORDER_WIDTH (f)) + { + f->internal_border_width = border; - SET_FRAME_GARBAGED (f); + if (FRAME_X_WINDOW (f)) + { + adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width); + pgtk_clear_under_internal_border (f); + } + } } commit 984f9cc7e5393ae8b34358eab6f7443830e2fd8f Author: Yuuki Harano Date: Sat Apr 11 23:36:08 2020 +0900 restore frame_rehighlight_hook. * src/frame.c (gui_set_border_width): diff --git a/src/frame.c b/src/frame.c index 82735491d0..191b0268c5 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4649,6 +4649,11 @@ gui_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) #endif f->border_width = border_width; + +#ifdef HAVE_PGTK + if (FRAME_TERMINAL (f)->frame_rehighlight_hook) + (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f); +#endif } void commit de7b0daf2b70648c968356036110cbe8c0c3188c Author: Yuuki Harano Date: Sun Apr 5 19:23:10 2020 +0900 use pgtk_menu_set_in_use. * ../src/pgtkfns.c: (Fx_file_dialog, clean_up_dialog): * src/pgtkmenu.c (pgtk_menu_wait_for_event): diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 69a7430b8d..b7d34d5680 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2916,6 +2916,12 @@ visible. */) return Qnil; } +static void +clean_up_dialog (void) +{ + pgtk_menu_set_in_use (false); +} + DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, doc: /* Read file name, prompting with PROMPT in directory DIR. Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file @@ -2940,14 +2946,17 @@ value of DIR as in previous invocations; this is standard MS Windows behavior. check_window_system (f); + if (popup_activated ()) + error ("Trying to use a menu from within a menu-entry"); + else + pgtk_menu_set_in_use (true); + CHECK_STRING (prompt); CHECK_STRING (dir); /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); -#if 0 record_unwind_protect_void (clean_up_dialog); -#endif block_input (); diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index b9462208d6..6f4195d6d8 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -69,7 +69,7 @@ pgtk_menu_set_in_use (bool in_use) /* Wait for an X event to arrive or for a timer to expire. */ -void +static void pgtk_menu_wait_for_event (void *data) { struct timespec next_time = timer_check (), *ntp; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 73e04b7da6..e740318439 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -610,6 +610,9 @@ extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object); extern void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms); +extern void pgtk_menu_set_in_use (bool in_use); + + extern void pgtk_enqueue_string(struct frame *f, gchar *str); extern void pgtk_enqueue_preedit(struct frame *f, Lisp_Object image_data); extern void pgtk_im_focus_in(struct frame *f); commit 04bfe701381ebf292bfc123177c48efd22613d41 Author: Yuuki Harano Date: Fri Apr 3 23:36:41 2020 +0900 implement popup/context menu * ../src/pgtkterm.c (x_draw_glyph_string_background) (x_draw_glyph_string_foreground) (x_draw_composite_glyph_string_foreground) (x_draw_glyphless_glyph_string_foreground, x_draw_relief_rect) (x_draw_box_rect, x_draw_glyph_string_box, x_draw_image_relief) (x_draw_image_foreground, x_draw_image_glyph_string) (button_event): * src/pgtkterm.h (struct pgtk_display_info): * src/pgtkmenu.c (pgtk_menu_set_in_use) (pgtk_menu_wait_for_event, Fx_menu_bar_open_internal) (popup_widget_loop, pgtk_activate_menubar) (popup_deactivate_callback, show_help_event): new functions (menu_highlight_callback): remove (update_frame_menubar, popup_selection_callback, pop_down_menu) (create_and_show_popup_menu, cleanup_widget_value_tree) (pgtk_menu_show, dialog_selection_callback): new (create_and_show_dialog, pgtk_dialog_show, pgtk_popup_dialog) (popup_activated, Fmenu_or_popup_active_p, syms_of_pgtkmenu): diff --git a/src/gtkutil.c b/src/gtkutil.c index 6d6e4b4685..16fac6cc08 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -2968,9 +2968,15 @@ create_menus (widget_value *data, if (name) gtk_widget_set_name (wmenu, name); +#ifndef HAVE_PGTK if (deactivate_cb) g_signal_connect (G_OBJECT (wmenu), "selection-done", deactivate_cb, 0); +#else + if (deactivate_cb) + g_signal_connect (G_OBJECT (wmenu), + "deactivate", deactivate_cb, 0); +#endif } for (item = data; item; item = item->next) diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index 9148504f8e..b9462208d6 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -41,14 +41,162 @@ along with GNU Emacs. If not, see . */ #include "gtkutil.h" #include +/* Flag which when set indicates a dialog or menu has been posted by + Xt on behalf of one of the widget sets. */ +static int popup_activated_flag; -Lisp_Object -pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) +/* Set menu_items_inuse so no other popup menu or dialog is created. */ + +void +pgtk_menu_set_in_use (bool in_use) +{ + Lisp_Object frames, frame; + + menu_items_inuse = in_use; + popup_activated_flag = in_use; + + /* Don't let frames in `above' z-group obscure popups. */ + FOR_EACH_FRAME (frames, frame) + { + struct frame *f = XFRAME (frame); + + if (in_use && FRAME_Z_GROUP_ABOVE (f)) + x_set_z_group (f, Qabove_suspended, Qabove); + else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f)) + x_set_z_group (f, Qabove, Qabove_suspended); + } +} + +/* Wait for an X event to arrive or for a timer to expire. */ + +void +pgtk_menu_wait_for_event (void *data) +{ + struct timespec next_time = timer_check (), *ntp; + + if (! timespec_valid_p (next_time)) + ntp = 0; + else + ntp = &next_time; + + /* Gtk3 have arrows on menus when they don't fit. When the + pointer is over an arrow, a timeout scrolls it a bit. Use + xg_select so that timeout gets triggered. */ + pgtk_select (0, NULL, NULL, NULL, ntp, NULL); +} + +DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", + doc: /* Start key navigation of the menu bar in FRAME. +This initially opens the first menu bar item and you can then navigate with the +arrow keys, select a menu entry with the return key or cancel with the +escape key. If FRAME has no menu bar this function does nothing. + +If FRAME is nil or not given, use the selected frame. */) + (Lisp_Object frame) { + GtkWidget *menubar; + struct frame *f; + + block_input (); + f = decode_window_system_frame (frame); + + if (FRAME_EXTERNAL_MENU_BAR (f)) + set_frame_menubar (f, false, true); + + menubar = FRAME_X_OUTPUT (f)->menubar_widget; + if (menubar) + { + /* Activate the first menu. */ + GList *children = gtk_container_get_children (GTK_CONTAINER (menubar)); + + if (children) + { + g_signal_emit_by_name (children->data, "activate_item"); + g_list_free (children); + } + } + unblock_input (); + return Qnil; } +/* Loop util popup_activated_flag is set to zero in a callback. + Used for popup menus and dialogs. */ +static void +popup_widget_loop (bool do_timers, GtkWidget *widget) +{ + ++popup_activated_flag; + + /* Process events in the Gtk event loop until done. */ + while (popup_activated_flag) + { + if (do_timers) pgtk_menu_wait_for_event (0); + gtk_main_iteration (); + } +} + +void pgtk_activate_menubar (struct frame *f) +{ + set_frame_menubar(f, false, true); + + popup_activated_flag = 1; + + /* f->output_data.pgtk->menubar_active = 1; */ +} + +/* This callback is invoked when a dialog or menu is finished being + used and has been unposted. */ + +static void +popup_deactivate_callback (GtkWidget *widget, gpointer client_data) +{ + popup_activated_flag = 0; +} + +/* Function that finds the frame for WIDGET and shows the HELP text + for that widget. + F is the frame if known, or NULL if not known. */ +static void +show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help) +{ + Lisp_Object frame; + + if (f) + { + XSETFRAME (frame, f); + kbd_buffer_store_help_event (frame, help); + } + else + show_help_echo (help, Qnil, Qnil, Qnil); +} + +/* Callback called when menu items are highlighted/unhighlighted + while moving the mouse over them. WIDGET is the menu bar or menu + popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to + the data structure for the menu item, or null in case of + unhighlighting. */ + +static void +menu_highlight_callback (GtkWidget *widget, gpointer call_data) +{ + xg_menu_item_cb_data *cb_data; + Lisp_Object help; + + cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA); + if (! cb_data) return; + + help = call_data ? cb_data->help : Qnil; + + /* If popup_activated_flag is greater than 1 we are in a popup menu. + Don't pass the frame to show_help_event for those. + Passing frame creates an Emacs event. As we are looping in + popup_widget_loop, it won't be handled. Passing NULL shows the tip + directly without using an Emacs event. This is what the Lucid code + does below. */ + show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL, + widget, help); +} /* Gtk calls callbacks just because we tell it what item should be selected in a radio group. If this variable is set to a non-zero @@ -97,30 +245,15 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data) cb_data->call_data); } -static void -menu_highlight_callback (GtkWidget *widget, gpointer call_data) -{ - xg_menu_item_cb_data *cb_data; - Lisp_Object help; - - cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA); - if (! cb_data) return; - - help = call_data ? cb_data->help : Qnil; -} - - -/* This callback is invoked when a dialog or menu is finished being - used and has been unposted. */ +/* Recompute all the widgets of frame F, when the menu bar has been + changed. */ static void -popup_deactivate_callback (GtkWidget *widget, gpointer client_data) +update_frame_menubar (struct frame *f) { + xg_update_frame_menubar (f); } - - - /* Set the contents of the menubar widgets of frame F. The argument FIRST_TIME is currently ignored; it is set the first time this is called, from initialize_frame_menubar. */ @@ -357,15 +490,13 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p) } free_menubar_widget_value_tree (first_wv); - xg_update_frame_menubar (f); + update_frame_menubar (f); xg_crazy_callback_abort = false; unblock_input (); } - - /* Called from Fx_create_frame to create the initial menubar of a frame before it is mapped, so that the window is mapped with the menubar already there instead of us tacking it on later and thrashing the window after it @@ -381,95 +512,644 @@ initialize_frame_menubar (struct frame *f) } -void pgtk_activate_menubar (struct frame *f) +/* x_menu_show actually displays a menu using the panes and items in menu_items + and returns the value selected from it. + There are two versions of x_menu_show, one for Xt and one for Xlib. + Both assume input is blocked by the caller. */ + +/* F is the frame the menu is for. + X and Y are the frame-relative specified position, + relative to the inside upper left corner of the frame F. + Bitfield MENUFLAGS bits are: + MENU_FOR_CLICK is set if this menu was invoked for a mouse click. + MENU_KEYMAPS is set if this menu was specified with keymaps; + in that case, we return a list containing the chosen item's value + and perhaps also the pane's prefix. + TITLE is the specified menu title. + ERROR is a place to store an error message string in case of failure. + (We return nil on failure, but the value doesn't actually matter.) */ + +/* The item selected in the popup menu. */ +static Lisp_Object *volatile menu_item_selection; + +static void +popup_selection_callback (GtkWidget *widget, gpointer client_data) { - set_frame_menubar(f, false, false); + xg_menu_item_cb_data *cb_data = client_data; - /* f->output_data.pgtk->menubar_active = 1; */ + if (xg_crazy_callback_abort) return; + if (cb_data) menu_item_selection = cb_data->call_data; +} + +static void +pop_down_menu (void *arg) +{ + popup_activated_flag = 0; + block_input (); + gtk_widget_destroy (GTK_WIDGET (arg)); + unblock_input (); +} + +/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the + menu pops down. + menu_item_selection will be set to the selection. */ +static void +create_and_show_popup_menu (struct frame *f, widget_value *first_wv, + int x, int y, bool for_click) +{ + GtkWidget *menu; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + + eassert (FRAME_PGTK_P (f)); + + xg_crazy_callback_abort = true; + menu = xg_create_widget ("popup", first_wv->name, f, first_wv, + G_CALLBACK (popup_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); + xg_crazy_callback_abort = false; + + /* Display the menu. */ + gtk_widget_show_all (menu); + + if (for_click) + gtk_menu_popup_at_pointer (GTK_MENU (menu), FRAME_DISPLAY_INFO(f)->last_click_event); + else { + GdkRectangle rect; + rect.x = x; + rect.y = y; + rect.width = 1; + rect.height = 1; + gtk_menu_popup_at_rect (GTK_MENU (menu), + gtk_widget_get_window(FRAME_GTK_WIDGET(f)), + &rect, + GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST, + FRAME_DISPLAY_INFO(f)->last_click_event); + } + + record_unwind_protect_ptr (pop_down_menu, menu); + + if (gtk_widget_get_mapped (menu)) + { + /* Set this to one. popup_widget_loop increases it by one, so it becomes + two. show_help_echo uses this to detect popup menus. */ + popup_activated_flag = 1; + /* Process events that apply to the menu. */ + popup_widget_loop (true, menu); + } + + unbind_to (specpdl_count, Qnil); + + /* Must reset this manually because the button release event is not passed + to Emacs event loop. */ + FRAME_DISPLAY_INFO (f)->grabbed = 0; } +static void +cleanup_widget_value_tree (void *arg) +{ + free_menubar_widget_value_tree (arg); +} Lisp_Object pgtk_menu_show (struct frame *f, int x, int y, int menuflags, Lisp_Object title, const char **error_name) { - Lisp_Object tem; + int i; + widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0; + widget_value **submenu_stack + = alloca (menu_items_used * sizeof *submenu_stack); + Lisp_Object *subprefix_stack + = alloca (menu_items_used * sizeof *subprefix_stack); + int submenu_depth = 0; + + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + + eassert (FRAME_PGTK_P (f)); + + *error_name = NULL; + + if (menu_items_used <= MENU_ITEMS_PANE_LENGTH) + { + *error_name = "Empty menu"; + return Qnil; + } block_input (); + /* Create a tree of widget_value objects + representing the panes and their items. */ + wv = make_widget_value ("menu", NULL, true, Qnil); + wv->button_type = BUTTON_TYPE_NONE; + first_wv = wv; + bool first_pane = true; - unblock_input (); + /* Loop over all panes and items, filling in the tree. */ + i = 0; + while (i < menu_items_used) + { + if (NILP (AREF (menu_items, i))) + { + submenu_stack[submenu_depth++] = save_wv; + save_wv = prev_wv; + prev_wv = 0; + first_pane = true; + i++; + } + else if (EQ (AREF (menu_items, i), Qlambda)) + { + prev_wv = save_wv; + save_wv = submenu_stack[--submenu_depth]; + first_pane = false; + i++; + } + else if (EQ (AREF (menu_items, i), Qt) + && submenu_depth != 0) + i += MENU_ITEMS_PANE_LENGTH; + /* Ignore a nil in the item list. + It's meaningful only for dialog boxes. */ + else if (EQ (AREF (menu_items, i), Qquote)) + i += 1; + else if (EQ (AREF (menu_items, i), Qt)) + { + /* Create a new pane. */ + Lisp_Object pane_name, prefix; + const char *pane_string; + + pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME); + prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); + +#ifndef HAVE_MULTILINGUAL_MENU + if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) + { + pane_name = ENCODE_MENU_STRING (pane_name); + ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); + } +#endif + pane_string = (NILP (pane_name) + ? "" : SSDATA (pane_name)); + /* If there is just one top-level pane, put all its items directly + under the top-level menu. */ + if (menu_items_n_panes == 1) + pane_string = ""; + + /* If the pane has a meaningful name, + make the pane a top-level menu item + with its items as a submenu beneath it. */ + if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, "")) + { + wv = make_widget_value (pane_string, NULL, true, Qnil); + if (save_wv) + save_wv->next = wv; + else + first_wv->contents = wv; + if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)) + wv->name++; + wv->button_type = BUTTON_TYPE_NONE; + save_wv = wv; + prev_wv = 0; + } + else if (first_pane) + { + save_wv = wv; + prev_wv = 0; + } + first_pane = false; + i += MENU_ITEMS_PANE_LENGTH; + } + else + { + /* Create a new item within current pane. */ + Lisp_Object item_name, enable, descrip, def, type, selected, help; + item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); + enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); + descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); + def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION); + type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE); + selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED); + help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); + +#ifndef HAVE_MULTILINGUAL_MENU + if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) + { + item_name = ENCODE_MENU_STRING (item_name); + ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); + } + + if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) + { + descrip = ENCODE_MENU_STRING (descrip); + ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip); + } +#endif /* not HAVE_MULTILINGUAL_MENU */ + + wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable), + STRINGP (help) ? help : Qnil); + if (prev_wv) + prev_wv->next = wv; + else + save_wv->contents = wv; + if (!NILP (descrip)) + wv->key = SSDATA (descrip); + /* If this item has a null value, + make the call_data null so that it won't display a box + when the mouse is on it. */ + wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0; + + if (NILP (type)) + wv->button_type = BUTTON_TYPE_NONE; + else if (EQ (type, QCtoggle)) + wv->button_type = BUTTON_TYPE_TOGGLE; + else if (EQ (type, QCradio)) + wv->button_type = BUTTON_TYPE_RADIO; + else + emacs_abort (); - // not implemented. - return Qnil; -} + wv->selected = !NILP (selected); -DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", - doc: /* Start key navigation of the menu bar in FRAME. -This initially opens the first menu bar item and you can then navigate with the -arrow keys, select a menu entry with the return key or cancel with the -escape key. If FRAME has no menu bar this function does nothing. + prev_wv = wv; -If FRAME is nil or not given, use the selected frame. */) - (Lisp_Object frame) -{ - GtkWidget *menubar; - struct frame *f; + i += MENU_ITEMS_ITEM_LENGTH; + } + } - block_input (); - f = decode_window_system_frame (frame); + /* Deal with the title, if it is non-nil. */ + if (!NILP (title)) + { + widget_value *wv_title; + widget_value *wv_sep1 = make_widget_value ("--", NULL, false, Qnil); + widget_value *wv_sep2 = make_widget_value ("--", NULL, false, Qnil); + + wv_sep2->next = first_wv->contents; + wv_sep1->next = wv_sep2; + +#ifndef HAVE_MULTILINGUAL_MENU + if (STRING_MULTIBYTE (title)) + title = ENCODE_MENU_STRING (title); +#endif + + wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil); + wv_title->button_type = BUTTON_TYPE_NONE; + wv_title->next = wv_sep1; + first_wv->contents = wv_title; + } - if (FRAME_EXTERNAL_MENU_BAR (f)) - set_frame_menubar (f, false, true); + /* No selection has been chosen yet. */ + menu_item_selection = 0; - menubar = FRAME_X_OUTPUT (f)->menubar_widget; - if (menubar) + /* Make sure to free the widget_value objects we used to specify the + contents even with longjmp. */ + record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv); + + /* Actually create and show the menu until popped down. */ + create_and_show_popup_menu (f, first_wv, x, y, + menuflags & MENU_FOR_CLICK); + + unbind_to (specpdl_count, Qnil); + + /* Find the selected item, and its pane, to return + the proper value. */ + if (menu_item_selection != 0) { - /* Activate the first menu. */ - GList *children = gtk_container_get_children (GTK_CONTAINER (menubar)); + Lisp_Object prefix, entry; - if (children) - { - g_signal_emit_by_name (children->data, "activate_item"); - g_list_free (children); - } + prefix = entry = Qnil; + i = 0; + while (i < menu_items_used) + { + if (NILP (AREF (menu_items, i))) + { + subprefix_stack[submenu_depth++] = prefix; + prefix = entry; + i++; + } + else if (EQ (AREF (menu_items, i), Qlambda)) + { + prefix = subprefix_stack[--submenu_depth]; + i++; + } + else if (EQ (AREF (menu_items, i), Qt)) + { + prefix + = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); + i += MENU_ITEMS_PANE_LENGTH; + } + /* Ignore a nil in the item list. + It's meaningful only for dialog boxes. */ + else if (EQ (AREF (menu_items, i), Qquote)) + i += 1; + else + { + entry + = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + if (menu_item_selection == aref_addr (menu_items, i)) + { + if (menuflags & MENU_KEYMAPS) + { + int j; + + entry = list1 (entry); + if (!NILP (prefix)) + entry = Fcons (prefix, entry); + for (j = submenu_depth - 1; j >= 0; j--) + if (!NILP (subprefix_stack[j])) + entry = Fcons (subprefix_stack[j], entry); + } + unblock_input (); + return entry; + } + i += MENU_ITEMS_ITEM_LENGTH; + } + } + } + else if (!(menuflags & MENU_FOR_CLICK)) + { + unblock_input (); + /* Make "Cancel" equivalent to C-g. */ + quit (); } - unblock_input (); + unblock_input (); return Qnil; } +static void +dialog_selection_callback (GtkWidget *widget, gpointer client_data) +{ + /* Treat the pointer as an integer. There's no problem + as long as pointers have enough bits to hold small integers. */ + if ((intptr_t) client_data != -1) + menu_item_selection = client_data; + + popup_activated_flag = 0; +} + +/* Pop up the dialog for frame F defined by FIRST_WV and loop until the + dialog pops down. + menu_item_selection will be set to the selection. */ +static void +create_and_show_dialog (struct frame *f, widget_value *first_wv) +{ + GtkWidget *menu; + + eassert (FRAME_PGTK_P (f)); + + menu = xg_create_widget ("dialog", first_wv->name, f, first_wv, + G_CALLBACK (dialog_selection_callback), + G_CALLBACK (popup_deactivate_callback), + 0); + + if (menu) + { + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + record_unwind_protect_ptr (pop_down_menu, menu); + + /* Display the menu. */ + gtk_widget_show_all (menu); + + /* Process events that apply to the menu. */ + popup_widget_loop (true, menu); + + unbind_to (specpdl_count, Qnil); + } +} static const char * button_names [] = { "button1", "button2", "button3", "button4", "button5", "button6", "button7", "button8", "button9", "button10" }; -extern Lisp_Object +Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, - Lisp_Object header, char **error) + Lisp_Object header, const char **error_name) { + int i, nb_buttons=0; + char dialog_name[6]; + + widget_value *wv, *first_wv = 0, *prev_wv = 0; + + /* Number of elements seen so far, before boundary. */ + int left_count = 0; + /* Whether we've seen the boundary between left-hand elts and right-hand. */ + bool boundary_seen = false; + + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + + eassert (FRAME_PGTK_P (f)); + + *error_name = NULL; + + if (menu_items_n_panes > 1) + { + *error_name = "Multiple panes in dialog box"; + return Qnil; + } + + /* Create a tree of widget_value objects + representing the text label and buttons. */ + { + Lisp_Object pane_name; + const char *pane_string; + pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME); + pane_string = (NILP (pane_name) + ? "" : SSDATA (pane_name)); + prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil); + first_wv = prev_wv; + + /* Loop over all panes and items, filling in the tree. */ + i = MENU_ITEMS_PANE_LENGTH; + while (i < menu_items_used) + { + + /* Create a new item within current pane. */ + Lisp_Object item_name, enable, descrip; + item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME); + enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE); + descrip + = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY); + + if (NILP (item_name)) + { + free_menubar_widget_value_tree (first_wv); + *error_name = "Submenu in dialog items"; + return Qnil; + } + if (EQ (item_name, Qquote)) + { + /* This is the boundary between left-side elts + and right-side elts. Stop incrementing right_count. */ + boundary_seen = true; + i++; + continue; + } + if (nb_buttons >= 9) + { + free_menubar_widget_value_tree (first_wv); + *error_name = "Too many dialog items"; + return Qnil; + } + + wv = make_widget_value (button_names[nb_buttons], + SSDATA (item_name), + !NILP (enable), Qnil); + prev_wv->next = wv; + if (!NILP (descrip)) + wv->key = SSDATA (descrip); + wv->call_data = aref_addr (menu_items, i); + prev_wv = wv; + + if (! boundary_seen) + left_count++; + + nb_buttons++; + i += MENU_ITEMS_ITEM_LENGTH; + } + + /* If the boundary was not specified, + by default put half on the left and half on the right. */ + if (! boundary_seen) + left_count = nb_buttons - nb_buttons / 2; + + wv = make_widget_value (dialog_name, NULL, false, Qnil); + + /* Frame title: 'Q' = Question, 'I' = Information. + Can also have 'E' = Error if, one day, we want + a popup for errors. */ + if (NILP (header)) + dialog_name[0] = 'Q'; + else + dialog_name[0] = 'I'; + + /* Dialog boxes use a really stupid name encoding + which specifies how many buttons to use + and how many buttons are on the right. */ + dialog_name[1] = '0' + nb_buttons; + dialog_name[2] = 'B'; + dialog_name[3] = 'R'; + /* Number of buttons to put on the right. */ + dialog_name[4] = '0' + nb_buttons - left_count; + dialog_name[5] = 0; + wv->contents = first_wv; + first_wv = wv; + } + + /* No selection has been chosen yet. */ + menu_item_selection = 0; + + /* Make sure to free the widget_value objects we used to specify the + contents even with longjmp. */ + record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv); + + /* Actually create and show the dialog. */ + create_and_show_dialog (f, first_wv); + + unbind_to (specpdl_count, Qnil); + + /* Find the selected item, and its pane, to return + the proper value. */ + if (menu_item_selection != 0) + { + i = 0; + while (i < menu_items_used) + { + Lisp_Object entry; + + if (EQ (AREF (menu_items, i), Qt)) + i += MENU_ITEMS_PANE_LENGTH; + else if (EQ (AREF (menu_items, i), Qquote)) + { + /* This is the boundary between left-side elts and + right-side elts. */ + ++i; + } + else + { + entry + = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE); + if (menu_item_selection == aref_addr (menu_items, i)) + return entry; + i += MENU_ITEMS_ITEM_LENGTH; + } + } + } + else + /* Make "Cancel" equivalent to C-g. */ + quit (); + return Qnil; } +Lisp_Object +pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) +{ + Lisp_Object title; + const char *error_name; + Lisp_Object selection; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + + check_window_system (f); + + /* Decode the dialog items from what was specified. */ + title = Fcar (contents); + CHECK_STRING (title); + record_unwind_protect_void (unuse_menu_items); + + if (NILP (Fcar (Fcdr (contents)))) + /* No buttons specified, add an "Ok" button so users can pop down + the dialog. Also, the lesstif/motif version crashes if there are + no buttons. */ + contents = list2 (title, Fcons (build_string ("Ok"), Qt)); + + list_of_panes (list1 (contents)); + + /* Display them in a dialog box. */ + block_input (); + selection = pgtk_dialog_show (f, title, header, &error_name); + unblock_input (); + + unbind_to (specpdl_count, Qnil); + discard_menu_items (); + + if (error_name) error ("%s", error_name); + return selection; +} + +/* Detect if a dialog or menu has been posted. MSDOS has its own + implementation on msdos.c. */ + +int +popup_activated (void) +{ + return popup_activated_flag; +} + /* The following is used by delayed window autoselection. */ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0, - doc: /* SKIP: real doc in xmenu.c. */) + doc: /* Return t if a menu or popup dialog is active. +\(On MS Windows, this refers to the selected frame.) */) (void) { - /* struct frame *f = SELECTED_FRAME (); */ - /* return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil; */ - return Qnil; + return (popup_activated ()) ? Qt : Qnil; } +static void syms_of_pgtkmenu_for_pdumper (void); + void syms_of_pgtkmenu (void) { - // current_popup_menu = NULL; - // PDUMPER_IGNORE (current_popup_menu); - DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); - DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog"); - defsubr (&Smenu_or_popup_active_p); + + DEFSYM (Qframe_monitor_workarea, "frame-monitor-workarea"); + + defsubr (&Sx_menu_bar_open_internal); + Ffset (intern_c_string ("accelerate-menu"), + intern_c_string (Sx_menu_bar_open_internal.s.symbol_name)); + + pdumper_do_now_and_after_load (syms_of_pgtkmenu_for_pdumper); +} + +static void +syms_of_pgtkmenu_for_pdumper (void) +{ } diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 0ab86b7a42..e5f89cf742 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1138,7 +1138,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) if (!s->background_filled_p) { PGTK_TRACE("x_draw_glyph_string_background: 1."); - int box_line_width = max (s->face->box_line_width, 0); + int box_line_width = max (s->face->box_horizontal_line_width, 0); PGTK_TRACE("x_draw_glyph_string_background: 2. %d, %d.", FONT_HEIGHT (s->font), s->height - 2 * box_line_width); @@ -1201,7 +1201,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s) of S to the right of that box line. */ if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) - x = s->x + eabs (s->face->box_line_width); + x = s->x + max (s->face->box_vertical_line_width, 0); else x = s->x; @@ -1250,7 +1250,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s) of S to the right of that box line. */ if (s->face && s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) - x = s->x + eabs (s->face->box_line_width); + x = s->x + max (s->face->box_vertical_line_width, 0); else x = s->x; @@ -1342,7 +1342,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) of S to the right of that box line. */ if (s->face && s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p) - x = s->x + eabs (s->face->box_line_width); + x = s->x + max (s->face->box_vertical_line_width, 0); else x = s->x; @@ -1637,7 +1637,7 @@ x_set_clip_rectangles (struct frame *f, cairo_t *cr, XRectangle *rectangles, int static void x_draw_relief_rect (struct frame *f, int left_x, int top_y, int right_x, int bottom_y, - int width, bool raised_p, bool top_p, bool bot_p, + int hwidth, int vwidth, bool raised_p, bool top_p, bool bot_p, bool left_p, bool right_p, XRectangle *clip_rect) { @@ -1662,7 +1662,7 @@ x_draw_relief_rect (struct frame *f, if (left_p) { pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - width, bottom_y + 1 - top_y); + vwidth, bottom_y + 1 - top_y); if (top_p) corners |= 1 << CORNER_TOP_LEFT; if (bot_p) @@ -1670,8 +1670,8 @@ x_draw_relief_rect (struct frame *f, } if (right_p) { - pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - width, top_y, - width, bottom_y + 1 - top_y); + pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - vwidth, top_y, + vwidth, bottom_y + 1 - top_y); if (top_p) corners |= 1 << CORNER_TOP_RIGHT; if (bot_p) @@ -1681,25 +1681,25 @@ x_draw_relief_rect (struct frame *f, { if (!right_p) pgtk_fill_rectangle (f, top_left_color, left_x, top_y, - right_x + 1 - left_x, width); + right_x + 1 - left_x, hwidth); else x_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y, - right_x + 1 - left_x, width, 1); + right_x + 1 - left_x, hwidth, 1); } if (bot_p) { if (!left_p) - pgtk_fill_rectangle (f, bottom_right_color, left_x, bottom_y + 1 - width, - right_x + 1 - left_x, width); + pgtk_fill_rectangle (f, bottom_right_color, left_x, bottom_y + 1 - hwidth, + right_x + 1 - left_x, hwidth); else x_fill_trapezoid_for_relief (f, bottom_right_color, - left_x, bottom_y + 1 - width, - right_x + 1 - left_x, width, 0); + left_x, bottom_y + 1 - hwidth, + right_x + 1 - left_x, hwidth, 0); } - if (left_p && width != 1) + if (left_p && vwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, 1, bottom_y + 1 - top_y); - if (top_p && width != 1) + if (top_p && hwidth > 1) pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, right_x + 1 - left_x, 1); if (corners) @@ -1721,8 +1721,8 @@ x_draw_relief_rect (struct frame *f, static void x_draw_box_rect (struct glyph_string *s, - int left_x, int top_y, int right_x, int bottom_y, int width, - bool left_p, bool right_p, XRectangle *clip_rect) + int left_x, int top_y, int right_x, int bottom_y, int hwidth, + int vwidth, bool left_p, bool right_p, XRectangle *clip_rect) { unsigned long foreground_backup; @@ -1735,21 +1735,21 @@ x_draw_box_rect (struct glyph_string *s, /* Top. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, right_x - left_x + 1, width); + left_x, top_y, right_x - left_x + 1, hwidth); /* Left. */ if (left_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, top_y, width, bottom_y - top_y + 1); + left_x, top_y, vwidth, bottom_y - top_y + 1); /* Bottom. */ pgtk_fill_rectangle (s->f, s->xgcv.foreground, - left_x, bottom_y - width + 1, right_x - left_x + 1, width); + left_x, bottom_y - hwidth + 1, right_x - left_x + 1, hwidth); /* Right. */ if (right_p) pgtk_fill_rectangle (s->f, s->xgcv.foreground, - right_x - width + 1, top_y, width, bottom_y - top_y + 1); + right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1); s->xgcv.foreground = foreground_backup; @@ -1762,7 +1762,7 @@ x_draw_box_rect (struct glyph_string *s, static void x_draw_glyph_string_box (struct glyph_string *s) { - int width, left_x, right_x, top_y, bottom_y, last_x; + int hwidth, vwidth, left_x, right_x, top_y, bottom_y, last_x; bool raised_p, left_p, right_p; struct glyph *last_glyph; XRectangle clip_rect; @@ -1776,7 +1776,8 @@ x_draw_glyph_string_box (struct glyph_string *s) ? s->first_glyph : s->first_glyph + s->nchars - 1); - width = eabs (s->face->box_line_width); + vwidth = eabs (s->face->box_vertical_line_width); + hwidth = eabs (s->face->box_horizontal_line_width); raised_p = s->face->box == FACE_RAISED_BOX; left_x = s->x; right_x = (s->row->full_width_p && s->extends_to_end_of_line_p @@ -1797,13 +1798,13 @@ x_draw_glyph_string_box (struct glyph_string *s) get_glyph_string_clip_rect (s, &clip_rect); if (s->face->box == FACE_SIMPLE_BOX) - x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, - left_p, right_p, &clip_rect); + x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, hwidth, + vwidth, left_p, right_p, &clip_rect); else { x_setup_relief_colors (s); - x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, - width, raised_p, true, true, left_p, right_p, + x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, hwidth, + vwidth, raised_p, true, true, left_p, right_p, &clip_rect); } } @@ -1896,7 +1897,7 @@ x_draw_image_relief (struct glyph_string *s) if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p && s->slice.x == 0) - x += eabs (s->face->box_line_width); + x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position by that margin. */ @@ -1964,7 +1965,7 @@ x_draw_image_relief (struct glyph_string *s) x_setup_relief_colors (s); get_glyph_string_clip_rect (s, &r); - x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p, + x_draw_relief_rect (s->f, x, y, x1, y1, thick, thick, raised_p, top_p, bot_p, left_p, right_p, &r); } @@ -1997,7 +1998,7 @@ x_draw_image_foreground (struct glyph_string *s) if (s->face->box != FACE_NO_BOX && s->first_glyph->left_box_line_p && s->slice.x == 0) - x += eabs (s->face->box_line_width); + x += max (s->face->box_vertical_line_width, 0); /* If there is a margin around the image, adjust x- and y-position by that margin. */ @@ -2028,8 +2029,8 @@ x_draw_image_foreground (struct glyph_string *s) static void x_draw_image_glyph_string (struct glyph_string *s) { - int box_line_hwidth = eabs (s->face->box_line_width); - int box_line_vwidth = max (s->face->box_line_width, 0); + int box_line_hwidth = max (s->face->box_vertical_line_width, 0); + int box_line_vwidth = max (s->face->box_horizontal_line_width, 0); int height; height = s->height; @@ -5902,6 +5903,10 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) { dpyinfo->grabbed |= (1 << event->button.button); dpyinfo->last_mouse_frame = f; + + if (dpyinfo->last_click_event != NULL) + gdk_event_free(dpyinfo->last_click_event); + dpyinfo->last_click_event = gdk_event_copy(event); } else dpyinfo->grabbed &= ~(1 << event->button.button); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index bb9dca65fe..73e04b7da6 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -222,7 +222,8 @@ struct pgtk_display_info /* Modifier masks in gdk */ int meta_mod_mask, alt_mod_mask; - /* whether to use Gtk's IM context. */ + /* The last click event. */ + GdkEvent *last_click_event; /* input method */ struct { @@ -572,7 +573,7 @@ extern void pgtk_cr_destroy_frame_context(struct frame *f); /* Defined in pgtkmenu.c */ extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents); -extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object header, char **error); +extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object header, const char **error_name); extern void initialize_frame_menubar (struct frame *); commit 49645df52e949da1c34a69f49aabbff300986893 Author: Yuuki Harano Date: Tue Mar 31 01:32:10 2020 +0900 minimize gtkutil.c differences. * src/pgtkterm.h: remove compiletime ifdefs * src/gtkutil.h: block out unused decl * src/gtkutil.c: (xg_get_pixbuf_from_pix_and_mask, xg_height_or_width_changed) (xg_create_frame_widgets, x_wm_set_size_hint) (xg_event_is_for_menubar, update_frame_tool_bar): resolve argument type mismatch. fix compatibility. diff --git a/src/gtkutil.c b/src/gtkutil.c index 2a45f057fd..6d6e4b4685 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -26,7 +26,7 @@ along with GNU Emacs. If not, see . */ #include -#if defined(USE_GTK) +#ifdef USE_GTK #include #include #include @@ -53,7 +53,6 @@ typedef struct pgtk_output xp_output; #include "coding.h" #ifndef PGTK_TRACE #define PGTK_TRACE(fmt, ...) ((void) 0) -#define PGTK_BACKTRACE() ((void) 0) #endif #include @@ -319,18 +318,16 @@ xg_create_default_cursor (GdkDisplay *gdpy) static GdkPixbuf * xg_get_pixbuf_from_pix_and_mask (struct frame *f, - Emacs_Pixmap pix, - Emacs_Pixmap mask) + Pixmap pix, + Pixmap mask) { GdkPixbuf *icon_buf = 0; int iunused; Window wunused; unsigned int width, height, depth, uunused; -#ifndef HAVE_PGTK if (FRAME_DISPLAY_INFO (f)->red_bits != 8) return 0; - XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, &width, &height, &uunused, &depth); if (depth != 24) @@ -362,21 +359,10 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, XDestroyImage (xmm); XDestroyImage (xim); } -#else - width = pix->width; - height = pix->height; - depth = pix->bits_per_pixel; - - icon_buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); - - -#endif return icon_buf; } - - #if defined USE_CAIRO && !defined HAVE_GTK3 static GdkPixbuf * xg_get_pixbuf_from_surface (cairo_surface_t *surface) @@ -907,7 +893,6 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y) bool xg_hide_tooltip (struct frame *f) { - bool ret = 0; if (f->output_data.xp->ttip_window) { GtkWindow *win = f->output_data.xp->ttip_window; @@ -1185,12 +1170,13 @@ xg_frame_set_char_size (struct frame *f, int width, int height) } else adjust_frame_size (f, width, height, 5, 0, Qxg_frame_set_char_size); + } -#ifndef HAVE_PGTK /* Handle height/width changes (i.e. add/remove/move menu/toolbar). The policy is to keep the number of editable lines. */ +#if 0 static void xg_height_or_width_changed (struct frame *f) { @@ -1368,7 +1354,7 @@ xg_create_frame_widgets (struct frame *f) else wtop = gtk_window_new (type); #else - if (!NILP(f->parent_frame)){ + if (!NILP(f->parent_frame)) { type = GTK_WINDOW_POPUP; } wtop = gtk_window_new (type); @@ -1493,17 +1479,11 @@ xg_create_frame_widgets (struct frame *f) #endif | GDK_VISIBILITY_NOTIFY_MASK); +#ifndef HAVE_PGTK /* Must realize the windows so the X window gets created. It is used by callers of this function. */ -#ifndef HAVE_PGTK gtk_widget_realize (wfixed); -#else - // gtk_widget_show_all(wtop); -#endif -#ifndef HAVE_PGTK FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); -#endif -#ifndef HAVE_PGTK initial_set_up_x_back_buffer (f); #endif @@ -1522,7 +1502,9 @@ xg_create_frame_widgets (struct frame *f) gtk_widget_modify_style (wfixed, style); #else gtk_widget_set_can_focus (wfixed, TRUE); +#ifdef HAVE_PGTK gtk_widget_grab_focus(wfixed); +#endif gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); #endif @@ -1717,7 +1699,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) { block_input (); gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - NULL, &size_hints, hint_flags); + NULL, &size_hints, hint_flags); f->output_data.xp->size_hints = size_hints; f->output_data.xp->hint_flags = hint_flags; unblock_input (); @@ -3763,9 +3745,9 @@ free_frame_menubar (struct frame *f) #ifndef HAVE_PGTK bool -xg_event_is_for_menubar (struct frame *f, const EVENT *event) +xg_event_is_for_menubar (struct frame *f, const XEvent *event) { - xp_output *x = f->output_data.xp; + struct x_output *x = f->output_data.x; GList *iter; GdkRectangle rec; GList *list; @@ -4768,7 +4750,6 @@ xg_tool_bar_help_callback (GtkWidget *w, } -#ifndef HAVE_GTK3 /* This callback is called when a tool bar item shall be redrawn. It modifies the expose event so that the GtkImage widget redraws the whole image. This to overcome a bug that makes GtkImage draw the image @@ -4779,6 +4760,7 @@ xg_tool_bar_help_callback (GtkWidget *w, Returns FALSE to tell GTK to keep processing this event. */ +#ifndef HAVE_GTK3 static gboolean xg_tool_bar_item_expose_callback (GtkWidget *w, GdkEventExpose *event, @@ -5189,11 +5171,7 @@ void update_frame_tool_bar (struct frame *f) { int i, j; -#ifndef HAVE_PGTK - struct x_output *x = f->output_data.xp; -#else - struct pgtk_output *x = f->output_data.pgtk; -#endif + xp_output *x = f->output_data.xp; int hmargin = 0, vmargin = 0; GtkToolbar *wtoolbar; GtkToolItem *ti; diff --git a/src/gtkutil.h b/src/gtkutil.h index 5087b3167d..b7f67ba928 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -180,9 +180,11 @@ extern bool xg_check_special_colors (struct frame *f, const char *color_name, Emacs_Color *color); +#ifndef HAVE_PGTK extern void xg_set_frame_icon (struct frame *f, Pixmap icon_pixmap, Pixmap icon_mask); +#endif extern void xg_set_undecorated (struct frame *f, Lisp_Object undecorated); extern void xg_frame_restack (struct frame *f1, struct frame *f2, bool above); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 9d6b0a1f80..bb9dca65fe 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -41,11 +41,6 @@ extern void pgtk_backtrace(const char *file, int lineno); #define PGTK_BACKTRACE() ((void) 0) #endif -/* The GtkTooltip API came in 2.12, but gtk-enable-tooltips in 2.14. */ -#if GTK_CHECK_VERSION (2, 14, 0) -#define USE_GTK_TOOLTIP -#endif - /* could use list to store these, but rest of emacs has a big infrastructure for managing a table of bitmap "records" */ struct pgtk_bitmap_record @@ -343,11 +338,9 @@ struct pgtk_output bool_bf toolbar_in_hbox : 1; bool_bf toolbar_is_packed : 1; -#ifdef USE_GTK_TOOLTIP GtkTooltip *ttip_widget; GtkWidget *ttip_lbl; GtkWindow *ttip_window; -#endif /* USE_GTK_TOOLTIP */ /* Height of menu bar widget, in pixels. This value is not meaningful if the menubar is turned off. */ commit cbd28cddea180ab3be14532e7a341c89ebc02fcc Author: Yuuki Harano Date: Tue Mar 31 01:31:07 2020 +0900 improve code readability. * src/gtkutil.c (xg_create_frame_widgets): diff --git a/src/gtkutil.c b/src/gtkutil.c index 4bd803c74b..2a45f057fd 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1366,17 +1366,13 @@ xg_create_frame_widgets (struct frame *f) wtop = gtk_plug_new_for_display (gdpy, f->output_data.xp->parent_desc); } else -#endif - -#ifdef HAVE_PGTK - if (!NILP(f->parent_frame)){ - type = GTK_WINDOW_POPUP; - } -#endif - + wtop = gtk_window_new (type); +#else + if (!NILP(f->parent_frame)){ + type = GTK_WINDOW_POPUP; + } wtop = gtk_window_new (type); -#ifdef HAVE_PGTK - gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); #endif /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu commit ef67659e985dcc31a48cfb3c5eefcf4d9f6aee6e Author: Jeff Walsh Date: Tue Feb 18 17:13:26 2020 +1100 Set screen/display dpi res to make broadway work as expected * src/pgtkterm.c (pgtk_initialize_display_info) (window_state_event, pgtk_term_init): * src/gtkutil.c (xg_create_frame_widgets): * src/pgtkterm.c (pgtk_initialize_display_info) (window_state_event, pgtk_term_init): * src/ftcrfont.c (ftcrfont_open): diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 8fffb33ee2..5bae8dae17 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -136,7 +136,9 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size) filename = XCAR (val); size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) + { size = pixel_size; + } block_input (); diff --git a/src/gtkutil.c b/src/gtkutil.c index 6573205e7b..4bd803c74b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1377,7 +1377,6 @@ xg_create_frame_widgets (struct frame *f) wtop = gtk_window_new (type); #ifdef HAVE_PGTK gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); - gtk_window_set_hide_titlebar_when_maximized(GTK_WINDOW(wtop), TRUE); #endif /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu diff --git a/src/pgtkfns.c b/src/pgtkfns.c index e7ab20897b..69a7430b8d 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -3160,7 +3160,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */); } - +#ifdef PGTK_DEBUG #include #include void pgtk_log(const char *file, int lineno, const char *fmt, ...) @@ -3181,7 +3181,7 @@ void pgtk_log(const char *file, int lineno, const char *fmt, ...) va_end(ap); fputc('\n', stderr); } -#ifdef PGTK_DEBUG + void pgtk_backtrace(const char *file, int lineno) { Lisp_Object bt = make_uninit_vector(10); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d7ac68c32f..0ab86b7a42 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -828,8 +828,8 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) Initialize global info and storage for display. -------------------------------------------------------------------------- */ { - dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */ - dpyinfo->resy = 72.27; + dpyinfo->resx = 96; + dpyinfo->resy = 96; dpyinfo->color_p = 1; dpyinfo->n_planes = 32; dpyinfo->root_window = 42; /* a placeholder.. */ @@ -5401,7 +5401,7 @@ static gboolean window_state_event(GtkWidget *widget, GdkEvent *event, gpointer if (inev.ie.kind != NO_EVENT) evq_enqueue(&inev); - return TRUE; + return FALSE; } static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) @@ -6297,7 +6297,13 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) { GdkScreen *gscr = gdk_display_get_default_screen(dpyinfo->gdpy); - gdouble dpi = gdk_screen_get_resolution(gscr); + + GSettings *set = g_settings_new("org.gnome.desktop.interface"); + gdouble x = g_settings_get_double(set,"text-scaling-factor"); + gdouble dpi = 0; + + dpi = 96.0 * x; + gdk_screen_set_resolution(gscr, dpi); dpyinfo->resx = dpi; dpyinfo->resy = dpi; } commit c9e6b4486b6aee1e1011c81fdf0ef8270e237a15 Author: Jeff Walsh Date: Thu Jan 9 16:36:11 2020 +1100 Some work toward posframe on wayland * src/pgtkterm.c (flip_cr_context, x_set_offset): update for new functionality (pgtk_set_window_size): remove dead code (x_set_parent_frame): cleanup trace code (pgtk_cr_update_surface_desired_size): add comment * src/pgtkmenu.c (Fmenu_or_popup_active_p): * src/pgtkfns.c (pgtk_frame_parm_handlers, Fx_create_frame): * src/gtkutil.c (xg_create_frame_widgets, x_wm_set_size_hint): * src/gtkutil.c (xg_create_frame_widgets): hacky GTK offsets taht will need better calculations Get parent frame's editor widget allocation for the offset Fix child-frame offsets for negative values Add some function comments around the new double context handling diff --git a/src/gtkutil.c b/src/gtkutil.c index 8cdbe3e4ad..6573205e7b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1353,6 +1353,7 @@ xg_create_frame_widgets (struct frame *f) #ifndef HAVE_GTK3 GtkRcStyle *style; #endif + GtkWindowType type = GTK_WINDOW_TOPLEVEL; char *title = 0; PGTK_TRACE("xg_create_frame_widgets."); @@ -1366,9 +1367,17 @@ xg_create_frame_widgets (struct frame *f) } else #endif - wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); + #ifdef HAVE_PGTK - gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + if (!NILP(f->parent_frame)){ + type = GTK_WINDOW_POPUP; + } +#endif + + wtop = gtk_window_new (type); +#ifdef HAVE_PGTK + gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); + gtk_window_set_hide_titlebar_when_maximized(GTK_WINDOW(wtop), TRUE); #endif /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu @@ -1494,7 +1503,7 @@ xg_create_frame_widgets (struct frame *f) #ifndef HAVE_PGTK gtk_widget_realize (wfixed); #else - gtk_widget_show_all(wtop); + // gtk_widget_show_all(wtop); #endif #ifndef HAVE_PGTK FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); @@ -1712,10 +1721,8 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) sizeof (size_hints)) != 0) { block_input (); -#ifndef HAVE_PGTK gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), - NULL, &size_hints, hint_flags); -#endif + NULL, &size_hints, hint_flags); f->output_data.xp->size_hints = size_hints; f->output_data.xp->hint_flags = hint_flags; unblock_input (); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 2c8f73ebcb..e7ab20897b 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -915,7 +915,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = pgtk_set_tool_bar_position, 0, /* x_set_inhibit_double_buffering */ x_set_undecorated, - 0, /* x_set_parent_frame, */ + x_set_parent_frame, x_set_skip_taskbar, x_set_no_focus_on_map, x_set_no_accept_focus, @@ -1454,17 +1454,23 @@ This function is an internal primitive--use `make-frame' instead. */) gui_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); -#if 0 if (!NILP (parent_frame)) { struct frame *p = XFRAME (parent_frame); block_input (); - XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - FRAME_X_WINDOW (p), f->left_pos, f->top_pos); + PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); + gtk_window_set_transient_for(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), + GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(p))); + gtk_window_set_attached_to(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), + FRAME_GTK_WIDGET(p)); + gtk_window_set_destroy_with_parent(GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)), + TRUE); + gtk_widget_show_all(FRAME_GTK_OUTER_WIDGET(f)); unblock_input (); } -#endif + + gtk_widget_show_all(FRAME_GTK_OUTER_WIDGET(f)); gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); @@ -3153,7 +3159,7 @@ When using Gtk+ tooltips, the tooltip face is not used. */); DEFSYM (Qreverse_landscape, "reverse-landscape"); } -#ifdef PGTK_DEBUG + #include #include @@ -3175,7 +3181,7 @@ void pgtk_log(const char *file, int lineno, const char *fmt, ...) va_end(ap); fputc('\n', stderr); } - +#ifdef PGTK_DEBUG void pgtk_backtrace(const char *file, int lineno) { Lisp_Object bt = make_uninit_vector(10); diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c index bbe47ddad6..9148504f8e 100644 --- a/src/pgtkmenu.c +++ b/src/pgtkmenu.c @@ -457,9 +457,8 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_ doc: /* SKIP: real doc in xmenu.c. */) (void) { - struct frame *f; - f = SELECTED_FRAME (); - // return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil; + /* struct frame *f = SELECTED_FRAME (); */ + /* return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil; */ return Qnil; } diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 86ebf864a7..d7ac68c32f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -38,6 +38,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "blockinput.h" +#include "frame.h" #include "sysselect.h" #include "gtkutil.h" #include "systime.h" @@ -97,6 +98,13 @@ static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, static struct frame * pgtk_any_window_to_frame (GdkWindow *window); +/* + * This is not a flip context in the same sense as gpu rendering + * scences, it only occurs when a new context was required due to a + * resize or other fundamental change. This is called when that + * context's surface has completed drawing + */ + static void flip_cr_context(struct frame *f) { PGTK_TRACE("flip_cr_context"); @@ -356,23 +364,36 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) External: Position the window -------------------------------------------------------------------------- */ { - /* not working on wayland. */ - PGTK_TRACE("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); - if (change_gravity > 0) - { - PGTK_TRACE("x_set_offset: change_gravity > 0"); - f->top_pos = yoff; + struct frame *parent = FRAME_PARENT_FRAME(f); + GtkAllocation a = {0}; + if (change_gravity > 0) { + if (parent) { + /* determing the "height" of the titlebar, by finding the + location of the "emacsfixed" widget on the surface/window */ + GtkWidget *w = FRAME_GTK_WIDGET(parent); + gtk_widget_get_allocation(w, &a); + } + + f->size_hint_flags &= ~ (XNegative | YNegative); + /* if the value is negative, don't include the titlebar offset */ + if (xoff < 0) { + f->size_hint_flags |= XNegative; f->left_pos = xoff; - f->size_hint_flags &= ~ (XNegative | YNegative); - if (xoff < 0) - f->size_hint_flags |= XNegative; - if (yoff < 0) - f->size_hint_flags |= YNegative; - f->win_gravity = NorthWestGravity; + } else { + f->left_pos = xoff + a.x; //~25 } + if (yoff < 0){ + f->size_hint_flags |= YNegative; + f->top_pos = yoff; + } else { + f->top_pos = yoff + a.y; //~60 + } + f->win_gravity = NorthWestGravity; + } + x_calc_absolute_position (f); block_input (); @@ -431,8 +452,6 @@ pgtk_set_window_size (struct frame *f, for (GtkWidget *w = FRAME_GTK_WIDGET(f); w != NULL; w = gtk_widget_get_parent(w)) { gint wd, hi; gtk_widget_get_size_request(w, &wd, &hi); - GtkAllocation alloc; - gtk_widget_get_allocation(w, &alloc); } f->output_data.pgtk->preferred_width = pixelwidth; @@ -673,6 +692,56 @@ x_display_pixel_width (struct pgtk_display_info *dpyinfo) return gdk_screen_get_width(gscr); } +void +x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* -------------------------------------------------------------------------- + Set frame F's `parent-frame' parameter. If non-nil, make F a child + frame of the frame specified by that parameter. Technically, this + makes F's window-system window a child window of the parent frame's + window-system window. If nil, make F's window-system window a + top-level window--a child of its display's root window. + + A child frame's `left' and `top' parameters specify positions + relative to the top-left corner of its parent frame's native + rectangle. On macOS moving a parent frame moves all its child + frames too, keeping their position relative to the parent + unaltered. When a parent frame is iconified or made invisible, its + child frames are made invisible. When a parent frame is deleted, + its child frames are deleted too. + + Whether a child frame has a tool bar may be window-system or window + manager dependent. It's advisable to disable it via the frame + parameter settings. + + Some window managers may not honor this parameter. + -------------------------------------------------------------------------- */ +{ + struct frame *p = NULL; + PGTK_TRACE ("x_set_parent_frame x: %d, y: %d", f->left_pos, f->top_pos); + + if (!NILP (new_value) + && (!FRAMEP (new_value) + || !FRAME_LIVE_P (p = XFRAME (new_value)) + || !FRAME_PGTK_P (p))) + { + store_frame_param (f, Qparent_frame, old_value); + error ("Invalid specification of `parent-frame'"); + } + + if (p != FRAME_PARENT_FRAME (f) + && (p != NULL)) + { + block_input (); + gtk_window_set_transient_for(FRAME_NATIVE_WINDOW(f), FRAME_NATIVE_WINDOW(p)); + gtk_window_set_attached_to(FRAME_NATIVE_WINDOW(f), FRAME_GTK_WIDGET(p)); + gtk_window_move(FRAME_NATIVE_WINDOW(f), f->left_pos, f->top_pos); + gtk_window_set_keep_above(FRAME_NATIVE_WINDOW(f), true); + unblock_input (); + + fset_parent_frame (f, new_value); + } +} + void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) @@ -2627,7 +2696,6 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, { PGTK_TRACE("draw_window_cursor: %d, %d, %d, %d, %d, %d.", x, y, cursor_type, cursor_width, on_p, active_p); - if (on_p) { w->phys_cursor_type = cursor_type; @@ -2676,6 +2744,7 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, xic_set_preeditarea (w, x, y); #endif } + } static void @@ -6538,10 +6607,16 @@ If set to a non-float value, there will be no wait at all. */); /* Tell Emacs about this window system. */ Fprovide (Qpgtk, Qnil); - } - +/* Cairo does not allow resizing a surface/context after it is + * created, so we need to trash the old context, create a new context + * on the next cr_clip_begin with the new dimensions and request a + * re-draw. + * + * This Will leave the active context available to present on screen + * until a redrawn frame is completed. + */ void pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) { commit e021e233b4e96740dbc78bbc2717de6ee6e68291 Author: Jeff Walsh Date: Mon Jan 13 16:17:50 2020 +1100 End Resize flickering by copying surface rather than just clearing * src/pgtkterm.h (FRAME_NATIVE_WINDOW): * src/pgtkterm.c (pgtk_set_window_size): cleanup traces (x_draw_bar_cursor, pgtk_handle_draw, syms_of_pgtkterm): diff --git a/src/pgtkterm.c b/src/pgtkterm.c index e214cc26c8..86ebf864a7 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -408,7 +408,6 @@ pgtk_set_window_size (struct frame *f, block_input (); gtk_widget_get_size_request(FRAME_GTK_WIDGET(f), &pixelwidth, &pixelheight); - PGTK_TRACE("old: %dx%d", pixelwidth, pixelheight); if (pixelwise) { @@ -429,18 +428,13 @@ pgtk_set_window_size (struct frame *f, make_fixnum (FRAME_PGTK_TITLEBAR_HEIGHT (f)), make_fixnum (FRAME_TOOLBAR_HEIGHT (f)))); - PGTK_TRACE("new: %dx%d", pixelwidth, pixelheight); for (GtkWidget *w = FRAME_GTK_WIDGET(f); w != NULL; w = gtk_widget_get_parent(w)) { - PGTK_TRACE("%p %s %d %d", w, G_OBJECT_TYPE_NAME(w), gtk_widget_get_mapped(w), gtk_widget_get_visible(w)); gint wd, hi; gtk_widget_get_size_request(w, &wd, &hi); - PGTK_TRACE(" %dx%d", wd, hi); GtkAllocation alloc; gtk_widget_get_allocation(w, &alloc); - PGTK_TRACE(" %dx%d+%d+%d", alloc.width, alloc.height, alloc.x, alloc.y); } - PGTK_TRACE("pgtk_set_window_size: %p: %dx%d.", f, width, height); f->output_data.pgtk->preferred_width = pixelwidth; f->output_data.pgtk->preferred_height = pixelheight; x_wm_set_size_hint(f, 0, 0); @@ -679,6 +673,7 @@ x_display_pixel_width (struct pgtk_display_info *dpyinfo) return gdk_screen_get_width(gscr); } + void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) /* Set frame F's `no-focus-on-map' parameter which, if non-nil, means @@ -2632,8 +2627,6 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, { PGTK_TRACE("draw_window_cursor: %d, %d, %d, %d, %d, %d.", x, y, cursor_type, cursor_width, on_p, active_p); - struct frame *f = XFRAME (WINDOW_FRAME (w)); - PGTK_TRACE("%p\n", f->output_data.pgtk); if (on_p) { @@ -4807,9 +4800,9 @@ pgtk_handle_draw(GtkWidget *widget, cairo_t *cr, gpointer *data) if (src == NULL && FRAME_CR_ACTIVE_CONTEXT(f) != NULL) src = cairo_get_target(FRAME_CR_ACTIVE_CONTEXT(f)); } - APGTK_TRACE(" surface=%p", src); + PGTK_TRACE(" surface=%p", src); if (src != NULL) { - APGTK_TRACE(" resized_p=%d", f->resized_p); + PGTK_TRACE(" resized_p=%d", f->resized_p); PGTK_TRACE(" garbaged=%d", f->garbaged); PGTK_TRACE(" scroll_bar_width=%f", (double) PGTK_SCROLL_BAR_WIDTH(f)); // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); @@ -6581,9 +6574,6 @@ pgtk_begin_cr_clip (struct frame *f) cr = FRAME_CR_CONTEXT (f) = cairo_create (surface); cairo_surface_destroy (surface); - - cr = cairo_create (FRAME_CR_SURFACE (f)); - FRAME_CR_CONTEXT (f) = cr; } cairo_save (cr); @@ -6601,7 +6591,7 @@ pgtk_end_cr_clip (struct frame *f) void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc) { - PGTK_TRACE("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); + PGTK_TRACE ("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); pgtk_set_cr_source_with_color(f, gc->foreground); } diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 5c59d5e623..9d6b0a1f80 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -425,8 +425,8 @@ enum /* aliases */ #define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET(f) -#define FRAME_X_WINDOW(f) FRAME_GTK_WIDGET(f) -#define FRAME_NATIVE_WINDOW(f) FRAME_GTK_WIDGET(f) +#define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET(f) +#define FRAME_NATIVE_WINDOW(f) GTK_WINDOW(FRAME_X_WINDOW(f)) #define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO(f)->gdpy) commit 975289663f353f830d121058320150ff099e809a Author: Jeff Walsh Date: Tue Jan 14 16:44:38 2020 +1100 Bring pgtk more inline with X11-cairo builds * src/pgtkterm.h (struct pgtk_output): * src/pgtkterm.c (FRAME_CR_ACTIVE_CONTEXT, flip_cr_context) (x_draw_bar_cursor, pgtk_scroll_run, pgtk_update_end) (pgtk_cr_draw_image, pgtk_flash, pgtk_handle_draw) (pgtk_cr_update_surface_desired_size, pgtk_begin_cr_clip) (pgtk_cr_destroy_frame_context): * src/image.c (image_create_pattern_from_pixbuf): - Don't create a context each time, just hold a reference - Pull in a few cairo image changes from master - Remove redundant code in pgtk_update_begin() diff --git a/src/image.c b/src/image.c index 0b85cf8634..c7ae3b9944 100644 --- a/src/image.c +++ b/src/image.c @@ -405,7 +405,8 @@ static cairo_pattern_t * image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf *pixbuf) { GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); - cairo_surface_t *surface = cairo_surface_create_similar_image (f->output_data.pgtk->cr_surface, + cairo_surface_t *surface = cairo_surface_create_similar_image (cairo_get_target( + f->output_data.pgtk->cr_context), CAIRO_FORMAT_A1, gdk_pixbuf_get_width (pb), gdk_pixbuf_get_height (pb)); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index fbfc295534..e214cc26c8 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -62,8 +62,9 @@ along with GNU Emacs. If not, see . */ #define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) -#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) -#define FRAME_CR_SURFACE(f) ((f)->output_data.pgtk->cr_surface) +#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) +#define FRAME_CR_ACTIVE_CONTEXT(f) ((f)->output_data.pgtk->cr_active) +#define FRAME_CR_SURFACE(f) (cairo_get_target(FRAME_CR_CONTEXT(f))) #define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ ((f)->output_data.pgtk->cr_surface_desired_width) #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ @@ -96,6 +97,21 @@ static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, static struct frame * pgtk_any_window_to_frame (GdkWindow *window); +static void flip_cr_context(struct frame *f) +{ + PGTK_TRACE("flip_cr_context"); + cairo_t * cr = FRAME_CR_ACTIVE_CONTEXT(f); + + block_input(); + if ( cr != FRAME_CR_CONTEXT(f)) + { + cairo_destroy(cr); + FRAME_CR_ACTIVE_CONTEXT(f) = cairo_reference(FRAME_CR_CONTEXT(f)); + + } + unblock_input(); +} + static void evq_enqueue(union buffered_input_event *ev) { @@ -2667,8 +2683,6 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, xic_set_preeditarea (w, x, y); #endif } - - gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); } static void @@ -2771,38 +2785,6 @@ pgtk_scroll_run (struct window *w, struct run *run) static void pgtk_update_begin (struct frame *f) { - if (! NILP (tip_frame) && XFRAME (tip_frame) == f - && ! FRAME_VISIBLE_P (f)) - return; - - if (! FRAME_CR_SURFACE (f)) - { - int width, height; - if (FRAME_GTK_WIDGET (f)) - { - GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); - width = gdk_window_get_width (w); - height = gdk_window_get_height (w); - } - else - { - width = FRAME_PIXEL_WIDTH (f); - height = FRAME_PIXEL_HEIGHT (f); - if (! FRAME_EXTERNAL_TOOL_BAR (f)) - height += FRAME_TOOL_BAR_HEIGHT (f); - if (! FRAME_EXTERNAL_MENU_BAR (f)) - height += FRAME_MENU_BAR_HEIGHT (f); - } - - if (width > 0 && height > 0) - { - block_input(); - FRAME_CR_SURFACE (f) = cairo_image_surface_create - (CAIRO_FORMAT_ARGB32, width, height); - unblock_input(); - } - } - pgtk_clear_under_internal_border (f); } @@ -2965,8 +2947,12 @@ pgtk_update_window_end (struct window *w, bool cursor_on_p, static void pgtk_update_end (struct frame *f) { + GtkWidget *widget = FRAME_GTK_WIDGET(f); /* Mouse highlight may be displayed again. */ MOUSE_HL_INFO (f)->mouse_face_defer = false; + + gtk_widget_queue_draw (widget); + flip_cr_context(f); } /* Return the current position of the mouse. @@ -3139,13 +3125,10 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, int src_x, int src_y, int width, int height, int dest_x, int dest_y, bool overlay_p) { - cairo_t *cr; - cairo_matrix_t matrix; - cairo_surface_t *surface; - cairo_format_t format; + cairo_t *cr = pgtk_begin_cr_clip (f); PGTK_TRACE("pgtk_cr_draw_image: 0: %d,%d,%d,%d,%d,%d,%d.", src_x, src_y, width, height, dest_x, dest_y, overlay_p); - cr = pgtk_begin_cr_clip (f); + if (overlay_p) cairo_rectangle (cr, dest_x, dest_y, width, height); else @@ -3154,42 +3137,24 @@ pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, cairo_rectangle (cr, dest_x, dest_y, width, height); cairo_fill_preserve (cr); } - cairo_clip (cr); - cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y); - cairo_pattern_set_matrix (image, &matrix); + cairo_translate (cr, dest_x - src_x, dest_y - src_y); + + cairo_surface_t *surface; cairo_pattern_get_surface (image, &surface); - format = cairo_image_surface_get_format (surface); + cairo_format_t format = cairo_image_surface_get_format (surface); if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1) { - PGTK_TRACE("other format."); cairo_set_source (cr, image); cairo_fill (cr); } else { - if (format == CAIRO_FORMAT_A8) - PGTK_TRACE("format A8."); - else if (format == CAIRO_FORMAT_A1) - PGTK_TRACE("format A1."); - else - PGTK_TRACE("format ??."); pgtk_set_cr_source_with_gc_foreground (f, gc); - cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr); - PGTK_TRACE("rects:"); - PGTK_TRACE(" status: %u", rects->status); - PGTK_TRACE(" rectangles:"); - for (int i = 0; i < rects->num_rectangles; i++) { - PGTK_TRACE(" %fx%f+%f+%f", - rects->rectangles[i].width, - rects->rectangles[i].height, - rects->rectangles[i].x, - rects->rectangles[i].y); - } - cairo_rectangle_list_destroy(rects); + cairo_clip (cr); cairo_mask (cr, image); } + pgtk_end_cr_clip (f); - PGTK_TRACE("pgtk_cr_draw_image: 9."); } static void @@ -3375,8 +3340,6 @@ recover_from_visible_bell(struct atimer *timer) if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; - - gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); } static void @@ -3436,8 +3399,6 @@ pgtk_flash (struct frame *f) width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); FRAME_X_OUTPUT(f)->cr_surface_visible_bell = surface; - gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); - { struct timespec delay = make_timespec (0, 50 * 1000 * 1000); if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) { @@ -4843,12 +4804,12 @@ pgtk_handle_draw(GtkWidget *widget, cairo_t *cr, gpointer *data) PGTK_TRACE(" f=%p", f); if (f != NULL) { src = FRAME_X_OUTPUT(f)->cr_surface_visible_bell; - if (src == NULL) - src = FRAME_CR_SURFACE(f); + if (src == NULL && FRAME_CR_ACTIVE_CONTEXT(f) != NULL) + src = cairo_get_target(FRAME_CR_ACTIVE_CONTEXT(f)); } - PGTK_TRACE(" surface=%p", src); + APGTK_TRACE(" surface=%p", src); if (src != NULL) { - PGTK_TRACE(" resized_p=%d", f->resized_p); + APGTK_TRACE(" resized_p=%d", f->resized_p); PGTK_TRACE(" garbaged=%d", f->garbaged); PGTK_TRACE(" scroll_bar_width=%f", (double) PGTK_SCROLL_BAR_WIDTH(f)); // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); @@ -6596,27 +6557,10 @@ pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) { - cairo_surface_t *old_surface = FRAME_CR_SURFACE(f); - cairo_t *cr = NULL; - cairo_t *old_cr = FRAME_CR_CONTEXT(f); - FRAME_CR_SURFACE(f) = gdk_window_create_similar_surface(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), - CAIRO_CONTENT_COLOR_ALPHA, - width, - height); - - if (old_surface){ - cr = cairo_create(FRAME_CR_SURFACE(f)); - cairo_set_source_surface (cr, old_surface, 0, 0); - - cairo_paint(cr); - FRAME_CR_CONTEXT (f) = cr; - - cairo_destroy(old_cr); - cairo_surface_destroy (old_surface); - } - gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); + pgtk_cr_destroy_frame_context(f); FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width; FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height; + SET_FRAME_GARBAGED(f); } } @@ -6627,16 +6571,17 @@ pgtk_begin_cr_clip (struct frame *f) cairo_t *cr = FRAME_CR_CONTEXT (f); PGTK_TRACE("pgtk_begin_cr_clip"); - if (! FRAME_CR_SURFACE (f)) - { - FRAME_CR_SURFACE(f) = gdk_window_create_similar_surface(gtk_widget_get_window (FRAME_GTK_WIDGET (f)), - CAIRO_CONTENT_COLOR_ALPHA, - FRAME_PIXEL_WIDTH (f), - FRAME_PIXEL_HEIGHT (f)); - } - if (!cr) { + cairo_surface_t *surface = + gdk_window_create_similar_surface(gtk_widget_get_window (FRAME_GTK_WIDGET (f)), + CAIRO_CONTENT_COLOR_ALPHA, + FRAME_CR_SURFACE_DESIRED_WIDTH (f), + FRAME_CR_SURFACE_DESIRED_HEIGHT (f)); + + cr = FRAME_CR_CONTEXT (f) = cairo_create (surface); + cairo_surface_destroy (surface); + cr = cairo_create (FRAME_CR_SURFACE (f)); FRAME_CR_CONTEXT (f) = cr; } @@ -6651,9 +6596,6 @@ pgtk_end_cr_clip (struct frame *f) { PGTK_TRACE("pgtk_end_cr_clip"); cairo_restore (FRAME_CR_CONTEXT (f)); - - GtkWidget *widget = FRAME_GTK_WIDGET(f); - gtk_widget_queue_draw(widget); } void @@ -6690,18 +6632,13 @@ pgtk_cr_draw_frame (cairo_t *cr, struct frame *f) } void -pgtk_cr_destroy_surface(struct frame *f) +pgtk_cr_destroy_frame_context(struct frame *f) { - PGTK_TRACE("pgtk_cr_destroy_surface"); + PGTK_TRACE("pgtk_cr_destroy_frame_context"); if (FRAME_CR_CONTEXT(f) != NULL) { cairo_destroy(FRAME_CR_CONTEXT(f)); FRAME_CR_CONTEXT(f) = NULL; } - if (FRAME_CR_SURFACE(f) != NULL) { - cairo_surface_destroy(FRAME_CR_SURFACE(f)); - FRAME_CR_SURFACE(f) = NULL; - } - SET_FRAME_GARBAGED (f); } void diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 7bc0f0da08..5c59d5e623 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -364,11 +364,10 @@ struct pgtk_output int toolbar_left_width, toolbar_right_width; #ifdef USE_CAIRO - /* Cairo drawing context. */ - cairo_t *cr_context; + /* Cairo drawing contexts. */ + cairo_t *cr_context, *cr_active; int cr_surface_desired_width, cr_surface_desired_height; /* Cairo surface for double buffering */ - cairo_surface_t *cr_surface; cairo_surface_t *cr_surface_visible_bell; #endif struct atimer *atimer_visible_bell; @@ -576,7 +575,7 @@ extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc extern void pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc); extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color); extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); -extern void pgtk_cr_destroy_surface(struct frame *f); +extern void pgtk_cr_destroy_frame_context(struct frame *f); /* Defined in pgtkmenu.c */ extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents); commit 992ef483006aad6c85138e901768fa9e1ef59784 Author: Yuuki Harano Date: Wed Mar 25 00:23:42 2020 +0900 update redisplay_interface. * src/pgtkfns.c (Fx_create_frame, pgtk_default_font_parameter): * src/pgtkterm.c (pgtk_redisplay_interface): * src/pgtkterm.h: diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 2525547c3f..2c8f73ebcb 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -991,8 +991,8 @@ x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color) signal_error ("Undefined color", color_name); } -static void -x_default_font_parameter (struct frame *f, Lisp_Object parms) +void +pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, @@ -1262,7 +1262,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* Extract the window parameters from the supplied values that are needed to determine window geometry. */ - x_default_font_parameter (f, parms); + pgtk_default_font_parameter (f, parms); if (!FRAME_FONT (f)) { delete_frame (frame, Qnoelisp); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 92ad1bc6c8..fbfc295534 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3328,7 +3328,8 @@ static struct redisplay_interface pgtk_redisplay_interface = pgtk_draw_window_divider, NULL, // pgtk_shift_glyphs_for_insert, pgtk_show_hourglass, - pgtk_hide_hourglass + pgtk_hide_hourglass, + pgtk_default_font_parameter, }; static void diff --git a/src/pgtkterm.h b/src/pgtkterm.h index d441e16106..7bc0f0da08 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -615,6 +615,8 @@ extern void x_change_tab_bar_height (struct frame *, int); extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object); +extern void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms); + extern void pgtk_enqueue_string(struct frame *f, gchar *str); extern void pgtk_enqueue_preedit(struct frame *f, Lisp_Object image_data); extern void pgtk_im_focus_in(struct frame *f); commit d2a29e883e662a3f269628d5cbdf195c783ddf01 Author: Yuuki Harano Date: Tue Mar 24 00:33:57 2020 +0900 emacsclient should use both of DISPLAY and WAYLAND_DISPLAY. * lisp/server.el (server-create-window-system-frame): error out when not on a supported window * lib-src/emacsclient.c (decode_options): handle WALAND_DISPLAY on PGTK diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 871fa7a8d3..a55e4bc705 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -611,7 +611,12 @@ decode_options (int argc, char **argv) alt_display = "w32"; #endif +#ifdef HAVE_PGTK + display = egetenv ("WAYLAND_DISPLAY"); + alt_display = egetenv ("DISPLAY"); +#else display = egetenv ("DISPLAY"); +#endif } if (!display) diff --git a/lisp/server.el b/lisp/server.el index 763f651fef..9559613a36 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -881,12 +881,17 @@ This handles splitting the command if it would be bigger than ) (cond (w - (server--create-frame - nowait proc - `((display . ,display) - ,@(if parent-id - `((parent-id . ,(string-to-number parent-id)))) - ,@parameters))) + (condition-case nil + (server--create-frame + nowait proc + `((display . ,display) + ,@(if parent-id + `((parent-id . ,(string-to-number parent-id)))) + ,@parameters)) + (error + (server-log "Window system unsupported" proc) + (server-send-string proc "-window-system-unsupported \n") + nil))) (t (server-log "Window system unsupported" proc) commit 806b7640c0fe757ee6c2213e33220a807a5aa05d Author: Yuuki Harano Date: Tue Jan 21 22:45:37 2020 +0900 Before sleep, dispatch draw events. * src/pgtkterm.c (pgtk_select): remove sigio signal (pgtk_term_init): dispatch draw diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 74eb08d330..92ad1bc6c8 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3605,6 +3605,17 @@ pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, tmop = &tmo; } + /* Before sleep, dispatch draw events. */ + if (context_acquired) + { + int pselect_errno = errno; + block_input (); + while (g_main_context_pending (context)) + g_main_context_dispatch (context); + unblock_input (); + errno = pselect_errno; + } + fds_lim = max_fds + 1; nfds = thread_select (pselect, fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, @@ -6271,13 +6282,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) xsettings_initialize (dpyinfo); -#ifdef F_SETOWN - fcntl (dpyinfo->connection, F_SETOWN, getpid ()); -#endif /* ! defined (F_SETOWN) */ - - if (interrupt_input) - init_sigio (dpyinfo->connection); - pgtk_selection_init(); pgtk_im_init (dpyinfo); commit 385e85c3dde572fd9832670feb871e3b7715b156 Author: Jeff Walsh Date: Mon Jan 13 16:17:50 2020 +1100 End Resize flickering by copying surface rather than just clearing * src/pgtkterm.h (struct pgtk_output): store desired sizes * src/pgtkterm.c (FRAME_CR_SURFACE_DESIRED_HEIGHT) (FRAME_CR_SURFACE_DESIRED_WIDTH, size_allocate, configure_event) (pgtk_cr_update_surface_desired_size): add "desired" size for handling surface change * src/gtkutil.c (xg_frame_resized, xg_create_frame_widgets): remove surface destroy, turn off double buffer call diff --git a/src/gtkutil.c b/src/gtkutil.c index 394d81ace6..8cdbe3e4ad 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1053,9 +1053,6 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) change_frame_size (f, width, height, 0, 1, 0, 1); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); -#ifdef HAVE_PGTK - pgtk_cr_destroy_surface (f); -#endif } } @@ -1449,7 +1446,10 @@ xg_create_frame_widgets (struct frame *f) FIXME: gtk_widget_set_double_buffered is deprecated and might stop working in the future. We need to migrate away from combining X and GTK+ drawing to a pure GTK+ build. */ + +#ifndef HAVE_PGTK gtk_widget_set_double_buffered (wfixed, FALSE); +#endif #if ! GTK_CHECK_VERSION (3, 22, 0) gtk_window_set_wmclass (GTK_WINDOW (wtop), diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 67ff378633..74eb08d330 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -22,6 +22,7 @@ along with GNU Emacs. If not, see . */ interpretation of even the system includes. */ #include +#include #include #include #include @@ -63,6 +64,11 @@ along with GNU Emacs. If not, see . */ #define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) #define FRAME_CR_SURFACE(f) ((f)->output_data.pgtk->cr_surface) +#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \ + ((f)->output_data.pgtk->cr_surface_desired_width) +#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ + ((f)->output_data.pgtk->cr_surface_desired_height) + struct pgtk_display_info *x_display_list; /* Chain of existing displays */ extern Lisp_Object tip_frame; @@ -4851,6 +4857,7 @@ static void size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer *use if (f) { PGTK_TRACE("%dx%d", alloc->width, alloc->height); xg_frame_resized(f, alloc->width, alloc->height); + pgtk_cr_update_surface_desired_size(f, alloc->width, alloc->height); } } @@ -5274,6 +5281,7 @@ static gboolean configure_event(GtkWidget *widget, GdkEvent *event, gpointer *us if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) { PGTK_TRACE("%dx%d", event->configure.width, event->configure.height); xg_frame_resized(f, event->configure.width, event->configure.height); + pgtk_cr_update_surface_desired_size(f, event->configure.width, event->configure.height); } return TRUE; } @@ -6574,6 +6582,40 @@ If set to a non-float value, there will be no wait at all. */); } + +void +pgtk_cr_update_surface_desired_size (struct frame *f, int width, int height) +{ + PGTK_TRACE("pgtk_cr_update_surface_desired_size"); + + if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width + || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height) + { + cairo_surface_t *old_surface = FRAME_CR_SURFACE(f); + cairo_t *cr = NULL; + cairo_t *old_cr = FRAME_CR_CONTEXT(f); + FRAME_CR_SURFACE(f) = gdk_window_create_similar_surface(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), + CAIRO_CONTENT_COLOR_ALPHA, + width, + height); + + if (old_surface){ + cr = cairo_create(FRAME_CR_SURFACE(f)); + cairo_set_source_surface (cr, old_surface, 0, 0); + + cairo_paint(cr); + FRAME_CR_CONTEXT (f) = cr; + + cairo_destroy(old_cr); + cairo_surface_destroy (old_surface); + } + gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); + FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width; + FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height; + } +} + + cairo_t * pgtk_begin_cr_clip (struct frame *f) { diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 694a85bac2..d441e16106 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -366,6 +366,7 @@ struct pgtk_output #ifdef USE_CAIRO /* Cairo drawing context. */ cairo_t *cr_context; + int cr_surface_desired_width, cr_surface_desired_height; /* Cairo surface for double buffering */ cairo_surface_t *cr_surface; cairo_surface_t *cr_surface_visible_bell; @@ -568,6 +569,7 @@ extern int pgtk_select (int nfds, fd_set *readfds, fd_set *writefds, sigset_t *sigmask); /* Cairo related functions implemented in pgtkterm.c */ +extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int); extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc); commit b1cc62cac3af2c17e0a71634571128bce4d42248 Author: Yuuki Harano Date: Sun Jan 12 01:29:39 2020 +0900 Add support for Jpeglib configure.ac: enable jpeglib support for pgtk jpeglib を使えるようにした。 imagemagick がうまく機能してるので気付かなかった… diff --git a/configure.ac b/configure.ac index 6f5ad44295..16f7ef0e7b 100644 --- a/configure.ac +++ b/configure.ac @@ -3655,7 +3655,7 @@ AC_SUBST(LIBXPM) ### Use -ljpeg if available, unless '--with-jpeg=no'. HAVE_JPEG=no LIBJPEG= -if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ +if test "${HAVE_X11}" = "yes" || test "$window_system" = "pgtk" || test "${HAVE_W32}" = "yes" \ || test "${HAVE_NS}" = "yes"; then if test "${with_jpeg}" != "no"; then AC_CACHE_CHECK([for jpeglib 6b or later], commit 526f7277fcbd99aa7a5e0e3cc5139872bf322ee5 Author: Yuuki Harano Date: Fri Nov 22 00:27:12 2019 +0900 Let gtk handle scaling. * src/gtkutil.c (xg_get_scale): diff --git a/src/gtkutil.c b/src/gtkutil.c index b202aa02e2..394d81ace6 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -223,6 +223,9 @@ xg_get_gdk_scale (void) int xg_get_scale (struct frame *f) { +#ifdef HAVE_PGTK + return 1; +#endif #ifdef HAVE_GTK3 if (FRAME_GTK_WIDGET (f)) return gtk_widget_get_scale_factor (FRAME_GTK_WIDGET (f)); commit 232c129fe4ccc091c6b403a4d72b51d3d9687e23 Author: Yuuki Harano Date: Wed Nov 13 23:36:27 2019 +0900 implement pre-edit input method * src/termhooks.h (enum event_kind): new pgtk value * src/pgtkterm.h (struct pgtk_display_info): * src/pgtkterm.c (x_free_frame_resources, pgtk_delete_terminal) (pgtk_enqueue_string, pgtk_enqueue_preedit, key_press_event) (focus_in_event, focus_out_event, pgtk_term_init): call pgtkim * src/pgtkim.c: new file (im_context_commit_cb, im_context_retrieve_surrounding_cb) (make_color_string, im_context_preedit_changed_cb) (im_context_preedit_end_cb, im_context_preedit_start_cb) (pgtk_im_focus_in, pgtk_im_focus_out, pgtk_im_filter_keypress) (pgtk_im_finish, Fpgtk_use_im_context, syms_of_pgtkim): * src/pgtkfns.c (check_pgtk_display_info): * src/keyboard.c (kbd_buffer_get_event, make_lispy_event) (keys_of_keyboard): * src/emacs.c (main): add syms_of_pgtkim * lisp/term/pgtk-win.el (pgtk-preedit-text): new defun * configure.ac (XWIDGETS_OBJ): add pgtkim.o input method 対応 preedit を overlay で表示するようにした。 preedit 表示後すぐに反映されなかったのを修正 この機能を ON/OFF できるようにした。 default off. 確定と同時に次の preedit が始まった場合に表示位置がおかしかったのを修正。 sample. preedit をテキストで渡すようにした diff --git a/configure.ac b/configure.ac index 6d3652d97e..6f5ad44295 100644 --- a/configure.ac +++ b/configure.ac @@ -2830,7 +2830,7 @@ LIBS=$OLD_LIBS PGTK_OBJ= PGTK_LIBS= if test "$window_system" = "pgtk"; then - PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o xsettings.o" + PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o pgtkim.o xsettings.o" PGTK_LIBS="$GTK_LIBS -ldl" AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) fi diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 1cf526b758..2205ad662b 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -368,6 +368,39 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") &context (window-system pgtk)) (pgtk-get-selection-internal selection-symbol target-type)) + +(defvar pgtk-preedit-overlay nil) + +(defun pgtk-preedit-text (e) + (interactive "e") + (when pgtk-preedit-overlay + (delete-overlay pgtk-preedit-overlay)) + (setq pgtk-preedit-overlay nil) + + (let ((ovstr "") + (idx 0) + atts ov str color face-name) + (dolist (part (nth 1 e)) + (setq str (car part)) + (setq face-name (intern (format "pgtk-im-%d" idx))) + (eval + `(defface ,face-name nil "face of input method preedit")) + (setq atts nil) + (when (setq color (cdr-safe (assq 'fg (cdr part)))) + (setq atts (append atts `(:foreground ,color)))) + (when (setq color (cdr-safe (assq 'bg (cdr part)))) + (setq atts (append atts `(:background ,color)))) + (when (setq color (cdr-safe (assq 'ul (cdr part)))) + (setq atts (append atts `(:underline ,color)))) + (face-spec-set face-name `((t . ,atts))) + (add-text-properties 0 (length str) `(face ,face-name) str) + (setq ovstr (concat ovstr str)) + (setq idx (1+ idx))) + + (setq ov (make-overlay (point) (point))) + (overlay-put ov 'before-string ovstr) + (setq pgtk-preedit-overlay ov))) + (provide 'pgtk-win) (provide 'term/pgtk-win) diff --git a/src/emacs.c b/src/emacs.c index 42d93737b9..ba5c64a152 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1922,6 +1922,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_pgtkfns(); syms_of_pgtkselect (); syms_of_pgtkmenu (); + syms_of_pgtkim (); syms_of_fontset (); syms_of_xsettings (); syms_of_xwidget (); diff --git a/src/keyboard.c b/src/keyboard.c index 49261fcc3e..f6c44a11fb 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3939,6 +3939,9 @@ kbd_buffer_get_event (KBOARD **kbp, *used_mouse_menu = true; FALLTHROUGH; #endif +#ifdef HAVE_PGTK + case PGTK_PREEDIT_TEXT_EVENT: +#endif #ifdef HAVE_NTGUI case END_SESSION_EVENT: case LANGUAGE_CHANGE_EVENT: @@ -6047,6 +6050,11 @@ make_lispy_event (struct input_event *event) return list3 (Qconfig_changed_event, event->arg, event->frame_or_window); +#ifdef HAVE_PGTK + case PGTK_PREEDIT_TEXT_EVENT: + return list2 (intern("pgtk-preedit-text"), event->arg); +#endif + /* The 'kind' field of the event is something we don't recognize. */ default: emacs_abort (); @@ -12451,6 +12459,8 @@ keys_of_keyboard (void) "ns-put-working-text"); initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", "ns-unput-working-text"); + initial_define_lispy_key (Vspecial_event_map, "pgtk-preedit-text", + "pgtk-preedit-text"); /* Here we used to use `ignore-event' which would simple set prefix-arg to current-prefix-arg, as is done in `handle-switch-frame'. But `handle-switch-frame is not run from the special-map. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 090ebf5b36..2525547c3f 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -60,7 +60,7 @@ static const char *pgtk_app_name = "Emacs"; ========================================================================== */ -static struct pgtk_display_info * +struct pgtk_display_info * check_pgtk_display_info (Lisp_Object object) { struct pgtk_display_info *dpyinfo = NULL; diff --git a/src/pgtkim.c b/src/pgtkim.c new file mode 100644 index 0000000000..d9bba7e590 --- /dev/null +++ b/src/pgtkim.c @@ -0,0 +1,243 @@ +/* Pure Gtk+-3 communication module. -*- coding: utf-8 -*- + +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2018 Free Software +Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#include "pgtkterm.h" + +static void im_context_commit_cb(GtkIMContext *imc, gchar *str, gpointer user_data) +{ + struct pgtk_display_info *dpyinfo = user_data; + struct frame *f = dpyinfo->im.focused_frame; + + if (dpyinfo->im.context == NULL) + return; + if (f == NULL) + return; + + pgtk_enqueue_string(f, str); +} + +static gboolean im_context_retrieve_surrounding_cb(GtkIMContext *imc, gpointer user_data) +{ + gtk_im_context_set_surrounding(imc, "", -1, 0); + return TRUE; +} + +static gboolean im_context_delete_surrounding_cb(GtkIMContext *imc, int offset, int n_chars, gpointer user_data) +{ + return TRUE; +} + +static Lisp_Object make_color_string(PangoAttrColor *pac) +{ + char buf[256]; + sprintf(buf, "#%02x%02x%02x", + pac->color.red >> 8, + pac->color.green >> 8, + pac->color.blue >> 8); + return build_string(buf); +} + +static void im_context_preedit_changed_cb(GtkIMContext *imc, gpointer user_data) +{ + struct pgtk_display_info *dpyinfo = user_data; + struct frame *f = dpyinfo->im.focused_frame; + char *str; + PangoAttrList *attrs; + int pos; + + if (dpyinfo->im.context == NULL) + return; + if (f == NULL) + return; + + gtk_im_context_get_preedit_string(imc, &str, &attrs, &pos); + + + /* + * ( + * (TEXT (ul . COLOR) (bg . COLOR) (fg . COLOR)) + * ... + * ) + */ + Lisp_Object list = Qnil; + + PangoAttrIterator* iter; + iter = pango_attr_list_get_iterator(attrs); + do { + int st, ed; + int has_underline = 0; + Lisp_Object part = Qnil; + + pango_attr_iterator_range(iter, &st, &ed); + + if (ed > strlen(str)) + ed = strlen(str); + if (st >= ed) + continue; + + Lisp_Object text = make_string(str + st, ed - st); + part = Fcons(text, part); + + PangoAttrInt *ul = (PangoAttrInt *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE); + if (ul != NULL) { + if (ul->value != PANGO_UNDERLINE_NONE) + has_underline = 1; + } + + PangoAttrColor *pac; + if (has_underline) { + pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE_COLOR); + if (pac != NULL) + part = Fcons(Fcons(Qul, make_color_string(pac)), part); + else + part = Fcons(Fcons(Qul, Qt), part); + } + + pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_FOREGROUND); + if (pac != NULL) + part = Fcons(Fcons(Qfg, make_color_string(pac)), part); + + pac = (PangoAttrColor *) pango_attr_iterator_get(iter, PANGO_ATTR_BACKGROUND); + if (pac != NULL) + part = Fcons(Fcons(Qbg, make_color_string(pac)), part); + + part = Fnreverse(part); + list = Fcons(part, list); + } while (pango_attr_iterator_next(iter)); + + list = Fnreverse(list); + pgtk_enqueue_preedit(f, list); + + g_free(str); + pango_attr_list_unref(attrs); +} + +static void im_context_preedit_end_cb(GtkIMContext *imc, gpointer user_data) +{ + struct pgtk_display_info *dpyinfo = user_data; + struct frame *f = dpyinfo->im.focused_frame; + + if (dpyinfo->im.context == NULL) + return; + if (f == NULL) + return; + + pgtk_enqueue_preedit(f, Qnil); +} + +static void im_context_preedit_start_cb(GtkIMContext *imc, gpointer user_data) +{ +} + +void pgtk_im_focus_in(struct frame *f) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->im.context != NULL) { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, gtk_widget_get_window (FRAME_GTK_WIDGET (f))); + gtk_im_context_focus_in (dpyinfo->im.context); + } + dpyinfo->im.focused_frame = f; +} + +void pgtk_im_focus_out(struct frame *f) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->im.focused_frame == f) { + if (dpyinfo->im.context != NULL) { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_focus_out (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, NULL); + } + dpyinfo->im.focused_frame = NULL; + } +} + +bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->im.context != NULL) { + if (gtk_im_context_filter_keypress (dpyinfo->im.context, ev)) + return true; + } + return false; +} + +void pgtk_im_init(struct pgtk_display_info *dpyinfo) +{ + dpyinfo->im.context = NULL; +} + +void pgtk_im_finish(struct pgtk_display_info *dpyinfo) +{ + if (dpyinfo->im.context != NULL) + g_object_unref(dpyinfo->im.context); + dpyinfo->im.context = NULL; +} + +DEFUN ("pgtk-use-im-context", Fpgtk_use_im_context, Spgtk_use_im_context, + 1, 2, 0, + doc: /* Set whether use Gtk's im context. */) + (Lisp_Object use_p, Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + + if (NILP(use_p)) { + if (dpyinfo->im.context != NULL) { + gtk_im_context_reset (dpyinfo->im.context); + gtk_im_context_focus_out (dpyinfo->im.context); + gtk_im_context_set_client_window (dpyinfo->im.context, NULL); + + g_object_unref(dpyinfo->im.context); + dpyinfo->im.context = NULL; + } + } else { + if (dpyinfo->im.context == NULL) { + dpyinfo->im.context = gtk_im_multicontext_new(); + g_signal_connect(dpyinfo->im.context, "commit", G_CALLBACK(im_context_commit_cb), dpyinfo); + g_signal_connect(dpyinfo->im.context, "retrieve-surrounding", G_CALLBACK(im_context_retrieve_surrounding_cb), dpyinfo); + g_signal_connect(dpyinfo->im.context, "delete-surrounding", G_CALLBACK(im_context_delete_surrounding_cb), dpyinfo); + g_signal_connect(dpyinfo->im.context, "preedit-changed", G_CALLBACK(im_context_preedit_changed_cb), dpyinfo); + g_signal_connect(dpyinfo->im.context, "preedit-end", G_CALLBACK(im_context_preedit_end_cb), dpyinfo); + g_signal_connect(dpyinfo->im.context, "preedit-start", G_CALLBACK(im_context_preedit_start_cb), dpyinfo); + gtk_im_context_set_use_preedit (dpyinfo->im.context, TRUE); + + if (dpyinfo->im.focused_frame) + pgtk_im_focus_in(dpyinfo->im.focused_frame); + } + } + + return Qnil; +} + +void +syms_of_pgtkim (void) +{ + defsubr (&Spgtk_use_im_context); + + DEFSYM (Qpgtk_refresh_preedit, "pgtk-refresh-preedit"); + DEFSYM (Qul, "ul"); + DEFSYM (Qfg, "fg"); + DEFSYM (Qbg, "bg"); +} diff --git a/src/pgtkterm.c b/src/pgtkterm.c index fab6e4eed9..67ff378633 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -188,6 +188,7 @@ x_free_frame_resources (struct frame *f) CLEAR_IF_EQ(last_mouse_frame); CLEAR_IF_EQ(last_mouse_motion_frame); CLEAR_IF_EQ(last_mouse_glyph_frame); + CLEAR_IF_EQ(im.focused_frame); #undef CLEAR_IF_EQ @@ -4282,6 +4283,8 @@ pgtk_delete_terminal (struct terminal *terminal) block_input (); + pgtk_im_finish (dpyinfo); + /* Normally, the display is available... */ if (dpyinfo->gdpy) { @@ -4952,6 +4955,45 @@ pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) #define IsKeypadKey(keysym) (0xff80 <= (keysym) && (keysym) < 0xffbe) #define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1) +void +pgtk_enqueue_string(struct frame *f, gchar *str) +{ + gunichar *ustr; + + ustr = g_utf8_to_ucs4 (str, -1, NULL, NULL, NULL); + if (ustr == NULL) + return; + for ( ; *ustr != 0; ustr++) { + union buffered_input_event inev; + Lisp_Object c = make_fixnum (*ustr); + EVENT_INIT (inev.ie); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c)) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.arg = Qnil; + inev.ie.code = XFIXNAT (c); + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers = 0; + inev.ie.timestamp = 0; + evq_enqueue (&inev); + } + +} + +void +pgtk_enqueue_preedit(struct frame *f, Lisp_Object preedit) +{ + union buffered_input_event inev; + EVENT_INIT (inev.ie); + inev.ie.kind = PGTK_PREEDIT_TEXT_EVENT; + inev.ie.arg = preedit; + inev.ie.code = 0; + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers = 0; + inev.ie.timestamp = 0; + evq_enqueue (&inev); +} + static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) { struct coding_system coding; @@ -4978,6 +5020,11 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us hlinfo->mouse_face_hidden = true; } + if (f != 0) { + if (pgtk_im_filter_keypress (f, &event->key)) + return TRUE; + } + if (f != 0) { guint keysym, orig_keysym; @@ -5462,6 +5509,9 @@ focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) FRAME_DISPLAY_INFO(frame), frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); + + pgtk_im_focus_in (frame); + return TRUE; } @@ -5483,6 +5533,9 @@ focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) FRAME_DISPLAY_INFO(frame), frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue(&inev); + + pgtk_im_focus_out (frame); + return TRUE; } @@ -6219,6 +6272,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) pgtk_selection_init(); + pgtk_im_init (dpyinfo); + unblock_input (); return dpyinfo; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index a2ba627425..694a85bac2 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -226,6 +226,14 @@ struct pgtk_display_info /* Modifier masks in gdk */ int meta_mod_mask, alt_mod_mask; + + /* whether to use Gtk's IM context. */ + + /* input method */ + struct { + GtkIMContext *context; + struct frame *focused_frame; + } im; }; /* This is a chain of structures for all the PGTK displays currently in use. */ @@ -579,6 +587,7 @@ extern void syms_of_pgtkterm (void); extern void syms_of_pgtkfns (void); extern void syms_of_pgtkmenu (void); extern void syms_of_pgtkselect (void); +extern void syms_of_pgtkim (void); /* Implemented in pgtkselect. */ extern void nxatoms_of_pgtkselect (void); @@ -602,4 +611,14 @@ extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo); extern void x_change_tab_bar_height (struct frame *, int); +extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object); + +extern void pgtk_enqueue_string(struct frame *f, gchar *str); +extern void pgtk_enqueue_preedit(struct frame *f, Lisp_Object image_data); +extern void pgtk_im_focus_in(struct frame *f); +extern void pgtk_im_focus_out(struct frame *f); +extern bool pgtk_im_filter_keypress(struct frame *f, GdkEventKey *ev); +extern void pgtk_im_init(struct pgtk_display_info *dpyinfo); +extern void pgtk_im_finish(struct pgtk_display_info *dpyinfo); + #endif /* HAVE_PGTK */ diff --git a/src/termhooks.h b/src/termhooks.h index 4403d518ff..c28c3fbbd0 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -264,6 +264,10 @@ enum event_kind , FILE_NOTIFY_EVENT #endif +#ifdef HAVE_PGTK + /* Pre-edit text was changed. */ + , PGTK_PREEDIT_TEXT_EVENT +#endif }; /* Bit width of an enum event_kind tag at the start of structs and unions. */ commit 9e56fa9853f5d0114b90d69ff43885a80ca8f5bd Author: Yuuki Harano Date: Sun Oct 13 01:41:34 2019 +0900 Support focus on click event * src/pgtkterm.c (enter_notify_event, leave_notify_event) (focus_in_event, focus_out_event): support focus on click focus-on-click な環境に対応。 diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 7c908a33f7..fab6e4eed9 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5393,7 +5393,11 @@ enter_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) { PGTK_TRACE("enter_notify_event"); union buffered_input_event inev; - struct frame *focus_frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + if (frame == NULL) + return FALSE; + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); + struct frame *focus_frame = dpyinfo->x_focus_frame; int focus_state = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0; @@ -5401,10 +5405,12 @@ enter_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (!(focus_state & FOCUS_EXPLICIT)) + if (event->crossing.detail != GDK_NOTIFY_INFERIOR + && event->crossing.focus + && ! (focus_state & FOCUS_EXPLICIT)) x_focus_changed (TRUE, FOCUS_IMPLICIT, - FRAME_DISPLAY_INFO(focus_frame), focus_frame, &inev); + dpyinfo, frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; @@ -5415,7 +5421,11 @@ leave_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) { PGTK_TRACE("leave_notify_event"); union buffered_input_event inev; - struct frame *focus_frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + if (frame == NULL) + return FALSE; + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); + struct frame *focus_frame = dpyinfo->x_focus_frame; int focus_state = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0; @@ -5423,10 +5433,12 @@ leave_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - if (!(focus_state & FOCUS_EXPLICIT)) + if (event->crossing.detail != GDK_NOTIFY_INFERIOR + && event->crossing.focus + && ! (focus_state & FOCUS_EXPLICIT)) x_focus_changed (FALSE, FOCUS_IMPLICIT, - FRAME_DISPLAY_INFO(focus_frame), focus_frame, &inev); + dpyinfo, frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); return TRUE; @@ -5446,7 +5458,7 @@ focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - x_focus_changed (TRUE, FOCUS_IMPLICIT, + x_focus_changed (TRUE, FOCUS_EXPLICIT, FRAME_DISPLAY_INFO(frame), frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue (&inev); @@ -5467,7 +5479,7 @@ focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; - x_focus_changed (FALSE, FOCUS_IMPLICIT, + x_focus_changed (FALSE, FOCUS_EXPLICIT, FRAME_DISPLAY_INFO(frame), frame, &inev); if (inev.ie.kind != NO_EVENT) evq_enqueue(&inev); commit 9eb35f9996197476fd300be1b8dd62c6b791678e Author: Yuuki Harano Date: Tue Oct 8 23:05:55 2019 +0900 experimental support of tab-bar. * src/window.h: compile conditional * src/pgtkterm.h: function decls * src/pgtkterm.c (x_draw_image_relief, pgtk_create_terminal) (motion_notify_event, button_event): tabbar support * src/pgtkfns.c (x_set_tab_bar_lines, x_change_tab_bar_height) (pgtk_frame_parm_handlers, Fx_create_frame, frame_geometry): tabbar support 余計なイベントが生成されていたのを修正。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 88702f1759..090ebf5b36 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -513,6 +513,93 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) adjust_frame_glyphs (f); } +/* Set the number of lines used for the tab bar of frame F to VALUE. + VALUE not an integer, or < 0 means set the lines to zero. OLDVAL + is the old number of tab bar lines. This function changes the + height of all windows on frame F to match the new tab bar height. + The frame's height doesn't change. */ + +static void +x_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ + int nlines; + + /* Treat tab bars like menu bars. */ + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + /* Use VALUE only if an int >= 0. */ + if (RANGED_FIXNUMP (0, value, INT_MAX)) + nlines = XFIXNAT (value); + else + nlines = 0; + + x_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); +} + + +/* Set the pixel height of the tab bar of frame F to HEIGHT. */ +void +x_change_tab_bar_height (struct frame *f, int height) +{ + int unit = FRAME_LINE_HEIGHT (f); + int old_height = FRAME_TAB_BAR_HEIGHT (f); + int lines = (height + unit - 1) / unit; + Lisp_Object fullscreen; + + /* Make sure we redisplay all windows in this frame. */ + fset_redisplay (f); + + /* Recalculate tab bar and frame text sizes. */ + FRAME_TAB_BAR_HEIGHT (f) = height; + FRAME_TAB_BAR_LINES (f) = lines; + /* Store the `tab-bar-lines' and `height' frame parameters. */ + store_frame_param (f, Qtab_bar_lines, make_fixnum (lines)); + store_frame_param (f, Qheight, make_fixnum (FRAME_LINES (f))); + + /* We also have to make sure that the internal border at the top of + the frame, below the menu bar or tab bar, is redrawn when the + tab bar disappears. This is so because the internal border is + below the tab bar if one is displayed, but is below the menu bar + if there isn't a tab bar. The tab bar draws into the area + below the menu bar. */ + if (FRAME_X_WINDOW (f) && FRAME_TAB_BAR_HEIGHT (f) == 0) + { + clear_frame (f); + clear_current_matrices (f); + } + + if ((height < old_height) && WINDOWP (f->tab_bar_window)) + clear_glyph_matrix (XWINDOW (f->tab_bar_window)->current_matrix); + + /* Recalculate tabbar height. */ + f->n_tab_bar_rows = 0; + if (old_height == 0 + && (!f->after_make_frame + || NILP (frame_inhibit_implied_resize) + || (CONSP (frame_inhibit_implied_resize) + && NILP (Fmemq (Qtab_bar_lines, frame_inhibit_implied_resize))))) + f->tab_bar_redisplayed = f->tab_bar_resized = false; + + adjust_frame_size (f, -1, -1, + ((!f->tab_bar_resized + && (NILP (fullscreen = + get_frame_param (f, Qfullscreen)) + || EQ (fullscreen, Qfullwidth))) ? 1 + : (old_height == 0 || height == 0) ? 2 + : 4), + false, Qtab_bar_lines); + + f->tab_bar_resized = f->tab_bar_redisplayed; + + /* adjust_frame_size might not have done anything, garbage frame + here. */ + adjust_frame_glyphs (f); + SET_FRAME_GARBAGED (f); + if (FRAME_X_WINDOW (f)) + pgtk_clear_under_internal_border (f); +} + /* Set the pixel height of the tool bar of frame F to HEIGHT. */ static void x_change_tool_bar_height (struct frame *f, int height) @@ -812,6 +899,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = gui_set_vertical_scroll_bars, /* generic OK */ gui_set_horizontal_scroll_bars, /* generic OK */ gui_set_visibility, /* generic OK */ + x_set_tab_bar_lines, x_set_tool_bar_lines, pgtk_set_scroll_bar_foreground, pgtk_set_scroll_bar_background, @@ -1277,6 +1365,10 @@ This function is an internal primitive--use `make-frame' instead. */) NILP (Vmenu_bar_mode) ? make_fixnum (0) : make_fixnum (1), NULL, NULL, RES_TYPE_NUMBER); + gui_default_parameter (f, parms, Qtab_bar_lines, + NILP (Vtab_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qtool_bar_lines, NILP (Vtool_bar_mode) ? make_fixnum (0) : make_fixnum (1), @@ -1296,7 +1388,7 @@ This function is an internal primitive--use `make-frame' instead. */) RES_TYPE_BOOLEAN); /* Compute the size of the X window. */ - window_prompting = gui_figure_window_size (f, parms, true, &x_width, &x_height); + window_prompting = gui_figure_window_size (f, parms, true, true, &x_width, &x_height); tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || EQ (tem, Qt); @@ -2568,11 +2660,18 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) int native_right = f->left_pos + outer_width - border; int native_bottom = f->top_pos + outer_height - border; int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f); + int tab_bar_height = 0, tab_bar_width = 0; int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f); int tool_bar_width = (tool_bar_height ? outer_width - 2 * internal_border_width : 0); + tab_bar_height = FRAME_TAB_BAR_HEIGHT (f); + tab_bar_width = (tab_bar_height + ? native_width - 2 * internal_border_width + : 0); + // inner_top += tab_bar_height; + /* Construct list. */ if (EQ (attribute, Qouter_edges)) return list4 (make_fixnum (f->left_pos), make_fixnum (f->top_pos), @@ -2604,6 +2703,9 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) Fcons (make_fixnum (0), make_fixnum (title_height))), Fcons (Qmenu_bar_external, Qnil), Fcons (Qmenu_bar_size, Fcons (make_fixnum (0), make_fixnum (0))), + Fcons (Qtab_bar_size, + Fcons (make_fixnum (tab_bar_width), + make_fixnum (tab_bar_height))), Fcons (Qtool_bar_external, FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil), Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)), diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 92f1409ede..7c908a33f7 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1821,7 +1821,11 @@ x_draw_image_relief (struct glyph_string *s) if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) { - thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF; + thick = (tab_bar_button_relief < 0 + ? DEFAULT_TAB_BAR_BUTTON_RELIEF + : (tool_bar_button_relief < 0 + ? DEFAULT_TOOL_BAR_BUTTON_RELIEF + : min (tool_bar_button_relief, 1000000))); raised_p = s->hl == DRAW_IMAGE_RAISED; } else @@ -1834,6 +1838,19 @@ x_draw_image_relief (struct glyph_string *s) y1 = y + s->slice.height - 1; extra_x = extra_y = 0; + if (s->face->id == TAB_BAR_FACE_ID) + { + if (CONSP (Vtab_bar_button_margin) + && FIXNUMP (XCAR (Vtab_bar_button_margin)) + && FIXNUMP (XCDR (Vtab_bar_button_margin))) + { + extra_x = XFIXNUM (XCAR (Vtab_bar_button_margin)); + extra_y = XFIXNUM (XCDR (Vtab_bar_button_margin)); + } + else if (FIXNUMP (Vtab_bar_button_margin)) + extra_x = extra_y = XFIXNUM (Vtab_bar_button_margin); + } + if (s->face->id == TOOL_BAR_FACE_ID) { if (CONSP (Vtool_bar_button_margin) @@ -4554,6 +4571,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->menu_show_hook = pgtk_menu_show; terminal->activate_menubar_hook = pgtk_activate_menubar; terminal->popup_dialog_hook = pgtk_popup_dialog; + terminal->change_tab_bar_height_hook = x_change_tab_bar_height; terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar; terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar; terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars; @@ -5556,7 +5574,7 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) { static Lisp_Object last_mouse_window; Lisp_Object window = window_from_coordinates - (f, event->motion.x, event->motion.y, 0, false); + (f, event->motion.x, event->motion.y, 0, false, false); /* A window will be autoselected only when it is not selected now and the last mouse movement event was @@ -5676,6 +5694,7 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) /* If we decide we want to generate an event to be seen by the rest of Emacs, we put it here. */ + bool tab_bar_p = false; bool tool_bar_p = false; EVENT_INIT (inev.ie); @@ -5725,9 +5744,30 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) if (f && xg_event_is_for_scrollbar (f, event)) f = 0; + + if (f) + { + /* Is this in the tab-bar? */ + if (WINDOWP (f->tab_bar_window) + && WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window))) + { + Lisp_Object window; + int x = event->button.x; + int y = event->button.y; + + window = window_from_coordinates (f, x, y, 0, true, true); + tab_bar_p = EQ (window, f->tab_bar_window); + + if (tab_bar_p && event->button.button < 4) + handle_tab_bar_click + (f, x, y, event->type == GDK_BUTTON_PRESS, + pgtk_gtk_to_emacs_modifiers (dpyinfo, event->button.state)); + } + } + if (f) { - if (!tool_bar_p) + if (!tab_bar_p && !tool_bar_p) { if (ignore_next_mouse_click_timeout) { diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 8caf31f8e4..a2ba627425 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -600,4 +600,6 @@ extern Lisp_Object x_get_focus_frame (struct frame *frame); extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo); +extern void x_change_tab_bar_height (struct frame *, int); + #endif /* HAVE_PGTK */ diff --git a/src/window.h b/src/window.h index 167d1be7ab..95cfcf3b10 100644 --- a/src/window.h +++ b/src/window.h @@ -756,7 +756,7 @@ wset_next_buffers (struct window *w, Lisp_Object val) #endif /* True if W is a tab bar window. */ -#if defined (HAVE_WINDOW_SYSTEM) +#if defined (HAVE_WINDOW_SYSTEM) && !defined(HAVE_PGTK) # define WINDOW_TAB_BAR_P(W) \ (WINDOWP (WINDOW_XFRAME (W)->tab_bar_window) \ && (W) == XWINDOW (WINDOW_XFRAME (W)->tab_bar_window)) commit bc35a1e1d5dbee82391d08c4fca361c7fc77d558 Author: Yuuki Harano Date: Thu Aug 1 01:26:55 2019 +0900 Make multipdisplay work by limiting selection while enabed * src/pgtkterm.c (pgtk_mouse_position): * src/pgtkselect.c (pgtk_selection_usable): new function (Fpgtk_own_selection_internal, Fpgtk_disown_selection_internal) (Fpgtk_selection_exists_p, Fpgtk_selection_owner_p) (Fpgtk_get_selection_internal): check usable selection multi-display で落ちる理由を一つ潰した。 まだまだありそう。 multi-display 時は selection を使えないようにした。 diff --git a/src/pgtkselect.c b/src/pgtkselect.c index b885425680..4f4a43da8b 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -200,6 +200,93 @@ void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer u g_object_set_qdata(G_OBJECT(widget), quark_size, 0); } +static bool +pgtk_selection_usable (void) +{ + /* + * https://github.com/GNOME/gtk/blob/gtk-3-24/gdk/wayland/gdkselection-wayland.c#L1033 + * + * Gdk uses gdk_display_get_default() when handling selections, so + * selections don't work properly on multi-display environment. + * + * ---------------- + * #include + * + * static GtkWidget *top1, *top2; + * + * int main(int argc, char **argv) + * { + * GtkWidget *w; + * GtkTextBuffer *buf; + * + * gtk_init(&argc, &argv); + * + * static char *text = "\ + * It is fine today.\n\ + * It will be fine tomorrow too.\n\ + * It is too hot."; + * + * top1 = gtk_window_new(GTK_WINDOW_TOPLEVEL); + * gtk_window_set_title(GTK_WINDOW(top1), "default"); + * gtk_widget_show(top1); + * w = gtk_text_view_new(); + * gtk_container_add(GTK_CONTAINER(top1), w); + * gtk_widget_show(w); + * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); + * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text)); + * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY)); + * + * unsetenv("GDK_BACKEND"); + * GdkDisplay *gdpy; + * const char *dpyname2; + * if (strcmp(G_OBJECT_TYPE_NAME(gtk_widget_get_window(top1)), "GdkWaylandWindow") == 0) + * dpyname2 = ":0"; + * else + * dpyname2 = "wayland-0"; + * gdpy = gdk_display_open (dpyname2); + * top2 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + * gtk_window_set_title(GTK_WINDOW(top2), dpyname2); + * gtk_window_set_screen (GTK_WINDOW (top2), gdk_display_get_default_screen(gdpy)); + * gtk_widget_show (top2); + * w = gtk_text_view_new(); + * gtk_container_add(GTK_CONTAINER(top2), w); + * gtk_widget_show(w); + * buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w)); + * gtk_text_buffer_insert_at_cursor(buf, text, strlen(text)); + * gtk_text_buffer_add_selection_clipboard(buf, gtk_widget_get_clipboard(w, GDK_SELECTION_PRIMARY)); + * + * gtk_main(); + * + * return 0; + * } + * ---------------- + * + * This code fails if + * GDK_BACKEND=x11 ./test + * and select on both of windows. + * + * ---------------- + * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.041: g_object_ref: assertion 'G_IS_OBJECT (object)' failed + * + * (test:15345): GLib-GObject-CRITICAL **: 01:56:38.042: g_object_ref: assertion 'G_IS_OBJECT (object)' failed + * + * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed + * + * (test:15345): GLib-GObject-CRITICAL **: 01:56:39.113: g_object_ref: assertion 'G_IS_OBJECT (object)' failed + * ---------------- + * (gtk-3.24.10) + * + * This function checks whether selections work by the number of displays. + * If you use more than 2 displays, then selection is disabled. + */ + + GdkDisplayManager *dpyman = gdk_display_manager_get (); + GSList *list = gdk_display_manager_list_displays (dpyman); + int len = g_slist_length (list); + g_slist_free (list); + return len < 2; +} + /* ========================================================================== Lisp Defuns @@ -228,6 +315,9 @@ nil, it defaults to the selected frame.*/) check_window_system (NULL); + if (!pgtk_selection_usable ()) + return Qnil; + if (NILP (frame)) frame = selected_frame; if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) error ("pgtk selection unavailable for this frame"); @@ -308,6 +398,9 @@ On PGTK, the TIME-OBJECT is unused. */) struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; + if (!pgtk_selection_usable ()) + return Qnil; + if (!f) return Qnil; @@ -337,6 +430,9 @@ On Nextstep, TERMINAL is unused. */) struct frame *f = frame_for_pgtk_selection (terminal); GtkClipboard *cb; + if (!pgtk_selection_usable ()) + return Qnil; + if (!f) return Qnil; @@ -368,6 +464,9 @@ On Nextstep, TERMINAL is unused. */) GObject *obj; GQuark quark_data, quark_size; + if (!pgtk_selection_usable ()) + return Qnil; + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); @@ -406,6 +505,9 @@ On PGTK, TIME-STAMP is unused. */) if (!f) error ("PGTK selection unavailable for this frame"); + if (!pgtk_selection_usable ()) + return Qnil; + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol); gchar *s = gtk_clipboard_wait_for_text(cb); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 50ee31e45c..92f1409ede 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2975,6 +2975,8 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, int win_x, win_y; GdkSeat *seat; GdkDevice *device; + GdkModifierType mask; + GdkWindow *win; block_input (); @@ -2988,32 +2990,33 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, dpyinfo->last_mouse_scroll_bar = NULL; - seat = gdk_display_get_default_seat(dpyinfo->gdpy); - device = gdk_seat_get_pointer(seat); - if (gui_mouse_grabbed (dpyinfo)) { - GdkWindow *win; - GdkModifierType mask; - /* get x, y relative to edit window of f1. */ + /* 1.1. use last_mouse_frame as frame where the pointer is on. */ f1 = dpyinfo->last_mouse_frame; - win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); - win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); } else { - GdkWindow *win; - GdkModifierType mask; - /* 1. get frame where the pointer is on. */ + f1 = *fp; + /* 1.2. get frame where the pointer is on. */ win = gtk_widget_get_window(FRAME_GTK_WIDGET(*fp)); + seat = gdk_display_get_default_seat(dpyinfo->gdpy); + device = gdk_seat_get_pointer(seat); win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); if (win != NULL) f1 = pgtk_any_window_to_frame(win); - else + else { + // crossing display server? f1 = SELECTED_FRAME(); - - /* 2. get x, y relative to edit window of the frame. */ - win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); - win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); + } } + /* 2. get the display and the device. */ + win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); + GdkDisplay *gdpy = gdk_window_get_display (win); + seat = gdk_display_get_default_seat(gdpy); + device = gdk_seat_get_pointer(seat); + + /* 3. get x, y relative to edit window of the frame. */ + win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); + if (f1 != NULL) { dpyinfo = FRAME_DISPLAY_INFO (f1); remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); commit 24d82638bc674d0c258ed95649fe98b22113d42f Author: Yuuki Harano Date: Mon Jul 29 22:44:58 2019 +0900 Improve drawing efficency by refactoring code * ../src/pgtkterm.c (fill_background, fill_background_by_face) (x_draw_glyph_string_background, x_draw_glyph_string_bg_rect) (x_draw_image_glyph_string, x_draw_stretch_glyph_string) (pgtk_clear_under_internal_border): Refator duplcate code 更に効率化。 diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 3e8357e774..50ee31e45c 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1003,45 +1003,37 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) } -static cairo_surface_t * -create_background_surface_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) +static void +fill_background_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) { - cairo_surface_t *surface = cairo_surface_create_similar (FRAME_CR_SURFACE (f), - CAIRO_CONTENT_COLOR, - width, - height); - - { - cairo_t *cr = cairo_create (surface); + cairo_t *cr = pgtk_begin_cr_clip(f); - double r = ((face->background >> 16) & 0xff) / 255.0; - double g = ((face->background >> 8) & 0xff) / 255.0; - double b = ((face->background >> 0) & 0xff) / 255.0; - cairo_set_source_rgb (cr, r, g, b); - cairo_paint (cr); + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); - cairo_destroy (cr); - } + double r = ((face->background >> 16) & 0xff) / 255.0; + double g = ((face->background >> 8) & 0xff) / 255.0; + double b = ((face->background >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_paint (cr); if (face->stipple != 0) { cairo_pattern_t *mask = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern; - cairo_t *cr = cairo_create (surface); double r = ((face->foreground >> 16) & 0xff) / 255.0; double g = ((face->foreground >> 8) & 0xff) / 255.0; double b = ((face->foreground >> 0) & 0xff) / 255.0; cairo_set_source_rgb (cr, r, g, b); cairo_mask (cr, mask); - cairo_destroy (cr); } - return surface; + pgtk_end_cr_clip (f); } -static cairo_surface_t * -create_background_surface (struct glyph_string *s, int x, int y, int width, int height) +static void +fill_background (struct glyph_string *s, int x, int y, int width, int height) { - return create_background_surface_by_face (s->f, s->face, x, y, width, height); + fill_background_by_face (s->f, s->face, x, y, width, height); } /* Draw the background of glyph_string S. If S->background_filled_p @@ -1072,20 +1064,9 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) { /* Fill background with a stipple pattern. */ - cairo_surface_t *bg = create_background_surface (s, - s->x, s->y + box_line_width, - s->background_width, s->height - 2 * box_line_width); - - cairo_t *cr = pgtk_begin_cr_clip (s->f); - cairo_set_source_surface (cr, bg, s->x, s->y + box_line_width); - cairo_rectangle (cr, + fill_background (s, s->x, s->y + box_line_width, s->background_width, s->height - 2 * box_line_width); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - - cairo_surface_destroy (bg); - s->background_filled_p = true; } else @@ -1893,15 +1874,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) { /* Fill background with a stipple pattern. */ - cairo_surface_t *bg = create_background_surface (s, x, y, w, h); - - cairo_t *cr = pgtk_begin_cr_clip (s->f); - cairo_set_source_surface (cr, bg, x, y); - cairo_rectangle (cr, x, y, w, h); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - - cairo_surface_destroy (bg); + fill_background (s, x, y, w, h); } else x_clear_glyph_string_rect (s, x, y, w, h); @@ -1975,15 +1948,7 @@ x_draw_image_glyph_string (struct glyph_string *s) { if (s->img->mask) { - cairo_surface_t *bg = create_background_surface (s, s->x, s->y, s->background_width, s->height); - - cairo_t *cr = pgtk_begin_cr_clip (s->f); - cairo_set_source_surface (cr, bg, s->x, s->y); - cairo_rectangle (cr, s->x, s->y, s->background_width, s->height); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - - cairo_surface_destroy (bg); + fill_background (s, s->x, s->y, s->background_width, s->height); } else { @@ -2001,15 +1966,7 @@ x_draw_image_glyph_string (struct glyph_string *s) if (s->slice.y == 0) y += box_line_vwidth; - cairo_surface_t *bg = create_background_surface (s, x, y, width, height); - - cairo_t *cr = pgtk_begin_cr_clip (s->f); - cairo_set_source_surface (cr, bg, x, y); - cairo_rectangle (cr, x, y, width, height); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - - cairo_surface_destroy (bg); + fill_background (s, x, y, width, height); } s->background_filled_p = true; @@ -2111,13 +2068,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s) if (s->face->stipple) { /* Fill background with a stipple pattern. */ - cairo_surface_t *bg = create_background_surface (s, x, y, w, h); - cairo_t *cr = pgtk_begin_cr_clip (s->f); - cairo_set_source_surface (cr, bg, x, y); - cairo_rectangle (cr, x, y, w, h); - cairo_fill (cr); - pgtk_end_cr_clip (s->f); - cairo_surface_destroy (bg); + fill_background (s, x, y, w, h); } else { @@ -3235,13 +3186,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr mono-displays, the fill style may have been changed to FillSolid in x_draw_glyph_string_background. */ if (face->stipple) { - cairo_surface_t *bg = create_background_surface_by_face(f, face, p->bx, p->by, p->nx, p->ny); - cairo_t *cr = pgtk_begin_cr_clip (f); - cairo_set_source_surface (cr, bg, p->bx, p->by); - cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); - cairo_fill (cr); - pgtk_end_cr_clip (f); - cairo_surface_destroy (bg); + fill_background_by_face(f, face, p->bx, p->by, p->nx, p->ny); } else { pgtk_set_cr_source_with_color(f, face->background); cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); @@ -4794,10 +4739,7 @@ pgtk_clear_under_internal_border (struct frame *f) int y = rects[i].y; int w = rects[i].w; int h = rects[i].h; - cairo_surface_t *bg = create_background_surface_by_face (f, face, x, y, w, h); - cairo_set_source_surface (cr, bg, x, y); - cairo_rectangle (cr, x, y, w, h); - cairo_fill (cr); + fill_background_by_face (f, face, x, y, w, h); } } else commit fd61a86ea593fec0fc8967550f515596dc596601 Author: Yuuki Harano Date: Mon Jul 29 21:31:42 2019 +0900 improve some efficiency - simplify draws * src/pgtkterm.h (struct pgtk_bitmap_record): * src/pgtkterm.c (create_background_surface_by_face): * src/image.c (image_create_pattern_from_pixbuf) (image_create_bitmap_from_data, image_create_bitmap_from_file): 少し効率化。 diff --git a/src/image.c b/src/image.c index 0242b50258..0b85cf8634 100644 --- a/src/image.c +++ b/src/image.c @@ -400,6 +400,32 @@ image_reference_bitmap (struct frame *f, ptrdiff_t id) ++FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; } +#ifdef HAVE_PGTK +static cairo_pattern_t * +image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf *pixbuf) +{ + GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); + cairo_surface_t *surface = cairo_surface_create_similar_image (f->output_data.pgtk->cr_surface, + CAIRO_FORMAT_A1, + gdk_pixbuf_get_width (pb), + gdk_pixbuf_get_height (pb)); + + cairo_t *cr = cairo_create (surface); + gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + + cairo_pattern_t *pat = cairo_pattern_create_for_surface (surface); + cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT); + + cairo_surface_destroy (surface); + g_object_unref (pb); + + return pat; +} +#endif + /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */ ptrdiff_t @@ -435,11 +461,39 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #endif #ifdef HAVE_PGTK - Emacs_Pixmap bitmap = image_pix_container_create_from_bitmap_data(f, bits, - width, - height, - 0xffffffff, - 0xff000000); + GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, + FALSE, + 8, + width, + height); + { + char *sp = bits; + int mask = 0x01; + unsigned char *buf = gdk_pixbuf_get_pixels (pixbuf); + int rowstride = gdk_pixbuf_get_rowstride (pixbuf); + for (int y = 0; y < height; y++) { + unsigned char *dp = buf + rowstride * y; + for (int x = 0; x < width; x++) { + if (*sp & mask) { + *dp++ = 0xff; + *dp++ = 0xff; + *dp++ = 0xff; + } else { + *dp++ = 0x00; + *dp++ = 0x00; + *dp++ = 0x00; + } + if ((mask <<= 1) >= 0x100) { + mask = 0x01; + sp++; + } + } + if (mask != 0x01) { + mask = 0x01; + sp++; + } + } + } #endif id = image_allocate_bitmap_record (f); @@ -450,8 +504,9 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #endif #ifdef HAVE_PGTK - dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].img = pixbuf; dpyinfo->bitmaps[id - 1].depth = 1; + dpyinfo->bitmaps[id - 1].pattern = image_create_pattern_from_pixbuf (f, pixbuf); #endif dpyinfo->bitmaps[id - 1].file = NULL; @@ -524,6 +579,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) //dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); + dpyinfo->bitmaps[id - 1].pattern = image_create_pattern_from_pixbuf (f, bitmap); return id; #endif @@ -600,6 +656,8 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) #endif #ifdef HAVE_PGTK + if (bm->pattern != NULL) + cairo_pattern_destroy (bm->pattern); #endif if (bm->file) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 4665a93471..3e8357e774 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -1024,34 +1024,15 @@ create_background_surface_by_face (struct frame *f, struct face *face, int x, in } if (face->stipple != 0) { - GdkPixbuf *pixbuf = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].img; - GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); - cairo_surface_t *mask = cairo_surface_create_similar_image (FRAME_CR_SURFACE (f), - CAIRO_FORMAT_A1, - width, - height); + cairo_pattern_t *mask = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].pattern; - { - cairo_t *cr = cairo_create (mask); - gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); - cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_destroy (cr); - } - - { - cairo_t *cr = cairo_create (surface); - double r = ((face->foreground >> 16) & 0xff) / 255.0; - double g = ((face->foreground >> 8) & 0xff) / 255.0; - double b = ((face->foreground >> 0) & 0xff) / 255.0; - cairo_set_source_rgb (cr, r, g, b); - cairo_mask_surface (cr, mask, 0, 0); - cairo_destroy (cr); - } - - cairo_surface_destroy (mask); - g_object_unref (pb); + cairo_t *cr = cairo_create (surface); + double r = ((face->foreground >> 16) & 0xff) / 255.0; + double g = ((face->foreground >> 8) & 0xff) / 255.0; + double b = ((face->foreground >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_mask (cr, mask); + cairo_destroy (cr); } return surface; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 4c6ef0f6bb..8caf31f8e4 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -54,6 +54,7 @@ struct pgtk_bitmap_record char *file; int refcount; int height, width, depth; + cairo_pattern_t *pattern; }; #define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b)) commit ae3bb140912827c38e7033c07851a94ba710428d Author: Yuuki Harano Date: Fri Jul 26 02:14:13 2019 +0900 implement restacking and cleanup frame z order src/pgtkfns.c: (pgtk_frame_restack, Fpgtk_frame_restack, syms_of_pgtkfns): pgtk-frame-restack を実装だけ。 ついでに、pgtk-frame-list-z-order は無意味なので削除した。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 52fc65694b..88702f1759 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1481,20 +1481,23 @@ pgtk_window_is_ancestor (PGTKWindow *win, PGTKWindow *candidate) } #endif -DEFUN ("pgtk-frame-list-z-order", Fpgtk_frame_list_z_order, - Spgtk_frame_list_z_order, 0, 1, 0, - doc: /* Return list of Emacs' frames, in Z (stacking) order. -If TERMINAL is non-nil and specifies a live frame, return the child -frames of that frame in Z (stacking) order. - -Frames are listed from topmost (first) to bottommost (last). - -On PGTK, this function is identical to frame-list. */) - (Lisp_Object terminal) +/** + * x_frame_restack: + * + * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In + * practice this is a two-step action: The first step removes F1's + * window-system window from the display. The second step reinserts + * F1's window below (above if ABOVE_FLAG is true) that of F2. + */ +static void +pgtk_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) { - return Fframe_list(); + block_input (); + xg_frame_restack (f1, f2, above_flag); + unblock_input (); } + DEFUN ("pgtk-frame-restack", Fpgtk_frame_restack, Spgtk_frame_restack, 2, 3, 0, doc: /* Restack FRAME1 below FRAME2. This means that if both frames are visible and the display areas of @@ -1503,29 +1506,23 @@ third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This means that if both frames are visible and the display areas of these frames overlap, FRAME1 (partially) obscures FRAME2. +This may be thought of as an atomic action performed in two steps: The +first step removes FRAME1's window-step window from the display. The +second step reinserts FRAME1's window below (above if ABOVE is true) +that of FRAME2. Hence the position of FRAME2 in its display's Z +\(stacking) order relative to all other frames excluding FRAME1 remains +unaltered. + Some window managers may refuse to restack windows. */) (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above) { struct frame *f1 = decode_live_frame (frame1); struct frame *f2 = decode_live_frame (frame2); - if (FRAME_PGTK_VIEW (f1) && FRAME_PGTK_VIEW (f2)) - { -#if 0 - PGTKWindow *window = [FRAME_PGTK_VIEW (f1) window]; - NSInteger window2 = [[FRAME_PGTK_VIEW (f2) window] windowNumber]; - PGTKWindowOrderingMode flag = NILP (above) ? PGTKWindowBelow : PGTKWindowAbove; - - [window orderWindow: flag - relativeTo: window2]; -#endif - return Qt; - } - else - { - error ("Cannot restack frames"); - return Qnil; - } + if (! (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))) + error ("Cannot restack frames"); + pgtk_frame_restack (f1, f2, !NILP (above)); + return Qt; } #ifdef HAVE_GSETTINGS @@ -2975,7 +2972,6 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_display_monitor_attributes_list); defsubr (&Spgtk_frame_geometry); defsubr (&Spgtk_frame_edges); - defsubr (&Spgtk_frame_list_z_order); defsubr (&Spgtk_frame_restack); defsubr (&Spgtk_set_mouse_absolute_pixel_position); defsubr (&Spgtk_mouse_absolute_pixel_position); commit fde74fa8b9ac3886ca8370e3aaea562fa8408ced Author: Yuuki Harano Date: Fri Jul 26 01:47:48 2019 +0900 implement pgtk-frame-list-z-order same as frame-list. * src/pgtkfns.c (Fpgtk_frame_list_z_order): return frame list as it's the same diff --git a/src/pgtkfns.c b/src/pgtkfns.c index a8f81761b3..52fc65694b 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1487,30 +1487,12 @@ DEFUN ("pgtk-frame-list-z-order", Fpgtk_frame_list_z_order, If TERMINAL is non-nil and specifies a live frame, return the child frames of that frame in Z (stacking) order. -Frames are listed from topmost (first) to bottommost (last). */) +Frames are listed from topmost (first) to bottommost (last). + +On PGTK, this function is identical to frame-list. */) (Lisp_Object terminal) { - Lisp_Object frames = Qnil; -#if 0 - PGTKWindow *parent = nil; - - if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) - parent = [FRAME_PGTK_VIEW (XFRAME (terminal)) window]; - - for (PGTKWindow *win in [[NSApp orderedWindows] reverseObjectEnumerator]) - { - Lisp_Object frame; - - /* Check against [win parentWindow] so that it doesn't match itself. */ - if (parent == nil || pgtk_window_is_ancestor (parent, [win parentWindow])) - { - XSETFRAME (frame, ((EmacsView *)[win delegate])->emacsframe); - frames = Fcons(frame, frames); - } - } -#endif - - return frames; + return Fframe_list(); } DEFUN ("pgtk-frame-restack", Fpgtk_frame_restack, Spgtk_frame_restack, 2, 3, 0, commit b3a20d7a21795f4e2847938ace6dd454f6b4e870 Author: Yuuki Harano Date: Sun Jul 21 23:11:50 2019 +0900 Implement Scroll-bar-forground and scroll-bar-background * src/pgtkterm.h (struct pgtk_output): * src/pgtkterm.c (x_free_frame_resources): * src/pgtkfns.c (pgtk_set_scroll_bar_foreground) (pgtk_set_scroll_bar_background, pgtk_frame_parm_handlers) (Fx_create_frame): * src/gtkutil.c (xg_finish_scroll_bar_creation):handle scrollbar css values * etc/org.gnu.emacs.defaults.gschema.xml: add scroll bar fields scroll-bar-foreground, scroll-bar-background 実装。 diff --git a/etc/org.gnu.emacs.defaults.gschema.xml b/etc/org.gnu.emacs.defaults.gschema.xml index 6f2c79196e..2d206e63a0 100644 --- a/etc/org.gnu.emacs.defaults.gschema.xml +++ b/etc/org.gnu.emacs.defaults.gschema.xml @@ -35,6 +35,8 @@ '' '' '' + '' + '' '' '' '' diff --git a/src/gtkutil.c b/src/gtkutil.c index 6c2691ecd9..b202aa02e2 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -4054,6 +4054,14 @@ xg_finish_scroll_bar_creation (struct frame *f, /* Set the cursor to an arrow. */ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); +#ifdef HAVE_PGTK + GtkStyleContext *ctxt = gtk_widget_get_style_context(wscroll); + gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); + gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(FRAME_OUTPUT_DATA (f)->scrollbar_background_css_provider), + GTK_STYLE_PROVIDER_PRIORITY_USER); +#endif + bar->x_window = scroll_id; } diff --git a/src/pgtkfns.c b/src/pgtkfns.c index f7edc073a0..a8f81761b3 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -743,6 +743,48 @@ pgtk_set_tool_bar_position (struct frame *f, wrong_choice (choice, new_value); } +static void +pgtk_set_scroll_bar_foreground (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + GtkCssProvider *css_provider = FRAME_X_OUTPUT (f)->scrollbar_foreground_css_provider; + + if (NILP (new_value)) { + gtk_css_provider_load_from_data(css_provider, "", -1, NULL); + } else if (STRINGP (new_value)) { + Emacs_Color rgb; + + if (!pgtk_parse_color (SSDATA (new_value), &rgb)) + error ("Unknown color."); + + char css[64]; + sprintf(css, "scrollbar slider { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); + gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + + } else + error ("Invalid scroll-bar-foreground."); +} + +static void +pgtk_set_scroll_bar_background (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + GtkCssProvider *css_provider = FRAME_X_OUTPUT (f)->scrollbar_background_css_provider; + + if (NILP (new_value)) { + gtk_css_provider_load_from_data(css_provider, "", -1, NULL); + } else if (STRINGP (new_value)) { + Emacs_Color rgb; + + if (!pgtk_parse_color (SSDATA (new_value), &rgb)) + error ("Unknown color."); + + char css[64]; + sprintf(css, "scrollbar trough { background-color: #%06x; }", (unsigned int) rgb.pixel & 0xffffff); + gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + + } else + error ("Invalid scroll-bar-background."); +} + /* Note: see frame.c for template, also where generic functions are impl */ frame_parm_handler pgtk_frame_parm_handlers[] = { @@ -771,8 +813,8 @@ frame_parm_handler pgtk_frame_parm_handlers[] = gui_set_horizontal_scroll_bars, /* generic OK */ gui_set_visibility, /* generic OK */ x_set_tool_bar_lines, - 0, /* x_set_scroll_bar_foreground, will ignore */ - 0, /* x_set_scroll_bar_background, will ignore */ + pgtk_set_scroll_bar_foreground, + pgtk_set_scroll_bar_background, gui_set_screen_gamma, /* generic OK */ gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ gui_set_left_fringe, /* generic OK */ @@ -1043,13 +1085,12 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_X_OUTPUT(f)->icon_bitmap = -1; #endif FRAME_FONTSET (f) = -1; -#if 0 - FRAME_X_OUTPUT(f)->scroll_bar_foreground_pixel = -1; - FRAME_X_OUTPUT(f)->scroll_bar_background_pixel = -1; -#endif FRAME_X_OUTPUT(f)->white_relief.pixel = -1; FRAME_X_OUTPUT(f)->black_relief.pixel = -1; + FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider = gtk_css_provider_new(); + FRAME_X_OUTPUT(f)->scrollbar_background_css_provider = gtk_css_provider_new(); + fset_icon_name (f, gui_display_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING)); @@ -1195,14 +1236,10 @@ This function is an internal primitive--use `make-frame' instead. */) gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); -#if 0 - x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground, - "scrollBarForeground", - "ScrollBarForeground", true); - x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background, - "scrollBarBackground", - "ScrollBarBackground", false); -#endif + gui_default_parameter (f, parms, Qscroll_bar_foreground, Qnil, + "scrollBarForeground", "ScrollBarForeground", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qscroll_bar_background, Qnil, + "scrollBarBackground", "ScrollBarBackground", RES_TYPE_STRING); /* Init faces before gui_default_parameter is called for the scroll-bar-width parameter because otherwise we end up in diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 5890326430..4665a93471 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -194,8 +194,6 @@ x_free_frame_resources (struct frame *f) if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); - gtk_widget_destroy(FRAME_GTK_OUTER_WIDGET(f)); - if (FRAME_X_OUTPUT(f)->border_color_css_provider != NULL) { GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; @@ -203,6 +201,20 @@ x_free_frame_resources (struct frame *f) FRAME_X_OUTPUT(f)->border_color_css_provider = NULL; } + if (FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider != NULL) { + GtkCssProvider *old = FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider; + g_object_unref (old); + FRAME_X_OUTPUT(f)->scrollbar_foreground_css_provider = NULL; + } + + if (FRAME_X_OUTPUT(f)->scrollbar_background_css_provider != NULL) { + GtkCssProvider *old = FRAME_X_OUTPUT(f)->scrollbar_background_css_provider; + g_object_unref (old); + FRAME_X_OUTPUT(f)->scrollbar_background_css_provider = NULL; + } + + gtk_widget_destroy(FRAME_GTK_OUTER_WIDGET(f)); + if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c85a9ea097..4c6ef0f6bb 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -265,6 +265,10 @@ struct pgtk_output unsigned long border_pixel; GtkCssProvider *border_color_css_provider; + /* scrollbar color */ + GtkCssProvider *scrollbar_foreground_css_provider; + GtkCssProvider *scrollbar_background_css_provider; + /* Widget whose cursor is hourglass_cursor. This widget is temporarily mapped to display an hourglass cursor. */ GtkWidget *hourglass_widget; commit bfbcb112484c3521cd9238e1c84aa961c2c89c2f Author: Yuuki Harano Date: Sun Jul 21 01:22:45 2019 +0900 implement set-tool-bar-position and set-sticky * ../src/pgtkfns.c (pgtk_set_tool_bar_position) (pgtk_frame_parm_handlers): tool-bar-position 実装。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 04181825b1..f7edc073a0 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -715,6 +715,34 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old } } +static void +pgtk_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + if (!NILP (new_value)) + gtk_window_stick (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); + else + gtk_window_unstick (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); +} + +static void +pgtk_set_tool_bar_position (struct frame *f, + Lisp_Object new_value, + Lisp_Object old_value) +{ + Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom); + + if (!NILP (Fmemq (new_value, choice))) + { + if (!EQ (new_value, old_value)) + { + xg_change_toolbar_position (f, new_value); + fset_tool_bar_position (f, new_value); + } + } + else + wrong_choice (choice, new_value); +} + /* Note: see frame.c for template, also where generic functions are impl */ frame_parm_handler pgtk_frame_parm_handlers[] = { @@ -743,18 +771,18 @@ frame_parm_handler pgtk_frame_parm_handlers[] = gui_set_horizontal_scroll_bars, /* generic OK */ gui_set_visibility, /* generic OK */ x_set_tool_bar_lines, - 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */ - 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */ + 0, /* x_set_scroll_bar_foreground, will ignore */ + 0, /* x_set_scroll_bar_background, will ignore */ gui_set_screen_gamma, /* generic OK */ gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ gui_set_left_fringe, /* generic OK */ gui_set_right_fringe, /* generic OK */ - 0, /* x_set_wait_for_wm, will ignore */ + 0, /* x_set_wait_for_wm */ gui_set_fullscreen, /* generic OK */ gui_set_font_backend, /* generic OK */ gui_set_alpha, - 0, /* x_set_sticky */ - 0, /* x_set_tool_bar_position */ + pgtk_set_sticky, + pgtk_set_tool_bar_position, 0, /* x_set_inhibit_double_buffering */ x_set_undecorated, 0, /* x_set_parent_frame, */ commit 9d9c8284fe224932f093e972b81e3c36fdce168b Author: Yuuki Harano Date: Fri Jul 19 00:15:52 2019 +0900 TIMERFD support for PGTK, prevent calling when timerfd<0 * ../src/atimer.c (set_alarm): diff --git a/src/atimer.c b/src/atimer.c index a7daf9dcf5..df123e1191 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -309,11 +309,13 @@ set_alarm (void) ispec.it_value = atimers->expiration; ispec.it_interval.tv_sec = ispec.it_interval.tv_nsec = 0; # ifdef HAVE_TIMERFD - if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) - { - add_timer_wait_descriptor (timerfd); - return; - } + if (timerfd >= 0) { + if (timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0) == 0) + { + add_timer_wait_descriptor (timerfd); + return; + } + } # endif if (alarm_timer_ok && timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0) == 0) @@ -461,7 +463,8 @@ turn_on_atimers (bool on) if (alarm_timer_ok) timer_settime (alarm_timer, TIMER_ABSTIME, &ispec, 0); # ifdef HAVE_TIMERFD - timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); + if (timerfd >= 0) + timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0); # endif #endif alarm (0); @@ -568,6 +571,9 @@ have_buggy_timerfd (void) # ifdef CYGWIN struct utsname name; return uname (&name) < 0 || strverscmp (name.release, "3.0.2") < 0; +# elif defined HAVE_PGTK + /* pgtk emacs does not want timerfd. */ + return true; # else return false; # endif commit 6957f9469ca0503088abda4d55df59e26339afa9 Author: Yuuki Harano Date: Thu Jul 18 19:42:02 2019 +0900 Add PGTK support for fullscreen * src/gtkutil.c (x_wm_set_size_hint): Fullscreen support for PGTK fullscreen にできるようにした。 diff --git a/src/gtkutil.c b/src/gtkutil.c index 2da6beb2ca..6c2691ecd9 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1617,17 +1617,18 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) XSETFRAME (frame, f); fs_state = Fframe_parameter (frame, Qfullscreen); + if ((EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) #ifndef HAVE_PGTK - if ((EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) && - (x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state) || - x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state_fullscreen))) + && (x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state) || + x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state_fullscreen)) +#endif + ) { /* Don't set hints when maximized or fullscreen. Apparently KWin and Gtk3 don't get along and the frame shrinks (!). */ return; } -#endif if (flags) { commit 31bba950bc867e43188922a8ef03c2f07c6a784a Author: Yuuki Harano Date: Thu Jul 18 01:07:36 2019 +0900 Use gsettings instead of X resource database * src/pgtkfns.c (pgtk_is_lower_char, pgtk_is_upper_char) (pgtk_is_numeric_char, parse_resource_key) (pgtk_get_defaults_value, pgtk_set_defaults_value) (Fpgtk_set_resource, pgtk_get_string_resource): handle gsettings scheme * m4/gsettings.m4: new file * etc/org.gnu.emacs.defaults.gschema.xml: new file * configure.ac (GLIB_DISABLE_DEPRECATION_WARNINGS) (gsettingsschemadir): * Makefile.in (gsettingsschemadir, GLIB_COMPILE_SCHEMAS) (install, uninstall, clean): * .gitignore: add gschema *.gschema.valid は生成ファイルなので無視。 schema の置き場所を変更。 diff --git a/.gitignore b/.gitignore index bf7e934981..8ac0f483f9 100644 --- a/.gitignore +++ b/.gitignore @@ -298,3 +298,6 @@ nt/emacs.rc nt/emacsclient.rc src/gdb.ini /var/ + +# gsettings schema +/etc/*.gschema.valid diff --git a/Makefile.in b/Makefile.in index fbb1891ba7..984c619344 100644 --- a/Makefile.in +++ b/Makefile.in @@ -216,6 +216,9 @@ icondir=$(datarootdir)/icons # The source directory for the icon files. iconsrcdir=$(srcdir)/etc/images/icons +# Where to install the gsettings schema file. +gsettingsschemadir = @gsettingsschemadir@ + # ==================== Emacs-specific directories ==================== # These variables hold the values Emacs will actually use. They are @@ -300,6 +303,8 @@ LN_S_FILEONLY = @LN_S_FILEONLY@ # We use gzip to compress installed .el and some .txt files. GZIP_PROG = @GZIP_PROG@ +GLIB_COMPILE_SCHEMAS = glib-compile-schemas + # ============================= Targets ============================== # Program name transformation. @@ -330,7 +335,9 @@ CONFIG_STATUS_FILES_IN = \ COPYDIR = ${srcdir}/etc ${srcdir}/lisp COPYDESTS = "$(DESTDIR)${etcdir}" "$(DESTDIR)${lispdir}" -all: ${SUBDIR} info +gsettings_SCHEMAS = etc/org.gnu.emacs.defaults.gschema.xml + +all: ${SUBDIR} info $(gsettings_SCHEMAS:.xml=.valid) .PHONY: all ${SUBDIR} blessmail epaths-force epaths-force-w32 etc-emacsver @@ -468,7 +475,7 @@ $(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/m4/*.m4 ## don't have to duplicate the list of utilities to install in ## this Makefile as well. -install: all install-arch-indep install-etcdoc install-arch-dep install-$(NTDIR) blessmail +install: all install-arch-indep install-etcdoc install-arch-dep install-$(NTDIR) blessmail install-gsettings-schemas @true ## Ensure that $subdir contains a subdirs.el file. @@ -760,7 +767,7 @@ install-strip: ### create (but not the noninstalled files such as 'make all' would create). ### ### Don't delete the lisp and etc directories if they're in the source tree. -uninstall: uninstall-$(NTDIR) uninstall-doc +uninstall: uninstall-$(NTDIR) uninstall-doc uninstall-gsettings-schemas rm -f "$(DESTDIR)$(includedir)/emacs-module.h" $(MAKE) -C lib-src uninstall -unset CDPATH; \ @@ -857,7 +864,7 @@ clean_dirs = $(mostlyclean_dirs) nextstep $(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean))) -clean: $(clean_dirs:=_clean) +clean: $(clean_dirs:=_clean) clean-gsettings-schemas $(MAKE) -C admin/charsets $@ [ ! -d test ] || $(MAKE) -C test $@ -rm -f ./*.tmp etc/*.tmp* @@ -1194,3 +1201,10 @@ gitmerge: ${GITMERGE_EMACS} -batch --no-site-file --no-site-lisp \ -l ${srcdir}/admin/gitmerge.el \ --eval '(setq gitmerge-minimum-missing ${GITMERGE_NMIN})' -f gitmerge + +@GSETTINGS_RULES@ + +install-gsettings-schemas: +uninstall-gsettings-schemas: +clean-gsettings-schemas: +$(gsettings_SCHEMAS:.xml=.valid): diff --git a/configure.ac b/configure.ac index ce9d016847..6d3652d97e 100644 --- a/configure.ac +++ b/configure.ac @@ -2683,6 +2683,9 @@ if test "${opsys}" != "mingw32"; then AC_DEFINE([GLIB_DISABLE_DEPRECATION_WARNINGS], [1], [Define to 1 to disable Glib deprecation warnings.]) fi + if test "$window_system" = pgtk; then + GLIB_GSETTINGS + fi else check_gtk2=yes gtk3_pkg_errors="$GTK_PKG_ERRORS " @@ -5297,6 +5300,7 @@ AC_SUBST(prefix) AC_SUBST(exec_prefix) AC_SUBST(bindir) AC_SUBST(datadir) +AC_SUBST(gsettingsschemadir) AC_SUBST(sharedstatedir) AC_SUBST(libexecdir) AC_SUBST(mandir) diff --git a/etc/org.gnu.emacs.defaults.gschema.xml b/etc/org.gnu.emacs.defaults.gschema.xml new file mode 100644 index 0000000000..6f2c79196e --- /dev/null +++ b/etc/org.gnu.emacs.defaults.gschema.xml @@ -0,0 +1,48 @@ + + + + + + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + + + + diff --git a/m4/gsettings.m4 b/m4/gsettings.m4 new file mode 100644 index 0000000000..882e6a83e7 --- /dev/null +++ b/m4/gsettings.m4 @@ -0,0 +1,88 @@ +# Increment this whenever this file is changed. +#serial 2 + +dnl GLIB_GSETTINGS +dnl Defines GSETTINGS_SCHEMAS_INSTALL which controls whether +dnl the schema should be compiled +dnl + +AC_DEFUN([GLIB_GSETTINGS], +[ + dnl We can't use PKG_PREREQ because that needs 0.29. + m4_ifndef([PKG_PROG_PKG_CONFIG], + [pkg.m4 version 0.28 or later is required]) + + m4_pattern_allow([AM_V_GEN]) + AC_ARG_ENABLE(schemas-compile, + AS_HELP_STRING([--disable-schemas-compile], + [Disable regeneration of gschemas.compiled on install]), + [case ${enableval} in + yes) GSETTINGS_DISABLE_SCHEMAS_COMPILE="" ;; + no) GSETTINGS_DISABLE_SCHEMAS_COMPILE="1" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-schemas-compile]) ;; + esac]) + AC_SUBST([GSETTINGS_DISABLE_SCHEMAS_COMPILE]) + PKG_PROG_PKG_CONFIG([0.16]) + AC_SUBST(gsettingsschemadir, [${datadir}/glib-2.0/schemas]) + AS_IF([test x$cross_compiling != xyes], + [PKG_CHECK_VAR([GLIB_COMPILE_SCHEMAS], [gio-2.0], [glib_compile_schemas])], + [AC_PATH_PROG([GLIB_COMPILE_SCHEMAS], [glib-compile-schemas])]) + AC_SUBST(GLIB_COMPILE_SCHEMAS) + if test "x$GLIB_COMPILE_SCHEMAS" = "x"; then + ifelse([$2],,[AC_MSG_ERROR([glib-compile-schemas not found.])],[$2]) + else + ifelse([$1],,[:],[$1]) + fi + + GSETTINGS_RULES=' +.PHONY : uninstall-gsettings-schemas install-gsettings-schemas clean-gsettings-schemas + +mostlyclean-am: clean-gsettings-schemas + +gsettings__enum_file = $(addsuffix .enums.xml,$(gsettings_ENUM_NAMESPACE)) + +%.gschema.valid: %.gschema.xml $(gsettings__enum_file) + $(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --strict --dry-run $(addprefix --schema-file=,$(gsettings__enum_file)) --schema-file=$< && mkdir -p [$](@D) && touch [$]@ + +all-am: $(gsettings_SCHEMAS:.xml=.valid) +uninstall-am: uninstall-gsettings-schemas +install-data-am: install-gsettings-schemas + +.SECONDARY: $(gsettings_SCHEMAS) + +install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file) + @$(NORMAL_INSTALL) + if test -n "$^"; then \ + test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \ + $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \ + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \ + fi + +uninstall-gsettings-schemas: + @$(NORMAL_UNINSTALL) + @list='\''$(gsettings_SCHEMAS) $(gsettings__enum_file)'\''; test -n "$(gsettingsschemadir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e '\''s|^.*/||'\''`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '\''$(DESTDIR)$(gsettingsschemadir)'\'' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(gsettingsschemadir)" && rm -f $$files + test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir) + +clean-gsettings-schemas: + rm -f $(gsettings_SCHEMAS:.xml=.valid) $(gsettings__enum_file) + +ifdef gsettings_ENUM_NAMESPACE +$(gsettings__enum_file): $(gsettings_ENUM_FILES) + $(AM_V_GEN) glib-mkenums --comments '\'''\'' --fhead "" --vhead " <@type@ id='\''$(gsettings_ENUM_NAMESPACE).@EnumName@'\''>" --vprod " " --vtail " " --ftail "" [$]^ > [$]@.tmp && mv [$]@.tmp [$]@ +endif +' + _GSETTINGS_SUBST(GSETTINGS_RULES) +]) + +dnl _GSETTINGS_SUBST(VARIABLE) +dnl Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +AC_DEFUN([_GSETTINGS_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 845c2c6f33..04181825b1 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1471,7 +1471,6 @@ Some window managers may refuse to restack windows. */) [window orderWindow: flag relativeTo: window2]; - #endif return Qt; } @@ -1482,22 +1481,211 @@ Some window managers may refuse to restack windows. */) } } +#ifdef HAVE_GSETTINGS + +#define RESOURCE_KEY_MAX_LEN 128 +#define SCHEMA_ID "org.gnu.emacs.defaults" +#define PATH_FOR_CLASS_TYPE "/org/gnu/emacs/defaults-by-class/" +#define PATH_PREFIX_FOR_NAME_TYPE "/org/gnu/emacs/defaults-by-name/" + +static inline int +pgtk_is_lower_char (int c) +{ + return c >= 'a' && c <= 'z'; +} + +static inline int +pgtk_is_upper_char (int c) +{ + return c >= 'A' && c <= 'Z'; +} + +static inline int +pgtk_is_numeric_char (int c) +{ + return c >= '0' && c <= '9'; +} + +static GSettings * +parse_resource_key (const char *res_key, char *setting_key) +{ + char path[32 + RESOURCE_KEY_MAX_LEN]; + const char *sp = res_key; + char *dp; + + /* + * res_key="emacs.cursorBlink" + * -> path="/org/gnu/emacs/defaults-by-name/emacs/" + * setting_key="cursor-blink" + * + * res_key="Emacs.CursorBlink" + * -> path="/org/gnu/emacs/defaults-by-class/" + * setting_key="cursor-blink" + * + * Returns GSettings* if setting_key exists in schema, otherwise NULL. + */ + + /* generate path */ + if (pgtk_is_upper_char(*sp)) { + /* First letter is upper case. It should be "Emacs", + * but don't care. + */ + strcpy (path, PATH_FOR_CLASS_TYPE); + while (*sp != '\0') { + if (*sp == '.') + break; + sp++; + } + } else { + strcpy (path, PATH_PREFIX_FOR_NAME_TYPE); + dp = path + strlen (path); + while (*sp != '\0') { + int c = *sp; + if (c == '.') + break; + if (pgtk_is_lower_char (c)) + (void) 0; /* lower -> NOP */ + else if (pgtk_is_upper_char (c)) + c = c - 'A' + 'a'; /* upper -> lower */ + else if (pgtk_is_numeric_char (c)) + (void) 0; /* numeric -> NOP */ + else + return NULL; /* invalid */ + *dp++ = c; + sp++; + } + *dp++ = '/'; /* must ends with '/' */ + *dp = '\0'; + } + + if (*sp++ != '.') + return NULL; + + /* generate setting_key */ + dp = setting_key; + while (*sp != '\0') { + int c = *sp; + if (pgtk_is_lower_char (c)) + (void) 0; /* lower -> NOP */ + else if (pgtk_is_upper_char (c)) { + c = c - 'A' + 'a'; /* upper -> lower */ + if (dp != setting_key) + *dp++ = '-'; /* store '-' unless first char */ + } else if (pgtk_is_numeric_char (c)) + (void) 0; /* numeric -> NOP */ + else + return NULL; /* invalid */ + + *dp++ = c; + sp++; + } + *dp = '\0'; + + /* check existence of setting_key */ + GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default (); + GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, FALSE); + if (!g_settings_schema_has_key (scm, setting_key)) { + g_settings_schema_unref (scm); + return NULL; + } + + /* create GSettings, and return it */ + GSettings *gs = g_settings_new_full (scm, NULL, path); + + g_settings_schema_unref (scm); + return gs; +} + +const char * +pgtk_get_defaults_value (const char *key) +{ + char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2]; + + if (strlen (key) >= RESOURCE_KEY_MAX_LEN) + error ("resource key too long."); + + GSettings *gs = parse_resource_key(key, skey); + if (gs == NULL) { + return NULL; + } + + gchar *str = g_settings_get_string (gs, skey); + + /* There is no timing to free str. + * So, copy it here and free it. + * + * MEMO: Resource values for emacs shouldn't need such a long string value. + */ + static char holder[128]; + strncpy (holder, str, 128); + holder[127] = '\0'; + + g_object_unref (gs); + g_free (str); + return holder[0] != '\0' ? holder : NULL; +} + +static void +pgtk_set_defaults_value (const char *key, const char *value) +{ + char skey[(RESOURCE_KEY_MAX_LEN + 1) * 2]; + + if (strlen (key) >= RESOURCE_KEY_MAX_LEN) + error ("resource key too long."); + + GSettings *gs = parse_resource_key(key, skey); + if (gs == NULL) { + error ("unknown resource key."); + } + if (value != NULL) { + g_settings_set_string (gs, skey, value); + } else { + g_settings_reset (gs, skey); + } + + g_object_unref (gs); +} + +#undef RESOURCE_KEY_MAX_LEN +#undef SCHEMA_ID +#undef PATH_FOR_CLASS_TYPE +#undef PATH_PREFIX_FOR_NAME_TYPE + +#else /* not HAVE_GSETTINGS */ + const char * pgtk_get_defaults_value (const char *key) { return NULL; } -DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 3, 3, 0, - doc: /* Set property NAME of OWNER to VALUE, from the defaults database. -If OWNER is nil, Emacs is assumed. -If VALUE is nil, the default is removed. */) - (Lisp_Object owner, Lisp_Object name, Lisp_Object value) +static void +pgtk_set_defaults_value (const char *key, const char *value) +{ + error ("gsettings not supported."); +} + +#endif + + +DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 2, 2, 0, + doc: /* Set the value of ATTRIBUTE, of class CLASS, as VALUE, into defaults database. */) + (Lisp_Object attribute, Lisp_Object value) { check_window_system (NULL); - if (NILP (owner)) - owner = build_string (pgtk_app_name); - CHECK_STRING (name); + + CHECK_STRING (attribute); + if (!NILP (value)) + CHECK_STRING (value); + + char *res = SSDATA (Vx_resource_name); + char *attr = SSDATA (attribute); + if (attr[0] >= 'A' && attr[0] <= 'Z') + res = SSDATA (Vx_resource_class); + + char *key = g_strdup_printf("%s.%s", res, attr); + + pgtk_set_defaults_value(key, NILP (value) ? NULL : SSDATA (value)); return Qnil; } @@ -1794,20 +1982,26 @@ pgtk_set_scroll_bar_default_height (struct frame *f) const char * pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class) { - /* remove appname prefix; TODO: allow for !="Emacs" */ - const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0); - check_window_system (NULL); if (inhibit_x_resources) /* --quick was passed, so this is a no-op. */ return NULL; - res = pgtk_get_defaults_value (toCheck); - return (char *) (!res ? NULL - : !c_strncasecmp (res, "YES", 3) ? "true" - : !c_strncasecmp (res, "NO", 2) ? "false" - : res); + const char *res = pgtk_get_defaults_value (name); + if (res == NULL) + res = pgtk_get_defaults_value (class); + + if (res == NULL) + return NULL; + + if (c_strncasecmp (res, "YES", 3) == 0) + return "true"; + + if (c_strncasecmp (res, "NO", 2) == 0) + return "false"; + + return res; } commit 519a4ac39f7cd9e2339b203463704db48752bc5b Author: Yuuki Harano Date: Wed Jul 10 02:32:35 2019 +0900 Implement Meta key detection * ../src/pgtkterm.c (x_find_modifier_meanings, ) (key_press_event, construct_mouse_click, scroll_event) (pgtk_term_init): * src/pgtkterm.h (struct pgtk_display_info): * ../src/gtkutil.c (xg_tool_bar_callback): meta キーの検出を実装。 X11 で alt キーを meta キーとして使えなくなっていたのを修正。 diff --git a/src/gtkutil.c b/src/gtkutil.c index 9655c8dfc1..2da6beb2ca 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -4693,7 +4693,7 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data) #ifndef HAVE_PGTK event.modifiers = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), mod); #else - event.modifiers = pgtk_gtk_to_emacs_modifiers (mod); + event.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), mod); #endif kbd_buffer_store_event (&event); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 2e98dedbc7..5890326430 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4895,64 +4895,100 @@ static void size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer *use } } -int -pgtk_gtk_to_emacs_modifiers (int state) +static void +x_find_modifier_meanings (struct pgtk_display_info *dpyinfo) +{ + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkKeymap *keymap = gdk_keymap_get_for_display (gdpy); + GdkModifierType state = GDK_META_MASK; + gboolean r = gdk_keymap_map_virtual_modifiers (keymap, &state); + if (r) { + /* Meta key exists. */ + if (state == GDK_META_MASK) { + dpyinfo->meta_mod_mask = GDK_MOD1_MASK; /* maybe this is meta. */ + dpyinfo->alt_mod_mask = 0; + } else { + dpyinfo->meta_mod_mask = state & ~GDK_META_MASK; + if (dpyinfo->meta_mod_mask == GDK_MOD1_MASK) + dpyinfo->alt_mod_mask = 0; + else + dpyinfo->alt_mod_mask = GDK_MOD1_MASK; + } + } else { + dpyinfo->meta_mod_mask = GDK_MOD1_MASK; + dpyinfo->alt_mod_mask = 0; + } +} + +static void get_modifier_values( + int *mod_ctrl, + int *mod_meta, + int *mod_alt, + int *mod_hyper, + int *mod_super) { - int mod_ctrl = ctrl_modifier; - int mod_meta = meta_modifier; - int mod_alt = alt_modifier; - int mod_hyper = hyper_modifier; - int mod_super = super_modifier; Lisp_Object tem; + *mod_ctrl = ctrl_modifier; + *mod_meta = meta_modifier; + *mod_alt = alt_modifier; + *mod_hyper = hyper_modifier; + *mod_super = super_modifier; + tem = Fget (Vx_ctrl_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) *mod_ctrl = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_alt_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) *mod_alt = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_meta_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) *mod_meta = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_hyper_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX; + if (INTEGERP (tem)) *mod_hyper = XFIXNUM (tem) & INT_MAX; tem = Fget (Vx_super_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_super = XFIXNUM (tem) & INT_MAX; - - return ( ((state & GDK_SHIFT_MASK) ? shift_modifier : 0) - | ((state & GDK_CONTROL_MASK) ? mod_ctrl : 0) - | ((state & GDK_META_MASK) ? mod_meta : 0) - | ((state & GDK_MOD1_MASK) ? mod_alt : 0) - | ((state & GDK_SUPER_MASK) ? mod_super : 0) - | ((state & GDK_HYPER_MASK) ? mod_hyper : 0)); + if (INTEGERP (tem)) *mod_super = XFIXNUM (tem) & INT_MAX; } -static int -pgtk_emacs_to_gtk_modifiers (EMACS_INT state) +int +pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state) { - EMACS_INT mod_ctrl = ctrl_modifier; - EMACS_INT mod_meta = meta_modifier; - EMACS_INT mod_alt = alt_modifier; - EMACS_INT mod_hyper = hyper_modifier; - EMACS_INT mod_super = super_modifier; + int mod_ctrl; + int mod_meta; + int mod_alt; + int mod_hyper; + int mod_super; + int mod; - Lisp_Object tem; + get_modifier_values(&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, &mod_super); - tem = Fget (Vx_ctrl_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_ctrl = XFIXNUM (tem); - tem = Fget (Vx_alt_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_alt = XFIXNUM (tem); - tem = Fget (Vx_meta_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_meta = XFIXNUM (tem); - tem = Fget (Vx_hyper_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_hyper = XFIXNUM (tem); - tem = Fget (Vx_super_keysym, Qmodifier_value); - if (INTEGERP (tem)) mod_super = XFIXNUM (tem); + mod = 0; + if (state & GDK_SHIFT_MASK) mod |= shift_modifier; + if (state & GDK_CONTROL_MASK) mod |= mod_ctrl; + if (state & dpyinfo->meta_mod_mask) mod |= mod_meta; + if (state & dpyinfo->alt_mod_mask) mod |= mod_alt; + if (state & GDK_SUPER_MASK) mod |= mod_super; + if (state & GDK_HYPER_MASK) mod |= mod_hyper; + return mod; +} + +static int +pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *dpyinfo, int state) +{ + int mod_ctrl; + int mod_meta; + int mod_alt; + int mod_hyper; + int mod_super; + int mask; + get_modifier_values(&mod_ctrl, &mod_meta, &mod_alt, &mod_hyper, &mod_super); - return ( ((state & mod_alt) ? GDK_MOD1_MASK : 0) - | ((state & mod_super) ? GDK_SUPER_MASK : 0) - | ((state & mod_hyper) ? GDK_HYPER_MASK : 0) - | ((state & shift_modifier) ? GDK_SHIFT_MASK : 0) - | ((state & mod_ctrl) ? GDK_CONTROL_MASK : 0) - | ((state & mod_meta) ? GDK_META_MASK : 0)); + mask = 0; + if (state & mod_alt) mask |= dpyinfo->alt_mod_mask; + if (state & mod_super) mask |= GDK_SUPER_MASK; + if (state & mod_hyper) mask |= GDK_HYPER_MASK; + if (state & shift_modifier) mask |= GDK_SHIFT_MASK; + if (state & mod_ctrl) mask |= GDK_CONTROL_MASK; + if (state & mod_meta) mask |= dpyinfo->meta_mod_mask; + return mask; } #define IsCursorKey(keysym) (0xff50 <= (keysym) && (keysym) < 0xff60) @@ -5008,7 +5044,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us Lisp_Object c; guint state = event->key.state; - state |= pgtk_emacs_to_gtk_modifiers (extra_keyboard_modifiers); + state |= pgtk_emacs_to_gtk_modifiers (FRAME_DISPLAY_INFO (f), extra_keyboard_modifiers); modifiers = state; /* This will have to go some day... */ @@ -5031,7 +5067,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *us /* Common for all keysym input events. */ XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (modifiers); + inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers); inev.ie.timestamp = event->key.time; /* First deal with keysyms which have defined @@ -5680,7 +5716,7 @@ construct_mouse_click (struct input_event *result, result->kind = MOUSE_CLICK_EVENT; result->code = event->button - 1; result->timestamp = event->time; - result->modifiers = (pgtk_gtk_to_emacs_modifiers (event->state) + result->modifiers = (pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->state) | (event->type == GDK_BUTTON_RELEASE ? up_modifier : down_modifier)); @@ -5817,7 +5853,7 @@ scroll_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) inev.ie.kind = WHEEL_EVENT; inev.ie.timestamp = event->scroll.time; - inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (event->scroll.state); + inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state); XSETINT (inev.ie.x, event->scroll.x); XSETINT (inev.ie.y, event->scroll.y); XSETFRAME (inev.ie.frame_or_window, f); @@ -6158,10 +6194,8 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) *nametail++ = '@'; lispstpcpy (nametail, system_name); -#if 0 /* Figure out which modifier bits mean what. */ x_find_modifier_meanings (dpyinfo); -#endif /* Get the scroll bar cursor. */ /* We must create a GTK cursor, it is required for GTK widgets. */ diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 3222bb2597..c85a9ea097 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -222,6 +222,9 @@ struct pgtk_display_info /* The frame where the mouse was last time we reported a mouse position. */ struct frame *last_mouse_glyph_frame; + + /* Modifier masks in gdk */ + int meta_mod_mask, alt_mod_mask; }; /* This is a chain of structures for all the PGTK displays currently in use. */ @@ -529,7 +532,7 @@ extern int pgtk_lisp_to_color (Lisp_Object color, Emacs_Color *col); /* Implemented in pgtkterm.c */ extern void pgtk_clear_area (struct frame *f, int x, int y, int width, int height); -extern int pgtk_gtk_to_emacs_modifiers (int state); +extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, int state); extern void pgtk_clear_under_internal_border (struct frame *f); extern void pgtk_set_event_handler(struct frame *f); commit 68b99a3e6615a7f3eb21dbd72b0b796960831a5e Author: Yuuki Harano Date: Mon Jul 8 01:56:21 2019 +0900 Implement invisible-pointer to create blinking effect * src/pgtkterm.h (struct pgtk_display_info): add cursor and callback * src/pgtkterm.c (x_setup_pointer_blanking) (XTtoggle_invisible_pointer, x_toggle_visible_pointer): new functions (pgtk_create_terminal, pgtk_term_init): use gdkcursor * src/pgtkgui.h: define Emacs_cursor as a GdkCursor invisible pointer 実装。 diff --git a/src/pgtkgui.h b/src/pgtkgui.h index e7e614ea1f..be9fb25bfe 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -43,7 +43,7 @@ typedef unichar XChar2b; (*(chp) & 0x00ff) -typedef void *Emacs_Cursor; +typedef struct _GdkCursor *Emacs_Cursor; typedef void * Color; typedef int Window; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 6d0dc9695a..2e98dedbc7 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4527,6 +4527,36 @@ XTframe_rehighlight (struct frame *frame) pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame)); } + +/* Toggle mouse pointer visibility on frame F by using invisible cursor. */ + +static void +x_toggle_visible_pointer (struct frame *f, bool invisible) +{ + Emacs_Cursor cursor; + if (invisible) + cursor = FRAME_DISPLAY_INFO (f)->invisible_cursor; + else + cursor = f->output_data.pgtk->current_cursor; + gdk_window_set_cursor(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), cursor); + f->pointer_invisible = invisible; +} + +static void +x_setup_pointer_blanking (struct pgtk_display_info *dpyinfo) +{ + dpyinfo->toggle_visible_pointer = x_toggle_visible_pointer; + dpyinfo->invisible_cursor = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_BLANK_CURSOR); +} + +static void +XTtoggle_invisible_pointer (struct frame *f, bool invisible) +{ + block_input (); + FRAME_DISPLAY_INFO (f)->toggle_visible_pointer (f, invisible); + unblock_input (); +} + /* The focus has changed. Update the frames as necessary to reflect the new situation. Note that we can't change the selected frame here, because the Lisp code we are interrupting might become confused. @@ -4570,6 +4600,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->clear_frame_hook = pgtk_clear_frame; terminal->ring_bell_hook = pgtk_ring_bell; + terminal->toggle_invisible_pointer_hook = XTtoggle_invisible_pointer; terminal->update_begin_hook = pgtk_update_begin; terminal->update_end_hook = pgtk_update_end; terminal->read_socket_hook = pgtk_read_socket; @@ -6136,13 +6167,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) /* We must create a GTK cursor, it is required for GTK widgets. */ dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy); -#if 0 dpyinfo->vertical_scroll_bar_cursor - = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow); + = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_SB_V_DOUBLE_ARROW); dpyinfo->horizontal_scroll_bar_cursor - = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow); -#endif + = gdk_cursor_new_for_display(dpyinfo->gdpy, GDK_SB_H_DOUBLE_ARROW); reset_mouse_highlight (&dpyinfo->mouse_highlight); @@ -6153,9 +6182,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->resy = dpi; } -#if 0 x_setup_pointer_blanking (dpyinfo); -#endif xsettings_initialize (dpyinfo); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c48b1b3e00..3222bb2597 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -209,6 +209,13 @@ struct pgtk_display_info /* The scroll bar in which the last motion event occurred. */ void *last_mouse_scroll_bar; + /* The invisible cursor used for pointer blanking. + Unused if this display supports Xfixes extension. */ + Emacs_Cursor invisible_cursor; + + /* Function used to toggle pointer visibility on this display. */ + void (*toggle_visible_pointer) (struct frame *, bool); + /* The GDK cursor for scroll bars and popup menus. */ GdkCursor *xg_cursor; commit ea3ecd320c441675e83f2325785bbb600711f3ac Author: Yuuki Harano Date: Fri Jul 26 23:55:03 2019 +0900 init border_pixel. * ../src/pgtkfns.c (Fx_create_frame): remove if preprocessor diff --git a/src/pgtkfns.c b/src/pgtkfns.c index a9293c5bbb..845c2c6f33 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1045,9 +1045,7 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_BACKGROUND_PIXEL (f) = -1; FRAME_X_OUTPUT(f)->cursor_color = -1; FRAME_X_OUTPUT(f)->cursor_foreground_color = -1; -#if 0 FRAME_X_OUTPUT(f)->border_pixel = -1; -#endif FRAME_X_OUTPUT(f)->mouse_color = -1; black = build_string ("black"); @@ -1059,10 +1057,8 @@ This function is an internal primitive--use `make-frame' instead. */) = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); FRAME_X_OUTPUT(f)->cursor_foreground_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); -#if 0 FRAME_X_OUTPUT(f)->border_pixel = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); -#endif FRAME_X_OUTPUT(f)->mouse_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); } commit da3c3518ed1ca12fad4a6b2a76d286056a4a3a87 Author: Yuuki Harano Date: Sun Jul 7 22:43:59 2019 +0900 border_color/pixel width * src/pgtkterm.h (struct pgtk_output): * src/pgtkterm.c (x_free_frame_resources, frame_highlight) (frame_unhighlight, pgtk_frame_rehighlight): use css information * src/pgtkfns.c (x_set_border_color, pgtk_frame_parm_handlers) (Fx_create_frame): new functions connected * src/frame.c (gui_set_border_width): ifdef for PGTK border_color/pixel 対応。 diff --git a/src/frame.c b/src/frame.c index 2c549a1d4d..82735491d0 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4643,8 +4643,10 @@ gui_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (border_width == f->border_width) return; +#ifndef HAVE_PGTK if (FRAME_NATIVE_WINDOW (f) != 0) error ("Cannot change the border width of a frame"); +#endif f->border_width = border_width; } diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 3f31c086f2..a9293c5bbb 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -48,6 +48,7 @@ static int as_status; static ptrdiff_t image_cache_refcount; +static int x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color); static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); static void pgtk_set_name_as_filename (struct frame *); @@ -193,6 +194,16 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) unblock_input (); } +static void +x_set_border_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int pix; + + CHECK_STRING (arg); + pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + FRAME_X_OUTPUT(f)->border_pixel = pix; + pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (f)); +} static void x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) @@ -710,8 +721,8 @@ frame_parm_handler pgtk_frame_parm_handlers[] = gui_set_autoraise, /* generic OK */ gui_set_autolower, /* generic OK */ x_set_background_color, - 0, /* x_set_border_color, may be impossible under Nextstep */ - 0, /* x_set_border_width, may be impossible under Nextstep */ + x_set_border_color, + gui_set_border_width, x_set_cursor_color, x_set_cursor_type, gui_set_font, /* generic OK */ @@ -1382,6 +1393,8 @@ This function is an internal primitive--use `make-frame' instead. */) if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) fset_param_alist (f, Fcons (XCAR (tem), f->param_alist)); + FRAME_X_OUTPUT(f)->border_color_css_provider = NULL; + FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 56a05dac9b..6d0dc9695a 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -196,6 +196,13 @@ x_free_frame_resources (struct frame *f) gtk_widget_destroy(FRAME_GTK_OUTER_WIDGET(f)); + if (FRAME_X_OUTPUT(f)->border_color_css_provider != NULL) { + GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); + GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; + gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); + FRAME_X_OUTPUT(f)->border_color_css_provider = NULL; + } + if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; @@ -4432,12 +4439,20 @@ frame_highlight (struct frame *f) the window-manager in use, tho something more is at play since I've been using that same window-manager binary for ever. Let's not crash just because of this (bug#9310). */ -#if 0 - x_catch_errors (FRAME_X_DISPLAY (f)); - XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_X_OUTPUT(f)->border_pixel); - x_uncatch_errors (); -#endif + + char *css = g_strdup_printf("decoration { border: solid %dpx #%06x; }", f->border_width, (unsigned int) FRAME_X_OUTPUT(f)->border_pixel & 0x00ffffff); + GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); + GtkCssProvider *css_provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + g_object_unref(css_provider); + g_free(css); + + GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; + FRAME_X_OUTPUT(f)->border_color_css_provider = css_provider; + if (old != NULL) + gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); + unblock_input (); gui_update_cursor (f, true); x_set_frame_alpha (f); @@ -4452,19 +4467,27 @@ frame_unhighlight (struct frame *f) client", so we can always change it to whatever we want. */ block_input (); /* Same as above for XSetWindowBorder (bug#9310). */ -#if 0 - x_catch_errors (FRAME_X_DISPLAY (f)); - XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_X_OUTPUT(f)->border_tile); - x_uncatch_errors (); -#endif + + char *css = g_strdup_printf("decoration { border: dotted %dpx #ffffff; }", f->border_width); + GtkStyleContext *ctxt = gtk_widget_get_style_context(FRAME_GTK_OUTER_WIDGET(f)); + GtkCssProvider *css_provider = gtk_css_provider_new(); + gtk_css_provider_load_from_data(css_provider, css, -1, NULL); + gtk_style_context_add_provider(ctxt, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER); + g_object_unref(css_provider); + g_free(css); + + GtkCssProvider *old = FRAME_X_OUTPUT(f)->border_color_css_provider; + FRAME_X_OUTPUT(f)->border_color_css_provider = css_provider; + if (old != NULL) + gtk_style_context_remove_provider(ctxt, GTK_STYLE_PROVIDER(old)); + unblock_input (); gui_update_cursor (f, true); x_set_frame_alpha (f); } -static void +void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo) { struct frame *old_highlight = dpyinfo->highlight_frame; @@ -4484,13 +4507,10 @@ pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo) else dpyinfo->highlight_frame = 0; - if (dpyinfo->highlight_frame != old_highlight) - { - if (old_highlight) - frame_unhighlight (old_highlight); - if (dpyinfo->highlight_frame) - frame_highlight (dpyinfo->highlight_frame); - } + if (old_highlight) + frame_unhighlight (old_highlight); + if (dpyinfo->highlight_frame) + frame_highlight (dpyinfo->highlight_frame); } /* The focus has changed, or we have redirected a frame's focus to diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 91990b203b..c48b1b3e00 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -251,6 +251,10 @@ struct pgtk_output /* PGTK-specific */ Emacs_Cursor current_pointer; + /* border color */ + unsigned long border_pixel; + GtkCssProvider *border_color_css_provider; + /* Widget whose cursor is hourglass_cursor. This widget is temporarily mapped to display an hourglass cursor. */ GtkWidget *hourglass_widget; commit 19da22ed25753d0e90b9cbc2c79b37d0aae67712 Author: Yuuki Harano Date: Sun Jul 7 03:15:20 2019 +0900 Add support for handing the internal border src/pgtkterm.c (pgtk_clear_under_internal_border): remove #if 0 src/pgtkfns.c (x_set_internal_border_width): add clear and fill support internal-border 対応。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index b726d1bcaf..3f31c086f2 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -549,7 +549,6 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) static void x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { -#if 0 int old_width = FRAME_INTERNAL_BORDER_WIDTH (f); CHECK_TYPE_RANGED_INTEGER (int, arg); @@ -564,7 +563,6 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width); SET_FRAME_GARBAGED (f); -#endif } diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1c2f0c9648..56a05dac9b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4734,19 +4734,32 @@ pgtk_clear_under_internal_border (struct frame *f) block_input (); + struct { + int x, y, w, h; + } rects[] = { + { 0, margin, width, border }, + { 0, 0, border, height }, + { width - border, 0, border, height }, + { 0, height - border, width, border }, + }; + if (face) { - pgtk_fill_rectangle (f, color, 0, margin, width, border); - pgtk_fill_rectangle (f, color, 0, 0, border, height); - pgtk_fill_rectangle (f, color, width - border, 0, border, height); - pgtk_fill_rectangle (f, color, 0, height - border, width, border); + for (int i = 0; i < 4; i++) { + int x = rects[i].x; + int y = rects[i].y; + int w = rects[i].w; + int h = rects[i].h; + cairo_surface_t *bg = create_background_surface_by_face (f, face, x, y, w, h); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + } } else { - pgtk_clear_area (f, 0, 0, border, height); - pgtk_clear_area (f, 0, margin, width, border); - pgtk_clear_area (f, width - border, 0, border, height); - pgtk_clear_area (f, 0, height - border, width, border); + for (int i = 0; i < 4; i++) + pgtk_clear_area (f, rects[i].x, rects[i].y, rects[i].w, rects[i].h); } unblock_input (); commit fbba846ee8d63304385b59e8f6a553398b533345 Author: Yuuki Harano Date: Sun Jul 7 02:24:14 2019 +0900 Addframe highlighting support * ../src/pgtkterm.c: (pgtk_focus_frame, set_opacity_recursively, x_set_frame_alpha) (frame_highlight, frame_unhighlight, pgtk_frame_rehighlight) (XTframe_rehighlight, x_new_focus_frame, pgtk_create_terminal): frame の highlight に対応。 とりあえず opacity のみ対応。 diff --git a/src/pgtkterm.c b/src/pgtkterm.c index fb2520614f..1c2f0c9648 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4351,6 +4351,190 @@ pgtk_free_pixmap (struct frame *_f, Emacs_Pixmap pixmap) } } +void +pgtk_focus_frame (struct frame *f, bool noactivate) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + + GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); + + if (dpyinfo->x_focus_frame != f) + { + block_input (); + gtk_window_present (GTK_WINDOW (wid)); + unblock_input (); + } +} + + +static void set_opacity_recursively (GtkWidget *w, gpointer data) +{ + gtk_widget_set_opacity (w, *(double *) data); + if (GTK_IS_CONTAINER (w)) + gtk_container_foreach (GTK_CONTAINER (w), set_opacity_recursively, data); +} + +static void +x_set_frame_alpha (struct frame *f) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + double alpha = 1.0; + double alpha_min = 1.0; + + if (dpyinfo->highlight_frame == f) + alpha = f->alpha[0]; + else + alpha = f->alpha[1]; + + if (alpha < 0.0) + return; + + if (FLOATP (Vframe_alpha_lower_limit)) + alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit); + else if (FIXNUMP (Vframe_alpha_lower_limit)) + alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0; + + if (alpha > 1.0) + alpha = 1.0; + else if (alpha < alpha_min && alpha_min <= 1.0) + alpha = alpha_min; + +#if 0 + /* If there is a parent from the window manager, put the property there + also, to work around broken window managers that fail to do that. + Do this unconditionally as this function is called on reparent when + alpha has not changed on the frame. */ + + if (!FRAME_PARENT_FRAME (f)) + { + Window parent = x_find_topmost_parent (f); + if (parent != None) + XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &opac, 1); + } +#endif + + set_opacity_recursively (FRAME_GTK_OUTER_WIDGET (f), &alpha); + /* without this, blending mode is strange on wayland. */ + gtk_widget_queue_resize_no_redraw (FRAME_GTK_OUTER_WIDGET (f)); +} + +static void +frame_highlight (struct frame *f) +{ + /* We used to only do this if Vx_no_window_manager was non-nil, but + the ICCCM (section 4.1.6) says that the window's border pixmap + and border pixel are window attributes which are "private to the + client", so we can always change it to whatever we want. */ + block_input (); + /* I recently started to get errors in this XSetWindowBorder, depending on + the window-manager in use, tho something more is at play since I've been + using that same window-manager binary for ever. Let's not crash just + because of this (bug#9310). */ +#if 0 + x_catch_errors (FRAME_X_DISPLAY (f)); + XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_X_OUTPUT(f)->border_pixel); + x_uncatch_errors (); +#endif + unblock_input (); + gui_update_cursor (f, true); + x_set_frame_alpha (f); +} + +static void +frame_unhighlight (struct frame *f) +{ + /* We used to only do this if Vx_no_window_manager was non-nil, but + the ICCCM (section 4.1.6) says that the window's border pixmap + and border pixel are window attributes which are "private to the + client", so we can always change it to whatever we want. */ + block_input (); + /* Same as above for XSetWindowBorder (bug#9310). */ +#if 0 + x_catch_errors (FRAME_X_DISPLAY (f)); + XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_X_OUTPUT(f)->border_tile); + x_uncatch_errors (); +#endif + unblock_input (); + gui_update_cursor (f, true); + x_set_frame_alpha (f); +} + + +static void +pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo) +{ + struct frame *old_highlight = dpyinfo->highlight_frame; + + if (dpyinfo->x_focus_frame) + { + dpyinfo->highlight_frame + = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) + ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) + : dpyinfo->x_focus_frame); + if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) + { + fset_focus_frame (dpyinfo->x_focus_frame, Qnil); + dpyinfo->highlight_frame = dpyinfo->x_focus_frame; + } + } + else + dpyinfo->highlight_frame = 0; + + if (dpyinfo->highlight_frame != old_highlight) + { + if (old_highlight) + frame_unhighlight (old_highlight); + if (dpyinfo->highlight_frame) + frame_highlight (dpyinfo->highlight_frame); + } +} + +/* The focus has changed, or we have redirected a frame's focus to + another frame (this happens when a frame uses a surrogate + mini-buffer frame). Shift the highlight as appropriate. + + The FRAME argument doesn't necessarily have anything to do with which + frame is being highlighted or un-highlighted; we only use it to find + the appropriate X display info. */ + +static void +XTframe_rehighlight (struct frame *frame) +{ + pgtk_frame_rehighlight (FRAME_DISPLAY_INFO (frame)); +} + +/* The focus has changed. Update the frames as necessary to reflect + the new situation. Note that we can't change the selected frame + here, because the Lisp code we are interrupting might become confused. + Each event gets marked with the frame in which it occurred, so the + Lisp code can tell when the switch took place by examining the events. */ + +static void +x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) +{ + struct frame *old_focus = dpyinfo->x_focus_frame; + /* doesn't work on wayland */ + + if (frame != dpyinfo->x_focus_frame) + { + /* Set this before calling other routines, so that they see + the correct value of x_focus_frame. */ + dpyinfo->x_focus_frame = frame; + + if (old_focus && old_focus->auto_lower) + gdk_window_lower (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (old_focus))); + + if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) + gdk_window_raise (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (dpyinfo->x_focus_frame))); + } + + pgtk_frame_rehighlight (dpyinfo); +} + static struct terminal * pgtk_create_terminal (struct pgtk_display_info *dpyinfo) /* -------------------------------------------------------------------------- @@ -4371,7 +4555,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->read_socket_hook = pgtk_read_socket; // terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; terminal->mouse_position_hook = pgtk_mouse_position; - // terminal->frame_rehighlight_hook = pgtk_frame_rehighlight; + terminal->frame_rehighlight_hook = XTframe_rehighlight; // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; terminal->fullscreen_hook = pgtk_fullscreen_hook; @@ -5095,132 +5279,6 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_ return TRUE; } -void -pgtk_focus_frame (struct frame *f, bool noactivate) -{ - struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - - GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); - - if (dpyinfo->x_focus_frame != f) - { - block_input (); - gtk_window_present (GTK_WINDOW (wid)); - unblock_input (); - } -} - - -static void -frame_highlight (struct frame *f) -{ - /* We used to only do this if Vx_no_window_manager was non-nil, but - the ICCCM (section 4.1.6) says that the window's border pixmap - and border pixel are window attributes which are "private to the - client", so we can always change it to whatever we want. */ - block_input (); - /* I recently started to get errors in this XSetWindowBorder, depending on - the window-manager in use, tho something more is at play since I've been - using that same window-manager binary for ever. Let's not crash just - because of this (bug#9310). */ -#if 0 - x_catch_errors (FRAME_X_DISPLAY (f)); - XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_X_OUTPUT(f)->border_pixel); - x_uncatch_errors (); -#endif - unblock_input (); - gui_update_cursor (f, true); -#if 0 - x_set_frame_alpha (f); -#endif -} - -static void -frame_unhighlight (struct frame *f) -{ - /* We used to only do this if Vx_no_window_manager was non-nil, but - the ICCCM (section 4.1.6) says that the window's border pixmap - and border pixel are window attributes which are "private to the - client", so we can always change it to whatever we want. */ - block_input (); - /* Same as above for XSetWindowBorder (bug#9310). */ -#if 0 - x_catch_errors (FRAME_X_DISPLAY (f)); - XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_X_OUTPUT(f)->border_tile); - x_uncatch_errors (); -#endif - unblock_input (); - gui_update_cursor (f, true); -#if 0 - x_set_frame_alpha (f); -#endif -} - - -static void -x_frame_rehighlight (struct pgtk_display_info *dpyinfo) -{ - struct frame *old_highlight = dpyinfo->highlight_frame; - - if (dpyinfo->x_focus_frame) - { - dpyinfo->highlight_frame - = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) - ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) - : dpyinfo->x_focus_frame); - if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) - { - fset_focus_frame (dpyinfo->x_focus_frame, Qnil); - dpyinfo->highlight_frame = dpyinfo->x_focus_frame; - } - } - else - dpyinfo->highlight_frame = 0; - - if (dpyinfo->highlight_frame != old_highlight) - { - if (old_highlight) - frame_unhighlight (old_highlight); - if (dpyinfo->highlight_frame) - frame_highlight (dpyinfo->highlight_frame); - } -} - -/* The focus has changed. Update the frames as necessary to reflect - the new situation. Note that we can't change the selected frame - here, because the Lisp code we are interrupting might become confused. - Each event gets marked with the frame in which it occurred, so the - Lisp code can tell when the switch took place by examining the events. */ - -static void -x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) -{ - struct frame *old_focus = dpyinfo->x_focus_frame; - - if (frame != dpyinfo->x_focus_frame) - { - /* Set this before calling other routines, so that they see - the correct value of x_focus_frame. */ - dpyinfo->x_focus_frame = frame; - -#if 0 - if (old_focus && old_focus->auto_lower) - x_lower_frame (old_focus); -#endif - -#if 0 - if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) - dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame; - else - dpyinfo->x_pending_autoraise_frame = NULL; -#endif - } - - x_frame_rehighlight (dpyinfo); -} - /* The focus may have changed. Figure out if it is a real focus change, by checking both FocusIn/Out and Enter/LeaveNotify events. @@ -5269,10 +5327,8 @@ x_focus_changed (gboolean is_enter, int state, struct pgtk_display_info *dpyinfo XSETFRAME (bufp->ie.frame_or_window, frame); } -#if 0 if (frame->pointer_invisible) - XTtoggle_invisible_pointer (frame, false); -#endif + XTtoggle_invisible_pointer (frame, false); } } diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 4b585079b8..91990b203b 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -579,5 +579,6 @@ extern void pgtk_set_scroll_bar_default_width (struct frame *f); extern void pgtk_set_scroll_bar_default_height (struct frame *f); extern Lisp_Object x_get_focus_frame (struct frame *frame); +extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo); #endif /* HAVE_PGTK */ commit 85441c96d74f82ca368b950aa0f5334297bf4fa0 Author: Yuuki Harano Date: Fri Jul 5 22:37:18 2019 +0900 Add Stipple support for PGTK * ../src/pgtkterm.c (create_background_surface_by_face) (create_background_surface, x_draw_glyph_string_background) (x_draw_glyph_string_bg_rect, x_draw_image_glyph_string) (x_draw_stretch_glyph_string, pgtk_draw_fringe_bitmap): handle stipple * ../src/image.c (image_create_bitmap_from_file, ) (syms_of_image): Add pgtk support * ../lisp/faces.el (face-valid-attribute-values): add pgtk support stipple 対応。 stipple がまともに動いてなかったので修正。 diff --git a/lisp/faces.el b/lisp/faces.el index 5e525e7953..ee4a95eb57 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1151,13 +1151,14 @@ an integer value." (:height 'integerp) (:stipple - (and (memq (window-system frame) '(x ns)) ; No stipple on w32 - (mapcar #'list + (and (memq (window-system frame) '(x ns pgtk)) ; No stipple on w32 + (mapcar (lambda (f) + (cons (file-name-base f) f)) (apply #'nconc (mapcar (lambda (dir) (and (file-readable-p dir) (file-directory-p dir) - (directory-files dir))) + (directory-files dir 'full))) x-bitmap-file-path))))) (:inherit (cons '("none" . nil) diff --git a/src/image.c b/src/image.c index 9beb35c484..0242b50258 100644 --- a/src/image.c +++ b/src/image.c @@ -507,12 +507,14 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) #endif #ifdef HAVE_PGTK - GError *err; + GError *err = NULL; ptrdiff_t id; void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); - if (!bitmap) + if (!bitmap) { + g_error_free(err); return -1; + } id = image_allocate_bitmap_record(f); @@ -10698,7 +10700,7 @@ non-numeric, there is no explicit limit on the size of images. */); DEFSYM (Qxbm, "xbm"); add_image_type (Qxbm); -#if defined (HAVE_XPM) || defined (HAVE_NS) +#if defined (HAVE_XPM) || defined (HAVE_NS) || defined (USE_CAIRO) DEFSYM (Qxpm, "xpm"); add_image_type (Qxpm); #endif diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 3e3c73ce50..fb2520614f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -984,6 +984,66 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) } +static cairo_surface_t * +create_background_surface_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) +{ + cairo_surface_t *surface = cairo_surface_create_similar (FRAME_CR_SURFACE (f), + CAIRO_CONTENT_COLOR, + width, + height); + + { + cairo_t *cr = cairo_create (surface); + + double r = ((face->background >> 16) & 0xff) / 255.0; + double g = ((face->background >> 8) & 0xff) / 255.0; + double b = ((face->background >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_paint (cr); + + cairo_destroy (cr); + } + + if (face->stipple != 0) { + GdkPixbuf *pixbuf = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].img; + GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); + cairo_surface_t *mask = cairo_surface_create_similar_image (FRAME_CR_SURFACE (f), + CAIRO_FORMAT_A1, + width, + height); + + { + cairo_t *cr = cairo_create (mask); + gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); + cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + } + + { + cairo_t *cr = cairo_create (surface); + double r = ((face->foreground >> 16) & 0xff) / 255.0; + double g = ((face->foreground >> 8) & 0xff) / 255.0; + double b = ((face->foreground >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_mask_surface (cr, mask, 0, 0); + cairo_destroy (cr); + } + + cairo_surface_destroy (mask); + g_object_unref (pb); + } + + return surface; +} + +static cairo_surface_t * +create_background_surface (struct glyph_string *s, int x, int y, int width, int height) +{ + return create_background_surface_by_face (s->f, s->face, x, y, width, height); +} + /* Draw the background of glyph_string S. If S->background_filled_p is non-zero don't draw it. FORCE_P non-zero means draw the background even if it wouldn't be drawn normally. This is used @@ -1007,20 +1067,28 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); -#if 0 + if (s->stippled_p) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - x_fill_rectangle (s->f, s->gc, s->x, - s->y + box_line_width, - s->background_width, - s->height - 2 * box_line_width); - XSetFillStyle (s->display, s->gc, FillSolid); + + cairo_surface_t *bg = create_background_surface (s, + s->x, s->y + box_line_width, + s->background_width, s->height - 2 * box_line_width); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, s->x, s->y + box_line_width); + cairo_rectangle (cr, + s->x, s->y + box_line_width, + s->background_width, s->height - 2 * box_line_width); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); + s->background_filled_p = true; } else -#endif if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font dimensions, since the actual glyphs might be @@ -1821,16 +1889,21 @@ x_draw_image_relief (struct glyph_string *s) static void x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) { -#if 0 if (s->stippled_p) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - x_fill_rectangle (s->f, s->gc, x, y, w, h); - XSetFillStyle (s->display, s->gc, FillSolid); + + cairo_surface_t *bg = create_background_surface (s, x, y, w, h); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); } else -#endif x_clear_glyph_string_rect (s, x, y, w, h); } @@ -1881,7 +1954,6 @@ x_draw_image_glyph_string (struct glyph_string *s) int box_line_hwidth = eabs (s->face->box_line_width); int box_line_vwidth = max (s->face->box_line_width, 0); int height; - cairo_surface_t *surface = NULL; height = s->height; if (s->slice.y == 0) @@ -1903,43 +1975,15 @@ x_draw_image_glyph_string (struct glyph_string *s) { if (s->img->mask) { - /* Create a pixmap as large as the glyph string. Fill it - with the background color. Copy the image to it, using - its mask. Copy the temporary pixmap to the display. */ - - /* Create a pixmap as large as the glyph string. */ - surface = cairo_surface_create_similar(FRAME_CR_SURFACE(s->f), CAIRO_CONTENT_COLOR_ALPHA, - s->background_width, - s->height); + cairo_surface_t *bg = create_background_surface (s, s->x, s->y, s->background_width, s->height); - /* Don't clip in the following because we're working on the - pixmap. */ - // XSetClipMask (s->display, s->gc, None); + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, s->x, s->y); + cairo_rectangle (cr, s->x, s->y, s->background_width, s->height); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); - /* Fill the pixmap with the background color/stipple. */ -#if 0 - if (s->stippled_p) - { - /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - XSetTSOrigin (s->display, s->gc, - s->x, - s->y); - XFillRectangle (s->display, pixmap, s->gc, - 0, 0, s->background_width, s->height); - XSetFillStyle (s->display, s->gc, FillSolid); - XSetTSOrigin (s->display, s->gc, 0, 0); - } - else -#endif - { - cairo_t *cr = cairo_create(surface); - int red = (s->xgcv.background >> 16) & 0xff; - int green = (s->xgcv.background >> 8) & 0xff; - int blue = (s->xgcv.background >> 0) & 0xff; - cairo_set_source_rgb (cr, red / 255.0, green / 255.0, blue / 255.0); - cairo_rectangle(cr, 0, 0, s->background_width, s->height); - cairo_fill(cr); - cairo_destroy(cr); - } + cairo_surface_destroy (bg); } else { @@ -1957,7 +2001,15 @@ x_draw_image_glyph_string (struct glyph_string *s) if (s->slice.y == 0) y += box_line_vwidth; - x_draw_glyph_string_bg_rect (s, x, y, width, height); + cairo_surface_t *bg = create_background_surface (s, x, y, width, height); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); } s->background_filled_p = true; @@ -1978,18 +2030,6 @@ x_draw_image_glyph_string (struct glyph_string *s) cairo_fill (cr); pgtk_end_cr_clip (s->f); } - else - if (surface != NULL) - { - cairo_t *cr = pgtk_begin_cr_clip(s->f); - - x_draw_image_foreground_1 (s, surface); - x_set_glyph_string_clipping (s, cr); - - cairo_set_source_surface(cr, surface, 0, 0); - cairo_rectangle(cr, s->x, s->y, s->background_width, s->height); - pgtk_end_cr_clip(s->f); - } else x_draw_image_foreground (s); @@ -1998,9 +2038,6 @@ x_draw_image_glyph_string (struct glyph_string *s) || s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) x_draw_image_relief (s); - - if (surface != NULL) - cairo_surface_destroy(surface); } /* Draw stretch glyph string S. */ @@ -2071,16 +2108,18 @@ x_draw_stretch_glyph_string (struct glyph_string *s) get_glyph_string_clip_rect (s, &r); x_set_clip_rectangles (s->f, cr, &r, 1); -#if 0 if (s->face->stipple) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, gc, FillOpaqueStippled); - x_fill_rectangle (s->f, gc, x, y, w, h); - XSetFillStyle (s->display, gc, FillSolid); + cairo_surface_t *bg = create_background_surface (s, x, y, w, h); + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + cairo_surface_destroy (bg); } else -#endif { pgtk_fill_rectangle(s->f, color, x, y, w, h); } @@ -3195,15 +3234,19 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr for something displayed in the text (e.g. face `region' on mono-displays, the fill style may have been changed to FillSolid in x_draw_glyph_string_background. */ -#if 0 - if (face->stipple) - XSetFillStyle (display, face->gc, FillOpaqueStippled); - else -#endif + if (face->stipple) { + cairo_surface_t *bg = create_background_surface_by_face(f, face, p->bx, p->by, p->nx, p->ny); + cairo_t *cr = pgtk_begin_cr_clip (f); + cairo_set_source_surface (cr, bg, p->bx, p->by); + cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); + cairo_fill (cr); + pgtk_end_cr_clip (f); + cairo_surface_destroy (bg); + } else { pgtk_set_cr_source_with_color(f, face->background); - - cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); - cairo_fill(cr); + cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); + cairo_fill(cr); + } } PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); commit 1d549fa0690d174446ff139bece6db5decd25eba Author: Yuuki Harano Date: Wed Jul 3 01:05:10 2019 +0900 Add support for make-frame-(in)visible * ../src/pgtkterm.c (pgtk_make_frame_visible_wait_for_map_event_cb) (pgtk_make_frame_visible_wait_for_map_event_timeout) (x_make_frame_visible, x_new_font) (pgtk_make_frame_visible_invisible, pgtk_make_frame_visible) (pgtk_redisplay_interface, pgtk_create_terminal, map_event) (syms_of_pgtkterm): make-frame-visible/invisible 実装。 diff --git a/src/pgtkterm.c b/src/pgtkterm.c index e081d8c23e..3e3c73ce50 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -462,14 +462,25 @@ pgtk_iconify_frame (struct frame *f) SET_FRAME_ICONIFIED (f, true); SET_FRAME_VISIBLE (f, 0); -#if 0 - XFlush (FRAME_X_DISPLAY (f)); -#else - gdk_flush(); -#endif unblock_input (); } +static gboolean +pgtk_make_frame_visible_wait_for_map_event_cb (GtkWidget *widget, GdkEventAny *event, gpointer user_data) +{ + int *foundptr = user_data; + *foundptr = 1; + return FALSE; +} + +static gboolean +pgtk_make_frame_visible_wait_for_map_event_timeout (gpointer user_data) +{ + int *timedoutptr = user_data; + *timedoutptr = 1; + return FALSE; +} + void pgtk_make_frame_visible (struct frame *f) /* -------------------------------------------------------------------------- @@ -478,54 +489,26 @@ pgtk_make_frame_visible (struct frame *f) { PGTK_TRACE("pgtk_make_frame_visible"); - GtkWidget *win = FRAME_OUTPUT_DATA(f)->widget; + GtkWidget *win = FRAME_GTK_OUTER_WIDGET (f); - gtk_widget_show(win); - -#if 0 - NSTRACE ("x_make_frame_visible"); - /* XXX: at some points in past this was not needed, as the only place that - called this (frame.c:Fraise_frame ()) also called raise_lower; - if this ends up the case again, comment this out again. */ - if (!FRAME_VISIBLE_P (f)) + if (! FRAME_VISIBLE_P (f)) { - EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); - NSWindow *window = [view window]; - - SET_FRAME_VISIBLE (f, 1); - ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f)); + gtk_widget_show(win); + gtk_window_deiconify(GTK_WINDOW(win)); - /* Making a new frame from a fullscreen frame will make the new frame - fullscreen also. So skip handleFS as this will print an error. */ - if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH - && [view isFullscreen]) - return; - - if (f->want_fullscreen != FULLSCREEN_NONE) - { - block_input (); - [view handleFS]; - unblock_input (); - } - - /* Making a frame invisible seems to break the parent->child - relationship, so reinstate it. */ - if ([window parentWindow] == nil && FRAME_PARENT_FRAME (f) != NULL) - { - NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window]; - - block_input (); - [parent addChildWindow: window - ordered: NSWindowAbove]; - unblock_input (); - - /* If the parent frame moved while the child frame was - invisible, the child frame's position won't have been - updated. Make sure it's in the right place now. */ - x_set_offset(f, f->left_pos, f->top_pos, 0); - } + if (FLOATP (Vpgtk_wait_for_event_timeout)) { + guint msec = (guint) (XFLOAT_DATA (Vpgtk_wait_for_event_timeout) * 1000); + int found = 0; + int timed_out = 0; + gulong id = g_signal_connect(win, "map-event", G_CALLBACK(pgtk_make_frame_visible_wait_for_map_event_cb), &found); + guint src = g_timeout_add(msec, pgtk_make_frame_visible_wait_for_map_event_timeout, &timed_out); + while (!found && !timed_out) + gtk_main_iteration(); + g_signal_handler_disconnect (win, id); + if (!timed_out) + g_source_remove(src); + } } -#endif } @@ -541,15 +524,17 @@ pgtk_make_frame_invisible (struct frame *f) gtk_widget_hide(win); -#if 0 - NSView *view; - NSTRACE ("x_make_frame_invisible"); - check_window_system (f); - view = FRAME_NS_VIEW (f); - [[view window] orderOut: NSApp]; SET_FRAME_VISIBLE (f, 0); - SET_FRAME_ICONIFIED (f, 0); -#endif + SET_FRAME_ICONIFIED (f, false); +} + +static void +pgtk_make_frame_visible_invisible (struct frame *f, bool visible) +{ + if (visible) + pgtk_make_frame_visible (f); + else + pgtk_make_frame_invisible (f); } static Lisp_Object @@ -3296,9 +3281,6 @@ pgtk_hide_hourglass(struct frame *f) static void pgtk_flush_display (struct frame *f) { - block_input (); - gdk_flush(); - unblock_input (); } extern frame_parm_handler pgtk_frame_parm_handlers[]; @@ -4348,6 +4330,7 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->mouse_position_hook = pgtk_mouse_position; // terminal->frame_rehighlight_hook = pgtk_frame_rehighlight; // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; + terminal->frame_visible_invisible_hook = pgtk_make_frame_visible_invisible; terminal->fullscreen_hook = pgtk_fullscreen_hook; terminal->menu_show_hook = pgtk_menu_show; terminal->activate_menubar_hook = pgtk_activate_menubar; @@ -5014,7 +4997,7 @@ static gboolean map_event(GtkWidget *widget, GdkEvent *event, gpointer *user_dat if (inev.ie.kind != NO_EVENT) evq_enqueue(&inev); - return TRUE; + return FALSE; } static gboolean window_state_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) commit 592badc3571cc3bb315db8f08ee38db4f6a8cb82 Author: Jeff Walsh Date: Fri Jun 12 21:44:18 2020 +1000 Early toolbar improvements * src/xdisp.c (redisplay_tool_bar): * src/pgtkterm.h: * src/pgtkterm.c: (pgtk_make_frame_visible, pgtk_make_frame_invisible) (pgtk_update_begin, pgtk_parse_color, pgtk_query_colors) (syms_of_pgtkterm): * src/pgtkfns.c: cleanup function * src/image.c (image_create_bitmap_from_file): * src/gtkutil.c (xg_get_pixbuf_from_pix_and_mask): diff --git a/src/gtkutil.c b/src/gtkutil.c index 10120422ae..9655c8dfc1 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -316,8 +316,8 @@ xg_create_default_cursor (GdkDisplay *gdpy) static GdkPixbuf * xg_get_pixbuf_from_pix_and_mask (struct frame *f, - Pixmap pix, - Pixmap mask) + Emacs_Pixmap pix, + Emacs_Pixmap mask) { GdkPixbuf *icon_buf = 0; int iunused; @@ -327,7 +327,7 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, #ifndef HAVE_PGTK if (FRAME_DISPLAY_INFO (f)->red_bits != 8) return 0; -#endif + XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, &width, &height, &uunused, &depth); if (depth != 24) @@ -359,10 +359,20 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, XDestroyImage (xmm); XDestroyImage (xim); } +#else + width = pix->width; + height = pix->height; + depth = pix->bits_per_pixel; + + icon_buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); + + +#endif return icon_buf; } -#endif + + #if defined USE_CAIRO && !defined HAVE_GTK3 static GdkPixbuf * @@ -414,6 +424,8 @@ xg_get_pixbuf_from_surface (cairo_surface_t *surface) } #endif /* USE_CAIRO && !HAVE_GTK3 */ +#endif /* !HAVE_PGTK */ + static Lisp_Object file_for_image (Lisp_Object image) { diff --git a/src/image.c b/src/image.c index 74cd6b854d..9beb35c484 100644 --- a/src/image.c +++ b/src/image.c @@ -507,7 +507,22 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) #endif #ifdef HAVE_PGTK - return -1; // fixme: + GError *err; + ptrdiff_t id; + void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); + + if (!bitmap) + return -1; + + id = image_allocate_bitmap_record(f); + + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].refcount = 1; + dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); + //dpyinfo->bitmaps[id - 1].depth = 1; + dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); + dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); + return id; #endif #ifdef HAVE_X_WINDOWS diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 34effd1346..b726d1bcaf 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1394,22 +1394,6 @@ This function is an internal primitive--use `make-frame' instead. */) return unbind_to (count, frame); } -void -x_focus_frame (struct frame *f, bool noactivate) -{ - struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - -#if 0 - if (dpyinfo->x_focus_frame != f) - { - EmacsView *view = FRAME_PGTK_VIEW (f); - block_input (); - [NSApp activateIgnoringOtherApps: YES]; - [[view window] makeKeyAndOrderFront: view]; - unblock_input (); - } -#endif -} #if 0 static int diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 9fbf41c6fb..e081d8c23e 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -80,6 +80,8 @@ static struct event_queue_t { static Time ignore_next_mouse_click_timeout; +static Lisp_Object xg_default_icon_file; + static void pgtk_delete_display (struct pgtk_display_info *dpyinfo); static void pgtk_clear_frame_area(struct frame *f, int x, int y, int width, int height); static void pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int width, int height); @@ -475,6 +477,11 @@ pgtk_make_frame_visible (struct frame *f) -------------------------------------------------------------------------- */ { PGTK_TRACE("pgtk_make_frame_visible"); + + GtkWidget *win = FRAME_OUTPUT_DATA(f)->widget; + + gtk_widget_show(win); + #if 0 NSTRACE ("x_make_frame_visible"); /* XXX: at some points in past this was not needed, as the only place that @@ -529,6 +536,11 @@ pgtk_make_frame_invisible (struct frame *f) -------------------------------------------------------------------------- */ { PGTK_TRACE("pgtk_make_frame_invisible"); + + GtkWidget *win = FRAME_OUTPUT_DATA(f)->widget; + + gtk_widget_hide(win); + #if 0 NSView *view; NSTRACE ("x_make_frame_invisible"); @@ -2766,16 +2778,30 @@ pgtk_update_begin (struct frame *f) if (! FRAME_CR_SURFACE (f)) { - int width = FRAME_PIXEL_WIDTH (f); - int height = FRAME_PIXEL_HEIGHT (f); + int width, height; + if (FRAME_GTK_WIDGET (f)) + { + GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); + width = gdk_window_get_width (w); + height = gdk_window_get_height (w); + } + else + { + width = FRAME_PIXEL_WIDTH (f); + height = FRAME_PIXEL_HEIGHT (f); + if (! FRAME_EXTERNAL_TOOL_BAR (f)) + height += FRAME_TOOL_BAR_HEIGHT (f); + if (! FRAME_EXTERNAL_MENU_BAR (f)) + height += FRAME_MENU_BAR_HEIGHT (f); + } if (width > 0 && height > 0) - { - block_input(); - FRAME_CR_SURFACE (f) = cairo_image_surface_create - (CAIRO_FORMAT_ARGB32, width, height); - unblock_input(); - } + { + block_input(); + FRAME_CR_SURFACE (f) = cairo_image_surface_create + (CAIRO_FORMAT_ARGB32, width, height); + unblock_input(); + } } pgtk_clear_under_internal_border (f); @@ -6123,7 +6149,7 @@ pgtk_defined_color (struct frame *f, int pgtk_parse_color (const char *color_name, Emacs_Color *color) { - // PGTK_TRACE("pgtk_parse_color: %s", color_name); + PGTK_TRACE("pgtk_parse_color: %s", color_name); GdkRGBA rgba; if (gdk_rgba_parse(&rgba, color_name)) { @@ -6173,6 +6199,7 @@ pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors) colors[i].red = GetRValue (pixel) * 257; colors[i].green = GetGValue (pixel) * 257; colors[i].blue = GetBValue (pixel) * 257; + PGTK_TRACE("pixel: %lx, red: %d, blue %d, green %d", colors[i].pixel, colors[i].red, colors[i].blue, colors[i].green); } } @@ -6217,6 +6244,12 @@ syms_of_pgtkterm (void) DEFSYM (Qlatin_1, "latin-1"); + xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); + staticpro (&xg_default_icon_file); + + DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); + + Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier)); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 6bb03697a5..4b585079b8 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -574,7 +574,7 @@ extern void pgtk_make_frame_invisible (struct frame *f); extern void x_wm_set_size_hint (struct frame *, long, bool); extern void x_free_frame_resources (struct frame *); extern void pgtk_iconify_frame (struct frame *f); -extern void x_focus_frame (struct frame *f, bool noactivate); +extern void pgtk_focus_frame (struct frame *f, bool noactivate); extern void pgtk_set_scroll_bar_default_width (struct frame *f); extern void pgtk_set_scroll_bar_default_height (struct frame *f); extern Lisp_Object x_get_focus_frame (struct frame *frame); diff --git a/src/xdisp.c b/src/xdisp.c index c523111fbd..3dabfea23d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -14330,10 +14330,8 @@ redisplay_tool_bar (struct frame *f) f->tool_bar_redisplayed = true; #ifdef HAVE_EXT_TOOL_BAR -#if 0 if (FRAME_EXTERNAL_TOOL_BAR (f)) update_frame_tool_bar (f); -#endif return false; #else /* ! (HAVE_EXT_TOOL_BAR) */ commit 164800da6f673afeba729befbfbfd0e6131eadb8 Author: Yuuki Harano Date: Wed Jun 26 00:30:33 2019 +0900 Add Preferred geometry settings * ../src/pgtkterm.h (struct pgtk_output): * ../src/pgtkterm.c (pgtk_set_window_size): * ../src/gtkutil.c (x_wm_set_size_hint): * ../src/emacsgtkfixed.c (emacs_fixed_get_preferred_width) (emacs_fixed_get_preferred_height): Fixup toolbar handling toolbar, menubar の ON/OFF でサイズが変化していっていたのを修正。 diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index aeca3d4f7c..4128f81cce 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -188,11 +188,13 @@ emacs_fixed_get_preferred_width (GtkWidget *widget, EmacsFixedPrivate *priv = fixed->priv; #ifdef HAVE_PGTK int w = priv->f->output_data.pgtk->size_hints.min_width; + if (minimum) *minimum = w; + if (natural) *natural = priv->f->output_data.pgtk->preferred_width; #else int w = priv->f->output_data.x->size_hints.min_width; -#endif if (minimum) *minimum = w; if (natural) *natural = w; +#endif } static void @@ -204,11 +206,13 @@ emacs_fixed_get_preferred_height (GtkWidget *widget, EmacsFixedPrivate *priv = fixed->priv; #ifdef HAVE_PGTK int h = priv->f->output_data.pgtk->size_hints.min_height; + if (minimum) *minimum = h; + if (natural) *natural = priv->f->output_data.pgtk->preferred_height; #else int h = priv->f->output_data.x->size_hints.min_height; -#endif if (minimum) *minimum = h; if (natural) *natural = h; +#endif } diff --git a/src/gtkutil.c b/src/gtkutil.c index 6c0d42103b..10120422ae 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1696,8 +1696,10 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) sizeof (size_hints)) != 0) { block_input (); +#ifndef HAVE_PGTK gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL, &size_hints, hint_flags); +#endif f->output_data.xp->size_hints = size_hints; f->output_data.xp->hint_flags = hint_flags; unblock_input (); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 622b5ef76f..6bb03697a5 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -297,6 +297,7 @@ struct pgtk_output /* The last size hints set. */ GdkGeometry size_hints; long hint_flags; + int preferred_width, preferred_height; /* The widget of this screen. This is the window of a top widget. */ GtkWidget *widget; commit 330a346ca734d39c0233ef899e044d05e0e1ebe9 Author: Yuuki Harano Date: Tue Jun 25 21:36:39 2019 +0900 Migrate to Emacs_GC * ../src/xfaces.c (x_create_gc, x_free_gc): * ../src/pgtkterm.h (struct pgtk_output, struct pgtk_output): * ../src/pgtkterm.c (x_set_cursor_gc, x_set_mouse_face_gc) (x_setup_relief_color, x_draw_image_foreground_1) (x_draw_image_foreground) (pgtk_cr_draw_image, pgtk_draw_fringe_bitmap) (pgtk_begin_cr_clip, pgtk_set_cr_source_with_gc_foreground) (pgtk_set_cr_source_with_gc_background): * ../src/pgtkgui.h: * ../src/dispextern.h (struct glyph_string): clean up XGCValues emulation XGCValues, GC 廃止。 Emacs_GC に統一。 diff --git a/src/dispextern.h b/src/dispextern.h index 35e1210410..126f2cb11e 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1402,7 +1402,7 @@ struct glyph_string HDC hdc; #endif #if defined (HAVE_PGTK) - XGCValues xgcv; + Emacs_GC xgcv; #endif /* A pointer to the first glyph in the string. This glyph diff --git a/src/pgtkgui.h b/src/pgtkgui.h index 27e94b213d..e7e614ea1f 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -43,26 +43,7 @@ typedef unichar XChar2b; (*(chp) & 0x00ff) -/* XXX: xfaces requires these structures, but the question is are we - forced to use them? */ -typedef struct _XGCValues -{ - unsigned long foreground; - unsigned long background; - void *font; -} XGCValues; - -typedef XGCValues * GC; - -#define GCForeground 0x01 -#define GCBackground 0x02 -#define GCFont 0x03 - -typedef void *Pixmap; - -typedef void *Cursor; - -#define No_Cursor (0) +typedef void *Emacs_Cursor; typedef void * Color; typedef int Window; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index ed8d7e841b..9fbf41c6fb 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -754,7 +754,7 @@ x_set_cursor_gc (struct glyph_string *s) else { /* Cursor on non-default face: must merge. */ - XGCValues xgcv; + Emacs_GC xgcv; PGTK_TRACE("x_set_cursor_gc: 2."); xgcv.background = FRAME_X_OUTPUT(s->f)->cursor_color; @@ -815,7 +815,7 @@ x_set_mouse_face_gc (struct glyph_string *s) { /* Otherwise construct scratch_cursor_gc with values from FACE except for FONT. */ - XGCValues xgcv; + Emacs_GC xgcv; xgcv.background = s->face->background; xgcv.foreground = s->face->foreground; @@ -1433,7 +1433,7 @@ static void x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, unsigned long default_pixel) { - XGCValues xgcv; + Emacs_GC xgcv; struct pgtk_output *di = FRAME_X_OUTPUT(f); unsigned long pixel; unsigned long background = di->relief_background; @@ -3107,7 +3107,7 @@ pgtk_clip_to_row (struct window *w, struct glyph_row *row, } static void -pgtk_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image, +pgtk_cr_draw_image (struct frame *f, Emacs_GC *gc, cairo_pattern_t *image, int src_x, int src_y, int width, int height, int dest_x, int dest_y, bool overlay_p) { @@ -3198,7 +3198,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); if (p->which && p->which < max_fringe_bmp) { - XGCValues gcv; + Emacs_GC gcv; PGTK_TRACE("cursor_p=%d.", p->cursor_p); PGTK_TRACE("overlay_p_p=%d.", p->overlay_p); @@ -6356,14 +6356,14 @@ pgtk_end_cr_clip (struct frame *f) } void -pgtk_set_cr_source_with_gc_foreground (struct frame *f, XGCValues *gc) +pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc) { PGTK_TRACE("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); pgtk_set_cr_source_with_color(f, gc->foreground); } void -pgtk_set_cr_source_with_gc_background (struct frame *f, XGCValues *gc) +pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc) { PGTK_TRACE("pgtk_set_cr_source_with_gc_background: %08lx", gc->background); pgtk_set_cr_source_with_color(f, gc->background); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 10dc9fc979..622b5ef76f 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -255,7 +255,7 @@ struct pgtk_output mapped to display an hourglass cursor. */ GtkWidget *hourglass_widget; - XGCValues cursor_xgcv; + Emacs_GC cursor_xgcv; /* lord knows why Emacs needs to know about our Window ids.. */ Window window_desc, parent_desc; @@ -349,7 +349,7 @@ struct pgtk_output /* Relief GCs, colors etc. */ struct relief { - XGCValues xgcv; + Emacs_GC xgcv; unsigned long pixel; } black_relief, white_relief; @@ -542,8 +542,8 @@ extern int pgtk_select (int nfds, fd_set *readfds, fd_set *writefds, /* Cairo related functions implemented in pgtkterm.c */ extern cairo_t *pgtk_begin_cr_clip (struct frame *f); extern void pgtk_end_cr_clip (struct frame *f); -extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, XGCValues *gc); -extern void pgtk_set_cr_source_with_gc_background (struct frame *f, XGCValues *gc); +extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, Emacs_GC *gc); +extern void pgtk_set_cr_source_with_gc_background (struct frame *f, Emacs_GC *gc); extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color); extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); extern void pgtk_cr_destroy_surface(struct frame *f); diff --git a/src/xfaces.c b/src/xfaces.c index a84e52157d..7f26610e37 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -578,18 +578,18 @@ x_free_gc (struct frame *f, Emacs_GC *gc) #ifdef HAVE_PGTK /* PGTK emulation of GCs */ -static GC +static Emacs_GC * x_create_gc (struct frame *f, unsigned long mask, - XGCValues *xgcv) + Emacs_GC *xgcv) { - GC gc = xmalloc (sizeof *gc); + Emacs_GC *gc = xmalloc (sizeof *gc); *gc = *xgcv; return gc; } static void -x_free_gc (struct frame *f, GC gc) +x_free_gc (struct frame *f, Emacs_GC *gc) { xfree (gc); } commit f4920a68831f769f0a1504c85145589bdb4c3eb9 Author: Yuuki Harano Date: Sun Jun 23 03:19:10 2019 +0900 Add pgtk-read-file-name function * ../src/pgtkfns.c (read_file_name_closed_cb) (Fpgtk_read_file_name, syms_of_pgtkfns): add function pgtk-read-file-name を作成。 toolbar からよく呼ばれるので… diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 203cce442d..1cf526b758 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -43,34 +43,6 @@ ;;;; File handling. -(defun x-file-dialog (prompt dir default_filename mustmatch only_dir_p) -"Read file name, prompting with PROMPT in directory DIR. -Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file -selection box, if specified. If MUSTMATCH is non-nil, the returned file -or directory must exist. - -This function is only defined on PGTK, MS Windows, and X Windows with the -Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored. -Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories." - (pgtk-read-file-name prompt dir mustmatch default_filename only_dir_p)) - -(defun pgtk-open-file-using-panel () - "Pop up open-file panel, and load the result in a buffer." - (interactive) - ;; Prompt dir defaultName isLoad initial. - (setq pgtk-input-file (pgtk-read-file-name "Select File to Load" nil t nil)) - (if pgtk-input-file - (and (setq pgtk-input-file (list pgtk-input-file)) (pgtk-find-file)))) - -(defun pgtk-write-file-using-panel () - "Pop up save-file panel, and save buffer in resulting name." - (interactive) - (let (pgtk-output-file) - ;; Prompt dir defaultName isLoad initial. - (setq pgtk-output-file (pgtk-read-file-name "Save As" nil nil nil)) - (message pgtk-output-file) - (if pgtk-output-file (write-file pgtk-output-file)))) - (defcustom pgtk-pop-up-frames 'fresh "Non-nil means open files upon request from the Workspace in a new frame. If t, always do so. Any other non-nil value means open a new frame @@ -83,33 +55,6 @@ unless the current buffer is a scratch buffer." (declare-function pgtk-hide-emacs "pgtkfns.c" (on)) -(defun pgtk-find-file () - "Do a `find-file' with the `pgtk-input-file' as argument." - (interactive) - (let* ((f (file-truename - (expand-file-name (pop pgtk-input-file) - command-line-default-directory))) - (file (find-file-noselect f)) - (bufwin1 (get-buffer-window file 'visible)) - (bufwin2 (get-buffer-window "*scratch*" 'visible))) - (cond - (bufwin1 - (select-frame (window-frame bufwin1)) - (raise-frame (window-frame bufwin1)) - (select-window bufwin1)) - ((and (eq pgtk-pop-up-frames 'fresh) bufwin2) - (pgtk-hide-emacs 'activate) - (select-frame (window-frame bufwin2)) - (raise-frame (window-frame bufwin2)) - (select-window bufwin2) - (find-file f)) - (pgtk-pop-up-frames - (pgtk-hide-emacs 'activate) - (let ((pop-up-frames t)) (pop-to-buffer file nil))) - (t - (pgtk-hide-emacs 'activate) - (find-file f))))) - (defun pgtk-drag-n-drop (event &optional new-frame force-text) "Edit the files listed in the drag-n-drop EVENT. diff --git a/src/gtkutil.c b/src/gtkutil.c index b7a397bf43..6c0d42103b 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -1319,6 +1319,7 @@ style_changed_cb (GObject *go, /* Called when a delete-event occurs on WIDGET. */ +#ifndef HAVE_PGTK static gboolean delete_cb (GtkWidget *widget, GdkEvent *event, @@ -1326,6 +1327,7 @@ delete_cb (GtkWidget *widget, { return TRUE; } +#endif /* Create and set up the GTK widgets for frame F. Return true if creation succeeded. */ @@ -4738,6 +4740,7 @@ xg_tool_bar_help_callback (GtkWidget *w, } +#ifndef HAVE_GTK3 /* This callback is called when a tool bar item shall be redrawn. It modifies the expose event so that the GtkImage widget redraws the whole image. This to overcome a bug that makes GtkImage draw the image @@ -4767,6 +4770,7 @@ xg_tool_bar_item_expose_callback (GtkWidget *w, return FALSE; } +#endif /* Attach a tool bar to frame F. */ diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 140f29a473..34effd1346 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -181,7 +181,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) PGTK_TRACE("x_set_background_color: col.pixel=%08lx.", col.pixel); FRAME_X_OUTPUT(f)->background_color = col.pixel; FRAME_BACKGROUND_PIXEL (f) = - ARGB_TO_ULONG ((int)(0xff), (int)(col.red>>8), (int)(col.green>>8), (int)(col.blue>>8)); + ARGB_TO_ULONG ((unsigned int)(0xff), (unsigned int)(col.red>>8), (unsigned int)(col.green>>8), (unsigned int)(col.blue>>8)); xg_set_background_color(f, col.pixel); update_face_from_frame_parameter (f, Qbackground_color, arg); @@ -2579,6 +2579,67 @@ visible. */) return Qnil; } +DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, + doc: /* Read file name, prompting with PROMPT in directory DIR. +Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file +selection box, if specified. If MUSTMATCH is non-nil, the returned file +or directory must exist. + +This function is defined only on PGTK, NS, MS Windows, and X Windows with the +Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored. +Otherwise, if ONLY-DIR-P is non-nil, the user can select only directories. +On MS Windows 7 and later, the file selection dialog "remembers" the last +directory where the user selected a file, and will open that directory +instead of DIR on subsequent invocations of this function with the same +value of DIR as in previous invocations; this is standard MS Windows behavior. */) + (Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p) +{ + struct frame *f = SELECTED_FRAME (); + char *fn; + Lisp_Object file = Qnil; + Lisp_Object decoded_file; + ptrdiff_t count = SPECPDL_INDEX (); + char *cdef_file; + + check_window_system (f); + + CHECK_STRING (prompt); + CHECK_STRING (dir); + + /* Prevent redisplay. */ + specbind (Qinhibit_redisplay, Qt); +#if 0 + record_unwind_protect_void (clean_up_dialog); +#endif + + block_input (); + + if (STRINGP (default_filename)) + cdef_file = SSDATA (default_filename); + else + cdef_file = SSDATA (dir); + + fn = xg_get_file_name (f, SSDATA (prompt), cdef_file, + ! NILP (mustmatch), + ! NILP (only_dir_p)); + + if (fn) + { + file = build_string (fn); + xfree (fn); + } + + unblock_input (); + + /* Make "Cancel" equivalent to C-g. */ + if (NILP (file)) + quit (); + + decoded_file = DECODE_FILE (file); + + return unbind_to (count, decoded_file); +} + DEFUN ("pgtk-backend-display-class", Fpgtk_backend_display_class, Spgtk_backend_display_class, 0, 1, "", doc: /* Returns the name of the Gdk backend display class of the TERMINAL. @@ -2711,6 +2772,8 @@ be used as the image of the icon representing the frame. */); defsubr (&Spgtk_print_frames_dialog); defsubr (&Spgtk_backend_display_class); + defsubr (&Sx_file_dialog); + as_status = 0; as_script = Qnil; as_result = 0; commit cdc04b4509772f2324c4ca63732caed2858cedf3 Author: Jeff Walsh Date: Sat Jun 15 14:44:47 2019 +1000 Implement menubar for pgtk emacs * src/xdisp.c (display_menu_bar): add pgtk case * ../src/pgtkterm.c (pgtk_create_terminal): update hooks (pgtk_menu_show): delete * src/pgtkterm.h: add decls * src/pgtkmenu.c: new file * ../src/pgtkfns.c (x_set_menu_bar_lines) (x_change_tool_bar_height, x_set_tool_bar_lines) (Fx_create_frame): diff --git a/configure.ac b/configure.ac index b168131f42..ce9d016847 100644 --- a/configure.ac +++ b/configure.ac @@ -2827,7 +2827,7 @@ LIBS=$OLD_LIBS PGTK_OBJ= PGTK_LIBS= if test "$window_system" = "pgtk"; then - PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o xsettings.o" + PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o xsettings.o" PGTK_LIBS="$GTK_LIBS -ldl" AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) fi diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index c6ced689a6..e1dea884c7 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -2506,6 +2506,7 @@ See `menu-bar-mode' for more information." (declare-function x-menu-bar-open "term/x-win" (&optional frame)) (declare-function w32-menu-bar-open "term/w32-win" (&optional frame)) +(declare-function pgtk-menu-bar-open "term/pgtk-win" (&optional frame)) (defun lookup-key-ignore-too-long (map key) "Call `lookup-key' and convert numeric values to nil." diff --git a/src/emacs.c b/src/emacs.c index 769a852e73..42d93737b9 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1921,6 +1921,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_pgtkterm(); syms_of_pgtkfns(); syms_of_pgtkselect (); + syms_of_pgtkmenu (); syms_of_fontset (); syms_of_xsettings (); syms_of_xwidget (); diff --git a/src/lisp.h b/src/lisp.h index 718c0f12a5..76d74200ac 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3298,7 +3298,7 @@ struct frame; #endif /* Define if the windowing system provides a tool-bar. */ -#if (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) +#if defined (USE_GTK) || defined (HAVE_NS) #define HAVE_EXT_TOOL_BAR true #endif diff --git a/src/menu.h b/src/menu.h index 44749ade75..baad4496e4 100644 --- a/src/menu.h +++ b/src/menu.h @@ -59,6 +59,12 @@ extern Lisp_Object ns_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); extern void ns_activate_menubar (struct frame *); #endif +#ifdef HAVE_PGTK +extern Lisp_Object pgtk_menu_show (struct frame *, int, int, int, + Lisp_Object, const char **); +extern void pgtk_activate_menubar (struct frame *); +#endif + extern Lisp_Object tty_menu_show (struct frame *, int, int, int, Lisp_Object, const char **); extern ptrdiff_t menu_item_width (const unsigned char *); diff --git a/src/pgtkfns.c b/src/pgtkfns.c index ce70202834..140f29a473 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -465,31 +465,63 @@ pgtk_set_doc_edited (void) static void x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { -#if 0 int nlines; - if (FRAME_MINIBUF_ONLY_P (f)) + /* Right now, menu bars don't work properly in minibuf-only frames; + most of the commands try to apply themselves to the minibuffer + frame itself, and get an error because you can't switch buffers + in or split the minibuffer window. */ + if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f)) return; - if (TYPE_RANGED_INTEGERP (int, value)) + if (TYPE_RANGED_FIXNUMP (int, value)) nlines = XFIXNUM (value); else nlines = 0; + /* Make sure we redisplay all windows in this frame. */ + fset_redisplay (f); + FRAME_MENU_BAR_LINES (f) = 0; + FRAME_MENU_BAR_HEIGHT (f) = 0; if (nlines) { FRAME_EXTERNAL_MENU_BAR (f) = 1; - /* does for all frames, whereas we just want for one frame - [NSMenu setMenuBarVisible: YES]; */ + if (FRAME_PGTK_P (f) && f->output_data.pgtk->menubar_widget == 0) + /* Make sure next redisplay shows the menu bar. */ + XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true; } else { if (FRAME_EXTERNAL_MENU_BAR (f) == 1) - free_frame_menubar (f); - /* [NSMenu setMenuBarVisible: NO]; */ + free_frame_menubar (f); FRAME_EXTERNAL_MENU_BAR (f) = 0; + if (FRAME_X_P (f)) + f->output_data.pgtk->menubar_widget = 0; + } + + adjust_frame_glyphs (f); +} + +/* Set the pixel height of the tool bar of frame F to HEIGHT. */ +static void +x_change_tool_bar_height (struct frame *f, int height) +{ + FRAME_TOOL_BAR_LINES (f) = 0; + FRAME_TOOL_BAR_HEIGHT (f) = 0; + if (height) + { + FRAME_EXTERNAL_TOOL_BAR (f) = true; + if (FRAME_X_P (f) && f->output_data.pgtk->toolbar_widget == 0) + /* Make sure next redisplay shows the tool bar. */ + XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true; + update_frame_tool_bar (f); + } + else + { + if (FRAME_EXTERNAL_TOOL_BAR (f)) + free_frame_tool_bar (f); + FRAME_EXTERNAL_TOOL_BAR (f) = false; } -#endif } @@ -497,70 +529,20 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) static void x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) { -#if 0 - /* Currently, when the tool bar change state, the frame is resized. - - TODO: It would be better if this didn't occur when 1) the frame - is full height or maximized or 2) when specified by - `frame-inhibit-implied-resize'. */ int nlines; - NSTRACE ("x_set_tool_bar_lines"); - + /* Treat tool bars like menu bars. */ if (FRAME_MINIBUF_ONLY_P (f)) return; - if (RANGED_INTEGERP (0, value, INT_MAX)) + /* Use VALUE only if an int >= 0. */ + if (RANGED_FIXNUMP (0, value, INT_MAX)) nlines = XFIXNAT (value); else nlines = 0; - if (nlines) - { - FRAME_EXTERNAL_TOOL_BAR (f) = 1; - update_frame_tool_bar (f); - } - else - { - if (FRAME_EXTERNAL_TOOL_BAR (f)) - { - free_frame_tool_bar (f); - FRAME_EXTERNAL_TOOL_BAR (f) = 0; - - { - EmacsView *view = FRAME_PGTK_VIEW (f); - int fs_state = [view fullscreenState]; - - if (fs_state == FULLSCREEN_MAXIMIZED) - { - [view setFSValue:FULLSCREEN_WIDTH]; - } - else if (fs_state == FULLSCREEN_HEIGHT) - { - [view setFSValue:FULLSCREEN_NONE]; - } - } - } - } + x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f)); - { - int inhibit - = ((f->after_make_frame - && !f->tool_bar_resized - && (EQ (frame_inhibit_implied_resize, Qt) - || (CONSP (frame_inhibit_implied_resize) - && !NILP (Fmemq (Qtool_bar_lines, - frame_inhibit_implied_resize)))) - && NILP (get_frame_param (f, Qfullscreen))) - ? 0 - : 2); - - NSTRACE_MSG ("inhibit:%d", inhibit); - - frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil); - adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines); - } -#endif } @@ -1327,25 +1309,14 @@ This function is an internal primitive--use `make-frame' instead. */) gui_default_parameter (f, parms, Qno_accept_focus, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Create the menu bar. */ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) { -#if 0 /* If this signals an error, we haven't set size hints for the frame and we didn't make it visible. */ initialize_frame_menubar (f); -#endif -#ifndef USE_GTK - /* This is a no-op, except under Motif where it arranges the - main window for the widgets on it. */ - lw_set_main_areas (FRAME_X_OUTPUT(f)->column_widget, - FRAME_X_OUTPUT(f)->menubar_widget, - FRAME_X_OUTPUT(f)->edit_widget); -#endif /* not USE_GTK */ } -#endif /* USE_X_TOOLKIT || USE_GTK */ /* Consider frame official, now. */ f->can_set_window_size = true; diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c new file mode 100644 index 0000000000..bbe47ddad6 --- /dev/null +++ b/src/pgtkmenu.c @@ -0,0 +1,476 @@ +/* Pure GTK3 menu and toolbar module. + Copyright (C) 2019 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +/* + */ + + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#include "lisp.h" +#include "frame.h" +#include "window.h" +#include "character.h" +#include "buffer.h" +#include "keymap.h" +#include "coding.h" +#include "commands.h" +#include "blockinput.h" +#include "termhooks.h" +#include "keyboard.h" +#include "menu.h" +#include "pdumper.h" + +#include "gtkutil.h" +#include + + +Lisp_Object +pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents) +{ + return Qnil; +} + + + +/* Gtk calls callbacks just because we tell it what item should be + selected in a radio group. If this variable is set to a non-zero + value, we are creating menus and don't want callbacks right now. +*/ +static bool xg_crazy_callback_abort; + +/* This callback is called from the menu bar pulldown menu + when the user makes a selection. + Figure out what the user chose + and put the appropriate events into the keyboard buffer. */ +static void +menubar_selection_callback (GtkWidget *widget, gpointer client_data) +{ + xg_menu_item_cb_data *cb_data = client_data; + + if (xg_crazy_callback_abort) + return; + + if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f) + return; + + /* For a group of radio buttons, GTK calls the selection callback first + for the item that was active before the selection and then for the one that + is active after the selection. For C-h k this means we get the help on + the deselected item and then the selected item is executed. Prevent that + by ignoring the non-active item. */ + if (GTK_IS_RADIO_MENU_ITEM (widget) + && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget))) + return; + + /* When a menu is popped down, X generates a focus event (i.e. focus + goes back to the frame below the menu). Since GTK buffers events, + we force it out here before the menu selection event. Otherwise + sit-for will exit at once if the focus event follows the menu selection + event. */ + + block_input (); + while (gtk_events_pending ()) + gtk_main_iteration (); + unblock_input (); + + find_and_call_menu_selection (cb_data->cl_data->f, + cb_data->cl_data->menu_bar_items_used, + cb_data->cl_data->menu_bar_vector, + cb_data->call_data); +} + +static void +menu_highlight_callback (GtkWidget *widget, gpointer call_data) +{ + xg_menu_item_cb_data *cb_data; + Lisp_Object help; + + cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA); + if (! cb_data) return; + + help = call_data ? cb_data->help : Qnil; +} + + +/* This callback is invoked when a dialog or menu is finished being + used and has been unposted. */ + +static void +popup_deactivate_callback (GtkWidget *widget, gpointer client_data) +{ +} + + + + +/* Set the contents of the menubar widgets of frame F. + The argument FIRST_TIME is currently ignored; + it is set the first time this is called, from initialize_frame_menubar. */ + +void +set_frame_menubar (struct frame *f, bool first_time, bool deep_p) +{ + GtkWidget * menubar_widget; + Lisp_Object items; + widget_value *wv, *first_wv, *prev_wv = 0; + int i; + int *submenu_start, *submenu_end; + bool *submenu_top_level_items; + int *submenu_n_panes; + + + menubar_widget = f->output_data.pgtk->menubar_widget; + + XSETFRAME(Vmenu_updating_frame, f); + + if (! menubar_widget) + deep_p = true; + + if (deep_p) + { + struct buffer *prev = current_buffer; + Lisp_Object buffer; + ptrdiff_t specpdl_count = SPECPDL_INDEX (); + int previous_menu_items_used = f->menu_bar_items_used; + Lisp_Object *previous_items + = alloca (previous_menu_items_used * sizeof *previous_items); + int subitems; + + /* If we are making a new widget, its contents are empty, + do always reinitialize them. */ + if (! menubar_widget) + previous_menu_items_used = 0; + + buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents; + specbind (Qinhibit_quit, Qt); + /* Don't let the debugger step into this code + because it is not reentrant. */ + specbind (Qdebug_on_next_call, Qnil); + + record_unwind_save_match_data (); + if (NILP (Voverriding_local_map_menu_flag)) + { + specbind (Qoverriding_terminal_local_map, Qnil); + specbind (Qoverriding_local_map, Qnil); + } + + set_buffer_internal_1 (XBUFFER (buffer)); + + /* Run the Lucid hook. */ + safe_run_hooks (Qactivate_menubar_hook); + + /* If it has changed current-menubar from previous value, + really recompute the menubar from the value. */ + if (! NILP (Vlucid_menu_bar_dirty_flag)) + call0 (Qrecompute_lucid_menubar); + safe_run_hooks (Qmenu_bar_update_hook); + fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); + + items = FRAME_MENU_BAR_ITEMS (f); + + /* Save the frame's previous menu bar contents data. */ + if (previous_menu_items_used) + memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents, + previous_menu_items_used * word_size); + + /* Fill in menu_items with the current menu bar contents. + This can evaluate Lisp code. */ + save_menu_items (); + + menu_items = f->menu_bar_vector; + menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; + subitems = ASIZE (items) / 4; + submenu_start = alloca ((subitems + 1) * sizeof *submenu_start); + submenu_end = alloca (subitems * sizeof *submenu_end); + submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes); + submenu_top_level_items = alloca (subitems + * sizeof *submenu_top_level_items); + init_menu_items (); + for (i = 0; i < subitems; i++) + { + Lisp_Object key, string, maps; + + key = AREF (items, 4 * i); + string = AREF (items, 4 * i + 1); + maps = AREF (items, 4 * i + 2); + if (NILP (string)) + break; + + submenu_start[i] = menu_items_used; + + menu_items_n_panes = 0; + submenu_top_level_items[i] + = parse_single_submenu (key, string, maps); + submenu_n_panes[i] = menu_items_n_panes; + + submenu_end[i] = menu_items_used; + } + + submenu_start[i] = -1; + finish_menu_items (); + + /* Convert menu_items into widget_value trees + to display the menu. This cannot evaluate Lisp code. */ + + wv = make_widget_value ("menubar", NULL, true, Qnil); + wv->button_type = BUTTON_TYPE_NONE; + first_wv = wv; + + for (i = 0; submenu_start[i] >= 0; i++) + { + menu_items_n_panes = submenu_n_panes[i]; + wv = digest_single_submenu (submenu_start[i], submenu_end[i], + submenu_top_level_items[i]); + if (prev_wv) + prev_wv->next = wv; + else + first_wv->contents = wv; + /* Don't set wv->name here; GC during the loop might relocate it. */ + wv->enabled = true; + wv->button_type = BUTTON_TYPE_NONE; + prev_wv = wv; + } + + set_buffer_internal_1 (prev); + + /* If there has been no change in the Lisp-level contents + of the menu bar, skip redisplaying it. Just exit. */ + + /* Compare the new menu items with the ones computed last time. */ + for (i = 0; i < previous_menu_items_used; i++) + if (menu_items_used == i + || (!EQ (previous_items[i], AREF (menu_items, i)))) + break; + if (i == menu_items_used && i == previous_menu_items_used && i != 0) + { + /* The menu items have not changed. Don't bother updating + the menus in any form, since it would be a no-op. */ + free_menubar_widget_value_tree (first_wv); + discard_menu_items (); + unbind_to (specpdl_count, Qnil); + return; + } + + /* The menu items are different, so store them in the frame. */ + fset_menu_bar_vector (f, menu_items); + f->menu_bar_items_used = menu_items_used; + + /* This undoes save_menu_items. */ + unbind_to (specpdl_count, Qnil); + + /* Now GC cannot happen during the lifetime of the widget_value, + so it's safe to store data from a Lisp_String. */ + wv = first_wv->contents; + for (i = 0; i < ASIZE (items); i += 4) + { + Lisp_Object string; + string = AREF (items, i + 1); + if (NILP (string)) + break; + wv->name = SSDATA (string); + update_submenu_strings (wv->contents); + wv = wv->next; + } + + } + else + { + /* Make a widget-value tree containing + just the top level menu bar strings. */ + + wv = make_widget_value ("menubar", NULL, true, Qnil); + wv->button_type = BUTTON_TYPE_NONE; + first_wv = wv; + + items = FRAME_MENU_BAR_ITEMS (f); + for (i = 0; i < ASIZE (items); i += 4) + { + Lisp_Object string; + + string = AREF (items, i + 1); + if (NILP (string)) + break; + + wv = make_widget_value (SSDATA (string), NULL, true, Qnil); + wv->button_type = BUTTON_TYPE_NONE; + /* This prevents lwlib from assuming this + menu item is really supposed to be empty. */ + /* The intptr_t cast avoids a warning. + This value just has to be different from small integers. */ + wv->call_data = (void *) (intptr_t) (-1); + + if (prev_wv) + prev_wv->next = wv; + else + first_wv->contents = wv; + prev_wv = wv; + } + + /* Forget what we thought we knew about what is in the + detailed contents of the menu bar menus. + Changing the top level always destroys the contents. */ + f->menu_bar_items_used = 0; + } + + block_input(); + + xg_crazy_callback_abort = true; + if (menubar_widget) + { + /* The fourth arg is DEEP_P, which says to consider the entire + menu trees we supply, rather than just the menu bar item names. */ + xg_modify_menubar_widgets (menubar_widget, + f, + first_wv, + deep_p, + G_CALLBACK (menubar_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); + } + else + { + menubar_widget + = xg_create_widget ("menubar", "menubar", f, first_wv, + G_CALLBACK (menubar_selection_callback), + G_CALLBACK (popup_deactivate_callback), + G_CALLBACK (menu_highlight_callback)); + + f->output_data.pgtk->menubar_widget = menubar_widget; + } + + free_menubar_widget_value_tree (first_wv); + xg_update_frame_menubar (f); + + xg_crazy_callback_abort = false; + + unblock_input (); +} + + + +/* Called from Fx_create_frame to create the initial menubar of a frame + before it is mapped, so that the window is mapped with the menubar already + there instead of us tacking it on later and thrashing the window after it + is visible. */ + +void +initialize_frame_menubar (struct frame *f) +{ + /* This function is called before the first chance to redisplay + the frame. It has to be, so the frame will have the right size. */ + fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f))); + set_frame_menubar (f, true, true); +} + + +void pgtk_activate_menubar (struct frame *f) +{ + set_frame_menubar(f, false, false); + + /* f->output_data.pgtk->menubar_active = 1; */ +} + + +Lisp_Object +pgtk_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) +{ + Lisp_Object tem; + + block_input (); + + + unblock_input (); + + // not implemented. + return Qnil; +} + +DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i", + doc: /* Start key navigation of the menu bar in FRAME. +This initially opens the first menu bar item and you can then navigate with the +arrow keys, select a menu entry with the return key or cancel with the +escape key. If FRAME has no menu bar this function does nothing. + +If FRAME is nil or not given, use the selected frame. */) + (Lisp_Object frame) +{ + GtkWidget *menubar; + struct frame *f; + + block_input (); + f = decode_window_system_frame (frame); + + if (FRAME_EXTERNAL_MENU_BAR (f)) + set_frame_menubar (f, false, true); + + menubar = FRAME_X_OUTPUT (f)->menubar_widget; + if (menubar) + { + /* Activate the first menu. */ + GList *children = gtk_container_get_children (GTK_CONTAINER (menubar)); + + if (children) + { + g_signal_emit_by_name (children->data, "activate_item"); + g_list_free (children); + } + } + unblock_input (); + + return Qnil; +} + + +static const char * button_names [] = { + "button1", "button2", "button3", "button4", "button5", + "button6", "button7", "button8", "button9", "button10" }; + +extern Lisp_Object +pgtk_dialog_show (struct frame *f, Lisp_Object title, + Lisp_Object header, char **error) +{ + return Qnil; +} + +/* The following is used by delayed window autoselection. */ + +DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0, + doc: /* SKIP: real doc in xmenu.c. */) + (void) +{ + struct frame *f; + f = SELECTED_FRAME (); + // return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil; + return Qnil; +} + +void +syms_of_pgtkmenu (void) +{ + // current_popup_menu = NULL; + // PDUMPER_IGNORE (current_popup_menu); + + DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); + DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog"); + + defsubr (&Smenu_or_popup_active_p); +} diff --git a/src/pgtkterm.c b/src/pgtkterm.c index a380c11eb1..ed8d7e841b 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -4253,14 +4253,6 @@ pgtk_fullscreen_hook (struct frame *f) } } -static Lisp_Object -pgtk_menu_show (struct frame *f, int x, int y, int menuflags, - Lisp_Object title, const char **error_name) -{ - // not implemented. - return Qnil; -} - /* This function is called when the last frame on a display is deleted. */ void pgtk_delete_terminal (struct terminal *terminal) @@ -4332,7 +4324,8 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; terminal->fullscreen_hook = pgtk_fullscreen_hook; terminal->menu_show_hook = pgtk_menu_show; - // terminal->popup_dialog_hook = pgtk_popup_dialog; + terminal->activate_menubar_hook = pgtk_activate_menubar; + terminal->popup_dialog_hook = pgtk_popup_dialog; terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar; terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar; terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars; diff --git a/src/pgtkterm.h b/src/pgtkterm.h index d14525e740..10dc9fc979 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -548,6 +548,12 @@ extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); extern void pgtk_cr_destroy_surface(struct frame *f); +/* Defined in pgtkmenu.c */ +extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents); +extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, Lisp_Object header, char **error); +extern void initialize_frame_menubar (struct frame *); + + /* Symbol initializations implemented in each pgtk sources. */ extern void syms_of_pgtkterm (void); extern void syms_of_pgtkfns (void); diff --git a/src/xdisp.c b/src/xdisp.c index e722a75780..c523111fbd 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25028,6 +25028,11 @@ display_menu_bar (struct window *w) if (FRAME_W32_P (f)) return; #endif +#if defined (HAVE_PGTK) + if (FRAME_PGTK_P (f)) + return; +#endif + #if defined (USE_X_TOOLKIT) || defined (USE_GTK) if (FRAME_X_P (f)) return; commit 12cc104cd54dd80a9bc1d391a256de49f4b77077 Author: Yuuki Harano Date: Fri May 3 17:20:47 2019 +0900 Cleanup x_* to gui_ to match upstream work * ../src/pgtkterm.h (struct pgtk_display_info): * ../src/pgtkterm.c (mark_pgtkterm, x_free_frame_resources) (pgtk_update_window_end, pgtk_mouse_position) (pgtk_redisplay_interface, pgtk_query_frame_background_color) (pgtk_delete_terminal, pgtk_create_terminal) (pgtk_query_frame_background_color, frame_highlight) (motion_notify_event, button_event, scroll_event): * ../src/pgtkfns.c (x_set_cursor_color, x_icon) (pgtk_frame_parm_handlers, x_default_font_parameter) (Fx_create_frame): "for the time being, commit" -- rename x->gui, frame_X_X(f) macros ひとまず commit。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index dd450a40bf..ce70202834 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -234,8 +234,8 @@ x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (FRAME_VISIBLE_P (f)) { - x_update_cursor (f, false); - x_update_cursor (f, true); + gui_update_cursor (f, false); + gui_update_cursor (f, true); } } @@ -349,7 +349,7 @@ x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) name; names set this way will never override names set by the user's lisp code. */ void -x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { PGTK_TRACE ("x_implicitly_set_name"); @@ -643,8 +643,8 @@ x_icon (struct frame *f, Lisp_Object parms) FRAME_X_OUTPUT(f)->icon_left = -1; /* Set the position of the icon. */ - icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); - icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); + icon_x = gui_display_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); + icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) { CHECK_NUMBER (icon_x); @@ -715,11 +715,11 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old { /* Here (xfwm) override_redirect can be changed for invisible frames only. */ - x_make_frame_invisible (f); + pgtk_make_frame_invisible (f); xg_set_override_redirect (f, new_value); - x_make_frame_visible (f); + pgtk_make_frame_visible (f); FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value); } } @@ -727,41 +727,41 @@ x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old /* Note: see frame.c for template, also where generic functions are impl */ frame_parm_handler pgtk_frame_parm_handlers[] = { - x_set_autoraise, /* generic OK */ - x_set_autolower, /* generic OK */ + gui_set_autoraise, /* generic OK */ + gui_set_autolower, /* generic OK */ x_set_background_color, 0, /* x_set_border_color, may be impossible under Nextstep */ 0, /* x_set_border_width, may be impossible under Nextstep */ x_set_cursor_color, x_set_cursor_type, - x_set_font, /* generic OK */ + gui_set_font, /* generic OK */ x_set_foreground_color, x_set_icon_name, x_set_icon_type, x_set_internal_border_width, /* generic OK */ - x_set_right_divider_width, - x_set_bottom_divider_width, + gui_set_right_divider_width, + gui_set_bottom_divider_width, x_set_menu_bar_lines, x_set_mouse_color, x_explicitly_set_name, - x_set_scroll_bar_width, /* generic OK */ - x_set_scroll_bar_height, /* generic OK */ + gui_set_scroll_bar_width, /* generic OK */ + gui_set_scroll_bar_height, /* generic OK */ x_set_title, - x_set_unsplittable, /* generic OK */ - x_set_vertical_scroll_bars, /* generic OK */ - x_set_horizontal_scroll_bars, /* generic OK */ - x_set_visibility, /* generic OK */ + gui_set_unsplittable, /* generic OK */ + gui_set_vertical_scroll_bars, /* generic OK */ + gui_set_horizontal_scroll_bars, /* generic OK */ + gui_set_visibility, /* generic OK */ x_set_tool_bar_lines, 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */ 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */ - x_set_screen_gamma, /* generic OK */ - x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ - x_set_left_fringe, /* generic OK */ - x_set_right_fringe, /* generic OK */ + gui_set_screen_gamma, /* generic OK */ + gui_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ + gui_set_left_fringe, /* generic OK */ + gui_set_right_fringe, /* generic OK */ 0, /* x_set_wait_for_wm, will ignore */ - x_set_fullscreen, /* generic OK */ - x_set_font_backend, /* generic OK */ - x_set_alpha, + gui_set_fullscreen, /* generic OK */ + gui_set_font_backend, /* generic OK */ + gui_set_alpha, 0, /* x_set_sticky */ 0, /* x_set_tool_bar_position */ 0, /* x_set_inhibit_double_buffering */ @@ -772,7 +772,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = x_set_no_accept_focus, x_set_z_group, x_set_override_redirect, - x_set_no_special_glyphs, + gui_set_no_special_glyphs, }; @@ -846,7 +846,7 @@ static void x_default_font_parameter (struct frame *f, Lisp_Object parms) { struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL, + Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font = Qnil; if (EQ (font_param, Qunbound)) @@ -864,7 +864,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) if (NILP (font)) font = !NILP (font_param) ? font_param - : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING); + : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING); if (! FONTP (font) && ! STRINGP (font)) { @@ -898,11 +898,11 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) /* Remember the explicit font parameter, so we can re-apply it after we've applied the `default' face settings. */ AUTO_FRAME_ARG (arg, Qfont_parameter, font_param); - x_set_frame_parameters (f, arg); + gui_set_frame_parameters (f, arg); } /* This call will make X resources override any system font setting. */ - x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); } /* ========================================================================== @@ -942,9 +942,9 @@ This function is an internal primitive--use `make-frame' instead. */) until we know if this frame has a specified name. */ Vx_resource_name = Vinvocation_name; - display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); + display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); if (EQ (display, Qunbound)) - display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); + display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); if (EQ (display, Qunbound)) display = Qnil; dpyinfo = check_pgtk_display_info (display); @@ -953,7 +953,7 @@ This function is an internal primitive--use `make-frame' instead. */) if (!dpyinfo->terminal->name) error ("Terminal is not live, can't create new frames on it"); - name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); + name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) && ! EQ (name, Qunbound) && ! NILP (name)) @@ -963,14 +963,14 @@ This function is an internal primitive--use `make-frame' instead. */) Vx_resource_name = name; /* See if parent window is specified. */ - parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); + parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); if (EQ (parent, Qunbound)) parent = Qnil; if (! NILP (parent)) CHECK_NUMBER (parent); frame = Qnil; - tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer", + tem = gui_display_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer", RES_TYPE_SYMBOL); if (EQ (tem, Qnone) || NILP (tem)) f = make_frame_without_minibuffer (Qnil, kb, display); @@ -984,7 +984,7 @@ This function is an internal primitive--use `make-frame' instead. */) else f = make_frame (true); - parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, + parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, RES_TYPE_SYMBOL); /* Accept parent-frame iff parent-id was not specified. */ if (!NILP (parent) @@ -998,7 +998,7 @@ This function is an internal primitive--use `make-frame' instead. */) fset_parent_frame (f, parent_frame); store_frame_param (f, Qparent_frame, parent_frame); - if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, + if (!NILP (tem = (gui_display_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN))) && !(EQ (tem, Qunbound))) undecorated = true; @@ -1006,7 +1006,7 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_UNDECORATED (f) = undecorated; store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil); - if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL, + if (!NILP (tem = (gui_display_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN))) && !(EQ (tem, Qunbound))) override_redirect = true; @@ -1032,7 +1032,7 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_X_OUTPUT(f)->black_relief.pixel = -1; fset_icon_name (f, - x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", + gui_display_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING)); if (! STRINGP (f->icon_name)) fset_icon_name (f, Qnil); @@ -1113,7 +1113,7 @@ This function is an internal primitive--use `make-frame' instead. */) #endif /* GLYPH_DEBUG */ #endif - x_default_parameter (f, parms, Qfont_backend, Qnil, + gui_default_parameter (f, parms, Qfont_backend, Qnil, "fontBackend", "FontBackend", RES_TYPE_STRING); /* Extract the window parameters from the supplied values @@ -1129,7 +1129,7 @@ This function is an internal primitive--use `make-frame' instead. */) #if 0 if (! FRAME_X_EMBEDDED_P (f)) #endif - x_default_parameter (f, parms, Qborder_width, make_fixnum (0), + gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), "borderWidth", "BorderWidth", RES_TYPE_NUMBER); /* This defaults to 1 in order to match xterm. We recognize either @@ -1139,45 +1139,45 @@ This function is an internal primitive--use `make-frame' instead. */) { Lisp_Object value; - value = x_get_arg (dpyinfo, parms, Qinternal_border_width, + value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); if (! EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } - x_default_parameter (f, parms, Qinternal_border_width, + gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (0), "internalBorderWidth", "internalBorderWidth", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), + gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), + gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qvertical_scroll_bars, + gui_default_parameter (f, parms, Qvertical_scroll_bars, Qright, "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); - x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, + gui_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, "horizontalScrollBars", "ScrollBars", RES_TYPE_SYMBOL); /* Also do the stuff which must be set before the window exists. */ - x_default_parameter (f, parms, Qforeground_color, build_string ("black"), + gui_default_parameter (f, parms, Qforeground_color, build_string ("black"), "foreground", "Foreground", RES_TYPE_STRING); - x_default_parameter (f, parms, Qbackground_color, build_string ("white"), + gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), "background", "Background", RES_TYPE_STRING); - x_default_parameter (f, parms, Qmouse_color, build_string ("black"), + gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), "pointerColor", "Foreground", RES_TYPE_STRING); - x_default_parameter (f, parms, Qborder_color, build_string ("black"), + gui_default_parameter (f, parms, Qborder_color, build_string ("black"), "borderColor", "BorderColor", RES_TYPE_STRING); - x_default_parameter (f, parms, Qscreen_gamma, Qnil, + gui_default_parameter (f, parms, Qscreen_gamma, Qnil, "screenGamma", "ScreenGamma", RES_TYPE_FLOAT); - x_default_parameter (f, parms, Qline_spacing, Qnil, + gui_default_parameter (f, parms, Qline_spacing, Qnil, "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qleft_fringe, Qnil, + gui_default_parameter (f, parms, Qleft_fringe, Qnil, "leftFringe", "LeftFringe", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qright_fringe, Qnil, + gui_default_parameter (f, parms, Qright_fringe, Qnil, "rightFringe", "RightFringe", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qno_special_glyphs, Qnil, + gui_default_parameter (f, parms, Qno_special_glyphs, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); #if 0 @@ -1189,7 +1189,7 @@ This function is an internal primitive--use `make-frame' instead. */) "ScrollBarBackground", false); #endif - /* Init faces before x_default_parameter is called for the + /* Init faces before gui_default_parameter is called for the scroll-bar-width parameter because otherwise we end up in init_iterator with a null face cache, which should not happen. */ init_frame_faces (f); @@ -1206,10 +1206,10 @@ This function is an internal primitive--use `make-frame' instead. */) Also process `min-width' and `min-height' parameters right here because `frame-windows-min-size' needs them. */ - tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER); + tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER); if (NUMBERP (tem)) store_frame_param (f, Qmin_width, tem); - tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER); + tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER); if (NUMBERP (tem)) store_frame_param (f, Qmin_height, tem); adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), @@ -1221,32 +1221,32 @@ This function is an internal primitive--use `make-frame' instead. */) here; they are processed specially at startup, and reflected in the values of the mode variables. */ - x_default_parameter (f, parms, Qmenu_bar_lines, + gui_default_parameter (f, parms, Qmenu_bar_lines, NILP (Vmenu_bar_mode) ? make_fixnum (0) : make_fixnum (1), NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qtool_bar_lines, + gui_default_parameter (f, parms, Qtool_bar_lines, NILP (Vtool_bar_mode) ? make_fixnum (0) : make_fixnum (1), NULL, NULL, RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qbuffer_predicate, Qnil, + gui_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL); - x_default_parameter (f, parms, Qtitle, Qnil, + gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title", RES_TYPE_STRING); - x_default_parameter (f, parms, Qwait_for_wm, Qt, + gui_default_parameter (f, parms, Qwait_for_wm, Qt, "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); - x_default_parameter (f, parms, Qtool_bar_position, + gui_default_parameter (f, parms, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); - x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, + gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, "inhibitDoubleBuffering", "InhibitDoubleBuffering", RES_TYPE_BOOLEAN); /* Compute the size of the X window. */ - window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height); + window_prompting = gui_figure_window_size (f, parms, true, &x_width, &x_height); - tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); + tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || EQ (tem, Qt); #if 0 @@ -1292,22 +1292,22 @@ This function is an internal primitive--use `make-frame' instead. */) /* We need to do this after creating the X window, so that the icon-creation functions can say whose icon they're describing. */ - x_default_parameter (f, parms, Qicon_type, Qt, + gui_default_parameter (f, parms, Qicon_type, Qt, "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN); - x_default_parameter (f, parms, Qauto_raise, Qnil, + gui_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); - x_default_parameter (f, parms, Qauto_lower, Qnil, + gui_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); - x_default_parameter (f, parms, Qcursor_type, Qbox, + gui_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType", RES_TYPE_SYMBOL); - x_default_parameter (f, parms, Qscroll_bar_width, Qnil, + gui_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qscroll_bar_height, Qnil, + gui_default_parameter (f, parms, Qscroll_bar_height, Qnil, "scrollBarHeight", "ScrollBarHeight", RES_TYPE_NUMBER); - x_default_parameter (f, parms, Qalpha, Qnil, + gui_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha", RES_TYPE_NUMBER); #if 0 @@ -1322,9 +1322,9 @@ This function is an internal primitive--use `make-frame' instead. */) } #endif - x_default_parameter (f, parms, Qno_focus_on_map, Qnil, + gui_default_parameter (f, parms, Qno_focus_on_map, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); - x_default_parameter (f, parms, Qno_accept_focus, Qnil, + gui_default_parameter (f, parms, Qno_accept_focus, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); #if defined (USE_X_TOOLKIT) || defined (USE_GTK) @@ -1348,7 +1348,7 @@ This function is an internal primitive--use `make-frame' instead. */) #endif /* USE_X_TOOLKIT || USE_GTK */ /* Consider frame official, now. */ - f->can_x_set_window_size = true; + f->can_set_window_size = true; if (x_width > 0) SET_FRAME_WIDTH (f, x_width); @@ -1368,7 +1368,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* Process fullscreen parameter here in the hope that normalizing a fullheight/fullwidth frame will produce the size set by the last adjust_frame_size call. */ - x_default_parameter (f, parms, Qfullscreen, Qnil, + gui_default_parameter (f, parms, Qfullscreen, Qnil, "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); /* Make the window appear on the frame and enable display, unless @@ -1377,27 +1377,27 @@ This function is an internal primitive--use `make-frame' instead. */) if (!FRAME_X_OUTPUT(f)->explicit_parent) { Lisp_Object visibility - = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); + = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); if (EQ (visibility, Qicon)) - x_iconify_frame (f); + pgtk_iconify_frame (f); else { if (EQ (visibility, Qunbound)) visibility = Qt; if (!NILP (visibility)) - x_make_frame_visible (f); + pgtk_make_frame_visible (f); } store_frame_param (f, Qvisibility, visibility); } /* Works iff frame has been already mapped. */ - x_default_parameter (f, parms, Qskip_taskbar, Qnil, + gui_default_parameter (f, parms, Qskip_taskbar, Qnil, NULL, NULL, RES_TYPE_BOOLEAN); /* The `z-group' parameter works only for visible frames. */ - x_default_parameter (f, parms, Qz_group, Qnil, + gui_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); /* Initialize `default-minibuffer-frame' in case this is the first @@ -1408,7 +1408,7 @@ This function is an internal primitive--use `make-frame' instead. */) kset_default_minibuffer_frame (kb, frame); /* All remaining specified parameters, which have not been "used" - by x_get_arg and friends, now go in the misc. alist of the frame. */ + by gui_display_get_arg and friends, now go in the misc. alist of the frame. */ for (tem = parms; CONSP (tem); tem = XCDR (tem)) if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) fset_param_alist (f, Fcons (XCAR (tem), f->param_alist)); @@ -1809,7 +1809,7 @@ check_x_display_info (Lisp_Object frame) void -x_set_scroll_bar_default_width (struct frame *f) +pgtk_set_scroll_bar_default_width (struct frame *f) { int unit = FRAME_COLUMN_WIDTH (f); int minw = xg_get_default_scrollbar_width (f); @@ -1819,7 +1819,7 @@ x_set_scroll_bar_default_width (struct frame *f) } void -x_set_scroll_bar_default_height (struct frame *f) +pgtk_set_scroll_bar_default_height (struct frame *f) { int height = FRAME_LINE_HEIGHT (f); int min_height = xg_get_default_scrollbar_height (f); @@ -1829,8 +1829,8 @@ x_set_scroll_bar_default_height (struct frame *f) } /* terms impl this instead of x-get-resource directly */ -char * -x_get_string_resource (XrmDatabase rdb, const char *name, const char *class) +const char * +pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class) { /* remove appname prefix; TODO: allow for !="Emacs" */ const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0); @@ -2239,7 +2239,7 @@ x_hide_tip (bool delete) tip_frame = Qnil; } else - x_make_frame_invisible (XFRAME (tip_frame)); + pgtk_make_frame_invisible (XFRAME (tip_frame)); was_open = Qt; } diff --git a/src/pgtkgui.h b/src/pgtkgui.h index 78e1da77d8..27e94b213d 100644 --- a/src/pgtkgui.h +++ b/src/pgtkgui.h @@ -69,7 +69,7 @@ typedef int Window; typedef struct _GdkDisplay Display; /* Xism */ -typedef Lisp_Object XrmDatabase; +typedef void *XrmDatabase; /* some sort of attempt to normalize rectangle handling.. seems a bit much diff --git a/src/pgtkterm.c b/src/pgtkterm.c index d84e3b1ae5..a380c11eb1 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -134,12 +134,12 @@ mark_pgtkterm(void) #if false /* marked in alloc.c:compact_font_caches() */ mark_object (dpyinfo->name_list_element); #endif - mark_object (dpyinfo->xrdb); + mark_object (dpyinfo->rdb); } } char * -x_get_keysym_name (int keysym) +get_keysym_name (int keysym) /* -------------------------------------------------------------------------- Called by keyboard.c. Not sure if the return val is important, except that it be unique. @@ -181,7 +181,7 @@ x_free_frame_resources (struct frame *f) do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false) CLEAR_IF_EQ(x_focus_frame); - CLEAR_IF_EQ(x_highlight_frame); + CLEAR_IF_EQ(highlight_frame); CLEAR_IF_EQ(x_focus_event_frame); CLEAR_IF_EQ(last_mouse_frame); CLEAR_IF_EQ(last_mouse_motion_frame); @@ -407,16 +407,16 @@ pgtk_set_window_size (struct frame *f, } void -x_iconify_frame (struct frame *f) +pgtk_iconify_frame (struct frame *f) /* -------------------------------------------------------------------------- External: Iconify window -------------------------------------------------------------------------- */ { - PGTK_TRACE("x_iconify_frame"); + PGTK_TRACE("pgtk_iconify_frame"); /* Don't keep the highlight on an invisible frame. */ - if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f) - FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0; + if (FRAME_DISPLAY_INFO (f)->highlight_frame == f) + FRAME_DISPLAY_INFO (f)->highlight_frame = 0; if (FRAME_ICONIFIED_P (f)) return; @@ -469,12 +469,12 @@ x_iconify_frame (struct frame *f) } void -x_make_frame_visible (struct frame *f) +pgtk_make_frame_visible (struct frame *f) /* -------------------------------------------------------------------------- External: Show the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE("x_make_frame_visible"); + PGTK_TRACE("pgtk_make_frame_visible"); #if 0 NSTRACE ("x_make_frame_visible"); /* XXX: at some points in past this was not needed, as the only place that @@ -523,12 +523,12 @@ x_make_frame_visible (struct frame *f) void -x_make_frame_invisible (struct frame *f) +pgtk_make_frame_invisible (struct frame *f) /* -------------------------------------------------------------------------- External: Hide the window (X11 semantics) -------------------------------------------------------------------------- */ { - PGTK_TRACE("x_make_frame_invisible"); + PGTK_TRACE("pgtk_make_frame_invisible"); #if 0 NSView *view; NSTRACE ("x_make_frame_invisible"); @@ -541,9 +541,9 @@ x_make_frame_invisible (struct frame *f) } static Lisp_Object -x_new_font (struct frame *f, Lisp_Object font_object, int fontset) +pgtk_new_font (struct frame *f, Lisp_Object font_object, int fontset) { - PGTK_TRACE("x_new_font"); + PGTK_TRACE("pgtk_new_font"); struct font *font = XFONT_OBJECT (font_object); int font_ascent, font_descent; @@ -730,7 +730,7 @@ pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) dpyinfo->color_p = 1; dpyinfo->n_planes = 32; dpyinfo->root_window = 42; /* a placeholder.. */ - dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL; + dpyinfo->highlight_frame = dpyinfo->x_focus_frame = NULL; dpyinfo->n_fonts = 0; dpyinfo->smallest_font_height = 1; dpyinfo->smallest_char_width = 1; @@ -2606,6 +2606,7 @@ pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, PGTK_TRACE("draw_window_cursor: %d, %d, %d, %d, %d, %d.", x, y, cursor_type, cursor_width, on_p, active_p); struct frame *f = XFRAME (WINDOW_FRAME (w)); + PGTK_TRACE("%p\n", f->output_data.pgtk); if (on_p) { @@ -2735,7 +2736,7 @@ pgtk_scroll_run (struct window *w, struct run *run) block_input (); /* Cursor off. Will be switched on again in x_update_window_end. */ - x_clear_cursor (w); + gui_clear_cursor (w); { cairo_rectangle_t src_rect = { x, from_y, width, height }; @@ -2913,9 +2914,9 @@ pgtk_update_window_end (struct window *w, bool cursor_on_p, if (draw_window_fringes (w, true)) { if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) - x_draw_right_divider (w); + gui_draw_right_divider (w); else - x_draw_vertical_border (w); + gui_draw_vertical_border (w); } unblock_input (); @@ -2989,7 +2990,7 @@ pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, seat = gdk_display_get_default_seat(dpyinfo->gdpy); device = gdk_seat_get_pointer(seat); - if (x_mouse_grabbed (dpyinfo)) { + if (gui_mouse_grabbed (dpyinfo)) { GdkWindow *win; GdkModifierType mask; /* get x, y relative to edit window of f1. */ @@ -3279,18 +3280,18 @@ extern frame_parm_handler pgtk_frame_parm_handlers[]; static struct redisplay_interface pgtk_redisplay_interface = { pgtk_frame_parm_handlers, - x_produce_glyphs, - x_write_glyphs, - x_insert_glyphs, - x_clear_end_of_line, + gui_produce_glyphs, + gui_write_glyphs, + gui_insert_glyphs, + gui_clear_end_of_line, pgtk_scroll_run, pgtk_after_update_window_line, pgtk_update_window_begin, pgtk_update_window_end, pgtk_flush_display, - x_clear_window_mouse_face, - x_get_glyph_overhangs, - x_fix_overlapping_area, + gui_clear_window_mouse_face, + gui_get_glyph_overhangs, + gui_fix_overlapping_area, pgtk_draw_fringe_bitmap, pgtk_define_fringe_bitmap, pgtk_destroy_fringe_bitmap, @@ -3298,6 +3299,7 @@ static struct redisplay_interface pgtk_redisplay_interface = pgtk_draw_glyph_string, pgtk_define_frame_cursor, pgtk_clear_frame_area, + pgtk_clear_under_internal_border, pgtk_draw_window_cursor, pgtk_draw_vertical_window_border, pgtk_draw_window_divider, @@ -4275,7 +4277,7 @@ pgtk_delete_terminal (struct terminal *terminal) /* Normally, the display is available... */ if (dpyinfo->gdpy) { - x_destroy_all_bitmaps (dpyinfo); + image_destroy_all_bitmaps (dpyinfo); xg_display_close (dpyinfo->gdpy); @@ -4336,8 +4338,16 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo) terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars; terminal->redeem_scroll_bar_hook = pgtk_redeem_scroll_bar; terminal->judge_scroll_bars_hook = pgtk_judge_scroll_bars; + terminal->get_string_resource_hook = pgtk_get_string_resource; terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = pgtk_delete_terminal; + terminal->query_frame_background_color = pgtk_query_frame_background_color; + terminal->defined_color_hook = pgtk_defined_color; + terminal->set_new_font_hook = pgtk_new_font; + terminal->implicit_set_name_hook = pgtk_implicitly_set_name; + terminal->iconify_frame_hook = pgtk_iconify_frame; + terminal->set_scroll_bar_default_width_hook = pgtk_set_scroll_bar_default_width; + terminal->set_scroll_bar_default_height_hook = pgtk_set_scroll_bar_default_height; terminal->set_window_size_hook = pgtk_set_window_size; terminal->query_colors = pgtk_query_colors; terminal->get_focus_frame = x_get_focus_frame; @@ -5075,7 +5085,7 @@ frame_highlight (struct frame *f) x_uncatch_errors (); #endif unblock_input (); - x_update_cursor (f, true); + gui_update_cursor (f, true); #if 0 x_set_frame_alpha (f); #endif @@ -5097,7 +5107,7 @@ frame_unhighlight (struct frame *f) x_uncatch_errors (); #endif unblock_input (); - x_update_cursor (f, true); + gui_update_cursor (f, true); #if 0 x_set_frame_alpha (f); #endif @@ -5107,29 +5117,29 @@ frame_unhighlight (struct frame *f) static void x_frame_rehighlight (struct pgtk_display_info *dpyinfo) { - struct frame *old_highlight = dpyinfo->x_highlight_frame; + struct frame *old_highlight = dpyinfo->highlight_frame; if (dpyinfo->x_focus_frame) { - dpyinfo->x_highlight_frame + dpyinfo->highlight_frame = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) : dpyinfo->x_focus_frame); - if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame)) + if (! FRAME_LIVE_P (dpyinfo->highlight_frame)) { fset_focus_frame (dpyinfo->x_focus_frame, Qnil); - dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame; + dpyinfo->highlight_frame = dpyinfo->x_focus_frame; } } else - dpyinfo->x_highlight_frame = 0; + dpyinfo->highlight_frame = 0; - if (dpyinfo->x_highlight_frame != old_highlight) + if (dpyinfo->highlight_frame != old_highlight) { if (old_highlight) frame_unhighlight (old_highlight); - if (dpyinfo->x_highlight_frame) - frame_highlight (dpyinfo->x_highlight_frame); + if (dpyinfo->highlight_frame) + frame_highlight (dpyinfo->highlight_frame); } } @@ -5376,7 +5386,7 @@ motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); dpyinfo = FRAME_DISPLAY_INFO (frame); - f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame + f = (gui_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame : pgtk_any_window_to_frame(gtk_widget_get_window(widget))); hlinfo = MOUSE_HL_INFO (f); @@ -5545,7 +5555,7 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) x_display_set_last_user_time (dpyinfo, event->button.time); #endif - if (x_mouse_grabbed (dpyinfo)) + if (gui_mouse_grabbed (dpyinfo)) f = dpyinfo->last_mouse_frame; else { @@ -5558,7 +5568,7 @@ button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) into a parent frame with the child frame selected and `no-accept-focus' is not set, select the clicked frame. */ - struct frame *hf = dpyinfo->x_highlight_frame; + struct frame *hf = dpyinfo->highlight_frame; if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) { @@ -5635,7 +5645,7 @@ scroll_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); dpyinfo = FRAME_DISPLAY_INFO (frame); - if (x_mouse_grabbed (dpyinfo)) + if (gui_mouse_grabbed (dpyinfo)) f = dpyinfo->last_mouse_frame; else f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 6cd6da4ccb..d14525e740 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -168,7 +168,7 @@ struct pgtk_display_info Window root_window; /* Xism */ - XrmDatabase xrdb; + XrmDatabase rdb; /* The cursor to use for vertical scroll bars. */ Emacs_Cursor vertical_scroll_bar_cursor; @@ -180,7 +180,7 @@ struct pgtk_display_info mouse-face. */ Mouse_HLInfo mouse_highlight; - struct frame *x_highlight_frame; + struct frame *highlight_frame; struct frame *x_focus_frame; /* The last frame mentioned in a FocusIn or FocusOut event. This is @@ -384,6 +384,7 @@ enum /* This gives the pgtk_display_info structure for the display F is on. */ #define FRAME_X_OUTPUT(f) ((f)->output_data.pgtk) +#define FRAME_OUTPUT_DATA(f) FRAME_X_OUTPUT (f) #define FRAME_DISPLAY_INFO(f) (FRAME_X_OUTPUT(f)->display_info) #define FRAME_FOREGROUND_COLOR(f) (FRAME_X_OUTPUT(f)->foreground_color) @@ -397,6 +398,7 @@ enum /* aliases */ #define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET(f) #define FRAME_X_WINDOW(f) FRAME_GTK_WIDGET(f) +#define FRAME_NATIVE_WINDOW(f) FRAME_GTK_WIDGET(f) #define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO(f)->gdpy) @@ -500,6 +502,8 @@ extern char *pgtk_xlfd_to_fontname (const char *xlfd); /* Implemented in pgtkfns. */ extern void pgtk_set_doc_edited (void); extern const char *pgtk_get_defaults_value (const char *key); +extern const char *pgtk_get_string_resource (XrmDatabase rdb, const char *name, const char *class); +extern void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval); /* Color management implemented in pgtkterm. */ extern bool pgtk_defined_color (struct frame *f, commit ed1f7d1e2a5caae4d3d90c6a166ccc15f143f776 Author: Yuuki Harano Date: Wed Apr 3 22:14:28 2019 +0900 Simplify compilaiton condtion * ../src/menu.c (single_menu_item): change condition. diff --git a/src/menu.c b/src/menu.c index e4fda572cd..ebda2f242f 100644 --- a/src/menu.c +++ b/src/menu.c @@ -422,7 +422,7 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk AREF (item_properties, ITEM_PROPERTY_SELECTED), AREF (item_properties, ITEM_PROPERTY_HELP)); -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI) +#ifdef HAVE_EXT_MENU_BAR /* Display a submenu using the toolkit. */ if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)) && ! (NILP (map) || NILP (enabled))) commit 53cb4316396586ffaa91191af4ae9c55687444f2 Author: Yuuki Harano Date: Wed Apr 3 21:45:37 2019 +0900 replace listn with list. * ../src/pgtkfns.c (frame_geometry): replace listn with list. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index b08b81a885..dd450a40bf 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2390,29 +2390,28 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute) make_fixnum (native_bottom - internal_border_width)); else return - listn (CONSTYPE_HEAP, 10, - Fcons (Qouter_position, - Fcons (make_fixnum (f->left_pos), - make_fixnum (f->top_pos))), - Fcons (Qouter_size, - Fcons (make_fixnum (outer_width), - make_fixnum (outer_height))), - Fcons (Qexternal_border_size, - (fullscreen - ? Fcons (make_fixnum (0), make_fixnum (0)) - : Fcons (make_fixnum (border), make_fixnum (border)))), - Fcons (Qtitle_bar_size, - Fcons (make_fixnum (0), make_fixnum (title_height))), - Fcons (Qmenu_bar_external, Qnil), - Fcons (Qmenu_bar_size, Fcons (make_fixnum (0), make_fixnum (0))), - Fcons (Qtool_bar_external, - FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil), - Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)), - Fcons (Qtool_bar_size, - Fcons (make_fixnum (tool_bar_width), - make_fixnum (tool_bar_height))), - Fcons (Qinternal_border_width, - make_fixnum (internal_border_width))); + list (Fcons (Qouter_position, + Fcons (make_fixnum (f->left_pos), + make_fixnum (f->top_pos))), + Fcons (Qouter_size, + Fcons (make_fixnum (outer_width), + make_fixnum (outer_height))), + Fcons (Qexternal_border_size, + (fullscreen + ? Fcons (make_fixnum (0), make_fixnum (0)) + : Fcons (make_fixnum (border), make_fixnum (border)))), + Fcons (Qtitle_bar_size, + Fcons (make_fixnum (0), make_fixnum (title_height))), + Fcons (Qmenu_bar_external, Qnil), + Fcons (Qmenu_bar_size, Fcons (make_fixnum (0), make_fixnum (0))), + Fcons (Qtool_bar_external, + FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil), + Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)), + Fcons (Qtool_bar_size, + Fcons (make_fixnum (tool_bar_width), + make_fixnum (tool_bar_height))), + Fcons (Qinternal_border_width, + make_fixnum (internal_border_width))); } DEFUN ("pgtk-frame-geometry", Fpgtk_frame_geometry, Spgtk_frame_geometry, 0, 1, 0, commit a9c8a56ba1fdbb6645ddebdabbb826993b6dca23 Author: Yuuki Harano Date: Sat May 12 23:49:00 2018 +0900 Fix xdg-open handling * ../src/pgtkterm.c (pgtk_term_init, NUM_ARGV, pgtk_term_init): * ../lisp/net/browse-url.el (browse-url): xdg-open できなかったのを修正。 diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 8b245b0106..27a4f1be5a 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -888,8 +888,17 @@ If ARGS are omitted, the default is to pass ;; When connected to various displays, be careful to use the display of ;; the currently selected frame, rather than the original start display, ;; which may not even exist any more. - (if (stringp (frame-parameter nil 'display)) - (setenv "DISPLAY" (frame-parameter nil 'display))) + (let ((dpy (frame-parameter nil 'display)) + classname) + (if (stringp dpy) + (cond + ((featurep 'pgtk) + (setq classname (pgtk-backend-display-class)) + (if (equal classname "GdkWaylandDisplay") + (setenv "WAYLAND_DISPLAY" dpy) + (setenv "DISPLAY" dpy))) + (t + (setenv "DISPLAY" dpy))))) (if (functionp function) (apply function url args) (error "No suitable browser for URL %s" url)))) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 4f2c454237..d84e3b1ae5 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5846,6 +5846,9 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) struct pgtk_display_info *dpyinfo; static int x_initialized = 0; static unsigned x_display_id = 0; + static char *initial_display = NULL; + char *dpy_name; + Lisp_Object lisp_dpy_name = Qnil; block_input (); @@ -5861,6 +5864,11 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) ++x_initialized; } + dpy_name = SSDATA (display_name); + if (strlen(dpy_name) == 0 && initial_display != NULL) + dpy_name = initial_display; + lisp_dpy_name = build_string (dpy_name); + { #define NUM_ARGV 10 int argc; @@ -5870,7 +5878,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) if (x_initialized++ > 1) { - xg_display_open (SSDATA (display_name), &dpy); + xg_display_open (dpy_name, &dpy); } else { @@ -5883,10 +5891,10 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) argc = 0; argv[argc++] = initial_argv[0]; - if (strlen(SSDATA(display_name)) != 0) + if (strlen(dpy_name) != 0) { argv[argc++] = display_opt; - argv[argc++] = SSDATA (display_name); + argv[argc++] = dpy_name; } argv[argc++] = name_opt; @@ -5910,6 +5918,10 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) xg_initialize (); dpy = DEFAULT_GDK_DISPLAY (); + + initial_display = g_strdup (gdk_display_get_name(dpy)); + dpy_name = initial_display; + lisp_dpy_name = build_string(dpy_name); } } @@ -5929,8 +5941,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) struct pgtk_display_info *share; for (share = x_display_list; share; share = share->next) - if (same_x_server (SSDATA (XCAR (share->name_list_element)), - SSDATA (display_name))) + if (same_x_server (SSDATA (XCAR (share->name_list_element)), dpy_name)) break; if (share) terminal->kboard = share->terminal->kboard; @@ -5951,7 +5962,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->next = x_display_list; x_display_list = dpyinfo; - dpyinfo->name_list_element = Fcons (display_name, Qnil); + dpyinfo->name_list_element = Fcons (lisp_dpy_name, Qnil); dpyinfo->gdpy = dpy; /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */ @@ -5959,7 +5970,7 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) dpyinfo->smallest_char_width = 1; /* Set the name of the terminal. */ - terminal->name = xlispstrdup (display_name); + terminal->name = xlispstrdup (lisp_dpy_name); Lisp_Object system_name = Fsystem_name (); ptrdiff_t nbytes; commit 045e25278bdec3e08c3c069a537e4ae7a66de262 Author: Yuuki Harano Date: Sat Jan 13 20:27:11 2018 +0900 Add support for cursor_foreground_colors * ../src/pgtkterm.c (x_set_cursor_gc): * ../src/pgtkfns.c (x_set_cursor_color, Fx_create_frame) (syms_of_pgtkfns): * src/pgtkterm.h (struct pgtk_output): cursor_foreground_color 対応。 あんまり意味なかった感じ。 diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 67391fac86..b08b81a885 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -197,25 +197,49 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) static void x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { + unsigned long fore_pixel, pixel; + struct pgtk_output *x = f->output_data.pgtk; Emacs_Color col; - block_input (); - if (pgtk_lisp_to_color (arg, &col)) + if (!NILP (Vx_cursor_fore_pixel)) { - store_frame_param (f, Qcursor_color, oldval); - unblock_input (); - error ("Unknown color"); + if (pgtk_lisp_to_color(Vx_cursor_fore_pixel, &col)) + signal_error ("Undefined color", Vx_cursor_fore_pixel); + fore_pixel = col.pixel; } + else + fore_pixel = FRAME_BACKGROUND_PIXEL (f); - FRAME_CURSOR_COLOR (f) = col.pixel; + if (pgtk_lisp_to_color(arg, &col)) + signal_error ("Undefined color", arg); + pixel = col.pixel; - if (FRAME_VISIBLE_P (f)) + /* Make sure that the cursor color differs from the background color. */ + if (pixel == FRAME_BACKGROUND_PIXEL (f)) + { + pixel = x->mouse_color; + if (pixel == fore_pixel) + { + fore_pixel = FRAME_BACKGROUND_PIXEL (f); + } + } + + x->cursor_foreground_color = fore_pixel; + x->cursor_color = pixel; + + if (FRAME_X_WINDOW (f) != 0) { - x_update_cursor (f, 0); - x_update_cursor (f, 1); + x->cursor_xgcv.background = x->cursor_color; + x->cursor_xgcv.foreground = fore_pixel; + + if (FRAME_VISIBLE_P (f)) + { + x_update_cursor (f, false); + x_update_cursor (f, true); + } } + update_face_from_frame_parameter (f, Qcursor_color, arg); - unblock_input (); } @@ -1029,11 +1053,11 @@ This function is an internal primitive--use `make-frame' instead. */) FRAME_FOREGROUND_PIXEL (f) = -1; FRAME_BACKGROUND_PIXEL (f) = -1; FRAME_X_OUTPUT(f)->cursor_color = -1; + FRAME_X_OUTPUT(f)->cursor_foreground_color = -1; #if 0 - FRAME_X_OUTPUT(f)->cursor_foreground_pixel = -1; FRAME_X_OUTPUT(f)->border_pixel = -1; - FRAME_X_OUTPUT(f)->mouse_pixel = -1; #endif + FRAME_X_OUTPUT(f)->mouse_color = -1; black = build_string ("black"); FRAME_FOREGROUND_PIXEL (f) @@ -1042,14 +1066,14 @@ This function is an internal primitive--use `make-frame' instead. */) = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); FRAME_X_OUTPUT(f)->cursor_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); -#if 0 - FRAME_X_OUTPUT(f)->cursor_foreground_pixel + FRAME_X_OUTPUT(f)->cursor_foreground_color = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); +#if 0 FRAME_X_OUTPUT(f)->border_pixel = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); - FRAME_X_OUTPUT(f)->mouse_pixel - = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); #endif + FRAME_X_OUTPUT(f)->mouse_color + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); } /* Specify the parent under which to make this X window. */ @@ -2615,6 +2639,10 @@ syms_of_pgtkfns (void) DEFSYM (Qicon_title_format, "icon-title-format"); DEFSYM (Qdark, "dark"); + DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, + doc: /* A string indicating the foreground color of the cursor box. */); + Vx_cursor_fore_pixel = Qnil; + DEFVAR_LISP ("pgtk-icon-type-alist", Vpgtk_icon_type_alist, doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames. If the title of a frame matches REGEXP, then IMAGE.tiff is diff --git a/src/pgtkterm.c b/src/pgtkterm.c index a1c42eb274..4f2c454237 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -765,10 +765,8 @@ x_set_cursor_gc (struct glyph_string *s) if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; PGTK_TRACE("x_set_cursor_gc: 4. %08lx, %08lx.", xgcv.background, xgcv.foreground); -#if 0 if (xgcv.foreground == xgcv.background) - xgcv.foreground = FRAME_X_OUTPUT(s->f)->cursor_foreground_pixel; -#endif + xgcv.foreground = FRAME_X_OUTPUT(s->f)->cursor_foreground_color; if (xgcv.foreground == xgcv.background) xgcv.foreground = s->face->foreground; PGTK_TRACE("x_set_cursor_gc: 5. %08lx, %08lx.", xgcv.background, xgcv.foreground); diff --git a/src/pgtkterm.h b/src/pgtkterm.h index c01d846748..6cd6da4ccb 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -226,7 +226,6 @@ struct pgtk_output void *view; void *miniimage; #endif - unsigned long cursor_color; unsigned long foreground_color; unsigned long background_color; void *toolbar; @@ -269,6 +268,10 @@ struct pgtk_output value contains an ID of the fontset, else -1. */ int fontset; /* only used with font_backend */ + unsigned long mouse_color; + unsigned long cursor_color; + unsigned long cursor_foreground_color; + int icon_top; int icon_left; commit 1b621c8e3c1aa1dd71d39f080703292cde270446 Author: Yuuki Harano Date: Wed Jan 10 22:33:18 2018 +0900 Don't mark name_list_element as it's not required * ../src/pgtkterm.c (mark_pgtkterm): これは余分。 diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 61da7d6650..a1c42eb274 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -131,7 +131,9 @@ mark_pgtkterm(void) struct pgtk_display_info *dpyinfo; for (dpyinfo = x_display_list; dpyinfo != NULL; dpyinfo = dpyinfo->next) { +#if false /* marked in alloc.c:compact_font_caches() */ mark_object (dpyinfo->name_list_element); +#endif mark_object (dpyinfo->xrdb); } } commit f15c6a408d88c13943c935f71626fc208eafcfed Author: Yuuki Harano Date: Mon Jan 8 21:21:55 2018 +0900 Add set_skip_taskbar frame parm * src/pgtkfns.c (x_set_skip_taskbar, pgtk_frame_parm_handlers): Add set_skip_taskbar diff --git a/src/pgtkfns.c b/src/pgtkfns.c index aa46461d24..67391fac86 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -655,6 +655,26 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value } } +/** + * x_set_skip_taskbar: + * + * Set frame F's `skip-taskbar' parameter. If non-nil, this should + * remove F's icon from the taskbar associated with the display of F's + * window-system window and inhibit switching to F's window via + * -. If nil, lift these restrictions. + * + * Some window managers may not honor this parameter. + */ +static void +x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + if (!EQ (new_value, old_value)) + { + xg_set_skip_taskbar (f, new_value); + FRAME_SKIP_TASKBAR (f) = !NILP (new_value); + } +} + /** * x_set_override_redirect: * @@ -721,9 +741,9 @@ frame_parm_handler pgtk_frame_parm_handlers[] = 0, /* x_set_sticky */ 0, /* x_set_tool_bar_position */ 0, /* x_set_inhibit_double_buffering */ - x_set_undecorated + x_set_undecorated, 0, /* x_set_parent_frame, */ - 0, /* x_set_skip_taskbar */ + x_set_skip_taskbar, x_set_no_focus_on_map, x_set_no_accept_focus, x_set_z_group, commit b721cbc6a8c5f8672e2b47c3bda2f91b5976d349 Author: Yuuki Harano Date: Mon Jan 8 21:13:25 2018 +0900 Add set_undecorated frame parameter * src/pgtkfns.c (x_set_undecorated, pgtk_frame_parm_handlers): Add undecorated frame parameter handle diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 39f5887320..aa46461d24 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -633,6 +633,28 @@ x_icon (struct frame *f, Lisp_Object parms) #endif } +/** + * x_set_undecorated: + * + * Set frame F's `undecorated' parameter. If non-nil, F's window-system + * window is drawn without decorations, title, minimize/maximize boxes + * and external borders. This usually means that the window cannot be + * dragged, resized, iconified, maximized or deleted with the mouse. If + * nil, draw the frame with all the elements listed above unless these + * have been suspended via window manager settings. + * + * Some window managers may not honor this parameter. + */ +static void +x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + if (!EQ (new_value, old_value)) + { + FRAME_UNDECORATED (f) = NILP (new_value) ? false : true; + xg_set_undecorated (f, new_value); + } +} + /** * x_set_override_redirect: * @@ -699,7 +721,7 @@ frame_parm_handler pgtk_frame_parm_handlers[] = 0, /* x_set_sticky */ 0, /* x_set_tool_bar_position */ 0, /* x_set_inhibit_double_buffering */ - 0, /*x_set_undecorated */ + x_set_undecorated 0, /* x_set_parent_frame, */ 0, /* x_set_skip_taskbar */ x_set_no_focus_on_map, commit f6d8c5939bff5b5baf46578718999e06061e26ff Author: Yuuki Harano Date: Sat Oct 28 16:16:29 2017 +0900 Introduce Pure GTK3 port * src/xsettings.h: * src/xsettings.c: (dpyinfo_valid, store_tool_bar_style_changed) (XSETTINGS_FONT_NAME, get_prop_window, read_settings) (apply_xft_settings, read_and_apply_settings) (xft_settings_event, init_xsettings, xsettings_initialize): * src/xfaces.c: (x_create_gc, x_free_gc): * src/xdisp.c (redisplay_tool_bar, redisplay_internal) (draw_glyphs_debug, draw_glyphs, mouse_face_from_buffer_pos) (note_mouse_highlight): * src/terminal.c (Fterminal_live_p): * src/termhooks.h (enum output_method, GCALIGNED_STRUCT) (TERMINAL_FONT_CACHE): * src/process.c (wait_reading_process_output): * src/pgtkterm.h: * src/pgtkterm.c: * src/pgtkselect.h: * src/pgtkselect.c: * src/pgtkgui.h: * src/pgtkfns.c: * src/image.c: (XGetPixel, XPutPixel, image_create_bitmap_from_data) (image_create_bitmap_from_file, free_bitmap_record) (image_destroy_x_image, gui_put_x_image, image_get_x_image) (Create_Pixmap_From_Bitmap_Data, xbm_load_image, ) (xpm_load_image, lookup_rgb_color, image_disable_image) (image_build_heuristic_mask, imagemagick_load_image): * src/gtkutil.h: * src/gtkutil.c (PGTK_TRACE, xg_set_screen, xg_display_open) (xg_display_close, xg_create_default_cursor) (xg_get_pixbuf_from_pix_and_mask, xg_check_special_colors) (qttip_cb, hierarchy_ch_cb, xg_prepare_tooltip, ) (xg_show_tooltip, xg_hide_tooltip, xg_frame_resized) (xg_frame_set_char_size, xg_height_or_width_changed) (xg_set_widget_bg, style_changed_cb, xg_create_frame_widgets) (xg_free_frame_widgets, x_wm_set_size_hint, xg_frame_restack) (xg_mark_data, xg_update_frame_menubar, free_frame_menubar) (xg_update_submenu, xg_finish_scroll_bar_creation) (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos) (xg_set_toolkit_scroll_bar_thumb, xg_event_is_for_scrollbar) (draw_page, xg_pack_tool_bar, xg_create_tool_bar) (xg_update_tool_bar_sizes, update_frame_tool_bar) (free_frame_tool_bar, xg_change_toolbar_position): * src/ftcrfont.c: (ftcrfont_draw): * src/fringe.c: (init_fringe_bitmap): * src/frame.h (GCALIGNED_STRUCT, FRAME_WINDOW_P): * src/frame.c (Fframep): * src/font.h: * src/font.c (syms_of_font): * src/emacsgtkfixed.c: (emacs_fixed_get_preferred_width) (emacs_fixed_get_preferred_height, XSetWMSizeHints): * src/emacs.c (main): * src/dispnew.c (init_display_interactive): * src/dispextern.h: * src/alloc.c: (garbage_collect): * src/Makefile.in (PGTK_OBJ, PGTK_LIBS, base_obj, LIBES): * src/.gdbinit: * lisp/url/url-privacy.el (url-setup-privacy-info): * lisp/term/pgtk-win.el (featurep): * lisp/startup.el (command-line, fancy-splash-frame): * lisp/net/eww.el (eww-form-submit, eww-form-file) (eww-form-checkbox, eww-form-select): * lisp/mwheel.el (mouse-wheel-down-event, mouse-wheel-up-event): * lisp/loadup.el (featurep): * lisp/international/mule-cmds.el (set-coding-system-map): * lisp/frame.el (pgtk-frame-geometry, frame-geometry) (w32-frame-edges, frame-edges) (pgtk-mouse-absolute-pixel-position) (mouse-absolute-pixel-position) (pgtk-set-mouse-absolute-pixel-position) (pgtk-frame-list-z-order, frame-list-z-order) (pgtk-frame-restack, frame-restack, display-mouse-p) (display-graphic-p, display-symbol-keys-p, ) (display-pixel-height, display-mm-height, display-mm-width) (display-backing-store, display-save-under, display-color-cells) (display-planes, display-visual-class) (pgtk-display-monitor-attributes-list) (display-monitor-attributes-list): * lisp/faces.el (face-spec-set-match-display, tool-bar): * lisp/cus-edit.el (custom-button, custom-button-mouse) (custom-button-pressed, custom-display): * configure.ac (AUTO_DEPEND, XARGS_LIMIT, XWIDGETS_OBJ): diff --git a/configure.ac b/configure.ac index 888b415148..b168131f42 100644 --- a/configure.ac +++ b/configure.ac @@ -1833,6 +1833,8 @@ window_system=none AC_PATH_X if test "$no_x" != yes; then window_system=x11 +else + window_system=pgtk fi LD_SWITCH_X_SITE_RPATH= @@ -2239,6 +2241,11 @@ dnl use the toolkit if we have gtk, or X11R5 or newer. w32 ) term_header=w32term.h ;; + pgtk ) + term_header=pgtkterm.h + with_gtk3=yes + USE_X_TOOLKIT=none + ;; esac if test "$window_system" = none && test "X$with_x" != "Xno"; then @@ -2567,7 +2574,7 @@ fi ### Use -lrsvg-2 if available, unless '--with-rsvg=no' is specified. HAVE_RSVG=no -if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${opsys}" = "mingw32"; then +if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${window_system}" = "pgtk" || test "${opsys}" = "mingw32"; then if test "${with_rsvg}" != "no"; then RSVG_REQUIRED=2.14.0 RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED" @@ -2588,7 +2595,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${opsys}" = fi HAVE_IMAGEMAGICK=no -if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" = "yes"; then +if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${window_system}" = "pgtk" || test "${HAVE_W32}" = "yes"; then if test "${with_imagemagick}" != "no"; then if test -n "$BREW"; then # Homebrew doesn't link ImageMagick 6 by default, so make sure @@ -2605,6 +2612,11 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" EMACS_CHECK_MODULES([IMAGEMAGICK], [Wand >= 6.3.5 Wand != 6.8.2]) fi + if test $HAVE_IMAGEMAGICK != yes; then + IMAGEMAGICK_MODULE="MagickWand-6.Q16HDRI >= 6.3.5 MagickWand-6.Q16HDRI != 6.8.2 MagickWand-6.Q16HDRI < 7 MagickCore-6.Q16HDRI >= 6.9.9 MagickCore-6.Q16HDRI < 7" + EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE]) + fi + if test $HAVE_IMAGEMAGICK = yes; then OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS @@ -2812,6 +2824,16 @@ AC_SUBST(XWIDGETS_OBJ) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS +PGTK_OBJ= +PGTK_LIBS= +if test "$window_system" = "pgtk"; then + PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o xsettings.o" + PGTK_LIBS="$GTK_LIBS -ldl" + AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) +fi +AC_SUBST(PGTK_OBJ) +AC_SUBST(PGTK_LIBS) + dnl D-Bus has been tested under GNU/Linux only. Must be adapted for dnl other platforms. HAVE_DBUS=no @@ -2841,7 +2863,7 @@ AC_SUBST(DBUS_OBJ) dnl GSettings has been tested under GNU/Linux only. HAVE_GSETTINGS=no -if test "${HAVE_X11}" = "yes" && test "${with_gsettings}" = "yes"; then +if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gsettings}" = "yes"; then EMACS_CHECK_MODULES([GSETTINGS], [gio-2.0 >= 2.26]) if test "$HAVE_GSETTINGS" = "yes"; then old_CFLAGS=$CFLAGS @@ -2875,7 +2897,7 @@ fi dnl GConf has been tested under GNU/Linux only. dnl The version is really arbitrary, it is about the same age as Gtk+ 2.6. HAVE_GCONF=no -if test "${HAVE_X11}" = "yes" && test "${with_gconf}" != "no"; then +if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gconf}" != "no"; then EMACS_CHECK_MODULES([GCONF], [gconf-2.0 >= 2.13]) if test "$HAVE_GCONF" = yes; then AC_DEFINE(HAVE_GCONF, 1, [Define to 1 if using GConf.]) @@ -3437,10 +3459,34 @@ if test "${HAVE_X11}" = "yes"; then fi fi else # "${HAVE_X11}" != "yes" - HAVE_XFT=no - HAVE_FREETYPE=no - HAVE_LIBOTF=no - HAVE_M17N_FLT=no + if test $window_system = pgtk; then + EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0]) + EMACS_CHECK_MODULES([FREETYPE], [freetype2]) + if test "$HAVE_FONTCONFIG" != yes -o "$HAVE_FREETYPE" != yes; then + AC_MSG_ERROR(fontconfig and freetype is required.) + fi + HAVE_LIBOTF=no + AC_DEFINE(HAVE_FREETYPE, 1, + [Define to 1 if using the freetype and fontconfig libraries.]) + if test "${with_libotf}" != "no"; then + EMACS_CHECK_MODULES([LIBOTF], [libotf]) + if test "$HAVE_LIBOTF" = "yes"; then + AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.]) + AC_CHECK_LIB(otf, OTF_get_variation_glyphs, + HAVE_OTF_GET_VARIATION_GLYPHS=yes, + HAVE_OTF_GET_VARIATION_GLYPHS=no) + if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then + AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1, + [Define to 1 if libotf has OTF_get_variation_glyphs.]) + fi + fi + fi + else + HAVE_XFT=no + HAVE_FREETYPE=no + HAVE_LIBOTF=no + HAVE_M17N_FLT=no + fi fi # "${HAVE_X11}" != "yes" HAVE_HARFBUZZ=no @@ -3452,6 +3498,7 @@ else harfbuzz_required_ver=0.9.42 fi if test "${HAVE_X11}" = "yes" && test "${HAVE_FREETYPE}" = "yes" \ + || test "$window_system" = "pgtk" \ || test "${HAVE_W32}" = "yes"; then if test "${with_harfbuzz}" != "no"; then EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver]) @@ -3479,6 +3526,25 @@ AC_SUBST(LIBOTF_LIBS) AC_SUBST(M17N_FLT_CFLAGS) AC_SUBST(M17N_FLT_LIBS) +HAVE_CAIRO=no +if test "${HAVE_X11}" = "yes" -o "$window_system" = pgtk; then + if test "${with_cairo}" != "no"; then + CAIRO_REQUIRED=1.12.0 + CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" + EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) + if test $HAVE_CAIRO = yes; then + AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) + else + AC_MSG_ERROR([cairo requested but not found.]) + fi + + CFLAGS="$CFLAGS $CAIRO_CFLAGS" + LIBS="$LIBS $CAIRO_LIBS" + AC_SUBST(CAIRO_CFLAGS) + AC_SUBST(CAIRO_LIBS) + fi +fi + if test "${HAVE_X11}" = "yes"; then AC_CHECK_HEADER(X11/Xlib-xcb.h, AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes)) @@ -3740,7 +3806,7 @@ if test "${with_png}" != no; then # mingw32 loads the library dynamically. if test "$opsys" = mingw32; then AC_CHECK_HEADER([png.h], [HAVE_PNG=yes]) - elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ + elif test "${HAVE_X11}" = "yes" || test "$window_system" = "pgtk" || test "${HAVE_W32}" = "yes" \ || test "${HAVE_NS}" = "yes"; then EMACS_CHECK_MODULES([PNG], [libpng >= 1.0.0]) if test $HAVE_PNG = yes; then @@ -3815,7 +3881,7 @@ if test "${opsys}" = "mingw32"; then if test "${HAVE_TIFF}" = "yes"; then AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).]) fi -elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ +elif test "${HAVE_X11}" = "yes" || test "${window_system}" = "pgtk" || test "${HAVE_W32}" = "yes" \ || test "${HAVE_NS}" = "yes"; then if test "${with_tiff}" != "no"; then AC_CHECK_HEADER(tiffio.h, @@ -3844,7 +3910,7 @@ if test "${opsys}" = "mingw32"; then if test "${HAVE_GIF}" = "yes"; then AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.]) fi -elif test "${HAVE_X11}" = "yes" && test "${with_gif}" != "no" \ +elif test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gif}" != "no" \ || test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes"; then AC_CHECK_HEADER(gif_lib.h, # EGifPutExtensionLast only exists from version libungif-4.1.0b1. @@ -5290,6 +5356,9 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then FONT_OBJ="$FONT_OBJ ftfont.o" fi fi +if test "${window_system}" = "pgtk"; then + FONT_OBJ="ftfont.o ftcrfont.o" +fi if test "${HAVE_HARFBUZZ}" = "yes" ; then FONT_OBJ="$FONT_OBJ hbfont.o" fi diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index eceba8fa4d..099b7daac5 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -2172,7 +2172,7 @@ and `face'." ;;; The `custom' Widget. (defface custom-button - '((((type x w32 ns) (class color)) ; Like default mode line + '((((type x w32 ns pgtk) (class color)) ; Like default mode line :box (:line-width 2 :style released-button) :background "lightgrey" :foreground "black")) "Face for custom buffer buttons if `custom-raised-buttons' is non-nil." @@ -2180,7 +2180,7 @@ and `face'." :group 'custom-faces) (defface custom-button-mouse - '((((type x w32 ns) (class color)) + '((((type x w32 ns pgtk) (class color)) :box (:line-width 2 :style released-button) :background "grey90" :foreground "black") (t @@ -2205,7 +2205,7 @@ and `face'." (if custom-raised-buttons 'custom-button-mouse 'highlight)) (defface custom-button-pressed - '((((type x w32 ns) (class color)) + '((((type x w32 ns pgtk) (class color)) :box (:line-width 2 :style pressed-button) :background "lightgrey" :foreground "black") (t :inverse-video t)) @@ -3445,6 +3445,10 @@ MS Windows.") :sibling-args (:help-echo "\ GNUstep or Macintosh OS Cocoa interface.") ns) + (const :format "PGTK " + :sibling-args (:help-echo "\ +Pure-GTK interface.") + ns) (const :format "DOS " :sibling-args (:help-echo "\ Plain MS-DOS.") diff --git a/lisp/faces.el b/lisp/faces.el index 7355e1dd0a..5e525e7953 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1487,7 +1487,7 @@ If FRAME is nil, the current FRAME is used." match (cond ((eq req 'type) (or (memq (window-system frame) options) (and (memq 'graphic options) - (memq (window-system frame) '(x w32 ns))) + (memq (window-system frame) '(x w32 ns pgtk))) ;; FIXME: This should be revisited to use ;; display-graphic-p, provided that the ;; color selection depends on the number @@ -2755,7 +2755,7 @@ Note: Other faces cannot inherit from the cursor face." '((default :box (:line-width 1 :style released-button) :foreground "black") - (((type x w32 ns) (class color)) + (((type x w32 ns pgtk) (class color)) :background "grey75") (((type x) (class mono)) :background "grey")) diff --git a/lisp/frame.el b/lisp/frame.el index 772ba3d8c4..a43e12f12a 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1601,6 +1601,7 @@ live frame and defaults to the selected one." (declare-function x-frame-geometry "xfns.c" (&optional frame)) (declare-function w32-frame-geometry "w32fns.c" (&optional frame)) (declare-function ns-frame-geometry "nsfns.m" (&optional frame)) +(declare-function pgtk-frame-geometry "pgtkfns.c" (&optional frame)) (defun frame-geometry (&optional frame) "Return geometric attributes of FRAME. @@ -1650,6 +1651,8 @@ and width values are in pixels. (w32-frame-geometry frame)) ((eq frame-type 'ns) (ns-frame-geometry frame)) + ((eq frame-type 'pgtk) + (pgtk-frame-geometry frame)) (t (list '(outer-position 0 . 0) @@ -1696,6 +1699,7 @@ selected frame." (declare-function x-frame-edges "xfns.c" (&optional frame type)) (declare-function w32-frame-edges "w32fns.c" (&optional frame type)) (declare-function ns-frame-edges "nsfns.m" (&optional frame type)) +(declare-function pgtk-frame-edges "pgtkfns.c" (&optional frame type)) (defun frame-edges (&optional frame type) "Return coordinates of FRAME's edges. @@ -1719,12 +1723,15 @@ FRAME." (w32-frame-edges frame type)) ((eq frame-type 'ns) (ns-frame-edges frame type)) + ((eq frame-type 'pgtk) + (pgtk-frame-edges frame type)) (t (list 0 0 (frame-width frame) (frame-height frame)))))) (declare-function w32-mouse-absolute-pixel-position "w32fns.c") (declare-function x-mouse-absolute-pixel-position "xfns.c") (declare-function ns-mouse-absolute-pixel-position "nsfns.m") +(declare-function pgtk-mouse-absolute-pixel-position "pgtkfns.c") (defun mouse-absolute-pixel-position () "Return absolute position of mouse cursor in pixels. @@ -1739,9 +1746,12 @@ position (0, 0) of the selected frame's terminal." (w32-mouse-absolute-pixel-position)) ((eq frame-type 'ns) (ns-mouse-absolute-pixel-position)) + ((eq frame-type 'pgtk) + (pgtk-mouse-absolute-pixel-position)) (t (cons 0 0))))) +(declare-function pgtk-set-mouse-absolute-pixel-position "pgtkfns.c" (x y)) (declare-function ns-set-mouse-absolute-pixel-position "nsfns.m" (x y)) (declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y)) (declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y)) @@ -1752,6 +1762,8 @@ The coordinates X and Y are interpreted in pixels relative to a position (0, 0) of the selected frame's terminal." (let ((frame-type (framep-on-display))) (cond + ((eq frame-type 'pgtk) + (pgtk-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'ns) (ns-set-mouse-absolute-pixel-position x y)) ((eq frame-type 'x) @@ -1850,6 +1862,7 @@ workarea attribute." (declare-function x-frame-list-z-order "xfns.c" (&optional display)) (declare-function w32-frame-list-z-order "w32fns.c" (&optional display)) (declare-function ns-frame-list-z-order "nsfns.m" (&optional display)) +(declare-function pgtk-frame-list-z-order "pgtkfns.c" (&optional display)) (defun frame-list-z-order (&optional display) "Return list of Emacs' frames, in Z (stacking) order. @@ -1869,11 +1882,14 @@ Return nil if DISPLAY contains no Emacs frame." ((eq frame-type 'w32) (w32-frame-list-z-order display)) ((eq frame-type 'ns) - (ns-frame-list-z-order display))))) + (ns-frame-list-z-order display)) + ((eq frame-type 'pgtk) + (pgtk-frame-list-z-order display))))) (declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above)) (declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above)) (declare-function ns-frame-restack "nsfns.m" (frame1 frame2 &optional above)) +(declare-function pgtk-frame-restack "pgtkfns.c" (frame1 frame2 &optional above)) (defun frame-restack (frame1 frame2 &optional above) "Restack FRAME1 below FRAME2. @@ -1903,7 +1919,9 @@ Some window managers may refuse to restack windows." ((eq frame-type 'w32) (w32-frame-restack frame1 frame2 above)) ((eq frame-type 'ns) - (ns-frame-restack frame1 frame2 above)))) + (ns-frame-restack frame1 frame2 above)) + ((eq frame-type 'pgtk) + (pgtk-frame-restack frame1 frame2 above)))) (error "Cannot restack frames"))) (defun frame-size-changed-p (&optional frame) @@ -1950,7 +1968,7 @@ frame's display)." ((eq frame-type 'w32) (with-no-warnings (> w32-num-mouse-buttons 0))) - ((memq frame-type '(x ns)) + ((memq frame-type '(x ns pgtk)) t) ;; We assume X and NeXTstep *always* have a pointing device (t (or (and (featurep 'xt-mouse) @@ -1976,7 +1994,7 @@ frames and several different fonts at once. This is true for displays that use a window system such as X, and false for text-only terminals. DISPLAY can be a display name, a frame, or nil (meaning the selected frame's display)." - (not (null (memq (framep-on-display display) '(x w32 ns))))) + (not (null (memq (framep-on-display display) '(x w32 ns pgtk))))) (defun display-images-p (&optional display) "Return non-nil if DISPLAY can display images. @@ -2004,7 +2022,7 @@ frame's display)." ;; a Windows DOS Box. (with-no-warnings (not (null dos-windows-version)))) - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) t) (t nil)))) @@ -2014,7 +2032,7 @@ frame's display)." This means that, for example, DISPLAY can differentiate between the keybinding RET and [return]." (let ((frame-type (framep-on-display display))) - (or (memq frame-type '(x w32 ns pc)) + (or (memq frame-type '(x w32 ns pc pgtk)) ;; MS-DOS and MS-Windows terminals have built-in support for ;; function (symbol) keys (memq system-type '(ms-dos windows-nt))))) @@ -2027,7 +2045,7 @@ DISPLAY should be either a frame or a display name (a string). If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-screens display)) (t 1)))) @@ -2047,7 +2065,7 @@ with DISPLAY. To get information for each physical monitor, use `display-monitor-attributes-list'." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-pixel-height display)) (t (frame-height (if (framep display) display (selected-frame))))))) @@ -2067,7 +2085,7 @@ with DISPLAY. To get information for each physical monitor, use `display-monitor-attributes-list'." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-pixel-width display)) (t (frame-width (if (framep display) display (selected-frame))))))) @@ -2105,7 +2123,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this refers to the height in millimeters for all physical monitors associated with DISPLAY. To get information for each physical monitor, use `display-monitor-attributes-list'." - (and (memq (framep-on-display display) '(x w32 ns)) + (and (memq (framep-on-display display) '(x w32 ns pgtk)) (or (cddr (assoc (or display (frame-parameter nil 'display)) display-mm-dimensions-alist)) (cddr (assoc t display-mm-dimensions-alist)) @@ -2126,7 +2144,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this refers to the width in millimeters for all physical monitors associated with DISPLAY. To get information for each physical monitor, use `display-monitor-attributes-list'." - (and (memq (framep-on-display display) '(x w32 ns)) + (and (memq (framep-on-display display) '(x w32 ns pgtk)) (or (cadr (assoc (or display (frame-parameter nil 'display)) display-mm-dimensions-alist)) (cadr (assoc t display-mm-dimensions-alist)) @@ -2144,7 +2162,7 @@ DISPLAY can be a display name or a frame. If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-backing-store display)) (t 'not-useful)))) @@ -2157,7 +2175,7 @@ DISPLAY can be a display name or a frame. If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-save-under display)) (t 'not-useful)))) @@ -2170,7 +2188,7 @@ DISPLAY can be a display name or a frame. If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-planes display)) ((eq frame-type 'pc) 4) @@ -2185,7 +2203,7 @@ DISPLAY can be a display name or a frame. If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-color-cells display)) ((eq frame-type 'pc) 16) @@ -2202,7 +2220,7 @@ DISPLAY can be a display name or a frame. If DISPLAY is omitted or nil, it defaults to the selected frame's display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 ns)) + ((memq frame-type '(x w32 ns pgtk)) (x-display-visual-class display)) ((and (memq frame-type '(pc t)) (tty-display-color-p display)) @@ -2216,6 +2234,8 @@ If DISPLAY is omitted or nil, it defaults to the selected frame's display." (&optional display)) (declare-function ns-display-monitor-attributes-list "nsfns.m" (&optional terminal)) +(declare-function pgtk-display-monitor-attributes-list "pgtkfns.c" + (&optional terminal)) (defun display-monitor-attributes-list (&optional display) "Return a list of physical monitor attributes on DISPLAY. @@ -2264,6 +2284,8 @@ monitors." (w32-display-monitor-attributes-list display)) ((eq frame-type 'ns) (ns-display-monitor-attributes-list display)) + ((eq frame-type 'pgtk) + (pgtk-display-monitor-attributes-list display)) (t (let ((geometry (list 0 0 (display-pixel-width display) (display-pixel-height display)))) diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index d361971a1f..e22876ba37 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el @@ -88,7 +88,7 @@ (bindings--define-key map [separator-3] menu-bar-separator) (bindings--define-key map [set-terminal-coding-system] '(menu-item "For Terminal" set-terminal-coding-system - :enable (null (memq initial-window-system '(x w32 ns))) + :enable (null (memq initial-window-system '(x w32 ns pgtk))) :help "How to encode terminal output")) (bindings--define-key map [set-keyboard-coding-system] '(menu-item "For Keyboard" set-keyboard-coding-system diff --git a/lisp/loadup.el b/lisp/loadup.el index 4b711eed06..50ed557515 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -336,6 +336,13 @@ (load "international/mule-util") (load "international/ucs-normalize") (load "term/ns-win")))) +(if (featurep 'pgtk) + (progn + (load "term/common-win") + ;; Don't load ucs-normalize.el unless uni-*.el files were + ;; already produced, because it needs uni-*.el files that might + ;; not be built early enough during bootstrap. + (load "term/pgtk-win"))) (if (fboundp 'x-create-frame) ;; Do it after loading term/foo-win.el since the value of the ;; mouse-wheel-*-event vars depends on those files being loaded or not. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 1d9fe68075..9dcdbe2de8 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -52,7 +52,7 @@ (when (bound-and-true-p mouse-wheel-mode) (mouse-wheel-mode 1))) (defcustom mouse-wheel-down-event - (if (or (featurep 'w32-win) (featurep 'ns-win)) + (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) 'wheel-up 'mouse-4) "Event used for scrolling down." @@ -61,7 +61,7 @@ :set 'mouse-wheel-change-button) (defcustom mouse-wheel-up-event - (if (or (featurep 'w32-win) (featurep 'ns-win)) + (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) 'wheel-down 'mouse-5) "Event used for scrolling up." @@ -215,13 +215,13 @@ Also see `mouse-wheel-tilt-scroll'." "Function that does the job of scrolling right.") (defvar mouse-wheel-left-event - (if (or (featurep 'w32-win) (featurep 'ns-win)) + (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) 'wheel-left 'mouse-6) "Event used for scrolling left.") (defvar mouse-wheel-right-event - (if (or (featurep 'w32-win) (featurep 'ns-win)) + (if (or (featurep 'w32-win) (featurep 'ns-win) (featurep 'pgtk)) 'wheel-right 'mouse-7) "Event used for scrolling right.") diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 9ed01ecc47..743abb0c8e 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -189,7 +189,7 @@ See also `eww-form-checkbox-selected-symbol'." string)) (defface eww-form-submit - '((((type x w32 ns) (class color)) ; Like default mode line + '((((type x w32 ns pgtk) (class color)) ; Like default mode line :box (:line-width 2 :style released-button) :background "#808080" :foreground "black")) "Face for eww buffer buttons." @@ -197,7 +197,7 @@ See also `eww-form-checkbox-selected-symbol'." :group 'eww) (defface eww-form-file - '((((type x w32 ns) (class color)) ; Like default mode line + '((((type x w32 ns pgtk) (class color)) ; Like default mode line :box (:line-width 2 :style released-button) :background "#808080" :foreground "black")) "Face for eww buffer buttons." @@ -205,7 +205,7 @@ See also `eww-form-checkbox-selected-symbol'." :group 'eww) (defface eww-form-checkbox - '((((type x w32 ns) (class color)) ; Like default mode line + '((((type x w32 ns pgtk) (class color)) ; Like default mode line :box (:line-width 2 :style released-button) :background "lightgrey" :foreground "black")) "Face for eww buffer buttons." @@ -213,7 +213,7 @@ See also `eww-form-checkbox-selected-symbol'." :group 'eww) (defface eww-form-select - '((((type x w32 ns) (class color)) ; Like default mode line + '((((type x w32 ns pgtk) (class color)) ; Like default mode line :box (:line-width 2 :style released-button) :background "lightgrey" :foreground "black")) "Face for eww buffer buttons." diff --git a/lisp/startup.el b/lisp/startup.el index 9f67dfde12..e3c792edff 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -1312,7 +1312,7 @@ please check its value") ;; only because all other settings of no-blinking-cursor are here. (unless (or noninteractive emacs-basic-display - (and (memq window-system '(x w32 ns)) + (and (memq window-system '(x w32 ns pgtk)) (not (member (x-get-resource "cursorBlink" "CursorBlink") '("no" "off" "false" "0"))))) (setq no-blinking-cursor t)) @@ -1962,6 +1962,8 @@ we put it on this frame." ;; frame visible. (if (eq (window-system) 'w32) (sit-for 0 t)) + (if (eq (window-system) 'pgtk) + (sit-for 0.1 t)) (dolist (frame (append (frame-list) (list (selected-frame)))) (if (and (frame-visible-p frame) (not (window-minibuffer-p (frame-selected-window frame)))) diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el new file mode 100644 index 0000000000..203cce442d --- /dev/null +++ b/lisp/term/pgtk-win.el @@ -0,0 +1,429 @@ +;;; + +;;; Code: +(eval-when-compile (require 'cl-lib)) +(or (featurep 'pgtk) + (error "%s: Loading pgtk-win.el but not compiled for pure Gtk+-3." + (invocation-name))) + +;; Documentation-purposes only: actually loaded in loadup.el. +(require 'term/common-win) +(require 'frame) +(require 'mouse) +(require 'scroll-bar) +(require 'faces) +(require 'menu-bar) +(require 'fontset) +(require 'dnd) + +(defgroup pgtk nil + "Pure-GTK specific features." + :group 'environment) + +;;;; Command line argument handling. + +(defvar x-invocation-args) +;; Set in term/common-win.el; currently unused by Gtk's x-open-connection. +(defvar x-command-line-resources) + +;; pgtkterm.c. +(defvar pgtk-input-file) + +(defun pgtk-handle-nxopen (_switch &optional temp) + (setq unread-command-events (append unread-command-events + (if temp '(pgtk-open-temp-file) + '(pgtk-open-file))) + pgtk-input-file (append pgtk-input-file (list (pop x-invocation-args))))) + +(defun pgtk-handle-nxopentemp (switch) + (pgtk-handle-nxopen switch t)) + +(defun pgtk-ignore-1-arg (_switch) + (setq x-invocation-args (cdr x-invocation-args))) + +;;;; File handling. + +(defun x-file-dialog (prompt dir default_filename mustmatch only_dir_p) +"Read file name, prompting with PROMPT in directory DIR. +Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file +selection box, if specified. If MUSTMATCH is non-nil, the returned file +or directory must exist. + +This function is only defined on PGTK, MS Windows, and X Windows with the +Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored. +Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories." + (pgtk-read-file-name prompt dir mustmatch default_filename only_dir_p)) + +(defun pgtk-open-file-using-panel () + "Pop up open-file panel, and load the result in a buffer." + (interactive) + ;; Prompt dir defaultName isLoad initial. + (setq pgtk-input-file (pgtk-read-file-name "Select File to Load" nil t nil)) + (if pgtk-input-file + (and (setq pgtk-input-file (list pgtk-input-file)) (pgtk-find-file)))) + +(defun pgtk-write-file-using-panel () + "Pop up save-file panel, and save buffer in resulting name." + (interactive) + (let (pgtk-output-file) + ;; Prompt dir defaultName isLoad initial. + (setq pgtk-output-file (pgtk-read-file-name "Save As" nil nil nil)) + (message pgtk-output-file) + (if pgtk-output-file (write-file pgtk-output-file)))) + +(defcustom pgtk-pop-up-frames 'fresh + "Non-nil means open files upon request from the Workspace in a new frame. +If t, always do so. Any other non-nil value means open a new frame +unless the current buffer is a scratch buffer." + :type '(choice (const :tag "Never" nil) + (const :tag "Always" t) + (other :tag "Except for scratch buffer" fresh)) + :version "23.1" + :group 'pgtk) + +(declare-function pgtk-hide-emacs "pgtkfns.c" (on)) + +(defun pgtk-find-file () + "Do a `find-file' with the `pgtk-input-file' as argument." + (interactive) + (let* ((f (file-truename + (expand-file-name (pop pgtk-input-file) + command-line-default-directory))) + (file (find-file-noselect f)) + (bufwin1 (get-buffer-window file 'visible)) + (bufwin2 (get-buffer-window "*scratch*" 'visible))) + (cond + (bufwin1 + (select-frame (window-frame bufwin1)) + (raise-frame (window-frame bufwin1)) + (select-window bufwin1)) + ((and (eq pgtk-pop-up-frames 'fresh) bufwin2) + (pgtk-hide-emacs 'activate) + (select-frame (window-frame bufwin2)) + (raise-frame (window-frame bufwin2)) + (select-window bufwin2) + (find-file f)) + (pgtk-pop-up-frames + (pgtk-hide-emacs 'activate) + (let ((pop-up-frames t)) (pop-to-buffer file nil))) + (t + (pgtk-hide-emacs 'activate) + (find-file f))))) + + +(defun pgtk-drag-n-drop (event &optional new-frame force-text) + "Edit the files listed in the drag-n-drop EVENT. +Switch to a buffer editing the last file dropped." + (interactive "e") + (let* ((window (posn-window (event-start event))) + (arg (car (cdr (cdr event)))) + (type (car arg)) + (data (car (cdr arg))) + (url-or-string (cond ((eq type 'file) + (concat "file:" data)) + (t data)))) + (set-frame-selected-window nil window) + (when new-frame + (select-frame (make-frame))) + (raise-frame) + (setq window (selected-window)) + (if force-text + (dnd-insert-text window 'private data) + (dnd-handle-one-url window 'private url-or-string)))) + + +(defun pgtk-drag-n-drop-other-frame (event) + "Edit the files listed in the drag-n-drop EVENT, in other frames. +May create new frames, or reuse existing ones. The frame editing +the last file dropped is selected." + (interactive "e") + (pgtk-drag-n-drop event t)) + +(defun pgtk-drag-n-drop-as-text (event) + "Drop the data in EVENT as text." + (interactive "e") + (pgtk-drag-n-drop event nil t)) + +(defun pgtk-drag-n-drop-as-text-other-frame (event) + "Drop the data in EVENT as text in a new frame." + (interactive "e") + (pgtk-drag-n-drop event t t)) + +(global-set-key [drag-n-drop] 'pgtk-drag-n-drop) +(global-set-key [C-drag-n-drop] 'pgtk-drag-n-drop-other-frame) +(global-set-key [M-drag-n-drop] 'pgtk-drag-n-drop-as-text) +(global-set-key [C-M-drag-n-drop] 'pgtk-drag-n-drop-as-text-other-frame) + +;;;; Frame-related functions. + +;; pgtkterm.c +(defvar pgtk-alternate-modifier) +(defvar pgtk-right-alternate-modifier) +(defvar pgtk-right-command-modifier) +(defvar pgtk-right-control-modifier) + +;; You say tomAYto, I say tomAHto.. +(defvaralias 'pgtk-option-modifier 'pgtk-alternate-modifier) +(defvaralias 'pgtk-right-option-modifier 'pgtk-right-alternate-modifier) + +(defun pgtk-do-hide-emacs () + (interactive) + (pgtk-hide-emacs t)) + +(declare-function pgtk-hide-others "pgtkfns.c" ()) + +(defun pgtk-do-hide-others () + (interactive) + (pgtk-hide-others)) + +(declare-function pgtk-emacs-info-panel "pgtkfns.c" ()) + +(defun pgtk-do-emacs-info-panel () + (interactive) + (pgtk-emacs-info-panel)) + +(defun pgtk-next-frame () + "Switch to next visible frame." + (interactive) + (other-frame 1)) + +(defun pgtk-prev-frame () + "Switch to previous visible frame." + (interactive) + (other-frame -1)) + +;; Frame will be focused anyway, so select it +;; (if this is not done, mode line is dimmed until first interaction) +;; FIXME: Sounds like we're working around a bug in the underlying code. +(add-hook 'after-make-frame-functions 'select-frame) + +(defvar tool-bar-mode) +(declare-function tool-bar-mode "tool-bar" (&optional arg)) + +;; Based on a function by David Reitter ; +;; see https://lists.gnu.org/archive/html/emacs-devel/2005-09/msg00681.html . +(defun pgtk-toggle-toolbar (&optional frame) + "Switches the tool bar on and off in frame FRAME. + If FRAME is nil, the change applies to the selected frame." + (interactive) + (modify-frame-parameters + frame (list (cons 'tool-bar-lines + (if (> (or (frame-parameter frame 'tool-bar-lines) 0) 0) + 0 1)) )) + (if (not tool-bar-mode) (tool-bar-mode t))) + + +;;;; Dialog-related functions. + +;; Ask user for confirm before printing. Due to Kevin Rodgers. +(defun pgtk-print-buffer () + "Interactive front-end to `print-buffer': asks for user confirmation first." + (interactive) + (if (and (called-interactively-p 'interactive) + (or (listp last-nonmenu-event) + (and (char-or-string-p (event-basic-type last-command-event)) + (memq 'super (event-modifiers last-command-event))))) + (let ((last-nonmenu-event (if (listp last-nonmenu-event) + last-nonmenu-event + ;; Fake it: + `(mouse-1 POSITION 1)))) + (if (y-or-n-p (format "Print buffer %s? " (buffer-name))) + (print-buffer) + (error "Canceled"))) + (print-buffer))) + +;;;; Font support. + +;; Needed for font listing functions under both backend and normal +(setq scalable-fonts-allowed t) + +;; Set to use font panel instead +(declare-function pgtk-popup-font-panel "pgtkfns.c" (&optional frame)) +(defalias 'x-select-font 'pgtk-popup-font-panel "Pop up the font panel. +This function has been overloaded in Nextstep.") +(defalias 'mouse-set-font 'pgtk-popup-font-panel "Pop up the font panel. +This function has been overloaded in Nextstep.") + +;; pgtkterm.c +(defvar pgtk-input-font) +(defvar pgtk-input-fontsize) + +(defun pgtk-respond-to-change-font () + "Respond to changeFont: event, expecting `pgtk-input-font' and\n\ +`pgtk-input-fontsize' of new font." + (interactive) + (modify-frame-parameters (selected-frame) + (list (cons 'fontsize pgtk-input-fontsize))) + (modify-frame-parameters (selected-frame) + (list (cons 'font pgtk-input-font))) + (set-frame-font pgtk-input-font)) + + +;; Default fontset. This is mainly here to show how a fontset +;; can be set up manually. Ordinarily, fontsets are auto-created whenever +;; a font is chosen by +(defvar pgtk-standard-fontset-spec + ;; Only some code supports this so far, so use uglier XLFD version + ;; "-pgtk-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai" + (mapconcat 'identity + '("-*-Monospace-*-*-*-*-10-*-*-*-*-*-fontset-standard" + "latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1" + "han:-*-Kai-*-*-*-*-10-*-*-*-*-*-iso10646-1" + "cyrillic:-*-Trebuchet$MS-*-*-*-*-10-*-*-*-*-*-iso10646-1") + ",") + "String of fontset spec of the standard fontset. +This defines a fontset consisting of the Courier and other fonts. +See the documentation of `create-fontset-from-fontset-spec' for the format.") + + +;;;; Pasteboard support. + +(define-obsolete-function-alias 'pgtk-store-cut-buffer-internal + 'gui-set-selection "24.1") + + +(defun pgtk-copy-including-secondary () + (interactive) + (call-interactively 'kill-ring-save) + (gui-set-selection 'SECONDARY (buffer-substring (point) (mark t)))) + +(defun pgtk-paste-secondary () + (interactive) + (insert (gui-get-selection 'SECONDARY))) + + +;;;; Color support. + +;; Functions for color panel + drag +(defun pgtk-face-at-pos (pos) + (let* ((frame (car pos)) + (frame-pos (cons (cadr pos) (cddr pos))) + (window (window-at (car frame-pos) (cdr frame-pos) frame)) + (window-pos (coordinates-in-window-p frame-pos window)) + (buffer (window-buffer window)) + (edges (window-edges window))) + (cond + ((not window-pos) + nil) + ((eq window-pos 'mode-line) + 'mode-line) + ((eq window-pos 'vertical-line) + 'default) + ((consp window-pos) + (with-current-buffer buffer + (let ((p (car (compute-motion (window-start window) + (cons (nth 0 edges) (nth 1 edges)) + (window-end window) + frame-pos + (- (window-width window) 1) + nil + window)))) + (cond + ((eq p (window-point window)) + 'cursor) + ((and mark-active (< (region-beginning) p) (< p (region-end))) + 'region) + (t + (let ((faces (get-char-property p 'face window))) + (if (consp faces) (car faces) faces))))))) + (t + nil)))) + +(defun pgtk-suspend-error () + ;; Don't allow suspending if any of the frames are PGTK frames. + (if (memq 'pgtk (mapcar 'window-system (frame-list))) + (error "Cannot suspend Emacs while a PGTK GUI frame exists"))) + + +;; Set some options to be as Nextstep-like as possible. +(setq frame-title-format t + icon-title-format t) + + +(defvar pgtk-initialized nil + "Non-nil if pure-GTK windowing has been initialized.") + +(declare-function x-handle-args "common-win" (args)) +(declare-function x-open-connection "pgtkfns.c" + (display &optional xrm-string must-succeed)) +(declare-function pgtk-set-resource "pgtkfns.c" (owner name value)) + +;; Do the actual pure-GTK Windows setup here; the above code just +;; defines functions and variables that we use now. +(cl-defmethod window-system-initialization (&context (window-system pgtk) + &optional display) + "Initialize Emacs for pure-GTK windowing." + (cl-assert (not pgtk-initialized)) + + ;; PENDING: not needed? + (setq command-line-args (x-handle-args command-line-args)) + + ;; Make sure we have a valid resource name. + (or (stringp x-resource-name) + (let (i) + (setq x-resource-name (invocation-name)) + + ;; Change any . or * characters in x-resource-name to hyphens, + ;; so as not to choke when we use it in X resource queries. + (while (setq i (string-match "[.*]" x-resource-name)) + (aset x-resource-name i ?-)))) + + ;; Setup the default fontset. + (create-default-fontset) + ;; Create the standard fontset. + (condition-case err + (create-fontset-from-fontset-spec pgtk-standard-fontset-spec t) + (error (display-warning + 'initialization + (format "Creation of the standard fontset failed: %s" err) + :error))) + + (x-open-connection (or display + x-display-name) + x-command-line-resources + ;; Exit Emacs with fatal error if this fails and we + ;; are the initial display. + (= (length (frame-list)) 0)) + + (x-apply-session-resources) + + ;; Don't let Emacs suspend under PGTK. + (add-hook 'suspend-hook 'pgtk-suspend-error) + + (setq pgtk-initialized t)) + +;; Any display name is OK. +(add-to-list 'display-format-alist '(".*" . pgtk)) +(cl-defmethod handle-args-function (args &context (window-system pgtk)) + (x-handle-args args)) + +(cl-defmethod frame-creation-function (params &context (window-system pgtk)) + (x-create-frame-with-faces params)) + +(declare-function pgtk-own-selection-internal "pgtkselect.c" (selection value &optional frame)) +(declare-function pgtk-disown-selection-internal "pgtkselect.c" (selection &optional time_object terminal)) +(declare-function pgtk-selection-owner-p "pgtkselect.c" (&optional selection terminal)) +(declare-function pgtk-selection-exists-p "pgtkselect.c" (&optional selection terminal)) +(declare-function pgtk-get-selection-internal "pgtkselect.c" (selection-symbol target-type &optional time_stamp terminal)) + +(cl-defmethod gui-backend-set-selection (selection value + &context (window-system pgtk)) + (if value (pgtk-own-selection-internal selection value) + (pgtk-disown-selection-internal selection))) + +(cl-defmethod gui-backend-selection-owner-p (selection + &context (window-system pgtk)) + (pgtk-selection-owner-p selection)) + +(cl-defmethod gui-backend-selection-exists-p (selection + &context (window-system pgtk)) + (pgtk-selection-exists-p selection)) + +(cl-defmethod gui-backend-get-selection (selection-symbol target-type + &context (window-system pgtk)) + (pgtk-get-selection-internal selection-symbol target-type)) + +(provide 'pgtk-win) +(provide 'term/pgtk-win) + +;;; pgtk-win.el ends here diff --git a/lisp/url/url-privacy.el b/lisp/url/url-privacy.el index 716e310742..f1cbb2620e 100644 --- a/lisp/url/url-privacy.el +++ b/lisp/url/url-privacy.el @@ -46,6 +46,7 @@ (pcase (or window-system 'tty) ('x "X11") ('ns "OpenStep") + ('pgtk "PureGTK") ('tty "TTY") (_ nil))))) diff --git a/src/.gdbinit b/src/.gdbinit index 78536fc01f..1efde9f195 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -41,6 +41,9 @@ handle SIGUSR2 noprint pass # debugging. handle SIGALRM ignore +# On selection send failed. +handle SIGPIPE nostop noprint + # Use $bugfix so that the value isn't a constant. # Using a constant runs into GDB bugs sometimes. define xgetptr @@ -1224,6 +1227,7 @@ set print pretty on set print sevenbit-strings show environment DISPLAY +show environment WAYLAND_DISPLAY show environment TERM # When debugging, it is handy to be able to "return" from diff --git a/src/Makefile.in b/src/Makefile.in index c5fb2ea3ab..2c1e873bc4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -286,6 +286,9 @@ W32_OBJ=@W32_OBJ@ ## -lkernel32 if CYGWIN but not HAVE_W32, else empty. W32_LIBS=@W32_LIBS@ +PGTK_OBJ=@PGTK_OBJ@ +PGTK_LIBS=@PGTK_LIBS@ + ## emacs.res if HAVE_W32 EMACSRES = @EMACSRES@ ## If HAVE_W32, compiler arguments for including @@ -421,7 +424,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ profiler.o decompress.o \ thread.o systhread.o \ $(if $(HYBRID_MALLOC),sheap.o) \ - $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ + $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(PGTK_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) $(GMP_OBJ) obj = $(base_obj) $(NS_OBJC_OBJ) @@ -519,7 +522,7 @@ shortlisp := loaddefs.el loadup.el $(sort ${shortlisp}) lisp = $(addprefix ${lispsource}/,${shortlisp}) ## Construct full set of libraries to be linked. -LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ +LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(PGTK_LIBS) $(LIBX_BASE) $(LIBIMAGE) \ $(LIBX_OTHER) $(LIBSOUND) \ $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ $(WEBKIT_LIBS) \ diff --git a/src/alloc.c b/src/alloc.c index 2b3643e35b..0dc7f7fac4 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -96,7 +96,7 @@ along with GNU Emacs. If not, see . */ #include #include -#ifdef USE_GTK +#if defined(USE_GTK) # include "gtkutil.h" #endif #ifdef WINDOWSNT @@ -6052,8 +6052,11 @@ garbage_collect (void) mark_terminals (); mark_kboards (); mark_threads (); +#ifdef HAVE_PGTK + mark_pgtkterm(); +#endif -#ifdef USE_GTK +#if defined(USE_GTK) xg_mark_data (); #endif diff --git a/src/dispextern.h b/src/dispextern.h index da51772b37..35e1210410 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -134,6 +134,14 @@ typedef Emacs_Pixmap Emacs_Pix_Context; #define FACE_COLOR_TO_PIXEL(face_color, frame) face_color #endif +#ifdef HAVE_PGTK +#include "pgtkgui.h" +/* Following typedef needed to accommodate the MSDOS port, believe it or not. */ +typedef struct pgtk_display_info Display_Info; +typedef Emacs_Pixmap XImagePtr; +typedef XImagePtr XImagePtr_or_DC; +#endif + #ifdef HAVE_WINDOW_SYSTEM # include # include "fontset.h" @@ -1393,6 +1401,9 @@ struct glyph_string Emacs_GC *gc; HDC hdc; #endif +#if defined (HAVE_PGTK) + XGCValues xgcv; +#endif /* A pointer to the first glyph in the string. This glyph corresponds to char2b[0]. Needed to draw rectangles if diff --git a/src/dispnew.c b/src/dispnew.c index 89dd32ad0f..1aee18e747 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -6403,6 +6403,19 @@ init_display_interactive (void) } #endif +#ifdef HAVE_PGTK + if (!inhibit_window_system +#ifndef CANNOT_DUMP + && initialized +#endif + ) + { + Vinitial_window_system = Qpgtk; + Vwindow_system_version = make_fixnum (1); + return; + } +#endif + /* If no window system has been specified, try to use the terminal. */ if (! isatty (STDIN_FILENO)) fatal ("standard input is not a tty"); diff --git a/src/emacs.c b/src/emacs.c index 172e460769..769a852e73 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1586,6 +1586,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_bignum (); init_threads (); init_eval (); +#ifdef HAVE_PGTK + init_pgtkterm (); /* before init_atimer(). */ +#endif init_atimer (); running_asynch_code = 0; init_random (); @@ -1914,6 +1917,14 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_nsselect (); syms_of_fontset (); #endif /* HAVE_NS */ +#ifdef HAVE_PGTK + syms_of_pgtkterm(); + syms_of_pgtkfns(); + syms_of_pgtkselect (); + syms_of_fontset (); + syms_of_xsettings (); + syms_of_xwidget (); +#endif syms_of_gnutls (); @@ -1982,8 +1993,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #ifdef HAVE_DBUS init_dbusbind (); #endif -#ifdef USE_GTK +#if defined(USE_GTK) +#ifndef HAVE_PGTK init_xterm (); +#endif #endif /* This can create a thread that may call getenv, so it must follow diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index ea9465d553..aeca3d4f7c 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -22,7 +22,11 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "frame.h" +#ifdef HAVE_PGTK +#include "pgtkterm.h" +#else #include "xterm.h" +#endif #include "xwidget.h" #include "emacsgtkfixed.h" @@ -182,7 +186,11 @@ emacs_fixed_get_preferred_width (GtkWidget *widget, { EmacsFixed *fixed = EMACS_FIXED (widget); EmacsFixedPrivate *priv = fixed->priv; +#ifdef HAVE_PGTK + int w = priv->f->output_data.pgtk->size_hints.min_width; +#else int w = priv->f->output_data.x->size_hints.min_width; +#endif if (minimum) *minimum = w; if (natural) *natural = w; } @@ -194,12 +202,18 @@ emacs_fixed_get_preferred_height (GtkWidget *widget, { EmacsFixed *fixed = EMACS_FIXED (widget); EmacsFixedPrivate *priv = fixed->priv; +#ifdef HAVE_PGTK + int h = priv->f->output_data.pgtk->size_hints.min_height; +#else int h = priv->f->output_data.x->size_hints.min_height; +#endif if (minimum) *minimum = h; if (natural) *natural = h; } +#ifndef HAVE_PGTK + /* Override the X function so we can intercept Gtk+ 3 calls. Use our values for min_width/height so that KDE don't freak out (Bug#8919), and so users can resize our frames as they wish. */ @@ -234,8 +248,13 @@ XSetWMSizeHints (Display *d, if ((hints->flags & PMinSize) && f) { +#ifdef HAVE_PGTK + int w = f->output_data.pgtk->size_hints.min_width; + int h = f->output_data.pgtk->size_hints.min_height; +#else int w = f->output_data.x->size_hints.min_width; int h = f->output_data.x->size_hints.min_height; +#endif data[5] = w; data[6] = h; } @@ -253,3 +272,5 @@ XSetWMNormalHints (Display *d, Window w, XSizeHints *hints) { XSetWMSizeHints (d, w, hints, XA_WM_NORMAL_HINTS); } + +#endif diff --git a/src/font.c b/src/font.c index 8dbf8cb899..52c1cb8a03 100644 --- a/src/font.c +++ b/src/font.c @@ -5567,7 +5567,11 @@ match. */); syms_of_xftfont (); #endif /* HAVE_XFT */ #endif /* not USE_CAIRO */ -#endif /* HAVE_X_WINDOWS */ +#else /* not HAVE_X_WINDOWS */ +#ifdef USE_CAIRO + syms_of_ftcrfont (); +#endif +#endif /* not HAVE_X_WINDOWS */ #else /* not HAVE_FREETYPE */ #ifdef HAVE_X_WINDOWS syms_of_xfont (); diff --git a/src/font.h b/src/font.h index 8614e7fa10..89c1a7a091 100644 --- a/src/font.h +++ b/src/font.h @@ -822,7 +822,7 @@ extern Lisp_Object merge_font_spec (Lisp_Object, Lisp_Object); extern Lisp_Object font_make_entity (void); extern Lisp_Object font_make_object (int, Lisp_Object, int); -#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) +#if defined (HAVE_XFT) || defined (HAVE_FREETYPE) || defined (HAVE_NS) || defined(HAVE_PGTK) extern Lisp_Object font_build_object (int, Lisp_Object, Lisp_Object, double); #endif diff --git a/src/frame.c b/src/frame.c index 512aaf5f45..2c549a1d4d 100644 --- a/src/frame.c +++ b/src/frame.c @@ -291,6 +291,8 @@ See also `frame-live-p'. */) return Qpc; case output_ns: return Qns; + case output_pgtk: + return Qpgtk; default: emacs_abort (); } @@ -2149,7 +2151,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force) /* Since a similar behavior was observed on the Lucid and Motif builds (see Bug#5802, Bug#21509, Bug#23499, Bug#27816), we now don't delete the terminal for these builds either. */ - if (terminal->reference_count == 0 && terminal->type == output_x_window) + if (terminal->reference_count == 0 && + (terminal->type == output_x_window || terminal->type == output_pgtk)) terminal->reference_count = 1; #endif /* USE_X_TOOLKIT || USE_GTK */ if (terminal->reference_count == 0) @@ -5749,7 +5752,7 @@ selected frame. This is useful when `make-pointer-invisible' is set. */) #ifdef HAVE_WINDOW_SYSTEM -# if (defined USE_GTK || defined HAVE_NS || defined HAVE_XINERAMA \ +# if (defined USE_GTK || defined HAVE_PGTK || defined HAVE_NS || defined HAVE_XINERAMA \ || defined HAVE_XRANDR) void free_monitors (struct MonitorInfo *monitors, int n_monitors) @@ -5876,6 +5879,7 @@ syms_of_frame (void) DEFSYM (Qw32, "w32"); DEFSYM (Qpc, "pc"); DEFSYM (Qns, "ns"); + DEFSYM (Qpgtk, "pgtk"); DEFSYM (Qvisible, "visible"); DEFSYM (Qbuffer_predicate, "buffer-predicate"); DEFSYM (Qbuffer_list, "buffer-list"); diff --git a/src/frame.h b/src/frame.h index 16ecfd311c..d8f7e4bd14 100644 --- a/src/frame.h +++ b/src/frame.h @@ -574,6 +574,7 @@ struct frame struct x_output *x; /* From xterm.h. */ struct w32_output *w32; /* From w32term.h. */ struct ns_output *ns; /* From nsterm.h. */ + struct pgtk_output *pgtk; /* From pgtkterm.h. */ } output_data; @@ -841,6 +842,11 @@ default_pixels_per_inch_y (void) #else #define FRAME_NS_P(f) ((f)->output_method == output_ns) #endif +#ifndef HAVE_PGTK +#define FRAME_PGTK_P(f) false +#else +#define FRAME_PGTK_P(f) ((f)->output_method == output_pgtk) +#endif /* FRAME_WINDOW_P tests whether the frame is a graphical window system frame. */ @@ -854,6 +860,9 @@ default_pixels_per_inch_y (void) #ifdef HAVE_NS #define FRAME_WINDOW_P(f) FRAME_NS_P(f) #endif +#ifdef HAVE_PGTK +#define FRAME_WINDOW_P(f) FRAME_PGTK_P(f) +#endif #ifndef FRAME_WINDOW_P #define FRAME_WINDOW_P(f) ((void) (f), false) #endif @@ -1701,7 +1710,7 @@ extern const char *x_get_resource_string (const char *, const char *); extern void x_sync (struct frame *); #endif /* HAVE_X_WINDOWS */ -#ifndef HAVE_NS +#if !defined(HAVE_NS) && !defined(HAVE_PGTK) /* Set F's bitmap icon, if specified among F's parameters. */ diff --git a/src/fringe.c b/src/fringe.c index 75496692d5..6259894f26 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -30,6 +30,8 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "pdumper.h" +#include "pgtkterm.h" + /* Fringe bitmaps are represented in three different ways: Logical bitmaps are used internally to denote things like @@ -1398,7 +1400,7 @@ If BITMAP overrides a standard fringe bitmap, the original bitmap is restored. On W32 and MAC (little endian), there's no need to do this. */ -#if defined (HAVE_X_WINDOWS) +#if defined (HAVE_X_WINDOWS) || defined(HAVE_PGTK) static const unsigned char swap_nibble[16] = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ @@ -1461,6 +1463,25 @@ init_fringe_bitmap (int which, struct fringe_bitmap *fb, int once_p) #endif /* not USE_CAIRO */ #endif /* HAVE_X_WINDOWS */ +#if !defined(HAVE_X_WINDOWS) && defined (HAVE_PGTK) + unsigned short *bits = fb->bits; + int j; + + for (j = 0; j < fb->height; j++) + { + unsigned short b = *bits; +#ifdef WORDS_BIGENDIAN + *bits++ = (b << (16 - fb->width)); +#else + b = (unsigned short)((swap_nibble[b & 0xf] << 12) + | (swap_nibble[(b>>4) & 0xf] << 8) + | (swap_nibble[(b>>8) & 0xf] << 4) + | (swap_nibble[(b>>12) & 0xf])); + *bits++ = (b >> (16 - fb->width)); +#endif + } +#endif /* !HAVE_X_WINDOWS && HAVE_PGTK */ + #ifdef HAVE_NTGUI unsigned short *bits = fb->bits; int j; diff --git a/src/ftcrfont.c b/src/ftcrfont.c index b89510704e..8fffb33ee2 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -22,7 +22,11 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#ifndef HAVE_PGTK #include "xterm.h" +#else +#include "pgtkterm.h" +#endif #include "blockinput.h" #include "charset.h" #include "composite.h" @@ -513,11 +517,19 @@ ftcrfont_draw (struct glyph_string *s, block_input (); +#ifndef HAVE_PGTK cr = x_begin_cr_clip (f, s->gc); +#else + cr = pgtk_begin_cr_clip (f); +#endif if (with_background) { +#ifndef HAVE_PGTK x_set_cr_source_with_gc_background (f, s->gc); +#else + pgtk_set_cr_source_with_color (f, s->xgcv.background); +#endif cairo_rectangle (cr, x, y - FONT_BASE (face->font), s->width, FONT_HEIGHT (face->font)); cairo_fill (cr); @@ -534,11 +546,19 @@ ftcrfont_draw (struct glyph_string *s, NULL)); } +#ifndef HAVE_PGTK x_set_cr_source_with_gc_foreground (f, s->gc); +#else + pgtk_set_cr_source_with_color (f, s->xgcv.foreground); +#endif cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font); cairo_show_glyphs (cr, glyphs, len); +#ifndef HAVE_PGTK x_end_cr_clip (f); +#else + pgtk_end_cr_clip (f); +#endif unblock_input (); diff --git a/src/ftfont.h b/src/ftfont.h index f771dc159b..94050ddc7b 100644 --- a/src/ftfont.h +++ b/src/ftfont.h @@ -25,6 +25,7 @@ along with GNU Emacs. If not, see . */ #include #include FT_FREETYPE_H #include FT_SIZES_H +#include FT_TRUETYPE_TABLES_H #ifdef FT_BDF_H # include FT_BDF_H #endif diff --git a/src/gtkutil.c b/src/gtkutil.c index fafd94c0f7..b7a397bf43 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -26,7 +26,7 @@ along with GNU Emacs. If not, see . */ #include -#ifdef USE_GTK +#if defined(USE_GTK) #include #include #include @@ -37,13 +37,24 @@ along with GNU Emacs. If not, see . */ #include "dispextern.h" #include "frame.h" #include "systime.h" +#ifndef HAVE_PGTK #include "xterm.h" +#define xp x +typedef struct x_output xp_output; +#else +#define xp pgtk +typedef struct pgtk_output xp_output; +#endif #include "blockinput.h" #include "window.h" #include "gtkutil.h" #include "termhooks.h" #include "keyboard.h" #include "coding.h" +#ifndef PGTK_TRACE +#define PGTK_TRACE(fmt, ...) ((void) 0) +#define PGTK_BACKTRACE() ((void) 0) +#endif #include @@ -52,7 +63,9 @@ along with GNU Emacs. If not, see . */ #endif #ifdef HAVE_GTK3 +#ifndef HAVE_PGTK #include +#endif #include "emacsgtkfixed.h" #endif @@ -129,6 +142,7 @@ static GdkDisplay *gdpy_def; static void xg_set_screen (GtkWidget *w, struct frame *f) { +#ifndef HAVE_PGTK if (FRAME_X_DISPLAY (f) != DEFAULT_GDK_DISPLAY ()) { GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); @@ -139,6 +153,17 @@ xg_set_screen (GtkWidget *w, struct frame *f) else gtk_window_set_screen (GTK_WINDOW (w), gscreen); } +#else + if (FRAME_X_DISPLAY(f) != DEFAULT_GDK_DISPLAY ()) + { + GdkScreen *gscreen = gdk_display_get_default_screen (FRAME_X_DISPLAY(f)); + + if (GTK_IS_MENU (w)) + gtk_menu_set_screen (GTK_MENU (w), gscreen); + else + gtk_window_set_screen (GTK_WINDOW (w), gscreen); + } +#endif } @@ -150,12 +175,20 @@ xg_set_screen (GtkWidget *w, struct frame *f) multiple displays. */ void +#ifndef HAVE_PGTK xg_display_open (char *display_name, Display **dpy) +#else +xg_display_open (char *display_name, GdkDisplay **dpy) +#endif { GdkDisplay *gdpy; unrequest_sigio (); /* See comment in x_display_ok, xterm.c. */ +#ifndef HAVE_PGTK gdpy = gdk_display_open (display_name); +#else + gdpy = gdk_display_open (strlen(display_name) == 0 ? NULL : display_name); +#endif request_sigio (); if (!gdpy_def && gdpy) { @@ -164,7 +197,11 @@ xg_display_open (char *display_name, Display **dpy) gdpy); } +#ifndef HAVE_PGTK *dpy = gdpy ? GDK_DISPLAY_XDISPLAY (gdpy) : NULL; +#else + *dpy = gdpy; +#endif } /* Scaling/HiDPI functions. */ @@ -196,8 +233,13 @@ xg_get_scale (struct frame *f) /* Close display DPY. */ void +#ifndef HAVE_PGTK xg_display_close (Display *dpy) +#else +xg_display_close (GdkDisplay *gdpy) +#endif { +#ifndef HAVE_PGTK GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy); /* If this is the default display, try to change it before closing. @@ -221,6 +263,31 @@ xg_display_close (Display *dpy) } gdk_display_close (gdpy); + +#else + + /* If this is the default display, try to change it before closing. + If there is no other display to use, gdpy_def is set to NULL, and + the next call to xg_display_open resets the default display. */ + if (gdk_display_get_default () == gdpy) + { + struct pgtk_display_info *dpyinfo; + GdkDisplay *gdpy_new = NULL; + + /* Find another display. */ + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (dpyinfo->gdpy != gdpy) + { + gdpy_new = dpyinfo->gdpy; + gdk_display_manager_set_default_display (gdk_display_manager_get (), + gdpy_new); + break; + } + gdpy_def = gdpy_new; + } + + gdk_display_close (gdpy); +#endif } @@ -232,12 +299,19 @@ xg_display_close (Display *dpy) scroll bars on display DPY. */ GdkCursor * +#ifndef HAVE_PGTK xg_create_default_cursor (Display *dpy) +#else +xg_create_default_cursor (GdkDisplay *gdpy) +#endif { +#ifndef HAVE_PGTK GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpy); +#endif return gdk_cursor_new_for_display (gdpy, GDK_LEFT_PTR); } +#ifndef HAVE_PGTK /* Apply GMASK to GPIX and return a GdkPixbuf with an alpha channel. */ static GdkPixbuf * @@ -250,8 +324,10 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, Window wunused; unsigned int width, height, depth, uunused; +#ifndef HAVE_PGTK if (FRAME_DISPLAY_INFO (f)->red_bits != 8) return 0; +#endif XGetGeometry (FRAME_X_DISPLAY (f), pix, &wunused, &iunused, &iunused, &width, &height, &uunused, &depth); if (depth != 24) @@ -286,6 +362,7 @@ xg_get_pixbuf_from_pix_and_mask (struct frame *f, return icon_buf; } +#endif #if defined USE_CAIRO && !defined HAVE_GTK3 static GdkPixbuf * @@ -633,7 +710,11 @@ xg_check_special_colors (struct frame *f, g = col.green * 65535, b = col.blue * 65535; sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b); +#ifndef HAVE_PGTK success_p = x_parse_color (f, buf, color) != 0; +#else + success_p = pgtk_parse_color (buf, color) != 0; +#endif #else GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); GdkColor *grgb = get_bg @@ -667,7 +748,7 @@ hierarchy_ch_cb (GtkWidget *widget, gpointer user_data) { struct frame *f = user_data; - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GtkWidget *top = gtk_widget_get_toplevel (x->ttip_lbl); if (! top || ! GTK_IS_WINDOW (top)) @@ -689,7 +770,7 @@ qttip_cb (GtkWidget *widget, gpointer user_data) { struct frame *f = user_data; - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; if (x->ttip_widget == NULL) { GtkWidget *p; @@ -736,7 +817,7 @@ xg_prepare_tooltip (struct frame *f, int *width, int *height) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GtkWidget *widget; GdkWindow *gwin; GdkScreen *screen; @@ -787,13 +868,19 @@ xg_prepare_tooltip (struct frame *f, void xg_show_tooltip (struct frame *f, int root_x, int root_y) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; if (x->ttip_window) { block_input (); +#ifndef HAVE_PGTK gtk_window_move (x->ttip_window, root_x / xg_get_scale (f), root_y / xg_get_scale (f)); gtk_widget_show (GTK_WIDGET (x->ttip_window)); +#else + gtk_widget_show (GTK_WIDGET (x->ttip_window)); + gtk_window_move (x->ttip_window, root_x / xg_get_scale (f), + root_y / xg_get_scale (f)); +#endif unblock_input (); } } @@ -805,10 +892,10 @@ xg_show_tooltip (struct frame *f, int root_x, int root_y) bool xg_hide_tooltip (struct frame *f) { - if (f->output_data.x->ttip_window) + bool ret = 0; + if (f->output_data.xp->ttip_window) { - GtkWindow *win = f->output_data.x->ttip_window; - + GtkWindow *win = f->output_data.xp->ttip_window; block_input (); gtk_widget_hide (GTK_WIDGET (win)); @@ -932,10 +1019,16 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth); height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight); + PGTK_TRACE("xg_frame_resized: pixel: %dx%d, text: %dx%d", pixelwidth, pixelheight, width, height); frame_size_history_add (f, Qxg_frame_resized, width, height, Qnil); + PGTK_TRACE("width: %d -> %d.", FRAME_TEXT_WIDTH(f), width); + PGTK_TRACE("height: %d -> %d.", FRAME_TEXT_HEIGHT(f), height); + PGTK_TRACE("pixelwidth: %d -> %d.", FRAME_PIXEL_WIDTH(f), pixelwidth); + PGTK_TRACE("pixelheight: %d -> %d.", FRAME_PIXEL_HEIGHT(f), pixelheight); + if (width != FRAME_TEXT_WIDTH (f) || height != FRAME_TEXT_HEIGHT (f) || pixelwidth != FRAME_PIXEL_WIDTH (f) @@ -945,6 +1038,9 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight) change_frame_size (f, width, height, 0, 1, 0, 1); SET_FRAME_GARBAGED (f); cancel_mouse_face (f); +#ifdef HAVE_PGTK + pgtk_cr_destroy_surface (f); +#endif } } @@ -1007,7 +1103,11 @@ xg_frame_set_char_size (struct frame *f, int width, int height) else if (FRAME_PARENT_FRAME (f) && FRAME_VISIBLE_P (f)) { was_visible = true; +#ifndef HAVE_PGTK hide_child_frame = EQ (x_gtk_resize_child_frames, Qhide); +#else + hide_child_frame = true; +#endif // !HAVE_PGTK if (totalwidth != gwidth || totalheight != gheight) { @@ -1060,7 +1160,9 @@ xg_frame_set_char_size (struct frame *f, int width, int height) /* Must call this to flush out events */ (void)gtk_events_pending (); gdk_flush (); +#ifndef HAVE_PGTK x_wait_for_event (f, ConfigureNotify); +#endif if (!NILP (fullscreen)) /* Try to restore fullscreen state. */ @@ -1071,24 +1173,24 @@ xg_frame_set_char_size (struct frame *f, int width, int height) } else adjust_frame_size (f, width, height, 5, 0, Qxg_frame_set_char_size); - } +#ifndef HAVE_PGTK /* Handle height/width changes (i.e. add/remove/move menu/toolbar). The policy is to keep the number of editable lines. */ -#if 0 static void xg_height_or_width_changed (struct frame *f) { gtk_window_resize (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FRAME_TOTAL_PIXEL_WIDTH (f), FRAME_TOTAL_PIXEL_HEIGHT (f)); - f->output_data.x->hint_flags = 0; + f->output_data.xp->hint_flags = 0; x_wm_set_size_hint (f, 0, 0); } #endif +#ifndef HAVE_PGTK /* Convert an X Window WSESC on display DPY to its corresponding GtkWidget. Must be done like this, because GtkWidget:s can have "hidden" X Window that aren't accessible. @@ -1116,6 +1218,7 @@ xg_win_to_widget (Display *dpy, Window wdesc) unblock_input (); return gwdesc; } +#endif /* Set the background of widget W to PIXEL. */ @@ -1123,9 +1226,18 @@ static void xg_set_widget_bg (struct frame *f, GtkWidget *w, unsigned long pixel) { #ifdef HAVE_GTK3 - XColor xbg; + Emacs_Color xbg; xbg.pixel = pixel; +#ifndef HAVE_PGTK if (XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &xbg)) +#else + xbg.red = (pixel >> 16) & 0xff; + xbg.green = (pixel >> 8) & 0xff; + xbg.blue = (pixel >> 0) & 0xff; + xbg.red |= xbg.red << 8; + xbg.green |= xbg.green << 8; + xbg.blue |= xbg.blue << 8; +#endif { const char format[] = "* { background-color: #%02x%02x%02x; }"; /* The format is always longer than the resulting string. */ @@ -1160,7 +1272,16 @@ style_changed_cb (GObject *go, struct input_event event; GdkDisplay *gdpy = user_data; const char *display_name = gdk_display_get_name (gdpy); +#ifndef HAVE_PGTK Display *dpy = GDK_DISPLAY_XDISPLAY (gdpy); +#else + GdkDisplay *dpy = gdpy; +#endif + +#ifndef HAVE_PGTK + if (display_name == NULL) + display_name = ""; +#endif EVENT_INIT (event); event.kind = CONFIG_CHANGED_EVENT; @@ -1181,7 +1302,11 @@ style_changed_cb (GObject *go, { struct frame *f = XFRAME (frame); if (FRAME_LIVE_P (f) +#ifndef HAVE_PGTK && FRAME_X_P (f) +#else + && FRAME_PGTK_P (f) +#endif && FRAME_X_DISPLAY (f) == dpy) { FRAME_TERMINAL (f)->set_scroll_bar_default_width_hook (f); @@ -1216,15 +1341,21 @@ xg_create_frame_widgets (struct frame *f) #endif char *title = 0; + PGTK_TRACE("xg_create_frame_widgets."); block_input (); +#ifndef HAVE_PGTK // gtk_plug not found. if (FRAME_X_EMBEDDED_P (f)) { GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); - wtop = gtk_plug_new_for_display (gdpy, f->output_data.x->parent_desc); + wtop = gtk_plug_new_for_display (gdpy, f->output_data.xp->parent_desc); } else +#endif wtop = gtk_window_new (GTK_WINDOW_TOPLEVEL); +#ifdef HAVE_PGTK + gtk_widget_add_events(wtop, GDK_ALL_EVENTS_MASK); +#endif /* gtk_window_set_has_resize_grip is a Gtk+ 3.0 function but Ubuntu has backported it to Gtk+ 2.0 and they add the resize grip for @@ -1281,8 +1412,8 @@ xg_create_frame_widgets (struct frame *f) FRAME_GTK_OUTER_WIDGET (f) = wtop; FRAME_GTK_WIDGET (f) = wfixed; - f->output_data.x->vbox_widget = wvbox; - f->output_data.x->hbox_widget = whbox; + f->output_data.xp->vbox_widget = wvbox; + f->output_data.xp->hbox_widget = whbox; gtk_widget_set_has_window (wfixed, TRUE); @@ -1309,10 +1440,12 @@ xg_create_frame_widgets (struct frame *f) SSDATA (Vx_resource_class)); #endif +#ifndef HAVE_PGTK /* Add callback to do nothing on WM_DELETE_WINDOW. The default in GTK is to destroy the widget. We want Emacs to do that instead. */ g_signal_connect (G_OBJECT (wtop), "delete-event", G_CALLBACK (delete_cb), f); +#endif /* Convert our geometry parameters into a geometry string and specify it. @@ -1323,7 +1456,9 @@ xg_create_frame_widgets (struct frame *f) gtk_widget_add_events (wfixed, GDK_POINTER_MOTION_MASK +#ifndef HAVE_PGTK | GDK_EXPOSURE_MASK +#endif | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK @@ -1331,13 +1466,25 @@ xg_create_frame_widgets (struct frame *f) | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK +#ifdef HAVE_PGTK + | GDK_SCROLL_MASK + | GDK_SMOOTH_SCROLL_MASK +#endif | GDK_VISIBILITY_NOTIFY_MASK); /* Must realize the windows so the X window gets created. It is used by callers of this function. */ +#ifndef HAVE_PGTK gtk_widget_realize (wfixed); +#else + gtk_widget_show_all(wtop); +#endif +#ifndef HAVE_PGTK FRAME_X_WINDOW (f) = GTK_WIDGET_TO_X_WIN (wfixed); +#endif +#ifndef HAVE_PGTK initial_set_up_x_back_buffer (f); +#endif /* Since GTK clears its window by filling with the background color, we must keep X and GTK background in sync. */ @@ -1354,6 +1501,7 @@ xg_create_frame_widgets (struct frame *f) gtk_widget_modify_style (wfixed, style); #else gtk_widget_set_can_focus (wfixed, TRUE); + gtk_widget_grab_focus(wfixed); gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); #endif @@ -1366,9 +1514,9 @@ xg_create_frame_widgets (struct frame *f) } /* Steal a tool tip window we can move ourselves. */ - f->output_data.x->ttip_widget = 0; - f->output_data.x->ttip_lbl = 0; - f->output_data.x->ttip_window = 0; + f->output_data.xp->ttip_widget = 0; + f->output_data.xp->ttip_lbl = 0; + f->output_data.xp->ttip_window = 0; gtk_widget_set_tooltip_text (wtop, "Dummy text"); g_signal_connect (wtop, "query-tooltip", G_CALLBACK (qttip_cb), f); @@ -1398,7 +1546,7 @@ xg_free_frame_widgets (struct frame *f) { if (FRAME_GTK_OUTER_WIDGET (f)) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; struct xg_frame_tb_info *tbinfo = g_object_get_data (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), TB_INFO_KEY); @@ -1406,10 +1554,14 @@ xg_free_frame_widgets (struct frame *f) xfree (tbinfo); /* x_free_frame_resources should have taken care of it */ +#ifndef HAVE_PGTK eassert (!FRAME_X_DOUBLE_BUFFERED_P (f)); +#endif gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f)); FRAME_X_WINDOW (f) = 0; /* Set to avoid XDestroyWindow in xterm.c */ +#ifndef HAVE_PGTK FRAME_X_RAW_DRAWABLE (f) = 0; +#endif FRAME_GTK_OUTER_WIDGET (f) = 0; if (x->ttip_widget) { @@ -1451,6 +1603,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) XSETFRAME (frame, f); fs_state = Fframe_parameter (frame, Qfullscreen); +#ifndef HAVE_PGTK if ((EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth)) && (x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state) || x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_wm_state_fullscreen))) @@ -1460,18 +1613,19 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) */ return; } +#endif if (flags) { memset (&size_hints, 0, sizeof (size_hints)); - f->output_data.x->size_hints = size_hints; - f->output_data.x->hint_flags = hint_flags; + f->output_data.xp->size_hints = size_hints; + f->output_data.xp->hint_flags = hint_flags; } else flags = f->size_hint_flags; - size_hints = f->output_data.x->size_hints; - hint_flags = f->output_data.x->hint_flags; + size_hints = f->output_data.xp->size_hints; + hint_flags = f->output_data.xp->hint_flags; hint_flags |= GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE; size_hints.width_inc = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f); @@ -1484,6 +1638,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 1) + FRAME_TOOLBAR_WIDTH (f); base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); + PGTK_TRACE("base: %dx%d\n", base_width, base_height); size_hints.base_width = base_width; size_hints.base_height = base_height; @@ -1533,16 +1688,16 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position) size_hints.width_inc /= scale; size_hints.height_inc /= scale; - if (hint_flags != f->output_data.x->hint_flags + if (hint_flags != f->output_data.xp->hint_flags || memcmp (&size_hints, - &f->output_data.x->size_hints, + &f->output_data.xp->size_hints, sizeof (size_hints)) != 0) { block_input (); gtk_window_set_geometry_hints (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), NULL, &size_hints, hint_flags); - f->output_data.x->size_hints = size_hints; - f->output_data.x->hint_flags = hint_flags; + f->output_data.xp->size_hints = size_hints; + f->output_data.xp->hint_flags = hint_flags; unblock_input (); } } @@ -1608,7 +1763,11 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) XSETFRAME (frame2, f2); gdk_window_restack (gwin1, gwin2, above_flag); +#ifndef HAVE_PGTK x_sync (f1); +#else + gdk_flush(); +#endif } unblock_input (); } @@ -1672,6 +1831,7 @@ xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect) unblock_input (); } +#ifndef HAVE_PGTK /* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK functions so GTK does not overwrite the icon. */ @@ -1684,6 +1844,7 @@ xg_set_frame_icon (struct frame *f, Pixmap icon_pixmap, Pixmap icon_mask) if (gp) gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), gp); } +#endif @@ -2500,7 +2661,7 @@ xg_mark_data (void) { struct frame *f = XFRAME (frame); - if (FRAME_X_P (f) && FRAME_GTK_OUTER_WIDGET (f)) + if ((FRAME_X_P (f) || FRAME_PGTK_P (f)) && FRAME_GTK_OUTER_WIDGET (f)) { struct xg_frame_tb_info *tbinfo = g_object_get_data (G_OBJECT (FRAME_GTK_OUTER_WIDGET (f)), @@ -3529,7 +3690,7 @@ menubar_map_cb (GtkWidget *w, gpointer user_data) void xg_update_frame_menubar (struct frame *f) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GtkRequisition req; if (!x->menubar_widget || gtk_widget_get_mapped (x->menubar_widget)) @@ -3562,7 +3723,7 @@ xg_update_frame_menubar (struct frame *f) void free_frame_menubar (struct frame *f) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; if (x->menubar_widget) { @@ -3578,10 +3739,11 @@ free_frame_menubar (struct frame *f) } } +#ifndef HAVE_PGTK bool -xg_event_is_for_menubar (struct frame *f, const XEvent *event) +xg_event_is_for_menubar (struct frame *f, const EVENT *event) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GList *iter; GdkRectangle rec; GList *list; @@ -3628,6 +3790,7 @@ xg_event_is_for_menubar (struct frame *f, const XEvent *event) g_list_free (list); return iter != 0; } +#endif @@ -3783,6 +3946,7 @@ xg_get_default_scrollbar_height (struct frame *f) return scroll_bar_width_for_theme * xg_get_scale (f); } +#ifndef HAVE_PGTK /* Return the scrollbar id for X Window WID on display DPY. Return -1 if WID not in id_to_widget. */ @@ -3803,6 +3967,7 @@ xg_get_scroll_id_for_window (Display *dpy, Window wid) return -1; } +#endif /* Callback invoked when scroll bar WIDGET is destroyed. DATA is the index into id_to_widget for WIDGET. @@ -3852,7 +4017,7 @@ xg_finish_scroll_bar_creation (struct frame *f, also, which causes flicker. Put an event box between the edit widget and the scroll bar, so the scroll bar instead draws itself on the event box window. */ - gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); + gtk_fixed_put (GTK_FIXED (f->output_data.xp->edit_widget), webox, -1, -1); gtk_container_add (GTK_CONTAINER (webox), wscroll); xg_set_widget_bg (f, webox, FRAME_BACKGROUND_PIXEL (f)); @@ -3862,7 +4027,12 @@ xg_finish_scroll_bar_creation (struct frame *f, real X window, it and its scroll-bar child try to draw on the Emacs main window, which we draw over using Xlib. */ gtk_widget_realize (webox); +#ifdef HAVE_PGTK + gtk_widget_show_all(webox); +#endif +#ifndef HAVE_PGTK GTK_WIDGET_TO_X_WIN (webox); +#endif /* Set the cursor to an arrow. */ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); @@ -3967,7 +4137,7 @@ xg_update_scrollbar_pos (struct frame *f, GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); if (wscroll) { - GtkWidget *wfixed = f->output_data.x->edit_widget; + GtkWidget *wfixed = f->output_data.xp->edit_widget; GtkWidget *wparent = gtk_widget_get_parent (wscroll); gint msl; int scale = xg_get_scale (f); @@ -4007,7 +4177,11 @@ xg_update_scrollbar_pos (struct frame *f, /* Clear under old scroll bar position. */ oldw += (scale - 1) * oldw; oldx -= (scale - 1) * oldw; +#ifndef HAVE_PGTK x_clear_area (f, oldx, oldy, oldw, oldh); +#else + pgtk_clear_area (f, oldx, oldy, oldw, oldh); +#endif } if (!hidden) @@ -4015,15 +4189,23 @@ xg_update_scrollbar_pos (struct frame *f, GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id); GtkWidget *webox = gtk_widget_get_parent (scrollbar); +#ifndef HAVE_PGTK /* Don't obscure any child frames. */ XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox)); +#else + gdk_window_lower(gtk_widget_get_window(webox)); +#endif } /* GTK does not redraw until the main loop is entered again, but if there are no X events pending we will not enter it. So we sync here to get some events. */ +#ifndef HAVE_PGTK x_sync (f); +#else + gdk_flush(); +#endif SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } @@ -4048,7 +4230,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, if (wscroll) { - GtkWidget *wfixed = f->output_data.x->edit_widget; + GtkWidget *wfixed = f->output_data.xp->edit_widget; GtkWidget *wparent = gtk_widget_get_parent (wscroll); gint msl; int scale = xg_get_scale (f); @@ -4084,7 +4266,11 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, } if (oldx != -1 && oldw > 0 && oldh > 0) /* Clear under old scroll bar position. */ +#ifndef HAVE_PGTK x_clear_area (f, oldx, oldy, oldw, oldh); +#else + pgtk_clear_area (f, oldx, oldy, oldw, oldh); +#endif /* GTK does not redraw until the main loop is entered again, but if there are no X events pending we will not enter it. So we sync @@ -4095,11 +4281,19 @@ xg_update_horizontal_scrollbar_pos (struct frame *f, xg_get_widget_from_map (scrollbar_id); GtkWidget *webox = gtk_widget_get_parent (scrollbar); +#ifndef HAVE_PGTK /* Don't obscure any child frames. */ XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox)); +#else + gdk_window_lower(gtk_widget_get_window(webox)); +#endif } +#ifndef HAVE_PGTK x_sync (f); +#else + gdk_flush(); +#endif SET_FRAME_GARBAGED (f); cancel_mouse_face (f); } @@ -4128,6 +4322,8 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: ----------------------------------"); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: %p, %d, %d, %d.", bar, portion, position, whole); if (wscroll && bar->dragging == -1) { GtkAdjustment *adj; @@ -4159,17 +4355,26 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, top = (gdouble) position / whole; shown = (gdouble) portion / whole; } + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: position=%d, portion=%d, whole=%d", position, portion, whole); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: top=%f, shown=%f", top, shown); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: shown*range=%f", shown * XG_SB_RANGE); size = clip_to_bounds (1, shown * XG_SB_RANGE, XG_SB_RANGE); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: size=%d.", size); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: top*range=%f.", top * XG_SB_RANGE); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: max-size=%d.", XG_SB_MAX - size); value = clip_to_bounds (XG_SB_MIN, top * XG_SB_RANGE, XG_SB_MAX - size); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: value=%d.", value); /* Assume all lines are of equal size. */ new_step = size / max (1, FRAME_LINES (f)); old_size = gtk_adjustment_get_page_size (adj); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: old_size=%d, size=%d", old_size, size); if (old_size != size) { int old_step = gtk_adjustment_get_step_increment (adj); + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: old_step=%d, new_step=%d", old_step, new_step); if (old_step != new_step) { gtk_adjustment_set_page_size (adj, size); @@ -4180,6 +4385,8 @@ xg_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, } } + PGTK_TRACE("xg_set_toolkit_scroll_bar_thumb: changed=%d, old=%d, value=%d.", + changed, int_gtk_range_get_value (GTK_RANGE (wscroll)), value); if (changed || int_gtk_range_get_value (GTK_RANGE (wscroll)) != value) { block_input (); @@ -4243,14 +4450,24 @@ xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, frame. This function does additional checks. */ bool -xg_event_is_for_scrollbar (struct frame *f, const XEvent *event) +xg_event_is_for_scrollbar (struct frame *f, const EVENT *event) { bool retval = 0; - if (f && event->type == ButtonPress && event->xbutton.button < 4) + if (f +#ifndef HAVE_PGTK + && event->type == ButtonPress && event->xbutton.button < 4 +#else + && event->type == GDK_BUTTON_PRESS && event->button.button < 4 +#endif + ) { /* Check if press occurred outside the edit widget. */ +#ifndef HAVE_PGTK GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (FRAME_X_DISPLAY (f)); +#else + GdkDisplay *gdpy = FRAME_X_DISPLAY(f); +#endif GdkWindow *gwin; #ifdef HAVE_GTK3 #if GTK_CHECK_VERSION (3, 20, 0) @@ -4264,11 +4481,17 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event) #else gwin = gdk_display_get_window_at_pointer (gdpy, NULL, NULL); #endif - retval = gwin != gtk_widget_get_window (f->output_data.x->edit_widget); + retval = gwin != gtk_widget_get_window (f->output_data.xp->edit_widget); } else if (f +#ifndef HAVE_PGTK && ((event->type == ButtonRelease && event->xbutton.button < 4) - || event->type == MotionNotify)) + || event->type == MotionNotify) +#else + && ((event->type == GDK_BUTTON_RELEASE && event->button.button < 4) + || event->type == GDK_MOTION_NOTIFY) +#endif + ) { /* If we are releasing or moving the scroll bar, it has the grab. */ GtkWidget *w = gtk_grab_get_current (); @@ -4346,7 +4569,11 @@ draw_page (GtkPrintOperation *operation, GtkPrintContext *context, struct frame *f = XFRAME (Fnth (make_fixnum (page_nr), frames)); cairo_t *cr = gtk_print_context_get_cairo_context (context); +#ifndef HAVE_PGTK x_cr_draw_frame (cr, f); +#else + pgtk_cr_draw_frame (cr, f); +#endif } void @@ -4447,7 +4674,11 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data) /* Convert between the modifier bits GDK uses and the modifier bits Emacs uses. This assumes GDK and X masks are the same, which they are when this is written. */ +#ifndef HAVE_PGTK event.modifiers = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), mod); +#else + event.modifiers = pgtk_gtk_to_emacs_modifiers (mod); +#endif kbd_buffer_store_event (&event); /* Return focus to the frame after we have clicked on a detached @@ -4517,7 +4748,6 @@ xg_tool_bar_help_callback (GtkWidget *w, Returns FALSE to tell GTK to keep processing this event. */ -#ifndef HAVE_GTK3 static gboolean xg_tool_bar_item_expose_callback (GtkWidget *w, GdkEventExpose *event, @@ -4537,14 +4767,13 @@ xg_tool_bar_item_expose_callback (GtkWidget *w, return FALSE; } -#endif /* Attach a tool bar to frame F. */ static void xg_pack_tool_bar (struct frame *f, Lisp_Object pos) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; bool into_hbox = EQ (pos, Qleft) || EQ (pos, Qright); GtkWidget *top_widget = x->toolbar_widget; @@ -4603,7 +4832,7 @@ tb_size_cb (GtkWidget *widget, static void xg_create_tool_bar (struct frame *f) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; #ifdef HAVE_GTK3 GtkStyleContext *gsty; #endif @@ -4842,7 +5071,7 @@ xg_tool_item_stale_p (GtkWidget *wbutton, const char *stock_name, static bool xg_update_tool_bar_sizes (struct frame *f) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GtkRequisition req; int nl = 0, nr = 0, nt = 0, nb = 0; GtkWidget *top_widget = x->toolbar_widget; @@ -4928,7 +5157,11 @@ void update_frame_tool_bar (struct frame *f) { int i, j; - struct x_output *x = f->output_data.x; +#ifndef HAVE_PGTK + struct x_output *x = f->output_data.xp; +#else + struct pgtk_output *x = f->output_data.pgtk; +#endif int hmargin = 0, vmargin = 0; GtkToolbar *wtoolbar; GtkToolItem *ti; @@ -5245,7 +5478,7 @@ update_frame_tool_bar (struct frame *f) void free_frame_tool_bar (struct frame *f) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; if (x->toolbar_widget) { @@ -5291,7 +5524,7 @@ free_frame_tool_bar (struct frame *f) void xg_change_toolbar_position (struct frame *f, Lisp_Object pos) { - struct x_output *x = f->output_data.x; + xp_output *x = f->output_data.xp; GtkWidget *top_widget = x->toolbar_widget; if (! x->toolbar_widget || ! top_widget) diff --git a/src/gtkutil.h b/src/gtkutil.h index 5419167cd7..5087b3167d 100644 --- a/src/gtkutil.h +++ b/src/gtkutil.h @@ -25,7 +25,13 @@ along with GNU Emacs. If not, see . */ #include #include "../lwlib/lwlib-widget.h" +#ifdef HAVE_PGTK +#include "pgtkterm.h" +#define EVENT GdkEvent +#else #include "xterm.h" +#define EVENT XEvent +#endif /* Minimum and maximum values used for GTK scroll bars */ @@ -105,7 +111,7 @@ extern void xg_modify_menubar_widgets (GtkWidget *menubar, extern void xg_update_frame_menubar (struct frame *f); -extern bool xg_event_is_for_menubar (struct frame *, const XEvent *); +extern bool xg_event_is_for_menubar (struct frame *, const EVENT *); extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid); @@ -142,7 +148,7 @@ extern void xg_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole); -extern bool xg_event_is_for_scrollbar (struct frame *, const XEvent *); +extern bool xg_event_is_for_scrollbar (struct frame *, const EVENT *); extern int xg_get_default_scrollbar_width (struct frame *f); extern int xg_get_default_scrollbar_height (struct frame *f); @@ -157,9 +163,15 @@ extern void xg_frame_set_char_size (struct frame *f, int width, int height); extern GtkWidget * xg_win_to_widget (Display *dpy, Window wdesc); extern int xg_get_scale (struct frame *f); +#ifndef HAVE_PGTK extern void xg_display_open (char *display_name, Display **dpy); extern void xg_display_close (Display *dpy); extern GdkCursor * xg_create_default_cursor (Display *dpy); +#else +extern void xg_display_open (char *display_name, GdkDisplay **dpy); +extern void xg_display_close (GdkDisplay *gdpy); +extern GdkCursor * xg_create_default_cursor (GdkDisplay *gdpy); +#endif extern bool xg_create_frame_widgets (struct frame *f); extern void xg_free_frame_widgets (struct frame *f); diff --git a/src/image.c b/src/image.c index 5eb4132295..74cd6b854d 100644 --- a/src/image.c +++ b/src/image.c @@ -129,6 +129,10 @@ typedef struct ns_bitmap_record Bitmap_Record; #endif /* HAVE_NS */ +#ifdef HAVE_PGTK +typedef struct pgtk_bitmap_record Bitmap_Record; +#endif /* HAVE_PGTK */ + #if (defined HAVE_X_WINDOWS \ && ! (defined HAVE_NTGUI || defined USE_CAIRO || defined HAVE_NS)) /* W32_TODO : Color tables on W32. */ @@ -430,6 +434,14 @@ image_create_bitmap_from_data (struct frame *f, char *bits, return -1; #endif +#ifdef HAVE_PGTK + Emacs_Pixmap bitmap = image_pix_container_create_from_bitmap_data(f, bits, + width, + height, + 0xffffffff, + 0xff000000); +#endif + id = image_allocate_bitmap_record (f); #ifdef HAVE_NS @@ -437,6 +449,11 @@ image_create_bitmap_from_data (struct frame *f, char *bits, dpyinfo->bitmaps[id - 1].depth = 1; #endif +#ifdef HAVE_PGTK + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].depth = 1; +#endif + dpyinfo->bitmaps[id - 1].file = NULL; dpyinfo->bitmaps[id - 1].height = height; dpyinfo->bitmaps[id - 1].width = width; @@ -489,6 +506,10 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) return id; #endif +#ifdef HAVE_PGTK + return -1; // fixme: +#endif + #ifdef HAVE_X_WINDOWS unsigned int width, height; Pixmap bitmap; @@ -561,6 +582,9 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) ns_release_object (bm->img); #endif +#ifdef HAVE_PGTK +#endif + if (bm->file) { xfree (bm->file); @@ -1320,7 +1344,6 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) return ascent; } - /* Image background colors. */ @@ -1344,6 +1367,7 @@ four_corners_best (Emacs_Pix_Context pimg, int *corners, corner_pixels[3] = GET_PIXEL (pimg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1); } else + { /* Get the colors at the corner_pixels of pimg. */ corner_pixels[0] = GET_PIXEL (pimg, 0, 0); @@ -3908,6 +3932,13 @@ xbm_load (struct frame *f, struct image *img) XPM images ***********************************************************************/ +#if defined (HAVE_XPM) || defined (HAVE_NS) || defined (HAVE_PGTK) + +static bool xpm_image_p (Lisp_Object object); +static bool xpm_load (struct frame *f, struct image *img); + +#endif /* HAVE_XPM || HAVE_NS */ + #ifdef HAVE_XPM #ifdef HAVE_NTGUI /* Indicate to xpm.h that we don't have Xlib. */ @@ -4795,7 +4826,7 @@ xpm_load_image (struct frame *f, Lisp_Object (*get_color_table) (Lisp_Object, const char *, int); Lisp_Object frame, color_symbols, color_table; int best_key; -#ifndef HAVE_NS +#if !defined(HAVE_NS) bool have_mask = false; #endif Emacs_Pix_Container ximg = NULL, mask_img = NULL; @@ -4849,7 +4880,7 @@ xpm_load_image (struct frame *f, } if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0) -#ifndef HAVE_NS +#if !defined(HAVE_NS) || !image_create_x_image_and_pixmap (f, img, width, height, 1, &mask_img, 1) #endif @@ -4977,7 +5008,7 @@ xpm_load_image (struct frame *f, PUT_PIXEL (ximg, x, y, FIXNUMP (color_val) ? XFIXNUM (color_val) : frame_fg); -#ifndef HAVE_NS +#if !defined(HAVE_NS) PUT_PIXEL (mask_img, x, y, (!EQ (color_val, Qt) ? PIX_MASK_DRAW : (have_mask = true, PIX_MASK_RETAIN))); @@ -4998,7 +5029,7 @@ xpm_load_image (struct frame *f, IMAGE_BACKGROUND (img, f, ximg); image_put_x_image (f, img, ximg, 0); -#ifndef HAVE_NS +#if !defined(HAVE_NS) if (have_mask) { /* Fill in the background_transparent field while we have the @@ -5729,7 +5760,7 @@ image_disable_image (struct frame *f, struct image *img) if (n_planes < 2 || cross_disabled_images) { #ifndef HAVE_NTGUI -#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */ +#if !defined(HAVE_NS) /* TODO: NS support, however this not needed for toolbars */ #ifndef USE_CAIRO #define CrossForeground(f) BLACK_PIX_DEFAULT (f) @@ -5807,7 +5838,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, image_clear_image_1 (f, img, CLEAR_IMAGE_MASK); #ifndef HAVE_NTGUI -#ifndef HAVE_NS +#if !defined HAVE_NS /* Create an image and pixmap serving as mask. */ if (! image_create_x_image_and_pixmap (f, img, img->width, img->height, 1, &mask_img, 1)) @@ -5869,7 +5900,7 @@ image_build_heuristic_mask (struct frame *f, struct image *img, if (XGetPixel (ximg, x, y) == bg) ns_set_alpha (ximg, x, y, 0); #endif /* HAVE_NS */ -#ifndef HAVE_NS +#if !defined HAVE_NS /* Fill in the background_transparent field while we have the mask handy. */ image_background_transparent (img, f, mask_img); @@ -9314,8 +9345,8 @@ imagemagick_load_image (struct frame *f, struct image *img, color_scale * pixel.red, color_scale * pixel.green, color_scale * pixel.blue)); - } - } + } + } DestroyPixelIterator (iterator); } @@ -10511,7 +10542,7 @@ static struct image_type const image_types[] = { SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image, IMAGE_TYPE_INIT (init_jpeg_functions) }, #endif -#if defined HAVE_XPM || defined HAVE_NS +#if defined HAVE_XPM || defined HAVE_NS || defined USE_CAIRO { SYMBOL_INDEX (Qxpm), xpm_image_p, xpm_load, image_clear_image, IMAGE_TYPE_INIT (init_xpm_functions) }, #endif diff --git a/src/lisp.h b/src/lisp.h index 76d74200ac..718c0f12a5 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3298,7 +3298,7 @@ struct frame; #endif /* Define if the windowing system provides a tool-bar. */ -#if defined (USE_GTK) || defined (HAVE_NS) +#if (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) #define HAVE_EXT_TOOL_BAR true #endif diff --git a/src/pgtkfns.c b/src/pgtkfns.c new file mode 100644 index 0000000000..39f5887320 --- /dev/null +++ b/src/pgtkfns.c @@ -0,0 +1,2778 @@ +/* Functions for the pure Gtk+-3. + +Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2017 Free Software +Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#include +#include + +#include "lisp.h" +#include "blockinput.h" +#include "gtkutil.h" +#include "window.h" +#include "character.h" +#include "buffer.h" +#include "keyboard.h" +#include "termhooks.h" +#include "fontset.h" +#include "font.h" +#include "xsettings.h" + + +#ifdef HAVE_PGTK + +//static EmacsTooltip *pgtk_tooltip = nil; + +/* Static variables to handle applescript execution. */ +static Lisp_Object as_script, *as_result; +static int as_status; + +static ptrdiff_t image_cache_refcount; + +static struct pgtk_display_info *pgtk_display_info_for_name (Lisp_Object); +static void pgtk_set_name_as_filename (struct frame *); + +static const char *pgtk_app_name = "Emacs"; + +/* ========================================================================== + + Internal utility functions + + ========================================================================== */ + +static struct pgtk_display_info * +check_pgtk_display_info (Lisp_Object object) +{ + struct pgtk_display_info *dpyinfo = NULL; + + if (NILP (object)) + { + struct frame *sf = XFRAME (selected_frame); + + if (FRAME_PGTK_P (sf) && FRAME_LIVE_P (sf)) + dpyinfo = FRAME_DISPLAY_INFO (sf); + else if (x_display_list != 0) + dpyinfo = x_display_list; + else + error ("Frames are not in use or not initialized"); + } + else if (TERMINALP (object)) + { + struct terminal *t = decode_live_terminal (object); + + if (t->type != output_pgtk) + error ("Terminal %d is not a display", t->id); + + dpyinfo = t->display_info.pgtk; + } + else if (STRINGP (object)) + dpyinfo = pgtk_display_info_for_name (object); + else + { + struct frame *f = decode_window_system_frame (object); + dpyinfo = FRAME_DISPLAY_INFO (f); + } + + return dpyinfo; +} + +/* Return the X display structure for the display named NAME. + Open a new connection if necessary. */ +static struct pgtk_display_info * +pgtk_display_info_for_name (Lisp_Object name) +{ + struct pgtk_display_info *dpyinfo; + + CHECK_STRING (name); + + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) + if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name))) + return dpyinfo; + + /* Use this general default value to start with. */ + Vx_resource_name = Vinvocation_name; + + validate_x_resource_name (); + + dpyinfo = pgtk_term_init (name, SSDATA (Vx_resource_name)); + + if (dpyinfo == 0) + error ("Cannot connect to display server %s", SDATA (name)); + + XSETFASTINT (Vwindow_system_version, 11); + + return dpyinfo; +} + +/* ========================================================================== + + Frame parameter setters + + ========================================================================== */ + + +static void +x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + Emacs_Color col; + + /* Must block_input, because pgtk_lisp_to_color does block/unblock_input + which means that col may be deallocated in its unblock_input if there + is user input, unless we also block_input. */ + block_input (); + if (pgtk_lisp_to_color (arg, &col)) + { + store_frame_param (f, Qforeground_color, oldval); + unblock_input (); + error ("Unknown color"); + } + + FRAME_X_OUTPUT(f)->foreground_color = col.pixel; + + FRAME_FOREGROUND_PIXEL (f) = col.pixel; + + if (FRAME_GTK_WIDGET (f)) + { + update_face_from_frame_parameter (f, Qforeground_color, arg); + /*recompute_basic_faces (f); */ + if (FRAME_VISIBLE_P (f)) + SET_FRAME_GARBAGED (f); + } + unblock_input (); +} + + +static void +x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + Emacs_Color col; + + block_input (); + if (pgtk_lisp_to_color (arg, &col)) + { + store_frame_param (f, Qbackground_color, oldval); + unblock_input (); + error ("Unknown color"); + } + + /* clear the frame */ + if (FRAME_VISIBLE_P (f)) + pgtk_clear_frame (f); + + PGTK_TRACE("x_set_background_color: col.pixel=%08lx.", col.pixel); + FRAME_X_OUTPUT(f)->background_color = col.pixel; + FRAME_BACKGROUND_PIXEL (f) = + ARGB_TO_ULONG ((int)(0xff), (int)(col.red>>8), (int)(col.green>>8), (int)(col.blue>>8)); + + xg_set_background_color(f, col.pixel); + update_face_from_frame_parameter (f, Qbackground_color, arg); + + PGTK_TRACE("visible_p=%d.", FRAME_VISIBLE_P(f)); + if (FRAME_VISIBLE_P (f)) + SET_FRAME_GARBAGED (f); + + unblock_input (); +} + + +static void +x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + Emacs_Color col; + + block_input (); + if (pgtk_lisp_to_color (arg, &col)) + { + store_frame_param (f, Qcursor_color, oldval); + unblock_input (); + error ("Unknown color"); + } + + FRAME_CURSOR_COLOR (f) = col.pixel; + + if (FRAME_VISIBLE_P (f)) + { + x_update_cursor (f, 0); + x_update_cursor (f, 1); + } + update_face_from_frame_parameter (f, Qcursor_color, arg); + unblock_input (); +} + + +static void +x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); + PGTK_TRACE ("x_set_icon_name"); + + /* see if it's changed */ + if (STRINGP (arg)) + { + if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + return; + } + else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil)) + return; + + fset_icon_name (f, arg); + + if (NILP (arg)) + { + if (!NILP (f->title)) + arg = f->title; + else + /* Explicit name and no icon-name -> explicit_name. */ + if (f->explicit_name) + arg = f->name; + else + { + /* No explicit name and no icon-name -> + name has to be rebuild from icon_title_format. */ + windows_or_buffers_changed = 67; + return; + } + } + + gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA(arg)); +} + +static void +pgtk_set_name_internal (struct frame *f, Lisp_Object name) +{ + Lisp_Object encoded_name, encoded_icon_name; + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + + encoded_name = ENCODE_UTF_8 (name); + gtk_window_set_title(GTK_WINDOW(widget), SSDATA (encoded_name)); + + if (!STRINGP (f->icon_name)) + encoded_icon_name = encoded_name; + else + encoded_icon_name = ENCODE_UTF_8 (f->icon_name); + gtk_window_set_icon_name(GTK_WINDOW(widget), SSDATA (encoded_icon_name)); +} + +static void +pgtk_set_name (struct frame *f, Lisp_Object name, int explicit) +{ + PGTK_TRACE ("pgtk_set_name"); + + /* Make sure that requests from lisp code override requests from + Emacs redisplay code. */ + if (explicit) + { + /* If we're switching from explicit to implicit, we had better + update the mode lines and thereby update the title. */ + if (f->explicit_name && NILP (name)) + update_mode_lines = 12; + + f->explicit_name = ! NILP (name); + } + else if (f->explicit_name) + return; + + if (NILP (name)) + name = build_string (pgtk_app_name); + else + CHECK_STRING (name); + + /* Don't change the name if it's already NAME. */ + if (! NILP (Fstring_equal (name, f->name))) + return; + + fset_name (f, name); + + /* Title overrides explicit name. */ + if (! NILP (f->title)) + name = f->title; + + pgtk_set_name_internal (f, name); +} + + +/* This function should be called when the user's lisp code has + specified a name for the frame; the name will override any set by the + redisplay code. */ +static void +x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + PGTK_TRACE ("x_explicitly_set_name"); + pgtk_set_name (f, arg, 1); +} + + +/* This function should be called by Emacs redisplay code to set the + name; names set this way will never override names set by the user's + lisp code. */ +void +x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + PGTK_TRACE ("x_implicitly_set_name"); + + Lisp_Object frame_title = buffer_local_value + (Qframe_title_format, XWINDOW (f->selected_window)->contents); + Lisp_Object icon_title = buffer_local_value + (Qicon_title_format, XWINDOW (f->selected_window)->contents); + + if (FRAME_PGTK_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (icon_title, Qt)) + || EQ (frame_title, Qt))) + pgtk_set_name_as_filename (f); + else + pgtk_set_name (f, arg, 0); +} + + +/* Change the title of frame F to NAME. + If NAME is nil, use the frame name as the title. */ + +static void +x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) +{ + PGTK_TRACE ("x_set_title"); + /* Don't change the title if it's already NAME. */ + if (EQ (name, f->title)) + return; + + update_mode_lines = 22; + + fset_title (f, name); + + if (NILP (name)) + name = f->name; + else + CHECK_STRING (name); + + pgtk_set_name_internal (f, name); +} + + +static void +pgtk_set_name_as_filename (struct frame *f) +{ + GtkWidget *widget; + Lisp_Object name, filename; + Lisp_Object buf = XWINDOW (f->selected_window)->contents; + const char *title; + Lisp_Object encoded_name, encoded_filename; + const char *str; + PGTK_TRACE ("pgtk_set_name_as_filename"); + + if (f->explicit_name || ! NILP (f->title)) + return; + + block_input (); + filename = BVAR (XBUFFER (buf), filename); + name = BVAR (XBUFFER (buf), name); + + if (NILP (name)) + { + if (! NILP (filename)) + name = Ffile_name_nondirectory (filename); + else + name = build_string (pgtk_app_name); + } + + encoded_name = ENCODE_UTF_8 (name); + + widget = FRAME_GTK_OUTER_WIDGET (f); + + title = FRAME_ICONIFIED_P (f) ? gtk_window_get_icon_name(GTK_WINDOW(widget)) + : gtk_window_get_title(GTK_WINDOW(widget)); + + if (title && (! strcmp (title, SSDATA (encoded_name)))) + { + unblock_input (); + return; + } + + str = SSDATA (encoded_name); + if (str == NULL) str = "Bad coding"; + + if (FRAME_ICONIFIED_P (f)) + gtk_window_set_icon_name(GTK_WINDOW(widget), str); + else + { + const char *fstr; + + if (! NILP (filename)) + { + encoded_filename = ENCODE_UTF_8 (filename); + + fstr = SSDATA (encoded_filename); + if (fstr == NULL) fstr = ""; + } + else + fstr = ""; + + gtk_window_set_title(GTK_WINDOW(widget), str); + fset_name (f, name); + } + + unblock_input (); +} + + +void +pgtk_set_doc_edited (void) +{ +} + + +static void +x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ +#if 0 + int nlines; + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + if (TYPE_RANGED_INTEGERP (int, value)) + nlines = XFIXNUM (value); + else + nlines = 0; + + FRAME_MENU_BAR_LINES (f) = 0; + if (nlines) + { + FRAME_EXTERNAL_MENU_BAR (f) = 1; + /* does for all frames, whereas we just want for one frame + [NSMenu setMenuBarVisible: YES]; */ + } + else + { + if (FRAME_EXTERNAL_MENU_BAR (f) == 1) + free_frame_menubar (f); + /* [NSMenu setMenuBarVisible: NO]; */ + FRAME_EXTERNAL_MENU_BAR (f) = 0; + } +#endif +} + + +/* toolbar support */ +static void +x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ +#if 0 + /* Currently, when the tool bar change state, the frame is resized. + + TODO: It would be better if this didn't occur when 1) the frame + is full height or maximized or 2) when specified by + `frame-inhibit-implied-resize'. */ + int nlines; + + NSTRACE ("x_set_tool_bar_lines"); + + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + if (RANGED_INTEGERP (0, value, INT_MAX)) + nlines = XFIXNAT (value); + else + nlines = 0; + + if (nlines) + { + FRAME_EXTERNAL_TOOL_BAR (f) = 1; + update_frame_tool_bar (f); + } + else + { + if (FRAME_EXTERNAL_TOOL_BAR (f)) + { + free_frame_tool_bar (f); + FRAME_EXTERNAL_TOOL_BAR (f) = 0; + + { + EmacsView *view = FRAME_PGTK_VIEW (f); + int fs_state = [view fullscreenState]; + + if (fs_state == FULLSCREEN_MAXIMIZED) + { + [view setFSValue:FULLSCREEN_WIDTH]; + } + else if (fs_state == FULLSCREEN_HEIGHT) + { + [view setFSValue:FULLSCREEN_NONE]; + } + } + } + } + + { + int inhibit + = ((f->after_make_frame + && !f->tool_bar_resized + && (EQ (frame_inhibit_implied_resize, Qt) + || (CONSP (frame_inhibit_implied_resize) + && !NILP (Fmemq (Qtool_bar_lines, + frame_inhibit_implied_resize)))) + && NILP (get_frame_param (f, Qfullscreen))) + ? 0 + : 2); + + NSTRACE_MSG ("inhibit:%d", inhibit); + + frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil); + adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines); + } +#endif +} + + +static void +x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +#if 0 + int old_width = FRAME_INTERNAL_BORDER_WIDTH (f); + + CHECK_TYPE_RANGED_INTEGER (int, arg); + f->internal_border_width = XFIXNUM (arg); + if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0) + f->internal_border_width = 0; + + if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width) + return; + + if (FRAME_X_WINDOW (f) != 0) + adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width); + + SET_FRAME_GARBAGED (f); +#endif +} + + +static void +x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + /* This does not work if on Wayland, or if icon is defined in emacs.desktop + * even if on X11. + */ + GdkPixbuf *pixbuf; + if (NILP (arg) || EQ (arg, Qt)) + pixbuf = NULL; + else { + GError *err = NULL; + CHECK_STRING (arg); + pixbuf = gdk_pixbuf_new_from_file (SSDATA (arg), &err); + if (pixbuf == NULL) { + Lisp_Object msg = build_string (err->message); + g_error_free (err); + error ("%s", SSDATA (msg)); + } + } + + gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf); + if (pixbuf != NULL) + g_object_unref (pixbuf); +} + +/* This is the same as the xfns.c definition. */ +static void +x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + set_frame_cursor_types (f, arg); +} + +/* called to set mouse pointer color, but all other terms use it to + initialize pointer types (and don't set the color ;) */ +static void +x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ +} + + +static void +x_icon (struct frame *f, Lisp_Object parms) +/* -------------------------------------------------------------------------- + Strangely-named function to set icon position parameters in frame. + This is irrelevant under macOS, but might be needed under GNUstep, + depending on the window manager used. Note, this is not a standard + frame parameter-setter; it is called directly from x-create-frame. + -------------------------------------------------------------------------- */ +{ +#if 0 + Lisp_Object icon_x, icon_y; + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (Qnil); + + FRAME_X_OUTPUT(f)->icon_top = -1; + FRAME_X_OUTPUT(f)->icon_left = -1; + + /* Set the position of the icon. */ + icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); + icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); + if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) + { + CHECK_NUMBER (icon_x); + CHECK_NUMBER (icon_y); + FRAME_X_OUTPUT(f)->icon_top = XFIXNUM (icon_y); + FRAME_X_OUTPUT(f)->icon_left = XFIXNUM (icon_x); + } + else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) + error ("Both left and top icon corners of icon must be specified"); +#endif +} + +/** + * x_set_override_redirect: + * + * Set frame F's `override_redirect' parameter which, if non-nil, hints + * that the window manager doesn't want to deal with F. Usually, such + * frames have no decorations and always appear on top of all frames. + * + * Some window managers may not honor this parameter. + */ +static void +x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +{ + if (!EQ (new_value, old_value)) + { + /* Here (xfwm) override_redirect can be changed for invisible + frames only. */ + x_make_frame_invisible (f); + + xg_set_override_redirect (f, new_value); + + x_make_frame_visible (f); + FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value); + } +} + +/* Note: see frame.c for template, also where generic functions are impl */ +frame_parm_handler pgtk_frame_parm_handlers[] = +{ + x_set_autoraise, /* generic OK */ + x_set_autolower, /* generic OK */ + x_set_background_color, + 0, /* x_set_border_color, may be impossible under Nextstep */ + 0, /* x_set_border_width, may be impossible under Nextstep */ + x_set_cursor_color, + x_set_cursor_type, + x_set_font, /* generic OK */ + x_set_foreground_color, + x_set_icon_name, + x_set_icon_type, + x_set_internal_border_width, /* generic OK */ + x_set_right_divider_width, + x_set_bottom_divider_width, + x_set_menu_bar_lines, + x_set_mouse_color, + x_explicitly_set_name, + x_set_scroll_bar_width, /* generic OK */ + x_set_scroll_bar_height, /* generic OK */ + x_set_title, + x_set_unsplittable, /* generic OK */ + x_set_vertical_scroll_bars, /* generic OK */ + x_set_horizontal_scroll_bars, /* generic OK */ + x_set_visibility, /* generic OK */ + x_set_tool_bar_lines, + 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */ + 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */ + x_set_screen_gamma, /* generic OK */ + x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ + x_set_left_fringe, /* generic OK */ + x_set_right_fringe, /* generic OK */ + 0, /* x_set_wait_for_wm, will ignore */ + x_set_fullscreen, /* generic OK */ + x_set_font_backend, /* generic OK */ + x_set_alpha, + 0, /* x_set_sticky */ + 0, /* x_set_tool_bar_position */ + 0, /* x_set_inhibit_double_buffering */ + 0, /*x_set_undecorated */ + 0, /* x_set_parent_frame, */ + 0, /* x_set_skip_taskbar */ + x_set_no_focus_on_map, + x_set_no_accept_focus, + x_set_z_group, + x_set_override_redirect, + x_set_no_special_glyphs, +}; + + +/* Handler for signals raised during x_create_frame and + x_create_tip_frame. FRAME is the frame which is partially + constructed. */ + +static Lisp_Object +unwind_create_frame (Lisp_Object frame) +{ + struct frame *f = XFRAME (frame); + + /* If frame is already dead, nothing to do. This can happen if the + display is disconnected after the frame has become official, but + before x_create_frame removes the unwind protect. */ + if (!FRAME_LIVE_P (f)) + return Qnil; + + /* If frame is ``official'', nothing to do. */ + if (NILP (Fmemq (frame, Vframe_list))) + { + /* If the frame's image cache refcount is still the same as our + private shadow variable, it means we are unwinding a frame + for which we didn't yet call init_frame_faces, where the + refcount is incremented. Therefore, we increment it here, so + that free_frame_faces, called in x_free_frame_resources + below, will not mistakenly decrement the counter that was not + incremented yet to account for this new frame. */ + if (FRAME_IMAGE_CACHE (f) != NULL + && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount) + FRAME_IMAGE_CACHE (f)->refcount++; + + x_free_frame_resources (f); + free_glyphs (f); + return Qt; + } + + return Qnil; +} + +static void +do_unwind_create_frame (Lisp_Object frame) +{ + unwind_create_frame (frame); +} + +/* Return the pixel color value for color COLOR_NAME on frame F. If F + is a monochrome frame, return MONO_COLOR regardless of what ARG says. + Signal an error if color can't be allocated. */ + +static int +x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color) +{ + Emacs_Color cdef; + + CHECK_STRING (color_name); + + /* Return MONO_COLOR for monochrome frames. */ + if (FRAME_DISPLAY_INFO (f)->n_planes == 1) + return mono_color; + + /* x_defined_color is responsible for coping with failures + by looking for a near-miss. */ + if (pgtk_defined_color (f, SSDATA (color_name), &cdef, true, 0)) + return cdef.pixel; + + signal_error ("Undefined color", color_name); +} + +static void +x_default_font_parameter (struct frame *f, Lisp_Object parms) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL, + RES_TYPE_STRING); + Lisp_Object font = Qnil; + if (EQ (font_param, Qunbound)) + font_param = Qnil; + + if (NILP (font_param)) + { + /* System font should take precedence over X resources. We suggest this + regardless of font-use-system-font because .emacs may not have been + read yet. */ + const char *system_font = xsettings_get_system_font (); + if (system_font) + font = font_open_by_name (f, build_unibyte_string (system_font)); + } + + if (NILP (font)) + font = !NILP (font_param) ? font_param + : x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING); + + if (! FONTP (font) && ! STRINGP (font)) + { + const char *names[] + = { + "monospace-10", + "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1", + "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", + "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1", + /* This was formerly the first thing tried, but it finds + too many fonts and takes too long. */ + "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1", + /* If those didn't work, look for something which will + at least work. */ + "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1", + "fixed", + NULL }; + int i; + + for (i = 0; names[i]; i++) + { + font = font_open_by_name (f, build_unibyte_string (names[i])); + if (! NILP (font)) + break; + } + if (NILP (font)) + error ("No suitable font was found"); + } + else if (!NILP (font_param)) + { + /* Remember the explicit font parameter, so we can re-apply it after + we've applied the `default' face settings. */ + AUTO_FRAME_ARG (arg, Qfont_parameter, font_param); + x_set_frame_parameters (f, arg); + } + + /* This call will make X resources override any system font setting. */ + x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING); +} + +/* ========================================================================== + + Lisp definitions + + ========================================================================== */ + +DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, + 1, 1, 0, + doc: /* Make a new X window, which is called a "frame" in Emacs terms. +Return an Emacs frame object. PARMS is an alist of frame parameters. +If the parameters specify that the frame should not have a minibuffer, +and do not specify a specific minibuffer window to use, then +`default-minibuffer-frame' must be a frame whose minibuffer can be +shared by the new frame. + +This function is an internal primitive--use `make-frame' instead. */) + (Lisp_Object parms) +{ + struct frame *f; + Lisp_Object frame, tem; + Lisp_Object name; + bool minibuffer_only = false; + bool undecorated = false, override_redirect = false; + long window_prompting = 0; + ptrdiff_t count = SPECPDL_INDEX (); + Lisp_Object display; + struct pgtk_display_info *dpyinfo = NULL; + Lisp_Object parent, parent_frame; + struct kboard *kb; + int x_width = 0, x_height = 0; + + parms = Fcopy_alist (parms); + + /* Use this general default value to start with + until we know if this frame has a specified name. */ + Vx_resource_name = Vinvocation_name; + + display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); + if (EQ (display, Qunbound)) + display = x_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); + if (EQ (display, Qunbound)) + display = Qnil; + dpyinfo = check_pgtk_display_info (display); + kb = dpyinfo->terminal->kboard; + + if (!dpyinfo->terminal->name) + error ("Terminal is not live, can't create new frames on it"); + + name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); + if (!STRINGP (name) + && ! EQ (name, Qunbound) + && ! NILP (name)) + error ("Invalid frame name--not a string or nil"); + + if (STRINGP (name)) + Vx_resource_name = name; + + /* See if parent window is specified. */ + parent = x_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); + if (EQ (parent, Qunbound)) + parent = Qnil; + if (! NILP (parent)) + CHECK_NUMBER (parent); + + frame = Qnil; + tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer", + RES_TYPE_SYMBOL); + if (EQ (tem, Qnone) || NILP (tem)) + f = make_frame_without_minibuffer (Qnil, kb, display); + else if (EQ (tem, Qonly)) + { + f = make_minibuffer_frame (); + minibuffer_only = true; + } + else if (WINDOWP (tem)) + f = make_frame_without_minibuffer (tem, kb, display); + else + f = make_frame (true); + + parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, + RES_TYPE_SYMBOL); + /* Accept parent-frame iff parent-id was not specified. */ + if (!NILP (parent) + || EQ (parent_frame, Qunbound) + || NILP (parent_frame) + || !FRAMEP (parent_frame) + || !FRAME_LIVE_P (XFRAME (parent_frame)) + || !FRAME_PGTK_P (XFRAME (parent_frame))) + parent_frame = Qnil; + + fset_parent_frame (f, parent_frame); + store_frame_param (f, Qparent_frame, parent_frame); + + if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, + RES_TYPE_BOOLEAN))) + && !(EQ (tem, Qunbound))) + undecorated = true; + + FRAME_UNDECORATED (f) = undecorated; + store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil); + + if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL, + RES_TYPE_BOOLEAN))) + && !(EQ (tem, Qunbound))) + override_redirect = true; + + FRAME_OVERRIDE_REDIRECT (f) = override_redirect; + store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil); + + XSETFRAME (frame, f); + + f->terminal = dpyinfo->terminal; + + f->output_method = output_pgtk; + FRAME_X_OUTPUT(f) = xzalloc (sizeof *FRAME_X_OUTPUT(f)); +#if 0 + FRAME_X_OUTPUT(f)->icon_bitmap = -1; +#endif + FRAME_FONTSET (f) = -1; +#if 0 + FRAME_X_OUTPUT(f)->scroll_bar_foreground_pixel = -1; + FRAME_X_OUTPUT(f)->scroll_bar_background_pixel = -1; +#endif + FRAME_X_OUTPUT(f)->white_relief.pixel = -1; + FRAME_X_OUTPUT(f)->black_relief.pixel = -1; + + fset_icon_name (f, + x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", + RES_TYPE_STRING)); + if (! STRINGP (f->icon_name)) + fset_icon_name (f, Qnil); + + FRAME_DISPLAY_INFO (f) = dpyinfo; + + /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */ + record_unwind_protect (do_unwind_create_frame, frame); + + /* These colors will be set anyway later, but it's important + to get the color reference counts right, so initialize them! */ + { + Lisp_Object black; + + /* Function x_decode_color can signal an error. Make + sure to initialize color slots so that we won't try + to free colors we haven't allocated. */ + FRAME_FOREGROUND_PIXEL (f) = -1; + FRAME_BACKGROUND_PIXEL (f) = -1; + FRAME_X_OUTPUT(f)->cursor_color = -1; +#if 0 + FRAME_X_OUTPUT(f)->cursor_foreground_pixel = -1; + FRAME_X_OUTPUT(f)->border_pixel = -1; + FRAME_X_OUTPUT(f)->mouse_pixel = -1; +#endif + + black = build_string ("black"); + FRAME_FOREGROUND_PIXEL (f) + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + FRAME_BACKGROUND_PIXEL (f) + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + FRAME_X_OUTPUT(f)->cursor_color + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); +#if 0 + FRAME_X_OUTPUT(f)->cursor_foreground_pixel + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + FRAME_X_OUTPUT(f)->border_pixel + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + FRAME_X_OUTPUT(f)->mouse_pixel + = x_decode_color (f, black, BLACK_PIX_DEFAULT (f)); +#endif + } + + /* Specify the parent under which to make this X window. */ + if (!NILP (parent)) + { + FRAME_X_OUTPUT(f)->parent_desc = (Window) XFIXNAT (parent); + FRAME_X_OUTPUT(f)->explicit_parent = true; + } + else + { + FRAME_X_OUTPUT(f)->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; + FRAME_X_OUTPUT(f)->explicit_parent = false; + } + + /* Set the name; the functions to which we pass f expect the name to + be set. */ + if (EQ (name, Qunbound) || NILP (name)) + { + fset_name (f, build_string (dpyinfo->x_id_name)); + f->explicit_name = false; + } + else + { + fset_name (f, name); + f->explicit_name = true; + /* Use the frame's title when getting resources for this frame. */ + specbind (Qx_resource_name, name); + } + + register_font_driver (&ftcrfont_driver, f); + + image_cache_refcount = + FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; +#if 0 +#ifdef GLYPH_DEBUG + dpyinfo_refcount = dpyinfo->reference_count; +#endif /* GLYPH_DEBUG */ +#endif + + x_default_parameter (f, parms, Qfont_backend, Qnil, + "fontBackend", "FontBackend", RES_TYPE_STRING); + + /* Extract the window parameters from the supplied values + that are needed to determine window geometry. */ + x_default_font_parameter (f, parms); + if (!FRAME_FONT (f)) + { + delete_frame (frame, Qnoelisp); + error ("Invalid frame font"); + } + + /* Frame contents get displaced if an embedded X window has a border. */ +#if 0 + if (! FRAME_X_EMBEDDED_P (f)) +#endif + x_default_parameter (f, parms, Qborder_width, make_fixnum (0), + "borderWidth", "BorderWidth", RES_TYPE_NUMBER); + + /* This defaults to 1 in order to match xterm. We recognize either + internalBorderWidth or internalBorder (which is what xterm calls + it). */ + if (NILP (Fassq (Qinternal_border_width, parms))) + { + Lisp_Object value; + + value = x_get_arg (dpyinfo, parms, Qinternal_border_width, + "internalBorder", "internalBorder", RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qinternal_border_width, value), + parms); + } + x_default_parameter (f, parms, Qinternal_border_width, + make_fixnum (0), + "internalBorderWidth", "internalBorderWidth", + RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qvertical_scroll_bars, + Qright, + "verticalScrollBars", "ScrollBars", + RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil, + "horizontalScrollBars", "ScrollBars", + RES_TYPE_SYMBOL); + /* Also do the stuff which must be set before the window exists. */ + x_default_parameter (f, parms, Qforeground_color, build_string ("black"), + "foreground", "Foreground", RES_TYPE_STRING); + x_default_parameter (f, parms, Qbackground_color, build_string ("white"), + "background", "Background", RES_TYPE_STRING); + x_default_parameter (f, parms, Qmouse_color, build_string ("black"), + "pointerColor", "Foreground", RES_TYPE_STRING); + x_default_parameter (f, parms, Qborder_color, build_string ("black"), + "borderColor", "BorderColor", RES_TYPE_STRING); + x_default_parameter (f, parms, Qscreen_gamma, Qnil, + "screenGamma", "ScreenGamma", RES_TYPE_FLOAT); + x_default_parameter (f, parms, Qline_spacing, Qnil, + "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qleft_fringe, Qnil, + "leftFringe", "LeftFringe", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qright_fringe, Qnil, + "rightFringe", "RightFringe", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qno_special_glyphs, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + +#if 0 + x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground, + "scrollBarForeground", + "ScrollBarForeground", true); + x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background, + "scrollBarBackground", + "ScrollBarBackground", false); +#endif + + /* Init faces before x_default_parameter is called for the + scroll-bar-width parameter because otherwise we end up in + init_iterator with a null face cache, which should not happen. */ + init_frame_faces (f); + + /* We have to call adjust_frame_size here since otherwise + x_set_tool_bar_lines will already work with the character sizes + installed by init_frame_faces while the frame's pixel size is still + calculated from a character size of 1 and we subsequently hit the + (height >= 0) assertion in window_box_height. + + The non-pixelwise code apparently worked around this because it + had one frame line vs one toolbar line which left us with a zero + root window height which was obviously wrong as well ... + + Also process `min-width' and `min-height' parameters right here + because `frame-windows-min-size' needs them. */ + tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER); + if (NUMBERP (tem)) + store_frame_param (f, Qmin_width, tem); + tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER); + if (NUMBERP (tem)) + store_frame_param (f, Qmin_height, tem); + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, + Qx_create_frame_1); + + /* Set the menu-bar-lines and tool-bar-lines parameters. We don't + look up the X resources controlling the menu-bar and tool-bar + here; they are processed specially at startup, and reflected in + the values of the mode variables. */ + + x_default_parameter (f, parms, Qmenu_bar_lines, + NILP (Vmenu_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qtool_bar_lines, + NILP (Vtool_bar_mode) + ? make_fixnum (0) : make_fixnum (1), + NULL, NULL, RES_TYPE_NUMBER); + + x_default_parameter (f, parms, Qbuffer_predicate, Qnil, + "bufferPredicate", "BufferPredicate", + RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qtitle, Qnil, + "title", "Title", RES_TYPE_STRING); + x_default_parameter (f, parms, Qwait_for_wm, Qt, + "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qtool_bar_position, + FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qinhibit_double_buffering, Qnil, + "inhibitDoubleBuffering", "InhibitDoubleBuffering", + RES_TYPE_BOOLEAN); + + /* Compute the size of the X window. */ + window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height); + + tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); + f->no_split = minibuffer_only || EQ (tem, Qt); + +#if 0 + x_icon_verify (f, parms); +#endif + + /* Create the X widget or window. */ + // x_window (f); + xg_create_frame_widgets (f); + pgtk_set_event_handler(f); + + +#define INSTALL_CURSOR(FIELD, NAME) \ + FRAME_X_OUTPUT(f)->FIELD = gdk_cursor_new_for_display(FRAME_X_DISPLAY(f), GDK_ ## NAME) + + INSTALL_CURSOR(text_cursor, XTERM); + INSTALL_CURSOR(nontext_cursor, LEFT_PTR); + INSTALL_CURSOR(modeline_cursor, XTERM); + INSTALL_CURSOR(hand_cursor, HAND2); + INSTALL_CURSOR(hourglass_cursor, WATCH); + INSTALL_CURSOR(horizontal_drag_cursor, SB_H_DOUBLE_ARROW); + INSTALL_CURSOR(vertical_drag_cursor, SB_V_DOUBLE_ARROW); + INSTALL_CURSOR(left_edge_cursor, LEFT_SIDE); + INSTALL_CURSOR(right_edge_cursor, RIGHT_SIDE); + INSTALL_CURSOR(top_edge_cursor, TOP_SIDE); + INSTALL_CURSOR(bottom_edge_cursor, BOTTOM_SIDE); + INSTALL_CURSOR(top_left_corner_cursor, TOP_LEFT_CORNER); + INSTALL_CURSOR(top_right_corner_cursor, TOP_RIGHT_CORNER); + INSTALL_CURSOR(bottom_right_corner_cursor, BOTTOM_RIGHT_CORNER); + INSTALL_CURSOR(bottom_left_corner_cursor, BOTTOM_LEFT_CORNER); + +#undef INSTALL_CURSOR + + x_icon (f, parms); +#if 0 + x_make_gc (f); +#endif + + /* Now consider the frame official. */ + f->terminal->reference_count++; + FRAME_DISPLAY_INFO (f)->reference_count++; + Vframe_list = Fcons (frame, Vframe_list); + + /* We need to do this after creating the X window, so that the + icon-creation functions can say whose icon they're describing. */ + x_default_parameter (f, parms, Qicon_type, Qt, + "bitmapIcon", "BitmapIcon", RES_TYPE_BOOLEAN); + + x_default_parameter (f, parms, Qauto_raise, Qnil, + "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qauto_lower, Qnil, + "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qcursor_type, Qbox, + "cursorType", "CursorType", RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qscroll_bar_width, Qnil, + "scrollBarWidth", "ScrollBarWidth", + RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qscroll_bar_height, Qnil, + "scrollBarHeight", "ScrollBarHeight", + RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qalpha, Qnil, + "alpha", "Alpha", RES_TYPE_NUMBER); + +#if 0 + if (!NILP (parent_frame)) + { + struct frame *p = XFRAME (parent_frame); + + block_input (); + XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + FRAME_X_WINDOW (p), f->left_pos, f->top_pos); + unblock_input (); + } +#endif + + x_default_parameter (f, parms, Qno_focus_on_map, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qno_accept_focus, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) + /* Create the menu bar. */ + if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) + { +#if 0 + /* If this signals an error, we haven't set size hints for the + frame and we didn't make it visible. */ + initialize_frame_menubar (f); +#endif + +#ifndef USE_GTK + /* This is a no-op, except under Motif where it arranges the + main window for the widgets on it. */ + lw_set_main_areas (FRAME_X_OUTPUT(f)->column_widget, + FRAME_X_OUTPUT(f)->menubar_widget, + FRAME_X_OUTPUT(f)->edit_widget); +#endif /* not USE_GTK */ + } +#endif /* USE_X_TOOLKIT || USE_GTK */ + + /* Consider frame official, now. */ + f->can_x_set_window_size = true; + + if (x_width > 0) + SET_FRAME_WIDTH (f, x_width); + if (x_height > 0) + SET_FRAME_HEIGHT (f, x_height); + + /* Tell the server what size and position, etc, we want, and how + badly we want them. This should be done after we have the menu + bar so that its size can be taken into account. */ + block_input (); + x_wm_set_size_hint (f, window_prompting, false); + unblock_input (); + + adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), + 0, true, Qx_create_frame_2); + + /* Process fullscreen parameter here in the hope that normalizing a + fullheight/fullwidth frame will produce the size set by the last + adjust_frame_size call. */ + x_default_parameter (f, parms, Qfullscreen, Qnil, + "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); + + /* Make the window appear on the frame and enable display, unless + the caller says not to. However, with explicit parent, Emacs + cannot control visibility, so don't try. */ + if (!FRAME_X_OUTPUT(f)->explicit_parent) + { + Lisp_Object visibility + = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); + + if (EQ (visibility, Qicon)) + x_iconify_frame (f); + else + { + if (EQ (visibility, Qunbound)) + visibility = Qt; + + if (!NILP (visibility)) + x_make_frame_visible (f); + } + + store_frame_param (f, Qvisibility, visibility); + } + + /* Works iff frame has been already mapped. */ + x_default_parameter (f, parms, Qskip_taskbar, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); + /* The `z-group' parameter works only for visible frames. */ + x_default_parameter (f, parms, Qz_group, Qnil, + NULL, NULL, RES_TYPE_SYMBOL); + + /* Initialize `default-minibuffer-frame' in case this is the first + frame on this terminal. */ + if (FRAME_HAS_MINIBUF_P (f) + && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame)) + || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))) + kset_default_minibuffer_frame (kb, frame); + + /* All remaining specified parameters, which have not been "used" + by x_get_arg and friends, now go in the misc. alist of the frame. */ + for (tem = parms; CONSP (tem); tem = XCDR (tem)) + if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) + fset_param_alist (f, Fcons (XCAR (tem), f->param_alist)); + + FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; + FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + + /* Make sure windows on this frame appear in calls to next-window + and similar functions. */ + Vwindow_list = Qnil; + + return unbind_to (count, frame); +} + +void +x_focus_frame (struct frame *f, bool noactivate) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + +#if 0 + if (dpyinfo->x_focus_frame != f) + { + EmacsView *view = FRAME_PGTK_VIEW (f); + block_input (); + [NSApp activateIgnoringOtherApps: YES]; + [[view window] makeKeyAndOrderFront: view]; + unblock_input (); + } +#endif +} + +#if 0 +static int +pgtk_window_is_ancestor (PGTKWindow *win, PGTKWindow *candidate) +/* Test whether CANDIDATE is an ancestor window of WIN. */ +{ + if (candidate == NULL) + return 0; + else if (win == candidate) + return 1; + else + return pgtk_window_is_ancestor(win, [candidate parentWindow]); +} +#endif + +DEFUN ("pgtk-frame-list-z-order", Fpgtk_frame_list_z_order, + Spgtk_frame_list_z_order, 0, 1, 0, + doc: /* Return list of Emacs' frames, in Z (stacking) order. +If TERMINAL is non-nil and specifies a live frame, return the child +frames of that frame in Z (stacking) order. + +Frames are listed from topmost (first) to bottommost (last). */) + (Lisp_Object terminal) +{ + Lisp_Object frames = Qnil; +#if 0 + PGTKWindow *parent = nil; + + if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) + parent = [FRAME_PGTK_VIEW (XFRAME (terminal)) window]; + + for (PGTKWindow *win in [[NSApp orderedWindows] reverseObjectEnumerator]) + { + Lisp_Object frame; + + /* Check against [win parentWindow] so that it doesn't match itself. */ + if (parent == nil || pgtk_window_is_ancestor (parent, [win parentWindow])) + { + XSETFRAME (frame, ((EmacsView *)[win delegate])->emacsframe); + frames = Fcons(frame, frames); + } + } +#endif + + return frames; +} + +DEFUN ("pgtk-frame-restack", Fpgtk_frame_restack, Spgtk_frame_restack, 2, 3, 0, + doc: /* Restack FRAME1 below FRAME2. +This means that if both frames are visible and the display areas of +these frames overlap, FRAME2 (partially) obscures FRAME1. If optional +third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This +means that if both frames are visible and the display areas of these +frames overlap, FRAME1 (partially) obscures FRAME2. + +Some window managers may refuse to restack windows. */) + (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above) +{ + struct frame *f1 = decode_live_frame (frame1); + struct frame *f2 = decode_live_frame (frame2); + + if (FRAME_PGTK_VIEW (f1) && FRAME_PGTK_VIEW (f2)) + { +#if 0 + PGTKWindow *window = [FRAME_PGTK_VIEW (f1) window]; + NSInteger window2 = [[FRAME_PGTK_VIEW (f2) window] windowNumber]; + PGTKWindowOrderingMode flag = NILP (above) ? PGTKWindowBelow : PGTKWindowAbove; + + [window orderWindow: flag + relativeTo: window2]; + +#endif + return Qt; + } + else + { + error ("Cannot restack frames"); + return Qnil; + } +} + +const char * +pgtk_get_defaults_value (const char *key) +{ + return NULL; +} + +DEFUN ("pgtk-set-resource", Fpgtk_set_resource, Spgtk_set_resource, 3, 3, 0, + doc: /* Set property NAME of OWNER to VALUE, from the defaults database. +If OWNER is nil, Emacs is assumed. +If VALUE is nil, the default is removed. */) + (Lisp_Object owner, Lisp_Object name, Lisp_Object value) +{ + check_window_system (NULL); + if (NILP (owner)) + owner = build_string (pgtk_app_name); + CHECK_STRING (name); + + return Qnil; +} + + +DEFUN ("x-server-max-request-size", Fx_server_max_request_size, + Sx_server_max_request_size, + 0, 1, 0, + doc: /* This function is a no-op. It is only present for completeness. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + /* This function has no real equivalent under PGTK. Return nil to + indicate this. */ + return Qnil; +} + + +DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0, + doc: /* Return the "vendor ID" string of the display server TERMINAL. +\(Labeling every distributor as a "vendor" embodies the false assumption +that operating systems cannot be developed and distributed noncommercially.) +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return Qnil; +} + + +DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0, + doc: /* Return the version numbers of the server of display TERMINAL. +The value is a list of three integers: the major and minor +version numbers of the X Protocol in use, and the distributor-specific release +number. See also the function `x-server-vendor'. + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + /*NOTE: it is unclear what would best correspond with "protocol"; + we return 10.3, meaning Panther, since this is roughly the + level that GNUstep's APIs correspond to. + The last number is where we distinguish between the Apple + and GNUstep implementations ("distributor-specific release + number") and give int'ized versions of major.minor. */ + return list3i (0, 0, 0); +} + + +DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, + doc: /* Return the number of screens on the display server TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +Note: "screen" here is not in X11's. For the number of physical monitors, + use `(length \(display-monitor-attributes-list TERMINAL))' instead. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return make_fixnum (1); +} + + +DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, + doc: /* Return the height in millimeters of the the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the height in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkMonitor *gmon = gdk_display_get_monitor_at_point(gdpy, 0, 0); + return make_fixnum (gdk_monitor_get_height_mm(gmon)); +} + + +DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, + doc: /* Return the width in millimeters of the the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the width in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkMonitor *gmon = gdk_display_get_monitor_at_point(gdpy, 0, 0); + return make_fixnum (gdk_monitor_get_width_mm(gmon)); +} + + +DEFUN ("x-display-backing-store", Fx_display_backing_store, + Sx_display_backing_store, 0, 1, 0, + doc: /* Return an indication of whether the the display TERMINAL does backing store. +The value may be `buffered', `retained', or `non-retained'. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return Qnil; +} + + +DEFUN ("x-display-visual-class", Fx_display_visual_class, + Sx_display_visual_class, 0, 1, 0, + doc: /* Return the visual class of the the display TERMINAL. +The value is one of the symbols `static-gray', `gray-scale', +`static-color', `pseudo-color', `true-color', or `direct-color'. + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On PGTK, always return true-color. */) + (Lisp_Object terminal) +{ + return intern ("true-color"); +} + + +DEFUN ("x-display-save-under", Fx_display_save_under, + Sx_display_save_under, 0, 1, 0, + doc: /* Return t if TERMINAL supports the save-under feature. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return Qnil; +} + + +DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection, + 1, 3, 0, + doc: /* Open a connection to a display server. +DISPLAY is the name of the display to connect to. +Optional second arg XRM-STRING is a string of resources in xrdb format. +If the optional third arg MUST-SUCCEED is non-nil, +terminate Emacs if we can't open the connection. */) + (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed) +{ + struct pgtk_display_info *dpyinfo; + + if (NILP(display)) + display = build_string(""); + + CHECK_STRING (display); + + nxatoms_of_pgtkselect (); + dpyinfo = pgtk_term_init (display, SSDATA(Vx_resource_name)); + if (dpyinfo == 0) + { + if (!NILP (must_succeed)) + fatal ("Display on %s not responding.\n", + SSDATA (display)); + else + error ("Display on %s not responding.\n", + SSDATA (display)); + } + + return Qnil; +} + + +DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, + 1, 1, 0, + doc: /* Close the connection to TERMINAL's display server. +For TERMINAL, specify a terminal object, a frame or a display name (a +string). If TERMINAL is nil, that stands for the selected frame's +terminal. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + + if (dpyinfo->reference_count > 0) + error ("Display still has frames on it"); + + pgtk_delete_terminal (dpyinfo->terminal); + + return Qnil; +} + + +DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0, + doc: /* Return the list of display names that Emacs has connections to. */) + (void) +{ + Lisp_Object result = Qnil; + struct pgtk_display_info *ndi; + + for (ndi = x_display_list; ndi; ndi = ndi->next) + result = Fcons (XCAR (ndi->name_list_element), result); + + return result; +} + + +DEFUN ("pgtk-hide-others", Fpgtk_hide_others, Spgtk_hide_others, + 0, 0, 0, + doc: /* Hides all applications other than Emacs. */) + (void) +{ + check_window_system (NULL); + return Qnil; +} + +DEFUN ("pgtk-hide-emacs", Fpgtk_hide_emacs, Spgtk_hide_emacs, + 1, 1, 0, + doc: /* If ON is non-nil, the entire Emacs application is hidden. +Otherwise if Emacs is hidden, it is unhidden. +If ON is equal to `activate', Emacs is unhidden and becomes +the active application. */) + (Lisp_Object on) +{ + check_window_system (NULL); + return Qnil; +} + + +DEFUN ("pgtk-font-name", Fpgtk_font_name, Spgtk_font_name, 1, 1, 0, + doc: /* Determine font PostScript or family name for font NAME. +NAME should be a string containing either the font name or an XLFD +font descriptor. If string contains `fontset' and not +`fontset-startup', it is left alone. */) + (Lisp_Object name) +{ + char *nm; + CHECK_STRING (name); + nm = SSDATA (name); + + if (nm[0] != '-') + return name; + if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup")) + return name; + + char *str = pgtk_xlfd_to_fontname (SSDATA (name)); + name = build_string (str); + xfree(str); + return name; +} + +/* ========================================================================== + + Miscellaneous functions not called through hooks + + ========================================================================== */ + +/* called from frame.c */ +struct pgtk_display_info * +check_x_display_info (Lisp_Object frame) +{ + return check_pgtk_display_info (frame); +} + + +void +x_set_scroll_bar_default_width (struct frame *f) +{ + int unit = FRAME_COLUMN_WIDTH (f); + int minw = xg_get_default_scrollbar_width (f); + /* A minimum width of 14 doesn't look good for toolkit scroll bars. */ + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + unit - 1) / unit; + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw; +} + +void +x_set_scroll_bar_default_height (struct frame *f) +{ + int height = FRAME_LINE_HEIGHT (f); + int min_height = xg_get_default_scrollbar_height (f); + /* A minimum height of 14 doesn't look good for toolkit scroll bars. */ + FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = min_height; + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (min_height + height - 1) / height; +} + +/* terms impl this instead of x-get-resource directly */ +char * +x_get_string_resource (XrmDatabase rdb, const char *name, const char *class) +{ + /* remove appname prefix; TODO: allow for !="Emacs" */ + const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0); + + check_window_system (NULL); + + if (inhibit_x_resources) + /* --quick was passed, so this is a no-op. */ + return NULL; + + res = pgtk_get_defaults_value (toCheck); + return (char *) (!res ? NULL + : !c_strncasecmp (res, "YES", 3) ? "true" + : !c_strncasecmp (res, "NO", 2) ? "false" + : res); +} + + +Lisp_Object +x_get_focus_frame (struct frame *frame) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); + Lisp_Object focus; + + if (!dpyinfo->x_focus_frame) + return Qnil; + + XSETFRAME (focus, dpyinfo->x_focus_frame); + return focus; +} + +/* ========================================================================== + + Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'. + + ========================================================================== */ + + +DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, + doc: /* Internal function called by `color-defined-p', which see. */) + (Lisp_Object color, Lisp_Object frame) +{ + Emacs_Color col; + return pgtk_lisp_to_color (color, &col) ? Qnil : Qt; +} + + +DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, + doc: /* Internal function called by `color-values', which see. */) + (Lisp_Object color, Lisp_Object frame) +{ + Emacs_Color col; + + CHECK_STRING (color); + + block_input (); + + if (pgtk_lisp_to_color (color, &col)) + { + unblock_input (); + return Qnil; + } + + unblock_input (); + + return list3i (col.red, col.green, col.blue); +} + + +DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, + doc: /* Internal function called by `display-color-p', which see. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return Qt; +} + + +DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, + 0, 1, 0, + doc: /* Return t if the display supports shades of gray. +Note that color displays do support shades of gray. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + return Qnil; +} + + +DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, + 0, 1, 0, + doc: /* Return the width in pixels of the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel width for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + + return make_fixnum (x_display_pixel_width (dpyinfo)); +} + + +DEFUN ("x-display-pixel-height", Fx_display_pixel_height, + Sx_display_pixel_height, 0, 1, 0, + doc: /* Return the height in pixels of the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel height for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + + return make_fixnum (x_display_pixel_height (dpyinfo)); +} + +DEFUN ("pgtk-display-monitor-attributes-list", + Fpgtk_display_monitor_attributes_list, + Spgtk_display_monitor_attributes_list, + 0, 1, 0, + doc: /* Return a list of physical monitor attributes on the X display TERMINAL. + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +Internal use only, use `display-monitor-attributes-list' instead. */) + (Lisp_Object terminal) +{ + struct terminal *term = decode_live_terminal (terminal); + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkMonitor **gmons; + int i, n_monitors, primary_index; + struct MonitorInfo *monitors; + Lisp_Object monitor_frames = Qnil; + Lisp_Object frame = Qnil, rest = Qnil; + Lisp_Object rv = Qnil; + + if (term->type != output_pgtk) + return Qnil; + + n_monitors = gdk_display_get_n_monitors(gdpy); + if (n_monitors == 0) + return Qnil; + + gmons = xmalloc(sizeof *gmons * n_monitors); + for (i = 0; i < n_monitors; i++) + gmons[i] = gdk_display_get_monitor(gdpy, i); + + monitors = xzalloc (n_monitors * sizeof *monitors); + for (i = 0; i < n_monitors; i++) { + struct MonitorInfo *mon = &monitors[i]; + GdkMonitor *gmon = gmons[i]; + if (gmon != NULL) { + GdkRectangle geom; + gdk_monitor_get_geometry(gmon, &geom); + mon->geom.x = geom.x; + mon->geom.y = geom.y; + mon->geom.width = geom.width; + mon->geom.height = geom.height; + + gdk_monitor_get_workarea(gmon, &geom); + mon->work.x = geom.x; + mon->work.y = geom.y; + mon->work.width = geom.width; + mon->work.height = geom.height; + + mon->mm_width = gdk_monitor_get_width_mm(gmon); + mon->mm_height = gdk_monitor_get_height_mm(gmon); + + mon->name = xstrdup(gdk_monitor_get_model(gmon)); + } + } + + monitor_frames = Fmake_vector (make_fixnum (n_monitors), Qnil); + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_PGTK_P (f)) + { + GtkWidget *widget = FRAME_GTK_WIDGET(f); + GdkMonitor *gmon = gdk_display_get_monitor_at_window(gdpy, gtk_widget_get_window(widget)); + + if (gmon != NULL) { + for (i = 0; i < n_monitors; i++) { + if (gmons[i] == gmon) { + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); + break; + } + } + } + } + } + + primary_index = -1; + for (i = 0; i < n_monitors; i++) { + if (gmons[i] != NULL && gdk_monitor_is_primary(gmons[i])) { + primary_index = i; + break; + } + } + + rv = make_monitor_attribute_list(monitors, n_monitors, primary_index, monitor_frames, "Gdk"); + + free_monitors(monitors, n_monitors); + xfree(gmons); + + return rv; +} + + +DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, + 0, 1, 0, + doc: /* Return the number of bitplanes of the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_pgtk_display_info (terminal); + return make_fixnum(32); +} + + +DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, + 0, 1, 0, + doc: /* Returns the number of color cells of the display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + /* We force 24+ bit depths to 24-bit to prevent an overflow. */ + return make_fixnum (1 << min (dpyinfo->n_planes, 24)); +} + +/*********************************************************************** + Tool tips + ***********************************************************************/ + +/* The frame of a currently visible tooltip. */ + +Lisp_Object tip_frame; + +/* If non-nil, a timer started that hides the last tooltip when it + fires. */ + +static Lisp_Object tip_timer; + +/* Compute where to display tip frame F. PARMS is the list of frame + parameters for F. DX and DY are specified offsets from the current + location of the mouse. WIDTH and HEIGHT are the width and height + of the tooltip. Return coordinates relative to the root window of + the display in *ROOT_X, and *ROOT_Y. */ + +static void +compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, int width, int height, int *root_x, int *root_y) +{ + Lisp_Object left, top, right, bottom; + int min_x, min_y, max_x, max_y = -1; + + /* User-specified position? */ + left = Fcdr (Fassq (Qleft, parms)); + top = Fcdr (Fassq (Qtop, parms)); + right = Fcdr (Fassq (Qright, parms)); + bottom = Fcdr (Fassq (Qbottom, parms)); + + /* Move the tooltip window where the mouse pointer is. Resize and + show it. */ + if ((!INTEGERP (left) && !INTEGERP (right)) + || (!INTEGERP (top) && !INTEGERP (bottom))) + { + Lisp_Object frame, attributes, monitor, geometry; + GdkSeat *seat = gdk_display_get_default_seat(FRAME_DISPLAY_INFO(f)->gdpy); + GdkDevice *dev = gdk_seat_get_pointer(seat); + GdkScreen *scr; + + block_input (); + gdk_device_get_position(dev, &scr, root_x, root_y); + unblock_input (); + + XSETFRAME(frame, f); + attributes = Fpgtk_display_monitor_attributes_list (frame); + + /* Try to determine the monitor where the mouse pointer is and + its geometry. See bug#22549. */ + while (CONSP (attributes)) + { + monitor = XCAR (attributes); + geometry = Fassq (Qgeometry, monitor); + if (CONSP (geometry)) + { + min_x = XFIXNUM (Fnth (make_fixnum (1), geometry)); + min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); + max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); + max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); + if (min_x <= *root_x && *root_x < max_x + && min_y <= *root_y && *root_y < max_y) + { + break; + } + max_y = -1; + } + + attributes = XCDR (attributes); + } + } + + /* It was not possible to determine the monitor's geometry, so we + assign some sane defaults here: */ + if ( max_y < 0 ) + { + min_x = 0; + min_y = 0; + max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (f)); + max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)); + } + + if (INTEGERP (top)) + *root_y = XFIXNUM (top); + else if (INTEGERP (bottom)) + *root_y = XFIXNUM (bottom) - height; + else if (*root_y + XFIXNUM (dy) <= min_y) + *root_y = min_y; /* Can happen for negative dy */ + else if (*root_y + XFIXNUM (dy) + height <= max_y) + /* It fits below the pointer */ + *root_y += XFIXNUM (dy); + else if (height + XFIXNUM (dy) + min_y <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XFIXNUM (dy); + else + /* Put it on the top. */ + *root_y = min_y; + + if (INTEGERP (left)) + *root_x = XFIXNUM (left); + else if (INTEGERP (right)) + *root_x = XFIXNUM (right) - width; + else if (*root_x + XFIXNUM (dx) <= min_x) + *root_x = 0; /* Can happen for negative dx */ + else if (*root_x + XFIXNUM (dx) + width <= max_x) + /* It fits to the right of the pointer. */ + *root_x += XFIXNUM (dx); + else if (width + XFIXNUM (dx) + min_x <= *root_x) + /* It fits to the left of the pointer. */ + *root_x -= width + XFIXNUM (dx); + else + /* Put it left justified on the screen -- it ought to fit that way. */ + *root_x = min_x; +} + + +/* Hide tooltip. Delete its frame if DELETE is true. */ +static Lisp_Object +x_hide_tip (bool delete) +{ + if (!NILP (tip_timer)) + { + call1 (Qcancel_timer, tip_timer); + tip_timer = Qnil; + } + + if (NILP (tip_frame) + || (!delete && FRAMEP (tip_frame) + && !FRAME_VISIBLE_P (XFRAME (tip_frame)))) + return Qnil; + else + { + ptrdiff_t count; + Lisp_Object was_open = Qnil; + + count = SPECPDL_INDEX (); + specbind (Qinhibit_redisplay, Qt); + specbind (Qinhibit_quit, Qt); + + { + /* When using system tooltip, tip_frame is the Emacs frame on + which the tip is shown. */ + struct frame *f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (f) && xg_hide_tooltip (f)) + { + tip_frame = Qnil; + was_open = Qt; + } + } + + if (FRAMEP (tip_frame)) + { + if (delete) + { + delete_frame (tip_frame, Qnil); + tip_frame = Qnil; + } + else + x_make_frame_invisible (XFRAME (tip_frame)); + + was_open = Qt; + } + else + tip_frame = Qnil; + + return unbind_to (count, was_open); + } +} + +DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, + doc: /* Show STRING in a "tooltip" window on frame FRAME. +A tooltip window is a small X window displaying a string. + +This is an internal function; Lisp code should call `tooltip-show'. + +FRAME nil or omitted means use the selected frame. + +PARMS is an optional list of frame parameters which can be used to +change the tooltip's appearance. + +Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil +means use the default timeout of 5 seconds. + +If the list of frame parameters PARMS contains a `left' parameter, +display the tooltip at that x-position. If the list of frame parameters +PARMS contains no `left' but a `right' parameter, display the tooltip +right-adjusted at that x-position. Otherwise display it at the +x-position of the mouse, with offset DX added (default is 5 if DX isn't +specified). + +Likewise for the y-position: If a `top' frame parameter is specified, it +determines the position of the upper edge of the tooltip window. If a +`bottom' parameter but no `top' frame parameter is specified, it +determines the position of the lower edge of the tooltip window. +Otherwise display the tooltip window at the y-position of the mouse, +with offset DY added (default is -10). + +A tooltip's maximum size is specified by `x-max-tooltip-size'. +Text larger than the specified size is clipped. */) + (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy) +{ + struct frame *f; + int root_x, root_y; + int width, height; + ptrdiff_t count = SPECPDL_INDEX (); + + specbind (Qinhibit_redisplay, Qt); + + CHECK_STRING (string); + if (SCHARS (string) == 0) + string = make_unibyte_string (" ", 1); + + f = decode_window_system_frame (frame); + if (NILP (timeout)) + timeout = make_fixnum (5); + else + CHECK_FIXNAT (timeout); + + if (NILP (dx)) + dx = make_fixnum (5); + else + CHECK_NUMBER (dx); + + if (NILP (dy)) + dy = make_fixnum (-10); + else + CHECK_NUMBER (dy); + + { + bool ok; + + /* Hide a previous tip, if any. */ + Fx_hide_tip (); + + block_input (); + ok = xg_prepare_tooltip (f, string, &width, &height); + if (ok) + { + compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); + xg_show_tooltip (f, root_x, root_y); + /* This is used in Fx_hide_tip. */ + XSETFRAME (tip_frame, f); + } + unblock_input (); + if (ok) goto start_timer; + } + + start_timer: + /* Let the tip disappear after timeout seconds. */ + tip_timer = call3 (intern ("run-at-time"), timeout, Qnil, + intern ("x-hide-tip")); + + return unbind_to (count, Qnil); +} + + +DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, + doc: /* Hide the current tooltip window, if there is any. +Value is t if tooltip was open, nil otherwise. */) + (void) +{ + return x_hide_tip (!tooltip_reuse_hidden_frame); +} + +/* Return geometric attributes of FRAME. According to the value of + ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner + edges of FRAME, the root window edges of frame (Qroot_edges). Any + other value means to return the geometry as returned by + Fx_frame_geometry. */ +static Lisp_Object +frame_geometry (Lisp_Object frame, Lisp_Object attribute) +{ + struct frame *f = decode_live_frame (frame); + Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen); + bool fullscreen = (EQ (fullscreen_symbol, Qfullboth) + || EQ (fullscreen_symbol, Qfullscreen)); + int border = fullscreen ? 0 : f->border_width; + int title_height = 0; + int native_width = FRAME_PIXEL_WIDTH (f); + int native_height = FRAME_PIXEL_HEIGHT (f); + int outer_width = native_width + 2 * border; + int outer_height = native_height + 2 * border + title_height; + int native_left = f->left_pos + border; + int native_top = f->top_pos + border + title_height; + int native_right = f->left_pos + outer_width - border; + int native_bottom = f->top_pos + outer_height - border; + int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f); + int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f); + int tool_bar_width = (tool_bar_height + ? outer_width - 2 * internal_border_width + : 0); + + /* Construct list. */ + if (EQ (attribute, Qouter_edges)) + return list4 (make_fixnum (f->left_pos), make_fixnum (f->top_pos), + make_fixnum (f->left_pos + outer_width), + make_fixnum (f->top_pos + outer_height)); + else if (EQ (attribute, Qnative_edges)) + return list4 (make_fixnum (native_left), make_fixnum (native_top), + make_fixnum (native_right), make_fixnum (native_bottom)); + else if (EQ (attribute, Qinner_edges)) + return list4 (make_fixnum (native_left + internal_border_width), + make_fixnum (native_top + + tool_bar_height + + internal_border_width), + make_fixnum (native_right - internal_border_width), + make_fixnum (native_bottom - internal_border_width)); + else + return + listn (CONSTYPE_HEAP, 10, + Fcons (Qouter_position, + Fcons (make_fixnum (f->left_pos), + make_fixnum (f->top_pos))), + Fcons (Qouter_size, + Fcons (make_fixnum (outer_width), + make_fixnum (outer_height))), + Fcons (Qexternal_border_size, + (fullscreen + ? Fcons (make_fixnum (0), make_fixnum (0)) + : Fcons (make_fixnum (border), make_fixnum (border)))), + Fcons (Qtitle_bar_size, + Fcons (make_fixnum (0), make_fixnum (title_height))), + Fcons (Qmenu_bar_external, Qnil), + Fcons (Qmenu_bar_size, Fcons (make_fixnum (0), make_fixnum (0))), + Fcons (Qtool_bar_external, + FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil), + Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)), + Fcons (Qtool_bar_size, + Fcons (make_fixnum (tool_bar_width), + make_fixnum (tool_bar_height))), + Fcons (Qinternal_border_width, + make_fixnum (internal_border_width))); +} + +DEFUN ("pgtk-frame-geometry", Fpgtk_frame_geometry, Spgtk_frame_geometry, 0, 1, 0, + doc: /* Return geometric attributes of FRAME. +FRAME must be a live frame and defaults to the selected one. The return +value is an association list of the attributes listed below. All height +and width values are in pixels. + +`outer-position' is a cons of the outer left and top edges of FRAME + relative to the origin - the position (0, 0) - of FRAME's display. + +`outer-size' is a cons of the outer width and height of FRAME. The + outer size includes the title bar and the external borders as well as + any menu and/or tool bar of frame. + +`external-border-size' is a cons of the horizontal and vertical width of + FRAME's external borders as supplied by the window manager. + +`title-bar-size' is a cons of the width and height of the title bar of + FRAME as supplied by the window manager. If both of them are zero, + FRAME has no title bar. If only the width is zero, Emacs was not + able to retrieve the width information. + +`menu-bar-external', if non-nil, means the menu bar is external (never + included in the inner edges of FRAME). + +`menu-bar-size' is a cons of the width and height of the menu bar of + FRAME. + +`tool-bar-external', if non-nil, means the tool bar is external (never + included in the inner edges of FRAME). + +`tool-bar-position' tells on which side the tool bar on FRAME is and can + be one of `left', `top', `right' or `bottom'. If this is nil, FRAME + has no tool bar. + +`tool-bar-size' is a cons of the width and height of the tool bar of + FRAME. + +`internal-border-width' is the width of the internal border of + FRAME. */) + (Lisp_Object frame) +{ + return frame_geometry (frame, Qnil); +} + +DEFUN ("pgtk-frame-edges", Fpgtk_frame_edges, Spgtk_frame_edges, 0, 2, 0, + doc: /* Return edge coordinates of FRAME. +FRAME must be a live frame and defaults to the selected one. The return +value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are +in pixels relative to the origin - the position (0, 0) - of FRAME's +display. + +If optional argument TYPE is the symbol `outer-edges', return the outer +edges of FRAME. The outer edges comprise the decorations of the window +manager (like the title bar or external borders) as well as any external +menu or tool bar of FRAME. If optional argument TYPE is the symbol +`native-edges' or nil, return the native edges of FRAME. The native +edges exclude the decorations of the window manager and any external +menu or tool bar of FRAME. If TYPE is the symbol `inner-edges', return +the inner edges of FRAME. These edges exclude title bar, any borders, +menu bar or tool bar of FRAME. */) + (Lisp_Object frame, Lisp_Object type) +{ + return frame_geometry (frame, ((EQ (type, Qouter_edges) + || EQ (type, Qinner_edges)) + ? type + : Qnative_edges)); +} + +DEFUN ("pgtk-set-mouse-absolute-pixel-position", + Fpgtk_set_mouse_absolute_pixel_position, + Spgtk_set_mouse_absolute_pixel_position, 2, 2, 0, + doc: /* Move mouse pointer to absolute pixel position (X, Y). +The coordinates X and Y are interpreted in pixels relative to a position +\(0, 0) of the selected frame's display. */) + (Lisp_Object x, Lisp_Object y) +{ + struct frame *f = SELECTED_FRAME (); + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); + GdkWindow *window = gtk_widget_get_window(widget); + GdkDisplay *gdpy = gdk_window_get_display(window); + GdkScreen *gscr = gdk_window_get_screen(window); + GdkSeat *seat = gdk_display_get_default_seat(gdpy); + GdkDevice *device = gdk_seat_get_pointer(seat); + + PGTK_TRACE("pgtk-set-mouse-absolute-pixel-position:"); + gdk_device_warp(device, gscr, XFIXNUM(x), XFIXNUM(y)); /* No effect on wayland. */ + + return Qnil; +} + +DEFUN ("pgtk-mouse-absolute-pixel-position", + Fpgtk_mouse_absolute_pixel_position, + Spgtk_mouse_absolute_pixel_position, 0, 0, 0, + doc: /* Return absolute position of mouse cursor in pixels. +The position is returned as a cons cell (X . Y) of the +coordinates of the mouse cursor position in pixels relative to a +position (0, 0) of the selected frame's terminal. */) + (void) +{ + struct frame *f = SELECTED_FRAME (); + GtkWidget *widget = FRAME_GTK_OUTER_WIDGET(f); + GdkWindow *window = gtk_widget_get_window(widget); + GdkDisplay *gdpy = gdk_window_get_display(window); + GdkScreen *gscr; + GdkSeat *seat = gdk_display_get_default_seat(gdpy); + GdkDevice *device = gdk_seat_get_pointer(seat); + int x = 0, y = 0; + + gdk_device_get_position(device, &gscr, &x, &y); /* can't get on wayland? */ + + return Fcons(make_fixnum(x), make_fixnum(y)); +} + + +DEFUN ("pgtk-page-setup-dialog", Fpgtk_page_setup_dialog, Spgtk_page_setup_dialog, 0, 0, 0, + doc: /* Pop up a page setup dialog. +The current page setup can be obtained using `x-get-page-setup'. */) + (void) +{ + block_input (); + xg_page_setup_dialog (); + unblock_input (); + + return Qnil; +} + +DEFUN ("pgtk-get-page-setup", Fpgtk_get_page_setup, Spgtk_get_page_setup, 0, 0, 0, + doc: /* Return the value of the current page setup. +The return value is an alist containing the following keys: + + orientation: page orientation (symbol `portrait', `landscape', + `reverse-portrait', or `reverse-landscape'). + width, height: page width/height in points not including margins. + left-margin, right-margin, top-margin, bottom-margin: print margins, + which is the parts of the page that the printer cannot print + on, in points. + +The paper width can be obtained as the sum of width, left-margin, and +right-margin values if the page orientation is `portrait' or +`reverse-portrait'. Otherwise, it is the sum of width, top-margin, +and bottom-margin values. Likewise, the paper height is the sum of +height, top-margin, and bottom-margin values if the page orientation +is `portrait' or `reverse-portrait'. Otherwise, it is the sum of +height, left-margin, and right-margin values. */) + (void) +{ + Lisp_Object result; + + block_input (); + result = xg_get_page_setup (); + unblock_input (); + + return result; +} + +DEFUN ("pgtk-print-frames-dialog", Fpgtk_print_frames_dialog, Spgtk_print_frames_dialog, 0, 1, "", + doc: /* Pop up a print dialog to print the current contents of FRAMES. +FRAMES should be nil (the selected frame), a frame, or a list of +frames (each of which corresponds to one page). Each frame should be +visible. */) + (Lisp_Object frames) +{ + Lisp_Object rest, tmp; + int count; + + if (!CONSP (frames)) + frames = list1 (frames); + + tmp = Qnil; + for (rest = frames; CONSP (rest); rest = XCDR (rest)) + { + struct frame *f = decode_window_system_frame (XCAR (rest)); + Lisp_Object frame; + + XSETFRAME (frame, f); + if (!FRAME_VISIBLE_P (f)) + error ("Frames to be printed must be visible."); + tmp = Fcons (frame, tmp); + } + frames = Fnreverse (tmp); + + /* Make sure the current matrices are up-to-date. */ + count = SPECPDL_INDEX (); + specbind (Qredisplay_dont_pause, Qt); + redisplay_preserve_echo_area (32); + unbind_to (count, Qnil); + + block_input (); + xg_print_frames_dialog (frames); + unblock_input (); + + return Qnil; +} + +DEFUN ("pgtk-backend-display-class", Fpgtk_backend_display_class, Spgtk_backend_display_class, + 0, 1, "", + doc: /* Returns the name of the Gdk backend display class of the TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + struct pgtk_display_info *dpyinfo = check_pgtk_display_info (terminal); + GdkDisplay *gdpy = dpyinfo->gdpy; + const gchar *type_name = G_OBJECT_TYPE_NAME(G_OBJECT(gdpy)); + return build_string(type_name); +} + +/* ========================================================================== + + Lisp interface declaration + + ========================================================================== */ + +void +syms_of_pgtkfns (void) +{ + DEFSYM (Qfont_parameter, "font-parameter"); + DEFSYM (Qfontsize, "fontsize"); + DEFSYM (Qcancel_timer, "cancel-timer"); + DEFSYM (Qframe_title_format, "frame-title-format"); + DEFSYM (Qicon_title_format, "icon-title-format"); + DEFSYM (Qdark, "dark"); + + DEFVAR_LISP ("pgtk-icon-type-alist", Vpgtk_icon_type_alist, + doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames. +If the title of a frame matches REGEXP, then IMAGE.tiff is +selected as the image of the icon representing the frame when it's +miniaturized. If an element is t, then Emacs tries to select an icon +based on the filetype of the visited file. + +The images have to be installed in a folder called English.lproj in the +Emacs folder. You have to restart Emacs after installing new icons. + +Example: Install an icon Gnus.tiff and execute the following code + + (setq pgtk-icon-type-alist + (append pgtk-icon-type-alist + \\='((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\" + . \"Gnus\")))) + +When you miniaturize a Group, Summary or Article frame, Gnus.tiff will +be used as the image of the icon representing the frame. */); + Vpgtk_icon_type_alist = list1 (Qt); + + + /* Provide x-toolkit also for GTK. Internally GTK does not use Xt so it + is not an X toolkit in that sense (USE_X_TOOLKIT is not defined). + But for a user it is a toolkit for X, and indeed, configure + accepts --with-x-toolkit=gtk. */ + Fprovide (intern_c_string ("x-toolkit"), Qnil); + Fprovide (intern_c_string ("gtk"), Qnil); + Fprovide (intern_c_string ("move-toolbar"), Qnil); + + DEFVAR_LISP ("gtk-version-string", Vgtk_version_string, + doc: /* Version info for GTK+. */); + { + char *ver = g_strdup_printf("%d.%d.%d", + GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); + int len = strlen(ver); + Vgtk_version_string = make_pure_string (ver, len, len, false); + g_free(ver); + } + + + Fprovide (intern_c_string ("cairo"), Qnil); + + DEFVAR_LISP ("cairo-version-string", Vcairo_version_string, + doc: /* Version info for cairo. */); + { + char *ver = g_strdup_printf("%d.%d.%d", + CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR, + CAIRO_VERSION_MICRO); + int len = strlen(ver); + Vcairo_version_string = make_pure_string (ver, len, len, false); + g_free(ver); + } + + + defsubr (&Spgtk_set_resource); + defsubr (&Sxw_display_color_p); /* this and next called directly by C code */ + defsubr (&Sx_display_grayscale_p); + defsubr (&Spgtk_font_name); + defsubr (&Sxw_color_defined_p); + defsubr (&Sxw_color_values); + defsubr (&Sx_server_max_request_size); + defsubr (&Sx_server_vendor); + defsubr (&Sx_server_version); + defsubr (&Sx_display_pixel_width); + defsubr (&Sx_display_pixel_height); + defsubr (&Spgtk_display_monitor_attributes_list); + defsubr (&Spgtk_frame_geometry); + defsubr (&Spgtk_frame_edges); + defsubr (&Spgtk_frame_list_z_order); + defsubr (&Spgtk_frame_restack); + defsubr (&Spgtk_set_mouse_absolute_pixel_position); + defsubr (&Spgtk_mouse_absolute_pixel_position); + defsubr (&Sx_display_mm_width); + defsubr (&Sx_display_mm_height); + defsubr (&Sx_display_screens); + defsubr (&Sx_display_planes); + defsubr (&Sx_display_color_cells); + defsubr (&Sx_display_visual_class); + defsubr (&Sx_display_backing_store); + defsubr (&Sx_display_save_under); + defsubr (&Sx_create_frame); + defsubr (&Sx_open_connection); + defsubr (&Sx_close_connection); + defsubr (&Sx_display_list); + + defsubr (&Spgtk_hide_others); + defsubr (&Spgtk_hide_emacs); + + defsubr (&Sx_show_tip); + defsubr (&Sx_hide_tip); + + // defsubr (&Spgtk_export_frames); + defsubr (&Spgtk_page_setup_dialog); + defsubr (&Spgtk_get_page_setup); + defsubr (&Spgtk_print_frames_dialog); + defsubr (&Spgtk_backend_display_class); + + as_status = 0; + as_script = Qnil; + as_result = 0; + + tip_frame = Qnil; + staticpro(&tip_frame); + tip_timer = Qnil; + staticpro(&tip_timer); + +/* This is not ifdef:ed, so other builds than GTK can customize it. */ + DEFVAR_BOOL ("x-gtk-use-old-file-dialog", x_gtk_use_old_file_dialog, + doc: /* Non-nil means prompt with the old GTK file selection dialog. +If nil or if the file selection dialog is not available, the new GTK file +chooser is used instead. To turn off all file dialogs set the +variable `use-file-dialog'. */); + x_gtk_use_old_file_dialog = false; + + DEFVAR_BOOL ("x-gtk-show-hidden-files", x_gtk_show_hidden_files, + doc: /* If non-nil, the GTK file chooser will by default show hidden files. +Note that this is just the default, there is a toggle button on the file +chooser to show or not show hidden files on a case by case basis. */); + x_gtk_show_hidden_files = false; + + DEFVAR_BOOL ("x-gtk-file-dialog-help-text", x_gtk_file_dialog_help_text, + doc: /* If non-nil, the GTK file chooser will show additional help text. +If more space for files in the file chooser dialog is wanted, set this to nil +to turn the additional text off. */); + x_gtk_file_dialog_help_text = true; + + DEFVAR_BOOL ("x-gtk-use-system-tooltips", x_gtk_use_system_tooltips, + doc: /* If non-nil with a Gtk+ built Emacs, the Gtk+ tooltip is used. +Otherwise use Emacs own tooltip implementation. +When using Gtk+ tooltips, the tooltip face is not used. */); + x_gtk_use_system_tooltips = true; + + + DEFSYM (Qmono, "mono"); + + DEFSYM (Qpdf, "pdf"); + + DEFSYM (Qorientation, "orientation"); + DEFSYM (Qtop_margin, "top-margin"); + DEFSYM (Qbottom_margin, "bottom-margin"); + DEFSYM (Qportrait, "portrait"); + DEFSYM (Qlandscape, "landscape"); + DEFSYM (Qreverse_portrait, "reverse-portrait"); + DEFSYM (Qreverse_landscape, "reverse-landscape"); +} + +#ifdef PGTK_DEBUG + +#include +#include +void pgtk_log(const char *file, int lineno, const char *fmt, ...) +{ + struct timespec ts; + struct tm tm; + char timestr[32]; + va_list ap; + + clock_gettime(CLOCK_REALTIME, &ts); + + localtime_r(&ts.tv_sec, &tm); + strftime(timestr, sizeof timestr, "%H:%M:%S", &tm); + + fprintf(stderr, "%s.%06ld %.10s:%04d ", timestr, ts.tv_nsec / 1000, file, lineno); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); +} + +void pgtk_backtrace(const char *file, int lineno) +{ + Lisp_Object bt = make_uninit_vector(10); + for (int i = 0; i < 10; i++) + ASET(bt, i, Qnil); + + struct timespec ts; + struct tm tm; + char timestr[32]; + + clock_gettime(CLOCK_REALTIME, &ts); + + localtime_r(&ts.tv_sec, &tm); + strftime(timestr, sizeof timestr, "%H:%M:%S", &tm); + + fprintf(stderr, "%s.%06ld %.10s:%04d ********\n", timestr, ts.tv_nsec / 1000, file, lineno); + + get_backtrace(bt); + for (int i = 0; i < 10; i++) { + Lisp_Object stk = AREF(bt, i); + if (!NILP(stk)) { + Lisp_Object args[2] = { build_string("%S"), stk }; + Lisp_Object str = Fformat(2, args); + fprintf(stderr, "%s %.10s:%04d %s\n", timestr, file, lineno, SSDATA(str)); + } + } + + fprintf(stderr, "%s %.10s:%04d ********\n", timestr, file, lineno); +} + +#endif + +#endif diff --git a/src/pgtkgui.h b/src/pgtkgui.h new file mode 100644 index 0000000000..78e1da77d8 --- /dev/null +++ b/src/pgtkgui.h @@ -0,0 +1,136 @@ +/* Definitions and headers for communication on the pure Gtk+3. + Copyright (C) 1995, 2005, 2008-2017 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +#ifndef __PGTKGUI_H__ +#define __PGTKGUI_H__ + +/* Emulate XCharStruct. */ +typedef struct _XCharStruct +{ + int rbearing; + int lbearing; + int width; + int ascent; + int descent; +} XCharStruct; + +/* Fake structure from Xlib.h to represent two-byte characters. */ +typedef unsigned short unichar; +typedef unichar XChar2b; + +#define STORE_XCHAR2B(chp, b1, b2) \ + (*(chp) = ((XChar2b)((((b1) & 0x00ff) << 8) | ((b2) & 0x00ff)))) + +#define XCHAR2B_BYTE1(chp) \ + ((*(chp) & 0xff00) >> 8) + +#define XCHAR2B_BYTE2(chp) \ + (*(chp) & 0x00ff) + + +/* XXX: xfaces requires these structures, but the question is are we + forced to use them? */ +typedef struct _XGCValues +{ + unsigned long foreground; + unsigned long background; + void *font; +} XGCValues; + +typedef XGCValues * GC; + +#define GCForeground 0x01 +#define GCBackground 0x02 +#define GCFont 0x03 + +typedef void *Pixmap; + +typedef void *Cursor; + +#define No_Cursor (0) + +typedef void * Color; +typedef int Window; +typedef struct _GdkDisplay Display; + +/* Xism */ +typedef Lisp_Object XrmDatabase; + + +/* some sort of attempt to normalize rectangle handling.. seems a bit much + for what is accomplished */ +typedef struct { + int x, y; + unsigned width, height; +} XRectangle; + +#define NativeRectangle XRectangle + +#define CONVERT_TO_EMACS_RECT(xr, nr) \ + ((xr).x = (nr).origin.x, \ + (xr).y = (nr).origin.y, \ + (xr).width = (nr).size.width, \ + (xr).height = (nr).size.height) + +#define CONVERT_FROM_EMACS_RECT(xr, nr) \ + ((nr).x = (xr).x, \ + (nr).y = (xr).y, \ + (nr).width = (xr).width, \ + (nr).height = (xr).height) + +#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \ + ((nr).x = (px), \ + (nr).y = (py), \ + (nr).width = (pwidth), \ + (nr).height = (pheight)) + +/* This stuff needed by frame.c. */ +#define ForgetGravity 0 +#define NorthWestGravity 1 +#define NorthGravity 2 +#define NorthEastGravity 3 +#define WestGravity 4 +#define CenterGravity 5 +#define EastGravity 6 +#define SouthWestGravity 7 +#define SouthGravity 8 +#define SouthEastGravity 9 +#define StaticGravity 10 + +#define NoValue 0x0000 +#define XValue 0x0001 +#define YValue 0x0002 +#define WidthValue 0x0004 +#define HeightValue 0x0008 +#define AllValues 0x000F +#define XNegative 0x0010 +#define YNegative 0x0020 + +#define USPosition (1L << 0) /* user specified x, y */ +#define USSize (1L << 1) /* user specified width, height */ + +#define PPosition (1L << 2) /* program specified position */ +#define PSize (1L << 3) /* program specified size */ +#define PMinSize (1L << 4) /* program specified minimum size */ +#define PMaxSize (1L << 5) /* program specified maximum size */ +#define PResizeInc (1L << 6) /* program specified resize increments */ +#define PAspect (1L << 7) /* program specified min, max aspect ratios */ +#define PBaseSize (1L << 8) /* program specified base for incrementing */ +#define PWinGravity (1L << 9) /* program specified window gravity */ + +#endif /* __PGTKGUI_H__ */ diff --git a/src/pgtkselect.c b/src/pgtkselect.c new file mode 100644 index 0000000000..b885425680 --- /dev/null +++ b/src/pgtkselect.c @@ -0,0 +1,466 @@ +/* Gtk selection processing for emacs. + Copyright (C) 1993-1994, 2005-2006, 2008-2017 Free Software + Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +/* +Originally by Carl Edman +Updated by Christian Limpach (chris@nice.ch) +OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) +macOS/Aqua port by Christophe de Dinechin (descubes@earthlink.net) +GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) +*/ + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#include "lisp.h" +#include "pgtkterm.h" +#include "termhooks.h" +#include "keyboard.h" +#include "pgtkselect.h" +#include + +#if 0 +static Lisp_Object Vselection_alist; +#endif + +static GQuark quark_primary_data = 0; +static GQuark quark_primary_size = 0; +static GQuark quark_secondary_data = 0; +static GQuark quark_secondary_size = 0; +static GQuark quark_clipboard_data = 0; +static GQuark quark_clipboard_size = 0; + +/* ========================================================================== + + Internal utility functions + + ========================================================================== */ + +/* From a Lisp_Object, return a suitable frame for selection + operations. OBJECT may be a frame, a terminal object, or nil + (which stands for the selected frame--or, if that is not an pgtk + frame, the first pgtk display on the list). If no suitable frame can + be found, return NULL. */ + +static struct frame * +frame_for_pgtk_selection (Lisp_Object object) +{ + Lisp_Object tail, frame; + struct frame *f; + + if (NILP (object)) + { + f = XFRAME (selected_frame); + if (FRAME_PGTK_P (f) && FRAME_LIVE_P (f)) + return f; + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + if (FRAME_PGTK_P (f) && FRAME_LIVE_P (f)) + return f; + } + } + else if (TERMINALP (object)) + { + struct terminal *t = decode_live_terminal (object); + + if (t->type == output_pgtk) + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + if (FRAME_LIVE_P (f) && f->terminal == t) + return f; + } + } + else if (FRAMEP (object)) + { + f = XFRAME (object); + if (FRAME_PGTK_P (f) && FRAME_LIVE_P (f)) + return f; + } + + return NULL; +} + +static GtkClipboard *symbol_to_gtk_clipboard(GtkWidget *widget, Lisp_Object symbol) +{ + GdkAtom atom; + + CHECK_SYMBOL (symbol); + if (NILP(symbol)) { + atom = GDK_SELECTION_PRIMARY; + } else if (EQ(symbol, QCLIPBOARD)) { + atom = GDK_SELECTION_CLIPBOARD; + } else if (EQ(symbol, QPRIMARY)) { + atom = GDK_SELECTION_PRIMARY; + } else if (EQ(symbol, QSECONDARY)) { + atom = GDK_SELECTION_SECONDARY; + } else if (EQ(symbol, Qt)) { + atom = GDK_SELECTION_SECONDARY; + } else { + atom = 0; + error ("Bad selection"); + } + + return gtk_widget_get_clipboard(widget, atom); +} + +static void selection_type_to_quarks(GdkAtom type, GQuark *quark_data, GQuark *quark_size) +{ + if (type == GDK_SELECTION_PRIMARY) { + *quark_data = quark_primary_data; + *quark_size = quark_primary_size; + } else if (type == GDK_SELECTION_SECONDARY) { + *quark_data = quark_secondary_data; + *quark_size = quark_secondary_size; + } else if (type == GDK_SELECTION_CLIPBOARD) { + *quark_data = quark_clipboard_data; + *quark_size = quark_clipboard_size; + } else { + /* fixme: Is it safe to use 'error' here? */ + error("Unknown selection type."); + } +} + +static void +get_func(GtkClipboard *cb, GtkSelectionData *data, guint info, gpointer user_data_or_owner) +{ + PGTK_TRACE("get_func:"); + GObject *obj = G_OBJECT(user_data_or_owner); + const char *str; + int size; + GQuark quark_data, quark_size; + + selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + + str = g_object_get_qdata(obj, quark_data); + size = GPOINTER_TO_SIZE(g_object_get_qdata(obj, quark_size)); + PGTK_TRACE("get_func: str: %s", str); + gtk_selection_data_set_text(data, str, size); +} + +static void +clear_func(GtkClipboard *cb, gpointer user_data_or_owner) +{ + PGTK_TRACE("clear_func:"); + GObject *obj = G_OBJECT(user_data_or_owner); + GQuark quark_data, quark_size; + + selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + + g_object_set_qdata(obj, quark_data, NULL); + g_object_set_qdata(obj, quark_size, 0); +} + + +/* ========================================================================== + + Functions used externally + + ========================================================================== */ + +void pgtk_selection_init(void) +{ + if (quark_primary_data == 0) { + quark_primary_data = g_quark_from_static_string("pgtk-primary-data"); + quark_primary_size = g_quark_from_static_string("pgtk-primary-size"); + quark_secondary_data = g_quark_from_static_string("pgtk-secondary-data"); + quark_secondary_size = g_quark_from_static_string("pgtk-secondary-size"); + quark_clipboard_data = g_quark_from_static_string("pgtk-clipboard-data"); + quark_clipboard_size = g_quark_from_static_string("pgtk-clipboard-size"); + } +} + +void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer user_data) +{ + GQuark quark_data, quark_size; + PGTK_TRACE("pgtk_selection_lost:"); + + selection_type_to_quarks(event->selection, &quark_data, &quark_size); + + g_object_set_qdata(G_OBJECT(widget), quark_data, NULL); + g_object_set_qdata(G_OBJECT(widget), quark_size, 0); +} + +/* ========================================================================== + + Lisp Defuns + + ========================================================================== */ + + +DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, + Spgtk_own_selection_internal, 2, 3, 0, + doc: /* Assert an X selection of type SELECTION and value VALUE. +SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what X expects.) +VALUE is typically a string, or a cons of two markers, but may be +anything that the functions on `selection-converter-alist' know about. + +FRAME should be a frame that should own the selection. If omitted or +nil, it defaults to the selected frame.*/) + (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) +{ + PGTK_TRACE("pgtk-own-selection-internal."); + Lisp_Object successful_p = Qnil; + Lisp_Object target_symbol, rest; + GtkClipboard *cb; + struct frame *f; + GQuark quark_data, quark_size; + + check_window_system (NULL); + + if (NILP (frame)) frame = selected_frame; + if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) + error ("pgtk selection unavailable for this frame"); + f = XFRAME(frame); + + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + + /* We only support copy of text. */ + target_symbol = QTEXT; + if (STRINGP (value)) + { + GtkTargetList *list; + GtkTargetEntry *targets; + gint n_targets; + GtkWidget *widget; + + list = gtk_target_list_new (NULL, 0); + gtk_target_list_add_text_targets (list, 0); + + targets = gtk_target_table_new_from_list (list, &n_targets); + + int size = SBYTES(value); + gchar *str = xmalloc(size + 1); + memcpy(str, SSDATA(value), size); + str[size] = '\0'; + + widget = FRAME_GTK_WIDGET(f); + g_object_set_qdata_full(G_OBJECT(widget), quark_data, str, xfree); + g_object_set_qdata_full(G_OBJECT(widget), quark_size, GSIZE_TO_POINTER(size), NULL); + + PGTK_TRACE("set_with_owner: owner=%p", FRAME_GTK_WIDGET(f)); + if (gtk_clipboard_set_with_owner (cb, + targets, n_targets, + get_func, clear_func, + G_OBJECT(FRAME_GTK_WIDGET(f)))) { + PGTK_TRACE("set_with_owner succeeded.."); + successful_p = Qt; + } else { + PGTK_TRACE("set_with_owner failed."); + } + gtk_clipboard_set_can_store (cb, NULL, 0); + + gtk_target_table_free (targets, n_targets); + gtk_target_list_unref (list); + } + + if (!EQ (Vpgtk_sent_selection_hooks, Qunbound)) + { + /* FIXME: Use run-hook-with-args! */ + for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); rest = Fcdr (rest)) + call3 (Fcar (rest), selection, target_symbol, successful_p); + } + + return value; +} + + +DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, + Spgtk_disown_selection_internal, 1, 3, 0, + doc: /* If we own the selection SELECTION, disown it. +Disowning it means there is no such selection. + +Sets the last-change time for the selection to TIME-OBJECT (by default +the time of the last event). + +TERMINAL should be a terminal object or a frame specifying the X +server to query. If omitted or nil, that stands for the selected +frame's display, or the first available X display. + +On Nextstep, the TIME-OBJECT and TERMINAL arguments are unused. +On MS-DOS, all this does is return non-nil if we own the selection. +On PGTK, the TIME-OBJECT is unused. */) + (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) +{ + PGTK_TRACE("pgtk-disown-selection-internal."); + + struct frame *f = frame_for_pgtk_selection (terminal); + GtkClipboard *cb; + + if (!f) + return Qnil; + + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + + gtk_clipboard_clear(cb); + + return Qt; +} + + +DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, + 0, 2, 0, doc: /* Whether there is an owner for the given X selection. +SELECTION should be the name of the selection in question, typically +one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects +these literal upper-case names.) The symbol nil is the same as +`PRIMARY', and t is the same as `SECONDARY'. + +TERMINAL should be a terminal object or a frame specifying the X +server to query. If omitted or nil, that stands for the selected +frame's display, or the first available X display. + +On Nextstep, TERMINAL is unused. */) + (Lisp_Object selection, Lisp_Object terminal) +{ + PGTK_TRACE("pgtk-selection-exists-p."); + struct frame *f = frame_for_pgtk_selection (terminal); + GtkClipboard *cb; + + if (!f) + return Qnil; + + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + + return gtk_clipboard_wait_is_text_available(cb) ? Qt : Qnil; +} + + +DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, + 0, 2, 0, + doc: /* Whether the current Emacs process owns the given X Selection. +The arg should be the name of the selection in question, typically one of +the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what X expects.) +For convenience, the symbol nil is the same as `PRIMARY', +and t is the same as `SECONDARY'. + +TERMINAL should be a terminal object or a frame specifying the X +server to query. If omitted or nil, that stands for the selected +frame's display, or the first available X display. + +On Nextstep, TERMINAL is unused. */) + (Lisp_Object selection, Lisp_Object terminal) +{ + PGTK_TRACE("pgtk-selection-owner-p."); + struct frame *f = frame_for_pgtk_selection (terminal); + GtkClipboard *cb; + GObject *obj; + GQuark quark_data, quark_size; + + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection); + selection_type_to_quarks(gtk_clipboard_get_selection(cb), &quark_data, &quark_size); + + obj = gtk_clipboard_get_owner(cb); + + return g_object_get_qdata(obj, quark_data) != NULL ? Qt : Qnil; +} + + +DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, + Spgtk_get_selection_internal, 2, 4, 0, + doc: /* Return text selected from some X window. +SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what X expects.) +TARGET-TYPE is the type of data desired, typically `STRING'. + +TIME-STAMP is the time to use in the XConvertSelection call for foreign +selections. If omitted, defaults to the time for the last event. + +TERMINAL should be a terminal object or a frame specifying the X +server to query. If omitted or nil, that stands for the selected +frame's display, or the first available X display. + +On Nextstep, TIME-STAMP and TERMINAL are unused. +On PGTK, TIME-STAMP is unused. */) + (Lisp_Object selection_symbol, Lisp_Object target_type, + Lisp_Object time_stamp, Lisp_Object terminal) +{ + struct frame *f = frame_for_pgtk_selection (terminal); + GtkClipboard *cb; + + CHECK_SYMBOL (selection_symbol); + CHECK_SYMBOL (target_type); + if (EQ (target_type, QMULTIPLE)) + error ("Retrieving MULTIPLE selections is currently unimplemented"); + if (!f) + error ("PGTK selection unavailable for this frame"); + + cb = symbol_to_gtk_clipboard(FRAME_GTK_WIDGET(f), selection_symbol); + + gchar *s = gtk_clipboard_wait_for_text(cb); + if (s == NULL) + return Qnil; + int size = strlen(s); + Lisp_Object str = make_unibyte_string (s, size); + Fput_text_property (make_fixnum (0), make_fixnum (size), + Qforeign_selection, QUTF8_STRING, str); + return str; +} + + +void +nxatoms_of_pgtkselect (void) +{ + PGTK_TRACE("nxatoms_of_pgtkselect"); +} + +void +syms_of_pgtkselect (void) +{ + PGTK_TRACE("syms_of_pgtkselect"); + + DEFSYM (QCLIPBOARD, "CLIPBOARD"); + DEFSYM (QSECONDARY, "SECONDARY"); + DEFSYM (QTEXT, "TEXT"); + DEFSYM (QFILE_NAME, "FILE_NAME"); + DEFSYM (QMULTIPLE, "MULTIPLE"); + + DEFSYM (Qforeign_selection, "foreign-selection"); + DEFSYM (QUTF8_STRING, "UTF8_STRING"); + + defsubr (&Spgtk_disown_selection_internal); + defsubr (&Spgtk_get_selection_internal); + defsubr (&Spgtk_own_selection_internal); + defsubr (&Spgtk_selection_exists_p); + defsubr (&Spgtk_selection_owner_p); + +#if 0 + Vselection_alist = Qnil; + staticpro (&Vselection_alist); +#endif + + DEFVAR_LISP ("pgtk-sent-selection-hooks", Vpgtk_sent_selection_hooks, + "A list of functions to be called when Emacs answers a selection request.\n\ +The functions are called with four arguments:\n\ + - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\ + - the selection-type which Emacs was asked to convert the\n\ + selection into before sending (for example, `STRING' or `LENGTH');\n\ + - a flag indicating success or failure for responding to the request.\n\ +We might have failed (and declined the request) for any number of reasons,\n\ +including being asked for a selection that we no longer own, or being asked\n\ +to convert into a type that we don't know about or that is inappropriate.\n\ +This hook doesn't let you change the behavior of Emacs's selection replies,\n\ +it merely informs you that they have happened."); + Vpgtk_sent_selection_hooks = Qnil; +} diff --git a/src/pgtkselect.h b/src/pgtkselect.h new file mode 100644 index 0000000000..a67b2218e4 --- /dev/null +++ b/src/pgtkselect.h @@ -0,0 +1,31 @@ +/* Definitions and headers for selection of pure Gtk+3. + Copyright (C) 1989, 1993, 2005, 2008-2017 Free Software Foundation, + Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + + +#include "dispextern.h" +#include "frame.h" + +#ifdef HAVE_PGTK + +#include + +extern void pgtk_selection_init(void); +void pgtk_selection_lost(GtkWidget *widget, GdkEventSelection *event, gpointer user_data); + +#endif /* HAVE_PGTK */ diff --git a/src/pgtkterm.c b/src/pgtkterm.c new file mode 100644 index 0000000000..61da7d6650 --- /dev/null +++ b/src/pgtkterm.c @@ -0,0 +1,6395 @@ +/* Pure Gtk+-3 communication module. -*- coding: utf-8 -*- + +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2017 Free Software +Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lisp.h" +#include "blockinput.h" +#include "sysselect.h" +#include "gtkutil.h" +#include "systime.h" +#include "character.h" +#include "xwidget.h" +#include "fontset.h" +#include "composite.h" +#include "ccl.h" +#include "dynlib.h" + +#include "termhooks.h" +#include "termopts.h" +#include "termchar.h" +#include "menu.h" +#include "window.h" +#include "keyboard.h" +#include "atimer.h" +#include "buffer.h" +#include "font.h" +#include "xsettings.h" +#include "pgtkselect.h" + +#define STORE_KEYSYM_FOR_DEBUG(keysym) ((void)0) + +#define FRAME_CR_CONTEXT(f) ((f)->output_data.pgtk->cr_context) +#define FRAME_CR_SURFACE(f) ((f)->output_data.pgtk->cr_surface) + +struct pgtk_display_info *x_display_list; /* Chain of existing displays */ +extern Lisp_Object tip_frame; + +static struct event_queue_t { + union buffered_input_event *q; + int nr, cap; +} event_q = { + NULL, 0, 0, +}; + +/* Non-zero timeout value means ignore next mouse click if it arrives + before that timeout elapses (i.e. as part of the same sequence of + events resulting from clicking on a frame to select it). */ + +static Time ignore_next_mouse_click_timeout; + +static void pgtk_delete_display (struct pgtk_display_info *dpyinfo); +static void pgtk_clear_frame_area(struct frame *f, int x, int y, int width, int height); +static void pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int width, int height); +static void pgtk_clip_to_row (struct window *w, struct glyph_row *row, + enum glyph_row_area area, cairo_t *cr); +static struct frame * +pgtk_any_window_to_frame (GdkWindow *window); + + +static void evq_enqueue(union buffered_input_event *ev) +{ + struct event_queue_t *evq = &event_q; + if (evq->cap == 0) { + evq->cap = 4; + evq->q = xmalloc(sizeof *evq->q * evq->cap); + } + + if (evq->nr >= evq->cap) { + evq->cap += evq->cap / 2; + evq->q = xrealloc(evq->q, sizeof *evq->q * evq->cap); + } + + evq->q[evq->nr++] = *ev; + raise(SIGIO); +} + +static int evq_flush(struct input_event *hold_quit) +{ + struct event_queue_t *evq = &event_q; + int i, n = evq->nr; + for (i = 0; i < n; i++) + kbd_buffer_store_buffered_event (&evq->q[i], hold_quit); + evq->nr = 0; + return n; +} + +void +mark_pgtkterm(void) +{ + struct event_queue_t *evq = &event_q; + int i, n = evq->nr; + for (i = 0; i < n; i++) { + union buffered_input_event *ev = &evq->q[i]; + mark_object (ev->ie.x); + mark_object (ev->ie.y); + mark_object (ev->ie.frame_or_window); + mark_object (ev->ie.arg); + } + + struct pgtk_display_info *dpyinfo; + for (dpyinfo = x_display_list; dpyinfo != NULL; dpyinfo = dpyinfo->next) { + mark_object (dpyinfo->name_list_element); + mark_object (dpyinfo->xrdb); + } +} + +char * +x_get_keysym_name (int keysym) +/* -------------------------------------------------------------------------- + Called by keyboard.c. Not sure if the return val is important, except + that it be unique. + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("x_get_ksysym_name"); + static char value[16]; + sprintf (value, "%d", keysym); + return value; +} + +void +frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +/* -------------------------------------------------------------------------- + Programmatically reposition mouse pointer in pixel coordinates + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("frame_set_mouse_pixel_position"); +} + +/* Free X resources of frame F. */ + +void +x_free_frame_resources (struct frame *f) +{ + struct pgtk_display_info *dpyinfo; + Mouse_HLInfo *hlinfo; + + PGTK_TRACE ("x_free_frame_resources"); + check_window_system (f); + dpyinfo = FRAME_DISPLAY_INFO (f); + hlinfo = MOUSE_HL_INFO (f); + + block_input (); + + free_frame_faces (f); + +#define CLEAR_IF_EQ(FIELD) \ + do { if (f == dpyinfo->FIELD) dpyinfo->FIELD = 0; } while (false) + + CLEAR_IF_EQ(x_focus_frame); + CLEAR_IF_EQ(x_highlight_frame); + CLEAR_IF_EQ(x_focus_event_frame); + CLEAR_IF_EQ(last_mouse_frame); + CLEAR_IF_EQ(last_mouse_motion_frame); + CLEAR_IF_EQ(last_mouse_glyph_frame); + +#undef CLEAR_IF_EQ + + if (f == hlinfo->mouse_face_mouse_frame) + reset_mouse_highlight (hlinfo); + + gtk_widget_destroy(FRAME_GTK_OUTER_WIDGET(f)); + + if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { + cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); + FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; + } + + if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) { + cancel_atimer(FRAME_X_OUTPUT(f)->atimer_visible_bell); + FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + } + + xfree (f->output_data.pgtk); + f->output_data.pgtk = NULL; + + unblock_input (); +} + +void +x_destroy_window (struct frame *f) +/* -------------------------------------------------------------------------- + External: Delete the window + -------------------------------------------------------------------------- */ +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + PGTK_TRACE ("x_destroy_window"); + + check_window_system (f); + if (dpyinfo->gdpy != NULL) + x_free_frame_resources (f); + + dpyinfo->reference_count--; +} + +/* Calculate the absolute position in frame F + from its current recorded position values and gravity. */ + +static void +x_calc_absolute_position (struct frame *f) +{ + int flags = f->size_hint_flags; + struct frame *p = FRAME_PARENT_FRAME (f); + + /* We have nothing to do if the current position + is already for the top-left corner. */ + if (! ((flags & XNegative) || (flags & YNegative))) + return; + + /* Treat negative positions as relative to the leftmost bottommost + position that fits on the screen. */ + if ((flags & XNegative) && (f->left_pos <= 0)) + { + int width = FRAME_PIXEL_WIDTH (f); + + /* A frame that has been visible at least once should have outer + edges. */ + if (FRAME_X_OUTPUT(f)->has_been_visible && !p) + { + Lisp_Object frame; + Lisp_Object edges = Qnil; + + XSETFRAME (frame, f); + edges = Fpgtk_frame_edges (frame, Qouter_edges); + if (!NILP (edges)) + width = (XFIXNUM (Fnth (make_fixnum (2), edges)) + - XFIXNUM (Fnth (make_fixnum (0), edges))); + } + + if (p) + f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width + + f->left_pos); + else + f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) + - width + f->left_pos); + + } + + if ((flags & YNegative) && (f->top_pos <= 0)) + { + int height = FRAME_PIXEL_HEIGHT (f); + + if (FRAME_X_OUTPUT(f)->has_been_visible && !p) + { + Lisp_Object frame; + Lisp_Object edges = Qnil; + + XSETFRAME (frame, f); + if (NILP (edges)) + edges = Fpgtk_frame_edges (frame, Qouter_edges); + if (!NILP (edges)) + height = (XFIXNUM (Fnth (make_fixnum (3), edges)) + - XFIXNUM (Fnth (make_fixnum (1), edges))); + } + + if (p) + f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width + + f->top_pos); + else + f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) + - height + f->top_pos); + } + + /* The left_pos and top_pos + are now relative to the top and left screen edges, + so the flags should correspond. */ + f->size_hint_flags &= ~ (XNegative | YNegative); +} + +/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, + to really change the position, and 0 when calling from + x_make_frame_visible (in that case, XOFF and YOFF are the current + position values). It is -1 when calling from x_set_frame_parameters, + which means, do adjust for borders but don't change the gravity. */ + +static void +x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) +/* -------------------------------------------------------------------------- + External: Position the window + -------------------------------------------------------------------------- */ +{ + /* not working on wayland. */ + + PGTK_TRACE("x_set_offset: %d,%d,%d.", xoff, yoff, change_gravity); + + if (change_gravity > 0) + { + PGTK_TRACE("x_set_offset: change_gravity > 0"); + f->top_pos = yoff; + f->left_pos = xoff; + f->size_hint_flags &= ~ (XNegative | YNegative); + if (xoff < 0) + f->size_hint_flags |= XNegative; + if (yoff < 0) + f->size_hint_flags |= YNegative; + f->win_gravity = NorthWestGravity; + } + + x_calc_absolute_position (f); + + block_input (); + x_wm_set_size_hint (f, 0, false); + + /* When a position change was requested and the outer GTK widget + has been realized already, leave it to gtk_window_move to DTRT + and return. Used for Bug#25851 and Bug#25943. */ + if (change_gravity != 0 && FRAME_GTK_OUTER_WIDGET (f)) { + PGTK_TRACE("x_set_offset: move to %d,%d.", f->left_pos, f->top_pos); + gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + f->left_pos, f->top_pos); + } + + unblock_input (); +} + +static void +pgtk_set_window_size (struct frame *f, + bool change_gravity, + int width, + int height, + bool pixelwise) +/* -------------------------------------------------------------------------- + Adjust window pixel size based on given character grid size + Impl is a bit more complex than other terms, need to do some + internal clipping. + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("pgtk_set_window_size(%dx%d, %s)", width, height, pixelwise ? "pixel" : "char"); + int pixelwidth, pixelheight; + + block_input (); + + gtk_widget_get_size_request(FRAME_GTK_WIDGET(f), &pixelwidth, &pixelheight); + PGTK_TRACE("old: %dx%d", pixelwidth, pixelheight); + + if (pixelwise) + { + pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height); + } + else + { + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width); + pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); + } + + frame_size_history_add + (f, Qx_set_window_size_1, width, height, + list5 (Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)), + Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)), + make_fixnum (f->border_width), + make_fixnum (FRAME_PGTK_TITLEBAR_HEIGHT (f)), + make_fixnum (FRAME_TOOLBAR_HEIGHT (f)))); + + PGTK_TRACE("new: %dx%d", pixelwidth, pixelheight); + for (GtkWidget *w = FRAME_GTK_WIDGET(f); w != NULL; w = gtk_widget_get_parent(w)) { + PGTK_TRACE("%p %s %d %d", w, G_OBJECT_TYPE_NAME(w), gtk_widget_get_mapped(w), gtk_widget_get_visible(w)); + gint wd, hi; + gtk_widget_get_size_request(w, &wd, &hi); + PGTK_TRACE(" %dx%d", wd, hi); + GtkAllocation alloc; + gtk_widget_get_allocation(w, &alloc); + PGTK_TRACE(" %dx%d+%d+%d", alloc.width, alloc.height, alloc.x, alloc.y); + } + + PGTK_TRACE("pgtk_set_window_size: %p: %dx%d.", f, width, height); + f->output_data.pgtk->preferred_width = pixelwidth; + f->output_data.pgtk->preferred_height = pixelheight; + x_wm_set_size_hint(f, 0, 0); + xg_frame_set_char_size (f, FRAME_PIXEL_TO_TEXT_WIDTH(f, pixelwidth), FRAME_PIXEL_TO_TEXT_HEIGHT(f, pixelheight)); + gtk_widget_queue_resize (FRAME_GTK_OUTER_WIDGET (f)); + + unblock_input (); +} + +void +x_iconify_frame (struct frame *f) +/* -------------------------------------------------------------------------- + External: Iconify window + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("x_iconify_frame"); + + /* Don't keep the highlight on an invisible frame. */ + if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f) + FRAME_DISPLAY_INFO (f)->x_highlight_frame = 0; + + if (FRAME_ICONIFIED_P (f)) + return; + + block_input (); + +#if 0 + x_set_bitmap_icon (f); +#endif + + if (FRAME_GTK_OUTER_WIDGET (f)) + { + if (! FRAME_VISIBLE_P (f)) + gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f)); + + gtk_window_iconify (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f))); + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, true); + unblock_input (); + return; + } + + /* Make sure the X server knows where the window should be positioned, + in case the user deiconifies with the window manager. */ + if (! FRAME_VISIBLE_P (f) + && ! FRAME_ICONIFIED_P (f) +#if 0 + && ! FRAME_X_EMBEDDED_P (f) +#endif + ) + x_set_offset (f, f->left_pos, f->top_pos, 0); + +#if 0 + if (!FRAME_VISIBLE_P (f)) + { + /* If the frame was withdrawn, before, we must map it. */ + XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); + } +#endif + + SET_FRAME_ICONIFIED (f, true); + SET_FRAME_VISIBLE (f, 0); + +#if 0 + XFlush (FRAME_X_DISPLAY (f)); +#else + gdk_flush(); +#endif + unblock_input (); +} + +void +x_make_frame_visible (struct frame *f) +/* -------------------------------------------------------------------------- + External: Show the window (X11 semantics) + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("x_make_frame_visible"); +#if 0 + NSTRACE ("x_make_frame_visible"); + /* XXX: at some points in past this was not needed, as the only place that + called this (frame.c:Fraise_frame ()) also called raise_lower; + if this ends up the case again, comment this out again. */ + if (!FRAME_VISIBLE_P (f)) + { + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); + NSWindow *window = [view window]; + + SET_FRAME_VISIBLE (f, 1); + ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f)); + + /* Making a new frame from a fullscreen frame will make the new frame + fullscreen also. So skip handleFS as this will print an error. */ + if ([view fsIsNative] && f->want_fullscreen == FULLSCREEN_BOTH + && [view isFullscreen]) + return; + + if (f->want_fullscreen != FULLSCREEN_NONE) + { + block_input (); + [view handleFS]; + unblock_input (); + } + + /* Making a frame invisible seems to break the parent->child + relationship, so reinstate it. */ + if ([window parentWindow] == nil && FRAME_PARENT_FRAME (f) != NULL) + { + NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window]; + + block_input (); + [parent addChildWindow: window + ordered: NSWindowAbove]; + unblock_input (); + + /* If the parent frame moved while the child frame was + invisible, the child frame's position won't have been + updated. Make sure it's in the right place now. */ + x_set_offset(f, f->left_pos, f->top_pos, 0); + } + } +#endif +} + + +void +x_make_frame_invisible (struct frame *f) +/* -------------------------------------------------------------------------- + External: Hide the window (X11 semantics) + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("x_make_frame_invisible"); +#if 0 + NSView *view; + NSTRACE ("x_make_frame_invisible"); + check_window_system (f); + view = FRAME_NS_VIEW (f); + [[view window] orderOut: NSApp]; + SET_FRAME_VISIBLE (f, 0); + SET_FRAME_ICONIFIED (f, 0); +#endif +} + +static Lisp_Object +x_new_font (struct frame *f, Lisp_Object font_object, int fontset) +{ + PGTK_TRACE("x_new_font"); + struct font *font = XFONT_OBJECT (font_object); + int font_ascent, font_descent; + + if (fontset < 0) + fontset = fontset_from_font (font_object); + FRAME_FONTSET (f) = fontset; + + if (FRAME_FONT (f) == font) { + /* This font is already set in frame F. There's nothing more to + do. */ + PGTK_TRACE("already set."); + return font_object; + } + + FRAME_FONT (f) = font; + PGTK_TRACE("font:"); + PGTK_TRACE(" %p", font); + PGTK_TRACE(" name: %s", SSDATA(font_get_name(font_object))); + PGTK_TRACE(" width: %d..%d", font->min_width, font->max_width); + PGTK_TRACE(" pixel_size: %d", font->pixel_size); + PGTK_TRACE(" height: %d", font->height); + PGTK_TRACE(" space_width: %d", font->space_width); + PGTK_TRACE(" average_width: %d", font->average_width); + PGTK_TRACE(" asc/desc: %d,%d", font->ascent, font->descent); + PGTK_TRACE(" ul thickness: %d", font->underline_thickness); + PGTK_TRACE(" ul position: %d", font->underline_position); + PGTK_TRACE(" vertical_centering: %d", font->vertical_centering); + PGTK_TRACE(" baseline_offset: %d", font->baseline_offset); + PGTK_TRACE(" relative_compose: %d", font->relative_compose); + PGTK_TRACE(" default_ascent: %d", font->default_ascent); + PGTK_TRACE(" encoding_charset: %d", font->encoding_charset); + PGTK_TRACE(" repertory_charset: %d", font->repertory_charset); + + FRAME_BASELINE_OFFSET (f) = font->baseline_offset; + FRAME_COLUMN_WIDTH (f) = font->average_width; + get_font_ascent_descent (font, &font_ascent, &font_descent); + FRAME_LINE_HEIGHT (f) = font_ascent + font_descent; + + /* Compute the scroll bar width in character columns. */ + if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) + { + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) + = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid; + } + else + { + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; + } + + /* Compute the scroll bar height in character lines. */ + if (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0) + { + int height = FRAME_LINE_HEIGHT (f); + FRAME_CONFIG_SCROLL_BAR_LINES (f) + = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + height - 1) / height; + } + else + { + int height = FRAME_LINE_HEIGHT (f); + FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height; + } + + /* Now make the frame display the given font. */ + if (FRAME_GTK_WIDGET (f) != NULL) + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 3, + false, Qfont); + + PGTK_TRACE("set new."); + return font_object; +} + +int +x_display_pixel_height (struct pgtk_display_info *dpyinfo) +{ + PGTK_TRACE("x_display_pixel_height"); + + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkScreen *gscr = gdk_display_get_default_screen(gdpy); + PGTK_TRACE(" = %d", gdk_screen_get_height(gscr)); + return gdk_screen_get_height(gscr); +} + +int +x_display_pixel_width (struct pgtk_display_info *dpyinfo) +{ + PGTK_TRACE("x_display_pixel_width"); + + GdkDisplay *gdpy = dpyinfo->gdpy; + GdkScreen *gscr = gdk_display_get_default_screen(gdpy); + PGTK_TRACE(" = %d", gdk_screen_get_width(gscr)); + return gdk_screen_get_width(gscr); +} + +void +x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* Set frame F's `no-focus-on-map' parameter which, if non-nil, means + * that F's window-system window does not want to receive input focus + * when it is mapped. (A frame's window is mapped when the frame is + * displayed for the first time and when the frame changes its state + * from `iconified' or `invisible' to `visible'.) + * + * Some window managers may not honor this parameter. */ +{ + PGTK_TRACE("x_set_no_accept_focus_on_map"); + /* doesn't work on wayland. */ + + if (!EQ (new_value, old_value)) + { + xg_set_no_focus_on_map (f, new_value); + FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value); + } +} + +void +x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* Set frame F's `no-accept-focus' parameter which, if non-nil, hints + * that F's window-system window does not want to receive input focus + * via mouse clicks or by moving the mouse into it. + * + * If non-nil, this may have the unwanted side-effect that a user cannot + * scroll a non-selected frame with the mouse. + * + * Some window managers may not honor this parameter. */ +{ + /* doesn't work on wayland. */ + PGTK_TRACE("x_set_no_accept_focus"); + + xg_set_no_accept_focus (f, new_value); + FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value); +} + +void +x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* Set frame F's `z-group' parameter. If `above', F's window-system + window is displayed above all windows that do not have the `above' + property set. If nil, F's window is shown below all windows that + have the `above' property set and above all windows that have the + `below' property set. If `below', F's window is displayed below + all windows that do. + + Some window managers may not honor this parameter. */ +{ + /* doesn't work on wayland. */ + PGTK_TRACE("x_set_z_group"); + + if (NILP (new_value)) + { + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + FRAME_Z_GROUP (f) = z_group_none; + } + else if (EQ (new_value, Qabove)) + { + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), TRUE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + FRAME_Z_GROUP (f) = z_group_above; + } + else if (EQ (new_value, Qabove_suspended)) + { + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + FRAME_Z_GROUP (f) = z_group_above_suspended; + } + else if (EQ (new_value, Qbelow)) + { + gtk_window_set_keep_above (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), FALSE); + gtk_window_set_keep_below (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), TRUE); + FRAME_Z_GROUP (f) = z_group_below; + } + else + error ("Invalid z-group specification"); +} + +static void +pgtk_initialize_display_info (struct pgtk_display_info *dpyinfo) +/* -------------------------------------------------------------------------- + Initialize global info and storage for display. + -------------------------------------------------------------------------- */ +{ + dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */ + dpyinfo->resy = 72.27; + dpyinfo->color_p = 1; + dpyinfo->n_planes = 32; + dpyinfo->root_window = 42; /* a placeholder.. */ + dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL; + dpyinfo->n_fonts = 0; + dpyinfo->smallest_font_height = 1; + dpyinfo->smallest_char_width = 1; + + reset_mouse_highlight (&dpyinfo->mouse_highlight); +} + +/* Set S->gc to a suitable GC for drawing glyph string S in cursor + face. */ + +static void +x_set_cursor_gc (struct glyph_string *s) +{ + PGTK_TRACE("x_set_cursor_gc."); + if (s->font == FRAME_FONT (s->f) + && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) + && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) + && !s->cmp) + PGTK_TRACE("x_set_cursor_gc: 1."), + s->xgcv = FRAME_X_OUTPUT(s->f)->cursor_xgcv; + else + { + /* Cursor on non-default face: must merge. */ + XGCValues xgcv; + + PGTK_TRACE("x_set_cursor_gc: 2."); + xgcv.background = FRAME_X_OUTPUT(s->f)->cursor_color; + xgcv.foreground = s->face->background; + PGTK_TRACE("x_set_cursor_gc: 3. %08lx, %08lx.", xgcv.background, xgcv.foreground); + + /* If the glyph would be invisible, try a different foreground. */ + if (xgcv.foreground == xgcv.background) + xgcv.foreground = s->face->foreground; + PGTK_TRACE("x_set_cursor_gc: 4. %08lx, %08lx.", xgcv.background, xgcv.foreground); +#if 0 + if (xgcv.foreground == xgcv.background) + xgcv.foreground = FRAME_X_OUTPUT(s->f)->cursor_foreground_pixel; +#endif + if (xgcv.foreground == xgcv.background) + xgcv.foreground = s->face->foreground; + PGTK_TRACE("x_set_cursor_gc: 5. %08lx, %08lx.", xgcv.background, xgcv.foreground); + + /* Make sure the cursor is distinct from text in this face. */ + if (xgcv.background == s->face->background + && xgcv.foreground == s->face->foreground) + { + xgcv.background = s->face->foreground; + xgcv.foreground = s->face->background; + } + PGTK_TRACE("x_set_cursor_gc: 6. %08lx, %08lx.", xgcv.background, xgcv.foreground); + + IF_DEBUG (x_check_font (s->f, s->font)); + + s->xgcv = xgcv; + } +} + + +/* Set up S->gc of glyph string S for drawing text in mouse face. */ + +static void +x_set_mouse_face_gc (struct glyph_string *s) +{ + int face_id; + struct face *face; + + /* What face has to be used last for the mouse face? */ + face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id; + face = FACE_FROM_ID_OR_NULL (s->f, face_id); + if (face == NULL) + face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); + + if (s->first_glyph->type == CHAR_GLYPH) + face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil); + else + face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil); + s->face = FACE_FROM_ID (s->f, face_id); + prepare_face_for_display (s->f, s->face); + + if (s->font == s->face->font) { + s->xgcv.foreground = s->face->foreground; + s->xgcv.background = s->face->background; + } else + { + /* Otherwise construct scratch_cursor_gc with values from FACE + except for FONT. */ + XGCValues xgcv; + + xgcv.background = s->face->background; + xgcv.foreground = s->face->foreground; + + s->xgcv = xgcv; + + } +} + + +/* Set S->gc of glyph string S to a GC suitable for drawing a mode line. + Faces to use in the mode line have already been computed when the + matrix was built, so there isn't much to do, here. */ + +static void +x_set_mode_line_face_gc (struct glyph_string *s) +{ + s->xgcv.foreground = s->face->foreground; + s->xgcv.background = s->face->background; +} + + +/* Set S->gc of glyph string S for drawing that glyph string. Set + S->stippled_p to a non-zero value if the face of S has a stipple + pattern. */ + +static void +x_set_glyph_string_gc (struct glyph_string *s) +{ + PGTK_TRACE("x_set_glyph_string_gc: s->f: %08lx, %08lx", s->f->background_pixel, s->f->foreground_pixel); + PGTK_TRACE("x_set_glyph_string_gc: s->face: %08lx, %08lx", s->face->background, s->face->foreground); + prepare_face_for_display (s->f, s->face); + PGTK_TRACE("x_set_glyph_string_gc: s->face: %08lx, %08lx", s->face->background, s->face->foreground); + + if (s->hl == DRAW_NORMAL_TEXT) + { + s->xgcv.foreground = s->face->foreground; + s->xgcv.background = s->face->background; + s->stippled_p = s->face->stipple != 0; + PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + } + else if (s->hl == DRAW_INVERSE_VIDEO) + { + x_set_mode_line_face_gc (s); + s->stippled_p = s->face->stipple != 0; + PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + } + else if (s->hl == DRAW_CURSOR) + { + x_set_cursor_gc (s); + s->stippled_p = false; + PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + } + else if (s->hl == DRAW_MOUSE_FACE) + { + x_set_mouse_face_gc (s); + s->stippled_p = s->face->stipple != 0; + PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + } + else if (s->hl == DRAW_IMAGE_RAISED + || s->hl == DRAW_IMAGE_SUNKEN) + { + s->xgcv.foreground = s->face->foreground; + s->xgcv.background = s->face->background; + s->stippled_p = s->face->stipple != 0; + PGTK_TRACE("x_set_glyph_string_gc: %08lx, %08lx", s->xgcv.background, s->xgcv.foreground); + } + else + emacs_abort (); +} + + +/* Set clipping for output of glyph string S. S may be part of a mode + line or menu if we don't have X toolkit support. */ + +static void +x_set_glyph_string_clipping (struct glyph_string *s, cairo_t *cr) +{ + XRectangle r[2]; + int n = get_glyph_string_clip_rects (s, r, 2); + PGTK_TRACE("x_set_glyph_string_clipping: n=%d.", n); + + if (n > 0) { + for (int i = 0; i < n; i++) { + PGTK_TRACE("x_set_glyph_string_clipping: r[%d]: %ux%u+%d+%d.", + i, r[i].width, r[i].height, r[i].x, r[i].y); + cairo_rectangle(cr, r[i].x, r[i].y, r[i].width, r[i].height); + } + cairo_clip(cr); + } + PGTK_TRACE("clip result:"); + cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr); + for (int i = 0; i < rects->num_rectangles; i++) { + PGTK_TRACE(" rect[%d]: %dx%d+%d+%d.", + i, + (int) rects->rectangles[i].width, + (int) rects->rectangles[i].height, + (int) rects->rectangles[i].x, + (int) rects->rectangles[i].y); + } + cairo_rectangle_list_destroy(rects); +} + + +/* Set SRC's clipping for output of glyph string DST. This is called + when we are drawing DST's left_overhang or right_overhang only in + the area of SRC. */ + +static void +x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_string *dst, cairo_t *cr) +{ + dst->clip[0].x = src->x; + dst->clip[0].y = src->y; + dst->clip[0].width = src->width; + dst->clip[0].height = src->height; + dst->num_clips = 1; + + cairo_rectangle(cr, src->x, src->y, src->width, src->height); + cairo_clip(cr); +} + + +/* RIF: + Compute left and right overhang of glyph string S. */ + +static void +pgtk_compute_glyph_string_overhangs (struct glyph_string *s) +{ + if (s->cmp == NULL + && (s->first_glyph->type == CHAR_GLYPH + || s->first_glyph->type == COMPOSITE_GLYPH)) + { + struct font_metrics metrics; + + if (s->first_glyph->type == CHAR_GLYPH) + { + unsigned *code = alloca (sizeof (unsigned) * s->nchars); + struct font *font = s->font; + int i; + + for (i = 0; i < s->nchars; i++) + code[i] = s->char2b[i]; + font->driver->text_extents (font, code, s->nchars, &metrics); + } + else + { + Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); + + composition_gstring_width (gstring, s->cmp_from, s->cmp_to, &metrics); + } + s->right_overhang = (metrics.rbearing > metrics.width + ? metrics.rbearing - metrics.width : 0); + s->left_overhang = metrics.lbearing < 0 ? - metrics.lbearing : 0; + } + else if (s->cmp) + { + s->right_overhang = s->cmp->rbearing - s->cmp->pixel_width; + s->left_overhang = - s->cmp->lbearing; + } +} + + +/* Fill rectangle X, Y, W, H with background color of glyph string S. */ + +static void +x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) +{ + pgtk_fill_rectangle(s->f, s->xgcv.background, x, y, w, h); +} + + +/* Draw the background of glyph_string S. If S->background_filled_p + is non-zero don't draw it. FORCE_P non-zero means draw the + background even if it wouldn't be drawn normally. This is used + when a string preceding S draws into the background of S, or S + contains the first component of a composition. */ + +static void +x_draw_glyph_string_background (struct glyph_string *s, bool force_p) +{ + PGTK_TRACE("x_draw_glyph_string_background: 0."); + /* Nothing to do if background has already been drawn or if it + shouldn't be drawn in the first place. */ + if (!s->background_filled_p) + { + PGTK_TRACE("x_draw_glyph_string_background: 1."); + int box_line_width = max (s->face->box_line_width, 0); + + PGTK_TRACE("x_draw_glyph_string_background: 2. %d, %d.", + FONT_HEIGHT (s->font), s->height - 2 * box_line_width); + PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", FONT_TOO_HIGH(s->font)); + PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); + PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); + PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); +#if 0 + if (s->stippled_p) + { + /* Fill background with a stipple pattern. */ + XSetFillStyle (s->display, s->gc, FillOpaqueStippled); + x_fill_rectangle (s->f, s->gc, s->x, + s->y + box_line_width, + s->background_width, + s->height - 2 * box_line_width); + XSetFillStyle (s->display, s->gc, FillSolid); + s->background_filled_p = true; + } + else +#endif + if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width + /* When xdisp.c ignores FONT_HEIGHT, we cannot trust + font dimensions, since the actual glyphs might be + much smaller. So in that case we always clear the + rectangle with background color. */ + || FONT_TOO_HIGH (s->font) + || s->font_not_found_p + || s->extends_to_end_of_line_p + || force_p) + { + PGTK_TRACE("x_draw_glyph_string_background: 3."); + x_clear_glyph_string_rect (s, s->x, s->y + box_line_width, + s->background_width, + s->height - 2 * box_line_width); + s->background_filled_p = true; + } + } +} + + +static void +pgtk_draw_rectangle (struct frame *f, unsigned long color, int x, int y, int width, int height) +{ + cairo_t *cr; + + cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x + 0.5, y + 0.5, width, height); + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + pgtk_end_cr_clip (f); +} + +/* Draw the foreground of glyph string S. */ + +static void +x_draw_glyph_string_foreground (struct glyph_string *s) +{ + int i, x; + + /* If first glyph of S has a left box line, start drawing the text + of S to the right of that box line. */ + if (s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p) + x = s->x + eabs (s->face->box_line_width); + else + x = s->x; + + /* Draw characters of S as rectangles if S's font could not be + loaded. */ + if (s->font_not_found_p) + { + for (i = 0; i < s->nchars; ++i) + { + struct glyph *g = s->first_glyph + i; + pgtk_draw_rectangle (s->f, + s->face->foreground, x, s->y, g->pixel_width - 1, + s->height - 1); + x += g->pixel_width; + } + } + else + { + struct font *font = s->font; + int boff = font->baseline_offset; + int y; + + if (font->vertical_centering) + boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff; + + y = s->ybase - boff; + if (s->for_overlaps + || (s->background_filled_p && s->hl != DRAW_CURSOR)) + font->driver->draw (s, 0, s->nchars, x, y, false); + else + font->driver->draw (s, 0, s->nchars, x, y, true); + if (s->face->overstrike) + font->driver->draw (s, 0, s->nchars, x + 1, y, false); + } +} + +/* Draw the foreground of composite glyph string S. */ + +static void +x_draw_composite_glyph_string_foreground (struct glyph_string *s) +{ + int i, j, x; + struct font *font = s->font; + + /* If first glyph of S has a left box line, start drawing the text + of S to the right of that box line. */ + if (s->face && s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p) + x = s->x + eabs (s->face->box_line_width); + else + x = s->x; + + /* S is a glyph string for a composition. S->cmp_from is the index + of the first character drawn for glyphs of this composition. + S->cmp_from == 0 means we are drawing the very first character of + this composition. */ + + /* Draw a rectangle for the composition if the font for the very + first character of the composition could not be loaded. */ + if (s->font_not_found_p) + { + if (s->cmp_from == 0) + pgtk_draw_rectangle (s->f, s->face->foreground, x, s->y, + s->width - 1, s->height - 1); + } + else if (! s->first_glyph->u.cmp.automatic) + { + int y = s->ybase; + + for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++) + /* TAB in a composition means display glyphs with padding + space on the left or right. */ + if (COMPOSITION_GLYPH (s->cmp, j) != '\t') + { + int xx = x + s->cmp->offsets[j * 2]; + int yy = y - s->cmp->offsets[j * 2 + 1]; + + font->driver->draw (s, j, j + 1, xx, yy, false); + if (s->face->overstrike) + font->driver->draw (s, j, j + 1, xx + 1, yy, false); + } + } + else + { + Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); + Lisp_Object glyph; + int y = s->ybase; + int width = 0; + + for (i = j = s->cmp_from; i < s->cmp_to; i++) + { + glyph = LGSTRING_GLYPH (gstring, i); + if (NILP (LGLYPH_ADJUSTMENT (glyph))) + width += LGLYPH_WIDTH (glyph); + else + { + int xoff, yoff, wadjust; + + if (j < i) + { + font->driver->draw (s, j, i, x, y, false); + if (s->face->overstrike) + font->driver->draw (s, j, i, x + 1, y, false); + x += width; + } + xoff = LGLYPH_XOFF (glyph); + yoff = LGLYPH_YOFF (glyph); + wadjust = LGLYPH_WADJUST (glyph); + font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false); + if (s->face->overstrike) + font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, + false); + x += wadjust; + j = i + 1; + width = 0; + } + } + if (j < i) + { + font->driver->draw (s, j, i, x, y, false); + if (s->face->overstrike) + font->driver->draw (s, j, i, x + 1, y, false); + } + } +} + + +/* Draw the foreground of glyph string S for glyphless characters. */ + +static void +x_draw_glyphless_glyph_string_foreground (struct glyph_string *s) +{ + struct glyph *glyph = s->first_glyph; + unsigned char2b[8]; + int x, i, j; + + /* If first glyph of S has a left box line, start drawing the text + of S to the right of that box line. */ + if (s->face && s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p) + x = s->x + eabs (s->face->box_line_width); + else + x = s->x; + + s->char2b = char2b; + + for (i = 0; i < s->nchars; i++, glyph++) + { +#ifdef GCC_LINT + enum { PACIFY_GCC_BUG_81401 = 1 }; +#else + enum { PACIFY_GCC_BUG_81401 = 0 }; +#endif + char buf[7 + PACIFY_GCC_BUG_81401]; + char *str = NULL; + int len = glyph->u.glyphless.len; + + if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM) + { + if (len > 0 + && CHAR_TABLE_P (Vglyphless_char_display) + && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) + >= 1)) + { + Lisp_Object acronym + = (! glyph->u.glyphless.for_no_font + ? CHAR_TABLE_REF (Vglyphless_char_display, + glyph->u.glyphless.ch) + : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); + if (STRINGP (acronym)) + str = SSDATA (acronym); + } + } + else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE) + { + unsigned int ch = glyph->u.glyphless.ch; + eassume (ch <= MAX_CHAR); + sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch); + str = buf; + } + + if (str) + { + int upper_len = (len + 1) / 2; + + /* It is assured that all LEN characters in STR is ASCII. */ + for (j = 0; j < len; j++) + char2b[j] = s->font->driver->encode_char (s->font, str[j]) & 0xFFFF; + s->font->driver->draw (s, 0, upper_len, + x + glyph->slice.glyphless.upper_xoff, + s->ybase + glyph->slice.glyphless.upper_yoff, + false); + s->font->driver->draw (s, upper_len, len, + x + glyph->slice.glyphless.lower_xoff, + s->ybase + glyph->slice.glyphless.lower_yoff, + false); + } + if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE) + pgtk_draw_rectangle (s->f, s->face->foreground, + x, s->ybase - glyph->ascent, + glyph->pixel_width - 1, + glyph->ascent + glyph->descent - 1); + x += glyph->pixel_width; + } +} + +/* Brightness beyond which a color won't have its highlight brightness + boosted. + + Nominally, highlight colors for `3d' faces are calculated by + brightening an object's color by a constant scale factor, but this + doesn't yield good results for dark colors, so for colors who's + brightness is less than this value (on a scale of 0-65535) have an + use an additional additive factor. + + The value here is set so that the default menu-bar/mode-line color + (grey75) will not have its highlights changed at all. */ +#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000 + + +/* Allocate a color which is lighter or darker than *PIXEL by FACTOR + or DELTA. Try a color with RGB values multiplied by FACTOR first. + If this produces the same color as PIXEL, try a color where all RGB + values have DELTA added. Return the allocated color in *PIXEL. + DISPLAY is the X display, CMAP is the colormap to operate on. + Value is non-zero if successful. */ + +static bool +x_alloc_lighter_color (struct frame *f, unsigned long *pixel, double factor, int delta) +{ + Emacs_Color color, new; + long bright; + bool success_p; + + /* Get RGB color values. */ + color.pixel = *pixel; + pgtk_query_color (f, &color); + + /* Change RGB values by specified FACTOR. Avoid overflow! */ + eassert (factor >= 0); + new.red = min (0xffff, factor * color.red); + new.green = min (0xffff, factor * color.green); + new.blue = min (0xffff, factor * color.blue); + + /* Calculate brightness of COLOR. */ + bright = (2 * color.red + 3 * color.green + color.blue) / 6; + + /* We only boost colors that are darker than + HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */ + if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT) + /* Make an additive adjustment to NEW, because it's dark enough so + that scaling by FACTOR alone isn't enough. */ + { + /* How far below the limit this color is (0 - 1, 1 being darker). */ + double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT; + /* The additive adjustment. */ + int min_delta = delta * dimness * factor / 2; + + if (factor < 1) + { + new.red = max (0, new.red - min_delta); + new.green = max (0, new.green - min_delta); + new.blue = max (0, new.blue - min_delta); + } + else + { + new.red = min (0xffff, min_delta + new.red); + new.green = min (0xffff, min_delta + new.green); + new.blue = min (0xffff, min_delta + new.blue); + } + } + + /* Try to allocate the color. */ + new.pixel = new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8; + success_p = true; + if (success_p) + { + if (new.pixel == *pixel) + { + /* If we end up with the same color as before, try adding + delta to the RGB values. */ + new.red = min (0xffff, delta + color.red); + new.green = min (0xffff, delta + color.green); + new.blue = min (0xffff, delta + color.blue); + new.pixel = new.red >> 8 << 16 | new.green >> 8 << 8 | new.blue >> 8; + success_p = true; + } + else + success_p = true; + *pixel = new.pixel; + } + + return success_p; +} + +static void +x_fill_trapezoid_for_relief (struct frame *f, unsigned long color, int x, int y, + int width, int height, int top_p) +{ + cairo_t *cr; + + cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, color); + cairo_move_to (cr, top_p ? x : x + height, y); + cairo_line_to (cr, x, y + height); + cairo_line_to (cr, top_p ? x + width - height : x + width, y + height); + cairo_line_to (cr, x + width, y); + cairo_fill (cr); + pgtk_end_cr_clip (f); +} + +enum corners + { + CORNER_BOTTOM_RIGHT, /* 0 -> pi/2 */ + CORNER_BOTTOM_LEFT, /* pi/2 -> pi */ + CORNER_TOP_LEFT, /* pi -> 3pi/2 */ + CORNER_TOP_RIGHT, /* 3pi/2 -> 2pi */ + CORNER_LAST + }; + +static void +x_erase_corners_for_relief (struct frame *f, unsigned long color, int x, int y, + int width, int height, + double radius, double margin, int corners) +{ + cairo_t *cr; + int i; + + cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, color); + for (i = 0; i < CORNER_LAST; i++) + if (corners & (1 << i)) + { + double xm, ym, xc, yc; + + if (i == CORNER_TOP_LEFT || i == CORNER_BOTTOM_LEFT) + xm = x - margin, xc = xm + radius; + else + xm = x + width + margin, xc = xm - radius; + if (i == CORNER_TOP_LEFT || i == CORNER_TOP_RIGHT) + ym = y - margin, yc = ym + radius; + else + ym = y + height + margin, yc = ym - radius; + + cairo_move_to (cr, xm, ym); + cairo_arc (cr, xc, yc, radius, i * M_PI_2, (i + 1) * M_PI_2); + } + cairo_clip (cr); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (f); +} + +/* Set up the foreground color for drawing relief lines of glyph + string S. RELIEF is a pointer to a struct relief containing the GC + with which lines will be drawn. Use a color that is FACTOR or + DELTA lighter or darker than the relief's background which is found + in S->f->output_data.pgtk->relief_background. If such a color cannot + be allocated, use DEFAULT_PIXEL, instead. */ + +static void +x_setup_relief_color (struct frame *f, struct relief *relief, double factor, + int delta, unsigned long default_pixel) +{ + XGCValues xgcv; + struct pgtk_output *di = FRAME_X_OUTPUT(f); + unsigned long pixel; + unsigned long background = di->relief_background; + + /* Allocate new color. */ + xgcv.foreground = default_pixel; + pixel = background; + if (x_alloc_lighter_color (f, &pixel, factor, delta)) + xgcv.foreground = relief->pixel = pixel; + + relief->xgcv = xgcv; +} + +/* Set up colors for the relief lines around glyph string S. */ + +static void +x_setup_relief_colors (struct glyph_string *s) +{ + struct pgtk_output *di = FRAME_X_OUTPUT(s->f); + unsigned long color; + + if (s->face->use_box_color_for_shadows_p) + color = s->face->box_color; + else if (s->first_glyph->type == IMAGE_GLYPH + && s->img->pixmap + && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) + color = IMAGE_BACKGROUND (s->img, s->f, 0); + else + { + /* Get the background color of the face. */ + color = s->xgcv.background; + } + + if (TRUE) + { + di->relief_background = color; + x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000, + WHITE_PIX_DEFAULT (s->f)); + x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000, + BLACK_PIX_DEFAULT (s->f)); + } +} + + +static void +x_set_clip_rectangles (struct frame *f, cairo_t *cr, XRectangle *rectangles, int n) +{ + if (n > 0) { + for (int i = 0; i < n; i++) { + cairo_rectangle(cr, + rectangles[i].x, + rectangles[i].y, + rectangles[i].width, + rectangles[i].height); + } + cairo_clip(cr); + } +} + +/* Draw a relief on frame F inside the rectangle given by LEFT_X, + TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief + to draw, it must be >= 0. RAISED_P means draw a raised + relief. LEFT_P means draw a relief on the left side of + the rectangle. RIGHT_P means draw a relief on the right + side of the rectangle. CLIP_RECT is the clipping rectangle to use + when drawing. */ + +static void +x_draw_relief_rect (struct frame *f, + int left_x, int top_y, int right_x, int bottom_y, + int width, bool raised_p, bool top_p, bool bot_p, + bool left_p, bool right_p, + XRectangle *clip_rect) +{ + unsigned long top_left_color, bottom_right_color; + int corners = 0; + + cairo_t *cr = pgtk_begin_cr_clip(f); + + if (raised_p) + { + top_left_color = FRAME_X_OUTPUT(f)->white_relief.xgcv.foreground; + bottom_right_color = FRAME_X_OUTPUT(f)->black_relief.xgcv.foreground; + } + else + { + top_left_color = FRAME_X_OUTPUT(f)->black_relief.xgcv.foreground; + bottom_right_color = FRAME_X_OUTPUT(f)->white_relief.xgcv.foreground; + } + + x_set_clip_rectangles (f, cr, clip_rect, 1); + + if (left_p) + { + pgtk_fill_rectangle (f, top_left_color, left_x, top_y, + width, bottom_y + 1 - top_y); + if (top_p) + corners |= 1 << CORNER_TOP_LEFT; + if (bot_p) + corners |= 1 << CORNER_BOTTOM_LEFT; + } + if (right_p) + { + pgtk_fill_rectangle (f, bottom_right_color, right_x + 1 - width, top_y, + width, bottom_y + 1 - top_y); + if (top_p) + corners |= 1 << CORNER_TOP_RIGHT; + if (bot_p) + corners |= 1 << CORNER_BOTTOM_RIGHT; + } + if (top_p) + { + if (!right_p) + pgtk_fill_rectangle (f, top_left_color, left_x, top_y, + right_x + 1 - left_x, width); + else + x_fill_trapezoid_for_relief (f, top_left_color, left_x, top_y, + right_x + 1 - left_x, width, 1); + } + if (bot_p) + { + if (!left_p) + pgtk_fill_rectangle (f, bottom_right_color, left_x, bottom_y + 1 - width, + right_x + 1 - left_x, width); + else + x_fill_trapezoid_for_relief (f, bottom_right_color, + left_x, bottom_y + 1 - width, + right_x + 1 - left_x, width, 0); + } + if (left_p && width != 1) + pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, + 1, bottom_y + 1 - top_y); + if (top_p && width != 1) + pgtk_fill_rectangle (f, bottom_right_color, left_x, top_y, + right_x + 1 - left_x, 1); + if (corners) + { + x_erase_corners_for_relief (f, FRAME_BACKGROUND_PIXEL (f), left_x, top_y, + right_x - left_x + 1, bottom_y - top_y + 1, + 6, 1, corners); + } + + pgtk_end_cr_clip(f); +} + +/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y, + RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to + draw, it must be >= 0. LEFT_P means draw a line on the + left side of the rectangle. RIGHT_P means draw a line + on the right side of the rectangle. CLIP_RECT is the clipping + rectangle to use when drawing. */ + +static void +x_draw_box_rect (struct glyph_string *s, + int left_x, int top_y, int right_x, int bottom_y, int width, + bool left_p, bool right_p, XRectangle *clip_rect) +{ + unsigned long foreground_backup; + + cairo_t *cr = pgtk_begin_cr_clip(s->f); + + foreground_backup = s->xgcv.foreground; + s->xgcv.foreground = s->face->box_color; + + x_set_clip_rectangles (s->f, cr, clip_rect, 1); + + /* Top. */ + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + left_x, top_y, right_x - left_x + 1, width); + + /* Left. */ + if (left_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + left_x, top_y, width, bottom_y - top_y + 1); + + /* Bottom. */ + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + left_x, bottom_y - width + 1, right_x - left_x + 1, width); + + /* Right. */ + if (right_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + right_x - width + 1, top_y, width, bottom_y - top_y + 1); + + s->xgcv.foreground = foreground_backup; + + pgtk_end_cr_clip(s->f); +} + + +/* Draw a box around glyph string S. */ + +static void +x_draw_glyph_string_box (struct glyph_string *s) +{ + int width, left_x, right_x, top_y, bottom_y, last_x; + bool raised_p, left_p, right_p; + struct glyph *last_glyph; + XRectangle clip_rect; + + last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area)); + + /* The glyph that may have a right box line. */ + last_glyph = (s->cmp || s->img + ? s->first_glyph + : s->first_glyph + s->nchars - 1); + + width = eabs (s->face->box_line_width); + raised_p = s->face->box == FACE_RAISED_BOX; + left_x = s->x; + right_x = (s->row->full_width_p && s->extends_to_end_of_line_p + ? last_x - 1 + : min (last_x, s->x + s->background_width) - 1); + top_y = s->y; + bottom_y = top_y + s->height - 1; + + left_p = (s->first_glyph->left_box_line_p + || (s->hl == DRAW_MOUSE_FACE + && (s->prev == NULL + || s->prev->hl != s->hl))); + right_p = (last_glyph->right_box_line_p + || (s->hl == DRAW_MOUSE_FACE + && (s->next == NULL + || s->next->hl != s->hl))); + + get_glyph_string_clip_rect (s, &clip_rect); + + if (s->face->box == FACE_SIMPLE_BOX) + x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, + left_p, right_p, &clip_rect); + else + { + x_setup_relief_colors (s); + x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, + width, raised_p, true, true, left_p, right_p, + &clip_rect); + } +} + +static void +x_get_scale_factor(int *scale_x, int *scale_y) +{ + *scale_x = *scale_y = 1; +} + +static void +x_draw_horizontal_wave (struct frame *f, unsigned long color, int x, int y, + int width, int height, int wave_length) +{ + cairo_t *cr; + double dx = wave_length, dy = height - 1; + int xoffset, n; + + cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + + if (x >= 0) + { + xoffset = x % (wave_length * 2); + if (xoffset == 0) + xoffset = wave_length * 2; + } + else + xoffset = x % (wave_length * 2) + wave_length * 2; + n = (width + xoffset) / wave_length + 1; + if (xoffset > wave_length) + { + xoffset -= wave_length; + --n; + y += height - 1; + dy = -dy; + } + + cairo_move_to (cr, x - xoffset + 0.5, y + 0.5); + while (--n >= 0) + { + cairo_rel_line_to (cr, dx, dy); + dy = -dy; + } + cairo_set_line_width (cr, 1); + cairo_stroke (cr); + pgtk_end_cr_clip (f); +} + +/* + Draw a wavy line under S. The wave fills wave_height pixels from y0. + + x0 wave_length = 2 + -- + y0 * * * * * + |* * * * * * * * * + wave_height = 3 | * * * * + +*/ +static void +x_draw_underwave (struct glyph_string *s, unsigned long color) +{ + /* Adjust for scale/HiDPI. */ + int scale_x, scale_y; + + x_get_scale_factor (&scale_x, &scale_y); + + int wave_height = 3 * scale_y, wave_length = 2 * scale_x; + + x_draw_horizontal_wave (s->f, color, s->x, s->ybase - wave_height + 3, + s->width, wave_height, wave_length); +} + +/* Draw a relief around the image glyph string S. */ + +static void +x_draw_image_relief (struct glyph_string *s) +{ + int x1, y1, thick; + bool raised_p, top_p, bot_p, left_p, right_p; + int extra_x, extra_y; + XRectangle r; + int x = s->x; + int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + + /* If first glyph of S has a left box line, start drawing it to the + right of that line. */ + if (s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += eabs (s->face->box_line_width); + + /* If there is a margin around the image, adjust x- and y-position + by that margin. */ + if (s->slice.x == 0) + x += s->img->hmargin; + if (s->slice.y == 0) + y += s->img->vmargin; + + if (s->hl == DRAW_IMAGE_SUNKEN + || s->hl == DRAW_IMAGE_RAISED) + { + thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF; + raised_p = s->hl == DRAW_IMAGE_RAISED; + } + else + { + thick = eabs (s->img->relief); + raised_p = s->img->relief > 0; + } + + x1 = x + s->slice.width - 1; + y1 = y + s->slice.height - 1; + + extra_x = extra_y = 0; + if (s->face->id == TOOL_BAR_FACE_ID) + { + if (CONSP (Vtool_bar_button_margin) + && INTEGERP (XCAR (Vtool_bar_button_margin)) + && INTEGERP (XCDR (Vtool_bar_button_margin))) + { + extra_x = XFIXNUM (XCAR (Vtool_bar_button_margin)); + extra_y = XFIXNUM (XCDR (Vtool_bar_button_margin)); + } + else if (INTEGERP (Vtool_bar_button_margin)) + extra_x = extra_y = XFIXNUM (Vtool_bar_button_margin); + } + + top_p = bot_p = left_p = right_p = false; + + if (s->slice.x == 0) + x -= thick + extra_x, left_p = true; + if (s->slice.y == 0) + y -= thick + extra_y, top_p = true; + if (s->slice.x + s->slice.width == s->img->width) + x1 += thick + extra_x, right_p = true; + if (s->slice.y + s->slice.height == s->img->height) + y1 += thick + extra_y, bot_p = true; + + x_setup_relief_colors (s); + get_glyph_string_clip_rect (s, &r); + x_draw_relief_rect (s->f, x, y, x1, y1, thick, raised_p, + top_p, bot_p, left_p, right_p, &r); +} + +/* Draw part of the background of glyph string S. X, Y, W, and H + give the rectangle to draw. */ + +static void +x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) +{ +#if 0 + if (s->stippled_p) + { + /* Fill background with a stipple pattern. */ + XSetFillStyle (s->display, s->gc, FillOpaqueStippled); + x_fill_rectangle (s->f, s->gc, x, y, w, h); + XSetFillStyle (s->display, s->gc, FillSolid); + } + else +#endif + x_clear_glyph_string_rect (s, x, y, w, h); +} + +/* Draw foreground of image glyph string S. */ + +static void +x_draw_image_foreground (struct glyph_string *s) +{ + int x = s->x; + int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + + /* If first glyph of S has a left box line, start drawing it to the + right of that line. */ + if (s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p + && s->slice.x == 0) + x += eabs (s->face->box_line_width); + + /* If there is a margin around the image, adjust x- and y-position + by that margin. */ + if (s->slice.x == 0) + x += s->img->hmargin; + if (s->slice.y == 0) + y += s->img->vmargin; + + /* Draw a rectangle if image could not be loaded. */ + pgtk_draw_rectangle (s->f, s->xgcv.foreground, x, y, + s->slice.width - 1, s->slice.height - 1); +} + +/* Draw image glyph string S. + + s->y + s->x +------------------------- + | s->face->box + | + | +------------------------- + | | s->img->margin + | | + | | +------------------- + | | | the image + + */ + +static void +x_draw_image_glyph_string (struct glyph_string *s) +{ + int box_line_hwidth = eabs (s->face->box_line_width); + int box_line_vwidth = max (s->face->box_line_width, 0); + int height; + cairo_surface_t *surface = NULL; + + height = s->height; + if (s->slice.y == 0) + height -= box_line_vwidth; + if (s->slice.y + s->slice.height >= s->img->height) + height -= box_line_vwidth; + + /* Fill background with face under the image. Do it only if row is + taller than image or if image has a clip mask to reduce + flickering. */ + s->stippled_p = s->face->stipple != 0; + if (height > s->slice.height + || s->img->hmargin + || s->img->vmargin + || s->img->mask + || s->img->pixmap == 0 + || s->stippled_p + || s->width != s->background_width) + { + if (s->img->mask) + { + /* Create a pixmap as large as the glyph string. Fill it + with the background color. Copy the image to it, using + its mask. Copy the temporary pixmap to the display. */ + + /* Create a pixmap as large as the glyph string. */ + surface = cairo_surface_create_similar(FRAME_CR_SURFACE(s->f), CAIRO_CONTENT_COLOR_ALPHA, + s->background_width, + s->height); + + /* Don't clip in the following because we're working on the + pixmap. */ + // XSetClipMask (s->display, s->gc, None); + + /* Fill the pixmap with the background color/stipple. */ +#if 0 + if (s->stippled_p) + { + /* Fill background with a stipple pattern. */ + XSetFillStyle (s->display, s->gc, FillOpaqueStippled); + XSetTSOrigin (s->display, s->gc, - s->x, - s->y); + XFillRectangle (s->display, pixmap, s->gc, + 0, 0, s->background_width, s->height); + XSetFillStyle (s->display, s->gc, FillSolid); + XSetTSOrigin (s->display, s->gc, 0, 0); + } + else +#endif + { + cairo_t *cr = cairo_create(surface); + int red = (s->xgcv.background >> 16) & 0xff; + int green = (s->xgcv.background >> 8) & 0xff; + int blue = (s->xgcv.background >> 0) & 0xff; + cairo_set_source_rgb (cr, red / 255.0, green / 255.0, blue / 255.0); + cairo_rectangle(cr, 0, 0, s->background_width, s->height); + cairo_fill(cr); + cairo_destroy(cr); + } + } + else + { + int x = s->x; + int y = s->y; + int width = s->background_width; + + if (s->first_glyph->left_box_line_p + && s->slice.x == 0) + { + x += box_line_hwidth; + width -= box_line_hwidth; + } + + if (s->slice.y == 0) + y += box_line_vwidth; + + x_draw_glyph_string_bg_rect (s, x, y, width, height); + } + + s->background_filled_p = true; + } + + /* Draw the foreground. */ + if (s->img->cr_data) + { + cairo_t *cr = pgtk_begin_cr_clip (s->f); + + int x = s->x + s->img->hmargin; + int y = s->y + s->img->vmargin; + int width = s->background_width; + + cairo_translate (cr, x - s->slice.x, y - s->slice.y); + cairo_set_source (cr, s->img->cr_data); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + } + else + if (surface != NULL) + { + cairo_t *cr = pgtk_begin_cr_clip(s->f); + + x_draw_image_foreground_1 (s, surface); + x_set_glyph_string_clipping (s, cr); + + cairo_set_source_surface(cr, surface, 0, 0); + cairo_rectangle(cr, s->x, s->y, s->background_width, s->height); + pgtk_end_cr_clip(s->f); + } + else + x_draw_image_foreground (s); + + /* If we must draw a relief around the image, do it. */ + if (s->img->relief + || s->hl == DRAW_IMAGE_RAISED + || s->hl == DRAW_IMAGE_SUNKEN) + x_draw_image_relief (s); + + if (surface != NULL) + cairo_surface_destroy(surface); +} + +/* Draw stretch glyph string S. */ + +static void +x_draw_stretch_glyph_string (struct glyph_string *s) +{ + eassert (s->first_glyph->type == STRETCH_GLYPH); + + if (s->hl == DRAW_CURSOR + && !x_stretch_cursor_p) + { + /* If `x-stretch-cursor' is nil, don't draw a block cursor as + wide as the stretch glyph. */ + int width, background_width = s->background_width; + int x = s->x; + + if (!s->row->reversed_p) + { + int left_x = window_box_left_offset (s->w, TEXT_AREA); + + if (x < left_x) + { + background_width -= left_x - x; + x = left_x; + } + } + else + { + /* In R2L rows, draw the cursor on the right edge of the + stretch glyph. */ + int right_x = window_box_right (s->w, TEXT_AREA); + + if (x + background_width > right_x) + background_width -= x - right_x; + x += background_width; + } + width = min (FRAME_COLUMN_WIDTH (s->f), background_width); + if (s->row->reversed_p) + x -= width; + + /* Draw cursor. */ + x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height); + + /* Clear rest using the GC of the original non-cursor face. */ + if (width < background_width) + { + int y = s->y; + int w = background_width - width, h = s->height; + XRectangle r; + unsigned long color; + + if (!s->row->reversed_p) + x += width; + else + x = s->x; + if (s->row->mouse_face_p + && cursor_in_mouse_face_p (s->w)) + { + x_set_mouse_face_gc (s); + color = s->xgcv.foreground; + } + else + color = s->face->foreground; + + cairo_t *cr = pgtk_begin_cr_clip(s->f); + + get_glyph_string_clip_rect (s, &r); + x_set_clip_rectangles (s->f, cr, &r, 1); + +#if 0 + if (s->face->stipple) + { + /* Fill background with a stipple pattern. */ + XSetFillStyle (s->display, gc, FillOpaqueStippled); + x_fill_rectangle (s->f, gc, x, y, w, h); + XSetFillStyle (s->display, gc, FillSolid); + } + else +#endif + { + pgtk_fill_rectangle(s->f, color, x, y, w, h); + } + + pgtk_end_cr_clip(s->f); + } + } + else if (!s->background_filled_p) + { + int background_width = s->background_width; + int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); + + /* Don't draw into left margin, fringe or scrollbar area + except for header line and mode line. */ + if (x < left_x && !s->row->mode_line_p) + { + background_width -= left_x - x; + x = left_x; + } + if (background_width > 0) + x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); + } + + s->background_filled_p = true; +} + +static void pgtk_draw_glyph_string(struct glyph_string *s) +{ + PGTK_TRACE("draw_glyph_string."); + PGTK_TRACE("draw_glyph_string: x=%d, y=%d, width=%d, height=%d.", + s->x, s->y, s->width, s->height); + + bool relief_drawn_p = false; + + /* If S draws into the background of its successors, draw the + background of the successors first so that S can draw into it. + This makes S->next use XDrawString instead of XDrawImageString. */ + if (s->next && s->right_overhang && !s->for_overlaps) + { + int width; + struct glyph_string *next; + + for (width = 0, next = s->next; + next && width < s->right_overhang; + width += next->width, next = next->next) + if (next->first_glyph->type != IMAGE_GLYPH) + { + cairo_t *cr = pgtk_begin_cr_clip(next->f); + PGTK_TRACE("pgtk_draw_glyph_string: 1."); + x_set_glyph_string_gc (next); + x_set_glyph_string_clipping (next, cr); + if (next->first_glyph->type == STRETCH_GLYPH) + x_draw_stretch_glyph_string (next); + else + x_draw_glyph_string_background (next, true); + next->num_clips = 0; + pgtk_end_cr_clip(next->f); + } + } + + /* Set up S->gc, set clipping and draw S. */ + PGTK_TRACE("pgtk_draw_glyph_string: 2."); + x_set_glyph_string_gc (s); + + cairo_t *cr = pgtk_begin_cr_clip(s->f); + + /* Draw relief (if any) in advance for char/composition so that the + glyph string can be drawn over it. */ + if (!s->for_overlaps + && s->face->box != FACE_NO_BOX + && (s->first_glyph->type == CHAR_GLYPH + || s->first_glyph->type == COMPOSITE_GLYPH)) + + { + PGTK_TRACE("pgtk_draw_glyph_string: 2.1."); + x_set_glyph_string_clipping (s, cr); + x_draw_glyph_string_background (s, true); + x_draw_glyph_string_box (s); + x_set_glyph_string_clipping (s, cr); + relief_drawn_p = true; + } + else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */ + && !s->clip_tail + && ((s->prev && s->prev->hl != s->hl && s->left_overhang) + || (s->next && s->next->hl != s->hl && s->right_overhang))) + /* We must clip just this glyph. left_overhang part has already + drawn when s->prev was drawn, and right_overhang part will be + drawn later when s->next is drawn. */ + PGTK_TRACE("pgtk_draw_glyph_string: 2.2."), + x_set_glyph_string_clipping_exactly (s, s, cr); + else + PGTK_TRACE("pgtk_draw_glyph_string: 2.3."), + x_set_glyph_string_clipping (s, cr); + + switch (s->first_glyph->type) + { + case IMAGE_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.4."); + x_draw_image_glyph_string (s); + break; + + case XWIDGET_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.5."); + x_draw_xwidget_glyph_string (s); + break; + + case STRETCH_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.6."); + x_draw_stretch_glyph_string (s); + break; + + case CHAR_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.7."); + if (s->for_overlaps) + s->background_filled_p = true; + else + x_draw_glyph_string_background (s, false); + x_draw_glyph_string_foreground (s); + break; + + case COMPOSITE_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.8."); + if (s->for_overlaps || (s->cmp_from > 0 + && ! s->first_glyph->u.cmp.automatic)) + s->background_filled_p = true; + else + x_draw_glyph_string_background (s, true); + x_draw_composite_glyph_string_foreground (s); + break; + + case GLYPHLESS_GLYPH: + PGTK_TRACE("pgtk_draw_glyph_string: 2.9."); + if (s->for_overlaps) + s->background_filled_p = true; + else + x_draw_glyph_string_background (s, true); + x_draw_glyphless_glyph_string_foreground (s); + break; + + default: + emacs_abort (); + } + + if (!s->for_overlaps) + { + /* Draw underline. */ + if (s->face->underline) + { + if (s->face->underline == FACE_UNDER_WAVE) + { + if (s->face->underline_defaulted_p) + x_draw_underwave (s, s->xgcv.foreground); + else + { + x_draw_underwave (s, s->face->underline_color); + } + } + else if (s->face->underline == FACE_UNDER_LINE) + { + unsigned long thickness, position; + int y; + + if (s->prev && s->prev->face->underline + && s->prev->face->underline == FACE_UNDER_LINE) + { + /* We use the same underline style as the previous one. */ + thickness = s->prev->underline_thickness; + position = s->prev->underline_position; + } + else + { + struct font *font = font_for_underline_metrics (s); + + /* Get the underline thickness. Default is 1 pixel. */ + if (font && font->underline_thickness > 0) + thickness = font->underline_thickness; + else + thickness = 1; + if (x_underline_at_descent_line) + position = (s->height - thickness) - (s->ybase - s->y); + else + { + /* Get the underline position. This is the recommended + vertical offset in pixels from the baseline to the top of + the underline. This is a signed value according to the + specs, and its default is + + ROUND ((maximum descent) / 2), with + ROUND(x) = floor (x + 0.5) */ + + if (x_use_underline_position_properties + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = (font->descent + 1) / 2; + else + position = underline_minimum_offset; + } + position = max (position, underline_minimum_offset); + } + /* Check the sanity of thickness and position. We should + avoid drawing underline out of the current line area. */ + if (s->y + s->height <= s->ybase + position) + position = (s->height - 1) - (s->ybase - s->y); + if (s->y + s->height < s->ybase + position + thickness) + thickness = (s->y + s->height) - (s->ybase + position); + s->underline_thickness = thickness; + s->underline_position = position; + y = s->ybase + position; + if (s->face->underline_defaulted_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, + s->x, y, s->width, thickness); + else + { + pgtk_fill_rectangle (s->f, s->face->underline_color, + s->x, y, s->width, thickness); + } + } + } + /* Draw overline. */ + if (s->face->overline_p) + { + unsigned long dy = 0, h = 1; + + if (s->face->overline_color_defaulted_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, s->y + dy, + s->width, h); + else + { + pgtk_fill_rectangle (s->f, s->face->overline_color, s->x, s->y + dy, + s->width, h); + } + } + + /* Draw strike-through. */ + if (s->face->strike_through_p) + { + /* Y-coordinate and height of the glyph string's first + glyph. We cannot use s->y and s->height because those + could be larger if there are taller display elements + (e.g., characters displayed with a larger font) in the + same glyph row. */ + int glyph_y = s->ybase - s->first_glyph->ascent; + int glyph_height = s->first_glyph->ascent + s->first_glyph->descent; + /* Strike-through width and offset from the glyph string's + top edge. */ + unsigned long h = 1; + unsigned long dy = (glyph_height - h) / 2; + + if (s->face->strike_through_color_defaulted_p) + pgtk_fill_rectangle (s->f, s->xgcv.foreground, s->x, glyph_y + dy, + s->width, h); + else + { + pgtk_fill_rectangle (s->f, s->face->strike_through_color, s->x, glyph_y + dy, + s->width, h); + } + } + + /* Draw relief if not yet drawn. */ + if (!relief_drawn_p && s->face->box != FACE_NO_BOX) + x_draw_glyph_string_box (s); + + if (s->prev) + { + struct glyph_string *prev; + + for (prev = s->prev; prev; prev = prev->prev) + if (prev->hl != s->hl + && prev->x + prev->width + prev->right_overhang > s->x) + { + /* As prev was drawn while clipped to its own area, we + must draw the right_overhang part using s->hl now. */ + enum draw_glyphs_face save = prev->hl; + + prev->hl = s->hl; + PGTK_TRACE("pgtk_draw_glyph_string: 3."); + x_set_glyph_string_gc (prev); + cairo_save(cr); + x_set_glyph_string_clipping_exactly (s, prev, cr); + if (prev->first_glyph->type == CHAR_GLYPH) + x_draw_glyph_string_foreground (prev); + else + x_draw_composite_glyph_string_foreground (prev); + prev->hl = save; + prev->num_clips = 0; + cairo_restore(cr); + } + } + + if (s->next) + { + struct glyph_string *next; + + for (next = s->next; next; next = next->next) + if (next->hl != s->hl + && next->x - next->left_overhang < s->x + s->width) + { + /* As next will be drawn while clipped to its own area, + we must draw the left_overhang part using s->hl now. */ + enum draw_glyphs_face save = next->hl; + + next->hl = s->hl; + PGTK_TRACE("pgtk_draw_glyph_string: 4."); + x_set_glyph_string_gc (next); + cairo_save(cr); + x_set_glyph_string_clipping_exactly (s, next, cr); + if (next->first_glyph->type == CHAR_GLYPH) + x_draw_glyph_string_foreground (next); + else + x_draw_composite_glyph_string_foreground (next); + cairo_restore(cr); + next->hl = save; + next->num_clips = 0; + next->clip_head = s->next; + } + } + } + + /* Reset clipping. */ + pgtk_end_cr_clip(s->f); + s->num_clips = 0; +} + +/* RIF: Define cursor CURSOR on frame F. */ + +static void +pgtk_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) +{ + if (!f->pointer_invisible + && FRAME_X_OUTPUT(f)->current_cursor != cursor) + gdk_window_set_cursor(gtk_widget_get_window(FRAME_GTK_WIDGET(f)), cursor); + FRAME_X_OUTPUT(f)->current_cursor = cursor; +} + +static void pgtk_after_update_window_line(struct window *w, struct glyph_row *desired_row) +{ + PGTK_TRACE("after_update_window_line."); + + struct frame *f; + int width, height; + + /* begin copy from other terms */ + eassert (w); + + if (!desired_row->mode_line_p && !w->pseudo_window_p) + desired_row->redraw_fringe_bitmaps_p = 1; + + /* When a window has disappeared, make sure that no rest of + full-width rows stays visible in the internal border. */ + if (windows_or_buffers_changed + && desired_row->full_width_p + && (f = XFRAME (w->frame), + width = FRAME_INTERNAL_BORDER_WIDTH (f), + width != 0) + && (height = desired_row->visible_height, + height > 0)) + { + int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); + + block_input (); + pgtk_clear_frame_area (f, 0, y, width, height); + pgtk_clear_frame_area (f, + FRAME_PIXEL_WIDTH (f) - width, + y, width, height); + unblock_input (); + } +} + +static void pgtk_clear_frame_area(struct frame *f, int x, int y, int width, int height) +{ + PGTK_TRACE("clear_frame_area."); + pgtk_clear_area (f, x, y, width, height); +} + +/* Draw a hollow box cursor on window W in glyph row ROW. */ + +static void +x_draw_hollow_cursor (struct window *w, struct glyph_row *row) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + int x, y, wd, h; + struct glyph *cursor_glyph; + + /* Get the glyph the cursor is on. If we can't tell because + the current matrix is invalid or such, give up. */ + cursor_glyph = get_phys_cursor_glyph (w); + if (cursor_glyph == NULL) + return; + + /* Compute frame-relative coordinates for phys cursor. */ + get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); + wd = w->phys_cursor_width - 1; + + /* The foreground of cursor_gc is typically the same as the normal + background color, which can cause the cursor box to be invisible. */ + cairo_t *cr = pgtk_begin_cr_clip(f); + pgtk_set_cr_source_with_color(f, FRAME_X_OUTPUT(f)->cursor_color); + + /* When on R2L character, show cursor at the right edge of the + glyph, unless the cursor box is as wide as the glyph or wider + (the latter happens when x-stretch-cursor is non-nil). */ + if ((cursor_glyph->resolved_level & 1) != 0 + && cursor_glyph->pixel_width > wd) + { + x += cursor_glyph->pixel_width - wd; + if (wd > 0) + wd -= 1; + } + /* Set clipping, draw the rectangle, and reset clipping again. */ + pgtk_clip_to_row (w, row, TEXT_AREA, cr); + pgtk_draw_rectangle (f, FRAME_X_OUTPUT(f)->cursor_color, x, y, wd, h - 1); + pgtk_end_cr_clip(f); +} + +/* Draw a bar cursor on window W in glyph row ROW. + + Implementation note: One would like to draw a bar cursor with an + angle equal to the one given by the font property XA_ITALIC_ANGLE. + Unfortunately, I didn't find a font yet that has this property set. + --gerd. */ + +static void +x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text_cursor_kinds kind) +{ + struct frame *f = XFRAME (w->frame); + struct glyph *cursor_glyph; + + /* If cursor is out of bounds, don't draw garbage. This can happen + in mini-buffer windows when switching between echo area glyphs + and mini-buffer. */ + cursor_glyph = get_phys_cursor_glyph (w); + if (cursor_glyph == NULL) + return; + + /* Experimental avoidance of cursor on xwidget. */ + if (cursor_glyph->type == XWIDGET_GLYPH) + return; + + /* If on an image, draw like a normal cursor. That's usually better + visible than drawing a bar, esp. if the image is large so that + the bar might not be in the window. */ + if (cursor_glyph->type == IMAGE_GLYPH) + { + struct glyph_row *r; + r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); + draw_phys_cursor_glyph (w, r, DRAW_CURSOR); + } + else + { + struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); + unsigned long color; + + cairo_t *cr = pgtk_begin_cr_clip(f); + + /* If the glyph's background equals the color we normally draw + the bars cursor in, the bar cursor in its normal color is + invisible. Use the glyph's foreground color instead in this + case, on the assumption that the glyph's colors are chosen so + that the glyph is legible. */ + if (face->background == FRAME_X_OUTPUT(f)->cursor_color) + color = face->foreground; + else + color = FRAME_X_OUTPUT(f)->cursor_color; + + pgtk_clip_to_row (w, row, TEXT_AREA, cr); + + if (kind == BAR_CURSOR) + { + int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + + if (width < 0) + width = FRAME_CURSOR_WIDTH (f); + width = min (cursor_glyph->pixel_width, width); + + w->phys_cursor_width = width; + + /* If the character under cursor is R2L, draw the bar cursor + on the right of its glyph, rather than on the left. */ + if ((cursor_glyph->resolved_level & 1) != 0) + x += cursor_glyph->pixel_width - width; + + pgtk_fill_rectangle (f, color, x, + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), + width, row->height); + } + else /* HBAR_CURSOR */ + { + int dummy_x, dummy_y, dummy_h; + int x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + + if (width < 0) + width = row->height; + + width = min (row->height, width); + + get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x, + &dummy_y, &dummy_h); + + if ((cursor_glyph->resolved_level & 1) != 0 + && cursor_glyph->pixel_width > w->phys_cursor_width - 1) + x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; + pgtk_fill_rectangle (f, color, x, + WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + + row->height - width), + w->phys_cursor_width - 1, width); + } + + pgtk_end_cr_clip(f); + } +} + +/* RIF: Draw cursor on window W. */ + +static void +pgtk_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, + int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) +{ + PGTK_TRACE("draw_window_cursor: %d, %d, %d, %d, %d, %d.", + x, y, cursor_type, cursor_width, on_p, active_p); + struct frame *f = XFRAME (WINDOW_FRAME (w)); + + if (on_p) + { + w->phys_cursor_type = cursor_type; + w->phys_cursor_on_p = true; + + if (glyph_row->exact_window_width_line_p + && (glyph_row->reversed_p + ? (w->phys_cursor.hpos < 0) + : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]))) + { + glyph_row->cursor_in_fringe_p = true; + draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p); + } + else + { + switch (cursor_type) + { + case HOLLOW_BOX_CURSOR: + x_draw_hollow_cursor (w, glyph_row); + break; + + case FILLED_BOX_CURSOR: + draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); + break; + + case BAR_CURSOR: + x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); + break; + + case HBAR_CURSOR: + x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); + break; + + case NO_CURSOR: + w->phys_cursor_width = 0; + break; + + default: + emacs_abort (); + } + } + +#ifdef HAVE_X_I18N + if (w == XWINDOW (f->selected_window)) + if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition)) + xic_set_preeditarea (w, x, y); +#endif + } + + gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); +} + +static void +pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, cairo_rectangle_t *dst_rect) +{ + PGTK_TRACE ("pgtk_copy_bits: %dx%d+%d+%d -> %dx%d+%d+%d", + (int) src_rect->width, + (int) src_rect->height, + (int) src_rect->x, + (int) src_rect->y, + (int) dst_rect->width, + (int) dst_rect->height, + (int) dst_rect->x, + (int) dst_rect->y); + + cairo_t *cr; + cairo_surface_t *surface; /* temporary surface */ + + surface = cairo_surface_create_similar(FRAME_CR_SURFACE(f), CAIRO_CONTENT_COLOR_ALPHA, + (int) src_rect->width, + (int) src_rect->height); + + cr = cairo_create(surface); + cairo_set_source_surface(cr, FRAME_CR_SURFACE(f), -src_rect->x, -src_rect->y); + cairo_rectangle(cr, 0, 0, src_rect->width, src_rect->height); + cairo_clip(cr); + cairo_paint(cr); + cairo_destroy(cr); + + cr = pgtk_begin_cr_clip(f); + cairo_set_source_surface(cr, surface, dst_rect->x, dst_rect->y); + cairo_rectangle(cr, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height); + cairo_clip(cr); + cairo_paint(cr); + pgtk_end_cr_clip(f); + + cairo_surface_destroy(surface); +} + +/* Scroll part of the display as described by RUN. */ + +static void +pgtk_scroll_run (struct window *w, struct run *run) +{ + struct frame *f = XFRAME (w->frame); + int x, y, width, height, from_y, to_y, bottom_y; + + /* Get frame-relative bounding box of the text display area of W, + without mode lines. Include in this box the left and right + fringe of W. */ + window_box (w, ANY_AREA, &x, &y, &width, &height); + + from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); + to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); + bottom_y = y + height; + + if (to_y < from_y) + { + /* Scrolling up. Make sure we don't copy part of the mode + line at the bottom. */ + if (from_y + run->height > bottom_y) + height = bottom_y - from_y; + else + height = run->height; + } + else + { + /* Scrolling down. Make sure we don't copy over the mode line. + at the bottom. */ + if (to_y + run->height > bottom_y) + height = bottom_y - to_y; + else + height = run->height; + } + + block_input (); + + /* Cursor off. Will be switched on again in x_update_window_end. */ + x_clear_cursor (w); + + { + cairo_rectangle_t src_rect = { x, from_y, width, height }; + cairo_rectangle_t dst_rect = { x, to_y, width, height }; + pgtk_copy_bits (f, &src_rect , &dst_rect); + } + + unblock_input (); +} + +/*********************************************************************** + Starting and ending an update + ***********************************************************************/ + +/* Start an update of frame F. This function is installed as a hook + for update_begin, i.e. it is called when update_begin is called. + This function is called prior to calls to x_update_window_begin for + each window being updated. Currently, there is nothing to do here + because all interesting stuff is done on a window basis. */ + +static void +pgtk_update_begin (struct frame *f) +{ + if (! NILP (tip_frame) && XFRAME (tip_frame) == f + && ! FRAME_VISIBLE_P (f)) + return; + + if (! FRAME_CR_SURFACE (f)) + { + int width = FRAME_PIXEL_WIDTH (f); + int height = FRAME_PIXEL_HEIGHT (f); + + if (width > 0 && height > 0) + { + block_input(); + FRAME_CR_SURFACE (f) = cairo_image_surface_create + (CAIRO_FORMAT_ARGB32, width, height); + unblock_input(); + } + } + + pgtk_clear_under_internal_border (f); +} + +/* Start update of window W. */ + +static void +pgtk_update_window_begin (struct window *w) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + + w->output_cursor = w->cursor; + + block_input (); + + if (f == hlinfo->mouse_face_mouse_frame) + { + /* Don't do highlighting for mouse motion during the update. */ + hlinfo->mouse_face_defer = true; + + /* If F needs to be redrawn, simply forget about any prior mouse + highlighting. */ + if (FRAME_GARBAGED_P (f)) + hlinfo->mouse_face_window = Qnil; + } + + unblock_input (); +} + + +/* Draw a vertical window border from (x,y0) to (x,y1) */ + +static void +pgtk_draw_vertical_window_border (struct window *w, int x, int y0, int y1) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face; + cairo_t *cr; + + cr = pgtk_begin_cr_clip (f); + + face = FACE_FROM_ID_OR_NULL (f, VERTICAL_BORDER_FACE_ID); + if (face) + pgtk_set_cr_source_with_color (f, face->foreground); + + cairo_rectangle (cr, x, y0, 1, y1 - y0); + cairo_fill (cr); + + pgtk_end_cr_clip (f); +} + +/* Draw a window divider from (x0,y0) to (x1,y1) */ + +static void +pgtk_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1) +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FACE_ID); + struct face *face_first + = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID); + struct face *face_last + = FACE_FROM_ID_OR_NULL (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID); + unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f); + unsigned long color_first = (face_first + ? face_first->foreground + : FRAME_FOREGROUND_PIXEL (f)); + unsigned long color_last = (face_last + ? face_last->foreground + : FRAME_FOREGROUND_PIXEL (f)); + cairo_t *cr = pgtk_begin_cr_clip (f); + + if (y1 - y0 > x1 - x0 && x1 - x0 > 2) + /* Vertical. */ + { + pgtk_set_cr_source_with_color (f, color_first); + cairo_rectangle (cr, x0, y0, 1, y1 - y0); + cairo_fill(cr); + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x0 + 1, y0, x1 - x0 - 2, y1 - y0); + cairo_fill(cr); + pgtk_set_cr_source_with_color (f, color_last); + cairo_rectangle (cr, x1 - 1, y0, 1, y1 - y0); + cairo_fill(cr); + } + else if (x1 - x0 > y1 - y0 && y1 - y0 > 3) + /* Horizontal. */ + { + pgtk_set_cr_source_with_color (f, color_first); + cairo_rectangle (cr, x0, y0, x1 - x0, 1); + cairo_fill(cr); + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x0, y0 + 1, x1 - x0, y1 - y0 - 2); + cairo_fill(cr); + pgtk_set_cr_source_with_color (f, color_last); + cairo_rectangle (cr, x0, y1 - 1, x1 - x0, 1); + cairo_fill(cr); + } + else + { + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x0, y0, x1 - x0, y1 - y0); + cairo_fill(cr); + } + + pgtk_end_cr_clip (f); +} + +/* End update of window W. + + Draw vertical borders between horizontally adjacent windows, and + display W's cursor if CURSOR_ON_P is non-zero. + + MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing + glyphs in mouse-face were overwritten. In that case we have to + make sure that the mouse-highlight is properly redrawn. + + W may be a menu bar pseudo-window in case we don't have X toolkit + support. Such windows don't have a cursor, so don't display it + here. */ + +static void +pgtk_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) +{ + if (!w->pseudo_window_p) + { + block_input (); + + if (cursor_on_p) + display_and_set_cursor (w, true, + w->output_cursor.hpos, w->output_cursor.vpos, + w->output_cursor.x, w->output_cursor.y); + + if (draw_window_fringes (w, true)) + { + if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) + x_draw_right_divider (w); + else + x_draw_vertical_border (w); + } + + unblock_input (); + } + + /* If a row with mouse-face was overwritten, arrange for + XTframe_up_to_date to redisplay the mouse highlight. */ + if (mouse_face_overwritten_p) + { + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); + + hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; + hlinfo->mouse_face_window = Qnil; + } +} + +/* End update of frame F. This function is installed as a hook in + update_end. */ + +static void +pgtk_update_end (struct frame *f) +{ + /* Mouse highlight may be displayed again. */ + MOUSE_HL_INFO (f)->mouse_face_defer = false; +} + +/* Return the current position of the mouse. + *FP should be a frame which indicates which display to ask about. + + If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW, + and *PART to the frame, window, and scroll bar part that the mouse + is over. Set *X and *Y to the portion and whole of the mouse's + position on the scroll bar. + + If the mouse movement started elsewhere, set *FP to the frame the + mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell + the mouse is over. + + Set *TIMESTAMP to the server time-stamp for the time at which the mouse + was at this position. + + Don't store anything if we don't have a valid set of values to report. + + This clears the mouse_moved flag, so we can wait for the next mouse + movement. */ + +static void +pgtk_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, + enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, + Time *timestamp) +{ + struct frame *f1; + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); + int win_x, win_y; + GdkSeat *seat; + GdkDevice *device; + + block_input (); + + Lisp_Object frame, tail; + + /* Clear the mouse-moved flag for every frame on this display. */ + FOR_EACH_FRAME (tail, frame) + if (FRAME_PGTK_P (XFRAME (frame)) + && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp)) + XFRAME (frame)->mouse_moved = false; + + dpyinfo->last_mouse_scroll_bar = NULL; + + seat = gdk_display_get_default_seat(dpyinfo->gdpy); + device = gdk_seat_get_pointer(seat); + + if (x_mouse_grabbed (dpyinfo)) { + GdkWindow *win; + GdkModifierType mask; + /* get x, y relative to edit window of f1. */ + f1 = dpyinfo->last_mouse_frame; + win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); + win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); + } else { + GdkWindow *win; + GdkModifierType mask; + /* 1. get frame where the pointer is on. */ + win = gtk_widget_get_window(FRAME_GTK_WIDGET(*fp)); + win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); + if (win != NULL) + f1 = pgtk_any_window_to_frame(win); + else + f1 = SELECTED_FRAME(); + + /* 2. get x, y relative to edit window of the frame. */ + win = gtk_widget_get_window(FRAME_GTK_WIDGET(f1)); + win = gdk_window_get_device_position(win, device, &win_x, &win_y, &mask); + } + + if (f1 != NULL) { + dpyinfo = FRAME_DISPLAY_INFO (f1); + remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph); + dpyinfo->last_mouse_glyph_frame = f1; + + *bar_window = Qnil; + *part = 0; + *fp = f1; + XSETINT (*x, win_x); + XSETINT (*y, win_y); + *timestamp = dpyinfo->last_mouse_movement_time; + } + + unblock_input (); +} + +/* Fringe bitmaps. */ + +static int max_fringe_bmp = 0; +static cairo_pattern_t **fringe_bmp = 0; + +static void +pgtk_define_fringe_bitmap (int which, unsigned short *bits, int h, int wd) +{ + int i, stride; + cairo_surface_t *surface; + unsigned char *data; + cairo_pattern_t *pattern; + + if (which >= max_fringe_bmp) + { + i = max_fringe_bmp; + max_fringe_bmp = which + 20; + fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *)); + while (i < max_fringe_bmp) + fringe_bmp[i++] = 0; + } + + block_input (); + + surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h); + stride = cairo_image_surface_get_stride (surface); + data = cairo_image_surface_get_data (surface); + + for (i = 0; i < h; i++) + { + *((unsigned short *) data) = bits[i]; + data += stride; + } + + cairo_surface_mark_dirty (surface); + pattern = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy (surface); + + unblock_input (); + + fringe_bmp[which] = pattern; +} + +static void +pgtk_destroy_fringe_bitmap (int which) +{ + if (which >= max_fringe_bmp) + return; + + if (fringe_bmp[which]) + { + block_input (); + cairo_pattern_destroy (fringe_bmp[which]); + unblock_input (); + } + fringe_bmp[which] = 0; +} + +static void +pgtk_clip_to_row (struct window *w, struct glyph_row *row, + enum glyph_row_area area, cairo_t *cr) +{ + int window_x, window_y, window_width; + cairo_rectangle_int_t rect; + + window_box (w, area, &window_x, &window_y, &window_width, 0); + + rect.x = window_x; + rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); + rect.y = max (rect.y, window_y); + rect.width = window_width; + rect.height = row->visible_height; + + cairo_rectangle(cr, rect.x, rect.y, rect.width, rect.height); + cairo_clip(cr); +} + +static void +pgtk_cr_draw_image (struct frame *f, GC gc, cairo_pattern_t *image, + int src_x, int src_y, int width, int height, + int dest_x, int dest_y, bool overlay_p) +{ + cairo_t *cr; + cairo_matrix_t matrix; + cairo_surface_t *surface; + cairo_format_t format; + + PGTK_TRACE("pgtk_cr_draw_image: 0: %d,%d,%d,%d,%d,%d,%d.", src_x, src_y, width, height, dest_x, dest_y, overlay_p); + cr = pgtk_begin_cr_clip (f); + if (overlay_p) + cairo_rectangle (cr, dest_x, dest_y, width, height); + else + { + pgtk_set_cr_source_with_gc_background (f, gc); + cairo_rectangle (cr, dest_x, dest_y, width, height); + cairo_fill_preserve (cr); + } + cairo_clip (cr); + cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y); + cairo_pattern_set_matrix (image, &matrix); + cairo_pattern_get_surface (image, &surface); + format = cairo_image_surface_get_format (surface); + if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1) + { + PGTK_TRACE("other format."); + cairo_set_source (cr, image); + cairo_fill (cr); + } + else + { + if (format == CAIRO_FORMAT_A8) + PGTK_TRACE("format A8."); + else if (format == CAIRO_FORMAT_A1) + PGTK_TRACE("format A1."); + else + PGTK_TRACE("format ??."); + pgtk_set_cr_source_with_gc_foreground (f, gc); + cairo_rectangle_list_t *rects = cairo_copy_clip_rectangle_list(cr); + PGTK_TRACE("rects:"); + PGTK_TRACE(" status: %u", rects->status); + PGTK_TRACE(" rectangles:"); + for (int i = 0; i < rects->num_rectangles; i++) { + PGTK_TRACE(" %fx%f+%f+%f", + rects->rectangles[i].width, + rects->rectangles[i].height, + rects->rectangles[i].x, + rects->rectangles[i].y); + } + cairo_rectangle_list_destroy(rects); + cairo_mask (cr, image); + } + pgtk_end_cr_clip (f); + PGTK_TRACE("pgtk_cr_draw_image: 9."); +} + +static void +pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fringe_bitmap_params *p) +{ + PGTK_TRACE("draw_fringe_bitmap."); + + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face = p->face; + + cairo_t *cr = pgtk_begin_cr_clip(f); + cairo_save(cr); + + /* Must clip because of partially visible lines. */ + pgtk_clip_to_row (w, row, ANY_AREA, cr); + + if (p->bx >= 0 && !p->overlay_p) + { + /* In case the same realized face is used for fringes and + for something displayed in the text (e.g. face `region' on + mono-displays, the fill style may have been changed to + FillSolid in x_draw_glyph_string_background. */ +#if 0 + if (face->stipple) + XSetFillStyle (display, face->gc, FillOpaqueStippled); + else +#endif + pgtk_set_cr_source_with_color(f, face->background); + + cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); + cairo_fill(cr); + } + + PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); + if (p->which && p->which < max_fringe_bmp) + { + XGCValues gcv; + + PGTK_TRACE("cursor_p=%d.", p->cursor_p); + PGTK_TRACE("overlay_p_p=%d.", p->overlay_p); + PGTK_TRACE("background=%08lx.", face->background); + PGTK_TRACE("cursor_color=%08lx.", FRAME_X_OUTPUT(f)->cursor_color); + PGTK_TRACE("foreground=%08lx.", face->foreground); + gcv.foreground = (p->cursor_p + ? (p->overlay_p ? face->background + : FRAME_X_OUTPUT(f)->cursor_color) + : face->foreground); + gcv.background = face->background; + pgtk_cr_draw_image (f, &gcv, fringe_bmp[p->which], 0, p->dh, + p->wd, p->h, p->x, p->y, p->overlay_p); + } + + cairo_restore(cr); +} + +static struct atimer *hourglass_atimer = NULL; +static int hourglass_enter_count = 0; + +static void hourglass_cb(struct atimer *timer) +{ + /*NOP*/ +} + +static void +pgtk_show_hourglass(struct frame *f) +{ + struct pgtk_output *x = FRAME_X_OUTPUT(f); + if (x->hourglass_widget != NULL) + gtk_widget_destroy(x->hourglass_widget); + x->hourglass_widget = gtk_event_box_new(); /* gtk_event_box is GDK_INPUT_ONLY. */ + gtk_widget_set_has_window(x->hourglass_widget, true); + gtk_fixed_put(GTK_FIXED(FRAME_GTK_WIDGET(f)), x->hourglass_widget, 0, 0); + gtk_widget_show(x->hourglass_widget); + gtk_widget_set_size_request(x->hourglass_widget, 30000, 30000); + gdk_window_raise(gtk_widget_get_window(x->hourglass_widget)); + gdk_window_set_cursor(gtk_widget_get_window(x->hourglass_widget), x->hourglass_cursor); + + /* For cursor animation, we receive signals, set pending_signals, and dispatch. */ + if (hourglass_enter_count++ == 0) { + struct timespec ts = make_timespec(0, 50 * 1000 * 1000); + if (hourglass_atimer != NULL) + cancel_atimer(hourglass_atimer); + hourglass_atimer = start_atimer(ATIMER_CONTINUOUS, ts, hourglass_cb, NULL); + } + + /* Cursor frequently stops animation. gtk's bug? */ +} + +static void +pgtk_hide_hourglass(struct frame *f) +{ + struct pgtk_output *x = FRAME_X_OUTPUT(f); + if (--hourglass_enter_count == 0) { + if (hourglass_atimer != NULL) { + cancel_atimer(hourglass_atimer); + hourglass_atimer = NULL; + } + } + if (x->hourglass_widget != NULL) { + gtk_widget_destroy(x->hourglass_widget); + x->hourglass_widget = NULL; + } +} + +/* Flushes changes to display. */ +static void +pgtk_flush_display (struct frame *f) +{ + block_input (); + gdk_flush(); + unblock_input (); +} + +extern frame_parm_handler pgtk_frame_parm_handlers[]; + +static struct redisplay_interface pgtk_redisplay_interface = +{ + pgtk_frame_parm_handlers, + x_produce_glyphs, + x_write_glyphs, + x_insert_glyphs, + x_clear_end_of_line, + pgtk_scroll_run, + pgtk_after_update_window_line, + pgtk_update_window_begin, + pgtk_update_window_end, + pgtk_flush_display, + x_clear_window_mouse_face, + x_get_glyph_overhangs, + x_fix_overlapping_area, + pgtk_draw_fringe_bitmap, + pgtk_define_fringe_bitmap, + pgtk_destroy_fringe_bitmap, + pgtk_compute_glyph_string_overhangs, + pgtk_draw_glyph_string, + pgtk_define_frame_cursor, + pgtk_clear_frame_area, + pgtk_draw_window_cursor, + pgtk_draw_vertical_window_border, + pgtk_draw_window_divider, + NULL, // pgtk_shift_glyphs_for_insert, + pgtk_show_hourglass, + pgtk_hide_hourglass +}; + +static void +pgtk_redraw_scroll_bars (struct frame *f) +{ + PGTK_TRACE("pgtk_redraw_scroll_bars"); +} + +void +pgtk_clear_frame (struct frame *f) +/* -------------------------------------------------------------------------- + External (hook): Erase the entire frame + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("pgtk_clear_frame"); + /* comes on initial frame because we have + after-make-frame-functions = select-frame */ + if (!FRAME_DEFAULT_FACE (f)) + return; + + // mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); + + block_input (); + + pgtk_clear_area(f, 0, 0, FRAME_PIXEL_WIDTH(f), FRAME_PIXEL_HEIGHT(f)); + + /* as of 2006/11 or so this is now needed */ + pgtk_redraw_scroll_bars (f); + unblock_input (); +} + +/* Invert the middle quarter of the frame for .15 sec. */ + +static void +recover_from_visible_bell(struct atimer *timer) +{ + struct frame *f = timer->client_data; + + if (FRAME_X_OUTPUT(f)->cr_surface_visible_bell != NULL) { + cairo_surface_destroy(FRAME_X_OUTPUT(f)->cr_surface_visible_bell); + FRAME_X_OUTPUT(f)->cr_surface_visible_bell = NULL; + } + + if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) + FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + + gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); +} + +static void +pgtk_flash (struct frame *f) +{ + block_input (); + + { + cairo_surface_t *surface_orig = FRAME_CR_SURFACE(f); + + int width = cairo_image_surface_get_width(surface_orig); + int height = cairo_image_surface_get_height(surface_orig); + cairo_surface_t *surface = cairo_surface_create_similar(surface_orig, CAIRO_CONTENT_COLOR_ALPHA, + width, height); + + cairo_t *cr = cairo_create(surface); + cairo_set_source_surface(cr, surface_orig, 0, 0); + cairo_rectangle(cr, 0, 0, width, height); + cairo_clip(cr); + cairo_paint(cr); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); + +#define XFillRectangle(d, win, gc, x, y, w, h) \ + ( cairo_rectangle (cr, x, y, w, h), cairo_fill (cr) ) + + { + /* Get the height not including a menu bar widget. */ + int height = FRAME_PIXEL_HEIGHT (f); + /* Height of each line to flash. */ + int flash_height = FRAME_LINE_HEIGHT (f); + /* These will be the left and right margins of the rectangles. */ + int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); + int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); + int width = flash_right - flash_left; + + /* If window is tall, flash top and bottom line. */ + if (height > 3 * FRAME_LINE_HEIGHT (f)) + { + XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, + flash_left, + (FRAME_INTERNAL_BORDER_WIDTH (f) + + FRAME_TOP_MARGIN_HEIGHT (f)), + width, flash_height); + XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, + flash_left, + (height - flash_height + - FRAME_INTERNAL_BORDER_WIDTH (f)), + width, flash_height); + + } + else + /* If it is short, flash it all. */ + XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc, + flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), + width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); + + FRAME_X_OUTPUT(f)->cr_surface_visible_bell = surface; + gtk_widget_queue_draw(FRAME_GTK_WIDGET(f)); + + { + struct timespec delay = make_timespec (0, 50 * 1000 * 1000); + if (FRAME_X_OUTPUT(f)->atimer_visible_bell != NULL) { + cancel_atimer(FRAME_X_OUTPUT(f)->atimer_visible_bell); + FRAME_X_OUTPUT(f)->atimer_visible_bell = NULL; + } + FRAME_X_OUTPUT(f)->atimer_visible_bell = start_atimer(ATIMER_RELATIVE, delay, recover_from_visible_bell, f); + } + +#undef XFillRectangle + } + } + + unblock_input (); +} + +/* Make audible bell. */ + +static void +pgtk_ring_bell (struct frame *f) +{ + if (visible_bell) + { + pgtk_flash(f); + } + else + { + block_input (); + gtk_widget_error_bell(FRAME_GTK_WIDGET(f)); + unblock_input (); + } +} + +/* Read events coming from the X server. + Return as soon as there are no more events to be read. + + Return the number of characters stored into the buffer, + thus pretending to be `read' (except the characters we store + in the keyboard buffer can be multibyte, so are not necessarily + C chars). */ + +static int +pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit) +{ + PGTK_TRACE("pgtk_read_socket: enter."); + GMainContext *context; + bool context_acquired = false; + int count; + + count = evq_flush(hold_quit); + if (count > 0) { + PGTK_TRACE("pgtk_read_socket: leave(1)."); + return count; + } + + context = g_main_context_default (); + context_acquired = g_main_context_acquire (context); + + block_input (); + PGTK_TRACE("pgtk_read_socket: 3: errno=%d.", errno); + + if (context_acquired) { + PGTK_TRACE("pgtk_read_socket: 4.1: acquired."); + while (g_main_context_pending (context)) { + PGTK_TRACE("pgtk_read_socket: 4: dispatch..."); + g_main_context_dispatch (context); + PGTK_TRACE("pgtk_read_socket: 5: dispatch... done."); + } + } + + PGTK_TRACE("pgtk_read_socket: 7: errno=%d.", errno); + unblock_input (); + + if (context_acquired) + g_main_context_release (context); + + count = evq_flush(hold_quit); + if (count > 0) { + PGTK_TRACE("pgtk_read_socket: leave(2)."); + return count; + } + + PGTK_TRACE("pgtk_read_socket: leave(3)."); + return 0; +} + +int +pgtk_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, + struct timespec *timeout, sigset_t *sigmask) +{ + fd_set all_rfds, all_wfds; + struct timespec tmo; + struct timespec *tmop = timeout; + + GMainContext *context; + bool have_wfds = wfds != NULL; + GPollFD gfds_buf[128]; + GPollFD *gfds = gfds_buf; + int gfds_size = ARRAYELTS (gfds_buf); + int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; + bool context_acquired = false; + int i, nfds, tmo_in_millisec, must_free = 0; + bool need_to_dispatch; + + PGTK_TRACE("pgtk_select: enter."); + + if (event_q.nr >= 1) { + PGTK_TRACE("pgtk_select: raise."); + raise(SIGIO); + errno = EINTR; + return -1; + } + + context = g_main_context_default (); + context_acquired = g_main_context_acquire (context); + /* FIXME: If we couldn't acquire the context, we just silently proceed + because this function handles more than just glib file descriptors. + Note that, as implemented, this failure is completely silent: there is + no feedback to the caller. */ + + if (rfds) all_rfds = *rfds; + else FD_ZERO (&all_rfds); + if (wfds) all_wfds = *wfds; + else FD_ZERO (&all_wfds); + + n_gfds = (context_acquired + ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, + gfds, gfds_size) + : -1); + + if (gfds_size < n_gfds) + { + /* Avoid using SAFE_NALLOCA, as that implicitly refers to the + current thread. Using xnmalloc avoids thread-switching + problems here. */ + gfds = xnmalloc (n_gfds, sizeof *gfds); + must_free = 1; + gfds_size = n_gfds; + n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, + gfds, gfds_size); + } + + for (i = 0; i < n_gfds; ++i) + { + if (gfds[i].events & G_IO_IN) + { + FD_SET (gfds[i].fd, &all_rfds); + if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; + } + if (gfds[i].events & G_IO_OUT) + { + FD_SET (gfds[i].fd, &all_wfds); + if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; + have_wfds = true; + } + } + + if (must_free) + xfree (gfds); + + if (n_gfds >= 0 && tmo_in_millisec >= 0) + { + tmo = make_timespec (tmo_in_millisec / 1000, + 1000 * 1000 * (tmo_in_millisec % 1000)); + if (!timeout || timespec_cmp (tmo, *timeout) < 0) + tmop = &tmo; + } + + fds_lim = max_fds + 1; + nfds = thread_select (pselect, fds_lim, + &all_rfds, have_wfds ? &all_wfds : NULL, efds, + tmop, sigmask); + if (nfds < 0) + retval = nfds; + else if (nfds > 0) + { + for (i = 0; i < fds_lim; ++i) + { + if (FD_ISSET (i, &all_rfds)) + { + if (rfds && FD_ISSET (i, rfds)) ++retval; + else ++our_fds; + } + else if (rfds) + FD_CLR (i, rfds); + + if (have_wfds && FD_ISSET (i, &all_wfds)) + { + if (wfds && FD_ISSET (i, wfds)) ++retval; + else ++our_fds; + } + else if (wfds) + FD_CLR (i, wfds); + + if (efds && FD_ISSET (i, efds)) + ++retval; + } + } + + /* If Gtk+ is in use eventually gtk_main_iteration will be called, + unless retval is zero. */ + need_to_dispatch = retval == 0; + if (need_to_dispatch && context_acquired) + { + int pselect_errno = errno; + PGTK_TRACE("retval=%d.", retval); + PGTK_TRACE("need_to_dispatch=%d.", need_to_dispatch); + PGTK_TRACE("context_acquired=%d.", context_acquired); + PGTK_TRACE("pselect_errno=%d.", pselect_errno); + /* Prevent g_main_dispatch recursion, that would occur without + block_input wrapper, because event handlers call + unblock_input. Event loop recursion was causing Bug#15801. */ + block_input (); + while (g_main_context_pending (context)) { + PGTK_TRACE("dispatch..."); + g_main_context_dispatch (context); + PGTK_TRACE("dispatch... done."); + } + unblock_input (); + errno = pselect_errno; + } + + if (context_acquired) + g_main_context_release (context); + + /* To not have to recalculate timeout, return like this. */ + if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) + { + retval = -1; + errno = EINTR; + } + + PGTK_TRACE("pgtk_select: leave."); + return retval; +} + + +/* Lisp window being scrolled. Set when starting to interact with + a toolkit scroll bar, reset to nil when ending the interaction. */ + +static Lisp_Object window_being_scrolled; + +static void +pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part, + int portion, int whole, bool horizontal) +{ + union buffered_input_event inev; + + EVENT_INIT (inev.ie); + + inev.ie.kind = horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : SCROLL_BAR_CLICK_EVENT; + inev.ie.frame_or_window = window; + inev.ie.arg = Qnil; + inev.ie.timestamp = 0; + inev.ie.code = 0; + inev.ie.part = part; + inev.ie.x = make_fixnum(portion); + inev.ie.y = make_fixnum(whole); + inev.ie.modifiers = 0; + + evq_enqueue(&inev); +} + + +/* Scroll bar callback for GTK scroll bars. WIDGET is the scroll + bar widget. DATA is a pointer to the scroll_bar structure. */ + +static gboolean +xg_scroll_callback (GtkRange *range, + GtkScrollType scroll, + gdouble value, + gpointer user_data) +{ + int whole = 0, portion = 0; + struct scroll_bar *bar = user_data; + enum scroll_bar_part part = scroll_bar_nowhere; + GtkAdjustment *adj = GTK_ADJUSTMENT (gtk_range_get_adjustment (range)); + PGTK_TRACE("xg_scroll_callback:"); + + if (xg_ignore_gtk_scrollbar) return false; + PGTK_TRACE("xg_scroll_callback: not ignored."); + + PGTK_TRACE("xg_scroll_callback: scroll=%u.", scroll); + switch (scroll) + { + case GTK_SCROLL_JUMP: +#if 0 + /* Buttons 1 2 or 3 must be grabbed. */ + if (FRAME_DISPLAY_INFO (f)->grabbed != 0 + && FRAME_DISPLAY_INFO (f)->grabbed < (1 << 4)) +#endif + { + if (bar->horizontal) + { + part = scroll_bar_horizontal_handle; + whole = (int)(gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj)); + portion = min ((int)value, whole); + bar->dragging = portion; + } + else + { + part = scroll_bar_handle; + whole = gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj); + portion = min ((int)value, whole); + bar->dragging = portion; + } + } + break; + case GTK_SCROLL_STEP_BACKWARD: + part = (bar->horizontal + ? scroll_bar_left_arrow : scroll_bar_up_arrow); + bar->dragging = -1; + break; + case GTK_SCROLL_STEP_FORWARD: + part = (bar->horizontal + ? scroll_bar_right_arrow : scroll_bar_down_arrow); + bar->dragging = -1; + break; + case GTK_SCROLL_PAGE_BACKWARD: + part = (bar->horizontal + ? scroll_bar_before_handle : scroll_bar_above_handle); + bar->dragging = -1; + break; + case GTK_SCROLL_PAGE_FORWARD: + part = (bar->horizontal + ? scroll_bar_after_handle : scroll_bar_below_handle); + bar->dragging = -1; + break; + default: + break; + } + + PGTK_TRACE("xg_scroll_callback: part=%u, scroll_bar_nowhere=%d.", part, scroll_bar_nowhere); + if (part != scroll_bar_nowhere) + { + window_being_scrolled = bar->window; + pgtk_send_scroll_bar_event (bar->window, part, portion, whole, + bar->horizontal); + } + + return false; +} + +/* Callback for button release. Sets dragging to -1 when dragging is done. */ + +static gboolean +xg_end_scroll_callback (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + struct scroll_bar *bar = user_data; + PGTK_TRACE("xg_end_scroll_callback:"); + bar->dragging = -1; + if (WINDOWP (window_being_scrolled)) + { + pgtk_send_scroll_bar_event (window_being_scrolled, + scroll_bar_end_scroll, 0, 0, bar->horizontal); + window_being_scrolled = Qnil; + } + + return false; +} + +#define SCROLL_BAR_NAME "verticalScrollBar" +#define SCROLL_BAR_HORIZONTAL_NAME "horizontalScrollBar" + +/* Create the widget for scroll bar BAR on frame F. Record the widget + and X window of the scroll bar in BAR. */ + +static void +x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) +{ + const char *scroll_bar_name = SCROLL_BAR_NAME; + + block_input (); + xg_create_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback), + G_CALLBACK (xg_end_scroll_callback), + scroll_bar_name); + unblock_input (); +} + +static void +x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) +{ + const char *scroll_bar_name = SCROLL_BAR_HORIZONTAL_NAME; + + block_input (); + xg_create_horizontal_scroll_bar (f, bar, G_CALLBACK (xg_scroll_callback), + G_CALLBACK (xg_end_scroll_callback), + scroll_bar_name); + unblock_input (); +} + +/* Set the thumb size and position of scroll bar BAR. We are currently + displaying PORTION out of a whole WHOLE, and our position POSITION. */ + +static void +x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) +{ + xg_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); +} + +static void +x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) +{ + xg_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole); +} + + + +/* Create a scroll bar and return the scroll bar vector for it. W is + the Emacs window on which to create the scroll bar. TOP, LEFT, + WIDTH and HEIGHT are the pixel coordinates and dimensions of the + scroll bar. */ + +static struct scroll_bar * +x_scroll_bar_create (struct window *w, int top, int left, + int width, int height, bool horizontal) +{ + struct frame *f = XFRAME (w->frame); + struct scroll_bar *bar + = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, prev, PVEC_OTHER); + Lisp_Object barobj; + + block_input (); + + if (horizontal) + x_create_horizontal_toolkit_scroll_bar (f, bar); + else + x_create_toolkit_scroll_bar (f, bar); + + XSETWINDOW (bar->window, w); + bar->top = top; + bar->left = left; + bar->width = width; + bar->height = height; + bar->start = 0; + bar->end = 0; + bar->dragging = -1; + bar->horizontal = horizontal; + + /* Add bar to its frame's list of scroll bars. */ + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (!NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + + /* Map the window/widget. */ + { + if (horizontal) + xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, + left, width, max (height, 1)); + else + xg_update_scrollbar_pos (f, bar->x_window, top, + left, width, max (height, 1)); + } + + unblock_input (); + return bar; +} + +/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to + nil. */ + +static void +x_scroll_bar_remove (struct scroll_bar *bar) +{ + struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); + block_input (); + + xg_remove_scroll_bar (f, bar->x_window); + + /* Dissociate this scroll bar from its window. */ + if (bar->horizontal) + wset_horizontal_scroll_bar (XWINDOW (bar->window), Qnil); + else + wset_vertical_scroll_bar (XWINDOW (bar->window), Qnil); + + unblock_input (); +} + +/* Set the handle of the vertical scroll bar for WINDOW to indicate + that we are displaying PORTION characters out of a total of WHOLE + characters, starting at POSITION. If WINDOW has no scroll bar, + create one. */ + +static void +pgtk_set_vertical_scroll_bar (struct window *w, int portion, int whole, int position) +{ + struct frame *f = XFRAME (w->frame); + Lisp_Object barobj; + struct scroll_bar *bar; + int top, height, left, width; + int window_y, window_height; + + /* Get window dimensions. */ + window_box (w, ANY_AREA, 0, &window_y, 0, &window_height); + top = window_y; + height = window_height; + left = WINDOW_SCROLL_BAR_AREA_X (w); + width = WINDOW_SCROLL_BAR_AREA_WIDTH (w); + PGTK_TRACE("pgtk_set_vertical_scroll_bar: has_vertical_scroll_bar: %d", WINDOW_HAS_VERTICAL_SCROLL_BAR(w)); + PGTK_TRACE("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", WINDOW_CONFIG_SCROLL_BAR_WIDTH(w)); + PGTK_TRACE("pgtk_set_vertical_scroll_bar: scroll_bar_width: %d", w->scroll_bar_width); + PGTK_TRACE("pgtk_set_vertical_scroll_bar: config_scroll_bar_width: %d", FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w))); + PGTK_TRACE("pgtk_set_vertical_scroll_bar: %dx%d+%d+%d", width, height, left, top); + + /* Does the scroll bar exist yet? */ + if (NILP (w->vertical_scroll_bar)) + { + if (width > 0 && height > 0) + { + block_input (); + pgtk_clear_area (f, left, top, width, height); + unblock_input (); + } + + bar = x_scroll_bar_create (w, top, left, width, max (height, 1), false); + } + else + { + /* It may just need to be moved and resized. */ + unsigned int mask = 0; + + bar = XSCROLL_BAR (w->vertical_scroll_bar); + + block_input (); + + if (left != bar->left) + mask |= 1; + if (top != bar->top) + mask |= 1; + if (width != bar->width) + mask |= 1; + if (height != bar->height) + mask |= 1; + + /* Move/size the scroll bar widget. */ + if (mask) + { + /* Since toolkit scroll bars are smaller than the space reserved + for them on the frame, we have to clear "under" them. */ + if (width > 0 && height > 0) + pgtk_clear_area (f, left, top, width, height); + xg_update_scrollbar_pos (f, bar->x_window, top, + left, width, max (height, 1)); + } + + /* Remember new settings. */ + bar->left = left; + bar->top = top; + bar->width = width; + bar->height = height; + + unblock_input (); + } + + x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); + + XSETVECTOR (barobj, bar); + wset_vertical_scroll_bar (w, barobj); +} + + +static void +pgtk_set_horizontal_scroll_bar (struct window *w, int portion, int whole, int position) +{ + struct frame *f = XFRAME (w->frame); + Lisp_Object barobj; + struct scroll_bar *bar; + int top, height, left, width; + int window_x, window_width; + int pixel_width = WINDOW_PIXEL_WIDTH (w); + + /* Get window dimensions. */ + window_box (w, ANY_AREA, &window_x, 0, &window_width, 0); + left = window_x; + width = window_width; + top = WINDOW_SCROLL_BAR_AREA_Y (w); + height = WINDOW_SCROLL_BAR_AREA_HEIGHT (w); + + /* Does the scroll bar exist yet? */ + if (NILP (w->horizontal_scroll_bar)) + { + if (width > 0 && height > 0) + { + block_input (); + + /* Clear also part between window_width and + WINDOW_PIXEL_WIDTH. */ + pgtk_clear_area (f, left, top, pixel_width, height); + unblock_input (); + } + + bar = x_scroll_bar_create (w, top, left, width, height, true); + } + else + { + /* It may just need to be moved and resized. */ + unsigned int mask = 0; + + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + + block_input (); + + if (left != bar->left) + mask |= 1; + if (top != bar->top) + mask |= 1; + if (width != bar->width) + mask |= 1; + if (height != bar->height) + mask |= 1; + + /* Move/size the scroll bar widget. */ + if (mask) + { + /* Since toolkit scroll bars are smaller than the space reserved + for them on the frame, we have to clear "under" them. */ + if (width > 0 && height > 0) + pgtk_clear_area (f, + WINDOW_LEFT_EDGE_X (w), top, + pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); + xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left, + width, height); + } + + /* Remember new settings. */ + bar->left = left; + bar->top = top; + bar->width = width; + bar->height = height; + + unblock_input (); + } + + x_set_toolkit_horizontal_scroll_bar_thumb (bar, portion, position, whole); + + XSETVECTOR (barobj, bar); + wset_horizontal_scroll_bar (w, barobj); +} + +/* The following three hooks are used when we're doing a thorough + redisplay of the frame. We don't explicitly know which scroll bars + are going to be deleted, because keeping track of when windows go + away is a real pain - "Can you say set-window-configuration, boys + and girls?" Instead, we just assert at the beginning of redisplay + that *all* scroll bars are to be removed, and then save a scroll bar + from the fiery pit when we actually redisplay its window. */ + +/* Arrange for all scroll bars on FRAME to be removed at the next call + to `*judge_scroll_bars_hook'. A scroll bar may be spared if + `*redeem_scroll_bar_hook' is applied to its window before the judgment. */ + +static void +pgtk_condemn_scroll_bars (struct frame *frame) +{ + if (!NILP (FRAME_SCROLL_BARS (frame))) + { + if (!NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) + { + /* Prepend scrollbars to already condemned ones. */ + Lisp_Object last = FRAME_SCROLL_BARS (frame); + + while (!NILP (XSCROLL_BAR (last)->next)) + last = XSCROLL_BAR (last)->next; + + XSCROLL_BAR (last)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); + XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = last; + } + + fset_condemned_scroll_bars (frame, FRAME_SCROLL_BARS (frame)); + fset_scroll_bars (frame, Qnil); + } +} + + +/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle. + Note that WINDOW isn't necessarily condemned at all. */ + +static void +pgtk_redeem_scroll_bar (struct window *w) +{ + struct scroll_bar *bar; + Lisp_Object barobj; + struct frame *f; + + /* We can't redeem this window's scroll bar if it doesn't have one. */ + if (NILP (w->vertical_scroll_bar) && NILP (w->horizontal_scroll_bar)) + emacs_abort (); + + if (!NILP (w->vertical_scroll_bar) && WINDOW_HAS_VERTICAL_SCROLL_BAR (w)) + { + bar = XSCROLL_BAR (w->vertical_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->vertical_scroll_bar)) + /* It's not condemned. Everything's fine. */ + goto horizontal; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->vertical_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } + else + XSCROLL_BAR (bar->prev)->next = bar->next; + + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + } + + horizontal: + if (!NILP (w->horizontal_scroll_bar) && WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)) + { + bar = XSCROLL_BAR (w->horizontal_scroll_bar); + /* Unlink it from the condemned list. */ + f = XFRAME (WINDOW_FRAME (w)); + if (NILP (bar->prev)) + { + /* If the prev pointer is nil, it must be the first in one of + the lists. */ + if (EQ (FRAME_SCROLL_BARS (f), w->horizontal_scroll_bar)) + /* It's not condemned. Everything's fine. */ + return; + else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), + w->horizontal_scroll_bar)) + fset_condemned_scroll_bars (f, bar->next); + else + /* If its prev pointer is nil, it must be at the front of + one or the other! */ + emacs_abort (); + } + else + XSCROLL_BAR (bar->prev)->next = bar->next; + + if (! NILP (bar->next)) + XSCROLL_BAR (bar->next)->prev = bar->prev; + + bar->next = FRAME_SCROLL_BARS (f); + bar->prev = Qnil; + XSETVECTOR (barobj, bar); + fset_scroll_bars (f, barobj); + if (! NILP (bar->next)) + XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); + } +} + +/* Remove all scroll bars on FRAME that haven't been saved since the + last call to `*condemn_scroll_bars_hook'. */ + +static void +pgtk_judge_scroll_bars (struct frame *f) +{ + Lisp_Object bar, next; + + bar = FRAME_CONDEMNED_SCROLL_BARS (f); + + /* Clear out the condemned list now so we won't try to process any + more events on the hapless scroll bars. */ + fset_condemned_scroll_bars (f, Qnil); + + for (; ! NILP (bar); bar = next) + { + struct scroll_bar *b = XSCROLL_BAR (bar); + + x_scroll_bar_remove (b); + + next = b->next; + b->next = b->prev = Qnil; + } + + /* Now there should be no references to the condemned scroll bars, + and they should get garbage-collected. */ +} + +static void set_fullscreen_state(struct frame *f) +{ + GtkWindow *widget = GTK_WINDOW(FRAME_GTK_OUTER_WIDGET(f)); + switch (f->want_fullscreen) { + case FULLSCREEN_NONE: + PGTK_TRACE("pgtk_fullscreen_hook: none."); + gtk_window_unfullscreen(widget); + gtk_window_unmaximize(widget); + store_frame_param(f, Qfullscreen, Qnil); + break; + + case FULLSCREEN_BOTH: + PGTK_TRACE("pgtk_fullscreen_hook: both."); + gtk_window_unmaximize(widget); + gtk_window_fullscreen(widget); + store_frame_param(f, Qfullscreen, Qfullboth); + break; + + case FULLSCREEN_MAXIMIZED: + PGTK_TRACE("pgtk_fullscreen_hook: maximized."); + gtk_window_unfullscreen(widget); + gtk_window_maximize(widget); + store_frame_param(f, Qfullscreen, Qmaximized); + break; + + case FULLSCREEN_WIDTH: + case FULLSCREEN_HEIGHT: + PGTK_TRACE("pgtk_fullscreen_hook: width or height."); + /* Not supported by gtk. Ignore them.*/ + } + + f->want_fullscreen = FULLSCREEN_NONE; +} + +static void +pgtk_fullscreen_hook (struct frame *f) +{ + PGTK_TRACE("pgtk_fullscreen_hook:"); + if (FRAME_VISIBLE_P (f)) + { + block_input (); + set_fullscreen_state(f); + unblock_input (); + } +} + +static Lisp_Object +pgtk_menu_show (struct frame *f, int x, int y, int menuflags, + Lisp_Object title, const char **error_name) +{ + // not implemented. + return Qnil; +} + +/* This function is called when the last frame on a display is deleted. */ +void +pgtk_delete_terminal (struct terminal *terminal) +{ + struct pgtk_display_info *dpyinfo = terminal->display_info.pgtk; + + /* Protect against recursive calls. delete_frame in + delete_terminal calls us back when it deletes our last frame. */ + if (!terminal->name) + return; + + block_input (); + + /* Normally, the display is available... */ + if (dpyinfo->gdpy) + { + x_destroy_all_bitmaps (dpyinfo); + + xg_display_close (dpyinfo->gdpy); + + /* Do not close the connection here because it's already closed + by X(t)CloseDisplay (Bug#18403). */ + dpyinfo->gdpy = NULL; + } + + pgtk_delete_display (dpyinfo); + unblock_input (); +} + +/* Store F's background color into *BGCOLOR. */ +static void +pgtk_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor) +{ + bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f); + pgtk_query_color (f, bgcolor); +} + +static void +pgtk_free_pixmap (struct frame *_f, Emacs_Pixmap pixmap) +{ + if (pixmap) + { + xfree (pixmap->data); + xfree (pixmap); + } +} + +static struct terminal * +pgtk_create_terminal (struct pgtk_display_info *dpyinfo) +/* -------------------------------------------------------------------------- + Set up use of Gtk before we make the first connection. + -------------------------------------------------------------------------- */ +{ + struct terminal *terminal; + + terminal = create_terminal (output_pgtk, &pgtk_redisplay_interface); + + terminal->display_info.pgtk = dpyinfo; + dpyinfo->terminal = terminal; + + terminal->clear_frame_hook = pgtk_clear_frame; + terminal->ring_bell_hook = pgtk_ring_bell; + terminal->update_begin_hook = pgtk_update_begin; + terminal->update_end_hook = pgtk_update_end; + terminal->read_socket_hook = pgtk_read_socket; + // terminal->frame_up_to_date_hook = pgtk_frame_up_to_date; + terminal->mouse_position_hook = pgtk_mouse_position; + // terminal->frame_rehighlight_hook = pgtk_frame_rehighlight; + // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower; + terminal->fullscreen_hook = pgtk_fullscreen_hook; + terminal->menu_show_hook = pgtk_menu_show; + // terminal->popup_dialog_hook = pgtk_popup_dialog; + terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar; + terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar; + terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars; + terminal->redeem_scroll_bar_hook = pgtk_redeem_scroll_bar; + terminal->judge_scroll_bars_hook = pgtk_judge_scroll_bars; + terminal->delete_frame_hook = x_destroy_window; + terminal->delete_terminal_hook = pgtk_delete_terminal; + terminal->set_window_size_hook = pgtk_set_window_size; + terminal->query_colors = pgtk_query_colors; + terminal->get_focus_frame = x_get_focus_frame; + terminal->focus_frame_hook = pgtk_focus_frame; + terminal->set_frame_offset_hook = x_set_offset; + terminal->free_pixmap = pgtk_free_pixmap; + + /* Other hooks are NULL by default. */ + + return terminal; +} + +struct pgtk_window_is_of_frame_recursive_t { + GdkWindow *window; + bool result; +}; + +static void +pgtk_window_is_of_frame_recursive(GtkWidget *widget, gpointer data) +{ + struct pgtk_window_is_of_frame_recursive_t *datap = data; + + if (datap->result) + return; + + if (gtk_widget_get_window(widget) == datap->window) { + datap->result = true; + return; + } + + if (GTK_IS_CONTAINER(widget)) + gtk_container_foreach(GTK_CONTAINER(widget), pgtk_window_is_of_frame_recursive, datap); +} + +static bool +pgtk_window_is_of_frame(struct frame *f, GdkWindow *window) +{ + struct pgtk_window_is_of_frame_recursive_t data; + data.window = window; + data.result = false; + pgtk_window_is_of_frame_recursive(FRAME_GTK_OUTER_WIDGET(f), &data); + return data.result; +} + +/* Like x_window_to_frame but also compares the window with the widget's + windows. */ +static struct frame * +pgtk_any_window_to_frame (GdkWindow *window) +{ + Lisp_Object tail, frame; + struct frame *f, *found = NULL; + + if (window == NULL) + return NULL; + + FOR_EACH_FRAME (tail, frame) + { + if (found) + break; + f = XFRAME (frame); + if (FRAME_PGTK_P (f)) + { + if (pgtk_window_is_of_frame(f, window)) + found = f; + } + } + + return found; +} + +static gboolean +pgtk_handle_event(GtkWidget *widget, GdkEvent *event, gpointer *data) +{ +#ifdef PGTK_DEBUG + const char *type_name = G_OBJECT_TYPE_NAME(widget); + switch (event->type) { + case GDK_NOTHING: PGTK_TRACE("GDK_NOTHING"); break; + case GDK_DELETE: PGTK_TRACE("GDK_DELETE"); break; + case GDK_DESTROY: PGTK_TRACE("GDK_DESTROY"); break; + case GDK_EXPOSE: PGTK_TRACE("GDK_EXPOSE"); break; + case GDK_MOTION_NOTIFY: PGTK_TRACE("GDK_MOTION_NOTIFY"); break; + case GDK_BUTTON_PRESS: PGTK_TRACE("GDK_BUTTON_PRESS"); break; + case GDK_2BUTTON_PRESS: PGTK_TRACE("GDK_2BUTTON_PRESS"); break; + case GDK_3BUTTON_PRESS: PGTK_TRACE("GDK_3BUTTON_PRESS"); break; + case GDK_BUTTON_RELEASE: PGTK_TRACE("GDK_BUTTON_RELEASE"); break; + case GDK_KEY_PRESS: PGTK_TRACE("GDK_KEY_PRESS"); break; + case GDK_KEY_RELEASE: PGTK_TRACE("GDK_KEY_RELEASE"); break; + case GDK_ENTER_NOTIFY: PGTK_TRACE("GDK_ENTER_NOTIFY"); break; + case GDK_LEAVE_NOTIFY: PGTK_TRACE("GDK_LEAVE_NOTIFY"); break; + case GDK_FOCUS_CHANGE: PGTK_TRACE("GDK_FOCUS_CHANGE"); break; + case GDK_CONFIGURE: PGTK_TRACE("GDK_CONFIGURE"); break; + case GDK_MAP: PGTK_TRACE("GDK_MAP"); break; + case GDK_UNMAP: PGTK_TRACE("GDK_UNMAP"); break; + case GDK_PROPERTY_NOTIFY: PGTK_TRACE("GDK_PROPERTY_NOTIFY"); break; + case GDK_SELECTION_CLEAR: PGTK_TRACE("GDK_SELECTION_CLEAR"); break; + case GDK_SELECTION_REQUEST: PGTK_TRACE("GDK_SELECTION_REQUEST"); break; + case GDK_SELECTION_NOTIFY: PGTK_TRACE("GDK_SELECTION_NOTIFY"); break; + case GDK_PROXIMITY_IN: PGTK_TRACE("GDK_PROXIMITY_IN"); break; + case GDK_PROXIMITY_OUT: PGTK_TRACE("GDK_PROXIMITY_OUT"); break; + case GDK_DRAG_ENTER: PGTK_TRACE("GDK_DRAG_ENTER"); break; + case GDK_DRAG_LEAVE: PGTK_TRACE("GDK_DRAG_LEAVE"); break; + case GDK_DRAG_MOTION: PGTK_TRACE("GDK_DRAG_MOTION"); break; + case GDK_DRAG_STATUS: PGTK_TRACE("GDK_DRAG_STATUS"); break; + case GDK_DROP_START: PGTK_TRACE("GDK_DROP_START"); break; + case GDK_DROP_FINISHED: PGTK_TRACE("GDK_DROP_FINISHED"); break; + case GDK_CLIENT_EVENT: PGTK_TRACE("GDK_CLIENT_EVENT"); break; + case GDK_VISIBILITY_NOTIFY: PGTK_TRACE("GDK_VISIBILITY_NOTIFY"); break; + case GDK_SCROLL: PGTK_TRACE("GDK_SCROLL"); break; + case GDK_WINDOW_STATE: PGTK_TRACE("GDK_WINDOW_STATE"); break; + case GDK_SETTING: PGTK_TRACE("GDK_SETTING"); break; + case GDK_OWNER_CHANGE: PGTK_TRACE("GDK_OWNER_CHANGE"); break; + case GDK_GRAB_BROKEN: PGTK_TRACE("GDK_GRAB_BROKEN"); break; + case GDK_DAMAGE: PGTK_TRACE("GDK_DAMAGE"); break; + case GDK_TOUCH_BEGIN: PGTK_TRACE("GDK_TOUCH_BEGIN"); break; + case GDK_TOUCH_UPDATE: PGTK_TRACE("GDK_TOUCH_UPDATE"); break; + case GDK_TOUCH_END: PGTK_TRACE("GDK_TOUCH_END"); break; + case GDK_TOUCH_CANCEL: PGTK_TRACE("GDK_TOUCH_CANCEL"); break; + case GDK_TOUCHPAD_SWIPE: PGTK_TRACE("GDK_TOUCHPAD_SWIPE"); break; + case GDK_TOUCHPAD_PINCH: PGTK_TRACE("GDK_TOUCHPAD_PINCH"); break; + case GDK_PAD_BUTTON_PRESS: PGTK_TRACE("GDK_PAD_BUTTON_PRESS"); break; + case GDK_PAD_BUTTON_RELEASE: PGTK_TRACE("GDK_PAD_BUTTON_RELEASE"); break; + case GDK_PAD_RING: PGTK_TRACE("GDK_PAD_RING"); break; + case GDK_PAD_STRIP: PGTK_TRACE("GDK_PAD_STRIP"); break; + case GDK_PAD_GROUP_MODE: PGTK_TRACE("GDK_PAD_GROUP_MODE"); break; + default: PGTK_TRACE("GDK_EVENT %d", event->type); + } + PGTK_TRACE(" Widget is %s", type_name); +#endif + return FALSE; +} + +static void +pgtk_fill_rectangle(struct frame *f, unsigned long color, int x, int y, int width, int height) +{ + PGTK_TRACE("pgtk_fill_rectangle"); + cairo_t *cr; + cr = pgtk_begin_cr_clip (f); + pgtk_set_cr_source_with_color (f, color); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (f); +} + +void +pgtk_clear_under_internal_border (struct frame *f) +{ + PGTK_TRACE("pgtk_clear_under_internal_border"); + if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) + { + int border = FRAME_INTERNAL_BORDER_WIDTH (f); + int width = FRAME_PIXEL_WIDTH (f); + int height = FRAME_PIXEL_HEIGHT (f); + int margin = 0; + struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID); + + block_input (); + + if (face) + { + pgtk_fill_rectangle (f, color, 0, margin, width, border); + pgtk_fill_rectangle (f, color, 0, 0, border, height); + pgtk_fill_rectangle (f, color, width - border, 0, border, height); + pgtk_fill_rectangle (f, color, 0, height - border, width, border); + } + else + { + pgtk_clear_area (f, 0, 0, border, height); + pgtk_clear_area (f, 0, margin, width, border); + pgtk_clear_area (f, width - border, 0, border, height); + pgtk_clear_area (f, 0, height - border, width, border); + } + + unblock_input (); + } +} + +static void print_widget_tree_recursive(GtkWidget *w, gpointer user_data) +{ + const char *indent = user_data; + char buf[1024] = ""; + int len = 0; + len += sprintf(buf + len, "%s", indent); + len += sprintf(buf + len, "%p %s mapped:%d visible:%d", w, G_OBJECT_TYPE_NAME(w), gtk_widget_get_mapped(w), gtk_widget_get_visible(w)); + gint wd, hi; + gtk_widget_get_size_request(w, &wd, &hi); + len += sprintf(buf + len, " size_req:%dx%d", wd, hi); + GtkAllocation alloc; + gtk_widget_get_allocation(w, &alloc); + len += sprintf(buf + len, " alloc:%dx%d+%d+%d", alloc.width, alloc.height, alloc.x, alloc.y); + len += sprintf(buf + len, " haswin:%d", gtk_widget_get_has_window(w)); + len += sprintf(buf + len, " gdkwin:%p", gtk_widget_get_window(w)); + PGTK_TRACE("%s", buf); + + if (GTK_IS_CONTAINER(w)) { + strcpy(buf, indent); + strcat(buf, " "); + gtk_container_foreach(GTK_CONTAINER(w), print_widget_tree_recursive, buf); + } +} + +static void print_widget_tree(GtkWidget *w) +{ + char indent[1] = ""; + w = gtk_widget_get_toplevel(w); + print_widget_tree_recursive(w, indent); +} + +static gboolean +pgtk_handle_draw(GtkWidget *widget, cairo_t *cr, gpointer *data) +{ + struct frame *f; + + PGTK_TRACE("pgtk_handle_draw"); + + print_widget_tree(widget); + + GdkWindow *win = gtk_widget_get_window(widget); + + PGTK_TRACE(" win=%p", win); + if (win != NULL) { + cairo_surface_t *src = NULL; + f = pgtk_any_window_to_frame(win); + PGTK_TRACE(" f=%p", f); + if (f != NULL) { + src = FRAME_X_OUTPUT(f)->cr_surface_visible_bell; + if (src == NULL) + src = FRAME_CR_SURFACE(f); + } + PGTK_TRACE(" surface=%p", src); + if (src != NULL) { + PGTK_TRACE(" resized_p=%d", f->resized_p); + PGTK_TRACE(" garbaged=%d", f->garbaged); + PGTK_TRACE(" scroll_bar_width=%f", (double) PGTK_SCROLL_BAR_WIDTH(f)); + // PGTK_TRACE(" scroll_bar_adjust=%d", PGTK_SCROLL_BAR_ADJUST(f)); + PGTK_TRACE(" scroll_bar_cols=%d", FRAME_SCROLL_BAR_COLS(f)); + PGTK_TRACE(" column_width=%d", FRAME_COLUMN_WIDTH(f)); + cairo_set_source_surface(cr, src, 0, 0); + cairo_paint(cr); + } + } + return FALSE; +} + +static void size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer *user_data) +{ + PGTK_TRACE("size-alloc: %dx%d+%d+%d.", alloc->width, alloc->height, alloc->x, alloc->y); + + struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window(widget)); + if (f) { + PGTK_TRACE("%dx%d", alloc->width, alloc->height); + xg_frame_resized(f, alloc->width, alloc->height); + } +} + +int +pgtk_gtk_to_emacs_modifiers (int state) +{ + int mod_ctrl = ctrl_modifier; + int mod_meta = meta_modifier; + int mod_alt = alt_modifier; + int mod_hyper = hyper_modifier; + int mod_super = super_modifier; + Lisp_Object tem; + + tem = Fget (Vx_ctrl_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_ctrl = XFIXNUM (tem) & INT_MAX; + tem = Fget (Vx_alt_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_alt = XFIXNUM (tem) & INT_MAX; + tem = Fget (Vx_meta_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_meta = XFIXNUM (tem) & INT_MAX; + tem = Fget (Vx_hyper_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_hyper = XFIXNUM (tem) & INT_MAX; + tem = Fget (Vx_super_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_super = XFIXNUM (tem) & INT_MAX; + + return ( ((state & GDK_SHIFT_MASK) ? shift_modifier : 0) + | ((state & GDK_CONTROL_MASK) ? mod_ctrl : 0) + | ((state & GDK_META_MASK) ? mod_meta : 0) + | ((state & GDK_MOD1_MASK) ? mod_alt : 0) + | ((state & GDK_SUPER_MASK) ? mod_super : 0) + | ((state & GDK_HYPER_MASK) ? mod_hyper : 0)); +} + +static int +pgtk_emacs_to_gtk_modifiers (EMACS_INT state) +{ + EMACS_INT mod_ctrl = ctrl_modifier; + EMACS_INT mod_meta = meta_modifier; + EMACS_INT mod_alt = alt_modifier; + EMACS_INT mod_hyper = hyper_modifier; + EMACS_INT mod_super = super_modifier; + + Lisp_Object tem; + + tem = Fget (Vx_ctrl_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_ctrl = XFIXNUM (tem); + tem = Fget (Vx_alt_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_alt = XFIXNUM (tem); + tem = Fget (Vx_meta_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_meta = XFIXNUM (tem); + tem = Fget (Vx_hyper_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_hyper = XFIXNUM (tem); + tem = Fget (Vx_super_keysym, Qmodifier_value); + if (INTEGERP (tem)) mod_super = XFIXNUM (tem); + + + return ( ((state & mod_alt) ? GDK_MOD1_MASK : 0) + | ((state & mod_super) ? GDK_SUPER_MASK : 0) + | ((state & mod_hyper) ? GDK_HYPER_MASK : 0) + | ((state & shift_modifier) ? GDK_SHIFT_MASK : 0) + | ((state & mod_ctrl) ? GDK_CONTROL_MASK : 0) + | ((state & mod_meta) ? GDK_META_MASK : 0)); +} + +#define IsCursorKey(keysym) (0xff50 <= (keysym) && (keysym) < 0xff60) +#define IsMiscFunctionKey(keysym) (0xff60 <= (keysym) && (keysym) < 0xff6c) +#define IsKeypadKey(keysym) (0xff80 <= (keysym) && (keysym) < 0xffbe) +#define IsFunctionKey(keysym) (0xffbe <= (keysym) && (keysym) < 0xffe1) + +static gboolean key_press_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + struct coding_system coding; + union buffered_input_event inev; + ptrdiff_t nbytes = 0; + Mouse_HLInfo *hlinfo; + + USE_SAFE_ALLOCA; + + PGTK_TRACE("key_press_event"); + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + struct frame *f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + hlinfo = MOUSE_HL_INFO(f); + + /* If mouse-highlight is an integer, input clears out + mouse highlighting. */ + if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + { + clear_mouse_face (hlinfo); + hlinfo->mouse_face_hidden = true; + } + + if (f != 0) + { + guint keysym, orig_keysym; + /* al%imercury@uunet.uu.net says that making this 81 + instead of 80 fixed a bug whereby meta chars made + his Emacs hang. + + It seems that some version of XmbLookupString has + a bug of not returning XBufferOverflow in + status_return even if the input is too long to + fit in 81 bytes. So, we must prepare sufficient + bytes for copy_buffer. 513 bytes (256 chars for + two-byte character set) seems to be a fairly good + approximation. -- 2000.8.10 handa@etl.go.jp */ + unsigned char copy_buffer[513]; + unsigned char *copy_bufptr = copy_buffer; + int copy_bufsiz = sizeof (copy_buffer); + int modifiers; + Lisp_Object coding_system = Qlatin_1; + Lisp_Object c; + guint state = event->key.state; + + state |= pgtk_emacs_to_gtk_modifiers (extra_keyboard_modifiers); + modifiers = state; + + /* This will have to go some day... */ + + /* make_lispy_event turns chars into control chars. + Don't do it here because XLookupString is too eager. */ + state &= ~GDK_CONTROL_MASK; + state &= ~(GDK_META_MASK + | GDK_SUPER_MASK + | GDK_HYPER_MASK + | GDK_MOD1_MASK); + + nbytes = event->key.length; + if (nbytes > copy_bufsiz) + nbytes = copy_bufsiz; + memcpy(copy_bufptr, event->key.string, nbytes); + + keysym = event->key.keyval; + orig_keysym = keysym; + + /* Common for all keysym input events. */ + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (modifiers); + inev.ie.timestamp = event->key.time; + + /* First deal with keysyms which have defined + translations to characters. */ + if (keysym >= 32 && keysym < 128) + /* Avoid explicitly decoding each ASCII character. */ + { + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; + goto done; + } + + /* Keysyms directly mapped to Unicode characters. */ + if (keysym >= 0x01000000 && keysym <= 0x0110FFFF) + { + if (keysym < 0x01000080) + inev.ie.kind = ASCII_KEYSTROKE_EVENT; + else + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.code = keysym & 0xFFFFFF; + goto done; + } + + /* Now non-ASCII. */ + if (HASH_TABLE_P (Vpgtk_keysym_table) + && (c = Fgethash (make_fixnum (keysym), + Vpgtk_keysym_table, + Qnil), + FIXNATP (c))) + { + inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c)) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = XFIXNAT (c); + goto done; + } + + /* Random non-modifier sorts of keysyms. */ + if (((keysym >= GDK_KEY_BackSpace && keysym <= GDK_KEY_Escape) + || keysym == GDK_KEY_Delete +#ifdef GDK_KEY_ISO_Left_Tab + || (keysym >= GDK_KEY_ISO_Left_Tab + && keysym <= GDK_KEY_ISO_Enter) +#endif + || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */ + || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */ +#ifdef HPUX + /* This recognizes the "extended function + keys". It seems there's no cleaner way. + Test IsModifierKey to avoid handling + mode_switch incorrectly. */ + || (GDK_KEY_Select <= keysym && keysym < GDK_KEY_KP_Space) +#endif +#ifdef GDK_KEY_dead_circumflex + || orig_keysym == GDK_KEY_dead_circumflex +#endif +#ifdef GDK_KEY_dead_grave + || orig_keysym == GDK_KEY_dead_grave +#endif +#ifdef GDK_KEY_dead_tilde + || orig_keysym == GDK_KEY_dead_tilde +#endif +#ifdef GDK_KEY_dead_diaeresis + || orig_keysym == GDK_KEY_dead_diaeresis +#endif +#ifdef GDK_KEY_dead_macron + || orig_keysym == GDK_KEY_dead_macron +#endif +#ifdef GDK_KEY_dead_degree + || orig_keysym == GDK_KEY_dead_degree +#endif +#ifdef GDK_KEY_dead_acute + || orig_keysym == GDK_KEY_dead_acute +#endif +#ifdef GDK_KEY_dead_cedilla + || orig_keysym == GDK_KEY_dead_cedilla +#endif +#ifdef GDK_KEY_dead_breve + || orig_keysym == GDK_KEY_dead_breve +#endif +#ifdef GDK_KEY_dead_ogonek + || orig_keysym == GDK_KEY_dead_ogonek +#endif +#ifdef GDK_KEY_dead_caron + || orig_keysym == GDK_KEY_dead_caron +#endif +#ifdef GDK_KEY_dead_doubleacute + || orig_keysym == GDK_KEY_dead_doubleacute +#endif +#ifdef GDK_KEY_dead_abovedot + || orig_keysym == GDK_KEY_dead_abovedot +#endif + || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ + || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */ + /* Any "vendor-specific" key is ok. */ + || (orig_keysym & (1 << 28)) + || (keysym != GDK_KEY_VoidSymbol && nbytes == 0)) + && ! (event->key.is_modifier + /* The symbols from GDK_KEY_ISO_Lock + to GDK_KEY_ISO_Last_Group_Lock + don't have real modifiers but + should be treated similarly to + Mode_switch by Emacs. */ +#if defined GDK_KEY_ISO_Lock && defined GDK_KEY_ISO_Last_Group_Lock + || (GDK_KEY_ISO_Lock <= orig_keysym + && orig_keysym <= GDK_KEY_ISO_Last_Group_Lock) +#endif + )) + { + STORE_KEYSYM_FOR_DEBUG (keysym); + /* make_lispy_event will convert this to a symbolic + key. */ + inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT; + inev.ie.code = keysym; + goto done; + } + + { /* Raw bytes, not keysym. */ + ptrdiff_t i; + int nchars, len; + + for (i = 0, nchars = 0; i < nbytes; i++) + { + if (ASCII_CHAR_P (copy_bufptr[i])) + nchars++; + STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); + } + + if (nchars < nbytes) + { + /* Decode the input data. */ + + /* The input should be decoded with `coding_system' + which depends on which X*LookupString function + we used just above and the locale. */ + setup_coding_system (coding_system, &coding); + coding.src_multibyte = false; + coding.dst_multibyte = true; + /* The input is converted to events, thus we can't + handle composition. Anyway, there's no XIM that + gives us composition information. */ + coding.common_flags &= ~CODING_ANNOTATION_MASK; + + SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, + nbytes); + coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes; + coding.mode |= CODING_MODE_LAST_BLOCK; + decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); + nbytes = coding.produced; + nchars = coding.produced_char; + copy_bufptr = coding.destination; + } + + /* Convert the input data to a sequence of + character events. */ + for (i = 0; i < nbytes; i += len) + { + int ch; + if (nchars == nbytes) + ch = copy_bufptr[i], len = 1; + else + ch = string_char_and_length (copy_bufptr + i, &len); + inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch) + ? ASCII_KEYSTROKE_EVENT + : MULTIBYTE_CHAR_KEYSTROKE_EVENT); + inev.ie.code = ch; + evq_enqueue (&inev); + } + + // count += nchars; + + inev.ie.kind = NO_EVENT; /* Already stored above. */ + + if (keysym == GDK_KEY_VoidSymbol) + goto done; + } + } + + done: + if (inev.ie.kind != NO_EVENT) + { + XSETFRAME (inev.ie.frame_or_window, f); + evq_enqueue (&inev); + // count++; + } + + SAFE_FREE(); + + return TRUE; +} + +static gboolean key_release_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("key_release_event"); + return TRUE; +} + +static gboolean configure_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + struct frame *f = pgtk_any_window_to_frame (event->configure.window); + if (f && widget == FRAME_GTK_OUTER_WIDGET (f)) { + PGTK_TRACE("%dx%d", event->configure.width, event->configure.height); + xg_frame_resized(f, event->configure.width, event->configure.height); + } + return TRUE; +} + +static gboolean map_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + struct frame *f = pgtk_any_window_to_frame (event->any.window); + union buffered_input_event inev; + + PGTK_TRACE("map_event"); + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + if (f) + { + bool iconified = FRAME_ICONIFIED_P (f); + + /* Check if fullscreen was specified before we where mapped the + first time, i.e. from the command line. */ + if (!FRAME_X_OUTPUT(f)->has_been_visible) + { + set_fullscreen_state(f); + } + + if (!iconified) + { + /* The `z-group' is reset every time a frame becomes + invisible. Handle this here. */ + if (FRAME_Z_GROUP (f) == z_group_above) + x_set_z_group (f, Qabove, Qnil); + else if (FRAME_Z_GROUP (f) == z_group_below) + x_set_z_group (f, Qbelow, Qnil); + } + + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + FRAME_X_OUTPUT(f)->has_been_visible = true; + + if (iconified) + { + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) + /* Force a redisplay sooner or later to update the + frame titles in case this is the second frame. */ + record_asynch_buffer_change (); + } + + if (inev.ie.kind != NO_EVENT) + evq_enqueue(&inev); + return TRUE; +} + +static gboolean window_state_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + struct frame *f = pgtk_any_window_to_frame (event->window_state.window); + union buffered_input_event inev; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + if (f) { + if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) + { + if (FRAME_ICONIFIED_P (f)) + { + /* Gnome shell does not iconify us when C-z is pressed. + It hides the frame. So if our state says we aren't + hidden anymore, treat it as deiconified. */ + SET_FRAME_VISIBLE (f, 1); + SET_FRAME_ICONIFIED (f, false); + FRAME_X_OUTPUT(f)->has_been_visible = true; + inev.ie.kind = DEICONIFY_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + } + } + + if (inev.ie.kind != NO_EVENT) + evq_enqueue(&inev); + return TRUE; +} + +static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + struct frame *f = pgtk_any_window_to_frame (event->any.window); + union buffered_input_event inev; + + PGTK_TRACE("delete_event"); + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + if (f) { + inev.ie.kind = DELETE_WINDOW_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + + if (inev.ie.kind != NO_EVENT) + evq_enqueue(&inev); + return TRUE; +} + +void +pgtk_focus_frame (struct frame *f, bool noactivate) +{ + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + + GtkWidget *wid = FRAME_GTK_OUTER_WIDGET(f); + + if (dpyinfo->x_focus_frame != f) + { + block_input (); + gtk_window_present (GTK_WINDOW (wid)); + unblock_input (); + } +} + + +static void +frame_highlight (struct frame *f) +{ + /* We used to only do this if Vx_no_window_manager was non-nil, but + the ICCCM (section 4.1.6) says that the window's border pixmap + and border pixel are window attributes which are "private to the + client", so we can always change it to whatever we want. */ + block_input (); + /* I recently started to get errors in this XSetWindowBorder, depending on + the window-manager in use, tho something more is at play since I've been + using that same window-manager binary for ever. Let's not crash just + because of this (bug#9310). */ +#if 0 + x_catch_errors (FRAME_X_DISPLAY (f)); + XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_X_OUTPUT(f)->border_pixel); + x_uncatch_errors (); +#endif + unblock_input (); + x_update_cursor (f, true); +#if 0 + x_set_frame_alpha (f); +#endif +} + +static void +frame_unhighlight (struct frame *f) +{ + /* We used to only do this if Vx_no_window_manager was non-nil, but + the ICCCM (section 4.1.6) says that the window's border pixmap + and border pixel are window attributes which are "private to the + client", so we can always change it to whatever we want. */ + block_input (); + /* Same as above for XSetWindowBorder (bug#9310). */ +#if 0 + x_catch_errors (FRAME_X_DISPLAY (f)); + XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_X_OUTPUT(f)->border_tile); + x_uncatch_errors (); +#endif + unblock_input (); + x_update_cursor (f, true); +#if 0 + x_set_frame_alpha (f); +#endif +} + + +static void +x_frame_rehighlight (struct pgtk_display_info *dpyinfo) +{ + struct frame *old_highlight = dpyinfo->x_highlight_frame; + + if (dpyinfo->x_focus_frame) + { + dpyinfo->x_highlight_frame + = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) + ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) + : dpyinfo->x_focus_frame); + if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame)) + { + fset_focus_frame (dpyinfo->x_focus_frame, Qnil); + dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame; + } + } + else + dpyinfo->x_highlight_frame = 0; + + if (dpyinfo->x_highlight_frame != old_highlight) + { + if (old_highlight) + frame_unhighlight (old_highlight); + if (dpyinfo->x_highlight_frame) + frame_highlight (dpyinfo->x_highlight_frame); + } +} + +/* The focus has changed. Update the frames as necessary to reflect + the new situation. Note that we can't change the selected frame + here, because the Lisp code we are interrupting might become confused. + Each event gets marked with the frame in which it occurred, so the + Lisp code can tell when the switch took place by examining the events. */ + +static void +x_new_focus_frame (struct pgtk_display_info *dpyinfo, struct frame *frame) +{ + struct frame *old_focus = dpyinfo->x_focus_frame; + + if (frame != dpyinfo->x_focus_frame) + { + /* Set this before calling other routines, so that they see + the correct value of x_focus_frame. */ + dpyinfo->x_focus_frame = frame; + +#if 0 + if (old_focus && old_focus->auto_lower) + x_lower_frame (old_focus); +#endif + +#if 0 + if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) + dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame; + else + dpyinfo->x_pending_autoraise_frame = NULL; +#endif + } + + x_frame_rehighlight (dpyinfo); +} + +/* The focus may have changed. Figure out if it is a real focus change, + by checking both FocusIn/Out and Enter/LeaveNotify events. + + Returns FOCUS_IN_EVENT event in *BUFP. */ + +/* Handle FocusIn and FocusOut state changes for FRAME. + If FRAME has focus and there exists more than one frame, puts + a FOCUS_IN_EVENT into *BUFP. */ + +static void +x_focus_changed (gboolean is_enter, int state, struct pgtk_display_info *dpyinfo, struct frame *frame, union buffered_input_event *bufp) +{ + if (is_enter) + { + if (dpyinfo->x_focus_event_frame != frame) + { + x_new_focus_frame (dpyinfo, frame); + dpyinfo->x_focus_event_frame = frame; + + /* Don't stop displaying the initial startup message + for a switch-frame event we don't need. */ + /* When run as a daemon, Vterminal_frame is always NIL. */ + bufp->ie.arg = (((NILP (Vterminal_frame) + || ! FRAME_PGTK_P (XFRAME (Vterminal_frame)) + || EQ (Fdaemonp (), Qt)) + && CONSP (Vframe_list) + && !NILP (XCDR (Vframe_list))) + ? Qt : Qnil); + bufp->ie.kind = FOCUS_IN_EVENT; + XSETFRAME (bufp->ie.frame_or_window, frame); + } + + frame->output_data.pgtk->focus_state |= state; + + } + else + { + frame->output_data.pgtk->focus_state &= ~state; + + if (dpyinfo->x_focus_event_frame == frame) + { + dpyinfo->x_focus_event_frame = 0; + x_new_focus_frame (dpyinfo, 0); + + bufp->ie.kind = FOCUS_OUT_EVENT; + XSETFRAME (bufp->ie.frame_or_window, frame); + } + +#if 0 + if (frame->pointer_invisible) + XTtoggle_invisible_pointer (frame, false); +#endif + } +} + +static gboolean +enter_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("enter_notify_event"); + union buffered_input_event inev; + struct frame *focus_frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + int focus_state + = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + if (!(focus_state & FOCUS_EXPLICIT)) + x_focus_changed (TRUE, + FOCUS_IMPLICIT, + FRAME_DISPLAY_INFO(focus_frame), focus_frame, &inev); + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + return TRUE; +} + +static gboolean +leave_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("leave_notify_event"); + union buffered_input_event inev; + struct frame *focus_frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + int focus_state + = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + if (!(focus_state & FOCUS_EXPLICIT)) + x_focus_changed (FALSE, + FOCUS_IMPLICIT, + FRAME_DISPLAY_INFO(focus_frame), focus_frame, &inev); + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + return TRUE; +} + +static gboolean +focus_in_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("focus_in_event"); + union buffered_input_event inev; + struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + + if (frame == NULL) + return TRUE; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + x_focus_changed (TRUE, FOCUS_IMPLICIT, + FRAME_DISPLAY_INFO(frame), frame, &inev); + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + return TRUE; +} + +static gboolean +focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("focus_out_event"); + union buffered_input_event inev; + struct frame *frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + + if (frame == NULL) + return TRUE; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + x_focus_changed (FALSE, FOCUS_IMPLICIT, + FRAME_DISPLAY_INFO(frame), frame, &inev); + if (inev.ie.kind != NO_EVENT) + evq_enqueue(&inev); + return TRUE; +} + +/* Function to report a mouse movement to the mainstream Emacs code. + The input handler calls this. + + We have received a mouse movement event, which is given in *event. + If the mouse is over a different glyph than it was last time, tell + the mainstream emacs code by setting mouse_moved. If not, ask for + another motion event, so we can check again the next time it moves. */ + +static bool +note_mouse_movement (struct frame *frame, const GdkEventMotion *event) +{ + XRectangle *r; + struct pgtk_display_info *dpyinfo; + + if (!FRAME_X_OUTPUT (frame)) + return false; + + dpyinfo = FRAME_DISPLAY_INFO (frame); + dpyinfo->last_mouse_movement_time = event->time; + dpyinfo->last_mouse_motion_frame = frame; + dpyinfo->last_mouse_motion_x = event->x; + dpyinfo->last_mouse_motion_y = event->y; + + if (event->window != gtk_widget_get_window(FRAME_GTK_WIDGET (frame))) + { + frame->mouse_moved = true; + dpyinfo->last_mouse_scroll_bar = NULL; + note_mouse_highlight (frame, -1, -1); + dpyinfo->last_mouse_glyph_frame = NULL; + return true; + } + + + /* Has the mouse moved off the glyph it was on at the last sighting? */ + r = &dpyinfo->last_mouse_glyph; + if (frame != dpyinfo->last_mouse_glyph_frame + || event->x < r->x || event->x >= r->x + r->width + || event->y < r->y || event->y >= r->y + r->height) + { + frame->mouse_moved = true; + dpyinfo->last_mouse_scroll_bar = NULL; + note_mouse_highlight (frame, event->x, event->y); + /* Remember which glyph we're now on. */ + remember_mouse_glyph (frame, event->x, event->y, r); + dpyinfo->last_mouse_glyph_frame = frame; + return true; + } + + return false; +} + +static gboolean +motion_notify_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("motion_notify_event"); + union buffered_input_event inev; + struct frame *f, *frame; + struct pgtk_display_info *dpyinfo; + Mouse_HLInfo *hlinfo; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + previous_help_echo_string = help_echo_string; + help_echo_string = Qnil; + + frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + dpyinfo = FRAME_DISPLAY_INFO (frame); + f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame + : pgtk_any_window_to_frame(gtk_widget_get_window(widget))); + hlinfo = MOUSE_HL_INFO (f); + + if (hlinfo->mouse_face_hidden) + { + hlinfo->mouse_face_hidden = false; + clear_mouse_face (hlinfo); + } + + if (f && xg_event_is_for_scrollbar (f, event)) + f = 0; + if (f) + { + /* Maybe generate a SELECT_WINDOW_EVENT for + `mouse-autoselect-window' but don't let popup menus + interfere with this (Bug#1261). */ + if (!NILP (Vmouse_autoselect_window) + /* Don't switch if we're currently in the minibuffer. + This tries to work around problems where the + minibuffer gets unselected unexpectedly, and where + you then have to move your mouse all the way down to + the minibuffer to select it. */ + && !MINI_WINDOW_P (XWINDOW (selected_window)) + /* With `focus-follows-mouse' non-nil create an event + also when the target window is on another frame. */ + && (f == XFRAME (selected_frame) + || !NILP (focus_follows_mouse))) + { + static Lisp_Object last_mouse_window; + Lisp_Object window = window_from_coordinates + (f, event->motion.x, event->motion.y, 0, false); + + /* A window will be autoselected only when it is not + selected now and the last mouse movement event was + not in it. The remainder of the code is a bit vague + wrt what a "window" is. For immediate autoselection, + the window is usually the entire window but for GTK + where the scroll bars don't count. For delayed + autoselection the window is usually the window's text + area including the margins. */ + if (WINDOWP (window) + && !EQ (window, last_mouse_window) + && !EQ (window, selected_window)) + { + inev.ie.kind = SELECT_WINDOW_EVENT; + inev.ie.frame_or_window = window; + } + + /* Remember the last window where we saw the mouse. */ + last_mouse_window = window; + } + + if (!note_mouse_movement (f, &event->motion)) + help_echo_string = previous_help_echo_string; + } + else + { + /* If we move outside the frame, then we're + certainly no longer on any text in the frame. */ + clear_mouse_face (hlinfo); + } + + /* If the contents of the global variable help_echo_string + has changed, generate a HELP_EVENT. */ + int do_help = 0; + if (!NILP (help_echo_string) + || !NILP (previous_help_echo_string)) + do_help = 1; + + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + + if (do_help > 0) { + Lisp_Object frame; + union buffered_input_event inev; + + if (f) + XSETFRAME (frame, f); + else + frame = Qnil; + + inev.ie.kind = HELP_EVENT; + inev.ie.frame_or_window = frame; + inev.ie.arg = help_echo_object; + inev.ie.x = help_echo_window; + inev.ie.y = help_echo_string; + inev.ie.timestamp = help_echo_pos; + evq_enqueue(&inev); + } + + return TRUE; +} + +/* Mouse clicks and mouse movement. Rah. + + Formerly, we used PointerMotionHintMask (in standard_event_mask) + so that we would have to call XQueryPointer after each MotionNotify + event to ask for another such event. However, this made mouse tracking + slow, and there was a bug that made it eventually stop. + + Simply asking for MotionNotify all the time seems to work better. + + In order to avoid asking for motion events and then throwing most + of them away or busy-polling the server for mouse positions, we ask + the server for pointer motion hints. This means that we get only + one event per group of mouse movements. "Groups" are delimited by + other kinds of events (focus changes and button clicks, for + example), or by XQueryPointer calls; when one of these happens, we + get another MotionNotify event the next time the mouse moves. This + is at least as efficient as getting motion events when mouse + tracking is on, and I suspect only negligibly worse when tracking + is off. */ + +/* Prepare a mouse-event in *RESULT for placement in the input queue. + + If the event is a button press, then note that we have grabbed + the mouse. */ + +static Lisp_Object +construct_mouse_click (struct input_event *result, + const GdkEventButton *event, + struct frame *f) +{ + /* Make the event type NO_EVENT; we'll change that when we decide + otherwise. */ + result->kind = MOUSE_CLICK_EVENT; + result->code = event->button - 1; + result->timestamp = event->time; + result->modifiers = (pgtk_gtk_to_emacs_modifiers (event->state) + | (event->type == GDK_BUTTON_RELEASE + ? up_modifier + : down_modifier)); + + XSETINT (result->x, event->x); + XSETINT (result->y, event->y); + XSETFRAME (result->frame_or_window, f); + result->arg = Qnil; + return Qnil; +} + +static gboolean +button_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("button_event: type=%d, button=%u.", event->button.type, event->button.button); + union buffered_input_event inev; + struct frame *f, *frame; + struct pgtk_display_info *dpyinfo; + + /* If we decide we want to generate an event to be seen + by the rest of Emacs, we put it here. */ + bool tool_bar_p = false; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + /* ignore double click and triple click. */ + if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) + return TRUE; + + frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + dpyinfo = FRAME_DISPLAY_INFO (frame); + + dpyinfo->last_mouse_glyph_frame = NULL; +#if 0 + x_display_set_last_user_time (dpyinfo, event->button.time); +#endif + + if (x_mouse_grabbed (dpyinfo)) + f = dpyinfo->last_mouse_frame; + else + { + f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + + if (f && event->button.type == GDK_BUTTON_PRESS + && !FRAME_NO_ACCEPT_FOCUS (f)) + { + /* When clicking into a child frame or when clicking + into a parent frame with the child frame selected and + `no-accept-focus' is not set, select the clicked + frame. */ + struct frame *hf = dpyinfo->x_highlight_frame; + + if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf))) + { + block_input (); +#if 0 + XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + RevertToParent, CurrentTime); + if (FRAME_PARENT_FRAME (f)) + XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f)); +#endif + unblock_input (); + } + } + } + + if (f && xg_event_is_for_scrollbar (f, event)) + f = 0; + if (f) + { + if (!tool_bar_p) + { + if (ignore_next_mouse_click_timeout) + { + if (event->type == GDK_BUTTON_PRESS + && event->button.time > ignore_next_mouse_click_timeout) + { + ignore_next_mouse_click_timeout = 0; + construct_mouse_click (&inev.ie, &event->button, f); + } + if (event->type == GDK_BUTTON_RELEASE) + ignore_next_mouse_click_timeout = 0; + } + else + construct_mouse_click (&inev.ie, &event->button, f); + } +#if 0 + if (FRAME_X_EMBEDDED_P (f)) + xembed_send_message (f, event->button.time, + XEMBED_REQUEST_FOCUS, 0, 0, 0); +#endif + } + + if (event->type == GDK_BUTTON_PRESS) + { + dpyinfo->grabbed |= (1 << event->button.button); + dpyinfo->last_mouse_frame = f; + } + else + dpyinfo->grabbed &= ~(1 << event->button.button); + + /* Ignore any mouse motion that happened before this event; + any subsequent mouse-movement Emacs events should reflect + only motion after the ButtonPress/Release. */ + if (f != 0) + f->mouse_moved = false; + + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + return TRUE; +} + +static gboolean +scroll_event(GtkWidget *widget, GdkEvent *event, gpointer *user_data) +{ + PGTK_TRACE("scroll_event"); + union buffered_input_event inev; + struct frame *f, *frame; + struct pgtk_display_info *dpyinfo; + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + frame = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + dpyinfo = FRAME_DISPLAY_INFO (frame); + + if (x_mouse_grabbed (dpyinfo)) + f = dpyinfo->last_mouse_frame; + else + f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + + inev.ie.kind = WHEEL_EVENT; + inev.ie.timestamp = event->scroll.time; + inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (event->scroll.state); + XSETINT (inev.ie.x, event->scroll.x); + XSETINT (inev.ie.y, event->scroll.y); + XSETFRAME (inev.ie.frame_or_window, f); + inev.ie.arg = Qnil; + + switch (event->scroll.direction) { + case GDK_SCROLL_UP: + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + break; + case GDK_SCROLL_DOWN: + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + break; + case GDK_SCROLL_LEFT: + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + break; + case GDK_SCROLL_RIGHT: + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + break; + case GDK_SCROLL_SMOOTH: + if (event->scroll.delta_y >= 0.5) { + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + } else if (event->scroll.delta_y <= -0.5) { + inev.ie.kind = WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + } else if (event->scroll.delta_x >= 0.5) { + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= down_modifier; + } else if (event->scroll.delta_x <= -0.5) { + inev.ie.kind = HORIZ_WHEEL_EVENT; + inev.ie.modifiers |= up_modifier; + } else + return TRUE; + break; + default: + return TRUE; + } + + if (inev.ie.kind != NO_EVENT) + evq_enqueue (&inev); + return TRUE; +} + +static gboolean drag_drop(GtkWidget *widget, + GdkDragContext *context, + gint x, gint y, + guint time_, + gpointer user_data) +{ + PGTK_TRACE("drag_drop"); + GdkAtom target = gtk_drag_dest_find_target(widget, context, NULL); + PGTK_TRACE("drag_drop: target: %p", (void *) target); + + if (target == GDK_NONE) { + gtk_drag_finish(context, TRUE, FALSE, time_); + return FALSE; + } + + gtk_drag_get_data(widget, context, target, time_); + + return TRUE; +} + +static void drag_data_received(GtkWidget *widget, GdkDragContext *context, + gint x, gint y, + GtkSelectionData *data, + guint info, guint time_, + gpointer user_data) +{ + PGTK_TRACE("drag_data_received:"); + struct frame *f = pgtk_any_window_to_frame(gtk_widget_get_window(widget)); + gchar **uris = gtk_selection_data_get_uris(data); + + if (uris != NULL) { + for (int i = 0; uris[i] != NULL; i++) { + union buffered_input_event inev; + Lisp_Object arg = Qnil; + + PGTK_TRACE("drag_data_received: uri: %s", uris[i]); + + EVENT_INIT (inev.ie); + inev.ie.kind = NO_EVENT; + inev.ie.arg = Qnil; + + arg = list2(Qurl, build_string(uris[i])); + + inev.ie.kind = DRAG_N_DROP_EVENT; + inev.ie.modifiers = 0; + XSETINT(inev.ie.x, x); + XSETINT(inev.ie.y, y); + XSETFRAME(inev.ie.frame_or_window, f); + inev.ie.arg = arg; + inev.ie.timestamp = 0; + + evq_enqueue (&inev); + } + } + PGTK_TRACE("drag_data_received: that's all."); + + gtk_drag_finish(context, TRUE, FALSE, time_); +} + +void +pgtk_set_event_handler(struct frame *f) +{ + gtk_drag_dest_set(FRAME_GTK_WIDGET(f), GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_uri_targets(FRAME_GTK_WIDGET(f)); + + g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "window-state-event", G_CALLBACK(window_state_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "delete-event", G_CALLBACK(delete_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "map-event", G_CALLBACK(map_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_OUTER_WIDGET(f)), "event", G_CALLBACK(pgtk_handle_event), NULL); + + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "size-allocate", G_CALLBACK(size_allocate), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "key-press-event", G_CALLBACK(key_press_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "key-release-event", G_CALLBACK(key_release_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "focus-in-event", G_CALLBACK(focus_in_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "focus-out-event", G_CALLBACK(focus_out_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "enter-notify-event", G_CALLBACK(enter_notify_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "leave-notify-event", G_CALLBACK(leave_notify_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "motion-notify-event", G_CALLBACK(motion_notify_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "button-press-event", G_CALLBACK(button_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "button-release-event", G_CALLBACK(button_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "scroll-event", G_CALLBACK(scroll_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "selection-clear-event", G_CALLBACK(pgtk_selection_lost), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "configure-event", G_CALLBACK(configure_event), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "drag-drop", G_CALLBACK(drag_drop), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "drag-data-received", G_CALLBACK(drag_data_received), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "draw", G_CALLBACK(pgtk_handle_draw), NULL); + g_signal_connect(G_OBJECT(FRAME_GTK_WIDGET(f)), "event", G_CALLBACK(pgtk_handle_event), NULL); +} + +static void +my_log_handler (const gchar *log_domain, GLogLevelFlags log_level, + const gchar *msg, gpointer user_data) +{ + if (!strstr (msg, "g_set_prgname")) + fprintf (stderr, "%s-WARNING **: %s", log_domain, msg); +} + +/* Test whether two display-name strings agree up to the dot that separates + the screen number from the server number. */ +static bool +same_x_server (const char *name1, const char *name2) +{ + bool seen_colon = false; + Lisp_Object sysname = Fsystem_name (); + const char *system_name = SSDATA (sysname); + ptrdiff_t system_name_length = SBYTES (sysname); + ptrdiff_t length_until_period = 0; + + while (system_name[length_until_period] != 0 + && system_name[length_until_period] != '.') + length_until_period++; + + /* Treat `unix' like an empty host name. */ + if (! strncmp (name1, "unix:", 5)) + name1 += 4; + if (! strncmp (name2, "unix:", 5)) + name2 += 4; + /* Treat this host's name like an empty host name. */ + if (! strncmp (name1, system_name, system_name_length) + && name1[system_name_length] == ':') + name1 += system_name_length; + if (! strncmp (name2, system_name, system_name_length) + && name2[system_name_length] == ':') + name2 += system_name_length; + /* Treat this host's domainless name like an empty host name. */ + if (! strncmp (name1, system_name, length_until_period) + && name1[length_until_period] == ':') + name1 += length_until_period; + if (! strncmp (name2, system_name, length_until_period) + && name2[length_until_period] == ':') + name2 += length_until_period; + + for (; *name1 != '\0' && *name1 == *name2; name1++, name2++) + { + if (*name1 == ':') + seen_colon = true; + if (seen_colon && *name1 == '.') + return true; + } + return (seen_colon + && (*name1 == '.' || *name1 == '\0') + && (*name2 == '.' || *name2 == '\0')); +} + +/* Open a connection to X display DISPLAY_NAME, and return + the structure that describes the open display. + If we cannot contact the display, return null. */ + +struct pgtk_display_info * +pgtk_term_init (Lisp_Object display_name, char *resource_name) +{ + GdkDisplay *dpy; + struct terminal *terminal; + struct pgtk_display_info *dpyinfo; + static int x_initialized = 0; + static unsigned x_display_id = 0; + + block_input (); + + if (!x_initialized) + { + Fset_input_interrupt_mode (Qt); + baud_rate = 19200; + +#ifdef USE_CAIRO + gui_init_fringe (&pgtk_redisplay_interface); +#endif + + ++x_initialized; + } + + { +#define NUM_ARGV 10 + int argc; + char *argv[NUM_ARGV]; + char **argv2 = argv; + guint id; + + if (x_initialized++ > 1) + { + xg_display_open (SSDATA (display_name), &dpy); + } + else + { + static char display_opt[] = "--display"; + static char name_opt[] = "--name"; + + for (argc = 0; argc < NUM_ARGV; ++argc) + argv[argc] = 0; + + argc = 0; + argv[argc++] = initial_argv[0]; + + if (strlen(SSDATA(display_name)) != 0) + { + argv[argc++] = display_opt; + argv[argc++] = SSDATA (display_name); + } + + argv[argc++] = name_opt; + argv[argc++] = resource_name; + + /* Work around GLib bug that outputs a faulty warning. See + https://bugzilla.gnome.org/show_bug.cgi?id=563627. */ + id = g_log_set_handler ("GLib", G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL + | G_LOG_FLAG_RECURSION, my_log_handler, NULL); + + /* gtk_init does set_locale. Fix locale before and after. */ + fixup_locale (); + unrequest_sigio (); /* See comment in x_display_ok. */ + gtk_init (&argc, &argv2); + request_sigio (); + fixup_locale (); + + + g_log_remove_handler ("GLib", id); + + xg_initialize (); + + dpy = DEFAULT_GDK_DISPLAY (); + } + } + + /* Detect failure. */ + if (dpy == 0) + { + unblock_input (); + return 0; + } + + + dpyinfo = xzalloc (sizeof *dpyinfo); + pgtk_initialize_display_info (dpyinfo); + terminal = pgtk_create_terminal (dpyinfo); + + { + struct pgtk_display_info *share; + + for (share = x_display_list; share; share = share->next) + if (same_x_server (SSDATA (XCAR (share->name_list_element)), + SSDATA (display_name))) + break; + if (share) + terminal->kboard = share->terminal->kboard; + else + { + terminal->kboard = allocate_kboard (Qpgtk); + + /* Don't let the initial kboard remain current longer than necessary. + That would cause problems if a file loaded on startup tries to + prompt in the mini-buffer. */ + if (current_kboard == initial_kboard) + current_kboard = terminal->kboard; + } + terminal->kboard->reference_count++; + } + + /* Put this display on the chain. */ + dpyinfo->next = x_display_list; + x_display_list = dpyinfo; + + dpyinfo->name_list_element = Fcons (display_name, Qnil); + dpyinfo->gdpy = dpy; + + /* https://lists.gnu.org/r/emacs-devel/2015-11/msg00194.html */ + dpyinfo->smallest_font_height = 1; + dpyinfo->smallest_char_width = 1; + + /* Set the name of the terminal. */ + terminal->name = xlispstrdup (display_name); + + Lisp_Object system_name = Fsystem_name (); + ptrdiff_t nbytes; + if (INT_ADD_WRAPV (SBYTES (Vinvocation_name), SBYTES (system_name) + 2, + &nbytes)) + memory_full (SIZE_MAX); + dpyinfo->x_id = ++x_display_id; + dpyinfo->x_id_name = xmalloc (nbytes); + char *nametail = lispstpcpy (dpyinfo->x_id_name, Vinvocation_name); + *nametail++ = '@'; + lispstpcpy (nametail, system_name); + +#if 0 + /* Figure out which modifier bits mean what. */ + x_find_modifier_meanings (dpyinfo); +#endif + + /* Get the scroll bar cursor. */ + /* We must create a GTK cursor, it is required for GTK widgets. */ + dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->gdpy); + +#if 0 + dpyinfo->vertical_scroll_bar_cursor + = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow); + + dpyinfo->horizontal_scroll_bar_cursor + = XCreateFontCursor (dpyinfo->display, XC_sb_h_double_arrow); +#endif + + reset_mouse_highlight (&dpyinfo->mouse_highlight); + + { + GdkScreen *gscr = gdk_display_get_default_screen(dpyinfo->gdpy); + gdouble dpi = gdk_screen_get_resolution(gscr); + dpyinfo->resx = dpi; + dpyinfo->resy = dpi; + } + +#if 0 + x_setup_pointer_blanking (dpyinfo); +#endif + + xsettings_initialize (dpyinfo); + +#ifdef F_SETOWN + fcntl (dpyinfo->connection, F_SETOWN, getpid ()); +#endif /* ! defined (F_SETOWN) */ + + if (interrupt_input) + init_sigio (dpyinfo->connection); + + pgtk_selection_init(); + + unblock_input (); + + return dpyinfo; +} + +/* Get rid of display DPYINFO, deleting all frames on it, + and without sending any more commands to the X server. */ + +static void +pgtk_delete_display (struct pgtk_display_info *dpyinfo) +{ + struct terminal *t; + + /* Close all frames and delete the generic struct terminal for this + X display. */ + for (t = terminal_list; t; t = t->next_terminal) + if (t->type == output_pgtk && t->display_info.pgtk == dpyinfo) + { + delete_terminal (t); + break; + } + + if (x_display_list == dpyinfo) + x_display_list = dpyinfo->next; + else + { + struct pgtk_display_info *tail; + + for (tail = x_display_list; tail; tail = tail->next) + if (tail->next == dpyinfo) + tail->next = tail->next->next; + } + + xfree (dpyinfo); +} + +char * +pgtk_xlfd_to_fontname (const char *xlfd) +/* -------------------------------------------------------------------------- + Convert an X font name (XLFD) to an Gtk font name. + Only family is used. + The string returned is temporarily allocated. + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("pgtk_xlfd_to_fontname"); + char *name = xmalloc (180); + + if (!strncmp (xlfd, "--", 2)) { + if (sscanf (xlfd, "--%179[^-]-", name) != 1) + name[0] = '\0'; + } else { + if (sscanf (xlfd, "-%*[^-]-%179[^-]-", name) != 1) + name[0] = '\0'; + } + + /* stopgap for malformed XLFD input */ + if (strlen (name) == 0) + strcpy (name, "Monospace"); + + PGTK_TRACE("converted '%s' to '%s'", xlfd, name); + return name; +} + +bool +pgtk_defined_color (struct frame *f, + const char *name, + Emacs_Color *color_def, + bool alloc, + bool makeIndex) +/* -------------------------------------------------------------------------- + Return true if named color found, and set color_def rgb accordingly. + If makeIndex and alloc are nonzero put the color in the color_table, + and set color_def pixel to the resulting index. + If makeIndex is zero, set color_def pixel to ARGB. + Return false if not found + -------------------------------------------------------------------------- */ +{ + // PGTK_TRACE("pgtk_defined_color(%s)", name); + int r; + + block_input (); + r = pgtk_parse_color (name, color_def); + unblock_input (); + return r; +} + +/* On frame F, translate the color name to RGB values. Use cached + information, if possible. + + Note that there is currently no way to clean old entries out of the + cache. However, it is limited to names in the server's database, + and names we've actually looked up; list-colors-display is probably + the most color-intensive case we're likely to hit. */ + +int pgtk_parse_color (const char *color_name, Emacs_Color *color) +{ + // PGTK_TRACE("pgtk_parse_color: %s", color_name); + + GdkRGBA rgba; + if (gdk_rgba_parse(&rgba, color_name)) { + color->red = rgba.red * 65535; + color->green = rgba.green * 65535; + color->blue = rgba.blue * 65535; + color->pixel = + (unsigned long) 0xff << 24 | + (color->red >> 8) << 16 | + (color->green >> 8) << 8 | + (color->blue >> 8) << 0; + return 1; + } + return 0; +} + +int +pgtk_lisp_to_color (Lisp_Object color, Emacs_Color *col) +/* -------------------------------------------------------------------------- + Convert a Lisp string object to a NS color + -------------------------------------------------------------------------- */ +{ + PGTK_TRACE("pgtk_lisp_to_color"); + if (STRINGP (color)) + return !pgtk_parse_color (SSDATA (color), col); + else if (SYMBOLP (color)) + return !pgtk_parse_color (SSDATA (SYMBOL_NAME (color)), col); + return 1; +} + +/* On frame F, translate pixel colors to RGB values for the NCOLORS + colors in COLORS. On W32, we no longer try to map colors to + a palette. */ +void +pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors) +{ + PGTK_TRACE("pgtk_query_colors"); + int i; + + for (i = 0; i < ncolors; i++) + { + unsigned long pixel = colors[i].pixel; + /* Convert to a 16 bit value in range 0 - 0xffff. */ +#define GetRValue(p) (((p) >> 16) & 0xff) +#define GetGValue(p) (((p) >> 8) & 0xff) +#define GetBValue(p) (((p) >> 0) & 0xff) + colors[i].red = GetRValue (pixel) * 257; + colors[i].green = GetGValue (pixel) * 257; + colors[i].blue = GetBValue (pixel) * 257; + } +} + +void +pgtk_query_color (struct frame *f, Emacs_Color *color) +{ + PGTK_TRACE("pgtk_query_color"); + pgtk_query_colors (f, color, 1); +} + +void +pgtk_clear_area (struct frame *f, int x, int y, int width, int height) +{ + PGTK_TRACE("pgtk_clear_area: %dx%d+%d+%d.", width, height, x, y); + cairo_t *cr; + + eassert (width > 0 && height > 0); + + cr = pgtk_begin_cr_clip (f); + PGTK_TRACE("back color %08lx.", (unsigned long) FRAME_X_OUTPUT(f)->background_color); + pgtk_set_cr_source_with_color (f, FRAME_X_OUTPUT(f)->background_color); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (f); +} + + +void +syms_of_pgtkterm (void) +{ + /* from 23+ we need to tell emacs what modifiers there are.. */ + DEFSYM (Qmodifier_value, "modifier-value"); + DEFSYM (Qalt, "alt"); + DEFSYM (Qhyper, "hyper"); + DEFSYM (Qmeta, "meta"); + DEFSYM (Qsuper, "super"); + DEFSYM (Qcontrol, "control"); + DEFSYM (QUTF8_STRING, "UTF8_STRING"); + + DEFSYM (Qfile, "file"); + DEFSYM (Qurl, "url"); + + DEFSYM (Qlatin_1, "latin-1"); + + Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); + Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); + Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier)); + Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier)); + Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier)); + + DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, + doc: /* Which keys Emacs uses for the ctrl modifier. +This should be one of the symbols `ctrl', `alt', `hyper', `meta', +`super'. For example, `ctrl' means use the Ctrl_L and Ctrl_R keysyms. +The default is nil, which is the same as `ctrl'. */); + Vx_ctrl_keysym = Qnil; + + DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym, + doc: /* Which keys Emacs uses for the alt modifier. +This should be one of the symbols `ctrl', `alt', `hyper', `meta', +`super'. For example, `alt' means use the Alt_L and Alt_R keysyms. +The default is nil, which is the same as `alt'. */); + Vx_alt_keysym = Qnil; + + DEFVAR_LISP ("x-hyper-keysym", Vx_hyper_keysym, + doc: /* Which keys Emacs uses for the hyper modifier. +This should be one of the symbols `ctrl', `alt', `hyper', `meta', +`super'. For example, `hyper' means use the Hyper_L and Hyper_R +keysyms. The default is nil, which is the same as `hyper'. */); + Vx_hyper_keysym = Qnil; + + DEFVAR_LISP ("x-meta-keysym", Vx_meta_keysym, + doc: /* Which keys Emacs uses for the meta modifier. +This should be one of the symbols `ctrl', `alt', `hyper', `meta', +`super'. For example, `meta' means use the Meta_L and Meta_R keysyms. +The default is nil, which is the same as `meta'. */); + Vx_meta_keysym = Qnil; + + DEFVAR_LISP ("x-super-keysym", Vx_super_keysym, + doc: /* Which keys Emacs uses for the super modifier. +This should be one of the symbols `ctrl', `alt', `hyper', `meta', +`super'. For example, `super' means use the Super_L and Super_R +keysyms. The default is nil, which is the same as `super'. */); + Vx_super_keysym = Qnil; + + /* TODO: move to common code */ + DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, + doc: /* Which toolkit scroll bars Emacs uses, if any. +A value of nil means Emacs doesn't use toolkit scroll bars. +With the X Window system, the value is a symbol describing the +X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. +With MS Windows or Nextstep, the value is t. */); + // Vx_toolkit_scroll_bars = Qt; + Vx_toolkit_scroll_bars = intern_c_string ("gtk"); + + DEFVAR_BOOL ("x-use-underline-position-properties", + x_use_underline_position_properties, + doc: /*Non-nil means make use of UNDERLINE_POSITION font properties. +A value of nil means ignore them. If you encounter fonts with bogus +UNDERLINE_POSITION font properties, for example 7x13 on XFree prior +to 4.1, set this to nil. */); + x_use_underline_position_properties = 0; + + DEFVAR_BOOL ("x-underline-at-descent-line", + x_underline_at_descent_line, + doc: /* Non-nil means to draw the underline at the same place as the descent line. +A value of nil means to draw the underline according to the value of the +variable `x-use-underline-position-properties', which is usually at the +baseline level. The default value is nil. */); + x_underline_at_descent_line = 0; + + DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move, + doc: /* Non-nil means rely on gtk_window_move to set frame positions. +If this variable is t (the default), the GTK build uses the function +gtk_window_move to set or store frame positions and disables some time +consuming frame position adjustments. In newer versions of GTK, Emacs +always uses gtk_window_move and ignores the value of this variable. */); + x_gtk_use_window_move = true; + + DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); + + DEFVAR_LISP ("pgtk-wait-for-event-timeout", Vpgtk_wait_for_event_timeout, + doc: /* How long to wait for X events. + +Emacs will wait up to this many seconds to receive X events after +making changes which affect the state of the graphical interface. +Under some window managers this can take an indefinite amount of time, +so it is important to limit the wait. + +If set to a non-float value, there will be no wait at all. */); + Vpgtk_wait_for_event_timeout = make_float (0.1); + + DEFVAR_LISP ("pgtk-keysym-table", Vpgtk_keysym_table, + doc: /* Hash table of character codes indexed by X keysym codes. */); + Vpgtk_keysym_table = make_hash_table (hashtest_eql, 900, + DEFAULT_REHASH_SIZE, + DEFAULT_REHASH_THRESHOLD, + Qnil, false); + + window_being_scrolled = Qnil; + staticpro(&window_being_scrolled); + + /* Tell Emacs about this window system. */ + Fprovide (Qpgtk, Qnil); + +} + +cairo_t * +pgtk_begin_cr_clip (struct frame *f) +{ + cairo_t *cr = FRAME_CR_CONTEXT (f); + + PGTK_TRACE("pgtk_begin_cr_clip"); + if (! FRAME_CR_SURFACE (f)) + { + FRAME_CR_SURFACE(f) = gdk_window_create_similar_surface(gtk_widget_get_window (FRAME_GTK_WIDGET (f)), + CAIRO_CONTENT_COLOR_ALPHA, + FRAME_PIXEL_WIDTH (f), + FRAME_PIXEL_HEIGHT (f)); + } + + if (!cr) + { + cr = cairo_create (FRAME_CR_SURFACE (f)); + FRAME_CR_CONTEXT (f) = cr; + } + + cairo_save (cr); + + return cr; +} + +void +pgtk_end_cr_clip (struct frame *f) +{ + PGTK_TRACE("pgtk_end_cr_clip"); + cairo_restore (FRAME_CR_CONTEXT (f)); + + GtkWidget *widget = FRAME_GTK_WIDGET(f); + gtk_widget_queue_draw(widget); +} + +void +pgtk_set_cr_source_with_gc_foreground (struct frame *f, XGCValues *gc) +{ + PGTK_TRACE("pgtk_set_cr_source_with_gc_foreground: %08lx", gc->foreground); + pgtk_set_cr_source_with_color(f, gc->foreground); +} + +void +pgtk_set_cr_source_with_gc_background (struct frame *f, XGCValues *gc) +{ + PGTK_TRACE("pgtk_set_cr_source_with_gc_background: %08lx", gc->background); + pgtk_set_cr_source_with_color(f, gc->background); +} + +void +pgtk_set_cr_source_with_color (struct frame *f, unsigned long color) +{ + PGTK_TRACE("pgtk_set_cr_source_with_color: %08lx.", color); + Emacs_Color col; + col.pixel = color; + pgtk_query_color(f, &col); + cairo_set_source_rgb (FRAME_CR_CONTEXT (f), col.red / 65535.0, + col.green / 65535.0, col.blue / 65535.0); +} + +void +pgtk_cr_draw_frame (cairo_t *cr, struct frame *f) +{ + PGTK_TRACE("pgtk_cr_draw_frame"); + cairo_set_source_surface(cr, FRAME_CR_SURFACE(f), 0, 0); + cairo_paint(cr); +} + +void +pgtk_cr_destroy_surface(struct frame *f) +{ + PGTK_TRACE("pgtk_cr_destroy_surface"); + if (FRAME_CR_CONTEXT(f) != NULL) { + cairo_destroy(FRAME_CR_CONTEXT(f)); + FRAME_CR_CONTEXT(f) = NULL; + } + if (FRAME_CR_SURFACE(f) != NULL) { + cairo_surface_destroy(FRAME_CR_SURFACE(f)); + FRAME_CR_SURFACE(f) = NULL; + } + SET_FRAME_GARBAGED (f); +} + +void +init_pgtkterm (void) +{ +} diff --git a/src/pgtkterm.h b/src/pgtkterm.h new file mode 100644 index 0000000000..c01d846748 --- /dev/null +++ b/src/pgtkterm.h @@ -0,0 +1,569 @@ +/* Definitions and headers for communication with pure Gtk+3. + Copyright (C) 1989, 1993, 2005, 2008-2017 Free Software Foundation, + Inc. + +This file is part of GNU Emacs. + +GNU Emacs 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 3 of the License, or (at +your option) any later version. + +GNU Emacs 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 GNU Emacs. If not, see . */ + + +#include "dispextern.h" +#include "frame.h" +#include "character.h" +#include "font.h" +#include "sysselect.h" + +#ifdef HAVE_PGTK + +#include + +// #define PGTK_DEBUG 1 + +#ifdef PGTK_DEBUG +extern void pgtk_log(const char *file, int lineno, const char *fmt, ...) + ATTRIBUTE_FORMAT_PRINTF (3, 4); +#define PGTK_TRACE(fmt, ...) pgtk_log(__FILE__, __LINE__, fmt, ## __VA_ARGS__) +extern void pgtk_backtrace(const char *file, int lineno); +#define PGTK_BACKTRACE() pgtk_backtrace(__FILE__, __LINE__) +#else +#define PGTK_TRACE(fmt, ...) ((void) 0) +#define PGTK_BACKTRACE() ((void) 0) +#endif + +/* The GtkTooltip API came in 2.12, but gtk-enable-tooltips in 2.14. */ +#if GTK_CHECK_VERSION (2, 14, 0) +#define USE_GTK_TOOLTIP +#endif + +/* could use list to store these, but rest of emacs has a big infrastructure + for managing a table of bitmap "records" */ +struct pgtk_bitmap_record +{ + void *img; + char *file; + int refcount; + int height, width, depth; +}; + +#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b)) +#define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +#define ALPHA_FROM_ULONG(color) ((color) >> 24) +#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) +#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff) +#define BLUE_FROM_ULONG(color) ((color) & 0xff) + +struct scroll_bar +{ + /* These fields are shared by all vectors. */ + union vectorlike_header header; + + /* The window we're a scroll bar for. */ + Lisp_Object window; + + /* The next and previous in the chain of scroll bars in this frame. */ + Lisp_Object next, prev; + + /* Fields from `x_window' down will not be traced by the GC. */ + + /* The X window representing this scroll bar. */ + Window x_window; + + /* The position and size of the scroll bar in pixels, relative to the + frame. */ + int top, left, width, height; + + /* The starting and ending positions of the handle, relative to the + handle area (i.e. zero is the top position, not + SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle + hasn't been drawn yet. + + These are not actually the locations where the beginning and end + are drawn; in order to keep handles from becoming invisible when + editing large files, we establish a minimum height by always + drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below + where they would be normally; the bottom and top are in a + different co-ordinate system. */ + int start, end; + + /* If the scroll bar handle is currently being dragged by the user, + this is the number of pixels from the top of the handle to the + place where the user grabbed it. If the handle isn't currently + being dragged, this is -1. */ + int dragging; + +#if defined (USE_TOOLKIT_SCROLL_BARS) && defined (USE_LUCID) + /* Last scroll bar part seen in xaw_jump_callback and xaw_scroll_callback. */ + enum scroll_bar_part last_seen_part; +#endif + +#if defined (USE_TOOLKIT_SCROLL_BARS) && !defined (USE_GTK) + /* Last value of whole for horizontal scrollbars. */ + int whole; +#endif + + /* True if the scroll bar is horizontal. */ + bool horizontal; +}; + + +/* init'd in pgtk_initialize_display_info () */ +struct pgtk_display_info +{ + /* Chain of all pgtk_display_info structures. */ + struct pgtk_display_info *next; + + /* The generic display parameters corresponding to this PGTK display. */ + struct terminal *terminal; + + /* This says how to access this display in Gdk. */ + GdkDisplay *gdpy; + + /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */ + Lisp_Object name_list_element; + + /* Number of frames that are on this display. */ + int reference_count; + + /* Logical identifier of this display. */ + unsigned x_id; + + /* Default name for all frames on this display. */ + char *x_id_name; + + /* The number of fonts loaded. */ + int n_fonts; + + /* Minimum width over all characters in all fonts in font_table. */ + int smallest_char_width; + + /* Minimum font height over all fonts in font_table. */ + int smallest_font_height; + + struct pgtk_bitmap_record *bitmaps; + ptrdiff_t bitmaps_size; + ptrdiff_t bitmaps_last; + + /* DPI resolution of this screen */ + double resx, resy; + + /* Mask of things that cause the mouse to be grabbed */ + int grabbed; + + int n_planes; + + int color_p; + + Window root_window; + + /* Xism */ + XrmDatabase xrdb; + + /* The cursor to use for vertical scroll bars. */ + Emacs_Cursor vertical_scroll_bar_cursor; + + /* The cursor to use for horizontal scroll bars. */ + Emacs_Cursor horizontal_scroll_bar_cursor; + + /* Information about the range of text currently shown in + mouse-face. */ + Mouse_HLInfo mouse_highlight; + + struct frame *x_highlight_frame; + struct frame *x_focus_frame; + + /* The last frame mentioned in a FocusIn or FocusOut event. This is + separate from x_focus_frame, because whether or not LeaveNotify + events cause us to lose focus depends on whether or not we have + received a FocusIn event for it. */ + struct frame *x_focus_event_frame; + + /* The frame where the mouse was last time we reported a mouse event. */ + struct frame *last_mouse_frame; + + /* The frame where the mouse was last time we reported a mouse motion. */ + struct frame *last_mouse_motion_frame; + + /* Position where the mouse was last time we reported a motion. + This is a position on last_mouse_motion_frame. */ + int last_mouse_motion_x; + int last_mouse_motion_y; + + /* Where the mouse was last time we reported a mouse position. */ + XRectangle last_mouse_glyph; + + /* Time of last mouse movement. */ + Time last_mouse_movement_time; + + /* The scroll bar in which the last motion event occurred. */ + void *last_mouse_scroll_bar; + + /* The GDK cursor for scroll bars and popup menus. */ + GdkCursor *xg_cursor; + + + /* The frame where the mouse was last time we reported a mouse position. */ + struct frame *last_mouse_glyph_frame; +}; + +/* This is a chain of structures for all the PGTK displays currently in use. */ +extern struct pgtk_display_info *x_display_list; + +struct pgtk_output +{ +#if 0 + void *view; + void *miniimage; +#endif + unsigned long cursor_color; + unsigned long foreground_color; + unsigned long background_color; + void *toolbar; + + /* Cursors */ + Emacs_Cursor current_cursor; + Emacs_Cursor text_cursor; + Emacs_Cursor nontext_cursor; + Emacs_Cursor modeline_cursor; + Emacs_Cursor hand_cursor; + Emacs_Cursor hourglass_cursor; + Emacs_Cursor horizontal_drag_cursor; + Emacs_Cursor vertical_drag_cursor; + Emacs_Cursor left_edge_cursor; + Emacs_Cursor top_left_corner_cursor; + Emacs_Cursor top_edge_cursor; + Emacs_Cursor top_right_corner_cursor; + Emacs_Cursor right_edge_cursor; + Emacs_Cursor bottom_right_corner_cursor; + Emacs_Cursor bottom_edge_cursor; + Emacs_Cursor bottom_left_corner_cursor; + + /* PGTK-specific */ + Emacs_Cursor current_pointer; + + /* Widget whose cursor is hourglass_cursor. This widget is temporarily + mapped to display an hourglass cursor. */ + GtkWidget *hourglass_widget; + + XGCValues cursor_xgcv; + + /* lord knows why Emacs needs to know about our Window ids.. */ + Window window_desc, parent_desc; + char explicit_parent; + + struct font *font; + int baseline_offset; + + /* If a fontset is specified for this frame instead of font, this + value contains an ID of the fontset, else -1. */ + int fontset; /* only used with font_backend */ + + int icon_top; + int icon_left; + + /* The size of the extra width currently allotted for vertical + scroll bars, in pixels. */ + int vertical_scroll_bar_extra; + + /* The height of the titlebar decoration (included in PGTKWindow's frame). */ + int titlebar_height; + + /* The height of the toolbar if displayed, else 0. */ + int toolbar_height; + + /* This is the Emacs structure for the PGTK display this frame is on. */ + struct pgtk_display_info *display_info; + + /* Non-zero if we are zooming (maximizing) the frame. */ + int zooming; + + /* Non-zero if we are doing an animation, e.g. toggling the tool bar. */ + int in_animation; + + /* The last size hints set. */ + GdkGeometry size_hints; + long hint_flags; + + /* The widget of this screen. This is the window of a top widget. */ + GtkWidget *widget; + /* The widget of the edit portion of this screen; the window in + "window_desc" is inside of this. */ + GtkWidget *edit_widget; + /* The widget used for laying out widgets vertically. */ + GtkWidget *vbox_widget; + /* The widget used for laying out widgets horizontally. */ + GtkWidget *hbox_widget; + /* The menubar in this frame. */ + GtkWidget *menubar_widget; + /* The tool bar in this frame */ + GtkWidget *toolbar_widget; + /* True if tool bar is packed into the hbox widget (i.e. vertical). */ + bool_bf toolbar_in_hbox : 1; + bool_bf toolbar_is_packed : 1; + +#ifdef USE_GTK_TOOLTIP + GtkTooltip *ttip_widget; + GtkWidget *ttip_lbl; + GtkWindow *ttip_window; +#endif /* USE_GTK_TOOLTIP */ + + /* Height of menu bar widget, in pixels. This value + is not meaningful if the menubar is turned off. */ + int menubar_height; + + /* Height of tool bar widget, in pixels. top_height is used if tool bar + at top, bottom_height if tool bar is at the bottom. + Zero if not using an external tool bar or if tool bar is vertical. */ + int toolbar_top_height, toolbar_bottom_height; + + /* Width of tool bar widget, in pixels. left_width is used if tool bar + at left, right_width if tool bar is at the right. + Zero if not using an external tool bar or if tool bar is horizontal. */ + int toolbar_left_width, toolbar_right_width; + +#ifdef USE_CAIRO + /* Cairo drawing context. */ + cairo_t *cr_context; + /* Cairo surface for double buffering */ + cairo_surface_t *cr_surface; + cairo_surface_t *cr_surface_visible_bell; +#endif + struct atimer *atimer_visible_bell; + + int has_been_visible; + + /* Relief GCs, colors etc. */ + struct relief + { + XGCValues xgcv; + unsigned long pixel; + } + black_relief, white_relief; + + /* The background for which the above relief GCs were set up. + They are changed only when a different background is involved. */ + unsigned long relief_background; + + /* Keep track of focus. May be EXPLICIT if we received a FocusIn for this + frame, or IMPLICIT if we received an EnterNotify. + FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ + int focus_state; +}; + +/* this dummy decl needed to support TTYs */ +struct x_output +{ + int unused; +}; + +enum +{ + /* Values for focus_state, used as bit mask. + EXPLICIT means we received a FocusIn for the frame and know it has + the focus. IMPLICIT means we received an EnterNotify and the frame + may have the focus if no window manager is running. + FocusOut and LeaveNotify clears EXPLICIT/IMPLICIT. */ + FOCUS_NONE = 0, + FOCUS_IMPLICIT = 1, + FOCUS_EXPLICIT = 2 +}; + +/* This gives the pgtk_display_info structure for the display F is on. */ +#define FRAME_X_OUTPUT(f) ((f)->output_data.pgtk) + +#define FRAME_DISPLAY_INFO(f) (FRAME_X_OUTPUT(f)->display_info) +#define FRAME_FOREGROUND_COLOR(f) (FRAME_X_OUTPUT(f)->foreground_color) +#define FRAME_BACKGROUND_COLOR(f) (FRAME_X_OUTPUT(f)->background_color) +#define FRAME_CURSOR_COLOR(f) (FRAME_X_OUTPUT(f)->cursor_color) +#define FRAME_POINTER_TYPE(f) (FRAME_X_OUTPUT(f)->current_pointer) +#define FRAME_FONT(f) (FRAME_X_OUTPUT(f)->font) +#define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT(f)->widget) +#define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT(f)->edit_widget) + +/* aliases */ +#define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET(f) +#define FRAME_X_WINDOW(f) FRAME_GTK_WIDGET(f) + +#define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO(f)->gdpy) + +#define DEFAULT_GDK_DISPLAY() gdk_display_get_default() + +/* Turning a lisp vector value into a pointer to a struct scroll_bar. */ +#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec)) + +#define PGTK_FACE_FOREGROUND(f) ((f)->foreground) +#define PGTK_FACE_BACKGROUND(f) ((f)->background) +#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) + +/* Compute pixel height of the frame's titlebar. */ +#define FRAME_PGTK_TITLEBAR_HEIGHT(f) 0 +#if 0 + (PGTKHeight([FRAME_PGTK_VIEW (f) frame]) == 0 ? \ + 0 \ + : (int)(PGTKHeight([FRAME_PGTK_VIEW (f) window].frame) \ + - PGTKHeight([PGTKWindow contentRectForFrameRect: \ + [[FRAME_PGTK_VIEW (f) window] frame] \ + styleMask:[[FRAME_PGTK_VIEW (f) window] styleMask]]))) +#endif + +/* Compute pixel size for vertical scroll bars */ +#define PGTK_SCROLL_BAR_WIDTH(f) \ + (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ + ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \ + ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ + : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \ + : 0) + +/* Compute pixel size for horizontal scroll bars */ +#define PGTK_SCROLL_BAR_HEIGHT(f) \ + (FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) \ + ? rint (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0 \ + ? FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) \ + : (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f))) \ + : 0) + +/* Difference btwn char-column-calculated and actual SB widths. + This is only a concern for rendering when SB on left. */ +#define PGTK_SCROLL_BAR_ADJUST(w, f) \ + (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? \ + (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \ + - PGTK_SCROLL_BAR_WIDTH (f)) : 0) + +/* Difference btwn char-line-calculated and actual SB heights. + This is only a concern for rendering when SB on top. */ +#define PGTK_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f) \ + (WINDOW_HAS_HORIZONTAL_SCROLL_BARS (w) ? \ + (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \ + - PGTK_SCROLL_BAR_HEIGHT (f)) : 0) + +#define FRAME_MENUBAR_HEIGHT(f) (FRAME_X_OUTPUT(f)->menubar_height) + +/* Calculate system coordinates of the left and top of the parent + window or, if there is no parent window, the screen. */ +#define PGTK_PARENT_WINDOW_LEFT_POS(f) \ + (FRAME_PARENT_FRAME (f) != NULL \ + ? [[FRAME_PGTK_VIEW (f) window] parentWindow].frame.origin.x : 0) +#define PGTK_PARENT_WINDOW_TOP_POS(f) \ + (FRAME_PARENT_FRAME (f) != NULL \ + ? ([[FRAME_PGTK_VIEW (f) window] parentWindow].frame.origin.y \ + + [[FRAME_PGTK_VIEW (f) window] parentWindow].frame.size.height \ + - FRAME_PGTK_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f))) \ + : [[[PGTKScreen screepgtk] objectAtIndex: 0] frame].size.height) + +#define FRAME_PGTK_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table) + +#define FRAME_TOOLBAR_TOP_HEIGHT(f) ((f)->output_data.pgtk->toolbar_top_height) +#define FRAME_TOOLBAR_BOTTOM_HEIGHT(f) \ + ((f)->output_data.pgtk->toolbar_bottom_height) +#define FRAME_TOOLBAR_HEIGHT(f) \ + (FRAME_TOOLBAR_TOP_HEIGHT (f) + FRAME_TOOLBAR_BOTTOM_HEIGHT (f)) +#define FRAME_TOOLBAR_LEFT_WIDTH(f) ((f)->output_data.pgtk->toolbar_left_width) +#define FRAME_TOOLBAR_RIGHT_WIDTH(f) ((f)->output_data.pgtk->toolbar_right_width) +#define FRAME_TOOLBAR_WIDTH(f) \ + (FRAME_TOOLBAR_LEFT_WIDTH (f) + FRAME_TOOLBAR_RIGHT_WIDTH (f)) + +#define FRAME_FONTSET(f) (FRAME_X_OUTPUT(f)->fontset) + +#define FRAME_BASELINE_OFFSET(f) (FRAME_X_OUTPUT(f)->baseline_offset) +#define BLACK_PIX_DEFAULT(f) 0x000000 +#define WHITE_PIX_DEFAULT(f) 0xFFFFFF + +/* First position where characters can be shown (instead of scrollbar, if + it is on left. */ +#define FIRST_CHAR_POSITION(f) \ + (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ + : FRAME_SCROLL_BAR_COLS (f)) + + +/* Display init/shutdown functions implemented in pgtkterm.c */ +extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, char *resource_name); +extern void pgtk_term_shutdown (int sig); + +/* Implemented in pgtkterm, published in or needed from pgtkfns. */ +extern void pgtk_clear_frame (struct frame *f); +extern char *pgtk_xlfd_to_fontname (const char *xlfd); + +/* Implemented in pgtkfns. */ +extern void pgtk_set_doc_edited (void); +extern const char *pgtk_get_defaults_value (const char *key); + +/* Color management implemented in pgtkterm. */ +extern bool pgtk_defined_color (struct frame *f, + const char *name, + Emacs_Color *color_def, bool alloc, + bool makeIndex); +extern void pgtk_query_color (struct frame *f, Emacs_Color *color); +extern void pgtk_query_colors (struct frame *f, Emacs_Color *colors, int ncolors); +extern int pgtk_parse_color (const char *color_name, Emacs_Color *color); +extern int pgtk_lisp_to_color (Lisp_Object color, Emacs_Color *col); + +/* Implemented in pgtkterm.c */ +extern void pgtk_clear_area (struct frame *f, int x, int y, int width, int height); +extern int pgtk_gtk_to_emacs_modifiers (int state); +extern void pgtk_clear_under_internal_border (struct frame *f); +extern void pgtk_set_event_handler(struct frame *f); + +/* Implemented in pgtkterm.c */ +extern int x_display_pixel_height (struct pgtk_display_info *); +extern int x_display_pixel_width (struct pgtk_display_info *); + +/* Implemented in pgtkterm.c */ +extern void x_destroy_window (struct frame *f); +extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value); +extern void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value); +extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value); +extern void x_set_z_group (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value); +extern int pgtk_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timespec *timeout, + sigset_t *sigmask); + +/* Cairo related functions implemented in pgtkterm.c */ +extern cairo_t *pgtk_begin_cr_clip (struct frame *f); +extern void pgtk_end_cr_clip (struct frame *f); +extern void pgtk_set_cr_source_with_gc_foreground (struct frame *f, XGCValues *gc); +extern void pgtk_set_cr_source_with_gc_background (struct frame *f, XGCValues *gc); +extern void pgtk_set_cr_source_with_color (struct frame *f, unsigned long color); +extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f); +extern void pgtk_cr_destroy_surface(struct frame *f); + +/* Symbol initializations implemented in each pgtk sources. */ +extern void syms_of_pgtkterm (void); +extern void syms_of_pgtkfns (void); +extern void syms_of_pgtkmenu (void); +extern void syms_of_pgtkselect (void); + +/* Implemented in pgtkselect. */ +extern void nxatoms_of_pgtkselect (void); + +/* Initialization and marking implemented in pgtkterm.c */ +extern void init_pgtkterm (void); +extern void mark_pgtkterm(void); +extern void pgtk_delete_terminal (struct terminal *terminal); + +extern void pgtk_make_frame_visible (struct frame *f); +extern void pgtk_make_frame_invisible (struct frame *f); +extern void x_wm_set_size_hint (struct frame *, long, bool); +extern void x_free_frame_resources (struct frame *); +extern void pgtk_iconify_frame (struct frame *f); +extern void x_focus_frame (struct frame *f, bool noactivate); +extern void pgtk_set_scroll_bar_default_width (struct frame *f); +extern void pgtk_set_scroll_bar_default_height (struct frame *f); +extern Lisp_Object x_get_focus_frame (struct frame *frame); + + +#endif /* HAVE_PGTK */ diff --git a/src/process.c b/src/process.c index bf64ead24e..9926993fae 100644 --- a/src/process.c +++ b/src/process.c @@ -5599,8 +5599,12 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, timeout = make_timespec (0, 0); #endif +#if defined HAVE_PGTK + nfds = pgtk_select (max_desc + 1, + &Available, (check_write ? &Writeok : 0), + NULL, &timeout, NULL); +#elif defined HAVE_GLIB && !defined HAVE_NS /* Non-macOS HAVE_GLIB builds call thread_select in xgselect.c. */ -#if defined HAVE_GLIB && !defined HAVE_NS nfds = xg_select (max_desc + 1, &Available, (check_write ? &Writeok : 0), NULL, &timeout, NULL); diff --git a/src/termhooks.h b/src/termhooks.h index 44ab14225f..4403d518ff 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -60,7 +60,8 @@ enum output_method output_x_window, output_msdos_raw, output_w32, - output_ns + output_ns, + output_pgtk }; /* Input queue declarations and hooks. */ @@ -445,6 +446,7 @@ struct terminal struct x_display_info *x; /* xterm.h */ struct w32_display_info *w32; /* w32term.h */ struct ns_display_info *ns; /* nsterm.h */ + struct pgtk_display_info *pgtk; /* pgtkterm.h */ } display_info; @@ -518,7 +520,7 @@ struct terminal BGCOLOR. */ void (*query_frame_background_color) (struct frame *f, Emacs_Color *bgcolor); -#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) +#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (HAVE_PGTK) /* On frame F, translate pixel colors to RGB values for the NCOLORS colors in COLORS. Use cached information, if available. */ @@ -833,6 +835,9 @@ extern struct terminal *terminal_list; #elif defined (HAVE_NS) #define TERMINAL_FONT_CACHE(t) \ (t->type == output_ns ? t->display_info.ns->name_list_element : Qnil) +#elif defined (HAVE_PGTK) +#define TERMINAL_FONT_CACHE(t) \ + (t->type == output_pgtk ? t->display_info.pgtk->name_list_element : Qnil) #endif extern struct terminal *decode_live_terminal (Lisp_Object); diff --git a/src/terminal.c b/src/terminal.c index e3b666ba61..ef2f0c34c2 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -445,6 +445,8 @@ possible return values. */) return Qpc; case output_ns: return Qns; + case output_pgtk: + return Qpgtk; default: emacs_abort (); } diff --git a/src/xdisp.c b/src/xdisp.c index e49cc43330..e722a75780 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -14330,8 +14330,10 @@ redisplay_tool_bar (struct frame *f) f->tool_bar_redisplayed = true; #ifdef HAVE_EXT_TOOL_BAR +#if 0 if (FRAME_EXTERNAL_TOOL_BAR (f)) update_frame_tool_bar (f); +#endif return false; #else /* ! (HAVE_EXT_TOOL_BAR) */ @@ -15485,7 +15487,7 @@ redisplay_internal (void) if (!fr->glyphs_initialized_p) return; -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) +#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) if (popup_activated ()) { return; @@ -28970,6 +28972,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, return x_reached; } +static int draw_glyphs_debug(const char *file, int lineno, + struct window *w, int x, struct glyph_row *row, + enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end, + enum draw_glyphs_face hl, int overlaps) +{ + return draw_glyphs(w, x, row, area, start, end, hl, overlaps); +} +#define draw_glyphs(w, x, r, a, s, e, h, o) \ + draw_glyphs_debug(__FILE__, __LINE__, w, x, r, a, s, e, h, o) + /* Find the first glyph in the run of underlined glyphs preceding the beginning of glyph string S, and return its font (which could be NULL). This is needed because that font determines the underline @@ -32550,7 +32562,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, hlinfo->mouse_face_face_id = face_at_buffer_position (w, mouse_charpos, &ignore, mouse_charpos + 1, - !hlinfo->mouse_face_hidden, -1, 0); + !hlinfo->mouse_face_hidden, -1, 0); show_mouse_face (hlinfo, DRAW_MOUSE_FACE); } @@ -33281,7 +33293,7 @@ note_mouse_highlight (struct frame *f, int x, int y) struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (MSDOS) +#if defined (USE_X_TOOLKIT) || (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS) || defined (MSDOS) if (popup_activated ()) return; #endif diff --git a/src/xfaces.c b/src/xfaces.c index 73a536b19c..a84e52157d 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -245,6 +245,10 @@ along with GNU Emacs. If not, see . */ #ifdef HAVE_NS #define GCGraphicsExposures 0 #endif /* HAVE_NS */ + +#ifdef HAVE_PGTK +#define GCGraphicsExposures 0 +#endif /* HAVE_NS */ #endif /* HAVE_WINDOW_SYSTEM */ #include "buffer.h" @@ -571,6 +575,26 @@ x_free_gc (struct frame *f, Emacs_GC *gc) } #endif /* HAVE_NS */ +#ifdef HAVE_PGTK +/* PGTK emulation of GCs */ + +static GC +x_create_gc (struct frame *f, + unsigned long mask, + XGCValues *xgcv) +{ + GC gc = xmalloc (sizeof *gc); + *gc = *xgcv; + return gc; +} + +static void +x_free_gc (struct frame *f, GC gc) +{ + xfree (gc); +} +#endif /* HAVE_NS */ + /*********************************************************************** Frames and faces ***********************************************************************/ diff --git a/src/xsettings.c b/src/xsettings.c index 1ba1021e40..444bea0884 100644 --- a/src/xsettings.c +++ b/src/xsettings.c @@ -26,7 +26,11 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#ifndef HAVE_PGTK #include "xterm.h" +#else +#include "gtkutil.h" +#endif #include "xsettings.h" #include "frame.h" #include "keyboard.h" @@ -34,7 +38,12 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "pdumper.h" +#ifndef HAVE_PGTK #include +#else +typedef unsigned short CARD16; +typedef unsigned int CARD32; +#endif #ifdef HAVE_GSETTINGS #include @@ -55,7 +64,7 @@ along with GNU Emacs. If not, see . */ static char *current_mono_font; static char *current_font; -static struct x_display_info *first_dpyinfo; +static Display_Info *first_dpyinfo; static Lisp_Object current_tool_bar_style; /* Store a config changed event in to the event queue. */ @@ -73,14 +82,18 @@ store_config_changed_event (Lisp_Object arg, Lisp_Object display_name) /* Return true if DPYINFO is still valid. */ static bool -dpyinfo_valid (struct x_display_info *dpyinfo) +dpyinfo_valid (Display_Info *dpyinfo) { bool found = false; if (dpyinfo != NULL) { - struct x_display_info *d; + Display_Info *d; for (d = x_display_list; !found && d; d = d->next) +#ifndef HAVE_PGTK found = d == dpyinfo && d->display == dpyinfo->display; +#else + found = d == dpyinfo && d->gdpy == dpyinfo->gdpy; +#endif } return found; } @@ -149,7 +162,7 @@ map_tool_bar_style (const char *tool_bar_style) static void store_tool_bar_style_changed (const char *newstyle, - struct x_display_info *dpyinfo) + Display_Info *dpyinfo) { Lisp_Object style = map_tool_bar_style (newstyle); if (EQ (current_tool_bar_style, style)) @@ -161,10 +174,12 @@ store_tool_bar_style_changed (const char *newstyle, XCAR (dpyinfo->name_list_element)); } +#ifndef HAVE_PGTK #if defined USE_CAIRO || defined HAVE_XFT #define XSETTINGS_FONT_NAME "Gtk/FontName" #endif #define XSETTINGS_TOOL_BAR_STYLE "Gtk/ToolbarStyle" +#endif enum { SEEN_AA = 0x01, @@ -321,10 +336,11 @@ something_changed_gconfCB (GConfClient *client, #endif /* USE_CAIRO || HAVE_XFT */ +#ifndef HAVE_PGTK /* Find the window that contains the XSETTINGS property values. */ static void -get_prop_window (struct x_display_info *dpyinfo) +get_prop_window (Display_Info *dpyinfo) { Display *dpy = dpyinfo->display; @@ -339,6 +355,9 @@ get_prop_window (struct x_display_info *dpyinfo) XUngrabServer (dpy); } +#endif + +#ifndef HAVE_PGTK #define PAD(nr) (((nr) + 3) & ~3) @@ -566,13 +585,15 @@ parse_settings (unsigned char *prop, return settings_seen; } +#endif +#ifndef HAVE_PGTK /* Read settings from the XSettings property window on display for DPYINFO. Store settings read in SETTINGS. Return true iff successful. */ static bool -read_settings (struct x_display_info *dpyinfo, struct xsettings *settings) +read_settings (Display_Info *dpyinfo, struct xsettings *settings) { Atom act_type; int act_form; @@ -600,12 +621,14 @@ read_settings (struct x_display_info *dpyinfo, struct xsettings *settings) return got_settings; } +#endif +#ifndef HAVE_PGTK /* Apply Xft settings in SETTINGS to the Xft library. Store a Lisp event that Xft settings changed. */ static void -apply_xft_settings (struct x_display_info *dpyinfo, +apply_xft_settings (Display_Info *dpyinfo, struct xsettings *settings) { #ifdef HAVE_XFT @@ -731,12 +754,14 @@ apply_xft_settings (struct x_display_info *dpyinfo, FcPatternDestroy (pat); #endif /* HAVE_XFT */ } +#endif +#ifndef HAVE_PGTK /* Read XSettings from the display for DPYINFO. If SEND_EVENT_P store a Lisp event settings that changed. */ static void -read_and_apply_settings (struct x_display_info *dpyinfo, bool send_event_p) +read_and_apply_settings (Display_Info *dpyinfo, bool send_event_p) { struct xsettings settings; @@ -763,11 +788,13 @@ read_and_apply_settings (struct x_display_info *dpyinfo, bool send_event_p) } #endif } +#endif +#ifndef HAVE_PGTK /* Check if EVENT for the display in DPYINFO is XSettings related. */ void -xft_settings_event (struct x_display_info *dpyinfo, const XEvent *event) +xft_settings_event (Display_Info *dpyinfo, const XEvent *event) { bool check_window_p = false, apply_settings_p = false; @@ -805,6 +832,7 @@ xft_settings_event (struct x_display_info *dpyinfo, const XEvent *event) if (apply_settings_p) read_and_apply_settings (dpyinfo, true); } +#endif /* Initialize GSettings and read startup values. */ @@ -940,10 +968,11 @@ init_gconf (void) #endif /* HAVE_GCONF */ } +#ifndef HAVE_PGTK /* Init Xsettings and read startup values. */ static void -init_xsettings (struct x_display_info *dpyinfo) +init_xsettings (Display_Info *dpyinfo) { Display *dpy = dpyinfo->display; @@ -959,13 +988,16 @@ init_xsettings (struct x_display_info *dpyinfo) unblock_input (); } +#endif void -xsettings_initialize (struct x_display_info *dpyinfo) +xsettings_initialize (Display_Info *dpyinfo) { if (first_dpyinfo == NULL) first_dpyinfo = dpyinfo; init_gconf (); +#ifndef HAVE_PGTK init_xsettings (dpyinfo); +#endif init_gsettings (); } diff --git a/src/xsettings.h b/src/xsettings.h index f29ce77c7f..1d2f1c69c9 100644 --- a/src/xsettings.h +++ b/src/xsettings.h @@ -20,12 +20,23 @@ along with GNU Emacs. If not, see . */ #ifndef XSETTINGS_H #define XSETTINGS_H +#ifndef HAVE_PGTK #include +#endif struct x_display_info; +struct pgtk_display_info; + +#ifndef HAVE_PGTK +typedef struct x_display_info Display_Info; +#else +typedef struct pgtk_display_info Display_Info; +#endif -extern void xsettings_initialize (struct x_display_info *); -extern void xft_settings_event (struct x_display_info *, const XEvent *); +extern void xsettings_initialize (Display_Info *); +#ifndef HAVE_PGTK +extern void xft_settings_event (Display_Info *, const XEvent *); +#endif extern const char *xsettings_get_system_font (void); #ifdef USE_LUCID extern const char *xsettings_get_system_normal_font (void);