mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-21 23:20:23 +00:00
More rework
This commit is contained in:
parent
4c16545424
commit
86a9383cd2
6 changed files with 131 additions and 23 deletions
|
@ -23,9 +23,6 @@ public class TerminalViewDockComp extends SimpleComp {
|
|||
stack.boundsInParentProperty().addListener((observable, oldValue, newValue) -> {
|
||||
update(stack);
|
||||
});
|
||||
stack.sceneProperty().addListener((observable, oldValue, newValue) -> {
|
||||
update(stack);
|
||||
});
|
||||
var s = AppMainWindow.getInstance().getStage();
|
||||
s.xProperty().addListener((observable, oldValue, newValue) -> {
|
||||
update(stack);
|
||||
|
@ -41,16 +38,14 @@ public class TerminalViewDockComp extends SimpleComp {
|
|||
});
|
||||
s.iconifiedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
TerminalView.get().onMinimize();
|
||||
TerminalView.get().onWindowMinimize();
|
||||
} else {
|
||||
TerminalView.get().onFocusGain();
|
||||
TerminalView.get().onWindowActivate();
|
||||
}
|
||||
});
|
||||
s.focusedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue) {
|
||||
TerminalView.get().onFocusGain();
|
||||
} else {
|
||||
TerminalView.get().onFocusLost();
|
||||
}
|
||||
});
|
||||
s.addEventFilter(WindowEvent.WINDOW_SHOWN,event -> {
|
||||
|
|
|
@ -11,6 +11,7 @@ import io.xpipe.app.prefs.AppPrefsComp;
|
|||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.LicenseProvider;
|
||||
|
||||
import io.xpipe.app.util.TerminalView;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
@ -64,15 +65,19 @@ public class AppLayoutModel {
|
|||
}
|
||||
|
||||
public void selectTerminal() {
|
||||
if (!TerminalView.isSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
selected.setValue(entries.get(2));
|
||||
}
|
||||
|
||||
public void selectSettings() {
|
||||
selected.setValue(entries.get(3));
|
||||
selected.setValue(entries.get(TerminalView.isSupported() ? 3 : 2));
|
||||
}
|
||||
|
||||
public void selectLicense() {
|
||||
selected.setValue(entries.get(4));
|
||||
selected.setValue(entries.get(TerminalView.isSupported() ? 4 : 3));
|
||||
}
|
||||
|
||||
public void selectConnections() {
|
||||
|
@ -138,6 +143,10 @@ public class AppLayoutModel {
|
|||
// null)
|
||||
));
|
||||
|
||||
if (!TerminalView.isSupported()) {
|
||||
l.remove(2);
|
||||
}
|
||||
|
||||
var now = Instant.now();
|
||||
var zone = ZoneId.of(ZoneId.SHORT_IDS.get("PST"));
|
||||
var phStart = ZonedDateTime.of(2024, 10, 22, 0, 1, 0, 0, zone).toInstant();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import io.sentry.protocol.User;
|
||||
import io.xpipe.app.util.Rect;
|
||||
import javafx.stage.Window;
|
||||
|
||||
|
@ -24,6 +25,11 @@ public class NativeWinWindowControl {
|
|||
public static Optional<NativeWinWindowControl> byPid(long pid) {
|
||||
var ref = new AtomicReference<NativeWinWindowControl>();
|
||||
User32.INSTANCE.EnumWindows((hWnd, data) -> {
|
||||
var visible = User32.INSTANCE.IsWindowVisible(hWnd);
|
||||
if (!visible) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var wpid = new IntByReference();
|
||||
User32.INSTANCE.GetWindowThreadProcessId(hWnd, wpid);
|
||||
if (wpid.getValue() == pid) {
|
||||
|
@ -59,16 +65,24 @@ public class NativeWinWindowControl {
|
|||
this.windowHandle = windowHandle;
|
||||
}
|
||||
|
||||
public boolean isIconified() {
|
||||
return (User32.INSTANCE.GetWindowLong(windowHandle,User32.GWL_STYLE) & User32.WS_MINIMIZE) != 0;
|
||||
}
|
||||
|
||||
public void alwaysInFront() {
|
||||
orderRelative(new WinDef.HWND(new Pointer( 0xFFFFFFFFFFFFFFFFL)));
|
||||
}
|
||||
|
||||
public void defaultOrder() {
|
||||
orderRelative(new WinDef.HWND(new Pointer( 1)));
|
||||
}
|
||||
|
||||
public void orderRelative(WinDef.HWND predecessor) {
|
||||
User32.INSTANCE.SetWindowPos(windowHandle, predecessor, 0, 0, 0, 0, User32.SWP_NOACTIVATE | User32.SWP_NOMOVE | User32.SWP_NOSIZE);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
User32.INSTANCE.ShowWindow(windowHandle,User32.SW_RESTORE);
|
||||
User32.INSTANCE.ShowWindow(windowHandle, User32.SW_RESTORE);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
|
|
@ -127,10 +127,17 @@ public class AppPrefs {
|
|||
final BooleanProperty requireDoubleClickForConnections =
|
||||
map(new SimpleBooleanProperty(false), "requireDoubleClickForConnections", Boolean.class);
|
||||
|
||||
final BooleanProperty enableTerminalDocking =
|
||||
map(new SimpleBooleanProperty(true), "enableTerminalDocking", Boolean.class);
|
||||
|
||||
public ObservableBooleanValue requireDoubleClickForConnections() {
|
||||
return requireDoubleClickForConnections;
|
||||
}
|
||||
|
||||
public ObservableBooleanValue enableTerminalDocking() {
|
||||
return enableTerminalDocking;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final Property<InPlaceSecretValue> lockPassword = new SimpleObjectProperty<>();
|
||||
|
||||
|
|
|
@ -10,12 +10,10 @@ import io.xpipe.app.fxcomps.impl.HorizontalComp;
|
|||
import io.xpipe.app.fxcomps.impl.StackComp;
|
||||
import io.xpipe.app.fxcomps.impl.TextFieldComp;
|
||||
import io.xpipe.app.terminal.ExternalTerminalType;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.OptionsBuilder;
|
||||
import io.xpipe.app.util.TerminalLauncher;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.app.util.*;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.ListCell;
|
||||
|
@ -58,7 +56,11 @@ public class TerminalCategory extends AppPrefsCategory {
|
|||
.hide(prefs.terminalType.isNotEqualTo(ExternalTerminalType.CUSTOM)))
|
||||
.addComp(terminalTest)
|
||||
.nameAndDescription("clearTerminalOnInit")
|
||||
.addToggle(prefs.clearTerminalOnInit))
|
||||
.addToggle(prefs.clearTerminalOnInit)
|
||||
.nameAndDescription("enableTerminalDocking")
|
||||
.addToggle(prefs.enableTerminalDocking)
|
||||
.hide(new SimpleBooleanProperty(!TerminalView.isSupported()))
|
||||
)
|
||||
.buildComp();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ package io.xpipe.app.util;
|
|||
import io.xpipe.app.core.AppLayoutModel;
|
||||
import io.xpipe.app.core.window.NativeWinWindowControl;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import javafx.application.Platform;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
@ -14,6 +16,10 @@ import java.util.List;
|
|||
|
||||
public class TerminalView {
|
||||
|
||||
public static boolean isSupported() {
|
||||
return OsType.getLocal() == OsType.WINDOWS;
|
||||
}
|
||||
|
||||
@Value
|
||||
public static class Session {
|
||||
ProcessHandle shell;
|
||||
|
@ -42,9 +48,15 @@ public class TerminalView {
|
|||
|
||||
public abstract void close();
|
||||
|
||||
public abstract boolean isActive();
|
||||
|
||||
public abstract Rect queryBounds();
|
||||
|
||||
public final void updateBoundsState() {
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = queryBounds();
|
||||
if (lastBounds != null && !lastBounds.equals(bounds)) {
|
||||
customBounds = true;
|
||||
|
@ -81,7 +93,8 @@ public class TerminalView {
|
|||
|
||||
@Override
|
||||
public void back() {
|
||||
NativeWinWindowControl.MAIN_WINDOW.orderRelative(control.getWindowHandle());
|
||||
control.defaultOrder();
|
||||
// NativeWinWindowControl.MAIN_WINDOW.orderRelative(control.getWindowHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,6 +109,11 @@ public class TerminalView {
|
|||
this.control.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return !control.isIconified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect queryBounds() {
|
||||
return control.getBounds();
|
||||
|
@ -108,6 +126,10 @@ public class TerminalView {
|
|||
private Rect viewBounds;
|
||||
private boolean viewActive;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return isSupported() && AppPrefs.get().enableTerminalDocking().get();
|
||||
}
|
||||
|
||||
public synchronized void open(long pid) {
|
||||
var processHandle = ProcessHandle.of(pid);
|
||||
if (processHandle.isEmpty() || !processHandle.get().isAlive()) {
|
||||
|
@ -137,6 +159,16 @@ public class TerminalView {
|
|||
return;
|
||||
}
|
||||
terminalInstances.add(new WindowsTerminalInstance(terminal.get(), control.get()));
|
||||
|
||||
TrackEvent.withTrace("Terminal instance opened")
|
||||
.tag("terminalPid", terminal.get().pid())
|
||||
.tag("viewEnabled", isEnabled())
|
||||
.handle();
|
||||
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
AppLayoutModel.get().selectTerminal();
|
||||
});
|
||||
|
@ -154,6 +186,9 @@ public class TerminalView {
|
|||
}
|
||||
|
||||
public synchronized void toggleView(boolean active) {
|
||||
TrackEvent.withTrace("Terminal view toggled")
|
||||
.tag("active", active)
|
||||
.handle();
|
||||
if (viewActive == active) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,30 +197,59 @@ public class TerminalView {
|
|||
if (active) {
|
||||
terminalInstances.forEach(terminalInstance -> terminalInstance.front());
|
||||
updatePositions();
|
||||
} else {
|
||||
terminalInstances.forEach(terminalInstance -> terminalInstance.back());
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onFocusLost() {
|
||||
terminalInstances.forEach(terminalInstance -> terminalInstance.back());
|
||||
}
|
||||
|
||||
public synchronized void onFocusGain() {
|
||||
terminalInstances.forEach(terminalInstance -> terminalInstance.show());
|
||||
TrackEvent.withTrace("Terminal view focus gained")
|
||||
.handle();
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
if (!terminalInstance.isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstance.updateBoundsState();
|
||||
if (terminalInstance.isCustomBounds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstance.show();
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void onMinimize() {
|
||||
public synchronized void onWindowActivate() {
|
||||
TrackEvent.withTrace("Terminal view focus gained")
|
||||
.handle();
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
terminalInstance.updateBoundsState();
|
||||
if (terminalInstance.isCustomBounds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstance.show();
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void onWindowMinimize() {
|
||||
TrackEvent.withTrace("Terminal view minimized")
|
||||
.handle();
|
||||
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
terminalInstance.updateBoundsState();
|
||||
if (terminalInstance.isCustomBounds()) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstance.minimize();
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void onClose() {
|
||||
TrackEvent.withTrace("Terminal view closed")
|
||||
.handle();
|
||||
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
terminalInstance.updateBoundsState();
|
||||
if (terminalInstance.isCustomBounds()) {
|
||||
|
@ -197,6 +261,10 @@ public class TerminalView {
|
|||
}
|
||||
|
||||
private void updatePositions() {
|
||||
if (viewBounds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
terminalInstance.updateBoundsState();
|
||||
if (terminalInstance.isCustomBounds()) {
|
||||
|
@ -208,14 +276,27 @@ public class TerminalView {
|
|||
}
|
||||
|
||||
public void resizeView(int x, int y, int w, int h) {
|
||||
if (w < 100 || h < 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewBounds = new Rect(x,y,w,h);
|
||||
TrackEvent.withTrace("Terminal view resized")
|
||||
.tag("rect", viewBounds)
|
||||
.handle();
|
||||
if (viewActive) {
|
||||
updatePositions();
|
||||
}
|
||||
}
|
||||
|
||||
public void clickView() {
|
||||
terminalInstances.forEach(terminalInstance -> terminalInstance.updatePosition(viewBounds));
|
||||
TrackEvent.withTrace("Terminal view clicked")
|
||||
.handle();
|
||||
|
||||
terminalInstances.forEach(terminalInstance -> {
|
||||
terminalInstance.show();
|
||||
terminalInstance.updatePosition(viewBounds);
|
||||
});
|
||||
}
|
||||
|
||||
private static TerminalView INSTANCE;
|
||||
|
|
Loading…
Reference in a new issue