Loading packages/SystemUI/res/drawable/ic_screen_capture_camera.xml +5 −5 Original line number Diff line number Diff line Loading @@ -15,12 +15,12 @@ Copyright (C) 2025 The Android Open Source Project --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="16dp" android:height="14dp" android:viewportWidth="16" android:viewportHeight="14" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20" android:tint="?android:attr/colorControlNormal"> <path android:fillColor="#FFFFFFFF" android:pathData="M3 14C2.16667 14 1.45833 13.7083 0.875 13.125C0.291667 12.5417 1.78814e-07 11.8333 1.78814e-07 11V4.5C1.78814e-07 3.66667 0.291667 2.95833 0.875 2.375C1.45833 1.79167 2.16667 1.5 3 1.5H4.5L6 -4.76837e-07H10L11.5 1.5H13C13.8333 1.5 14.5417 1.79167 15.125 2.375C15.7083 2.95833 16 3.66667 16 4.5V11C16 11.8333 15.7083 12.5417 15.125 13.125C14.5417 13.7083 13.8333 14 13 14H3ZM8 10.625C8.77778 10.625 9.4375 10.3542 9.97917 9.8125C10.5208 9.25694 10.7917 8.59028 10.7917 7.8125C10.7917 7.03472 10.5208 6.375 9.97917 5.83333C9.4375 5.29167 8.77778 5.02083 8 5.02083C7.22222 5.02083 6.5625 5.29167 6.02083 5.83333C5.47917 6.375 5.20833 7.03472 5.20833 7.8125C5.20833 8.59028 5.47917 9.25694 6.02083 9.8125C6.5625 10.3542 7.22222 10.625 8 10.625Z" /> android:pathData="M5 17C4.16667 17 3.45833 16.7083 2.875 16.125C2.29167 15.5417 2 14.8333 2 14V7.5C2 6.66667 2.29167 5.95833 2.875 5.375C3.45833 4.79167 4.16667 4.5 5 4.5H6.5L8 3H12L13.5 4.5H15C15.8333 4.5 16.5417 4.79167 17.125 5.375C17.7083 5.95833 18 6.66667 18 7.5V14C18 14.8333 17.7083 15.5417 17.125 16.125C16.5417 16.7083 15.8333 17 15 17H5ZM10 13.625C10.7778 13.625 11.4375 13.3542 11.9792 12.8125C12.5208 12.2569 12.7917 11.5903 12.7917 10.8125C12.7917 10.0347 12.5208 9.375 11.9792 8.83333C11.4375 8.29167 10.7778 8.02083 10 8.02083C9.22222 8.02083 8.5625 8.29167 8.02083 8.83333C7.47917 9.375 7.20833 10.0347 7.20833 10.8125C7.20833 11.5903 7.47917 12.2569 8.02083 12.8125C8.5625 13.3542 9.22222 13.625 10 13.625Z" /> </vector> packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -351,6 +351,8 @@ <!-- Header for the carousel to choose an app for screen recording. [CHAR LIMIT=50] --> <string name="screen_record_capture_target_choose_app">Choose an app to record</string> <!-- Button text for taking a fullscreen screenshot [CHAR LIMIT=35] --> <string name="screen_capture_fullscreen_screenshot_button">Capture entire screen</string> <!-- Button text in the region select box for triggering a screenshot of the selected area. [CHAR LIMIT=35] --> <string name="screen_capture_region_selection_button">Capture selected area</string> <!-- Button text in the toolbar for choosing the screenshot type. [CHAR LIMIT=35] --> Loading packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/compose/PreCaptureUI.kt +47 −3 Original line number Diff line number Diff line Loading @@ -16,14 +16,58 @@ package com.android.systemui.screencapture.record.largescreen.ui.compose import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import com.android.systemui.res.R import com.android.systemui.screencapture.common.ui.compose.PrimaryButton import com.android.systemui.screencapture.record.largescreen.ui.viewmodel.PreCaptureViewModel import com.android.systemui.screencapture.record.largescreen.ui.viewmodel.ScreenCaptureRegion /** Main component for the pre-capture UI. */ @Composable fun PreCaptureUI(viewModel: PreCaptureViewModel) { PreCaptureToolbar(viewModel = viewModel, expanded = true, onCloseClick = {}) Box(modifier = Modifier.fillMaxSize()) { Box( modifier = Modifier.fillMaxWidth() .wrapContentSize(Alignment.TopCenter) .padding(top = 36.dp) .zIndex(1f) ) { PreCaptureToolbar( viewModel = viewModel, expanded = true, onCloseClick = { // TODO(b/424792547) Close the activity. }, ) } // TODO(b/423967051) If the capture region is FULLSCREEN, show centered capture button. when (viewModel.captureRegion) { ScreenCaptureRegion.FULLSCREEN -> { Box( modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.Center).zIndex(0f) ) { PrimaryButton( icon = viewModel.icons?.screenshotButton, text = stringResource(R.string.screen_capture_fullscreen_screenshot_button), onClick = { viewModel.takeFullscreenScreenshot() }, ) } } ScreenCaptureRegion.PARTIAL -> { // TODO(b/422834671) If the capture region is PARTIAL, add region box here. } ScreenCaptureRegion.APP_WINDOW -> {} } } } packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/viewmodel/PreCaptureViewModel.kt +9 −3 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.systemui.screencapture.record.largescreen.ui.viewmodel import android.content.Context import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.lifecycle.HydratedActivatable import com.android.systemui.res.R import com.android.systemui.screencapture.record.largescreen.domain.interactor.ScreenCaptureRecordLargeScreenFeaturesInteractor import com.android.systemui.screencapture.record.largescreen.domain.interactor.ScreenshotInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine Loading @@ -45,6 +47,7 @@ class PreCaptureViewModel @AssistedInject constructor( @Application private val applicationContext: Context, @Background private val backgroundScope: CoroutineScope, private val iconProvider: ScreenCaptureIconProvider, private val screenshotInteractor: ScreenshotInteractor, private val featuresInteractor: ScreenCaptureRecordLargeScreenFeaturesInteractor, Loading Loading @@ -85,11 +88,14 @@ constructor( captureRegionSource.value = selectedRegion } suspend fun takeFullscreenScreenshot() { fun takeFullscreenScreenshot() { require(captureTypeSource.value == ScreenCaptureType.SCREENSHOT) require(captureRegionSource.value == ScreenCaptureRegion.FULLSCREEN) backgroundScope.launch { // TODO(b/430361425) Pass in current display as argument. screenshotInteractor.takeFullscreenScreenshot() } // TODO(b/427500006) Close the window after requesting a fullscreen screenshot. } Loading @@ -110,7 +116,7 @@ constructor( onClick = { updateCaptureType(ScreenCaptureType.SCREEN_RECORD) }, ), RadioButtonGroupItemViewModel( icon = icons?.screenshot, icon = icons?.screenshotToolbar, label = applicationContext.getString(R.string.screen_capture_toolbar_capture_button), isSelected = selectedType == ScreenCaptureType.SCREENSHOT, Loading packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/viewmodel/ScreenCaptureIconProvider.kt +4 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext data class ScreenCaptureIcons( val screenshot: Icon, val screenshotToolbar: Icon, val screenshotButton: Icon, val screenRecord: Icon, val fullscreen: Icon, val region: Icon, Loading @@ -55,7 +56,8 @@ constructor( flow { emit( ScreenCaptureIcons( screenshot = loadIcon(R.drawable.ic_screen_capture_camera), screenshotToolbar = loadIcon(R.drawable.ic_screen_capture_camera), screenshotButton = loadIcon(R.drawable.ic_screen_capture_camera), screenRecord = loadIcon(R.drawable.ic_screenrecord), fullscreen = loadIcon(R.drawable.ic_screen_capture_fullscreen), region = loadIcon(R.drawable.ic_screen_capture_region), Loading Loading
packages/SystemUI/res/drawable/ic_screen_capture_camera.xml +5 −5 Original line number Diff line number Diff line Loading @@ -15,12 +15,12 @@ Copyright (C) 2025 The Android Open Source Project --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="16dp" android:height="14dp" android:viewportWidth="16" android:viewportHeight="14" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20" android:tint="?android:attr/colorControlNormal"> <path android:fillColor="#FFFFFFFF" android:pathData="M3 14C2.16667 14 1.45833 13.7083 0.875 13.125C0.291667 12.5417 1.78814e-07 11.8333 1.78814e-07 11V4.5C1.78814e-07 3.66667 0.291667 2.95833 0.875 2.375C1.45833 1.79167 2.16667 1.5 3 1.5H4.5L6 -4.76837e-07H10L11.5 1.5H13C13.8333 1.5 14.5417 1.79167 15.125 2.375C15.7083 2.95833 16 3.66667 16 4.5V11C16 11.8333 15.7083 12.5417 15.125 13.125C14.5417 13.7083 13.8333 14 13 14H3ZM8 10.625C8.77778 10.625 9.4375 10.3542 9.97917 9.8125C10.5208 9.25694 10.7917 8.59028 10.7917 7.8125C10.7917 7.03472 10.5208 6.375 9.97917 5.83333C9.4375 5.29167 8.77778 5.02083 8 5.02083C7.22222 5.02083 6.5625 5.29167 6.02083 5.83333C5.47917 6.375 5.20833 7.03472 5.20833 7.8125C5.20833 8.59028 5.47917 9.25694 6.02083 9.8125C6.5625 10.3542 7.22222 10.625 8 10.625Z" /> android:pathData="M5 17C4.16667 17 3.45833 16.7083 2.875 16.125C2.29167 15.5417 2 14.8333 2 14V7.5C2 6.66667 2.29167 5.95833 2.875 5.375C3.45833 4.79167 4.16667 4.5 5 4.5H6.5L8 3H12L13.5 4.5H15C15.8333 4.5 16.5417 4.79167 17.125 5.375C17.7083 5.95833 18 6.66667 18 7.5V14C18 14.8333 17.7083 15.5417 17.125 16.125C16.5417 16.7083 15.8333 17 15 17H5ZM10 13.625C10.7778 13.625 11.4375 13.3542 11.9792 12.8125C12.5208 12.2569 12.7917 11.5903 12.7917 10.8125C12.7917 10.0347 12.5208 9.375 11.9792 8.83333C11.4375 8.29167 10.7778 8.02083 10 8.02083C9.22222 8.02083 8.5625 8.29167 8.02083 8.83333C7.47917 9.375 7.20833 10.0347 7.20833 10.8125C7.20833 11.5903 7.47917 12.2569 8.02083 12.8125C8.5625 13.3542 9.22222 13.625 10 13.625Z" /> </vector>
packages/SystemUI/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -351,6 +351,8 @@ <!-- Header for the carousel to choose an app for screen recording. [CHAR LIMIT=50] --> <string name="screen_record_capture_target_choose_app">Choose an app to record</string> <!-- Button text for taking a fullscreen screenshot [CHAR LIMIT=35] --> <string name="screen_capture_fullscreen_screenshot_button">Capture entire screen</string> <!-- Button text in the region select box for triggering a screenshot of the selected area. [CHAR LIMIT=35] --> <string name="screen_capture_region_selection_button">Capture selected area</string> <!-- Button text in the toolbar for choosing the screenshot type. [CHAR LIMIT=35] --> Loading
packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/compose/PreCaptureUI.kt +47 −3 Original line number Diff line number Diff line Loading @@ -16,14 +16,58 @@ package com.android.systemui.screencapture.record.largescreen.ui.compose import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex import com.android.systemui.res.R import com.android.systemui.screencapture.common.ui.compose.PrimaryButton import com.android.systemui.screencapture.record.largescreen.ui.viewmodel.PreCaptureViewModel import com.android.systemui.screencapture.record.largescreen.ui.viewmodel.ScreenCaptureRegion /** Main component for the pre-capture UI. */ @Composable fun PreCaptureUI(viewModel: PreCaptureViewModel) { PreCaptureToolbar(viewModel = viewModel, expanded = true, onCloseClick = {}) Box(modifier = Modifier.fillMaxSize()) { Box( modifier = Modifier.fillMaxWidth() .wrapContentSize(Alignment.TopCenter) .padding(top = 36.dp) .zIndex(1f) ) { PreCaptureToolbar( viewModel = viewModel, expanded = true, onCloseClick = { // TODO(b/424792547) Close the activity. }, ) } // TODO(b/423967051) If the capture region is FULLSCREEN, show centered capture button. when (viewModel.captureRegion) { ScreenCaptureRegion.FULLSCREEN -> { Box( modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.Center).zIndex(0f) ) { PrimaryButton( icon = viewModel.icons?.screenshotButton, text = stringResource(R.string.screen_capture_fullscreen_screenshot_button), onClick = { viewModel.takeFullscreenScreenshot() }, ) } } ScreenCaptureRegion.PARTIAL -> { // TODO(b/422834671) If the capture region is PARTIAL, add region box here. } ScreenCaptureRegion.APP_WINDOW -> {} } } }
packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/viewmodel/PreCaptureViewModel.kt +9 −3 Original line number Diff line number Diff line Loading @@ -18,12 +18,14 @@ package com.android.systemui.screencapture.record.largescreen.ui.viewmodel import android.content.Context import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.lifecycle.HydratedActivatable import com.android.systemui.res.R import com.android.systemui.screencapture.record.largescreen.domain.interactor.ScreenCaptureRecordLargeScreenFeaturesInteractor import com.android.systemui.screencapture.record.largescreen.domain.interactor.ScreenshotInteractor import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine Loading @@ -45,6 +47,7 @@ class PreCaptureViewModel @AssistedInject constructor( @Application private val applicationContext: Context, @Background private val backgroundScope: CoroutineScope, private val iconProvider: ScreenCaptureIconProvider, private val screenshotInteractor: ScreenshotInteractor, private val featuresInteractor: ScreenCaptureRecordLargeScreenFeaturesInteractor, Loading Loading @@ -85,11 +88,14 @@ constructor( captureRegionSource.value = selectedRegion } suspend fun takeFullscreenScreenshot() { fun takeFullscreenScreenshot() { require(captureTypeSource.value == ScreenCaptureType.SCREENSHOT) require(captureRegionSource.value == ScreenCaptureRegion.FULLSCREEN) backgroundScope.launch { // TODO(b/430361425) Pass in current display as argument. screenshotInteractor.takeFullscreenScreenshot() } // TODO(b/427500006) Close the window after requesting a fullscreen screenshot. } Loading @@ -110,7 +116,7 @@ constructor( onClick = { updateCaptureType(ScreenCaptureType.SCREEN_RECORD) }, ), RadioButtonGroupItemViewModel( icon = icons?.screenshot, icon = icons?.screenshotToolbar, label = applicationContext.getString(R.string.screen_capture_toolbar_capture_button), isSelected = selectedType == ScreenCaptureType.SCREENSHOT, Loading
packages/SystemUI/src/com/android/systemui/screencapture/record/largescreen/ui/viewmodel/ScreenCaptureIconProvider.kt +4 −2 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext data class ScreenCaptureIcons( val screenshot: Icon, val screenshotToolbar: Icon, val screenshotButton: Icon, val screenRecord: Icon, val fullscreen: Icon, val region: Icon, Loading @@ -55,7 +56,8 @@ constructor( flow { emit( ScreenCaptureIcons( screenshot = loadIcon(R.drawable.ic_screen_capture_camera), screenshotToolbar = loadIcon(R.drawable.ic_screen_capture_camera), screenshotButton = loadIcon(R.drawable.ic_screen_capture_camera), screenRecord = loadIcon(R.drawable.ic_screenrecord), fullscreen = loadIcon(R.drawable.ic_screen_capture_fullscreen), region = loadIcon(R.drawable.ic_screen_capture_region), Loading