Compare commits

...

34 Commits
v0.54 ... v0.60

Author SHA1 Message Date
Fredrik Fornwall
48fab33b79 Bump version to 0.60 2018-01-26 01:00:37 +01:00
Marcel Dopita
8d7a67645b Fix notification icon color
Icons used in notifications/status bar are monochrome and should use only white color and transparency. It is displayed fine on Android emulators but it's shown in black on Samsung Galaxy S7 running Android 7.0.

After the change, status bar icon is white and the small icon in notification still uses the black color set via setColor(). Termux doesn't support devices running Android older than 5.0 but using white color in vector drawables would be also necessary to generate proper (white) bitmap icons.
2018-01-01 23:17:22 +01:00
Fredrik Fornwall
186b49d429 Work around travis API 27 SDK checksum mismatch
See https://github.com/travis-ci/travis-ci/issues/8874.
2018-01-01 23:16:43 +01:00
Fredrik Fornwall
40a2775f52 Bump version to 0.59 2017-12-09 00:59:19 +01:00
Fredrik Fornwall
f802d6001d Do not send mouse clicks out of range (fixes #501) 2017-12-09 00:58:31 +01:00
Fredrik Fornwall
50f66a12da Bump version to 0.58 2017-12-08 23:32:44 +01:00
Fredrik Fornwall
d8e6fd21d1 Set android:resizeableActivity="true"
Setting android:resizeableActivity="true" should AFAIK not be needed
as https://developer.android.com/guide/topics/ui/multi-window.html
states that:

  If your app targets API level 24, but you do not specify a value
  for this attribute, the attribute's value defaults to true.

However, on a Galaxy S8 running Android 7.0 this attribute is needed
in order to have resizeable windows when in Samsung Dex mode.

Fixes #309.
2017-12-08 23:30:45 +01:00
Fredrik Fornwall
0964d83572 Bump com.android.support dependencies 2017-12-07 10:25:02 +01:00
Fredrik Fornwall
cee0466dd7 Bump version to 0.57 2017-12-07 01:48:51 +01:00
Fredrik Fornwall
de4f334e24 Remove the fullscreen setting
Trying to use fullscreen doesn't work well in a multi-windowed world
and makes using translucent navigation and status bars more complicated.
2017-12-07 01:46:16 +01:00
Fredrik Fornwall
ab205ae05b Update build tools in travis 2017-12-07 01:45:30 +01:00
Fredrik Fornwall
b29b24f507 Add android.max_aspect=10.0 metadata
This is needed to mark the app with

	"This app is optimized to run in full screen"

when run on a Samsung Galaxy S8.
2017-12-07 01:39:43 +01:00
Fredrik Fornwall
b3472e9e62 Disable the "quick scale" gesture
Disable the default android behaviour where a double tap followed by a
swipe is interpreted as a zoom gesture. Most people seem not to know
about it and hit it by mistake, see #495 for an example.
2017-12-07 01:36:29 +01:00
Fredrik Fornwall
ab59e08959 Update build tools 2017-12-07 01:12:39 +01:00
Fredrik Fornwall
8b566485e8 Do not clear the sessions on ACTION_STOP_SERVICE
There is no point doing so and it may cause problems with the list
adapter.
2017-11-26 00:56:13 +01:00
Fredrik Fornwall
231c02a0c7 Check for null mTermSession in inputCodePoint() 2017-11-26 00:50:13 +01:00
Fredrik Fornwall
65f30e77ba Add tools:ignore="AppLinkUrlError" 2017-11-25 22:59:03 +01:00
Fredrik Fornwall
686677ae45 Update android support dependencies 2017-11-25 22:58:46 +01:00
Fredrik Fornwall
85037a75a6 Remove redundant cast 2017-11-25 22:58:23 +01:00
Fredrik Fornwall
6025afc2c0 Update the Android Plugin for Gradle to 3.0.1 2017-11-24 23:11:55 +01:00
Fredrik Fornwall
a4e4f76775 Remove some Android Studio warnings 2017-11-22 01:27:14 +01:00
Fredrik Fornwall
02af113dda Bump app version to 0.56 2017-11-19 20:54:16 +01:00
Fredrik Fornwall
fc4ef838bf Configure proguard to keep line numbers 2017-11-19 20:53:56 +01:00
Fredrik Fornwall
86bd3ca21b Bump app version to 0.54 2017-11-19 15:27:17 +01:00
Fredrik Fornwall
367398bafb Update gradle configuration 2017-11-19 15:27:00 +01:00
Lauri Tirkkonen
dd502e55f8 set default notification priority to low
since we're a foreground service, in oreo we already get a higher
priority; see
https://developer.android.com/reference/android/app/NotificationManager.html#IMPORTANCE_MIN
2017-11-12 23:44:14 +01:00
Fredrik Fornwall
798125ef7a Remove outdated comment 2017-11-12 23:06:28 +01:00
Fredrik Fornwall
5126f06e06 Update .travis.yml to latest setup 2017-11-12 22:30:09 +01:00
Fredrik Fornwall
0bdbf314ef Update gradle configuration 2017-11-07 04:25:48 +01:00
Fredrik Fornwall
2deb9899bd Update buildToolsVersion to 27.0.1 2017-11-07 04:13:26 +01:00
Fredrik Fornwall
694ccc38c4 Remove WakefulBroadcastReceiver usage 2017-11-04 23:38:49 +01:00
Fredrik Fornwall
c949940374 Update support deps 2017-11-02 01:56:42 +01:00
Fredrik Fornwall
d09f70de1e Use a notification channel on Android O 2017-11-01 21:15:41 +01:00
Fredrik Fornwall
ac338ce2c5 Update gradle to 4.3 2017-10-31 19:07:00 +01:00
24 changed files with 106 additions and 168 deletions

View File

@@ -12,13 +12,14 @@ android:
components:
- platform-tools
- tools
- build-tools-27.0.0
- android-26
- build-tools-27.0.2
- android-27
- extra-android-m2repository
before_install:
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk
- export ANDROID_NDK_HOME=$HOME/android-ndk
- yes | sdkmanager "platforms;android-27"
script:
- ./gradlew testDebugUnitTest

View File

@@ -1,22 +1,21 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "27.0.0"
compileSdkVersion 27
buildToolsVersion "27.0.2"
dependencies {
compile 'com.android.support:support-annotations:27.0.0'
compile "com.android.support:support-core-utils:26.1.0"
compile "com.android.support:support-core-ui:26.1.0"
compile project(":terminal-view")
implementation 'com.android.support:support-annotations:27.0.2'
implementation "com.android.support:support-core-ui:27.0.2"
implementation project(":terminal-view")
}
defaultConfig {
applicationId "com.termux"
minSdkVersion 21
targetSdkVersion 26
versionCode 54
versionName "0.54"
targetSdkVersion 27
versionCode 60
versionName "0.60"
}
buildTypes {
@@ -29,5 +28,5 @@ android {
}
dependencies {
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
}

View File

@@ -7,11 +7,5 @@
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable

View File

@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.termux"
android:installLocation="internalOnly"
android:sharedUserId="com.termux"
@@ -23,10 +24,15 @@
android:theme="@style/Theme.Termux"
android:supportsRtl="false" >
<!-- This (or rather, value 2.1 or higher) is needed to make the Samsung Galaxy S8
mark the app with "This app is optimized to run in full screen." -->
<meta-data android:name="android.max_aspect" android:value="10.0" />
<activity
android:name="com.termux.app.TermuxActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:windowSoftInputMode="adjustResize|stateAlwaysVisible" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -44,6 +50,7 @@
android:exported="false"
android:theme="@android:style/Theme.Material.Light.DarkActionBar"
android:parentActivityName=".app.TermuxActivity"
android:resizeableActivity="true"
android:label="@string/application_name" />
<activity
@@ -51,6 +58,7 @@
android:label="@string/application_name"
android:taskAffinity="com.termux.filereceiver"
android:excludeFromRecents="true"
android:resizeableActivity="true"
android:noHistory="true">
<!-- Accept multiple file types when sending. -->
<intent-filter>
@@ -65,7 +73,7 @@
<data android:mimeType="video/*" />
</intent-filter>
<!-- Be more restrictive for viewing files, restricting ourselves to text files. -->
<intent-filter>
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />

View File

@@ -61,7 +61,7 @@ public final class ExtraKeysView extends GridLayout {
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
} else {
TerminalView terminalView = (TerminalView) view.findViewById(R.id.terminal_view);
TerminalView terminalView = view.findViewById(R.id.terminal_view);
TerminalSession session = terminalView.getCurrentSession();
if (session != null) session.write(chars);
}

View File

@@ -1,67 +0,0 @@
package com.termux.app;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.view.View;
import com.termux.R;
/**
* Utility to manage full screen immersive mode.
* <p/>
* See https://code.google.com/p/android/issues/detail?id=5497
*/
final class FullScreenHelper {
private boolean mEnabled = false;
final TermuxActivity mActivity;
public FullScreenHelper(TermuxActivity activity) {
this.mActivity = activity;
}
public void setImmersive(boolean enabled) {
if (enabled == mEnabled) return;
mEnabled = enabled;
View decorView = mActivity.getWindow().getDecorView();
if (enabled) {
decorView.setOnSystemUiVisibilityChangeListener
(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
if (mActivity.mSettings.isShowExtraKeys()) {
mActivity.findViewById(R.id.viewpager).setVisibility(View.VISIBLE);
}
setImmersiveMode();
} else {
mActivity.findViewById(R.id.viewpager).setVisibility(View.GONE);
}
}
});
setImmersiveMode();
} else {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
decorView.setOnSystemUiVisibilityChangeListener(null);
}
}
private static boolean isColorLight(int color) {
double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
return darkness < 0.5;
}
void setImmersiveMode() {
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN;
int color = ((ColorDrawable) mActivity.getWindow().getDecorView().getBackground()).getColor();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && isColorLight(color))
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
mActivity.getWindow().getDecorView().setSystemUiVisibility(flags);
}
}

