mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-26 07:33:47 +00:00
Implement frame restacking under Android
* java/org/gnu/emacs/EmacsActivity.java (invalidateFocus1): Synchronize with window.children for iteration through it. * java/org/gnu/emacs/EmacsService.java (queryTree): Synchronize with windowList for iteration through it. * java/org/gnu/emacs/EmacsView.java (moveChildToBack): Correct formatting mistake. (moveAbove, moveBelow): New functions. * java/org/gnu/emacs/EmacsWindow.java (destroyHandle, reparentTo) (raise, lower): Remedy synchronization blunders. (reconfigure): New function. * src/android.c (android_init_emacs_window): Link with `reconfigure'. (android_reconfigure_wm_window): New wrapper function. * src/androidfns.c (android_frame_restack): New function. (Fandroid_frame_restack): Properly implement this function and expunge outdated comment. * src/androidgui.h (enum android_stack_mode) (enum android_window_changes): New enumerators.
This commit is contained in:
parent
238292d657
commit
336c367411
@ -89,8 +89,11 @@ public class EmacsActivity extends Activity
|
||||
if (window.view.isFocused ())
|
||||
focusedWindow = window;
|
||||
|
||||
for (EmacsWindow child : window.children)
|
||||
invalidateFocus1 (child);
|
||||
synchronized (window.children)
|
||||
{
|
||||
for (EmacsWindow child : window.children)
|
||||
invalidateFocus1 (child);
|
||||
}
|
||||
}
|
||||
|
||||
public static void
|
||||
|
@ -505,15 +505,18 @@ invocation of app_process (through android-emacs) can
|
||||
else
|
||||
windowList = window.children;
|
||||
|
||||
array = new short[windowList.size () + 1];
|
||||
i = 1;
|
||||
synchronized (windowList)
|
||||
{
|
||||
array = new short[windowList.size () + 1];
|
||||
i = 1;
|
||||
|
||||
array[0] = (window == null
|
||||
? 0 : (window.parent != null
|
||||
? window.parent.handle : 0));
|
||||
array[0] = (window == null
|
||||
? 0 : (window.parent != null
|
||||
? window.parent.handle : 0));
|
||||
|
||||
for (EmacsWindow treeWindow : windowList)
|
||||
array[i++] = treeWindow.handle;
|
||||
for (EmacsWindow treeWindow : windowList)
|
||||
array[i++] = treeWindow.handle;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
@ -581,12 +581,12 @@ else if (child.getVisibility () != GONE)
|
||||
|
||||
/* The view at 0 is the surface view. */
|
||||
attachViewToParent (child, 1,
|
||||
child.getLayoutParams());
|
||||
child.getLayoutParams ());
|
||||
}
|
||||
}
|
||||
|
||||
/* The following two functions must not be called if the view has no
|
||||
parent, or is parented to an activity. */
|
||||
/* The following four functions must not be called if the view has
|
||||
no parent, or is parented to an activity. */
|
||||
|
||||
public void
|
||||
raise ()
|
||||
@ -615,6 +615,40 @@ else if (child.getVisibility () != GONE)
|
||||
parent.moveChildToBack (this);
|
||||
}
|
||||
|
||||
public void
|
||||
moveAbove (EmacsView view)
|
||||
{
|
||||
EmacsView parent;
|
||||
int index;
|
||||
|
||||
parent = (EmacsView) getParent ();
|
||||
|
||||
if (parent != view.getParent ())
|
||||
throw new IllegalStateException ("Moving view above non-sibling");
|
||||
|
||||
index = parent.indexOfChild (this);
|
||||
parent.detachViewFromParent (index);
|
||||
index = parent.indexOfChild (view);
|
||||
parent.attachViewToParent (this, index + 1, getLayoutParams ());
|
||||
}
|
||||
|
||||
public void
|
||||
moveBelow (EmacsView view)
|
||||
{
|
||||
EmacsView parent;
|
||||
int index;
|
||||
|
||||
parent = (EmacsView) getParent ();
|
||||
|
||||
if (parent != view.getParent ())
|
||||
throw new IllegalStateException ("Moving view above non-sibling");
|
||||
|
||||
index = parent.indexOfChild (this);
|
||||
parent.detachViewFromParent (index);
|
||||
index = parent.indexOfChild (view);
|
||||
parent.attachViewToParent (this, index, getLayoutParams ());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void
|
||||
onCreateContextMenu (ContextMenu menu)
|
||||
|
@ -22,6 +22,7 @@
|
||||
import java.lang.IllegalStateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@ -93,7 +94,9 @@ private static class Coordinate
|
||||
public EmacsWindow parent;
|
||||
|
||||
/* List of all children in stacking order. This must be kept
|
||||
consistent with their Z order! */
|
||||
consistent with their Z order!
|
||||
|
||||
Synchronize access to this list with itself. */
|
||||
public ArrayList<EmacsWindow> children;
|
||||
|
||||
/* Map between pointer identifiers and last known position. Used to
|
||||
@ -165,7 +168,11 @@ private static class Coordinate
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
parent.children.add (this);
|
||||
synchronized (parent.children)
|
||||
{
|
||||
parent.children.add (this);
|
||||
}
|
||||
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
@ -214,7 +221,12 @@ private static class Coordinate
|
||||
destroyHandle () throws IllegalStateException
|
||||
{
|
||||
if (parent != null)
|
||||
parent.children.remove (this);
|
||||
{
|
||||
synchronized (parent.children)
|
||||
{
|
||||
parent.children.remove (this);
|
||||
}
|
||||
}
|
||||
|
||||
EmacsActivity.invalidateFocus ();
|
||||
|
||||
@ -1163,10 +1175,20 @@ private static class Coordinate
|
||||
/* Reparent this window to the other window. */
|
||||
|
||||
if (parent != null)
|
||||
parent.children.remove (this);
|
||||
{
|
||||
synchronized (parent.children)
|
||||
{
|
||||
parent.children.remove (this);
|
||||
}
|
||||
}
|
||||
|
||||
if (otherWindow != null)
|
||||
otherWindow.children.add (this);
|
||||
{
|
||||
synchronized (otherWindow.children)
|
||||
{
|
||||
otherWindow.children.add (this);
|
||||
}
|
||||
}
|
||||
|
||||
parent = otherWindow;
|
||||
|
||||
@ -1239,9 +1261,12 @@ else if (EmacsWindow.this.isMapped)
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
synchronized (parent.children)
|
||||
{
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
}
|
||||
|
||||
/* Request a relayout. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@ -1261,9 +1286,12 @@ else if (EmacsWindow.this.isMapped)
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
synchronized (parent.children)
|
||||
{
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
}
|
||||
|
||||
/* Request a relayout. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@ -1276,6 +1304,86 @@ else if (EmacsWindow.this.isMapped)
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void
|
||||
reconfigure (final EmacsWindow window, final int stackMode)
|
||||
{
|
||||
ListIterator<EmacsWindow> iterator;
|
||||
EmacsWindow object;
|
||||
|
||||
/* This does nothing here. */
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
/* If window is NULL, call lower or upper subject to
|
||||
stackMode. */
|
||||
|
||||
if (window == null)
|
||||
{
|
||||
if (stackMode == 1) /* ANDROID_BELOW */
|
||||
lower ();
|
||||
else
|
||||
raise ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, if window.parent is distinct from this, return. */
|
||||
if (window.parent != this.parent)
|
||||
return;
|
||||
|
||||
/* Synchronize with the parent's child list. Iterate over each
|
||||
item until WINDOW is encountered, before moving this window to
|
||||
the location prescribed by STACKMODE. */
|
||||
|
||||
synchronized (parent.children)
|
||||
{
|
||||
/* Remove this window from parent.children, for it will be
|
||||
reinserted before or after WINDOW. */
|
||||
parent.children.remove (this);
|
||||
|
||||
/* Create an iterator. */
|
||||
iterator = parent.children.listIterator ();
|
||||
|
||||
while (iterator.hasNext ())
|
||||
{
|
||||
object = iterator.next ();
|
||||
|
||||
if (object == window)
|
||||
{
|
||||
/* Now place this before or after the cursor of the
|
||||
iterator. */
|
||||
|
||||
if (stackMode == 0) /* ANDROID_ABOVE */
|
||||
iterator.add (this);
|
||||
else
|
||||
{
|
||||
iterator.previous ();
|
||||
iterator.add (this);
|
||||
}
|
||||
|
||||
/* Effect the same adjustment upon the view
|
||||
hiearchy. */
|
||||
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
if (stackMode == 0)
|
||||
view.moveAbove (window.view);
|
||||
else
|
||||
view.moveBelow (window.view);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* parent.children does not list WINDOW, which should never
|
||||
transpire. */
|
||||
EmacsNative.emacsAbort ();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int[]
|
||||
getWindowGeometry ()
|
||||
{
|
||||
|
@ -104,6 +104,7 @@ struct android_emacs_window
|
||||
jmethodID make_input_focus;
|
||||
jmethodID raise;
|
||||
jmethodID lower;
|
||||
jmethodID reconfigure;
|
||||
jmethodID get_window_geometry;
|
||||
jmethodID translate_coordinates;
|
||||
jmethodID set_dont_accept_focus;
|
||||
@ -1755,6 +1756,7 @@ android_init_emacs_window (void)
|
||||
FIND_METHOD (make_input_focus, "makeInputFocus", "(J)V");
|
||||
FIND_METHOD (raise, "raise", "()V");
|
||||
FIND_METHOD (lower, "lower", "()V");
|
||||
FIND_METHOD (reconfigure, "reconfigure", "(Lorg/gnu/emacs/EmacsWindow;I)V");
|
||||
FIND_METHOD (get_window_geometry, "getWindowGeometry",
|
||||
"()[I");
|
||||
FIND_METHOD (translate_coordinates, "translateCoordinates",
|
||||
@ -4963,6 +4965,37 @@ android_lower_window (android_window handle)
|
||||
android_exception_check ();
|
||||
}
|
||||
|
||||
void
|
||||
android_reconfigure_wm_window (android_window handle,
|
||||
enum android_wc_value_mask value_mask,
|
||||
struct android_window_changes *values)
|
||||
{
|
||||
jobject sibling, window;
|
||||
|
||||
window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
|
||||
|
||||
if (!(value_mask & ANDROID_CW_STACK_MODE))
|
||||
return;
|
||||
|
||||
/* If value_mask & ANDROID_CW_SIBLING, place HANDLE above or below
|
||||
values->sibling pursuant to values->stack_mode; else, reposition
|
||||
it at the top or the bottom of its parent. */
|
||||
|
||||
sibling = NULL;
|
||||
|
||||
if (value_mask & ANDROID_CW_SIBLING)
|
||||
sibling = android_resolve_handle (values->sibling,
|
||||
ANDROID_HANDLE_WINDOW);
|
||||
|
||||
(*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
|
||||
window,
|
||||
window_class.class,
|
||||
window_class.reconfigure,
|
||||
sibling,
|
||||
(jint) values->stack_mode);
|
||||
android_exception_check ();
|
||||
}
|
||||
|
||||
int
|
||||
android_query_tree (android_window handle, android_window *root_return,
|
||||
android_window *parent_return,
|
||||
|
@ -1591,7 +1591,8 @@ and width values are in pixels.
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFUN ("android-frame-edges", Fandroid_frame_edges, Sandroid_frame_edges, 0, 2, 0,
|
||||
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
|
||||
@ -1693,6 +1694,28 @@ TERMINAL is a frame. */)
|
||||
#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.
|
||||
@ -1709,19 +1732,25 @@ that of FRAME2. Hence the position of FRAME2 in its display's Z
|
||||
\(stacking) order relative to all other frames excluding FRAME1 remains
|
||||
unaltered.
|
||||
|
||||
The Android system refuses to restack windows, so this does not
|
||||
work. */)
|
||||
(Lisp_Object frame1, Lisp_Object frame2, Lisp_Object frame3)
|
||||
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
|
||||
/* This is not supported on Android because of limitations in the
|
||||
platform that prevent ViewGroups from restacking
|
||||
SurfaceViews. */
|
||||
return Qnil;
|
||||
#endif
|
||||
#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",
|
||||
|
@ -564,6 +564,24 @@ enum android_ic_mode
|
||||
ANDROID_IC_MODE_TEXT = 2,
|
||||
};
|
||||
|
||||
enum android_stack_mode
|
||||
{
|
||||
ANDROID_ABOVE = 0,
|
||||
ANDROID_BELOW = 1,
|
||||
};
|
||||
|
||||
enum android_wc_value_mask
|
||||
{
|
||||
ANDROID_CW_SIBLING = 0,
|
||||
ANDROID_CW_STACK_MODE = 1,
|
||||
};
|
||||
|
||||
struct android_window_changes
|
||||
{
|
||||
android_window sibling;
|
||||
enum android_stack_mode stack_mode;
|
||||
};
|
||||
|
||||
extern int android_pending (void);
|
||||
extern void android_next_event (union android_event *);
|
||||
extern bool android_check_if_event (union android_event *,
|
||||
@ -643,6 +661,9 @@ extern void android_bell (void);
|
||||
extern void android_set_input_focus (android_window, unsigned long);
|
||||
extern void android_raise_window (android_window);
|
||||
extern void android_lower_window (android_window);
|
||||
extern void android_reconfigure_wm_window (android_window,
|
||||
enum android_wc_value_mask,
|
||||
struct android_window_changes *);
|
||||
extern int android_query_tree (android_window, android_window *,
|
||||
android_window *, android_window **,
|
||||
unsigned int *);
|
||||
|
Loading…
Reference in New Issue
Block a user