From b0140bcd44326632538dc377dd336b82a1df4dd9 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 23 Dec 2025 10:39:45 +0800 Subject: [PATCH] Implement set_window_size_and_position_hook on Android * java/org/gnu/emacs/EmacsWindow.java (moveResizeWindow): New method, which alters all of the bounding box of a window at once. * src/android.c (android_init_emacs_window): Load method `move_resize_window'. (android_move_resize_window): Invoke this method, rather than a sequence of operations that will produce two ConfigureNotify events. * src/androidterm.c (android_set_window_size_and_position_1) (android_set_window_size_and_position): New functions; ported from X. (android_create_terminal): Register the same. --- java/org/gnu/emacs/EmacsWindow.java | 10 +++++++ src/android.c | 20 +++++++++++-- src/androidterm.c | 44 +++++++++++++++++++++++++++++ src/androidterm.h | 1 + 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index fffa2cc5d49..7cbc1c1db43 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -426,6 +426,16 @@ public final class EmacsWindow extends EmacsHandleObject requestViewLayout (); } + public synchronized void + moveResizeWindow (int x, int y, int width, int height) + { + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + requestViewLayout (); + } + /* Return WM layout parameters for an override redirect window with the geometry provided here. */ diff --git a/src/android.c b/src/android.c index 5f2f2e35239..b87430bdd74 100644 --- a/src/android.c +++ b/src/android.c @@ -102,6 +102,7 @@ struct android_emacs_window jmethodID unmap_window; jmethodID resize_window; jmethodID move_window; + jmethodID move_resize_window; jmethodID make_input_focus; jmethodID raise; jmethodID lower; @@ -1965,6 +1966,7 @@ android_init_emacs_window (void) FIND_METHOD (unmap_window, "unmapWindow", "()V"); FIND_METHOD (resize_window, "resizeWindow", "(II)V"); FIND_METHOD (move_window, "moveWindow", "(II)V"); + FIND_METHOD (move_resize_window, "moveResizeWindow", "(IIII)V"); FIND_METHOD (make_input_focus, "makeInputFocus", "(J)V"); FIND_METHOD (raise, "raise", "()V"); FIND_METHOD (lower, "lower", "()V"); @@ -5331,11 +5333,23 @@ android_get_geometry (android_window handle, } void -android_move_resize_window (android_window window, int x, int y, +android_move_resize_window (android_window handle, int x, int y, unsigned int width, unsigned int height) { - android_move_window (window, x, y); - android_resize_window (window, width, height); + jobject window; + jmethodID move_resize_window; + + window = android_resolve_handle (handle); + move_resize_window = window_class.move_resize_window; + + (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, + window, + window_class.class, + move_resize_window, + (jint) x, (jint) y, + (jint) width, + (jint) height); + android_exception_check (); } void diff --git a/src/androidterm.c b/src/androidterm.c index d9830e5cd08..7342b8d2dae 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -2334,6 +2334,48 @@ android_set_window_size (struct frame *f, bool change_gravity, do_pending_window_change (false); } +static void +android_set_window_size_and_position_1 (struct frame *f, int width, int height) +{ + int x = f->left_pos; + int y = f->top_pos; + + android_move_resize_window (FRAME_ANDROID_WINDOW (f), x, y, width, height); + + SET_FRAME_GARBAGED (f); + + if (FRAME_VISIBLE_P (f)) + android_wait_for_event (f, ANDROID_CONFIGURE_NOTIFY); + else + /* Call adjust_frame_size right. It might be tempting to clear out + f->new_width and f->new_height here. */ + adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width), + FRAME_PIXEL_TO_TEXT_HEIGHT (f, height), + 5, 0, Qx_set_window_size_1); +} + +void +android_set_window_size_and_position (struct frame *f, int width, int height) +{ + block_input (); + + android_set_window_size_and_position_1 (f, width, height); + android_clear_under_internal_border (f); + + /* If cursor was outside the new size, mark it as off. */ + mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); + + /* Clear out any recollection of where the mouse highlighting was, + since it might be in a place that's outside the new frame size. + Actually checking whether it is outside is a pain in the neck, + so don't try--just let the highlighting be done afresh with new size. */ + cancel_mouse_face (f); + + unblock_input (); + + do_pending_window_change (false); +} + /* Calculate the absolute position in frame F from its current recorded position values and gravity. */ @@ -6705,6 +6747,8 @@ android_create_terminal (struct android_display_info *dpyinfo) terminal->fullscreen_hook = android_fullscreen_hook; terminal->iconify_frame_hook = android_iconify_frame; terminal->set_window_size_hook = android_set_window_size; + terminal->set_window_size_and_position_hook + = android_set_window_size_and_position; terminal->set_frame_offset_hook = android_set_offset; terminal->set_frame_alpha_hook = android_set_alpha; terminal->set_new_font_hook = android_new_font; diff --git a/src/androidterm.h b/src/androidterm.h index e9e8d594169..10806ce39bf 100644 --- a/src/androidterm.h +++ b/src/androidterm.h @@ -404,6 +404,7 @@ extern void android_set_preeditarea (struct window *, int, int); extern void android_term_init (void); extern void android_set_window_size (struct frame *, bool, int, int); +extern void android_set_window_size_and_position (struct frame *, int, int); extern void android_iconify_frame (struct frame *); extern void android_make_frame_visible (struct frame *); extern void android_make_frame_invisible (struct frame *);