Add remaining files
[juce-lv2.git] / juce / source / src / native / android / juce_android_Windowing.cpp
blobae7dfae94a3fca788ee7ab5c9b9631c371fba4d7
1 /*
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
34 public:
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),
40 fullScreen (false),
41 sizeAllocated (0)
43 if (isFocused())
44 handleFocusGain();
47 ~AndroidComponentPeer()
49 if (MessageManager::getInstance()->isThisTheMessageThread())
51 android.activity.callVoidMethod (android.deleteView, view.get());
53 else
55 class ViewDeleter : public CallbackMessage
57 public:
58 ViewDeleter (const GlobalRef& view_)
59 : view (view_)
61 post();
64 void messageCallback()
66 android.activity.callVoidMethod (android.deleteView, view.get());
69 private:
70 GlobalRef view;
73 new ViewDeleter (view);
76 view.clear();
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);
90 else
92 class VisibilityChanger : public CallbackMessage
94 public:
95 VisibilityChanger (const GlobalRef& view_, bool shouldBeVisible_)
96 : view (view_), shouldBeVisible (shouldBeVisible_)
98 post();
101 void messageCallback()
103 view.callVoidMethod (android.setVisible, shouldBeVisible);
106 private:
107 GlobalRef view;
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;
137 w = jmax (0, w);
138 h = jmax (0, h);
140 view.callVoidMethod (android.layout, x, y, x + w, y + h);
142 else
144 class ViewMover : public CallbackMessage
146 public:
147 ViewMover (const GlobalRef& view_, int x_, int y_, int w_, int h_)
148 : view (view_), x (x_), y (y_), w (w_), h (h_)
150 post();
153 void messageCallback()
155 view.callVoidMethod (android.layout, x, y, x + w, y + h);
158 private:
159 GlobalRef view;
160 int x, y, w, 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)
193 // n/a
196 bool isMinimised() const
198 return false;
201 void setFullScreen (bool shouldBeFullScreen)
203 Rectangle<int> r (shouldBeFullScreen ? Desktop::getInstance().getMainMonitorArea()
204 : lastNonFullscreenBounds);
206 if ((! shouldBeFullScreen) && r.isEmpty())
207 r = getBounds();
209 // (can't call the component's setBounds method because that'll reset our fullscreen flag)
210 if (! r.isEmpty())
211 setBounds (r.getX(), r.getY(), r.getWidth(), r.getHeight(), shouldBeFullScreen);
213 component->repaint();
216 bool isFullScreen() const
218 return fullScreen;
221 void setIcon (const Image& newIcon)
223 // n/a
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
235 // TODO
236 return BorderSize<int>();
239 bool setAlwaysOnTop (bool alwaysOnTop)
241 // TODO
242 return false;
245 void toFront (bool makeActive)
247 view.callVoidMethod (android.bringToFront);
249 if (makeActive)
250 grabFocus();
252 handleBroughtToFront();
255 void toBehind (ComponentPeer* other)
257 // TODO
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);
289 void grabFocus()
291 view.callBooleanMethod (android.requestFocus);
294 void handleFocusChangeCallback (bool hasFocus)
296 if (hasFocus)
297 handleFocusGain();
298 else
299 handleFocusLoss();
302 void textInputRequired (const Point<int>& position)
304 // TODO
307 //==============================================================================
308 void handlePaintCallback (JNIEnv* env, jobject canvas)
310 #if USE_ANDROID_CANVAS
311 if (usingAndroidGraphics)
313 AndroidLowLevelGraphicsContext g (canvas);
314 handlePaint (g);
316 else
317 #endif
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)
331 buffer.clear();
332 sizeAllocated = sizeNeeded;
333 buffer = GlobalRef (env->NewIntArray (sizeNeeded));
336 jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), 0);
338 if (dest != 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());
347 handlePaint (g);
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());
366 else
368 class ViewRepainter : public CallbackMessage
370 public:
371 ViewRepainter (const GlobalRef& view_, const Rectangle<int>& area_)
372 : view (view_), area (area_)
374 post();
377 void messageCallback()
379 view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom());
382 private:
383 GlobalRef view;
384 const Rectangle<int>& area;
387 new ViewRepainter (view, area);
391 void performAnyPendingRepaintsNow()
393 // TODO
396 void setAlpha (float newAlpha)
398 // TODO
401 StringArray getAvailableRenderingEngines()
403 StringArray s (ComponentPeer::getAvailableRenderingEngines());
404 s.add ("Android Canvas Renderer");
405 return s;
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();
422 #endif
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)
433 return ap;
436 return nullptr;
439 static ModifierKeys currentModifiers;
440 static Point<int> lastMousePos;
442 private:
443 //==============================================================================
444 GlobalRef view;
445 GlobalRef buffer;
446 bool usingAndroidGraphics, fullScreen;
447 int sizeAllocated;
449 class PreallocatedImage : public Image::SharedImage
451 public:
452 //==============================================================================
453 PreallocatedImage (const int width_, const int height_, jint* data_, bool hasAlpha_)
454 : Image::SharedImage (Image::ARGB, width_, height_), data (data_), hasAlpha (hasAlpha_)
456 if (hasAlpha_)
457 zeromem (data_, width * height * sizeof (jint));
460 ~PreallocatedImage()
462 if (hasAlpha)
464 PixelARGB* pix = (PixelARGB*) data;
466 for (int i = width * height; --i >= 0;)
468 pix->unpremultiply();
469 ++pix;
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);
485 SharedImage* clone()
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);
491 return s;
494 //==============================================================================
495 private:
496 jint* data;
497 HeapBlock<jint> allocatedData;
498 bool hasAlpha;
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); \
514 if (peer != 0) \
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
544 return true;
547 Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
549 // TODO
550 return upright;
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)
568 // not needed
571 //==============================================================================
572 bool KeyPress::isKeyCurrentlyDown (const int keyCode)
574 // TODO
575 return false;
578 void ModifierKeys::updateCurrentModifiers() noexcept
580 currentModifiers = AndroidComponentPeer::currentModifiers;
583 const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() noexcept
585 return AndroidComponentPeer::currentModifiers;
588 //==============================================================================
589 bool Process::isForegroundProcess()
591 return true; // TODO
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);
611 return false;
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);
623 return 0;
626 JUCE_JNI_CALLBACK (JuceAppActivity, alertDismissed, void, (JNIEnv* env, jobject activity,
627 jlong callbackAsLong, jint result))
629 ModalComponentManager::Callback* callback = (ModalComponentManager::Callback*) callbackAsLong;
631 if (callback != 0)
632 callback->modalStateFinished (result);
635 //==============================================================================
636 void Desktop::setScreenSaverEnabled (const bool isEnabled)
638 // TODO
641 bool Desktop::isScreenSaverEnabled()
643 return true;
646 //==============================================================================
647 void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool allowMenusAndBars)
649 // TODO
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)
672 return Image::null;
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)
687 return false;
690 bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
692 return false;
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;
752 #endif