comparison android/DWindows.kt @ 2665:aca4b56f50dd

Android: Attempt at multi-window support using ViewPager2. I tried initially with FragmentContainerView but ran into issues. Seems to be having issues with nested ViewPager2s used in the notebooks. Still needs a lot o work but the core is there now.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Tue, 12 Oct 2021 23:04:13 +0000
parents 3a14d7fd4b99
children 4f2d433747e2
comparison
equal deleted inserted replaced
2664:b0712a3debe2 2665:aca4b56f50dd
766 return rowView 766 return rowView
767 } 767 }
768 } 768 }
769 769
770 class DWindows : AppCompatActivity() { 770 class DWindows : AppCompatActivity() {
771 var firstWindow: Boolean = true 771 var windowLayout: ViewPager2? = null
772 var windowLayout: LinearLayout? = null
773 var threadLock = ReentrantLock() 772 var threadLock = ReentrantLock()
774 var threadCond = threadLock.newCondition() 773 var threadCond = threadLock.newCondition()
775 var notificationID: Int = 0 774 var notificationID: Int = 0
776 var darkMode: Int = -1 775 var darkMode: Int = -1
777 var lastClickView: View? = null 776 var lastClickView: View? = null
778 private var paint = Paint() 777 private var paint = Paint()
779 private var bgcolor: Int? = null 778 private var bgcolor: Int? = null
780 private var menuBar: DWMenu? = null 779 private var menuBar: DWMenu? = null
781 private var defaultItem: View? = null
782 private var fileURI: Uri? = null 780 private var fileURI: Uri? = null
783 private var fileLock = ReentrantLock() 781 private var fileLock = ReentrantLock()
784 private var fileCond = threadLock.newCondition() 782 private var fileCond = threadLock.newCondition()
783 // Lists of data for our Windows
784 private var windowTitles = mutableListOf<String?>()
785 private var windowMenuBars = mutableListOf<DWMenu?>()
786 private var windowStyles = mutableListOf<Int>()
787 private var windowDefault = mutableListOf<View?>()
785 788
786 // Our version of runOnUiThread that waits for execution 789 // Our version of runOnUiThread that waits for execution
787 fun waitOnUiThread(runnable: Runnable) 790 fun waitOnUiThread(runnable: Runnable)
788 { 791 {
789 if(Looper.myLooper() == Looper.getMainLooper()) { 792 if(Looper.myLooper() == Looper.getMainLooper()) {
878 // Extract any non-resource assets to the cache directory 881 // Extract any non-resource assets to the cache directory
879 // So that our C code can access them as files, like on 882 // So that our C code can access them as files, like on
880 // other Dynamic Windows platforms 883 // other Dynamic Windows platforms
881 extractAssets() 884 extractAssets()
882 885
886 // Setup our ViewPager2 as our activty window container
887 windowLayout = ViewPager2(this)
888 windowLayout!!.id = View.generateViewId()
889 windowLayout!!.adapter = DWTabViewPagerAdapter()
890 windowLayout!!.isUserInputEnabled = false
891 windowLayout!!.layoutParams =
892 ViewGroup.LayoutParams(
893 ViewGroup.LayoutParams.MATCH_PARENT,
894 ViewGroup.LayoutParams.MATCH_PARENT
895 )
896
883 // Initialize the Dynamic Windows code... 897 // Initialize the Dynamic Windows code...
884 // This will start a new thread that calls the app's dwmain() 898 // This will start a new thread that calls the app's dwmain()
885 dwindowsInit(s, c, this.getPackageName()) 899 dwindowsInit(s, c, this.getPackageName())
886 } 900 }
887 901
896 910
897 // Send a DW_SIGNAL_CONFIGURE on orientation change 911 // Send a DW_SIGNAL_CONFIGURE on orientation change
898 if(windowLayout != null) { 912 if(windowLayout != null) {
899 val width: Int = windowLayout!!.width 913 val width: Int = windowLayout!!.width
900 val height: Int = windowLayout!!.height 914 val height: Int = windowLayout!!.height
901 915 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
902 eventHandlerInt(windowLayout as View, DWEvent.CONFIGURE, width, height, 0, 0) 916 val window = adapter.viewList[windowLayout!!.currentItem]
917
918 eventHandlerInt(window, DWEvent.CONFIGURE, width, height, 0, 0)
903 } 919 }
904 } 920 }
905 921
906 override fun onCreateOptionsMenu(menu: Menu?): Boolean { 922 override fun onCreateOptionsMenu(menu: Menu?): Boolean {
907 if(menuBar == null) { 923 if(menuBar == null) {
1044 } 1060 }
1045 } 1061 }
1046 } 1062 }
1047 1063
1048 fun windowNew(title: String, style: Int): LinearLayout? { 1064 fun windowNew(title: String, style: Int): LinearLayout? {
1049 if (firstWindow) { 1065 var window: LinearLayout? = null
1066
1067 if(windowLayout != null) {
1050 waitOnUiThread { 1068 waitOnUiThread {
1051 val dataArrayMap = SimpleArrayMap<String, Long>() 1069 val dataArrayMap = SimpleArrayMap<String, Long>()
1052 windowLayout = LinearLayout(this) 1070 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
1053 1071
1054 windowLayout!!.visibility = View.GONE
1055 windowLayout!!.tag = dataArrayMap
1056 setContentView(windowLayout) 1072 setContentView(windowLayout)
1057 this.title = title 1073
1058 // For now we just return our DWindows' main activity layout... 1074 window = LinearLayout(this)
1059 // in the future, later calls should create new activities 1075 window!!.visibility = View.GONE
1060 firstWindow = false 1076 window!!.tag = dataArrayMap
1061 } 1077 window!!.layoutParams =
1062 return windowLayout 1078 LinearLayout.LayoutParams(
1063 } 1079 LinearLayout.LayoutParams.MATCH_PARENT,
1064 return null 1080 LinearLayout.LayoutParams.MATCH_PARENT
1081 )
1082
1083 // Update our window list
1084 adapter.viewList.add(window!!)
1085 windowTitles.add(title)
1086 windowMenuBars.add(null)
1087 windowStyles.add(style)
1088 windowDefault.add(null)
1089
1090 // If this is our first/only window...
1091 // We can set stuff immediately
1092 if (adapter.viewList.count() == 1) {
1093 this.title = title
1094 windowLayout!!.setCurrentItem(0, false)
1095 }
1096 }
1097 }
1098 return window
1065 } 1099 }
1066 1100
1067 fun windowSetFocus(window: View) 1101 fun windowSetFocus(window: View)
1068 { 1102 {
1069 waitOnUiThread { 1103 waitOnUiThread {
1071 } 1105 }
1072 } 1106 }
1073 1107
1074 fun windowDefault(window: View, default: View) 1108 fun windowDefault(window: View, default: View)
1075 { 1109 {
1076 // TODO: Verify this is the correct activity... 1110 if(windowLayout != null) {
1077 defaultItem = default 1111 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
1112 val index = adapter.viewList.indexOf(window)
1113
1114 if (index != -1) {
1115 windowDefault[index] = default
1116 }
1117 }
1078 } 1118 }
1079 1119
1080 fun windowSetStyle(window: View, style: Int, mask: Int) 1120 fun windowSetStyle(window: View, style: Int, mask: Int)
1081 { 1121 {
1082 waitOnUiThread { 1122 waitOnUiThread {
1083 if (window is TextView && window !is EditText) { 1123 if (window is TextView && window !is EditText) {
1084 val text = window
1085 val ourmask = (Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.VERTICAL_GRAVITY_MASK) and mask 1124 val ourmask = (Gravity.HORIZONTAL_GRAVITY_MASK or Gravity.VERTICAL_GRAVITY_MASK) and mask
1086 1125
1087 if (ourmask != 0) { 1126 if (ourmask != 0) {
1088 // Gravity with the masked parts zeroed out 1127 // Gravity with the masked parts zeroed out
1089 val newgravity = style and ourmask 1128 val newgravity = style and ourmask
1090 1129
1091 text.gravity = newgravity 1130 window.gravity = newgravity
1092 } 1131 }
1093 } 1132 }
1094 } 1133 }
1095 } 1134 }
1096 1135
1262 } 1301 }
1263 } 1302 }
1264 } 1303 }
1265 1304
1266 fun windowSetText(window: View, text: String) { 1305 fun windowSetText(window: View, text: String) {
1267 waitOnUiThread { 1306 if(windowLayout != null) {
1268 if (window is TextView) { 1307 waitOnUiThread {
1269 val textview: TextView = window 1308 if (window is TextView) {
1270 textview.text = text 1309 val textview: TextView = window
1271 } else if (window is Button) { 1310 textview.text = text
1272 val button: Button = window 1311 } else if (window is Button) {
1273 button.text = text 1312 val button: Button = window
1274 } else if (window is LinearLayout) { 1313 button.text = text
1275 // TODO: Make sure this is actually the top-level layout, not just a box 1314 } else if (window is LinearLayout) {
1276 this.title = text 1315 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
1316 val index = adapter.viewList.indexOf(window)
1317
1318 if(index != -1) {
1319 windowTitles[index] = text
1320 if(index == windowLayout!!.currentItem) {
1321 this.title = text
1322 }
1323 }
1324 }
1277 } 1325 }
1278 } 1326 }
1279 } 1327 }
1280 1328
1281 fun windowGetText(window: View): String? { 1329 fun windowGetText(window: View): String? {
1282 var text: String? = null 1330 var text: String? = null
1283 1331
1284 waitOnUiThread { 1332 if(windowLayout != null) {
1285 if (window is TextView) { 1333 waitOnUiThread {
1286 val textview: TextView = window 1334 if (window is TextView) {
1287 text = textview.text.toString() 1335 val textview: TextView = window
1288 } else if (window is Button) { 1336 text = textview.text.toString()
1289 val button: Button = window 1337 } else if (window is Button) {
1290 text = button.text.toString() 1338 val button: Button = window
1291 } else if (window is LinearLayout) { 1339 text = button.text.toString()
1292 // TODO: Make sure this is actually the top-level layout, not just a box 1340 } else if (window is LinearLayout) {
1293 text = this.title.toString() 1341 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
1342 val index = adapter.viewList.indexOf(window)
1343
1344 if(index != -1) {
1345 text = windowTitles[index]
1346 }
1347 }
1294 } 1348 }
1295 } 1349 }
1296 return text 1350 return text
1297 } 1351 }
1298 1352
1299 fun windowHideShow(window: View, state: Int) 1353 fun windowHideShow(window: View, state: Int)
1300 { 1354 {
1301 waitOnUiThread { 1355 if(windowLayout != null) {
1302 if(state == 0) { 1356 waitOnUiThread {
1303 window.visibility = View.GONE 1357 val adapter: DWTabViewPagerAdapter = windowLayout!!.adapter as DWTabViewPagerAdapter
1304 } else { 1358 val index = adapter.viewList.indexOf(window)
1305 window.visibility = View.VISIBLE 1359 var defaultItem: View? = null
1306 defaultItem?.requestFocus() 1360
1361 if(state == 0) {
1362 window.visibility = View.GONE
1363 } else {
1364 window.visibility = View.VISIBLE
1365 }
1366 if (index != -1) {
1367 defaultItem = windowDefault[index]
1368 if(state != 0) {
1369 windowLayout!!.setCurrentItem(index, true)
1370 }
1371 }
1372 if(state != 0 && defaultItem != null) {
1373 defaultItem.requestFocus()
1374 }
1307 } 1375 }
1308 } 1376 }
1309 } 1377 }
1310 1378
1311 fun clipboardGetText(): String { 1379 fun clipboardGetText(): String {