diff --git a/build.xml b/build.xml index 8f152721..52a57857 100644 --- a/build.xml +++ b/build.xml @@ -12,7 +12,7 @@ - + diff --git a/debian/changelog b/debian/changelog index d80918a7..f45cee7d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +dayon (15.0.0) stable; urgency=medium + + * Option to monitor in true colors + * Additional gray scales + * Improved UI responsiveness + + -- Reto Galante Mon, 18 November 2024 12:00:00 +0000 + dayon (14.0.2) stable; urgency=low * Improved UPnP gateway discovery diff --git a/docs/assistant_capture_settings.jpg b/docs/assistant_capture_settings.jpg index 7201dd3b..34fdf126 100644 Binary files a/docs/assistant_capture_settings.jpg and b/docs/assistant_capture_settings.jpg differ diff --git a/docs/de_settings.html b/docs/de_settings.html index 78472ece..979354e5 100644 --- a/docs/de_settings.html +++ b/docs/de_settings.html @@ -61,6 +61,8 @@

Assistent   Assistierten Seite verbraucht wird.

diff --git a/docs/fr_settings.html b/docs/fr_settings.html index 83d135b0..dfdce578 100644 --- a/docs/fr_settings.html +++ b/docs/fr_settings.html @@ -62,6 +62,8 @@

Assistant  capturé ; vous pouvez configurer l'interval de temps (en milliseconde) entre deux captures (aka. tic-tac) ainsi que le nombre de niveaux de gris. Moins de niveaux veut dire moins d'information à transmettre sur le réseau (au détriment de la qualité des images). + À partir de Dayon ! 15, les couleurs sRGB peuvent également être utilisées comme alternative. Dans ce cas, le nombre de niveaux de gris est ignoré. + Veuillez noter que l'utilisation des "Couleurs réelles" consomme plus de bande passante et plus de RAM du côté de l'assisté.

diff --git a/docs/settings.html b/docs/settings.html index ffed4aaf..4d396c04 100644 --- a/docs/settings.html +++ b/docs/settings.html @@ -60,6 +60,8 @@

Assistant   assisted side.

diff --git a/docs/sv_settings.html b/docs/sv_settings.html index dc46e8ab..74f4ee7e 100644 --- a/docs/sv_settings.html +++ b/docs/sv_settings.html @@ -59,6 +59,8 @@

Hjälpgivare  hjälpgivare-sidan.

diff --git a/docs/zh_settings.html b/docs/zh_settings.html index 6ffd0d37..0af53132 100644 --- a/docs/zh_settings.html +++ b/docs/zh_settings.html @@ -59,6 +59,8 @@

Assistant   Assisted - 用户端 端消耗更多带宽和内存。

