Skip to content

Commit df7491b

Browse files
committed
fix: notify all activities attachment state changed
1 parent 0a20cb7 commit df7491b

3 files changed

Lines changed: 53 additions & 31 deletions

File tree

app/src/main/java/com/termux/app/TermuxActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,14 @@ public void onDestroy() {
370370
mTermuxService.resetSessionClient(currentSession);
371371
}
372372
mTerminalView.detachSession();
373+
374+
// Notify other windows that session attachment state changed
375+
mTermuxService.notifyAllSessionListsUpdated();
373376
}
374377

375378
if (mTermuxService != null) {
379+
// Remove this activity's client from the service's set
380+
mTermuxService.removeTermuxTerminalSessionClient(mTermuxTerminalSessionActivityClient);
376381
mTermuxService = null;
377382
}
378383

app/src/main/java/com/termux/app/TermuxService.java

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@
5050
import com.termux.terminal.TerminalSessionClient;
5151

5252
import java.util.ArrayList;
53+
import java.util.HashSet;
5354
import java.util.List;
55+
import java.util.Set;
5456

5557
/**
5658
* A service holding a list of {@link TermuxSession} in {@link TermuxShellManager#mTermuxSessions} and background {@link AppShell}
@@ -77,11 +79,12 @@ class LocalBinder extends Binder {
7779
private final Handler mHandler = new Handler();
7880

7981

80-
/** The full implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
81-
* that holds activity references for activity related functions.
82-
* Note that the service may often outlive the activity, so need to clear this reference.
82+
/** The full implementations of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
83+
* that hold activity references for activity related functions. In multi-window mode, multiple
84+
* activities may be bound simultaneously. Note that the service may often outlive the activities,
85+
* so need to clear these references when activities are destroyed.
8386
*/
84-
private TermuxTerminalSessionActivityClient mTermuxTerminalSessionActivityClient;
87+
private final Set<TermuxTerminalSessionActivityClient> mActivityClients = new HashSet<>();
8588

8689
/** The basic implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
8790
* that does not hold activity references and only a service reference.
@@ -195,7 +198,7 @@ public boolean onUnbind(Intent intent) {
195198
// Since we cannot rely on {@link TermuxActivity.onDestroy()} to always complete,
196199
// we unset clients here as well if it failed, so that we do not leave service and session
197200
// clients with references to the activity.
198-
if (mTermuxTerminalSessionActivityClient != null)
201+
if (!mActivityClients.isEmpty())
199202
unsetTermuxTerminalSessionClient();
200203
return false;
201204
}
@@ -612,10 +615,8 @@ public synchronized TermuxSession createTermuxSession(ExecutionCommand execution
612615
if (executionCommand.isPluginExecutionCommand)
613616
mShellManager.mPendingPluginExecutionCommands.remove(executionCommand);
614617

615-
// Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
616-
// activity in is foreground
617-
if (mTermuxTerminalSessionActivityClient != null)
618-
mTermuxTerminalSessionActivityClient.termuxSessionListNotifyUpdated();
618+
// Notify all activities that sessions list has been updated
619+
notifyAllSessionListsUpdated();
619620

620621
updateNotification();
621622

@@ -649,10 +650,8 @@ public void onTermuxSessionExited(final TermuxSession termuxSession) {
649650

650651
mShellManager.mTermuxSessions.remove(termuxSession);
651652

652-
// Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
653-
// activity in is foreground
654-
if (mTermuxTerminalSessionActivityClient != null)
655-
mTermuxTerminalSessionActivityClient.termuxSessionListNotifyUpdated();
653+
// Notify all activities that sessions list has been updated
654+
notifyAllSessionListsUpdated();
656655
}
657656

658657
updateNotification();
@@ -687,8 +686,8 @@ private void handleSessionAction(int sessionAction, TerminalSession newTerminalS
687686
switch (sessionAction) {
688687
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY:
689688
setCurrentStoredTerminalSession(newTerminalSession);
690-
if (mTermuxTerminalSessionActivityClient != null)
691-
mTermuxTerminalSessionActivityClient.setCurrentSession(newTerminalSession);
689+
if (!mActivityClients.isEmpty())
690+
mActivityClients.iterator().next().setCurrentSession(newTerminalSession);
692691
startTermuxActivity();
693692
break;
694693
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_OPEN_ACTIVITY:
@@ -698,8 +697,8 @@ private void handleSessionAction(int sessionAction, TerminalSession newTerminalS
698697
break;
699698
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_DONT_OPEN_ACTIVITY:
700699
setCurrentStoredTerminalSession(newTerminalSession);
701-
if (mTermuxTerminalSessionActivityClient != null)
702-
mTermuxTerminalSessionActivityClient.setCurrentSession(newTerminalSession);
700+
if (!mActivityClients.isEmpty())
701+
mActivityClients.iterator().next().setCurrentSession(newTerminalSession);
703702
break;
704703
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_DONT_OPEN_ACTIVITY:
705704
if (getTermuxSessionsSize() == 1)
@@ -731,40 +730,44 @@ private void startTermuxActivity() {
731730

732731

733732

734-
/** If {@link TermuxActivity} has not bound to the {@link TermuxService} yet or is destroyed, then
733+
/** If no {@link TermuxActivity} has bound to the {@link TermuxService} yet or all are destroyed, then
735734
* interface functions requiring the activity should not be available to the terminal sessions,
736735
* so we just return the {@link #mTermuxTerminalSessionServiceClient}. Once {@link TermuxActivity} bind
737-
* callback is received, it should call {@link #setTermuxTerminalSessionClient} to set the
738-
* {@link TermuxService#mTermuxTerminalSessionActivityClient} so that further terminal sessions are directly
739-
* passed the {@link TermuxTerminalSessionActivityClient} object which fully implements the
736+
* callback is received, it should call {@link #setTermuxTerminalSessionClient} to add its client
737+
* to {@link TermuxService#mActivityClients} so that further terminal sessions are directly
738+
* passed a {@link TermuxTerminalSessionActivityClient} object which fully implements the
740739
* {@link TerminalSessionClient} interface.
741740
*
742-
* @return Returns the {@link TermuxTerminalSessionActivityClient} if {@link TermuxActivity} has bound with
743-
* {@link TermuxService}, otherwise {@link TermuxTerminalSessionServiceClient}.
741+
* @return Returns the first available {@link TermuxTerminalSessionActivityClient} if any {@link TermuxActivity}
742+
* has bound with {@link TermuxService}, otherwise {@link TermuxTerminalSessionServiceClient}.
744743
*/
745744
public synchronized TermuxTerminalSessionClientBase getTermuxTerminalSessionClient() {
746-
if (mTermuxTerminalSessionActivityClient != null)
747-
return mTermuxTerminalSessionActivityClient;
745+
if (!mActivityClients.isEmpty())
746+
return mActivityClients.iterator().next();
748747
else
749748
return mTermuxTerminalSessionServiceClient;
750749
}
751750

