Skip to content

Commit

Permalink
Merge branch 'jb-main' into ivan.matkov/interop-render-order
Browse files Browse the repository at this point in the history
# Conflicts:
#	compose/mpp/demo/src/uikitMain/kotlin/androidx/compose/mpp/demo/main.uikit.kt
  • Loading branch information
MatkovIvan committed Feb 29, 2024
2 parents d4c9bb6 + 9e9f8be commit ba2457b
Show file tree
Hide file tree
Showing 31 changed files with 865 additions and 190 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ internal fun findNextNonWhitespaceSymbolsSubsequenceStartOffset(
}
currentOffset = nextOffset

nextOffset = charIterator.next()

while (nextOffset != BreakIterator.DONE) {
nextOffset = charIterator.next()
if (currentText.codePointAt(currentOffset).isWhitespace() && !currentText.codePointAt(
nextOffset
).isWhitespace()
Expand All @@ -131,6 +132,8 @@ internal fun findNextNonWhitespaceSymbolsSubsequenceStartOffset(
} else {
currentOffset = nextOffset
}

nextOffset = charIterator.next()
}
return currentOffset
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,83 +43,84 @@ class CupertinoTextFieldDelegateTest {
private val defaultDensity = Density(density = 1f)
private val fontFamilyResolver = createFontFamilyResolver()

@Test
fun determineCursorDesiredOffset_tap_in_the_middle_of_the_word() {
val givenOffset = 3
val desiredOffset = 4
val result = determineCursorDesiredOffset(
fun testDetermineCursorDesiredOffset(
givenOffset: Int,
expected: Int,
sampleString: String,
cursorOffset: Int? = null
) {
val actual = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
createSimpleTextFieldValue(text = sampleText, cursorOffset = cursorOffset),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

// add the substring "<here>" at the expected and actual offsets
val expectedString = sampleString.substring(0, expected) + "<expected here($expected)>" + sampleString.substring(expected)
val actualString = sampleString.substring(0, actual) + "<got here($actual)>" + sampleString.substring(actual)

assertEquals(expected, actual, "$expectedString\n<${"=".repeat(20)}>\n$actualString")
}

@Test
fun determineCursorDesiredOffset_tap_in_the_middle_of_the_word() {
val givenOffset = 3
val desiredOffset = 4

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

// TODO: ticket for reviewing our approach will be made and covered in this test
@Test
fun determineCursorDesiredOffset_tap_before_punctuation() {
// https://github.com/JetBrains/compose-multiplatform/issues/4388
val text = "0@1"
val givenOffset = 1
val desiredOffset = 0 // TODO: define what should happen exactly, this test only assures that no crash happens

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, text)
}

@Test
fun determineCursorDesiredOffset_tap_in_the_first_half_of_word() {
val givenOffset = 23
val desiredOffset = 19
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_in_the_middle_of_the_symbols_sequence() {
val givenOffset = 34
val desiredOffset = 53
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_in_the_middle_of_the_whitespaces() {
val givenOffset = 48
val desiredOffset = 53
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_on_the_standalone_symbols_sequence() {
val givenOffset = 56
val desiredOffset = 57
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_on_the_right_edge() {
// Tap was on the first line in the given example string
val givenOffset = 57
val desiredOffset = 57
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
Expand All @@ -128,27 +129,17 @@ class CupertinoTextFieldDelegateTest {
// Tap was on the last line in the given example string
val givenOffset = 231
val desiredOffset = 231
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_on_the_left_edge() {
// Tap was on the second line in the given example string
val givenOffset = 58
val desiredOffset = 58
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
Expand All @@ -157,39 +148,24 @@ class CupertinoTextFieldDelegateTest {
// Tap was on the last line in the given example string
val givenOffset = 231
val desiredOffset = 231
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = null),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText)
}

@Test
fun determineCursorDesiredOffset_tap_on_the_caret_at_the_same_position() {
val givenOffset = 24
val desiredOffset = 24
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = 24),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText, 24)
}

@Test
fun determineCursorDesiredOffset_tap_between_two__emoji() {
val givenOffset = 218
val desiredOffset = 218
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = 24),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText, 24)
}

// TODO: remove ignore after fix two compound emojis considered as one whole word
Expand All @@ -198,13 +174,8 @@ class CupertinoTextFieldDelegateTest {
fun determineCursorDesiredOffset_tap_between_two_compound_emoji() {
val givenOffset = 96
val desiredOffset = 96
val result = determineCursorDesiredOffset(
offset = givenOffset,
createSimpleTextFieldValue(text = sampleText, cursorOffset = 24),
textLayoutResult = createSimpleTextLayoutResultProxy(sampleText),
currentText = sampleText
)
assertEquals(result, desiredOffset)

testDetermineCursorDesiredOffset(givenOffset, desiredOffset, sampleText, 24)
}

private fun createSimpleTextFieldValue(text: String, cursorOffset: Int?) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import SwiftUIInteropExample
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ExperimentalComposeApi
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.main.defaultUIKitMain
import androidx.compose.ui.platform.AccessibilityDebugLogger
import androidx.compose.ui.platform.AccessibilitySyncOptions
Expand All @@ -14,8 +15,10 @@ import bugs.IosBugs
import bugs.StartRecompositionCheck
import platform.UIKit.UIViewController

@OptIn(ExperimentalComposeApi::class)
@OptIn(ExperimentalComposeApi::class, ExperimentalComposeUiApi::class)
fun main(vararg args: String) {
androidx.compose.ui.util.enableTraceOSLog()

val arg = args.firstOrNull() ?: ""
defaultUIKitMain("ComposeDemo", ComposeUIViewController(configure = {
accessibilitySyncOptions = AccessibilitySyncOptions.WhenRequiredByAccessibilityServices(object: AccessibilityDebugLogger {
Expand Down
17 changes: 13 additions & 4 deletions compose/runtime/runtime/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,19 @@ if(AndroidXComposePlugin.isMultiplatformEnabled(project)) {
desktopMain.dependsOn(jbMain)
jsNativeMain.dependsOn(jbMain)

linuxArm64Main.dependsOn(nativeMain)
linuxArm64Test.dependsOn(nativeTest)
linuxX64Main.dependsOn(nativeMain)
linuxX64Test.dependsOn(nativeTest)
linuxMain {
dependsOn(nativeMain)
}

linuxTest {
dependsOn(nativeTest)
}

linuxArm64Main.dependsOn(linuxMain)
linuxArm64Test.dependsOn(linuxTest)
linuxX64Main.dependsOn(linuxMain)
linuxX64Test.dependsOn(linuxTest)

mingwX64Main.dependsOn(nativeMain)
mingwX64Test.dependsOn(nativeTest)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.runtime

internal actual object Trace {
/**
* Writes a trace message to indicate that a given section of code has begun.
* This call must be followed by a corresponding call to [endSection] on the same thread.
*
* @return An arbitrary token which will be supplied to the corresponding call
* to [endSection]. May be null.
*/
actual fun beginSection(name: String): Any? {
return null
}

/**
* Writes a trace message to indicate that a given section of code has ended.
* This call must be preceded by a corresponding call to [beginSection].
* Calling this method will mark the end of the most recently begun section of code, so care
* must be taken to ensure that `beginSection` / `endSection` pairs are properly nested and
* called from the same thread.
*
* @param token The instance returned from the corresponding call to [beginSection].
*/
actual fun endSection(token: Any?) {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.runtime

internal actual object Trace {
/**
* Writes a trace message to indicate that a given section of code has begun.
* This call must be followed by a corresponding call to [endSection] on the same thread.
*
* @return An arbitrary token which will be supplied to the corresponding call
* to [endSection]. May be null.
*/
actual fun beginSection(name: String): Any? {
return null
}

/**
* Writes a trace message to indicate that a given section of code has ended.
* This call must be preceded by a corresponding call to [beginSection].
* Calling this method will mark the end of the most recently begun section of code, so care
* must be taken to ensure that `beginSection` / `endSection` pairs are properly nested and
* called from the same thread.
*
* @param token The instance returned from the corresponding call to [beginSection].
*/
actual fun endSection(token: Any?) {
}
}
Loading

0 comments on commit ba2457b

Please sign in to comment.