View File

@@ -73,6 +73,7 @@ import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -95,7 +96,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
private static final int CONTEXTMENU_KILL_PROCESS_ID = 4;
private static final int CONTEXTMENU_RESET_TERMINAL_ID = 5;
private static final int CONTEXTMENU_STYLING_ID = 6;
private static final int CONTEXTMENU_TOGGLE_FULLSCREEN_ID = 7;
private static final int CONTEXTMENU_HELP_ID = 8;
private static final int MAX_SESSIONS = 8;
@@ -111,8 +111,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
ExtraKeysView mExtraKeysView;
final FullScreenHelper mFullScreenHelper = new FullScreenHelper(this);
TermuxPreferences mSettings;
/**
@@ -157,7 +155,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
void checkForFontAndColors() {
try {
// Hard-coded paths since this file is used also in Termux:Float.
@SuppressLint("SdCardPath") File fontFile = new File("/data/data/com.termux/files/home/.termux/font.ttf");
@SuppressLint("SdCardPath") File colorsFile = new File("/data/data/com.termux/files/home/.termux/colors.properties");
@@ -212,14 +209,13 @@ public final class TermuxActivity extends Activity implements ServiceConnection
mSettings = new TermuxPreferences(this);
setContentView(R.layout.drawer_layout);
mTerminalView = (TerminalView) findViewById(R.id.terminal_view);
mTerminalView = findViewById(R.id.terminal_view);
mTerminalView.setOnKeyListener(new TermuxViewClient(this));
mTerminalView.setTextSize(mSettings.getFontSize());
mFullScreenHelper.setImmersive(mSettings.isFullScreen());
mTerminalView.requestFocus();
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
final ViewPager viewPager = findViewById(R.id.viewpager);
if (mSettings.isShowExtraKeys()) viewPager.setVisibility(View.VISIBLE);
viewPager.setAdapter(new PagerAdapter() {
@@ -229,19 +225,20 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
@Override
public boolean isViewFromObject(View view, Object object) {
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(ViewGroup collection, int position) {
public Object instantiateItem(@NonNull ViewGroup collection, int position) {
LayoutInflater inflater = LayoutInflater.from(TermuxActivity.this);
View layout;
if (position == 0) {
layout = mExtraKeysView = (ExtraKeysView) inflater.inflate(R.layout.extra_keys_main, collection, false);
} else {
layout = inflater.inflate(R.layout.extra_keys_right, collection, false);
final EditText editText = (EditText) layout.findViewById(R.id.text_input);
final EditText editText = layout.findViewById(R.id.text_input);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
@@ -265,7 +262,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
public void destroyItem(@NonNull ViewGroup collection, int position, @NonNull Object view) {
collection.removeView((View) view);
}
});
@@ -276,7 +273,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
if (position == 0) {
mTerminalView.requestFocus();
} else {
final EditText editText = (EditText) viewPager.findViewById(R.id.text_input);
final EditText editText = viewPager.findViewById(R.id.text_input);
if (editText != null) editText.requestFocus();
}
}
@@ -340,7 +337,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
void toggleShowExtraKeys() {
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
final ViewPager viewPager = findViewById(R.id.viewpager);
final boolean showNow = mSettings.toggleShowExtraKeys(TermuxActivity.this);
viewPager.setVisibility(showNow ? View.VISIBLE : View.GONE);
if (showNow && viewPager.getCurrentItem() == 1) {
@@ -425,7 +422,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
};
ListView listView = (ListView) findViewById(R.id.left_drawer_list);
ListView listView = findViewById(R.id.left_drawer_list);
mListViewAdapter = new ArrayAdapter<TerminalSession>(getApplicationContext(), R.layout.line_in_drawer, mTermService.getSessions()) {
final StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
final StyleSpan italicSpan = new StyleSpan(Typeface.ITALIC);
@@ -442,7 +439,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
TerminalSession sessionAtRow = getItem(position);
boolean sessionRunning = sessionAtRow.isRunning();
TextView firstLineView = (TextView) row.findViewById(R.id.row_line);
TextView firstLineView = row.findViewById(R.id.row_line);
String name = sessionAtRow.mSessionName;
String sessionTitle = sessionAtRow.getTitle();
@@ -538,10 +535,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
@Override
public void onServiceDisconnected(ComponentName name) {
if (mTermService != null) {
// Respect being stopped from the TermuxService notification action.
finish();
}
// Respect being stopped from the TermuxService notification action.
finish();
}
@Nullable
@@ -645,7 +640,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
final int indexOfSession = mTermService.getSessions().indexOf(session);
showToast(toToastTitle(session), false);
mListViewAdapter.notifyDataSetChanged();
final ListView lv = ((ListView) findViewById(R.id.left_drawer_list));
final ListView lv = findViewById(R.id.left_drawer_list);
lv.setItemChecked(indexOfSession, true);
lv.smoothScrollToPosition(indexOfSession);
}
@@ -659,7 +654,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
menu.add(Menu.NONE, CONTEXTMENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.select_all_and_share);
menu.add(Menu.NONE, CONTEXTMENU_RESET_TERMINAL_ID, Menu.NONE, R.string.reset_terminal);
menu.add(Menu.NONE, CONTEXTMENU_KILL_PROCESS_ID, Menu.NONE, getResources().getString(R.string.kill_process, getCurrentTermSession().getPid())).setEnabled(currentSession.isRunning());
menu.add(Menu.NONE, CONTEXTMENU_TOGGLE_FULLSCREEN_ID, Menu.NONE, R.string.toggle_fullscreen).setCheckable(true).setChecked(mSettings.isFullScreen());
menu.add(Menu.NONE, CONTEXTMENU_STYLING_ID, Menu.NONE, R.string.style_terminal);
menu.add(Menu.NONE, CONTEXTMENU_HELP_ID, Menu.NONE, R.string.help);
}
@@ -793,11 +787,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
}).setNegativeButton(android.R.string.cancel, null).show();
}
}
return true;
case CONTEXTMENU_TOGGLE_FULLSCREEN_ID:
toggleImmersive();
return true;
}
case CONTEXTMENU_HELP_ID:
startActivity(new Intent(this, TermuxHelpActivity.class));
return true;
@@ -813,12 +804,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
}
}
void toggleImmersive() {
boolean newValue = !mSettings.isFullScreen();
mSettings.setFullScreen(this, newValue);
mFullScreenHelper.setImmersive(newValue);
}
void changeFontSize(boolean increase) {
mSettings.changeFontSize(this, increase);
mTerminalView.setTextSize(mSettings.getFontSize());
@@ -837,9 +822,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
public TerminalSession getStoredCurrentSessionOrLast() {
TerminalSession stored = TermuxPreferences.getCurrentSession(this);
if (stored != null) return stored;
int numberOfSessions = mTermService.getSessions().size();
if (numberOfSessions == 0) return null;
return mTermService.getSessions().get(numberOfSessions - 1);
List<TerminalSession> sessions = mTermService.getSessions();
return sessions.isEmpty() ? null : sessions.get(sessions.size() - 1);
}
/** Show a toast and dismiss the last one if still visible. */