752-
/** This should be called when {@link TermuxActivity#onServiceConnected} is called to set the
753-
* {@link TermuxService#mTermuxTerminalSessionActivityClient} variable and update the {@link TerminalSession}
754-
* and {@link TerminalEmulator} clients in case they were passed {@link TermuxTerminalSessionServiceClient}
755-
* earlier.
751+
/** This should be called when {@link TermuxActivity#onServiceConnected} is called to add
752+
* the activity's client to {@link TermuxService#mActivityClients}. In multi-window mode,
753+
* multiple activities may be bound simultaneously.
756754
*
757755
* @param termuxTerminalSessionActivityClient The {@link TermuxTerminalSessionActivityClient} object that fully
758756
* implements the {@link TerminalSessionClient} interface.
759757
*/
760758
public synchronized void setTermuxTerminalSessionClient(TermuxTerminalSessionActivityClient termuxTerminalSessionActivityClient) {
761-
mTermuxTerminalSessionActivityClient = termuxTerminalSessionActivityClient;
759+
mActivityClients.add(termuxTerminalSessionActivityClient);
762760

763761
// Don't update all sessions' clients here - in multi-window mode, each activity
764762
// should only set the client for its own attached session. The client is set
765763
// when setCurrentSession() is called in TermuxTerminalSessionActivityClient.
766764
}
767765

766+
/** Remove an activity client when its activity is destroyed. */
767+
public synchronized void removeTermuxTerminalSessionClient(TermuxTerminalSessionActivityClient client) {
768+
mActivityClients.remove(client);
769+
}
770+
768771
/** This should be called when {@link TermuxActivity} has been destroyed and in {@link #onUnbind(Intent)}
769772
* so that the {@link TermuxService} and {@link TerminalSession} and {@link TerminalEmulator}
770773
* clients do not hold an activity references.
@@ -773,7 +776,7 @@ public synchronized void unsetTermuxTerminalSessionClient() {
773776
for (int i = 0; i < mShellManager.mTermuxSessions.size(); i++)
774777
mShellManager.mTermuxSessions.get(i).getTerminalSession().updateTerminalSessionClient(mTermuxTerminalSessionServiceClient);
775778

776-
mTermuxTerminalSessionActivityClient = null;
779+
mActivityClients.clear();
777780
}
778781

779782
/** Reset a specific session's client to the service client. Used when an activity is destroyed
@@ -784,6 +787,14 @@ public synchronized void resetSessionClient(TerminalSession session) {
784787
}
785788
}
786789

790+
/** Notify all bound activities to update their session lists. Used when session attachment
791+
* state changes in multi-window mode. */
792+
public synchronized void notifyAllSessionListsUpdated() {
793+
for (TermuxTerminalSessionActivityClient client : mActivityClients) {
794+
client.termuxSessionListNotifyUpdated();
795+
}
796+
}
797+
787798

788799

789800

app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ public void setCurrentSession(TerminalSession session) {
299299
if (mActivity.getTerminalView().attachSession(session)) {
300300
// notify about switched session if not already displaying the session
301301
notifyOfSessionChange();
302+
303+
// Notify all windows that session attachment state changed so they can update their lists
304+
TermuxService service = mActivity.getTermuxService();
305+
if (service != null) {
306+
service.notifyAllSessionListsUpdated();
307+
}
302308
}
303309

304310
// Set this activity's client on the session so it receives callbacks (render updates, etc.)

0 commit comments

Comments
 (0)