Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java
41159 views
1
/*
2
* Copyright (c) 2002, 2020, 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 sun.awt.X11;
27
28
import java.awt.AWTEvent;
29
import java.awt.AWTException;
30
import java.awt.BufferCapabilities;
31
import java.awt.Color;
32
import java.awt.Component;
33
import java.awt.Container;
34
import java.awt.Cursor;
35
import java.awt.Dimension;
36
import java.awt.Font;
37
import java.awt.FontMetrics;
38
import java.awt.Graphics;
39
import java.awt.GraphicsConfiguration;
40
import java.awt.Image;
41
import java.awt.Insets;
42
import java.awt.Rectangle;
43
import java.awt.SystemColor;
44
import java.awt.Toolkit;
45
import java.awt.Window;
46
import java.awt.dnd.DropTarget;
47
import java.awt.dnd.peer.DropTargetPeer;
48
import java.awt.event.FocusEvent;
49
import java.awt.event.InputEvent;
50
import java.awt.event.InputMethodEvent;
51
import java.awt.event.KeyEvent;
52
import java.awt.event.MouseEvent;
53
import java.awt.event.MouseWheelEvent;
54
import java.awt.event.PaintEvent;
55
import java.awt.event.WindowEvent;
56
import java.awt.image.VolatileImage;
57
import java.awt.peer.ComponentPeer;
58
import java.awt.peer.ContainerPeer;
59
import java.util.Collection;
60
import java.util.Objects;
61
import java.util.Set;
62
63
import sun.awt.AWTAccessor;
64
import sun.awt.AWTAccessor.ComponentAccessor;
65
import sun.awt.SunToolkit;
66
import sun.awt.X11GraphicsConfig;
67
import sun.awt.event.IgnorePaintEvent;
68
import sun.awt.image.SunVolatileImage;
69
import sun.java2d.BackBufferCapsProvider;
70
import sun.java2d.pipe.Region;
71
import sun.util.logging.PlatformLogger;
72
73
74
public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
75
BackBufferCapsProvider
76
{
77
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer");
78
private static final PlatformLogger buffersLog = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
79
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XComponentPeer");
80
private static final PlatformLogger fontLog = PlatformLogger.getLogger("sun.awt.X11.font.XComponentPeer");
81
private static final PlatformLogger enableLog = PlatformLogger.getLogger("sun.awt.X11.enable.XComponentPeer");
82
private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.X11.shape.XComponentPeer");
83
84
boolean paintPending = false;
85
boolean isLayouting = false;
86
private boolean enabled;
87
88
// Actually used only by XDecoratedPeer
89
protected int boundsOperation;
90
91
Color foreground;
92
Color background;
93
94
// Colors calculated as on Motif using MotifColorUtilties.
95
// If you use these, call updateMotifColors() in the peer's Constructor and
96
// setBackground(). Examples are XCheckboxPeer and XButtonPeer.
97
Color darkShadow;
98
Color lightShadow;
99
Color selectColor;
100
101
Font font;
102
private long backBuffer = 0;
103
private VolatileImage xBackBuffer = null;
104
105
static Color[] systemColors;
106
107
XComponentPeer() {
108
}
109
110
XComponentPeer (XCreateWindowParams params) {
111
super(params);
112
}
113
114
XComponentPeer(Component target, long parentWindow, Rectangle bounds) {
115
super(target, parentWindow, bounds);
116
}
117
118
/**
119
* Standard peer constructor, with corresponding Component
120
*/
121
XComponentPeer(Component target) {
122
super(target);
123
}
124
125
126
void preInit(XCreateWindowParams params) {
127
super.preInit(params);
128
boundsOperation = DEFAULT_OPERATION;
129
}
130
void postInit(XCreateWindowParams params) {
131
super.postInit(params);
132
133
pSetCursor(target.getCursor());
134
135
foreground = target.getForeground();
136
background = target.getBackground();
137
font = target.getFont();
138
139
if (isInitialReshape()) {
140
Rectangle r = target.getBounds();
141
reshape(r.x, r.y, r.width, r.height);
142
}
143
144
setEnabled(target.isEnabled());
145
146
if (target.isVisible()) {
147
setVisible(true);
148
}
149
}
150
151
protected boolean isInitialReshape() {
152
return true;
153
}
154
155
public void reparent(ContainerPeer newNativeParent) {
156
XComponentPeer newPeer = (XComponentPeer)newNativeParent;
157
XToolkit.awtLock();
158
try {
159
XlibWrapper.XReparentWindow(XToolkit.getDisplay(),
160
getWindow(), newPeer.getContentWindow(),
161
scaleUp(x), scaleUp(y));
162
parentWindow = newPeer;
163
} finally {
164
XToolkit.awtUnlock();
165
}
166
}
167
public boolean isReparentSupported() {
168
return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false");
169
}
170
171
@SuppressWarnings("deprecation")
172
public boolean isObscured() {
173
Container container = (target instanceof Container) ?
174
(Container)target : target.getParent();
175
176
if (container == null) {
177
return true;
178
}
179
180
Container parent;
181
while ((parent = container.getParent()) != null) {
182
container = parent;
183
}
184
185
if (container instanceof Window) {
186
XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
187
.getPeer(container);
188
if (wpeer != null) {
189
return (wpeer.winAttr.visibilityState !=
190
XWindowAttributesData.AWT_UNOBSCURED);
191
}
192
}
193
return true;
194
}
195
196
public boolean canDetermineObscurity() {
197
return true;
198
}
199
200
/*************************************************
201
* FOCUS STUFF
202
*************************************************/
203
204
/**
205
* Keeps the track of focused state of the _NATIVE_ window
206
*/
207
boolean bHasFocus = false;
208
209
/**
210
* Descendants should use this method to determine whether or not native window
211
* has focus.
212
*/
213
public final boolean hasFocus() {
214
return bHasFocus;
215
}
216
217
/**
218
* Called when component receives focus
219
*/
220
public void focusGained(FocusEvent e) {
221
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
222
focusLog.fine("{0}", e);
223
}
224
bHasFocus = true;
225
}
226
227
/**
228
* Called when component loses focus
229
*/
230
public void focusLost(FocusEvent e) {
231
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
232
focusLog.fine("{0}", e);
233
}
234
bHasFocus = false;
235
}
236
237
public boolean isFocusable() {
238
/* should be implemented by other sub-classes */
239
return false;
240
}
241
242
static final AWTEvent wrapInSequenced(AWTEvent event) {
243
return AWTAccessor.getSequencedEventAccessor().create(event);
244
}
245
246
// TODO: consider moving it to KeyboardFocusManagerPeerImpl
247
@SuppressWarnings("deprecation")
248
public final boolean requestFocus(Component lightweightChild, boolean temporary,
249
boolean focusedWindowChangeAllowed, long time,
250
FocusEvent.Cause cause)
251
{
252
if (XKeyboardFocusManagerPeer.
253
processSynchronousLightweightTransfer(target, lightweightChild, temporary,
254
focusedWindowChangeAllowed, time))
255
{
256
return true;
257
}
258
259
int result = XKeyboardFocusManagerPeer.
260
shouldNativelyFocusHeavyweight(target, lightweightChild,
261
temporary, focusedWindowChangeAllowed,
262
time, cause);
263
264
switch (result) {
265
case XKeyboardFocusManagerPeer.SNFH_FAILURE:
266
return false;
267
case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
268
// Currently we just generate focus events like we deal with lightweight instead of calling
269
// XSetInputFocus on native window
270
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
271
focusLog.finer("Proceeding with request to " +
272
lightweightChild + " in " + target);
273
}
274
/**
275
* The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
276
* checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
277
* been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
278
* in requests list - and it breaks our requests sequence as first record on WGF should be the last
279
* focus owner which had focus before WLF. So, we should not add request record for such requests
280
* but store this component in mostRecent - and return true as before for compatibility.
281
*/
282
Window parentWindow = SunToolkit.getContainingWindow(target);
283
if (parentWindow == null) {
284
return rejectFocusRequestHelper("WARNING: Parent window is null");
285
}
286
XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
287
.getPeer(parentWindow);
288
if (wpeer == null) {
289
return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
290
}
291
/*
292
* Passing null 'actualFocusedWindow' as we don't want to restore focus on it
293
* when a component inside a Frame is requesting focus.
294
* See 6314575 for details.
295
*/
296
boolean res = wpeer.requestWindowFocus(null);
297
298
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
299
focusLog.finer("Requested window focus: " + res);
300
}
301
// If parent window can be made focused and has been made focused(synchronously)
302
// then we can proceed with children, otherwise we retreat.
303
if (!(res && parentWindow.isFocused())) {
304
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
305
}
306
return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
307
target,
308
temporary,
309
focusedWindowChangeAllowed,
310
time, cause);
311
// Motif compatibility code
312
case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
313
// Either lightweight or excessive request - all events are generated.
314
return true;
315
}
316
return false;
317
}
318
319
private boolean rejectFocusRequestHelper(String logMsg) {
320
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
321
focusLog.finer(logMsg);
322
}
323
XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
324
return false;
325
}
326
327
void handleJavaFocusEvent(AWTEvent e) {
328
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
329
focusLog.finer(e.toString());
330
}
331
if (e.getID() == FocusEvent.FOCUS_GAINED) {
332
focusGained((FocusEvent)e);
333
} else {
334
focusLost((FocusEvent)e);
335
}
336
}
337
338
void handleJavaWindowFocusEvent(AWTEvent e) {
339
}
340
341
/*************************************************
342
* END OF FOCUS STUFF
343
*************************************************/
344
345
346
347
public void setVisible(boolean b) {
348
xSetVisible(b);
349
}
350
351
public void hide() {
352
setVisible(false);
353
}
354
355
/**
356
* @see java.awt.peer.ComponentPeer
357
*/
358
public void setEnabled(final boolean value) {
359
if (enableLog.isLoggable(PlatformLogger.Level.FINE)) {
360
enableLog.fine("{0}ing {1}", (value ? "Enabl" : "Disabl"), this);
361
}
362
boolean status = value;
363
// If any of our heavyweight ancestors are disable, we should be too
364
// See 6176875 for more information
365
final Container cp = SunToolkit.getNativeContainer(target);
366
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
367
if (cp != null) {
368
status &= acc.<XComponentPeer>getPeer(cp).isEnabled();
369
}
370
synchronized (getStateLock()) {
371
if (enabled == status) {
372
return;
373
}
374
enabled = status;
375
}
376
377
if (target instanceof Container) {
378
final Component[] list = ((Container) target).getComponents();
379
for (final Component child : list) {
380
final ComponentPeer p = acc.getPeer(child);
381
if (p != null) {
382
p.setEnabled(status && child.isEnabled());
383
}
384
}
385
}
386
repaint();
387
}
388
389
//
390
// public so aw/Window can call it
391
//
392
public final boolean isEnabled() {
393
synchronized (getStateLock()) {
394
return enabled;
395
}
396
}
397
398
@Override
399
public void paint(final Graphics g) {
400
super.paint(g);
401
// allow target to change the picture
402
target.paint(g);
403
}
404
405
public Graphics getGraphics() {
406
return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont());
407
}
408
public void print(Graphics g) {
409
// clear rect here to emulate X clears rect before Expose
410
g.setColor(target.getBackground());
411
g.fillRect(0, 0, target.getWidth(), target.getHeight());
412
g.setColor(target.getForeground());
413
// paint peer
414
paintPeer(g);
415
// allow target to change the picture
416
target.print(g);
417
}
418
419
public void setBounds(int x, int y, int width, int height, int op) {
420
this.x = x;
421
this.y = y;
422
this.width = width;
423
this.height = height;
424
xSetBounds(x,y,width,height);
425
validateSurface();
426
layout();
427
}
428
429
public void reshape(int x, int y, int width, int height) {
430
setBounds(x, y, width, height, SET_BOUNDS);
431
}
432
433
public void coalescePaintEvent(PaintEvent e) {
434
Rectangle r = e.getUpdateRect();
435
if (!(e instanceof IgnorePaintEvent)) {
436
paintArea.add(r, e.getID());
437
}
438
if (true) {
439
switch(e.getID()) {
440
case PaintEvent.UPDATE:
441
if (log.isLoggable(PlatformLogger.Level.FINER)) {
442
log.finer("XCP coalescePaintEvent : UPDATE : add : x = " +
443
r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
444
}
445
return;
446
case PaintEvent.PAINT:
447
if (log.isLoggable(PlatformLogger.Level.FINER)) {
448
log.finer("XCP coalescePaintEvent : PAINT : add : x = " +
449
r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
450
}
451
return;
452
}
453
}
454
}
455
456
XWindowPeer getParentTopLevel() {
457
ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
458
Container parent = (target instanceof Container) ? ((Container)target) : (compAccessor.getParent(target));
459
// Search for parent window
460
while (parent != null && !(parent instanceof Window)) {
461
parent = compAccessor.getParent(parent);
462
}
463
if (parent != null) {
464
return (XWindowPeer)compAccessor.getPeer(parent);
465
} else {
466
return null;
467
}
468
}
469
470
/* This method is intended to be over-ridden by peers to perform user interaction */
471
void handleJavaMouseEvent(MouseEvent e) {
472
switch (e.getID()) {
473
case MouseEvent.MOUSE_PRESSED:
474
if (target == e.getSource() &&
475
!target.isFocusOwner() &&
476
XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
477
{
478
XWindowPeer parentXWindow = getParentTopLevel();
479
Window parentWindow = ((Window)parentXWindow.getTarget());
480
// Simple windows are non-focusable in X terms but focusable in Java terms.
481
// As X-non-focusable they don't receive any focus events - we should generate them
482
// by ourselfves.
483
// if (parentXWindow.isFocusableWindow() /*&& parentXWindow.isSimpleWindow()*/ &&
484
// !(getCurrentNativeFocusedWindow() == parentWindow))
485
// {
486
// setCurrentNativeFocusedWindow(parentWindow);
487
// WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
488
// parentWindow.dispatchEvent(wfg);
489
// }
490
XKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
491
}
492
break;
493
}
494
}
495
496
/* This method is intended to be over-ridden by peers to perform user interaction */
497
void handleJavaKeyEvent(KeyEvent e) {
498
}
499
500
/* This method is intended to be over-ridden by peers to perform user interaction */
501
void handleJavaMouseWheelEvent(MouseWheelEvent e) {
502
}
503
504
505
/* This method is intended to be over-ridden by peers to perform user interaction */
506
void handleJavaInputMethodEvent(InputMethodEvent e) {
507
}
508
509
void handleF10JavaKeyEvent(KeyEvent e) {
510
if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_F10) {
511
XWindowPeer winPeer = this.getToplevelXWindow();
512
if (winPeer instanceof XFramePeer) {
513
XMenuBarPeer mPeer = ((XFramePeer)winPeer).getMenubarPeer();
514
if (mPeer != null) {
515
mPeer.handleF10KeyPress(e);
516
}
517
}
518
}
519
}
520
521
@SuppressWarnings("fallthrough")
522
public void handleEvent(java.awt.AWTEvent e) {
523
if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled()) {
524
if (e instanceof MouseEvent) {
525
if (e instanceof MouseWheelEvent) {
526
handleJavaMouseWheelEvent((MouseWheelEvent) e);
527
}
528
else
529
handleJavaMouseEvent((MouseEvent) e);
530
}
531
else if (e instanceof KeyEvent) {
532
handleF10JavaKeyEvent((KeyEvent)e);
533
handleJavaKeyEvent((KeyEvent)e);
534
}
535
}
536
else if (e instanceof KeyEvent && !((InputEvent)e).isConsumed()) {
537
// even if target is disabled.
538
handleF10JavaKeyEvent((KeyEvent)e);
539
}
540
else if (e instanceof InputMethodEvent) {
541
handleJavaInputMethodEvent((InputMethodEvent) e);
542
}
543
544
int id = e.getID();
545
546
switch(id) {
547
case PaintEvent.PAINT:
548
// Got native painting
549
paintPending = false;
550
// Fallthrough to next statement
551
case PaintEvent.UPDATE:
552
// Skip all painting while layouting and all UPDATEs
553
// while waiting for native paint
554
if (!isLayouting && !paintPending) {
555
paintArea.paint(target,false);
556
}
557
return;
558
case FocusEvent.FOCUS_LOST:
559
case FocusEvent.FOCUS_GAINED:
560
handleJavaFocusEvent(e);
561
break;
562
case WindowEvent.WINDOW_LOST_FOCUS:
563
case WindowEvent.WINDOW_GAINED_FOCUS:
564
handleJavaWindowFocusEvent(e);
565
break;
566
default:
567
break;
568
}
569
570
}
571
572
public Dimension getMinimumSize() {
573
return target.getSize();
574
}
575
576
public Dimension getPreferredSize() {
577
return getMinimumSize();
578
}
579
580
public void layout() {}
581
582
void updateMotifColors(Color bg) {
583
int red = bg.getRed();
584
int green = bg.getGreen();
585
int blue = bg.getBlue();
586
587
darkShadow = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue));
588
lightShadow = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue));
589
selectColor= new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue));
590
}
591
592
/*
593
* Draw a 3D rectangle using the Motif colors.
594
* "Normal" rectangles have shadows on the bottom.
595
* "Depressed" rectangles (such as pressed buttons) have shadows on the top,
596
* in which case true should be passed for topShadow.
597
*/
598
public void drawMotif3DRect(Graphics g,
599
int x, int y, int width, int height,
600
boolean topShadow) {
601
g.setColor(topShadow ? darkShadow : lightShadow);
602
g.drawLine(x, y, x+width, y); // top
603
g.drawLine(x, y+height, x, y); // left
604
605
g.setColor(topShadow ? lightShadow : darkShadow );
606
g.drawLine(x+1, y+height, x+width, y+height); // bottom
607
g.drawLine(x+width, y+height, x+width, y+1); // right
608
}
609
610
@Override
611
public void setBackground(Color c) {
612
if (log.isLoggable(PlatformLogger.Level.FINE)) {
613
log.fine("Set background to " + c);
614
}
615
synchronized (getStateLock()) {
616
if (Objects.equals(background, c)) {
617
return;
618
}
619
background = c;
620
}
621
super.setBackground(c);
622
repaint();
623
}
624
625
@Override
626
public void setForeground(Color c) {
627
if (log.isLoggable(PlatformLogger.Level.FINE)) {
628
log.fine("Set foreground to " + c);
629
}
630
synchronized (getStateLock()) {
631
if (Objects.equals(foreground, c)) {
632
return;
633
}
634
foreground = c;
635
}
636
repaint();
637
}
638
639
/**
640
* Gets the font metrics for the specified font.
641
* @param font the font for which font metrics is to be
642
* obtained
643
* @return the font metrics for {@code font}
644
* @see #getFont
645
* @see java.awt.peer.ComponentPeer#getFontMetrics(Font)
646
* @see Toolkit#getFontMetrics(Font)
647
* @since 1.0
648
*/
649
public FontMetrics getFontMetrics(Font font) {
650
if (fontLog.isLoggable(PlatformLogger.Level.FINE)) {
651
fontLog.fine("Getting font metrics for " + font);
652
}
653
return sun.font.FontDesignMetrics.getMetrics(font);
654
}
655
656
@Override
657
public void setFont(Font f) {
658
if (f == null) {
659
f = XWindow.getDefaultFont();
660
}
661
synchronized (getStateLock()) {
662
if (f.equals(font)) {
663
return;
664
}
665
font = f;
666
}
667
// as it stands currently we don't need to do layout since
668
// layout is done in the Component upon setFont.
669
//layout();
670
repaint();
671
}
672
673
public Font getFont() {
674
return font;
675
}
676
677
public void updateCursorImmediately() {
678
XGlobalCursorManager.getCursorManager().updateCursorImmediately();
679
}
680
681
public final void pSetCursor(Cursor cursor) {
682
this.pSetCursor(cursor, true);
683
}
684
685
/*
686
* The method changes the cursor.
687
* @param cursor a new cursor to change to.
688
* @param ignoreSubComponents if {@code true} is passed then
689
* the new cursor will be installed on window.
690
* if {@code false} is passed then
691
* subsequent components will try to handle
692
* this request and install their cursor.
693
*/
694
//ignoreSubComponents not used here
695
public void pSetCursor(Cursor cursor, boolean ignoreSubComponents) {
696
XToolkit.awtLock();
697
try {
698
long xcursor = XGlobalCursorManager.getCursor(cursor);
699
700
XSetWindowAttributes xwa = new XSetWindowAttributes();
701
xwa.set_cursor(xcursor);
702
703
long valuemask = XConstants.CWCursor;
704
705
XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData);
706
XlibWrapper.XFlush(XToolkit.getDisplay());
707
xwa.dispose();
708
} finally {
709
XToolkit.awtUnlock();
710
}
711
}
712
713
public Image createImage(int width, int height) {
714
return graphicsConfig.createAcceleratedImage(target, width, height);
715
}
716
717
public VolatileImage createVolatileImage(int width, int height) {
718
return new SunVolatileImage(target, width, height);
719
}
720
721
public Insets getInsets() {
722
return new Insets(0, 0, 0, 0);
723
}
724
725
public void beginValidate() {
726
}
727
728
public void endValidate() {
729
}
730
731
// Returns true if we are inside begin/endLayout and
732
// are waiting for native painting
733
public boolean isPaintPending() {
734
return paintPending && isLayouting;
735
}
736
737
public boolean handlesWheelScrolling() {
738
return false;
739
}
740
741
public void beginLayout() {
742
// Skip all painting till endLayout
743
isLayouting = true;
744
745
}
746
747
public void endLayout() {
748
if (!paintPending && !paintArea.isEmpty()
749
&& !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target))
750
{
751
// if not waiting for native painting repaint damaged area
752
postEvent(new PaintEvent(target, PaintEvent.PAINT,
753
new Rectangle()));
754
}
755
isLayouting = false;
756
}
757
758
public Color getWinBackground() {
759
return getPeerBackground();
760
}
761
762
static int[] getRGBvals(Color c) {
763
764
int[] rgbvals = new int[3];
765
766
rgbvals[0] = c.getRed();
767
rgbvals[1] = c.getGreen();
768
rgbvals[2] = c.getBlue();
769
770
return rgbvals;
771
}
772
773
static final int BACKGROUND_COLOR = 0;
774
static final int HIGHLIGHT_COLOR = 1;
775
static final int SHADOW_COLOR = 2;
776
static final int FOREGROUND_COLOR = 3;
777
778
public Color[] getGUIcolors() {
779
Color[] c = new Color[4];
780
float backb, highb, shadowb, hue, saturation;
781
c[BACKGROUND_COLOR] = getWinBackground();
782
if (c[BACKGROUND_COLOR] == null) {
783
c[BACKGROUND_COLOR] = super.getWinBackground();
784
}
785
if (c[BACKGROUND_COLOR] == null) {
786
c[BACKGROUND_COLOR] = Color.lightGray;
787
}
788
789
int[] rgb = getRGBvals(c[BACKGROUND_COLOR]);
790
791
float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null);
792
793
hue = hsb[0];
794
saturation = hsb[1];
795
backb = hsb[2];
796
797
798
/* Calculate Highlight Brightness */
799
800
highb = backb + 0.2f;
801
shadowb = backb - 0.4f;
802
if ((highb > 1.0) ) {
803
if ((1.0 - backb) < 0.05) {
804
highb = shadowb + 0.25f;
805
} else {
806
highb = 1.0f;
807
}
808
} else {
809
if (shadowb < 0.0) {
810
if ((backb - 0.0) < 0.25) {
811
highb = backb + 0.75f;
812
shadowb = highb - 0.2f;
813
} else {
814
shadowb = 0.0f;
815
}
816
}
817
}
818
c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb);
819
c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb);
820
821
822
/*
823
c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker();
824
int r2 = c[SHADOW_COLOR].getRed();
825
int g2 = c[SHADOW_COLOR].getGreen();
826
int b2 = c[SHADOW_COLOR].getBlue();
827
*/
828
829
c[FOREGROUND_COLOR] = getPeerForeground();
830
if (c[FOREGROUND_COLOR] == null) {
831
c[FOREGROUND_COLOR] = Color.black;
832
}
833
/*
834
if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR]))
835
&& (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) {
836
c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75,
837
c[BACKGROUND_COLOR].getGreen() + 75,
838
c[BACKGROUND_COLOR].getBlue() + 75);
839
c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter();
840
} else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) {
841
c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR];
842
c[SHADOW_COLOR] = c[SHADOW_COLOR].darker();
843
}
844
*/
845
if (! isEnabled()) {
846
c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker();
847
// Reduce the contrast
848
// Calculate the NTSC gray (NB: REC709 L* might be better!)
849
// for foreground and background; then multiply the foreground
850
// by the average lightness
851
852
853
Color tc = c[BACKGROUND_COLOR];
854
int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
855
856
tc = c[FOREGROUND_COLOR];
857
int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
858
859
float ave = (float) ((fg + bg) / 51000.0);
860
// 255 * 100 * 2
861
862
Color newForeground = new Color((int) (tc.getRed() * ave),
863
(int) (tc.getGreen() * ave),
864
(int) (tc.getBlue() * ave));
865
866
if (newForeground.equals(c[FOREGROUND_COLOR])) {
867
// This probably means the foreground color is black or white
868
newForeground = new Color(ave, ave, ave);
869
}
870
c[FOREGROUND_COLOR] = newForeground;
871
872
}
873
874
875
return c;
876
}
877
878
/**
879
* Returns an array of Colors similar to getGUIcolors(), but using the
880
* System colors. This is useful if pieces of a Component (such as
881
* the integrated scrollbars of a List) should retain the System color
882
* instead of the background color set by Component.setBackground().
883
*/
884
static Color[] getSystemColors() {
885
if (systemColors == null) {
886
systemColors = new Color[4];
887
systemColors[BACKGROUND_COLOR] = SystemColor.window;
888
systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight;
889
systemColors[SHADOW_COLOR] = SystemColor.controlShadow;
890
systemColors[FOREGROUND_COLOR] = SystemColor.windowText;
891
}
892
return systemColors;
893
}
894
895
/**
896
* Draw a 3D oval.
897
*/
898
public void draw3DOval(Graphics g, Color[] colors,
899
int x, int y, int w, int h, boolean raised)
900
{
901
Color c = g.getColor();
902
g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
903
g.drawArc(x, y, w, h, 45, 180);
904
g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
905
g.drawArc(x, y, w, h, 225, 180);
906
g.setColor(c);
907
}
908
909
public void draw3DRect(Graphics g, Color[] colors,
910
int x, int y, int width, int height, boolean raised)
911
{
912
Color c = g.getColor();
913
g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
914
g.drawLine(x, y, x, y + height);
915
g.drawLine(x + 1, y, x + width - 1, y);
916
g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
917
g.drawLine(x + 1, y + height, x + width, y + height);
918
g.drawLine(x + width, y, x + width, y + height - 1);
919
g.setColor(c);
920
}
921
922
/*
923
* drawXXX() methods are used to print the native components by
924
* rendering the Motif look ourselves.
925
* ToDo(aim): needs to query native motif for more accurate color
926
* information.
927
*/
928
void draw3DOval(Graphics g, Color bg,
929
int x, int y, int w, int h, boolean raised)
930
{
931
Color c = g.getColor();
932
Color shadow = bg.darker();
933
Color highlight = bg.brighter();
934
935
g.setColor(raised ? highlight : shadow);
936
g.drawArc(x, y, w, h, 45, 180);
937
g.setColor(raised ? shadow : highlight);
938
g.drawArc(x, y, w, h, 225, 180);
939
g.setColor(c);
940
}
941
942
void draw3DRect(Graphics g, Color bg,
943
int x, int y, int width, int height,
944
boolean raised) {
945
Color c = g.getColor();
946
Color shadow = bg.darker();
947
Color highlight = bg.brighter();
948
949
g.setColor(raised ? highlight : shadow);
950
g.drawLine(x, y, x, y + height);
951
g.drawLine(x + 1, y, x + width - 1, y);
952
g.setColor(raised ? shadow : highlight);
953
g.drawLine(x + 1, y + height, x + width, y + height);
954
g.drawLine(x + width, y, x + width, y + height - 1);
955
g.setColor(c);
956
}
957
958
void drawScrollbar(Graphics g, Color bg, int thickness, int length,
959
int min, int max, int val, int vis, boolean horizontal) {
960
Color c = g.getColor();
961
double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
962
int v1 = thickness + (int)(f * (val - min));
963
int v2 = (int)(f * vis);
964
int w2 = thickness-4;
965
int[] tpts_x = new int[3];
966
int[] tpts_y = new int[3];
967
968
if (length < 3*w2 ) {
969
v1 = v2 = 0;
970
if (length < 2*w2 + 2) {
971
w2 = (length-2)/2;
972
}
973
} else if (v2 < 7) {
974
// enforce a minimum handle size
975
v1 = Math.max(0, v1 - ((7 - v2)>>1));
976
v2 = 7;
977
}
978
979
int ctr = thickness/2;
980
int sbmin = ctr - w2/2;
981
int sbmax = ctr + w2/2;
982
983
// paint the background slightly darker
984
{
985
Color d = new Color((int) (bg.getRed() * 0.85),
986
(int) (bg.getGreen() * 0.85),
987
(int) (bg.getBlue() * 0.85));
988
989
g.setColor(d);
990
if (horizontal) {
991
g.fillRect(0, 0, length, thickness);
992
} else {
993
g.fillRect(0, 0, thickness, length);
994
}
995
}
996
997
// paint the thumb and arrows in the normal background color
998
g.setColor(bg);
999
if (v1 > 0) {
1000
if (horizontal) {
1001
g.fillRect(v1, 3, v2, thickness-3);
1002
} else {
1003
g.fillRect(3, v1, thickness-3, v2);
1004
}
1005
}
1006
1007
tpts_x[0] = ctr; tpts_y[0] = 2;
1008
tpts_x[1] = sbmin; tpts_y[1] = w2;
1009
tpts_x[2] = sbmax; tpts_y[2] = w2;
1010
if (horizontal) {
1011
g.fillPolygon(tpts_y, tpts_x, 3);
1012
} else {
1013
g.fillPolygon(tpts_x, tpts_y, 3);
1014
}
1015
1016
tpts_y[0] = length-2;
1017
tpts_y[1] = length-w2;
1018
tpts_y[2] = length-w2;
1019
if (horizontal) {
1020
g.fillPolygon(tpts_y, tpts_x, 3);
1021
} else {
1022
g.fillPolygon(tpts_x, tpts_y, 3);
1023
}
1024
1025
Color highlight = bg.brighter();
1026
1027
// // // // draw the "highlighted" edges
1028
g.setColor(highlight);
1029
1030
// outline & arrows
1031
if (horizontal) {
1032
g.drawLine(1, thickness, length - 1, thickness);
1033
g.drawLine(length - 1, 1, length - 1, thickness);
1034
1035
// arrows
1036
g.drawLine(1, ctr, w2, sbmin);
1037
g.drawLine(length - w2, sbmin, length - w2, sbmax);
1038
g.drawLine(length - w2, sbmin, length - 2, ctr);
1039
1040
} else {
1041
g.drawLine(thickness, 1, thickness, length - 1);
1042
g.drawLine(1, length - 1, thickness, length - 1);
1043
1044
// arrows
1045
g.drawLine(ctr, 1, sbmin, w2);
1046
g.drawLine(sbmin, length - w2, sbmax, length - w2);
1047
g.drawLine(sbmin, length - w2, ctr, length - 2);
1048
}
1049
1050
// thumb
1051
if (v1 > 0) {
1052
if (horizontal) {
1053
g.drawLine(v1, 2, v1 + v2, 2);
1054
g.drawLine(v1, 2, v1, thickness-3);
1055
} else {
1056
g.drawLine(2, v1, 2, v1 + v2);
1057
g.drawLine(2, v1, thickness-3, v1);
1058
}
1059
}
1060
1061
Color shadow = bg.darker();
1062
1063
// // // // draw the "shadowed" edges
1064
g.setColor(shadow);
1065
1066
// outline && arrows
1067
if (horizontal) {
1068
g.drawLine(0, 0, 0, thickness);
1069
g.drawLine(0, 0, length - 1, 0);
1070
1071
// arrows
1072
g.drawLine(w2, sbmin, w2, sbmax);
1073
g.drawLine(w2, sbmax, 1, ctr);
1074
g.drawLine(length-2, ctr, length-w2, sbmax);
1075
1076
} else {
1077
g.drawLine(0, 0, thickness, 0);
1078
g.drawLine(0, 0, 0, length - 1);
1079
1080
// arrows
1081
g.drawLine(sbmin, w2, sbmax, w2);
1082
g.drawLine(sbmax, w2, ctr, 1);
1083
g.drawLine(ctr, length-2, sbmax, length-w2);
1084
}
1085
1086
// thumb
1087
if (v1 > 0) {
1088
if (horizontal) {
1089
g.drawLine(v1 + v2, 2, v1 + v2, thickness-2);
1090
g.drawLine(v1, thickness-2, v1 + v2, thickness-2);
1091
} else {
1092
g.drawLine(2, v1 + v2, thickness-2, v1 + v2);
1093
g.drawLine(thickness-2, v1, thickness-2, v1 + v2);
1094
}
1095
}
1096
g.setColor(c);
1097
}
1098
1099
/**
1100
* The following multibuffering-related methods delegate to our
1101
* associated GraphicsConfig (X11 or GLX) to handle the appropriate
1102
* native windowing system specific actions.
1103
*/
1104
1105
private BufferCapabilities backBufferCaps;
1106
1107
public void createBuffers(int numBuffers, BufferCapabilities caps)
1108
throws AWTException
1109
{
1110
if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1111
buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")");
1112
}
1113
// set the caps first, they're used when creating the bb
1114
backBufferCaps = caps;
1115
backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps);
1116
xBackBuffer = graphicsConfig.createBackBufferImage(target,
1117
backBuffer);
1118
}
1119
1120
@Override
1121
public BufferCapabilities getBackBufferCaps() {
1122
return backBufferCaps;
1123
}
1124
1125
public void flip(int x1, int y1, int x2, int y2,
1126
BufferCapabilities.FlipContents flipAction)
1127
{
1128
if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1129
buffersLog.fine("flip(" + flipAction + ")");
1130
}
1131
if (backBuffer == 0) {
1132
throw new IllegalStateException("Buffers have not been created");
1133
}
1134
graphicsConfig.flip(this, target, xBackBuffer,
1135
x1, y1, x2, y2, flipAction);
1136
}
1137
1138
public Image getBackBuffer() {
1139
if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1140
buffersLog.fine("getBackBuffer()");
1141
}
1142
if (backBuffer == 0) {
1143
throw new IllegalStateException("Buffers have not been created");
1144
}
1145
return xBackBuffer;
1146
}
1147
1148
public void destroyBuffers() {
1149
if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1150
buffersLog.fine("destroyBuffers()");
1151
}
1152
graphicsConfig.destroyBackBuffer(backBuffer);
1153
backBuffer = 0;
1154
xBackBuffer = null;
1155
}
1156
1157
// End of multi-buffering
1158
1159
public void notifyTextComponentChange(boolean add){
1160
Container parent = AWTAccessor.getComponentAccessor().getParent(target);
1161
while(!(parent == null ||
1162
parent instanceof java.awt.Frame ||
1163
parent instanceof java.awt.Dialog)) {
1164
parent = AWTAccessor.getComponentAccessor().getParent(parent);
1165
}
1166
1167
/* FIX ME - FIX ME need to implement InputMethods
1168
if (parent instanceof java.awt.Frame ||
1169
parent instanceof java.awt.Dialog) {
1170
if (add)
1171
((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this);
1172
else
1173
((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this);
1174
}
1175
*/
1176
}
1177
1178
/**
1179
* Returns true if this event is disabled and shouldn't be processed by window
1180
* Currently if target component is disabled the following event will be disabled on window:
1181
* ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify
1182
*/
1183
protected boolean isEventDisabled(XEvent e) {
1184
if (enableLog.isLoggable(PlatformLogger.Level.FINEST)) {
1185
enableLog.finest("Component is {1}, checking for disabled event {0}", e, (isEnabled()?"enabled":"disable"));
1186
}
1187
if (!isEnabled()) {
1188
switch (e.get_type()) {
1189
case XConstants.ButtonPress:
1190
case XConstants.ButtonRelease:
1191
case XConstants.KeyPress:
1192
case XConstants.KeyRelease:
1193
case XConstants.EnterNotify:
1194
case XConstants.LeaveNotify:
1195
case XConstants.MotionNotify:
1196
if (enableLog.isLoggable(PlatformLogger.Level.FINER)) {
1197
enableLog.finer("Event {0} is disable", e);
1198
}
1199
return true;
1200
}
1201
}
1202
switch(e.get_type()) {
1203
case XConstants.MapNotify:
1204
case XConstants.UnmapNotify:
1205
return true;
1206
}
1207
return super.isEventDisabled(e);
1208
}
1209
1210
Color getPeerBackground() {
1211
return background;
1212
}
1213
1214
Color getPeerForeground() {
1215
return foreground;
1216
}
1217
1218
Font getPeerFont() {
1219
return font;
1220
}
1221
1222
Dimension getPeerSize() {
1223
return new Dimension(width,height);
1224
}
1225
1226
public void setBoundsOperation(int operation) {
1227
synchronized(getStateLock()) {
1228
if (boundsOperation == DEFAULT_OPERATION) {
1229
boundsOperation = operation;
1230
} else if (operation == RESET_OPERATION) {
1231
boundsOperation = DEFAULT_OPERATION;
1232
}
1233
}
1234
}
1235
1236
static String operationToString(int operation) {
1237
switch (operation) {
1238
case SET_LOCATION:
1239
return "SET_LOCATION";
1240
case SET_SIZE:
1241
return "SET_SIZE";
1242
case SET_CLIENT_SIZE:
1243
return "SET_CLIENT_SIZE";
1244
default:
1245
case SET_BOUNDS:
1246
return "SET_BOUNDS";
1247
}
1248
}
1249
1250
/**
1251
* Lowers this component at the bottom of the above HW peer. If the above parameter
1252
* is null then the method places this component at the top of the Z-order.
1253
*/
1254
public void setZOrder(ComponentPeer above) {
1255
long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
1256
1257
XToolkit.awtLock();
1258
try{
1259
XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
1260
}finally{
1261
XToolkit.awtUnlock();
1262
}
1263
}
1264
1265
private void addTree(Collection<Long> order, Set<Long> set, Container cont) {
1266
for (int i = 0; i < cont.getComponentCount(); i++) {
1267
Component comp = cont.getComponent(i);
1268
Object peer = AWTAccessor.getComponentAccessor().getPeer(comp);
1269
if (peer instanceof XComponentPeer) {
1270
Long window = Long.valueOf(((XComponentPeer)peer).getWindow());
1271
if (!set.contains(window)) {
1272
set.add(window);
1273
order.add(window);
1274
}
1275
} else if (comp instanceof Container) {
1276
// It is lightweight container, it might contain heavyweight components attached to this
1277
// peer
1278
addTree(order, set, (Container)comp);
1279
}
1280
}
1281
}
1282
1283
/****** DropTargetPeer implementation ********************/
1284
1285
public void addDropTarget(DropTarget dt) {
1286
Component comp = target;
1287
while(!(comp == null || comp instanceof Window)) {
1288
comp = comp.getParent();
1289
}
1290
1291
if (comp instanceof Window) {
1292
XWindowPeer wpeer = AWTAccessor.getComponentAccessor().getPeer(comp);
1293
if (wpeer != null) {
1294
wpeer.addDropTarget();
1295
}
1296
}
1297
}
1298
1299
public void removeDropTarget(DropTarget dt) {
1300
Component comp = target;
1301
while(!(comp == null || comp instanceof Window)) {
1302
comp = comp.getParent();
1303
}
1304
1305
if (comp instanceof Window) {
1306
XWindowPeer wpeer = AWTAccessor.getComponentAccessor()
1307
.getPeer(comp);
1308
if (wpeer != null) {
1309
wpeer.removeDropTarget();
1310
}
1311
}
1312
}
1313
1314
/**
1315
* Applies the shape to the X-window.
1316
* @since 1.7
1317
*/
1318
public void applyShape(Region shape) {
1319
if (XlibUtil.isShapingSupported()) {
1320
if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1321
shapeLog.finer(
1322
"*** INFO: Setting shape: PEER: " + this
1323
+ "; WINDOW: " + getWindow()
1324
+ "; TARGET: " + target
1325
+ "; SHAPE: " + shape);
1326
}
1327
XToolkit.awtLock();
1328
try {
1329
if (shape != null) {
1330
1331
int scale = getScale();
1332
if (scale != 1) {
1333
shape = shape.getScaledRegion(scale, scale);
1334
}
1335
1336
XlibWrapper.SetRectangularShape(
1337
XToolkit.getDisplay(),
1338
getWindow(),
1339
shape.getLoX(), shape.getLoY(),
1340
shape.getHiX(), shape.getHiY(),
1341
(shape.isRectangular() ? null : shape)
1342
);
1343
} else {
1344
XlibWrapper.SetRectangularShape(
1345
XToolkit.getDisplay(),
1346
getWindow(),
1347
0, 0,
1348
0, 0,
1349
null
1350
);
1351
}
1352
} finally {
1353
XToolkit.awtUnlock();
1354
}
1355
} else {
1356
if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1357
shapeLog.finer("*** WARNING: Shaping is NOT supported!");
1358
}
1359
}
1360
}
1361
1362
public boolean updateGraphicsData(GraphicsConfiguration gc) {
1363
int oldVisual = -1, newVisual = -1;
1364
1365
if (graphicsConfig != null) {
1366
oldVisual = graphicsConfig.getVisual();
1367
}
1368
if (gc != null && gc instanceof X11GraphicsConfig) {
1369
newVisual = ((X11GraphicsConfig)gc).getVisual();
1370
}
1371
1372
// If the new visual differs from the old one, the peer must be
1373
// recreated because X11 does not allow changing the visual on the fly.
1374
// So we even skip the initGraphicsConfiguration() call.
1375
// The initial assignment should happen though, hence the != -1 thing.
1376
if (oldVisual != -1 && oldVisual != newVisual) {
1377
return true;
1378
}
1379
1380
initGraphicsConfiguration();
1381
doValidateSurface();
1382
return false;
1383
}
1384
}
1385
1386