View File

@@ -32,12 +32,10 @@ final class TermuxPreferences {
private final int MIN_FONTSIZE;
private static final int MAX_FONTSIZE = 256;
private static final String FULLSCREEN_KEY = "fullscreen";
private static final String SHOW_EXTRA_KEYS_KEY = "show_extra_keys";
private static final String FONTSIZE_KEY = "fontsize";
private static final String CURRENT_SESSION_KEY = "current_session";
private boolean mFullScreen;
private int mFontSize;
@AsciiBellBehaviour
@@ -56,7 +54,6 @@ final class TermuxPreferences {
// to prevent invisible text due to zoom be mistake:
MIN_FONTSIZE = (int) (4f * dipInPixels);
mFullScreen = prefs.getBoolean(FULLSCREEN_KEY, false);
mShowExtraKeys = prefs.getBoolean(SHOW_EXTRA_KEYS_KEY, false);
// http://www.google.com/design/spec/style/typography.html#typography-line-height
@@ -72,15 +69,6 @@ final class TermuxPreferences {
mFontSize = Math.max(MIN_FONTSIZE, Math.min(mFontSize, MAX_FONTSIZE));
}
boolean isFullScreen() {
return mFullScreen;
}
void setFullScreen(Context context, boolean newValue) {
mFullScreen = newValue;
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(FULLSCREEN_KEY, newValue).apply();
}
boolean isShowExtraKeys() {
return mShowExtraKeys;
}

View File

@@ -2,6 +2,7 @@ package com.termux.app;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@@ -11,10 +12,10 @@ import android.content.res.Resources;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
import android.widget.ArrayAdapter;
@@ -41,6 +42,8 @@ import java.util.List;
*/
public final class TermuxService extends Service implements SessionChangedCallback {
private static final String NOTIFICATION_CHANNEL_ID = "termux_notification_channel";
/** Note that this is a symlink on the Android M preview. */
@SuppressLint("SdCardPath")
public static final String FILES_PATH = "/data/data/com.termux/files";
@@ -153,11 +156,6 @@ public final class TermuxService extends Service implements SessionChangedCallba
Log.e(EmulatorDebug.LOG_TAG, "Unknown TermuxService action: '" + action + "'");
}
if ((flags & START_FLAG_REDELIVERY) == 0) {
// Service is started by WBR, not restarted by system, so release the WakeLock from WBR.
WakefulBroadcastReceiver.completeWakefulIntent(intent);
}
// If this service really do get killed, there is no point restarting it automatically - let the user do on next
// start of {@link Term):
return Service.START_NOT_STICKY;
@@ -170,6 +168,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
@Override
public void onCreate() {
setupNotificationChannel();
startForeground(NOTIFICATION_ID, buildNotification());
}
@@ -208,8 +207,8 @@ public final class TermuxService extends Service implements SessionChangedCallba
builder.setOngoing(true);
// If holding a wake or wifi lock consider the notification of high priority since it's using power,
// otherwise use a minimal priority since this is just a background service notification:
builder.setPriority((wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_MIN);
// otherwise use a low priority
builder.setPriority((wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_LOW);
// No need to show a timestamp:
builder.setShowWhen(false);
@@ -217,6 +216,10 @@ public final class TermuxService extends Service implements SessionChangedCallba
// Background color for small notification icon:
builder.setColor(0xFF000000);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
Resources res = getResources();
Intent exitIntent = new Intent(this, TermuxService.class).setAction(ACTION_STOP_SERVICE);
builder.addAction(android.R.drawable.ic_delete, res.getString(R.string.notification_action_exit), PendingIntent.getService(this, 0, exitIntent, 0));
@@ -241,7 +244,6 @@ public final class TermuxService extends Service implements SessionChangedCallba
for (int i = 0; i < mTerminalSessions.size(); i++)
mTerminalSessions.get(i).finishIfRunning();
mTerminalSessions.clear();
}
public List<TerminalSession> getSessions() {
@@ -341,4 +343,17 @@ public final class TermuxService extends Service implements SessionChangedCallba
}
});
}
private void setupNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
String channelName = "Termux";
String channelDescription = "Notifications from Termux";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,importance);
channel.setDescription(channelDescription);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
}
}

