diff options
-rw-r--r-- | src/newt/classes/com/sun/javafx/newt/Insets.java | 13 | ||||
-rwxr-xr-x | src/newt/classes/com/sun/javafx/newt/Window.java | 33 | ||||
-rwxr-xr-x | src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java | 48 | ||||
-rwxr-xr-x | src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java | 15 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 7 | ||||
-rw-r--r-- | src/newt/native/NewtMacWindow.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/newt/native/NewtMacWindow.m | 41 | ||||
-rwxr-xr-x | src/newt/native/WindowsWindow.c | 117 |
8 files changed, 262 insertions, 14 deletions
diff --git a/src/newt/classes/com/sun/javafx/newt/Insets.java b/src/newt/classes/com/sun/javafx/newt/Insets.java index 653ae8a10..7d379cd92 100644 --- a/src/newt/classes/com/sun/javafx/newt/Insets.java +++ b/src/newt/classes/com/sun/javafx/newt/Insets.java @@ -33,10 +33,11 @@ package com.sun.javafx.newt; /** - * + * Simple class representing insets. + * * @author tdv */ -public class Insets { +public class Insets implements Cloneable { public int top; public int left; public int bottom; @@ -93,4 +94,12 @@ public class Insets { ",bottom=" + bottom + ",right=" + right + "]"; } + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + throw new InternalError(); + } + } + } diff --git a/src/newt/classes/com/sun/javafx/newt/Window.java b/src/newt/classes/com/sun/javafx/newt/Window.java index 8970298d6..46eaf402f 100755 --- a/src/newt/classes/com/sun/javafx/newt/Window.java +++ b/src/newt/classes/com/sun/javafx/newt/Window.java @@ -306,14 +306,33 @@ public abstract class Window implements NativeWindow return config; } + /** + * Returns the width of the client area of this window + * @return width of the client area + */ public int getWidth() { return width; } + /** + * Returns the height of the client area of this window + * @return height of the client area + */ public int getHeight() { return height; } + /** + * Returns the insets for this native window (the difference between the + * size of the toplevel window with the decorations and the client area). + * + * @return insets for this platform window + */ + // this probably belongs to NativeWindow interface + public Insets getInsets() { + return new Insets(0,0,0,0); + } + /** If this Window actually wraps one from another toolkit such as the AWT, this will return a non-null value. */ public Object getWrappedWindow() { @@ -381,7 +400,21 @@ public abstract class Window implements NativeWindow } public abstract void setVisible(boolean visible); + /** + * Sets the size of the client area of the window, excluding decorations + * Total size of the window will be + * {@code width+insets.left+insets.right, height+insets.top+insets.bottom} + * @param width of the client area of the window + * @param height of the client area of the window + */ public abstract void setSize(int width, int height); + /** + * Sets the location of the top left corner of the window, including + * decorations (so the client area will be placed at + * {@code x+insets.left,y+insets.top}. + * @param x coord of the top left corner + * @param y coord of the top left corner + */ public abstract void setPosition(int x, int y); public abstract boolean setFullscreen(boolean fullscreen); diff --git a/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java index 704b578c4..ca7954a1c 100755 --- a/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/macosx/MacWindow.java @@ -130,6 +130,7 @@ public class MacWindow extends Window { private volatile long surfaceHandle; // non fullscreen dimensions .. private int nfs_width, nfs_height, nfs_x, nfs_y; + private final Insets insets = new Insets(0,0,0,0); static { MacDisplay.initSingleton(); @@ -183,6 +184,31 @@ public class MacWindow extends Window { } } + class EnsureWindowCreatedAction implements Runnable { + public void run() { + nsViewLock.lock(); + try { + createWindow(false); + } finally { + nsViewLock.unlock(); + } + } + } + private EnsureWindowCreatedAction ensureWindowCreatedAction = + new EnsureWindowCreatedAction(); + + public Insets getInsets() { + // in order to properly calculate insets we need the window to be + // created + MainThread.invoke(true, ensureWindowCreatedAction); + nsViewLock.lock(); + try { + return (Insets) insets.clone(); + } finally { + nsViewLock.unlock(); + } + } + private ToolkitLock nsViewLock = new ToolkitLock() { private Thread owner; private int recursionCount; @@ -233,6 +259,9 @@ public class MacWindow extends Window { if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); if (visible) { createWindow(false); + if (windowHandle != 0) { + makeKeyAndOrderFront(windowHandle); + } } else { if (windowHandle != 0) { orderOut(windowHandle); @@ -344,6 +373,9 @@ public class MacWindow extends Window { System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); } createWindow(true); + if (windowHandle != 0) { + makeKeyAndOrderFront(windowHandle); + } } finally { nsViewLock.unlock(); } @@ -386,6 +418,19 @@ public class MacWindow extends Window { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); } + private void insetsChanged(int left, int top, int right, int bottom) { + if (DEBUG_IMPLEMENTATION) { + System.out.println(Thread.currentThread().getName()+ + " Insets changed to " + left + ", " + top + ", " + right + ", " + bottom); + } + if (left != -1 && top != -1 && right != -1 && bottom != -1) { + insets.left = left; + insets.top = top; + insets.right = right; + insets.bottom = bottom; + } + } + private void positionChanged(int newX, int newY) { if (DEBUG_IMPLEMENTATION) { System.out.println(Thread.currentThread().getName()+" Position changed to " + newX + ", " + newY); @@ -527,7 +572,8 @@ public class MacWindow extends Window { } surfaceHandle = contentView(windowHandle); setTitle0(windowHandle, getTitle()); - makeKeyAndOrderFront(windowHandle); + // don't make the window visible on window creation +// makeKeyAndOrderFront(windowHandle); sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); sendWindowEvent(WindowEvent.EVENT_WINDOW_GAINED_FOCUS); diff --git a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java index 18dc7dae3..f725874ef 100755 --- a/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java +++ b/src/newt/classes/com/sun/javafx/newt/windows/WindowsWindow.java @@ -34,9 +34,7 @@ package com.sun.javafx.newt.windows; import javax.media.nativewindow.*; - import com.sun.javafx.newt.*; -import com.sun.javafx.newt.impl.*; public class WindowsWindow extends Window { @@ -45,6 +43,7 @@ public class WindowsWindow extends Window { private long windowHandleClose; // non fullscreen dimensions .. private int nfs_width, nfs_height, nfs_x, nfs_y; + private final Insets insets = new Insets(0, 0, 0, 0); static { WindowsDisplay.initSingleton(); @@ -204,6 +203,10 @@ public class WindowsWindow extends Window { } } + public Insets getInsets() { + return (Insets)insets.clone(); + } + //---------------------------------------------------------------------- // Internals only // @@ -223,6 +226,14 @@ public class WindowsWindow extends Window { private static native void setTitle(long windowHandle, String title); private static native void requestFocus(long windowHandle); + private void insetsChanged(int left, int top, int right, int bottom) { + if (left != -1 && top != -1 && right != -1 && bottom != -1) { + insets.left = left; + insets.top = top; + insets.right = right; + insets.bottom = bottom; + } + } private void sizeChanged(int newWidth, int newHeight) { width = newWidth; height = newHeight; 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 index 62c6a6e25..f52d3b1bb 100644..100755 --- 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); } |