diff --git a/pom.xml b/pom.xml index 3e3da40c..3fe1e4f7 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ https://github.com/retgal/dayon mpo.dayon dayon - 14.0.2 + 15.0.0 cross platform remote desktop solution @@ -658,7 +658,7 @@ 1.8.3 ../dist/ - assisted.command + Assisted.command ./dayon_assisted.sh @@ -718,7 +718,7 @@ 1.8.3 ../dist/ - assistant.command + Assistant.command ./dayon_assistant.sh diff --git a/resources/dayon.sh b/resources/dayon.sh index db18bccc..3edce22e 100755 --- a/resources/dayon.sh +++ b/resources/dayon.sh @@ -20,7 +20,7 @@ elif [ ! -f /etc/alternatives/java ]; then else JAVA=$(ls -l /etc/alternatives/java | awk -F'> ' '{print $2}') fi -JAVA_OPTS="-Xmx256M" +JAVA_OPTS="-Xmx512M" case "$@" in *log=console*) LOG= diff --git a/src/main/java/mpo/dayon/assistant/decompressor/DeCompressorEngine.java b/src/main/java/mpo/dayon/assistant/decompressor/DeCompressorEngine.java index ce315205..4699f4ae 100644 --- a/src/main/java/mpo/dayon/assistant/decompressor/DeCompressorEngine.java +++ b/src/main/java/mpo/dayon/assistant/decompressor/DeCompressorEngine.java @@ -103,7 +103,7 @@ protected void execute() throws IOException { cache = configuration.useCache() ? new RegularTileCache(configuration.getCacheMaxSize(), configuration.getCachePurgeSize()) : new NullTileCache(); - Log.info("De-Compressor engine has been reconfigured [tile:" + message.getId() + "] " + configuration); + Log.info("De-Compressor engine has been reconfigured [tile:" + message.getId() + "]" + configuration); } cache.clearHits(); diff --git a/src/main/java/mpo/dayon/assistant/gui/Assistant.java b/src/main/java/mpo/dayon/assistant/gui/Assistant.java index 31efb4b0..a0d87f77 100644 --- a/src/main/java/mpo/dayon/assistant/gui/Assistant.java +++ b/src/main/java/mpo/dayon/assistant/gui/Assistant.java @@ -22,6 +22,7 @@ import mpo.dayon.common.squeeze.CompressionMethod; import mpo.dayon.common.network.FileUtilities; import mpo.dayon.common.utils.Language; +import mpo.dayon.common.version.Version; import javax.swing.*; import java.awt.*; @@ -46,10 +47,11 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; -import static java.lang.Math.abs; +import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY; +import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE; +import static java.lang.Math.*; import static java.lang.String.format; import static java.lang.String.valueOf; -import static java.lang.Thread.sleep; import static javax.swing.SwingConstants.HORIZONTAL; import static mpo.dayon.common.babylon.Babylon.translate; import static mpo.dayon.common.gui.common.ImageUtilities.getOrCreateIcon; @@ -87,6 +89,8 @@ public class Assistant implements ClipboardOwner { private final Object prevBufferLOCK = new Object(); + private final Object upnpEnabledLOCK = new Object(); + private byte[] prevBuffer = null; private int prevWidth = -1; @@ -169,18 +173,6 @@ private void createCounters() { counters = new ArrayList<>(Arrays.asList(receivedBitCounter, receivedTileCounter, skippedTileCounter, mergedTileCounter, captureCompressionCounter)); } - public boolean isUpnpEnabled() { - while (upnpEnabled == null) { - try { - sleep(10L); - } catch (InterruptedException e) { - Log.warn("Swallowed", e); - Thread.currentThread().interrupt(); - } - } - return upnpEnabled; - } - public NetworkAssistantEngine getNetworkEngine() { return networkEngine; } @@ -369,13 +361,13 @@ public void actionPerformed(ActionEvent ev) { JFrame captureFrame = (JFrame) SwingUtilities.getRoot((Component) ev.getSource()); final JPanel pane = new JPanel(); - pane.setLayout(new GridLayout(2, 2, 10, 10)); + pane.setLayout(new GridLayout(3, 2, 10, 10)); final JLabel tickLbl = new JLabel(translate("tick")); tickLbl.setToolTipText(translate("tick.tooltip")); final JSlider tickMillisSlider = new JSlider(HORIZONTAL, 50, 1000, captureEngineConfiguration.getCaptureTick()); final Properties tickLabelTable = new Properties(3); - JLabel actualTick = new JLabel(format("%dms", tickMillisSlider.getValue())); + JLabel actualTick = new JLabel(format(" %dms ", tickMillisSlider.getValue())); tickLabelTable.put(50, new JLabel(translate("min"))); tickLabelTable.put(550, actualTick); tickLabelTable.put(1000, new JLabel(translate("max"))); @@ -389,43 +381,54 @@ public void actionPerformed(ActionEvent ev) { final JLabel grayLevelsLbl = new JLabel(translate("grays")); final JSlider grayLevelsSlider = new JSlider(HORIZONTAL, 0, 6, 6 - captureEngineConfiguration.getCaptureQuantization().ordinal()); final Properties grayLabelTable = new Properties(3); - JLabel actualLevels = new JLabel(format("%d", toGrayLevel(grayLevelsSlider.getValue()).getLevels())); - grayLabelTable.put(0, new JLabel(translate("min"))); - grayLabelTable.put(3, actualLevels); + JLabel actualLevels = new JLabel(format(" %d ", toGrayLevel(grayLevelsSlider.getValue()).getLevels())); + if (!networkConfiguration.isMonochromePeer()) { + grayLabelTable.put(0, new JLabel(translate("min"))); + grayLabelTable.put(3, actualLevels); + } else { + grayLabelTable.put(3, new JLabel(translate("min"))); + grayLevelsSlider.setMinimum(3); + } grayLabelTable.put(6, new JLabel(translate("max"))); grayLevelsSlider.setLabelTable(grayLabelTable); grayLevelsSlider.setMajorTickSpacing(1); grayLevelsSlider.setPaintTicks(true); grayLevelsSlider.setPaintLabels(true); grayLevelsSlider.setSnapToTicks(true); - pane.add(grayLevelsLbl); - pane.add(grayLevelsSlider); + pane.add(grayLevelsLbl).setEnabled(!captureEngineConfiguration.isCaptureColors()); + pane.add(grayLevelsSlider).setEnabled(!captureEngineConfiguration.isCaptureColors()); + + final JLabel colorsLbl = new JLabel(translate("colors")); + final JCheckBox colorsCb = new JCheckBox(); + colorsCb.setSelected(captureEngineConfiguration.isCaptureColors()); + pane.add(colorsLbl).setEnabled(!networkConfiguration.isMonochromePeer()); + pane.add(colorsCb).setEnabled(!networkConfiguration.isMonochromePeer()); tickMillisSlider.addChangeListener(e -> { actualTick.setText(tickMillisSlider.getValue() < 1000 ? format("%dms", tickMillisSlider.getValue()) : "1s"); if (!tickMillisSlider.getValueIsAdjusting()) { sendCaptureConfiguration(new CaptureEngineConfiguration(tickMillisSlider.getValue(), - toGrayLevel(grayLevelsSlider.getValue()))); + toGrayLevel(grayLevelsSlider.getValue()), captureEngineConfiguration.isCaptureColors())); } }); grayLevelsSlider.addChangeListener(e -> { actualLevels.setText(format("%d", toGrayLevel(grayLevelsSlider.getValue()).getLevels())); - if (!grayLevelsSlider.getValueIsAdjusting()) { + if (!grayLevelsSlider.getValueIsAdjusting() && !captureEngineConfiguration.isCaptureColors()) { sendCaptureConfiguration(new CaptureEngineConfiguration(tickMillisSlider.getValue(), - toGrayLevel(grayLevelsSlider.getValue()))); + toGrayLevel(grayLevelsSlider.getValue()), false)); } }); + colorsCb.addActionListener(e -> { + grayLevelsLbl.setEnabled(!colorsCb.isSelected()); + grayLevelsSlider.setEnabled(!colorsCb.isSelected()); + }); final boolean ok = DialogFactory.showOkCancel(captureFrame, translate("capture"), pane, true, null); if (ok) { final CaptureEngineConfiguration newCaptureEngineConfiguration = new CaptureEngineConfiguration(tickMillisSlider.getValue(), - toGrayLevel(grayLevelsSlider.getValue())); - if (!newCaptureEngineConfiguration.equals(captureEngineConfiguration)) { - captureEngineConfiguration = newCaptureEngineConfiguration; - captureEngineConfiguration.persist(); - sendCaptureConfiguration(captureEngineConfiguration); - } + toGrayLevel(grayLevelsSlider.getValue()), colorsCb.isSelected()); + updateCaptureConfiguration(newCaptureEngineConfiguration); } } }; @@ -434,6 +437,14 @@ public void actionPerformed(ActionEvent ev) { return configure; } + private void updateCaptureConfiguration(CaptureEngineConfiguration newCaptureEngineConfiguration) { + if (!newCaptureEngineConfiguration.equals(captureEngineConfiguration)) { + captureEngineConfiguration = newCaptureEngineConfiguration; + captureEngineConfiguration.persist(); + sendCaptureConfiguration(captureEngineConfiguration); + } + } + private Gray8Bits toGrayLevel(int value) { switch (value) { case 6: @@ -742,12 +753,29 @@ protected void done() { } } + public boolean isUpnpEnabled() { + synchronized (upnpEnabledLOCK) { + while (upnpEnabled == null) { + try { + upnpEnabledLOCK.wait(); + } catch (InterruptedException e) { + Log.warn("Swallowed", e); + Thread.currentThread().interrupt(); + } + } + return upnpEnabled; + } + } + private void initUpnp() { - CompletableFuture.supplyAsync(UPnP::isUPnPAvailable).thenApply(enabled -> { - Log.info(format("UPnP is %s", enabled.booleanValue() ? "enabled" : "disabled")); - upnpEnabled = enabled; - return enabled; - }); + synchronized (upnpEnabledLOCK) { + CompletableFuture.supplyAsync(UPnP::isUPnPAvailable).thenApply(enabled -> { + Log.info(format("UPnP is %s", enabled.booleanValue() ? "enabled" : "disabled")); + upnpEnabled = enabled; + return enabled; + }); + upnpEnabledLOCK.notifyAll(); + } } private class MyDeCompressorEngineListener implements DeCompressorEngineListener { @@ -788,7 +816,7 @@ private BufferedImage scaleImage(BufferedImage image, int width, int height) { AffineTransform scaleTransform = AffineTransform.getScaleInstance(frame.getxFactor(), frame.getyFactor()); try { AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR); - return bilinearScaleOp.filter(image, new BufferedImage(abs(width), abs(height), image.getType())); + return bilinearScaleOp.filter(image, new BufferedImage(abs(width), abs(height), image.getType() == 0 ? TYPE_INT_ARGB_PRE : TYPE_BYTE_GRAY)); } catch (ImagingOpException e) { Log.error(e.getMessage()); return image; @@ -828,11 +856,20 @@ public boolean onAccepted(Socket connection) { * Should not block as called from the network receiving thread (!) */ @Override - public void onConnected(Socket connection, char osId, String inputLocale) { + public void onConnected(Socket connection, char osId, String inputLocale, int peerMajorVersion) { + assureCompatibility(peerMajorVersion); sendCaptureConfiguration(captureEngineConfiguration); sendCompressorConfiguration(compressorEngineConfiguration); frame.resetCanvas(); - frame.onSessionStarted(osId, inputLocale); + frame.onSessionStarted(osId, inputLocale, peerMajorVersion); + } + + private void assureCompatibility(int peerMajorVersion) { + if (!Version.isColoredVersion(peerMajorVersion) && (captureEngineConfiguration.isCaptureColors() || captureEngineConfiguration.getCaptureQuantization().getLevels() < Gray8Bits.X_32.getLevels())) { + Log.warn(format("Pre color v%d.x.x peer detected: CaptureEngineConfiguration adjusted to %s", peerMajorVersion, Gray8Bits.X_128)); + captureEngineConfiguration = new CaptureEngineConfiguration(captureEngineConfiguration.getCaptureTick(), Gray8Bits.X_128, false); + captureEngineConfiguration.persist(); + } } @Override @@ -881,17 +918,20 @@ public void onResizeScreen(int width, int height) { @Override public void onDisconnecting() { frame.onDisconnecting(); + networkConfiguration.setMonochromePeer(false); } @Override public void onTerminating() { Log.info("Session got terminated by peer"); frame.onTerminating(); + networkConfiguration.setMonochromePeer(false); } @Override public void onIOError(IOException error) { frame.onIOError(error); + networkConfiguration.setMonochromePeer(false); } } diff --git a/src/main/java/mpo/dayon/assistant/gui/AssistantFrame.java b/src/main/java/mpo/dayon/assistant/gui/AssistantFrame.java index daf71f65..06a23acc 100644 --- a/src/main/java/mpo/dayon/assistant/gui/AssistantFrame.java +++ b/src/main/java/mpo/dayon/assistant/gui/AssistantFrame.java @@ -9,6 +9,7 @@ import mpo.dayon.common.log.Log; import mpo.dayon.common.monitoring.counter.Counter; import mpo.dayon.common.utils.Language; +import mpo.dayon.common.version.Version; import javax.swing.*; import java.awt.*; @@ -481,7 +482,7 @@ void onClipboardReceived() { toggleTransferControls(true); } - void onSessionStarted(char osId, String inputLocale) { + void onSessionStarted(char osId, String inputLocale, int assistedMajorVersion) { this.osId = osId; if (osId == 'm') { windowsKeyToggleButton.setIcon(getOrCreateIcon(ImageNames.CMD)); @@ -490,6 +491,10 @@ void onSessionStarted(char osId, String inputLocale) { windowsKeyToggleButton.setIcon(getOrCreateIcon(ImageNames.WIN)); windowsKeyToggleButton.setToolTipText(translate("send.winKey")); } + if (Version.isOutdatedVersion(Version.get().getMajor(), assistedMajorVersion)) { + String infoMessage = format("%s%n%s", translate("outdated.msg1"), translate("outdated.msg2")); + JOptionPane.showMessageDialog(this, infoMessage, "", JOptionPane.INFORMATION_MESSAGE); + } if (!inputLocale.isEmpty() && !inputLocale.equals(InputContext.getInstance().getLocale().toString())) { String infoMessage = format("%s%n%s%n%s", translate("keyboardlayout.msg1", inputLocale), translate("keyboardlayout.msg2"), translate("keyboardlayout.msg3")); JOptionPane.showMessageDialog(this, infoMessage, "", JOptionPane.INFORMATION_MESSAGE); diff --git a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngine.java b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngine.java index 7980c448..e04084ca 100644 --- a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngine.java +++ b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngine.java @@ -26,6 +26,7 @@ import static java.lang.String.format; import static mpo.dayon.common.utils.SystemUtilities.safeClose; +import static mpo.dayon.common.version.Version.isColoredVersion; import static mpo.dayon.common.version.Version.isCompatibleVersion; public class NetworkAssistantEngine extends NetworkEngine implements ReConfigurable { @@ -289,6 +290,7 @@ private NetworkHelloMessage introduce(ObjectInputStream in) throws IOException { Log.error(format("Incompatible assisted version: %d.%d", hello.getMajor(), hello.getMinor())); throw new IOException("version.wrong"); } + configuration.setMonochromePeer(!isColoredVersion(hello.getMajor())); return hello; } @@ -297,7 +299,7 @@ private NetworkHelloMessage introduce(ObjectInputStream in) throws IOException { */ public void sendCaptureConfiguration(CaptureEngineConfiguration configuration) { if (sender != null) { - sender.sendCaptureConfiguration(configuration); + sender.sendCaptureConfiguration(configuration, this.configuration.isMonochromePeer()); } } @@ -359,7 +361,7 @@ private boolean fireOnAccepted(Socket connection) { } private void fireOnConnected(Socket connection, NetworkHelloMessage hello) { - listeners.getListeners().forEach(listener -> listener.onConnected(connection, hello.getOsId(), hello.getInputLocale())); + listeners.getListeners().forEach(listener -> listener.onConnected(connection, hello.getOsId(), hello.getInputLocale(), hello.getMajor())); } private void fireOnByteReceived(int count) { diff --git a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineConfiguration.java b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineConfiguration.java index 871db0b1..ca47fe91 100644 --- a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineConfiguration.java +++ b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineConfiguration.java @@ -18,6 +18,8 @@ public class NetworkAssistantEngineConfiguration extends Configuration { private final String tokenServerUrl; + private boolean monochromePeer = false; + /** * Default : takes its values from the current preferences. */ @@ -39,6 +41,14 @@ public String getTokenServerUrl() { return tokenServerUrl; } + public boolean isMonochromePeer() { + return monochromePeer; + } + + public void setMonochromePeer(boolean monochromePeer) { + this.monochromePeer = monochromePeer; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineListener.java b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineListener.java index f131aedd..21e6af80 100644 --- a/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineListener.java +++ b/src/main/java/mpo/dayon/assistant/network/NetworkAssistantEngineListener.java @@ -21,7 +21,7 @@ public interface NetworkAssistantEngineListener extends Listener { /** * Should not block as called from the network receiving thread (!) */ - void onConnected(Socket connection, char osId, String inputLocale); + void onConnected(Socket connection, char osId, String inputLocale, int peerMajorVersion); /** * Should not block as called from the network receiving thread (!) diff --git a/src/main/java/mpo/dayon/assisted/capture/CaptureEngine.java b/src/main/java/mpo/dayon/assisted/capture/CaptureEngine.java index 34078a0b..5f50fef6 100644 --- a/src/main/java/mpo/dayon/assisted/capture/CaptureEngine.java +++ b/src/main/java/mpo/dayon/assisted/capture/CaptureEngine.java @@ -96,6 +96,7 @@ public void stop() { private void mainLoop() throws InterruptedException { Gray8Bits quantization = null; + boolean captureColors = false; int tick = -1; long start = -1L; int captureId = 0; @@ -108,6 +109,7 @@ private void mainLoop() throws InterruptedException { if (reconfigured) { // assuming everything has changed (!) quantization = configuration.getCaptureQuantization(); + captureColors = configuration.isCaptureColors(); tick = configuration.getCaptureTick(); start = System.currentTimeMillis(); captureCount = 0; @@ -123,7 +125,7 @@ private void mainLoop() throws InterruptedException { } ++captureCount; ++captureId; - final byte[] pixels = captureFactory.captureGray(quantization); + final byte[] pixels = captureColors ? captureFactory.captureScreen(null) : captureFactory.captureScreen(quantization); if (pixels == null) { // testing purpose (!) @@ -177,8 +179,8 @@ private void updatePreviousCapture(Capture capture) { } private CaptureTile[] computeDirtyTiles(byte[] capture) { - final int x = (captureDimension.width + TILE_DIMENSION.width -1) / TILE_DIMENSION.width; - final int y = (captureDimension.height + TILE_DIMENSION.height -1) / TILE_DIMENSION.height; + final int x = (captureDimension.width + TILE_DIMENSION.width - 1) / TILE_DIMENSION.width; + final int y = (captureDimension.height + TILE_DIMENSION.height - 1) / TILE_DIMENSION.height; final int length = x * y; // change in screen resolution? if (length != previousCapture.length) { @@ -188,13 +190,13 @@ private CaptureTile[] computeDirtyTiles(byte[] capture) { CaptureTile[] dirty = new CaptureTile[length]; byte[] tileData; boolean hasDirty = false; + int pixelSize = configuration.isCaptureColors() ? 4 : 1; int tileId = 0; for (int ty = 0; ty < captureDimension.height; ty += TILE_DIMENSION.height) { final int th = min(captureDimension.height - ty, TILE_DIMENSION.height); for (int tx = 0; tx < captureDimension.width; tx += TILE_DIMENSION.width) { - final int tw = min(captureDimension.width - tx, TILE_DIMENSION.width); - final int offset = ty * captureDimension.width + tx; - tileData = createTile(capture, captureDimension.width, offset, tw, th); + final int tw = Math.min(captureDimension.width - tx, TILE_DIMENSION.width); + tileData = createTile(capture, captureDimension.width, tw, th, tx, ty, pixelSize); final long cs = CaptureTile.computeChecksum(tileData, 0, tileData.length); if (cs != previousCapture[tileId]) { dirty[tileId] = new CaptureTile(cs, new Position(tx, ty), tw, th, tileData); @@ -207,19 +209,19 @@ private CaptureTile[] computeDirtyTiles(byte[] capture) { } /** - * Screen-rectangle buffer to tile-rectangle buffer. + * Screen-rectangle buffer to tile-rectangle buffer. Use pixelSize 4 for colored and 1 for gray pixels. */ - private static byte[] createTile(byte[] capture, int width, int srcPos, int tw, int th) { - final int capacity = tw * th; + private static byte[] createTile(byte[] capture, int width, int tw, int th, int tx, int ty, int pixelSize) { + final int capacity = tw * th * pixelSize; final byte[] tile = new byte[capacity]; final int maxSrcPos = capture.length; - final int maxDestPos = capacity - tw + 1; + final int maxDestPos = capacity - tw * pixelSize + 1; + int srcPos = ty * width * pixelSize + tx * pixelSize; int destPos = 0; - while (destPos < maxDestPos && srcPos < maxSrcPos) { - System.arraycopy(capture, srcPos, tile, destPos, tw); - srcPos += width; - destPos += tw; + System.arraycopy(capture, srcPos, tile, destPos, tw * pixelSize); + srcPos += width * pixelSize; + destPos += tw * pixelSize; } return tile; } diff --git a/src/main/java/mpo/dayon/assisted/capture/CaptureFactory.java b/src/main/java/mpo/dayon/assisted/capture/CaptureFactory.java index 8335e60b..4c784764 100644 --- a/src/main/java/mpo/dayon/assisted/capture/CaptureFactory.java +++ b/src/main/java/mpo/dayon/assisted/capture/CaptureFactory.java @@ -8,6 +8,6 @@ public interface CaptureFactory { Dimension getDimension(); - byte[] captureGray(Gray8Bits quantization); + byte[] captureScreen(Gray8Bits quantization); } diff --git a/src/main/java/mpo/dayon/assisted/capture/RobotCaptureFactory.java b/src/main/java/mpo/dayon/assisted/capture/RobotCaptureFactory.java index d1b2eb51..03347eea 100644 --- a/src/main/java/mpo/dayon/assisted/capture/RobotCaptureFactory.java +++ b/src/main/java/mpo/dayon/assisted/capture/RobotCaptureFactory.java @@ -19,7 +19,7 @@ public Dimension getDimension() { } @Override - public byte[] captureGray(Gray8Bits quantization) { - return ScreenUtilities.captureGray(quantization); + public byte[] captureScreen(Gray8Bits quantization) { + return quantization == null ? ScreenUtilities.captureColors() : ScreenUtilities.captureGray(quantization); } } diff --git a/src/main/java/mpo/dayon/assisted/utils/ScreenUtilities.java b/src/main/java/mpo/dayon/assisted/utils/ScreenUtilities.java index 01ba451b..cad96c03 100644 --- a/src/main/java/mpo/dayon/assisted/utils/ScreenUtilities.java +++ b/src/main/java/mpo/dayon/assisted/utils/ScreenUtilities.java @@ -3,6 +3,7 @@ import java.awt.*; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.nio.ByteBuffer; import mpo.dayon.common.capture.Gray8Bits; @@ -74,12 +75,19 @@ public static byte[] captureGray(Gray8Bits quantization) { return rgbToGray8(quantization, captureRGB(sharedScreenSize)); } + public static byte[] captureColors() { + final int[] ints = captureRGB(sharedScreenSize); + ByteBuffer bb = ByteBuffer.allocate(4 * ints.length); + bb.asIntBuffer().put(ints); + return bb.array(); + } + private static int[] captureRGB(Rectangle bounds) { BufferedImage image = ROBOT.createScreenCapture(bounds); final int imageHeight = min(image.getHeight(), bounds.height); final int imageWidth = min(image.getWidth(), bounds.width); int[] pixels = new int[imageHeight * imageWidth]; - return image.getRGB(0,0, imageWidth, imageHeight, pixels, 0, imageWidth); + return image.getRGB(0, 0, imageWidth, imageHeight, pixels, 0, imageWidth); } public static byte[] captureGray(Rectangle bounds, Gray8Bits quantization) { diff --git a/src/main/java/mpo/dayon/common/buffer/MemByteBuffer.java b/src/main/java/mpo/dayon/common/buffer/MemByteBuffer.java index 76c05733..7c5fd11b 100644 --- a/src/main/java/mpo/dayon/common/buffer/MemByteBuffer.java +++ b/src/main/java/mpo/dayon/common/buffer/MemByteBuffer.java @@ -10,7 +10,6 @@ public class MemByteBuffer extends OutputStream { private static final int DEFAULT_INITIAL_CAPACITY = 32; private byte[] buffer; - private int count; public MemByteBuffer() { @@ -26,8 +25,8 @@ private MemByteBuffer(int capacity) { * the newly created buffer is adopting that byte array (!) */ public MemByteBuffer(byte[] data) { - buffer = data.clone(); count = data.length; + buffer = Arrays.copyOf(data, count); } public int size() { @@ -35,7 +34,7 @@ public int size() { } public byte[] getInternal() { - return buffer.clone(); + return Arrays.copyOf(buffer, count); } public int mark() { @@ -53,8 +52,8 @@ private void resetToMark(int mark) { * b. The 24 high-order bits of b are ignored. */ @Override - public void write(int val) { - increaseBuffer(count + 1); + public void write(int val) { + ensureCapacity(count + 1); buffer[count++] = (byte) val; } @@ -62,25 +61,24 @@ public void write(int val) { * @see #write(int) */ private void write(int val1, int val2) { - increaseBuffer(count + 2); + ensureCapacity(count + 2); buffer[count++] = (byte) val1; buffer[count++] = (byte) val2; } @Override - public void write(byte[] buffer) { + public void write(byte[] buffer) { write(buffer, 0, buffer.length); } @Override - public void write(byte[] buffer, int off, int len) { + public void write(byte[] buffer, int off, int len) { if (len == 0) { return; } - final int newCount = count + len; - increaseBuffer(newCount); + ensureCapacity(count + len); System.arraycopy(buffer, off, this.buffer, count, len); - count = newCount; + count += len; } /** @@ -107,22 +105,20 @@ public void writeLenAsShort(int mark) { } public void fill(int len, int val) { - final int newCount = count + len; - increaseBuffer(newCount); - Arrays.fill(buffer, count, newCount, (byte) val); - count = newCount; + ensureCapacity(count + len); + Arrays.fill(buffer, count, count + len, (byte) val); + count += len; } public void arraycopy(byte[] in, int start, int len) { - final int newCount = count + len; - increaseBuffer(newCount); + ensureCapacity(count + len); System.arraycopy(in, start, buffer, count, len); - count = newCount; + count += len; } - private void increaseBuffer(int newCount) { + private void ensureCapacity(int newCount) { if (newCount > buffer.length) { buffer = Arrays.copyOf(buffer, Math.max(buffer.length << 1, newCount)); } } -} +} \ No newline at end of file diff --git a/src/main/java/mpo/dayon/common/capture/Capture.java b/src/main/java/mpo/dayon/common/capture/Capture.java index 956fd787..2eca2d96 100644 --- a/src/main/java/mpo/dayon/common/capture/Capture.java +++ b/src/main/java/mpo/dayon/common/capture/Capture.java @@ -10,13 +10,14 @@ import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.util.AbstractMap; -import java.util.Arrays; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import mpo.dayon.common.buffer.MemByteBuffer; import mpo.dayon.common.log.Log; +import static java.util.Arrays.stream; + public class Capture { private final int id; @@ -91,7 +92,7 @@ public double computeCompressionRatio(int compressed) { * number of gray levels. */ private int computeInitialByteCount() { - return Arrays.stream(dirty).filter(Objects::nonNull).mapToInt(tile -> tile.getCapture().size()).sum(); + return stream(dirty).filter(Objects::nonNull).mapToInt(tile -> tile.getCapture().size()).sum(); } public int getWidth() { @@ -111,7 +112,7 @@ public int getTHeight() { } public int getDirtyTileCount() { - return (int) Arrays.stream(dirty).filter(Objects::nonNull).count(); + return (int) stream(dirty).filter(Objects::nonNull).count(); } public CaptureTile[] getDirtyTiles() { @@ -128,7 +129,7 @@ public void mergeDirtyTiles(Capture[] olders) { } skipped.addAndGet(xskipped); merged.set(1 + xmerged); - Log.warn(String.format("Merged [id:%d] [count:%d] [skipped:%d][merged:%d]", id, olders.length, skipped.get(), merged.get())); + Log.warn(String.format("Merged [id:%d][count:%d][skipped:%d][merged:%d]", id, olders.length, skipped.get(), merged.get())); } /** @@ -161,20 +162,29 @@ private void doMergeDirtyTiles(Capture older) { * Tile-rectangle buffer to screen-rectangle buffer. */ public AbstractMap.SimpleEntry createBufferedImage(byte[] prevBuffer, int prevWidth, int prevHeight) { + final boolean isGray = stream(dirty) + .anyMatch(tile -> tile != null && tile.getCapture().size() == tile.getWidth() * tile.getHeight()); + return isGray ? createBufferedMonochromeImage(prevBuffer, prevWidth, prevHeight) : createBufferedColorImage(prevBuffer, prevWidth, prevHeight); + } + + /** + * Tile-rectangle buffer to screen-rectangle buffer. (monochromatic, 1 byte per pixel) + */ + private AbstractMap.SimpleEntry createBufferedMonochromeImage(byte[] prevBuffer, int prevWidth, int prevHeight) { final int capWidth = captureDimension.width; final int capHeight = captureDimension.height; - final byte[] buffer = (prevBuffer != null && capWidth == prevWidth && capHeight == prevHeight) ? prevBuffer : new byte[capWidth * capHeight]; - Arrays.stream(dirty) + final byte[] buffer = (prevBuffer != null && capWidth == prevWidth && capHeight == prevHeight && prevBuffer.length == capWidth * capHeight) ? prevBuffer : new byte[capWidth * capHeight]; + stream(dirty) .parallel() .filter(Objects::nonNull) .forEach(tile -> { final MemByteBuffer src = tile.getCapture(); - final int srcSize = src.size(); - final int tw = tile.getWidth(); - int destPos = tile.getY() * captureDimension.width + tile.getX(); - for (int srcPos = 0; srcPos < srcSize; srcPos += tw) { - System.arraycopy(src.getInternal(), srcPos, buffer, destPos, tw); - destPos += captureDimension.width; + final int tileWidth = tile.getWidth(); + final int srcSize = tileWidth * tile.getHeight(); + int destPos = tile.getY() * capWidth + tile.getX(); + for (int srcPos = 0; srcPos < srcSize; srcPos += tileWidth) { + System.arraycopy(src.getInternal(), srcPos, buffer, destPos, tileWidth); + destPos += capWidth; } }); @@ -183,4 +193,32 @@ public AbstractMap.SimpleEntry createBufferedImage(byte[] final ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] { 8 }, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); return new AbstractMap.SimpleEntry<>(new BufferedImage(cm, raster, false, null), buffer); } + + /** + * Tile-rectangle buffer to screen-rectangle buffer. (color, 4 bytes per pixel) + */ + private AbstractMap.SimpleEntry createBufferedColorImage(byte[] prevBuffer, int prevWidth, int prevHeight) { + final int capWidth = captureDimension.width; + final int capHeight = captureDimension.height; + final byte[] buffer = (prevBuffer != null && capWidth == prevWidth && capHeight == prevHeight && prevBuffer.length == capWidth * capHeight * 4) ? prevBuffer : new byte[capWidth * capHeight * 4]; + final int capWidthByteSize = capWidth * 4; + stream(dirty) + .parallel() + .filter(Objects::nonNull) + .forEach(tile -> { + final MemByteBuffer src = tile.getCapture(); + final int tileWidthByteSize = tile.getWidth() * 4; + final int srcSize = tileWidthByteSize * tile.getHeight(); + int destPos = tile.getY() * capWidthByteSize + tile.getX() * 4; + for (int srcPos = 0; srcPos < srcSize; srcPos += tileWidthByteSize) { + System.arraycopy(src.getInternal(), srcPos, buffer, destPos, tileWidthByteSize); + destPos += capWidthByteSize; + } + }); + + final DataBufferByte dbuffer = new DataBufferByte(buffer, buffer.length); + final WritableRaster raster = Raster.createInterleavedRaster(dbuffer, capWidth, capHeight, capWidthByteSize , 4, new int[] { 1, 2, 3 }, null); + final ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); + return new AbstractMap.SimpleEntry<>(new BufferedImage(cm, raster, false, null), buffer); + } } diff --git a/src/main/java/mpo/dayon/common/capture/CaptureEngineConfiguration.java b/src/main/java/mpo/dayon/common/capture/CaptureEngineConfiguration.java index 1a1ca3d5..4c52c46c 100644 --- a/src/main/java/mpo/dayon/common/capture/CaptureEngineConfiguration.java +++ b/src/main/java/mpo/dayon/common/capture/CaptureEngineConfiguration.java @@ -10,6 +10,8 @@ public class CaptureEngineConfiguration extends Configuration { private static final String PREF_CAPTURE_QUANTIZATION = "assistant.capture.grayLevelQuantization"; + private static final String PREF_CAPTURE_COLORS = "assistant.capture.colors"; + /** * A capture is performed every tick (millis). */ @@ -20,6 +22,8 @@ public class CaptureEngineConfiguration extends Configuration { */ private final Gray8Bits captureQuantization; + private final boolean captureColors; + /** * Default : takes its values from the current preferences. * @@ -29,11 +33,13 @@ public CaptureEngineConfiguration() { final Preferences prefs = Preferences.getPreferences(); captureTick = prefs.getIntPreference(PREF_CAPTURE_TICK, 200); captureQuantization = prefs.getEnumPreference(PREF_CAPTURE_QUANTIZATION, Gray8Bits.X_128, Gray8Bits.values()); + captureColors = prefs.getBooleanPreference(PREF_CAPTURE_COLORS, false); } - public CaptureEngineConfiguration(int captureTick, Gray8Bits captureQuantization) { + public CaptureEngineConfiguration(int captureTick, Gray8Bits captureQuantization, boolean captureColor) { this.captureTick = captureTick; this.captureQuantization = captureQuantization; + this.captureColors = captureColor; } public int getCaptureTick() { @@ -44,6 +50,10 @@ public Gray8Bits getCaptureQuantization() { return captureQuantization; } + public boolean isCaptureColors() { + return captureColors; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -55,12 +65,12 @@ public boolean equals(Object o) { final CaptureEngineConfiguration that = (CaptureEngineConfiguration) o; - return captureTick == that.getCaptureTick() && captureQuantization == that.getCaptureQuantization(); + return captureTick == that.getCaptureTick() && captureQuantization == that.getCaptureQuantization() && captureColors == that.captureColors; } @Override public int hashCode() { - return 31 * captureTick + (captureQuantization != null ? captureQuantization.hashCode() : 0); + return 31 * captureTick + (captureQuantization != null ? captureQuantization.hashCode() : 0) + (captureColors ? 1 : 0); } /** @@ -77,6 +87,7 @@ private Preferences.Props getProps(boolean clear) { props.set(PREF_VERSION, String.valueOf(1)); props.set(PREF_CAPTURE_TICK, String.valueOf(captureTick)); props.set(PREF_CAPTURE_QUANTIZATION, String.valueOf(captureQuantization.ordinal())); + props.set(PREF_CAPTURE_COLORS, String.valueOf(captureColors)); // migration support (!) if (clear) { @@ -87,6 +98,6 @@ private Preferences.Props getProps(boolean clear) { @Override public String toString() { - return "[tick:" + captureTick + "][quantization:" + captureQuantization + "]"; + return "[tick:" + captureTick + "][quantization:" + captureQuantization + "][color:" + captureColors + "]"; } } diff --git a/src/main/java/mpo/dayon/common/capture/CaptureTile.java b/src/main/java/mpo/dayon/common/capture/CaptureTile.java index 83e43859..a94c52a2 100644 --- a/src/main/java/mpo/dayon/common/capture/CaptureTile.java +++ b/src/main/java/mpo/dayon/common/capture/CaptureTile.java @@ -59,9 +59,6 @@ public CaptureTile(XYWH xywh, MemByteBuffer capture) { this.width = xywh.w; this.height = xywh.h; this.capture = capture; - if (width * height != capture.size()) { - throw new IllegalArgumentException("Ouch!"); - } this.singleLevel = -1; this.fromCache = false; } @@ -74,7 +71,7 @@ public CaptureTile(XYWH xywh, byte singleLevel) { this.position = new Position(xywh.x, xywh.y); this.width = xywh.w; this.height = xywh.h; - final byte[] data = new byte[width * height]; + final byte[] data = new byte[width * height * 4]; Arrays.fill(data, singleLevel); this.capture = new MemByteBuffer(data); this.singleLevel = singleLevel; @@ -89,11 +86,8 @@ public CaptureTile(XYWH xywh, CaptureTile cached) { this.position = new Position(xywh.x, xywh.y); this.width = xywh.w; this.height = xywh.h; - this.capture = (cached == MISSING) ? new MemByteBuffer(new byte[width * height]) // black image (!) + this.capture = (cached == MISSING) ? new MemByteBuffer(new byte[width * height * 4]) // black image (!) : cached.getCapture(); // sharing it (!) - if (width * height != capture.size()) { - throw new IllegalArgumentException("Ouch!"); - } this.singleLevel = -1; this.fromCache = true; } @@ -122,6 +116,10 @@ public int getWidth() { return width; } + public int getHeight() { + return height; + } + public MemByteBuffer getCapture() { return capture; } diff --git a/src/main/java/mpo/dayon/common/network/NetworkSender.java b/src/main/java/mpo/dayon/common/network/NetworkSender.java index da1afeb0..fb145961 100644 --- a/src/main/java/mpo/dayon/common/network/NetworkSender.java +++ b/src/main/java/mpo/dayon/common/network/NetworkSender.java @@ -100,8 +100,8 @@ public boolean sendMouseLocation(Point location) { *