View File

@@ -73,8 +73,6 @@ public final class TermuxViewClient implements TerminalViewClient {
mActivity.getDrawer().openDrawer(Gravity.LEFT);
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
mActivity.getDrawer().closeDrawers();
} else if (unicodeChar == 'f'/* full screen */) {
mActivity.toggleImmersive();
} else if (unicodeChar == 'k'/* keyboard */) {
InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

View File

@@ -9,7 +9,7 @@
<!-- Screen border. -->
<path android:fillColor="#00000000"
android:strokeColor="#000"
android:strokeColor="#FFF"
android:strokeWidth="3"
android:pathData="M7,4
l34,0
@@ -23,7 +23,7 @@
/>
<!-- Block cursor. -->
<path android:fillColor="#000"
<path android:fillColor="#FFF"
android:pathData="M14,14
l5,0
l0,10

View File

@@ -1,7 +1,8 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:fitsSystemWindows="true">
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"

View File

@@ -7,7 +7,6 @@
<string name="toggle_soft_keyboard">Keyboard</string>
<string name="reset_terminal">Reset</string>
<string name="style_terminal">Style</string>
<string name="toggle_fullscreen">Fullscreen</string>
<string name="share_transcript_title">Terminal transcript</string>
<string name="help">Help</string>

View File

@@ -15,6 +15,9 @@
selecting text on pre-6.0 (non-floating toolbar). -->
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<!-- https://developer.android.com/training/tv/start/start.html#transition-color -->
<item name="android:windowAllowReturnTransitionOverlap">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>

View File

@@ -4,7 +4,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
classpath 'com.android.tools.build:gradle:3.0.1'
}
}

