1 /* 2 * Copyright (c) 2002-2016, the original author or authors. 3 * 4 * This software is distributable under the BSD license. See the terms of the 5 * BSD license in the documentation provided with this software. 6 * 7 * https://opensource.org/licenses/BSD-3-Clause 8 */ 9 package jdk.internal.org.jline.terminal.impl; 10 11 import jdk.internal.org.jline.terminal.MouseEvent; 12 import jdk.internal.org.jline.terminal.Terminal; 13 import jdk.internal.org.jline.utils.InfoCmp; 14 import jdk.internal.org.jline.utils.InputStreamReader; 15 16 import java.io.EOFException; 17 import java.io.IOError; 18 import java.io.IOException; 19 import java.nio.charset.StandardCharsets; 20 import java.util.EnumSet; 21 import java.util.function.IntSupplier; 22 23 public class MouseSupport { 24 hasMouseSupport(Terminal terminal)25 public static boolean hasMouseSupport(Terminal terminal) { 26 return terminal.getStringCapability(InfoCmp.Capability.key_mouse) != null; 27 } 28 trackMouse(Terminal terminal, Terminal.MouseTracking tracking)29 public static boolean trackMouse(Terminal terminal, Terminal.MouseTracking tracking) { 30 if (hasMouseSupport(terminal)) { 31 switch (tracking) { 32 case Off: 33 terminal.writer().write("\033[?1000l"); 34 break; 35 case Normal: 36 terminal.writer().write("\033[?1005h\033[?1000h"); 37 break; 38 case Button: 39 terminal.writer().write("\033[?1005h\033[?1002h"); 40 break; 41 case Any: 42 terminal.writer().write("\033[?1005h\033[?1003h"); 43 break; 44 } 45 terminal.flush(); 46 return true; 47 } else { 48 return false; 49 } 50 } 51 readMouse(Terminal terminal, MouseEvent last)52 public static MouseEvent readMouse(Terminal terminal, MouseEvent last) { 53 return readMouse(() -> readExt(terminal), last); 54 } 55 readMouse(IntSupplier reader, MouseEvent last)56 public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { 57 int cb = reader.getAsInt() - ' '; 58 int cx = reader.getAsInt() - ' ' - 1; 59 int cy = reader.getAsInt() - ' ' - 1; 60 MouseEvent.Type type; 61 MouseEvent.Button button; 62 EnumSet<MouseEvent.Modifier> modifiers = EnumSet.noneOf(MouseEvent.Modifier.class); 63 if ((cb & 4) == 4) { 64 modifiers.add(MouseEvent.Modifier.Shift); 65 } 66 if ((cb & 8) == 8) { 67 modifiers.add(MouseEvent.Modifier.Alt); 68 } 69 if ((cb & 16) == 16) { 70 modifiers.add(MouseEvent.Modifier.Control); 71 } 72 if ((cb & 64) == 64) { 73 type = MouseEvent.Type.Wheel; 74 button = (cb & 1) == 1 ? MouseEvent.Button.WheelDown : MouseEvent.Button.WheelUp; 75 } else { 76 int b = (cb & 3); 77 switch (b) { 78 case 0: 79 button = MouseEvent.Button.Button1; 80 if (last.getButton() == button 81 && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { 82 type = MouseEvent.Type.Dragged; 83 } else { 84 type = MouseEvent.Type.Pressed; 85 } 86 break; 87 case 1: 88 button = MouseEvent.Button.Button2; 89 if (last.getButton() == button 90 && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { 91 type = MouseEvent.Type.Dragged; 92 } else { 93 type = MouseEvent.Type.Pressed; 94 } 95 break; 96 case 2: 97 button = MouseEvent.Button.Button3; 98 if (last.getButton() == button 99 && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { 100 type = MouseEvent.Type.Dragged; 101 } else { 102 type = MouseEvent.Type.Pressed; 103 } 104 break; 105 default: 106 if (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged) { 107 button = last.getButton(); 108 type = MouseEvent.Type.Released; 109 } else { 110 button = MouseEvent.Button.NoButton; 111 type = MouseEvent.Type.Moved; 112 } 113 break; 114 } 115 } 116 return new MouseEvent(type, button, modifiers, cx, cy); 117 } 118 readExt(Terminal terminal)119 private static int readExt(Terminal terminal) { 120 try { 121 // The coordinates are encoded in UTF-8, so if that's not the input encoding, 122 // we need to get around 123 int c; 124 if (terminal.encoding() != StandardCharsets.UTF_8) { 125 c = new InputStreamReader(terminal.input(), StandardCharsets.UTF_8).read(); 126 } else { 127 c = terminal.reader().read(); 128 } 129 if (c < 0) { 130 throw new EOFException(); 131 } 132 return c; 133 } catch (IOException e) { 134 throw new IOError(e); 135 } 136 } 137 138 } 139