jdk/src/solaris/classes/sun/awt/motif/MWindowPeer.java
changeset 1203 3e5496df0d2b
parent 1202 5a725d2f0daa
parent 1201 e87f9c042699
child 1211 b659a7cee935
equal deleted inserted replaced
1202:5a725d2f0daa 1203:3e5496df0d2b
     1 /*
       
     2  * Copyright 1995-2008 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 package sun.awt.motif;
       
    26 
       
    27 import java.util.Vector;
       
    28 import java.awt.*;
       
    29 import java.awt.peer.*;
       
    30 import java.awt.event.*;
       
    31 import java.awt.image.BufferedImage;
       
    32 import java.awt.image.DataBuffer;
       
    33 import java.awt.image.DataBufferByte;
       
    34 import java.awt.image.DataBufferInt;
       
    35 import java.awt.image.ImageObserver;
       
    36 import sun.awt.image.ImageRepresentation;
       
    37 import sun.awt.motif.MInputMethod;
       
    38 import sun.awt.motif.MInputMethodControl;
       
    39 import sun.awt.im.*;
       
    40 import sun.awt.DisplayChangedListener;
       
    41 import sun.awt.SunToolkit;
       
    42 import sun.awt.X11GraphicsDevice;
       
    43 
       
    44 class MWindowPeer extends MPanelPeer implements WindowPeer,
       
    45 DisplayChangedListener {
       
    46 
       
    47     Insets insets = new Insets( 0, 0, 0, 0 );
       
    48     MWindowAttributes winAttr;
       
    49     static Vector allWindows = new Vector();
       
    50     int         iconWidth  = -1;
       
    51     int         iconHeight = -1;
       
    52 
       
    53     int dropTargetCount = 0;
       
    54     boolean alwaysOnTop;
       
    55 
       
    56     native void pCreate(MComponentPeer parent, String targetClassName, boolean isFocusableWindow);
       
    57     native void pShow();
       
    58     native void pToFront();
       
    59     native void pShowModal(boolean isModal);
       
    60     native void pHide();
       
    61     native void pReshape(int x, int y, int width, int height);
       
    62     native void pDispose();
       
    63     native void pSetTitle(String title);
       
    64     public native void setState(int state);
       
    65     public native int getState();
       
    66 
       
    67     public native void setResizable(boolean resizable);
       
    68     native void addTextComponentNative(MComponentPeer tc);
       
    69     native void removeTextComponentNative();
       
    70     native void pSetIMMOption(String option);
       
    71     native void pSetMenuBar(MMenuBarPeer mbpeer);
       
    72     native void setSaveUnder(boolean state);
       
    73 
       
    74     native void registerX11DropTarget(Component target);
       
    75     native void unregisterX11DropTarget(Component target);
       
    76     native void updateAlwaysOnTop(boolean isAlwaysOnTop);
       
    77 
       
    78     private static native void initIDs();
       
    79 
       
    80     static {
       
    81         initIDs();
       
    82     }
       
    83 
       
    84     // this function is privileged! do not change it to public!
       
    85     private static int getInset(final String name, final int def) {
       
    86         Integer tmp = (Integer) java.security.AccessController.doPrivileged(
       
    87             new sun.security.action.GetIntegerAction(name, def));
       
    88         return tmp.intValue();
       
    89     }
       
    90 
       
    91     MWindowPeer() {
       
    92         insets = new Insets(0,0,0,0);
       
    93         winAttr = new MWindowAttributes();
       
    94     }
       
    95 
       
    96     MWindowPeer(Window target) {
       
    97 
       
    98         this();
       
    99         init(target);
       
   100 
       
   101         allWindows.addElement(this);
       
   102     }
       
   103 
       
   104     void create(MComponentPeer parent) {
       
   105         pCreate(parent, target.getClass().getName(), ((Window)target).isFocusableWindow());
       
   106     }
       
   107 
       
   108     void init( Window target ) {
       
   109         if ( winAttr.nativeDecor == true ) {
       
   110             insets.top = getInset("awt.frame.topInset", -1);
       
   111             insets.left = getInset("awt.frame.leftInset", -1);
       
   112             insets.bottom = getInset("awt.frame.bottomInset", -1);
       
   113             insets.right = getInset("awt.frame.rightInset", -1);
       
   114         }
       
   115 
       
   116         Rectangle bounds = target.getBounds();
       
   117         sysX = bounds.x;
       
   118         sysY = bounds.y;
       
   119         sysW = bounds.width;
       
   120         sysH = bounds.height;
       
   121 
       
   122         super.init(target);
       
   123         InputMethodManager imm = InputMethodManager.getInstance();
       
   124         String menuString = imm.getTriggerMenuString();
       
   125         if (menuString != null)
       
   126         {
       
   127             pSetIMMOption(menuString);
       
   128         }
       
   129         pSetTitle(winAttr.title);
       
   130 
       
   131         /*
       
   132          * For Windows and undecorated Frames and Dialogs this just
       
   133          * disables/enables resizing functions in the system menu.
       
   134          */
       
   135         setResizable(winAttr.isResizable);
       
   136 
       
   137         setSaveUnder(true);
       
   138 
       
   139         Font f = target.getFont();
       
   140         if (f == null) {
       
   141             f = defaultFont;
       
   142             target.setFont(f);
       
   143             setFont(f);
       
   144         }
       
   145         Color c = target.getBackground();
       
   146         if (c == null) {
       
   147             target.setBackground(SystemColor.window);
       
   148             setBackground(SystemColor.window);
       
   149         }
       
   150         c = target.getForeground();
       
   151         if (c == null) {
       
   152             target.setForeground(SystemColor.windowText);
       
   153             setForeground(SystemColor.windowText);
       
   154         }
       
   155         alwaysOnTop = ((Window)target).isAlwaysOnTop() && ((Window)target).isAlwaysOnTopSupported();
       
   156 
       
   157         GraphicsConfiguration gc = getGraphicsConfiguration();
       
   158         ((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
       
   159 
       
   160     }
       
   161 
       
   162     /* Support for multiple icons is not implemented in MAWT */
       
   163     public void updateIconImages() {
       
   164         if (this instanceof MFramePeer) {
       
   165             ((MFramePeer)this).setIconImage(((Frame)target).getIconImage());
       
   166         }
       
   167     }
       
   168 
       
   169 
       
   170     /* Not implemented in MAWT */
       
   171     public void updateMinimumSize() {
       
   172     }
       
   173 
       
   174     protected void disposeImpl() {
       
   175         allWindows.removeElement(this);
       
   176         super.disposeImpl();
       
   177     }
       
   178 
       
   179     public native void toBack();
       
   180 
       
   181     public void setAlwaysOnTop(boolean alwaysOnTop) {
       
   182         this.alwaysOnTop = alwaysOnTop;
       
   183         updateAlwaysOnTop(alwaysOnTop);
       
   184     }
       
   185 
       
   186     public void toFront() {
       
   187         if (target.isVisible()) {
       
   188             updateFocusableWindowState();
       
   189             pToFront();
       
   190         }
       
   191     }
       
   192 
       
   193     public void updateFocusableWindowState() {
       
   194         setFocusableWindow(((Window)target).isFocusableWindow());
       
   195     }
       
   196     native void setFocusableWindow(boolean value);
       
   197 
       
   198     public void setVisible( boolean b ) {
       
   199         if (b) {
       
   200             updateFocusableWindowState();
       
   201         }
       
   202         super.setVisible(b);
       
   203         updateAlwaysOnTop(alwaysOnTop);
       
   204     }
       
   205 
       
   206     public Insets getInsets() {
       
   207         return insets;
       
   208     }
       
   209 
       
   210     public void handleQuit() {
       
   211         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
       
   212     }
       
   213 
       
   214     // XXX: nasty WM, foul play.  spank WM author.
       
   215     public void handleDestroy() {
       
   216         final Window target = (Window)this.target;
       
   217         SunToolkit.executeOnEventHandlerThread(target,
       
   218                                                new Runnable() {
       
   219                                                    public void run() {
       
   220                                                        // This seems like the only reasonable thing we
       
   221                                                        // could do in this situation as the native window
       
   222                                                        // is already dead.
       
   223                                                        target.dispose();
       
   224                                                    }
       
   225                                                });
       
   226     }
       
   227 
       
   228 
       
   229     // NOTE: This method may be called by privileged threads.
       
   230     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   231     public void handleIconify() {
       
   232         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
       
   233     }
       
   234 
       
   235     // NOTE: This method may be called by privileged threads.
       
   236     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   237     public void handleDeiconify() {
       
   238         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
       
   239     }
       
   240 
       
   241     // NOTE: This method may be called by privileged threads.
       
   242     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   243     public void handleStateChange(int oldState, int newState) {
       
   244         postEvent(new WindowEvent((Window)target,
       
   245                                   WindowEvent.WINDOW_STATE_CHANGED,
       
   246                                   oldState, newState));
       
   247     }
       
   248 
       
   249     /**
       
   250      * Called to inform the Window that its size has changed and it
       
   251      * should layout its children.
       
   252      */
       
   253     // NOTE: This method may be called by privileged threads.
       
   254     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   255     public void handleResize(int width, int height) {
       
   256         sysW = width;
       
   257         sysH = height;
       
   258 
       
   259         // REMIND: Is this secure? Can client code subclass input method?
       
   260         if (!tcList.isEmpty() &&
       
   261             !imList.isEmpty()){
       
   262             int i;
       
   263             for (i = 0; i < imList.size(); i++){
       
   264                 ((MInputMethod)imList.elementAt(i)).configureStatus();
       
   265             }
       
   266         }
       
   267         validateSurface(width, height);
       
   268         postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_RESIZED));
       
   269     }
       
   270 
       
   271 
       
   272     /**
       
   273      * DEPRECATED:  Replaced by getInsets().
       
   274      */
       
   275     public Insets insets() {
       
   276         return getInsets();
       
   277     }
       
   278 
       
   279     public void handleMoved(int x, int y) {
       
   280         sysX = x;
       
   281         sysY = y;
       
   282         postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
       
   283     }
       
   284 
       
   285     private native AWTEvent wrapInSequenced(AWTEvent event);
       
   286 
       
   287     // NOTE: This method may be called by privileged threads.
       
   288     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   289     public void handleWindowFocusIn() {
       
   290         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
       
   291         /* wrap in Sequenced, then post*/
       
   292         postEvent(wrapInSequenced((AWTEvent) we));
       
   293     }
       
   294 
       
   295     // NOTE: This method may be called by privileged threads.
       
   296     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   297     public void handleWindowFocusOut(Window oppositeWindow) {
       
   298         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS,
       
   299                                          oppositeWindow);
       
   300         /* wrap in Sequenced, then post*/
       
   301         postEvent(wrapInSequenced((AWTEvent) we));
       
   302     }
       
   303 
       
   304 
       
   305 // relocation of Imm stuff
       
   306     private Vector imList = new Vector();
       
   307     private Vector tcList = new Vector();
       
   308 
       
   309     // NOTE: This method is called by privileged threads.
       
   310     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
       
   311     void notifyIMMOptionChange(){
       
   312 
       
   313         // REMIND: IS THIS SECURE??? CAN USER CODE SUBCLASS INPUTMETHODMGR???
       
   314         InputMethodManager.getInstance().notifyChangeRequest(target);
       
   315     }
       
   316 
       
   317     public void addInputMethod(MInputMethod im) {
       
   318         if (!imList.contains(im))
       
   319             imList.addElement(im);
       
   320     }
       
   321 
       
   322     public void removeInputMethod(MInputMethod im) {
       
   323         if (imList.contains(im))
       
   324             imList.removeElement(im);
       
   325     }
       
   326 
       
   327     public void addTextComponent(MComponentPeer tc) {
       
   328         if (tcList.contains(tc))
       
   329             return;
       
   330         if (tcList.isEmpty()){
       
   331             addTextComponentNative(tc);
       
   332             if (!imList.isEmpty()) {
       
   333                 for (int i = 0; i < imList.size(); i++) {
       
   334                     ((MInputMethod)imList.elementAt(i)).reconfigureXIC((MInputMethodControl)this);
       
   335                 }
       
   336             }
       
   337             MToolkit.executeOnEventHandlerThread(target, new Runnable() {
       
   338                     public void run() {
       
   339                         synchronized(target.getTreeLock()) {
       
   340                             target.doLayout();
       
   341                         }
       
   342                     }
       
   343                 });
       
   344         }
       
   345         tcList.addElement(tc);
       
   346 
       
   347     }
       
   348 
       
   349     public void removeTextComponent(MComponentPeer tc) {
       
   350         if (!tcList.contains(tc))
       
   351             return;
       
   352         tcList.removeElement(tc);
       
   353         if (tcList.isEmpty()){
       
   354             removeTextComponentNative();
       
   355             if (!imList.isEmpty()) {
       
   356                 for (int i = 0; i < imList.size(); i++) {
       
   357                     ((MInputMethod)imList.elementAt(i)).reconfigureXIC((MInputMethodControl)this);
       
   358                 }
       
   359             }
       
   360             target.doLayout();
       
   361         }
       
   362     }
       
   363 
       
   364     public MComponentPeer getTextComponent() {
       
   365         if (!tcList.isEmpty()) {
       
   366             return (MComponentPeer)tcList.firstElement();
       
   367         } else {
       
   368             return null;
       
   369         }
       
   370     }
       
   371 
       
   372     boolean hasDecorations(int decor) {
       
   373         if (!winAttr.nativeDecor) {
       
   374             return false;
       
   375         }
       
   376         else {
       
   377             int myDecor = winAttr.decorations;
       
   378             boolean hasBits = ((myDecor & decor) == decor);
       
   379             if ((myDecor & MWindowAttributes.AWT_DECOR_ALL) != 0)
       
   380                 return !hasBits;
       
   381             else
       
   382                 return hasBits;
       
   383         }
       
   384     }
       
   385 
       
   386     /* Returns the native paint should be posted after setting new size
       
   387      */
       
   388     public boolean checkNativePaintOnSetBounds(int width, int height) {
       
   389         // Fix for 4418155. Window does not repaint
       
   390         // automticaly if shrinking. Should not wait for Expose
       
   391         return (width > oldWidth) || (height > oldHeight);
       
   392     }
       
   393 
       
   394 /* --- DisplayChangedListener Stuff --- */
       
   395 
       
   396     native void resetTargetGC(Component target);
       
   397 
       
   398     /* Xinerama
       
   399      * called to update our GC when dragged onto another screen
       
   400      */
       
   401     public void draggedToNewScreen(int screenNum) {
       
   402         final int finalScreenNum = screenNum;
       
   403 
       
   404         SunToolkit.executeOnEventHandlerThread((Component)target, new Runnable()
       
   405             {
       
   406                 public void run() {
       
   407                     displayChanged(finalScreenNum);
       
   408                 }
       
   409             });
       
   410     }
       
   411 
       
   412     /* Xinerama
       
   413      * called to update our GC when dragged onto another screen
       
   414      */
       
   415     public void displayChanged(int screenNum) {
       
   416         // update our GC
       
   417         resetLocalGC(screenNum);         /* upcall to MCanvasPeer */
       
   418         resetTargetGC(target);           /* call Window.resetGC() via native */
       
   419 
       
   420         //propagate to children
       
   421         super.displayChanged(screenNum); /* upcall to MPanelPeer */
       
   422     }
       
   423 
       
   424     /**
       
   425      * Helper method that executes the displayChanged(screen) method on
       
   426      * the event dispatch thread.  This method is used in the Xinerama case
       
   427      * and after display mode change events.
       
   428      */
       
   429     private void executeDisplayChangedOnEDT(int screenNum) {
       
   430         final int finalScreenNum = screenNum;
       
   431         Runnable dc = new Runnable() {
       
   432             public void run() {
       
   433                 displayChanged(finalScreenNum);
       
   434             }
       
   435         };
       
   436         SunToolkit.executeOnEventHandlerThread((Component)target, dc);
       
   437     }
       
   438 
       
   439     /**
       
   440      * From the DisplayChangedListener interface; called from
       
   441      * X11GraphicsDevice when the display mode has been changed.
       
   442      */
       
   443     public void displayChanged() {
       
   444         GraphicsConfiguration gc = getGraphicsConfiguration();
       
   445         int curScreenNum = ((X11GraphicsDevice)gc.getDevice()).getScreen();
       
   446         executeDisplayChangedOnEDT(curScreenNum);
       
   447     }
       
   448 
       
   449     /**
       
   450      * From the DisplayChangedListener interface; top-levels do not need
       
   451      * to react to this event.
       
   452      */
       
   453     public void paletteChanged() {
       
   454     }
       
   455 
       
   456     public synchronized void addDropTarget() {
       
   457         if (dropTargetCount == 0) {
       
   458             registerX11DropTarget(target);
       
   459         }
       
   460         dropTargetCount++;
       
   461     }
       
   462 
       
   463     public synchronized void removeDropTarget() {
       
   464         dropTargetCount--;
       
   465         if (dropTargetCount == 0) {
       
   466             unregisterX11DropTarget(target);
       
   467         }
       
   468     }
       
   469 
       
   470     protected synchronized void updateDropTarget() {
       
   471         if (dropTargetCount > 0) {
       
   472             unregisterX11DropTarget(target);
       
   473             registerX11DropTarget(target);
       
   474         }
       
   475     }
       
   476 
       
   477     public boolean requestWindowFocus() {
       
   478         return false;
       
   479     }
       
   480 
       
   481     public void setModalBlocked(Dialog blocker, boolean blocked) {
       
   482         // do nothing
       
   483     }
       
   484 
       
   485     public void postUngrabEvent() {
       
   486         postEvent(new sun.awt.UngrabEvent((Window)target));
       
   487     }
       
   488 
       
   489     boolean isOwnerOf(MComponentPeer child) {
       
   490         if (child == null) return false;
       
   491 
       
   492         Component comp = child.target;
       
   493         while (comp != null && !(comp instanceof Window)) {
       
   494             comp = getParent_NoClientCode(comp);
       
   495         }
       
   496         if (!(comp instanceof Window)) {
       
   497             return false;
       
   498         }
       
   499 
       
   500         while (comp != null && !(comp == target) && !(comp instanceof Dialog)) {
       
   501             comp = getParent_NoClientCode(comp);
       
   502         }
       
   503         return (comp == target);
       
   504     }
       
   505 
       
   506     boolean processUngrabMouseEvent(MComponentPeer compPeer, int x_root, int y_root, int type) {
       
   507         switch (type) {
       
   508           case 4: // ButtonPress
       
   509               // Check that the target is the child of the grabbed
       
   510               // window or the child of one of the owned windows of
       
   511               // the grabbed window
       
   512               if (!isOwnerOf(compPeer)) {
       
   513                   postUngrabEvent();
       
   514                   return true;
       
   515               }
       
   516         }
       
   517         return false;
       
   518     }
       
   519 
       
   520     private final boolean hasWarningWindow() {
       
   521         return ((Window)target).getWarningString() != null;
       
   522     }
       
   523 
       
   524     // This method is overriden at Dialog and Frame peers.
       
   525     boolean isTargetUndecorated() {
       
   526         return true;
       
   527     }
       
   528 
       
   529     private volatile int sysX = 0;
       
   530     private volatile int sysY = 0;
       
   531     private volatile int sysW = 0;
       
   532     private volatile int sysH = 0;
       
   533 
       
   534     Rectangle constrainBounds(int x, int y, int width, int height) {
       
   535         // We don't restrict the setBounds() operation if the code is trusted.
       
   536         if (!hasWarningWindow()) {
       
   537             return new Rectangle(x, y, width, height);
       
   538         }
       
   539 
       
   540         int newX = x;
       
   541         int newY = y;
       
   542         int newW = width;
       
   543         int newH = height;
       
   544 
       
   545         GraphicsConfiguration gc = ((Window)target).getGraphicsConfiguration();
       
   546         Rectangle sB = gc.getBounds();
       
   547         Insets sIn = ((Window)target).getToolkit().getScreenInsets(gc);
       
   548 
       
   549         int screenW = sB.width - sIn.left - sIn.right;
       
   550         int screenH = sB.height - sIn.top - sIn.bottom;
       
   551 
       
   552         // If it's undecorated or is not currently visible,
       
   553         // then check each point is within the visible part of the screen
       
   554         if (!target.isVisible() || isTargetUndecorated()) {
       
   555             int screenX = sB.x + sIn.left;
       
   556             int screenY = sB.y + sIn.top;
       
   557 
       
   558             // First make sure the size is withing the visible part of the screen
       
   559             if (newW > screenW) {
       
   560                 newW = screenW;
       
   561             }
       
   562 
       
   563             if (newH > screenH) {
       
   564                 newH = screenH;
       
   565             }
       
   566 
       
   567             // Tweak the location if needed
       
   568             if (newX < screenX) {
       
   569                 newX = screenX;
       
   570             } else if (newX + newW > screenX + screenW) {
       
   571                 newX = screenX + screenW - newW;
       
   572             }
       
   573 
       
   574             if (newY < screenY) {
       
   575                 newY = screenY;
       
   576             } else if (newY + newH > screenY + screenH) {
       
   577                 newY = screenY + screenH - newH;
       
   578             }
       
   579         } else {
       
   580             int maxW = Math.max(screenW, sysW);
       
   581             int maxH = Math.max(screenH, sysH);
       
   582 
       
   583             // Make sure the size is withing the visible part of the screen
       
   584             // OR is less that the current size of the window.
       
   585             if (newW > maxW) {
       
   586                 newW = maxW;
       
   587             }
       
   588 
       
   589             if (newH > maxH) {
       
   590                 newH = maxH;
       
   591             }
       
   592         }
       
   593 
       
   594         return new Rectangle(newX, newY, newW, newH);
       
   595     }
       
   596 
       
   597     public void setBounds(int x, int y, int width, int height, int op) {
       
   598         Rectangle newBounds = constrainBounds(x, y, width, height);
       
   599         super.setBounds(newBounds.x, newBounds.y, newBounds.width, newBounds.height, op);
       
   600     }
       
   601 
       
   602 }