001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Michael Danilov
019: * @version $Revision$
020: */package org.apache.harmony.awt.wtk.linux;
021:
022: import java.awt.Color;
023: import java.awt.Dimension;
024: import java.awt.Frame;
025: import java.awt.Graphics;
026: import java.awt.GraphicsEnvironment;
027: import java.awt.Image;
028: import java.awt.Insets;
029: import java.awt.Point;
030: import java.awt.Rectangle;
031: import java.awt.image.BufferedImage;
032:
033: import org.apache.harmony.awt.gl.MultiRectArea;
034: import org.apache.harmony.awt.gl.Utils;
035: import org.apache.harmony.awt.gl.linux.XVolatileImage;
036: import org.apache.harmony.awt.gl.linux.XGraphicsConfiguration;
037: import org.apache.harmony.awt.nativebridge.CLongPointer;
038: import org.apache.harmony.awt.nativebridge.Int32Pointer;
039: import org.apache.harmony.awt.nativebridge.NativeBridge;
040: import org.apache.harmony.awt.nativebridge.PointerPointer;
041: import org.apache.harmony.awt.nativebridge.VoidPointer;
042: import org.apache.harmony.awt.nativebridge.linux.X11;
043: import org.apache.harmony.awt.nativebridge.linux.X11Defs;
044: import org.apache.harmony.awt.wtk.CreationParams;
045: import org.apache.harmony.awt.wtk.NativeWindow;
046:
047: class LinuxWindow implements NativeWindow {
048:
049: private static final int DEFAULT_MASK = X11Defs.StructureNotifyMask
050: | X11Defs.ExposureMask | X11Defs.FocusChangeMask
051: | X11Defs.KeyPressMask | X11Defs.KeyReleaseMask
052: | X11Defs.ButtonPressMask | X11Defs.ButtonReleaseMask
053: | X11Defs.PointerMotionMask | X11Defs.OwnerGrabButtonMask
054: | X11Defs.LeaveWindowMask | X11Defs.EnterWindowMask
055: | X11Defs.PropertyChangeMask;
056:
057: private static final int DISABLED_MASK = X11Defs.ExposureMask
058: | X11Defs.StructureNotifyMask | X11Defs.PropertyChangeMask
059: | X11Defs.FocusChangeMask;
060:
061: private static final int MOUSE_GRAB_MASK = X11Defs.PointerMotionMask
062: | X11Defs.ButtonPressMask | X11Defs.ButtonReleaseMask;
063:
064: private final static Insets DEFAULT_INSETS = new Insets(25, 5, 5, 5); // initial "guessed" insets
065:
066: // Window size limits
067: public final static int MIN_WINDOW_WIDTH = 1;
068: public final static int MAX_WINDOW_WIDTH = Short.MAX_VALUE;
069: public final static int MIN_WINDOW_HEIGHT = 1;
070: public final static int MAX_WINDOW_HEIGHT = Short.MAX_VALUE;
071:
072: static boolean manualGrabActive = false;
073: static boolean autoGrabActive = false;
074: static LinuxWindow grabWindow = null;
075:
076: private final boolean child;
077:
078: private final long display;
079:
080: private final long windowID;
081:
082: private long parentID;
083:
084: private boolean visible;
085:
086: private boolean enabled;
087:
088: private boolean resizable;
089:
090: private boolean popup;
091:
092: private Dimension requestedSize;
093:
094: private Rectangle windowRect;
095:
096: private static final X11 x11 = X11.getInstance();
097: private static final NativeBridge bridge = NativeBridge
098: .getInstance();
099:
100: private final LinuxWindowFactory factory;
101:
102: private final WindowManager wm;
103:
104: boolean moved, resized;
105:
106: private boolean iconified = false;
107: private boolean maximized = false;
108: private int currentState = 0;
109: boolean alwaysOnTop = false;
110:
111: Insets savedInsets = new Insets(0, 0, 0, 0);
112:
113: private boolean undecorated = true;
114:
115: private boolean focusable = true;
116:
117: private Insets oldInsets;
118:
119: private boolean packed;
120:
121: private ContentWindow contentWindow;
122:
123: private boolean insetsChanged;
124:
125: LinuxWindow(LinuxWindowFactory factory, CreationParams p) {
126:
127: display = factory.getDisplay();
128: visible = p.visible;
129: enabled = !p.disabled;
130: resizable = p.resizable;
131: this .factory = factory;
132: wm = factory.wm;
133: child = p.child;
134: popup = (p.decorType == CreationParams.DECOR_TYPE_POPUP);
135: undecorated = (p.decorType == CreationParams.DECOR_TYPE_UNDECOR)
136: || p.undecorated || popup;
137: if (p.maximizedState == p.MAXIMIZED) {
138: currentState |= Frame.MAXIMIZED_BOTH;
139: }
140: if (p.iconified) {
141: currentState |= Frame.ICONIFIED;
142: }
143:
144: parentID = p.child ? p.parentId : x11
145: .XDefaultRootWindow(display);
146: long ownerID = p.child ? 0 : p.parentId;
147: //X can't create windows with zero size
148: p.w = adjustedWidth(p.w);
149: p.h = adjustedHeight(p.h);
150: if (child) {
151: windowRect = new Rectangle(p.x, p.y, p.w, p.h);
152: }
153:
154: XGraphicsConfiguration xgcfg = (XGraphicsConfiguration) GraphicsEnvironment
155: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
156: .getDefaultConfiguration();
157:
158: X11.XSetWindowAttributes setAttrs = x11
159: .createXSetWindowAttributes(false);
160: setAttrs.set_colormap(xgcfg.getXColormap());
161:
162: windowID = x11.XCreateWindow(display, parentID, p.x, p.y, p.w,
163: p.h, 0, xgcfg.getDepth(), X11Defs.InputOutput, xgcfg
164: .getVisual(), (long) (X11Defs.CWColormap),
165: setAttrs);
166:
167: /*
168: windowID = x11.XCreateWindow(display, parentID, p.x, p.y, p.w, p.h, 0,
169: X11Defs.CopyFromParent,
170: X11Defs.InputOutput,
171: X11Defs.CopyFromParent, 0, 0);
172: */
173: String title = (p.name != null) ? p.name : ""; //$NON-NLS-1$
174: x11.Xutf8SetWMProperties(display, windowID, title, title, null,
175: 0, null, null, null);
176: x11.XSelectInput(display, windowID, enabled ? DEFAULT_MASK
177: : DISABLED_MASK);
178:
179: if (!popup) {
180: if (!child && ownerID != 0) {
181: x11.XSetTransientForHint(display, windowID, ownerID);
182: }
183: wm.setDecorType(windowID, p.decorType, p.undecorated);
184: wm.setInputAllowed(windowID, !p.disabled);
185: wm.setWMProtocols(windowID);
186: } else {
187: setPopupAttributes();
188: }
189:
190: if (child) {
191: //windowRect = new Rectangle(p.x, p.y, p.w, p.h);
192: x11.XLowerWindow(display, windowID);
193: } else {
194: if (!popup) {
195: wm.setResizableHint(windowID, resizable, p.x, p.y, p.w,
196: p.h);
197: // Override the window position set by Window Manager
198: windowRect = new Rectangle(0, 0, p.w, p.h);
199: setBounds(p.x, p.y, p.w, p.h, 0);
200: } else {
201: windowRect = new Rectangle(p.x, p.y, p.w, p.h);
202: }
203: //A Client whose window has not yet been mapped can request of the
204: //Window Manager an estimate of the frame extents it will be given
205: //upon mapping
206: if (!child && !undecorated) {
207: savedInsets = DEFAULT_INSETS;
208: wm.requestFrameExtents(windowID);
209: }
210: x11.XRaiseWindow(display, windowID);
211: }
212: if (visible) {
213: x11.XMapWindow(display, windowID);
214: }
215: }
216:
217: // for EmbeddedWindow
218: LinuxWindow(long nativeWindowId, LinuxWindowFactory factory) {
219:
220: this .factory = factory;
221: windowID = nativeWindowId;
222: display = factory.getDisplay();
223: visible = true;
224: enabled = true;
225: resizable = false;
226: undecorated = true;
227: wm = factory.wm;
228: child = true;
229: popup = false;
230: }
231:
232: public void setVisible(boolean v) {
233: if (visible != v) {
234: visible = v;
235: if (visible) {
236: if (!isChild()) {
237: // update state hints before the window is mapped:
238: // wm removes the property upon window withdrawal
239: setState(currentState);
240: setAlwaysOnTop(alwaysOnTop);
241: }
242: x11.XMapWindow(display, windowID);
243: } else {
244: x11.XWithdrawWindow(display, windowID, factory
245: .getScreen());
246: }
247: }
248: x11.XFlush(display);
249: }
250:
251: public long getId() {
252: return windowID;
253: }
254:
255: Rectangle onBoundsChange(Rectangle newBounds) {
256:
257: moved = resized = false;
258: Rectangle oldRect = (Rectangle) windowRect.clone();
259:
260: windowRect.setBounds(newBounds);
261:
262: if (!resizable && requestedSize != null
263: && newBounds.width == requestedSize.width
264: && newBounds.height == requestedSize.height) {
265: wm.setResizableHint(windowID, false, newBounds.x,
266: newBounds.y, newBounds.width, newBounds.height);
267: requestedSize = null;
268: }
269: Point loc = windowRect.getLocation(), oldLoc = oldRect
270: .getLocation();
271: if (!loc.equals(oldLoc)) {
272: moved = true;
273: }
274: Dimension size = windowRect.getSize(), oldSize = oldRect
275: .getSize();
276: if (!size.equals(oldSize)) {
277: resized = true;
278: }
279: return oldRect;
280: }
281:
282: public void setBounds(int x, int y, int w, int h, int boundsMask) {
283:
284: int newWidth = adjustedWidth(w);
285: int newHeight = adjustedHeight(h);
286:
287: windowRect = getBounds(); // TODO: check if windowRect field can be removed
288: boolean willMove = (x != windowRect.x || y != windowRect.y)
289: && (boundsMask & BOUNDS_NOMOVE) == 0;
290: boolean willResize = (newWidth != windowRect.width || newHeight != windowRect.height)
291: && (boundsMask & BOUNDS_NOSIZE) == 0;
292:
293: if (!willMove && !willResize) {
294: return;
295: }
296:
297: toFront();
298:
299: if (willMove) {
300: x11.XMoveWindow(display, windowID, x, y);
301: }
302: if (willResize) {
303: // if (!resizable) {
304: requestedSize = new Dimension(newWidth, newHeight);
305: // }
306: int wasOverrideRedirect = -1;
307: if (!child && !resizable) {
308: // allow program(not user) resizing of a non-resizable window
309: X11.XWindowAttributes winAttr = x11
310: .createXWindowAttributes(false);
311: x11.XGetWindowAttributes(display, windowID, winAttr);
312: wasOverrideRedirect = winAttr.get_override_redirect();
313: setOverrideRedirect(1);
314: }
315: x11.XResizeWindow(display, windowID, newWidth, newHeight);
316:
317: if (wasOverrideRedirect >= 0) {
318: setOverrideRedirect(wasOverrideRedirect);
319: }
320:
321: }
322:
323: x11.XFlush(display);
324: }
325:
326: private void setOverrideRedirect(int on) {
327: X11.XSetWindowAttributes winAttr = x11
328: .createXSetWindowAttributes(true);
329: winAttr.set_override_redirect(on);
330: long mask = X11Defs.CWOverrideRedirect;
331: x11.XChangeWindowAttributes(display, windowID, mask, winAttr);
332: }
333:
334: /**
335: * Query window size and position from X server
336: */
337: public Rectangle getBounds() {
338: Int32Pointer x = bridge.createInt32Pointer(1, false);
339: Int32Pointer y = bridge.createInt32Pointer(1, false);
340: Int32Pointer w = bridge.createInt32Pointer(1, false);
341: Int32Pointer h = bridge.createInt32Pointer(1, false);
342: CLongPointer root = bridge.createCLongPointer(1, false);
343: Int32Pointer border = bridge.createInt32Pointer(1, false);
344: Int32Pointer depth = bridge.createInt32Pointer(1, false);
345:
346: x11.XGetGeometry(display, windowID, root, x, y, w, h, border,
347: depth);
348: long rootID = root.get(0);
349: if (!child || (this instanceof ContentWindow)) {
350: CLongPointer childWindow = bridge.createCLongPointer(1,
351: false);
352: x11.XTranslateCoordinates(display, getParentID(), rootID, x
353: .get(0), y.get(0), x, y, childWindow);
354: }
355: Rectangle r = new Rectangle(x.get(0), y.get(0), w.get(0), h
356: .get(0));
357:
358: return r;
359: }
360:
361: public Insets updateInsets() {
362: Insets insets = new Insets(0, 0, 0, 0);
363: if (!child && !undecorated) {
364: Int32Pointer x = bridge.createInt32Pointer(1, false);
365: Int32Pointer y = bridge.createInt32Pointer(1, false);
366: Int32Pointer w = bridge.createInt32Pointer(1, false);
367: Int32Pointer h = bridge.createInt32Pointer(1, false);
368: CLongPointer root = bridge.createCLongPointer(1, false);
369: Int32Pointer border = bridge.createInt32Pointer(1, false);
370: Int32Pointer depth = bridge.createInt32Pointer(1, false);
371:
372: x11.XGetGeometry(display, windowID, root, x, y, w, h,
373: border, depth);
374: long rootID = root.get(0);
375: long frameID = getFrameID(windowID, rootID);
376:
377: if (frameID != 0 && frameID != rootID && parentID == rootID) {
378: int width = w.get(0), height = h.get(0);
379: CLongPointer childWindow = bridge.createCLongPointer(1,
380: false);
381:
382: //get window coordinates relative to WM's frame
383: x11.XTranslateCoordinates(display, getParentID(),
384: frameID, x.get(0), y.get(0), x, y, childWindow);
385: insets.top = y.get(0);
386: insets.left = x.get(0);
387: x11.XGetGeometry(display, frameID, root, x, y, w, h,
388: border, depth);
389: int frameW = w.get(0);
390: int frameH = h.get(0);
391: insets.right = frameW - width - insets.left;
392: insets.bottom = frameH - height - insets.top;
393: } else {
394: // Suggested insets, just to have some
395: insets.top = 25;
396: insets.bottom = insets.left = insets.right = 5;
397: }
398: }
399: setInsets(insets);
400: return (Insets) insets.clone();
401: }
402:
403: public Insets getInsets() {
404: return (Insets) savedInsets.clone();
405: }
406:
407: public void setEnabled(boolean value) {
408: if (enabled != value) {
409: enabled = value;
410: x11.XSelectInput(display, windowID, enabled ? DEFAULT_MASK
411: : DISABLED_MASK);
412: setInputAllowed(value);
413: }
414: x11.XFlush(display);
415: }
416:
417: public void dispose() {
418: factory.onWindowDispose(windowID);
419: x11.XDestroyWindow(display, windowID);
420: x11.XFlush(display);
421: }
422:
423: public void placeAfter(NativeWindow w) {
424: if (w == null) {
425: toFront();
426: return;
427: }
428: CLongPointer params = bridge.createCLongPointer(2, false);
429: params.set(0, w.getId());
430: params.set(1, windowID);
431: x11.XRestackWindows(display, params, 2);
432: x11.XFlush(display);
433: }
434:
435: public void toFront() {
436: x11.XRaiseWindow(display, windowID);
437: x11.XFlush(display);
438: }
439:
440: public void toBack() {
441: x11.XLowerWindow(display, windowID);
442: x11.XFlush(display);
443: }
444:
445: Point queryPointer() {
446: CLongPointer rootReturned = bridge.createCLongPointer(1, false);
447: CLongPointer childReturned = bridge
448: .createCLongPointer(1, false);
449: Int32Pointer rootX = bridge.createInt32Pointer(1, false);
450: Int32Pointer rootY = bridge.createInt32Pointer(1, false);
451: Int32Pointer windowX = bridge.createInt32Pointer(1, false);
452: Int32Pointer windowY = bridge.createInt32Pointer(1, false);
453: Int32Pointer mask = bridge.createInt32Pointer(1, false);
454:
455: x11.XQueryPointer(display, windowID, rootReturned,
456: childReturned, rootX, rootY, windowX, windowY, mask);
457:
458: return new Point(windowX.get(0), windowY.get(0));
459: }
460:
461: public boolean setFocus(boolean focus) {
462:
463: if (!isFocusable()) {
464: return false;
465: }
466: // avoid focus request loops:
467: if (wm.getFocusedWindow() == getId()) {
468: return true;
469: }
470:
471: boolean isViewable = (getMapState() == X11Defs.IsViewable);
472: // try to set input focus only if window is mapped
473: // [and all ancestor windows are mapped]
474: // , clear focus otherwise
475: boolean setFocus = isViewable && focus;
476: long id = setFocus ? windowID : X11Defs.None;
477:
478: x11.XSetInputFocus(display, id, X11Defs.RevertToParent,
479: X11Defs.CurrentTime);
480:
481: x11.XFlush(display);
482: return setFocus;
483: }
484:
485: int getMapState() {
486: X11.XWindowAttributes winAttr = x11
487: .createXWindowAttributes(false);
488: x11.XGetWindowAttributes(display, windowID, winAttr);
489:
490: return winAttr.get_map_state();
491: }
492:
493: public void setTitle(String title) {
494: if (title == null) {
495: title = ""; //$NON-NLS-1$
496: }
497: x11.Xutf8SetWMProperties(display, windowID, title, title, null,
498: 0, null, null, null);
499: x11.XFlush(display);
500: }
501:
502: public void setResizable(boolean value) {
503: if (value != resizable) {
504: resizable = value;
505: wm.setResizableHint(windowID, resizable, windowRect.x,
506: windowRect.y, requestedSize.width,
507: requestedSize.height);
508: }
509: x11.XFlush(display);
510: }
511:
512: /**
513: * Start manual mouse grab
514: */
515: public void grabMouse() {
516: manualGrabActive = true;
517: grabWindow = this ;
518:
519: x11.XGrabPointer(display, windowID, X11Defs.True,
520: MOUSE_GRAB_MASK, X11Defs.GrabModeAsync,
521: X11Defs.GrabModeAsync, X11Defs.None, X11Defs.None,
522: X11Defs.CurrentTime);
523: x11.XFlush(display);
524: }
525:
526: /**
527: * End manual mouse grab. If automatic grab is still active,
528: * the ungrab is postponed until all mouse buttons are released.
529: */
530: public void ungrabMouse() {
531: manualGrabActive = false;
532:
533: if (!autoGrabActive) {
534: ungrabMouseImpl();
535: }
536: }
537:
538: /**
539: * Actually end the mouse grab
540: */
541: private void ungrabMouseImpl() {
542: x11.XUngrabPointer(display, X11Defs.CurrentTime);
543: x11.XFlush(display);
544:
545: grabWindow = null;
546: }
547:
548: /**
549: * Notify that mouse button was pressed. If there was no manual grab
550: * the automatic mouse grab is activated implicitly. Cancel manual grab
551: * if it was active and mouse was clicked outside of application windows
552: *
553: * @param winId - window that got the event
554: * @param x - x mouse position in window coordinates
555: * @param y - x mouse position in window coordinates
556: * @return false if explicit grab was canceled; true otherwise
557: */
558: static boolean startAutoGrab(long winId, int x, int y) {
559: // If the click was outside of any LinuxWindow it was reported to grabWindow
560: if (grabWindow != null && grabWindow.getId() == winId
561: && !grabWindow.isInside(winId, x, y)) {
562:
563: autoGrabActive = false;
564: grabWindow.ungrabMouseImpl();
565: return false;
566: }
567:
568: autoGrabActive = true;
569: return true;
570: }
571:
572: /**
573: * Notify that all mouse buttons were released and automatic grab has to be ended.
574: * If the manual ungrab was postponed, do it now.
575: */
576: static void endAutoGrab() {
577: autoGrabActive = false;
578: if (!manualGrabActive && grabWindow != null) {
579: grabWindow.ungrabMouseImpl();
580: }
581: }
582:
583: private boolean isInside(long winId, int x, int y) {
584: return (winId == windowID && x >= 0 && x < windowRect.width
585: && y >= 0 && y < windowRect.height);
586: }
587:
588: private void setPopupAttributes() {
589: X11.XSetWindowAttributes winAttr = x11
590: .createXSetWindowAttributes(false);
591: winAttr.set_override_redirect(1);
592: winAttr.set_save_under(1);
593: long mask = X11Defs.CWOverrideRedirect | X11Defs.CWSaveUnder;
594: x11.XChangeWindowAttributes(display, windowID, mask, winAttr);
595: }
596:
597: boolean isInputAllowed() {
598: return wm.isInputAllowed(windowID);
599: }
600:
601: void setInputAllowed(boolean value) {
602: wm.setInputAllowed(windowID, value);
603: }
604:
605: boolean isChild() {
606: return child;
607: }
608:
609: static final int adjustedWidth(int width) {
610: return Math.min(Math.max(MIN_WINDOW_WIDTH, width),
611: MAX_WINDOW_WIDTH);
612: }
613:
614: static final int adjustedHeight(int height) {
615: return Math.min(Math.max(MIN_WINDOW_HEIGHT, height),
616: MAX_WINDOW_HEIGHT);
617: }
618:
619: public void setFocusable(boolean value) {
620: setInputAllowed(value);
621: focusable = value;
622: }
623:
624: public boolean isFocusable() {
625: return focusable;//isInputAllowed();
626: }
627:
628: /**
629: * @return actual native parent of a window
630: * (for a top-level this maybe a WM frame window)
631: */
632: long getParentID() {
633: return getParentID(windowID);
634: }
635:
636: long getFrameID() {
637: return getFrameID(windowID, factory.getRootWindow());
638: }
639:
640: /**
641: * @return actual native parent of a window
642: * (for a top-level this maybe a WM frame window)
643: */
644: private long getParentID(long windowID) {
645: if (windowID == 0) {
646: return 0;
647: }
648:
649: CLongPointer root = bridge.createCLongPointer(1, false);
650: CLongPointer parent = bridge.createCLongPointer(1, false);
651: PointerPointer children = bridge.createPointerPointer(1, true);
652: Int32Pointer count = bridge.createInt32Pointer(1, false);
653:
654: if (x11.XQueryTree(display, windowID, root, parent, children,
655: count) != 0) {
656: final VoidPointer data = children.get(0);
657:
658: if (data != null) {
659: x11.XFree(data);
660: }
661:
662: return parent.get(0);
663: }
664:
665: return 0;
666: }
667:
668: private long getFrameID(long windowId, long rootID) {
669: long frameID = getParentID(windowId);
670:
671: if (frameID != 0 && frameID != rootID) {
672:
673: while (getParentID(frameID) != rootID) {
674: frameID = getParentID(frameID);
675: }
676:
677: }
678: return frameID != rootID ? frameID : 0;
679: }
680:
681: /**
682: * @return display of the current window
683: */
684: long getDisplay() {
685: return display;
686: }
687:
688: /**
689: * @return saved requested window bounds
690: */
691: Rectangle getWindowRect() {
692: return windowRect;
693: }
694:
695: LinuxWindow getParent() {
696: if (factory.validWindowId(parentID)) {
697: return (LinuxWindow) factory.getWindowById(parentID);
698: }
699: return null;
700: }
701:
702: boolean isIconified() {
703: return iconified;
704: }
705:
706: private int setBits(int n, int bits, boolean set) {
707: return (set ? (n | bits) : (n & ~bits));
708: }
709:
710: void setIconified(boolean iconified) {
711: this .iconified = iconified;
712: currentState = setBits(currentState, Frame.ICONIFIED, iconified);
713: }
714:
715: void setMaximized(boolean maximized) {
716: this .maximized = maximized;
717: currentState = setBits(currentState, Frame.MAXIMIZED_BOTH,
718: maximized);
719: }
720:
721: boolean isMaximized() {
722: return maximized;
723: }
724:
725: int getState() {
726: int state = 0;
727:
728: if (maximized) {
729: state |= Frame.MAXIMIZED_BOTH;
730: }
731: if (iconified) {
732: state |= Frame.ICONIFIED;
733: }
734:
735: return state;
736: }
737:
738: int getCurrentState() {
739: return currentState;
740: }
741:
742: public void setState(int state) {
743: currentState = state;
744: if (iconified) {
745: if ((state & Frame.ICONIFIED) == 0) {
746: x11.XMapRaised(display, windowID);
747: }
748: } else {
749: if ((state & Frame.ICONIFIED) > 0) {
750: x11.XIconifyWindow(display, windowID, factory
751: .getScreen());
752: }
753: }
754:
755: if ((maximized && ((state & Frame.MAXIMIZED_BOTH) == 0))
756: || (!maximized && ((state & Frame.MAXIMIZED_BOTH) > 0))) {
757: long[] states = new long[] {
758: wm.NET_WM_STATE_MAXIMIZED_HORZ,
759: wm.NET_WM_STATE_MAXIMIZED_VERT };
760: wm.changeWindowState(this , maximized ? 0 : 1, states);
761: }
762: x11.XFlush(display);
763: }
764:
765: /**
766: * @see org.apache.harmony.awt.wtk.NativeWindow#setIconImage(java.awt.Image)
767: */
768: public void setIconImage(Image image) {
769: long pixmap = 0;
770: if (image != null) {
771: BufferedImage bufImg = Utils.getBufferedImage(image);
772: if (bufImg == null) {
773: return;
774: }
775: pixmap = createPixmap(image);
776: }
777: wm.setIcon(windowID, pixmap, 0);
778: }
779:
780: private long createPixmap(Image image) {
781: int w = image.getWidth(null);
782: int h = image.getHeight(null);
783: XVolatileImage xvi = (XVolatileImage) GraphicsEnvironment
784: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
785: .getDefaultConfiguration()
786: .createCompatibleVolatileImage(w, h);
787: Graphics g = xvi.getGraphics();
788: g.setColor(Color.lightGray);
789: g.fillRect(0, 0, w, h);
790: g.drawImage(image, 0, 0, null);
791: g.dispose();
792: return xvi.getPixmap();
793: }
794:
795: /**
796: * @see org.apache.harmony.awt.wtk.NativeWindow#setMaximizedBounds(java.awt.Rectangle)
797: */
798: public void setMaximizedBounds(Rectangle bounds) {
799: final int MAX = Integer.MAX_VALUE;
800: if (bounds == null) {
801: return;
802: }
803: int w = bounds.width;
804: int h = bounds.height;
805: int screen = factory.getScreen();
806:
807: if (w == MAX) {
808: w = x11.XDisplayWidth(display, screen);
809: }
810:
811: if (h == MAX) {
812: h = x11.XDisplayHeight(display, screen);
813: }
814: //TODO: call adjustRect(bounds, 0, -1) to decrease requested from WM
815: //size on insets size
816: wm.setResizableHint(windowID, true, true, bounds.x, bounds.y,
817: w, h);
818:
819: }
820:
821: boolean isUndecorated() {
822: return undecorated;
823: }
824:
825: /**
826: * @see org.apache.harmony.awt.wtk.NativeWindow#getScreenPos()
827: */
828: public Point getScreenPos() {
829:
830: Int32Pointer x = bridge.createInt32Pointer(1, false);
831: Int32Pointer y = bridge.createInt32Pointer(1, false);
832: Int32Pointer w = bridge.createInt32Pointer(1, false);
833: Int32Pointer h = bridge.createInt32Pointer(1, false);
834: CLongPointer root = bridge.createCLongPointer(1, false);
835: Int32Pointer border = bridge.createInt32Pointer(1, false);
836: Int32Pointer depth = bridge.createInt32Pointer(1, false);
837:
838: x11.XGetGeometry(display, windowID, root, x, y, w, h, border,
839: depth);
840: long rootID = root.get(0);
841:
842: CLongPointer childWindow = bridge.createCLongPointer(1, false);
843: x11.XTranslateCoordinates(display, getParentID(), rootID, x
844: .get(0), y.get(0), x, y, childWindow);
845:
846: Point pos = new Point(x.get(0), y.get(0));
847: return pos;
848: }
849:
850: /**
851: * @see org.apache.harmony.awt.wtk.NativeWindow#setAlwaysOnTop(boolean)
852: */
853: public void setAlwaysOnTop(boolean value) {
854: wm.changeWindowState(this , value ? 1 : 0,
855: new long[] { wm.NET_WM_STATE_ABOVE,
856: wm.NET_WM_STATE_STAYS_ON_TOP, 0l });
857: alwaysOnTop = value;
858:
859: }
860:
861: void setInsets(Insets newInsets) {
862: if ((newInsets == null) || newInsets.equals(savedInsets)) {
863: return;
864: }
865: oldInsets = (insetsChanged ? savedInsets : new Insets(0, 0, 0,
866: 0));
867: insetsChanged = true;
868: savedInsets = (Insets) newInsets.clone();
869:
870: if (contentWindow != null) {
871: // Rectangle contentRect = contentWindow.getBounds();
872: x11.XMoveWindow(getDisplay(), contentWindow.getId(),
873: -newInsets.left, -newInsets.top);
874:
875: Rectangle rect = getBounds();
876:
877: int dx = savedInsets.left - oldInsets.left;
878: int dy = savedInsets.top - oldInsets.top;
879: int dw = dx + (savedInsets.right - oldInsets.right);
880: int dh = dy + (savedInsets.bottom - oldInsets.bottom);
881:
882: if (contentWindow.isPacked()) {
883: // don't adjust client area size if
884: // the window is packed
885: int w = adjustedWidth(/*contentRect*/rect.width + dw);
886: int h = adjustedHeight(/*contentRect*/rect.height + dh);
887: x11.XResizeWindow(display, contentWindow.getId(), w, h);
888: contentWindow.setPacked(false);
889: } else {
890: // adjust client area size to match
891: // new insets
892: int newWidth = adjustedWidth(rect.width - dw);
893: int newHeight = adjustedHeight(rect.height - dh);
894: // update WM hints to resize "frame" window
895: wm.setResizableHint(windowID, resizable, rect.x,
896: rect.y, newWidth, newHeight);
897: x11.XResizeWindow(display, windowID, newWidth,
898: newHeight);
899: }
900:
901: x11.XFlush(display);
902:
903: }
904: }
905:
906: /**
907: * @return Returns the contentWindow.
908: */
909: ContentWindow getContentWindow() {
910: return contentWindow;
911: }
912:
913: /**
914: * @param contentWindow The contentWindow to set.
915: */
916: void setContentWindow(ContentWindow contentWindow) {
917: this .contentWindow = contentWindow;
918: }
919:
920: /**
921: * @see org.apache.harmony.awt.wtk.NativeWindow#setPacked(boolean)
922: */
923: public void setPacked(boolean packed) {
924: this .packed = true;
925: }
926:
927: /**
928: * @return Returns the packed flag.
929: */
930: boolean isPacked() {
931: return packed;
932: }
933:
934: public MultiRectArea getObscuredRegion(Rectangle part) {
935: return null;
936: }
937:
938: public void setIMStyle() {
939: }
940: }
|