61 }
62
63 public long getShell() {
64 return window;
65 }
66
67 public long getContentWindow() {
68 return (content == null) ? window : content.getWindow();
69 }
70
71 void preInit(XCreateWindowParams params) {
72 super.preInit(params);
73 winAttr.initialFocus = true;
74
75 currentInsets = new Insets(0,0,0,0);
76 applyGuessedInsets();
77
78 Rectangle bounds = (Rectangle)params.get(BOUNDS);
79 dimensions = new WindowDimensions(bounds, getRealInsets(), false);
80 params.put(BOUNDS, dimensions.getClientRect());
81 if (insLog.isLoggable(PlatformLogger.FINE)) {
82 insLog.fine("Initial dimensions {0}", dimensions);
83 }
84
85 // Deny default processing of these events on the shell - proxy will take care of
86 // them instead
87 Long eventMask = (Long)params.get(EVENT_MASK);
88 params.add(EVENT_MASK, Long.valueOf(eventMask.longValue() & ~(XConstants.FocusChangeMask | XConstants.KeyPressMask | XConstants.KeyReleaseMask)));
89 }
90
91 void postInit(XCreateWindowParams params) {
92 // The size hints must be set BEFORE mapping the window (see 6895647)
93 updateSizeHints(dimensions);
94
95 // The super method maps the window if it's visible on the shared level
96 super.postInit(params);
97
98 // The lines that follow need to be in a postInit, so they
99 // happen after the X window is created.
100 initResizability();
101 XWM.requestWMExtents(getWindow());
164 XFocusProxyWindow createFocusProxy() {
165 return new XFocusProxyWindow(this);
166 }
167
168 protected XAtomList getWMProtocols() {
169 XAtomList protocols = super.getWMProtocols();
170 protocols.add(wm_delete_window);
171 protocols.add(wm_take_focus);
172 return protocols;
173 }
174
175 public Graphics getGraphics() {
176 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
177 return getGraphics(content.surfaceData,
178 compAccessor.getForeground(target),
179 compAccessor.getBackground(target),
180 compAccessor.getFont(target));
181 }
182
183 public void setTitle(String title) {
184 if (log.isLoggable(PlatformLogger.FINE)) {
185 log.fine("Title is " + title);
186 }
187 winAttr.title = title;
188 updateWMName();
189 }
190
191 protected String getWMName() {
192 if (winAttr.title == null || winAttr.title.trim().equals("")) {
193 return " ";
194 } else {
195 return winAttr.title;
196 }
197 }
198
199 void updateWMName() {
200 super.updateWMName();
201 String name = getWMName();
202 XToolkit.awtLock();
203 try {
204 if (name == null || name.trim().equals("")) {
214 }
215
216 // NOTE: This method may be called by privileged threads.
217 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
218 public void handleIconify() {
219 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
220 }
221
222 // NOTE: This method may be called by privileged threads.
223 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
224 public void handleDeiconify() {
225 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
226 }
227
228 public void handleFocusEvent(XEvent xev) {
229 super.handleFocusEvent(xev);
230 XFocusChangeEvent xfe = xev.get_xfocus();
231
232 // If we somehow received focus events forward it instead to proxy
233 // FIXME: Shouldn't we instead check for inferrior?
234 if (focusLog.isLoggable(PlatformLogger.FINER)) {
235 focusLog.finer("Received focus event on shell: " + xfe);
236 }
237 // focusProxy.xRequestFocus();
238 }
239
240 /***************************************************************************************
241 * I N S E T S C O D E
242 **************************************************************************************/
243
244 protected boolean isInitialReshape() {
245 return false;
246 }
247
248 private static Insets difference(Insets i1, Insets i2) {
249 return new Insets(i1.top-i2.top, i1.left - i2.left, i1.bottom-i2.bottom, i1.right-i2.right);
250 }
251
252 private static boolean isNull(Insets i) {
253 return (i == null) || ((i.left | i.top | i.right | i.bottom) == 0);
254 }
258 }
259
260 // insets which we get from WM (e.g from _NET_FRAME_EXTENTS)
261 private Insets wm_set_insets;
262
263 private Insets getWMSetInsets(XAtom changedAtom) {
264 if (isEmbedded()) {
265 return null;
266 }
267
268 if (wm_set_insets != null) {
269 return wm_set_insets;
270 }
271
272 if (changedAtom == null) {
273 wm_set_insets = XWM.getInsetsFromExtents(getWindow());
274 } else {
275 wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
276 }
277
278 if (insLog.isLoggable(PlatformLogger.FINER)) {
279 insLog.finer("FRAME_EXTENTS: {0}", wm_set_insets);
280 }
281
282 if (wm_set_insets != null) {
283 wm_set_insets = copy(wm_set_insets);
284 }
285 return wm_set_insets;
286 }
287
288 private void resetWMSetInsets() {
289 wm_set_insets = null;
290 }
291
292 public void handlePropertyNotify(XEvent xev) {
293 super.handlePropertyNotify(xev);
294
295 XPropertyEvent ev = xev.get_xproperty();
296 if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
297 || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
298 {
299 getWMSetInsets(XAtom.get(ev.get_atom()));
300 }
301 }
302
303 long reparent_serial = 0;
304
305 public void handleReparentNotifyEvent(XEvent xev) {
306 XReparentEvent xe = xev.get_xreparent();
307 if (insLog.isLoggable(PlatformLogger.FINE)) {
308 insLog.fine(xe.toString());
309 }
310 reparent_serial = xe.get_serial();
311 XToolkit.awtLock();
312 try {
313 long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
314
315 if (isEmbedded()) {
316 setReparented(true);
317 insets_corrected = true;
318 return;
319 }
320 Component t = (Component)target;
321 if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
322 setReparented(true);
323 insets_corrected = true;
324 reshape(dimensions, SET_SIZE, false);
325 } else if (xe.get_parent() == root) {
326 configure_seen = false;
327 insets_corrected = false;
328
329 /*
330 * We can be repareted to root for two reasons:
331 * . setVisible(false)
332 * . WM exited
333 */
334 if (isVisible()) { /* WM exited */
335 /* Work around 4775545 */
336 XWM.getWM().unshadeKludge(this);
337 insLog.fine("- WM exited");
338 } else {
339 insLog.fine(" - reparent due to hide");
340 }
341 } else { /* reparented to WM frame, figure out our insets */
342 setReparented(true);
343 insets_corrected = false;
344
345 // Check if we have insets provided by the WM
346 Insets correctWM = getWMSetInsets(null);
347 if (correctWM != null) {
348 if (insLog.isLoggable(PlatformLogger.FINER)) {
349 insLog.finer("wm-provided insets {0}", correctWM);
350 }
351 // If these insets are equal to our current insets - no actions are necessary
352 Insets dimInsets = dimensions.getInsets();
353 if (correctWM.equals(dimInsets)) {
354 insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
355 no_reparent_artifacts = true;
356 insets_corrected = true;
357 applyGuessedInsets();
358 return;
359 }
360 } else {
361 correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
362
363 if (insLog.isLoggable(PlatformLogger.FINER)) {
364 if (correctWM != null) {
365 insLog.finer("correctWM {0}", correctWM);
366 } else {
367 insLog.finer("correctWM insets are not available, waiting for configureNotify");
368 }
369 }
370 }
371
372 if (correctWM != null) {
373 handleCorrectInsets(correctWM);
374 }
375 }
376 } finally {
377 XToolkit.awtUnlock();
378 }
379 }
380
381 protected void handleCorrectInsets(Insets correctWM) {
382 XToolkit.awtLock();
383 try {
384 /*
385 * Ok, now see if we need adjust window size because
386 * initial insets were wrong (most likely they were).
387 */
388 Insets correction = difference(correctWM, currentInsets);
389 if (insLog.isLoggable(PlatformLogger.FINEST)) {
390 insLog.finest("Corrention {0}", correction);
391 }
392 if (!isNull(correction)) {
393 currentInsets = copy(correctWM);
394 applyGuessedInsets();
395
396 //Fix for 6318109: PIT: Min Size is not honored properly when a
397 //smaller size is specified in setSize(), XToolkit
398 //update minimum size hints
399 updateMinSizeHints();
400 }
401 if (insLog.isLoggable(PlatformLogger.FINER)) {
402 insLog.finer("Dimensions before reparent: " + dimensions);
403 }
404
405 dimensions.setInsets(getRealInsets());
406 insets_corrected = true;
407
408 if (isMaximized()) {
409 return;
410 }
411
412 /*
413 * If this window has been sized by a pack() we need
414 * to keep the interior geometry intact. Since pack()
415 * computed width and height with wrong insets, we
416 * must adjust the target dimensions appropriately.
417 */
418 if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
419 reshape(dimensions, SET_BOUNDS, false);
420 } else {
421 reshape(dimensions, SET_SIZE, false);
456
457 public void revalidate() {
458 XToolkit.executeOnEventHandlerThread(target, new Runnable() {
459 public void run() {
460 target.invalidate();
461 target.validate();
462 }
463 });
464 }
465
466 Insets getRealInsets() {
467 if (isNull(currentInsets)) {
468 applyGuessedInsets();
469 }
470 return currentInsets;
471 }
472
473 public Insets getInsets() {
474 Insets in = copy(getRealInsets());
475 in.top += getMenuBarHeight();
476 if (insLog.isLoggable(PlatformLogger.FINEST)) {
477 insLog.finest("Get insets returns {0}", in);
478 }
479 return in;
480 }
481
482 boolean gravityBug() {
483 return XWM.configureGravityBuggy();
484 }
485
486 // The height of area used to display current active input method
487 int getInputMethodHeight() {
488 return 0;
489 }
490
491 void updateSizeHints(WindowDimensions dims) {
492 Rectangle rec = dims.getClientRect();
493 checkShellRect(rec);
494 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
495 }
496
497 void updateSizeHints() {
498 updateSizeHints(dimensions);
499 }
500
501 // Coordinates are that of the target
502 // Called only on Toolkit thread
503 public void reshape(WindowDimensions newDimensions, int op,
504 boolean userReshape)
505 {
506 if (insLog.isLoggable(PlatformLogger.FINE)) {
507 insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
508 }
509 if (userReshape) {
510 // We handle only userReshape == true cases. It means that
511 // if the window manager or any other part of the windowing
512 // system sets inappropriate size for this window, we can
513 // do nothing but accept it.
514 Rectangle newBounds = newDimensions.getBounds();
515 Insets insets = newDimensions.getInsets();
516 // Inherit isClientSizeSet from newDimensions
517 if (newDimensions.isClientSizeSet()) {
518 newBounds = new Rectangle(newBounds.x, newBounds.y,
519 newBounds.width - insets.left - insets.right,
520 newBounds.height - insets.top - insets.bottom);
521 }
522 newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
523 }
524 XToolkit.awtLock();
525 try {
526 if (!isReparented() || !isVisible()) {
527 if (insLog.isLoggable(PlatformLogger.FINE)) {
528 insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
529 Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
530 }
531
532 // Fix for 6323293.
533 // This actually is needed to preserve compatibility with previous releases -
534 // some of licensees are expecting componentMoved event on invisible one while
535 // its location changes.
536 Point oldLocation = getLocation();
537
538 Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX((Component)target),
539 AWTAccessor.getComponentAccessor().getY((Component)target));
540
541 if (!newLocation.equals(oldLocation)) {
542 handleMoved(newDimensions);
543 }
544
545 dimensions = new WindowDimensions(newDimensions);
546 updateSizeHints(dimensions);
547 Rectangle client = dimensions.getClientRect();
615 break;
616 case SET_SIZE:
617 // Set size sets bounds size. However, until the window is mapped we
618 // should use client coordinates
619 dims.setSize(width, height);
620 break;
621 case SET_CLIENT_SIZE: {
622 // Sets client rect size. Width and height contain insets.
623 Insets in = currentInsets;
624 width -= in.left+in.right;
625 height -= in.top+in.bottom;
626 dims.setClientSize(width, height);
627 break;
628 }
629 case SET_BOUNDS:
630 default:
631 dims.setLocation(x, y);
632 dims.setSize(width, height);
633 break;
634 }
635 if (insLog.isLoggable(PlatformLogger.FINE)) {
636 insLog.fine("For the operation {0} new dimensions are {1}",
637 operationToString(operation), dims);
638 }
639
640 reshape(dims, operation, userReshape);
641 }
642
643 // This method gets overriden in XFramePeer & XDialogPeer.
644 abstract boolean isTargetUndecorated();
645
646 /**
647 * @see java.awt.peer.ComponentPeer#setBounds
648 */
649 public void setBounds(int x, int y, int width, int height, int op) {
650 // TODO: Rewrite with WindowDimensions
651 reshape(x, y, width, height, op, true);
652 validateSurface();
653 }
654
655 // Coordinates are that of the shell
656 void reconfigureContentWindow(WindowDimensions dims) {
657 if (content == null) {
658 insLog.fine("WARNING: Content window is null");
659 return;
660 }
661 content.setContentBounds(dims);
662 }
663
664 boolean no_reparent_artifacts = false;
665 public void handleConfigureNotifyEvent(XEvent xev) {
666 assert (SunToolkit.isAWTLockHeldByCurrentThread());
667 XConfigureEvent xe = xev.get_xconfigure();
668 if (insLog.isLoggable(PlatformLogger.FINE)) {
669 insLog.fine("Configure notify {0}", xe);
670 }
671
672 // XXX: should really only consider synthetic events, but
673 if (isReparented()) {
674 configure_seen = true;
675 }
676
677 if (!isMaximized()
678 && (xe.get_serial() == reparent_serial || xe.get_window() != getShell())
679 && !no_reparent_artifacts)
680 {
681 insLog.fine("- reparent artifact, skipping");
682 return;
683 }
684 no_reparent_artifacts = false;
685
686 /**
687 * When there is a WM we receive some CN before being visible and after.
688 * We should skip all CN which are before being visible, because we assume
689 * the gravity is in action while it is not yet.
690 *
691 * When there is no WM we receive CN only _before_ being visible.
692 * We should process these CNs.
693 */
694 if (!isVisible() && XWM.getWMID() != XWM.NO_WM) {
695 insLog.fine(" - not visible, skipping");
696 return;
697 }
698
699 /*
700 * Some window managers configure before we are reparented and
701 * the send event flag is set! ugh... (Enlighetenment for one,
702 * possibly MWM as well). If we haven't been reparented yet
703 * this is just the WM shuffling us into position. Ignore
704 * it!!!! or we wind up in a bogus location.
705 */
706 int runningWM = XWM.getWMID();
707 if (insLog.isLoggable(PlatformLogger.FINE)) {
708 insLog.fine("reparented={0}, visible={1}, WM={2}, decorations={3}",
709 isReparented(), isVisible(), runningWM, getDecorations());
710 }
711 if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
712 && !XWM.isNonReparentingWM()
713 && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
714 insLog.fine("- visible but not reparented, skipping");
715 return;
716 }
717 //Last chance to correct insets
718 if (!insets_corrected && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
719 long parent = XlibUtil.getParentWindow(window);
720 Insets correctWM = (parent != -1) ? XWM.getWM().getInsets(this, window, parent) : null;
721 if (insLog.isLoggable(PlatformLogger.FINER)) {
722 if (correctWM != null) {
723 insLog.finer("Configure notify - insets : " + correctWM);
724 } else {
725 insLog.finer("Configure notify - insets are still not available");
726 }
727 }
728 if (correctWM != null) {
729 handleCorrectInsets(correctWM);
730 } else {
731 //Only one attempt to correct insets is made (to lower risk)
732 //if insets are still not available we simply set the flag
733 insets_corrected = true;
734 }
735 }
736
737 updateChildrenSizes();
738
739 // Bounds of the window
740 Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds((Component)target);
741
742 Point newLocation = targetBounds.getLocation();
743 if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
744 // Location, Client size + insets
745 newLocation = new Point(xe.get_x() - currentInsets.left, xe.get_y() - currentInsets.top);
746 } else {
747 // ICCCM 4.1.5 states that a real ConfigureNotify will be sent when
748 // a window is resized but the client can not tell if the window was
749 // moved or not. The client should consider the position as unkown
750 // and use TranslateCoordinates to find the actual position.
751 //
752 // TODO this should be the default for every case.
753 switch (XWM.getWMID()) {
754 case XWM.CDE_WM:
755 case XWM.MOTIF_WM:
756 case XWM.METACITY_WM:
757 case XWM.MUTTER_WM:
758 case XWM.SAWFISH_WM:
759 {
760 Point xlocation = queryXLocation();
761 if (log.isLoggable(PlatformLogger.FINE)) {
762 log.fine("New X location: {0}", xlocation);
763 }
764 if (xlocation != null) {
765 newLocation = xlocation;
766 }
767 break;
768 }
769 default:
770 break;
771 }
772 }
773
774 WindowDimensions newDimensions =
775 new WindowDimensions(newLocation,
776 new Dimension(xe.get_width(), xe.get_height()),
777 copy(currentInsets),
778 true);
779
780 if (insLog.isLoggable(PlatformLogger.FINER)) {
781 insLog.finer("Insets are {0}, new dimensions {1}",
782 currentInsets, newDimensions);
783 }
784
785 checkIfOnNewScreen(newDimensions.getBounds());
786
787 Point oldLocation = getLocation();
788 dimensions = newDimensions;
789 if (!newLocation.equals(oldLocation)) {
790 handleMoved(newDimensions);
791 }
792 reconfigureContentWindow(newDimensions);
793 updateChildrenSizes();
794
795 repositionSecurityWarning();
796 }
797
798 private void checkShellRectSize(Rectangle shellRect) {
799 shellRect.width = Math.max(MIN_SIZE, shellRect.width);
800 shellRect.height = Math.max(MIN_SIZE, shellRect.height);
801 }
802
803 private void checkShellRectPos(Rectangle shellRect) {
804 int wm = XWM.getWMID();
805 if (wm == XWM.MOTIF_WM || wm == XWM.CDE_WM) {
806 if (shellRect.x == 0 && shellRect.y == 0) {
807 shellRect.x = shellRect.y = 1;
808 }
809 }
810 }
811
812 private void checkShellRect(Rectangle shellRect) {
813 checkShellRectSize(shellRect);
814 checkShellRectPos(shellRect);
815 }
816
817 public void setShellBounds(Rectangle rec) {
818 if (insLog.isLoggable(PlatformLogger.FINE)) {
819 insLog.fine("Setting shell bounds on " + this + " to " + rec);
820 }
821 XToolkit.awtLock();
822 try {
823 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
824 XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(), rec.width, rec.height);
825 XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(), rec.x, rec.y);
826 }
827 finally {
828 XToolkit.awtUnlock();
829 }
830 }
831 public void setShellSize(Rectangle rec) {
832 if (insLog.isLoggable(PlatformLogger.FINE)) {
833 insLog.fine("Setting shell size on " + this + " to " + rec);
834 }
835 XToolkit.awtLock();
836 try {
837 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
838 XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(), rec.width, rec.height);
839 }
840 finally {
841 XToolkit.awtUnlock();
842 }
843 }
844 public void setShellPosition(Rectangle rec) {
845 if (insLog.isLoggable(PlatformLogger.FINE)) {
846 insLog.fine("Setting shell position on " + this + " to " + rec);
847 }
848 XToolkit.awtLock();
849 try {
850 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
851 XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(), rec.x, rec.y);
852 }
853 finally {
854 XToolkit.awtUnlock();
855 }
856 }
857
858 void initResizability() {
859 setResizable(winAttr.initialResizability);
860 }
861 public void setResizable(boolean resizable) {
862 int fs = winAttr.functions;
863 if (!isResizable() && resizable) {
864 currentInsets = new Insets(0, 0, 0, 0);
865 resetWMSetInsets();
927
928 public int getWidth() {
929 return getSize().width;
930 }
931
932 public int getHeight() {
933 return getSize().height;
934 }
935
936 final public WindowDimensions getDimensions() {
937 return dimensions;
938 }
939
940 public Point getLocationOnScreen() {
941 XToolkit.awtLock();
942 try {
943 if (configure_seen) {
944 return toGlobal(0,0);
945 } else {
946 Point location = target.getLocation();
947 if (insLog.isLoggable(PlatformLogger.FINE)) {
948 insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
949 this, location);
950 }
951 return location;
952 }
953 } finally {
954 XToolkit.awtUnlock();
955 }
956 }
957
958
959 /***************************************************************************************
960 * END OF I N S E T S C O D E
961 **************************************************************************************/
962
963 protected boolean isEventDisabled(XEvent e) {
964 switch (e.get_type()) {
965 // Do not generate MOVED/RESIZED events since we generate them by ourselves
966 case XConstants.ConfigureNotify:
967 return true;
968 case XConstants.EnterNotify:
969 case XConstants.LeaveNotify:
970 // Disable crossing event on outer borders of Frame so
971 // we receive only one set of cross notifications(first set is from content window)
972 return true;
973 default:
974 return super.isEventDisabled(e);
975 }
976 }
977
978 int getDecorations() {
979 return winAttr.decorations;
980 }
981
982 int getFunctions() {
983 return winAttr.functions;
984 }
985
986 public void setVisible(boolean vis) {
987 if (log.isLoggable(PlatformLogger.FINER)) {
988 log.finer("Setting {0} to visible {1}", this, Boolean.valueOf(vis));
989 }
990 if (vis && !isVisible()) {
991 XWM.setShellDecor(this);
992 super.setVisible(vis);
993 if (winAttr.isResizable) {
994 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
995 //We need to update frame's minimum size, not to reset it
996 XWM.removeSizeHints(this, XUtilConstants.PMaxSize);
997 updateMinimumSize();
998 }
999 } else {
1000 super.setVisible(vis);
1001 }
1002 }
1003
1004 protected void suppressWmTakeFocus(boolean doSuppress) {
1005 XAtomList protocols = getWMProtocols();
1006 if (doSuppress) {
1007 protocols.remove(wm_take_focus);
1020 if (iconWindow != null) {
1021 iconWindow.destroy();
1022 }
1023
1024 super.dispose();
1025 }
1026
1027 public void handleClientMessage(XEvent xev) {
1028 super.handleClientMessage(xev);
1029 XClientMessageEvent cl = xev.get_xclient();
1030 if ((wm_protocols != null) && (cl.get_message_type() == wm_protocols.getAtom())) {
1031 if (cl.get_data(0) == wm_delete_window.getAtom()) {
1032 handleQuit();
1033 } else if (cl.get_data(0) == wm_take_focus.getAtom()) {
1034 handleWmTakeFocus(cl);
1035 }
1036 }
1037 }
1038
1039 private void handleWmTakeFocus(XClientMessageEvent cl) {
1040 if (focusLog.isLoggable(PlatformLogger.FINE)) {
1041 focusLog.fine("WM_TAKE_FOCUS on {0}", this);
1042 }
1043 requestWindowFocus(cl.get_data(1), true);
1044 }
1045
1046 /**
1047 * Requests focus to this decorated top-level by requesting X input focus
1048 * to the shell window.
1049 */
1050 protected void requestXFocus(long time, boolean timeProvided) {
1051 // We have proxied focus mechanism - instead of shell the focus is held
1052 // by "proxy" - invisible mapped window. When we want to set X input focus to
1053 // toplevel set it on proxy instead.
1054 if (focusProxy == null) {
1055 if (focusLog.isLoggable(PlatformLogger.WARNING)) {
1056 focusLog.warning("Focus proxy is null for " + this);
1057 }
1058 } else {
1059 if (focusLog.isLoggable(PlatformLogger.FINE)) {
1060 focusLog.fine("Requesting focus to proxy: " + focusProxy);
1061 }
1062 if (timeProvided) {
1063 focusProxy.xRequestFocus(time);
1064 } else {
1065 focusProxy.xRequestFocus();
1066 }
1067 }
1068 }
1069
1070 XFocusProxyWindow getFocusProxy() {
1071 return focusProxy;
1072 }
1073
1074 public void handleQuit() {
1075 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
1076 }
1077
1078 final void dumpMe() {
1079 System.err.println(">>> Peer: " + x + ", " + y + ", " + width + ", " + height);
1133 dumpShell();
1134 dumpContent();
1135 }
1136
1137 boolean isMaximized() {
1138 return false;
1139 }
1140
1141 @Override
1142 boolean isOverrideRedirect() {
1143 return Window.Type.POPUP.equals(getWindowType());
1144 }
1145
1146 public boolean requestWindowFocus(long time, boolean timeProvided) {
1147 focusLog.fine("Request for decorated window focus");
1148 // If this is Frame or Dialog we can't assure focus request success - but we still can try
1149 // If this is Window and its owner Frame is active we can be sure request succedded.
1150 Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1151 Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1152
1153 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1154 focusLog.finer("Current window is: active={0}, focused={1}",
1155 Boolean.valueOf(target == activeWindow),
1156 Boolean.valueOf(target == focusedWindow));
1157 }
1158
1159 XWindowPeer toFocus = this;
1160 while (toFocus.nextTransientFor != null) {
1161 toFocus = toFocus.nextTransientFor;
1162 }
1163 if (toFocus == null || !toFocus.focusAllowedFor()) {
1164 // This might change when WM will have property to determine focus policy.
1165 // Right now, because policy is unknown we can't be sure we succedded
1166 return false;
1167 }
1168 if (this == toFocus) {
1169 if (isWMStateNetHidden()) {
1170 focusLog.fine("The window is unmapped, so rejecting the request");
1171 return false;
1172 }
1173 if (target == activeWindow && target != focusedWindow) {
1174 // Happens when an owned window is currently focused
1175 focusLog.fine("Focus is on child window - transfering it back to the owner");
1176 handleWindowFocusInSync(-1);
1177 return true;
1178 }
1179 Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();
1180 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
1181 focusLog.finest("Real native focused window: " + realNativeFocusedWindow +
1182 "\nKFM's focused window: " + focusedWindow);
1183 }
1184
1185 // A workaround for Metacity. See 6522725, 6613426, 7147075.
1186 if (target == realNativeFocusedWindow && XWM.getWMID() == XWM.METACITY_WM) {
1187 if (focusLog.isLoggable(PlatformLogger.FINE)) {
1188 focusLog.fine("The window is already natively focused.");
1189 }
1190 return true;
1191 }
1192 }
1193 if (focusLog.isLoggable(PlatformLogger.FINE)) {
1194 focusLog.fine("Requesting focus to " + (this == toFocus ? "this window" : toFocus));
1195 }
1196
1197 if (timeProvided) {
1198 toFocus.requestXFocus(time);
1199 } else {
1200 toFocus.requestXFocus();
1201 }
1202 return (this == toFocus);
1203 }
1204
1205 XWindowPeer actualFocusedWindow = null;
1206 void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1207 synchronized(getStateLock()) {
1208 this.actualFocusedWindow = actualFocusedWindow;
1209 }
1210 }
1211
1212 boolean requestWindowFocus(XWindowPeer actualFocusedWindow,
1213 long time, boolean timeProvided)
|
61 }
62
63 public long getShell() {
64 return window;
65 }
66
67 public long getContentWindow() {
68 return (content == null) ? window : content.getWindow();
69 }
70
71 void preInit(XCreateWindowParams params) {
72 super.preInit(params);
73 winAttr.initialFocus = true;
74
75 currentInsets = new Insets(0,0,0,0);
76 applyGuessedInsets();
77
78 Rectangle bounds = (Rectangle)params.get(BOUNDS);
79 dimensions = new WindowDimensions(bounds, getRealInsets(), false);
80 params.put(BOUNDS, dimensions.getClientRect());
81 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
82 insLog.fine("Initial dimensions {0}", dimensions);
83 }
84
85 // Deny default processing of these events on the shell - proxy will take care of
86 // them instead
87 Long eventMask = (Long)params.get(EVENT_MASK);
88 params.add(EVENT_MASK, Long.valueOf(eventMask.longValue() & ~(XConstants.FocusChangeMask | XConstants.KeyPressMask | XConstants.KeyReleaseMask)));
89 }
90
91 void postInit(XCreateWindowParams params) {
92 // The size hints must be set BEFORE mapping the window (see 6895647)
93 updateSizeHints(dimensions);
94
95 // The super method maps the window if it's visible on the shared level
96 super.postInit(params);
97
98 // The lines that follow need to be in a postInit, so they
99 // happen after the X window is created.
100 initResizability();
101 XWM.requestWMExtents(getWindow());
164 XFocusProxyWindow createFocusProxy() {
165 return new XFocusProxyWindow(this);
166 }
167
168 protected XAtomList getWMProtocols() {
169 XAtomList protocols = super.getWMProtocols();
170 protocols.add(wm_delete_window);
171 protocols.add(wm_take_focus);
172 return protocols;
173 }
174
175 public Graphics getGraphics() {
176 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
177 return getGraphics(content.surfaceData,
178 compAccessor.getForeground(target),
179 compAccessor.getBackground(target),
180 compAccessor.getFont(target));
181 }
182
183 public void setTitle(String title) {
184 if (log.isLoggable(PlatformLogger.Level.FINE)) {
185 log.fine("Title is " + title);
186 }
187 winAttr.title = title;
188 updateWMName();
189 }
190
191 protected String getWMName() {
192 if (winAttr.title == null || winAttr.title.trim().equals("")) {
193 return " ";
194 } else {
195 return winAttr.title;
196 }
197 }
198
199 void updateWMName() {
200 super.updateWMName();
201 String name = getWMName();
202 XToolkit.awtLock();
203 try {
204 if (name == null || name.trim().equals("")) {
214 }
215
216 // NOTE: This method may be called by privileged threads.
217 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
218 public void handleIconify() {
219 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
220 }
221
222 // NOTE: This method may be called by privileged threads.
223 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
224 public void handleDeiconify() {
225 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
226 }
227
228 public void handleFocusEvent(XEvent xev) {
229 super.handleFocusEvent(xev);
230 XFocusChangeEvent xfe = xev.get_xfocus();
231
232 // If we somehow received focus events forward it instead to proxy
233 // FIXME: Shouldn't we instead check for inferrior?
234 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
235 focusLog.finer("Received focus event on shell: " + xfe);
236 }
237 // focusProxy.xRequestFocus();
238 }
239
240 /***************************************************************************************
241 * I N S E T S C O D E
242 **************************************************************************************/
243
244 protected boolean isInitialReshape() {
245 return false;
246 }
247
248 private static Insets difference(Insets i1, Insets i2) {
249 return new Insets(i1.top-i2.top, i1.left - i2.left, i1.bottom-i2.bottom, i1.right-i2.right);
250 }
251
252 private static boolean isNull(Insets i) {
253 return (i == null) || ((i.left | i.top | i.right | i.bottom) == 0);
254 }
258 }
259
260 // insets which we get from WM (e.g from _NET_FRAME_EXTENTS)
261 private Insets wm_set_insets;
262
263 private Insets getWMSetInsets(XAtom changedAtom) {
264 if (isEmbedded()) {
265 return null;
266 }
267
268 if (wm_set_insets != null) {
269 return wm_set_insets;
270 }
271
272 if (changedAtom == null) {
273 wm_set_insets = XWM.getInsetsFromExtents(getWindow());
274 } else {
275 wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
276 }
277
278 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
279 insLog.finer("FRAME_EXTENTS: {0}", wm_set_insets);
280 }
281
282 if (wm_set_insets != null) {
283 wm_set_insets = copy(wm_set_insets);
284 }
285 return wm_set_insets;
286 }
287
288 private void resetWMSetInsets() {
289 wm_set_insets = null;
290 }
291
292 public void handlePropertyNotify(XEvent xev) {
293 super.handlePropertyNotify(xev);
294
295 XPropertyEvent ev = xev.get_xproperty();
296 if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
297 || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
298 {
299 getWMSetInsets(XAtom.get(ev.get_atom()));
300 }
301 }
302
303 long reparent_serial = 0;
304
305 public void handleReparentNotifyEvent(XEvent xev) {
306 XReparentEvent xe = xev.get_xreparent();
307 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
308 insLog.fine(xe.toString());
309 }
310 reparent_serial = xe.get_serial();
311 XToolkit.awtLock();
312 try {
313 long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
314
315 if (isEmbedded()) {
316 setReparented(true);
317 insets_corrected = true;
318 return;
319 }
320 Component t = (Component)target;
321 if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
322 setReparented(true);
323 insets_corrected = true;
324 reshape(dimensions, SET_SIZE, false);
325 } else if (xe.get_parent() == root) {
326 configure_seen = false;
327 insets_corrected = false;
328
329 /*
330 * We can be repareted to root for two reasons:
331 * . setVisible(false)
332 * . WM exited
333 */
334 if (isVisible()) { /* WM exited */
335 /* Work around 4775545 */
336 XWM.getWM().unshadeKludge(this);
337 insLog.fine("- WM exited");
338 } else {
339 insLog.fine(" - reparent due to hide");
340 }
341 } else { /* reparented to WM frame, figure out our insets */
342 setReparented(true);
343 insets_corrected = false;
344
345 // Check if we have insets provided by the WM
346 Insets correctWM = getWMSetInsets(null);
347 if (correctWM != null) {
348 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
349 insLog.finer("wm-provided insets {0}", correctWM);
350 }
351 // If these insets are equal to our current insets - no actions are necessary
352 Insets dimInsets = dimensions.getInsets();
353 if (correctWM.equals(dimInsets)) {
354 insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
355 no_reparent_artifacts = true;
356 insets_corrected = true;
357 applyGuessedInsets();
358 return;
359 }
360 } else {
361 correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
362
363 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
364 if (correctWM != null) {
365 insLog.finer("correctWM {0}", correctWM);
366 } else {
367 insLog.finer("correctWM insets are not available, waiting for configureNotify");
368 }
369 }
370 }
371
372 if (correctWM != null) {
373 handleCorrectInsets(correctWM);
374 }
375 }
376 } finally {
377 XToolkit.awtUnlock();
378 }
379 }
380
381 protected void handleCorrectInsets(Insets correctWM) {
382 XToolkit.awtLock();
383 try {
384 /*
385 * Ok, now see if we need adjust window size because
386 * initial insets were wrong (most likely they were).
387 */
388 Insets correction = difference(correctWM, currentInsets);
389 if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
390 insLog.finest("Corrention {0}", correction);
391 }
392 if (!isNull(correction)) {
393 currentInsets = copy(correctWM);
394 applyGuessedInsets();
395
396 //Fix for 6318109: PIT: Min Size is not honored properly when a
397 //smaller size is specified in setSize(), XToolkit
398 //update minimum size hints
399 updateMinSizeHints();
400 }
401 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
402 insLog.finer("Dimensions before reparent: " + dimensions);
403 }
404
405 dimensions.setInsets(getRealInsets());
406 insets_corrected = true;
407
408 if (isMaximized()) {
409 return;
410 }
411
412 /*
413 * If this window has been sized by a pack() we need
414 * to keep the interior geometry intact. Since pack()
415 * computed width and height with wrong insets, we
416 * must adjust the target dimensions appropriately.
417 */
418 if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
419 reshape(dimensions, SET_BOUNDS, false);
420 } else {
421 reshape(dimensions, SET_SIZE, false);
456
457 public void revalidate() {
458 XToolkit.executeOnEventHandlerThread(target, new Runnable() {
459 public void run() {
460 target.invalidate();
461 target.validate();
462 }
463 });
464 }
465
466 Insets getRealInsets() {
467 if (isNull(currentInsets)) {
468 applyGuessedInsets();
469 }
470 return currentInsets;
471 }
472
473 public Insets getInsets() {
474 Insets in = copy(getRealInsets());
475 in.top += getMenuBarHeight();
476 if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
477 insLog.finest("Get insets returns {0}", in);
478 }
479 return in;
480 }
481
482 boolean gravityBug() {
483 return XWM.configureGravityBuggy();
484 }
485
486 // The height of area used to display current active input method
487 int getInputMethodHeight() {
488 return 0;
489 }
490
491 void updateSizeHints(WindowDimensions dims) {
492 Rectangle rec = dims.getClientRect();
493 checkShellRect(rec);
494 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
495 }
496
497 void updateSizeHints() {
498 updateSizeHints(dimensions);
499 }
500
501 // Coordinates are that of the target
502 // Called only on Toolkit thread
503 public void reshape(WindowDimensions newDimensions, int op,
504 boolean userReshape)
505 {
506 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
507 insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
508 }
509 if (userReshape) {
510 // We handle only userReshape == true cases. It means that
511 // if the window manager or any other part of the windowing
512 // system sets inappropriate size for this window, we can
513 // do nothing but accept it.
514 Rectangle newBounds = newDimensions.getBounds();
515 Insets insets = newDimensions.getInsets();
516 // Inherit isClientSizeSet from newDimensions
517 if (newDimensions.isClientSizeSet()) {
518 newBounds = new Rectangle(newBounds.x, newBounds.y,
519 newBounds.width - insets.left - insets.right,
520 newBounds.height - insets.top - insets.bottom);
521 }
522 newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
523 }
524 XToolkit.awtLock();
525 try {
526 if (!isReparented() || !isVisible()) {
527 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
528 insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
529 Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
530 }
531
532 // Fix for 6323293.
533 // This actually is needed to preserve compatibility with previous releases -
534 // some of licensees are expecting componentMoved event on invisible one while
535 // its location changes.
536 Point oldLocation = getLocation();
537
538 Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX((Component)target),
539 AWTAccessor.getComponentAccessor().getY((Component)target));
540
541 if (!newLocation.equals(oldLocation)) {
542 handleMoved(newDimensions);
543 }
544
545 dimensions = new WindowDimensions(newDimensions);
546 updateSizeHints(dimensions);
547 Rectangle client = dimensions.getClientRect();
615 break;
616 case SET_SIZE:
617 // Set size sets bounds size. However, until the window is mapped we
618 // should use client coordinates
619 dims.setSize(width, height);
620 break;
621 case SET_CLIENT_SIZE: {
622 // Sets client rect size. Width and height contain insets.
623 Insets in = currentInsets;
624 width -= in.left+in.right;
625 height -= in.top+in.bottom;
626 dims.setClientSize(width, height);
627 break;
628 }
629 case SET_BOUNDS:
630 default:
631 dims.setLocation(x, y);
632 dims.setSize(width, height);
633 break;
634 }
635 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
636 insLog.fine("For the operation {0} new dimensions are {1}",
637 operationToString(operation), dims);
638 }
639
640 reshape(dims, operation, userReshape);
641 }
642
643 // This method gets overriden in XFramePeer & XDialogPeer.
644 abstract boolean isTargetUndecorated();
645
646 /**
647 * @see java.awt.peer.ComponentPeer#setBounds
648 */
649 public void setBounds(int x, int y, int width, int height, int op) {
650 // TODO: Rewrite with WindowDimensions
651 reshape(x, y, width, height, op, true);
652 validateSurface();
653 }
654
655 // Coordinates are that of the shell
656 void reconfigureContentWindow(WindowDimensions dims) {
657 if (content == null) {
658 insLog.fine("WARNING: Content window is null");
659 return;
660 }
661 content.setContentBounds(dims);
662 }
663
664 boolean no_reparent_artifacts = false;
665 public void handleConfigureNotifyEvent(XEvent xev) {
666 assert (SunToolkit.isAWTLockHeldByCurrentThread());
667 XConfigureEvent xe = xev.get_xconfigure();
668 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
669 insLog.fine("Configure notify {0}", xe);
670 }
671
672 // XXX: should really only consider synthetic events, but
673 if (isReparented()) {
674 configure_seen = true;
675 }
676
677 if (!isMaximized()
678 && (xe.get_serial() == reparent_serial || xe.get_window() != getShell())
679 && !no_reparent_artifacts)
680 {
681 insLog.fine("- reparent artifact, skipping");
682 return;
683 }
684 no_reparent_artifacts = false;
685
686 /**
687 * When there is a WM we receive some CN before being visible and after.
688 * We should skip all CN which are before being visible, because we assume
689 * the gravity is in action while it is not yet.
690 *
691 * When there is no WM we receive CN only _before_ being visible.
692 * We should process these CNs.
693 */
694 if (!isVisible() && XWM.getWMID() != XWM.NO_WM) {
695 insLog.fine(" - not visible, skipping");
696 return;
697 }
698
699 /*
700 * Some window managers configure before we are reparented and
701 * the send event flag is set! ugh... (Enlighetenment for one,
702 * possibly MWM as well). If we haven't been reparented yet
703 * this is just the WM shuffling us into position. Ignore
704 * it!!!! or we wind up in a bogus location.
705 */
706 int runningWM = XWM.getWMID();
707 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
708 insLog.fine("reparented={0}, visible={1}, WM={2}, decorations={3}",
709 isReparented(), isVisible(), runningWM, getDecorations());
710 }
711 if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
712 && !XWM.isNonReparentingWM()
713 && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
714 insLog.fine("- visible but not reparented, skipping");
715 return;
716 }
717 //Last chance to correct insets
718 if (!insets_corrected && getDecorations() != XWindowAttributesData.AWT_DECOR_NONE) {
719 long parent = XlibUtil.getParentWindow(window);
720 Insets correctWM = (parent != -1) ? XWM.getWM().getInsets(this, window, parent) : null;
721 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
722 if (correctWM != null) {
723 insLog.finer("Configure notify - insets : " + correctWM);
724 } else {
725 insLog.finer("Configure notify - insets are still not available");
726 }
727 }
728 if (correctWM != null) {
729 handleCorrectInsets(correctWM);
730 } else {
731 //Only one attempt to correct insets is made (to lower risk)
732 //if insets are still not available we simply set the flag
733 insets_corrected = true;
734 }
735 }
736
737 updateChildrenSizes();
738
739 // Bounds of the window
740 Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds((Component)target);
741
742 Point newLocation = targetBounds.getLocation();
743 if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
744 // Location, Client size + insets
745 newLocation = new Point(xe.get_x() - currentInsets.left, xe.get_y() - currentInsets.top);
746 } else {
747 // ICCCM 4.1.5 states that a real ConfigureNotify will be sent when
748 // a window is resized but the client can not tell if the window was
749 // moved or not. The client should consider the position as unkown
750 // and use TranslateCoordinates to find the actual position.
751 //
752 // TODO this should be the default for every case.
753 switch (XWM.getWMID()) {
754 case XWM.CDE_WM:
755 case XWM.MOTIF_WM:
756 case XWM.METACITY_WM:
757 case XWM.MUTTER_WM:
758 case XWM.SAWFISH_WM:
759 {
760 Point xlocation = queryXLocation();
761 if (log.isLoggable(PlatformLogger.Level.FINE)) {
762 log.fine("New X location: {0}", xlocation);
763 }
764 if (xlocation != null) {
765 newLocation = xlocation;
766 }
767 break;
768 }
769 default:
770 break;
771 }
772 }
773
774 WindowDimensions newDimensions =
775 new WindowDimensions(newLocation,
776 new Dimension(xe.get_width(), xe.get_height()),
777 copy(currentInsets),
778 true);
779
780 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
781 insLog.finer("Insets are {0}, new dimensions {1}",
782 currentInsets, newDimensions);
783 }
784
785 checkIfOnNewScreen(newDimensions.getBounds());
786
787 Point oldLocation = getLocation();
788 dimensions = newDimensions;
789 if (!newLocation.equals(oldLocation)) {
790 handleMoved(newDimensions);
791 }
792 reconfigureContentWindow(newDimensions);
793 updateChildrenSizes();
794
795 repositionSecurityWarning();
796 }
797
798 private void checkShellRectSize(Rectangle shellRect) {
799 shellRect.width = Math.max(MIN_SIZE, shellRect.width);
800 shellRect.height = Math.max(MIN_SIZE, shellRect.height);
801 }
802
803 private void checkShellRectPos(Rectangle shellRect) {
804 int wm = XWM.getWMID();
805 if (wm == XWM.MOTIF_WM || wm == XWM.CDE_WM) {
806 if (shellRect.x == 0 && shellRect.y == 0) {
807 shellRect.x = shellRect.y = 1;
808 }
809 }
810 }
811
812 private void checkShellRect(Rectangle shellRect) {
813 checkShellRectSize(shellRect);
814 checkShellRectPos(shellRect);
815 }
816
817 public void setShellBounds(Rectangle rec) {
818 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
819 insLog.fine("Setting shell bounds on " + this + " to " + rec);
820 }
821 XToolkit.awtLock();
822 try {
823 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
824 XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(), rec.width, rec.height);
825 XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(), rec.x, rec.y);
826 }
827 finally {
828 XToolkit.awtUnlock();
829 }
830 }
831 public void setShellSize(Rectangle rec) {
832 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
833 insLog.fine("Setting shell size on " + this + " to " + rec);
834 }
835 XToolkit.awtLock();
836 try {
837 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
838 XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(), rec.width, rec.height);
839 }
840 finally {
841 XToolkit.awtUnlock();
842 }
843 }
844 public void setShellPosition(Rectangle rec) {
845 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
846 insLog.fine("Setting shell position on " + this + " to " + rec);
847 }
848 XToolkit.awtLock();
849 try {
850 updateSizeHints(rec.x, rec.y, rec.width, rec.height);
851 XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(), rec.x, rec.y);
852 }
853 finally {
854 XToolkit.awtUnlock();
855 }
856 }
857
858 void initResizability() {
859 setResizable(winAttr.initialResizability);
860 }
861 public void setResizable(boolean resizable) {
862 int fs = winAttr.functions;
863 if (!isResizable() && resizable) {
864 currentInsets = new Insets(0, 0, 0, 0);
865 resetWMSetInsets();
927
928 public int getWidth() {
929 return getSize().width;
930 }
931
932 public int getHeight() {
933 return getSize().height;
934 }
935
936 final public WindowDimensions getDimensions() {
937 return dimensions;
938 }
939
940 public Point getLocationOnScreen() {
941 XToolkit.awtLock();
942 try {
943 if (configure_seen) {
944 return toGlobal(0,0);
945 } else {
946 Point location = target.getLocation();
947 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
948 insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
949 this, location);
950 }
951 return location;
952 }
953 } finally {
954 XToolkit.awtUnlock();
955 }
956 }
957
958
959 /***************************************************************************************
960 * END OF I N S E T S C O D E
961 **************************************************************************************/
962
963 protected boolean isEventDisabled(XEvent e) {
964 switch (e.get_type()) {
965 // Do not generate MOVED/RESIZED events since we generate them by ourselves
966 case XConstants.ConfigureNotify:
967 return true;
968 case XConstants.EnterNotify:
969 case XConstants.LeaveNotify:
970 // Disable crossing event on outer borders of Frame so
971 // we receive only one set of cross notifications(first set is from content window)
972 return true;
973 default:
974 return super.isEventDisabled(e);
975 }
976 }
977
978 int getDecorations() {
979 return winAttr.decorations;
980 }
981
982 int getFunctions() {
983 return winAttr.functions;
984 }
985
986 public void setVisible(boolean vis) {
987 if (log.isLoggable(PlatformLogger.Level.FINER)) {
988 log.finer("Setting {0} to visible {1}", this, Boolean.valueOf(vis));
989 }
990 if (vis && !isVisible()) {
991 XWM.setShellDecor(this);
992 super.setVisible(vis);
993 if (winAttr.isResizable) {
994 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
995 //We need to update frame's minimum size, not to reset it
996 XWM.removeSizeHints(this, XUtilConstants.PMaxSize);
997 updateMinimumSize();
998 }
999 } else {
1000 super.setVisible(vis);
1001 }
1002 }
1003
1004 protected void suppressWmTakeFocus(boolean doSuppress) {
1005 XAtomList protocols = getWMProtocols();
1006 if (doSuppress) {
1007 protocols.remove(wm_take_focus);
1020 if (iconWindow != null) {
1021 iconWindow.destroy();
1022 }
1023
1024 super.dispose();
1025 }
1026
1027 public void handleClientMessage(XEvent xev) {
1028 super.handleClientMessage(xev);
1029 XClientMessageEvent cl = xev.get_xclient();
1030 if ((wm_protocols != null) && (cl.get_message_type() == wm_protocols.getAtom())) {
1031 if (cl.get_data(0) == wm_delete_window.getAtom()) {
1032 handleQuit();
1033 } else if (cl.get_data(0) == wm_take_focus.getAtom()) {
1034 handleWmTakeFocus(cl);
1035 }
1036 }
1037 }
1038
1039 private void handleWmTakeFocus(XClientMessageEvent cl) {
1040 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1041 focusLog.fine("WM_TAKE_FOCUS on {0}", this);
1042 }
1043 requestWindowFocus(cl.get_data(1), true);
1044 }
1045
1046 /**
1047 * Requests focus to this decorated top-level by requesting X input focus
1048 * to the shell window.
1049 */
1050 protected void requestXFocus(long time, boolean timeProvided) {
1051 // We have proxied focus mechanism - instead of shell the focus is held
1052 // by "proxy" - invisible mapped window. When we want to set X input focus to
1053 // toplevel set it on proxy instead.
1054 if (focusProxy == null) {
1055 if (focusLog.isLoggable(PlatformLogger.Level.WARNING)) {
1056 focusLog.warning("Focus proxy is null for " + this);
1057 }
1058 } else {
1059 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1060 focusLog.fine("Requesting focus to proxy: " + focusProxy);
1061 }
1062 if (timeProvided) {
1063 focusProxy.xRequestFocus(time);
1064 } else {
1065 focusProxy.xRequestFocus();
1066 }
1067 }
1068 }
1069
1070 XFocusProxyWindow getFocusProxy() {
1071 return focusProxy;
1072 }
1073
1074 public void handleQuit() {
1075 postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
1076 }
1077
1078 final void dumpMe() {
1079 System.err.println(">>> Peer: " + x + ", " + y + ", " + width + ", " + height);
1133 dumpShell();
1134 dumpContent();
1135 }
1136
1137 boolean isMaximized() {
1138 return false;
1139 }
1140
1141 @Override
1142 boolean isOverrideRedirect() {
1143 return Window.Type.POPUP.equals(getWindowType());
1144 }
1145
1146 public boolean requestWindowFocus(long time, boolean timeProvided) {
1147 focusLog.fine("Request for decorated window focus");
1148 // If this is Frame or Dialog we can't assure focus request success - but we still can try
1149 // If this is Window and its owner Frame is active we can be sure request succedded.
1150 Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1151 Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1152
1153 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1154 focusLog.finer("Current window is: active={0}, focused={1}",
1155 Boolean.valueOf(target == activeWindow),
1156 Boolean.valueOf(target == focusedWindow));
1157 }
1158
1159 XWindowPeer toFocus = this;
1160 while (toFocus.nextTransientFor != null) {
1161 toFocus = toFocus.nextTransientFor;
1162 }
1163 if (toFocus == null || !toFocus.focusAllowedFor()) {
1164 // This might change when WM will have property to determine focus policy.
1165 // Right now, because policy is unknown we can't be sure we succedded
1166 return false;
1167 }
1168 if (this == toFocus) {
1169 if (isWMStateNetHidden()) {
1170 focusLog.fine("The window is unmapped, so rejecting the request");
1171 return false;
1172 }
1173 if (target == activeWindow && target != focusedWindow) {
1174 // Happens when an owned window is currently focused
1175 focusLog.fine("Focus is on child window - transfering it back to the owner");
1176 handleWindowFocusInSync(-1);
1177 return true;
1178 }
1179 Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();
1180 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
1181 focusLog.finest("Real native focused window: " + realNativeFocusedWindow +
1182 "\nKFM's focused window: " + focusedWindow);
1183 }
1184
1185 // A workaround for Metacity. See 6522725, 6613426, 7147075.
1186 if (target == realNativeFocusedWindow && XWM.getWMID() == XWM.METACITY_WM) {
1187 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1188 focusLog.fine("The window is already natively focused.");
1189 }
1190 return true;
1191 }
1192 }
1193 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1194 focusLog.fine("Requesting focus to " + (this == toFocus ? "this window" : toFocus));
1195 }
1196
1197 if (timeProvided) {
1198 toFocus.requestXFocus(time);
1199 } else {
1200 toFocus.requestXFocus();
1201 }
1202 return (this == toFocus);
1203 }
1204
1205 XWindowPeer actualFocusedWindow = null;
1206 void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1207 synchronized(getStateLock()) {
1208 this.actualFocusedWindow = actualFocusedWindow;
1209 }
1210 }
1211
1212 boolean requestWindowFocus(XWindowPeer actualFocusedWindow,
1213 long time, boolean timeProvided)
|