2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 // (This file gets included by juce_win32_NativeCode.cpp, rather than being
27 // compiled on its own).
28 #if JUCE_INCLUDED_FILE
31 //==============================================================================
32 class AndroidComponentPeer
: public ComponentPeer
35 //==============================================================================
36 AndroidComponentPeer (Component
* const component
, const int windowStyleFlags
)
37 : ComponentPeer (component
, windowStyleFlags
),
38 view (android
.activity
.callObjectMethod (android
.createNewView
, component
->isOpaque())),
39 usingAndroidGraphics (false),
47 ~AndroidComponentPeer()
49 if (MessageManager::getInstance()->isThisTheMessageThread())
51 android
.activity
.callVoidMethod (android
.deleteView
, view
.get());
55 class ViewDeleter
: public CallbackMessage
58 ViewDeleter (const GlobalRef
& view_
)
64 void messageCallback()
66 android
.activity
.callVoidMethod (android
.deleteView
, view
.get());
73 new ViewDeleter (view
);
79 void* getNativeHandle() const
81 return (void*) view
.get();
84 void setVisible (bool shouldBeVisible
)
86 if (MessageManager::getInstance()->isThisTheMessageThread())
88 view
.callVoidMethod (android
.setVisible
, shouldBeVisible
);
92 class VisibilityChanger
: public CallbackMessage
95 VisibilityChanger (const GlobalRef
& view_
, bool shouldBeVisible_
)
96 : view (view_
), shouldBeVisible (shouldBeVisible_
)
101 void messageCallback()
103 view
.callVoidMethod (android
.setVisible
, shouldBeVisible
);
108 bool shouldBeVisible
;
111 new VisibilityChanger (view
, shouldBeVisible
);
115 void setTitle (const String
& title
)
117 view
.callVoidMethod (android
.setViewName
, javaString (title
).get());
120 void setPosition (int x
, int y
)
122 const Rectangle
<int> pos (getBounds());
123 setBounds (x
, y
, pos
.getWidth(), pos
.getHeight(), false);
126 void setSize (int w
, int h
)
128 const Rectangle
<int> pos (getBounds());
129 setBounds (pos
.getX(), pos
.getY(), w
, h
, false);
132 void setBounds (int x
, int y
, int w
, int h
, bool isNowFullScreen
)
134 if (MessageManager::getInstance()->isThisTheMessageThread())
136 fullScreen
= isNowFullScreen
;
140 view
.callVoidMethod (android
.layout
, x
, y
, x
+ w
, y
+ h
);
144 class ViewMover
: public CallbackMessage
147 ViewMover (const GlobalRef
& view_
, int x_
, int y_
, int w_
, int h_
)
148 : view (view_
), x (x_
), y (y_
), w (w_
), h (h_
)
153 void messageCallback()
155 view
.callVoidMethod (android
.layout
, x
, y
, x
+ w
, y
+ h
);
163 new ViewMover (view
, x
, y
, w
, h
);
167 const Rectangle
<int> getBounds() const
169 return Rectangle
<int> (view
.callIntMethod (android
.getLeft
),
170 view
.callIntMethod (android
.getTop
),
171 view
.callIntMethod (android
.getWidth
),
172 view
.callIntMethod (android
.getHeight
));
175 const Point
<int> getScreenPosition() const
177 return Point
<int> (view
.callIntMethod (android
.getLeft
),
178 view
.callIntMethod (android
.getTop
));
181 const Point
<int> localToGlobal (const Point
<int>& relativePosition
)
183 return relativePosition
+ getScreenPosition();
186 const Point
<int> globalToLocal (const Point
<int>& screenPosition
)
188 return screenPosition
- getScreenPosition();
191 void setMinimised (bool shouldBeMinimised
)
196 bool isMinimised() const
201 void setFullScreen (bool shouldBeFullScreen
)
203 Rectangle
<int> r (shouldBeFullScreen
? Desktop::getInstance().getMainMonitorArea()
204 : lastNonFullscreenBounds
);
206 if ((! shouldBeFullScreen
) && r
.isEmpty())
209 // (can't call the component's setBounds method because that'll reset our fullscreen flag)
211 setBounds (r
.getX(), r
.getY(), r
.getWidth(), r
.getHeight(), shouldBeFullScreen
);
213 component
->repaint();
216 bool isFullScreen() const
221 void setIcon (const Image
& newIcon
)
226 bool contains (const Point
<int>& position
, bool trueIfInAChildWindow
) const
228 return isPositiveAndBelow (position
.getX(), component
->getWidth())
229 && isPositiveAndBelow (position
.getY(), component
->getHeight())
230 && ((! trueIfInAChildWindow
) || view
.callBooleanMethod (android
.containsPoint
, position
.getX(), position
.getY()));
233 const BorderSize
<int> getFrameSize() const
236 return BorderSize
<int>();
239 bool setAlwaysOnTop (bool alwaysOnTop
)
245 void toFront (bool makeActive
)
247 view
.callVoidMethod (android
.bringToFront
);
252 handleBroughtToFront();
255 void toBehind (ComponentPeer
* other
)
260 //==============================================================================
261 void handleMouseDownCallback (float x
, float y
, int64 time
)
263 lastMousePos
.setXY ((int) x
, (int) y
);
264 currentModifiers
= currentModifiers
.withoutMouseButtons();
265 handleMouseEvent (0, lastMousePos
, currentModifiers
, time
);
266 currentModifiers
= currentModifiers
.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier
);
267 handleMouseEvent (0, lastMousePos
, currentModifiers
, time
);
270 void handleMouseDragCallback (float x
, float y
, int64 time
)
272 lastMousePos
.setXY ((int) x
, (int) y
);
273 handleMouseEvent (0, lastMousePos
, currentModifiers
, time
);
276 void handleMouseUpCallback (float x
, float y
, int64 time
)
278 lastMousePos
.setXY ((int) x
, (int) y
);
279 currentModifiers
= currentModifiers
.withoutMouseButtons();
280 handleMouseEvent (0, lastMousePos
, currentModifiers
, time
);
283 //==============================================================================
284 bool isFocused() const
286 return view
.callBooleanMethod (android
.hasFocus
);
291 view
.callBooleanMethod (android
.requestFocus
);
294 void handleFocusChangeCallback (bool hasFocus
)
302 void textInputRequired (const Point
<int>& position
)
307 //==============================================================================
308 void handlePaintCallback (JNIEnv
* env
, jobject canvas
)
310 #if USE_ANDROID_CANVAS
311 if (usingAndroidGraphics
)
313 AndroidLowLevelGraphicsContext
g (canvas
);
319 jobject rect
= env
->CallObjectMethod (canvas
, android
.getClipBounds2
);
320 const int left
= env
->GetIntField (rect
, android
.rectLeft
);
321 const int top
= env
->GetIntField (rect
, android
.rectTop
);
322 const int right
= env
->GetIntField (rect
, android
.rectRight
);
323 const int bottom
= env
->GetIntField (rect
, android
.rectBottom
);
324 env
->DeleteLocalRef (rect
);
326 const Rectangle
<int> clip (left
, top
, right
- left
, bottom
- top
);
328 const int sizeNeeded
= clip
.getWidth() * clip
.getHeight();
329 if (sizeAllocated
< sizeNeeded
)
332 sizeAllocated
= sizeNeeded
;
333 buffer
= GlobalRef (env
->NewIntArray (sizeNeeded
));
336 jint
* dest
= env
->GetIntArrayElements ((jintArray
) buffer
.get(), 0);
341 Image
temp (new PreallocatedImage (clip
.getWidth(), clip
.getHeight(),
342 dest
, ! component
->isOpaque()));
345 LowLevelGraphicsSoftwareRenderer
g (temp
);
346 g
.setOrigin (-clip
.getX(), -clip
.getY());
351 env
->ReleaseIntArrayElements ((jintArray
) buffer
.get(), dest
, 0);
353 env
->CallVoidMethod (canvas
, android
.drawMemoryBitmap
, (jintArray
) buffer
.get(), 0, clip
.getWidth(),
354 (jfloat
) clip
.getX(), (jfloat
) clip
.getY(),
355 clip
.getWidth(), clip
.getHeight(), true, (jobject
) 0);
360 void repaint (const Rectangle
<int>& area
)
362 if (MessageManager::getInstance()->isThisTheMessageThread())
364 view
.callVoidMethod (android
.invalidate
, area
.getX(), area
.getY(), area
.getRight(), area
.getBottom());
368 class ViewRepainter
: public CallbackMessage
371 ViewRepainter (const GlobalRef
& view_
, const Rectangle
<int>& area_
)
372 : view (view_
), area (area_
)
377 void messageCallback()
379 view
.callVoidMethod (android
.invalidate
, area
.getX(), area
.getY(), area
.getRight(), area
.getBottom());
384 const Rectangle
<int>& area
;
387 new ViewRepainter (view
, area
);
391 void performAnyPendingRepaintsNow()
396 void setAlpha (float newAlpha
)
401 StringArray
getAvailableRenderingEngines()
403 StringArray
s (ComponentPeer::getAvailableRenderingEngines());
404 s
.add ("Android Canvas Renderer");
408 #if USE_ANDROID_CANVAS
409 int getCurrentRenderingEngine() const
411 return usingAndroidGraphics
? 1 : 0;
414 void setCurrentRenderingEngine (int index
)
416 if (usingAndroidGraphics
!= (index
> 0))
418 usingAndroidGraphics
= index
> 0;
419 component
->repaint();
424 //==============================================================================
425 static AndroidComponentPeer
* findPeerForJavaView (jobject viewToFind
)
427 for (int i
= getNumPeers(); --i
>= 0;)
429 AndroidComponentPeer
* const ap
= static_cast <AndroidComponentPeer
*> (getPeer(i
));
430 jassert (dynamic_cast <AndroidComponentPeer
*> (getPeer(i
)) != 0);
432 if (ap
->view
== viewToFind
)
439 static ModifierKeys currentModifiers
;
440 static Point
<int> lastMousePos
;
443 //==============================================================================
446 bool usingAndroidGraphics
, fullScreen
;
449 class PreallocatedImage
: public Image::SharedImage
452 //==============================================================================
453 PreallocatedImage (const int width_
, const int height_
, jint
* data_
, bool hasAlpha_
)
454 : Image::SharedImage (Image::ARGB
, width_
, height_
), data (data_
), hasAlpha (hasAlpha_
)
457 zeromem (data_
, width
* height
* sizeof (jint
));
464 PixelARGB
* pix
= (PixelARGB
*) data
;
466 for (int i
= width
* height
; --i
>= 0;)
468 pix
->unpremultiply();
474 Image::ImageType
getType() const { return Image::SoftwareImage
; }
475 LowLevelGraphicsContext
* createLowLevelContext() { return new LowLevelGraphicsSoftwareRenderer (Image (this)); }
477 void initialiseBitmapData (Image::BitmapData
& bm
, int x
, int y
, Image::BitmapData::ReadWriteMode mode
)
479 bm
.lineStride
= width
* sizeof (jint
);
480 bm
.pixelStride
= sizeof (jint
);
481 bm
.pixelFormat
= Image::ARGB
;
482 bm
.data
= (uint8
*) (data
+ x
+ y
* width
);
487 PreallocatedImage
* s
= new PreallocatedImage (width
, height
, 0, hasAlpha
);
488 s
->allocatedData
.malloc (sizeof (jint
) * width
* height
);
489 s
->data
= s
->allocatedData
;
490 memcpy (s
->data
, data
, sizeof (jint
) * width
* height
);
494 //==============================================================================
497 HeapBlock
<jint
> allocatedData
;
500 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PreallocatedImage
);
503 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer
);
506 ModifierKeys
AndroidComponentPeer::currentModifiers
= 0;
507 Point
<int> AndroidComponentPeer::lastMousePos
;
509 //==============================================================================
510 #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \
511 JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \
513 AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \
515 peer->juceMethodInvocation; \
518 JUCE_VIEW_CALLBACK (void, handlePaint
, (JNIEnv
* env
, jobject view
, jobject canvas
),
519 handlePaintCallback (env
, canvas
))
521 JUCE_VIEW_CALLBACK (void, handleMouseDown
, (JNIEnv
*, jobject view
, jfloat x
, jfloat y
, jlong time
),
522 handleMouseDownCallback ((float) x
, (float) y
, (int64
) time
))
523 JUCE_VIEW_CALLBACK (void, handleMouseDrag
, (JNIEnv
*, jobject view
, jfloat x
, jfloat y
, jlong time
),
524 handleMouseDragCallback ((float) x
, (float) y
, (int64
) time
))
525 JUCE_VIEW_CALLBACK (void, handleMouseUp
, (JNIEnv
*, jobject view
, jfloat x
, jfloat y
, jlong time
),
526 handleMouseUpCallback ((float) x
, (float) y
, (int64
) time
))
528 JUCE_VIEW_CALLBACK (void, viewSizeChanged
, (JNIEnv
*, jobject view
),
529 handleMovedOrResized())
531 JUCE_VIEW_CALLBACK (void, focusChanged
, (JNIEnv
*, jobject view
, jboolean hasFocus
),
532 handleFocusChangeCallback (hasFocus
))
534 //==============================================================================
535 ComponentPeer
* Component::createNewPeer (int styleFlags
, void*)
537 return new AndroidComponentPeer (this, styleFlags
);
541 //==============================================================================
542 bool Desktop::canUseSemiTransparentWindows() noexcept
547 Desktop::DisplayOrientation
Desktop::getCurrentOrientation() const
553 void Desktop::createMouseInputSources()
555 // This creates a mouse input source for each possible finger
557 for (int i
= 0; i
< 10; ++i
)
558 mouseSources
.add (new MouseInputSource (i
, false));
561 const Point
<int> MouseInputSource::getCurrentMousePosition()
563 return AndroidComponentPeer::lastMousePos
;
566 void Desktop::setMousePosition (const Point
<int>& newPosition
)
571 //==============================================================================
572 bool KeyPress::isKeyCurrentlyDown (const int keyCode
)
578 void ModifierKeys::updateCurrentModifiers() noexcept
580 currentModifiers
= AndroidComponentPeer::currentModifiers
;
583 const ModifierKeys
ModifierKeys::getCurrentModifiersRealtime() noexcept
585 return AndroidComponentPeer::currentModifiers
;
588 //==============================================================================
589 bool Process::isForegroundProcess()
594 //==============================================================================
595 void JUCE_CALLTYPE
NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType
,
596 const String
& title
, const String
& message
,
597 Component
* associatedComponent
)
599 android
.activity
.callVoidMethod (android
.showMessageBox
, javaString (title
).get(), javaString (message
).get(), (jlong
) 0);
602 bool JUCE_CALLTYPE
NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType
,
603 const String
& title
, const String
& message
,
604 Component
* associatedComponent
,
605 ModalComponentManager::Callback
* callback
)
607 jassert (callback
!= 0); // on android, all alerts must be non-modal!!
609 android
.activity
.callVoidMethod (android
.showOkCancelBox
, javaString (title
).get(), javaString (message
).get(),
610 (jlong
) (pointer_sized_int
) callback
);
614 int JUCE_CALLTYPE
NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconType iconType
,
615 const String
& title
, const String
& message
,
616 Component
* associatedComponent
,
617 ModalComponentManager::Callback
* callback
)
619 jassert (callback
!= 0); // on android, all alerts must be non-modal!!
621 android
.activity
.callVoidMethod (android
.showYesNoCancelBox
, javaString (title
).get(), javaString (message
).get(),
622 (jlong
) (pointer_sized_int
) callback
);
626 JUCE_JNI_CALLBACK (JuceAppActivity
, alertDismissed
, void, (JNIEnv
* env
, jobject activity
,
627 jlong callbackAsLong
, jint result
))
629 ModalComponentManager::Callback
* callback
= (ModalComponentManager::Callback
*) callbackAsLong
;
632 callback
->modalStateFinished (result
);
635 //==============================================================================
636 void Desktop::setScreenSaverEnabled (const bool isEnabled
)
641 bool Desktop::isScreenSaverEnabled()
646 //==============================================================================
647 void Desktop::setKioskComponent (Component
* kioskModeComponent
, bool enableOrDisable
, bool allowMenusAndBars
)
652 //==============================================================================
653 void Desktop::getCurrentMonitorPositions (Array
<Rectangle
<int> >& monitorCoords
, const bool clipToWorkArea
)
655 monitorCoords
.add (Rectangle
<int> (0, 0, android
.screenWidth
, android
.screenHeight
));
658 JUCE_JNI_CALLBACK (JuceAppActivity
, setScreenSize
, void, (JNIEnv
* env
, jobject activity
,
659 jint screenWidth
, jint screenHeight
))
661 const bool isSystemInitialised
= android
.screenWidth
!= 0;
662 android
.screenWidth
= screenWidth
;
663 android
.screenHeight
= screenHeight
;
665 if (isSystemInitialised
)
666 Desktop::getInstance().refreshMonitorSizes();
669 //==============================================================================
670 Image
juce_createIconForFile (const File
& file
)
675 //==============================================================================
676 void* MouseCursor::createMouseCursorFromImage (const Image
&, int, int) { return nullptr; }
677 void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorType
) { return nullptr; }
678 void MouseCursor::deleteMouseCursor (void* const /*cursorHandle*/, const bool /*isStandard*/) {}
680 //==============================================================================
681 void MouseCursor::showInWindow (ComponentPeer
*) const {}
682 void MouseCursor::showInAllWindows() const {}
684 //==============================================================================
685 bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray
& files
, const bool canMove
)
690 bool DragAndDropContainer::performExternalDragDropOfText (const String
& text
)
695 //==============================================================================
696 const int extendedKeyModifier
= 0x10000;
698 const int KeyPress::spaceKey
= ' ';
699 const int KeyPress::returnKey
= 0x0d;
700 const int KeyPress::escapeKey
= 0x1b;
701 const int KeyPress::backspaceKey
= 0x7f;
702 const int KeyPress::leftKey
= extendedKeyModifier
+ 1;
703 const int KeyPress::rightKey
= extendedKeyModifier
+ 2;
704 const int KeyPress::upKey
= extendedKeyModifier
+ 3;
705 const int KeyPress::downKey
= extendedKeyModifier
+ 4;
706 const int KeyPress::pageUpKey
= extendedKeyModifier
+ 5;
707 const int KeyPress::pageDownKey
= extendedKeyModifier
+ 6;
708 const int KeyPress::endKey
= extendedKeyModifier
+ 7;
709 const int KeyPress::homeKey
= extendedKeyModifier
+ 8;
710 const int KeyPress::deleteKey
= extendedKeyModifier
+ 9;
711 const int KeyPress::insertKey
= -1;
712 const int KeyPress::tabKey
= 9;
713 const int KeyPress::F1Key
= extendedKeyModifier
+ 10;
714 const int KeyPress::F2Key
= extendedKeyModifier
+ 11;
715 const int KeyPress::F3Key
= extendedKeyModifier
+ 12;
716 const int KeyPress::F4Key
= extendedKeyModifier
+ 13;
717 const int KeyPress::F5Key
= extendedKeyModifier
+ 14;
718 const int KeyPress::F6Key
= extendedKeyModifier
+ 16;
719 const int KeyPress::F7Key
= extendedKeyModifier
+ 17;
720 const int KeyPress::F8Key
= extendedKeyModifier
+ 18;
721 const int KeyPress::F9Key
= extendedKeyModifier
+ 19;
722 const int KeyPress::F10Key
= extendedKeyModifier
+ 20;
723 const int KeyPress::F11Key
= extendedKeyModifier
+ 21;
724 const int KeyPress::F12Key
= extendedKeyModifier
+ 22;
725 const int KeyPress::F13Key
= extendedKeyModifier
+ 23;
726 const int KeyPress::F14Key
= extendedKeyModifier
+ 24;
727 const int KeyPress::F15Key
= extendedKeyModifier
+ 25;
728 const int KeyPress::F16Key
= extendedKeyModifier
+ 26;
729 const int KeyPress::numberPad0
= extendedKeyModifier
+ 27;
730 const int KeyPress::numberPad1
= extendedKeyModifier
+ 28;
731 const int KeyPress::numberPad2
= extendedKeyModifier
+ 29;
732 const int KeyPress::numberPad3
= extendedKeyModifier
+ 30;
733 const int KeyPress::numberPad4
= extendedKeyModifier
+ 31;
734 const int KeyPress::numberPad5
= extendedKeyModifier
+ 32;
735 const int KeyPress::numberPad6
= extendedKeyModifier
+ 33;
736 const int KeyPress::numberPad7
= extendedKeyModifier
+ 34;
737 const int KeyPress::numberPad8
= extendedKeyModifier
+ 35;
738 const int KeyPress::numberPad9
= extendedKeyModifier
+ 36;
739 const int KeyPress::numberPadAdd
= extendedKeyModifier
+ 37;
740 const int KeyPress::numberPadSubtract
= extendedKeyModifier
+ 38;
741 const int KeyPress::numberPadMultiply
= extendedKeyModifier
+ 39;
742 const int KeyPress::numberPadDivide
= extendedKeyModifier
+ 40;
743 const int KeyPress::numberPadSeparator
= extendedKeyModifier
+ 41;
744 const int KeyPress::numberPadDecimalPoint
= extendedKeyModifier
+ 42;
745 const int KeyPress::numberPadEquals
= extendedKeyModifier
+ 43;
746 const int KeyPress::numberPadDelete
= extendedKeyModifier
+ 44;
747 const int KeyPress::playKey
= extendedKeyModifier
+ 45;
748 const int KeyPress::stopKey
= extendedKeyModifier
+ 46;
749 const int KeyPress::fastForwardKey
= extendedKeyModifier
+ 47;
750 const int KeyPress::rewindKey
= extendedKeyModifier
+ 48;