/* ============================================================================== 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,244,59,63,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,9,120,91,197,181, 199,207,204,213,98,203,178,45,203,137,237,36,86,44,59,155,226,196,182,156,61,56,64,118,226,196,89,136,29,67,236,180,141,108,95, 219,74,228,43,69,146,55,66,31,41,80,8,75,41,75,216,67,129,54,165,27,143,165,44,31,229,81,186,1,165,101,41,180,240,160,45,180, 208,242,74,88,74,83,118,104,31,188,255,153,59,178,229,44,77,219,231,124,191,123,206,204,156,153,59,119,230,204,153,185,215,113, 151,57,228,9,207,157,79,197,179,155,15,182,174,201,59,197,108,45,216,252,173,174,187,158,170,250,166,177,120,119,238,69,203,47, 157,71,148,32,162,161,214,121,126,210,63,143,207,37,10,8,59,127,17,120,197,65,180,28,242,33,39,81,25,228,11,57,68,103,64,238, 207,37,66,17,197,242,137,14,76,39,122,19,242,242,0,209,62,112,53,184,14,124,21,220,2,30,4,63,2,15,131,71,193,227,224,41,240,43, 240,28,120,31,20,78,38,242,131,18,48,17,76,6,83,64,8,212,128,85,96,55,184,10,220,9,30,7,111,2,111,5,209,66,112,42,216,1,206, 2,87,130,219,192,207,193,123,192,19,36,154,10,182,129,207,131,59,192,43,160,188,146,168,9,164,192,141,224,73,80,88,69,116,26, 184,28,220,3,126,13,62,2,229,83,136,26,192,22,208,11,46,6,223,5,63,5,175,131,79,64,96,42,81,61,216,14,206,4,87,128,3,224,94,240, 0,248,57,120,2,60,13,158,7,47,128,87,192,235,224,16,120,15,124,4,62,1,198,52,162,28,80,0,252,96,34,8,128,42,16,2,53,96,30,56, 1,156,4,86,128,117,96,51,104,5,109,192,2,231,128,47,131,235,193,55,192,93,224,7,224,49,240,28,248,35,248,11,248,59,200,195,60, 86,130,153,96,1,88,10,218,65,55,136,130,51,193,185,224,98,176,15,220,48,221,158,251,59,193,131,224,73,240,34,248,19,248,51,240, 204,32,242,129,98,48,17,44,1,167,128,13,96,27,136,130,243,192,1,112,59,120,4,60,11,126,15,222,0,31,1,71,136,104,2,168,5,139, 193,90,112,58,136,128,29,96,16,92,0,174,5,183,129,239,131,39,192,27,224,175,224,3,240,49,200,155,137,241,3,117,224,36,176,14, 68,64,18,156,3,46,7,55,130,187,193,131,224,57,240,50,120,21,188,14,222,7,127,3,222,106,162,73,96,54,88,8,86,129,141,224,52,208, 9,250,192,94,112,5,216,15,238,1,15,129,199,192,111,192,75,224,32,56,4,222,1,31,1,57,11,237,130,137,160,10,132,64,45,88,6,90,65, 47,216,13,174,1,223,1,15,130,231,192,239,193,91,224,19,174,63,155,168,20,76,7,117,96,49,88,3,90,193,103,65,15,216,5,134,192, 185,224,10,112,29,248,30,120,0,60,12,94,3,238,26,248,28,40,6,83,64,61,88,11,218,64,47,56,27,92,11,238,5,63,1,191,4,191,3,111, 129,191,131,188,90,140,15,168,6,43,193,90,176,9,156,14,182,131,110,176,19,236,2,187,193,127,128,47,130,75,192,62,240,117,112, 7,248,49,120,26,188,8,94,2,127,4,175,130,55,192,95,192,59,224,3,224,66,12,66,72,162,60,80,2,74,201,142,83,19,192,68,48,9,148, 3,132,24,66,184,32,132,3,194,210,39,44,117,194,178,38,44,91,194,114,35,184,63,193,101,9,46,71,112,23,194,84,19,166,134,48,180, 132,97,33,60,26,225,118,84,7,194,160,30,204,1,8,151,132,48,74,243,193,2,176,80,199,205,197,224,4,208,0,150,128,19,193,73,224, 100,176,20,44,35,59,174,174,0,171,192,26,112,26,136,128,14,208,9,186,200,126,190,204,143,91,203,15,39,217,207,44,116,218,163, 117,206,231,113,144,58,223,155,209,49,0,133,89,109,249,245,152,229,232,252,2,157,95,168,203,50,250,120,173,251,244,184,114,251, 197,90,247,233,186,101,89,109,242,88,151,149,219,58,143,113,80,219,76,207,106,103,166,110,167,72,235,33,216,140,211,122,184, 220,190,39,143,249,34,221,14,235,75,117,59,53,186,157,241,122,30,214,148,219,253,225,185,216,84,110,143,225,28,109,211,168,117, 190,215,90,173,159,14,155,117,90,231,251,54,105,189,11,250,122,173,167,161,111,208,250,30,232,27,181,126,49,244,77,90,223,7, 125,179,214,247,103,229,31,200,210,111,133,222,162,245,187,179,242,127,152,165,63,154,165,63,149,213,230,243,89,249,47,65,111, 214,250,193,172,252,131,147,70,117,30,231,83,181,30,206,106,231,80,150,61,143,225,150,204,152,64,111,205,140,85,96,212,198,151, 165,151,5,108,127,156,171,199,243,116,173,7,145,191,85,235,161,44,125,30,244,54,173,47,133,222,174,245,53,208,183,105,189,5,250, 103,181,190,29,250,103,180,222,155,149,207,126,245,57,173,39,144,191,93,235,123,178,236,47,14,176,111,11,26,34,91,230,10,94, 235,211,40,73,182,188,75,73,65,247,106,121,159,150,223,211,242,126,45,255,75,219,63,162,134,33,72,46,97,203,66,193,177,98,46, 61,76,44,43,200,45,56,110,216,229,21,186,188,2,37,126,193,126,94,162,206,74,65,172,180,187,149,172,160,135,148,12,208,47,148, 156,75,255,163,100,30,29,84,126,62,157,86,67,58,17,121,254,66,188,38,93,244,101,37,199,211,13,144,185,136,92,134,146,115,233, 109,226,181,61,67,165,243,116,126,30,162,192,59,234,185,237,116,33,238,123,137,146,37,116,169,78,127,133,199,81,231,251,112,74, 187,66,167,175,81,210,160,107,201,94,139,215,105,121,189,146,130,190,166,229,1,226,181,39,105,159,146,33,250,42,241,58,155,170, 238,87,140,200,246,123,37,23,209,75,74,78,162,63,18,175,201,217,148,214,242,16,113,44,158,79,63,34,142,21,94,122,74,201,9,244, 22,251,149,238,247,4,172,108,150,229,136,142,223,85,114,38,189,175,228,73,42,152,5,176,194,13,53,47,121,116,142,146,101,116,190, 78,239,85,114,33,189,174,230,167,70,217,77,70,139,47,18,207,139,93,175,2,249,166,150,221,74,22,82,143,146,19,72,8,91,74,53, 127,211,148,125,16,51,210,171,100,45,69,149,92,74,59,148,44,166,157,90,198,148,60,153,250,148,156,64,131,90,158,169,228,2,218, 163,100,144,46,84,210,79,23,43,153,79,95,82,210,69,151,107,63,217,167,203,175,84,114,30,93,165,100,46,237,87,210,67,55,106,187, 155,148,204,161,155,149,180,231,33,136,17,186,69,203,111,104,249,77,37,39,211,183,180,252,182,206,255,142,246,195,91,181,252, 79,45,111,211,126,122,187,146,39,208,29,74,206,167,31,106,249,99,37,171,232,87,74,86,210,51,90,62,171,229,127,235,242,231,116, 250,121,45,127,173,100,1,253,70,201,233,244,91,37,103,209,11,74,158,72,191,83,210,246,159,160,246,31,78,191,172,228,28,250,131, 146,182,63,177,253,43,74,54,208,155,74,214,211,187,90,190,167,100,53,125,168,228,68,250,88,201,48,253,77,167,255,174,237,254, 87,203,79,116,249,167,122,92,124,130,247,164,82,186,154,88,46,163,31,168,117,41,233,251,74,22,81,129,224,125,199,246,211,89,88, 17,151,17,41,47,251,188,146,146,126,70,188,255,140,163,7,137,207,2,19,180,159,218,107,41,179,31,226,117,137,110,66,140,254, 178,222,144,38,235,124,222,207,56,118,115,249,125,144,183,233,242,10,93,127,86,86,253,71,81,254,35,93,30,36,123,207,228,253,238, 144,174,255,60,228,107,186,156,247,249,19,160,47,155,99,159,5,214,205,177,243,182,67,246,0,67,151,239,2,187,181,205,185,42, 223,80,250,199,181,246,153,160,93,120,40,225,227,222,180,203,60,204,101,14,90,225,123,57,235,236,115,145,95,180,116,120,104,151, 111,14,242,243,100,9,94,1,235,165,116,44,150,14,114,251,138,168,165,35,143,118,97,139,72,98,213,179,93,75,167,109,107,80,158, 99,215,166,121,180,188,223,35,23,203,63,127,106,249,120,60,220,190,208,171,14,125,255,73,117,246,249,164,10,35,154,240,13,171, 167,229,123,115,191,167,213,217,231,171,99,221,219,160,34,225,247,207,157,49,225,200,123,134,231,211,114,167,23,190,118,8,247, 228,253,193,35,172,224,52,68,39,175,8,253,233,72,235,5,202,58,244,26,199,89,135,234,79,67,157,61,119,45,9,219,142,75,74,164,58, 115,200,197,176,241,35,174,180,236,242,100,151,75,113,174,184,210,125,203,160,107,33,158,204,67,161,67,6,250,203,207,120,74, 29,199,117,140,172,63,31,207,152,70,158,159,182,249,188,234,252,149,131,20,63,235,166,58,123,31,45,118,141,163,42,233,133,29, 143,66,75,42,159,90,230,22,144,229,91,14,43,175,88,44,150,140,230,5,87,99,47,25,181,56,25,22,30,99,243,84,126,23,20,116,103,203, 101,100,56,230,111,159,72,91,82,24,7,163,132,252,198,54,104,25,251,150,116,62,250,93,139,39,241,58,184,255,14,53,14,115,105,133, 147,237,23,27,110,90,184,221,73,254,98,174,195,247,26,143,117,110,249,198,241,147,29,118,143,208,147,60,151,236,115,187,235, 236,243,90,187,191,64,63,103,21,198,48,17,156,9,15,111,247,129,226,66,245,204,66,253,35,186,168,206,254,150,144,240,241,169,174, 96,36,255,138,145,252,176,202,151,250,196,123,125,157,237,207,45,190,66,181,38,216,131,248,190,95,171,179,207,188,45,193,66, 244,145,79,214,120,206,74,31,122,61,17,119,46,24,177,251,246,49,237,38,41,187,2,120,60,63,201,157,176,123,156,253,206,237,47, 73,4,75,16,95,171,28,121,232,141,11,189,106,223,87,130,84,5,37,194,179,104,95,110,251,190,98,164,2,72,77,85,169,113,104,247,36, 204,181,215,49,209,25,71,187,152,65,232,21,142,18,212,43,162,114,135,19,121,187,176,207,122,28,139,28,159,161,10,15,167,121,63, 110,219,239,135,214,71,195,180,237,250,241,208,186,177,23,89,193,30,117,237,197,190,93,133,54,19,62,181,15,59,198,209,148,101, 243,104,186,224,211,158,21,116,160,231,45,220,39,39,214,111,208,73,220,162,27,119,245,27,150,175,95,247,228,3,242,79,159,210, 189,0,207,211,145,83,74,235,115,92,110,127,105,121,78,158,210,172,112,130,90,92,94,99,145,49,142,252,210,63,117,202,202,133,228, 119,238,242,165,48,14,94,215,122,151,195,233,31,239,87,210,10,15,209,21,14,246,52,246,110,126,42,187,247,251,40,116,115,190,35, 244,46,120,27,28,2,191,1,188,57,24,14,117,198,31,253,217,115,50,253,75,233,195,127,236,114,62,39,150,96,61,242,247,40,62,183, 72,35,116,173,152,113,181,168,189,82,200,217,55,136,234,235,5,233,232,130,53,28,182,125,166,57,232,87,113,214,161,34,31,98,75, 88,251,88,184,137,42,141,2,172,121,167,138,119,181,97,59,198,38,182,152,84,185,194,163,252,57,83,167,33,83,22,94,138,58,94,229, 131,153,178,149,35,101,75,70,202,220,234,148,135,119,12,93,54,224,58,85,69,6,110,211,169,215,253,182,176,189,102,154,151,250, 179,226,139,1,95,228,156,68,184,145,28,34,244,241,232,243,116,233,182,248,157,183,13,207,84,160,251,192,63,59,194,118,236,247, 251,10,71,214,76,58,156,89,51,227,84,159,50,249,103,232,252,45,190,241,234,254,82,175,189,61,97,251,189,210,242,173,84,125,85, 177,14,237,225,60,248,137,161,239,115,94,216,222,71,10,84,61,251,173,243,146,172,60,151,142,223,87,30,231,217,78,209,207,150, 177,255,202,113,236,215,140,140,133,221,143,111,28,165,31,183,31,37,239,222,172,60,135,190,215,247,195,246,183,0,191,224,175, 5,237,97,73,182,52,104,107,61,226,222,161,173,97,55,109,13,187,116,110,46,252,24,51,233,219,26,118,160,60,7,235,113,2,250,131, 51,159,40,210,207,203,115,242,120,216,222,171,143,222,255,150,229,120,99,216,188,137,28,167,134,62,100,223,48,148,255,61,115, 204,58,115,87,125,250,169,122,238,165,13,228,136,112,29,47,238,195,123,245,203,168,195,103,84,255,4,63,53,127,21,245,120,71,20, 210,177,8,123,120,203,205,69,152,187,114,158,59,236,22,6,113,164,243,98,173,120,114,44,95,62,100,158,235,217,47,124,74,179,4, 127,135,8,189,221,124,51,199,157,66,46,71,188,240,177,116,88,216,207,33,157,238,155,6,114,248,141,88,92,26,250,221,241,236,214, 219,118,63,63,158,221,70,219,142,95,208,132,67,125,215,224,49,224,249,224,243,19,127,111,201,69,138,199,50,191,222,254,222,226, 247,53,119,140,62,225,98,97,239,188,179,221,252,45,130,75,44,95,30,198,196,35,18,167,174,165,233,169,208,59,241,112,41,13,228, 96,247,125,203,242,45,194,204,132,248,101,65,218,99,157,249,62,196,223,23,242,53,30,148,240,253,66,245,246,119,6,191,24,185,159, 62,99,20,138,197,238,92,220,39,23,125,243,72,255,148,57,115,220,20,95,90,70,3,215,120,68,232,109,203,231,225,40,43,23,169, 211,141,173,91,193,1,220,195,163,250,151,216,132,126,25,254,162,208,139,246,156,243,189,86,214,219,223,50,198,206,185,253,100, 156,199,207,228,194,189,18,155,215,193,91,252,190,208,123,164,35,9,246,221,250,81,95,206,213,49,107,123,189,237,67,241,211,113, 18,26,200,110,117,17,238,105,175,157,56,214,14,215,41,212,62,180,11,197,229,104,168,249,105,88,27,60,186,194,80,163,43,10,133, 165,206,38,158,92,246,152,2,202,115,63,123,25,123,204,251,106,116,66,127,109,254,165,31,146,103,121,178,154,93,222,57,61,78, 158,101,72,151,251,105,246,6,156,112,138,66,47,28,223,114,163,109,249,211,227,91,110,128,165,229,227,61,218,147,231,47,90,56, 169,154,252,149,83,202,231,195,219,150,209,19,228,159,56,255,254,74,226,86,184,141,219,184,13,196,70,72,225,119,174,116,122,157, 103,111,121,100,188,21,44,182,115,74,86,186,188,174,179,187,31,41,201,180,251,188,7,51,249,18,250,113,206,56,193,47,11,247,92, 246,178,71,228,44,246,148,209,63,251,4,51,169,251,211,236,254,252,59,61,225,150,66,191,253,215,123,176,94,247,96,218,255,187, 7,235,85,15,120,109,218,95,28,217,183,56,254,213,105,201,235,148,191,117,164,148,239,73,117,86,58,88,111,127,31,69,31,113,222, 112,195,251,39,26,31,145,127,220,148,149,56,111,56,59,92,56,111,168,179,67,130,230,56,248,252,234,70,191,243,177,151,128,191, 251,253,83,170,112,218,48,248,180,145,131,19,197,122,135,52,248,148,177,75,134,222,202,151,161,55,193,235,224,32,251,123,17,250, 198,223,25,189,28,109,229,236,146,234,50,35,20,154,49,187,182,58,43,206,143,155,51,186,54,12,157,91,62,199,62,123,47,146,110, 226,17,217,9,139,2,242,47,13,253,141,159,79,191,103,204,177,191,47,241,217,141,79,217,19,229,3,234,236,86,137,187,85,224,189, 113,17,34,135,229,27,196,10,245,136,19,69,49,70,219,10,79,161,48,158,120,149,178,183,194,85,228,115,180,212,23,227,68,61,91,181, 159,41,241,75,43,92,73,62,105,151,213,240,248,190,109,255,206,140,127,50,223,113,249,59,233,135,249,52,250,65,86,255,120,15,75, 151,31,150,230,250,227,200,222,243,139,208,59,161,243,152,160,150,57,186,220,175,247,247,137,58,191,66,75,169,9,234,241,154, 69,11,85,126,141,206,175,161,5,90,10,21,67,133,254,231,164,209,179,132,212,190,145,57,67,216,186,123,228,155,180,196,232,142, 230,179,204,87,105,135,238,131,75,151,185,96,39,117,158,91,203,92,45,51,223,180,11,84,79,72,159,101,248,185,230,234,254,7,85, 254,92,237,183,115,71,122,106,215,159,167,229,124,93,79,232,243,23,203,124,125,127,214,11,71,202,11,85,255,164,182,200,60,95, 233,72,63,236,182,125,250,126,193,17,75,251,185,130,218,90,144,253,110,47,66,132,119,55,215,146,168,21,77,159,68,242,164,6,42, 89,17,239,75,196,45,211,74,111,50,205,100,107,212,28,172,221,17,25,136,144,88,77,114,117,35,137,70,146,141,51,1,212,181,36,215, 54,81,96,109,127,167,185,172,179,211,76,165,162,29,209,88,52,61,188,33,222,101,110,74,198,7,162,93,102,146,74,215,153,195,29, 241,72,178,107,101,52,213,23,77,165,154,162,169,180,105,161,64,52,145,108,66,107,77,104,166,169,137,140,38,36,112,89,203,151, 38,42,105,138,88,93,201,120,180,171,46,146,72,212,45,235,76,71,7,208,114,3,205,27,155,159,72,196,162,157,145,116,52,110,77,205, 216,52,69,187,205,206,225,206,152,185,34,18,139,117,68,58,119,166,26,104,194,177,106,101,23,117,198,45,244,44,93,183,130,229, 80,58,187,168,39,25,73,244,70,59,83,117,43,34,214,64,4,13,78,62,74,81,60,22,79,174,142,198,210,102,242,216,229,235,35,233,100, 116,168,129,102,254,195,242,49,77,149,29,105,186,41,18,181,208,191,210,35,75,54,155,157,40,40,30,41,136,167,234,150,247,91,93, 49,179,129,198,101,103,54,46,143,90,93,220,250,104,27,3,152,234,58,76,214,170,1,147,27,159,56,182,96,125,156,135,75,151,205, 28,91,198,78,50,117,163,181,58,222,217,159,90,209,27,177,122,204,204,36,103,119,101,196,52,251,145,70,50,79,73,198,251,19,13, 180,224,200,146,150,164,105,110,236,72,153,201,1,51,137,187,156,18,139,119,68,98,77,145,225,120,127,122,244,54,21,255,184,94, 3,213,143,53,136,100,251,107,221,24,239,93,31,177,34,61,92,101,206,63,93,133,29,190,209,234,142,31,209,255,227,212,201,44,146, 6,170,29,91,47,106,37,250,211,125,102,186,55,222,85,183,60,146,66,227,72,195,47,45,76,175,242,218,105,199,182,95,213,21,77,199, 147,118,119,170,143,109,118,68,147,53,199,177,93,175,244,145,209,57,185,169,51,222,87,151,236,75,197,234,118,32,0,212,29,17,54, 166,254,195,184,208,64,171,143,219,192,49,34,199,212,177,51,187,248,223,109,167,129,42,143,87,181,129,170,154,186,34,177,129, 232,206,186,136,101,197,211,42,102,212,173,178,58,99,241,84,212,234,89,17,139,164,84,48,56,210,166,17,3,155,212,229,149,71,41, 95,111,246,117,104,3,19,38,129,163,152,52,71,123,172,72,186,63,105,242,130,225,24,92,23,195,218,170,195,10,75,54,155,187,250, 77,171,19,37,69,217,37,246,237,170,178,178,26,99,49,179,39,18,179,167,97,213,80,167,153,176,39,123,234,81,108,146,61,253,125, 120,246,44,171,226,108,43,4,197,30,123,208,70,51,55,196,155,251,59,123,109,207,200,170,231,207,50,217,216,177,67,197,164,64,86, 94,179,217,217,159,132,67,28,163,74,51,98,160,213,195,30,57,154,151,52,187,99,104,7,221,24,136,219,161,187,37,146,236,49,179, 123,59,241,40,230,118,215,26,104,188,93,214,159,142,198,234,150,37,147,145,97,118,130,6,42,204,202,230,28,242,29,150,129,119, 220,150,173,155,86,145,55,219,231,72,180,146,108,109,36,103,107,35,126,160,174,37,87,235,218,198,213,171,215,146,3,178,145,175, 188,163,181,174,109,67,33,43,188,171,181,170,172,166,54,148,54,181,97,207,107,109,67,173,54,213,130,104,35,163,141,235,225, 210,196,106,19,57,219,214,178,238,128,192,62,217,198,185,216,31,93,109,77,42,219,201,18,249,237,216,148,219,27,201,223,126,164, 23,20,183,31,101,18,60,118,64,154,26,14,135,71,244,250,44,125,78,150,62,55,75,159,151,165,207,207,210,23,100,233,11,179,244, 69,208,243,108,125,117,44,210,147,162,252,49,145,144,198,69,142,18,113,201,21,81,161,136,107,178,108,138,116,152,49,202,137,232, 125,157,38,68,186,186,142,30,255,41,55,162,157,55,69,162,131,138,120,215,95,222,159,78,199,173,77,73,220,198,236,34,87,71, 28,201,62,72,181,27,146,171,83,109,228,228,238,84,251,85,23,57,113,96,136,36,41,175,147,99,84,28,219,235,178,52,39,70,182,100, 42,80,137,150,100,196,74,117,199,147,125,148,207,199,5,236,195,41,101,141,134,236,83,3,26,138,247,35,61,169,51,105,70,210,71, 198,63,142,203,228,232,138,118,119,147,48,201,105,242,134,74,193,110,236,198,71,53,77,45,31,110,225,86,115,217,66,109,176,228, 236,86,194,219,61,186,221,118,81,158,74,113,200,106,236,162,73,88,23,99,90,91,157,85,88,126,120,225,152,211,90,174,42,85,179, 48,158,213,209,147,146,62,21,81,62,178,57,4,97,90,204,36,94,144,56,201,30,71,30,214,180,145,151,87,38,63,90,75,180,207,84,141, 174,49,163,61,189,105,42,134,170,118,147,236,46,113,102,147,94,213,27,173,102,140,156,105,169,74,246,234,165,66,168,106,148, 17,48,213,224,122,71,51,80,221,141,212,230,200,224,233,25,101,43,229,177,18,143,167,185,125,242,33,209,60,12,71,233,107,198,234, 141,118,154,84,128,156,45,86,148,167,154,159,68,221,255,240,19,131,122,206,214,232,136,199,114,157,211,48,7,241,193,150,248, 78,116,175,124,36,173,140,98,38,54,151,68,44,50,188,58,25,193,19,59,80,122,186,186,110,37,209,75,133,152,37,120,29,70,115,83, 164,159,221,209,55,146,177,217,76,193,113,71,114,150,143,120,46,229,219,57,216,188,86,198,7,177,40,70,146,91,18,52,110,36,161, 54,182,53,209,174,46,244,73,223,102,125,28,247,80,117,198,100,36,35,61,153,54,85,6,154,209,109,170,227,36,21,235,132,153,100, 255,214,78,144,211,27,73,217,110,87,218,11,7,105,142,119,235,233,75,198,251,236,199,135,9,106,43,39,117,244,198,17,66,69,148, 60,152,245,141,42,42,167,200,136,246,245,81,33,191,95,68,35,177,21,145,68,106,61,134,157,242,117,70,179,25,91,101,117,141,148, 35,217,156,142,36,225,239,234,248,209,50,156,48,201,171,212,207,217,71,17,202,193,205,90,35,177,126,44,225,40,182,130,157,38, 110,150,106,180,82,233,8,182,67,148,166,54,38,34,216,27,105,66,52,213,18,199,222,180,106,40,129,101,171,92,107,149,21,193,60, 117,161,237,148,158,51,114,239,52,135,87,112,127,74,119,30,227,45,37,63,83,208,220,203,35,234,140,169,160,148,143,153,54,147, 220,189,13,56,47,144,35,102,118,167,201,21,51,173,158,116,47,185,116,87,133,69,14,139,189,193,109,153,131,27,88,201,177,50,17, 192,107,101,175,58,87,188,131,67,9,57,226,177,174,94,117,29,164,162,184,149,121,163,89,161,66,9,214,201,104,214,74,51,149,78, 198,135,217,113,70,51,181,115,101,213,204,120,215,164,209,172,230,200,128,153,25,47,140,117,218,204,182,87,131,63,182,137,230, 116,60,145,64,86,41,66,128,234,199,97,7,71,116,222,130,111,13,82,126,60,251,13,128,10,226,99,66,53,121,227,214,154,56,22,150, 10,11,148,27,183,50,142,157,175,212,245,253,177,116,52,193,83,162,146,112,206,28,222,1,84,85,88,52,71,207,48,51,177,14,45,217, 83,171,90,114,197,237,9,119,219,242,115,168,215,143,224,157,70,108,114,38,148,99,123,18,145,36,44,85,48,200,79,140,113,111,103, 66,5,239,64,34,158,232,143,29,51,92,139,36,185,147,246,59,37,85,37,205,30,246,141,228,177,95,55,169,60,105,246,225,81,237,199, 223,104,29,182,87,57,147,42,18,26,41,51,77,5,41,142,153,35,47,123,228,69,90,13,34,123,42,149,102,167,26,237,135,86,171,135,171, 101,157,201,85,181,166,140,71,82,25,82,71,125,27,163,241,169,76,40,220,18,205,138,109,147,142,154,205,135,225,8,54,193,148,29, 28,149,3,231,167,198,4,69,79,38,25,179,251,116,90,52,22,219,16,79,43,119,240,166,176,96,50,1,10,21,145,26,137,30,48,102,71,179, 251,133,163,30,138,225,101,163,201,178,148,221,155,198,209,123,233,39,117,168,237,197,145,238,141,166,200,197,215,169,97,45,235, 145,203,155,141,129,150,160,242,64,228,244,167,187,23,169,8,47,6,200,57,160,162,134,91,137,141,221,228,224,183,28,42,228,107, 182,115,229,114,70,75,124,75,202,36,223,192,17,123,194,64,52,153,238,143,196,244,190,229,25,24,29,10,49,72,98,136,228,80,24,212, 131,57,96,46,152,71,98,152,110,119,72,186,92,186,11,218,106,232,94,135,216,39,221,1,153,247,180,28,10,236,48,232,23,162,236, 15,235,232,167,14,249,69,137,252,2,122,194,33,46,20,238,192,99,242,140,192,219,6,93,44,170,107,46,119,18,189,224,48,246,201,228, 128,187,224,39,21,244,103,41,8,77,45,161,119,37,185,103,183,27,242,45,145,127,129,33,94,23,197,181,67,31,24,244,69,33,119, 44,17,69,69,209,37,50,21,112,210,18,145,231,66,125,105,119,64,46,216,42,215,13,214,208,175,165,184,134,239,118,184,252,3,154, 44,184,155,94,181,197,18,227,108,241,170,184,71,184,103,203,167,169,65,238,149,131,242,41,49,56,36,159,223,253,210,94,33,157, 158,101,53,75,106,151,44,57,169,221,160,179,60,103,26,98,143,152,191,228,150,74,195,120,76,132,69,233,248,240,100,67,62,42,164, 40,42,117,74,121,42,122,226,20,78,195,229,145,179,14,56,61,46,114,9,151,116,25,213,213,114,96,182,83,86,203,212,108,90,104, 247,96,161,188,70,94,171,20,7,43,215,201,235,199,230,142,40,206,76,241,126,78,238,231,30,95,88,78,3,16,235,232,45,67,94,45,111, 224,252,55,28,200,160,189,60,98,244,138,193,215,125,14,153,62,3,242,18,135,72,67,124,104,176,64,205,27,85,250,162,114,218,171, 13,174,179,13,206,182,197,245,134,56,136,121,89,183,174,166,109,93,91,45,157,37,118,171,90,247,27,242,75,242,187,2,21,39,213, 208,159,132,56,159,7,171,236,19,185,51,176,206,200,73,202,38,195,117,129,52,100,94,175,40,46,148,131,1,92,131,172,13,5,232,235, 82,62,196,214,129,243,165,63,32,19,1,89,216,32,251,15,108,147,195,107,233,81,105,60,36,206,81,133,50,255,60,57,16,184,170,125, 199,249,240,5,41,219,232,65,93,173,224,252,96,249,85,116,151,225,60,243,103,226,66,249,182,24,70,23,191,109,56,174,146,183,136, 95,137,95,162,252,196,243,219,232,106,97,155,202,71,41,32,239,63,11,93,202,229,46,185,185,75,63,161,173,114,233,108,116,38,108, 227,107,50,242,30,23,242,196,37,134,247,77,177,224,68,33,12,207,189,66,214,136,242,252,147,157,30,167,183,222,153,183,195,229, 169,21,197,37,114,119,195,18,151,247,68,17,24,207,249,99,51,229,106,17,40,160,159,25,226,74,140,125,208,16,231,202,176,240,151, 72,239,108,217,23,168,48,232,60,81,51,217,73,74,153,53,197,73,47,135,171,233,97,67,60,137,46,210,107,134,24,116,23,68,203,233, 2,41,46,66,229,135,12,186,79,4,106,119,172,27,218,62,225,124,146,149,226,75,178,44,40,171,164,229,240,63,46,74,243,229,84,100, 148,187,75,69,233,210,210,220,210,149,165,178,180,186,212,97,91,85,40,43,9,171,83,70,236,11,228,20,182,23,101,147,109,69,150, 5,202,42,72,10,135,231,210,160,240,79,253,194,30,199,129,242,105,226,161,114,33,14,4,132,248,33,120,96,50,138,133,87,138,75,131, 51,247,236,113,236,173,168,22,183,86,144,225,162,2,174,33,252,179,80,231,80,80,236,13,222,84,137,203,125,124,121,170,82,200, 131,224,210,42,114,149,78,42,242,195,247,253,246,191,122,24,223,87,5,147,115,167,227,178,159,47,119,243,229,41,190,188,201,151, 189,51,28,103,75,18,128,165,91,235,255,12,227,128,7,44,18,7,102,8,241,12,56,52,3,3,31,26,47,246,135,132,184,27,60,15,222,4, 123,102,10,113,7,120,9,188,11,246,86,11,177,31,28,2,7,102,193,14,60,80,35,196,173,181,66,92,83,39,28,207,128,131,117,176,9,59, 197,43,243,96,55,95,138,115,23,72,241,205,5,250,251,114,246,239,10,88,102,254,78,135,191,67,103,254,86,135,191,79,103,254,94, 39,243,187,78,254,155,29,254,54,157,249,187,29,23,141,254,237,142,225,179,203,248,119,17,34,104,255,142,103,106,1,108,130,182, 13,255,31,54,225,179,127,183,195,255,111,77,6,237,251,242,223,250,24,218,158,255,239,152,35,104,255,142,225,132,57,246,47,29, 184,174,250,191,111,62,187,175,252,119,69,255,7,207,224,91,10,144,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, "", "(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, "", "(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 androidDisplayCutoutToBorderSize (LocalRef 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) }; } //============================================================================== 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 (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 (env->NewLocalRef (static_cast (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 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 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 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 activity (getCurrentActivity()); if (activity == nullptr) activity = getMainActivity(); viewGroup = GlobalRef (LocalRef (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& 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 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 getBounds() const override { Rectangle 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 getScreenPosition() const { auto* env = getEnv(); LocalRef position (env->NewIntArray (2)); env->CallVoidMethod (view.get(), AndroidView.getLocationOnScreen, position.get()); jint* const screenPosition = env->GetIntArrayElements (position.get(), nullptr); Point pos (screenPosition[0], screenPosition[1]); env->ReleaseIntArrayElements (position.get(), screenPosition, 0); return pos; } Point localToGlobal (Point relativePosition) override { return relativePosition + (getScreenPosition().toFloat() / scale); } using ComponentPeer::localToGlobal; Point globalToLocal (Point 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 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)); } BorderSize 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 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::invalidPressure, MouseInputSource::invalidOrientation, time, {}, index); if (isValidPeer (this)) handleMouseDragCallback (index, sysPos, time); } void handleMouseDragCallback (int index, Point 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::invalidPressure, MouseInputSource::invalidOrientation, time, {}, index); } void handleMouseUpCallback (int index, Point 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::invalidPressure, MouseInputSource::invalidOrientation, time, {}, index); } void handleKeyDownCallback (int k, int kc) { handleKeyPress (k, static_cast (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 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 (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, 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::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) 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& 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 lastMousePos; static int64 touchesDown; //============================================================================== struct StartupActivityCallbackListener : public ActivityLifecycleCallbacks { void onActivityStarted (jobject /*activity*/) override { auto* env = getEnv(); LocalRef 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, "", "(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 (handleKeyDownJni, "handleKeyDown", "(JII)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 (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 (host)) myself->handleMouseDownCallback (i, Point ((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 (host)) myself->handleMouseDragCallback (i, Point ((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 (host)) myself->handleMouseUpCallback (i, Point ((float) x, (float) y), (int64) time); } static void JNICALL viewSizeChangedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleMovedOrResized(); } static void JNICALL focusChangedJni (JNIEnv*, jobject /*view*/, jlong host, jboolean hasFocus) { if (auto* myself = reinterpret_cast (host)) myself->handleFocusChangeCallback (hasFocus); } static void JNICALL handleKeyDownJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyDownCallback ((int) k, (int) kc); } static void JNICALL handleKeyUpJni (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyUpCallback ((int) k, (int) kc); } static void JNICALL handleBackButtonJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleBackButtonCallback(); } static void JNICALL handleKeyboardHiddenJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleKeyboardHiddenCallback(); } static void JNICALL handleAppPausedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleAppPausedCallback(); } static void JNICALL handleAppResumedJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) myself->handleAppResumedCallback(); } static jboolean JNICALL populateAccessibilityNodeInfoJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jobject info) { if (auto* myself = reinterpret_cast (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 (host)) return myself->handlePerformActionCallback (virtualViewId, action, arguments); return false; } static jobject JNICALL getInputFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) return myself->getInputFocusViewIdCallback(); return nullptr; } static jobject JNICALL getAccessibilityFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host) { if (auto* myself = reinterpret_cast (host)) return myself->getAccessibilityFocusViewIdCallback(); return nullptr; } //============================================================================== struct ViewWindowInsetsListener : public juce::AndroidInterfaceImplementer { jobject onApplyWindowInsets (LocalRef v, LocalRef insets) { auto* env = getEnv(); LocalRef 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 windowView (env->GetObjectArrayElement (args, 0)); LocalRef 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 (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 createType() const override { return std::make_unique(); } std::unique_ptr createLowLevelContext() override { return std::make_unique (Image (this)); } void initialiseBitmapData (Image::BitmapData& bm, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) override { bm.lineStride = width * static_cast (sizeof (jint)); bm.pixelStride = static_cast (sizeof (jint)); bm.pixelFormat = Image::ARGB; bm.data = (uint8*) (data + x + y * width); } ImagePixelData::Ptr clone() override { auto s = new PreallocatedImage (width, height, nullptr, hasAlpha); s->allocatedData.malloc (sizeof (jint) * static_cast (width * height)); s->data = s->allocatedData; memcpy (s->data, data, sizeof (jint) * static_cast (width * height)); return s; } private: jint* data; HeapBlock 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 static void callOnMessageThread (Callback&& callback) { if (MessageManager::getInstance()->isThisTheMessageThread()) callback(); else MessageManager::callAsync (std::forward (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 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 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 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 resources (env->CallObjectMethod (getAppContext().get(), AndroidContext.getResources)); const LocalRef 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::createNativeDarkModeChangeDetectorImpl() { return std::make_unique(); } 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 windowServiceString (javaString ("window")); LocalRef windowManager = LocalRef (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get())); if (windowManager.get() != nullptr) { LocalRef display = LocalRef (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 MouseInputSource::getCurrentRawMousePosition() { return AndroidComponentPeer::lastMousePos; } void MouseInputSource::setRawMousePosition (Point) { // not needed } //============================================================================== bool KeyPress::isKeyCurrentlyDown (int /*keyCode*/) { // TODO return false; } JUCE_API void JUCE_CALLTYPE Process::hide() { auto* env = getEnv(); LocalRef currentActivity (getCurrentActivity().get()); if (env->CallBooleanMethod (currentActivity.get(), AndroidActivity.moveTaskToBack, true) == 0) { GlobalRef intent (LocalRef (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, "", "(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 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 callback; int result; }; //============================================================================== static void createAndroidDialog (const MessageBoxOptions& opts, ModalComponentManager::Callback* callbackIn, AlertWindowMappings::MapFn mapFn) { auto* env = getEnv(); LocalRef builder (env->NewObject (AndroidAlertDialogBuilder, AndroidAlertDialogBuilder.construct, getMainActivity().get())); builder = LocalRef (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setTitle, javaString (opts.getTitle()).get())); builder = LocalRef (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setMessage, javaString (opts.getMessage()).get())); builder = LocalRef (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setCancelable, true)); std::shared_ptr sharedCallback (AlertWindowMappings::getWrappedCallback (callbackIn, mapFn)); builder = LocalRef (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setOnCancelListener, CreateJavaInterface (new DialogListener (sharedCallback, 0), "android/content/DialogInterface$OnCancelListener").get())); builder = LocalRef (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 (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 (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.setNeutralButton, javaString (opts.getButtonText (2)).get(), CreateJavaInterface (new DialogListener (sharedCallback, 2), "android/content/DialogInterface$OnClickListener").get())); LocalRef dialog (env->CallObjectMethod (builder.get(), AndroidAlertDialogBuilder.create)); LocalRef 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 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 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 activity (getMainActivity()); if (activity != nullptr) { auto* env = getEnv(); LocalRef 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 (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 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, "", "()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 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 view (env->GetObjectArrayElement (args, 0)); int dims[8]; for (int i = 1; i < 9; ++i) { LocalRef 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 callback; }; //============================================================================== struct MainActivityWindowLayoutListener : public LayoutChangeListener { MainActivityWindowLayoutListener (std::function&& updateDisplaysCb) : forceDisplayUpdate (std::move (updateDisplaysCb)) { } void onLayoutChange (LocalRef /*view*/, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) override { auto newBounds = Rectangle::leftTopRightBottom (left, top, right, bottom); auto oldBounds = Rectangle::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 forceDisplayUpdate; }; //============================================================================== void Displays::findDisplays (float masterScale) { auto* env = getEnv(); LocalRef usableSize (env->NewObject (AndroidPoint, AndroidPoint.create, 0, 0)); LocalRef windowServiceString (javaString ("window")); LocalRef displayMetrics (env->NewObject (AndroidDisplayMetrics, AndroidDisplayMetrics.create)); LocalRef windowManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get())); LocalRef 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 (env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.widthPixels), env->GetIntField (displayMetrics.get(), AndroidDisplayMetrics.heightPixels)) / d.scale; d.userArea = Rectangle (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 activity (getMainActivity()); if (activity != nullptr) { LocalRef mainWindow (env->CallObjectMethod (activity.get(), AndroidActivity.getWindow)); LocalRef decorView (env->CallObjectMethod (mainWindow.get(), AndroidWindow.getDecorView)); LocalRef contentView (env->CallObjectMethod (decorView.get(), AndroidView.findViewById, 0x01020002 /* android.R.id.content */)); if (contentView != nullptr) { Rectangle 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 insets (env->CallObjectMethod (contentView.get(), getRootWindowInsetsMethodId)); if (insets != nullptr) { LocalRef 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 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(); } //============================================================================== void* CustomMouseCursorInfo::create() const { return nullptr; } void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType) { return nullptr; } void MouseCursor::deleteMouseCursor (void* /*cursorHandle*/, bool /*isStandard*/) {} //============================================================================== void MouseCursor::showInWindow (ComponentPeer*) const {} //============================================================================== bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& /*files*/, bool /*canMove*/, Component* /*srcComp*/, std::function /*callback*/) { jassertfalse; // no such thing on Android! return false; } bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/, Component* /*srcComp*/, std::function /*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 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 clipboardManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, javaString ("clipboard").get())); LocalRef charSequence (env->CallObjectMethod (clipboardManager.get(), AndroidClipboardManager.getText)); if (charSequence == nullptr) return {}; return juceString(LocalRef ((jstring) env->CallObjectMethod(charSequence.get(), JavaCharSequence.toString))); } //============================================================================== const int extendedKeyModifier = 0x10000; const int KeyPress::spaceKey = ' '; const int KeyPress::returnKey = 66; const int KeyPress::escapeKey = 4; const int KeyPress::backspaceKey = 67; const int KeyPress::leftKey = extendedKeyModifier + 1; const int KeyPress::rightKey = extendedKeyModifier + 2; const int KeyPress::upKey = extendedKeyModifier + 3; const int KeyPress::downKey = extendedKeyModifier + 4; const int KeyPress::pageUpKey = extendedKeyModifier + 5; const int KeyPress::pageDownKey = extendedKeyModifier + 6; const int KeyPress::endKey = extendedKeyModifier + 7; const int KeyPress::homeKey = extendedKeyModifier + 8; const int KeyPress::deleteKey = extendedKeyModifier + 9; const int KeyPress::insertKey = -1; const int KeyPress::tabKey = 61; const int KeyPress::F1Key = extendedKeyModifier + 10; const int KeyPress::F2Key = extendedKeyModifier + 11; const int KeyPress::F3Key = extendedKeyModifier + 12; const int KeyPress::F4Key = extendedKeyModifier + 13; const int KeyPress::F5Key = extendedKeyModifier + 14; const int KeyPress::F6Key = extendedKeyModifier + 16; const int KeyPress::F7Key = extendedKeyModifier + 17; const int KeyPress::F8Key = extendedKeyModifier + 18; const int KeyPress::F9Key = extendedKeyModifier + 19; const int KeyPress::F10Key = extendedKeyModifier + 20; const int KeyPress::F11Key = extendedKeyModifier + 21; const int KeyPress::F12Key = extendedKeyModifier + 22; const int KeyPress::F13Key = extendedKeyModifier + 23; const int KeyPress::F14Key = extendedKeyModifier + 24; const int KeyPress::F15Key = extendedKeyModifier + 25; const int KeyPress::F16Key = extendedKeyModifier + 26; const int KeyPress::F17Key = extendedKeyModifier + 50; const int KeyPress::F18Key = extendedKeyModifier + 51; const int KeyPress::F19Key = extendedKeyModifier + 52; const int KeyPress::F20Key = extendedKeyModifier + 53; const int KeyPress::F21Key = extendedKeyModifier + 54; const int KeyPress::F22Key = extendedKeyModifier + 55; const int KeyPress::F23Key = extendedKeyModifier + 56; const int KeyPress::F24Key = extendedKeyModifier + 57; const int KeyPress::F25Key = extendedKeyModifier + 58; const int KeyPress::F26Key = extendedKeyModifier + 59; const int KeyPress::F27Key = extendedKeyModifier + 60; const int KeyPress::F28Key = extendedKeyModifier + 61; const int KeyPress::F29Key = extendedKeyModifier + 62; const int KeyPress::F30Key = extendedKeyModifier + 63; const int KeyPress::F31Key = extendedKeyModifier + 64; const int KeyPress::F32Key = extendedKeyModifier + 65; const int KeyPress::F33Key = extendedKeyModifier + 66; const int KeyPress::F34Key = extendedKeyModifier + 67; const int KeyPress::F35Key = extendedKeyModifier + 68; const int KeyPress::numberPad0 = extendedKeyModifier + 27; const int KeyPress::numberPad1 = extendedKeyModifier + 28; const int KeyPress::numberPad2 = extendedKeyModifier + 29; const int KeyPress::numberPad3 = extendedKeyModifier + 30; const int KeyPress::numberPad4 = extendedKeyModifier + 31; const int KeyPress::numberPad5 = extendedKeyModifier + 32; const int KeyPress::numberPad6 = extendedKeyModifier + 33; const int KeyPress::numberPad7 = extendedKeyModifier + 34; const int KeyPress::numberPad8 = extendedKeyModifier + 35; const int KeyPress::numberPad9 = extendedKeyModifier + 36; const int KeyPress::numberPadAdd = extendedKeyModifier + 37; const int KeyPress::numberPadSubtract = extendedKeyModifier + 38; const int KeyPress::numberPadMultiply = extendedKeyModifier + 39; const int KeyPress::numberPadDivide = extendedKeyModifier + 40; const int KeyPress::numberPadSeparator = extendedKeyModifier + 41; const int KeyPress::numberPadDecimalPoint = extendedKeyModifier + 42; const int KeyPress::numberPadEquals = extendedKeyModifier + 43; const int KeyPress::numberPadDelete = extendedKeyModifier + 44; const int KeyPress::playKey = extendedKeyModifier + 45; const int KeyPress::stopKey = extendedKeyModifier + 46; const int KeyPress::fastForwardKey = extendedKeyModifier + 47; const int KeyPress::rewindKey = extendedKeyModifier + 48; //============================================================================== #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 (intentData)); } }; JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity; #endif } // namespace juce