001: /*
002: * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.awt.motif;
026:
027: import java.util.Vector;
028: import java.awt.*;
029: import java.awt.peer.*;
030: import java.awt.event.*;
031: import java.awt.image.BufferedImage;
032: import java.awt.image.DataBuffer;
033: import java.awt.image.DataBufferByte;
034: import java.awt.image.DataBufferInt;
035: import java.awt.image.ImageObserver;
036: import sun.awt.image.ImageRepresentation;
037: import sun.awt.motif.MInputMethod;
038: import sun.awt.motif.MInputMethodControl;
039: import sun.awt.im.*;
040: import sun.awt.DisplayChangedListener;
041: import sun.awt.SunToolkit;
042: import sun.awt.X11GraphicsDevice;
043:
044: class MWindowPeer extends MPanelPeer implements WindowPeer,
045: DisplayChangedListener {
046:
047: Insets insets = new Insets(0, 0, 0, 0);
048: MWindowAttributes winAttr;
049: static Vector allWindows = new Vector();
050: int iconWidth = -1;
051: int iconHeight = -1;
052:
053: int dropTargetCount = 0;
054: boolean alwaysOnTop;
055:
056: native void pCreate(MComponentPeer parent, String targetClassName,
057: boolean isFocusableWindow);
058:
059: native void pShow();
060:
061: native void pToFront();
062:
063: native void pShowModal(boolean isModal);
064:
065: native void pHide();
066:
067: native void pReshape(int x, int y, int width, int height);
068:
069: native void pDispose();
070:
071: native void pSetTitle(String title);
072:
073: public native void setState(int state);
074:
075: public native int getState();
076:
077: public native void setResizable(boolean resizable);
078:
079: native void addTextComponentNative(MComponentPeer tc);
080:
081: native void removeTextComponentNative();
082:
083: native void pSetIMMOption(String option);
084:
085: native void pSetMenuBar(MMenuBarPeer mbpeer);
086:
087: native void setSaveUnder(boolean state);
088:
089: native void registerX11DropTarget(Component target);
090:
091: native void unregisterX11DropTarget(Component target);
092:
093: native void updateAlwaysOnTop(boolean isAlwaysOnTop);
094:
095: private static native void initIDs();
096:
097: static {
098: initIDs();
099: }
100:
101: // this function is privileged! do not change it to public!
102: private static int getInset(final String name, final int def) {
103: Integer tmp = (Integer) java.security.AccessController
104: .doPrivileged(new sun.security.action.GetIntegerAction(
105: name, def));
106: return tmp.intValue();
107: }
108:
109: MWindowPeer() {
110: insets = new Insets(0, 0, 0, 0);
111: winAttr = new MWindowAttributes();
112: }
113:
114: MWindowPeer(Window target) {
115:
116: this ();
117: init(target);
118:
119: allWindows.addElement(this );
120: }
121:
122: void create(MComponentPeer parent) {
123: pCreate(parent, target.getClass().getName(), ((Window) target)
124: .isFocusableWindow());
125: }
126:
127: void init(Window target) {
128: if (winAttr.nativeDecor == true) {
129: insets.top = getInset("awt.frame.topInset", -1);
130: insets.left = getInset("awt.frame.leftInset", -1);
131: insets.bottom = getInset("awt.frame.bottomInset", -1);
132: insets.right = getInset("awt.frame.rightInset", -1);
133: }
134:
135: super .init(target);
136: InputMethodManager imm = InputMethodManager.getInstance();
137: String menuString = imm.getTriggerMenuString();
138: if (menuString != null) {
139: pSetIMMOption(menuString);
140: }
141: pSetTitle(winAttr.title);
142:
143: /*
144: * For Windows and undecorated Frames and Dialogs this just
145: * disables/enables resizing functions in the system menu.
146: */
147: setResizable(winAttr.isResizable);
148:
149: setSaveUnder(true);
150:
151: Font f = target.getFont();
152: if (f == null) {
153: f = defaultFont;
154: target.setFont(f);
155: setFont(f);
156: }
157: Color c = target.getBackground();
158: if (c == null) {
159: target.setBackground(SystemColor.window);
160: setBackground(SystemColor.window);
161: }
162: c = target.getForeground();
163: if (c == null) {
164: target.setForeground(SystemColor.windowText);
165: setForeground(SystemColor.windowText);
166: }
167: alwaysOnTop = ((Window) target).isAlwaysOnTop()
168: && ((Window) target).isAlwaysOnTopSupported();
169:
170: GraphicsConfiguration gc = getGraphicsConfiguration();
171: ((X11GraphicsDevice) gc.getDevice())
172: .addDisplayChangedListener(this );
173: }
174:
175: /* Support for multiple icons is not implemented in MAWT */
176: public void updateIconImages() {
177: if (this instanceof MFramePeer) {
178: ((MFramePeer) this ).setIconImage(((Frame) target)
179: .getIconImage());
180: }
181: }
182:
183: /* Not implemented in MAWT */
184: public void updateMinimumSize() {
185: }
186:
187: protected void disposeImpl() {
188: allWindows.removeElement(this );
189: super .disposeImpl();
190: }
191:
192: public native void toBack();
193:
194: public void setAlwaysOnTop(boolean alwaysOnTop) {
195: this .alwaysOnTop = alwaysOnTop;
196: updateAlwaysOnTop(alwaysOnTop);
197: }
198:
199: public void toFront() {
200: if (target.isVisible()) {
201: updateFocusableWindowState();
202: pToFront();
203: }
204: }
205:
206: public void updateFocusableWindowState() {
207: setFocusableWindow(((Window) target).isFocusableWindow());
208: }
209:
210: native void setFocusableWindow(boolean value);
211:
212: public void setVisible(boolean b) {
213: if (b) {
214: updateFocusableWindowState();
215: }
216: super .setVisible(b);
217: updateAlwaysOnTop(alwaysOnTop);
218: }
219:
220: public Insets getInsets() {
221: return insets;
222: }
223:
224: public void handleQuit() {
225: postEvent(new WindowEvent((Window) target,
226: WindowEvent.WINDOW_CLOSING));
227: }
228:
229: // XXX: nasty WM, foul play. spank WM author.
230: public void handleDestroy() {
231: final Window target = (Window) this .target;
232: SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
233: public void run() {
234: // This seems like the only reasonable thing we
235: // could do in this situation as the native window
236: // is already dead.
237: target.dispose();
238: }
239: });
240: }
241:
242: // NOTE: This method may be called by privileged threads.
243: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
244: public void handleIconify() {
245: postEvent(new WindowEvent((Window) target,
246: WindowEvent.WINDOW_ICONIFIED));
247: }
248:
249: // NOTE: This method may be called by privileged threads.
250: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
251: public void handleDeiconify() {
252: postEvent(new WindowEvent((Window) target,
253: WindowEvent.WINDOW_DEICONIFIED));
254: }
255:
256: // NOTE: This method may be called by privileged threads.
257: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
258: public void handleStateChange(int oldState, int newState) {
259: postEvent(new WindowEvent((Window) target,
260: WindowEvent.WINDOW_STATE_CHANGED, oldState, newState));
261: }
262:
263: /**
264: * Called to inform the Window that its size has changed and it
265: * should layout its children.
266: */
267: // NOTE: This method may be called by privileged threads.
268: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
269: public void handleResize(int width, int height) {
270:
271: // REMIND: Is this secure? Can client code subclass input method?
272: if (!tcList.isEmpty() && !imList.isEmpty()) {
273: int i;
274: for (i = 0; i < imList.size(); i++) {
275: ((MInputMethod) imList.elementAt(i)).configureStatus();
276: }
277: }
278: validateSurface(width, height);
279: postEvent(new ComponentEvent(target,
280: ComponentEvent.COMPONENT_RESIZED));
281: }
282:
283: /**
284: * DEPRECATED: Replaced by getInsets().
285: */
286: public Insets insets() {
287: return getInsets();
288: }
289:
290: public void handleMoved(int x, int y) {
291: postEvent(new ComponentEvent(target,
292: ComponentEvent.COMPONENT_MOVED));
293: }
294:
295: private native AWTEvent wrapInSequenced(AWTEvent event);
296:
297: // NOTE: This method may be called by privileged threads.
298: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
299: public void handleWindowFocusIn() {
300: WindowEvent we = new WindowEvent((Window) target,
301: WindowEvent.WINDOW_GAINED_FOCUS);
302: /* wrap in Sequenced, then post*/
303: postEvent(wrapInSequenced((AWTEvent) we));
304: }
305:
306: // NOTE: This method may be called by privileged threads.
307: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
308: public void handleWindowFocusOut(Window oppositeWindow) {
309: WindowEvent we = new WindowEvent((Window) target,
310: WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
311: /* wrap in Sequenced, then post*/
312: postEvent(wrapInSequenced((AWTEvent) we));
313: }
314:
315: // relocation of Imm stuff
316: private Vector imList = new Vector();
317: private Vector tcList = new Vector();
318:
319: // NOTE: This method is called by privileged threads.
320: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
321: void notifyIMMOptionChange() {
322:
323: // REMIND: IS THIS SECURE??? CAN USER CODE SUBCLASS INPUTMETHODMGR???
324: InputMethodManager.getInstance().notifyChangeRequest(target);
325: }
326:
327: public void addInputMethod(MInputMethod im) {
328: if (!imList.contains(im))
329: imList.addElement(im);
330: }
331:
332: public void removeInputMethod(MInputMethod im) {
333: if (imList.contains(im))
334: imList.removeElement(im);
335: }
336:
337: public void addTextComponent(MComponentPeer tc) {
338: if (tcList.contains(tc))
339: return;
340: if (tcList.isEmpty()) {
341: addTextComponentNative(tc);
342: if (!imList.isEmpty()) {
343: for (int i = 0; i < imList.size(); i++) {
344: ((MInputMethod) imList.elementAt(i))
345: .reconfigureXIC((MInputMethodControl) this );
346: }
347: }
348: MToolkit.executeOnEventHandlerThread(target,
349: new Runnable() {
350: public void run() {
351: synchronized (target.getTreeLock()) {
352: target.doLayout();
353: }
354: }
355: });
356: }
357: tcList.addElement(tc);
358:
359: }
360:
361: public void removeTextComponent(MComponentPeer tc) {
362: if (!tcList.contains(tc))
363: return;
364: tcList.removeElement(tc);
365: if (tcList.isEmpty()) {
366: removeTextComponentNative();
367: if (!imList.isEmpty()) {
368: for (int i = 0; i < imList.size(); i++) {
369: ((MInputMethod) imList.elementAt(i))
370: .reconfigureXIC((MInputMethodControl) this );
371: }
372: }
373: target.doLayout();
374: }
375: }
376:
377: public MComponentPeer getTextComponent() {
378: if (!tcList.isEmpty()) {
379: return (MComponentPeer) tcList.firstElement();
380: } else {
381: return null;
382: }
383: }
384:
385: boolean hasDecorations(int decor) {
386: if (!winAttr.nativeDecor) {
387: return false;
388: } else {
389: int myDecor = winAttr.decorations;
390: boolean hasBits = ((myDecor & decor) == decor);
391: if ((myDecor & MWindowAttributes.AWT_DECOR_ALL) != 0)
392: return !hasBits;
393: else
394: return hasBits;
395: }
396: }
397:
398: /* Returns the native paint should be posted after setting new size
399: */
400: public boolean checkNativePaintOnSetBounds(int width, int height) {
401: // Fix for 4418155. Window does not repaint
402: // automticaly if shrinking. Should not wait for Expose
403: return (width > oldWidth) || (height > oldHeight);
404: }
405:
406: /* --- DisplayChangedListener Stuff --- */
407:
408: native void resetTargetGC(Component target);
409:
410: /* Xinerama
411: * called to update our GC when dragged onto another screen
412: */
413: public void draggedToNewScreen(int screenNum) {
414: final int finalScreenNum = screenNum;
415:
416: SunToolkit.executeOnEventHandlerThread((Component) target,
417: new Runnable() {
418: public void run() {
419: displayChanged(finalScreenNum);
420: }
421: });
422: }
423:
424: /* Xinerama
425: * called to update our GC when dragged onto another screen
426: */
427: public void displayChanged(int screenNum) {
428: // update our GC
429: resetLocalGC(screenNum); /* upcall to MCanvasPeer */
430: resetTargetGC(target); /* call Window.resetGC() via native */
431:
432: //propagate to children
433: super .displayChanged(screenNum); /* upcall to MPanelPeer */
434: }
435:
436: /**
437: * Helper method that executes the displayChanged(screen) method on
438: * the event dispatch thread. This method is used in the Xinerama case
439: * and after display mode change events.
440: */
441: private void executeDisplayChangedOnEDT(int screenNum) {
442: final int finalScreenNum = screenNum;
443: Runnable dc = new Runnable() {
444: public void run() {
445: displayChanged(finalScreenNum);
446: }
447: };
448: SunToolkit.executeOnEventHandlerThread((Component) target, dc);
449: }
450:
451: /**
452: * From the DisplayChangedListener interface; called from
453: * X11GraphicsDevice when the display mode has been changed.
454: */
455: public void displayChanged() {
456: GraphicsConfiguration gc = getGraphicsConfiguration();
457: int curScreenNum = ((X11GraphicsDevice) gc.getDevice())
458: .getScreen();
459: executeDisplayChangedOnEDT(curScreenNum);
460: }
461:
462: /**
463: * From the DisplayChangedListener interface; top-levels do not need
464: * to react to this event.
465: */
466: public void paletteChanged() {
467: }
468:
469: public synchronized void addDropTarget() {
470: if (dropTargetCount == 0) {
471: registerX11DropTarget(target);
472: }
473: dropTargetCount++;
474: }
475:
476: public synchronized void removeDropTarget() {
477: dropTargetCount--;
478: if (dropTargetCount == 0) {
479: unregisterX11DropTarget(target);
480: }
481: }
482:
483: protected synchronized void updateDropTarget() {
484: if (dropTargetCount > 0) {
485: unregisterX11DropTarget(target);
486: registerX11DropTarget(target);
487: }
488: }
489:
490: public boolean requestWindowFocus() {
491: return false;
492: }
493:
494: public void setModalBlocked(Dialog blocker, boolean blocked) {
495: // do nothing
496: }
497:
498: public void postUngrabEvent() {
499: postEvent(new sun.awt.UngrabEvent((Window) target));
500: }
501:
502: boolean isOwnerOf(MComponentPeer child) {
503: if (child == null)
504: return false;
505:
506: Component comp = child.target;
507: while (comp != null && !(comp instanceof Window)) {
508: comp = getParent_NoClientCode(comp);
509: }
510: if (!(comp instanceof Window)) {
511: return false;
512: }
513:
514: while (comp != null && !(comp == target)
515: && !(comp instanceof Dialog)) {
516: comp = getParent_NoClientCode(comp);
517: }
518: return (comp == target);
519: }
520:
521: boolean processUngrabMouseEvent(MComponentPeer compPeer,
522: int x_root, int y_root, int type) {
523: switch (type) {
524: case 4: // ButtonPress
525: // Check that the target is the child of the grabbed
526: // window or the child of one of the owned windows of
527: // the grabbed window
528: if (!isOwnerOf(compPeer)) {
529: postUngrabEvent();
530: return true;
531: }
532: }
533: return false;
534: }
535: }
|