/* * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.awt.motif; import java.awt.*; import java.awt.peer.*; import java.awt.event.PaintEvent; import java.awt.event.MouseEvent; import java.awt.event.InputEvent; import sun.awt.*; import sun.awt.image.ToolkitImage; import sun.awt.image.SunVolatileImage; import java.awt.image.ImageProducer; import java.awt.image.ImageObserver; import java.awt.image.ColorModel; import java.awt.image.VolatileImage; import java.awt.dnd.DropTarget; import java.awt.dnd.peer.DropTargetPeer; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import java.lang.reflect.Method; import java.util.logging.*; import sun.java2d.pipe.Region; public /* REMIND: should not be public */ abstract class MComponentPeer implements ComponentPeer, DropTargetPeer, X11ComponentPeer { private static final Logger log = Logger.getLogger("sun.awt.motif.MComponentPeer"); private static final Logger focusLog = Logger.getLogger("sun.awt.motif.focus.MComponentPeer"); Component target; long pData; long jniGlobalRef; protected X11GraphicsConfig graphicsConfig; SurfaceData surfaceData; int oldWidth = -1; int oldHeight = -1; private RepaintArea paintArea; boolean isLayouting = false; boolean paintPending = false; protected boolean disposed = false; private static int JAWT_LOCK_ERROR=0x00000001; private static int JAWT_LOCK_CLIP_CHANGED=0x00000002; private static int JAWT_LOCK_BOUNDS_CHANGED=0x00000004; private static int JAWT_LOCK_SURFACE_CHANGED=0x00000008; private int drawState = JAWT_LOCK_CLIP_CHANGED | JAWT_LOCK_BOUNDS_CHANGED | JAWT_LOCK_SURFACE_CHANGED; /* These are the enumerated types in awt_p.h*/ static final int MOTIF_NA = 0 ; static final int MOTIF_V1 = 1 ; static final int MOTIF_V2 = 2 ; private Font font; private long backBuffer = 0; private VolatileImage xBackBuffer = null; static { initIDs(); } /* initialize the fieldIDs of fields that may be accessed from C */ private native static void initIDs(); /* This will return the last state of a window. ie the specific * "gotcha" is that if you iconify a window its obscurity remains * unchanged. Current use of this is just in user-initiated scrolling. * If that use expands to more cases you may need to "and" this with * the value of the iconic state of a Frame. * Note that de-iconifying an X11 window DOES generate a new event * correctly notifying you of the new visibility of the window */ public boolean isObscured() { Container container = (target instanceof Container) ? (Container)target : target.getParent(); if (container == null) { return true; } Container parent; while ((parent = container.getParent()) != null) { container = parent; } if (container instanceof Window) { MWindowPeer wpeer = (MWindowPeer)(container.getPeer()); if (wpeer != null) { return (wpeer.winAttr.visibilityState != MWindowAttributes.AWT_UNOBSCURED); } } return true; } public boolean canDetermineObscurity() { return true; } abstract void create(MComponentPeer parent); void create(MComponentPeer parent, Object arg) { create(parent); } void EFcreate(MComponentPeer parent, int x){} native void pInitialize(); native void pShow(); native void pHide(); native void pEnable(); native void pDisable(); native void pReshape(int x, int y, int width, int height); native void pDispose(); native void pMakeCursorVisible(); native Point pGetLocationOnScreen(); native Point pGetLocationOnScreen2(Window win, MWindowPeer wpeer); native void pSetForeground(Color c); native void pSetBackground(Color c); private native void pSetFont(Font f); //Added for bug 4175560 //Returns the native representation for the Color argument, //using the given GraphicsConfiguration. native int getNativeColor(Color clr, GraphicsConfiguration gc); // Returns the parent of the component, without invoking client // code. This must go through native code, because it invokes // private methods in the java.awt package, which we cannot // do from this package. static native Container getParent_NoClientCode(Component component); // Returns the parent of the component, without invoking client // code. This must go through native code, because it invokes // private methods in the java.awt package, which we cannot // do from this package. static native Component[] getComponents_NoClientCode(Container container); void initialize() { if (!target.isVisible()) { hide(); } Color c; Font f; Cursor cursor; pInitialize(); if ((c = target.getForeground()) != null) { setForeground(c); } if ((c = target.getBackground()) != null) { setBackground(c); } if ((f = target.getFont()) != null) { setFont(f); } pSetCursor(target.getCursor()); if (!target.isEnabled()) { disable(); } Rectangle r = target.getBounds(); reshape(r.x, r.y, r.width, r.height); if (target.isVisible()) { show(); } surfaceData = graphicsConfig.createSurfaceData(this); } public void init(Component target, Object arg) { this.target = target; this.paintArea = new RepaintArea(); Container parent = MToolkit.getNativeContainer(target); MComponentPeer parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent); create(parentPeer, arg); initialize(); } MComponentPeer(Component target, Object arg) { init(target, arg); } MComponentPeer() {} public void init(Component target) { this.target = target; this.paintArea = new RepaintArea(); Container parent = MToolkit.getNativeContainer(target); MComponentPeer parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent); create(parentPeer); if (parent != null && parent instanceof ScrollPane) { MScrollPanePeer speer = (MScrollPanePeer) parentPeer; speer.setScrollChild(this); } initialize(); } MComponentPeer(Component target) { init(target); } protected void finalize() throws Throwable { dispose(); super.finalize(); } public void setForeground(Color c) { pSetForeground(c); } public void setBackground(Color c) { pSetBackground(c); } public void updateCursorImmediately() { MGlobalCursorManager.getCursorManager().updateCursorImmediately(); } public void setFont(Font f) { ComponentPeer peer; if (f == null) { f = defaultFont; } pSetFont(f); if ( target instanceof Container ) { Container container = (Container) target; int count = container.getComponentCount(); Component[] children = container.getComponents(); for (int i=0; i>1)); v2 = 7; } int ctr = thickness/2; int sbmin = ctr - w2/2; int sbmax = ctr + w2/2; // paint the background slightly darker { Color d = new Color((int) (bg.getRed() * 0.85), (int) (bg.getGreen() * 0.85), (int) (bg.getBlue() * 0.85)); g.setColor(d); if (horizontal) { g.fillRect(0, 0, length, thickness); } else { g.fillRect(0, 0, thickness, length); } } // paint the thumb and arrows in the normal background color g.setColor(bg); if (v1 > 0) { if (horizontal) { g.fillRect(v1, 3, v2, thickness-3); } else { g.fillRect(3, v1, thickness-3, v2); } } tpts_x[0] = ctr; tpts_y[0] = 2; tpts_x[1] = sbmin; tpts_y[1] = w2; tpts_x[2] = sbmax; tpts_y[2] = w2; if (horizontal) { g.fillPolygon(tpts_y, tpts_x, 3); } else { g.fillPolygon(tpts_x, tpts_y, 3); } tpts_y[0] = length-2; tpts_y[1] = length-w2; tpts_y[2] = length-w2; if (horizontal) { g.fillPolygon(tpts_y, tpts_x, 3); } else { g.fillPolygon(tpts_x, tpts_y, 3); } Color highlight = bg.brighter(); // // // // draw the "highlighted" edges g.setColor(highlight); // outline & arrows if (horizontal) { g.drawLine(1, thickness, length - 1, thickness); g.drawLine(length - 1, 1, length - 1, thickness); // arrows g.drawLine(1, ctr, w2, sbmin); g.drawLine(length - w2, sbmin, length - w2, sbmax); g.drawLine(length - w2, sbmin, length - 2, ctr); } else { g.drawLine(thickness, 1, thickness, length - 1); g.drawLine(1, length - 1, thickness, length - 1); // arrows g.drawLine(ctr, 1, sbmin, w2); g.drawLine(sbmin, length - w2, sbmax, length - w2); g.drawLine(sbmin, length - w2, ctr, length - 2); } // thumb if (v1 > 0) { if (horizontal) { g.drawLine(v1, 2, v1 + v2, 2); g.drawLine(v1, 2, v1, thickness-3); } else { g.drawLine(2, v1, 2, v1 + v2); g.drawLine(2, v1, thickness-3, v1); } } Color shadow = bg.darker(); // // // // draw the "shadowed" edges g.setColor(shadow); // outline && arrows if (horizontal) { g.drawLine(0, 0, 0, thickness); g.drawLine(0, 0, length - 1, 0); // arrows g.drawLine(w2, sbmin, w2, sbmax); g.drawLine(w2, sbmax, 1, ctr); g.drawLine(length-2, ctr, length-w2, sbmax); } else { g.drawLine(0, 0, thickness, 0); g.drawLine(0, 0, 0, length - 1); // arrows g.drawLine(sbmin, w2, sbmax, w2); g.drawLine(sbmax, w2, ctr, 1); g.drawLine(ctr, length-2, sbmax, length-w2); } // thumb if (v1 > 0) { if (horizontal) { g.drawLine(v1 + v2, 2, v1 + v2, thickness-2); g.drawLine(v1, thickness-2, v1 + v2, thickness-2); } else { g.drawLine(2, v1 + v2, thickness-2, v1 + v2); g.drawLine(thickness-2, v1, thickness-2, v1 + v2); } } g.setColor(c); } public String toString() { return getClass().getName() + "[" + target + "]"; } /* New 1.1 API */ public void setVisible(boolean b) { if (b) { Dimension s = target.getSize(); oldWidth = s.width; oldHeight = s.height; pShow(); } else { pHide(); } } /* New 1.1 API */ public void setEnabled(boolean b) { if (b) { pEnable(); } else { pDisable(); } } /* New 1.1 API */ public Point getLocationOnScreen() { synchronized (target.getTreeLock()) { Component comp = target; while (comp != null && !(comp instanceof Window)) { comp = getParent_NoClientCode(comp); } // applets, embedded, etc - translate directly if (comp == null || comp instanceof sun.awt.EmbeddedFrame) { return pGetLocationOnScreen(); } MWindowPeer wpeer = (MWindowPeer)(MToolkit.targetToPeer(comp)); if (wpeer == null) { return pGetLocationOnScreen(); } return pGetLocationOnScreen2((Window)comp, wpeer); } } public int serialNum = 0; /* Returns the native paint should be posted after setting new size */ public boolean checkNativePaintOnSetBounds(int width, int height) { return (width != oldWidth) || (height != oldHeight); } void setBounds(int x, int y, int width, int height) { setBounds(x, y, width, height, SET_BOUNDS); } /* New 1.1 API */ public void setBounds(int x, int y, int width, int height, int op) { if (disposed) return; Container parent = getParent_NoClientCode(target); // Should set paintPending before reshape to prevent // thread race between PaintEvent and setBounds // This part of the 4267393 fix proved to be unstable under solaris, // dissabled due to regressions 4418155, 4486762, 4490079 paintPending = false; //checkNativePaintOnSetBounds(width, height); // Note: it would be ideal to NOT execute this if it's // merely a Move which is occurring. if (parent != null && parent instanceof ScrollPane) { MScrollPanePeer speer = (MScrollPanePeer)parent.getPeer(); if (!speer.ignore) { pReshape(x, y, width, height); speer.childResized(width, height); } } else { pReshape(x, y, width, height); } if ((width != oldWidth) || (height != oldHeight)) { SurfaceData oldData = surfaceData; if (oldData != null) { surfaceData = graphicsConfig.createSurfaceData(this); oldData.invalidate(); } oldWidth = width; oldHeight = height; } validateSurface(width, height); serialNum++; } void validateSurface(int width, int height) { SunToolkit.awtLock(); try { if (!disposed && (width != oldWidth || height != oldHeight)) { SurfaceData oldData = surfaceData; if (oldData != null) { surfaceData = graphicsConfig.createSurfaceData(this); oldData.invalidate(); } oldWidth = width; oldHeight = height; } } finally { SunToolkit.awtUnlock(); } } public void beginValidate() { } native void restoreFocus(); public void endValidate() { restoreFocus(); } public void beginLayout() { // Skip all painting till endLayout isLayouting = true; } public void endLayout() { if (!paintPending && !paintArea.isEmpty() && !((Component)target).getIgnoreRepaint()) { // if not waiting for native painting repaint damaged area postEvent(new PaintEvent((Component)target, PaintEvent.PAINT, new Rectangle())); } isLayouting = false; } /** * DEPRECATED: Replaced by setVisible(boolean). */ public void show() { setVisible(true); } /** * DEPRECATED: Replaced by setVisible(boolean). */ public void hide() { setVisible(false); } /** * DEPRECATED: Replaced by setEnabled(boolean). */ public void enable() { setEnabled(true); } /** * DEPRECATED: Replaced by setEnabled(boolean). */ public void disable() { setEnabled(false); } /** * DEPRECATED: Replaced by setBounds(int, int, int, int). */ public void reshape(int x, int y, int width, int height) { setBounds(x, y, width, height); } /** * DEPRECATED: Replaced by getMinimumSize(). */ public Dimension minimumSize() { return getMinimumSize(); } /** * DEPRECATED: Replaced by getPreferredSize(). */ public Dimension preferredSize() { return getPreferredSize(); } /** * */ public void addDropTarget(DropTarget dt) { if (MToolkit.useMotifDnD()) { addNativeDropTarget(dt); } else { Component comp = target; while(!(comp == null || comp instanceof java.awt.Window)) { comp = getParent_NoClientCode(comp); } if (comp instanceof Window) { MWindowPeer wpeer = (MWindowPeer)(comp.getPeer()); if (wpeer != null) { wpeer.addDropTarget(); } } } } /** * */ public void removeDropTarget(DropTarget dt) { if (MToolkit.useMotifDnD()) { removeNativeDropTarget(dt); } else { Component comp = target; while(!(comp == null || comp instanceof java.awt.Window)) { comp = getParent_NoClientCode(comp); } if (comp instanceof Window) { MWindowPeer wpeer = (MWindowPeer)(comp.getPeer()); if (wpeer != null) { wpeer.removeDropTarget(); } } } } public void notifyTextComponentChange(boolean add){ Container parent = getParent_NoClientCode(target); while(!(parent == null || parent instanceof java.awt.Frame || parent instanceof java.awt.Dialog)) { parent = getParent_NoClientCode(parent); } if (parent instanceof java.awt.Frame || parent instanceof java.awt.Dialog) { if (add) ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this); else ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this); } } native void addNativeDropTarget(DropTarget dt); native void removeNativeDropTarget(DropTarget dt); public GraphicsConfiguration getGraphicsConfiguration() { GraphicsConfiguration ret = graphicsConfig; if (ret == null) { ret = target.getGraphicsConfiguration(); } return ret; } // Returns true if we are inside begin/endLayout and // are waiting for native painting public boolean isPaintPending() { return paintPending && isLayouting; } public boolean handlesWheelScrolling() { return false; } /** * The following multibuffering-related methods delegate to our * associated GraphicsConfig (X11 or GLX) to handle the appropriate * native windowing system specific actions. */ private native long getWindow(long pData); public long getContentWindow() { return getWindow(pData); } public void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException { backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps); xBackBuffer = graphicsConfig.createBackBufferImage(target, backBuffer); } public void flip(int x1, int y1, int x2, int y2, BufferCapabilities.FlipContents flipAction) { if (backBuffer == 0) { throw new IllegalStateException("Buffers have not been created"); } graphicsConfig.flip(this, target, xBackBuffer, x1, y1, x2, y2, flipAction); } public Image getBackBuffer() { if (backBuffer == 0) { throw new IllegalStateException("Buffers have not been created"); } return xBackBuffer; } public void destroyBuffers() { graphicsConfig.destroyBackBuffer(backBuffer); backBuffer = 0; xBackBuffer = null; } /** * @see java.awt.peer.ComponentPeer#isReparentSupported */ public boolean isReparentSupported() { return false; } /** * @see java.awt.peer.ComponentPeer#reparent */ public void reparent(ContainerPeer newNativeParent) { throw new UnsupportedOperationException(); } /** * Applies the shape to the native component window. * @since 1.7 */ public void applyShape(Region shape) { } }