* Assistant 2 assisted. */ - public void sendCaptureConfiguration(CaptureEngineConfiguration configuration) { - send(true, new NetworkCaptureConfigurationMessage(configuration)); + public void sendCaptureConfiguration(CaptureEngineConfiguration configuration, boolean monochromePeer) { + send(true, new NetworkCaptureConfigurationMessage(configuration, monochromePeer)); } /** diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkCaptureConfigurationMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkCaptureConfigurationMessage.java index 485d4651..af61873c 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkCaptureConfigurationMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkCaptureConfigurationMessage.java @@ -7,9 +7,11 @@ public class NetworkCaptureConfigurationMessage extends NetworkMessage { private final CaptureEngineConfiguration configuration; + private final boolean monochromePeer; - public NetworkCaptureConfigurationMessage(CaptureEngineConfiguration configuration) { + public NetworkCaptureConfigurationMessage(CaptureEngineConfiguration configuration, boolean monochromePeer) { this.configuration = configuration; + this.monochromePeer = monochromePeer; } @Override @@ -27,7 +29,11 @@ public CaptureEngineConfiguration getConfiguration() { */ @Override public int getWireSize() { - return 6; // type (byte) + quantization (byte) + tick (int) + // for backwards compatibility + if (monochromePeer) { + return 6; + } + return 8; // type (byte) + quantization (byte) + tick (int) + colors (short) } @Override @@ -35,15 +41,21 @@ public void marshall(ObjectOutputStream out) throws IOException { marshallEnum(out, getType()); marshallEnum(out, configuration.getCaptureQuantization()); out.writeInt(configuration.getCaptureTick()); + // for backwards compatibility + if (!monochromePeer) { + out.writeShort(configuration.isCaptureColors() ? 1 : 0); + } } public static NetworkCaptureConfigurationMessage unmarshall(ObjectInputStream in) throws IOException { final Gray8Bits quantization = unmarshallEnum(in, Gray8Bits.class); - return new NetworkCaptureConfigurationMessage(new CaptureEngineConfiguration(in.readInt(), quantization)); + final int tick = in.readInt(); + final boolean colors = in.readShort() == 1; + return new NetworkCaptureConfigurationMessage(new CaptureEngineConfiguration(tick, quantization, colors), false); } public String toString() { - return String.format("[quantization:%s] [tick:%d]", configuration.getCaptureQuantization(), configuration.getCaptureTick()); + return String.format("[quantization:%s][tick:%d][colors:%b]", configuration.getCaptureQuantization(), configuration.getCaptureTick(), configuration.isCaptureColors()); } } diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkCaptureMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkCaptureMessage.java index b85fa0a7..f622916f 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkCaptureMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkCaptureMessage.java @@ -102,6 +102,6 @@ public MemByteBuffer getPayload() { } public String toString() { - return String.format("[id:%d] [%s]", id, UnitUtilities.toBitSize(8d * payload.size())); + return String.format("[id:%d][%s]", id, UnitUtilities.toBitSize(8d * payload.size())); } } \ No newline at end of file diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkClipboardFilesMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkClipboardFilesMessage.java index 5241b867..6adc85e4 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkClipboardFilesMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkClipboardFilesMessage.java @@ -52,11 +52,14 @@ public static NetworkClipboardFilesHelper unmarshall(ObjectInputStream in, Netwo if (!append) { Log.info("Receiving " + fileName); } - String tempFilePath = format("%s%s%s%s", tmpDir, File.separator, helper.getTransferId(), fileName); + if (!tmpDir.endsWith(File.separator)) { + tmpDir += File.separator; + } + String tempFilePath = format("%s%s%s", tmpDir, helper.getTransferId(), fileName); writeToTempFile(buffer, read, tempFilePath, append); if (getRemainingTotalFilesSize(helper, read, position) == 0) { - String rootPath = format("%s%s%s", tmpDir, File.separator, helper.getTransferId()); + String rootPath = format("%s%s", tmpDir, helper.getTransferId()); File[] filesArray = new File(rootPath).listFiles(); if (filesArray != null) { helper.setFiles(Arrays.asList(Objects.requireNonNull(filesArray))); diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkHelloMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkHelloMessage.java index c287d18c..117f6064 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkHelloMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkHelloMessage.java @@ -69,6 +69,6 @@ public static NetworkHelloMessage unmarshall(ObjectInputStream in) throws IOExce } public String toString() { - return String.format("[major:%d] [minor:%d] [osId:%c] [inputLocale:%s]", major, minor, osId, inputLocale); + return String.format("[major:%d][minor:%d][osId:%c][inputLocale:%s]", major, minor, osId, inputLocale); } } \ No newline at end of file diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkMouseControlMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkMouseControlMessage.java index 78df660a..596e4dd8 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkMouseControlMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkMouseControlMessage.java @@ -128,9 +128,9 @@ public static NetworkMouseControlMessage unmarshall(ObjectInputStream in) throws public String toString() { if (isWheel()) { - return String.format("[x:%d] [y:%s] [WHEEL] [%d]", x, y, rotations); + return String.format("[x:%d][y:%s][WHEEL][%d]", x, y, rotations); } - return String.format("[x:%d] [y:%s] [%s] [%s]", x, y, toStringPressed(), toStringButton()); + return String.format("[x:%d][y:%s][%s][%s]", x, y, toStringPressed(), toStringButton()); } private String toStringPressed() { diff --git a/src/main/java/mpo/dayon/common/network/message/NetworkMouseLocationMessage.java b/src/main/java/mpo/dayon/common/network/message/NetworkMouseLocationMessage.java index 0b6ccdfa..ddd35177 100644 --- a/src/main/java/mpo/dayon/common/network/message/NetworkMouseLocationMessage.java +++ b/src/main/java/mpo/dayon/common/network/message/NetworkMouseLocationMessage.java @@ -51,6 +51,6 @@ public static NetworkMouseLocationMessage unmarshall(ObjectInputStream in) throw } public String toString() { - return String.format("[x:%d] [y:%s]", x, y); + return String.format("[x:%d][y:%s]", x, y); } } \ No newline at end of file diff --git a/src/main/java/mpo/dayon/common/squeeze/Compressor.java b/src/main/java/mpo/dayon/common/squeeze/Compressor.java index c32e9f2b..0a2061c5 100644 --- a/src/main/java/mpo/dayon/common/squeeze/Compressor.java +++ b/src/main/java/mpo/dayon/common/squeeze/Compressor.java @@ -64,7 +64,7 @@ public MemByteBuffer compress(TileCache cache, Capture capture) throws IOExcepti encoded.write(capture.getSkipped()); // as a byte (!) encoded.write(capture.getMerged()); // as a byte (!) if (capture.isReset()) { - Log.info("Clear compressor cache [tile:" + capture.getId() + "]"); + Log.debug("Clear compressor cache [tile:" + capture.getId() + "]"); cache.clear(); // here for symmetry with the de-compressor (!) } encoded.writeShort(capture.getWidth()); @@ -139,7 +139,7 @@ public Capture decompress(TileCache cache, MemByteBuffer zipped) throws IOExcept final int cId = in.readInt(); final boolean cReset = in.read() == 1; if (cReset) { - Log.info("Clear de-compressor cache [tile:" + cId + "]"); + Log.debug("Clear de-compressor cache [tile:" + cId + "]"); cache.clear(); } final int cSkipped = in.readByte() & 0xFF; diff --git a/src/main/java/mpo/dayon/common/squeeze/RegularTileCache.java b/src/main/java/mpo/dayon/common/squeeze/RegularTileCache.java index 3732c3dc..16828f36 100644 --- a/src/main/java/mpo/dayon/common/squeeze/RegularTileCache.java +++ b/src/main/java/mpo/dayon/common/squeeze/RegularTileCache.java @@ -11,14 +11,14 @@ public class RegularTileCache implements TileCache { /** - * Maximum number of tiles; currently a tile is basically a 32x32 byte array (i.e., 1K). + * Maximum number of tiles; currently a tile is basically a 32x32 byte array (i.e., 1K for gray, 4K for color). */ - public static final int DEFAULT_MAX_SIZE = 16 * 1024; + public static final int DEFAULT_MAX_SIZE = 32 * 4096; /** * Number of tiles after a purge. */ - public static final int DEFAULT_PURGE_SIZE = 14 * 1024; + public static final int DEFAULT_PURGE_SIZE = 24 * 4096; private final Map tiles = new HashMap<>(); @@ -73,7 +73,7 @@ public int size() { @Override public void clear() { - Log.info("Clearing the cache..."); + Log.debug("Clearing the cache..."); tiles.clear(); lru.clear(); } diff --git a/src/main/java/mpo/dayon/common/version/Version.java b/src/main/java/mpo/dayon/common/version/Version.java index 31f95d61..e34e7dec 100644 --- a/src/main/java/mpo/dayon/common/version/Version.java +++ b/src/main/java/mpo/dayon/common/version/Version.java @@ -96,6 +96,17 @@ public static boolean isCompatibleVersion(int major, int minor, Version that) { return that.getMajor() == major && that.getMinor() == minor; } + public static boolean isOutdatedVersion(int major, int otherMajor) { + if (major == 0 || otherMajor == 0) { + return false; + } + return major > otherMajor; + } + + public static boolean isColoredVersion(int major) { + return major > 14 || major == 0; + } + static boolean isProd(int major, int minor) { return major + minor > 0; } diff --git a/src/main/resources/Babylon.properties b/src/main/resources/Babylon.properties index e55daff0..36c7f5be 100644 --- a/src/main/resources/Babylon.properties +++ b/src/main/resources/Babylon.properties @@ -144,6 +144,7 @@ capture.reset = Reset screen capture (i.e., cache, etc...) tick = Tick tick.tooltip = The screen is captured every [ tick ] milliseconds grays = Gray levels +colors = True colors # Compression ... @@ -187,11 +188,14 @@ share.all.screens = Share all screens compatibility.mode = Compatibility mode for previous versions compatibility.mode.enable = Enable compatibility mode! compatibility.mode.active = Compatibility mode active -compatibility.mode.info = Please consider updating Assisted to the latest version to minimize risks. +compatibility.mode.info = Please consider updating your peer to the latest version to minimize risks. changeLanguage = Change language startChat = Start a chat keyboardlayout.msg1 = The assisted currently uses a different keyboard layout: %s keyboardlayout.msg2 = This can lead to problems, especially when entering special characters. -keyboardlayout.msg3 = If you experience problems, please ensure you are using the same on both computers. \ No newline at end of file +keyboardlayout.msg3 = If you experience problems, please ensure you are using the same on both computers. + +outdated.msg1 = Reduced functionality. +outdated.msg2 = Update your peer to the latest version to enjoy all features. \ No newline at end of file diff --git a/src/main/resources/Babylon_de.properties b/src/main/resources/Babylon_de.properties index 7daa2e6c..01a815bf 100644 --- a/src/main/resources/Babylon_de.properties +++ b/src/main/resources/Babylon_de.properties @@ -140,6 +140,7 @@ capture.reset = Bildschirmerfassung zur\u00FCck setzen (Puffer, etc...) tick = Tick tick.tooltip = Bildschirmerfassungs-Intervall [ tick ] Millisekunden grays = Graustufen +colors = Farben # Compression ... @@ -183,11 +184,14 @@ share.all.screens = Alle Bildschirme teilen compatibility.mode = Kompatibilit\u00E4tsmodus f\u00FCr Vorg\u00E4ngerversionen compatibility.mode.enable = Kompatibilit\u00E4tsmodus aktivieren! compatibility.mode.active = Kompatibilit\u00E4tsmodus aktiv -compatibility.mode.info = Um Sicherheitsrisiken zu minimieren, aktualisieren Sie doch bitte den Assistierten auf die neuste Version. +compatibility.mode.info = Um Sicherheitsrisiken zu minimieren, aktualisieren Sie doch bitte die Gegenseite auf die neuste Version. changeLanguage = Sprache \u00E4ndern startChat = Chat starten keyboardlayout.msg1 = Der Assistierte verwendet derzeit eine andere Tastaturbelegung: %s keyboardlayout.msg2 = Dies kann insbesondere bei der Eingabe von Sonderzeichen zu Problemen f\u00FChren. -keyboardlayout.msg3 = Sollten Probleme auftreten, stellen Sie bitte sicher,\ndass Sie auf beiden Computern die gleiche Tastaturbelegung verwenden. \ No newline at end of file +keyboardlayout.msg3 = Sollten Probleme auftreten, stellen Sie bitte sicher,\ndass Sie auf beiden Computern die gleiche Tastaturbelegung verwenden. + +outdated.msg1 = Reduzierter Funktionsumfang. +outdated.msg2 = Aktualisieren Sie die Gegenseite auf die neuste Version um alle Funktionen zu nutzen. \ No newline at end of file diff --git a/src/main/resources/Babylon_es.properties b/src/main/resources/Babylon_es.properties index 0d6a5724..56a56a27 100644 --- a/src/main/resources/Babylon_es.properties +++ b/src/main/resources/Babylon_es.properties @@ -144,6 +144,7 @@ capture.reset = Reiniciar grabaci\u00F3n de pantalla (cach\u00E9, etc...) tick = Periodo tick.tooltip = La pantalla est\u00E1 grabado cada [ periodo ] de milisegundos grays = Escala de grises +colors = Colores aut\u00E9nticos # Compression ... @@ -187,11 +188,14 @@ share.all.screens = Compartir todas las pantallas compatibility.mode = Modo de compatibilidad para versiones anteriores compatibility.mode.enable = \u00A1Habilite el modo de compatibilidad! compatibility.mode.active = Modo de compatibilidad activo -compatibility.mode.info = Por favor, considere actualizar Assisted a la \u00FAltima versi\u00F3n para minimizar los riesgos. +compatibility.mode.info = Por favor, considere actualizar tu par a la \u00FAltima versi\u00F3n para minimizar los riesgos. changeLanguage = Cambiar el idioma startChat = Iniciar un chat keyboardlayout.msg1 = Actualmente, el asistido utiliza una distribuci\u00F3n de teclado diferente: %s keyboardlayout.msg2 = Esto puede ocasionar problemas, especialmente al introducir caracteres especiales. -keyboardlayout.msg3 = Si se producen problemas, aseg\u00FArese de que utiliza la misma distribuci\u00F3n de teclado en ambos ordenadores. \ No newline at end of file +keyboardlayout.msg3 = Si se producen problemas, aseg\u00FArese de que utiliza la misma distribuci\u00F3n de teclado en ambos ordenadores. + +outdated.msg1 = Funciones reducidas. +outdated.msg2 = Actualiza tu par a la \u00FAltima versi\u00F3n para disfrutar de todas las funciones. \ No newline at end of file diff --git a/src/main/resources/Babylon_fr.properties b/src/main/resources/Babylon_fr.properties index a8970a83..1f46f13e 100644 --- a/src/main/resources/Babylon_fr.properties +++ b/src/main/resources/Babylon_fr.properties @@ -144,6 +144,7 @@ capture.reset = Remise-\u00E0-Z\u00E9ro de la capture d'\u00E9cran (i.e., tick = Tic-tac tick.tooltip = L'\u00E9cran est captur\u00E9 tous les [ tic-tac ] milli-secondes grays = Niveaux de Gris +colors = Couleurs r\u00E9elles # Compression ... @@ -187,11 +188,14 @@ share.all.screens = Partager tous les \u00E9crans compatibility.mode = Mode de compatibilit\u00E9 pour les versions pr\u00E9c\u00E9dentes compatibility.mode.enable = Activez le mode compatibilit\u00E9! compatibility.mode.active = Mode de compatibilit\u00E9 actif -compatibility.mode.info = Veuillez consid\u00E9rer la mise \u00E0 jour de l'assist\u00E9 vers la derni\u00E8re version afin de minimiser les risques. +compatibility.mode.info = Veuillez consid\u00E9rer la mise \u00E0 jour de votre peer vers la derni\u00E8re version afin de minimiser les risques. changeLanguage = Changer la langue startChat = Commencer un chat keyboardlayout.msg1 = L'assist\u00E9 utilise actuellement une autre disposition de clavier : %s keyboardlayout.msg2 = Cela peut entra\u00EEner des probl\u00E8mes, notamment lors de la saisie de caract\u00E8res sp\u00E9ciaux. -keyboardlayout.msg3 = En cas de probl\u00E8me, assurez-vous que vous utilisez la m\u00EAme disposition de clavier sur les deux ordinateurs. \ No newline at end of file +keyboardlayout.msg3 = En cas de probl\u00E8me, assurez-vous que vous utilisez la m\u00EAme disposition de clavier sur les deux ordinateurs. + +outdated.msg1 = Fonctionnalit\u00E9s r\u00E9duites. +outdated.msg2 = Mettez \u00E0 jour votre peer vers la derni\u00E8re version pour profiter de toutes les fonctionnalit\u00E9s. \ No newline at end of file diff --git a/src/main/resources/Babylon_it.properties b/src/main/resources/Babylon_it.properties index 1652e63e..d62b27d7 100644 --- a/src/main/resources/Babylon_it.properties +++ b/src/main/resources/Babylon_it.properties @@ -144,6 +144,7 @@ capture.reset = Reimposta l'acquisizione dello schermo (ad esempio, cache tick = Tick tick.tooltip = Lo schermo viene catturato ogni [ tick ] milli-secondi grays = Livelli di grigio +colors = Colori reali # Compression ... @@ -187,11 +188,14 @@ share.all.screens = Condividi tutti gli schermi compatibility.mode = Modalit\u00E0 di compatibilit\u00E0 per le versioni precedenti compatibility.mode.enable = Abilita la modalit\u00E0 compatibilit\u00E0! compatibility.mode.active = Modalit\u00E0 di compatibilit\u00E0 attiva -compatibility.mode.info = Si consiglia di aggiornare assistito alla versione pi\u00F9 recente per ridurre al minimo i rischi. +compatibility.mode.info = Si consiglia di aggiornare il tuo peer all'ultima versione per ridurre al minimo i rischi. changeLanguage = Cambiare la lingua startChat = Iniziare una chat keyboardlayout.msg1 = L'assistito utilizza attualmente un layout di tastiera diverso: %s keyboardlayout.msg2 = Questo pu\u00F2 causare problemi, soprattutto nell'inserimento di caratteri speciali. -keyboardlayout.msg3 = In caso di problemi, accertarsi di utilizzare lo stesso layout di tastiera su entrambi i computer. \ No newline at end of file +keyboardlayout.msg3 = In caso di problemi, accertarsi di utilizzare lo stesso layout di tastiera su entrambi i computer. + +outdated.msg1 = Funzionalit\u00E0 ridotta. +outdated.msg2 = Aggiorna il tuo peer all'ultima versione per usufruire di tutte le funzionalit\u00E0. \ No newline at end of file diff --git a/src/main/resources/Babylon_ru.properties b/src/main/resources/Babylon_ru.properties index 76f24767..9c62c4bb 100644 --- a/src/main/resources/Babylon_ru.properties +++ b/src/main/resources/Babylon_ru.properties @@ -144,6 +144,7 @@ capture.reset = \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0441\u tick = Tick tick.tooltip = \u042D\u043A\u0440\u0430\u043D \u0441\u043D\u0438\u043C\u0430\u0435\u0442\u0441\u044F \u043A\u0430\u0436\u0434\u044B\u0435 [ tick ] \u043C\u0438\u043B\u043B\u0438\u0441\u0435\u043A\u0443\u043D\u0434\u044B grays = \u0423\u0440\u043E\u0432\u043D\u0438 \u0441\u0435\u0440\u043E\u0433\u043E +colors = \u041D\u0430\u0441\u0442\u043E\u044F\u0449\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 # Compression ... @@ -187,11 +188,14 @@ share.all.screens = \u0414\u0435\u043B\u0438\u0442\u0435\u0441\u044C \u0432\u044 compatibility.mode = \u0420\u0435\u0436\u0438\u043C \u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u043E\u0441\u0442\u0438 \u0441 \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u043C\u0438 \u0432\u0435\u0440\u0441\u0438\u044F\u043C\u0438 compatibility.mode.enable = \u0412\u043A\u043B\u044E\u0447\u0438\u0442\u0435 \u0440\u0435\u0436\u0438\u043C \u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u043E\u0441\u0442\u0438! compatibility.mode.active = \u0420\u0435\u0436\u0438\u043C \u0441\u043E\u0432\u043C\u0435\u0441\u0442\u0438\u043C\u043E\u0441\u0442\u0438 \u0430\u043A\u0442\u0438\u0432\u0435\u043D -compatibility.mode.info = \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u043E\u0431\u043D\u043E\u0432\u0438\u0442\u0435 \u041F\u043E\u043C\u043E\u0433\u0430\u043B \u0434\u043E \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0447\u0442\u043E\u0431\u044B \u043C\u0438\u043D\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0438\u0441\u043A\u0438. +compatibility.mode.info = \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0440\u0430\u0441\u0441\u043C\u043E\u0442\u0440\u0438\u0442\u0435 \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u044C \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F \u0432\u0430\u0448\u0435\u0433\u043E \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u0430 \u0434\u043E \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0447\u0442\u043E\u0431\u044B \u043C\u0438\u043D\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0438\u0441\u043A\u0438. changeLanguage = \u0438\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u044F\u0437\u044B\u043A startChat = \u043D\u0430\u0447\u0430\u0442\u044C \u0447\u0430\u0442 keyboardlayout.msg1 = \u0412 \u043D\u0430\u0441\u0442\u043E\u044F\u0449\u0435\u0435 \u0432\u0440\u0435\u043C\u044F \u041F\u043E\u043C\u043E\u0433\u0430\u043B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442 \u0434\u0440\u0443\u0433\u0443\u044E \u0440\u0430\u0441\u043A\u043B\u0430\u0434\u043A\u0443 \u043A\u043B\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044B: %s keyboardlayout.msg2 = \u042D\u0442\u043E \u043C\u043E\u0436\u0435\u0442 \u043F\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043A \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0430\u043C, \u043E\u0441\u043E\u0431\u0435\u043D\u043D\u043E \u043F\u0440\u0438 \u0432\u0432\u043E\u0434\u0435 \u0441\u043F\u0435\u0446\u0438\u0430\u043B\u044C\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432. -keyboardlayout.msg3 = \u0415\u0441\u043B\u0438 \u0432\u043E\u0437\u043D\u0438\u043A\u043B\u0438 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044C, \u0447\u0442\u043E \u043D\u0430 \u043E\u0431\u043E\u0438\u0445 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430\u0445 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u043E\u0434\u0438\u043D\u0430\u043A\u043E\u0432\u0430\u044F \u0440\u0430\u0441\u043A\u043B\u0430\u0434\u043A\u0430 \u043A\u043B\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044B. \ No newline at end of file +keyboardlayout.msg3 = \u0415\u0441\u043B\u0438 \u0432\u043E\u0437\u043D\u0438\u043A\u043B\u0438 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044C, \u0447\u0442\u043E \u043D\u0430 \u043E\u0431\u043E\u0438\u0445 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430\u0445 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u043E\u0434\u0438\u043D\u0430\u043A\u043E\u0432\u0430\u044F \u0440\u0430\u0441\u043A\u043B\u0430\u0434\u043A\u0430 \u043A\u043B\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044B. + +outdated.msg1 = \u0421\u043D\u0438\u0436\u0435\u043D\u043D\u0430\u044F \u0444\u0443\u043D\u043A\u0446\u0438\u043E\u043D\u0430\u043B\u044C\u043D\u043E\u0441\u0442\u044C. +outdated.msg2 = \u041E\u0431\u043D\u043E\u0432\u0438\u0442\u0435 \u0441\u0432\u043E\u0435 \u0443\u0441\u0442\u0440\u043E\u0439\u0441\u0442\u0432\u043E \u0434\u043E \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u0447\u0442\u043E\u0431\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C\u0441\u044F \u0432\u0441\u0435\u043C\u0438 \u0444\u0443\u043D\u043A\u0446\u0438\u044F\u043C\u0438. \ No newline at end of file diff --git a/src/main/resources/Babylon_sv.properties b/src/main/resources/Babylon_sv.properties index 94ea07b3..5fde21e8 100644 --- a/src/main/resources/Babylon_sv.properties +++ b/src/main/resources/Babylon_sv.properties @@ -144,6 +144,7 @@ capture.reset = \u00C5terst\u00E4ll sk\u00E4rmbild (dvs. cache osv...) tick = Tick tick.tooltip = Sk\u00E4rmbilden avl\u00E4ses [ tick ] millisekunder grays = Gr\u00E5skalor +colors = Sanna f\u00E4rger # Compression ... @@ -187,11 +188,14 @@ share.all.screens = Dela alla sk\u00E4rmar compatibility.mode = Kompatibelt l\u00E4ge f\u00F6r tidigare versioner compatibility.mode.enable = Aktivera kompatibilitetsl\u00E4ge! compatibility.mode.active = Kompatibiltetsl\u00E4ge aktiverat -compatibility.mode.info = V\u00E4nligen uppdatera Hj\u00E4lptagare till den senaste versionen f\u00F6r att minimera risker. +compatibility.mode.info = V\u00E4nligen uppdatera din peer till den senaste versionen f\u00F6r att minimera risker. changeLanguage = V\u00E4xla spr\u00E5kl\u00E4ge startChat = Starta en chatt keyboardlayout.msg1 = Hj\u00E4lptagare anv\u00E4nder f\u00F6r n\u00E4rvarande en annan tangentbordslayout: %s keyboardlayout.msg2 = Detta kan leda till problem, s\u00E4rskilt vid inmatning av specialtecken. -keyboardlayout.msg3 = Om du upplever problem, kontrollera att du anv\u00E4nder samma tangentbord p\u00E5 b\u00E5da datorerna. \ No newline at end of file +keyboardlayout.msg3 = Om du upplever problem, kontrollera att du anv\u00E4nder samma tangentbord p\u00E5 b\u00E5da datorerna. + +outdated.msg1 = Reducerad funktionalitet. +outdated.msg2 = Uppdatera din peer till den senaste versionen f\u00F6r att njuta av alla funktioner. \ No newline at end of file diff --git a/src/main/resources/Babylon_tr.properties b/src/main/resources/Babylon_tr.properties index ee5bead5..a140ef32 100644 --- a/src/main/resources/Babylon_tr.properties +++ b/src/main/resources/Babylon_tr.properties @@ -144,6 +144,7 @@ capture.reset = Ekran g\u00F6r\u00FCnt\u00FCs\u00FCn\u00FC s\u0131f\u0131 tick = Tik tick.tooltip = Ekran her [tik] milisaniyede bir yakalan\u0131r grays = Gri seviyeleri +colors = Ger\u00E7ek renkler # Compression ... @@ -187,11 +188,14 @@ share.all.screens = T\u00FCm ekranlar\u0131 payla\u015F compatibility.mode = \u00D6nceki s\u00FCr\u00FCmler i\u00E7in uyumluluk modu compatibility.mode.enable = Uyumluluk modunu etkinle\u015Ftirin! compatibility.mode.active = Uyumluluk modu etkin -compatibility.mode.info = Riskleri en aza indirmek i\u00E7in l\u00FCtfen yard\u0131ml\u0131 en son s\u00FCr\u00FCme g\u00FCncellemeyi d\u00FC\u015F\u00FCn\u00FCn. +compatibility.mode.info = Riskleri en aza indirmek i\u00E7in l\u00FCtfen akran\u0131n\u0131z\u0131 en son s\u00FCr\u00FCme g\u00FCncellemeyi d\u00FC\u015F\u00FCn\u00FCn. changeLanguage = Dili de\u011Fi\u015Ftir startChat = Sohbet ba\u015Flat keyboardlayout.msg1 = Yard\u0131ml\u0131 \u015Fu anda farkl\u0131 bir klavye d\u00FCzeni kullan\u0131yor: %s keyboardlayout.msg2 = Bu, \u00F6zellikle \u00F6zel karakterleri girerken sorunlara neden olabilir. -keyboardlayout.msg3 = Sorun ya\u015Farsan\u0131z, l\u00FCtfen her iki bilgisayarda da ayn\u0131 klavyeyi kulland\u0131\u011F\u0131n\u0131zdan emin olun. \ No newline at end of file +keyboardlayout.msg3 = Sorun ya\u015Farsan\u0131z, l\u00FCtfen her iki bilgisayarda da ayn\u0131 klavyeyi kulland\u0131\u011F\u0131n\u0131zdan emin olun. + +outdated.msg1 = Azalt\u0131lm\u0131\u015F i\u015Flevsellik. +outdated.msg2 = T\u00FCm \u00F6zelliklerden yararlanabilmek i\u00E7in arkada\u015F\u0131n\u0131z\u0131 en son s\u00FCr\u00FCme g\u00FCncelleyin. diff --git a/src/main/resources/Babylon_zh.properties b/src/main/resources/Babylon_zh.properties index 1e4932e3..e671cc96 100644 --- a/src/main/resources/Babylon_zh.properties +++ b/src/main/resources/Babylon_zh.properties @@ -218,6 +218,8 @@ tick.tooltip = \u6BCF [\u6355\u83B7\u95F4\u9694] \u6BEB\u79D2\u6355\u83B # The tick is not a valid number. (min. 50) # Gray levels grays = \u7070\u5EA6\uFF08\u753B\u8D28\uFF09 +# True colors +colors = \u771F\u9762\u76EE # Compression ... @@ -297,6 +299,9 @@ compatibility.mode.info = \u8BF7\u8003\u8651\u5C06\u60A8\u7684\u540C\u884C\u7CFB changeLanguage = \u6539\u53D8\u8BED\u8A00 startChat = \u5F00\u59CB\u804A\u5929 -Keyboardlayout.msg1 = Assisted - \u7528\u6237\u7AEF\u5F53\u524D\u4F7F\u7528\u4E0D\u540C\u7684\u952E\u76D8\u5E03\u5C40\uFF1A%s -Keyboardlayout.msg2 = \u8FD9\u53EF\u80FD\u4F1A\u5BFC\u81F4\u95EE\u9898\uFF0C\u5C24\u5176\u662F\u5728\u8F93\u5165\u7279\u6B8A\u5B57\u7B26\u65F6\u3002 -Keyboardlayout.msg3 = \u5982\u679C\u60A8\u9047\u5230\u95EE\u9898\uFF0C\u8BF7\u786E\u4FDD\u60A8\u5728\u4E24\u53F0\u8BA1\u7B97\u673A\u4E0A\u4F7F\u7528\u76F8\u540C\u7684\u8BBE\u7F6E\u3002 \ No newline at end of file +keyboardlayout.msg1 = Assisted - \u7528\u6237\u7AEF\u5F53\u524D\u4F7F\u7528\u4E0D\u540C\u7684\u952E\u76D8\u5E03\u5C40\uFF1A%s +keyboardlayout.msg2 = \u8FD9\u53EF\u80FD\u4F1A\u5BFC\u81F4\u95EE\u9898\uFF0C\u5C24\u5176\u662F\u5728\u8F93\u5165\u7279\u6B8A\u5B57\u7B26\u65F6\u3002 +keyboardlayout.msg3 = \u5982\u679C\u60A8\u9047\u5230\u95EE\u9898\uFF0C\u8BF7\u786E\u4FDD\u60A8\u5728\u4E24\u53F0\u8BA1\u7B97\u673A\u4E0A\u4F7F\u7528\u76F8\u540C\u7684\u8BBE\u7F6E\u3002 + +outdated.msg1 = \u529F\u80FD\u51CF\u5C11\u3002 +outdated.msg2 = \u5C06\u60A8\u7684\u5BF9\u7B49\u4F53\u66F4\u65B0\u81F3\u6700\u65B0\u7248\u672C\u4EE5\u4EAB\u53D7\u6240\u6709\u529F\u80FD\u3002 \ No newline at end of file diff --git a/src/test/java/mpo/dayon/common/buffer/MemByteBufferTest.java b/src/test/java/mpo/dayon/common/buffer/MemByteBufferTest.java index 04546b76..ec86632d 100644 --- a/src/test/java/mpo/dayon/common/buffer/MemByteBufferTest.java +++ b/src/test/java/mpo/dayon/common/buffer/MemByteBufferTest.java @@ -67,9 +67,10 @@ void writeLenAsShort() { @Test void copyConstructor() throws IOException { - buffer.fill(33, BEAST); + int size = 42; + buffer.fill(size, BEAST); try(MemByteBuffer memBuffer = new MemByteBuffer(buffer.getInternal())) { - assertEquals(64, memBuffer.size()); + assertEquals(size, memBuffer.size()); assertEquals(buffer.getInternal().length, memBuffer.getInternal().length); } } diff --git a/src/test/java/mpo/dayon/common/network/NetworkSenderTest.java b/src/test/java/mpo/dayon/common/network/NetworkSenderTest.java index 30249c9d..3e3b92f3 100644 --- a/src/test/java/mpo/dayon/common/network/NetworkSenderTest.java +++ b/src/test/java/mpo/dayon/common/network/NetworkSenderTest.java @@ -1,5 +1,6 @@ package mpo.dayon.common.network; +import mpo.dayon.common.capture.Gray8Bits; import mpo.dayon.common.compressor.CompressorEngineConfiguration; import mpo.dayon.common.buffer.MemByteBuffer; import mpo.dayon.common.capture.Capture; @@ -104,11 +105,12 @@ void sendMouseLocation() throws IOException { } @Test - void sendCaptureConfiguration() throws IOException { + void sendCaptureConfigurationToLegacyPeerShouldNotIncludeCaptureColorValue() throws IOException { // given CaptureEngineConfiguration configuration = new CaptureEngineConfiguration(); + boolean monochromePeer = true; // when - sender.sendCaptureConfiguration(configuration); + sender.sendCaptureConfiguration(configuration, monochromePeer); // then verify(outMock, timeout(50)).writeByte(MAGIC_NUMBER); verify(outMock).write(NetworkMessageType.CAPTURE_CONFIGURATION.ordinal()); @@ -116,6 +118,21 @@ void sendCaptureConfiguration() throws IOException { verify(outMock).writeInt(configuration.getCaptureTick()); } + @Test + void sendCaptureConfigurationIncludeTheRightCaptureColorValue() throws IOException { + // given + CaptureEngineConfiguration configuration = new CaptureEngineConfiguration(333, Gray8Bits.X_16, true); + boolean monochromePeer = false; + // when + sender.sendCaptureConfiguration(configuration, monochromePeer); + // then + verify(outMock, timeout(50)).writeByte(MAGIC_NUMBER); + verify(outMock).write(NetworkMessageType.CAPTURE_CONFIGURATION.ordinal()); + verify(outMock).write(configuration.getCaptureQuantization().ordinal()); + verify(outMock).writeInt(configuration.getCaptureTick()); + verify(outMock).writeShort(1); + } + @Test void sendCompressorConfiguration() throws IOException { // given diff --git a/src/test/java/mpo/dayon/common/version/VersionTest.java b/src/test/java/mpo/dayon/common/version/VersionTest.java index 1ea3d76c..a093df7b 100644 --- a/src/test/java/mpo/dayon/common/version/VersionTest.java +++ b/src/test/java/mpo/dayon/common/version/VersionTest.java @@ -4,8 +4,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; -import static mpo.dayon.common.version.Version.isCompatibleVersion; -import static mpo.dayon.common.version.Version.isProd; +import static java.lang.Integer.parseInt; +import static mpo.dayon.common.version.Version.*; import static org.junit.jupiter.api.Assertions.*; class VersionTest { @@ -103,4 +103,28 @@ void isCompatibleVersionShouldReturnTrueForHardCodedCompatibleVersions(String th assertTrue(isCompatibleVersion(other.getMajor(), other.getMinor(), that)); } + @ParameterizedTest + @CsvSource({ "15,14", "15,13"}) + void isOutdatedVersionShouldReturnTrueForOutdatedVersions(String thatV, String otherV) { + // given when then + assertTrue(isOutdatedVersion(parseInt(thatV), parseInt(otherV))); + } + + @ParameterizedTest + @CsvSource({ "15,16", "15,15", "0,13", "15,0", "0,0"}) + void isOutdatedVersionShouldReturnFalseForNotOutdatedVersions(String thatV, String otherV) { + // given when then + assertFalse(isOutdatedVersion(parseInt(thatV), parseInt(otherV))); + } + + @ParameterizedTest + @CsvSource({ "15.0.0", "0.0.0" }) + void isColoredVersionShouldReturnTrueForHardCodedVersions(String thatV) { + // given + Version that = new Version(thatV); + + // when then + assertTrue(isColoredVersion(that.getMajor())); + } + }