Improve overlapping LCD.

This commit is contained in:
dgis 2019-11-27 01:04:53 +01:00
parent 74c362d374
commit fccb189b24
7 changed files with 192 additions and 97 deletions

View file

@ -731,8 +731,6 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onObjectSave(JNIEn
JNIEXPORT void JNICALL Java_org_emulator_calculator_NativeLib_onViewCopy(JNIEnv *env, jobject thisz, jobject bitmapScreen) {
//jobject bitmapScreen = (*env)->NewGlobalRef(env, bitmapScreen0);
AndroidBitmapInfo bitmapScreenInfo;
int ret = AndroidBitmap_getInfo(env, bitmapScreen, &bitmapScreenInfo);
if (ret < 0) {

View file

@ -116,6 +116,7 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
#endif
TCHAR * foundDocumentScheme = _tcsstr(lpFileName, documentScheme);
TCHAR * urlContentSchemeFound = _tcsstr(lpFileName, contentScheme);
if(chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || chooseCurrentKmlMode == ChooseKmlMode_CHANGE_KML) {
// When we open a new E48 state document
@ -156,7 +157,10 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
}
}
if(!forceNormalFile && (szCurrentAssetDirectory || _tcsncmp(lpFileName, assetsPrefix, assetsPrefixLength) == 0) && foundDocumentScheme == NULL) {
if(!forceNormalFile
&& (szCurrentAssetDirectory || _tcsncmp(lpFileName, assetsPrefix, assetsPrefixLength) == 0)
&& foundDocumentScheme == NULL
&& urlContentSchemeFound == NULL) {
// Asset file
TCHAR szFileName[MAX_PATH];
AAsset * asset = NULL;
@ -201,7 +205,6 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
lpFileName = filename + 1;
}
TCHAR * urlContentSchemeFound = _tcsstr(lpFileName, contentScheme);
if(urlContentSchemeFound) {
// Case of an absolute file with the scheme content://
fd = openFileFromContentResolver(lpFileName, dwDesiredAccess);

View file

@ -27,19 +27,24 @@ public class LCDOverlappingView extends View {
private Bitmap bitmapLCD;
private float bitmapRatio = -1;
private float minViewSize = 200.0f;
private int overlappingLCDMode = 1;
public static int OVERLAPPING_LCD_MODE_NONE = 0;
public static int OVERLAPPING_LCD_MODE_AUTO = 1;
public static int OVERLAPPING_LCD_MODE_MANUAL = 2;
private int overlappingLCDMode = OVERLAPPING_LCD_MODE_AUTO;
private MainScreenView mainScreenView;
private boolean viewSized = false;
private boolean firstTime = true;
public LCDOverlappingView(Context context, MainScreenView mainScreenView) {
super(context);
this.mainScreenView = mainScreenView;
this.mainScreenView.setOnUpdateLayoutListener(() -> this.updateLayout(this.mainScreenView.viewPanOffsetX, this.mainScreenView.viewPanOffsetY, this.mainScreenView.viewScaleFactorX, this.mainScreenView.viewScaleFactorY));
this.mainScreenView.setOnUpdateLayoutListener(this::updateLayout);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
//paint.setFilterBitmap(true);
//paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setAntiAlias(true);
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
@ -59,6 +64,19 @@ public class LCDOverlappingView extends View {
return (float)Math.sqrt(x * x + y * y);
}
private MotionEvent currentDownEvent;
private MotionEvent previousUpEvent;
private boolean isDoubleTap(MotionEvent firstDown, MotionEvent firstUp, MotionEvent secondDown) {
long deltaTime = secondDown.getEventTime() - firstUp.getEventTime();
if (deltaTime > 300 || deltaTime < 40)
return false;
int deltaX = (int)firstDown.getX() - (int)secondDown.getX();
int deltaY = (int)firstDown.getY() - (int)secondDown.getY();
return deltaX * deltaX + deltaY * deltaY < 100 * 100;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(debug) Log.d(TAG, "onTouchEvent() getAction(): " + event.getAction() + ", getPointerCount(): " + event.getPointerCount());
@ -89,6 +107,19 @@ public class LCDOverlappingView extends View {
previousDownX0 = currentX0;
previousDownY0 = currentY0;
if(currentDownEvent != null && previousUpEvent != null && isDoubleTap(currentDownEvent, previousUpEvent, event)) {
// This is a double tap
if(debug) Log.d(TAG, "onTouchEvent() Double tap");
if(overlappingLCDMode != OVERLAPPING_LCD_MODE_AUTO)
post(() -> {
setOverlappingLCDMode(OVERLAPPING_LCD_MODE_AUTO);
changeOverlappingLCDModeToAuto();
});
}
if (currentDownEvent != null)
currentDownEvent.recycle();
currentDownEvent = MotionEvent.obtain(event);
break;
case MotionEvent.ACTION_MOVE:
//if(debug) Log.d(TAG, "touchesMoved count: " + touchCount);
@ -98,7 +129,7 @@ public class LCDOverlappingView extends View {
viewFlowLayout.leftMargin += currentX0 - previousDownX0;
viewFlowLayout.topMargin += currentY0 - previousDownY0;
setLayoutParams(viewFlowLayout);
changeOverlappingLCDMode();
changeOverlappingLCDModeToManual();
} else if (touchCount == 2) {
if(previousX0 != -1.0f) {
FrameLayout.LayoutParams viewFlowLayout = (FrameLayout.LayoutParams)getLayoutParams();
@ -143,7 +174,7 @@ public class LCDOverlappingView extends View {
+ ", width: " + viewFlowLayout.width + ", height: " + viewFlowLayout.height);
setLayoutParams(viewFlowLayout);
changeOverlappingLCDMode();
changeOverlappingLCDModeToManual();
}
previousX0 = currentX0;
previousY0 = currentY0;
@ -157,6 +188,10 @@ public class LCDOverlappingView extends View {
previousY0 = -1.0f;
previousX1 = -1.0f;
previousY1 = -1.0f;
if (previousUpEvent != null)
previousUpEvent.recycle();
previousUpEvent = MotionEvent.obtain(event);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
@ -170,9 +205,9 @@ public class LCDOverlappingView extends View {
protected void onDraw(Canvas canvas) {
//if(debug) Log.d(TAG, "onDraw()");
canvas.drawColor(Color.RED); //TODO to remove
//canvas.drawColor(Color.RED);
if(this.overlappingLCDMode > 0 && bitmapLCD != null) {
if(this.overlappingLCDMode != OVERLAPPING_LCD_MODE_NONE && bitmapLCD != null) {
int x = NativeLib.getScreenPositionX();
int y = NativeLib.getScreenPositionY();
srcBitmapCopy.set(x, y, x + NativeLib.getScreenWidth(), y + NativeLib.getScreenHeight());
@ -181,11 +216,12 @@ public class LCDOverlappingView extends View {
}
}
public int updateCallback(int type, int param1, int param2, String param3, String param4) {
if(this.overlappingLCDMode == 0)
return -1;
public void updateCallback(int type, int param1, int param2, String param3, String param4) {
if(this.overlappingLCDMode == OVERLAPPING_LCD_MODE_NONE)
return;
switch (type) {
case NativeLib.CALLBACK_TYPE_INVALIDATE:
//if(debug) Log.d(TAG, "PAINT updateCallback() postInvalidate()");
if(debug) Log.d(TAG, "updateCallback() CALLBACK_TYPE_INVALIDATE");
if(bitmapLCD.getWidth() > 1)
postInvalidate();
@ -205,13 +241,69 @@ public class LCDOverlappingView extends View {
if(oldBitmapLCD != null)
oldBitmapLCD.recycle();
if(this.overlappingLCDMode != 1) {
if(viewSized)
updateLayout();
}
break;
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(debug) Log.d(TAG, "onSizeChanged() width: " + w + ", height: " + h);
viewSized = true;
updateLayout();
}
public void updateLayout() {
if(debug) Log.d(TAG, "updateLayout()");
if(this.overlappingLCDMode != OVERLAPPING_LCD_MODE_NONE) {
int lcdWidth = Math.max(1, NativeLib.getScreenWidth());
int lcdHeight = Math.max(1, NativeLib.getScreenHeight());
if(this.overlappingLCDMode == OVERLAPPING_LCD_MODE_AUTO) {
float viewPanOffsetX = this.mainScreenView.viewPanOffsetX;
float viewPanOffsetY = this.mainScreenView.viewPanOffsetY;
float viewScaleFactorX = this.mainScreenView.viewScaleFactorX;
float viewScaleFactorY = this.mainScreenView.viewScaleFactorY;
int finalViewWidth = (int) (lcdWidth * viewScaleFactorX);
int finalViewHeight = (int) (lcdHeight * viewScaleFactorY);
post(() -> {
FrameLayout.LayoutParams viewFlowLayout = new FrameLayout.LayoutParams(finalViewWidth, finalViewHeight);
if(viewPanOffsetX > 0)
viewFlowLayout.leftMargin = (int)(viewScaleFactorX * NativeLib.getScreenPositionX() + viewPanOffsetX);
else
viewFlowLayout.leftMargin = this.mainScreenView.getWidth() - (int)(viewScaleFactorX * (this.mainScreenView.virtualSizeWidth - NativeLib.getScreenPositionX()));
if(viewPanOffsetY >= 0)
viewFlowLayout.topMargin = (int)(viewScaleFactorY * NativeLib.getScreenPositionY() + viewPanOffsetY);
else
viewFlowLayout.topMargin = (int)(viewScaleFactorY * NativeLib.getScreenPositionY());
int tolerance = 80;
if (viewFlowLayout.leftMargin + finalViewWidth < tolerance)
viewFlowLayout.leftMargin = 0;
if (viewFlowLayout.leftMargin + tolerance > this.mainScreenView.getWidth())
viewFlowLayout.leftMargin = this.mainScreenView.getWidth() - finalViewWidth;
if (viewFlowLayout.topMargin + finalViewHeight < tolerance)
viewFlowLayout.topMargin = 0;
if (viewFlowLayout.topMargin + tolerance > this.mainScreenView.getHeight())
viewFlowLayout.topMargin = this.mainScreenView.getHeight() - finalViewHeight;
if(debug) Log.d(TAG, "updateLayout() leftMargin: " + viewFlowLayout.leftMargin + ", topMargin: " + viewFlowLayout.topMargin
+ ", width: " + viewFlowLayout.width + ", height: " + viewFlowLayout.height);
setLayoutParams(viewFlowLayout);
setVisibility(View.VISIBLE);
});
} else if(this.overlappingLCDMode == OVERLAPPING_LCD_MODE_MANUAL) {
if(firstTime) {
firstTime = false;
float scale = sharedPreferences.getFloat("settings_lcd_overlapping_scale", 1.0f);
if (scale < 0.01f)
scale = 0.01f;
int viewWidth = (int) (newWidth * scale);
int viewHeight = (int) (newHeight * scale);
int viewWidth = (int) (lcdWidth * scale);
int viewHeight = (int) (lcdHeight * scale);
if (viewWidth < minViewSize && viewHeight < minViewSize) {
if (bitmapRatio > 0.0f) {
if (bitmapRatio < 1.0f) {
@ -227,42 +319,21 @@ public class LCDOverlappingView extends View {
}
}
FrameLayout.LayoutParams viewFlowLayout = new FrameLayout.LayoutParams(viewWidth, viewHeight);
int finalViewWidth = viewWidth;
int finalViewHeight = viewHeight;
post(() -> {
FrameLayout.LayoutParams viewFlowLayout = new FrameLayout.LayoutParams(finalViewWidth, finalViewHeight);
viewFlowLayout.leftMargin = sharedPreferences.getInt("settings_lcd_overlapping_x", 20);
viewFlowLayout.topMargin = sharedPreferences.getInt("settings_lcd_overlapping_y", 80);
if (viewFlowLayout.leftMargin + viewWidth < 0)
viewFlowLayout.leftMargin = 0;
if (viewFlowLayout.topMargin + viewHeight < 0)
viewFlowLayout.topMargin = 0;
setLayoutParams(viewFlowLayout);
}
}
break;
}
return -1;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(debug) Log.d(TAG, "onSizeChanged() width: " + w + ", height: " + h);
}
public void updateLayout(float viewPanOffsetX, float viewPanOffsetY, float viewScaleFactorX, float viewScaleFactorY) {
if(debug) Log.d(TAG, "updateLayout()");
if(this.overlappingLCDMode == 0) // No Overlapping LCD
return;
if(this.overlappingLCDMode == 1) { // Auto
int newLCDWidth = NativeLib.getScreenWidth();
int newLCDHeight = NativeLib.getScreenHeight();
int newWidth = Math.max(1, newLCDWidth);
int newHeight = Math.max(1, newLCDHeight);
post(() -> {
FrameLayout.LayoutParams viewFlowLayout = new FrameLayout.LayoutParams((int) (newWidth * viewScaleFactorX), (int) (newHeight * viewScaleFactorY));
viewFlowLayout.leftMargin = (int)(viewScaleFactorX * NativeLib.getScreenPositionX() + viewPanOffsetX);
viewFlowLayout.topMargin = (int)(viewScaleFactorY * NativeLib.getScreenPositionY() + viewPanOffsetY);
int tolerance = 80;
if (viewFlowLayout.leftMargin + finalViewWidth < tolerance)
viewFlowLayout.leftMargin = tolerance - finalViewWidth;
if (viewFlowLayout.leftMargin + tolerance > this.mainScreenView.getWidth())
viewFlowLayout.leftMargin = this.mainScreenView.getWidth() - tolerance;
if (viewFlowLayout.topMargin + finalViewHeight < tolerance)
viewFlowLayout.topMargin = tolerance - finalViewHeight;
if (viewFlowLayout.topMargin + tolerance > this.mainScreenView.getHeight())
viewFlowLayout.topMargin = this.mainScreenView.getHeight() - tolerance;
if(debug) Log.d(TAG, "updateLayout() leftMargin: " + viewFlowLayout.leftMargin + ", topMargin: " + viewFlowLayout.topMargin
+ ", width: " + viewFlowLayout.width + ", height: " + viewFlowLayout.height);
setLayoutParams(viewFlowLayout);
@ -270,9 +341,11 @@ public class LCDOverlappingView extends View {
});
}
}
}
}
public void saveViewLayout() {
if(this.overlappingLCDMode > 0)
if(this.overlappingLCDMode == OVERLAPPING_LCD_MODE_NONE)
return;
FrameLayout.LayoutParams viewFlowLayout = (FrameLayout.LayoutParams)getLayoutParams();
SharedPreferences.Editor editor = sharedPreferences.edit();
@ -283,9 +356,9 @@ public class LCDOverlappingView extends View {
editor.apply();
}
private void changeOverlappingLCDMode() {
if(this.overlappingLCDMode == 1) { // Mode Auto
this.overlappingLCDMode = 2; // We change the mode to Manual
private void changeOverlappingLCDModeToManual() {
if(this.overlappingLCDMode == OVERLAPPING_LCD_MODE_AUTO) { // Mode Auto
this.overlappingLCDMode = OVERLAPPING_LCD_MODE_MANUAL; // We change the mode to Manual
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("settings_lcd_overlapping_mode", Integer.toString(this.overlappingLCDMode));
editor.apply();
@ -295,23 +368,33 @@ public class LCDOverlappingView extends View {
}
}
public void setOverlappingLCDMode(int overlappingLCDMode, boolean isDynamic) {
private void changeOverlappingLCDModeToAuto() {
this.overlappingLCDMode = OVERLAPPING_LCD_MODE_AUTO; // We change the mode to Auto
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("settings_lcd_overlapping_mode", Integer.toString(this.overlappingLCDMode));
editor.apply();
Context context = getContext();
if(context != null)
Utils.showAlert(context, context.getString(Utils.resId(context, "string", "message_change_overlapping_lcd_mode_to_auto")));
}
public void setOverlappingLCDMode(int overlappingLCDMode) {
if(debug) Log.d(TAG, "setOverlappingLCDMode(" + overlappingLCDMode + ")");
int previousOverlappingLCDMode = this.overlappingLCDMode;
this.overlappingLCDMode = overlappingLCDMode;
if(previousOverlappingLCDMode == 0) { // Off 0
if(overlappingLCDMode == 1) // Auto 1
this.updateLayout(this.mainScreenView.viewPanOffsetX, this.mainScreenView.viewPanOffsetY, this.mainScreenView.viewScaleFactorX, this.mainScreenView.viewScaleFactorY);
else if(overlappingLCDMode == 2) // Manual 2
if(previousOverlappingLCDMode == OVERLAPPING_LCD_MODE_NONE) {
if(overlappingLCDMode == OVERLAPPING_LCD_MODE_AUTO)
this.updateLayout();
else if(overlappingLCDMode == OVERLAPPING_LCD_MODE_MANUAL)
setVisibility(VISIBLE);
} else if(previousOverlappingLCDMode == 1) { // Auto 1
if(overlappingLCDMode == 0) // Off 0
} else if(previousOverlappingLCDMode == OVERLAPPING_LCD_MODE_AUTO) {
if(overlappingLCDMode == OVERLAPPING_LCD_MODE_NONE)
setVisibility(GONE);
} else if(previousOverlappingLCDMode == 2) { // Manual 2
if(overlappingLCDMode == 0) // Off 0
} else if(previousOverlappingLCDMode == OVERLAPPING_LCD_MODE_MANUAL) {
if(overlappingLCDMode == OVERLAPPING_LCD_MODE_NONE)
setVisibility(GONE);
else if(overlappingLCDMode == 1) // Auto 1
this.updateLayout(this.mainScreenView.viewPanOffsetX, this.mainScreenView.viewPanOffsetY, this.mainScreenView.viewScaleFactorX, this.mainScreenView.viewScaleFactorY);
else if(overlappingLCDMode == OVERLAPPING_LCD_MODE_AUTO)
this.updateLayout();
}
}
}

View file

@ -35,7 +35,7 @@ import java.util.Set;
public class MainScreenView extends PanAndScaleView {
protected static final String TAG = "MainScreenView";
protected final boolean debug = true;
protected final boolean debug = false;
private Paint paint = new Paint();
private Bitmap bitmapMainScreen;
@ -259,20 +259,31 @@ public class MainScreenView extends PanAndScaleView {
((Activity)getContext()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
if (autoZoom) {
//((Activity) getContext()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
if (imageRatio < 1.0f != viewRatio < 1.0f) {
// With have different screens orientations, so we automatically zoom
float translateX, translateY, scale;
if(viewRatio > imageRatio) {
float alpha = viewRatio / imageRatio;
scale = Math.min(2, alpha) * viewSizeWidth / virtualSizeWidth;
float screenHorizontalPositionRatio = ((float)NativeLib.getScreenPositionX() + (float)NativeLib.getScreenWidth() * 0.5f ) / (virtualSizeWidth + 0.1f);
if(screenHorizontalPositionRatio < 0.5f)
// Screen seems to be at the left
translateX = 0;
else
// Screen seems to be at the right
translateX = viewSizeWidth - scale * virtualSizeWidth;
translateY = (viewSizeHeight - scale * virtualSizeHeight) / 2.0f;
} else {
float beta = imageRatio / viewRatio;
scale = Math.min(2, beta) * viewSizeHeight / virtualSizeHeight;
translateX = (viewSizeWidth - scale * virtualSizeWidth) / 2.0f;
float screenVerticalPositionRatio = ((float)NativeLib.getScreenPositionY() + (float)NativeLib.getScreenHeight() * 0.5f ) / (virtualSizeHeight + 0.1f);
if(screenVerticalPositionRatio < 0.5f)
// Screen seems to be at the top
translateY = 0.0f;
else
// Screen seems to be at the bottom
translateY = viewSizeHeight - scale * virtualSizeHeight;
}
viewScaleFactorX = scale;
@ -313,7 +324,7 @@ public class MainScreenView extends PanAndScaleView {
canvas.drawBitmap(bitmapMainScreen, 0, 0, paint);
}
public int updateCallback(int type, int param1, int param2, String param3, String param4) {
public void updateCallback(int type, int param1, int param2, String param3, String param4) {
switch (type) {
case NativeLib.CALLBACK_TYPE_INVALIDATE:
//Log.d(TAG, "PAINT updateCallback() postInvalidate()");
@ -341,7 +352,6 @@ public class MainScreenView extends PanAndScaleView {
}
break;
}
return -1;
}
public void setRotationMode(int rotationMode, boolean isDynamic) {

View file

@ -40,11 +40,6 @@ public class PanAndScaleView extends View {
protected static final String TAG = "PanAndScaleView";
protected final boolean debug = false;
protected float viewSizeWidth = 0.0f;
protected float viewSizeHeight = 0.0f;
protected float virtualSizeWidth = 0f;
protected float virtualSizeHeight = 0f;
protected ScaleGestureDetector scaleDetector;
protected GestureDetector gestureDetector;
protected OverScroller scroller;
@ -75,10 +70,15 @@ public class PanAndScaleView extends View {
protected OnTapListener onTapDownListener;
protected OnTapListener onTapUpListener;
public float viewPanOffsetX;
public float viewPanOffsetY;
public float viewScaleFactorX;
public float viewScaleFactorY;
public float viewSizeWidth = 0.0f; // pixel of the view
public float viewSizeHeight = 0.0f; // pixel of the view
public float virtualSizeWidth = 0f; // pixel of the pan and zoom bitmap
public float virtualSizeHeight = 0f; // pixel of the pan and zoom bitmap
public float viewPanOffsetX; // pixel of the view
public float viewPanOffsetY; // pixel of the view
public float viewScaleFactorX; // pixel of the view / pixel of the pan and zoom bitmap
public float viewScaleFactorY; // pixel of the view / pixel of the pan and zoom bitmap
protected float previousViewPanOffsetX;
protected float previousViewPanOffsetY;

View file

@ -848,7 +848,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
private void OnViewPrinter() {
fragmentPrinterSimulator.show(getSupportFragmentManager(), "Hello Fragment");
fragmentPrinterSimulator.show(getSupportFragmentManager(), "PrinterSimulatorFragment");
}
private void showKMLPicker(boolean changeKML) {
@ -1570,13 +1570,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
mainScreenView.setAllowPinchZoom(sharedPreferences.getBoolean("settings_allow_pinch_zoom", true));
break;
case "settings_lcd_overlapping_mode":
int overlappingLCDMode = 0;
int overlappingLCDMode = LCDOverlappingView.OVERLAPPING_LCD_MODE_NONE;
try {
overlappingLCDMode = Integer.parseInt(sharedPreferences.getString("settings_lcd_overlapping_mode", "0"));
} catch (NumberFormatException ex) {
// Catch bad number format
}
lcdOverlappingView.setOverlappingLCDMode(overlappingLCDMode, isDynamic);
lcdOverlappingView.setOverlappingLCDMode(overlappingLCDMode);
break;
case "settings_hide_bar":
case "settings_hide_bar_status":

View file

@ -87,6 +87,7 @@
<string name="message_printer_share_graphic">Save printer paper as image</string>
<string name="message_printer_out_of_paper">Out of paper error for the graphic printer (max line: %d, max pixel line: %d).</string>
<string name="message_change_overlapping_lcd_mode_to_manual">The overlapping LCD mode has been changed to "Manual".</string>
<string name="message_change_overlapping_lcd_mode_to_auto">The overlapping LCD mode has been changed to "Auto".</string>
<string name="settings_category_general_title">General</string>