Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/awt_Robot.c
32287 views
1
/*
2
* Copyright (c) 1999, 2014, 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
/*
27
#ifdef HEADLESS
28
#error This file should not be included in headless library
29
#endif
30
*/
31
32
#include "jvm_md.h"
33
#include <dlfcn.h>
34
35
#include "awt_p.h"
36
#include "awt_GraphicsEnv.h"
37
#define XK_MISCELLANY
38
#include <X11/keysymdef.h>
39
#include <X11/Intrinsic.h>
40
#include <X11/Xutil.h>
41
#include <X11/Xmd.h>
42
#include <X11/extensions/xtestext1.h>
43
#include <X11/extensions/XTest.h>
44
#include <X11/extensions/XInput.h>
45
#include <X11/extensions/XI.h>
46
#include <jni.h>
47
#include <sizecalc.h>
48
#include "canvas.h"
49
#include "wsutils.h"
50
#include "list.h"
51
#include "multiVis.h"
52
53
#include "java_awt_event_InputEvent.h"
54
55
#if defined(__linux__) || defined(MACOSX)
56
#include <sys/socket.h>
57
#endif
58
59
static Bool (*compositeQueryExtension) (Display*, int*, int*);
60
static Status (*compositeQueryVersion) (Display*, int*, int*);
61
static Window (*compositeGetOverlayWindow) (Display *, Window);
62
63
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
64
65
static jint * masks;
66
static jint num_buttons;
67
68
static void *xCompositeHandle;
69
70
static const char* XCOMPOSITE = JNI_LIB_NAME("Xcomposite");
71
static const char* XCOMPOSITE_VERSIONED = VERSIONED_JNI_LIB_NAME("Xcomposite", "1");
72
73
#ifndef HEADLESS
74
static Bool checkXCompositeFunctions(void) {
75
return (compositeQueryExtension != NULL &&
76
compositeQueryVersion != NULL &&
77
compositeGetOverlayWindow != NULL);
78
}
79
80
static void initXCompositeFunctions(void) {
81
82
if (xCompositeHandle == NULL) {
83
xCompositeHandle = dlopen(XCOMPOSITE, RTLD_LAZY | RTLD_GLOBAL);
84
if (xCompositeHandle == NULL) {
85
xCompositeHandle = dlopen(XCOMPOSITE_VERSIONED, RTLD_LAZY | RTLD_GLOBAL);
86
}
87
}
88
//*(void **)(&asyncGetCallTraceFunction)
89
if (xCompositeHandle != NULL) {
90
*(void **)(&compositeQueryExtension) = dlsym(xCompositeHandle, "XCompositeQueryExtension");
91
*(void **)(&compositeQueryVersion) = dlsym(xCompositeHandle, "XCompositeQueryVersion");
92
*(void **)(&compositeGetOverlayWindow) = dlsym(xCompositeHandle, "XCompositeGetOverlayWindow");
93
}
94
95
if (xCompositeHandle && !checkXCompositeFunctions()) {
96
dlclose(xCompositeHandle);
97
}
98
}
99
100
static int32_t isXTestAvailable() {
101
int32_t major_opcode, first_event, first_error;
102
int32_t event_basep, error_basep, majorp, minorp;
103
int32_t isXTestAvailable;
104
105
/* check if XTest is available */
106
isXTestAvailable = XQueryExtension(awt_display, XTestExtensionName, &major_opcode, &first_event, &first_error);
107
if (isXTestAvailable) {
108
DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XTEST) returns major_opcode = %d, first_event = %d, first_error = %d",
109
major_opcode, first_event, first_error);
110
/* check if XTest version is OK */
111
XTestQueryExtension(awt_display, &event_basep, &error_basep, &majorp, &minorp);
112
DTRACE_PRINTLN4("RobotPeer: XTestQueryExtension returns event_basep = %d, error_basep = %d, majorp = %d, minorp = %d",
113
event_basep, error_basep, majorp, minorp);
114
if (majorp < 2 || (majorp == 2 && minorp < 2)) {
115
/* bad version*/
116
DTRACE_PRINTLN2("XRobotPeer: XTEST version is %d.%d \n", majorp, minorp);
117
if (majorp == 2 && minorp == 1) {
118
DTRACE_PRINTLN("XRobotPeer: XTEST is 2.1 - no grab is available\n");
119
} else {
120
isXTestAvailable = False;
121
}
122
} else {
123
/* allow XTest calls even if someone else has the grab; e.g. during
124
* a window resize operation. Works only with XTEST2.2*/
125
XTestGrabControl(awt_display, True);
126
}
127
} else {
128
DTRACE_PRINTLN("RobotPeer: XTEST extension is unavailable");
129
}
130
131
return isXTestAvailable;
132
}
133
134
static Bool hasXCompositeOverlayExtension(Display *display) {
135
136
int xoverlay = False;
137
int eventBase, errorBase;
138
if (checkXCompositeFunctions() &&
139
compositeQueryExtension(display, &eventBase, &errorBase))
140
{
141
int major = 0;
142
int minor = 0;
143
144
compositeQueryVersion(display, &major, &minor);
145
if (major > 0 || minor >= 3) {
146
xoverlay = True;
147
}
148
}
149
150
return xoverlay;
151
}
152
153
static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
154
155
char NET_WM_CM_Sn[25];
156
snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
157
158
Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
159
Window owner = XGetSelectionOwner(display, managerSelection);
160
161
return owner != 0;
162
}
163
164
static XImage *getWindowImage(Display * display, Window window,
165
int32_t x, int32_t y,
166
int32_t w, int32_t h) {
167
XImage *image;
168
int32_t transparentOverlays;
169
int32_t numVisuals;
170
XVisualInfo *pVisuals;
171
int32_t numOverlayVisuals;
172
OverlayInfo *pOverlayVisuals;
173
int32_t numImageVisuals;
174
XVisualInfo **pImageVisuals;
175
list_ptr vis_regions; /* list of regions to read from */
176
list_ptr vis_image_regions ;
177
int32_t allImage = 0 ;
178
int32_t format = ZPixmap;
179
180
/* prevent user from moving stuff around during the capture */
181
XGrabServer(display);
182
183
/*
184
* The following two functions live in multiVis.c-- they are pretty
185
* much verbatim taken from the source to the xwd utility from the
186
* X11 source. This version of the xwd source was somewhat better written
187
* for reuse compared to Sun's version.
188
*
189
* ftp.x.org/pub/R6.3/xc/programs/xwd
190
*
191
* We use these functions since they do the very tough job of capturing
192
* the screen correctly when it contains multiple visuals. They take into
193
* account the depth/colormap of each visual and produce a capture as a
194
* 24-bit RGB image so we don't have to fool around with colormaps etc.
195
*/
196
197
GetMultiVisualRegions(
198
display,
199
window,
200
x, y, w, h,
201
&transparentOverlays,
202
&numVisuals,
203
&pVisuals,
204
&numOverlayVisuals,
205
&pOverlayVisuals,
206
&numImageVisuals,
207
&pImageVisuals,
208
&vis_regions,
209
&vis_image_regions,
210
&allImage );
211
212
image = ReadAreaToImage(
213
display,
214
window,
215
x, y, w, h,
216
numVisuals,
217
pVisuals,
218
numOverlayVisuals,
219
pOverlayVisuals,
220
numImageVisuals,
221
pImageVisuals,
222
vis_regions,
223
vis_image_regions,
224
format,
225
allImage );
226
227
/* allow user to do stuff again */
228
XUngrabServer(display);
229
230
/* make sure the grab/ungrab is flushed */
231
XSync(display, False);
232
233
return image;
234
}
235
#endif
236
237
/*********************************************************************************************/
238
239
// this should be called from XRobotPeer constructor
240
JNIEXPORT void JNICALL
241
Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
242
{
243
#ifndef HEADLESS
244
int32_t xtestAvailable;
245
jint *tmp;
246
int i;
247
248
DTRACE_PRINTLN("RobotPeer: setup()");
249
250
num_buttons = numberOfButtons;
251
tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
252
CHECK_NULL(tmp);
253
254
masks = (jint *)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), num_buttons);
255
if (masks == (jint *) NULL) {
256
(*env)->ExceptionClear(env);
257
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
258
JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
259
return;
260
}
261
for (i = 0; i < num_buttons; i++) {
262
masks[i] = tmp[i];
263
}
264
(*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
265
266
AWT_LOCK();
267
xtestAvailable = isXTestAvailable();
268
DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
269
if (!xtestAvailable) {
270
JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
271
}
272
273
AWT_UNLOCK();
274
#endif
275
}
276
277
278
JNIEXPORT void JNICALL
279
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
280
jclass cls,
281
jobject xgc,
282
jint x,
283
jint y,
284
jint width,
285
jint height,
286
jintArray pixelArray) {
287
#ifndef HEADLESS
288
XImage *image;
289
jint *ary; /* Array of jints for sending pixel values back
290
* to parent process.
291
*/
292
Window rootWindow;
293
AwtGraphicsConfigDataPtr adata;
294
295
DTRACE_PRINTLN6("RobotPeer: getRGBPixelsImpl(%lx, %d, %d, %d, %d, %x)", xgc, x, y, width, height, pixelArray);
296
297
AWT_LOCK();
298
299
/* avoid a lot of work for empty rectangles */
300
if ((width * height) == 0) {
301
AWT_UNLOCK();
302
return;
303
}
304
DASSERT(width * height > 0); /* only allow positive size */
305
306
adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
307
DASSERT(adata != NULL);
308
309
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
310
if (hasXCompositeOverlayExtension(awt_display) &&
311
isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
312
{
313
rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
314
}
315
316
image = getWindowImage(awt_display, rootWindow, x, y, width, height);
317
318
/* Array to use to crunch around the pixel values */
319
if (!IS_SAFE_SIZE_MUL(width, height) ||
320
!(ary = (jint *) SAFE_SIZE_ARRAY_ALLOC(malloc, width * height, sizeof (jint))))
321
{
322
JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
323
XDestroyImage(image);
324
AWT_UNLOCK();
325
return;
326
}
327
/* convert to Java ARGB pixels */
328
for (y = 0; y < height; y++) {
329
for (x = 0; x < width; x++) {
330
jint pixel = (jint) XGetPixel(image, x, y); /* Note ignore upper
331
* 32-bits on 64-bit
332
* OSes.
333
*/
334
335
pixel |= 0xff000000; /* alpha - full opacity */
336
337
ary[(y * width) + x] = pixel;
338
}
339
}
340
(*env)->SetIntArrayRegion(env, pixelArray, 0, height * width, ary);
341
free(ary);
342
343
XDestroyImage(image);
344
345
AWT_UNLOCK();
346
#endif
347
}
348
349
JNIEXPORT void JNICALL
350
Java_sun_awt_X11_XRobotPeer_keyPressImpl (JNIEnv *env,
351
jclass cls,
352
jint keycode) {
353
#ifndef HEADLESS
354
AWT_LOCK();
355
356
DTRACE_PRINTLN1("RobotPeer: keyPressImpl(%i)", keycode);
357
358
XTestFakeKeyEvent(awt_display,
359
XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
360
True,
361
CurrentTime);
362
363
XSync(awt_display, False);
364
365
AWT_UNLOCK();
366
#endif
367
}
368
369
JNIEXPORT void JNICALL
370
Java_sun_awt_X11_XRobotPeer_keyReleaseImpl (JNIEnv *env,
371
jclass cls,
372
jint keycode) {
373
#ifndef HEADLESS
374
AWT_LOCK();
375
376
DTRACE_PRINTLN1("RobotPeer: keyReleaseImpl(%i)", keycode);
377
378
XTestFakeKeyEvent(awt_display,
379
XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
380
False,
381
CurrentTime);
382
383
XSync(awt_display, False);
384
385
AWT_UNLOCK();
386
#endif
387
}
388
389
JNIEXPORT void JNICALL
390
Java_sun_awt_X11_XRobotPeer_mouseMoveImpl (JNIEnv *env,
391
jclass cls,
392
jobject xgc,
393
jint root_x,
394
jint root_y) {
395
#ifndef HEADLESS
396
AwtGraphicsConfigDataPtr adata;
397
398
AWT_LOCK();
399
400
DTRACE_PRINTLN3("RobotPeer: mouseMoveImpl(%lx, %i, %i)", xgc, root_x, root_y);
401
402
adata = (AwtGraphicsConfigDataPtr) JNU_GetLongFieldAsPtr(env, xgc, x11GraphicsConfigIDs.aData);
403
DASSERT(adata != NULL);
404
405
XWarpPointer(awt_display, None, XRootWindow(awt_display, adata->awt_visInfo.screen), 0, 0, 0, 0, root_x, root_y);
406
XSync(awt_display, False);
407
408
AWT_UNLOCK();
409
#endif
410
}
411
412
/*
413
* Function joining the code of mousePressImpl and mouseReleaseImpl
414
*/
415
void mouseAction(JNIEnv *env,
416
jclass cls,
417
jint buttonMask,
418
Bool isMousePress)
419
{
420
#ifndef HEADLESS
421
AWT_LOCK();
422
423
DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask);
424
DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress);
425
426
if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
427
buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK )
428
{
429
XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime);
430
}
431
if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
432
buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) &&
433
(num_buttons >= 2)) {
434
XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime);
435
}
436
if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
437
buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) &&
438
(num_buttons >= 3)) {
439
XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime);
440
}
441
442
if (num_buttons > 3){
443
int32_t i;
444
int32_t button = 0;
445
for (i = 3; i<num_buttons; i++){
446
if ((buttonMask & masks[i])) {
447
// arrays starts from zero index => +1
448
// users wants to affect 4 or 5 button but they are assigned
449
// to the wheel so => we have to shift it to the right by 2.
450
button = i + 3;
451
XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime);
452
}
453
}
454
}
455
456
XSync(awt_display, False);
457
AWT_UNLOCK();
458
#endif
459
}
460
461
JNIEXPORT void JNICALL
462
Java_sun_awt_X11_XRobotPeer_mousePressImpl (JNIEnv *env,
463
jclass cls,
464
jint buttonMask) {
465
mouseAction(env, cls, buttonMask, True);
466
}
467
468
JNIEXPORT void JNICALL
469
Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl (JNIEnv *env,
470
jclass cls,
471
jint buttonMask) {
472
mouseAction(env, cls, buttonMask, False);
473
}
474
475
JNIEXPORT void JNICALL
476
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
477
jclass cls,
478
jint wheelAmt) {
479
/* Mouse wheel is implemented as a button press of button 4 and 5, so it */
480
/* probably could have been hacked into robot_mouseButtonEvent, but it's */
481
/* cleaner to give it its own command type, in case the implementation */
482
/* needs to be changed later. -bchristi, 6/20/01 */
483
#ifndef HEADLESS
484
int32_t repeat = abs(wheelAmt);
485
int32_t button = wheelAmt < 0 ? 4 : 5; /* wheel up: button 4 */
486
/* wheel down: button 5 */
487
int32_t loopIdx;
488
489
AWT_LOCK();
490
491
DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);
492
493
for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for */
494
/* wheelAmt == 0 */
495
XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
496
XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
497
}
498
XSync(awt_display, False);
499
500
AWT_UNLOCK();
501
#endif
502
}
503
504
JNIEXPORT void JNICALL
505
Java_sun_awt_X11_XRobotPeer_loadNativeLibraries (JNIEnv *env, jclass cls) {
506
#ifndef HEADLESS
507
initXCompositeFunctions();
508
#endif
509
}
510
511