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