mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
In CoreGraphicsPixelData::createImage, image data was copied from a BitmapData created from the Image passed into the function. The BitmapData instance didn't keep track of the size of the buffer it pointed to, so the buffer size was computed by multiplying the BitmapData height by its line stride. However, if the BitmapData pointed to a subsection of an image, the `data` pointer might be offset from the allocated region, and `data + lineStride * height` would point past the end of the allocated region. Trying to read/copy this range would cause a heap buffer overflow at the end of the range. This change adjusts BitmapData so that it keeps track of the size of the allocated region. Taking a subsection of an image should subtract the data pointer offset from the size of the allocated region.
2108 lines
110 KiB
C++
2108 lines
110 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE library.
|
|
Copyright (c) 2020 - Raw Material Software Limited
|
|
|
|
JUCE is an open source library subject to commercial or open-source
|
|
licensing.
|
|
|
|
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
|
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
|
|
|
End User License Agreement: www.juce.com/juce-6-licence
|
|
Privacy Policy: www.juce.com/juce-privacy-policy
|
|
|
|
Or: You may also use this code under the terms of the GPL v3 (see
|
|
www.gnu.org/licenses).
|
|
|
|
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
|
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
|
DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
namespace juce
|
|
{
|
|
// This byte-code is generated from native/java/com/rmsl/juce/ComponentPeerView.java with min sdk version 16
|
|
// See juce_core/native/java/README.txt on how to generate this byte-code.
|
|
static const uint8 javaComponentPeerView[] =
|
|
{ 31,139,8,8,217,126,216,97,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,165,155,11,124,212,213,149,199,207,189,255,255,204,36,147,215,100,18,146,64,18,50,9,175,16,72,102,8,111,19,148,183,6,18,64,18,16,18,171,76,146,127,146,
|
|
129,201,127,134,153,73,72,124,21,149,143,96,173,21,45,82,21,109,177,165,182,110,109,215,90,219,181,22,181,93,93,215,173,186,85,107,87,180,90,31,69,197,150,90,180,86,105,117,117,127,247,49,147,9,143,210,118,195,231,59,231,252,207,125,223,123,238,185,247,
|
|
63,33,221,214,144,59,48,115,54,125,253,172,186,247,86,249,42,166,141,253,112,218,236,231,195,83,47,91,120,183,99,205,99,123,255,208,184,125,22,81,148,136,134,214,207,242,146,254,57,56,147,168,146,41,251,60,240,129,73,180,4,242,121,7,81,9,228,241,12,162,
|
|
203,33,31,200,36,66,18,237,207,33,218,52,153,200,151,75,212,94,78,116,33,184,24,116,130,205,192,6,215,128,107,193,245,96,55,216,3,110,1,251,192,215,192,195,224,5,240,18,248,13,120,3,188,5,126,15,142,129,63,131,156,241,232,7,184,8,12,131,61,224,126,240,
|
|
60,248,12,140,173,32,170,7,231,130,207,129,65,112,19,120,8,60,7,142,130,137,62,162,101,96,8,220,3,14,131,194,74,162,6,208,11,246,130,23,64,69,21,198,2,46,7,119,130,159,129,195,192,152,64,84,14,2,160,13,92,2,110,0,247,129,199,193,155,224,47,160,122,34,
|
|
209,82,208,1,194,224,10,176,3,220,4,110,6,183,130,253,224,0,184,7,220,7,126,12,30,1,143,129,39,192,211,224,57,240,2,120,5,188,14,222,1,71,193,123,224,35,240,9,48,38,17,101,130,28,224,5,227,64,37,152,4,166,130,5,96,45,184,8,108,6,131,224,42,240,37,112,
|
|
27,184,11,220,7,30,6,79,130,151,192,49,112,28,56,176,174,121,160,6,204,6,243,192,74,208,10,58,64,23,8,131,56,216,14,174,7,119,128,123,192,15,193,65,240,34,120,21,188,1,222,1,89,83,136,138,64,57,152,6,230,129,117,32,14,174,0,55,128,187,192,15,193,35,224,
|
|
73,240,34,56,12,254,2,114,171,137,202,192,20,48,15,44,7,171,193,6,96,129,109,96,39,184,29,124,7,252,4,188,8,94,5,111,130,35,128,79,37,42,0,147,192,92,176,28,180,130,16,184,4,92,7,110,3,223,2,7,193,227,224,85,240,14,248,35,120,31,124,10,140,26,248,15,
|
|
152,0,102,129,115,64,11,184,0,92,12,182,128,1,176,27,236,3,7,192,67,224,41,240,75,240,6,56,2,142,129,227,224,99,192,166,17,185,65,33,168,2,53,32,0,230,128,38,112,17,136,130,171,193,126,240,3,240,56,120,21,188,13,62,4,206,233,40,15,42,64,29,152,11,22,
|
|
129,53,224,34,208,3,34,96,24,108,7,95,4,251,192,215,193,207,192,99,224,105,240,30,200,171,197,122,129,82,48,13,204,7,107,65,39,136,130,47,128,59,193,195,224,73,240,18,120,11,124,8,204,58,204,51,152,0,234,65,51,88,11,54,128,77,160,15,216,32,14,134,193,
|
|
213,224,26,112,61,216,11,110,7,223,5,15,128,159,131,23,193,155,224,8,248,61,248,35,248,19,248,8,124,12,62,3,78,196,36,132,40,202,2,69,160,152,84,220,26,11,198,129,82,80,6,16,82,8,97,131,16,22,8,97,128,176,237,9,91,156,176,125,9,219,138,224,254,4,119,
|
|
37,184,28,193,101,8,203,77,88,30,194,244,18,166,133,48,60,66,115,228,7,1,48,3,212,3,132,79,66,88,165,217,96,14,152,171,227,232,124,112,22,104,0,141,96,1,56,27,156,3,22,130,69,96,49,169,88,187,12,156,7,54,128,78,208,5,186,129,69,106,124,201,31,151,150,
|
|
247,151,170,49,51,253,236,214,186,176,139,121,224,218,158,173,245,131,176,231,165,213,229,213,115,246,152,182,231,106,123,158,78,75,234,99,180,238,209,243,42,234,47,208,250,83,186,108,73,90,157,98,174,159,47,85,186,152,227,151,117,158,201,105,245,76,
|
|
213,245,228,107,253,48,244,66,173,31,45,85,109,138,57,255,64,215,35,244,79,116,61,181,186,158,49,122,29,204,50,213,31,177,22,217,101,106,14,235,117,158,38,173,139,182,86,104,189,16,121,86,106,93,180,219,172,117,31,236,45,90,15,64,95,165,245,70,232,171,
|
|
181,126,30,244,53,90,111,131,126,190,214,47,132,222,170,245,238,52,123,56,77,79,64,95,167,245,203,210,236,187,210,244,221,105,250,45,105,117,238,79,179,127,27,122,155,214,239,77,179,31,40,29,209,197,156,175,213,186,152,207,100,61,15,164,229,23,243,185,
|
|
94,235,63,133,253,2,173,63,145,150,231,80,154,254,90,153,242,205,153,122,110,55,106,253,8,236,237,90,63,150,166,127,2,189,67,235,25,226,142,160,117,15,244,207,105,189,76,220,27,180,94,13,253,34,173,7,210,236,194,199,54,105,125,30,236,65,173,159,151,150,
|
|
191,173,92,248,57,163,97,82,50,135,137,125,63,137,226,164,228,191,73,201,232,65,45,15,106,249,144,150,15,107,249,136,206,255,115,18,177,194,71,110,166,100,1,19,113,99,38,253,23,9,89,65,89,76,196,16,149,94,161,211,43,144,82,196,132,207,23,209,86,225,79,
|
|
216,117,15,72,89,65,79,72,89,78,191,148,114,38,189,35,101,22,29,149,62,63,153,150,67,58,16,129,254,68,98,127,58,233,70,41,199,208,126,200,76,68,49,67,202,89,244,33,137,125,94,45,159,179,180,61,11,17,225,35,57,110,245,156,135,118,111,144,178,136,110,210,
|
|
207,183,106,121,167,152,127,157,46,228,110,41,77,186,89,63,239,147,210,160,219,73,237,211,59,180,252,170,148,140,238,210,242,91,36,246,37,167,189,82,78,165,111,146,216,131,147,100,251,5,136,120,191,149,114,62,29,150,178,148,222,38,177,95,107,105,64,203,
|
|
15,72,196,233,57,244,31,36,226,72,54,61,47,229,88,122,159,68,44,81,227,24,139,136,43,100,25,162,230,143,164,172,161,191,74,121,14,153,114,93,2,50,189,28,51,176,67,202,18,218,165,159,175,149,114,30,189,43,215,171,78,230,27,143,26,95,39,177,78,170,92,5,
|
|
236,61,90,246,74,153,71,125,82,142,37,7,83,210,41,215,115,178,204,239,195,10,133,164,244,211,102,41,23,209,22,41,11,40,172,101,191,148,11,201,150,114,44,13,105,121,185,148,115,233,74,41,43,233,58,41,189,116,189,148,57,244,37,41,157,180,71,251,205,94,
|
|
157,254,21,41,103,211,45,82,102,210,215,164,116,211,215,117,190,111,72,153,65,7,164,84,235,32,252,236,110,41,203,232,95,180,252,142,150,247,104,127,252,174,148,227,233,123,218,254,175,186,220,189,90,126,95,203,251,164,244,209,15,164,108,160,251,165,156,
|
|
67,143,105,249,184,148,19,232,5,41,171,232,144,150,47,106,249,146,78,255,181,126,126,89,203,87,164,204,165,223,72,57,133,94,149,114,58,189,38,229,217,244,134,148,202,143,124,218,143,196,243,155,122,255,188,37,165,242,43,145,255,136,148,141,116,76,202,
|
|
122,58,174,229,95,164,156,70,159,72,57,142,62,149,114,6,125,166,159,137,169,124,76,75,206,84,186,193,212,188,20,50,113,110,21,211,109,36,228,98,122,84,238,87,78,63,147,50,159,188,76,156,77,202,95,167,97,103,124,153,196,249,100,208,21,82,114,122,154,196,
|
|
25,85,72,255,78,226,190,48,86,251,171,218,83,201,51,19,175,88,116,33,98,220,21,250,208,26,175,237,226,204,19,49,93,164,39,32,239,208,233,21,186,252,180,180,242,59,144,126,175,78,247,145,58,87,197,153,120,143,46,191,7,242,144,78,23,119,129,169,208,3,245,
|
|
234,190,112,86,189,178,173,134,92,15,12,157,190,9,108,214,121,226,210,110,72,157,251,213,189,161,131,185,41,234,17,55,168,14,158,133,181,204,64,45,162,173,28,191,186,59,121,89,91,167,155,182,122,102,193,158,197,139,240,218,56,131,115,115,62,55,201,229,
|
|
201,167,182,206,44,218,234,171,160,24,118,191,200,215,214,165,242,26,148,101,110,93,51,135,22,15,184,249,124,254,135,207,108,143,24,143,203,83,253,182,169,219,159,224,87,119,152,42,204,104,212,115,153,28,173,104,91,244,187,214,175,238,96,167,107,219,
|
|
160,124,230,245,206,156,50,246,228,54,3,115,105,177,35,27,49,227,24,218,20,113,202,205,108,223,20,68,169,108,86,253,214,201,185,231,201,220,213,239,136,248,107,202,254,44,241,171,181,107,139,170,124,34,165,136,203,123,9,159,143,60,94,196,151,182,173,
|
|
238,244,116,206,118,176,155,93,119,109,115,206,199,200,16,215,143,25,232,175,24,227,106,191,136,247,152,89,111,14,198,184,13,54,47,93,232,201,150,119,180,12,60,137,177,110,240,171,179,182,192,89,72,85,60,27,249,196,44,180,197,115,168,109,102,46,217,158,
|
|
165,200,149,205,230,179,198,17,155,239,60,236,197,145,28,139,144,195,109,172,157,40,222,21,25,125,191,237,70,50,204,217,155,198,209,186,56,230,193,40,34,175,113,33,180,100,254,182,68,14,250,29,192,72,178,77,209,127,83,206,195,108,90,226,16,249,231,27,
|
|
46,154,187,201,65,222,2,81,70,180,85,140,56,103,123,138,196,200,78,104,163,250,191,197,90,10,159,187,218,175,238,116,29,222,92,61,206,42,204,97,212,39,246,82,135,7,20,228,201,49,51,249,143,232,203,126,245,253,67,212,35,110,123,185,41,251,190,148,189,
|
|
94,218,185,190,21,127,195,175,252,185,205,147,39,247,132,240,32,209,238,119,252,234,94,220,230,203,67,31,197,205,27,227,172,244,160,215,101,104,57,55,149,239,190,211,230,43,151,249,114,225,241,98,36,63,70,190,167,132,223,185,188,69,81,95,9,226,111,149,
|
|
153,133,222,56,209,171,142,61,69,120,170,160,104,160,150,246,100,118,236,41,192,83,57,158,38,203,167,66,212,187,16,107,157,109,142,115,68,81,47,86,16,122,133,89,132,114,249,84,102,58,96,75,32,190,187,205,121,230,231,168,194,45,158,241,158,74,237,183,
|
|
123,161,69,113,227,185,112,223,24,104,33,156,77,182,111,179,252,220,130,243,190,10,117,70,61,242,60,54,11,105,194,162,89,52,153,137,27,161,237,51,209,243,54,209,39,7,246,175,207,65,162,70,23,90,245,26,182,103,72,247,228,99,242,78,158,208,51,7,227,233,
|
|
204,40,166,150,12,167,203,91,92,150,145,37,53,59,16,167,54,103,182,49,207,40,36,47,247,78,156,176,116,46,121,29,91,61,131,152,135,108,103,139,211,116,120,199,120,165,180,3,151,210,151,77,225,105,194,187,197,168,84,239,247,80,245,157,57,102,245,7,224,
|
|
125,112,12,188,4,196,225,97,152,242,61,96,228,103,251,57,244,15,61,159,248,163,210,197,93,178,8,251,241,18,82,247,23,110,84,223,202,166,124,133,213,221,204,248,244,59,88,205,62,70,58,186,224,221,47,160,124,166,213,231,149,113,214,148,145,15,239,125,1,
|
|
237,99,129,213,84,105,228,98,207,59,100,188,155,27,80,49,54,186,174,143,42,151,184,165,63,39,203,44,77,166,5,22,163,76,182,244,193,100,90,75,42,237,236,84,154,75,222,254,16,135,117,218,160,179,77,70,6,81,167,67,239,123,43,160,246,76,235,66,111,90,124,
|
|
49,224,139,194,18,13,52,227,118,84,253,215,145,241,244,235,186,196,123,113,59,198,148,171,251,32,126,226,1,21,251,189,158,188,212,158,185,60,144,220,51,133,178,79,73,251,213,218,190,206,51,70,182,207,245,222,187,54,160,222,61,109,207,114,217,87,25,235,
|
|
80,159,151,170,63,53,116,59,55,4,212,57,146,43,203,169,55,211,175,164,217,156,58,126,127,245,12,99,91,161,199,150,204,255,173,51,228,95,153,154,11,213,143,123,79,209,143,7,78,97,123,36,205,102,234,182,30,15,168,239,11,188,76,124,163,208,17,224,164,164,
|
|
65,27,103,32,238,29,219,24,112,209,198,128,83,91,51,225,199,88,73,207,198,128,137,244,12,236,199,177,232,79,21,249,88,190,30,175,88,147,95,5,212,89,125,234,254,183,45,46,162,232,218,86,50,207,175,62,46,124,195,144,254,247,202,105,203,204,92,246,217,103,
|
|
114,220,11,23,144,25,20,101,220,104,71,156,213,191,11,168,239,57,218,182,231,99,157,196,41,229,198,73,55,142,90,175,68,20,241,228,98,215,187,177,251,189,66,154,182,167,64,72,135,141,53,204,164,44,167,107,251,96,70,147,246,17,177,166,110,180,37,124,244,
|
|
163,128,250,174,195,235,105,141,161,39,226,140,101,56,99,153,58,233,166,139,87,62,18,41,54,206,45,85,95,150,144,78,215,86,182,99,208,217,130,249,173,254,67,36,48,150,118,102,226,228,59,98,123,206,194,8,171,197,69,143,171,113,38,191,191,17,178,64,147,
|
|
173,207,218,49,51,212,123,159,151,90,175,66,219,78,217,182,115,62,51,208,242,252,204,76,180,137,158,227,4,247,86,213,87,186,40,178,112,28,221,242,32,90,121,223,246,184,97,207,102,243,152,184,89,40,221,246,13,11,191,117,136,154,68,31,179,68,31,175,100,
|
|
123,84,31,189,158,234,23,212,220,139,245,154,57,67,125,239,48,122,238,213,136,133,77,140,213,73,110,30,93,187,10,171,134,178,127,38,189,163,137,22,205,24,241,169,76,29,59,86,207,80,107,25,217,80,74,109,131,233,181,206,67,155,202,135,99,240,97,81,38,79,
|
|
175,229,38,36,151,161,162,214,103,145,219,16,35,103,134,156,117,150,199,108,79,14,234,119,103,138,181,203,165,44,215,175,110,252,140,166,177,15,165,215,86,191,215,250,156,23,210,246,229,227,140,21,235,44,98,129,88,151,2,33,157,174,103,7,51,214,136,17,
|
|
231,87,191,124,230,156,107,85,206,255,60,115,206,243,145,211,246,136,211,210,157,229,205,159,91,90,67,222,202,9,101,179,113,18,44,193,253,216,59,110,246,131,149,36,106,17,117,124,79,212,225,43,20,146,121,29,75,29,217,142,171,214,61,62,198,246,141,81,
|
|
150,162,165,206,108,231,85,61,143,23,37,235,61,228,118,179,234,215,208,143,171,113,83,199,165,254,135,55,190,238,102,25,243,221,37,244,247,142,96,42,245,124,150,222,159,127,166,39,162,166,234,95,255,227,61,88,163,123,48,233,255,221,131,53,178,7,88,102,
|
|
166,190,29,20,190,37,226,144,95,75,17,191,196,187,91,92,250,30,151,119,150,23,102,168,239,50,209,71,156,251,46,202,230,227,140,255,37,111,225,132,165,56,247,29,157,78,156,251,242,12,143,83,189,41,238,145,46,244,59,7,251,31,124,226,245,78,168,194,169,
|
|
111,136,83,63,3,39,123,139,201,13,113,218,111,229,213,239,230,240,234,163,224,119,224,136,240,247,124,244,173,84,238,93,68,61,62,189,168,166,196,168,174,158,50,189,174,38,45,222,26,245,35,123,195,208,214,172,122,117,7,158,199,93,36,102,196,70,142,92,
|
|
242,46,172,254,88,140,79,197,228,194,122,21,7,196,29,74,220,118,199,241,159,202,59,84,37,90,171,192,251,219,60,68,15,219,115,9,118,168,155,45,96,5,152,109,59,48,137,2,24,241,185,50,191,29,152,72,30,179,109,70,1,110,182,117,178,254,100,138,151,219,129,
|
|
9,228,225,42,205,47,230,247,125,146,191,239,18,63,201,239,92,197,123,206,116,216,102,37,191,60,213,63,11,79,120,94,115,194,179,40,95,72,234,236,205,71,239,152,182,9,124,90,102,232,116,175,62,103,199,105,123,133,150,92,227,211,243,53,141,230,74,123,173,
|
|
182,215,34,58,43,201,100,60,101,250,159,131,70,206,116,174,125,35,121,150,155,41,157,105,187,43,245,93,50,199,76,179,84,126,33,115,82,101,132,116,234,52,39,242,113,109,115,105,153,169,101,242,187,232,92,217,43,210,247,11,49,198,153,122,44,62,105,159,
|
|
169,125,120,102,170,215,170,252,44,45,103,235,114,201,126,10,153,163,219,23,122,94,42,61,47,109,76,57,169,177,22,167,250,161,234,246,232,246,124,169,156,106,92,62,157,155,145,122,223,102,213,132,247,41,103,99,200,14,37,206,38,126,118,3,21,45,137,244,
|
|
71,35,182,101,39,214,88,86,108,125,200,218,86,183,57,56,24,36,182,156,248,242,38,98,77,196,155,166,2,168,43,136,175,104,166,242,21,3,93,214,162,174,46,43,30,15,117,134,194,161,196,240,170,72,183,181,38,22,25,12,117,91,49,42,94,105,13,119,70,130,177,238,
|
|
165,161,120,127,40,30,111,14,197,19,150,141,4,214,76,188,25,181,53,163,154,230,102,50,154,241,128,143,21,226,163,153,138,154,131,118,119,44,18,234,246,7,163,81,255,162,174,68,104,16,53,55,208,172,209,246,104,52,28,234,10,38,66,17,123,98,50,79,115,168,
|
|
199,234,26,238,10,91,75,130,225,112,103,176,107,75,188,129,198,158,174,84,122,82,87,196,70,207,18,254,37,66,14,37,210,147,122,99,193,104,95,168,43,238,95,18,180,7,131,168,112,252,41,146,34,225,72,108,121,40,156,176,98,167,79,111,9,38,98,161,161,6,154,
|
|
250,55,211,71,85,85,114,114,214,53,193,144,141,254,21,159,156,178,214,234,66,66,65,42,33,18,247,47,30,176,187,195,86,3,21,166,27,155,22,135,236,110,81,251,72,29,131,88,106,63,22,107,217,160,37,42,31,55,58,161,37,34,166,75,167,77,29,157,38,156,100,226,
|
|
106,123,121,164,107,32,190,164,47,104,247,90,201,69,78,239,74,42,107,250,144,82,198,115,99,145,129,104,3,205,57,57,165,45,102,89,171,59,227,86,108,208,138,161,149,115,195,145,206,96,184,57,56,28,25,72,140,52,83,241,183,203,53,208,140,209,25,130,233,254,
|
|
234,31,229,189,45,65,59,216,43,138,212,255,221,69,132,195,55,217,61,145,147,250,127,134,50,201,77,210,64,117,163,203,133,236,232,64,162,223,74,244,69,186,253,139,131,113,84,142,103,248,165,141,229,149,94,59,233,244,249,151,117,135,18,145,152,234,78,205,
|
|
233,179,157,84,101,237,25,242,182,72,61,53,59,231,52,119,69,250,253,177,254,120,216,191,25,1,192,127,82,216,152,248,55,227,66,3,45,63,99,5,167,137,28,19,71,175,236,252,127,182,158,6,170,60,83,209,6,170,106,238,14,134,7,67,91,252,65,219,142,36,100,204,
|
|
240,47,179,187,194,145,120,200,238,93,18,14,198,101,48,56,57,79,19,38,54,166,211,43,79,145,222,98,245,119,234,12,22,178,148,159,34,75,107,168,215,14,38,6,98,150,216,48,34,6,251,195,216,91,126,236,176,88,171,181,117,192,178,187,144,146,159,158,162,154,
|
|
171,74,51,53,133,195,86,111,48,172,150,97,217,80,151,21,85,139,61,241,20,121,98,189,3,253,24,123,90,174,130,244,92,8,138,189,106,210,70,140,171,34,173,3,93,125,202,51,210,202,121,211,178,172,238,220,44,99,82,121,154,173,213,234,26,136,193,33,78,83,164,
|
|
21,49,208,238,21,30,57,98,139,89,61,97,212,131,110,12,70,84,232,110,11,198,122,173,244,222,142,59,69,118,213,181,6,26,163,210,6,18,161,176,127,81,44,22,28,22,78,208,64,121,105,102,97,33,207,9,134,6,50,219,54,174,89,70,217,233,62,71,108,61,241,245,77,
|
|
228,88,223,132,31,168,43,200,185,126,69,211,242,229,120,155,135,20,9,43,68,2,30,196,193,182,126,69,59,242,8,69,28,110,235,165,169,185,29,169,205,237,56,250,214,183,163,112,187,172,136,181,147,209,46,202,225,163,89,168,205,228,104,95,33,116,19,2,199,101,
|
|
187,176,226,152,116,182,55,75,179,67,72,216,59,112,54,119,52,145,183,227,100,103,40,232,56,197,90,184,85,92,154,24,8,4,82,250,140,52,189,62,77,159,153,166,207,74,211,103,167,233,115,210,244,185,105,250,60,232,89,74,95,30,14,246,198,41,103,84,64,164,194,
|
|
224,41,2,47,57,131,50,34,137,146,66,54,7,59,173,48,101,4,245,241,78,99,131,221,221,167,62,6,40,51,168,125,56,78,172,147,242,197,225,191,120,32,145,136,216,107,98,104,198,234,38,103,103,4,143,253,144,242,80,36,103,151,60,207,201,213,37,143,173,110,114,
|
|
224,222,16,140,81,86,151,8,85,17,156,178,139,18,226,33,117,50,83,174,124,104,139,5,237,120,79,36,214,79,57,226,214,128,227,56,46,115,163,34,117,121,64,69,145,1,60,151,118,197,172,96,226,228,48,40,194,51,153,221,161,158,30,98,22,57,44,113,174,146,175,
|
|
7,135,242,41,179,198,23,15,183,137,90,51,69,14,121,206,146,163,71,138,236,158,145,83,183,155,178,228,147,136,92,77,221,84,138,237,49,170,182,229,105,137,101,39,38,142,186,180,101,202,84,185,10,121,41,181,37,24,223,130,54,198,8,195,200,13,74,223,150,40,
|
|
7,102,17,154,176,78,86,44,78,25,226,81,184,32,185,133,166,51,101,139,29,43,198,218,22,234,183,100,43,231,89,161,222,190,4,21,64,149,167,76,122,31,133,177,89,239,246,213,118,43,166,210,178,101,21,216,213,193,86,68,73,85,133,218,227,178,163,114,17,16,86,
|
|
229,220,103,143,24,80,153,11,79,107,131,219,54,36,149,141,148,37,148,72,36,33,90,35,15,30,90,135,225,71,253,173,216,227,161,46,139,114,97,89,103,135,132,39,136,113,201,222,156,120,175,144,163,94,31,74,57,180,40,115,1,150,40,178,173,45,178,5,157,45,75,
|
|
61,203,76,97,11,71,80,52,28,28,94,30,11,98,252,38,82,55,200,207,141,196,250,168,4,139,8,167,28,181,42,231,69,68,43,121,58,37,26,93,19,28,16,126,236,73,25,214,90,113,120,124,202,178,56,229,242,148,163,44,56,252,150,70,182,97,55,165,30,215,69,169,48,245,
|
|
32,15,198,243,66,221,221,232,173,110,166,37,130,54,100,153,81,134,88,176,55,89,167,52,160,26,93,167,188,142,82,129,126,176,98,98,99,104,239,201,232,11,198,149,191,22,247,193,179,90,35,61,122,153,99,145,126,53,49,200,130,210,210,187,205,190,8,66,48,11,
|
|
145,27,222,177,90,70,245,56,25,161,254,126,202,19,239,39,161,96,120,73,48,26,111,193,130,80,142,54,180,90,225,101,118,119,42,29,143,240,139,24,54,138,188,190,180,13,71,45,202,150,234,197,234,42,67,25,104,108,125,48,60,128,189,31,194,81,178,197,66,99,
|
|
241,38,59,158,8,226,56,69,106,124,117,52,136,179,149,198,134,226,109,17,156,109,203,134,162,216,239,210,5,151,217,65,172,96,55,234,142,235,213,36,215,22,107,120,137,232,79,241,150,211,188,229,228,36,19,90,251,196,140,58,194,50,154,229,192,7,172,152,232,
|
|
222,42,220,55,200,12,91,61,9,114,134,45,187,55,209,71,78,221,85,102,147,105,11,63,113,217,214,182,85,66,201,176,147,161,35,219,78,223,174,206,72,167,136,65,100,70,194,221,125,242,115,27,229,71,236,228,27,209,18,25,131,176,159,70,76,75,173,120,34,22,25,
|
|
22,142,51,98,212,206,149,86,50,233,93,165,35,166,214,224,160,149,156,47,181,7,211,242,203,201,31,93,69,107,34,18,141,194,84,140,80,33,251,113,194,197,19,157,183,225,91,219,40,39,146,254,6,65,185,145,81,49,158,178,35,182,220,12,50,124,80,102,196,78,58,
|
|
118,142,84,91,6,194,137,80,84,44,137,124,132,115,102,136,163,67,22,69,142,214,208,37,86,50,72,162,38,181,180,178,38,103,68,45,184,75,201,139,81,110,0,81,63,129,24,230,136,74,199,118,71,131,49,228,148,97,34,39,58,202,189,29,81,25,245,203,163,145,232,64,
|
|
248,180,113,158,197,200,21,83,239,164,84,21,179,122,133,111,196,78,255,186,74,101,49,171,31,67,85,195,95,109,159,112,200,57,98,50,98,26,113,43,65,185,113,17,91,83,47,139,148,141,103,57,137,194,83,169,56,253,169,73,13,90,238,30,81,44,237,78,47,139,53,
|
|
39,61,146,74,240,116,202,183,57,26,19,79,6,201,117,161,180,168,87,122,74,179,184,76,7,113,122,198,85,216,148,14,156,19,31,21,46,221,201,199,176,234,211,5,161,112,120,85,36,33,221,33,59,142,13,147,12,80,40,136,167,84,244,64,102,225,104,170,95,184,42,34,
|
|
25,94,54,242,88,18,87,189,105,26,105,75,143,212,148,199,144,153,232,11,197,201,41,62,39,6,180,156,1,171,56,148,12,212,4,85,76,68,198,64,162,103,158,140,253,108,144,28,131,50,106,184,164,88,221,67,166,120,75,162,60,241,153,238,92,153,194,208,22,89,23,
|
|
183,200,51,120,210,105,49,24,138,37,6,130,97,125,190,185,7,71,166,130,109,35,54,68,124,40,0,102,128,122,48,19,204,34,54,76,223,52,57,237,229,174,220,246,90,186,199,100,183,112,87,57,207,122,150,15,149,111,54,232,151,172,228,141,149,244,144,201,175,229,
|
|
176,231,210,163,38,187,142,185,202,159,228,151,148,191,111,208,245,172,166,246,38,7,209,115,166,113,11,143,111,115,229,62,90,65,191,229,140,80,85,35,253,142,147,107,122,135,193,223,103,57,215,26,236,93,86,80,55,244,145,65,215,48,190,185,145,229,231,135,
|
|
26,121,188,220,65,141,44,203,137,242,92,117,128,207,217,200,87,110,171,165,95,112,118,187,104,237,68,121,8,85,230,222,79,175,40,209,104,92,205,126,207,126,204,92,211,249,179,212,192,63,101,219,248,51,108,219,16,127,227,210,215,118,49,238,112,47,170,109,
|
|
172,107,108,60,187,195,160,237,204,125,153,193,174,100,179,27,239,170,52,140,95,176,0,43,30,19,24,111,240,167,24,103,249,197,14,206,207,71,87,28,204,97,56,221,124,218,1,135,219,73,78,230,228,78,163,166,134,15,78,119,240,26,30,159,78,115,85,23,230,242,
|
|
219,249,29,82,49,133,242,85,254,181,209,214,148,226,72,38,239,23,143,215,137,46,127,161,140,6,33,86,210,97,131,239,227,119,10,251,235,38,12,180,75,76,25,189,100,136,207,47,152,124,224,82,200,29,38,27,128,120,215,16,2,37,111,150,207,215,149,209,167,134,
|
|
202,176,91,101,56,46,51,208,141,6,59,138,133,89,185,178,182,125,101,123,29,125,158,93,38,75,221,107,240,27,249,143,24,10,150,214,210,219,140,237,130,186,139,21,229,249,104,15,231,79,136,199,242,157,124,76,57,239,47,231,121,13,117,43,45,62,176,226,66,
|
|
62,188,130,30,228,198,19,108,135,76,231,249,215,240,88,249,222,142,205,187,12,199,110,206,253,214,57,116,175,46,155,187,211,87,182,151,238,54,28,151,63,205,190,196,63,100,151,160,35,251,13,243,54,126,55,123,129,253,15,210,23,236,108,167,91,84,171,59,
|
|
249,19,84,206,31,252,124,249,74,35,51,206,155,13,215,245,220,224,143,210,70,190,112,58,43,200,11,40,60,205,70,214,51,140,47,104,52,178,143,177,57,11,24,51,220,15,50,94,203,202,114,206,113,184,29,217,51,28,89,155,157,238,58,86,80,196,47,109,104,116,102,
|
|
47,96,229,99,132,125,180,145,47,103,229,185,244,136,193,110,197,12,251,12,182,139,7,152,183,136,103,79,199,40,43,12,218,201,106,199,59,72,42,211,38,56,232,245,64,13,253,196,96,207,161,139,244,170,193,134,92,185,161,50,58,206,216,13,40,252,152,65,7,89,
|
|
121,221,230,149,67,155,198,238,36,94,201,110,228,37,62,94,197,35,166,247,25,86,156,195,39,194,80,230,42,102,197,11,139,51,139,151,22,243,226,154,98,83,229,170,144,185,224,143,197,231,166,242,231,242,9,34,63,43,25,175,20,94,82,94,82,65,156,153,238,221,
|
|
62,230,157,124,229,118,243,80,217,20,118,188,140,177,67,229,140,125,0,142,141,71,50,203,230,108,183,111,218,246,237,230,193,138,233,236,181,10,50,156,148,43,74,48,111,45,202,28,168,100,187,124,207,139,143,163,226,99,71,21,227,183,131,199,170,200,89,82,
|
|
154,239,133,135,123,213,191,153,200,124,180,10,89,30,152,140,143,103,196,199,17,241,177,99,10,62,246,139,143,131,83,204,171,56,49,32,164,75,235,127,47,133,192,13,206,98,135,166,96,201,171,25,59,80,109,176,7,170,139,216,51,208,143,128,47,78,101,108,63,
|
|
184,31,28,6,123,106,24,251,54,56,8,158,1,7,166,97,232,224,139,211,25,123,13,188,92,203,216,243,117,204,220,237,103,230,1,63,210,252,14,182,127,22,99,247,204,230,236,167,224,240,108,79,218,239,7,146,50,249,119,57,226,251,234,228,223,230,136,239,177,147,
|
|
127,159,147,252,93,169,248,27,29,241,29,118,242,239,116,156,52,242,183,58,134,71,127,191,157,139,58,125,234,247,66,27,160,59,125,42,143,248,255,103,204,163,236,226,255,156,113,159,106,87,252,109,143,161,243,139,255,247,101,250,212,239,37,166,214,171,
|
|
95,84,136,178,242,255,173,121,84,95,197,223,17,253,31,67,245,215,66,128,52,0,0,0,0 };
|
|
|
|
//==============================================================================
|
|
#if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra
|
|
extern bool juce_handleNotificationIntent (void*);
|
|
extern void juce_firebaseDeviceNotificationsTokenRefreshed (void*);
|
|
extern void juce_firebaseRemoteNotificationReceived (void*);
|
|
extern void juce_firebaseRemoteMessagesDeleted();
|
|
extern void juce_firebaseRemoteMessageSent(void*);
|
|
extern void juce_firebaseRemoteMessageSendError (void*, void*);
|
|
#endif
|
|
|
|
//==============================================================================
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
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")
|
|
|
|
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") \
|
|
FIELD (windowAnimations, "windowAnimations", "I")
|
|
|
|
DECLARE_JNI_CLASS (AndroidWindowManagerLayoutParams, "android/view/WindowManager$LayoutParams")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (getDisplayCutout, "getDisplayCutout", "()Landroid/view/DisplayCutout;")
|
|
|
|
DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsets, "android/view/WindowInsets", 28)
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (getSafeInsetBottom, "getSafeInsetBottom", "()I") \
|
|
METHOD (getSafeInsetLeft, "getSafeInsetLeft", "()I") \
|
|
METHOD (getSafeInsetRight, "getSafeInsetRight", "()I") \
|
|
METHOD (getSafeInsetTop, "getSafeInsetTop", "()I")
|
|
|
|
DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidDisplayCutout, "android/view/DisplayCutout", 28)
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
//==============================================================================
|
|
namespace
|
|
{
|
|
enum
|
|
{
|
|
SYSTEM_UI_FLAG_VISIBLE = 0,
|
|
SYSTEM_UI_FLAG_LOW_PROFILE = 1,
|
|
SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2,
|
|
SYSTEM_UI_FLAG_FULLSCREEN = 4,
|
|
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512,
|
|
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024,
|
|
SYSTEM_UI_FLAG_IMMERSIVE = 2048,
|
|
SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096
|
|
};
|
|
|
|
constexpr int fullScreenFlags = SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
|
constexpr int FLAG_NOT_FOCUSABLE = 0x8;
|
|
}
|
|
|
|
//==============================================================================
|
|
static bool supportsDisplayCutout()
|
|
{
|
|
return getAndroidSDKVersion() >= 28;
|
|
}
|
|
|
|
static BorderSize<int> androidDisplayCutoutToBorderSize (LocalRef<jobject> displayCutout, double displayScale)
|
|
{
|
|
if (displayCutout.get() == nullptr)
|
|
return {};
|
|
|
|
auto* env = getEnv();
|
|
|
|
auto getInset = [&] (jmethodID methodID)
|
|
{
|
|
return roundToInt (env->CallIntMethod (displayCutout.get(), methodID) / displayScale);
|
|
};
|
|
|
|
return { getInset (AndroidDisplayCutout.getSafeInsetTop),
|
|
getInset (AndroidDisplayCutout.getSafeInsetLeft),
|
|
getInset (AndroidDisplayCutout.getSafeInsetBottom),
|
|
getInset (AndroidDisplayCutout.getSafeInsetRight) };
|
|
}
|
|
|
|
/* The usage of the KeyPress class relies on its keyCode member having the standard ASCII values
|
|
represent ASCII keycodes. However in the native Android keycodes the values for special keys
|
|
e.g. RETURN, F1-F12 overlap with the ASCII range. Hence we need to translate them.
|
|
*/
|
|
static constexpr int translateAndroidKeyCode (int keyCode) noexcept
|
|
{
|
|
switch (keyCode)
|
|
{
|
|
case 7: return '0';
|
|
case 8: return '1';
|
|
case 9: return '2';
|
|
case 10: return '3';
|
|
case 11: return '4';
|
|
case 12: return '5';
|
|
case 13: return '6';
|
|
case 14: return '7';
|
|
case 15: return '8';
|
|
case 16: return '9';
|
|
case 17: return '*';
|
|
case 18: return '#';
|
|
case 19: return KeyPress::upKey; // KEYCODE_DPAD_UP
|
|
case 20: return KeyPress::downKey; // KEYCODE_DPAD_DOWN
|
|
case 21: return KeyPress::leftKey; // KEYCODE_DPAD_LEFT
|
|
case 22: return KeyPress::rightKey; // KEYCODE_DPAD_RIGHT
|
|
case 29: return 'A';
|
|
case 30: return 'B';
|
|
case 31: return 'C';
|
|
case 32: return 'D';
|
|
case 33: return 'E';
|
|
case 34: return 'F';
|
|
case 35: return 'G';
|
|
case 36: return 'H';
|
|
case 37: return 'I';
|
|
case 38: return 'J';
|
|
case 39: return 'K';
|
|
case 40: return 'L';
|
|
case 41: return 'M';
|
|
case 42: return 'N';
|
|
case 43: return 'O';
|
|
case 44: return 'P';
|
|
case 45: return 'Q';
|
|
case 46: return 'R';
|
|
case 47: return 'S';
|
|
case 48: return 'T';
|
|
case 49: return 'U';
|
|
case 50: return 'V';
|
|
case 51: return 'W';
|
|
case 52: return 'X';
|
|
case 53: return 'Y';
|
|
case 54: return 'Z';
|
|
case 55: return ',';
|
|
case 56: return '.';
|
|
case 61: return KeyPress::tabKey; // KEYCODE_TAB
|
|
case 62: return KeyPress::spaceKey; // KEYCODE_SPACE
|
|
case 66: return KeyPress::returnKey; // KEYCODE_ENTER
|
|
case 67: return KeyPress::backspaceKey; // KEYCODE_DEL
|
|
case 68: return '`';
|
|
case 69: return '-';
|
|
case 70: return '=';
|
|
case 71: return '[';
|
|
case 72: return ']';
|
|
case 73: return '\\';
|
|
case 74: return ';';
|
|
case 75: return '\'';
|
|
case 76: return '/';
|
|
case 77: return '@';
|
|
case 81: return '+';
|
|
case 85: return KeyPress::playKey; // KEYCODE_MEDIA_PLAY_PAUSE
|
|
case 86: return KeyPress::stopKey; // KEYCODE_MEDIA_STOP
|
|
case 87: return KeyPress::fastForwardKey; // KEYCODE_MEDIA_NEXT
|
|
case 88: return KeyPress::rewindKey; // KEYCODE_MEDIA_PREVIOUS
|
|
case 92: return KeyPress::pageUpKey; // KEYCODE_PAGE_UP
|
|
case 93: return KeyPress::pageDownKey; // KEYCODE_PAGE_DOWN
|
|
case 111: return KeyPress::escapeKey; // KEYCODE_ESCAPE
|
|
case 112: return KeyPress::deleteKey; // KEYCODE_FORWARD_DEL
|
|
case 122: return KeyPress::homeKey; // KEYCODE_MOVE_HOME
|
|
case 123: return KeyPress::endKey; // KEYCODE_MOVE_END
|
|
case 124: return KeyPress::insertKey; // KEYCODE_INSERT
|
|
case 131: return KeyPress::F1Key; // KEYCODE_F1
|
|
case 132: return KeyPress::F2Key; // KEYCODE_F2
|
|
case 133: return KeyPress::F3Key; // KEYCODE_F3
|
|
case 134: return KeyPress::F4Key; // KEYCODE_F4
|
|
case 135: return KeyPress::F5Key; // KEYCODE_F5
|
|
case 136: return KeyPress::F6Key; // KEYCODE_F6
|
|
case 137: return KeyPress::F7Key; // KEYCODE_F7
|
|
case 138: return KeyPress::F8Key; // KEYCODE_F8
|
|
case 139: return KeyPress::F9Key; // KEYCODE_F9
|
|
case 140: return KeyPress::F10Key; // KEYCODE_F10
|
|
case 141: return KeyPress::F11Key; // KEYCODE_F11
|
|
case 142: return KeyPress::F12Key; // KEYCODE_F12
|
|
case 144: return '0';
|
|
case 145: return '1';
|
|
case 146: return '2';
|
|
case 147: return '3';
|
|
case 148: return '4';
|
|
case 149: return '5';
|
|
case 150: return '6';
|
|
case 151: return '7';
|
|
case 152: return '8';
|
|
case 153: return '9';
|
|
case 154: return '/';
|
|
case 155: return '*';
|
|
case 156: return '-';
|
|
case 157: return '+';
|
|
case 158: return '.';
|
|
case 159: return ',';
|
|
case 161: return '=';
|
|
case 162: return '(';
|
|
case 163: return ')';
|
|
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
static constexpr int translateAndroidKeyboardFlags (int javaFlags) noexcept
|
|
{
|
|
constexpr int metaShiftOn = 0x1;
|
|
constexpr int metaAltOn = 0x02;
|
|
constexpr int metaCtrlOn = 0x1000;
|
|
|
|
int flags = 0;
|
|
|
|
if ((javaFlags & metaShiftOn) != 0) flags |= ModifierKeys::shiftModifier;
|
|
if ((javaFlags & metaAltOn) != 0) flags |= ModifierKeys::altModifier;
|
|
if ((javaFlags & metaCtrlOn) != 0) flags |= ModifierKeys::ctrlModifier;
|
|
|
|
return flags;
|
|
}
|
|
|
|
//==============================================================================
|
|
class AndroidComponentPeer : public ComponentPeer,
|
|
private Timer
|
|
{
|
|
public:
|
|
AndroidComponentPeer (Component& comp, int windowStyleFlags, void* nativeViewHandle)
|
|
: ComponentPeer (comp, windowStyleFlags)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
// NB: must not put this in the initialiser list, as it invokes a callback,
|
|
// which will fail if the peer is only half-constructed.
|
|
view = GlobalRef (LocalRef<jobject> (env->NewObject (ComponentPeerView, ComponentPeerView.create,
|
|
getAppContext().get(), (jboolean) component.isOpaque(),
|
|
(jlong) this)));
|
|
|
|
if (nativeViewHandle != nullptr)
|
|
{
|
|
viewGroupIsWindow = false;
|
|
|
|
// 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)));
|
|
|
|
if (env->IsInstanceOf (nativeView.get(), AndroidActivity))
|
|
{
|
|
viewGroup = GlobalRef (nativeView);
|
|
env->CallVoidMethod (viewGroup.get(), AndroidActivity.setContentView, view.get());
|
|
}
|
|
else if (env->IsInstanceOf (nativeView.get(), AndroidViewGroup))
|
|
{
|
|
viewGroup = GlobalRef (nativeView);
|
|
LocalRef<jobject> layoutParams (env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2));
|
|
|
|
env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, layoutParams.get());
|
|
env->CallVoidMethod ((jobject) viewGroup.get(), AndroidViewGroup.addView, view.get());
|
|
}
|
|
else
|
|
{
|
|
// the native handle you passed as a second argument to Component::addToDesktop must
|
|
// either be an Activity or a ViewGroup
|
|
jassertfalse;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
viewGroupIsWindow = true;
|
|
|
|
LocalRef<jobject> viewLayoutParams (env->NewObject (AndroidLayoutParams, AndroidLayoutParams.create, -2, -2));
|
|
env->CallVoidMethod (view.get(), AndroidView.setLayoutParams, viewLayoutParams.get());
|
|
|
|
auto physicalBounds = (comp.getBoundsInParent().toFloat() * scale).toNearestInt();
|
|
|
|
view.callVoidMethod (AndroidView.layout,
|
|
physicalBounds.getX(), physicalBounds.getY(), physicalBounds.getRight(), physicalBounds.getBottom());
|
|
|
|
LocalRef<jobject> windowLayoutParams (env->NewObject (AndroidWindowManagerLayoutParams, AndroidWindowManagerLayoutParams.create,
|
|
physicalBounds.getWidth(), physicalBounds.getHeight(),
|
|
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 */);
|
|
|
|
if (supportsDisplayCutout())
|
|
{
|
|
jfieldID layoutInDisplayCutoutModeFieldId = env->GetFieldID (AndroidWindowManagerLayoutParams,
|
|
"layoutInDisplayCutoutMode",
|
|
"I");
|
|
|
|
if (layoutInDisplayCutoutModeFieldId != nullptr)
|
|
env->SetIntField (windowLayoutParams.get(),
|
|
layoutInDisplayCutoutModeFieldId,
|
|
LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS);
|
|
}
|
|
|
|
if (Desktop::getInstance().getKioskModeComponent() != nullptr)
|
|
setNavBarsHidden (true);
|
|
|
|
LocalRef<jobject> activity (getCurrentActivity());
|
|
|
|
if (activity == nullptr)
|
|
activity = getMainActivity();
|
|
|
|
viewGroup = GlobalRef (LocalRef<jobject> (env->CallObjectMethod (activity.get(), AndroidContext.getSystemService, javaString ("window").get())));
|
|
env->CallVoidMethod (viewGroup.get(), AndroidViewManager.addView, view.get(), windowLayoutParams.get());
|
|
}
|
|
|
|
if (supportsDisplayCutout())
|
|
{
|
|
jmethodID setOnApplyWindowInsetsListenerMethodId = env->GetMethodID (AndroidView,
|
|
"setOnApplyWindowInsetsListener",
|
|
"(Landroid/view/View$OnApplyWindowInsetsListener;)V");
|
|
|
|
if (setOnApplyWindowInsetsListenerMethodId != nullptr)
|
|
env->CallVoidMethod (view.get(), setOnApplyWindowInsetsListenerMethodId,
|
|
CreateJavaInterface (new ViewWindowInsetsListener,
|
|
"android/view/View$OnApplyWindowInsetsListener").get());
|
|
}
|
|
|
|
if (isFocused())
|
|
handleFocusGain();
|
|
}
|
|
|
|
~AndroidComponentPeer() override
|
|
{
|
|
stopTimer();
|
|
|
|
auto* env = getEnv();
|
|
|
|
env->CallVoidMethod (view, ComponentPeerView.clear);
|
|
frontWindow = nullptr;
|
|
|
|
GlobalRef localView (view);
|
|
GlobalRef localViewGroup (viewGroup);
|
|
|
|
callOnMessageThread ([env, localView, localViewGroup]
|
|
{
|
|
if (env->IsInstanceOf (localViewGroup.get(), AndroidActivity))
|
|
env->CallVoidMethod (localViewGroup.get(), AndroidActivity.setContentView, nullptr);
|
|
else
|
|
env->CallVoidMethod (localViewGroup.get(), AndroidViewManager.removeView, localView.get());
|
|
});
|
|
}
|
|
|
|
void* getNativeHandle() const override
|
|
{
|
|
return (void*) view.get();
|
|
}
|
|
|
|
void setVisible (bool shouldBeVisible) override
|
|
{
|
|
GlobalRef localView (view);
|
|
|
|
callOnMessageThread ([localView, shouldBeVisible]
|
|
{
|
|
localView.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible);
|
|
});
|
|
}
|
|
|
|
void setTitle (const String& title) override
|
|
{
|
|
view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get());
|
|
}
|
|
|
|
void setBounds (const Rectangle<int>& userRect, bool isNowFullScreen) override
|
|
{
|
|
auto bounds = (userRect.toFloat() * scale).toNearestInt();
|
|
|
|
if (MessageManager::getInstance()->isThisTheMessageThread())
|
|
{
|
|
fullScreen = isNowFullScreen;
|
|
|
|
view.callVoidMethod (AndroidView.layout,
|
|
bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom());
|
|
|
|
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
|
|
{
|
|
GlobalRef localView (view);
|
|
|
|
MessageManager::callAsync ([localView, bounds]
|
|
{
|
|
localView.callVoidMethod (AndroidView.layout,
|
|
bounds.getX(), bounds.getY(), bounds.getRight(), bounds.getBottom());
|
|
});
|
|
}
|
|
}
|
|
|
|
Rectangle<int> getBounds() const override
|
|
{
|
|
Rectangle<int> bounds (view.callIntMethod (AndroidView.getLeft),
|
|
view.callIntMethod (AndroidView.getTop),
|
|
view.callIntMethod (AndroidView.getWidth),
|
|
view.callIntMethod (AndroidView.getHeight));
|
|
|
|
return (bounds.toFloat() / scale).toNearestInt();
|
|
}
|
|
|
|
void handleScreenSizeChange() override
|
|
{
|
|
ComponentPeer::handleScreenSizeChange();
|
|
|
|
if (isFullScreen())
|
|
setFullScreen (true);
|
|
}
|
|
|
|
Point<int> getScreenPosition() const
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jintArray> position (env->NewIntArray (2));
|
|
env->CallVoidMethod (view.get(), AndroidView.getLocationOnScreen, position.get());
|
|
|
|
jint* const screenPosition = env->GetIntArrayElements (position.get(), nullptr);
|
|
Point<int> pos (screenPosition[0], screenPosition[1]);
|
|
env->ReleaseIntArrayElements (position.get(), screenPosition, 0);
|
|
|
|
return pos;
|
|
}
|
|
|
|
Point<float> localToGlobal (Point<float> relativePosition) override
|
|
{
|
|
return relativePosition + (getScreenPosition().toFloat() / scale);
|
|
}
|
|
|
|
using ComponentPeer::localToGlobal;
|
|
|
|
Point<float> globalToLocal (Point<float> screenPosition) override
|
|
{
|
|
return screenPosition - (getScreenPosition().toFloat() / scale);
|
|
}
|
|
|
|
using ComponentPeer::globalToLocal;
|
|
|
|
void setMinimised (bool /*shouldBeMinimised*/) override
|
|
{
|
|
// n/a
|
|
}
|
|
|
|
bool isMinimised() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void setFullScreen (bool shouldBeFullScreen) override
|
|
{
|
|
if (shouldNavBarsBeHidden (shouldBeFullScreen))
|
|
{
|
|
if (isTimerRunning())
|
|
return;
|
|
|
|
startTimer (500);
|
|
}
|
|
else
|
|
{
|
|
setNavBarsHidden (false);
|
|
}
|
|
|
|
auto newBounds = [&]
|
|
{
|
|
if (navBarsHidden || shouldBeFullScreen)
|
|
if (auto* display = Desktop::getInstance().getDisplays().getPrimaryDisplay())
|
|
return navBarsHidden ? display->totalArea
|
|
: display->userArea;
|
|
|
|
return lastNonFullscreenBounds.isEmpty() ? getBounds() : lastNonFullscreenBounds;
|
|
}();
|
|
|
|
if (! newBounds.isEmpty())
|
|
setBounds (newBounds, shouldBeFullScreen);
|
|
|
|
component.repaint();
|
|
}
|
|
|
|
bool isFullScreen() const override
|
|
{
|
|
return fullScreen;
|
|
}
|
|
|
|
void setIcon (const Image& /*newIcon*/) override
|
|
{
|
|
// n/a
|
|
}
|
|
|
|
bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override
|
|
{
|
|
return isPositiveAndBelow (localPos.x, component.getWidth())
|
|
&& isPositiveAndBelow (localPos.y, component.getHeight())
|
|
&& ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint,
|
|
(float) localPos.x * scale,
|
|
(float) localPos.y * scale));
|
|
}
|
|
|
|
OptionalBorderSize getFrameSizeIfPresent() const override
|
|
{
|
|
// TODO
|
|
return {};
|
|
}
|
|
|
|
BorderSize<int> getFrameSize() const override
|
|
{
|
|
// TODO
|
|
return {};
|
|
}
|
|
|
|
bool setAlwaysOnTop (bool /*alwaysOnTop*/) override
|
|
{
|
|
// TODO
|
|
return false;
|
|
}
|
|
|
|
void toFront (bool makeActive) override
|
|
{
|
|
// Avoid calling bringToFront excessively: it's very slow
|
|
if (frontWindow != this)
|
|
{
|
|
view.callVoidMethod (AndroidView.bringToFront);
|
|
frontWindow = this;
|
|
}
|
|
|
|
if (makeActive)
|
|
grabFocus();
|
|
|
|
handleBroughtToFront();
|
|
}
|
|
|
|
void toBehind (ComponentPeer*) override
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
//==============================================================================
|
|
void handleMouseDownCallback (int index, Point<float> sysPos, int64 time)
|
|
{
|
|
lastMousePos = sysPos / scale;
|
|
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::defaultPressure,
|
|
MouseInputSource::defaultOrientation,
|
|
time,
|
|
{},
|
|
index);
|
|
|
|
if (isValidPeer (this))
|
|
handleMouseDragCallback (index, sysPos, time);
|
|
}
|
|
|
|
void handleMouseDragCallback (int index, Point<float> sysPos, int64 time)
|
|
{
|
|
lastMousePos = sysPos / scale;
|
|
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::defaultPressure,
|
|
MouseInputSource::defaultOrientation,
|
|
time,
|
|
{},
|
|
index);
|
|
}
|
|
|
|
void handleMouseUpCallback (int index, Point<float> sysPos, int64 time)
|
|
{
|
|
lastMousePos = sysPos / scale;
|
|
auto pos = globalToLocal (lastMousePos);
|
|
|
|
jassert (index < 64);
|
|
touchesDown = (touchesDown & ~(1 << (index & 63)));
|
|
|
|
if (touchesDown == 0)
|
|
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withoutMouseButtons();
|
|
|
|
handleMouseEvent (MouseInputSource::InputSourceType::touch,
|
|
pos,
|
|
ModifierKeys::currentModifiers.withoutMouseButtons(),
|
|
MouseInputSource::defaultPressure,
|
|
MouseInputSource::defaultOrientation,
|
|
time,
|
|
{},
|
|
index);
|
|
}
|
|
|
|
void handleAccessibilityHoverCallback (int command, Point<float> sysPos, int64)
|
|
{
|
|
enum
|
|
{
|
|
TYPE_VIEW_HOVER_ENTER = 0x00000080,
|
|
TYPE_VIEW_HOVER_EXIT = 0x00000100,
|
|
|
|
ACTION_HOVER_ENTER = 0x00000009,
|
|
ACTION_HOVER_MOVE = 0x00000007,
|
|
ACTION_HOVER_EXIT = 0x0000000a
|
|
};
|
|
|
|
if (auto* topHandler = component.getAccessibilityHandler())
|
|
{
|
|
if (auto* virtualHandler = topHandler->getChildAt ((sysPos / scale).roundToInt()))
|
|
{
|
|
switch (command)
|
|
{
|
|
case ACTION_HOVER_ENTER:
|
|
case ACTION_HOVER_MOVE:
|
|
sendAccessibilityEventImpl (*virtualHandler, TYPE_VIEW_HOVER_ENTER, 0);
|
|
break;
|
|
|
|
case ACTION_HOVER_EXIT:
|
|
sendAccessibilityEventImpl (*virtualHandler, TYPE_VIEW_HOVER_EXIT, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleKeyDownCallback (int k, int kc, int kbFlags)
|
|
{
|
|
ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withOnlyMouseButtons()
|
|
.withFlags (translateAndroidKeyboardFlags (kbFlags));
|
|
handleKeyPress (translateAndroidKeyCode (k), static_cast<juce_wchar> (kc));
|
|
}
|
|
|
|
void handleKeyUpCallback (int /*k*/, int /*kc*/)
|
|
{
|
|
}
|
|
|
|
void handleBackButtonCallback()
|
|
{
|
|
bool handled = false;
|
|
|
|
if (auto* app = JUCEApplicationBase::getInstance())
|
|
handled = app->backButtonPressed();
|
|
|
|
if (isKioskModeComponent())
|
|
setNavBarsHidden (navBarsHidden);
|
|
|
|
if (! handled)
|
|
{
|
|
auto* env = getEnv();
|
|
LocalRef<jobject> activity (getCurrentActivity());
|
|
|
|
if (activity != nullptr)
|
|
{
|
|
jmethodID finishMethod = env->GetMethodID (AndroidActivity, "finish", "()V");
|
|
|
|
if (finishMethod != nullptr)
|
|
env->CallVoidMethod (activity.get(), finishMethod);
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleKeyboardHiddenCallback()
|
|
{
|
|
Component::unfocusAllComponents();
|
|
}
|
|
|
|
void handleAppPausedCallback() {}
|
|
|
|
void handleAppResumedCallback()
|
|
{
|
|
if (isKioskModeComponent())
|
|
setNavBarsHidden (navBarsHidden);
|
|
}
|
|
|
|
//==============================================================================
|
|
AccessibilityNativeHandle* getNativeHandleForViewId (jint virtualViewId) const
|
|
{
|
|
if (auto* handler = (virtualViewId == HOST_VIEW_ID
|
|
? component.getAccessibilityHandler()
|
|
: AccessibilityNativeHandle::getAccessibilityHandlerForVirtualViewId (virtualViewId)))
|
|
{
|
|
return handler->getNativeImplementation();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
jboolean populateAccessibilityNodeInfoCallback (jint virtualViewId, jobject info) const
|
|
{
|
|
if (auto* handle = getNativeHandleForViewId (virtualViewId))
|
|
{
|
|
handle->populateNodeInfo (info);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
jboolean handlePerformActionCallback (jint virtualViewId, jint action, jobject arguments) const
|
|
{
|
|
if (auto* handle = getNativeHandleForViewId (virtualViewId))
|
|
return handle->performAction (action, arguments);
|
|
|
|
return false;
|
|
}
|
|
|
|
static jobject getFocusViewIdForHandler (const AccessibilityHandler* handler)
|
|
{
|
|
if (handler != nullptr)
|
|
return getEnv()->NewObject (JavaInteger,
|
|
JavaInteger.constructor,
|
|
handler->getNativeImplementation()->getVirtualViewId());
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
jobject getInputFocusViewIdCallback()
|
|
{
|
|
if (auto* comp = dynamic_cast<Component*> (findCurrentTextInputTarget()))
|
|
return getFocusViewIdForHandler (comp->getAccessibilityHandler());
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
jobject getAccessibilityFocusViewIdCallback() const
|
|
{
|
|
if (auto* handler = component.getAccessibilityHandler())
|
|
{
|
|
if (auto* modal = Component::getCurrentlyModalComponent())
|
|
{
|
|
if (! component.isParentOf (modal)
|
|
&& component.isCurrentlyBlockedByAnotherModalComponent())
|
|
{
|
|
if (auto* modalHandler = modal->getAccessibilityHandler())
|
|
{
|
|
if (auto* focusChild = modalHandler->getChildFocus())
|
|
return getFocusViewIdForHandler (focusChild);
|
|
|
|
return getFocusViewIdForHandler (modalHandler);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (auto* focusChild = handler->getChildFocus())
|
|
return getFocusViewIdForHandler (focusChild);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//==============================================================================
|
|
bool isFocused() const override
|
|
{
|
|
if (view != nullptr)
|
|
return view.callBooleanMethod (AndroidView.hasFocus);
|
|
|
|
return false;
|
|
}
|
|
|
|
void grabFocus() override
|
|
{
|
|
if (view != nullptr)
|
|
view.callBooleanMethod (AndroidView.requestFocus);
|
|
}
|
|
|
|
void handleFocusChangeCallback (bool hasFocus)
|
|
{
|
|
if (isFullScreen())
|
|
setFullScreen (true);
|
|
|
|
if (hasFocus)
|
|
handleFocusGain();
|
|
else
|
|
handleFocusLoss();
|
|
}
|
|
|
|
static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept
|
|
{
|
|
switch (type)
|
|
{
|
|
case TextInputTarget::textKeyboard: return "text";
|
|
case TextInputTarget::numericKeyboard: return "number";
|
|
case TextInputTarget::decimalKeyboard: return "numberDecimal";
|
|
case TextInputTarget::urlKeyboard: return "textUri";
|
|
case TextInputTarget::emailAddressKeyboard: return "textEmailAddress";
|
|
case TextInputTarget::phoneNumberKeyboard: return "phone";
|
|
default: jassertfalse; break;
|
|
}
|
|
|
|
return "text";
|
|
}
|
|
|
|
void textInputRequired (Point<int>, TextInputTarget& target) override
|
|
{
|
|
view.callVoidMethod (ComponentPeerView.showKeyboard,
|
|
javaString (getVirtualKeyboardType (target.getKeyboardType())).get());
|
|
}
|
|
|
|
void dismissPendingTextInput() override
|
|
{
|
|
view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get());
|
|
|
|
if (! isTimerRunning())
|
|
startTimer (500);
|
|
}
|
|
|
|
//==============================================================================
|
|
void handlePaintCallback (jobject canvas, jobject paint)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
jobject rect = env->CallObjectMethod (canvas, AndroidCanvas.getClipBounds);
|
|
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);
|
|
|
|
auto clip = Rectangle<int>::leftTopRightBottom (left, top, right, bottom);
|
|
|
|
if (clip.isEmpty())
|
|
return;
|
|
|
|
auto sizeNeeded = clip.getWidth() * clip.getHeight();
|
|
|
|
if (sizeAllocated < sizeNeeded)
|
|
{
|
|
buffer.clear();
|
|
sizeAllocated = sizeNeeded;
|
|
buffer = GlobalRef (LocalRef<jobject> ((jobject) env->NewIntArray (sizeNeeded)));
|
|
}
|
|
|
|
if (jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), nullptr))
|
|
{
|
|
{
|
|
Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(),
|
|
dest, ! component.isOpaque()));
|
|
|
|
{
|
|
LowLevelGraphicsSoftwareRenderer g (temp);
|
|
g.setOrigin (-clip.getPosition());
|
|
g.addTransform (AffineTransform::scale (scale));
|
|
handlePaint (g);
|
|
}
|
|
}
|
|
|
|
env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0);
|
|
|
|
env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),
|
|
(jfloat) clip.getX(), (jfloat) clip.getY(),
|
|
clip.getWidth(), clip.getHeight(), true, paint);
|
|
}
|
|
}
|
|
|
|
void repaint (const Rectangle<int>& userArea) override
|
|
{
|
|
auto area = (userArea.toFloat() * scale).toNearestInt();
|
|
|
|
GlobalRef localView (view);
|
|
|
|
callOnMessageThread ([area, localView]
|
|
{
|
|
localView.callVoidMethod (AndroidView.invalidate,
|
|
area.getX(), area.getY(), area.getRight(), area.getBottom());
|
|
});
|
|
}
|
|
|
|
void performAnyPendingRepaintsNow() override
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
void setAlpha (float /*newAlpha*/) override
|
|
{
|
|
// TODO
|
|
}
|
|
|
|
StringArray getAvailableRenderingEngines() override
|
|
{
|
|
return StringArray ("Software Renderer");
|
|
}
|
|
|
|
//==============================================================================
|
|
static Point<float> lastMousePos;
|
|
static int64 touchesDown;
|
|
|
|
//==============================================================================
|
|
struct StartupActivityCallbackListener : public ActivityLifecycleCallbacks
|
|
{
|
|
void onActivityStarted (jobject /*activity*/) override
|
|
{
|
|
auto* env = getEnv();
|
|
LocalRef<jobject> appContext (getAppContext());
|
|
|
|
if (appContext.get() != nullptr)
|
|
{
|
|
env->CallVoidMethod (appContext.get(),
|
|
AndroidApplication.unregisterActivityLifecycleCallbacks,
|
|
activityCallbackListener.get());
|
|
clear();
|
|
activityCallbackListener.clear();
|
|
|
|
forceDisplayUpdate();
|
|
}
|
|
}
|
|
};
|
|
|
|
private:
|
|
//==============================================================================
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (create, "<init>", "(Landroid/content/Context;ZJ)V") \
|
|
METHOD (clear, "clear", "()V") \
|
|
METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \
|
|
METHOD (setVisible, "setVisible", "(Z)V") \
|
|
METHOD (isVisible, "isVisible", "()Z") \
|
|
METHOD (containsPoint, "containsPoint", "(II)Z") \
|
|
METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \
|
|
METHOD (setSystemUiVisibilityCompat, "setSystemUiVisibilityCompat", "(I)V") \
|
|
CALLBACK (handlePaintJni, "handlePaint", "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \
|
|
CALLBACK (handleMouseDownJni, "handleMouseDown", "(JIFFJ)V") \
|
|
CALLBACK (handleMouseDragJni, "handleMouseDrag", "(JIFFJ)V") \
|
|
CALLBACK (handleMouseUpJni, "handleMouseUp", "(JIFFJ)V") \
|
|
CALLBACK (handleAccessibleHoverJni, "handleAccessibilityHover", "(JIFFJ)V") \
|
|
CALLBACK (handleKeyDownJni, "handleKeyDown", "(JIII)V") \
|
|
CALLBACK (handleKeyUpJni, "handleKeyUp", "(JII)V") \
|
|
CALLBACK (handleBackButtonJni, "handleBackButton", "(J)V") \
|
|
CALLBACK (handleKeyboardHiddenJni, "handleKeyboardHidden", "(J)V") \
|
|
CALLBACK (viewSizeChangedJni, "viewSizeChanged", "(J)V") \
|
|
CALLBACK (focusChangedJni, "focusChanged", "(JZ)V") \
|
|
CALLBACK (handleAppPausedJni, "handleAppPaused", "(J)V") \
|
|
CALLBACK (handleAppResumedJni, "handleAppResumed", "(J)V") \
|
|
CALLBACK (populateAccessibilityNodeInfoJni, "populateAccessibilityNodeInfo", "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \
|
|
CALLBACK (handlePerformActionJni, "handlePerformAction", "(JIILandroid/os/Bundle;)Z") \
|
|
CALLBACK (getInputFocusViewIdJni, "getInputFocusViewId", "(J)Ljava/lang/Integer;") \
|
|
CALLBACK (getAccessibilityFocusViewIdJni, "getAccessibilityFocusViewId", "(J)Ljava/lang/Integer;") \
|
|
|
|
DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView, sizeof (javaComponentPeerView))
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
static void JNICALL handlePaintJni (JNIEnv*, jobject /*view*/, jlong host, jobject canvas, jobject paint) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handlePaintCallback (canvas, paint); }
|
|
static void JNICALL handleMouseDownJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDownCallback (i, Point<float> ((float) x, (float) y), (int64) time); }
|
|
static void JNICALL handleMouseDragJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDragCallback (i, Point<float> ((float) x, (float) y), (int64) time); }
|
|
static void JNICALL handleMouseUpJni (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseUpCallback (i, Point<float> ((float) x, (float) y), (int64) time); }
|
|
static void JNICALL handleAccessibleHoverJni(JNIEnv*, jobject /*view*/, jlong host, jint c, jfloat x, jfloat y, jlong time) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAccessibilityHoverCallback ((int) c, Point<float> ((float) x, (float) y), (int64) time); }
|
|
static void JNICALL viewSizeChangedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMovedOrResized(); }
|
|
static void JNICALL focusChangedJni (JNIEnv*, jobject /*view*/, jlong host, jboolean hasFocus) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleFocusChangeCallback (hasFocus); }
|
|
static void JNICALL handleKeyDownJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc, jint kbFlags) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyDownCallback ((int) k, (int) kc, (int) kbFlags); }
|
|
static void JNICALL handleKeyUpJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyUpCallback ((int) k, (int) kc); }
|
|
static void JNICALL handleBackButtonJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleBackButtonCallback(); }
|
|
static void JNICALL handleKeyboardHiddenJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyboardHiddenCallback(); }
|
|
static void JNICALL handleAppPausedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAppPausedCallback(); }
|
|
static void JNICALL handleAppResumedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAppResumedCallback(); }
|
|
|
|
static jboolean JNICALL populateAccessibilityNodeInfoJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jobject info)
|
|
{
|
|
if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))
|
|
return myself->populateAccessibilityNodeInfoCallback (virtualViewId, info);
|
|
|
|
return false;
|
|
}
|
|
|
|
static jboolean JNICALL handlePerformActionJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jint action, jobject arguments)
|
|
{
|
|
if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))
|
|
return myself->handlePerformActionCallback (virtualViewId, action, arguments);
|
|
|
|
return false;
|
|
}
|
|
|
|
static jobject JNICALL getInputFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host)
|
|
{
|
|
if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))
|
|
return myself->getInputFocusViewIdCallback();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static jobject JNICALL getAccessibilityFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host)
|
|
{
|
|
if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))
|
|
return myself->getAccessibilityFocusViewIdCallback();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
//==============================================================================
|
|
struct ViewWindowInsetsListener : public juce::AndroidInterfaceImplementer
|
|
{
|
|
jobject onApplyWindowInsets (LocalRef<jobject> v, LocalRef<jobject> insets)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> displayCutout (env->CallObjectMethod (insets.get(), AndroidWindowInsets.getDisplayCutout));
|
|
|
|
if (displayCutout != nullptr)
|
|
{
|
|
const auto& mainDisplay = *Desktop::getInstance().getDisplays().getPrimaryDisplay();
|
|
auto newSafeAreaInsets = androidDisplayCutoutToBorderSize (displayCutout, mainDisplay.scale);
|
|
|
|
if (newSafeAreaInsets != mainDisplay.safeAreaInsets)
|
|
forceDisplayUpdate();
|
|
|
|
auto* fieldId = env->GetStaticFieldID (AndroidWindowInsets, "CONSUMED", "Landroid/view/WindowInsets");
|
|
jassert (fieldId != nullptr);
|
|
|
|
return env->GetStaticObjectField (AndroidWindowInsets, fieldId);
|
|
}
|
|
|
|
jmethodID onApplyWindowInsetsMethodId = env->GetMethodID (AndroidView,
|
|
"onApplyWindowInsets",
|
|
"(Landroid/view/WindowInsets;)Landroid/view/WindowInsets;");
|
|
|
|
jassert (onApplyWindowInsetsMethodId != nullptr);
|
|
|
|
return env->CallObjectMethod (v.get(), onApplyWindowInsetsMethodId, insets.get());
|
|
}
|
|
|
|
private:
|
|
jobject invoke (jobject proxy, jobject method, jobjectArray args) override
|
|
{
|
|
auto* env = getEnv();
|
|
auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName));
|
|
|
|
if (methodName == "onApplyWindowInsets")
|
|
{
|
|
jassert (env->GetArrayLength (args) == 2);
|
|
|
|
LocalRef<jobject> windowView (env->GetObjectArrayElement (args, 0));
|
|
LocalRef<jobject> insets (env->GetObjectArrayElement (args, 1));
|
|
|
|
return onApplyWindowInsets (std::move (windowView), std::move (insets));
|
|
}
|
|
|
|
// invoke base class
|
|
return AndroidInterfaceImplementer::invoke (proxy, method, args);
|
|
}
|
|
};
|
|
|
|
//==============================================================================
|
|
struct PreallocatedImage : public ImagePixelData
|
|
{
|
|
PreallocatedImage (int width_, int height_, jint* data_, bool hasAlpha_)
|
|
: ImagePixelData (Image::ARGB, width_, height_), data (data_), hasAlpha (hasAlpha_)
|
|
{
|
|
if (hasAlpha_)
|
|
zeromem (data_, static_cast<size_t> (width * height) * sizeof (jint));
|
|
}
|
|
|
|
~PreallocatedImage() override
|
|
{
|
|
if (hasAlpha)
|
|
{
|
|
auto pix = (PixelARGB*) data;
|
|
|
|
for (int i = width * height; --i >= 0;)
|
|
{
|
|
pix->unpremultiply();
|
|
++pix;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ImageType> createType() const override
|
|
{
|
|
return std::make_unique<SoftwareImageType>();
|
|
}
|
|
|
|
std::unique_ptr<LowLevelGraphicsContext> createLowLevelContext() override
|
|
{
|
|
return std::make_unique<LowLevelGraphicsSoftwareRenderer> (Image (this));
|
|
}
|
|
|
|
void initialiseBitmapData (Image::BitmapData& bm, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) override
|
|
{
|
|
bm.lineStride = width * static_cast<int> (sizeof (jint));
|
|
bm.pixelStride = static_cast<int> (sizeof (jint));
|
|
bm.pixelFormat = Image::ARGB;
|
|
const auto offset = (size_t) x + (size_t) y * (size_t) width;
|
|
bm.data = (uint8*) (data + offset);
|
|
bm.size = sizeof (jint) * (((size_t) height * (size_t) width) - offset);
|
|
}
|
|
|
|
ImagePixelData::Ptr clone() override
|
|
{
|
|
auto s = new PreallocatedImage (width, height, nullptr, hasAlpha);
|
|
s->allocatedData.malloc (sizeof (jint) * static_cast<size_t> (width * height));
|
|
s->data = s->allocatedData;
|
|
memcpy (s->data, data, sizeof (jint) * static_cast<size_t> (width * height));
|
|
return s;
|
|
}
|
|
|
|
private:
|
|
jint* data;
|
|
HeapBlock<jint> allocatedData;
|
|
bool hasAlpha;
|
|
|
|
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;
|
|
static constexpr int LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS = 0x3;
|
|
|
|
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)
|
|
};
|
|
|
|
Point<float> AndroidComponentPeer::lastMousePos;
|
|
int64 AndroidComponentPeer::touchesDown = 0;
|
|
AndroidComponentPeer* AndroidComponentPeer::frontWindow = nullptr;
|
|
GlobalRef AndroidComponentPeer::activityCallbackListener;
|
|
AndroidComponentPeer::ComponentPeerView_Class AndroidComponentPeer::ComponentPeerView;
|
|
|
|
//==============================================================================
|
|
ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindow)
|
|
{
|
|
return new AndroidComponentPeer (*this, styleFlags, nativeWindow);
|
|
}
|
|
|
|
//==============================================================================
|
|
bool Desktop::canUseSemiTransparentWindows() noexcept
|
|
{
|
|
return true;
|
|
}
|
|
|
|
class Desktop::NativeDarkModeChangeDetectorImpl : public ActivityLifecycleCallbacks
|
|
{
|
|
public:
|
|
NativeDarkModeChangeDetectorImpl()
|
|
{
|
|
LocalRef<jobject> appContext (getAppContext());
|
|
|
|
if (appContext != nullptr)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
myself = GlobalRef (CreateJavaInterface (this, "android/app/Application$ActivityLifecycleCallbacks"));
|
|
env->CallVoidMethod (appContext.get(), AndroidApplication.registerActivityLifecycleCallbacks, myself.get());
|
|
}
|
|
}
|
|
|
|
~NativeDarkModeChangeDetectorImpl() override
|
|
{
|
|
LocalRef<jobject> appContext (getAppContext());
|
|
|
|
if (appContext != nullptr && myself != nullptr)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
env->CallVoidMethod (appContext.get(),
|
|
AndroidApplication.unregisterActivityLifecycleCallbacks,
|
|
myself.get());
|
|
clear();
|
|
myself.clear();
|
|
}
|
|
}
|
|
|
|
bool isDarkModeEnabled() const noexcept { return darkModeEnabled; }
|
|
|
|
void onActivityStarted (jobject /*activity*/) override
|
|
{
|
|
const auto isEnabled = getDarkModeSetting();
|
|
|
|
if (darkModeEnabled != isEnabled)
|
|
{
|
|
darkModeEnabled = isEnabled;
|
|
Desktop::getInstance().darkModeChanged();
|
|
}
|
|
}
|
|
|
|
private:
|
|
static bool getDarkModeSetting()
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
const LocalRef<jobject> resources (env->CallObjectMethod (getAppContext().get(), AndroidContext.getResources));
|
|
const LocalRef<jobject> configuration (env->CallObjectMethod (resources, AndroidResources.getConfiguration));
|
|
|
|
const auto uiMode = env->GetIntField (configuration, AndroidConfiguration.uiMode);
|
|
|
|
return ((uiMode & UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES);
|
|
}
|
|
|
|
static constexpr int UI_MODE_NIGHT_MASK = 0x00000030,
|
|
UI_MODE_NIGHT_NO = 0x00000010,
|
|
UI_MODE_NIGHT_UNDEFINED = 0x00000000,
|
|
UI_MODE_NIGHT_YES = 0x00000020;
|
|
|
|
GlobalRef myself;
|
|
bool darkModeEnabled = getDarkModeSetting();
|
|
|
|
//==============================================================================
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeDarkModeChangeDetectorImpl)
|
|
};
|
|
|
|
std::unique_ptr<Desktop::NativeDarkModeChangeDetectorImpl> Desktop::createNativeDarkModeChangeDetectorImpl()
|
|
{
|
|
return std::make_unique<NativeDarkModeChangeDetectorImpl>();
|
|
}
|
|
|
|
bool Desktop::isDarkModeActive() const
|
|
{
|
|
return nativeDarkModeChangeDetectorImpl->isDarkModeEnabled();
|
|
}
|
|
|
|
double Desktop::getDefaultMasterScale()
|
|
{
|
|
return 1.0;
|
|
}
|
|
|
|
Desktop::DisplayOrientation Desktop::getCurrentOrientation() const
|
|
{
|
|
enum
|
|
{
|
|
ROTATION_0 = 0,
|
|
ROTATION_90 = 1,
|
|
ROTATION_180 = 2,
|
|
ROTATION_270 = 3
|
|
};
|
|
|
|
JNIEnv* env = getEnv();
|
|
LocalRef<jstring> windowServiceString (javaString ("window"));
|
|
|
|
|
|
LocalRef<jobject> windowManager = LocalRef<jobject> (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get()));
|
|
|
|
if (windowManager.get() != nullptr)
|
|
{
|
|
LocalRef<jobject> display = LocalRef<jobject> (env->CallObjectMethod (windowManager, AndroidWindowManager.getDefaultDisplay));
|
|
|
|
if (display.get() != nullptr)
|
|
{
|
|
int rotation = env->CallIntMethod (display, AndroidDisplay.getRotation);
|
|
|
|
switch (rotation)
|
|
{
|
|
case ROTATION_0: return upright;
|
|
case ROTATION_90: return rotatedAntiClockwise;
|
|
case ROTATION_180: return upsideDown;
|
|
case ROTATION_270: return rotatedClockwise;
|
|
}
|
|
}
|
|
}
|
|
|
|
jassertfalse;
|
|
return upright;
|
|
}
|
|
|
|
bool MouseInputSource::SourceList::addSource()
|
|
{
|
|
addSource (sources.size(), MouseInputSource::InputSourceType::touch);
|
|
return true;
|
|
}
|
|
|
|
bool MouseInputSource::SourceList::canUseTouch()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Point<float> MouseInputSource::getCurrentRawMousePosition()
|
|
{
|
|
return AndroidComponentPeer::lastMousePos;
|
|
}
|
|
|
|
void MouseInputSource::setRawMousePosition (Point<float>)
|
|
{
|
|
// not needed
|
|
}
|
|
|
|
//==============================================================================
|
|
bool KeyPress::isKeyCurrentlyDown (int /*keyCode*/)
|
|
{
|
|
// TODO
|
|
return false;
|
|
}
|
|
|
|
JUCE_API void JUCE_CALLTYPE Process::hide()
|
|
{
|
|
auto* env = getEnv();
|
|
LocalRef<jobject> currentActivity (getCurrentActivity().get());
|
|
|
|
if (env->CallBooleanMethod (currentActivity.get(), AndroidActivity.moveTaskToBack, true) == 0)
|
|
{
|
|
GlobalRef intent (LocalRef<jobject> (env->NewObject (AndroidIntent, AndroidIntent.constructor)));
|
|
env->CallObjectMethod (intent, AndroidIntent.setAction, javaString ("android.intent.action.MAIN") .get());
|
|
env->CallObjectMethod (intent, AndroidIntent.addCategory, javaString ("android.intent.category.HOME").get());
|
|
|
|
env->CallVoidMethod (currentActivity.get(), AndroidContext.startActivity, intent.get());
|
|
}
|
|
}
|
|
|
|
//==============================================================================
|
|
// TODO
|
|
JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess() { return true; }
|
|
JUCE_API void JUCE_CALLTYPE Process::makeForegroundProcess() {}
|
|
|
|
//==============================================================================
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (show, "show", "()V") \
|
|
METHOD (getWindow, "getWindow", "()Landroid/view/Window;")
|
|
|
|
DECLARE_JNI_CLASS (AndroidDialog, "android/app/Dialog")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (construct, "<init>", "(Landroid/content/Context;)V") \
|
|
METHOD (create, "create", "()Landroid/app/AlertDialog;") \
|
|
METHOD (setTitle, "setTitle", "(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setMessage, "setMessage", "(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setCancelable, "setCancelable", "(Z)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setOnCancelListener, "setOnCancelListener", "(Landroid/content/DialogInterface$OnCancelListener;)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setPositiveButton, "setPositiveButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setNegativeButton, "setNegativeButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;") \
|
|
METHOD (setNeutralButton, "setNeutralButton", "(Ljava/lang/CharSequence;Landroid/content/DialogInterface$OnClickListener;)Landroid/app/AlertDialog$Builder;")
|
|
|
|
DECLARE_JNI_CLASS (AndroidAlertDialogBuilder, "android/app/AlertDialog$Builder")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (dismiss, "dismiss", "()V")
|
|
|
|
DECLARE_JNI_CLASS (AndroidDialogInterface, "android/content/DialogInterface")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
|
|
DECLARE_JNI_CLASS (AndroidDialogOnClickListener, "android/content/DialogInterface$OnClickListener")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
//==============================================================================
|
|
class DialogListener : public juce::AndroidInterfaceImplementer
|
|
{
|
|
public:
|
|
DialogListener (std::shared_ptr<ModalComponentManager::Callback> callbackToUse, int resultToUse)
|
|
: callback (std::move (callbackToUse)), result (resultToUse)
|
|
{}
|
|
|
|
void onResult (jobject dialog)
|
|
{
|
|
auto* env = getEnv();
|
|
env->CallVoidMethod (dialog, AndroidDialogInterface.dismiss);
|
|
|
|
if (callback != nullptr)
|
|
callback->modalStateFinished (result);
|
|
|
|
callback = nullptr;
|
|
}
|
|
|
|
private:
|
|
jobject invoke (jobject proxy, jobject method, jobjectArray args) override
|
|
{
|
|
auto* env = getEnv();
|
|
auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName));
|
|
|
|
if (methodName == "onCancel" || methodName == "onClick")
|
|
{
|
|
onResult (env->GetObjectArrayElement (args, 0));
|
|
return nullptr;
|
|
}
|
|
|
|
// invoke base class
|
|
return AndroidInterfaceImplementer::invoke (proxy, method, args);
|
|
}
|
|
|
|
std::shared_ptr<ModalComponentManager::Callback> callback;
|
|
int result;
|
|
};
|
|
|
|
//==============================================================================
|
|
static void createAndroidDialog (const MessageBoxOptions& opts,
|
|
ModalComponentManager::Callback* callbackIn,
|
|
AlertWindowMappings::MapFn mapFn)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> builder (env->NewObject (AndroidAlertDialogBuilder, AndroidAlertDialogBuilder.construct, getMainActivity().get()));
|
|
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setTitle, javaString (opts.getTitle()).get()));
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setMessage, javaString (opts.getMessage()).get()));
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setCancelable, true));
|
|
|
|
std::shared_ptr<ModalComponentManager::Callback> sharedCallback (AlertWindowMappings::getWrappedCallback (callbackIn, mapFn));
|
|
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setOnCancelListener,
|
|
CreateJavaInterface (new DialogListener (sharedCallback, 0),
|
|
"android/content/DialogInterface$OnCancelListener").get()));
|
|
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setPositiveButton,
|
|
javaString (opts.getButtonText (0)).get(),
|
|
CreateJavaInterface (new DialogListener (sharedCallback, 0),
|
|
"android/content/DialogInterface$OnClickListener").get()));
|
|
|
|
if (opts.getButtonText (1).isNotEmpty())
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNegativeButton,
|
|
javaString (opts.getButtonText (1)).get(),
|
|
CreateJavaInterface (new DialogListener (sharedCallback, 1),
|
|
"android/content/DialogInterface$OnClickListener").get()));
|
|
|
|
if (opts.getButtonText (2).isNotEmpty())
|
|
builder = LocalRef<jobject> (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNeutralButton,
|
|
javaString (opts.getButtonText (2)).get(),
|
|
CreateJavaInterface (new DialogListener (sharedCallback, 2),
|
|
"android/content/DialogInterface$OnClickListener").get()));
|
|
|
|
LocalRef<jobject> dialog (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.create));
|
|
|
|
LocalRef<jobject> window (env->CallObjectMethod (dialog.get(), AndroidDialog.getWindow));
|
|
|
|
if (Desktop::getInstance().getKioskModeComponent() != nullptr)
|
|
{
|
|
env->CallVoidMethod (window.get(), AndroidWindow.setFlags, FLAG_NOT_FOCUSABLE, FLAG_NOT_FOCUSABLE);
|
|
LocalRef<jobject> decorView (env->CallObjectMethod (window.get(), AndroidWindow.getDecorView));
|
|
env->CallVoidMethod (decorView.get(), AndroidView.setSystemUiVisibility, fullScreenFlags);
|
|
}
|
|
|
|
env->CallVoidMethod (dialog.get(), AndroidDialog.show);
|
|
|
|
if (Desktop::getInstance().getKioskModeComponent() != nullptr)
|
|
env->CallVoidMethod (window.get(), AndroidWindow.clearFlags, FLAG_NOT_FOCUSABLE);
|
|
}
|
|
|
|
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (MessageBoxIconType /*iconType*/,
|
|
const String& title, const String& message,
|
|
Component* /*associatedComponent*/,
|
|
ModalComponentManager::Callback* callback)
|
|
{
|
|
createAndroidDialog (MessageBoxOptions()
|
|
.withTitle (title)
|
|
.withMessage (message)
|
|
.withButton (TRANS("OK")),
|
|
callback, AlertWindowMappings::messageBox);
|
|
}
|
|
|
|
bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (MessageBoxIconType /*iconType*/,
|
|
const String& title, const String& message,
|
|
Component* /*associatedComponent*/,
|
|
ModalComponentManager::Callback* callback)
|
|
{
|
|
createAndroidDialog (MessageBoxOptions()
|
|
.withTitle (title)
|
|
.withMessage (message)
|
|
.withButton (TRANS("OK"))
|
|
.withButton (TRANS("Cancel")),
|
|
callback, AlertWindowMappings::okCancel);
|
|
|
|
return false;
|
|
}
|
|
|
|
int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (MessageBoxIconType /*iconType*/,
|
|
const String& title, const String& message,
|
|
Component* /*associatedComponent*/,
|
|
ModalComponentManager::Callback* callback)
|
|
{
|
|
createAndroidDialog (MessageBoxOptions()
|
|
.withTitle (title)
|
|
.withMessage (message)
|
|
.withButton (TRANS("Yes"))
|
|
.withButton (TRANS("No"))
|
|
.withButton (TRANS("Cancel")),
|
|
callback, AlertWindowMappings::yesNoCancel);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int JUCE_CALLTYPE NativeMessageBox::showYesNoBox (MessageBoxIconType /*iconType*/,
|
|
const String& title, const String& message,
|
|
Component* /*associatedComponent*/,
|
|
ModalComponentManager::Callback* callback)
|
|
{
|
|
createAndroidDialog (MessageBoxOptions()
|
|
.withTitle (title)
|
|
.withMessage (message)
|
|
.withButton (TRANS("Yes"))
|
|
.withButton (TRANS("No")),
|
|
callback, AlertWindowMappings::okCancel);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
|
|
ModalComponentManager::Callback* callback)
|
|
{
|
|
createAndroidDialog (options, callback, AlertWindowMappings::noMapping);
|
|
}
|
|
|
|
void JUCE_CALLTYPE NativeMessageBox::showAsync (const MessageBoxOptions& options,
|
|
std::function<void (int)> callback)
|
|
{
|
|
showAsync (options, ModalCallbackFunction::create (callback));
|
|
}
|
|
|
|
//==============================================================================
|
|
static bool androidScreenSaverEnabled = true;
|
|
|
|
void Desktop::setScreenSaverEnabled (bool shouldEnable)
|
|
{
|
|
constexpr auto FLAG_KEEP_SCREEN_ON = 0x80;
|
|
|
|
if (shouldEnable != androidScreenSaverEnabled)
|
|
{
|
|
LocalRef<jobject> activity (getMainActivity());
|
|
|
|
if (activity != nullptr)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> mainWindow (env->CallObjectMethod (activity.get(), AndroidActivity.getWindow));
|
|
env->CallVoidMethod (mainWindow.get(), AndroidWindow.setFlags, shouldEnable ? 0 : FLAG_KEEP_SCREEN_ON, FLAG_KEEP_SCREEN_ON);
|
|
}
|
|
|
|
androidScreenSaverEnabled = shouldEnable;
|
|
}
|
|
}
|
|
|
|
bool Desktop::isScreenSaverEnabled()
|
|
{
|
|
return androidScreenSaverEnabled;
|
|
}
|
|
|
|
//==============================================================================
|
|
void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, bool allowMenusAndBars)
|
|
{
|
|
ignoreUnused (allowMenusAndBars);
|
|
|
|
if (AndroidComponentPeer* peer = dynamic_cast<AndroidComponentPeer*> (kioskComp->getPeer()))
|
|
peer->setFullScreen (enableOrDisable);
|
|
else
|
|
jassertfalse; // (this should have been checked by the caller)
|
|
}
|
|
|
|
//==============================================================================
|
|
static jint getAndroidOrientationFlag (int orientations) noexcept
|
|
{
|
|
enum
|
|
{
|
|
SCREEN_ORIENTATION_LANDSCAPE = 0,
|
|
SCREEN_ORIENTATION_PORTRAIT = 1,
|
|
SCREEN_ORIENTATION_USER = 2,
|
|
SCREEN_ORIENTATION_REVERSE_LANDSCAPE = 8,
|
|
SCREEN_ORIENTATION_REVERSE_PORTRAIT = 9,
|
|
SCREEN_ORIENTATION_USER_LANDSCAPE = 11,
|
|
SCREEN_ORIENTATION_USER_PORTRAIT = 12,
|
|
};
|
|
|
|
switch (orientations)
|
|
{
|
|
case Desktop::upright: return (jint) SCREEN_ORIENTATION_PORTRAIT;
|
|
case Desktop::upsideDown: return (jint) SCREEN_ORIENTATION_REVERSE_PORTRAIT;
|
|
case Desktop::upright + Desktop::upsideDown: return (jint) SCREEN_ORIENTATION_USER_PORTRAIT;
|
|
case Desktop::rotatedAntiClockwise: return (jint) SCREEN_ORIENTATION_LANDSCAPE;
|
|
case Desktop::rotatedClockwise: return (jint) SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
|
|
case Desktop::rotatedClockwise + Desktop::rotatedAntiClockwise: return (jint) SCREEN_ORIENTATION_USER_LANDSCAPE;
|
|
default: return (jint) SCREEN_ORIENTATION_USER;
|
|
}
|
|
}
|
|
|
|
void Desktop::allowedOrientationsChanged()
|
|
{
|
|
LocalRef<jobject> activity (getMainActivity());
|
|
|
|
if (activity != nullptr)
|
|
getEnv()->CallVoidMethod (activity.get(), AndroidActivity.setRequestedOrientation, getAndroidOrientationFlag (allowedOrientations));
|
|
}
|
|
|
|
//==============================================================================
|
|
bool juce_areThereAnyAlwaysOnTopWindows()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//==============================================================================
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (create, "<init>", "()V") \
|
|
FIELD (density, "density", "F") \
|
|
FIELD (widthPixels, "widthPixels", "I") \
|
|
FIELD (heightPixels, "heightPixels", "I")
|
|
|
|
DECLARE_JNI_CLASS (AndroidDisplayMetrics, "android/util/DisplayMetrics")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
//==============================================================================
|
|
class LayoutChangeListener : public juce::AndroidInterfaceImplementer
|
|
{
|
|
public:
|
|
virtual void onLayoutChange (LocalRef<jobject> view, int left, int top, int right, int bottom,
|
|
int oldLeft, int oldTop, int oldRight, int oldBottom) = 0;
|
|
|
|
private:
|
|
jobject invoke (jobject proxy, jobject method, jobjectArray args) override
|
|
{
|
|
auto* env = getEnv();
|
|
auto methodName = juce::juceString ((jstring) env->CallObjectMethod (method, JavaMethod.getName));
|
|
|
|
if (methodName == "onLayoutChange")
|
|
{
|
|
jassert (env->GetArrayLength (args) == 9);
|
|
|
|
LocalRef<jobject> view (env->GetObjectArrayElement (args, 0));
|
|
int dims[8];
|
|
|
|
for (int i = 1; i < 9; ++i)
|
|
{
|
|
LocalRef<jobject> integer (env->GetObjectArrayElement (args, i));
|
|
dims[i - 1] = env->CallIntMethod (integer.get(), JavaInteger.intValue);
|
|
}
|
|
|
|
onLayoutChange (std::move (view), dims[0], dims[1], dims[2], dims[3],
|
|
dims[4], dims[5], dims[6], dims[7]);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// invoke base class
|
|
return AndroidInterfaceImplementer::invoke (proxy, method, args);
|
|
}
|
|
|
|
std::unique_ptr<ModalComponentManager::Callback> callback;
|
|
};
|
|
|
|
//==============================================================================
|
|
struct MainActivityWindowLayoutListener : public LayoutChangeListener
|
|
{
|
|
MainActivityWindowLayoutListener (std::function<void()>&& updateDisplaysCb)
|
|
: forceDisplayUpdate (std::move (updateDisplaysCb))
|
|
{
|
|
}
|
|
|
|
void onLayoutChange (LocalRef<jobject> /*view*/, int left, int top, int right, int bottom,
|
|
int oldLeft, int oldTop, int oldRight, int oldBottom) override
|
|
{
|
|
auto newBounds = Rectangle<int>::leftTopRightBottom (left, top, right, bottom);
|
|
auto oldBounds = Rectangle<int>::leftTopRightBottom (oldLeft, oldTop, oldRight, oldBottom);
|
|
|
|
if (newBounds != oldBounds)
|
|
{
|
|
const auto& mainDisplay = *Desktop::getInstance().getDisplays().getPrimaryDisplay();
|
|
auto userArea = (newBounds.toFloat() / mainDisplay.scale).toNearestInt();
|
|
|
|
if (userArea != mainDisplay.userArea)
|
|
forceDisplayUpdate();
|
|
}
|
|
}
|
|
|
|
std::function<void()> forceDisplayUpdate;
|
|
};
|
|
|
|
//==============================================================================
|
|
void Displays::findDisplays (float masterScale)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> usableSize (env->NewObject (AndroidPoint, AndroidPoint.create, 0, 0));
|
|
LocalRef<jstring> windowServiceString (javaString ("window"));
|
|
LocalRef<jobject> displayMetrics (env->NewObject (AndroidDisplayMetrics, AndroidDisplayMetrics.create));
|
|
LocalRef<jobject> windowManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get()));
|
|
LocalRef <jobject> display (env->CallObjectMethod (windowManager, AndroidWindowManager.getDefaultDisplay));
|
|
|
|
jmethodID getRealMetricsMethod = env->GetMethodID (AndroidDisplay, "getRealMetrics", "(Landroid/util/DisplayMetrics;)V");
|
|
|
|
if (getRealMetricsMethod != nullptr)
|
|
env->CallVoidMethod (display.get(), getRealMetricsMethod, displayMetrics.get());
|
|
else
|
|
env->CallVoidMethod (display.get(), AndroidDisplay.getMetrics, displayMetrics.get());
|
|
|
|
env->CallVoidMethod (display.get(), AndroidDisplay.getSize, usableSize.get());
|
|
|
|
Display d;
|
|
|
|
d.isMain = true;
|
|
d.scale = env->GetFloatField (displayMetrics.get(), AndroidDisplayMetrics.density);
|
|
d.dpi = (d.scale * 160.f);
|
|
d.scale *= masterScale;
|
|
|
|
d.totalArea = Rectangle<int> (env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.widthPixels),
|
|
env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.heightPixels)) / d.scale;
|
|
|
|
d.userArea = Rectangle<int> (env->GetIntField (usableSize.get(), AndroidPoint.x),
|
|
env->GetIntField (usableSize.get(), AndroidPoint.y)) / d.scale;
|
|
|
|
// unfortunately usableSize still contains the nav bar
|
|
// the best workaround is to try to get the size of the top-level view of
|
|
// the main activity
|
|
LocalRef<jobject> activity (getMainActivity());
|
|
|
|
if (activity != nullptr)
|
|
{
|
|
LocalRef<jobject> mainWindow (env->CallObjectMethod (activity.get(), AndroidActivity.getWindow));
|
|
LocalRef<jobject> decorView (env->CallObjectMethod (mainWindow.get(), AndroidWindow.getDecorView));
|
|
LocalRef<jobject> contentView (env->CallObjectMethod (decorView.get(), AndroidView.findViewById, 0x01020002 /* android.R.id.content */));
|
|
|
|
if (contentView != nullptr)
|
|
{
|
|
Rectangle<int> activityArea (env->CallIntMethod (contentView.get(), AndroidView.getLeft),
|
|
env->CallIntMethod (contentView.get(), AndroidView.getTop),
|
|
env->CallIntMethod (contentView.get(), AndroidView.getWidth),
|
|
env->CallIntMethod (contentView.get(), AndroidView.getHeight));
|
|
|
|
if (! activityArea.isEmpty())
|
|
d.userArea = activityArea / d.scale;
|
|
|
|
if (supportsDisplayCutout())
|
|
{
|
|
jmethodID getRootWindowInsetsMethodId = env->GetMethodID (AndroidView,
|
|
"getRootWindowInsets",
|
|
"()Landroid/view/WindowInsets;");
|
|
|
|
if (getRootWindowInsetsMethodId != nullptr)
|
|
{
|
|
LocalRef<jobject> insets (env->CallObjectMethod (contentView.get(), getRootWindowInsetsMethodId));
|
|
|
|
if (insets != nullptr)
|
|
{
|
|
LocalRef<jobject> displayCutout (env->CallObjectMethod (insets.get(), AndroidWindowInsets.getDisplayCutout));
|
|
|
|
if (displayCutout.get() != nullptr)
|
|
d.safeAreaInsets = androidDisplayCutoutToBorderSize (displayCutout, d.scale);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool hasAddedMainActivityListener = false;
|
|
|
|
if (! hasAddedMainActivityListener)
|
|
{
|
|
hasAddedMainActivityListener = true;
|
|
|
|
env->CallVoidMethod (contentView.get(), AndroidView.addOnLayoutChangeListener,
|
|
CreateJavaInterface (new MainActivityWindowLayoutListener ([this] { refresh(); }),
|
|
"android/view/View$OnLayoutChangeListener").get());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// the main activity may have not started yet so add an activity listener
|
|
if (AndroidComponentPeer::activityCallbackListener == nullptr)
|
|
{
|
|
LocalRef<jobject> appContext (getAppContext());
|
|
|
|
if (appContext.get() != nullptr)
|
|
{
|
|
AndroidComponentPeer::activityCallbackListener = GlobalRef (CreateJavaInterface (
|
|
new AndroidComponentPeer::StartupActivityCallbackListener,
|
|
"android/app/Application$ActivityLifecycleCallbacks"));
|
|
|
|
env->CallVoidMethod (appContext.get(),
|
|
AndroidApplication.registerActivityLifecycleCallbacks,
|
|
AndroidComponentPeer::activityCallbackListener.get());
|
|
}
|
|
}
|
|
}
|
|
|
|
displays.add (d);
|
|
}
|
|
|
|
//==============================================================================
|
|
Image juce_createIconForFile (const File& /*file*/)
|
|
{
|
|
return Image();
|
|
}
|
|
|
|
//==============================================================================
|
|
class MouseCursor::PlatformSpecificHandle
|
|
{
|
|
public:
|
|
PlatformSpecificHandle (const MouseCursor::StandardCursorType) {}
|
|
PlatformSpecificHandle (const CustomMouseCursorInfo&) {}
|
|
|
|
static void showInWindow (PlatformSpecificHandle*, ComponentPeer*) {}
|
|
};
|
|
|
|
//==============================================================================
|
|
bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& /*files*/, bool /*canMove*/,
|
|
Component* /*srcComp*/, std::function<void()> /*callback*/)
|
|
{
|
|
jassertfalse; // no such thing on Android!
|
|
return false;
|
|
}
|
|
|
|
bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/, Component* /*srcComp*/,
|
|
std::function<void()> /*callback*/)
|
|
{
|
|
jassertfalse; // no such thing on Android!
|
|
return false;
|
|
}
|
|
|
|
//==============================================================================
|
|
void LookAndFeel::playAlertSound()
|
|
{
|
|
}
|
|
|
|
//==============================================================================
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
METHOD (getText, "getText", "()Ljava/lang/CharSequence;") \
|
|
METHOD (setText, "setText", "(Ljava/lang/CharSequence;)V")
|
|
|
|
DECLARE_JNI_CLASS (AndroidClipboardManager, "android/content/ClipboardManager")
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
//==============================================================================
|
|
void SystemClipboard::copyTextToClipboard (const String& text)
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> clipboardManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, javaString ("clipboard").get()));
|
|
env->CallVoidMethod (clipboardManager.get(), AndroidClipboardManager.setText, javaString(text).get());
|
|
}
|
|
|
|
String SystemClipboard::getTextFromClipboard()
|
|
{
|
|
auto* env = getEnv();
|
|
|
|
LocalRef<jobject> clipboardManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, javaString ("clipboard").get()));
|
|
LocalRef<jobject> charSequence (env->CallObjectMethod (clipboardManager.get(), AndroidClipboardManager.getText));
|
|
|
|
if (charSequence == nullptr)
|
|
return {};
|
|
|
|
return juceString(LocalRef<jstring> ((jstring) env->CallObjectMethod(charSequence.get(), JavaCharSequence.toString)));
|
|
}
|
|
|
|
//==============================================================================
|
|
constexpr int extendedKeyModifier = 0x10000;
|
|
|
|
const int KeyPress::spaceKey = ' ';
|
|
const int KeyPress::returnKey = extendedKeyModifier + 2;
|
|
const int KeyPress::escapeKey = extendedKeyModifier + 3;
|
|
const int KeyPress::backspaceKey = extendedKeyModifier + 4;
|
|
const int KeyPress::leftKey = extendedKeyModifier + 5;
|
|
const int KeyPress::rightKey = extendedKeyModifier + 6;
|
|
const int KeyPress::upKey = extendedKeyModifier + 7;
|
|
const int KeyPress::downKey = extendedKeyModifier + 8;
|
|
const int KeyPress::pageUpKey = extendedKeyModifier + 9;
|
|
const int KeyPress::pageDownKey = extendedKeyModifier + 10;
|
|
const int KeyPress::endKey = extendedKeyModifier + 11;
|
|
const int KeyPress::homeKey = extendedKeyModifier + 12;
|
|
const int KeyPress::deleteKey = extendedKeyModifier + 13;
|
|
const int KeyPress::insertKey = extendedKeyModifier + 14;
|
|
const int KeyPress::tabKey = extendedKeyModifier + 15;
|
|
const int KeyPress::F1Key = extendedKeyModifier + 16;
|
|
const int KeyPress::F2Key = extendedKeyModifier + 17;
|
|
const int KeyPress::F3Key = extendedKeyModifier + 18;
|
|
const int KeyPress::F4Key = extendedKeyModifier + 19;
|
|
const int KeyPress::F5Key = extendedKeyModifier + 20;
|
|
const int KeyPress::F6Key = extendedKeyModifier + 21;
|
|
const int KeyPress::F7Key = extendedKeyModifier + 22;
|
|
const int KeyPress::F8Key = extendedKeyModifier + 23;
|
|
const int KeyPress::F9Key = extendedKeyModifier + 24;
|
|
const int KeyPress::F10Key = extendedKeyModifier + 25;
|
|
const int KeyPress::F11Key = extendedKeyModifier + 26;
|
|
const int KeyPress::F12Key = extendedKeyModifier + 27;
|
|
const int KeyPress::F13Key = extendedKeyModifier + 28;
|
|
const int KeyPress::F14Key = extendedKeyModifier + 29;
|
|
const int KeyPress::F15Key = extendedKeyModifier + 30;
|
|
const int KeyPress::F16Key = extendedKeyModifier + 31;
|
|
const int KeyPress::F17Key = extendedKeyModifier + 32;
|
|
const int KeyPress::F18Key = extendedKeyModifier + 33;
|
|
const int KeyPress::F19Key = extendedKeyModifier + 34;
|
|
const int KeyPress::F20Key = extendedKeyModifier + 35;
|
|
const int KeyPress::F21Key = extendedKeyModifier + 36;
|
|
const int KeyPress::F22Key = extendedKeyModifier + 37;
|
|
const int KeyPress::F23Key = extendedKeyModifier + 38;
|
|
const int KeyPress::F24Key = extendedKeyModifier + 39;
|
|
const int KeyPress::F25Key = extendedKeyModifier + 40;
|
|
const int KeyPress::F26Key = extendedKeyModifier + 41;
|
|
const int KeyPress::F27Key = extendedKeyModifier + 42;
|
|
const int KeyPress::F28Key = extendedKeyModifier + 43;
|
|
const int KeyPress::F29Key = extendedKeyModifier + 44;
|
|
const int KeyPress::F30Key = extendedKeyModifier + 45;
|
|
const int KeyPress::F31Key = extendedKeyModifier + 46;
|
|
const int KeyPress::F32Key = extendedKeyModifier + 47;
|
|
const int KeyPress::F33Key = extendedKeyModifier + 48;
|
|
const int KeyPress::F34Key = extendedKeyModifier + 49;
|
|
const int KeyPress::F35Key = extendedKeyModifier + 50;
|
|
const int KeyPress::numberPad0 = extendedKeyModifier + 51;
|
|
const int KeyPress::numberPad1 = extendedKeyModifier + 52;
|
|
const int KeyPress::numberPad2 = extendedKeyModifier + 53;
|
|
const int KeyPress::numberPad3 = extendedKeyModifier + 54;
|
|
const int KeyPress::numberPad4 = extendedKeyModifier + 55;
|
|
const int KeyPress::numberPad5 = extendedKeyModifier + 56;
|
|
const int KeyPress::numberPad6 = extendedKeyModifier + 57;
|
|
const int KeyPress::numberPad7 = extendedKeyModifier + 58;
|
|
const int KeyPress::numberPad8 = extendedKeyModifier + 59;
|
|
const int KeyPress::numberPad9 = extendedKeyModifier + 60;
|
|
const int KeyPress::numberPadAdd = extendedKeyModifier + 61;
|
|
const int KeyPress::numberPadSubtract = extendedKeyModifier + 62;
|
|
const int KeyPress::numberPadMultiply = extendedKeyModifier + 63;
|
|
const int KeyPress::numberPadDivide = extendedKeyModifier + 64;
|
|
const int KeyPress::numberPadSeparator = extendedKeyModifier + 65;
|
|
const int KeyPress::numberPadDecimalPoint = extendedKeyModifier + 66;
|
|
const int KeyPress::numberPadEquals = extendedKeyModifier + 67;
|
|
const int KeyPress::numberPadDelete = extendedKeyModifier + 68;
|
|
const int KeyPress::playKey = extendedKeyModifier + 69;
|
|
const int KeyPress::stopKey = extendedKeyModifier + 70;
|
|
const int KeyPress::fastForwardKey = extendedKeyModifier + 71;
|
|
const int KeyPress::rewindKey = extendedKeyModifier + 72;
|
|
|
|
//==============================================================================
|
|
#ifdef JUCE_PUSH_NOTIFICATIONS_ACTIVITY
|
|
struct JuceActivityNewIntentListener
|
|
{
|
|
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
|
|
CALLBACK (appNewIntent, "appNewIntent", "(Landroid/content/Intent;)V")
|
|
|
|
DECLARE_JNI_CLASS (JavaActivity, JUCE_PUSH_NOTIFICATIONS_ACTIVITY)
|
|
#undef JNI_CLASS_MEMBERS
|
|
|
|
static void JNICALL appNewIntent (JNIEnv*, jobject /*activity*/, jobject intentData)
|
|
{
|
|
juce_handleNotificationIntent (static_cast<void*> (intentData));
|
|
}
|
|
};
|
|
|
|
JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity;
|
|
#endif
|
|
|
|
} // namespace juce
|