Binary file not shown.

View File

@@ -1,4 +1,4 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists

View File

@@ -1,5 +1,4 @@
// Start https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle
apply plugin: 'com.github.dcendents.android-maven'
group = publishedGroupId // Maven Group ID for the artifact
install {
repositories.mavenInstaller {

View File

@@ -13,16 +13,16 @@ ext {
libraryDescription = 'The terminal emulator used in Termux'
siteUrl = 'https://github.com/termux/termux'
gitUrl = 'https://github.com/termux/termux.git'
libraryVersion = '0.51'
libraryVersion = '0.52'
}
android {
compileSdkVersion 26
buildToolsVersion "27.0.0"
compileSdkVersion 27
buildToolsVersion "27.0.2"
defaultConfig {
minSdkVersion 21
targetSdkVersion 26
targetSdkVersion 27
externalNativeBuild {
ndkBuild {
@@ -56,7 +56,7 @@ tasks.withType(Test) {
}
dependencies {
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
}
apply from: '../scripts/bintray-publish.gradle'

View File

@@ -301,6 +301,11 @@ public final class TerminalEmulator {
* @param mouseButton one of the MOUSE_* constants of this class.
*/
public void sendMouseEvent(int mouseButton, int column, int row, boolean pressed) {
if (column < 1) column = 1;
if (column > mColumns) column = mColumns;
if (row < 1) row = 1;
if (row > mRows) row = mRows;
if (mouseButton == MOUSE_LEFT_BUTTON_MOVED && !isDecsetInternalBitSet(DECSET_BIT_MOUSE_TRACKING_BUTTON_EVENT)) {
// Do not send tracking.
} else if (isDecsetInternalBitSet(DECSET_BIT_MOUSE_PROTOCOL_SGR)) {
@@ -308,7 +313,7 @@ public final class TerminalEmulator {
} else {
mouseButton = pressed ? mouseButton : 3; // 3 for release of all buttons.
// Clip to screen, and clip to the limits of 8-bit data.
boolean out_of_bounds = column < 1 || row < 1 || column > mColumns || row > mRows || column > 255 - 32 || row > 255 - 32;
boolean out_of_bounds = column > 255 - 32 || row > 255 - 32;
if (!out_of_bounds) {
byte[] data = {'\033', '[', 'M', (byte) (32 + mouseButton), (byte) (32 + column), (byte) (32 + row)};
mSession.write(data, 0, data.length);

View File

@@ -55,6 +55,14 @@ public class TerminalTest extends TerminalTestCase {
assertEquals("\033[<0;3;4M", mOutput.getOutputAndClear());
mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 3, 4, false);
assertEquals("\033[<0;3;4m", mOutput.getOutputAndClear());
// When the client says that a click is outside (which could happen when pixels are outside
// the terminal area, see https://github.com/termux/termux-app/issues/501) the terminal
// sends a click at the edge.
mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 0, 0, true);
assertEquals("\033[<0;1;1M", mOutput.getOutputAndClear());
mTerminal.sendMouseEvent(TerminalEmulator.MOUSE_LEFT_BUTTON, 11, 11, false);
assertEquals("\033[<0;10;10m", mOutput.getOutputAndClear());
}
public void testNormalization() throws UnsupportedEncodingException {

View File

@@ -1,6 +1,6 @@
plugins {
id "com.jfrog.bintray" version "1.7"
id "com.github.dcendents.android-maven" version "1.5"
id "com.jfrog.bintray" version "1.7.3"
id "com.github.dcendents.android-maven" version "2.0"
}
apply plugin: 'com.android.library'
@@ -13,21 +13,21 @@ ext {
libraryDescription = 'The terminal view used in Termux'
siteUrl = 'https://github.com/termux/termux'
gitUrl = 'https://github.com/termux/termux.git'
libraryVersion = '0.49'
libraryVersion = '0.50'
}
android {
compileSdkVersion 26
buildToolsVersion "27.0.0"
compileSdkVersion 27
buildToolsVersion "27.0.2"
dependencies {
compile 'com.android.support:support-annotations:25.3.1'
compile project(":terminal-emulator")
implementation 'com.android.support:support-annotations:27.0.0'
api project(":terminal-emulator")
}
defaultConfig {
minSdkVersion 21
targetSdkVersion 26
targetSdkVersion 27
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
@@ -40,7 +40,7 @@ android {
}
dependencies {
testCompile 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
}
apply from: '../scripts/bintray-publish.gradle'

View File

@@ -85,6 +85,7 @@ final class GestureAndScaleRecognizer {
return mListener.onScale(detector.getFocusX(), detector.getFocusY(), detector.getScaleFactor());
}
});
mScaleDetector.setQuickScaleEnabled(false);
}
public void onTouchEvent(MotionEvent event) {

View File

@@ -642,6 +642,8 @@ public final class TerminalView extends View {
+ leftAltDownFromEvent + ")");
}
if (mTermSession == null) return;
final boolean controlDown = controlDownFromEvent || mClient.readControlKey();
final boolean altDown = leftAltDownFromEvent || mClient.readAltKey();