# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1621039464 0 # Node ID 127779860ac113e780e11dfcf2c45a60e2951d96 # Parent a8d90e2896bc618d16eb36aba4adc77373e2e035 Android: Implement DW_CLR_DEFAULT and some basic dark mode support. diff -r a8d90e2896bc -r 127779860ac1 android/DWindows.kt --- a/android/DWindows.kt Fri May 14 19:12:39 2021 +0000 +++ b/android/DWindows.kt Sat May 15 00:44:24 2021 +0000 @@ -25,6 +25,7 @@ import android.util.Base64 import android.util.Log import android.util.SparseBooleanArray +import android.util.TypedValue import android.view.* import android.view.View.OnTouchListener import android.view.inputmethod.EditorInfo @@ -33,6 +34,7 @@ import android.widget.* import android.widget.AdapterView.OnItemClickListener import android.widget.SeekBar.OnSeekBarChangeListener +import androidx.annotation.RequiresApi import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.AppCompatEditText @@ -462,6 +464,7 @@ var threadLock = ReentrantLock() var threadCond = threadLock.newCondition() var notificationID: Int = 0 + var darkMode: Int = -1 private var paint = Paint() private var bgcolor: Int = 0 private var menuBar: DWMenu? = null @@ -510,6 +513,12 @@ override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) + val currentNightMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK + when (currentNightMode) { + Configuration.UI_MODE_NIGHT_NO -> { darkMode = 0 } // Night mode is not active, we're using the light theme + Configuration.UI_MODE_NIGHT_YES -> { darkMode = 1 } // Night mode is active, we're using dark theme + } + // Send a DW_SIGNAL_CONFIGURE on orientation change if(windowLayout != null) { var width: Int = windowLayout!!.width @@ -537,6 +546,11 @@ return super.onPrepareOptionsMenu(menu) } + fun darkModeDetected(): Int + { + return darkMode + } + fun menuBarNew(location: View): DWMenu? { // TODO: Make sure location is this activity @@ -752,21 +766,50 @@ } } - fun windowSetColor(window: View, falpha: Int, fred: Int, fgreen: Int, fblue: Int, - balpha: Int, bred: Int, bgreen: Int, bblue: Int) { + fun windowSetColor(window: View, fore: Int, falpha: Int, fred: Int, fgreen: Int, fblue: Int, + back: Int, balpha: Int, bred: Int, bgreen: Int, bblue: Int) { + var colorfore: Int = Color.rgb(fred, fgreen, fblue) + var colorback: Int = Color.rgb(bred, bgreen, bblue) + + // DW_CLR_DEFAULT on background sets it transparent... + // so the background drawable shows through + if(back == 16) { + colorback = Color.TRANSPARENT + } waitOnUiThread { if (window is TextView) { var textview: TextView = window - textview.setTextColor(Color.rgb(fred, fgreen, fblue)) - textview.setBackgroundColor(Color.rgb(bred, bgreen, bblue)) + + // Handle DW_CLR_DEFAULT + if(fore == 16) { + val value = TypedValue() + this.theme.resolveAttribute(R.attr.editTextColor, value, true) + colorfore = value.data + } + textview.setTextColor(colorfore) + textview.setBackgroundColor(colorback) } else if (window is Button) { var button: Button = window - button.setTextColor(Color.rgb(fred, fgreen, fblue)) - button.setBackgroundColor(Color.rgb(bred, bgreen, bblue)) + + // Handle DW_CLR_DEFAULT + if(fore == 16) { + val value = TypedValue() + // colorButtonNormal requires API 21... use the editTextColor... + // on older versions as a placeholder... this is probably wrong + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + this.theme.resolveAttribute(R.attr.colorButtonNormal, value, true) + } else { + this.theme.resolveAttribute(R.attr.editTextColor, value, true) + } + colorfore = value.data + } + button.setTextColor(colorfore) + button.setBackgroundColor(colorback) } else if(window is LinearLayout) { var box: LinearLayout = window - box.setBackgroundColor(Color.rgb(bred, bgreen, bblue)) + + box.setBackgroundColor(colorback) } } } diff -r a8d90e2896bc -r 127779860ac1 android/dw.cpp --- a/android/dw.cpp Fri May 14 19:12:39 2021 +0000 +++ b/android/dw.cpp Sat May 15 00:44:24 2021 +0000 @@ -589,6 +589,23 @@ return 0; } +int _dw_dark_mode_detected() +{ + JNIEnv *env; + + if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) + { + // First get the class that contains the method you need to call + jclass clazz = _dw_find_class(env, DW_CLASS_NAME); + // Get the method that you want to call + jmethodID darkModeDetected = env->GetMethodID(clazz, "darkModeDetected", + "()I"); + // Call the method on the object + return env->CallIntMethod(_dw_obj, darkModeDetected); + } + return DW_ERROR_UNKNOWN; +} + /* * Runs a message loop for Dynamic Windows. */ @@ -4450,11 +4467,11 @@ jclass clazz = _dw_find_class(env, DW_CLASS_NAME); // Get the method that you want to call jmethodID windowSetColor = env->GetMethodID(clazz, "windowSetColor", - "(Landroid/view/View;IIIIIIII)V"); + "(Landroid/view/View;IIIIIIIIII)V"); // Call the method on the object env->CallVoidMethod(_dw_obj, windowSetColor, handle, - 0, (jint)DW_RED_VALUE(_fore), (jint)DW_GREEN_VALUE(_fore), (jint)DW_BLUE_VALUE(_fore), - 0, (jint)DW_RED_VALUE(_back), (jint)DW_GREEN_VALUE(_back), (jint)DW_BLUE_VALUE(_back)); + (jint)fore, 0, (jint)DW_RED_VALUE(_fore), (jint)DW_GREEN_VALUE(_fore), (jint)DW_BLUE_VALUE(_fore), + (jint)back, 0, (jint)DW_RED_VALUE(_back), (jint)DW_GREEN_VALUE(_back), (jint)DW_BLUE_VALUE(_back)); return DW_ERROR_NONE; } return DW_ERROR_GENERAL; @@ -6428,12 +6445,19 @@ { case DW_FEATURE_HTML: /* Supports the HTML Widget */ case DW_FEATURE_HTML_RESULT: /* Supports the DW_SIGNAL_HTML_RESULT callback */ - case DW_FEATURE_DARK_MODE: /* Supports Dark Mode user interface */ case DW_FEATURE_NOTIFICATION: /* Supports sending system notifications */ case DW_FEATURE_UTF8_UNICODE: /* Supports UTF8 encoded Unicode text */ case DW_FEATURE_MLE_WORD_WRAP: /* Supports word wrapping in Multi-line Edit boxes */ case DW_FEATURE_CONTAINER_STRIPE: /* Supports striped line display in container widgets */ return DW_FEATURE_ENABLED; + case DW_FEATURE_DARK_MODE: /* Supports Dark Mode user interface */ + { + /* Dark Mode on Android requires Android 10 (API 29) */ + if(_dw_android_api >= 29) { + return _dw_dark_mode_detected(); + } + return DW_FEATURE_UNSUPPORTED; + } default: return DW_FEATURE_UNSUPPORTED; } @@ -6459,13 +6483,23 @@ /* These features are supported but not configurable */ case DW_FEATURE_HTML: /* Supports the HTML Widget */ case DW_FEATURE_HTML_RESULT: /* Supports the DW_SIGNAL_HTML_RESULT callback */ - case DW_FEATURE_DARK_MODE: /* Supports Dark Mode user interface */ case DW_FEATURE_NOTIFICATION: /* Supports sending system notifications */ case DW_FEATURE_UTF8_UNICODE: /* Supports UTF8 encoded Unicode text */ case DW_FEATURE_MLE_WORD_WRAP: /* Supports word wrapping in Multi-line Edit boxes */ case DW_FEATURE_CONTAINER_STRIPE: /* Supports striped line display in container widgets */ return DW_ERROR_GENERAL; /* These features are supported and configurable */ + case DW_FEATURE_DARK_MODE: /* Supports Dark Mode user interface */ + { + /* Dark Mode on Android requires 10 (API 29) */ + if(_dw_android_api >= 29) { + /* While technically configurable.... + * for now just return DW_ERROR_GENERAL + */ + return DW_ERROR_GENERAL; + } + return DW_FEATURE_UNSUPPORTED; + } default: return DW_FEATURE_UNSUPPORTED; }