Feature: Add X sessions
This commit is contained in:
parent
2033accbee
commit
6158752b8e
@ -0,0 +1,8 @@
|
||||
package io.neoterm.frontend.xorg;
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
public class XParameter {
|
||||
}
|
@ -1,11 +1,18 @@
|
||||
package io.neoterm.frontend.xorg
|
||||
|
||||
import android.content.Context
|
||||
import io.neoterm.backend.TerminalSession
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
class XSession {
|
||||
class XSession private constructor() {
|
||||
companion object {
|
||||
fun createSession(context: Context, parameter: XParameter) : XSession {
|
||||
return XSession()
|
||||
}
|
||||
}
|
||||
|
||||
var mSessionName = "";
|
||||
}
|
||||
|
@ -10,14 +10,14 @@ import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.os.PowerManager
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import android.support.v4.content.WakefulBroadcastReceiver
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.EmulatorDebug
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.frontend.shell.ShellParameter
|
||||
import io.neoterm.frontend.xorg.XParameter
|
||||
import io.neoterm.frontend.xorg.XSession
|
||||
import io.neoterm.ui.term.NeoTermActivity
|
||||
import io.neoterm.utils.TerminalUtils
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
@ -31,6 +31,7 @@ class NeoTermService : Service() {
|
||||
|
||||
private val serviceBinder = NeoTermBinder()
|
||||
private val mTerminalSessions = ArrayList<TerminalSession>()
|
||||
private val mXSessions = ArrayList<XSession>()
|
||||
private var mWakeLock: PowerManager.WakeLock? = null
|
||||
private var mWifiLock: WifiManager.WifiLock? = null
|
||||
|
||||
@ -58,11 +59,6 @@ class NeoTermService : Service() {
|
||||
ACTION_RELEASE_LOCK -> releaseLock()
|
||||
}
|
||||
|
||||
if (flags and Service.START_FLAG_REDELIVERY == 0) {
|
||||
// Service is started by WBR, not restarted by system, so release the WakeLock from WBR.
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent)
|
||||
}
|
||||
|
||||
return Service.START_NOT_STICKY
|
||||
}
|
||||
|
||||
@ -77,6 +73,9 @@ class NeoTermService : Service() {
|
||||
val sessions: List<TerminalSession>
|
||||
get() = mTerminalSessions
|
||||
|
||||
val xSessions: List<XSession>
|
||||
get() = mXSessions
|
||||
|
||||
fun createTermSession(parameter: ShellParameter): TerminalSession {
|
||||
val session = TerminalUtils.createShellSession(this, parameter)
|
||||
mTerminalSessions.add(session)
|
||||
@ -93,6 +92,22 @@ class NeoTermService : Service() {
|
||||
return indexOfRemoved
|
||||
}
|
||||
|
||||
fun createXSession(parameter: XParameter): XSession {
|
||||
val session = XSession.createSession(this, parameter)
|
||||
mXSessions.add(session)
|
||||
updateNotification()
|
||||
return session
|
||||
}
|
||||
|
||||
fun removeXSession(sessionToRemove: XSession): Int {
|
||||
val indexOfRemoved = mXSessions.indexOf(sessionToRemove)
|
||||
if (indexOfRemoved >= 0) {
|
||||
mXSessions.removeAt(indexOfRemoved)
|
||||
updateNotification()
|
||||
}
|
||||
return indexOfRemoved
|
||||
}
|
||||
|
||||
private fun updateNotification() {
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
service.notify(NOTIFICATION_ID, createNotification())
|
||||
@ -104,7 +119,8 @@ class NeoTermService : Service() {
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0)
|
||||
|
||||
val sessionCount = mTerminalSessions.size
|
||||
var contentText = getString(R.string.service_status_text, sessionCount)
|
||||
val xSessionCount = mXSessions.size
|
||||
var contentText = getString(R.string.service_status_text, sessionCount, xSessionCount)
|
||||
|
||||
val lockAcquired = mWakeLock != null
|
||||
if (lockAcquired) contentText += getString(R.string.service_lock_acquired)
|
||||
|
@ -24,15 +24,18 @@ import io.neoterm.component.setup.BaseFileInstaller
|
||||
import io.neoterm.frontend.client.TermSessionCallback
|
||||
import io.neoterm.frontend.client.TermViewClient
|
||||
import io.neoterm.frontend.client.event.*
|
||||
import io.neoterm.frontend.logging.NLog
|
||||
import io.neoterm.frontend.preference.NeoPermission
|
||||
import io.neoterm.frontend.preference.NeoPreference
|
||||
import io.neoterm.frontend.shell.ShellParameter
|
||||
import io.neoterm.frontend.xorg.XParameter
|
||||
import io.neoterm.frontend.xorg.XSession
|
||||
import io.neoterm.services.NeoTermService
|
||||
import io.neoterm.ui.pm.PackageManagerActivity
|
||||
import io.neoterm.ui.settings.SettingActivity
|
||||
import io.neoterm.ui.setup.SetupActivity
|
||||
import io.neoterm.ui.term.tab.NeoTabDecorator
|
||||
import io.neoterm.ui.term.tab.TermTab
|
||||
import io.neoterm.ui.term.tab.TermTabDecorator
|
||||
import io.neoterm.ui.term.tab.XSessionTab
|
||||
import io.neoterm.utils.FullScreenHelper
|
||||
import io.neoterm.utils.RangedInt
|
||||
@ -82,7 +85,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
})
|
||||
|
||||
tabSwitcher = findViewById(R.id.tab_switcher)
|
||||
tabSwitcher.decorator = TermTabDecorator(this)
|
||||
tabSwitcher.decorator = NeoTabDecorator(this)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(tabSwitcher, createWindowInsetsListener())
|
||||
tabSwitcher.showToolbars(false)
|
||||
|
||||
@ -193,7 +196,9 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
|
||||
override fun onTabRemoved(tabSwitcher: TabSwitcher, index: Int, tab: Tab, animation: Animation) {
|
||||
if (tab is TermTab) {
|
||||
closeTab(tab)
|
||||
SessionRemover.removeSession(termService, tab)
|
||||
} else if (tab is XSessionTab) {
|
||||
SessionRemover.removeXSession(termService, tab)
|
||||
}
|
||||
}
|
||||
|
||||
@ -349,6 +354,10 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
addNewSession(session)
|
||||
}
|
||||
|
||||
for (session in termService!!.xSessions) {
|
||||
addXSession(session)
|
||||
}
|
||||
|
||||
if (intent?.action == Intent.ACTION_RUN) {
|
||||
// app shortcuts
|
||||
addNewSession(null,
|
||||
@ -446,13 +455,49 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
}
|
||||
|
||||
private fun addXSession() {
|
||||
if (!tabSwitcher.isSwitcherShown) {
|
||||
toggleSwitcher(showSwitcher = true, easterEgg = false)
|
||||
}
|
||||
|
||||
// TODO: Start X server
|
||||
val parameter = XParameter()
|
||||
val session = termService!!.createXSession(parameter)
|
||||
|
||||
session.mSessionName = generateXSessionName("X")
|
||||
val tab = createXTab(session.mSessionName) as XSessionTab
|
||||
tab.session = session
|
||||
|
||||
addNewTab(tab, createRevealAnimation())
|
||||
switchToSession(tab)
|
||||
}
|
||||
|
||||
private fun addXSession(session: XSession?) {
|
||||
if (session == null) {
|
||||
return
|
||||
}
|
||||
|
||||
// Do not add the same session again
|
||||
// Or app will crash when rotate
|
||||
val tabCount = tabSwitcher.count
|
||||
(0..(tabCount - 1))
|
||||
.map { tabSwitcher.getTab(it) }
|
||||
.filter { it is XSessionTab && it.session == session }
|
||||
.forEach { return }
|
||||
|
||||
val tab = createXTab(session.mSessionName) as XSessionTab
|
||||
|
||||
addNewTab(tab, createRevealAnimation())
|
||||
switchToSession(tab)
|
||||
}
|
||||
|
||||
private fun generateSessionName(prefix: String): String {
|
||||
return "$prefix #${termService!!.sessions.size}"
|
||||
}
|
||||
|
||||
private fun generateXSessionName(prefix: String): String {
|
||||
return "$prefix #${termService!!.xSessions.size}"
|
||||
}
|
||||
|
||||
private fun switchToSession(session: TerminalSession?) {
|
||||
if (session == null) {
|
||||
return
|
||||
@ -500,7 +545,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
return postTabCreated(XSessionTab(tabTitle ?: "NeoTerm"))
|
||||
}
|
||||
|
||||
private fun <T : Tab> postTabCreated(tab: T) : T {
|
||||
private fun <T : Tab> postTabCreated(tab: T): T {
|
||||
// We must create a Bundle for each tab
|
||||
// tabs can use them to store status.
|
||||
tab.parameters = Bundle()
|
||||
@ -554,10 +599,6 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
}
|
||||
}
|
||||
|
||||
private fun closeTab(tab: TermTab) {
|
||||
SessionRemover.removeSession(termService, tab)
|
||||
}
|
||||
|
||||
private fun toggleSwitcher(showSwitcher: Boolean, easterEgg: Boolean) {
|
||||
if (tabSwitcher.count == 0 && easterEgg) {
|
||||
App.get().easterEgg(this, "Stop! You don't know what you are doing!")
|
||||
|
@ -1,8 +1,11 @@
|
||||
package io.neoterm.ui.term
|
||||
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.frontend.logging.NLog
|
||||
import io.neoterm.frontend.xorg.XSession
|
||||
import io.neoterm.services.NeoTermService
|
||||
import io.neoterm.ui.term.tab.TermTab
|
||||
import io.neoterm.ui.term.tab.XSessionTab
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
@ -14,6 +17,10 @@ object SessionRemover {
|
||||
tab.cleanup()
|
||||
}
|
||||
|
||||
fun removeXSession(termService: NeoTermService?, tab: XSessionTab?) {
|
||||
removeFinishedSession(termService, tab?.session)
|
||||
}
|
||||
|
||||
private fun removeFinishedSession(termService: NeoTermService?, finishedSession: TerminalSession?) {
|
||||
if (termService == null || finishedSession == null) {
|
||||
return
|
||||
@ -21,4 +28,12 @@ object SessionRemover {
|
||||
|
||||
termService.removeTermSession(finishedSession)
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeFinishedSession(termService: NeoTermService?, finishedSession: XSession?) {
|
||||
if (termService == null || finishedSession == null) {
|
||||
return
|
||||
}
|
||||
|
||||
termService.removeXSession(finishedSession)
|
||||
}
|
||||
}
|
||||
|
@ -22,25 +22,51 @@ import io.neoterm.utils.TerminalUtils
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
||||
class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
||||
companion object {
|
||||
private val VIEW_TYPE_TERM = 1
|
||||
private val VIEW_TYPE_X = 2
|
||||
}
|
||||
|
||||
override fun onInflateView(inflater: LayoutInflater, parent: ViewGroup?, viewType: Int): View {
|
||||
val view = inflater.inflate(R.layout.ui_term, parent, false)
|
||||
return view
|
||||
return when (viewType) {
|
||||
VIEW_TYPE_TERM -> {
|
||||
inflater.inflate(R.layout.ui_term, parent, false)
|
||||
}
|
||||
|
||||
VIEW_TYPE_X -> {
|
||||
inflater.inflate(R.layout.ui_xorg, parent, false)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw RuntimeException("Unknown view type")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onShowTab(context: Context, tabSwitcher: TabSwitcher,
|
||||
view: View, tab: Tab, index: Int, viewType: Int, savedInstanceState: Bundle?) {
|
||||
val toolbar = this@TermTabDecorator.context.toolbar
|
||||
val toolbar = this@NeoTabDecorator.context.toolbar
|
||||
toolbar.title = if (tabSwitcher.isSwitcherShown) null else tab.title
|
||||
|
||||
if (tab is TermTab) {
|
||||
tab.toolbar = toolbar
|
||||
}
|
||||
when (viewType) {
|
||||
VIEW_TYPE_TERM -> {
|
||||
val termTab = tab as TermTab
|
||||
termTab.toolbar = toolbar
|
||||
val terminalView = findViewById<TerminalView>(R.id.terminal_view)
|
||||
val extraKeysView = findViewById<ExtraKeysView>(R.id.extra_keys)
|
||||
bindTerminalView(termTab, terminalView, extraKeysView)
|
||||
terminalView.requestFocus()
|
||||
}
|
||||
|
||||
val terminalView = findViewById<TerminalView>(R.id.terminal_view)
|
||||
val extraKeysView = findViewById<ExtraKeysView>(R.id.extra_keys)
|
||||
bindTerminalView(tab, terminalView, extraKeysView)
|
||||
terminalView.requestFocus()
|
||||
VIEW_TYPE_X -> {
|
||||
val xtab = tab as XSessionTab
|
||||
bindXSessionView(tab)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindXSessionView(tab: XSessionTab) {
|
||||
}
|
||||
|
||||
private fun bindTerminalView(tab: Tab, view: TerminalView?, extraKeysView: ExtraKeysView?) {
|
||||
@ -84,10 +110,15 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
||||
}
|
||||
|
||||
override fun getViewTypeCount(): Int {
|
||||
return 1
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun getViewType(tab: Tab, index: Int): Int {
|
||||
if (tab is TermTab) {
|
||||
return VIEW_TYPE_TERM
|
||||
} else if (tab is XSessionTab) {
|
||||
return VIEW_TYPE_X
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package io.neoterm.ui.term.tab
|
||||
|
||||
import de.mrapp.android.tabswitcher.Tab
|
||||
import io.neoterm.frontend.xorg.XSession
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class XSessionTab(title: CharSequence) : Tab(title) {
|
||||
|
||||
var session: XSession? = null
|
||||
}
|
||||
|
12
app/src/main/res/layout/ui_xorg.xml
Normal file
12
app/src/main/res/layout/ui_xorg.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello X Server! Comming soon."/>
|
||||
|
||||
</RelativeLayout>
|
@ -75,7 +75,7 @@
|
||||
<string name="crash_app">应用: %s</string>
|
||||
<string name="crash_stack_trace">堆栈信息</string>
|
||||
<string name="crash_tips">我们正努力让这个 Activity 永不见天日…</string>
|
||||
<string name="service_status_text">%d 个会话</string>
|
||||
<string name="service_status_text">%d 个会话, %d 个图形会话</string>
|
||||
<string name="service_lock_acquired"> (永不休眠)</string>
|
||||
<string name="service_acquire_lock">取得休眠锁</string>
|
||||
<string name="service_release_lock">释放休眠锁</string>
|
||||
|
@ -70,7 +70,7 @@
|
||||
<string name="crash_app">程式: %s</string>
|
||||
<string name="crash_stack_trace">錯誤訊息</string>
|
||||
<string name="crash_tips">我們正在努力讓這個 Activity 永不見天日…</string>
|
||||
<string name="service_status_text">%d 個會話</string>
|
||||
<string name="service_status_text">%d 個會話, %d 個图形會話</string>
|
||||
<string name="service_lock_acquired"> (永不休眠)</string>
|
||||
<string name="service_acquire_lock">開啟休眠鎖</string>
|
||||
<string name="service_release_lock">關閉休眠鎖</string>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<string name="toggle_tab_switcher_menu_item">Toggle Tabs</string>
|
||||
<string name="new_session">New Session</string>
|
||||
<string name="new_system_session">New System Shell</string>
|
||||
<string name="service_status_text">%d session(s)</string>
|
||||
<string name="service_status_text">%d session(s), %d X session(s)</string>
|
||||
<string name="service_lock_acquired"> (Wake Locked)</string>
|
||||
<string name="service_acquire_lock">Acquire Lock</string>
|
||||
<string name="service_release_lock">Release Lock</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user