summaryrefslogtreecommitdiff
path: root/src/androidfns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/androidfns.c')
-rw-r--r--src/androidfns.c3574
1 files changed, 3574 insertions, 0 deletions
diff --git a/src/androidfns.c b/src/androidfns.c
new file mode 100644
index 00000000000..14561afe29a
--- /dev/null
+++ b/src/androidfns.c
@@ -0,0 +1,3574 @@
+/* Communication module for Android terminals.
+
+Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <math.h>
+
+#include "lisp.h"
+#include "android.h"
+#include "androidterm.h"
+#include "blockinput.h"
+#include "keyboard.h"
+#include "buffer.h"
+#include "androidgui.h"
+#include "pdumper.h"
+
+#ifndef ANDROID_STUBIFY
+
+/* Some kind of reference count for the image cache. */
+static ptrdiff_t image_cache_refcount;
+
+/* The frame of the currently visible tooltip, or nil if none. */
+static Lisp_Object tip_frame;
+
+/* The window-system window corresponding to the frame of the
+ currently visible tooltip. */
+static android_window tip_window;
+
+/* The X and Y deltas of the last call to `x-show-tip'. */
+static Lisp_Object tip_dx, tip_dy;
+
+/* 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;
+
+#endif
+
+static struct android_display_info *
+android_display_info_for_name (Lisp_Object name)
+{
+ struct android_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;
+ }
+
+ error ("Cannot connect to Android if it was not initialized"
+ " at startup");
+}
+
+static struct android_display_info *
+check_android_display_info (Lisp_Object object)
+{
+ struct android_display_info *dpyinfo;
+ struct frame *sf, *f;
+ struct terminal *t;
+
+ if (NILP (object))
+ {
+ sf = XFRAME (selected_frame);
+
+ if (FRAME_ANDROID_P (sf) && FRAME_LIVE_P (sf))
+ dpyinfo = FRAME_DISPLAY_INFO (sf);
+ else if (x_display_list)
+ dpyinfo = x_display_list;
+ else
+ error ("Android windows are not in use or not initialized");
+ }
+ else if (TERMINALP (object))
+ {
+ t = decode_live_terminal (object);
+
+ if (t->type != output_android)
+ error ("Terminal %d is not an Android display", t->id);
+
+ dpyinfo = t->display_info.android;
+ }
+ else if (STRINGP (object))
+ dpyinfo = android_display_info_for_name (object);
+ else
+ {
+ f = decode_window_system_frame (object);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+ }
+
+ return dpyinfo;
+}
+
+Display_Info *
+check_x_display_info (Lisp_Object object)
+{
+ return check_android_display_info (object);
+}
+
+
+
+#ifndef ANDROID_STUBIFY
+
+void
+gamma_correct (struct frame *f, Emacs_Color *color)
+{
+ if (f->gamma)
+ {
+ color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
+ color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
+ color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
+ }
+}
+
+/* Decide if color named COLOR_NAME is valid for use on frame F. If
+ so, return the RGB values in COLOR. If ALLOC_P, allocate the
+ color. Value is false if COLOR_NAME is invalid, or no color could
+ be allocated. MAKE_INDEX is some mysterious argument used on
+ NS. */
+
+bool
+android_defined_color (struct frame *f, const char *color_name,
+ Emacs_Color *color, bool alloc_p,
+ bool make_index)
+{
+ bool success_p;
+
+ success_p = false;
+
+ block_input ();
+ success_p = android_parse_color (f, color_name, color);
+ if (success_p && alloc_p)
+ success_p = android_alloc_nearest_color (f, color);
+ unblock_input ();
+
+ return success_p;
+}
+
+/* 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 unsigned long
+android_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
+{
+ Emacs_Color cdef;
+
+ CHECK_STRING (color_name);
+
+ if (android_defined_color (f, SSDATA (color_name), &cdef,
+ true, false))
+ return cdef.pixel;
+
+ signal_error ("Undefined color", color_name);
+}
+
+static void
+android_set_parent_frame (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ struct frame *p;
+
+ p = NULL;
+
+ if (!NILP (new_value)
+ && (!FRAMEP (new_value)
+ || !FRAME_LIVE_P (p = XFRAME (new_value))
+ || !FRAME_ANDROID_P (p)))
+ {
+ store_frame_param (f, Qparent_frame, old_value);
+ error ("Invalid specification of `parent-frame'");
+ }
+
+ if (p != FRAME_PARENT_FRAME (f))
+ {
+ block_input ();
+ android_reparent_window (FRAME_ANDROID_WINDOW (f),
+ (p ? FRAME_ANDROID_WINDOW (p)
+ : FRAME_DISPLAY_INFO (f)->root_window),
+ f->left_pos, f->top_pos);
+ unblock_input ();
+
+ fset_parent_frame (f, new_value);
+ }
+
+ /* Update the fullscreen frame parameter as well. */
+ FRAME_TERMINAL (f)->fullscreen_hook (f);
+}
+
+void
+android_implicitly_set_name (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+
+}
+
+void
+android_explicitly_set_name (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+
+}
+
+/* Set the number of lines used for the tool bar of frame F to VALUE.
+ VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
+ is the old number of tool bar lines. This function changes the
+ height of all windows on frame F to match the new tool bar height.
+ The frame's height doesn't change. */
+
+static void
+android_set_tool_bar_lines (struct frame *f, Lisp_Object value,
+ Lisp_Object oldval)
+{
+ int nlines;
+
+ /* Treat tool 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;
+
+ android_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+}
+
+static void
+android_set_tool_bar_position (struct frame *f,
+ Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ if (!EQ (new_value, Qtop) && !EQ (new_value, Qbottom))
+ error ("Tool bar position must be either `top' or `bottom'");
+
+ if (EQ (new_value, old_value))
+ return;
+
+ /* Set the tool bar position. */
+ fset_tool_bar_position (f, new_value);
+
+ /* Now reconfigure frame glyphs to place the tool bar at the
+ bottom. While the inner height has not changed, call
+ `resize_frame_windows' to place each of the windows at its
+ new position. */
+
+ adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_position);
+ adjust_frame_glyphs (f);
+ SET_FRAME_GARBAGED (f);
+
+ if (FRAME_ANDROID_WINDOW (f))
+ android_clear_under_internal_border (f);
+}
+
+void
+android_change_tool_bar_height (struct frame *f, int height)
+{
+ int unit = FRAME_LINE_HEIGHT (f);
+ int old_height = FRAME_TOOL_BAR_HEIGHT (f);
+ int lines = (height + unit - 1) / unit;
+ Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
+
+ /* Make sure we redisplay all windows in this frame. */
+ fset_redisplay (f);
+
+ FRAME_TOOL_BAR_HEIGHT (f) = height;
+ FRAME_TOOL_BAR_LINES (f) = lines;
+ store_frame_param (f, Qtool_bar_lines, make_fixnum (lines));
+
+ if (FRAME_ANDROID_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
+ {
+ clear_frame (f);
+ clear_current_matrices (f);
+ }
+
+ if ((height < old_height) && WINDOWP (f->tool_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+
+ if (!f->tool_bar_resized)
+ {
+ /* As long as tool_bar_resized is false, effectively try to change
+ F's native height. */
+ if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+ 1, false, Qtool_bar_lines);
+ else
+ adjust_frame_size (f, -1, -1, 4, false, Qtool_bar_lines);
+
+ f->tool_bar_resized = f->tool_bar_redisplayed;
+ }
+ else
+ /* Any other change may leave the native size of F alone. */
+ adjust_frame_size (f, -1, -1, 3, false, Qtool_bar_lines);
+
+ /* adjust_frame_size might not have done anything, garbage frame
+ here. */
+ adjust_frame_glyphs (f);
+ SET_FRAME_GARBAGED (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 may change the
+ height of all windows on frame F to match the new tab bar height.
+ The frame's height may change if frame_inhibit_implied_resize was
+ set accordingly. */
+
+static void
+android_set_tab_bar_lines (struct frame *f, Lisp_Object value,
+ Lisp_Object oldval)
+{
+ int olines;
+ int nlines;
+
+ olines = FRAME_TAB_BAR_LINES (f);
+
+ /* 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;
+
+ if (nlines != olines && (olines == 0 || nlines == 0))
+ android_change_tab_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
+}
+
+void
+android_change_tab_bar_height (struct frame *f, int height)
+{
+ int unit, old_height, lines;
+ Lisp_Object fullscreen;
+
+ unit = FRAME_LINE_HEIGHT (f);
+ old_height = FRAME_TAB_BAR_HEIGHT (f);
+ fullscreen = get_frame_param (f, Qfullscreen);
+
+ /* This differs from the tool bar code in that the tab bar height is
+ not rounded up. Otherwise, if redisplay_tab_bar decides to grow
+ the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
+ leading to the tab bar height being incorrectly set upon the next
+ call to android_set_font. (bug#59285) */
+
+ lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
+ if (lines == 0 && height != 0)
+ lines = 1;
+
+ /* 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_frame_param (f, Qtab_bar_lines, make_fixnum (lines));
+
+ if (FRAME_ANDROID_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);
+
+ if (!f->tab_bar_resized)
+ {
+ /* As long as tab_bar_resized is false, effectively try to change
+ F's native height. */
+ if (NILP (fullscreen) || EQ (fullscreen, Qfullwidth))
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+ 1, false, Qtab_bar_lines);
+ else
+ adjust_frame_size (f, -1, -1, 4, false, Qtab_bar_lines);
+
+ f->tab_bar_resized = f->tab_bar_redisplayed;
+ }
+ else
+ /* Any other change may leave the native size of F alone. */
+ adjust_frame_size (f, -1, -1, 3, false, Qtab_bar_lines);
+
+ /* adjust_frame_size might not have done anything, garbage frame
+ here. */
+ adjust_frame_glyphs (f);
+ SET_FRAME_GARBAGED (f);
+}
+
+void
+android_set_scroll_bar_default_height (struct frame *f)
+{
+ int height;
+
+ height = FRAME_LINE_HEIGHT (f);
+
+ /* The height of a non-toolkit scrollbar is 14 pixels. */
+ FRAME_CONFIG_SCROLL_BAR_LINES (f) = (14 + height - 1) / height;
+
+ /* Use all of that space (aside from required margins) for the
+ scroll bar. */
+ FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = 14;
+}
+
+void
+android_set_scroll_bar_default_width (struct frame *f)
+{
+ int unit;
+
+ unit = FRAME_COLUMN_WIDTH (f);
+
+ FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f)
+ = FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
+}
+
+
+/* Verify that the icon position args for this window are valid. */
+
+static void
+android_icon_verify (struct frame *f, Lisp_Object parms)
+{
+ Lisp_Object icon_x, icon_y;
+
+ /* Set the position of the icon. Note that twm groups all
+ icons in an icon window. */
+ icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0,
+ RES_TYPE_NUMBER);
+ icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0,
+ RES_TYPE_NUMBER);
+
+ if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound))
+ {
+ CHECK_FIXNUM (icon_x);
+ CHECK_FIXNUM (icon_y);
+ }
+ else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound))
+ error ("Both left and top icon corners of icon must be specified");
+}
+
+/* Handle the icon stuff for this window. Perhaps later we might
+ want an x_set_icon_position which can be called interactively as
+ well. */
+
+static void
+android_icon (struct frame *f, Lisp_Object parms)
+{
+ /* Set the position of the icon. Note that twm groups all
+ icons in an icon window. */
+ Lisp_Object icon_x
+ = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0,
+ RES_TYPE_NUMBER);
+ Lisp_Object icon_y
+ = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0,
+ RES_TYPE_NUMBER);
+
+ bool xgiven = !BASE_EQ (icon_x, Qunbound);
+ bool ygiven = !BASE_EQ (icon_y, Qunbound);
+
+ if (xgiven != ygiven)
+ error ("Both left and top icon corners of icon must be specified");
+
+ if (xgiven)
+ {
+ check_integer_range (icon_x, INT_MIN, INT_MAX);
+ check_integer_range (icon_y, INT_MIN, INT_MAX);
+ }
+
+ /* Now return as this is not supported on Android. */
+}
+
+/* Make the GCs needed for this window, setting the background
+ color. */
+
+static void
+android_make_gc (struct frame *f)
+{
+ struct android_gc_values gc_values;
+
+ block_input ();
+
+ /* Create the GCs of this frame.
+ Note that many default values are used. */
+
+ gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
+ gc_values.background = FRAME_BACKGROUND_PIXEL (f);
+ f->output_data.android->normal_gc
+ = android_create_gc (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND,
+ &gc_values);
+
+ /* Reverse video style. */
+ gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+ gc_values.background = FRAME_FOREGROUND_PIXEL (f);
+ f->output_data.android->reverse_gc
+ = android_create_gc (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND,
+ &gc_values);
+
+ /* Cursor has cursor-color background, background-color foreground. */
+ gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+ gc_values.background = f->output_data.android->cursor_pixel;
+ f->output_data.android->cursor_gc
+ = android_create_gc (ANDROID_GC_FOREGROUND | ANDROID_GC_BACKGROUND,
+ &gc_values);
+ unblock_input ();
+}
+
+
+/* Free what was allocated in android_make_gc. */
+
+void
+android_free_gcs (struct frame *f)
+{
+ block_input ();
+
+ if (f->output_data.android->normal_gc)
+ {
+ android_free_gc (f->output_data.android->normal_gc);
+ f->output_data.android->normal_gc = 0;
+ }
+
+ if (f->output_data.android->reverse_gc)
+ {
+ android_free_gc (f->output_data.android->reverse_gc);
+ f->output_data.android->reverse_gc = 0;
+ }
+
+ if (f->output_data.android->cursor_gc)
+ {
+ android_free_gc (f->output_data.android->cursor_gc);
+ f->output_data.android->cursor_gc = 0;
+ }
+
+ unblock_input ();
+}
+
+/* Handler for signals raised during x_create_frame and
+ Fx_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 Fx_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++;
+
+ android_free_frame_resources (f);
+ free_glyphs (f);
+ return Qt;
+ }
+
+ return Qnil;
+}
+
+static void
+do_unwind_create_frame (Lisp_Object frame)
+{
+ unwind_create_frame (frame);
+}
+
+void
+android_default_font_parameter (struct frame *f, Lisp_Object parms)
+{
+ struct android_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 = Qnil;
+ if (BASE_EQ (font_param, Qunbound))
+ font_param = Qnil;
+
+ if (NILP (font))
+ font = (!NILP (font_param)
+ ? font_param
+ : gui_display_get_arg (dpyinfo, parms,
+ Qfont, "font", "Font",
+ RES_TYPE_STRING));
+
+ if (! FONTP (font) && ! STRINGP (font))
+ {
+ const char *names[] = {
+ "Droid Sans Mono-12",
+ "Monospace-12",
+ "DroidSansMono-12",
+ 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");
+ }
+
+ gui_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+}
+
+static void
+android_create_frame_window (struct frame *f)
+{
+ struct android_set_window_attributes attributes;
+ enum android_window_value_mask attribute_mask;
+
+ attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+ attribute_mask = ANDROID_CW_BACK_PIXEL;
+
+ block_input ();
+ FRAME_ANDROID_WINDOW (f)
+ = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
+ f->left_pos,
+ f->top_pos,
+ FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f),
+ attribute_mask, &attributes);
+ unblock_input ();
+}
+
+#endif /* ANDROID_STUBIFY */
+
+
+
+DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
+ 1, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object parms)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ struct frame *f;
+ Lisp_Object frame, tem;
+ Lisp_Object name;
+ bool minibuffer_only;
+ bool undecorated, override_redirect;
+ long window_prompting;
+ specpdl_ref count;
+ Lisp_Object display;
+ struct android_display_info *dpyinfo;
+ Lisp_Object parent, parent_frame;
+ struct kboard *kb;
+
+ minibuffer_only = false;
+ undecorated = false;
+ override_redirect = false;
+ window_prompting = 0;
+ count = SPECPDL_INDEX ();
+ dpyinfo = NULL;
+
+ /* Not actually used, but be consistent with X. */
+ ((void) window_prompting);
+
+ 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 = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0,
+ RES_TYPE_NUMBER);
+ if (BASE_EQ (display, Qunbound))
+ display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0,
+ RES_TYPE_STRING);
+ if (BASE_EQ (display, Qunbound))
+ display = Qnil;
+ dpyinfo = check_android_display_info (display);
+ kb = dpyinfo->terminal->kboard;
+
+ 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)
+ && ! BASE_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);
+ if (BASE_EQ (parent, Qunbound))
+ parent = Qnil;
+ if (! NILP (parent))
+ CHECK_FIXNUM (parent);
+
+ frame = Qnil;
+ 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))
+ {
+ 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 = 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)
+ || BASE_EQ (parent_frame, Qunbound)
+ || NILP (parent_frame)
+ || !FRAMEP (parent_frame)
+ || !FRAME_LIVE_P (XFRAME (parent_frame))
+ || !FRAME_ANDROID_P (XFRAME (parent_frame)))
+ parent_frame = Qnil;
+
+ 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)))
+ && !(BASE_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)))
+ && !(BASE_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_android;
+ f->output_data.android = xzalloc (sizeof *f->output_data.android);
+ FRAME_FONTSET (f) = -1;
+ f->output_data.android->scroll_bar_foreground_pixel = -1;
+ f->output_data.android->scroll_bar_background_pixel = -1;
+ f->output_data.android->white_relief.pixel = -1;
+ f->output_data.android->black_relief.pixel = -1;
+
+ fset_icon_name (f, 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;
+
+ /* 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!
+
+ (Not really on Android, but it's best to be consistent with
+ X.) */
+ {
+ 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.android->cursor_pixel = -1;
+ f->output_data.android->cursor_foreground_pixel = -1;
+ f->output_data.android->mouse_pixel = -1;
+
+ black = build_string ("black");
+ FRAME_FOREGROUND_PIXEL (f)
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ FRAME_BACKGROUND_PIXEL (f)
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->cursor_pixel
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->cursor_foreground_pixel
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->mouse_pixel
+ = android_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 (BASE_EQ (name, Qunbound) || NILP (name))
+ {
+ fset_name (f, build_string ("GNU Emacs"));
+ 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 (&androidfont_driver, f);
+ register_font_driver (&android_sfntfont_driver, f);
+
+ image_cache_refcount = (FRAME_IMAGE_CACHE (f)
+ ? FRAME_IMAGE_CACHE (f)->refcount
+ : 0);
+
+ 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. */
+ android_default_font_parameter (f, parms);
+ if (!FRAME_FONT (f))
+ {
+ delete_frame (frame, Qnoelisp);
+ error ("Invalid frame font");
+ }
+
+ 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 (! BASE_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);
+
+ /* 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,
+ "childFrameBorder", "childFrameBorder",
+ RES_TYPE_NUMBER);
+ if (! BASE_EQ (value, Qunbound))
+ parms = Fcons (Fcons (Qchild_frame_border_width, value),
+ parms);
+ }
+
+ gui_default_parameter (f, parms, Qchild_frame_border_width, Qnil,
+ "childFrameBorderWidth", "childFrameBorderWidth",
+ 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);
+
+ /* `vertical-scroll-bars' defaults to nil on Android as a
+ consequence of scroll bars not being supported at all. */
+
+ gui_default_parameter (f, parms, Qvertical_scroll_bars, Qnil,
+ "verticalScrollBars", "ScrollBars",
+ RES_TYPE_SYMBOL);
+ 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. */
+ 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, Qborder_color, build_string ("black"),
+ "borderColor", "BorderColor", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qscreen_gamma, Qnil,
+ "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
+ gui_default_parameter (f, parms, Qline_spacing, Qnil,
+ "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qleft_fringe, Qnil,
+ "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qright_fringe, Qnil,
+ "rightFringe", "RightFringe", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qno_special_glyphs, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+#if 0
+ android_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
+ "scrollBarForeground",
+ "ScrollBarForeground", true);
+ android_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_background,
+ "scrollBarBackground",
+ "ScrollBarBackground", false);
+#endif
+
+ /* 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);
+
+ tem = gui_display_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL,
+ RES_TYPE_NUMBER);
+ if (FIXNUMP (tem))
+ store_frame_param (f, Qmin_width, tem);
+ tem = gui_display_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL,
+ RES_TYPE_NUMBER);
+ if (FIXNUMP (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. */
+
+ gui_default_parameter (f, parms, Qmenu_bar_lines,
+ 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),
+ NULL, NULL, RES_TYPE_NUMBER);
+
+ gui_default_parameter (f, parms, Qbuffer_predicate, Qnil,
+ "bufferPredicate", "BufferPredicate",
+ RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qtitle, Qnil,
+ "title", "Title", RES_TYPE_STRING);
+ gui_default_parameter (f, parms, Qwait_for_wm, Qt,
+ "waitForWM", "WaitForWM", RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qtool_bar_position,
+ FRAME_TOOL_BAR_POSITION (f), 0, 0, RES_TYPE_SYMBOL);
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
+ /* Compute the size of the X window. */
+ window_prompting = gui_figure_window_size (f, parms, true, true);
+
+ tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0,
+ RES_TYPE_BOOLEAN);
+ f->no_split = minibuffer_only || EQ (tem, Qt);
+
+ android_icon_verify (f, parms);
+ android_create_frame_window (f);
+ android_icon (f, parms);
+ android_make_gc (f);
+
+ /* Now consider the frame official. */
+ f->terminal->reference_count++;
+ Vframe_list = Fcons (frame, Vframe_list);
+
+ /* We need to do this after creating the 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);
+
+ 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);
+ /* Scroll bars are not supported on Android, as they are near
+ useless. */
+ gui_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+ "scrollBarWidth", "ScrollBarWidth",
+ RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qscroll_bar_height, Qnil,
+ "scrollBarHeight", "ScrollBarHeight",
+ RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha, Qnil,
+ "alpha", "Alpha", RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+
+ if (!NILP (parent_frame))
+ {
+ struct frame *p = XFRAME (parent_frame);
+
+ block_input ();
+ android_reparent_window (FRAME_ANDROID_WINDOW (f),
+ FRAME_ANDROID_WINDOW (p),
+ f->left_pos, f->top_pos);
+ unblock_input ();
+ }
+
+ gui_default_parameter (f, parms, Qno_focus_on_map, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+ gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+ /* Consider frame official, now. */
+ f->can_set_window_size = true;
+
+ 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. Note that Android only supports the
+ `maximized' state. */
+ gui_default_parameter (f, parms, Qfullscreen, Qmaximized,
+ "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
+
+ /* When called from `x-create-frame-with-faces' visibility is
+ always explicitly nil. */
+ Lisp_Object visibility
+ = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
+ RES_TYPE_SYMBOL);
+ Lisp_Object height
+ = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ Lisp_Object width
+ = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+
+ if (EQ (visibility, Qicon))
+ {
+ f->was_invisible = true;
+ android_iconify_frame (f);
+ }
+ else
+ {
+ if (BASE_EQ (visibility, Qunbound))
+ visibility = Qt;
+
+ if (!NILP (visibility))
+ android_make_frame_visible (f);
+ else
+ f->was_invisible = true;
+ }
+
+ /* Leave f->was_invisible true only if height or width were
+ specified too. This takes effect only when we are not called
+ from `x-create-frame-with-faces' (see above comment). */
+ f->was_invisible
+ = (f->was_invisible
+ && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound)));
+
+ store_frame_param (f, Qvisibility, visibility);
+
+ /* Set whether or not frame synchronization is enabled. */
+ gui_default_parameter (f, parms, Quse_frame_synchronization, Qt,
+ NULL, NULL, RES_TYPE_BOOLEAN);
+
+ /* Works iff frame has been already mapped. */
+ gui_default_parameter (f, parms, Qskip_taskbar, Qnil,
+ 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);
+
+ /* 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
+ 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));
+
+ /* Make sure windows on this frame appear in calls to next-window
+ and similar functions. */
+ Vwindow_list = Qnil;
+
+ return unbind_to (count, frame);
+#endif
+}
+
+DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p,
+ 1, 2, 0, doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object color, Lisp_Object frame)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ Emacs_Color foo;
+ struct frame *f;
+
+ f = decode_window_system_frame (frame);
+
+ CHECK_STRING (color);
+
+ if (android_defined_color (f, SSDATA (color), &foo, false, false))
+ return Qt;
+ else
+ return Qnil;
+#endif
+}
+
+DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2,
+ 0, doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object color, Lisp_Object frame)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ Emacs_Color foo;
+ struct frame *f;
+
+ f = decode_window_system_frame (frame);
+
+ CHECK_STRING (color);
+
+ if (android_defined_color (f, SSDATA (color), &foo, false, false))
+ return list3i (foo.red, foo.green, foo.blue);
+ else
+ return Qnil;
+#endif
+}
+
+DEFUN ("xw-display-color-p", Fxw_display_color_p,
+ Sxw_display_color_p, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ return Qt;
+}
+
+DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
+ Sx_display_grayscale_p, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ return Qnil;
+}
+
+DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
+ Sx_display_pixel_width, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ return make_fixnum (android_get_screen_width ());
+#endif
+}
+
+DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
+ Sx_display_pixel_height, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ return make_fixnum (android_get_screen_height ());
+#endif
+}
+
+DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
+ 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ struct android_display_info *dpyinfo;
+
+ dpyinfo = check_android_display_info (terminal);
+
+ return make_fixnum (dpyinfo->n_planes);
+}
+
+DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
+ 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ struct android_display_info *dpyinfo;
+ int nr_planes;
+
+ dpyinfo = check_android_display_info (terminal);
+ nr_planes = dpyinfo->n_planes;
+
+ /* Truncate nr_planes to 24 to avoid integer overflow. */
+
+ if (nr_planes > 24)
+ nr_planes = 24;
+
+ return make_fixnum (1 << nr_planes);
+}
+
+DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ check_android_display_info (terminal);
+ return Vandroid_build_manufacturer;
+#endif
+}
+
+DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ check_android_display_info (terminal);
+ return list3i (android_get_current_api_level (), 0, 0);
+#endif
+}
+
+DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens,
+ 0, 1, 0, doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ check_android_display_info (terminal);
+ return make_fixnum (1);
+}
+
+DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width,
+ 0, 1, 0, doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ return make_fixnum (android_get_mm_width ());
+#endif
+}
+
+DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height,
+ 0, 1, 0, doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ return make_fixnum (android_get_mm_height ());
+#endif
+}
+
+DEFUN ("x-display-backing-store", Fx_display_backing_store,
+ Sx_display_backing_store, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ check_android_display_info (terminal);
+
+ /* Window contents are preserved insofar as they remain mapped, in a
+ fashion tantamount to WhenMapped. */
+ return Qwhen_mapped;
+}
+
+DEFUN ("x-display-visual-class", Fx_display_visual_class,
+ Sx_display_visual_class, 0, 1, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object terminal)
+{
+ check_android_display_info (terminal);
+
+ return Qtrue_color;
+}
+
+#ifndef ANDROID_STUBIFY
+
+static Lisp_Object
+android_make_monitor_attribute_list (struct MonitorInfo *monitors,
+ int n_monitors,
+ int primary_monitor)
+{
+ Lisp_Object monitor_frames;
+ Lisp_Object frame, rest;
+ struct frame *f;
+
+ monitor_frames = make_nil_vector (n_monitors);
+
+ FOR_EACH_FRAME (rest, frame)
+ {
+ f = XFRAME (frame);
+
+ /* Associate all frames with the primary monitor. */
+
+ if (FRAME_WINDOW_P (f)
+ && !FRAME_TOOLTIP_P (f))
+ ASET (monitor_frames, primary_monitor,
+ Fcons (frame, AREF (monitor_frames,
+ primary_monitor)));
+ }
+
+ return make_monitor_attribute_list (monitors, n_monitors,
+ primary_monitor,
+ monitor_frames, NULL);
+}
+
+#endif
+
+DEFUN ("android-display-monitor-attributes-list",
+ Fandroid_display_monitor_attributes_list,
+ Sandroid_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)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ struct MonitorInfo monitor;
+
+ memset (&monitor, 0, sizeof monitor);
+ monitor.geom.width = android_get_screen_width ();
+ monitor.geom.height = android_get_screen_height ();
+ monitor.mm_width = android_get_mm_width ();
+ monitor.mm_height = android_get_mm_height ();
+ monitor.work = monitor.geom;
+ monitor.name = (char *) "Android device monitor";
+
+ return android_make_monitor_attribute_list (&monitor, 1, 0);
+#endif
+}
+
+#ifndef ANDROID_STUBIFY
+
+static Lisp_Object
+frame_geometry (Lisp_Object frame, Lisp_Object attribute)
+{
+ struct frame *f = decode_live_frame (frame);
+ android_window rootw;
+ unsigned int native_width, native_height, x_border_width = 0;
+ int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
+ int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
+ int outer_left, outer_top, outer_right, outer_bottom;
+ int native_left, native_top, native_right, native_bottom;
+ int inner_left, inner_top, inner_right, inner_bottom;
+ int internal_border_width;
+ bool menu_bar_external = false, tool_bar_external = false;
+ int menu_bar_height = 0, menu_bar_width = 0;
+ int tab_bar_height = 0, tab_bar_width = 0;
+ int tool_bar_height = 0, tool_bar_width = 0;
+
+ if (FRAME_INITIAL_P (f) || !FRAME_ANDROID_P (f)
+ || !FRAME_ANDROID_WINDOW (f))
+ return Qnil;
+
+ block_input ();
+ android_get_geometry (FRAME_ANDROID_WINDOW (f),
+ &rootw, &x_native, &y_native,
+ &native_width, &native_height, &x_border_width);
+ unblock_input ();
+
+ if (FRAME_PARENT_FRAME (f))
+ {
+ Lisp_Object parent, edges;
+
+ XSETFRAME (parent, FRAME_PARENT_FRAME (f));
+ edges = Fandroid_frame_edges (parent, Qnative_edges);
+ if (!NILP (edges))
+ {
+ x_native += XFIXNUM (Fnth (make_fixnum (0), edges));
+ y_native += XFIXNUM (Fnth (make_fixnum (1), edges));
+ }
+
+ outer_left = x_native;
+ outer_top = y_native;
+ outer_right = outer_left + native_width + 2 * x_border_width;
+ outer_bottom = outer_top + native_height + 2 * x_border_width;
+
+ native_left = x_native + x_border_width;
+ native_top = y_native + x_border_width;
+ native_right = native_left + native_width;
+ native_bottom = native_top + native_height;
+ }
+ else
+ {
+ outer_left = xptr;
+ outer_top = yptr;
+ outer_right = outer_left + left_off + native_width + right_off;
+ outer_bottom = outer_top + top_off + native_height + bottom_off;
+
+ native_left = outer_left + left_off;
+ native_top = outer_top + top_off;
+ native_right = native_left + native_width;
+ native_bottom = native_top + native_height;
+ }
+
+ internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+ inner_left = native_left + internal_border_width;
+ inner_top = native_top + internal_border_width;
+ inner_right = native_right - internal_border_width;
+ inner_bottom = native_bottom - internal_border_width;
+
+ menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+ inner_top += menu_bar_height;
+ menu_bar_width = menu_bar_height ? native_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;
+
+ tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
+ tool_bar_width = (tool_bar_height
+ ? native_width - 2 * internal_border_width
+ : 0);
+
+ /* Subtract or add to the inner dimensions based on the tool bar
+ position. */
+
+ if (EQ (FRAME_TOOL_BAR_POSITION (f), Qtop))
+ inner_top += tool_bar_height;
+ else
+ inner_bottom -= tool_bar_height;
+
+ /* Construct list. */
+ if (EQ (attribute, Qouter_edges))
+ return list4i (outer_left, outer_top, outer_right, outer_bottom);
+ else if (EQ (attribute, Qnative_edges))
+ return list4i (native_left, native_top, native_right, native_bottom);
+ else if (EQ (attribute, Qinner_edges))
+ return list4i (inner_left, inner_top, inner_right, inner_bottom);
+ else
+ return
+ list (Fcons (Qouter_position,
+ Fcons (make_fixnum (outer_left),
+ make_fixnum (outer_top))),
+ Fcons (Qouter_size,
+ Fcons (make_fixnum (outer_right - outer_left),
+ make_fixnum (outer_bottom - outer_top))),
+ /* Approximate. */
+ Fcons (Qexternal_border_size,
+ Fcons (make_fixnum (right_off),
+ make_fixnum (bottom_off))),
+ Fcons (Qouter_border_width, make_fixnum (x_border_width)),
+ /* Approximate. */
+ Fcons (Qtitle_bar_size,
+ Fcons (make_fixnum (0),
+ make_fixnum (top_off - bottom_off))),
+ Fcons (Qmenu_bar_external, menu_bar_external ? Qt : Qnil),
+ Fcons (Qmenu_bar_size,
+ Fcons (make_fixnum (menu_bar_width),
+ make_fixnum (menu_bar_height))),
+ Fcons (Qtab_bar_size,
+ Fcons (make_fixnum (tab_bar_width),
+ make_fixnum (tab_bar_height))),
+ Fcons (Qtool_bar_external, tool_bar_external ? 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)));
+}
+
+#endif
+
+DEFUN ("android-frame-geometry", Fandroid_frame_geometry,
+ Sandroid_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)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ return frame_geometry (frame, Qnil);
+#endif
+}
+
+DEFUN ("android-frame-edges", Fandroid_frame_edges,
+ Sandroid_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)
+{
+#ifndef ANDROID_STUBIFY
+ return frame_geometry (frame, ((EQ (type, Qouter_edges)
+ || EQ (type, Qinner_edges))
+ ? type
+ : Qnative_edges));
+#else
+ return Qnil;
+#endif
+}
+
+#ifndef ANDROID_STUBIFY
+
+static Lisp_Object
+android_frame_list_z_order (struct android_display_info *dpyinfo,
+ android_window window)
+{
+ android_window root, parent, *children;
+ unsigned int nchildren;
+ unsigned long i;
+ Lisp_Object frames;
+
+ frames = Qnil;
+
+ if (android_query_tree (window, &root, &parent,
+ &children, &nchildren))
+ {
+ for (i = 0; i < nchildren; i++)
+ {
+ Lisp_Object frame, tail;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ struct frame *cf = XFRAME (frame);
+
+ if (FRAME_ANDROID_P (cf)
+ && (FRAME_ANDROID_WINDOW (cf) == children[i]))
+ frames = Fcons (frame, frames);
+ }
+ }
+
+ if (children)
+ xfree (children);
+ }
+
+ return frames;
+}
+
+#endif
+
+DEFUN ("android-frame-list-z-order", Fandroid_frame_list_z_order,
+ Sandroid_frame_list_z_order, 0, 1, 0,
+ doc: /* Return list of Emacs' frames, in Z (stacking) order.
+The optional argument TERMINAL specifies which display to ask about.
+TERMINAL should be either a frame or a display name (a string). If
+omitted or nil, that stands for the selected frame's display. Return
+nil if TERMINAL contains no Emacs frame.
+
+As a special case, 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 Android, the order of the frames returned is undefined unless
+TERMINAL is a frame. */)
+ (Lisp_Object terminal)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ struct android_display_info *dpyinfo;
+ android_window window;
+
+ dpyinfo = check_android_display_info (terminal);
+
+ if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
+ window = FRAME_ANDROID_WINDOW (XFRAME (terminal));
+ else
+ window = dpyinfo->root_window;
+
+ return android_frame_list_z_order (dpyinfo, window);
+#endif
+}
+
+#ifndef ANDROID_STUBIFY
+
+static void
+android_frame_restack (struct frame *f1, struct frame *f2,
+ bool above_flag)
+{
+ android_window window1;
+ struct android_window_changes wc;
+ unsigned long mask;
+
+ window1 = FRAME_ANDROID_WINDOW (f1);
+ wc.sibling = FRAME_ANDROID_WINDOW (f2);
+ wc.stack_mode = above_flag ? ANDROID_ABOVE : ANDROID_BELOW;
+ mask = ANDROID_CW_SIBLING | ANDROID_CW_STACK_MODE;
+
+ block_input ();
+ android_reconfigure_wm_window (window1, mask, &wc);
+ unblock_input ();
+}
+
+#endif /* !ANDROID_STUBIFY */
+
+DEFUN ("android-frame-restack", Fandroid_frame_restack,
+ Sandroid_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.
+
+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.
+
+Android does not facilitate restacking top-level windows managed by
+its own window manager; nor is it possible to restack frames that are
+children of different parents. Consequently, this function only
+functions when FRAME1 and FRAME2 are both child frames subordinate to
+the same parent frame. */)
+ (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else /* !ANDROID_STUBIFY */
+ struct frame *f1 = decode_live_frame (frame1);
+ struct frame *f2 = decode_live_frame (frame2);
+
+ if (!(FRAME_ANDROID_WINDOW (f1) && FRAME_ANDROID_WINDOW (f2)))
+ error ("Cannot restack frames");
+ android_frame_restack (f1, f2, !NILP (above));
+ return Qt;
+#endif /* ANDROID_STUBIFY */
+}
+
+DEFUN ("android-mouse-absolute-pixel-position",
+ Fandroid_mouse_absolute_pixel_position,
+ Sandroid_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 display. This does not work on Android. */)
+ (void)
+{
+ /* This cannot be implemented on Android. */
+ return Qnil;
+}
+
+DEFUN ("android-set-mouse-absolute-pixel-position",
+ Fandroid_set_mouse_absolute_pixel_position,
+ Sandroid_set_mouse_absolute_pixel_position, 2, 2, 0,
+ doc: /* Move mouse pointer to a pixel position at (X, Y). The
+coordinates X and Y are interpreted to start from the top-left corner
+of the screen. This does not work on Android. */)
+ (Lisp_Object x, Lisp_Object y)
+{
+ /* This cannot be implemented on Android. */
+ return Qnil;
+}
+
+DEFUN ("android-get-connection", Fandroid_get_connection,
+ Sandroid_get_connection, 0, 0, 0,
+ doc: /* Get the connection to the display server.
+Return the terminal if it exists, else nil.
+
+Emacs cannot open a connection to the display server itself under
+Android, so there is no equivalent of `x-open-connection'. */)
+ (void)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ Lisp_Object terminal;
+
+ terminal = Qnil;
+
+ if (x_display_list)
+ XSETTERMINAL (terminal, x_display_list->terminal);
+
+ return terminal;
+#endif
+}
+
+DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (void)
+{
+ Lisp_Object result;
+
+ result = Qnil;
+
+ if (x_display_list)
+ result = Fcons (XCAR (x_display_list->name_list_element),
+ result);
+
+ return result;
+}
+
+#ifndef ANDROID_STUBIFY
+
+static void
+unwind_create_tip_frame (Lisp_Object frame)
+{
+ Lisp_Object deleted;
+
+ deleted = unwind_create_frame (frame);
+ if (EQ (deleted, Qt))
+ {
+ tip_window = ANDROID_NONE;
+ tip_frame = Qnil;
+ }
+}
+
+static Lisp_Object
+android_create_tip_frame (struct android_display_info *dpyinfo,
+ Lisp_Object parms)
+{
+ struct frame *f;
+ Lisp_Object frame;
+ Lisp_Object name;
+ specpdl_ref count = SPECPDL_INDEX ();
+ bool face_change_before = face_change;
+
+ 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)
+ && !BASE_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_android;
+ f->output_data.android = xzalloc (sizeof *f->output_data.android);
+ FRAME_FONTSET (f) = -1;
+ f->output_data.android->white_relief.pixel = -1;
+ f->output_data.android->black_relief.pixel = -1;
+
+ f->tooltip = true;
+ fset_icon_name (f, Qnil);
+ FRAME_DISPLAY_INFO (f) = dpyinfo;
+ f->output_data.android->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
+
+ /* 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 android_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.android->cursor_pixel = -1;
+ f->output_data.android->cursor_foreground_pixel = -1;
+ f->output_data.android->mouse_pixel = -1;
+
+ black = build_string ("black");
+ FRAME_FOREGROUND_PIXEL (f)
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ FRAME_BACKGROUND_PIXEL (f)
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->cursor_pixel
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->cursor_foreground_pixel
+ = android_decode_color (f, black, BLACK_PIX_DEFAULT (f));
+ f->output_data.android->mouse_pixel
+ = android_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 (BASE_EQ (name, Qunbound) || NILP (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 (&androidfont_driver, f);
+ register_font_driver (&android_sfntfont_driver, f);
+
+ 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. */
+ android_default_font_parameter (f, parms);
+
+ 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
+ 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 (! BASE_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);
+
+ {
+ struct android_set_window_attributes attrs;
+ unsigned long mask;
+
+ block_input ();
+ mask = ANDROID_CW_OVERRIDE_REDIRECT | ANDROID_CW_BACK_PIXEL;
+
+ attrs.override_redirect = true;
+ attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+ tip_window
+ = FRAME_ANDROID_WINDOW (f)
+ = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
+ /* x, y, width, height, value-mask,
+ attrs. */
+ 0, 0, 1, 1, mask, &attrs);
+ unblock_input ();
+ }
+
+ /* 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);
+
+ gui_default_parameter (f, parms, Qinhibit_double_buffering, Qnil,
+ "inhibitDoubleBuffering", "InhibitDoubleBuffering",
+ RES_TYPE_BOOLEAN);
+
+ gui_figure_window_size (f, parms, false, false);
+
+ f->output_data.android->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
+
+ android_make_gc (f);
+
+ 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);
+ gui_default_parameter (f, parms, Qalpha_background, Qnil,
+ "alphaBackground", "AlphaBackground", RES_TYPE_NUMBER);
+
+ /* 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 = Qcolor;
+
+ 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. */
+ {
+ 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. */
+ 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;
+ adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f),
+ 0, true, Qtip_frame);
+
+ /* 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);
+}
+
+static Lisp_Object
+android_hide_tip (bool delete)
+{
+ if (!NILP (tip_timer))
+ {
+ call1 (Qcancel_timer, tip_timer);
+ tip_timer = Qnil;
+ }
+
+ if (NILP (tip_frame)
+ || (!delete
+ && !NILP (tip_frame)
+ && FRAME_LIVE_P (XFRAME (tip_frame))
+ && !FRAME_VISIBLE_P (XFRAME (tip_frame))))
+ return Qnil;
+ else
+ {
+ Lisp_Object was_open = Qnil;
+
+ specpdl_ref count = SPECPDL_INDEX ();
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+ if (!NILP (tip_frame))
+ {
+ struct frame *f = XFRAME (tip_frame);
+
+ if (FRAME_LIVE_P (f))
+ {
+ if (delete)
+ {
+ delete_frame (tip_frame, Qnil);
+ tip_frame = Qnil;
+ }
+ else
+ android_make_frame_invisible (XFRAME (tip_frame));
+
+ was_open = Qt;
+ }
+ else
+ tip_frame = Qnil;
+ }
+ else
+ tip_frame = Qnil;
+
+ return unbind_to (count, was_open);
+ }
+}
+
+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;
+ android_window window;
+ struct frame *mouse_frame;
+
+ /* Initialize these values in case there is no mouse frame. */
+ *root_x = 0;
+ *root_y = 0;
+
+ /* User-specified position? */
+ left = CDR (Fassq (Qleft, parms));
+ top = CDR (Fassq (Qtop, parms));
+ right = CDR (Fassq (Qright, parms));
+ bottom = CDR (Fassq (Qbottom, parms));
+
+ /* Move the tooltip window where the mouse pointer was last seen.
+ Resize and show it. */
+ if ((!FIXNUMP (left) && !FIXNUMP (right))
+ || (!FIXNUMP (top) && !FIXNUMP (bottom)))
+ {
+ if (x_display_list->last_mouse_motion_frame)
+ {
+ *root_x = x_display_list->last_mouse_motion_x;
+ *root_y = x_display_list->last_mouse_motion_y;
+ mouse_frame = x_display_list->last_mouse_motion_frame;
+ window = FRAME_ANDROID_WINDOW (mouse_frame);
+
+ /* Translate the coordinates to the screen. */
+ android_translate_coordinates (window, *root_x, *root_y,
+ root_x, root_y);
+ }
+ }
+
+ min_x = 0;
+ min_y = 0;
+ max_x = android_get_screen_width ();
+ max_y = android_get_screen_height ();
+
+ if (FIXNUMP (top))
+ *root_y = XFIXNUM (top);
+ else if (FIXNUMP (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 (FIXNUMP (left))
+ *root_x = XFIXNUM (left);
+ else if (FIXNUMP (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;
+}
+
+#endif
+
+DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (Lisp_Object string, Lisp_Object frame, Lisp_Object parms,
+ Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
+{
+#ifdef ANDROID_STUBIFY
+ error ("Android cross-compilation stub called!");
+ return Qnil;
+#else
+ 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;
+ specpdl_ref count = SPECPDL_INDEX ();
+ Lisp_Object window, size, tip_buf;
+ bool displayed;
+#ifdef ENABLE_CHECKING
+ struct glyph_row *row, *end;
+#endif
+ AUTO_STRING (tip, " *tip*");
+
+ specbind (Qinhibit_redisplay, Qt);
+
+ CHECK_STRING (string);
+ 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 = Vx_show_tooltip_timeout;
+ CHECK_FIXNAT (timeout);
+
+ if (NILP (dx))
+ dx = make_fixnum (5);
+ else
+ CHECK_FIXNUM (dx);
+
+ if (NILP (dy))
+ dy = make_fixnum (-10);
+ else
+ CHECK_FIXNUM (dy);
+
+ tip_dx = dx;
+ tip_dy = dy;
+
+ if (!NILP (tip_frame) && FRAME_LIVE_P (XFRAME (tip_frame)))
+ {
+ if (FRAME_VISIBLE_P (XFRAME (tip_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);
+ android_move_window (FRAME_ANDROID_WINDOW (tip_f),
+ root_x, root_y);
+ unblock_input ();
+
+ goto start_timer;
+ }
+ else
+ android_hide_tip (true);
+ }
+ else
+ android_hide_tip (true);
+
+ tip_last_frame = frame;
+ tip_last_string = string;
+ tip_last_parms = parms;
+
+ if (NILP (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 = android_create_tip_frame (FRAME_DISPLAY_INFO (f),
+ parms)))
+ /* 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, 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));
+ 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;
+ /* Try to avoid that `other-window' select us (Bug#47207). */
+ Fset_window_parameter (window, Qno_other_window, Qt);
+
+ /* 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. */
+ specpdl_ref 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);
+ displayed = try_window (window, pos, TRY_WINDOW_IGNORE_FONTS_CHANGE);
+
+ if (!displayed && NILP (Vx_max_tooltip_size))
+ {
+#ifdef ENABLE_CHECKING
+ row = w->desired_matrix->rows;
+ end = w->desired_matrix->rows + w->desired_matrix->nrows;
+
+ while (row < end)
+ {
+ if (!row->displays_text_p
+ || row->ends_at_zv_p)
+ break;
+ ++row;
+ }
+
+ eassert (row < end && row->ends_at_zv_p);
+#endif
+ }
+
+ /* Calculate size of tooltip window. */
+ size = Fwindow_text_pixel_size (window, Qnil, Qnil, Qnil,
+ make_fixnum (w->pixel_height), Qnil,
+ Qnil);
+ /* Add the frame's internal border to calculated size. */
+ width = XFIXNUM (CAR (size)) + 2 * FRAME_INTERNAL_BORDER_WIDTH (tip_f);
+ height = XFIXNUM (CDR (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 ();
+ android_move_resize_window (FRAME_ANDROID_WINDOW (tip_f),
+ root_x, root_y, width,
+ height);
+ android_map_raised (FRAME_ANDROID_WINDOW (tip_f));
+ unblock_input ();
+
+ /* Garbage the tip frame too. */
+ SET_FRAME_GARBAGED (tip_f);
+
+ 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;
+
+ /* MapNotify events are not sent on Android, so make the frame
+ visible. */
+
+ SET_FRAME_VISIBLE (tip_f, true);
+
+ start_timer:
+ /* Let the tip disappear after timeout seconds. */
+ tip_timer = call3 (Qrun_at_time, timeout, Qnil,
+ Qx_hide_tip);
+
+ return unbind_to (count, Qnil);
+#endif
+}
+
+DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
+ doc: /* SKIP: real doc in xfns.c. */)
+ (void)
+{
+#ifdef ANDROID_STUBIFY
+ /* Fx_hide_tip is called from pre-command-hook (in turn called from
+ the tests.) Since signaling here prevents any tests from being
+ run, refrain from protesting if this stub is called. */
+#if 0
+ error ("Android cross-compilation stub called!");
+#endif /* 0 */
+ return Qnil;
+#else /* !ANDROID_STUBIFY */
+ return android_hide_tip (true);
+#endif /* ANDROID_STUBIFY */
+}
+
+DEFUN ("android-detect-mouse", Fandroid_detect_mouse,
+ Sandroid_detect_mouse, 0, 0, 0,
+ doc: /* Figure out whether or not there is a mouse.
+Return non-nil if a mouse is connected to this computer, and nil if
+there is no mouse. */)
+ (void)
+{
+#ifndef ANDROID_STUBIFY
+ /* If no display connection is present, just return nil. */
+
+ if (!android_init_gui)
+ return Qnil;
+
+ return android_detect_mouse () ? Qt : Qnil;
+#else
+ return Qnil;
+#endif
+}
+
+DEFUN ("android-toggle-on-screen-keyboard",
+ Fandroid_toggle_on_screen_keyboard,
+ Sandroid_toggle_on_screen_keyboard, 2, 2, 0,
+ doc: /* Display or hide the on-screen keyboard.
+If HIDE is non-nil, hide the on screen keyboard if it is currently
+being displayed. Else, request that the system display it on behalf
+of FRAME. This request may be rejected if FRAME does not have the
+input focus. */)
+ (Lisp_Object frame, Lisp_Object hide)
+{
+#ifndef ANDROID_STUBIFY
+ struct frame *f;
+
+ f = decode_window_system_frame (frame);
+
+ block_input ();
+ android_toggle_on_screen_keyboard (FRAME_ANDROID_WINDOW (f),
+ NILP (hide));
+ unblock_input ();
+#endif
+
+ return Qnil;
+}
+
+
+
+#ifndef ANDROID_STUBIFY
+
+static void
+android_set_background_color (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ struct android_output *x;
+ unsigned long bg;
+
+ x = f->output_data.android;
+ bg = android_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
+ FRAME_BACKGROUND_PIXEL (f) = bg;
+
+ if (FRAME_ANDROID_WINDOW (f) != 0)
+ {
+ block_input ();
+ android_set_background (x->normal_gc, bg);
+ android_set_foreground (x->reverse_gc, bg);
+ android_set_window_background (FRAME_ANDROID_WINDOW (f), bg);
+ android_set_foreground (x->cursor_gc, bg);
+ unblock_input ();
+
+ update_face_from_frame_parameter (f, Qbackground_color, arg);
+
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
+}
+
+static void
+android_set_border_color (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ /* Left unimplemented because Android has no window borders. */
+ CHECK_STRING (arg);
+ android_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ update_face_from_frame_parameter (f, Qborder_color, arg);
+}
+
+static void
+android_set_cursor_color (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ unsigned long fore_pixel, pixel;
+ struct android_output *x;
+
+ x = f->output_data.android;
+
+ if (!NILP (Vx_cursor_fore_pixel))
+ fore_pixel = android_decode_color (f, Vx_cursor_fore_pixel,
+ WHITE_PIX_DEFAULT (f));
+ else
+ fore_pixel = FRAME_BACKGROUND_PIXEL (f);
+
+ pixel = android_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))
+ {
+ pixel = FRAME_FOREGROUND_PIXEL (f);
+ if (pixel == fore_pixel)
+ fore_pixel = FRAME_BACKGROUND_PIXEL (f);
+ }
+
+ x->cursor_foreground_pixel = fore_pixel;
+ x->cursor_pixel = pixel;
+
+ if (FRAME_ANDROID_WINDOW (f) != 0)
+ {
+ block_input ();
+ android_set_background (x->cursor_gc, x->cursor_pixel);
+ android_set_foreground (x->cursor_gc, fore_pixel);
+ unblock_input ();
+
+ if (FRAME_VISIBLE_P (f))
+ {
+ gui_update_cursor (f, false);
+ gui_update_cursor (f, true);
+ }
+ }
+
+ update_face_from_frame_parameter (f, Qcursor_color, arg);
+}
+
+static void
+android_set_cursor_type (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ set_frame_cursor_types (f, arg);
+}
+
+static void
+android_set_foreground_color (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ struct android_output *x;
+ unsigned long fg, old_fg;
+
+ x = f->output_data.android;
+
+ fg = android_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ old_fg = FRAME_FOREGROUND_PIXEL (f);
+ FRAME_FOREGROUND_PIXEL (f) = fg;
+
+ if (FRAME_ANDROID_WINDOW (f) != 0)
+ {
+ block_input ();
+ android_set_foreground (x->normal_gc, fg);
+ android_set_background (x->reverse_gc, fg);
+
+ if (x->cursor_pixel == old_fg)
+ {
+ x->cursor_pixel = fg;
+ android_set_background (x->cursor_gc, x->cursor_pixel);
+ }
+
+ unblock_input ();
+
+ update_face_from_frame_parameter (f, Qforeground_color, arg);
+
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
+}
+
+static void
+android_set_child_frame_border_width (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ int border;
+
+ if (NILP (arg))
+ border = -1;
+ else if (RANGED_FIXNUMP (0, arg, INT_MAX))
+ border = XFIXNAT (arg);
+ else
+ signal_error ("Invalid child frame border width", arg);
+
+ if (border != FRAME_CHILD_FRAME_BORDER_WIDTH (f))
+ {
+ f->child_frame_border_width = border;
+
+ if (FRAME_ANDROID_WINDOW (f))
+ {
+ adjust_frame_size (f, -1, -1, 3, false, Qchild_frame_border_width);
+ android_clear_under_internal_border (f);
+ }
+ }
+}
+
+static void
+android_set_internal_border_width (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ int border = check_int_nonnegative (arg);
+
+ if (border != FRAME_INTERNAL_BORDER_WIDTH (f))
+ {
+ f->internal_border_width = border;
+
+ if (FRAME_ANDROID_WINDOW (f))
+ {
+ adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
+ android_clear_under_internal_border (f);
+ }
+ }
+}
+
+static void
+android_set_menu_bar_lines (struct frame *f, Lisp_Object value,
+ Lisp_Object oldval)
+{
+ int nlines;
+ int olines = FRAME_MENU_BAR_LINES (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_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) = nlines;
+ FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
+ if (FRAME_ANDROID_WINDOW (f))
+ android_clear_under_internal_border (f);
+
+ /* If the menu bar height gets changed, the internal border below
+ the top margin has to be cleared. Also, if the menu bar gets
+ larger, the area for the added lines has to be cleared except for
+ the first menu bar line that is to be drawn later. */
+ if (nlines != olines)
+ {
+ int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = FRAME_PIXEL_WIDTH (f);
+ int y;
+
+ adjust_frame_size (f, -1, -1, 3, true, Qmenu_bar_lines);
+
+ /* height can be zero here. */
+ if (FRAME_ANDROID_WINDOW (f) && height > 0 && width > 0)
+ {
+ y = FRAME_TOP_MARGIN_HEIGHT (f);
+
+ block_input ();
+ android_clear_area (FRAME_ANDROID_DRAWABLE (f),
+ 0, y, width, height);
+ unblock_input ();
+ }
+
+ if (nlines > 1 && nlines > olines)
+ {
+ y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
+ height = nlines * FRAME_LINE_HEIGHT (f) - y;
+
+ block_input ();
+ android_clear_area (FRAME_ANDROID_DRAWABLE (f), 0, y,
+ width, height);
+ unblock_input ();
+ }
+
+ if (nlines == 0 && WINDOWP (f->menu_bar_window))
+ clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
+ }
+
+ adjust_frame_glyphs (f);
+}
+
+
+
+/* These enums must stay in sync with the mouse_cursor_types array
+ below! */
+
+enum mouse_cursor
+ {
+ mouse_cursor_text,
+ mouse_cursor_nontext,
+ mouse_cursor_hourglass,
+ mouse_cursor_mode,
+ mouse_cursor_hand,
+ mouse_cursor_horizontal_drag,
+ mouse_cursor_vertical_drag,
+ mouse_cursor_left_edge,
+ mouse_cursor_top_left_corner,
+ mouse_cursor_top_edge,
+ mouse_cursor_top_right_corner,
+ mouse_cursor_right_edge,
+ mouse_cursor_bottom_right_corner,
+ mouse_cursor_bottom_edge,
+ mouse_cursor_bottom_left_corner,
+ mouse_cursor_max
+ };
+
+struct mouse_cursor_types
+{
+ /* Printable name for error messages (optional). */
+ const char *name;
+
+ /* Lisp variable controlling the cursor shape. */
+ /* FIXME: A couple of these variables are defined in the C code but
+ are not actually accessible from Lisp. They should probably be
+ made accessible or removed. */
+ Lisp_Object *shape_var_ptr;
+
+ /* The default shape. */
+ int default_shape;
+};
+
+/* This array must stay in sync with enum mouse_cursor above! */
+
+static const struct mouse_cursor_types mouse_cursor_types[] =
+ {
+ {"text", &Vx_pointer_shape, ANDROID_XC_XTERM, },
+ {"nontext", &Vx_nontext_pointer_shape, ANDROID_XC_LEFT_PTR, },
+ {"hourglass", &Vx_hourglass_pointer_shape, ANDROID_XC_WATCH, },
+ {"modeline", &Vx_mode_pointer_shape, ANDROID_XC_XTERM, },
+ {NULL, &Vx_sensitive_text_pointer_shape, ANDROID_XC_HAND2, },
+ {NULL, &Vx_window_horizontal_drag_shape, ANDROID_XC_SB_H_DOUBLE_ARROW, },
+ {NULL, &Vx_window_vertical_drag_shape, ANDROID_XC_SB_V_DOUBLE_ARROW, },
+ {NULL, &Vx_window_left_edge_shape, ANDROID_XC_LEFT_SIDE, },
+ {NULL, &Vx_window_top_left_corner_shape, ANDROID_XC_TOP_LEFT_CORNER, },
+ {NULL, &Vx_window_top_edge_shape, ANDROID_XC_TOP_SIDE, },
+ {NULL, &Vx_window_top_right_corner_shape, ANDROID_XC_TOP_RIGHT_CORNER, },
+ {NULL, &Vx_window_right_edge_shape, ANDROID_XC_RIGHT_SIDE, },
+ {NULL, &Vx_window_bottom_right_corner_shape,
+ ANDROID_XC_BOTTOM_RIGHT_CORNER, },
+ {NULL, &Vx_window_bottom_edge_shape, ANDROID_XC_BOTTOM_SIDE, },
+ {NULL, &Vx_window_bottom_left_corner_shape,
+ ANDROID_XC_BOTTOM_LEFT_CORNER, },
+ };
+
+struct mouse_cursor_data
+{
+ /* Cursor numbers chosen. */
+ unsigned int cursor_num[mouse_cursor_max];
+
+ /* Allocated Cursor values, or zero for failed attempts. */
+ android_cursor cursor[mouse_cursor_max];
+};
+
+
+
+static void
+android_set_mouse_color (struct frame *f, Lisp_Object arg,
+ Lisp_Object oldval)
+{
+ struct android_output *x = f->output_data.android;
+ struct mouse_cursor_data cursor_data = { -1, -1 };
+ unsigned long pixel = android_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
+ int i;
+
+ /* Don't let pointers be invisible. */
+ if (mask_color == pixel)
+ pixel = FRAME_FOREGROUND_PIXEL (f);
+
+ x->mouse_pixel = pixel;
+
+ for (i = 0; i < mouse_cursor_max; i++)
+ {
+ Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr;
+ cursor_data.cursor_num[i]
+ = (!NILP (shape_var)
+ ? check_uinteger_max (shape_var, UINT_MAX)
+ : mouse_cursor_types[i].default_shape);
+ }
+
+ block_input ();
+
+ for (i = 0; i < mouse_cursor_max; i++)
+ cursor_data.cursor[i]
+ = android_create_font_cursor (cursor_data.cursor_num[i]);
+
+ if (FRAME_ANDROID_WINDOW (f))
+ {
+ f->output_data.android->current_cursor
+ = cursor_data.cursor[mouse_cursor_text];
+ android_define_cursor (FRAME_ANDROID_WINDOW (f),
+ f->output_data.android->current_cursor);
+ }
+
+#define INSTALL_CURSOR(FIELD, SHORT_INDEX) \
+ eassert (x->FIELD \
+ != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \
+ if (x->FIELD != 0) \
+ android_free_cursor (x->FIELD); \
+ x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX];
+
+ INSTALL_CURSOR (text_cursor, text);
+ INSTALL_CURSOR (nontext_cursor, nontext);
+ INSTALL_CURSOR (hourglass_cursor, hourglass);
+ INSTALL_CURSOR (modeline_cursor, mode);
+ INSTALL_CURSOR (hand_cursor, hand);
+ INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
+ INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
+ INSTALL_CURSOR (left_edge_cursor, left_edge);
+ INSTALL_CURSOR (top_left_corner_cursor, top_left_corner);
+ INSTALL_CURSOR (top_edge_cursor, top_edge);
+ INSTALL_CURSOR (top_right_corner_cursor, top_right_corner);
+ INSTALL_CURSOR (right_edge_cursor, right_edge);
+ INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner);
+ INSTALL_CURSOR (bottom_edge_cursor, bottom_edge);
+ INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner);
+
+#undef INSTALL_CURSOR
+
+ unblock_input ();
+
+ update_face_from_frame_parameter (f, Qmouse_color, arg);
+}
+
+static void
+android_set_title (struct frame *f, Lisp_Object name,
+ Lisp_Object old_name)
+{
+ /* Don't change the title if it's already NAME. */
+ if (EQ (name, f->title))
+ return;
+
+ update_mode_lines = 38;
+
+ fset_title (f, name);
+
+ if (NILP (name))
+ name = f->name;
+ else
+ CHECK_STRING (name);
+}
+
+static void
+android_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+ double alpha = 1.0;
+ double newval[2];
+ int i;
+ Lisp_Object item;
+
+ /* N.B. that setting the window alpha is actually unsupported under
+ Android. */
+
+ for (i = 0; i < 2; i++)
+ {
+ newval[i] = 1.0;
+ if (CONSP (arg))
+ {
+ item = CAR (arg);
+ arg = CDR (arg);
+ }
+ else
+ item = arg;
+
+ if (NILP (item))
+ alpha = - 1.0;
+ else if (FLOATP (item))
+ {
+ alpha = XFLOAT_DATA (item);
+ if (! (0 <= alpha && alpha <= 1.0))
+ args_out_of_range (make_float (0.0), make_float (1.0));
+ }
+ else if (FIXNUMP (item))
+ {
+ EMACS_INT ialpha = XFIXNUM (item);
+ if (! (0 <= ialpha && ialpha <= 100))
+ args_out_of_range (make_fixnum (0), make_fixnum (100));
+ alpha = ialpha / 100.0;
+ }
+ else
+ wrong_type_argument (Qnumberp, item);
+ newval[i] = alpha;
+ }
+
+ for (i = 0; i < 2; i++)
+ f->alpha[i] = newval[i];
+
+ if (FRAME_TERMINAL (f)->set_frame_alpha_hook)
+ {
+ block_input ();
+ FRAME_TERMINAL (f)->set_frame_alpha_hook (f);
+ unblock_input ();
+ }
+}
+
+static void
+android_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ if (!EQ (new_value, old_value))
+ {
+ android_set_dont_focus_on_map (FRAME_ANDROID_WINDOW (f),
+ !NILP (new_value));
+ FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
+ }
+}
+
+static void
+android_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+ if (!EQ (new_value, old_value))
+ {
+ android_set_dont_accept_focus (FRAME_ANDROID_WINDOW (f),
+ !NILP (new_value));
+ FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
+ }
+}
+
+frame_parm_handler android_frame_parm_handlers[] =
+{
+ gui_set_autoraise,
+ gui_set_autolower,
+ android_set_background_color,
+ android_set_border_color,
+ gui_set_border_width,
+ android_set_cursor_color,
+ android_set_cursor_type,
+ gui_set_font,
+ android_set_foreground_color,
+ NULL,
+ NULL,
+ android_set_child_frame_border_width,
+ android_set_internal_border_width,
+ gui_set_right_divider_width,
+ gui_set_bottom_divider_width,
+ android_set_menu_bar_lines,
+ android_set_mouse_color,
+ android_explicitly_set_name,
+ gui_set_scroll_bar_width,
+ gui_set_scroll_bar_height,
+ android_set_title,
+ gui_set_unsplittable,
+ gui_set_vertical_scroll_bars,
+ gui_set_horizontal_scroll_bars,
+ gui_set_visibility,
+ android_set_tab_bar_lines,
+ android_set_tool_bar_lines,
+ NULL,
+ NULL,
+ gui_set_screen_gamma,
+ gui_set_line_spacing,
+ gui_set_left_fringe,
+ gui_set_right_fringe,
+ NULL,
+ gui_set_fullscreen,
+ gui_set_font_backend,
+ android_set_alpha,
+ NULL,
+ android_set_tool_bar_position,
+ NULL,
+ NULL,
+ android_set_parent_frame,
+ NULL,
+ android_set_no_focus_on_map,
+ android_set_no_accept_focus,
+ NULL,
+ NULL,
+ gui_set_no_special_glyphs,
+ NULL,
+ NULL,
+};
+
+
+
+/* Battery information support. */
+
+DEFUN ("android-query-battery", Fandroid_query_battery,
+ Sandroid_query_battery, 0, 0, 0,
+ doc: /* Perform a query for battery information.
+Value is nil upon failure, or a list of the form:
+
+ (CAPACITY CHARGE-COUNTER CURRENT-AVERAGE CURRENT-NOW STATUS
+ REMAINING PLUGGED TEMP)
+
+where REMAINING, CURRENT-AVERAGE, and CURRENT-NOW are undefined prior
+to Android 5.0.
+
+See the documentation at
+
+ https://developer.android.com/reference/android/os/BatteryManager
+
+for more details about these values. */)
+ (void)
+{
+ struct android_battery_state state;
+
+ /* Make sure the Android libraries have been initialized. */
+
+ if (!android_init_gui)
+ return Qnil;
+
+ /* Perform the query. */
+
+ if (android_query_battery (&state))
+ return Qnil;
+
+ return listn (8, make_int (state.capacity),
+ make_fixnum (state.charge_counter),
+ make_int (state.current_average),
+ make_int (state.current_now),
+ make_fixnum (state.status),
+ make_int (state.remaining),
+ make_fixnum (state.plugged),
+ make_fixnum (state.temperature));
+}
+
+
+
+/* Directory access requests. */
+
+DEFUN ("android-request-directory-access", Fandroid_request_directory_access,
+ Sandroid_request_directory_access, 0, 0, "",
+ doc: /* Request access to a directory within external storage.
+On Android 5.0 and later, prompt for a directory within external or
+application storage, and grant access to it; some of these directories
+cannot be accessed through the regular `/sdcard' filesystem.
+
+If access to the directory is granted, it will eventually appear
+within the directory `/content/storage'. */)
+ (void)
+{
+ if (android_get_current_api_level () < 21)
+ error ("Emacs can only access application storage on"
+ " Android 5.0 and later");
+
+ if (!android_init_gui)
+ return Qnil;
+
+ android_request_directory_access ();
+ return Qnil;
+}
+
+
+
+/* Functions concerning storage permissions. */
+
+DEFUN ("android-external-storage-available-p",
+ Fandroid_external_storage_available_p,
+ Sandroid_external_storage_available_p, 0, 0, 0,
+ doc: /* Return non-nil if Emacs is entitled to access external storage.
+Return nil if the requisite permissions for external storage access
+have not been granted to Emacs, t otherwise. Such permissions can be
+requested by means of the `android-request-storage-access'
+command.
+
+External storage on Android encompasses the `/sdcard' and
+`/storage/emulated' directories, access to which is denied to programs
+absent these permissions. */)
+ (void)
+{
+ return android_external_storage_available_p () ? Qt : Qnil;
+}
+
+DEFUN ("android-request-storage-access", Fandroid_request_storage_access,
+ Sandroid_request_storage_access, 0, 0, "",
+ doc: /* Request permissions to access external storage.
+
+Return nil regardless of whether access permissions are granted or not,
+immediately after displaying the permissions request dialog.
+
+Use `android-external-storage-available-p' (which see) to verify
+whether Emacs has actually received such access permissions. */)
+ (void)
+{
+ android_request_storage_access ();
+ return Qnil;
+}
+
+
+
+/* Miscellaneous input method related stuff. */
+
+/* Report X, Y, by the phys cursor width and height as the cursor
+ anchor rectangle for W's frame. */
+
+void
+android_set_preeditarea (struct window *w, int x, int y)
+{
+ struct frame *f;
+
+ f = WINDOW_XFRAME (w);
+
+ /* Convert the window coordinates to the frame's coordinate
+ space. */
+ x = (WINDOW_TO_FRAME_PIXEL_X (w, x)
+ + WINDOW_LEFT_FRINGE_WIDTH (w)
+ + WINDOW_LEFT_MARGIN_WIDTH (w));
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, y);
+
+ /* Note that calculating the baseline is too hard, so the bottom of
+ the cursor is used instead. */
+ android_update_cursor_anchor_info (FRAME_ANDROID_WINDOW (f), x,
+ y, y + w->phys_cursor_height,
+ y + w->phys_cursor_height);
+}
+
+#endif /* !ANDROID_STUBIFY */
+
+
+
+#ifndef ANDROID_STUBIFY
+
+static void
+syms_of_androidfns_for_pdumper (void)
+{
+ jclass locale;
+ jmethodID method;
+ jobject object;
+ jstring string;
+ Lisp_Object language, country, script, variant;
+ const char *data;
+
+ /* Find the Locale class. */
+
+ locale = (*android_java_env)->FindClass (android_java_env,
+ "java/util/Locale");
+ if (!locale)
+ emacs_abort ();
+
+ /* And the method from which the default locale can be
+ extracted. */
+
+ method = (*android_java_env)->GetStaticMethodID (android_java_env,
+ locale,
+ "getDefault",
+ "()Ljava/util/Locale;");
+ if (!method)
+ emacs_abort ();
+
+ /* Retrieve the default locale. */
+
+ object = (*android_java_env)->CallStaticObjectMethod (android_java_env,
+ locale, method);
+ android_exception_check_1 (locale);
+
+ if (!object)
+ emacs_abort ();
+
+ /* Retrieve its language field. Each of these methods is liable to
+ return the empty string, though if language is empty, the locale
+ is malformed. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getLanguage",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ language = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ language = empty_unibyte_string;
+ else
+ {
+ language = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ /* Delete the reference to this string. */
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* Proceed to retrieve the country code. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getCountry",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ country = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ country = empty_unibyte_string;
+ else
+ {
+ country = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* Proceed to retrieve the script. */
+
+ if (android_get_current_api_level () < 21)
+ script = empty_unibyte_string;
+ else
+ {
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getScript",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env,
+ object, method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ script = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ script = empty_unibyte_string;
+ else
+ {
+ script = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+ }
+
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* And variant. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getVariant",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ variant = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ variant = empty_unibyte_string;
+ else
+ {
+ variant = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ /* Delete the reference to this string. */
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* And other remaining local references. */
+ ANDROID_DELETE_LOCAL_REF (object);
+ ANDROID_DELETE_LOCAL_REF (locale);
+
+ /* Set Vandroid_os_language. */
+ Vandroid_os_language = list4 (language, country, script, variant);
+}
+
+#endif /* ANDROID_STUBIFY */
+
+void
+syms_of_androidfns (void)
+{
+ /* Miscellaneous symbols used by some functions here. */
+ DEFSYM (Qtrue_color, "true-color");
+ DEFSYM (Qwhen_mapped, "when-mapped");
+
+ DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_pointer_shape = Qnil;
+
+#if false /* This doesn't really do anything. */
+ DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape,
+ doc: /* SKIP: real doc in xfns.c. */);
+#endif
+ Vx_nontext_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_hourglass_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-sensitive-text-pointer-shape",
+ Vx_sensitive_text_pointer_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_sensitive_text_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-horizontal-drag-cursor",
+ Vx_window_horizontal_drag_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_horizontal_drag_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-vertical-drag-cursor",
+ Vx_window_vertical_drag_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_vertical_drag_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-left-edge-cursor",
+ Vx_window_left_edge_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_left_edge_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-top-left-corner-cursor",
+ Vx_window_top_left_corner_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_top_left_corner_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-top-edge-cursor",
+ Vx_window_top_edge_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_top_edge_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-top-right-corner-cursor",
+ Vx_window_top_right_corner_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_top_right_corner_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-right-edge-cursor",
+ Vx_window_right_edge_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_right_edge_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
+ Vx_window_bottom_right_corner_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_bottom_right_corner_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-bottom-edge-cursor",
+ Vx_window_bottom_edge_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_bottom_edge_shape = Qnil;
+
+#if false /* This doesn't really do anything. */
+ DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape,
+ doc: /* SKIP: real doc in xfns.c. */);
+#endif
+ Vx_mode_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
+ Vx_window_bottom_left_corner_shape,
+ doc: /* SKIP: real text in xfns.c. */);
+ Vx_window_bottom_left_corner_shape = Qnil;
+
+ DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_cursor_fore_pixel = Qnil;
+
+ /* Used by Fx_show_tip. */
+ DEFSYM (Qrun_at_time, "run-at-time");
+ DEFSYM (Qx_hide_tip, "x-hide-tip");
+ DEFSYM (Qcancel_timer, "cancel-timer");
+ DEFSYM (Qassq_delete_all, "assq-delete-all");
+ DEFSYM (Qcolor, "color");
+
+ DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
+ doc: /* SKIP: real doc in xfns.c. */);
+ Vx_max_tooltip_size = Qnil;
+
+ DEFVAR_BOOL ("android-pass-multimedia-buttons-to-system",
+ android_pass_multimedia_buttons_to_system,
+ doc: /* Whether or not to pass volume control buttons to the system.
+Generally, the `volume-up', `volume-down' and `volume-mute' keys are
+processed by Emacs, but setting this to non-nil they are passed to the
+operating system instead of being intercepted by Emacs.
+
+Note that if you set this, you will no longer be able to quit Emacs
+using the volume down button. */);
+ android_pass_multimedia_buttons_to_system = false;
+
+ DEFVAR_BOOL ("android-intercept-control-space",
+ android_intercept_control_space,
+ doc: /* Whether Emacs should intercept C-SPC.
+When this variable is set, Emacs intercepts C-SPC events as they are
+delivered to a frame before they are registered and filtered by the
+input method.
+
+For no apparent purpose, Android input methods customarily discard SPC
+events with the Ctrl modifier set without delivering them to Emacs
+afterwards, which is an impediment to typing key sequences
+incorporating such keys. */);
+ android_intercept_control_space = true;
+
+ DEFVAR_BOOL ("android-use-exec-loader", android_use_exec_loader,
+ doc: /* Whether or not to bypass system restrictions on program execution.
+
+Android 10 and later prevent programs from executing files installed
+in writable directories, such as the application data directory.
+
+When non-nil, Emacs will bypass this restriction by running such
+executables under system call tracing, and replacing the `execve'
+system call with a version which ignores the system's security
+restrictions.
+
+This option has no effect on Android 9 and earlier. */);
+ android_use_exec_loader = true;
+
+ DEFVAR_INT ("android-keyboard-bell-duration",
+ android_keyboard_bell_duration,
+ doc: /* Number of milliseconds to vibrate after ringing the keyboard bell.
+The keyboard bell under Android systems takes the form of a vibrating
+element that is activated for a given number of milliseconds upon the
+bell being rung. */);
+ android_keyboard_bell_duration = 50;
+
+ DEFVAR_LISP ("android-os-language", Vandroid_os_language,
+ doc: /* A list representing the configured system language on Android.
+This list has four elements: LANGUAGE, COUNTRY, SCRIPT and VARIANT, where:
+
+LANGUAGE and COUNTRY are ISO language and country codes identical to
+those found in POSIX locale specifications.
+
+SCRIPT is an ISO 15924 script tag, representing the script used
+if available, or if required to disambiguate between distinct
+writing systems for the same combination of language and country.
+
+VARIANT is an arbitrary string representing the variant of the
+LANGUAGE or SCRIPT.
+
+Each of these fields might be empty or nil, but the locale is invalid
+if LANGUAGE is empty. Users of this variable should consider the
+language to be US English if LANGUAGE is empty. */);
+ Vandroid_os_language = Qnil;
+
+ /* Functions defined. */
+ defsubr (&Sx_create_frame);
+ defsubr (&Sxw_color_defined_p);
+ defsubr (&Sxw_color_values);
+ defsubr (&Sxw_display_color_p);
+ defsubr (&Sx_display_grayscale_p);
+ defsubr (&Sx_display_pixel_width);
+ defsubr (&Sx_display_pixel_height);
+ defsubr (&Sx_display_planes);
+ defsubr (&Sx_display_color_cells);
+ defsubr (&Sx_display_screens);
+ defsubr (&Sx_display_mm_width);
+ defsubr (&Sx_display_mm_height);
+ defsubr (&Sx_display_backing_store);
+ defsubr (&Sx_display_visual_class);
+ defsubr (&Sandroid_display_monitor_attributes_list);
+ defsubr (&Sandroid_frame_geometry);
+ defsubr (&Sandroid_frame_edges);
+ defsubr (&Sandroid_frame_list_z_order);
+ defsubr (&Sandroid_frame_restack);
+ defsubr (&Sandroid_mouse_absolute_pixel_position);
+ defsubr (&Sandroid_set_mouse_absolute_pixel_position);
+ defsubr (&Sandroid_get_connection);
+ defsubr (&Sx_display_list);
+ defsubr (&Sx_show_tip);
+ defsubr (&Sx_hide_tip);
+ defsubr (&Sandroid_detect_mouse);
+ defsubr (&Sandroid_toggle_on_screen_keyboard);
+ defsubr (&Sx_server_vendor);
+ defsubr (&Sx_server_version);
+#ifndef ANDROID_STUBIFY
+ defsubr (&Sandroid_query_battery);
+ defsubr (&Sandroid_request_directory_access);
+ defsubr (&Sandroid_external_storage_available_p);
+ defsubr (&Sandroid_request_storage_access);
+
+ 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);
+ tip_dx = Qnil;
+ staticpro (&tip_dx);
+ tip_dy = Qnil;
+ staticpro (&tip_dy);
+
+ pdumper_do_now_and_after_load (syms_of_androidfns_for_pdumper);
+#endif /* !ANDROID_STUBIFY */
+}