/*
* @(#)QtWindowPeer.java 1.47 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package sun.awt.qt;
import sun.awt.peer.WindowPeer;
import java.awt.*;
import java.awt.event.*;
/**
* QtWindowPeer.java
*
* @author Indrayana Rustandi
* @author Nicholas Allen
*/
class QtWindowPeer extends QtPanelPeer implements WindowPeer
{
private static native void initIDs();
public native void setActiveNative();
public native void setFocusInWindow(QtComponentPeer toFocus);
// 6182409: Window.pack does not work correctly.
// The winsets object, if set, overwrites the insets object in the
// QtContainerPeer. It is necessary to introduce a different object
// because we are guessing/setting winsets in the peer constructor
// and this conflicts with QtContainerPeer constructor where insets
// is initialized to new Insets(0, 0, 0, 0). If we update super.insets
// instead of winsets, the super.insets gets overwritten at the end.
// See also setInsets() and updateInsets().
protected Insets winsets;
private Rectangle paintRect = null;
static
{
initIDs();
}
QtWindowPeer (QtToolkit toolkit, Window target)
{
super (toolkit, target);
}
protected native void create (QtComponentPeer parentPeer);
public void show()
{
/*
* Fixed (partially) bug 4828042 where the initial splash screen
* (an instance of java.awt.Window) was setMainWidget()'ed.
* We now dictate that only java.awt.Frame can be honored as the
* main widget.
*/
if (this instanceof QtFramePeer) {
toolkit.setMainWidget(this);
}
// bug 6186499 - we need to set the focus in native before showing
// the window. Otherwise, Qt will first focus the frame, then the
// widget that we want to have the focus
Component toFocus = ((Window)target).getMostRecentFocusOwner();
if (toFocus == null)
toFocus = ((Window)target).getFocusTraversalPolicy().getInitialComponent((Window)target);
sun.awt.peer.ComponentPeer peer = QtToolkit.getComponentPeer(toFocus);
if (peer instanceof QtComponentPeer)
setFocusInWindow((QtComponentPeer)peer);
// bug 6186499
super.show();
// 6224133.
// No longer needed.
// toolkit.setRun(true);
// 6224133.
computeInsets(); //6182365
/* Don't call setBounds here - bounds is already set at QtComponentPeer's
constructor, and we don't know the insets of this window right after
the show() anyway. */
//Rectangle bounds = target.getBounds();
//setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
//don't return from this method until we receive notifiation that
//we're actually visible on the screen
}
// 6182409: Window.pack does not work correctly.
// Called from computeInsets() native method impl.
// The 6182365 comment is no longer valid.
/* 6182365. For x86 only. Called from Qt's paint event delivery */
private void restoreBounds() {
Rectangle bounds = target.getBounds();
if (QtComponentPeer.isPacked(target)) {
if (insetsChanged) {
// must obey the interior size constraint of our target.
// Now that we have an accurate insets, update the Java layer
// about the correct target bounds if necessary.
bounds.setSize(bounds.width + getWidthDelta(),
bounds.height + getHeightDelta());
target.setSize(bounds.width, bounds.height);
}
} else {
// Window was NOT packed before show and the insets may or may not
// have changed.
}
// The bounds may have been set correctly by the application before
// target.show(), but we have found out that it is necessary to do
// another peer.setBounds(), followed by, if necessary, the layout
// of the Window so that the window is positioned correctly on the
// screen.
setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
if (insetsChanged) {
target.invalidate();
target.validate();
}
resetInsetsDeltas();
}
// 6182409: Window.pack does not work correctly.
// The follow delta related functions are for pack() to work correctly.
// Subclasses may override them, for example, QtFramePeer.
protected int getWidthDelta() {
return leftBorderDelta + rightBorderDelta;
}
protected int getHeightDelta() {
return topBorderDelta + bottomBorderDelta;
}
protected void resetInsetsDeltas() {
topBorderDelta = leftBorderDelta = bottomBorderDelta = rightBorderDelta = 0;
insetsChanged = false;
}
public native void computeInsets(); //6182365
public native void toFront ();
public native void toBack ();
public native int warningLabelHeight(); //6233632
public native void setResizable(boolean resizable);
/** This is overridden to set the bounds on the window manager's
frame. */
public void setBounds (int x, int y, int w, int h)
{
super.setBounds (x + leftBorder,
y + topBorder,
Math.max (w - leftBorder - rightBorder, 0),
Math.max (h - topBorder - bottomBorder, 0));
}
// Bug 5108647.
// Overrides QtComponentPeer.setBoundsNative() in order to
// check whether this peer is user resizable.
native void setBoundsNative (int x, int y, int width, int height);
public Graphics getGraphics ()
{
Graphics g = super.getGraphics();
if (g != null) {
g.translate(-leftBorder, -topBorder) ;
}
return g;
}
void postMouseEvent (int id, long when, int modifiers, int x,
int y, int clickCount, boolean popupTrigger,
int nativeEvent)
{
super.postMouseEvent (id, when, modifiers, x + leftBorder,
y + topBorder, clickCount,
popupTrigger, nativeEvent);
}
/**
* Called to inform the Frame that its size has changed and it
* should layout its children.
*/
private void postResizedEvent ()
{
QtToolkit.postEvent(new ComponentEvent(target,
ComponentEvent.COMPONENT_RESIZED));
}
private void postMovedEvent ()
{
QtToolkit.postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
}
private void postShownEvent()
{
QtToolkit.postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_SHOWN));
}
protected void postWindowEvent (int type) {
WindowEvent we = new WindowEvent((Window)target, type);
if (type == WindowEvent.WINDOW_ACTIVATED) {
if (!postedActivatedEvent) {
QtToolkit.postEvent(we);
postedActivatedEvent = true;
}
}
else if (type == WindowEvent.WINDOW_DEACTIVATED) {
if (postedActivatedEvent) {
QtToolkit.postEvent(we);
postedActivatedEvent = false;
}
}
else {
QtToolkit.postEvent(we);
}
}
// Bug 6211281
protected void postWindowEvent(AWTEvent event) {
QtToolkit.postEvent(event);
}
// 6182409: Window.pack does not work correctly.
// Overrides QtContainerPeer.getInsets() so that the native layer can
// update the Java window peer about new insets value when they become
// available.
public Insets getInsets()
{
Insets newInsets;
if (winsets != null) {
//6233632
newInsets = new Insets(winsets.top,
winsets.left,
winsets.bottom + warningLabelHeight(),
winsets.right);
return newInsets;
//6233632 return winsets;
} else {
return super.getInsets();
}
}
// 6182409: Window.pack does not work correctly.
/**
* Sets the window peer's insets.
*/
protected void setInsets(Insets newInsets, boolean isInsetsChanged)
{
this.winsets = newInsets;
this.insetsChanged = isInsetsChanged;
}
/** Calculates the insets using any values appropriate (such as borders). */
Insets calculateInsets ()
{
return new Insets (topBorder, leftBorder, bottomBorder, rightBorder);
}
// 6182409: Window.pack does not work correctly.
/**
* Sets this Frame/Dialog's inset values.
* Invoked by the frame/dialog native layer which guesses the borders
* for decorated windows. Pass isInsetsChanged = false.
*/
private void setInsets(int top, int left, int bottom, int right)
{
setInsets(top, left, bottom, right, false);
}
private void setInsets(int top, int left, int bottom, int right, boolean isInsetsChanged)
{
topBorder = top;
leftBorder = left;
bottomBorder = bottom;
rightBorder = right;
setInsets(calculateInsets(), isInsetsChanged);
}
// 6182409: Window.pack does not work correctly.
/**
* Updates this Frame/Dialog's inset values.
* Invoked by the native layer after the window is realized.
*/
protected void updateInsets(int top, int left, int bottom, int right)
{
topBorderDelta = top - topBorder;
leftBorderDelta = left - leftBorder;
bottomBorderDelta = bottom - bottomBorder;
rightBorderDelta = right - rightBorder;
if (topBorderDelta != 0 || leftBorderDelta != 0 ||
rightBorderDelta != 0 && bottomBorderDelta != 0)
{
setInsets(top, left, bottom, right, true);
}
}
static void setQWSCoords (int x, int y)
{
qwsX = x;
qwsY = y;
}
int getOriginX () {return -leftBorder;}
int getOriginY () {return -topBorder;}
int topBorder, leftBorder, bottomBorder, rightBorder;
// 6182409: Window.pack does not work correctly.
// Indicates the deltas for decorations before/after peer.show().
int topBorderDelta, leftBorderDelta, bottomBorderDelta, rightBorderDelta;
// 6182409: Window.pack does not work correctly.
// Indicates whether insets have changed before/after peer.show().
boolean insetsChanged;
static int qwsX, qwsY;
static boolean qwsInit = false;
private boolean postedActivatedEvent;
// 5108404
// Called from the native code with qt-library lock held, so call the
// hide method in the event queue thread
void hideLater() {
EventQueue.invokeLater(new Runnable() {
public void run() {
target.hide() ;
}
});
}
// 5108404
public void setActive() {
if (target.isVisible() && target.isFocusable())
setActiveNative();
}
public void hide() {
// bug 6186499
// if we are the focused window, generate a WINDOW_LOST_FOCUS event
// before hiding ourselves - because Qt won't necessarily do so
if (((Window)target).isFocused())
postWindowEvent(WindowEvent.WINDOW_LOST_FOCUS);
super.hide();
// bug 6186499
}
}