mirror of
https://github.com/Ishan09811/pine.git
synced 2025-04-28 09:35:08 +00:00
Merge branch 'master' into android-15-support
This commit is contained in:
commit
6e3d14c00c
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -1,6 +1,7 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 80dada6a7b455cf18c39788d70aa7711323ea977
|
||||
Subproject commit 1055cb5e780c12fb2aab98949cc5a0d45f6ed0a1
|
@ -165,6 +165,14 @@ extern "C" JNIEXPORT jboolean Java_emu_skyline_EmulationActivity_setSurface(JNIE
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_pauseEmulation(JNIEnv *, jobject, jboolean pause) {
|
||||
auto gpu = GpuWeak.lock();
|
||||
if (!gpu) return;
|
||||
if (pause) {
|
||||
gpu->presentation.Pause();
|
||||
} else gpu->presentation.Resume();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_changeAudioStatus(JNIEnv *, jobject, jboolean play) {
|
||||
auto audio{AudioWeak.lock()};
|
||||
if (audio)
|
||||
|
@ -209,7 +209,7 @@ namespace skyline::gpu {
|
||||
static vk::raii::DebugReportCallbackEXT CreateDebugReportCallback(GPU *gpu, const vk::raii::Instance &instance) {
|
||||
return vk::raii::DebugReportCallbackEXT(instance, vk::DebugReportCallbackCreateInfoEXT{
|
||||
.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning | vk::DebugReportFlagBitsEXT::eInformation | vk::DebugReportFlagBitsEXT::eDebug,
|
||||
.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(&DebugCallback),
|
||||
.pfnCallback = reinterpret_cast<vk::PFN_DebugReportCallbackEXT>(&DebugCallback),
|
||||
.pUserData = gpu,
|
||||
});
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace skyline::gpu {
|
||||
|
||||
auto result{(*gpu.vkDevice).allocateCommandBuffers(&commandBufferAllocateInfo, &commandBuffer, *gpu.vkDevice.getDispatcher())};
|
||||
if (result != vk::Result::eSuccess)
|
||||
vk::throwResultException(result, __builtin_FUNCTION());
|
||||
vk::detail::throwResultException(result, __builtin_FUNCTION());
|
||||
return {pool->buffers.emplace_back(gpu.vkDevice, commandBuffer, pool->vkCommandPool)};
|
||||
}
|
||||
|
||||
|
@ -70,11 +70,11 @@ namespace skyline::gpu {
|
||||
if (pool->freeSetCount > 0)
|
||||
pool->freeSetCount--;
|
||||
|
||||
return vk::createResultValue(result, descriptorSet, __builtin_FUNCTION(), {
|
||||
vk::Result::eSuccess,
|
||||
vk::Result::eErrorOutOfPoolMemory,
|
||||
vk::Result::eErrorFragmentedPool
|
||||
});
|
||||
if (result == vk::Result::eSuccess) {
|
||||
return vk::ResultValue<vk::DescriptorSet>(vk::Result::eSuccess, descriptorSet);
|
||||
} else {
|
||||
return vk::ResultValue<vk::DescriptorSet>(result, vk::DescriptorSet{});
|
||||
}
|
||||
}
|
||||
|
||||
DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} {}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
#include <common/spin_lock.h>
|
||||
#include "vk_descriptor_set_layout_hash.hpp"
|
||||
#include <common.h>
|
||||
|
||||
namespace skyline::gpu {
|
||||
|
@ -10,7 +10,7 @@ namespace skyline::gpu::memory {
|
||||
*/
|
||||
void ThrowOnFail(VkResult result, const char *function = __builtin_FUNCTION()) {
|
||||
if (result != VK_SUCCESS)
|
||||
vk::throwResultException(vk::Result(result), function);
|
||||
vk::detail::throwResultException(vk::Result(result), function);
|
||||
}
|
||||
|
||||
Buffer::~Buffer() {
|
||||
|
@ -24,7 +24,7 @@ namespace skyline::gpu::memory {
|
||||
|
||||
Buffer(const Buffer &) = delete;
|
||||
|
||||
constexpr Buffer(Buffer &&other)
|
||||
Buffer(Buffer &&other)
|
||||
: vmaAllocator(std::exchange(other.vmaAllocator, nullptr)),
|
||||
vmaAllocation(std::exchange(other.vmaAllocation, nullptr)),
|
||||
vkBuffer(std::exchange(other.vkBuffer, {})),
|
||||
@ -94,7 +94,7 @@ namespace skyline::gpu::memory {
|
||||
|
||||
Image(const Image &) = delete;
|
||||
|
||||
constexpr Image(Image &&other)
|
||||
Image(Image &&other)
|
||||
: pointer(std::exchange(other.pointer, nullptr)),
|
||||
vmaAllocator(std::exchange(other.vmaAllocator, nullptr)),
|
||||
vmaAllocation(std::exchange(other.vmaAllocation, nullptr)),
|
||||
|
@ -21,6 +21,8 @@ extern jfloat AverageFrametimeDeviationMs;
|
||||
namespace skyline::gpu {
|
||||
using namespace service::hosbinder;
|
||||
|
||||
std::atomic<bool> paused{false};
|
||||
|
||||
PresentationEngine::PresentationEngine(const DeviceState &state, GPU &gpu)
|
||||
: state{state},
|
||||
gpu{gpu},
|
||||
@ -76,7 +78,14 @@ namespace skyline::gpu {
|
||||
try {
|
||||
choreographerLooper = ALooper_prepare(0);
|
||||
AChoreographer_postFrameCallback64(AChoreographer_getInstance(), reinterpret_cast<AChoreographer_frameCallback64>(&ChoreographerCallback), this);
|
||||
while (ALooper_pollOnce(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop); // Will block and process callbacks till ALooper_wake() is called with choreographerStop set
|
||||
|
||||
|
||||
while (ALooper_pollOnce(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop) {
|
||||
while (paused.load(std::memory_order_acquire)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (const signal::SignalException &e) {
|
||||
LOGE("{}\nStack Trace:{}", e.what(), state.loader->GetStackTrace(e.frames));
|
||||
if (state.process)
|
||||
@ -235,6 +244,9 @@ namespace skyline::gpu {
|
||||
|
||||
try {
|
||||
presentQueue.Process([this](const PresentableFrame &frame) {
|
||||
while (paused.load(std::memory_order_acquire)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
PresentFrame(frame);
|
||||
frame.presentCallback(); // We're calling the callback here as it's outside of all the locks in PresentFrame
|
||||
skipSignal = true;
|
||||
@ -412,6 +424,16 @@ namespace skyline::gpu {
|
||||
return nextFrameId++;
|
||||
}
|
||||
|
||||
void PresentationEngine::Pause() {
|
||||
paused.store(true, std::memory_order_release);
|
||||
LOGI("PresentationEngine paused.");
|
||||
}
|
||||
|
||||
void PresentationEngine::Resume() {
|
||||
paused.store(false, std::memory_order_release);
|
||||
LOGI("PresentationEngine resumed.");
|
||||
}
|
||||
|
||||
NativeWindowTransform PresentationEngine::GetTransformHint() {
|
||||
if (!vkSurface.has_value()) {
|
||||
std::unique_lock lock{mutex};
|
||||
|
@ -115,6 +115,9 @@ namespace skyline::gpu {
|
||||
*/
|
||||
void UpdateSurface(jobject newSurface);
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
|
||||
/**
|
||||
* @brief Queue the supplied texture to be presented to the screen
|
||||
* @param timestamp The earliest timestamp (relative to skyline::util::GetTickNs) at which the frame must be presented, it should be 0 when it doesn't matter
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common/trap_manager.h"
|
||||
#include <gpu/tag_allocator.h>
|
||||
#include <gpu/memory_manager.h>
|
||||
#include <vulkan/vulkan_format_traits.hpp>
|
||||
#include <gpu/usage_tracker.h>
|
||||
|
||||
namespace skyline::gpu {
|
||||
|
@ -0,0 +1,18 @@
|
||||
#ifndef VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP
|
||||
#define VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
// Specialization of std::hash for vk::DescriptorSetLayout
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<vk::DescriptorSetLayout> {
|
||||
std::size_t operator()(const vk::DescriptorSetLayout &layout) const noexcept {
|
||||
// Use the raw Vulkan handle for hashing
|
||||
return std::hash<VkDescriptorSetLayout>()(static_cast<VkDescriptorSetLayout>(layout));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP
|
@ -33,6 +33,7 @@ import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.widget.Toast
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.TextView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@ -41,6 +42,9 @@ import androidx.core.view.isGone
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.updateMargins
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@ -172,6 +176,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
*/
|
||||
private external fun stopEmulation(join : Boolean) : Boolean
|
||||
|
||||
private external fun pauseEmulation(pause: Boolean)
|
||||
|
||||
/**
|
||||
* This sets the surface object in libskyline to the provided value, emulation is halted if set to null
|
||||
*
|
||||
@ -308,7 +314,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
|
||||
requestedOrientation = emulationSettings.orientation
|
||||
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
||||
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
inputHandler = InputHandler(inputManager, emulationSettings)
|
||||
setContentView(binding.root)
|
||||
|
||||
@ -445,11 +451,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
// No op
|
||||
}
|
||||
})
|
||||
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.game_title).text = item.title
|
||||
binding.inGameMenu.setNavigationItemSelectedListener {
|
||||
when (it.itemId) {
|
||||
R.id.menu_emulation_resume -> {
|
||||
if (isEmulatorPaused) {
|
||||
pauseEmulator()
|
||||
resumeEmulator()
|
||||
it.title = resources.getString(R.string.pause_emulation)
|
||||
it.icon = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
@ -457,7 +464,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
this.theme
|
||||
)
|
||||
} else {
|
||||
resumeEmulator()
|
||||
pauseEmulator()
|
||||
it.title = resources.getString(R.string.resume_emulation)
|
||||
it.icon = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
@ -493,21 +500,39 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
setInsets()
|
||||
executeApplication(intent!!)
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.inGameMenu
|
||||
) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
val cutInsets: Insets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||
var left = 0
|
||||
var right = 0
|
||||
if (ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
||||
left = cutInsets.left
|
||||
} else {
|
||||
right = cutInsets.right
|
||||
}
|
||||
|
||||
v.setPadding(left, cutInsets.top, right, 0)
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun pauseEmulator() {
|
||||
if (isEmulatorPaused) return
|
||||
setSurface(null)
|
||||
pauseEmulation(true)
|
||||
changeAudioStatus(false)
|
||||
isEmulatorPaused = true
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun resumeEmulator() {
|
||||
gameSurface?.let { setSurface(it) }
|
||||
pauseEmulation(false)
|
||||
changeAudioStatus(true)
|
||||
isEmulatorPaused = false
|
||||
}
|
||||
|
@ -12,13 +12,16 @@ import android.os.Bundle
|
||||
import android.provider.DocumentsContract
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.res.use
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
@ -27,6 +30,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.R as MaterialR
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import emu.skyline.adapter.*
|
||||
import emu.skyline.data.AppItem
|
||||
@ -41,6 +45,7 @@ import emu.skyline.settings.SettingsActivity
|
||||
import emu.skyline.utils.GpuDriverHelper
|
||||
import emu.skyline.utils.SearchLocationHelper
|
||||
import emu.skyline.utils.WindowInsetsHelper
|
||||
import emu.skyline.SkylineApplication
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.ceil
|
||||
|
||||
@ -147,6 +152,29 @@ class MainActivity : AppCompatActivity() {
|
||||
window.decorView.findViewById<View>(android.R.id.content).viewTreeObserver.addOnTouchModeChangeListener { isInTouchMode ->
|
||||
refreshIconVisible = !isInTouchMode
|
||||
}
|
||||
|
||||
binding.statusBarShade.setBackgroundColor(
|
||||
SkylineApplication.applyAlphaToColor(
|
||||
MaterialColors.getColor(
|
||||
binding.root,
|
||||
MaterialR.attr.colorSurface
|
||||
),
|
||||
0.9f
|
||||
)
|
||||
)
|
||||
|
||||
if (SkylineApplication.detectNavigationType(this) != SkylineApplication.NAV_TYPE_GESTURE) {
|
||||
binding.navigationBarShade.setBackgroundColor(
|
||||
SkylineApplication.applyAlphaToColor(
|
||||
MaterialColors.getColor(
|
||||
binding.root,
|
||||
MaterialR.attr.colorSurface
|
||||
),
|
||||
0.9f
|
||||
)
|
||||
)
|
||||
}
|
||||
setInsets()
|
||||
}
|
||||
|
||||
private fun setAppListDecoration() {
|
||||
@ -331,4 +359,20 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
viewModel.checkRomHash(SearchLocationHelper.getSearchLocations(this), EmulationSettings.global.systemLanguage)
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val mlpStatusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
|
||||
mlpStatusShade.height = insets.top
|
||||
binding.statusBarShade.layoutParams = mlpStatusShade
|
||||
|
||||
val mlpNavShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
|
||||
mlpNavShade.height = insets.bottom
|
||||
binding.navigationBarShade.layoutParams = mlpNavShade
|
||||
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,14 @@ package emu.skyline
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import androidx.annotation.ColorInt
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.color.DynamicColorsOptions
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
import emu.skyline.di.getSettings
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* @return The optimal directory for putting public files inside, this may return a private directory if a public directory cannot be retrieved
|
||||
@ -29,6 +32,61 @@ class SkylineApplication : Application() {
|
||||
private set
|
||||
|
||||
val context : Context get() = instance.applicationContext
|
||||
|
||||
|
||||
const val NAV_TYPE_THREE_BUTTON = 0
|
||||
const val NAV_TYPE_TWO_BUTTON = 1
|
||||
const val NAV_TYPE_GESTURE = 2
|
||||
|
||||
/**
|
||||
* Adjusts the opacity of a color by applying an alpha factor.
|
||||
*
|
||||
* @param color The original color (including alpha).
|
||||
* @param alphaFactor A value between 0.0 (fully transparent) and 1.0 (no change in opacity).
|
||||
* @return A new color with the adjusted opacity.
|
||||
*/
|
||||
@ColorInt
|
||||
fun applyAlphaToColor(@ColorInt color: Int, alphaFactor: Float): Int {
|
||||
val newAlpha = (Color.alpha(color) * alphaFactor).coerceIn(0f, 255f).roundToInt()
|
||||
return Color.argb(
|
||||
newAlpha,
|
||||
Color.red(color),
|
||||
Color.green(color),
|
||||
Color.blue(color)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the system navigation type.
|
||||
*
|
||||
* @param context The context used to access resources.
|
||||
* @return An integer representing the navigation type:
|
||||
* - 0: Three-button navigation
|
||||
* - 1: Two-button navigation
|
||||
* - 2: Gesture navigation
|
||||
*/
|
||||
fun detectNavigationType(context: Context): Int {
|
||||
val navBarModeResource = context.resources.getIdentifier(
|
||||
"config_navBarInteractionMode",
|
||||
"integer",
|
||||
"android"
|
||||
)
|
||||
return if (navBarModeResource != 0) {
|
||||
try {
|
||||
context.resources.getInteger(navBarModeResource)
|
||||
} catch (e: Exception) {
|
||||
NAV_TYPE_THREE_BUTTON // Fallback to default
|
||||
}
|
||||
} else {
|
||||
NAV_TYPE_THREE_BUTTON // Fallback to default
|
||||
}
|
||||
}
|
||||
|
||||
fun setTheme(newValue: Boolean) {
|
||||
val dynamicColorsOptions = DynamicColorsOptions.Builder().setPrecondition { _, _ -> newValue }.build()
|
||||
DynamicColors.applyToActivitiesIfAvailable(instance, dynamicColorsOptions)
|
||||
if (newValue == false) { instance.setTheme(R.style.AppTheme) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
|
@ -20,6 +20,7 @@ import emu.skyline.MainActivity
|
||||
import emu.skyline.R
|
||||
import emu.skyline.utils.GpuDriverHelper
|
||||
import emu.skyline.utils.WindowInsetsHelper
|
||||
import emu.skyline.SkylineApplication
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -45,9 +46,10 @@ class GlobalSettingsFragment : PreferenceFragmentCompat() {
|
||||
addPreferencesFromResource(R.xml.credits_preferences)
|
||||
|
||||
// Re-launch the app if Material You is toggled
|
||||
findPreference<Preference>("use_material_you")?.setOnPreferenceChangeListener { _, _ ->
|
||||
requireActivity().finishAffinity()
|
||||
startActivity(Intent(requireContext(), MainActivity::class.java))
|
||||
findPreference<Preference>("use_material_you")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
val isMaterialYouEnabled = newValue as Boolean
|
||||
SkylineApplication.setTheme(isMaterialYouEnabled)
|
||||
requireActivity().recreate()
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -8,14 +8,18 @@ package emu.skyline.settings
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.ViewTreeObserver
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
@ -24,6 +28,8 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.forEach
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.internal.ToolbarUtils
|
||||
import com.google.android.material.R as MaterialR
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import emu.skyline.BuildConfig
|
||||
import emu.skyline.R
|
||||
import emu.skyline.data.AppItemTag
|
||||
@ -33,6 +39,7 @@ import emu.skyline.preference.dialog.EditTextPreferenceMaterialDialogFragmentCom
|
||||
import emu.skyline.preference.dialog.IntegerListPreferenceMaterialDialogFragmentCompat
|
||||
import emu.skyline.preference.dialog.ListPreferenceMaterialDialogFragmentCompat
|
||||
import emu.skyline.utils.WindowInsetsHelper
|
||||
import emu.skyline.SkylineApplication
|
||||
|
||||
private const val PREFERENCE_DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG"
|
||||
|
||||
@ -123,6 +130,29 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
||||
.replace(R.id.settings, preferenceFragment)
|
||||
.commit()
|
||||
}
|
||||
|
||||
binding.statusBarShade.setBackgroundColor(
|
||||
SkylineApplication.applyAlphaToColor(
|
||||
MaterialColors.getColor(
|
||||
binding.root,
|
||||
MaterialR.attr.colorSurface
|
||||
),
|
||||
0.9f
|
||||
)
|
||||
)
|
||||
|
||||
if (SkylineApplication.detectNavigationType(this) != SkylineApplication.NAV_TYPE_GESTURE) {
|
||||
binding.navigationBarShade.setBackgroundColor(
|
||||
SkylineApplication.applyAlphaToColor(
|
||||
MaterialColors.getColor(
|
||||
binding.root,
|
||||
MaterialR.attr.colorSurface
|
||||
),
|
||||
0.9f
|
||||
)
|
||||
)
|
||||
}
|
||||
setInsets()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu : Menu?) : Boolean {
|
||||
@ -131,13 +161,13 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
||||
val searchView = menuItem.actionView as SearchView
|
||||
searchView.queryHint = getString(R.string.search)
|
||||
|
||||
searchView.setOnQueryTextFocusChangeListener { _, focus ->
|
||||
/* searchView.setOnQueryTextFocusChangeListener { _, focus ->
|
||||
(binding.titlebar.toolbar.layoutParams as AppBarLayout.LayoutParams).scrollFlags =
|
||||
if (focus)
|
||||
AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
|
||||
else
|
||||
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
|
||||
}
|
||||
}*/
|
||||
|
||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query : String) : Boolean {
|
||||
@ -233,4 +263,20 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setInsets() =
|
||||
ViewCompat.setOnApplyWindowInsetsListener(
|
||||
binding.root
|
||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val statusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
|
||||
statusShade.height = insets.top
|
||||
binding.statusBarShade.layoutParams = statusShade
|
||||
|
||||
val navShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
|
||||
navShade.height = insets.bottom
|
||||
binding.navigationBarShade.layoutParams = navShade
|
||||
|
||||
windowInsets
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:background="@android:color/black"
|
||||
android:keepScreenOn="true"
|
||||
tools:context=".EmulationActivity"
|
||||
tools:openDrawer="start"
|
||||
@ -94,6 +93,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:focusedByDefault="true"
|
||||
app:headerLayout="@layout/game_menu_header"
|
||||
app:menu="@menu/menu_in_game"
|
||||
tools:visibility="gone" />
|
||||
|
||||
|
14
app/src/main/res/layout/game_menu_header.xml
Normal file
14
app/src/main/res/layout/game_menu_header.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/game_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:textAppearance="?attr/textAppearanceHeadlineMedium"
|
||||
android:textColor="?attr/colorOnSurface"
|
||||
android:textAlignment="viewStart"
|
||||
tools:text="Game Title" />
|
@ -6,6 +6,15 @@
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<View
|
||||
android:id="@+id/status_bar_shade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
@ -142,4 +151,12 @@
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
android:paddingBottom="20dp" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
<View
|
||||
android:id="@+id/navigation_bar_shade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="bottom" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -6,6 +6,15 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/status_bar_shade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
<include
|
||||
android:id="@+id/titlebar"
|
||||
layout="@layout/titlebar" />
|
||||
@ -15,4 +24,13 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<View
|
||||
android:id="@+id/navigation_bar_shade"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="bottom" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -1,16 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/app_bar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:fitsSystemWindows="true"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_scrollFlags="scroll" />
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
style="?attr/collapsingToolbarLayoutMediumStyle"
|
||||
android:id="@+id/toolbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="pin" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
@ -33,6 +33,8 @@
|
||||
<style name="BaseAppTheme" parent="ColorAppTheme">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:enforceStatusBarContrast">false</item>
|
||||
<item name="android:enforceNavigationBarContrast">false</item>
|
||||
<item name="chipChoiceStyle">@style/ChipChoice</item>
|
||||
|
||||
<!-- Workaround for AndroidX PreferenceScreen since it doesn't use MaterialAlertDialogs -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user