Added|Changed: Fill .ws_xpixel and .ws_ypixel in winsize

This allows to get terminal size in pixel using `TIOCGWINSZ` ioctl.
Set `.ws_xpixel` using `columns * cell_width` and set `.ws_ypixel` using `rows * cell_height`.
Cell width and height is font width and line spacing, respectively.
This commit is contained in:
Krunal Patel
2022-11-16 14:03:07 +05:30
committed by Fredrik Fornwall
parent 36d811ea7d
commit 438cd73fff
4 changed files with 20 additions and 16 deletions

View File

@@ -23,10 +23,10 @@ final class JNI {
* @return the file descriptor resulting from opening /dev/ptmx master device. The sub process will have opened the * @return the file descriptor resulting from opening /dev/ptmx master device. The sub process will have opened the
* slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr. * slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr.
*/ */
public static native int createSubprocess(String cmd, String cwd, String[] args, String[] envVars, int[] processId, int rows, int columns); public static native int createSubprocess(String cmd, String cwd, String[] args, String[] envVars, int[] processId, int rows, int columns, int cellWidth, int cellHeight);
/** Set the window size for a given pty, which allows connected programs to learn how large their screen is. */ /** Set the window size for a given pty, which allows connected programs to learn how large their screen is. */
public static native void setPtyWindowSize(int fd, int rows, int cols); public static native void setPtyWindowSize(int fd, int rows, int cols, int cellWidth, int cellHeight);
/** /**
* Causes the calling thread to wait for the process associated with the receiver to finish executing. * Causes the calling thread to wait for the process associated with the receiver to finish executing.

View File

@@ -21,7 +21,7 @@ import java.util.UUID;
* A terminal session, consisting of a process coupled to a terminal interface. * A terminal session, consisting of a process coupled to a terminal interface.
* <p> * <p>
* The subprocess will be executed by the constructor, and when the size is made known by a call to * The subprocess will be executed by the constructor, and when the size is made known by a call to
* {@link #updateSize(int, int)} terminal emulation will begin and threads will be spawned to handle the subprocess I/O. * {@link #updateSize(int, int, int, int)} terminal emulation will begin and threads will be spawned to handle the subprocess I/O.
* All terminal emulation and callback methods will be performed on the main thread. * All terminal emulation and callback methods will be performed on the main thread.
* <p> * <p>
* The child process may be exited forcefully by using the {@link #finishIfRunning()} method. * The child process may be exited forcefully by using the {@link #finishIfRunning()} method.
@@ -61,7 +61,7 @@ public final class TerminalSession extends TerminalOutput {
/** /**
* The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling * The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling
* {@link JNI#createSubprocess(String, String, String[], String[], int[], int, int)}. * {@link JNI#createSubprocess(String, String, String[], String[], int[], int, int, int, int)}.
*/ */
private int mTerminalFileDescriptor; private int mTerminalFileDescriptor;
@@ -100,11 +100,11 @@ public final class TerminalSession extends TerminalOutput {
} }
/** Inform the attached pty of the new size and reflow or initialize the emulator. */ /** Inform the attached pty of the new size and reflow or initialize the emulator. */
public void updateSize(int columns, int rows) { public void updateSize(int columns, int rows, int fontWidth, int fontHeight) {
if (mEmulator == null) { if (mEmulator == null) {
initializeEmulator(columns, rows); initializeEmulator(columns, rows, fontWidth, fontHeight);
} else { } else {
JNI.setPtyWindowSize(mTerminalFileDescriptor, rows, columns); JNI.setPtyWindowSize(mTerminalFileDescriptor, rows, columns, fontWidth, fontHeight);
mEmulator.resize(columns, rows); mEmulator.resize(columns, rows);
} }
} }
@@ -120,11 +120,11 @@ public final class TerminalSession extends TerminalOutput {
* @param columns The number of columns in the terminal window. * @param columns The number of columns in the terminal window.
* @param rows The number of rows in the terminal window. * @param rows The number of rows in the terminal window.
*/ */
public void initializeEmulator(int columns, int rows) { public void initializeEmulator(int columns, int rows, int cellWidth, int cellHeight) {
mEmulator = new TerminalEmulator(this, columns, rows, mTranscriptRows, mClient); mEmulator = new TerminalEmulator(this, columns, rows, mTranscriptRows, mClient);
int[] processId = new int[1]; int[] processId = new int[1];
mTerminalFileDescriptor = JNI.createSubprocess(mShellPath, mCwd, mArgs, mEnv, processId, rows, columns); mTerminalFileDescriptor = JNI.createSubprocess(mShellPath, mCwd, mArgs, mEnv, processId, rows, columns, cellWidth, cellHeight);
mShellPid = processId[0]; mShellPid = processId[0];
mClient.setTerminalShellPid(this, mShellPid); mClient.setTerminalShellPid(this, mShellPid);

View File

@@ -29,7 +29,9 @@ static int create_subprocess(JNIEnv* env,
char** envp, char** envp,
int* pProcessId, int* pProcessId,
jint rows, jint rows,
jint columns) jint columns,
jint cell_width,
jint cell_height)
{ {
int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC); int ptm = open("/dev/ptmx", O_RDWR | O_CLOEXEC);
if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx"); if (ptm < 0) return throw_runtime_exception(env, "Cannot open /dev/ptmx");
@@ -57,7 +59,7 @@ static int create_subprocess(JNIEnv* env,
tcsetattr(ptm, TCSANOW, &tios); tcsetattr(ptm, TCSANOW, &tios);
/** Set initial winsize. */ /** Set initial winsize. */
struct winsize sz = { .ws_row = (unsigned short) rows, .ws_col = (unsigned short) columns }; struct winsize sz = { .ws_row = (unsigned short) rows, .ws_col = (unsigned short) columns, .ws_xpixel = (unsigned short) (columns * cell_width), .ws_ypixel = (unsigned short) (rows * cell_height)};
ioctl(ptm, TIOCSWINSZ, &sz); ioctl(ptm, TIOCSWINSZ, &sz);
pid_t pid = fork(); pid_t pid = fork();
@@ -121,7 +123,9 @@ JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
jobjectArray envVars, jobjectArray envVars,
jintArray processIdArray, jintArray processIdArray,
jint rows, jint rows,
jint columns) jint columns,
jint cell_width,
jint cell_height)
{ {
jsize size = args ? (*env)->GetArrayLength(env, args) : 0; jsize size = args ? (*env)->GetArrayLength(env, args) : 0;
char** argv = NULL; char** argv = NULL;
@@ -156,7 +160,7 @@ JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
int procId = 0; int procId = 0;
char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL); char const* cmd_cwd = (*env)->GetStringUTFChars(env, cwd, NULL);
char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL); char const* cmd_utf8 = (*env)->GetStringUTFChars(env, cmd, NULL);
int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns); int ptm = create_subprocess(env, cmd_utf8, cmd_cwd, argv, envp, &procId, rows, columns, cell_width, cell_height);
(*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8); (*env)->ReleaseStringUTFChars(env, cmd, cmd_utf8);
(*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd); (*env)->ReleaseStringUTFChars(env, cmd, cmd_cwd);
@@ -178,9 +182,9 @@ JNIEXPORT jint JNICALL Java_com_termux_terminal_JNI_createSubprocess(
return ptm; return ptm;
} }
JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyWindowSize(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd, jint rows, jint cols) JNIEXPORT void JNICALL Java_com_termux_terminal_JNI_setPtyWindowSize(JNIEnv* TERMUX_UNUSED(env), jclass TERMUX_UNUSED(clazz), jint fd, jint rows, jint cols, jint cell_width, jint cell_height)
{ {
struct winsize sz = { .ws_row = (unsigned short) rows, .ws_col = (unsigned short) cols }; struct winsize sz = { .ws_row = (unsigned short) rows, .ws_col = (unsigned short) cols, .ws_xpixel = (unsigned short) (cols * cell_width), .ws_ypixel = (unsigned short) (rows * cell_height) };
ioctl(fd, TIOCSWINSZ, &sz); ioctl(fd, TIOCSWINSZ, &sz);
} }

View File

@@ -975,7 +975,7 @@ public final class TerminalView extends View {
int newRows = Math.max(4, (viewHeight - mRenderer.mFontLineSpacingAndAscent) / mRenderer.mFontLineSpacing); int newRows = Math.max(4, (viewHeight - mRenderer.mFontLineSpacingAndAscent) / mRenderer.mFontLineSpacing);
if (mEmulator == null || (newColumns != mEmulator.mColumns || newRows != mEmulator.mRows)) { if (mEmulator == null || (newColumns != mEmulator.mColumns || newRows != mEmulator.mRows)) {
mTermSession.updateSize(newColumns, newRows); mTermSession.updateSize(newColumns, newRows, (int) mRenderer.getFontWidth(), mRenderer.getFontLineSpacing());
mEmulator = mTermSession.getEmulator(); mEmulator = mTermSession.getEmulator();
mClient.onEmulatorSet(); mClient.onEmulatorSet();