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     if (GlassApplication::IsUIScaleOverridden()) {
 651         return;
 652     }
 653 
 654     UINT xDPI = LOWORD(wParam);
 655     UINT yDPI = HIWORD(wParam);
 656 
 657     JNIEnv* env = GetEnv();
 658     jfloat xScale = xDPI / ((float) USER_DEFAULT_SCREEN_DPI);
 659     jfloat yScale = yDPI / ((float) USER_DEFAULT_SCREEN_DPI);
 660     env->CallVoidMethod(m_grefThis, midNotifyScaleChanged, xScale, yScale, xScale, yScale);
 661     CheckAndClearException(env);
 662 
 663     // Windows provides new bounds for the window, but they assume that
 664     // all parts (client and non-client) will be rescaled equally.
 665     // Unfortunately, the basic window decoration support does not scale
 666     // so we need to adjust the new bounds to represent the new intended
 667     // client dimensions padded for the unchanging frame border.
 668     LPRECT lprcNewBounds = (LPRECT) lParam;
 669     RECT oldBounds, oldClient, padding, newClient, newBounds;
 670     ::GetWindowRect(GetHWND(), &oldBounds);
 671     ::GetClientRect(GetHWND(), &oldClient);
 672     float rescaleX = ((float) (lprcNewBounds->right - lprcNewBounds->left)) /
 673                               (oldBounds.right - oldBounds.left);
 674     float rescaleY = ((float) (lprcNewBounds->bottom - lprcNewBounds->top)) /
 675                               (oldBounds.bottom - oldBounds.top);
 676 
 677     // First compute the padding between non-client and client for the old
 678     // values for the window.  This is the size of the frame border
 679     // decorations.  These will remain unchanged after the change in DPI.
 680     padding.left   = oldClient.left   - oldBounds.left;
 681     padding.top    = oldClient.top    - oldBounds.top;
 682     padding.right  = oldBounds.right  - oldClient.right;
 683     padding.bottom = oldBounds.bottom - oldClient.bottom;
 684 
 685     // Next compute the correctly scaled new dimensions for the client
 686     // area, based on the ratio of the old window bounds to the suggested
 687     // new window bounds.
 688     jint newClientW = (jint) ceil((oldClient.right - oldClient.left) * rescaleX);
 689     jint newClientH = (jint) ceil((oldClient.bottom - oldClient.top) * rescaleY);
 690 
 691     // Next compute the new client bounds implied by the values provided by
 692     // the WM event data
 693     newClient.left   = lprcNewBounds->left   + padding.left;
 694     newClient.top    = lprcNewBounds->top    + padding.top;
 695     newClient.right  = newClient.left + newClientW;
 696     newClient.bottom = newClient.top  + newClientH;
 697 
 698     // Finally, compute the new bounds of the window by padding out the
 699     // correctly scaled new client region.
 700     newBounds.left   = newClient.left   - padding.left;
 701     newBounds.top    = newClient.top    - padding.top;
 702     newBounds.right  = newClient.right  + padding.right;
 703     newBounds.bottom = newClient.bottom + padding.bottom;
 704 #if 0
 705     POINT cursor;
 706     ::GetCursorPos(&cursor);
 707     fprintf(stderr, "    @ %d, %d\n", cursor.x, cursor.y);
 708     fprintf(stderr, "    (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d]\n",
 709             oldClient.left,   oldClient.top,  oldClient.right,   oldClient.bottom,
 710             oldClient.right - oldClient.left, oldClient.bottom - oldClient.top,
 711             oldBounds.left,   oldBounds.top,  oldBounds.right,   oldBounds.bottom,
 712             oldBounds.right - oldBounds.left, oldBounds.bottom - oldBounds.top);
 713     fprintf(stderr, "    => (suggested) (%d, %d, %d, %d) [%d x %d]\n",
 714             lprcNewBounds->left,   lprcNewBounds->top,  lprcNewBounds->right,   lprcNewBounds->bottom,
 715             lprcNewBounds->right - lprcNewBounds->left, lprcNewBounds->bottom - lprcNewBounds->top);
 716     fprintf(stderr, "    => (recomputed) (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d]\n",
 717             newClient.left,   newClient.top,  newClient.right,   newClient.bottom,
 718             newClient.right - newClient.left, newClient.bottom - newClient.top,
 719             newBounds.left,   newBounds.top,  newBounds.right,   newBounds.bottom,
 720             newBounds.right - newBounds.left, newBounds.bottom - newBounds.top);
 721 #endif
 722     ::SetWindowPos(GetHWND(), HWND_TOP,
 723                    newBounds.left,
 724                    newBounds.top,
 725                    newBounds.right  - newBounds.left,
 726                    newBounds.bottom - newBounds.top,
 727                    SWP_NOZORDER | SWP_NOACTIVATE);
 728 }
 729 
 730 void GlassWindow::HandleWindowPosChangedEvent()
 731 {
 732     JNIEnv* env = GetEnv();
 733 
 734     HMONITOR toMonitor = ::MonitorFromWindow(GetHWND(), MONITOR_DEFAULTTOPRIMARY);
 735     HMONITOR fromMonitor = GetMonitor();
 736     if (toMonitor != fromMonitor) {
 737 //        fprintf(stderr, "Monitor changed!\n");
 738         env->CallVoidMethod(m_grefThis, midNotifyMoveToAnotherScreen,
 739                             GlassScreen::GetJavaMonitor(env, toMonitor));
 740         CheckAndClearException(env);
 741         SetMonitor(toMonitor);
 742     }
 743 }
 744 
 745 void GlassWindow::HandleActivateEvent(jint event)
 746 {
 747     const bool active = event != com_sun_glass_events_WindowEvent_FOCUS_LOST;
 748 
 749     if (!active) {
 750         UngrabFocus();
 751     }
 752 
 753     JNIEnv* env = GetEnv();
 754     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocus, event);
 755     CheckAndClearException(env);
 756 }
 757 
 758 void GlassWindow::HandleFocusDisabledEvent()
 759 {
 760     JNIEnv* env = GetEnv();
 761 
 762     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocusDisabled);
 763     CheckAndClearException(env);
 764 }
 765 
 766 bool GlassWindow::HandleCommand(WORD cmdID) {
 767     return HandleMenuCommand(GetHWND(), cmdID);
 768 }
 769 
 770 HMONITOR GlassWindow::GetMonitor()
 771 {
 772     return m_hMonitor;
 773 }
 774 
 775 void GlassWindow::SetMonitor(HMONITOR hMonitor)
 776 {
 777     m_hMonitor = hMonitor;
 778 }
 779 
 780 void GlassWindow::SetAlpha(BYTE alpha)
 781 {
 782     m_alpha = alpha;
 783 
 784     if (m_isTransparent) {
 785         // If the window is transparent, the opacity is handled in
 786         // uploadPixels() below (see BLENDFUNCTION structure
 787         // and its SourceConstantAlpha member)
 788         return;
 789     }
 790 
 791     // The window is opaque. We make it layered temporarily only when
 792     // its alpha is less than 0xFF.
 793     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
 794 
 795     if (alpha == 0xFF) {
 796         if (exStyle & WS_EX_LAYERED) {
 797             ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED);
 798         }
 799     } else {
 800         if (!(exStyle & WS_EX_LAYERED)) {
 801             ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
 802         }
 803         ::SetLayeredWindowAttributes(GetHWND(), RGB(0, 0, 0), alpha, LWA_ALPHA);
 804     }
 805 }
 806 
 807 void GlassWindow::UpdateInsets()
 808 {
 809     if (::IsIconic(GetHWND())) {
 810         return;
 811     }
 812 
 813     RECT outer, inner;
 814 
 815     ::GetWindowRect(GetHWND(), &outer);
 816     ::GetClientRect(GetHWND(), &inner);
 817 
 818     ::MapWindowPoints(GetHWND(), (HWND)NULL, (LPPOINT)&inner, (sizeof(RECT)/sizeof(POINT)));
 819 
 820     m_insets.top = inner.top - outer.top;
 821     m_insets.left = inner.left - outer.left;
 822     m_insets.bottom = outer.bottom - inner.bottom;
 823     m_insets.right = outer.right - inner.right;
 824 
 825     if (m_insets.top < 0 || m_insets.left < 0 ||
 826             m_insets.bottom < 0 || m_insets.right < 0)
 827     {
 828         if (!IsDecorated()) {
 829             ::ZeroMemory(&m_insets, sizeof(m_insets));
 830         } else {
 831             if (GetStyle() & WS_THICKFRAME) {
 832                 m_insets.left = m_insets.right =
 833                     ::GetSystemMetrics(SM_CXSIZEFRAME);
 834                 m_insets.top = m_insets.bottom =
 835                     ::GetSystemMetrics(SM_CYSIZEFRAME);
 836             } else {
 837                 m_insets.left = m_insets.right =
 838                     ::GetSystemMetrics(SM_CXDLGFRAME);
 839                 m_insets.top = m_insets.bottom =
 840                     ::GetSystemMetrics(SM_CYDLGFRAME);
 841             }
 842 
 843             m_insets.top += ::GetSystemMetrics(SM_CYCAPTION);
 844         }
 845         if (GetMenu()) {
 846             //Well, if menu wraps on multiple lines... sorry about that.
 847             m_insets.top += ::GetSystemMetrics(SM_CYMENU);
 848         }
 849     }
 850 }
 851 
 852 bool GlassWindow::SetResizable(bool resizable)
 853 {
 854     LONG style = GetStyle();
 855 
 856     if (style & WS_CHILD) {
 857         return false;
 858     }
 859 
 860     LONG resizableStyle = WS_MAXIMIZEBOX;
 861     if (IsDecorated()) {
 862         resizableStyle |= WS_THICKFRAME;
 863     }
 864 
 865     if (resizable) {
 866         style |= resizableStyle;
 867     } else {
 868         style &= ~resizableStyle;
 869     }
 870 
 871     SetStyle(style);
 872     m_isResizable = resizable;
 873 
 874     return true;
 875 }
 876 
 877 /* static */ void GlassWindow::ResetGrab()
 878 {
 879     if (sm_grabWindow) {
 880         GlassWindow *pWindow = GlassWindow::FromHandle(sm_grabWindow);
 881         if (pWindow) {
 882             pWindow->UngrabFocus();
 883         }
 884         sm_grabWindow = NULL;
 885     }
 886 }
 887 
 888 bool GlassWindow::GrabFocus()
 889 {
 890     HWND hwnd = GetCurrentHWND();
 891 
 892     if (sm_grabWindow == hwnd) {
 893         // Already grabbed
 894         return true;
 895     }
 896 
 897     GlassWindow::ResetGrab();
 898 
 899     sm_grabWindow = hwnd;
 900 
 901     return true;
 902 }
 903 
 904 void GlassWindow::UngrabFocus()
 905 {
 906     HWND hwnd = GetCurrentHWND();
 907 
 908     if (hwnd != sm_grabWindow) {
 909         return;
 910     }
 911 
 912     JNIEnv* env = GetEnv();
 913     env->CallVoidMethod(m_grefThis, javaIDs.Window.notifyFocusUngrab);
 914     CheckAndClearException(env);
 915 
 916     sm_grabWindow = NULL;
 917 }
 918 
 919 void GlassWindow::CheckUngrab()
 920 {
 921     if (!sm_grabWindow) {
 922         return;
 923     }
 924 
 925     // If this window doesn't belong to an owned windows hierarchy that
 926     // holds the grab currently, then the grab should be released.
 927     // Fix RT-16490: use GetAncestor() instead of ::GetParent() to support embedded windows
 928     for (BaseWnd * window = this; window != NULL; window = BaseWnd::FromHandle(window->GetAncestor())) {
 929         if (window->GetHWND() == sm_grabWindow) {
 930             return;
 931         }
 932     }
 933 
 934     GlassWindow::ResetGrab();
 935 }
 936 
 937 bool GlassWindow::RequestFocus(jint event)
 938 {
 939     if (!IsChild()) {
 940         ASSERT(event == com_sun_glass_events_WindowEvent_FOCUS_GAINED);
 941         // The event will be delivered as a part of WM_ACTIVATE message handling
 942         return ::SetForegroundWindow(GetHWND()) != FALSE;
 943     }
 944 
 945     if (event == com_sun_glass_events_WindowEvent_FOCUS_LOST) {
 946         if (IsFocused()) {
 947             ::SetFocus(NULL);
 948         }
 949 
 950         return true;
 951     }
 952 
 953     // First try to activate the toplevel window
 954     HWND toplevel = ::GetAncestor(GetHWND(), GA_ROOT);
 955     if (::GetForegroundWindow() != toplevel && !::SetForegroundWindow(toplevel)) {
 956         // We're unable to bring our top-level window to foreground.
 957         // But since it anyway becomes active, we (or the plugin) won't receive
 958         // any subsequent notifications. So let's pretend we got the focus -
 959         //IGNORE: return false;
 960         //We'll anyway get a reasonable response from the ::SetFocus() later
 961     }
 962 
 963     m_focusEvent = event; // reset upon WM_SETFOCUS
 964 
 965     // If we request focus from 'nowhere', the SetFocus may still return NULL I guess
 966     return ::SetFocus(GetHWND()) != NULL || ::GetLastError() == 0;
 967 }
 968 
 969 static BOOL CALLBACK EnumChildWndProc(HWND hwnd, LPARAM lParam)
 970 {
 971     HWND * hwnds = (HWND*)lParam;
 972 
 973     ::SetParent(hwnd, hwnds[1]);
 974 
 975     BaseWnd * window = BaseWnd::FromHandle(hwnd);
 976     if (window) {
 977         window->SetAncestor(hwnds[1]);
 978     }
 979 
 980     return TRUE;
 981 }
 982 
 983 static BOOL CALLBACK EnumOwnedWndProc(HWND hwnd, LPARAM lParam)
 984 {
 985     HWND * hwnds = (HWND*)lParam;
 986 
 987     GlassWindow * window = NULL;
 988     if ((HWND)::GetWindowLongPtr(hwnd, GWLP_HWNDPARENT) == hwnds[0] && (window = GlassWindow::FromHandle(hwnd)) != NULL) {
 989         ::SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONG_PTR)hwnds[1]);
 990         window->SetAncestor(hwnds[1]);
 991         ::SetWindowPos(hwnd, hwnds[1], 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOACTIVATE);
 992     }
 993 
 994     return TRUE;
 995 }
 996 
 997 void GlassWindow::SetDelegateWindow(HWND hWnd)
 998 {
 999     if (m_delegateWindow == hWnd) {
1000         return;
1001     }
1002 
1003     // Make sure any popups are hidden
1004     UngrabFocus();
1005 
1006     HWND hwnds[2]; // [0] = from; [1] = to;
1007 
1008     hwnds[0] = m_delegateWindow ? m_delegateWindow : GetHWND();
1009     hwnds[1] = hWnd ? hWnd : GetHWND();
1010 
1011     STRACE(_T("SetDelegateWindow: from %p to %p"), hwnds[0], hwnds[1]);
1012 
1013     // Reparent child, and then owned windows
1014     ::EnumChildWindows(hwnds[0], &EnumChildWndProc, (LPARAM)&hwnds);
1015     ::EnumThreadWindows(GlassApplication::GetMainThreadId(), &EnumOwnedWndProc, (LPARAM)&hwnds);
1016 
1017     m_delegateWindow = hWnd;
1018 
1019     GetEnv()->CallVoidMethod(m_grefThis,
1020             javaIDs.Window.notifyDelegatePtr, (jlong)hWnd);
1021     CheckAndClearException(GetEnv());
1022 }
1023 
1024 BOOL GlassWindow::EnterFullScreenMode(GlassView * view, BOOL animate, BOOL keepRatio)
1025 {
1026     if (IsChild()) {
1027         return FALSE;
1028     }
1029     if (IsInFullScreenMode()) {
1030         return TRUE;
1031     }
1032     if (view != GetGlassView()) {
1033         STRACE(_T("EnterFullScreenMode(view = %p) while the real view for this window is: %p"), view, GetGlassView());
1034         return FALSE;
1035     }
1036 
1037     static const LONG FS_STYLE_MASK = WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_BORDER | WS_THICKFRAME;
1038     static const LONG FS_EXSTYLE_MASK = WS_EX_WINDOWEDGE;
1039 
1040     LONG style = ::GetWindowLong(GetHWND(), GWL_STYLE);
1041     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
1042 
1043     ::GetWindowRect(GetHWND(), &m_beforeFullScreenRect);
1044     m_beforeFullScreenStyle = style & FS_STYLE_MASK;
1045     m_beforeFullScreenExStyle = exStyle & FS_EXSTYLE_MASK;
1046     m_beforeFullScreenMenu = ::GetMenu(GetHWND());
1047 
1048     RECT viewRect, screenRect, contentRect;
1049 
1050     FullScreenWindow::ClientRectInScreen(GetHWND(), &viewRect);
1051     FullScreenWindow::CalculateBounds(GetHWND(), &screenRect,
1052             &contentRect, keepRatio, viewRect);
1053 
1054     //XXX: if (keepRatio) initBlackBackground(screenRect);
1055 
1056     ::SetWindowLong(GetHWND(), GWL_STYLE, style & ~FS_STYLE_MASK);
1057     ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle & ~FS_EXSTYLE_MASK);
1058 
1059     ::SetMenu(GetHWND(), NULL);
1060 
1061     ::SetWindowPos(GetHWND(), HWND_TOPMOST,
1062             contentRect.left, contentRect.top,
1063             contentRect.right - contentRect.left, contentRect.bottom - contentRect.top,
1064             SWP_FRAMECHANGED | SWP_NOCOPYBITS);
1065 
1066     m_isInFullScreen = true;
1067 
1068     return TRUE;
1069 }
1070 
1071 void GlassWindow::ExitFullScreenMode(BOOL animate)
1072 {
1073     if (IsChild() || !IsInFullScreenMode()) {
1074         return;
1075     }
1076 
1077     LONG style = ::GetWindowLong(GetHWND(), GWL_STYLE);
1078     LONG exStyle = ::GetWindowLong(GetHWND(), GWL_EXSTYLE);
1079 
1080     ::SetWindowLong(GetHWND(), GWL_STYLE, style | m_beforeFullScreenStyle);
1081     ::SetWindowLong(GetHWND(), GWL_EXSTYLE, exStyle | m_beforeFullScreenExStyle);
1082 
1083     ::SetMenu(GetHWND(), m_beforeFullScreenMenu);
1084 
1085     LONG swpFlags = SWP_FRAMECHANGED | SWP_NOCOPYBITS;
1086     if (!IsFocused()) {
1087         swpFlags |= SWP_NOACTIVATE;
1088     }
1089     ::SetWindowPos(GetHWND(), HWND_NOTOPMOST,
1090             m_beforeFullScreenRect.left, m_beforeFullScreenRect.top,
1091             m_beforeFullScreenRect.right - m_beforeFullScreenRect.left,
1092             m_beforeFullScreenRect.bottom - m_beforeFullScreenRect.top,
1093             swpFlags);
1094 
1095     m_isInFullScreen = false;
1096 }
1097 
1098 void GlassWindow::SetEnabled(bool enabled)
1099 {
1100     if (!enabled) {
1101         ResetMouseTracking(GetHWND());
1102     }
1103 
1104     m_isEnabled = enabled;
1105 }
1106 
1107 void GlassWindow::SetIcon(HICON hIcon)
1108 {
1109     ::SendMessage(GetHWND(), WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
1110     ::SendMessage(GetHWND(), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
1111 
1112     if (m_hIcon) {
1113         ::DestroyIcon(m_hIcon);
1114     }
1115     m_hIcon = hIcon;
1116 }
1117 
1118 /*
1119  * JNI methods section
1120  *
1121  */
1122 
1123 extern "C" {
1124 
1125 /*
1126  * Class:     com_sun_glass_ui_win_WinWindow
1127  * Method:    _initIDs
1128  * Signature: ()V
1129  */
1130 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1initIDs
1131     (JNIEnv *env, jclass cls)
1132 {
1133      midNotifyClose = env->GetMethodID(cls, "notifyClose", "()V");
1134      ASSERT(midNotifyClose);
1135      if (env->ExceptionCheck()) return;
1136 
1137      midNotifyMove = env->GetMethodID(cls, "notifyMove", "(II)V");
1138      ASSERT(midNotifyMove);
1139      if (env->ExceptionCheck()) return;
1140 
1141      midNotifyResize = env->GetMethodID(cls, "notifyResize", "(III)V");
1142      ASSERT(midNotifyResize);
1143      if (env->ExceptionCheck()) return;
1144 
1145      midNotifyScaleChanged = env->GetMethodID(cls, "notifyScaleChanged", "(FFFF)V");
1146      ASSERT(midNotifyScaleChanged);
1147      if (env->ExceptionCheck()) return;
1148 
1149      javaIDs.Window.notifyFocus = env->GetMethodID(cls, "notifyFocus", "(I)V");
1150      ASSERT(javaIDs.Window.notifyFocus);
1151      if (env->ExceptionCheck()) return;
1152 
1153      javaIDs.Window.notifyFocusDisabled = env->GetMethodID(cls, "notifyFocusDisabled", "()V");
1154      ASSERT(javaIDs.Window.notifyFocusDisabled);
1155      if (env->ExceptionCheck()) return;
1156 
1157      javaIDs.Window.notifyFocusUngrab = env->GetMethodID(cls, "notifyFocusUngrab", "()V");
1158      ASSERT(javaIDs.Window.notifyFocusUngrab);
1159      if (env->ExceptionCheck()) return;
1160 
1161      midNotifyMoveToAnotherScreen = env->GetMethodID(cls, "notifyMoveToAnotherScreen", "(Lcom/sun/glass/ui/Screen;)V");
1162      ASSERT(midNotifyMoveToAnotherScreen);
1163      if (env->ExceptionCheck()) return;
1164 
1165      javaIDs.Window.notifyDestroy = env->GetMethodID(cls, "notifyDestroy", "()V");
1166      ASSERT(javaIDs.Window.notifyDestroy);
1167      if (env->ExceptionCheck()) return;
1168 
1169      javaIDs.Window.notifyDelegatePtr = env->GetMethodID(cls, "notifyDelegatePtr", "(J)V");
1170      ASSERT(javaIDs.Window.notifyDelegatePtr);
1171      if (env->ExceptionCheck()) return;
1172 }
1173 
1174 /*
1175  * Class:     com_sun_glass_ui_win_WinWindow
1176  * Method:    _createWindow
1177  * Signature: (JJZI)J
1178  */
1179 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createWindow
1180     (JNIEnv *env, jobject jThis, jlong ownerPtr, jlong screenPtr, jint mask)
1181 {
1182     ENTER_MAIN_THREAD_AND_RETURN(jlong)
1183     {
1184         DWORD dwStyle;
1185         DWORD dwExStyle;
1186         bool closeable;
1187 
1188         dwStyle = WS_CLIPCHILDREN | WS_SYSMENU;
1189         closeable = (mask & com_sun_glass_ui_Window_CLOSABLE) != 0;
1190 
1191         if (mask & com_sun_glass_ui_Window_TITLED) {
1192             dwExStyle = WS_EX_WINDOWEDGE;
1193             dwStyle |= WS_CAPTION;
1194 
1195             if (mask & com_sun_glass_ui_Window_MINIMIZABLE) {
1196                 dwStyle |= WS_MINIMIZEBOX;
1197             }
1198             if (mask & com_sun_glass_ui_Window_MAXIMIZABLE) {
1199                 dwStyle |= WS_MAXIMIZEBOX;
1200             }
1201         } else {
1202             dwExStyle = 0;
1203             dwStyle |= WS_POPUP;
1204         }
1205 
1206         if (mask & com_sun_glass_ui_Window_TRANSPARENT) {
1207             dwExStyle |= WS_EX_LAYERED;
1208         }
1209 
1210         if (mask & com_sun_glass_ui_Window_POPUP) {
1211             dwStyle |= WS_POPUP;
1212             // Popups should not appear in the taskbar, so WS_EX_TOOLWINDOW
1213             dwExStyle |= WS_EX_TOOLWINDOW;
1214         }
1215 
1216         if (mask & com_sun_glass_ui_Window_UTILITY) {
1217             dwExStyle |= WS_EX_TOOLWINDOW;
1218         }
1219 
1220         if (mask & com_sun_glass_ui_Window_RIGHT_TO_LEFT) {
1221             dwExStyle |= WS_EX_NOINHERITLAYOUT | WS_EX_LAYOUTRTL;
1222         }
1223 
1224         GlassWindow *pWindow =
1225             new GlassWindow(jThis,
1226                 (mask & com_sun_glass_ui_Window_TRANSPARENT) != 0,
1227                 (mask & com_sun_glass_ui_Window_TITLED) != 0,
1228                 (mask & com_sun_glass_ui_Window_UNIFIED) != 0,
1229                 false,
1230                 owner);
1231 
1232         HWND hWnd = pWindow->Create(dwStyle, dwExStyle, hMonitor, owner);
1233 
1234         if (!hWnd) {
1235             delete pWindow;
1236         } else {
1237             if (!closeable) {
1238                 HMENU hSysMenu = ::GetSystemMenu(hWnd, FALSE);
1239                 if (hSysMenu != NULL) {
1240                     ::EnableMenuItem(hSysMenu, SC_CLOSE,
1241                             MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1242                 }
1243             }
1244         }
1245 
1246         return (jlong)hWnd;
1247     }
1248     DECL_jobject(jThis);
1249     HWND owner;
1250     HMONITOR hMonitor;
1251     jint mask;
1252     LEAVE_MAIN_THREAD;
1253 
1254     ARG(jThis) = jThis;
1255     ARG(owner) = (HWND)ownerPtr;
1256     ARG(hMonitor) = (HMONITOR)screenPtr;
1257     ARG(mask) = mask;
1258 
1259     return PERFORM_AND_RETURN();
1260 }
1261 
1262 /*
1263  * Class:     com_sun_glass_ui_win_WinWindow
1264  * Method:    _createChildWindow
1265  * Signature: (J)J
1266  */
1267 JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinWindow__1createChildWindow
1268     (JNIEnv *env, jobject jThis, jlong parentPtr)
1269 {
1270     ENTER_MAIN_THREAD_AND_RETURN(jlong)
1271     {
1272         // Check that the 'parent' isn't a garbage value
1273         if (!::IsWindow((HWND)parent)) {
1274             return (jlong)0;
1275         }
1276 
1277         DWORD dwStyle;
1278         DWORD dwExStyle;
1279 
1280         dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD;
1281         dwExStyle = WS_EX_NOINHERITLAYOUT;
1282 
1283         GlassWindow *pWindow =
1284             new GlassWindow(jThis, false, false, false, true, parent);
1285 
1286         HWND hWnd = pWindow->Create(dwStyle, dwExStyle, NULL, parent);
1287 
1288         if (!hWnd) {
1289             delete pWindow;
1290         }
1291         pWindow->HandleWindowPosChangedEvent();
1292 
1293         return (jlong)hWnd;
1294     }
1295     DECL_jobject(jThis);
1296     HWND parent;
1297     LEAVE_MAIN_THREAD;
1298 
1299     ARG(jThis) = jThis;
1300     ARG(parent) = (HWND)parentPtr;
1301 
1302     return PERFORM_AND_RETURN();
1303 }
1304 /*
1305  * Class:     com_sun_glass_ui_win_WinWindow
1306  * Method:    _close
1307  * Signature: (J)Z
1308  */
1309 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1close
1310     (JNIEnv *env, jobject jThis, jlong ptr)
1311 {
1312     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1313     {
1314         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1315         pWindow->Close();
1316         return bool_to_jbool(::DestroyWindow(hWnd));
1317     }
1318     LEAVE_MAIN_THREAD_WITH_hWnd;
1319 
1320     return PERFORM_AND_RETURN();
1321 }
1322 
1323 /*
1324  * Class:     com_sun_glass_ui_win_WinWindow
1325  * Method:    _setView
1326  * Signature: (JJ)Z
1327  */
1328 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setView
1329     (JNIEnv * env, jobject jThis, jlong ptr, jobject view)
1330 {
1331     ENTER_MAIN_THREAD()
1332     {
1333         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1334 
1335         if (activeTouchWindow == hWnd) {
1336             activeTouchWindow = 0;
1337         }
1338         pWindow->ResetMouseTracking(hWnd);
1339         pWindow->SetGlassView(view);
1340         // The condition below may be restricted to WS_POPUP windows
1341         if (::IsWindowVisible(hWnd)) {
1342             pWindow->NotifyViewSize(hWnd);
1343         }
1344     }
1345     GlassView * view;
1346     LEAVE_MAIN_THREAD_WITH_hWnd;
1347 
1348     ARG(view) = view == NULL ? NULL : (GlassView*)env->GetLongField(view, javaIDs.View.ptr);
1349 
1350     PERFORM();
1351     return JNI_TRUE;
1352 }
1353 
1354 /*
1355  * Class:     com_sun_glass_ui_win_WinWindow
1356  * Method:    _setMenubar
1357  * Signature: (JJ)Z
1358  */
1359 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMenubar
1360     (JNIEnv *env, jobject jThis, jlong ptr, jlong menuPtr)
1361 {
1362     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1363     {
1364         if (::SetMenu(hWnd, hMenu))
1365         {
1366             GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1367             if (pWindow) {
1368                 pWindow->SetMenu(hMenu);
1369             }
1370 
1371             return JNI_TRUE;
1372         }
1373         return JNI_FALSE;
1374     }
1375     HMENU hMenu;
1376     LEAVE_MAIN_THREAD_WITH_hWnd;
1377 
1378     ARG(hMenu) = (HMENU)menuPtr;
1379     return PERFORM_AND_RETURN();
1380 }
1381 
1382 /*
1383  * Class:     com_sun_glass_ui_win_WinWindow
1384  * Method:    _setLevel
1385  * Signature: (JI)V
1386  */
1387 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setLevel
1388 (JNIEnv *env, jobject jwindow, jlong ptr, jint jLevel)
1389 {
1390     ENTER_MAIN_THREAD()
1391     {
1392         ::SetWindowPos(hWnd, hWndInsertAfter, 0, 0, 0, 0,
1393                 SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
1394     }
1395     HWND hWndInsertAfter;
1396     LEAVE_MAIN_THREAD_WITH_hWnd;
1397 
1398     ARG(hWndInsertAfter) = HWND_NOTOPMOST;
1399     switch (jLevel) {
1400         case com_sun_glass_ui_Window_Level_FLOATING:
1401         case com_sun_glass_ui_Window_Level_TOPMOST:
1402             ARG(hWndInsertAfter) = HWND_TOPMOST;
1403             break;
1404     }
1405     PERFORM();
1406 }
1407 
1408 /*
1409  * Class:     com_sun_glass_ui_win_WinWindow
1410  * Method:    _setFocusable
1411  * Signature: (JZ)V
1412  */
1413 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setFocusable
1414 (JNIEnv *env, jobject jwindow, jlong ptr, jboolean isFocusable)
1415 {
1416     ENTER_MAIN_THREAD()
1417     {
1418         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1419         pWindow->SetFocusable(isFocusable);
1420     }
1421     bool isFocusable;
1422     LEAVE_MAIN_THREAD_WITH_hWnd;
1423 
1424     ARG(isFocusable) = isFocusable == JNI_TRUE;
1425     PERFORM();
1426 }
1427 
1428 /*
1429  * Class:     com_sun_glass_ui_win_WinWindow
1430  * Method:    _setEnabled
1431  * Signature: (JZ)V
1432  */
1433 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setEnabled
1434 (JNIEnv *env, jobject jwindow, jlong ptr, jboolean isEnabled)
1435 {
1436     ENTER_MAIN_THREAD()
1437     {
1438         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1439         pWindow->SetEnabled(isEnabled);
1440         ::EnableWindow(hWnd, isEnabled);
1441     }
1442     bool isEnabled;
1443     LEAVE_MAIN_THREAD_WITH_hWnd;
1444 
1445     ARG(isEnabled) = isEnabled == JNI_TRUE;
1446     PERFORM();
1447 }
1448 
1449 // Converts a float [0..1] to a BYTE [0..255]
1450 #define F2B(value) BYTE(255.f * (value))
1451 
1452 /*
1453  * Class:     com_sun_glass_ui_win_WinWindow
1454  * Method:    _setAlpha
1455  * Signature: (JF)V
1456  */
1457 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setAlpha
1458     (JNIEnv *env, jobject jThis, jlong ptr, jfloat alpha)
1459 {
1460     ENTER_MAIN_THREAD()
1461     {
1462         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1463         pWindow->SetAlpha(alpha);
1464     }
1465     BYTE alpha;
1466     LEAVE_MAIN_THREAD_WITH_hWnd;
1467 
1468     ARG(alpha) = F2B(alpha);
1469     PERFORM();
1470 }
1471 
1472 /*
1473  * Class:     com_sun_glass_ui_win_WinWindow
1474  * Method:    _setBackground
1475  * Signature: (JFFF)Z
1476  */
1477 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setBackground
1478     (JNIEnv *env, jobject jThis, jlong ptr, jfloat r, jfloat g, jfloat b)
1479 {
1480     ENTER_MAIN_THREAD()
1481     {
1482         HBRUSH hbrBackground;
1483 
1484         // That's a hack with 'negative' color
1485         if (r < 0) {
1486             hbrBackground = NULL;
1487         } else {
1488             hbrBackground = ::CreateSolidBrush(RGB(F2B(r), F2B(g), F2B(b)));
1489         }
1490 
1491         HBRUSH oldBrush = (HBRUSH)::SetClassLongPtr(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)hbrBackground);
1492 
1493         if (oldBrush) {
1494             ::DeleteObject(oldBrush);
1495         }
1496     }
1497     jfloat r, g, b;
1498     LEAVE_MAIN_THREAD_WITH_hWnd;
1499 
1500     ARG(r) = r;
1501     ARG(g) = g;
1502     ARG(b) = b;
1503     PERFORM();
1504 
1505     return JNI_TRUE;
1506 }
1507 
1508 /*
1509  * Class:     com_sun_glass_ui_win_WinWindow
1510  * Method:    _setBounds
1511  * Signature: (JIIZZIIIIFF)Z
1512  */
1513 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setBounds
1514     (JNIEnv *env, jobject jThis, jlong ptr,
1515      jint x, jint y, jboolean xSet, jboolean ySet,
1516      jint w, jint h, jint cw, jint ch,
1517      jfloat xGravity, jfloat yGravity)
1518 {
1519     ENTER_MAIN_THREAD()
1520     {
1521         if (!::IsWindow(hWnd)) return;
1522         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1523 
1524         pWindow->UpdateInsets();
1525         RECT is = pWindow->GetInsets();
1526 
1527         RECT r;
1528         ::GetWindowRect(hWnd, &r);
1529 
1530         int newX = jbool_to_bool(xSet) ? x : r.left;
1531         int newY = jbool_to_bool(ySet) ? y : r.top;
1532         int newW = w > 0 ? w :
1533                        cw > 0 ? cw + is.right + is.left : r.right - r.left;
1534         int newH = h > 0 ? h :
1535                        ch > 0 ? ch + is.bottom + is.top : r.bottom - r.top;
1536 
1537         if (xSet || ySet) {
1538             ::SetWindowPos(hWnd, NULL, newX, newY, newW, newH,
1539                            SWP_NOACTIVATE | SWP_NOZORDER);
1540         } else {
1541             ::SetWindowPos(hWnd, NULL, 0, 0, newW, newH,
1542                            SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
1543         }
1544     }
1545     jint x, y;
1546     jboolean xSet, ySet;
1547     jint w, h, cw, ch;
1548     LEAVE_MAIN_THREAD_WITH_hWnd;
1549 
1550     ARG(x) = x;
1551     ARG(y) = y;
1552     ARG(xSet) = xSet;
1553     ARG(ySet) = ySet;
1554     ARG(w) = w;
1555     ARG(h) = h;
1556     ARG(cw) = cw;
1557     ARG(ch) = ch;
1558     PERFORM();
1559 
1560 }
1561 
1562 /*
1563  * Class:     com_sun_glass_ui_win_WinWindow
1564  * Method:    _setTitle
1565  * Signature: (JLjava/lang/String;)Z
1566  */
1567 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setTitle
1568     (JNIEnv *env, jobject jThis, jlong ptr, jstring jTitle)
1569 {
1570     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1571     {
1572         if (::SetWindowText(hWnd, title)) {
1573             return JNI_TRUE;
1574         }
1575         return JNI_FALSE;
1576     }
1577     LPCTSTR title;
1578     LEAVE_MAIN_THREAD_WITH_hWnd;
1579 
1580     JString title(env, jTitle);
1581     ARG(title) = title;
1582     return PERFORM_AND_RETURN();
1583 }
1584 
1585 /*
1586  * Class:     com_sun_glass_ui_win_WinWindow
1587  * Method:    _setResizable
1588  * Signature: (Z)Z
1589  */
1590 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setResizable
1591 (JNIEnv *env, jobject jWindow, jlong ptr, jboolean jResizable)
1592 {
1593     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1594     {
1595         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1596         if (pWindow && pWindow->SetResizable(jbool_to_bool(jResizable))) {
1597             return JNI_TRUE;
1598         }
1599 
1600         return JNI_FALSE;
1601     }
1602     jboolean jResizable;
1603     LEAVE_MAIN_THREAD_WITH_hWnd;
1604 
1605     ARG(jResizable) = jResizable;
1606     return PERFORM_AND_RETURN();
1607 }
1608 
1609 /*
1610  * Class:     com_sun_glass_ui_win_WinWindow
1611  * Method:    _setVisible
1612  * Signature: (JZ)Z
1613  */
1614 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setVisible
1615     (JNIEnv *env, jobject jThis, jlong ptr, jboolean visible)
1616 {
1617     ENTER_MAIN_THREAD()
1618     {
1619         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1620         if (!visible) {
1621             if (pWindow) {
1622                 pWindow->UngrabFocus();
1623             }
1624 
1625             if (activeTouchWindow == hWnd) {
1626                 pWindow->HandleViewTouchEvent(hWnd, 0, 0, 0);
1627                 activeTouchWindow = 0;
1628             }
1629         }
1630 
1631 
1632         ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE);
1633 
1634         if (visible) {
1635             if (pWindow) {
1636                 if (pWindow->IsFocusable()) {
1637                     ::SetForegroundWindow(hWnd);
1638                 } else {
1639                     // RT-14197:
1640                     // On some latest platform versions, unfocusable windows
1641                     // are shown below the currently active window, so we
1642                     // need to pull them to front explicitly. However,
1643                     // neither BringWindowToTop nor SetForegroundWindow()
1644                     // can be used because of the window unfocusability, so
1645                     // here is a workaround: we first made the window TOPMOST
1646                     // and then reset this flag to just TOP.
1647                     ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
1648                                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
1649                     ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0,
1650                                    SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
1651                 }
1652             }
1653             ::UpdateWindow(hWnd);
1654         }
1655     }
1656     jboolean visible;
1657     LEAVE_MAIN_THREAD_WITH_hWnd;
1658 
1659     ARG(visible) = visible;
1660     PERFORM();
1661     return visible;
1662 }
1663 
1664 /*
1665  * Class:     com_sun_glass_ui_win_WinWindow
1666  * Method:    _requestFocus
1667  * Signature: (JI)Z
1668  */
1669 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1requestFocus
1670     (JNIEnv *env, jobject jThis, jlong ptr, jint event)
1671 {
1672     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1673     {
1674         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1675         return bool_to_jbool(pWindow && pWindow->RequestFocus(event));
1676     }
1677     jint event;
1678     LEAVE_MAIN_THREAD_WITH_hWnd;
1679 
1680     ARG(event) = event;
1681 
1682     return PERFORM_AND_RETURN();
1683 }
1684 
1685 /*
1686  * Class:     com_sun_glass_ui_win_WinWindow
1687  * Method:    _grabFocus
1688  * Signature: (J)Z
1689  */
1690 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1grabFocus
1691     (JNIEnv *env, jobject jThis, jlong ptr)
1692 {
1693     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1694     {
1695         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1696         return bool_to_jbool(pWindow && pWindow->GrabFocus());
1697     }
1698     LEAVE_MAIN_THREAD_WITH_hWnd;
1699 
1700     return PERFORM_AND_RETURN();
1701 }
1702 
1703 /*
1704  * Class:     com_sun_glass_ui_win_WinWindow
1705  * Method:    _ungrabFocus
1706  * Signature: (J)V
1707  */
1708 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1ungrabFocus
1709     (JNIEnv *env, jobject jThis, jlong ptr)
1710 {
1711     ENTER_MAIN_THREAD()
1712     {
1713         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1714         if (pWindow) {
1715             pWindow->UngrabFocus();
1716         }
1717     }
1718     LEAVE_MAIN_THREAD_WITH_hWnd;
1719 
1720     PERFORM();
1721 }
1722 
1723 /*
1724  * Class:     com_sun_glass_ui_win_WinWindow
1725  * Method:    _minimize
1726  * Signature: (JZ)Z
1727  */
1728 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1minimize
1729     (JNIEnv *env, jobject jThis, jlong ptr, jboolean minimize)
1730 {
1731     ENTER_MAIN_THREAD()
1732     {
1733         ::ShowWindow(hWnd, minimize ? SW_MINIMIZE : SW_RESTORE);
1734     }
1735     jboolean minimize;
1736     LEAVE_MAIN_THREAD_WITH_hWnd;
1737 
1738     ARG(minimize) = minimize;
1739     PERFORM();
1740 
1741     return JNI_TRUE;
1742 }
1743 
1744 /*
1745  * Class:     com_sun_glass_ui_win_WinWindow
1746  * Method:    _maximize
1747  * Signature: (JZ)Z
1748  */
1749 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1maximize
1750   (JNIEnv *env, jobject jThis, jlong ptr, jboolean maximize, jboolean wasMaximized)
1751 {
1752     ENTER_MAIN_THREAD()
1753     {
1754         ::ShowWindow(hWnd, maximize ? SW_MAXIMIZE : SW_RESTORE);
1755     }
1756     jboolean maximize;
1757     LEAVE_MAIN_THREAD_WITH_hWnd;
1758 
1759     ARG(maximize) = maximize;
1760     PERFORM();
1761 
1762     return JNI_TRUE;
1763 }
1764 
1765 /*
1766  * Class:     com_sun_glass_ui_win_WinWindow
1767  * Method:    _setMinimumSize
1768  * Signature: (JII)Z
1769  */
1770 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMinimumSize
1771     (JNIEnv *env, jobject jThis, jlong ptr, jint minWidth, jint minHeight)
1772 {
1773     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1774     {
1775         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1776         if (pWindow) {
1777             pWindow->setMinSize(minWidth, minHeight);
1778             return JNI_TRUE;
1779         }
1780         return JNI_FALSE;
1781     }
1782     jint minWidth;
1783     jint minHeight;
1784     LEAVE_MAIN_THREAD_WITH_hWnd;
1785 
1786     ARG(minWidth) = minWidth == 0 ? -1 : minWidth;
1787     ARG(minHeight) = minHeight == 0 ? -1 : minHeight;
1788     return PERFORM_AND_RETURN();
1789 }
1790 
1791 /*
1792  * Class:     com_sun_glass_ui_win_WinWindow
1793  * Method:    _setMaximumSize
1794  * Signature: (JII)Z
1795  */
1796 JNIEXPORT jboolean JNICALL Java_com_sun_glass_ui_win_WinWindow__1setMaximumSize
1797     (JNIEnv *env, jobject jThis, jlong ptr, jint maxWidth, jint maxHeight)
1798 {
1799     ENTER_MAIN_THREAD_AND_RETURN(jboolean)
1800     {
1801         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1802         if (pWindow) {
1803             pWindow->setMaxSize(maxWidth, maxHeight);
1804             return JNI_TRUE;
1805         }
1806         return JNI_FALSE;
1807     }
1808     jint maxWidth;
1809     jint maxHeight;
1810     LEAVE_MAIN_THREAD_WITH_hWnd;
1811 
1812     ARG(maxWidth) = maxWidth;
1813     ARG(maxHeight) = maxHeight;
1814     return PERFORM_AND_RETURN();
1815 }
1816 
1817 /*
1818  * Class:     com_sun_glass_ui_win_WinWindow
1819  * Method:    _setIcon
1820  * Signature: (JLcom/sun/glass/ui/Pixels;)V
1821  */
1822 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setIcon
1823     (JNIEnv *env, jobject jThis, jlong ptr, jobject jPixels)
1824 {
1825     HWND hWnd = (HWND)ptr;
1826     GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1827     if (pWindow) {
1828         pWindow->SetIcon(!jPixels ? NULL : Pixels::CreateIcon(env, jPixels));
1829     }
1830 }
1831 
1832 /*
1833  * Class:     com_sun_glass_ui_win_WinWindow
1834  * Method:    _toFront
1835  * Signature: (J)V
1836  */
1837 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1toFront
1838     (JNIEnv *env, jobject jThis, jlong ptr)
1839 {
1840     ENTER_MAIN_THREAD()
1841     {
1842         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1843         // See comment in __1setVisible() above about unfocusable windows
1844         if (pWindow && !pWindow->IsFocusable()) {
1845             ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1846         }
1847         ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1848     }
1849     LEAVE_MAIN_THREAD_WITH_hWnd;
1850 
1851     PERFORM();
1852 }
1853 
1854 /*
1855  * Class:     com_sun_glass_ui_win_WinWindow
1856  * Method:    _toBack
1857  * Signature: (J)V
1858  */
1859 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1toBack
1860     (JNIEnv *env, jobject jThis, jlong ptr)
1861 {
1862     ENTER_MAIN_THREAD()
1863     {
1864         ::SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1865     }
1866     LEAVE_MAIN_THREAD_WITH_hWnd;
1867 
1868     PERFORM();
1869 }
1870 
1871 /*
1872  * Class:     com_sun_glass_ui_win_WinWindow
1873  * Method:    _getEmbeddedX
1874  * Signature: (J)I
1875  */
1876 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinWindow__1getEmbeddedX
1877     (JNIEnv *env, jobject jThis, jlong ptr)
1878 {
1879     ENTER_MAIN_THREAD_AND_RETURN(jint)
1880     {
1881         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1882         HWND delegateHWnd = pWindow ? pWindow->GetDelegateWindow() : 0;
1883         RECT rect = {0};
1884         ::MapWindowPoints(delegateHWnd ? delegateHWnd : hWnd, (HWND)NULL, (LPPOINT)&rect, (sizeof(RECT)/sizeof(POINT)));
1885         return rect.left;
1886     }
1887     LEAVE_MAIN_THREAD_WITH_hWnd;
1888 
1889     return PERFORM_AND_RETURN();
1890 }
1891 
1892 /*
1893  * Class:     com_sun_glass_ui_win_WinWindow
1894  * Method:    _getEmbeddedY
1895  * Signature: (J)I
1896  */
1897 JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinWindow__1getEmbeddedY
1898     (JNIEnv *env, jobject jThis, jlong ptr)
1899 {
1900     ENTER_MAIN_THREAD_AND_RETURN(jint)
1901     {
1902         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1903         HWND delegateHWnd = pWindow ? pWindow->GetDelegateWindow() : 0;
1904         RECT rect = {0};
1905         ::MapWindowPoints(delegateHWnd ? delegateHWnd : hWnd, (HWND)NULL, (LPPOINT)&rect, (sizeof(RECT)/sizeof(POINT)));
1906         return rect.top;
1907     }
1908     LEAVE_MAIN_THREAD_WITH_hWnd;
1909 
1910     return PERFORM_AND_RETURN();
1911 }
1912 
1913 /*
1914  * Class:     com_sun_glass_ui_win_WinWindow
1915  * Method:    _setCursor
1916  * Signature: (Lcom/sun/glass/ui/Cursor;)V
1917  */
1918 JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinWindow__1setCursor
1919     (JNIEnv *env, jobject jThis, jlong ptr, jobject jCursor)
1920 {
1921     ENTER_MAIN_THREAD()
1922     {
1923         const HCURSOR cursor = JCursorToHCURSOR(GetEnv(), jCursor);
1924 
1925         GlassWindow *pWindow = GlassWindow::FromHandle(hWnd);
1926         if (pWindow) {
1927             pWindow->SetCursor(cursor);
1928 
1929             // Update the delegate window as well if present
1930             HWND delegateHwnd = pWindow->GetDelegateWindow();
1931             if (delegateHwnd) {
1932                 BaseWnd *pDelegateWindow = BaseWnd::FromHandle(delegateHwnd);
1933                 if (pDelegateWindow) {
1934                     pDelegateWindow->SetCursor(cursor);
1935                 }
1936             }
1937         }
1938     }
1939     DECL_jobject(jCursor);
1940     LEAVE_MAIN_THREAD_WITH_hWnd;
1941 
1942     ARG(jCursor) = jCursor;
1943     PERFORM();
1944 }
1945 
1946 }   // extern "C"