Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11/XContentWindow.java
41159 views
/*1* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.awt.X11;2526import java.awt.Component;27import java.awt.Rectangle;28import java.awt.Insets;2930import java.awt.event.ComponentEvent;3132import sun.util.logging.PlatformLogger;3334import sun.awt.AWTAccessor;3536/**37* This class implements window which serves as content window for decorated frames.38* Its purpose to provide correct events dispatching for the complex39* constructs such as decorated frames.40*41* It should always be located at (- left inset, - top inset) in the associated42* decorated window. So coordinates in it would be the same as java coordinates.43*/44public final class XContentWindow extends XWindow {45private static PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XContentWindow");4647static XContentWindow createContent(XDecoratedPeer parentFrame) {48final WindowDimensions dims = parentFrame.getDimensions();49Rectangle rec = dims.getBounds();50// Fix for - set the location of the content window to the (-left inset, -top inset)51Insets ins = dims.getInsets();52if (ins != null) {53rec.x = -ins.left;54rec.y = -ins.top;55} else {56rec.x = 0;57rec.y = 0;58}59final XContentWindow cw = new XContentWindow(parentFrame, rec);60cw.xSetVisible(true);61return cw;62}6364private final XDecoratedPeer parentFrame;6566// A list of expose events that come when the parentFrame is iconified67private final java.util.List<SavedExposeEvent> iconifiedExposeEvents =68new java.util.ArrayList<SavedExposeEvent>();6970private XContentWindow(XDecoratedPeer parentFrame, Rectangle bounds) {71super((Component)parentFrame.getTarget(), parentFrame.getShell(), bounds);72this.parentFrame = parentFrame;73}7475void preInit(XCreateWindowParams params) {76super.preInit(params);77params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity));78Long eventMask = (Long)params.get(EVENT_MASK);79if (eventMask != null) {80eventMask = eventMask & ~(XConstants.StructureNotifyMask);81params.put(EVENT_MASK, eventMask);82}83}8485protected String getWMName() {86return "Content window";87}88protected boolean isEventDisabled(XEvent e) {89switch (e.get_type()) {90// Override parentFrame to receive MouseEnter/Exit91case XConstants.EnterNotify:92case XConstants.LeaveNotify:93return false;94// We handle ConfigureNotify specifically in XDecoratedPeer95case XConstants.ConfigureNotify:96return true;97// We don't want SHOWN/HIDDEN on content window since it will duplicate XDecoratedPeer98case XConstants.MapNotify:99case XConstants.UnmapNotify:100return true;101default:102return super.isEventDisabled(e) || parentFrame.isEventDisabled(e);103}104}105106// Coordinates are that of the shell107void setContentBounds(WindowDimensions dims) {108XToolkit.awtLock();109try {110// Bounds of content window are of the same size as bounds of Java window and with111// location as -(insets)112Rectangle newBounds = dims.getBounds();113Insets in = dims.getInsets();114if (in != null) {115newBounds.setLocation(-in.left, -in.top);116}117if (insLog.isLoggable(PlatformLogger.Level.FINE)) {118insLog.fine("Setting content bounds {0}, old bounds {1}",119newBounds, getBounds());120}121// Fix for 5023533:122// Change in the size of the content window means, well, change of the size123// Change in the location of the content window means change in insets124boolean needHandleResize = !(newBounds.equals(getBounds()));125boolean needPaint = width <= 0 || height <= 0;126reshape(newBounds);127if (needHandleResize) {128insLog.fine("Sending RESIZED");129handleResize(newBounds);130}131if (needPaint) {132postPaintEvent(target, 0, 0, newBounds.width, newBounds.height);133}134} finally {135XToolkit.awtUnlock();136}137}138139@Override140public void handleExposeEvent(XEvent xev) {141if(parentFrame.isTargetUndecorated() &&142XWM.getWMID() != XWM.UNITY_COMPIZ_WM &&143width <= 0 && height <= 0) {144// WM didn't send initial ConfigureNotify, so set the bounds here145setContentBounds(parentFrame.getDimensions());146}147if (width <= 0 || height <= 0) {148return;149}150super.handleExposeEvent(xev);151}152153// NOTE: This method may be called by privileged threads.154// DO NOT INVOKE CLIENT CODE ON THIS THREAD!155public void handleResize(Rectangle bounds) {156AWTAccessor.getComponentAccessor().setSize(target, bounds.width, bounds.height);157postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_RESIZED));158}159160161public void postPaintEvent(Component target, int x, int y, int w, int h) {162// TODO: ?163// get rid of 'istanceof' by subclassing:164// XContentWindow -> XFrameContentWindow165166// Expose event(s) that result from deiconification167// come before a deicinofication notification.168// We reorder these events by saving all expose events169// that come when the frame is iconified. Then we170// actually handle saved expose events on deiconification.171172if (parentFrame instanceof XFramePeer &&173(((XFramePeer)parentFrame).getState() & java.awt.Frame.ICONIFIED) != 0) {174// Save expose events if the frame is iconified175// in order to handle them on deiconification.176iconifiedExposeEvents.add(new SavedExposeEvent(target, x, y, w, h));177} else {178// Normal case: [it is not a frame or] the frame is not iconified.179super.postPaintEvent(target, x, y, w, h);180}181}182183void purgeIconifiedExposeEvents() {184for (SavedExposeEvent evt : iconifiedExposeEvents) {185super.postPaintEvent(evt.target, evt.x, evt.y, evt.w, evt.h);186}187iconifiedExposeEvents.clear();188}189190private static class SavedExposeEvent {191Component target;192int x, y, w, h;193SavedExposeEvent(Component target, int x, int y, int w, int h) {194this.target = target;195this.x = x;196this.y = y;197this.w = w;198this.h = h;199}200}201202public String toString() {203return getClass().getName() + "[" + getBounds() + "]";204}205}206207208