From 29b675c229e3d797f2c454803e289765b0bc801c Mon Sep 17 00:00:00 2001 From: trembovetski Date: Thu, 20 Aug 2009 10:32:13 -0700 Subject: newt: one more attempt to commit insets-related changes --- src/newt/native/MacWindow.m | 7 ++- src/newt/native/NewtMacWindow.h | 2 + src/newt/native/NewtMacWindow.m | 41 ++++++++++++-- src/newt/native/WindowsWindow.c | 117 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 158 insertions(+), 9 deletions(-) mode change 100644 => 100755 src/newt/native/NewtMacWindow.m (limited to 'src/newt/native') diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 008a2417c..a93157c3f 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -55,7 +55,8 @@ NSString* jstringToNSString(JNIEnv* env, jstring jstr) void setFrameTopLeftPoint(NSWindow* win, jint x, jint y) { NSScreen* screen = [NSScreen mainScreen]; - NSRect visibleScreenRect = [screen visibleFrame]; + // this allows for better compatibility with awt behavior + NSRect visibleScreenRect = [screen frame]; NSPoint pt; pt = NSMakePoint(x, visibleScreenRect.origin.y + visibleScreenRect.size.height - y); @@ -89,6 +90,10 @@ NS_ENDHANDLER } [win setContentView: newView]; + // make sure the insets are updated in the java object + NewtMacWindow* newtw = (NewtMacWindow*)win; + [newtw updateInsets: env]; + return oldView; } diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index 09f9ffbd2..e19be2ed8 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -61,6 +61,8 @@ + (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; +- (void) updateInsets: (JNIEnv*) env; + - (id) initWithContentRect: (NSRect) contentRect styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m old mode 100644 new mode 100755 index 62c6a6e25..f52d3b1bb --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -67,6 +67,7 @@ static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; +static jmethodID insetsChangedID = NULL; static jmethodID sizeChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; @@ -80,16 +81,46 @@ static jmethodID windowDestroyedID = NULL; sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); - if (sendMouseEventID && sendKeyEventID && sizeChangedID && positionChangedID && focusChangedID && windowDestroyedID && windowDestroyNotifyID) { + if (sendMouseEventID && sendKeyEventID && sizeChangedID && insetsChangedID && + positionChangedID && focusChangedID && windowDestroyedID && windowDestroyNotifyID) + { return YES; } return NO; } +- (void) updateInsets: (JNIEnv*) env +{ + NSView* nsview = [self contentView]; + if( ! [nsview isMemberOfClass:[NewtView class]] ) { + return; + } + NewtView* view = (NewtView *) nsview; + jobject javaWindowObject = [view getJavaWindowObject]; + if (env==NULL || javaWindowObject == NULL) { + return; + } + + NSRect frameRect = [self frame]; + NSRect contentRect = [self contentRectForFrameRect: frameRect]; + + // note: this is a simplistic implementation which doesn't take + // into account DPI and scaling factor + CGFloat l = contentRect.origin.x - frameRect.origin.x; + jint top = (jint)(frameRect.size.height - contentRect.size.height); + jint left = (jint)l; + jint bottom = (jint)(contentRect.origin.y - frameRect.origin.y); + jint right = (jint)(frameRect.size.width - (contentRect.size.width + l)); + + (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, + left, top, right, bottom); +} + - (id) initWithContentRect: (NSRect) contentRect styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType @@ -299,6 +330,9 @@ static jint mods2JavaMods(NSUInteger mods) return; } + // update insets on every window resize for lack of better hook place + [self updateInsets: env]; + NSRect frameRect = [self frame]; NSRect contentRect = [self contentRectForFrameRect: frameRect]; @@ -321,14 +355,13 @@ static jint mods2JavaMods(NSUInteger mods) } NSRect rect = [self frame]; - NSScreen* menuBarScreen = NULL; NSScreen* screen = NULL; NSRect screenRect; NSPoint pt; - // FIXME: unclear whether this works correctly in multiple monitor situations screen = [self screen]; - screenRect = [screen visibleFrame]; + // this allows for better compatibility with awt behavior + screenRect = [screen frame]; pt = NSMakePoint(rect.origin.x, screenRect.origin.y + screenRect.size.height - rect.origin.y - rect.size.height); (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 5bd929ef7..5628fac81 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -97,6 +97,7 @@ #include "KeyEvent.h" static jmethodID sizeChangedID = NULL; +static jmethodID insetsChangedID = NULL; static jmethodID positionChangedID = NULL; static jmethodID focusChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; @@ -105,6 +106,8 @@ static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; static jmethodID sendPaintEventID = NULL; +static RECT* UpdateInsets(JNIEnv *env, HWND hwnd, jobject window); + typedef struct { JNIEnv* jenv; jobject jinstance; @@ -590,10 +593,91 @@ static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt, return 0; } +static RECT * UpdateInsets(JNIEnv *env, HWND hwnd, jobject window) +{ + // being naughty here + static RECT m_insets = { 0, 0, 0, 0 }; + RECT outside; + RECT inside; + + if (IsIconic(hwnd)) { + m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = -1; + return FALSE; + } + + m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; + + GetClientRect(hwnd, &inside); + GetWindowRect(hwnd, &outside); + + if (outside.right - outside.left > 0 && outside.bottom - outside.top > 0) { + MapWindowPoints(hwnd, 0, (LPPOINT)&inside, 2); + m_insets.top = inside.top - outside.top; + m_insets.bottom = outside.bottom - inside.bottom; + m_insets.left = inside.left - outside.left; + m_insets.right = outside.right - inside.right; + } else { + m_insets.top = -1; + } + if (m_insets.left < 0 || m_insets.top < 0 || + m_insets.right < 0 || m_insets.bottom < 0) + { + LONG style = GetWindowLong(hwnd, GWL_STYLE); + // TODO: TDV: better undecorated checking needed + BOOL bIsUndecorated = (style & (WS_POPUP|WS_SYSMENU)) != 0; + if (!bIsUndecorated) { + /* Get outer frame sizes. */ + if (style & WS_THICKFRAME) { + m_insets.left = m_insets.right = + GetSystemMetrics(SM_CXSIZEFRAME); + m_insets.top = m_insets.bottom = + GetSystemMetrics(SM_CYSIZEFRAME); + } else { + m_insets.left = m_insets.right = + GetSystemMetrics(SM_CXDLGFRAME); + m_insets.top = m_insets.bottom = + GetSystemMetrics(SM_CYDLGFRAME); + } + + /* Add in title. */ + m_insets.top += GetSystemMetrics(SM_CYCAPTION); + } else { + /* undo the -1 set above */ + m_insets.left = m_insets.top = m_insets.right = m_insets.bottom = 0; + } + } + + (*env)->CallVoidMethod(env, window, insetsChangedID, + m_insets.left, m_insets.top, + m_insets.right, m_insets.bottom); + return &m_insets; +} + +static void WmSize(JNIEnv *env, HWND wnd, jobject window, UINT type) +{ + RECT rc; + int w, h; + + // make sure insets are up to date + (void)UpdateInsets(env, wnd, window); + + if (type == SIZE_MINIMIZED) { + // TODO: deal with minimized window sizing + return; + } + + GetClientRect(wnd, &rc); + + // we report back the dimensions of the client area + w = rc.right - rc.left; + h = rc.bottom - rc.top; + + (*env)->CallVoidMethod(env, window, sizeChangedID, w, h); +} + static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) { - RECT rc; int useDefWindowProc = 0; JNIEnv *env = NULL; jobject window = NULL; @@ -660,10 +744,20 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_SIZE: - GetClientRect(wnd, &rc); - (*env)->CallVoidMethod(env, window, sizeChangedID, (jint) rc.right, (jint) rc.bottom); + WmSize(env, wnd, window, (UINT)wParam); + break; + + case WM_SETTINGCHANGE: + if (wParam == SPI_SETNONCLIENTMETRICS) { + // make sure insets are updated, we don't need to resize the window + // because the size of the client area doesn't change + (void)UpdateInsets(env, wnd, window); + } else { + useDefWindowProc = 1; + } break; + case WM_LBUTTONDOWN: (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, @@ -911,6 +1005,7 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initID (JNIEnv *env, jclass clazz) { sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(II)V"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(IIII)V"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(II)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(JZ)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); @@ -919,6 +1014,7 @@ JNIEXPORT jboolean JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_initID sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); sendPaintEventID = (*env)->GetMethodID(env, clazz, "sendPaintEvent", "(IIIII)V"); if (sizeChangedID == NULL || + insetsChangedID == NULL || positionChangedID == NULL || focusChangedID == NULL || windowDestroyNotifyID == NULL || @@ -980,6 +1076,9 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CreateWin #else SetWindowLongPtr(window, GWLP_USERDATA, (intptr_t) wud); #endif + + UpdateInsets(env, window, obj); + ShowWindow(window, SW_SHOWNORMAL); } @@ -989,6 +1088,7 @@ JNIEXPORT jlong JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_CreateWin (*env)->ReleaseStringUTFChars(env, jWndName, wndName); #endif + return (jlong) (intptr_t) window; } @@ -1066,8 +1166,17 @@ JNIEXPORT void JNICALL Java_com_sun_javafx_newt_windows_WindowsWindow_setSize0 { RECT r; HWND w = (HWND) window; + // since width, height are the size of the client area, we need to add + // insets + RECT *pInsets = UpdateInsets(env, w, obj); + int nWidth, nHeight; + GetWindowRect(w, &r); - MoveWindow(w, r.left, r.top, width, height, TRUE); + + nWidth = width + pInsets->left + pInsets->right; + nHeight = height + pInsets->top + pInsets->bottom; + MoveWindow(w, r.left, r.top, nWidth, nHeight, TRUE); + // we report back the size of client area (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); } -- cgit v1.2.3