1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "common.h"
  27 
  28 #include "FullScreenWindow.h"
  29 #include "GlassApplication.h"
  30 #include "GlassWindow.h"
  31 #include "GlassScreen.h"
  32 #include "GlassMenu.h"
  33 #include "GlassView.h"
  34 #include "GlassDnD.h"
  35 #include "Pixels.h"
  36 #include "GlassCursor.h"
  37 #include "GlassScreen.h"
  38 
  39 #include "com_sun_glass_events_WindowEvent.h"
  40 #include "com_sun_glass_ui_Window.h"
  41 #include "com_sun_glass_ui_Window_Level.h"
  42 #include "com_sun_glass_ui_win_WinWindow.h"
  43 
  44 
  45 // Helper LEAVE_MAIN_THREAD for GlassWindow
  46 #define LEAVE_MAIN_THREAD_WITH_hWnd  \
  47     HWND hWnd;  \
  48     LEAVE_MAIN_THREAD;  \
  49     ARG(hWnd) = (HWND)ptr;
  50 
  51 static LPCTSTR szGlassWindowClassName = TEXT("GlassWindowClass");
  52 
  53 static jmethodID midNotifyClose;
  54 static jmethodID midNotifyMove;
  55 static jmethodID midNotifyResize;
  56 static jmethodID midNotifyScaleChanged;
  57 static jmethodID midNotifyMoveToAnotherScreen;
  58 
  59 unsigned int GlassWindow::sm_instanceCounter = 0;
  60 HHOOK GlassWindow::sm_hCBTFilter = NULL;
  61 HWND GlassWindow::sm_grabWindow = NULL;
  62 
  63 GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isChild, HWND parentOrOwner)
  64     : BaseWnd(parentOrOwner),
  65     ViewContainer(),
  66     m_state(Normal),
  67     m_isFocusable(true),
  68     m_isFocused(false),
  69     m_focusEvent(0),
  70     m_isResizable(true),
  71     m_isTransparent(isTransparent),
  72     m_isDecorated(isDecorated),
  73     m_isUnified(isUnified),
  74     m_hMenu(NULL),
  75     m_alpha(255),
  76     m_isEnabled(true),
  77     m_parent(isChild ? parentOrOwner : NULL),
  78     m_delegateWindow(NULL),
  79     m_isInFullScreen(false),
  80     m_beforeFullScreenStyle(0),
  81     m_beforeFullScreenExStyle(0),
  82     m_beforeFullScreenMenu(NULL),
  83     m_hIcon(NULL)
  84 {
  85     m_grefThis = GetEnv()->NewGlobalRef(jrefThis);
  86     m_minSize.x = m_minSize.y = -1;   // "not set" value
  87     m_maxSize.x = m_maxSize.y = -1;   // "not set" value
  88     m_hMonitor = NULL;
  89     m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0;
  90     m_beforeFullScreenRect.left = m_beforeFullScreenRect.top =
  91         m_beforeFullScreenRect.right = m_beforeFullScreenRect.bottom = 0;
  92 
  93     if (++GlassWindow::sm_instanceCounter == 1) {
  94         GlassWindow::sm_hCBTFilter =
  95             ::SetWindowsHookEx(WH_CBT,
  96                     (HOOKPROC)GlassWindow::CBTFilter,
  97                     0, GlassApplication::GetMainThreadId());
  98     }
  99     if (isChild) {
 100         GlassApplication::InstallMouseLLHook();
 101     }
 102 }
 103 
 104 GlassWindow::~GlassWindow()
 105 {
 106     if (m_hIcon) {
 107         ::DestroyIcon(m_hIcon);
 108     }
 109 
 110     if (m_grefThis) {
 111         GetEnv()->DeleteGlobalRef(m_grefThis);
 112     }
 113 
 114     if (IsChild()) {
 115         GlassApplication::UninstallMouseLLHook();
 116     }
 117 
 118     if (--GlassWindow::sm_instanceCounter == 0) {
 119         ::UnhookWindowsHookEx(GlassWindow::sm_hCBTFilter);
 120     }
 121 }
 122 
 123 LPCTSTR GlassWindow::GetWindowClassNameSuffix()
 124 {
 125     return szGlassWindowClassName;
 126 }
 127 
 128 HWND GlassWindow::Create(DWORD dwStyle, DWORD dwExStyle, HMONITOR hMonitor, HWND owner)
 129 {
 130     m_hMonitor = hMonitor;
 131 
 132     int x = CW_USEDEFAULT;
 133     int y = CW_USEDEFAULT;
 134     int w = CW_USEDEFAULT;
 135     int h = CW_USEDEFAULT;
 136     if ((dwStyle & WS_POPUP) != 0) {
 137         // CW_USEDEFAULT doesn't work for WS_POPUP windows
 138         RECT r;
 139         if (BaseWnd::GetDefaultWindowBounds(&r)) {
 140             x = r.left;
 141             y = r.top;
 142             w = r.right - r.left;
 143             h = r.bottom - r.top;
 144         }
 145     }
 146 
 147     HWND hwnd = BaseWnd::Create(owner, x, y, w, h,
 148                                 TEXT(""), dwExStyle, dwStyle, NULL);
 149 
 150     ViewContainer::InitDropTarget(hwnd);
 151     ViewContainer::InitManipProcessor(hwnd);
 152 
 153     return hwnd;
 154 }
 155 
 156 void GlassWindow::Close()
 157 {
 158     UngrabFocus();
 159     ViewContainer::ReleaseDropTarget();
 160     ViewContainer::ReleaseManipProcessor();
 161 }
 162 
 163 void GlassWindow::setMinSize(long width, long height)
 164 {
 165     m_minSize.x = width;
 166     m_minSize.y = height;
 167 }
 168 
 169 void GlassWindow::setMaxSize(long width, long height)
 170 {
 171     m_maxSize.x = width;
 172     m_maxSize.y = height;
 173 }
 174 
 175 void GlassWindow::updateMinMaxSize(RECT &windowRect)
 176 {
 177     if (m_minSize.x >= 0) {
 178         // min size has been set
 179         if (windowRect.right - windowRect.left < m_minSize.x) {
 180             windowRect.right = windowRect.left + m_minSize.x;
 181         }
 182         if (windowRect.bottom - windowRect.top < m_minSize.y) {
 183             windowRect.bottom = windowRect.top + m_minSize.y;
 184         }
 185     }
 186     if (m_maxSize.x >= 0) {
 187         // max size has been set
 188         if (windowRect.right - windowRect.left > m_maxSize.x) {
 189             windowRect.right = windowRect.left + m_maxSize.x;
 190         }
 191         if (windowRect.bottom - windowRect.top > m_maxSize.y) {
 192             windowRect.bottom = windowRect.top + m_maxSize.y;
 193         }
 194     }
 195 
 196 }
 197 
 198 void GlassWindow::SetFocusable(bool isFocusable)
 199 {
 200     m_isFocusable = isFocusable;
 201 
 202     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
 203     if (!isFocusable) {
 204         //NOTE: this style works 'by itself' when there's only one window
 205         //      in this application. It does prevent the window from activation
 206         //      then. However, as soon as there is another window, we also need
 207         //      to handle WM_MOUSEACTIVATE and use the CBTFilter() hook.
 208         //      The useful part of the style: it removes the window from the
 209         //      task bar (and the Alt-Tab list).
 210         ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
 211 
 212         if (::GetFocus() == GetHWND()) {
 213             // We can't resign activation, but at least we can reset the focus
 214             ::SetFocus(NULL);
 215         }
 216     } else {
 217         ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
 218     }
 219 }
 220 
 221 LRESULT CALLBACK GlassWindow::CBTFilter(int nCode, WPARAM wParam, LPARAM lParam)
 222 {
 223     if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS) {
 224         BaseWnd *pWindow = BaseWnd::FromHandle((HWND)wParam);
 225         if (pWindow && pWindow->IsGlassWindow()) {
 226             GlassWindow * window = (GlassWindow*)pWindow;
 227 
 228             if (!window->IsEnabled()) {
 229                 window->HandleFocusDisabledEvent();
 230                 return 1;
 231             }
 232             if (!window->IsFocusable()) {
 233                 return 1;
 234             }
 235         }
 236     }
 237     return ::CallNextHookEx(GlassWindow::sm_hCBTFilter, nCode, wParam, lParam);
 238 }
 239 
 240 #ifndef WM_DPICHANGED
 241 #define WM_DPICHANGED       0x02E0
 242 #endif
 243 
 244 char *StringForMsg(UINT msg) {
 245     switch (msg) {
 246         case WM_DPICHANGED: return "WM_DPICHANGED";
 247         case WM_ERASEBKGND: return "WM_ERASEBKGND";
 248         case WM_WINDOWPOSCHANGING: return "WM_WINDOWPOSCHANGING";
 249         case WM_NCPAINT: return "WM_NCPAINT";
 250         case WM_SETCURSOR: return "WM_SETCURSOR";
 251         case WM_NCMOUSEMOVE: return "WM_NCMOUSEMOVE";
 252         case WM_NCHITTEST: return "WM_NCHITTEST";
 253         case WM_NCMOUSELEAVE: return "WM_NCMOUSELEAVE";
 254         case WM_EXITSIZEMOVE: return "WM_EXITSIZEMOVE";
 255         case WM_CREATE: return "WM_CREATE";
 256         case WM_NCDESTROY: return "WM_NCDESTROY";
 257         case WM_STYLECHANGED: return "WM_STYLECHANGED";
 258         case WM_STYLECHANGING: return "WM_STYLECHANGING";
 259         case WM_GETICON: return "WM_GETICON";
 260         case WM_SETICON: return "WM_SETICON";
 261         case WM_ACTIVATEAPP: return "WM_ACTIVATEAPP";
 262         case WM_NCACTIVATE: return "WM_NCACTIVATE";
 263         case WM_IME_SETCONTEXT: return "WM_IME_SETCONTEXT";
 264         case WM_SETTEXT: return "WM_SETTEXT";
 265         case WM_DWMNCRENDERINGCHANGED: return "WM_DWMNCRENDERINGCHANGED";
 266         case WM_SYSCOMMAND: return "WM_SYSCOMMAND";
 267 
 268         case WM_SHOWWINDOW: return "WM_SHOWWINDOW";
 269         case WM_DWMCOMPOSITIONCHANGED: return "WM_DWMCOMPOSITIONCHANGED";
 270         case WM_SIZE: return "WM_SIZE";
 271         case WM_MOVING: return "WM_MOVING";
 272         case WM_MOVE: return "WM_MOVE";
 273         case WM_WINDOWPOSCHANGED: return "WM_WINDOWPOSCHANGED";
 274         case WM_CLOSE: return "WM_CLOSE";
 275         case WM_DESTROY: return "WM_DESTROY";
 276         case WM_ACTIVATE: return "WM_ACTIVATE";
 277         case WM_MOUSEACTIVATE: return "WM_MOUSEACTIVATE";
 278         case WM_SETFOCUS: return "WM_SETFOCUS";
 279         case WM_KILLFOCUS: return "WM_KILLFOCUS";
 280         case WM_GETMINMAXINFO: return "WM_GETMINMAXINFO";
 281         case WM_COMMAND: return "WM_COMMAND";
 282         case WM_INPUTLANGCHANGE: return "WM_INPUTLANGCHANGE";
 283         case WM_NCCALCSIZE: return "WM_NCCALCSIZE";
 284         case WM_PAINT: return "WM_PAINT";
 285         case WM_CONTEXTMENU: return "WM_CONTEXTMENU";
 286         case WM_LBUTTONDOWN: return "WM_LBUTTONDOWN";
 287         case WM_RBUTTONDOWN: return "WM_RBUTTONDOWN";
 288         case WM_MBUTTONDOWN: return "WM_MBUTTONDOWN";
 289         case WM_LBUTTONUP: return "WM_LBUTTONUP";
 290         case WM_LBUTTONDBLCLK: return "WM_LBUTTONDBLCLK";
 291         case WM_RBUTTONUP: return "WM_RBUTTONUP";
 292         case WM_RBUTTONDBLCLK: return "WM_RBUTTONDBLCLK";
 293         case WM_MBUTTONUP: return "WM_MBUTTONUP";
 294         case WM_MBUTTONDBLCLK: return "WM_MBUTTONDBLCLK";
 295         case WM_MOUSEWHEEL: return "WM_MOUSEWHEEL";
 296         case WM_MOUSEHWHEEL: return "WM_MOUSEHWHEEL";
 297         case WM_MOUSELEAVE: return "WM_MOUSELEAVE";
 298         case WM_MOUSEMOVE: return "WM_MOUSEMOVE";
 299         case WM_CAPTURECHANGED: return "WM_CAPTURECHANGED";
 300         case WM_SYSKEYDOWN: return "WM_SYSKEYDOWN";
 301         case WM_SYSKEYUP: return "WM_SYSKEYUP";
 302         case WM_KEYDOWN: return "WM_KEYDOWN";
 303         case WM_KEYUP: return "WM_KEYUP";
 304         case WM_DEADCHAR: return "WM_DEADCHAR";
 305         case WM_CHAR: return "WM_CHAR";
 306         case WM_IME_CHAR: return "WM_IME_CHAR";
 307         case WM_IME_COMPOSITION: return "WM_IME_COMPOSITION";
 308         case WM_IME_ENDCOMPOSITION: return "WM_IME_ENDCOMPOSITION";
 309         case WM_IME_NOTIFY: return "WM_IME_NOTIFY";
 310         case WM_IME_STARTCOMPOSITION: return "WM_IME_STARTCOMPOSITION";
 311         case WM_NCLBUTTONDOWN: return "WM_NCLBUTTONDOWN";
 312         case WM_NCMBUTTONDOWN: return "WM_NCMBUTTONDOWN";
 313         case WM_NCRBUTTONDOWN: return "WM_NCRBUTTONDOWN";
 314         case WM_NCXBUTTONDOWN: return "WM_NCXBUTTONDOWN";
 315         case WM_TOUCH: return "WM_TOUCH";
 316         case WM_TIMER: return "WM_TIMER";
 317         case WM_GETOBJECT: return "WM_GETOBJECT";
 318     }
 319     return "Unknown";
 320 }
 321 
 322 LRESULT GlassWindow::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
 323 {
 324 //    fprintf(stderr, "msg = 0x%04x (%s)\n", msg, StringForMsg(msg));
 325     MessageResult commonResult = BaseWnd::CommonWindowProc(msg, wParam, lParam);
 326     if (commonResult.processed) {
 327 //        fprintf(stderr, "   (handled by CommonWindowProc)\n");
 328         return commonResult.result;
 329     }
 330 
 331     switch (msg) {
 332         case WM_SHOWWINDOW:
 333             // It's possible that move/size events are reported by the platform
 334             // before the peer listener is set. As a result, location/size are
 335             // not reported, so resending them from here.
 336             HandleMoveEvent(NULL);
 337             HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE, NULL);
 338             // The call below may be restricted to WS_POPUP windows
 339             NotifyViewSize(GetHWND());
 340 
 341             if (!wParam) {
 342                 ResetMouseTracking(GetHWND());
 343             }
 344             if (IS_WINVISTA) {
 345                 ::SendMessage(GetHWND(), WM_DWMCOMPOSITIONCHANGED, 0, 0);
 346             }
 347             break;
 348         case WM_DWMCOMPOSITIONCHANGED:
 349             if (m_isUnified && (IS_WINVISTA)) {
 350                 BOOL bEnabled = FALSE;
 351                 if(SUCCEEDED(::DwmIsCompositionEnabled(&bEnabled)) && bEnabled) {
 352                     MARGINS dwmMargins = { -1, -1, -1, -1 };
 353                     ::DwmExtendFrameIntoClientArea(GetHWND(), &dwmMargins);
 354                 }
 355             }
 356             //When toggling between Aero and Classic theme the size of window changes
 357             //No predefined WM_SIZE event type for this, so using -1 as parameters
 358             HandleViewSizeEvent(GetHWND(), -1, -1, -1);
 359             break;
 360         case WM_SIZE:
 361             switch (wParam) {
 362                 case SIZE_RESTORED:
 363                     if (m_state != Normal) {
 364                         HandleSizeEvent(com_sun_glass_events_WindowEvent_RESTORE, NULL);
 365                         m_state = Normal;
 366                     } else {
 367                         HandleSizeEvent(com_sun_glass_events_WindowEvent_RESIZE, NULL);
 368                     }
 369                     break;
 370                 case SIZE_MINIMIZED:
 371                     HandleSizeEvent(com_sun_glass_events_WindowEvent_MINIMIZE, NULL);
 372                     m_state = Minimized;
 373                     break;
 374                 case SIZE_MAXIMIZED:
 375                     HandleSizeEvent(com_sun_glass_events_WindowEvent_MAXIMIZE, NULL);
 376                     m_state = Maximized;
 377                     break;
 378             }
 379             HandleViewSizeEvent(GetHWND(), msg, wParam, lParam);
 380             break;
 381 //        case WM_MOVING:
 382 //            HandleMoveEvent((RECT *)lParam);
 383 //            break;
 384         case WM_MOVE:
 385             HandleMoveEvent(NULL);
 386             break;
 387         case WM_WINDOWPOSCHANGED:
 388             HandleWindowPosChangedEvent();
 389             break;
 390         case WM_DPICHANGED:
 391             HandleDPIEvent(wParam, lParam);
 392             return 0;
 393         case WM_CLOSE:
 394             HandleCloseEvent();
 395             return 0;
 396         case WM_DESTROY:
 397             HandleDestroyEvent();
 398             return 0;
 399         case WM_ACTIVATE:
 400             {
 401                 // The fActive shouldn't be WA_INACTIVE && the window shouldn't be minimized:
 402                 const bool isFocusGained = LOWORD(wParam) != WA_INACTIVE && HIWORD(wParam) == 0;
 403 
 404                 if (IsInFullScreenMode()) {
 405                     HWND hWndInsertAfter = isFocusGained ? HWND_TOPMOST : HWND_BOTTOM;
 406                     ::SetWindowPos(GetHWND(), hWndInsertAfter, 0, 0, 0, 0,
 407                             SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
 408                 }
 409                 if (!GetDelegateWindow()) {
 410                     HandleActivateEvent(isFocusGained ?
 411                             com_sun_glass_events_WindowEvent_FOCUS_GAINED :
 412                             com_sun_glass_events_WindowEvent_FOCUS_LOST);
 413                 }
 414             }
 415             // Let the DefWindowProc() set the focus to this window
 416             break;
 417         case WM_MOUSEACTIVATE:
 418             if (!IsEnabled()) {
 419                 HandleFocusDisabledEvent();
 420                 // Do not activate, and discard the event
 421                 return MA_NOACTIVATEANDEAT;
 422             }
 423             if (!IsFocusable()) {
 424                 // Do not activate, but pass the mouse event
 425                 return MA_NOACTIVATE;
 426             }
 427             break;
 428         case WM_SETFOCUS:
 429             if (!GetDelegateWindow()) {
 430                 SetFocused(true);
 431                 if (IsChild()) {
 432                     // Synthesize the event
 433                     HandleActivateEvent(m_focusEvent ? m_focusEvent : com_sun_glass_events_WindowEvent_FOCUS_GAINED);
 434                     m_focusEvent = 0;
 435                 }
 436             }
 437             break;
 438         case WM_KILLFOCUS:
 439             if (!GetDelegateWindow()) {
 440                 SetFocused(false);
 441                 if (IsChild()) {
 442                     // Synthesize the event
 443                     HandleActivateEvent(com_sun_glass_events_WindowEvent_FOCUS_LOST);
 444                 }
 445             }
 446             break;
 447         case WM_GETMINMAXINFO:
 448             if (m_minSize.x >= 0 || m_minSize.y >= 0 ||
 449                     m_maxSize.x >= 0 || m_maxSize.y >= 0)
 450             {
 451                 MINMAXINFO *info = (MINMAXINFO *)lParam;
 452                 if (m_minSize.x >= 0) {
 453                     info->ptMinTrackSize.x = m_minSize.x;
 454                 }
 455                 if (m_minSize.y >= 0) {
 456                     info->ptMinTrackSize.y = m_minSize.y;
 457                 }
 458                 if (m_maxSize.x >= 0) {
 459                     info->ptMaxTrackSize.x = m_maxSize.x;
 460                 }
 461                 if (m_maxSize.y >= 0) {
 462                     info->ptMaxTrackSize.y = m_maxSize.y;
 463                 }
 464                 return 0;
 465             }
 466             break;
 467         case WM_COMMAND:
 468             if (HandleCommand(LOWORD(wParam))) {
 469                 return 0;
 470             }
 471             break;
 472         case WM_INPUTLANGCHANGE:
 473             HandleViewInputLangChange(GetHWND(), msg, wParam, lParam);
 474             return 0;
 475         case WM_NCCALCSIZE:
 476 // Workaround for RT-13998. It has some side effects and thus commented out
 477 //            if ((BOOL)wParam && !IsDecorated()) {
 478 //                NCCALCSIZE_PARAMS *p = (NCCALCSIZE_PARAMS *)lParam;
 479 //                p->rgrc[0].right++;
 480 //                p->rgrc[0].bottom++;
 481 //                return WVR_VALIDRECTS;
 482 //            }
 483             break;
 484         case WM_PAINT:
 485             HandleViewPaintEvent(GetHWND(), msg, wParam, lParam);
 486             break;
 487         case WM_CONTEXTMENU:
 488             HandleViewMenuEvent(GetHWND(), msg, wParam, lParam);
 489             break;
 490         case WM_LBUTTONDOWN:
 491         case WM_RBUTTONDOWN:
 492         case WM_MBUTTONDOWN:
 493             CheckUngrab(); // check if other owned windows hierarchy holds the grab
 494             if (IsChild() && !IsFocused() && IsFocusable()) {
 495                 RequestFocus(com_sun_glass_events_WindowEvent_FOCUS_GAINED);
 496             }
 497             // ... and fall through for other mouse events
 498         case WM_LBUTTONUP:
 499         case WM_LBUTTONDBLCLK:
 500         case WM_RBUTTONUP:
 501         case WM_RBUTTONDBLCLK:
 502         case WM_MBUTTONUP:
 503         case WM_MBUTTONDBLCLK:
 504         case WM_MOUSEWHEEL:
 505         case WM_MOUSEHWHEEL:
 506         case WM_MOUSELEAVE:
 507         case WM_MOUSEMOVE:
 508             if (IsEnabled()) {
 509                 if (msg == WM_MOUSELEAVE && GetDelegateWindow()) {
 510                     // Skip generating MouseEvent.EXIT when entering FullScreen
 511                     return 0;
 512                 }
 513                 BOOL handled = HandleViewMouseEvent(GetHWND(), msg, wParam, lParam);
 514                 if (handled && msg == WM_RBUTTONUP) {
 515                     // By default, DefWindowProc() sends WM_CONTEXTMENU from WM_LBUTTONUP
 516                     // Since DefWindowProc() is not called, call the mouse menu handler directly 
 517                     HandleViewMenuEvent(GetHWND(), WM_CONTEXTMENU, (WPARAM) GetHWND(), ::GetMessagePos ());
 518                     //::DefWindowProc(GetHWND(), msg, wParam, lParam);
 519                 }
 520                 if (handled) {
 521                     // Do not call the DefWindowProc() for mouse events that were handled
 522                     return 0;
 523                 }
 524             } else {
 525                 HandleFocusDisabledEvent();
 526                 return 0;
 527             }
 528             break;
 529         case WM_CAPTURECHANGED:
 530             ViewContainer::NotifyCaptureChanged(GetHWND(), (HWND)lParam);
 531             break;
 532         case WM_SYSKEYDOWN:
 533         case WM_SYSKEYUP:
 534         case WM_KEYDOWN:
 535         case WM_KEYUP:
 536             if (!IsEnabled()) {
 537                 return 0;
 538             }
 539             HandleViewKeyEvent(GetHWND(), msg, wParam, lParam);
 540             // Always pass the message down to the DefWindowProc() to handle
 541             // system keys (Alt+F4, etc.) with only excpetion for F10 and ALT:
 542             if (!GetMenu()) {
 543                 if (wParam == VK_MENU || (wParam == VK_F10 && !GetModifiers())) {
 544                     // Disable activation of the window's system menu
 545                     return 0;
 546                 }
 547             }
 548             break;
 549         case WM_DEADCHAR:
 550             if (IsEnabled()) HandleViewDeadKeyEvent(GetHWND(), msg, wParam, lParam);
 551             break;
 552         case WM_CHAR:
 553         case WM_IME_CHAR:
 554             if (IsEnabled()) {
 555                 HandleViewTypedEvent(GetHWND(), msg, wParam, lParam);
 556                 return 0;
 557             }
 558             break;
 559         case WM_IME_COMPOSITION:
 560         case WM_IME_ENDCOMPOSITION:
 561         case WM_IME_NOTIFY:
 562         case WM_IME_STARTCOMPOSITION:
 563             if (IsEnabled() &&
 564                 HandleViewInputMethodEvent(GetHWND(), msg, wParam, lParam)) {
 565                 return 0;
 566             }
 567             break;
 568         case WM_NCLBUTTONDOWN:
 569         case WM_NCMBUTTONDOWN:
 570         case WM_NCRBUTTONDOWN:
 571         case WM_NCXBUTTONDOWN:
 572             UngrabFocus(); // ungrab itself
 573             CheckUngrab(); // check if other owned windows hierarchy holds the grab
 574             // Pass the event to DefWindowProc()
 575             break;
 576         case WM_TOUCH:
 577             if (IsEnabled()) {
 578                 HandleViewTouchEvent(GetHWND(), msg, wParam, lParam);
 579                 return 0;
 580             }
 581             break;
 582         case WM_TIMER:
 583             HandleViewTimerEvent(GetHWND(), wParam);
 584             return 0;
 585         case WM_GETOBJECT: {
 586             LRESULT lr = HandleViewGetAccessible(GetHWND(), wParam, lParam);
 587             if (lr) return lr;
 588             break;
 589         }
 590     }
 591 
 592     return ::DefWindowProc(GetHWND(), msg, wParam, lParam);
 593 }
 594 
 595 void GlassWindow::HandleCloseEvent()
 596 {
 597     JNIEnv* env = GetEnv();
 598 
 599     env->CallVoidMethod(m_grefThis, midNotifyClose);
 600     CheckAndClearException(env);
 601 }
 602 
 603 void GlassWindow::HandleDestroyEvent()
 604 {
 605     JNIEnv* env = GetEnv();
 606 
 607     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyDestroy);
 608     CheckAndClearException(env);
 609 }
 610 
 611 // if pRect == NULL => get position/size by GetWindowRect
 612 void GlassWindow::HandleMoveEvent(RECT *pRect)
 613 {
 614     JNIEnv* env = GetEnv();
 615 
 616     RECT r;
 617     if (pRect == NULL) {
 618         ::GetWindowRect(GetHWND(), &r);
 619         pRect = &r;
 620     }
 621 
 622     env->CallVoidMethod(m_grefThis, midNotifyMove, pRect->left, pRect->top);
 623     CheckAndClearException(env);
 624 }
 625 
 626 // if pRect == NULL => get position/size by GetWindowRect
 627 void GlassWindow::HandleSizeEvent(int type, RECT *pRect)
 628 {
 629     JNIEnv* env = GetEnv();
 630 
 631     RECT r;
 632     if (pRect == NULL) {
 633         ::GetWindowRect(GetHWND(), &r);
 634         pRect = &r;
 635     }
 636 
 637     env->CallVoidMethod(m_grefThis, midNotifyResize,
 638                         type, pRect->right-pRect->left, pRect->bottom-pRect->top);
 639     CheckAndClearException(env);
 640 }
 641 
 642 void GlassWindow::HandleDPIEvent(WPARAM wParam, LPARAM lParam) {
 643     UINT xDPI = LOWORD(wParam);
 644     UINT yDPI = HIWORD(wParam);
 645 
 646 //    fprintf(stderr, "DPI Changed (=> %d, %d)!\n", yDPI, xDPI);
 647     JNIEnv* env = GetEnv();
 648     jfloat newUIScale = GlassApplication::GetUIScale(xDPI);
 649     jfloat newRenderScale = GlassApplication::getRenderScale(newUIScale);
 650     env->CallVoidMethod(m_grefThis, midNotifyScaleChanged, newUIScale, newRenderScale);
 651     CheckAndClearException(env);
 652 
 653     LPRECT lprcNewScale = (LPRECT) lParam;
 654 #if 0
 655     RECT oldBounds, oldClient;
 656     ::GetWindowRect(GetHWND(), &oldBounds);
 657     ::GetClientRect(GetHWND(), &oldClient);
 658     POINT cursor;
 659     ::GetCursorPos(&cursor);
 660     fprintf(stderr, "    @ %d, %d\n", cursor.x, cursor.y);
 661     fprintf(stderr, "    (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d] => (%d, %d, %d, %d) [%d x %d]\n",
 662             oldClient.left, oldClient.top, oldClient.right, oldClient.bottom,
 663             oldClient.right - oldClient.left, oldClient.bottom - oldClient.top,
 664             oldBounds.left, oldBounds.top, oldBounds.right, oldBounds.bottom,
 665             oldBounds.right - oldBounds.left, oldBounds.bottom - oldBounds.top,
 666             lprcNewScale->left, lprcNewScale->top, lprcNewScale->right, lprcNewScale->bottom,
 667             lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top);
 668 #endif
 669     ::SetWindowPos(GetHWND(), HWND_TOP,
 670                    lprcNewScale->left,
 671                    lprcNewScale->top,
 672                    lprcNewScale->right - lprcNewScale->left,
 673                    lprcNewScale->bottom - lprcNewScale->top,
 674                    SWP_NOZORDER | SWP_NOACTIVATE);
 675 }
 676 
 677 void GlassWindow::HandleWindowPosChangedEvent()
 678 {
 679     JNIEnv* env = GetEnv();
 680 
 681     HMONITOR toMonitor = ::MonitorFromWindow(GetHWND(), MONITOR_DEFAULTTOPRIMARY);
 682     HMONITOR fromMonitor = GetMonitor();
 683     if (toMonitor != fromMonitor) {
 684 //        fprintf(stderr, "Monitor changed!\n");
 685         env->CallVoidMethod(m_grefThis, midNotifyMoveToAnotherScreen,
 686                             GlassScreen::GetJavaMonitor(env, toMonitor));
 687         CheckAndClearException(env);
 688         SetMonitor(toMonitor);
 689     }
 690 }
 691 
 692 void GlassWindow::HandleActivateEvent(jint event)
 693 {
 694     const bool active = event != com_sun_glass_events_WindowEvent_FOCUS_LOST;
 695 
 696     if (!active) {
 697         UngrabFocus();
 698     }
 699     
 700     JNIEnv* env = GetEnv();
 701     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocus, event);
 702     CheckAndClearException(env);
 703 }
 704 
 705 void GlassWindow::HandleFocusDisabledEvent()
 706 {
 707     JNIEnv* env = GetEnv();
 708 
 709     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocusDisabled);
 710     CheckAndClearException(env);
 711 }
 712 
 713 bool GlassWindow::HandleCommand(WORD cmdID) {
 714     return HandleMenuCommand(GetHWND(), cmdID);
 715 }
 716 
 717 HMONITOR GlassWindow::GetMonitor()
 718 {
 719     return m_hMonitor;
 720 }
 721 
 722 void GlassWindow::SetMonitor(HMONITOR hMonitor)
 723 {
 724     m_hMonitor = hMonitor;
 725 }
 726 
 727 void GlassWindow::SetAlpha(BYTE alpha)
 728 {
 729     m_alpha = alpha;
 730 
 731     if (m_isTransparent) {
 732         // If the window is transparent, the opacity is handled in
 733         // uploadPixels() below (see BLENDFUNCTION structure
 734         // and its SourceConstantAlpha member)
 735         return;
 736     }
 737 
 738     // The window is opaque. We make it layered temporarily only when
 739     // its alpha is less than 0xFF.
 740     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
 741 
 742     if (alpha == 0xFF) {
 743         if (exStyle & WS_EX_LAYERED) {
 744             ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
 745         }
 746     } else {
 747         if (!(exStyle & WS_EX_LAYERED)) {
 748             ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
 749         }
 750         ::SetLayeredWindowAttributes(GetHWND(), RGB(0, 0, 0), alpha, LWA_ALPHA);
 751     }
 752 }
 753 
 754 void GlassWindow::UpdateInsets()
 755 {
 756     if (::IsIconic(GetHWND())) {
 757         return;
 758     }
 759 
 760     RECT outer, inner;
 761 
 762     ::GetWindowRect(GetHWND(), &outer);
 763     ::GetClientRect(GetHWND(), &inner);
 764 
 765     ::MapWindowPoints(GetHWND(), (HWND)NULL, (LPPOINT)&inner, (sizeof(RECT)/sizeof(POINT)));
 766 
 767     m_insets.top = inner.top - outer.top;
 768     m_insets.left = inner.left - outer.left;
 769     m_insets.bottom = outer.bottom - inner.bottom;
 770     m_insets.right = outer.right - inner.right;
 771 
 772     if (m_insets.top < 0 || m_insets.left < 0 ||
 773             m_insets.bottom < 0 || m_insets.right < 0)
 774     {
 775         if (!IsDecorated()) {
 776             ::ZeroMemory(&m_insets, sizeof(m_insets));
 777         } else {
 778             if (GetStyle() & WS_THICKFRAME) {
 779                 m_insets.left = m_insets.right =
 780                     ::GetSystemMetrics(SM_CXSIZEFRAME);
 781                 m_insets.top = m_insets.bottom =
 782                     ::GetSystemMetrics(SM_CYSIZEFRAME);
 783             } else {
 784                 m_insets.left = m_insets.right =
 785                     ::GetSystemMetrics(SM_CXDLGFRAME);
 786                 m_insets.top = m_insets.bottom =
 787                     ::GetSystemMetrics(SM_CYDLGFRAME);
 788             }
 789 
 790             m_insets.top += ::GetSystemMetrics(SM_CYCAPTION);
 791         }
 792         if (GetMenu()) {
 793             //Well, if menu wraps on multiple lines... sorry about that.
 794             m_insets.top += ::GetSystemMetrics(SM_CYMENU);
 795         }
 796     }
 797 }
 798 
 799 bool GlassWindow::SetResizable(bool resizable)
 800 {
 801     LONG style = GetStyle();
 802 
 803     if (style & WS_CHILD) {
 804         return false;
 805     }
 806 
 807     LONG resizableStyle = WS_MAXIMIZEBOX;
 808     if (IsDecorated()) {
 809         resizableStyle |= WS_THICKFRAME;
 810     }
 811 
 812     if (resizable) {
 813         style |= resizableStyle;
 814     } else {
 815         style &= ~resizableStyle;
 816     }
 817 
 818     SetStyle(style);
 819     m_isResizable = resizable;
 820 
 821     return true;
 822 }
 823 
 824 /* static */ void GlassWindow::ResetGrab()
 825 {
 826     if (sm_grabWindow) {
 827         GlassWindow *pWindow = GlassWindow::FromHandle(sm_grabWindow);
 828         if (pWindow) {
 829             pWindow->UngrabFocus();
 830         }
 831         sm_grabWindow = NULL;
 832     }
 833 }
 834 
 835 bool GlassWindow::GrabFocus()
 836 {
 837     HWND hwnd = GetCurrentHWND();
 838 
 839     if (sm_grabWindow == hwnd) {
 840         // Already grabbed
 841         return true;
 842     }
 843 
 844     GlassWindow::ResetGrab();
 845 
 846     sm_grabWindow = hwnd;
 847 
 848     return true;
 849 }
 850 
 851 void GlassWindow::UngrabFocus()
 852 {
 853     HWND hwnd = GetCurrentHWND();
 854 
 855     if (hwnd != sm_grabWindow) {
 856         return;
 857     }
 858 
 859     JNIEnv* env = GetEnv();
 860     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocusUngrab);
 861     CheckAndClearException(env);
 862 
 863     sm_grabWindow = NULL;
 864 }
 865 
 866 void GlassWindow::CheckUngrab()
 867 {
 868     if (!sm_grabWindow) {
 869         return;
 870     }
 871 
 872     // If this window doesn't belong to an owned windows hierarchy that
 873     // holds the grab currently, then the grab should be released.
 874     // Fix RT-16490: use GetAncestor() instead of ::GetParent() to support embedded windows
 875     for (BaseWnd * window = this; window != NULL; window = BaseWnd::FromHandle(window->GetAncestor())) {
 876         if (window->GetHWND() == sm_grabWindow) {
 877             return;
 878         }
 879     }
 880 
 881     GlassWindow::ResetGrab();
 882 }
 883 
 884 bool GlassWindow::RequestFocus(jint event)
 885 {
 886     if (!IsChild()) {
 887         ASSERT(event == com_sun_glass_events_WindowEvent_FOCUS_GAINED);
 888         // The event will be delivered as a part of WM_ACTIVATE message handling
 889         return ::SetForegroundWindow(GetHWND()) != FALSE;
 890     }
 891 
 892     if (event == com_sun_glass_events_WindowEvent_FOCUS_LOST) {
 893         if (IsFocused()) {
 894             ::SetFocus(NULL);
 895         }
 896 
 897         return true;
 898     }
 899 
 900     // First try to activate the toplevel window
 901     HWND toplevel = ::GetAncestor(GetHWND(), GA_ROOT);
 902     if (::GetForegroundWindow() != toplevel && !::SetForegroundWindow(toplevel)) {
 903         // We're unable to bring our top-level window to foreground.
 904         // But since it anyway becomes active, we (or the plugin) won't receive
 905         // any subsequent notifications. So let's pretend we got the focus - 
 906         //IGNORE: return false;
 907         //We'll anyway get a reasonable response from the ::SetFocus() later
 908     }
 909 
 910     m_focusEvent = event; // reset upon WM_SETFOCUS
 911 
 912     // If we request focus from 'nowhere', the SetFocus may still return NULL I guess
 913     return ::SetFocus(GetHWND()) != NULL || ::GetLastError() == 0;
 914 }
 915 
 916 static BOOL CALLBACK EnumChildWndProc(HWND hwnd, LPARAM lParam)
 917 {
 918     HWND * hwnds = (HWND*)lParam;
 919 
 920     ::SetParent(hwnd, hwnds[1]);
 921 
 922     BaseWnd * window = BaseWnd::FromHandle(hwnd);
 923     if (window) {
 924         window->SetAncestor(hwnds[1]);
 925     }
 926 
 927     return TRUE;
 928 }
 929 
 930 static BOOL CALLBACK EnumOwnedWndProc(HWND hwnd, LPARAM lParam)
 931 {
 932     HWND * hwnds = (HWND*)lParam;
 933 
 934     GlassWindow * window = NULL;
 935     if ((HWND)::GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) == hwnds[0] && (window = GlassWindow::FromHandle(hwnd)) != NULL) {
 936         ::SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwnds[1]);
 937         window->SetAncestor(hwnds[1]);
 938         ::SetWindowPos(hwnd, hwnds[1], 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE);
 939     }
 940 
 941     return TRUE;
 942 }
 943 
 944 void GlassWindow::SetDelegateWindow(HWND hWnd)
 945 {
 946     if (m_delegateWindow == hWnd) {
 947         return;
 948     }
 949 
 950     // Make sure any popups are hidden
 951     UngrabFocus();
 952 
 953     HWND hwnds[2]; // [0] = from; [1] = to;
 954 
 955     hwnds[0] = m_delegateWindow ? m_delegateWindow : GetHWND();
 956     hwnds[1] = hWnd ? hWnd : GetHWND();
 957 
 958     STRACE(_T("SetDelegateWindow: from %p to %p"), hwnds[0], hwnds[1]);
 959 
 960     // Reparent child, and then owned windows
 961     ::EnumChildWindows(hwnds[0], &EnumChildWndProc, (LPARAM)&hwnds);
 962     ::EnumThreadWindows(GlassApplication::GetMainThreadId(), &EnumOwnedWndProc, (LPARAM)&hwnds);
 963 
 964     m_delegateWindow = hWnd;
 965 
 966     GetEnv()->CallVoidMethod(m_grefThis,
 967             javaIDs.Window.notifyDelegatePtr, (jlong)hWnd);
 968     CheckAndClearException(GetEnv());
 969 }
 970 
 971 BOOL GlassWindow::EnterFullScreenMode(GlassView * view, BOOL animate, BOOL keepRatio)
 972 {
 973     if (IsChild()) {
 974         return FALSE;
 975     }
 976     if (IsInFullScreenMode()) {
 977         return TRUE;
 978     }
 979     if (view != GetGlassView()) {
 980         STRACE(_T("EnterFullScreenMode(view = %p) while the real view for this window is: %p"), view, GetGlassView());
 981         return FALSE;
 982     }
 983 
 984     static const LONG FS_STYLE_MASK = WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_BORDER | WS_THICKFRAME;
 985     static const LONG FS_EXSTYLE_MASK = WS_EX_WINDOWEDGE;
 986 
 987     LONG style = ::GetWindowLong(GetHWND(), GWL_STYLE);
 988     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
 989 
 990     ::GetWindowRect(GetHWND(), &m_beforeFullScreenRect);
 991     m_beforeFullScreenStyle = style & FS_STYLE_MASK;
 992     m_beforeFullScreenExStyle = exStyle & FS_EXSTYLE_MASK;
 993     m_beforeFullScreenMenu = ::GetMenu(GetHWND());
 994 
 995     RECT viewRect, screenRect, contentRect;
 996 
 997     FullScreenWindow::ClientRectInScreen(GetHWND(), &viewRect);
 998     FullScreenWindow::CalculateBounds(GetHWND(), &screenRect,
 999             &contentRect, keepRatio, viewRect);
1000 
1001     //XXX: if (keepRatio) initBlackBackground(screenRect);
1002 
1003     ::SetWindowLong(GetHWND(), GWL_STYLE, style & ~FS_STYLE_MASK);
1004     ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle & ~FS_EXSTYLE_MASK);
1005 
1006     ::SetMenu(GetHWND(), NULL);
1007 
1008     ::SetWindowPos(GetHWND(), HWND_TOPMOST,
1009             contentRect.left, contentRect.top,
1010             contentRect.right - contentRect.left, contentRect.bottom - contentRect.top,
1011             SWP_FRAMECHANGED | SWP_NOCOPYBITS);
1012 
1013     m_isInFullScreen = true;
1014 
1015     return TRUE;
1016 }
1017 
1018 void GlassWindow::ExitFullScreenMode(BOOL animate)
1019 {
1020     if (IsChild() || !IsInFullScreenMode()) {
1021         return;
1022     }
1023 
1024     LONG style = ::GetWindowLong(GetHWND(), GWL_STYLE);
1025     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
1026 
1027     ::SetWindowLong(GetHWND(), GWL_STYLE, style | m_beforeFullScreenStyle);
1028     ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle | m_beforeFullScreenExStyle);
1029 
1030     ::SetMenu(GetHWND(), m_beforeFullScreenMenu);
1031 
1032     LONG swpFlags = SWP_FRAMECHANGED | SWP_NOCOPYBITS;
1033     if (!IsFocused()) {
1034         swpFlags |= SWP_NOACTIVATE;
1035     }
1036     ::SetWindowPos(GetHWND(), HWND_NOTOPMOST,
1037             m_beforeFullScreenRect.left, m_beforeFullScreenRect.top,
1038             m_beforeFullScreenRect.right - m_beforeFullScreenRect.left,
1039             m_beforeFullScreenRect.bottom - m_beforeFullScreenRect.top,
1040             swpFlags);
1041 
1042     m_isInFullScreen = false;
1043 }
1044 
1045 void GlassWindow::SetEnabled(bool enabled)
1046 {
1047     if (!enabled) {
1048         ResetMouseTracking(GetHWND());
1049     }
1050 
1051     m_isEnabled = enabled;
1052 }
1053 
1054 void GlassWindow::SetIcon(HICON hIcon)
1055 {
1056     ::SendMessage(GetHWND(), WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
1057     ::SendMessage(GetHWND(), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
1058 
1059     if (m_hIcon) {
1060         ::DestroyIcon(m_hIcon);
1061     }
1062     m_hIcon = hIcon;
1063 }
1064 
1065 /*
1066  * JNI methods section
1067  *
1068  */
1069 
1070 extern "C" {
1071 
1072 /*
1073  * Class:     com_sun_glass_ui_win_WinWindow
1074  * Method:    _initIDs
1075  * Signature: ()V
1076  */
1077 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1initIDs
1078     (JNIEnv *env, jclass cls)
1079 {
1080      midNotifyClose = env->GetMethodID(cls, "notifyClose", "()V");
1081      ASSERT(midNotifyClose);
1082      if (env->ExceptionCheck()) return;
1083 
1084      midNotifyMove = env->GetMethodID(cls, "notifyMove", "(II)V");
1085      ASSERT(midNotifyMove);
1086      if (env->ExceptionCheck()) return;
1087 
1088      midNotifyResize = env->GetMethodID(cls, "notifyResize", "(III)V");
1089      ASSERT(midNotifyResize);
1090      if (env->ExceptionCheck()) return;
1091 
1092      midNotifyScaleChanged = env->GetMethodID(cls, "notifyScaleChanged", "(FF)V");
1093      ASSERT(midNotifyScaleChanged);
1094      if (env->ExceptionCheck()) return;
1095 
1096      javaIDs.Window.notifyFocus = env->GetMethodID(cls, "notifyFocus", "(I)V");
1097      ASSERT(javaIDs.Window.notifyFocus);
1098      if (env->ExceptionCheck()) return;
1099 
1100      javaIDs.Window.notifyFocusDisabled = env->GetMethodID(cls, "notifyFocusDisabled", "()V");
1101      ASSERT(javaIDs.Window.notifyFocusDisabled);
1102      if (env->ExceptionCheck()) return;
1103 
1104      javaIDs.Window.notifyFocusUngrab = env->GetMethodID(cls, "notifyFocusUngrab", "()V");
1105      ASSERT(javaIDs.Window.notifyFocusUngrab);
1106      if (env->ExceptionCheck()) return;
1107 
1108      midNotifyMoveToAnotherScreen = env->GetMethodID(cls, "notifyMoveToAnotherScreen", "(Lcom/sun/glass/ui/Screen;)V");
1109      ASSERT(midNotifyMoveToAnotherScreen);
1110      if (env->ExceptionCheck()) return;
1111 
1112      javaIDs.Window.notifyDestroy = env->GetMethodID(cls, "notifyDestroy", "()V");
1113      ASSERT(javaIDs.Window.notifyDestroy);
1114      if (env->ExceptionCheck()) return;
1115 
1116      javaIDs.Window.notifyDelegatePtr = env->GetMethodID(cls, "notifyDelegatePtr", "(J)V");
1117      ASSERT(javaIDs.Window.notifyDelegatePtr);
1118      if (env->ExceptionCheck()) return;
1119 }
1120 
1121 /*
1122  * Class:     com_sun_glass_ui_win_WinWindow
1123  * Method:    _createWindow
1124  * Signature: (JJZI)J
1125  */
1126 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createWindow
1127     (JNIEnv *env, jobject jThis, jlong ownerPtr, jlong screenPtr, jint mask)
1128 {
1129     ENTER_MAIN_THREAD_AND_RETURN(jlong)
1130     {
1131         DWORD dwStyle;
1132         DWORD dwExStyle;
1133         bool closeable;
1134 
1135         dwStyle = WS_CLIPCHILDREN | WS_SYSMENU;
1136         closeable = (mask & com_sun_glass_ui_Window_CLOSABLE) != 0;
1137 
1138         if (mask & com_sun_glass_ui_Window_TITLED) {
1139             dwExStyle = WS_EX_WINDOWEDGE;
1140             dwStyle |= WS_CAPTION;
1141 
1142             if (mask & com_sun_glass_ui_Window_MINIMIZABLE) {
1143                 dwStyle |= WS_MINIMIZEBOX;
1144             }
1145             if (mask & com_sun_glass_ui_Window_MAXIMIZABLE) {
1146                 dwStyle |= WS_MAXIMIZEBOX;
1147             }
1148         } else {
1149             dwExStyle = 0;
1150             dwStyle |= WS_POPUP;
1151         }
1152 
1153         if (mask & com_sun_glass_ui_Window_TRANSPARENT) {
1154             dwExStyle |= WS_EX_LAYERED;
1155         }
1156 
1157         if (mask & com_sun_glass_ui_Window_POPUP) {
1158             dwStyle |= WS_POPUP;
1159             // Popups should not appear in the taskbar, so WS_EX_TOOLWINDOW
1160             dwExStyle |= WS_EX_TOOLWINDOW;
1161         }
1162 
1163         if (mask & com_sun_glass_ui_Window_UTILITY) {
1164             dwExStyle |= WS_EX_TOOLWINDOW;
1165         }
1166 
1167         if (mask & com_sun_glass_ui_Window_RIGHT_TO_LEFT) {
1168             dwExStyle |= WS_EX_NOINHERITLAYOUT | WS_EX_LAYOUTRTL;
1169         }
1170 
1171         GlassWindow *pWindow =
1172             new GlassWindow(jThis,
1173                 (mask & com_sun_glass_ui_Window_TRANSPARENT) != 0,
1174                 (mask & com_sun_glass_ui_Window_TITLED) != 0,
1175                 (mask & com_sun_glass_ui_Window_UNIFIED) != 0,
1176                 false,
1177                 owner);
1178 
1179         HWND hWnd = pWindow->Create(dwStyle, dwExStyle, hMonitor, owner);
1180 
1181         if (!hWnd) {
1182             delete pWindow;
1183         } else {
1184             if (!closeable) {
1185                 HMENU hSysMenu = ::GetSystemMenu(hWnd, FALSE);
1186                 if (hSysMenu != NULL) {
1187                     ::EnableMenuItem(hSysMenu, SC_CLOSE,
1188                             MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1189                 }
1190             }
1191         }
1192 
1193         return (jlong)hWnd;
1194     }
1195     DECL_jobject(jThis);
1196     HWND owner;
1197     HMONITOR hMonitor;
1198     jint mask;
1199     LEAVE_MAIN_THREAD;
1200 
1201     ARG(jThis) = jThis;
1202     ARG(owner) = (HWND)ownerPtr;
1203     ARG(hMonitor) = (HMONITOR)screenPtr;
1204     ARG(mask) = mask;
1205 
1206     return PERFORM_AND_RETURN();
1207 }
1208 
1209 /*
1210  * Class:     com_sun_glass_ui_win_WinWindow
1211  * Method:    _createChildWindow
1212  * Signature: (J)J
1213  */
1214 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createChildWindow
1215     (JNIEnv *env, jobject jThis, jlong parentPtr)
1216 {
1217     ENTER_MAIN_THREAD_AND_RETURN(jlong)
1218     {
1219         // Check that the 'parent' isn't a garbage value
1220         if (!::IsWindow((HWND)parent)) {
1221             return (jlong)0;
1222         }
1223 
1224         DWORD dwStyle;
1225         DWORD dwExStyle;
1226 
1227         dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD;
1228         dwExStyle = WS_EX_NOINHERITLAYOUT;
1229 
1230         GlassWindow *pWindow =
1231             new GlassWindow(jThis, false, false, false, true, parent);
1232 
1233         HWND hWnd = pWindow->Create(dwStyle, dwExStyle, NULL, parent);
1234 
1235         if (!hWnd) {
1236             delete pWindow;
1237         }
1238         pWindow->HandleWindowPosChangedEvent();
1239 
1240         return (jlong)hWnd;
1241     }
1242     DECL_jobject(jThis);
1243     HWND parent;
1244     LEAVE_MAIN_THREAD;
1245 
1246     ARG(jThis) = jThis;
1247     ARG(parent) = (HWND)parentPtr;
1248 
1249     return PERFORM_AND_RETURN();
1250 }
1251 /*
1252  * Class:     com_sun_glass_ui_win_WinWindow
1253  * Method:    _close
1254  * Signature: (J)Z
1255  */
1256 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1close
1257     (JNIEnv *env, jobject jThis, jlong ptr)
1258 {
1259     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1260     {
1261         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1262         pWindow->Close();
1263         return bool_to_jbool(::DestroyWindow(hWnd));
1264     }
1265     LEAVE_MAIN_THREAD_WITH_hWnd;
1266 
1267     return PERFORM_AND_RETURN();
1268 }
1269 
1270 /*
1271  * Class:     com_sun_glass_ui_win_WinWindow
1272  * Method:    _setView
1273  * Signature: (JJ)Z
1274  */
1275 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setView
1276     (JNIEnv * env, jobject jThis, jlong ptr, jobject view)
1277 {
1278     ENTER_MAIN_THREAD()
1279     {
1280         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1281         pWindow->ResetMouseTracking(hWnd);
1282         pWindow->SetGlassView(view);
1283         // The condition below may be restricted to WS_POPUP windows
1284         if (::IsWindowVisible(hWnd)) {
1285             pWindow->NotifyViewSize(hWnd);
1286         }
1287     }
1288     GlassView * view;
1289     LEAVE_MAIN_THREAD_WITH_hWnd;
1290 
1291     ARG(view) = view == NULL ? NULL : (GlassView*)env->GetLongField(view, javaIDs.View.ptr);
1292 
1293     PERFORM();
1294     return JNI_TRUE;
1295 }
1296 
1297 /*
1298  * Class:     com_sun_glass_ui_win_WinWindow
1299  * Method:    _setMenubar
1300  * Signature: (JJ)Z
1301  */
1302 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMenubar
1303     (JNIEnv *env, jobject jThis, jlong ptr, jlong menuPtr)
1304 {
1305     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1306     {
1307         if (::SetMenu(hWnd, hMenu))
1308         {
1309             GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1310             if (pWindow) {
1311                 pWindow->SetMenu(hMenu);
1312             }
1313 
1314             return JNI_TRUE;
1315         }
1316         return JNI_FALSE;
1317     }
1318     HMENU hMenu;
1319     LEAVE_MAIN_THREAD_WITH_hWnd;
1320 
1321     ARG(hMenu) = (HMENU)menuPtr;
1322     return PERFORM_AND_RETURN();
1323 }
1324 
1325 /*
1326  * Class:     com_sun_glass_ui_win_WinWindow
1327  * Method:    _setLevel
1328  * Signature: (JI)V
1329  */
1330 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setLevel
1331 (JNIEnv *env, jobject jwindow, jlong ptr, jint jLevel)
1332 {
1333     ENTER_MAIN_THREAD()
1334     {
1335         ::SetWindowPos(hWnd, hWndInsertAfter, 0, 0, 0, 0,
1336                 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
1337     }
1338     HWND hWndInsertAfter;
1339     LEAVE_MAIN_THREAD_WITH_hWnd;
1340 
1341     ARG(hWndInsertAfter) = HWND_NOTOPMOST;
1342     switch (jLevel) {
1343         case com_sun_glass_ui_Window_Level_FLOATING:
1344         case com_sun_glass_ui_Window_Level_TOPMOST:
1345             ARG(hWndInsertAfter) = HWND_TOPMOST;
1346             break;
1347     }
1348     PERFORM();
1349 }
1350 
1351 /*
1352  * Class:     com_sun_glass_ui_win_WinWindow
1353  * Method:    _setFocusable
1354  * Signature: (JZ)V
1355  */
1356 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setFocusable
1357 (JNIEnv *env, jobject jwindow, jlong ptr, jboolean isFocusable)
1358 {
1359     ENTER_MAIN_THREAD()
1360     {
1361         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1362         pWindow->SetFocusable(isFocusable);
1363     }
1364     bool isFocusable;
1365     LEAVE_MAIN_THREAD_WITH_hWnd;
1366 
1367     ARG(isFocusable) = isFocusable == JNI_TRUE;
1368     PERFORM();
1369 }
1370 
1371 /*
1372  * Class:     com_sun_glass_ui_win_WinWindow
1373  * Method:    _setEnabled
1374  * Signature: (JZ)V
1375  */
1376 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setEnabled
1377 (JNIEnv *env, jobject jwindow, jlong ptr, jboolean isEnabled)
1378 {
1379     ENTER_MAIN_THREAD()
1380     {
1381         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1382         pWindow->SetEnabled(isEnabled);
1383         ::EnableWindow(hWnd, isEnabled);
1384     }
1385     bool isEnabled;
1386     LEAVE_MAIN_THREAD_WITH_hWnd;
1387 
1388     ARG(isEnabled) = isEnabled == JNI_TRUE;
1389     PERFORM();
1390 }
1391 
1392 // Converts a float [0..1] to a BYTE [0..255]
1393 #define F2B(value) BYTE(255.f * (value))
1394 
1395 /*
1396  * Class:     com_sun_glass_ui_win_WinWindow
1397  * Method:    _setAlpha
1398  * Signature: (JF)V
1399  */
1400 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setAlpha
1401     (JNIEnv *env, jobject jThis, jlong ptr, jfloat alpha)
1402 {
1403     ENTER_MAIN_THREAD()
1404     {
1405         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1406         pWindow->SetAlpha(alpha);
1407     }
1408     BYTE alpha;
1409     LEAVE_MAIN_THREAD_WITH_hWnd;
1410 
1411     ARG(alpha) = F2B(alpha);
1412     PERFORM();
1413 }
1414 
1415 /*
1416  * Class:     com_sun_glass_ui_win_WinWindow
1417  * Method:    _setBackground
1418  * Signature: (JFFF)Z
1419  */
1420 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setBackground
1421     (JNIEnv *env, jobject jThis, jlong ptr, jfloat r, jfloat g, jfloat b)
1422 {
1423     ENTER_MAIN_THREAD()
1424     {
1425         HBRUSH hbrBackground;
1426 
1427         // That's a hack with 'negative' color
1428         if (r < 0) {
1429             hbrBackground = NULL;
1430         } else {
1431             hbrBackground = ::CreateSolidBrush(RGB(F2B(r), F2B(g), F2B(b)));
1432         }
1433 
1434         HBRUSH oldBrush = (HBRUSH)::SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)hbrBackground);
1435 
1436         if (oldBrush) {
1437             ::DeleteObject(oldBrush);
1438         }
1439     }
1440     jfloat r, g, b;
1441     LEAVE_MAIN_THREAD_WITH_hWnd;
1442 
1443     ARG(r) = r;
1444     ARG(g) = g;
1445     ARG(b) = b;
1446     PERFORM();
1447 
1448     return JNI_TRUE;
1449 }
1450 
1451 /*
1452  * Class:     com_sun_glass_ui_win_WinWindow
1453  * Method:    _setBounds
1454  * Signature: (JIIZZIIIIFF)Z
1455  */
1456 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setBounds
1457     (JNIEnv *env, jobject jThis, jlong ptr,
1458      jint x, jint y, jboolean xSet, jboolean ySet,
1459      jint w, jint h, jint cw, jint ch,
1460      jfloat xGravity, jfloat yGravity)
1461 {
1462     ENTER_MAIN_THREAD()
1463     {
1464         if (!::IsWindow(hWnd)) return;
1465         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1466 
1467         pWindow->UpdateInsets();
1468         RECT is = pWindow->GetInsets();
1469 
1470         RECT r;
1471         ::GetWindowRect(hWnd, &r);
1472 
1473         int newX = jbool_to_bool(xSet) ? x : r.left;
1474         int newY = jbool_to_bool(ySet) ? y : r.top;
1475         int newW = w > 0 ? w :
1476                        cw > 0 ? cw + is.right + is.left : r.right - r.left;
1477         int newH = h > 0 ? h :
1478                        ch > 0 ? ch + is.bottom + is.top : r.bottom - r.top;
1479 
1480         if (xSet || ySet) {
1481             ::SetWindowPos(hWnd, NULL, newX, newY, newW, newH,
1482                            SWP_NOACTIVATE | SWP_NOZORDER);
1483         } else {
1484             ::SetWindowPos(hWnd, NULL, 0, 0, newW, newH,
1485                            SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
1486         }
1487     }
1488     jint x, y;
1489     jboolean xSet, ySet;
1490     jint w, h, cw, ch;
1491     LEAVE_MAIN_THREAD_WITH_hWnd;
1492 
1493     ARG(x) = x;
1494     ARG(y) = y;
1495     ARG(xSet) = xSet;
1496     ARG(ySet) = ySet;
1497     ARG(w) = w;
1498     ARG(h) = h;
1499     ARG(cw) = cw;
1500     ARG(ch) = ch;
1501     PERFORM();
1502 
1503 }
1504 
1505 /*
1506  * Class:     com_sun_glass_ui_win_WinWindow
1507  * Method:    _setTitle
1508  * Signature: (JLjava/lang/String;)Z
1509  */
1510 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setTitle
1511     (JNIEnv *env, jobject jThis, jlong ptr, jstring jTitle)
1512 {
1513     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1514     {
1515         if (::SetWindowText(hWnd, title)) {
1516             return JNI_TRUE;
1517         }
1518         return JNI_FALSE;
1519     }
1520     LPCTSTR title;
1521     LEAVE_MAIN_THREAD_WITH_hWnd;
1522 
1523     JString title(env, jTitle);
1524     ARG(title) = title;
1525     return PERFORM_AND_RETURN();
1526 }
1527 
1528 /*
1529  * Class:     com_sun_glass_ui_win_WinWindow
1530  * Method:    _setResizable
1531  * Signature: (Z)Z
1532  */
1533 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setResizable
1534 (JNIEnv *env, jobject jWindow, jlong ptr, jboolean jResizable)
1535 {
1536     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1537     {
1538         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1539         if (pWindow && pWindow->SetResizable(jbool_to_bool(jResizable))) {
1540             return JNI_TRUE;
1541         }
1542 
1543         return JNI_FALSE;
1544     }
1545     jboolean jResizable;
1546     LEAVE_MAIN_THREAD_WITH_hWnd;
1547 
1548     ARG(jResizable) = jResizable;
1549     return PERFORM_AND_RETURN();
1550 }
1551 
1552 /*
1553  * Class:     com_sun_glass_ui_win_WinWindow
1554  * Method:    _setVisible
1555  * Signature: (JZ)Z
1556  */
1557 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setVisible
1558     (JNIEnv *env, jobject jThis, jlong ptr, jboolean visible)
1559 {
1560     ENTER_MAIN_THREAD()
1561     {
1562         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1563         if (!visible) {
1564             if (pWindow) {
1565                 pWindow->UngrabFocus();
1566             }
1567         }
1568         
1569         ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE);
1570         
1571         if (visible) {
1572             if (pWindow) {
1573                 if (pWindow->IsFocusable()) {
1574                     ::SetForegroundWindow(hWnd);
1575                 } else {
1576                     // RT-14197:
1577                     // On some latest platform versions, unfocusable windows
1578                     // are shown below the currently active window, so we
1579                     // need to pull them to front explicitly. However,
1580                     // neither BringWindowToTop nor SetForegroundWindow()
1581                     // can be used because of the window unfocusability, so
1582                     // here is a workaround: we first made the window TOPMOST
1583                     // and then reset this flag to just TOP.
1584                     ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
1585                                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
1586                     ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0,
1587                                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
1588                 }
1589             }
1590             ::UpdateWindow(hWnd);
1591         }
1592     }
1593     jboolean visible;
1594     LEAVE_MAIN_THREAD_WITH_hWnd;
1595 
1596     ARG(visible) = visible;
1597     PERFORM();
1598     return visible;
1599 }
1600 
1601 /*
1602  * Class:     com_sun_glass_ui_win_WinWindow
1603  * Method:    _requestFocus
1604  * Signature: (JI)Z
1605  */
1606 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1requestFocus
1607     (JNIEnv *env, jobject jThis, jlong ptr, jint event)
1608 {
1609     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1610     {
1611         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1612         return bool_to_jbool(pWindow && pWindow->RequestFocus(event));
1613     }
1614     jint event;
1615     LEAVE_MAIN_THREAD_WITH_hWnd;
1616 
1617     ARG(event) = event;
1618 
1619     return PERFORM_AND_RETURN();
1620 }
1621 
1622 /*
1623  * Class:     com_sun_glass_ui_win_WinWindow
1624  * Method:    _grabFocus
1625  * Signature: (J)Z
1626  */
1627 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1grabFocus
1628     (JNIEnv *env, jobject jThis, jlong ptr)
1629 {
1630     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1631     {
1632         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1633         return bool_to_jbool(pWindow && pWindow->GrabFocus());
1634     }
1635     LEAVE_MAIN_THREAD_WITH_hWnd;
1636 
1637     return PERFORM_AND_RETURN();
1638 }
1639 
1640 /*
1641  * Class:     com_sun_glass_ui_win_WinWindow
1642  * Method:    _ungrabFocus
1643  * Signature: (J)V
1644  */
1645 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1ungrabFocus
1646     (JNIEnv *env, jobject jThis, jlong ptr)
1647 {
1648     ENTER_MAIN_THREAD()
1649     {
1650         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1651         if (pWindow) {
1652             pWindow->UngrabFocus();
1653         }
1654     }
1655     LEAVE_MAIN_THREAD_WITH_hWnd;
1656 
1657     PERFORM();
1658 }
1659 
1660 /*
1661  * Class:     com_sun_glass_ui_win_WinWindow
1662  * Method:    _minimize
1663  * Signature: (JZ)Z
1664  */
1665 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1minimize
1666     (JNIEnv *env, jobject jThis, jlong ptr, jboolean minimize)
1667 {
1668     ENTER_MAIN_THREAD()
1669     {
1670         ::ShowWindow(hWnd, minimize ? SW_MINIMIZE : SW_RESTORE);
1671     }
1672     jboolean minimize;
1673     LEAVE_MAIN_THREAD_WITH_hWnd;
1674 
1675     ARG(minimize) = minimize;
1676     PERFORM();
1677 
1678     return JNI_TRUE;
1679 }
1680 
1681 /*
1682  * Class:     com_sun_glass_ui_win_WinWindow
1683  * Method:    _maximize
1684  * Signature: (JZ)Z
1685  */
1686 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1maximize
1687   (JNIEnv *env, jobject jThis, jlong ptr, jboolean maximize, jboolean wasMaximized)
1688 {
1689     ENTER_MAIN_THREAD()
1690     {
1691         ::ShowWindow(hWnd, maximize ? SW_MAXIMIZE : SW_RESTORE);
1692     }
1693     jboolean maximize;
1694     LEAVE_MAIN_THREAD_WITH_hWnd;
1695 
1696     ARG(maximize) = maximize;
1697     PERFORM();
1698 
1699     return JNI_TRUE;
1700 }
1701 
1702 /*
1703  * Class:     com_sun_glass_ui_win_WinWindow
1704  * Method:    _setMinimumSize
1705  * Signature: (JII)Z
1706  */
1707 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMinimumSize
1708     (JNIEnv *env, jobject jThis, jlong ptr, jint minWidth, jint minHeight)
1709 {
1710     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1711     {
1712         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1713         if (pWindow) {
1714             pWindow->setMinSize(minWidth, minHeight);
1715             return JNI_TRUE;
1716         }
1717         return JNI_FALSE;
1718     }
1719     jint minWidth;
1720     jint minHeight;
1721     LEAVE_MAIN_THREAD_WITH_hWnd;
1722 
1723     ARG(minWidth) = minWidth == 0 ? -1 : minWidth;
1724     ARG(minHeight) = minHeight == 0 ? -1 : minHeight;
1725     return PERFORM_AND_RETURN();
1726 }
1727 
1728 /*
1729  * Class:     com_sun_glass_ui_win_WinWindow
1730  * Method:    _setMaximumSize
1731  * Signature: (JII)Z
1732  */
1733 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMaximumSize
1734     (JNIEnv *env, jobject jThis, jlong ptr, jint maxWidth, jint maxHeight)
1735 {
1736     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1737     {
1738         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1739         if (pWindow) {
1740             pWindow->setMaxSize(maxWidth, maxHeight);
1741             return JNI_TRUE;
1742         }
1743         return JNI_FALSE;
1744     }
1745     jint maxWidth;
1746     jint maxHeight;
1747     LEAVE_MAIN_THREAD_WITH_hWnd;
1748 
1749     ARG(maxWidth) = maxWidth;
1750     ARG(maxHeight) = maxHeight;
1751     return PERFORM_AND_RETURN();
1752 }
1753 
1754 /*
1755  * Class:     com_sun_glass_ui_win_WinWindow
1756  * Method:    _setIcon
1757  * Signature: (JLcom/sun/glass/ui/Pixels;)V
1758  */
1759 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setIcon
1760     (JNIEnv *env, jobject jThis, jlong ptr, jobject jPixels)
1761 {
1762     HWND hWnd = (HWND)ptr;
1763     GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1764     if (pWindow) {
1765         pWindow->SetIcon(!jPixels ? NULL : Pixels::CreateIcon(env, jPixels));
1766     }
1767 }
1768 
1769 /*
1770  * Class:     com_sun_glass_ui_win_WinWindow
1771  * Method:    _toFront
1772  * Signature: (J)V
1773  */
1774 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1toFront
1775     (JNIEnv *env, jobject jThis, jlong ptr)
1776 {
1777     ENTER_MAIN_THREAD()
1778     {
1779         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1780         // See comment in __1setVisible() above about unfocusable windows
1781         if (pWindow && !pWindow->IsFocusable()) {
1782             ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1783         }
1784         ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1785     }
1786     LEAVE_MAIN_THREAD_WITH_hWnd;
1787 
1788     PERFORM();
1789 }
1790 
1791 /*
1792  * Class:     com_sun_glass_ui_win_WinWindow
1793  * Method:    _toBack
1794  * Signature: (J)V
1795  */
1796 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1toBack
1797     (JNIEnv *env, jobject jThis, jlong ptr)
1798 {
1799     ENTER_MAIN_THREAD()
1800     {
1801         ::SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1802     }
1803     LEAVE_MAIN_THREAD_WITH_hWnd;
1804 
1805     PERFORM();
1806 }
1807 
1808 /*
1809  * Class:     com_sun_glass_ui_win_WinWindow
1810  * Method:    _getEmbeddedX
1811  * Signature: (J)I
1812  */
1813 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinWindow__1getEmbeddedX
1814     (JNIEnv *env, jobject jThis, jlong ptr)
1815 {
1816     ENTER_MAIN_THREAD_AND_RETURN(jint)
1817     {
1818         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1819         HWND delegateHWnd = pWindow ? pWindow->GetDelegateWindow() : 0;
1820         RECT rect = {0};
1821         ::MapWindowPoints(delegateHWnd ? delegateHWnd : hWnd, (HWND)NULL, (LPPOINT)&rect, (sizeof(RECT)/sizeof(POINT)));
1822         return rect.left;
1823     }
1824     LEAVE_MAIN_THREAD_WITH_hWnd;
1825 
1826     return PERFORM_AND_RETURN();
1827 }
1828 
1829 /*
1830  * Class:     com_sun_glass_ui_win_WinWindow
1831  * Method:    _getEmbeddedY
1832  * Signature: (J)I
1833  */
1834 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinWindow__1getEmbeddedY
1835     (JNIEnv *env, jobject jThis, jlong ptr)
1836 {
1837     ENTER_MAIN_THREAD_AND_RETURN(jint)
1838     {
1839         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1840         HWND delegateHWnd = pWindow ? pWindow->GetDelegateWindow() : 0;
1841         RECT rect = {0};
1842         ::MapWindowPoints(delegateHWnd ? delegateHWnd : hWnd, (HWND)NULL, (LPPOINT)&rect, (sizeof(RECT)/sizeof(POINT)));
1843         return rect.top;
1844     }
1845     LEAVE_MAIN_THREAD_WITH_hWnd;
1846 
1847     return PERFORM_AND_RETURN();
1848 }
1849 
1850 /*
1851  * Class:     com_sun_glass_ui_win_WinWindow
1852  * Method:    _setCursor
1853  * Signature: (Lcom/sun/glass/ui/Cursor;)V
1854  */
1855 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setCursor
1856     (JNIEnv *env, jobject jThis, jlong ptr, jobject jCursor)
1857 {
1858     ENTER_MAIN_THREAD()
1859     {
1860         const HCURSOR cursor = JCursorToHCURSOR(GetEnv(), jCursor);
1861 
1862         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1863         if (pWindow) {
1864             pWindow->SetCursor(cursor);
1865 
1866             // Update the delegate window as well if present
1867             HWND delegateHwnd = pWindow->GetDelegateWindow();
1868             if (delegateHwnd) {
1869                 BaseWnd *pDelegateWindow = BaseWnd::FromHandle(delegateHwnd);
1870                 if (pDelegateWindow) {
1871                     pDelegateWindow->SetCursor(cursor);
1872                 }
1873             }
1874         }
1875     }
1876     DECL_jobject(jCursor);
1877     LEAVE_MAIN_THREAD_WITH_hWnd;
1878 
1879     ARG(jCursor) = jCursor;
1880     PERFORM();
1881 }
1882 
1883 }   // extern "C"