1 /* 2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.glass.ui.monocle; 27 28 import java.nio.ByteBuffer; 29 import java.nio.IntBuffer; 30 import java.nio.ShortBuffer; 31 32 import javafx.scene.input.KeyCode; 33 import javafx.scene.input.MouseButton; 34 import javafx.scene.paint.Color; 35 36 import com.sun.glass.events.MouseEvent; 37 import com.sun.glass.ui.Application; 38 import com.sun.glass.ui.GlassRobot; 39 40 class MonocleRobot extends GlassRobot { 41 @Override 42 public void create() { 43 // no-op 44 } 45 46 @Override 47 public void destroy() { 48 // no-op 49 } 50 51 @Override 52 public void keyPress(KeyCode code) { 53 Application.checkEventThread(); 54 KeyState state = new KeyState(); 55 KeyInput.getInstance().getState(state); 56 state.pressKey(code.getCode()); 57 KeyInput.getInstance().setState(state); 58 } 59 60 @Override 61 public void keyRelease(KeyCode code) { 62 Application.checkEventThread(); 63 KeyState state = new KeyState(); 64 KeyInput.getInstance().getState(state); 65 state.releaseKey(code.getCode()); 66 KeyInput.getInstance().setState(state); 67 } 68 69 @Override 70 public void mouseMove(double x, double y) { 71 Application.checkEventThread(); 72 MouseState state = new MouseState(); 73 MouseInput.getInstance().getState(state); 74 state.setX((int) x); 75 state.setY((int) y); 76 MouseInput.getInstance().setState(state, false); 77 } 78 79 private static MouseState convertToMouseState(boolean press, MouseState state, MouseButton... buttons) { 80 for (MouseButton button : buttons) { 81 switch (button) { 82 case PRIMARY: 83 if (press) { 84 state.pressButton(MouseEvent.BUTTON_LEFT); 85 } else { 86 state.releaseButton(MouseEvent.BUTTON_LEFT); 87 } 88 break; 89 case SECONDARY: 90 if (press) { 91 state.pressButton(MouseEvent.BUTTON_RIGHT); 92 } else { 93 state.releaseButton(MouseEvent.BUTTON_RIGHT); 94 } 95 break; 96 case MIDDLE: 97 if (press) { 98 state.pressButton(MouseEvent.BUTTON_OTHER); 99 } else { 100 state.releaseButton(MouseEvent.BUTTON_OTHER); 101 } 102 break; 103 default: throw new IllegalArgumentException("MouseButton: " + button + 104 " not supported by Monocle Robot"); 105 } 106 } 107 return state; 108 } 109 110 @Override 111 public void mousePress(MouseButton... buttons) { 112 Application.checkEventThread(); 113 MouseState state = new MouseState(); 114 MouseInput.getInstance().getState(state); 115 MouseInput.getInstance().setState(convertToMouseState(true, state, buttons), false); 116 } 117 118 @Override 119 public void mouseRelease(MouseButton... buttons) { 120 Application.checkEventThread(); 121 MouseState state = new MouseState(); 122 MouseInput.getInstance().getState(state); 123 MouseInput.getInstance().setState(convertToMouseState(false, state, buttons), false); 124 } 125 126 @Override 127 public void mouseWheel(int wheelAmt) { 128 Application.checkEventThread(); 129 MouseState state = new MouseState(); 130 MouseInput mouse = MouseInput.getInstance(); 131 mouse.getState(state); 132 int direction = wheelAmt < 0 133 ? MouseState.WHEEL_DOWN 134 : MouseState.WHEEL_UP; 135 for (int i = 0; i < Math.abs(wheelAmt); i++) { 136 state.setWheel(direction); 137 mouse.setState(state, false); 138 state.setWheel(MouseState.WHEEL_NONE); 139 mouse.setState(state, false); 140 } 141 } 142 143 @Override 144 public double getMouseX() { 145 Application.checkEventThread(); 146 MouseState state = new MouseState(); 147 MouseInput.getInstance().getState(state); 148 return state.getX(); 149 } 150 151 @Override 152 public double getMouseY() { 153 Application.checkEventThread(); 154 MouseState state = new MouseState(); 155 MouseInput.getInstance().getState(state); 156 return state.getY(); 157 } 158 159 @Override 160 public Color getPixelColor(double x, double y) { 161 Application.checkEventThread(); 162 NativeScreen screen = NativePlatformFactory.getNativePlatform().getScreen(); 163 final int byteDepth = screen.getDepth() >>> 3; 164 final int bwidth = screen.getWidth(); 165 final int bheight = screen.getHeight(); 166 167 if (x < 0 || x > bwidth || y < 0 || y > bheight) { 168 return GlassRobot.convertFromIntArgb(0); 169 } 170 171 synchronized (NativeScreen.framebufferSwapLock) { 172 173 ByteBuffer buffer = screen.getScreenCapture(); 174 175 if (byteDepth == 2) { 176 ShortBuffer shortbuf = buffer.asShortBuffer(); 177 178 int v = shortbuf.get((int) (y * bwidth) + (int) x); 179 int red = (v & 0xF800) >> 11 << 3; 180 int green = (v & 0x7E0) >> 5 << 2; 181 int blue = (v & 0x1F) << 3; 182 183 int p = (0xff000000 184 | (red << 16) 185 | (green << 8) 186 | blue); 187 return GlassRobot.convertFromIntArgb(p); 188 } else if (byteDepth >= 4) { 189 IntBuffer intbuf = buffer.asIntBuffer(); 190 return GlassRobot.convertFromIntArgb(intbuf.get((int) (y * bwidth) + (int) x)); 191 } else { 192 throw new RuntimeException("Unknown bit depth: " + byteDepth); 193 } 194 } 195 } 196 197 @Override 198 public void getScreenCapture(int x, int y, int width, int height, int[] data, boolean scaleToFit) { 199 Application.checkEventThread(); 200 NativeScreen screen = NativePlatformFactory.getNativePlatform().getScreen(); 201 final int scrWidth = screen.getWidth(); 202 final int scrHeight = screen.getHeight(); 203 204 synchronized (NativeScreen.framebufferSwapLock) { 205 IntBuffer buffer = screen.getScreenCapture().asIntBuffer(); 206 207 if (x == 0 && y == 0 && width == scrWidth && height == scrHeight) { 208 // Easy case, the entire screen is being captured. 209 System.arraycopy(buffer.array(), 0, data, 0, buffer.array().length); 210 return; 211 } 212 213 int rowStop = Math.min(y + height, scrHeight); 214 int colStop = Math.min(x + width, scrWidth); 215 for (int row = y; row < rowStop; row++) { 216 for (int col = x; col < colStop; col++) { 217 data[row * scrWidth + col] = buffer.get(row * scrWidth + col); 218 } 219 } 220 } 221 } 222 }