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
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;
}
/* 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 ()
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)
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;
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
if (parent != null)
{
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ parent.children.add (this);
+ }
+
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@Override
public void
destroyHandle () throws IllegalStateException
{
if (parent != null)
- parent.children.remove (this);
+ {
+ synchronized (parent.children)
+ {
+ parent.children.remove (this);
+ }
+ }
EmacsActivity.invalidateFocus ();
/* 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;
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 () {
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 () {
});
}
+ 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 ()
{
jmethodID make_input_focus;
jmethodID raise;
jmethodID lower;
+ jmethodID reconfigure;
jmethodID get_window_geometry;
jmethodID translate_coordinates;
jmethodID set_dont_accept_focus;
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",
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,
#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
#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.
\(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",
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 *,
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 *);