Package sun.awt.motif

Source Code of sun.awt.motif.MComponentPeer

/*
* Copyright (c) 1995, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.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<count; i++) {
                if ( children[i] != null ) {
/*
** note: recursion in the widget in pSetFont() has by now broken any
**       children with different Fonts - so fix now:
*/
                    peer = children[i].getPeer();
                    if (peer != null) {
                        Font rightFont = children[i].getFont();
                        if (!f.equals(rightFont)) {
                            peer.setFont(rightFont);
                        } else
                            if (children[i] instanceof Container) {
                                peer.setFont(f);
                            }
                    }
                }
            }
        }

        /*
         * Keep a reference to the java.awt.Font object in order to
         * preserve the XFontStructs which underlying widgets are using.
         * Save this AFTER changing the widgets in order to keep the
         * previous reference (if any) alive.
         */
        font = f;
    }


    public native void setTargetBackground(Color c);
    public native void pSetCursor(Cursor c);
    public native void pSetScrollbarBackground(Color c);
    public native void pSetInnerForeground(Color c);

    public boolean isFocusable() {
        return false;
    }

    public SurfaceData getSurfaceData() {
        return surfaceData;
    }

    public ColorModel getColorModel() {
        return graphicsConfig.getColorModel();
    }

    public ColorModel getColorModel(int transparency) {
        return graphicsConfig.getColorModel(transparency);
    }

    public int updatePriority() {
        return Thread.NORM_PRIORITY;
    }

    public void repaint(long tm, int x, int y, int width, int height) {
    }

    public void paint(Graphics g) {
        Dimension d = target.getSize();
        if (g instanceof Graphics2D ||
            g instanceof sun.awt.Graphics2Delegate) {
            // background color is setup correctly, so just use clearRect
            g.clearRect(0, 0, d.width, d.height);
        } else {
            // emulate clearRect
            g.setColor(target.getBackground());
            g.fillRect(0, 0, d.width, d.height);
            g.setColor(target.getForeground());
        }

        target.paint(g);
    }
    public void print(Graphics g) {
        Dimension d = target.getSize();
        if (g instanceof Graphics2D ||
            g instanceof sun.awt.Graphics2Delegate) {
            // background color is setup correctly, so just use clearRect
            g.clearRect(0, 0, d.width, d.height);
        } else {
            // emulate clearRect
            g.setColor(target.getBackground());
            g.fillRect(0, 0, d.width, d.height);
            g.setColor(target.getForeground());
        }

        target.print(g);
    }

    public void coalescePaintEvent(PaintEvent e) {
        Rectangle r = e.getUpdateRect();
        paintArea.add(r, e.getID());

        if (log.isLoggable(Level.FINEST)) {
            switch(e.getID()) {
              case PaintEvent.UPDATE:
                  log.log(Level.FINEST, "coalescePaintEvent: UPDATE: add: x = " +
                          r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
                  return;
              case PaintEvent.PAINT:
                  log.log(Level.FINEST, "coalescePaintEvent: PAINT: add: x = " +
                          r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
                  return;
            }
        }
    }

    native void nativeHandleEvent(AWTEvent e);

    /**
     * Returns whether or not this component should be given focus on mouse click.
     * Default implementation return whether or not this peer is "focusable"
     * Descendants might want to override it to extend/restrict conditions at which this
     * component should be focused by click (see MCanvasPeer and MPanelPeer)
     */
    protected boolean shouldFocusOnClick() {
        return isFocusable();
    }

    /**
     * Checks whether or not this component would be focused by native system if it would be allowed to do so.
     * Currently it checks that it displayable, visible, enabled and focusable.
     */
    static boolean canBeFocusedByClick(Component component) {
        if (component == null) {
            return false;
        } else {
            return component.isDisplayable() && component.isVisible() && component.isEnabled() && component.isFocusable();
        }
    }

    static Method requestFocusWithCause;

    static void callRequestFocusInWindow(Component target, CausedFocusEvent.Cause cause) {
        AWTAccessor.getComponentAccessor().requestFocusInWindow(target, cause);
    }

    public void handleEvent(AWTEvent e) {
        int id = e.getID();

        switch(id) {
          case PaintEvent.PAINT:
              // Got native painting
              paintPending = false;
              // Fallthrough to next statement
          case PaintEvent.UPDATE:
              // Skip all painting while layouting and all UPDATEs
              // while waiting for native paint
              if (!isLayouting && !paintPending) {
                  paintArea.paint(target,false);
              }
              return;
          case MouseEvent.MOUSE_PRESSED:
              if (target == e.getSource() && !((InputEvent)e).isConsumed() && shouldFocusOnClick()
                  && !target.isFocusOwner() && canBeFocusedByClick(target))
              {
                  callRequestFocusInWindow(target, CausedFocusEvent.Cause.MOUSE_EVENT);
              }
              break;
          default:
              break;
        }

        // Call the native code
        nativeHandleEvent(e);
    }

    /* New API for 1.1 */
    public Dimension getMinimumSize() {
        return target.getSize();
    }

    /* New API for 1.1 */
    public Dimension getPreferredSize() {
        return getMinimumSize();
    }

    // Do nothing for heavyweight implementation
    public void layout() {}

    public Rectangle getBounds() {
        return ((Component)target).getBounds();
    }

    public Object getTarget() {
        return target;
    }

    public java.awt.Toolkit getToolkit() {
        // XXX: bogus
        return Toolkit.getDefaultToolkit();
    }

    // fallback default font object
    final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);

    public synchronized Graphics getGraphics() {
        if (!disposed) {
            Component target = (Component) this.target;

            /* Fix for bug 4746122. Color and Font shouldn't be null */
            Color bgColor = target.getBackground();
            if (bgColor == null) {
                bgColor = SystemColor.window;
            }
            Color fgColor = target.getForeground();
            if (fgColor == null) {
                fgColor = SystemColor.windowText;
            }
            Font font = target.getFont();
            if (font == null) {
                font = defaultFont;
            }
            return new SunGraphics2D(surfaceData, fgColor, bgColor, font);
        }

        return null;
    }

    public Image createImage(ImageProducer producer) {
        return new ToolkitImage(producer);
    }

    public Image createImage(int width, int height) {
        return graphicsConfig.createAcceleratedImage(target, width, height);
    }

    public VolatileImage createVolatileImage(int width, int height) {
        return new SunVolatileImage(target, width, height);
    }

    public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
        return getToolkit().prepareImage(img, w, h, o);
    }

    public int checkImage(Image img, int w, int h, ImageObserver o) {
        return getToolkit().checkImage(img, w, h, o);
    }

    public FontMetrics getFontMetrics(Font font) {
        return X11FontMetrics.getFontMetrics(font);
    }

    /*
     * Subclasses should override disposeImpl() instead of dispose(). Client
     * code should always invoke dispose(), never disposeImpl().
     */
    protected void disposeImpl() {
        SurfaceData oldData = surfaceData;
        surfaceData = null;
        oldData.invalidate();
        MToolkit.targetDisposedPeer(target, this);
        pDispose();
    }
    public final void dispose() {
        boolean call_disposeImpl = false;

        if (!disposed) {
            synchronized (this) {
                SunToolkit.awtLock();
                try {
                    if (!disposed) {
                        disposed = call_disposeImpl = true;
                    }
                } finally {
                    SunToolkit.awtUnlock();
                }
            }
        }

        if (call_disposeImpl) {
            disposeImpl();
        }
    }

    native static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
                                                                boolean temporary, boolean focusedWindowChangeAllowed,
                                                                long time);
    public boolean requestFocus
    (Component lightweightChild, boolean temporary,
         boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) {
        if (processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
                                                  focusedWindowChangeAllowed, time)) {
            return true;
        } else {
            if (focusLog.isLoggable(Level.FINER)) {
                focusLog.log(Level.FINER, "Current native focused window " + getNativeFocusedWindow());
            }
            /**
             * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
             * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
             * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
             * in requests list - and it breaks our requests sequence as first record on WGF should be the last focus
             * owner which had focus before WLF. So, we should not add request record for such requests
             * but store this component in mostRecent - and return true as before for compatibility.
             */
            Container parent = (target instanceof Container) ? ((Container)target) : (target.getParent());
            // Search for parent window
            while (parent != null && !(parent instanceof Window)) {
                parent = getParent_NoClientCode(parent);
            }
            if (parent != null) {
                Window parentWindow = (Window)parent;
                // and check that it is focused
                if (focusLog.isLoggable(Level.FINER)) {
                    focusLog.log(Level.FINER, "Parent window " + parentWindow);
                }
                if (!parentWindow.isFocused() && getNativeFocusedWindow() == parentWindow) {
                    // if it is not - skip requesting focus on Solaris
                    // but return true for compatibility.
                    return true;
                } else if (getNativeFocusedWindow() != parentWindow) {
                    WindowPeer wpeer = (WindowPeer)parentWindow.getPeer();
                    boolean res = wpeer.requestWindowFocus();
                    if (focusLog.isLoggable(Level.FINER)) {
                        focusLog.log(Level.FINER, "Requested window focus: " + res);
                    }
                    // If parent window can be made focused and has been made focused(synchronously)
                    // then we can proceed with children, otherwise we retreat.
                    if (!(res && parentWindow.isFocused())) {
                        focusLog.finer("Waiting for asynchronous processing of window focus request");
                        KeyboardFocusManagerPeerImpl.removeLastFocusRequest(target);
                        return false;
                    }
                }
            }
            return _requestFocus(lightweightChild, temporary, focusedWindowChangeAllowed, time, cause);
        }
    }

    native boolean _requestFocus
        (Component lightweightChild, boolean temporary,
         boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause);

    static native Window getNativeFocusedWindow();

    /*
     * Post an event to the event queue.
     */
    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    void postEvent(AWTEvent event) {
        MToolkit.postEvent(MToolkit.targetToAppContext(target), event);
    }

    /* Callbacks for window-system events to the frame
     *
     * NOTE: This method may be called by privileged threads.
     *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
     */
    void handleExpose(int x, int y, int w, int h) {
        if ( !ComponentAccessor.getIgnoreRepaint(target) ) {
            postEvent(new PaintEvent(target, PaintEvent.PAINT,
                                     new Rectangle(x, y, w, h)));
        }
    }

    /* Callbacks for window-system events to the frame
     *
     * NOTE: This method may be called by privileged threads.
     *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
     */
    void handleRepaint(int x, int y, int w, int h) {
        if ( !ComponentAccessor.getIgnoreRepaint(target) ) {
            postEvent(new PaintEvent(target, PaintEvent.UPDATE,
                                     new Rectangle(x, y, w, h)));
        }
    }

    /* Return the component's z-order position relative to
     * other peer'd siblings (don't count lightweight siblings
     * or siblings who don't yet have valid peers).
     *
     * NOTE: This method may be called by privileged threads.
     *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
     */
    public int getZOrderPosition_NoClientCode() {
        // SECURITY: use _NoClientCode() methods, because we may
        //           be running on a privileged thread
        Container p = getParent_NoClientCode(target);
        if (p != null) {
            // SECURITY: use _NoClientCode() methods, because we may
            //           be running on a privileged thread
            Component children[] = getComponents_NoClientCode(p);
            int i;
            int index = 0;
            for (i = 0; i < children.length; i++) {
                if (children[i] == target) {
                    return index;
                } else {
                    Object cpeer = MToolkit.targetToPeer(children[i]);
                    if (cpeer != null &&
                        !(cpeer instanceof java.awt.peer.LightweightPeer)) {
                        index++;
                    }
                }
            }
        }
        return -1;
    }

    /*
     * drawXXX() methods are used to print the native components by
     * rendering the Motif look ourselves.
     * ToDo(aim): needs to query native motif for more accurate color
     * information.
     */
    void draw3DOval(Graphics g, Color bg,
                    int x, int y, int w, int h, boolean raised) {
        Color c = g.getColor();
        Color shadow = bg.darker();
        Color highlight = bg.brighter();

        g.setColor(raised ? highlight : shadow);
        g.drawArc(x, y, w, h, 45, 180);
        g.setColor(raised ? shadow : highlight);
        g.drawArc(x, y, w, h, 225, 180);
        g.setColor(c);
    }
    void draw3DRect(Graphics g, Color bg,
                    int x, int y, int width, int height,
                    boolean raised) {
        Color c = g.getColor();
        Color shadow = bg.darker();
        Color highlight = bg.brighter();

        g.setColor(raised ? highlight : shadow);
        g.drawLine(x, y, x, y + height);
        g.drawLine(x + 1, y, x + width - 1, y);
        g.setColor(raised ? shadow : highlight);
        g.drawLine(x + 1, y + height, x + width, y + height);
        g.drawLine(x + width, y, x + width, y + height - 1);
        g.setColor(c);
    }
    void drawScrollbar(Graphics g, Color bg, int thickness, int length,
                       int min, int max, int val, int vis, boolean horizontal) {
        Color c = g.getColor();
        double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
        int v1 = thickness + (int)(f * (val - min));
        int v2 = (int)(f * vis);
        int w2 = thickness-4;
        int tpts_x[] = new int[3];
        int tpts_y[] = new int[3];

        if (length < 3*w2 ) {
            v1 = v2 = 0;
            if (length < 2*w2 + 2) {
                w2 = (length-2)/2;
            }
        } else  if (v2 < 7) {
            // enforce a minimum handle size
            v1 = Math.max(0, v1 - ((7 - v2)>>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(BufferCapabilities.FlipContents flipAction) {
        if (backBuffer == 0) {
            throw new IllegalStateException("Buffers have not been created");
        }
        graphicsConfig.flip(this, target, xBackBuffer, 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) {
    }

}
TOP

Related Classes of sun.awt.motif.MComponentPeer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.