mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Android: Tidied up some code in AndroidComponentPeer
This commit is contained in:
parent
a9b5fe3a39
commit
c0cb5dcf34
1 changed files with 174 additions and 222 deletions
|
|
@ -186,7 +186,6 @@ static const uint8 javaComponentPeerView[] =
|
|||
|
||||
//==============================================================================
|
||||
#if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra
|
||||
// Returns true if the intent was handled.
|
||||
extern bool juce_handleNotificationIntent (void*);
|
||||
extern void juce_firebaseDeviceNotificationsTokenRefreshed (void*);
|
||||
extern void juce_firebaseRemoteNotificationReceived (void*);
|
||||
|
|
@ -197,21 +196,19 @@ static const uint8 javaComponentPeerView[] =
|
|||
|
||||
//==============================================================================
|
||||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
||||
METHOD (create, "<init>", "(II)V")
|
||||
METHOD (create, "<init>", "(II)V")
|
||||
|
||||
DECLARE_JNI_CLASS (AndroidLayoutParams, "android/view/ViewGroup$LayoutParams")
|
||||
#undef JNI_CLASS_MEMBERS
|
||||
|
||||
//==============================================================================
|
||||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
||||
METHOD (addView, "addView", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V") \
|
||||
METHOD (removeView, "removeView", "(Landroid/view/View;)V") \
|
||||
METHOD (updateViewLayout, "updateViewLayout", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V")
|
||||
METHOD (addView, "addView", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V") \
|
||||
METHOD (removeView, "removeView", "(Landroid/view/View;)V") \
|
||||
METHOD (updateViewLayout, "updateViewLayout", "(Landroid/view/View;Landroid/view/ViewGroup$LayoutParams;)V")
|
||||
|
||||
DECLARE_JNI_CLASS (AndroidViewManager, "android/view/ViewManager")
|
||||
#undef JNI_CLASS_MEMBERS
|
||||
|
||||
//==============================================================================
|
||||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
||||
METHOD (create, "<init>", "(IIIIIII)V") \
|
||||
FIELD (gravity, "gravity", "I") \
|
||||
|
|
@ -220,7 +217,6 @@ DECLARE_JNI_CLASS (AndroidViewManager, "android/view/ViewManager")
|
|||
DECLARE_JNI_CLASS (AndroidWindowManagerLayoutParams, "android/view/WindowManager$LayoutParams")
|
||||
#undef JNI_CLASS_MEMBERS
|
||||
|
||||
//==============================================================================
|
||||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
||||
METHOD (getDecorView, "getDecorView", "()Landroid/view/View;") \
|
||||
METHOD (setFlags, "setFlags", "(II)V") \
|
||||
|
|
@ -229,6 +225,7 @@ DECLARE_JNI_CLASS (AndroidWindowManagerLayoutParams, "android/view/WindowManager
|
|||
DECLARE_JNI_CLASS (AndroidWindow, "android/view/Window")
|
||||
#undef JNI_CLASS_MEMBERS
|
||||
|
||||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
enum
|
||||
|
|
@ -244,7 +241,6 @@ namespace
|
|||
};
|
||||
|
||||
constexpr int fullScreenFlags = SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
|
||||
constexpr int FLAG_NOT_FOCUSABLE = 0x8;
|
||||
}
|
||||
|
||||
|
|
@ -254,11 +250,7 @@ class AndroidComponentPeer : public ComponentPeer,
|
|||
{
|
||||
public:
|
||||
AndroidComponentPeer (Component& comp, int windowStyleFlags, void* nativeViewHandle)
|
||||
: ComponentPeer (comp, windowStyleFlags),
|
||||
fullScreen (false),
|
||||
navBarsHidden (false),
|
||||
sizeAllocated (0),
|
||||
scale ((float) Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale)
|
||||
: ComponentPeer (comp, windowStyleFlags)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
|
|
@ -274,7 +266,7 @@ public:
|
|||
|
||||
// we don't know if the user is holding on to a local ref to this, so
|
||||
// explicitly create a new one
|
||||
auto nativeView = LocalRef<jobject>(env->NewLocalRef(static_cast<jobject> (nativeViewHandle)));
|
||||
auto nativeView = LocalRef<jobject> (env->NewLocalRef (static_cast<jobject> (nativeViewHandle)));
|
||||
|
||||
if (env->IsInstanceOf (nativeView.get(), AndroidActivity))
|
||||
{
|
||||
|
|
@ -301,10 +293,9 @@ public:
|
|||
viewGroupIsWindow = true;
|
||||
|
||||
LocalRef<jobject> viewLayoutParams (env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2));
|
||||
|
||||
env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, viewLayoutParams.get());
|
||||
|
||||
Rectangle<int> physicalBounds = comp.getBoundsInParent() * scale;
|
||||
auto physicalBounds = (comp.getBoundsInParent().toFloat() * scale).toNearestInt();
|
||||
|
||||
view.callVoidMethod (AndroidView.layout,
|
||||
physicalBounds.getX(), physicalBounds.getY(), physicalBounds.getRight(), physicalBounds.getBottom());
|
||||
|
|
@ -314,6 +305,7 @@ public:
|
|||
physicalBounds.getX(), physicalBounds.getY(),
|
||||
TYPE_APPLICATION, FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS | FLAG_NOT_FOCUSABLE,
|
||||
component.isOpaque() ? PIXEL_FORMAT_OPAQUE : PIXEL_FORMAT_TRANSPARENT));
|
||||
|
||||
env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.gravity, GRAVITY_LEFT | GRAVITY_TOP);
|
||||
env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.windowAnimations, 0x01030000 /* android.R.style.Animation */);
|
||||
|
||||
|
|
@ -335,40 +327,23 @@ public:
|
|||
|
||||
~AndroidComponentPeer() override
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
auto* env = getEnv();
|
||||
|
||||
env->CallVoidMethod (view, ComponentPeerView.clear);
|
||||
frontWindow = nullptr;
|
||||
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
GlobalRef localView (view);
|
||||
GlobalRef localViewGroup (viewGroup);
|
||||
|
||||
callOnMessageThread ([env, localView, localViewGroup]
|
||||
{
|
||||
if (env->IsInstanceOf (viewGroup.get(), AndroidActivity))
|
||||
env->CallVoidMethod (viewGroup.get(), AndroidActivity.setContentView, nullptr);
|
||||
if (env->IsInstanceOf (localViewGroup.get(), AndroidActivity))
|
||||
env->CallVoidMethod (localViewGroup.get(), AndroidActivity.setContentView, nullptr);
|
||||
else
|
||||
env->CallVoidMethod (viewGroup.get(), AndroidViewManager.removeView, view.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ViewDeleter : public CallbackMessage
|
||||
{
|
||||
ViewDeleter (const GlobalRef& view_, const GlobalRef& viewGroup_) : view (view_), group (viewGroup_) {}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
auto* callbackEnv = getEnv();
|
||||
|
||||
if (callbackEnv->IsInstanceOf (group.get(), AndroidActivity))
|
||||
callbackEnv->CallVoidMethod (group.get(), AndroidActivity.setContentView, nullptr);
|
||||
else
|
||||
callbackEnv->CallVoidMethod (group.get(), AndroidViewManager.removeView, view.get());
|
||||
}
|
||||
|
||||
private:
|
||||
GlobalRef view, group;
|
||||
};
|
||||
|
||||
(new ViewDeleter (view, viewGroup))->post();
|
||||
}
|
||||
env->CallVoidMethod (localViewGroup.get(), AndroidViewManager.removeView, localView.get());
|
||||
});
|
||||
}
|
||||
|
||||
void* getNativeHandle() const override
|
||||
|
|
@ -378,29 +353,12 @@ public:
|
|||
|
||||
void setVisible (bool shouldBeVisible) override
|
||||
{
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
GlobalRef localView (view);
|
||||
|
||||
callOnMessageThread ([localView, shouldBeVisible]
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct VisibilityChanger : public CallbackMessage
|
||||
{
|
||||
VisibilityChanger (const GlobalRef& view_, bool shouldBeVisible_)
|
||||
: view (view_), shouldBeVisible (shouldBeVisible_)
|
||||
{}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
|
||||
}
|
||||
|
||||
GlobalRef view;
|
||||
bool shouldBeVisible;
|
||||
};
|
||||
|
||||
(new VisibilityChanger (view, shouldBeVisible))->post();
|
||||
}
|
||||
localView.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
|
||||
});
|
||||
}
|
||||
|
||||
void setTitle (const String& title) override
|
||||
|
|
@ -410,60 +368,48 @@ public:
|
|||
|
||||
void setBounds (const Rectangle<int>& userRect, bool isNowFullScreen) override
|
||||
{
|
||||
Rectangle<int> r = (userRect.toFloat() * scale).toNearestInt();
|
||||
auto bounds = (userRect.toFloat() * scale).toNearestInt();
|
||||
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
fullScreen = isNowFullScreen;
|
||||
|
||||
{
|
||||
view.callVoidMethod (AndroidView.layout,
|
||||
r.getX(), r.getY(), r.getRight(), r.getBottom());
|
||||
view.callVoidMethod (AndroidView.layout,
|
||||
bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom());
|
||||
|
||||
if (viewGroup != nullptr && viewGroupIsWindow)
|
||||
{
|
||||
LocalRef<jobject> windowLayoutParams (env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.create,
|
||||
r.getWidth(), r.getHeight(),
|
||||
r.getX(), r.getY(),
|
||||
TYPE_APPLICATION, FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS,
|
||||
component.isOpaque() ? PIXEL_FORMAT_OPAQUE : PIXEL_FORMAT_TRANSPARENT));
|
||||
env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.gravity, 0x3 /* LEFT */ | 0x30 /* TOP */);
|
||||
env->CallVoidMethod (viewGroup.get(), AndroidViewManager.updateViewLayout, view.get(), windowLayoutParams.get());
|
||||
}
|
||||
if (viewGroup != nullptr && viewGroupIsWindow)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
LocalRef<jobject> windowLayoutParams (env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.create,
|
||||
bounds.getWidth(), bounds.getHeight(), bounds.getX(), bounds.getY(),
|
||||
TYPE_APPLICATION, FLAG_NOT_TOUCH_MODAL | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS,
|
||||
component.isOpaque() ? PIXEL_FORMAT_OPAQUE : PIXEL_FORMAT_TRANSPARENT));
|
||||
|
||||
env->SetIntField (windowLayoutParams.get(), AndroidWindowManagerLayoutParams.gravity, GRAVITY_LEFT | GRAVITY_TOP);
|
||||
env->CallVoidMethod (viewGroup.get(), AndroidViewManager.updateViewLayout, view.get(), windowLayoutParams.get());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
class ViewMover : public CallbackMessage
|
||||
GlobalRef localView (view);
|
||||
|
||||
MessageManager::callAsync ([localView, bounds]
|
||||
{
|
||||
public:
|
||||
ViewMover (const GlobalRef& v, Rectangle<int> boundsToUse) : view (v), bounds (boundsToUse) {}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
view.callVoidMethod (AndroidView.layout,
|
||||
bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom());
|
||||
}
|
||||
|
||||
private:
|
||||
GlobalRef view;
|
||||
Rectangle<int> bounds;
|
||||
};
|
||||
|
||||
(new ViewMover (view, r))->post();
|
||||
localView.callVoidMethod (AndroidView.layout,
|
||||
bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle<int> getBounds() const override
|
||||
{
|
||||
Rectangle<int> r (view.callIntMethod (AndroidView.getLeft),
|
||||
view.callIntMethod (AndroidView.getTop),
|
||||
view.callIntMethod (AndroidView.getWidth),
|
||||
view.callIntMethod (AndroidView.getHeight));
|
||||
Rectangle<int> bounds (view.callIntMethod (AndroidView.getLeft),
|
||||
view.callIntMethod (AndroidView.getTop),
|
||||
view.callIntMethod (AndroidView.getWidth),
|
||||
view.callIntMethod (AndroidView.getHeight));
|
||||
|
||||
return r / scale;
|
||||
return (bounds.toFloat() / scale).toNearestInt();
|
||||
}
|
||||
|
||||
void handleScreenSizeChange() override
|
||||
|
|
@ -512,49 +458,32 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool shouldNavBarsBeHidden (bool shouldBeFullScreen) const
|
||||
{
|
||||
if (shouldBeFullScreen)
|
||||
if (Component* kiosk = Desktop::getInstance().getKioskModeComponent())
|
||||
if (kiosk->getPeer() == this)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setNavBarsHidden (bool hidden)
|
||||
{
|
||||
view.callVoidMethod (ComponentPeerView.setSystemUiVisibilityCompat,
|
||||
hidden ? (jint) (fullScreenFlags)
|
||||
: (jint) (SYSTEM_UI_FLAG_VISIBLE));
|
||||
|
||||
navBarsHidden = hidden;
|
||||
}
|
||||
|
||||
void setFullScreen (bool shouldBeFullScreen) override
|
||||
{
|
||||
// updating the nav bar visibility is a bit odd on Android - need to wait for
|
||||
if (shouldNavBarsBeHidden (shouldBeFullScreen))
|
||||
{
|
||||
if (! isTimerRunning())
|
||||
{
|
||||
startTimer (500);
|
||||
}
|
||||
if (isTimerRunning())
|
||||
return;
|
||||
|
||||
startTimer (500);
|
||||
}
|
||||
else
|
||||
{
|
||||
setNavBarsHidden (false);
|
||||
}
|
||||
|
||||
Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getDisplays().getPrimaryDisplay()->userArea
|
||||
: lastNonFullscreenBounds);
|
||||
auto newBounds = [&]
|
||||
{
|
||||
if (navBarsHidden || shouldBeFullScreen)
|
||||
if (auto* display = Desktop::getInstance().getDisplays().getPrimaryDisplay())
|
||||
return navBarsHidden ? display->totalArea
|
||||
: display->userArea;
|
||||
|
||||
if ((! shouldBeFullScreen) && r.isEmpty())
|
||||
r = getBounds();
|
||||
return lastNonFullscreenBounds.isEmpty() ? getBounds() : lastNonFullscreenBounds;
|
||||
}();
|
||||
|
||||
// (can't call the component's setBounds method because that'll reset our fullscreen flag)
|
||||
if (! r.isEmpty())
|
||||
setBounds (r, shouldBeFullScreen);
|
||||
if (! newBounds.isEmpty())
|
||||
setBounds (newBounds, shouldBeFullScreen);
|
||||
|
||||
component.repaint();
|
||||
}
|
||||
|
|
@ -564,13 +493,6 @@ public:
|
|||
return fullScreen;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
setNavBarsHidden (shouldNavBarsBeHidden (fullScreen));
|
||||
setFullScreen (fullScreen);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
void setIcon (const Image& /*newIcon*/) override
|
||||
{
|
||||
// n/a
|
||||
|
|
@ -588,7 +510,7 @@ public:
|
|||
BorderSize<int> getFrameSize() const override
|
||||
{
|
||||
// TODO
|
||||
return BorderSize<int>();
|
||||
return {};
|
||||
}
|
||||
|
||||
bool setAlwaysOnTop (bool /*alwaysOnTop*/) override
|
||||
|
|
@ -603,7 +525,6 @@ public:
|
|||
if (frontWindow != this)
|
||||
{
|
||||
view.callVoidMethod (AndroidView.bringToFront);
|
||||
|
||||
frontWindow = this;
|
||||
}
|
||||
|
||||
|
|
@ -622,11 +543,17 @@ public:
|
|||
void handleMouseDownCallback (int index, Point<float> sysPos, int64 time)
|
||||
{
|
||||
lastMousePos = sysPos / scale;
|
||||
Point<float> pos = globalToLocal (lastMousePos);
|
||||
auto pos = globalToLocal (lastMousePos);
|
||||
|
||||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before.
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons(),
|
||||
MouseInputSource::invalidPressure, MouseInputSource::invalidOrientation, time, {}, index);
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch,
|
||||
pos,
|
||||
ModifierKeys::currentModifiers.withoutMouseButtons(),
|
||||
MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation,
|
||||
time,
|
||||
{},
|
||||
index);
|
||||
|
||||
if (isValidPeer (this))
|
||||
handleMouseDragCallback (index, sysPos, time);
|
||||
|
|
@ -635,19 +562,27 @@ public:
|
|||
void handleMouseDragCallback (int index, Point<float> sysPos, int64 time)
|
||||
{
|
||||
lastMousePos = sysPos / scale;
|
||||
Point<float> pos = globalToLocal (lastMousePos);
|
||||
auto pos = globalToLocal (lastMousePos);
|
||||
|
||||
jassert (index < 64);
|
||||
touchesDown = (touchesDown | (1 << (index & 63)));
|
||||
|
||||
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier);
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier),
|
||||
MouseInputSource::invalidPressure, MouseInputSource::invalidOrientation, time, {}, index);
|
||||
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch,
|
||||
pos,
|
||||
ModifierKeys::currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier),
|
||||
MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation,
|
||||
time,
|
||||
{},
|
||||
index);
|
||||
}
|
||||
|
||||
void handleMouseUpCallback (int index, Point<float> sysPos, int64 time)
|
||||
{
|
||||
lastMousePos = sysPos / scale;
|
||||
Point<float> pos = globalToLocal (lastMousePos);
|
||||
auto pos = globalToLocal (lastMousePos);
|
||||
|
||||
jassert (index < 64);
|
||||
touchesDown = (touchesDown & ~(1 << (index & 63)));
|
||||
|
|
@ -655,8 +590,14 @@ public:
|
|||
if (touchesDown == 0)
|
||||
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons();
|
||||
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch, pos, ModifierKeys::currentModifiers.withoutMouseButtons(), MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation, time, {}, index);
|
||||
handleMouseEvent (MouseInputSource::InputSourceType::touch,
|
||||
pos,
|
||||
ModifierKeys::currentModifiers.withoutMouseButtons(),
|
||||
MouseInputSource::invalidPressure,
|
||||
MouseInputSource::invalidOrientation,
|
||||
time,
|
||||
{},
|
||||
index);
|
||||
}
|
||||
|
||||
void handleKeyDownCallback (int k, int kc)
|
||||
|
|
@ -675,9 +616,8 @@ public:
|
|||
if (auto* app = JUCEApplicationBase::getInstance())
|
||||
handled = app->backButtonPressed();
|
||||
|
||||
if (Component* kiosk = Desktop::getInstance().getKioskModeComponent())
|
||||
if (kiosk->getPeer() == this)
|
||||
setNavBarsHidden (navBarsHidden);
|
||||
if (isKioskModeComponent())
|
||||
setNavBarsHidden (navBarsHidden);
|
||||
|
||||
if (! handled)
|
||||
{
|
||||
|
|
@ -692,7 +632,6 @@ public:
|
|||
env->CallVoidMethod (activity.get(), finishMethod);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void handleKeyboardHiddenCallback()
|
||||
|
|
@ -704,9 +643,8 @@ public:
|
|||
|
||||
void handleAppResumedCallback()
|
||||
{
|
||||
if (Component* kiosk = Desktop::getInstance().getKioskModeComponent())
|
||||
if (kiosk->getPeer() == this)
|
||||
setNavBarsHidden (navBarsHidden);
|
||||
if (isKioskModeComponent())
|
||||
setNavBarsHidden (navBarsHidden);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -761,41 +699,35 @@ public:
|
|||
{
|
||||
view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get());
|
||||
|
||||
// updating the nav bar visibility is a bit odd on Android - need to wait for
|
||||
if (! isTimerRunning())
|
||||
hideNavBarDelayed();
|
||||
startTimer (500);
|
||||
}
|
||||
|
||||
void hideNavBarDelayed()
|
||||
{
|
||||
startTimer (500);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void handlePaintCallback (jobject canvas, jobject paint)
|
||||
{
|
||||
auto* env = getEnv();
|
||||
|
||||
jobject rect = env->CallObjectMethod (canvas, AndroidCanvas.getClipBounds);
|
||||
const int left = env->GetIntField (rect, AndroidRect.left);
|
||||
const int top = env->GetIntField (rect, AndroidRect.top);
|
||||
const int right = env->GetIntField (rect, AndroidRect.right);
|
||||
const int bottom = env->GetIntField (rect, AndroidRect.bottom);
|
||||
auto left = env->GetIntField (rect, AndroidRect.left);
|
||||
auto top = env->GetIntField (rect, AndroidRect.top);
|
||||
auto right = env->GetIntField (rect, AndroidRect.right);
|
||||
auto bottom = env->GetIntField (rect, AndroidRect.bottom);
|
||||
env->DeleteLocalRef (rect);
|
||||
|
||||
const Rectangle<int> clip (left, top, right - left, bottom - top);
|
||||
auto clip = Rectangle<int>::leftTopRightBottom (left, top, right, bottom);
|
||||
|
||||
if (clip.isEmpty())
|
||||
return;
|
||||
|
||||
auto sizeNeeded = clip.getWidth() * clip.getHeight();
|
||||
|
||||
const int sizeNeeded = clip.getWidth() * clip.getHeight();
|
||||
if (sizeAllocated < sizeNeeded)
|
||||
{
|
||||
buffer.clear();
|
||||
sizeAllocated = sizeNeeded;
|
||||
buffer = GlobalRef (LocalRef<jobject> ((jobject) env->NewIntArray (sizeNeeded)));
|
||||
}
|
||||
else if (sizeNeeded == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), nullptr))
|
||||
{
|
||||
|
|
@ -821,32 +753,15 @@ public:
|
|||
|
||||
void repaint (const Rectangle<int>& userArea) override
|
||||
{
|
||||
Rectangle<int> area = userArea * scale;
|
||||
auto area = (userArea.toFloat() * scale).toNearestInt();
|
||||
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
GlobalRef localView (view);
|
||||
|
||||
callOnMessageThread ([area, localView]
|
||||
{
|
||||
view.callVoidMethod (AndroidView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ViewRepainter : public CallbackMessage
|
||||
{
|
||||
ViewRepainter (const GlobalRef& view_, const Rectangle<int>& area_)
|
||||
: view (view_), area (area_) {}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
view.callVoidMethod (AndroidView.invalidate, area.getX(), area.getY(),
|
||||
area.getRight(), area.getBottom());
|
||||
}
|
||||
|
||||
private:
|
||||
GlobalRef view;
|
||||
const Rectangle<int> area;
|
||||
};
|
||||
|
||||
(new ViewRepainter (view, area))->post();
|
||||
}
|
||||
localView.callVoidMethod (AndroidView.invalidate,
|
||||
area.getX(), area.getY(), area.getRight(), area.getBottom());
|
||||
});
|
||||
}
|
||||
|
||||
void performAnyPendingRepaintsNow() override
|
||||
|
|
@ -878,28 +793,18 @@ public:
|
|||
|
||||
if (appContext.get() != nullptr)
|
||||
{
|
||||
|
||||
env->CallVoidMethod (appContext.get(),
|
||||
AndroidApplication.unregisterActivityLifecycleCallbacks,
|
||||
activityCallbackListener.get());
|
||||
clear();
|
||||
activityCallbackListener.clear();
|
||||
|
||||
const_cast<Displays &> (Desktop::getInstance().getDisplays()).refresh();
|
||||
const_cast<Displays&> (Desktop::getInstance().getDisplays()).refresh();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
GlobalRef view, viewGroup;
|
||||
bool viewGroupIsWindow = false;
|
||||
GlobalRef buffer;
|
||||
bool fullScreen;
|
||||
bool navBarsHidden;
|
||||
int sizeAllocated;
|
||||
float scale;
|
||||
|
||||
//==============================================================================
|
||||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
||||
METHOD (create, "<init>", "(Landroid/content/Context;ZJ)V") \
|
||||
|
|
@ -940,16 +845,6 @@ private:
|
|||
static void JNICALL handleAppResumedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAppResumedCallback(); }
|
||||
|
||||
//==============================================================================
|
||||
friend class Displays;
|
||||
static AndroidComponentPeer* frontWindow;
|
||||
static GlobalRef activityCallbackListener;
|
||||
|
||||
//==============================================================================
|
||||
static constexpr int GRAVITY_LEFT = 0x3, GRAVITY_TOP = 0x30;
|
||||
static constexpr int TYPE_APPLICATION = 0x2;
|
||||
static constexpr int FLAG_NOT_TOUCH_MODAL = 0x20, FLAG_LAYOUT_IN_SCREEN = 0x100, FLAG_LAYOUT_NO_LIMITS = 0x200;
|
||||
static constexpr int PIXEL_FORMAT_OPAQUE = -1, PIXEL_FORMAT_TRANSPARENT = -2;
|
||||
|
||||
struct PreallocatedImage : public ImagePixelData
|
||||
{
|
||||
PreallocatedImage (int width_, int height_, jint* data_, bool hasAlpha_)
|
||||
|
|
@ -1008,6 +903,63 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PreallocatedImage)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void timerCallback() override
|
||||
{
|
||||
setNavBarsHidden (shouldNavBarsBeHidden (fullScreen));
|
||||
setFullScreen (fullScreen);
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
bool isKioskModeComponent() const
|
||||
{
|
||||
if (auto* kiosk = Desktop::getInstance().getKioskModeComponent())
|
||||
return kiosk->getPeer() == this;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool shouldNavBarsBeHidden (bool shouldBeFullScreen) const
|
||||
{
|
||||
return (shouldBeFullScreen && isKioskModeComponent());
|
||||
}
|
||||
|
||||
void setNavBarsHidden (bool hidden)
|
||||
{
|
||||
if (navBarsHidden != hidden)
|
||||
{
|
||||
navBarsHidden = hidden;
|
||||
|
||||
view.callVoidMethod (ComponentPeerView.setSystemUiVisibilityCompat,
|
||||
(navBarsHidden ? (jint) (fullScreenFlags) : (jint) (SYSTEM_UI_FLAG_VISIBLE)));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
static void callOnMessageThread (Callback&& callback)
|
||||
{
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
callback();
|
||||
else
|
||||
MessageManager::callAsync (std::forward<Callback> (callback));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
friend class Displays;
|
||||
static AndroidComponentPeer* frontWindow;
|
||||
static GlobalRef activityCallbackListener;
|
||||
|
||||
static constexpr int GRAVITY_LEFT = 0x3, GRAVITY_TOP = 0x30;
|
||||
static constexpr int TYPE_APPLICATION = 0x2;
|
||||
static constexpr int FLAG_NOT_TOUCH_MODAL = 0x20, FLAG_LAYOUT_IN_SCREEN = 0x100, FLAG_LAYOUT_NO_LIMITS = 0x200;
|
||||
static constexpr int PIXEL_FORMAT_OPAQUE = -1, PIXEL_FORMAT_TRANSPARENT = -2;
|
||||
|
||||
GlobalRef view, viewGroup, buffer;
|
||||
bool viewGroupIsWindow = false, fullScreen = false, navBarsHidden = false;
|
||||
int sizeAllocated = 0;
|
||||
float scale = (float) Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale;
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer)
|
||||
};
|
||||
|
||||
|
|
@ -1430,7 +1382,7 @@ public:
|
|||
auto& displays = Desktop::getInstance().getDisplays();
|
||||
auto& mainDisplay = *displays.getPrimaryDisplay();
|
||||
|
||||
Rectangle<int> userArea = newBounds / mainDisplay.scale;
|
||||
auto userArea = (newBounds.toFloat() / mainDisplay.scale).toNearestInt();
|
||||
|
||||
if (userArea != mainDisplay.userArea)
|
||||
const_cast<Displays&> (displays).refresh();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue