001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Pavel Dolgov
019: * @version $Revision$
020: */package org.apache.harmony.awt.wtk.windows;
021:
022: import java.awt.Dimension;
023: import java.awt.Frame;
024: import java.awt.Insets;
025: import java.awt.Point;
026: import java.awt.Rectangle;
027: import java.util.HashMap;
028: import java.util.Map;
029: import org.apache.harmony.awt.nativebridge.NativeBridge;
030: import org.apache.harmony.awt.nativebridge.windows.Win32;
031: import org.apache.harmony.awt.nativebridge.windows.WindowsDefs;
032: import org.apache.harmony.awt.wtk.CreationParams;
033: import org.apache.harmony.awt.wtk.NativeWindow;
034: import org.apache.harmony.awt.wtk.WindowFactory;
035:
036: public final class WinWindowFactory implements WindowFactory {
037:
038: static final Win32 win32 = Win32.getInstance();
039: static final NativeBridge bridge = NativeBridge.getInstance();
040:
041: private final Map<Long, WinWindow> hwnd2winMap = new HashMap<Long, WinWindow>();
042: private CreationParams creationParams = null;
043:
044: final WinEventQueue eventQueue;
045:
046: // for WinEvent
047: long lastHwndUnderPointer = 0;
048:
049: final MouseGrab mouseGrab = new MouseGrab();
050:
051: WinWindowFactory(WinEventQueue eq) {
052: eventQueue = eq;
053: eventQueue.addPreprocessor(mouseGrab);
054: }
055:
056: public NativeWindow createWindow(final CreationParams p) {
057: WinEventQueue.Task task = new WinEventQueue.Task() {
058: @Override
059: public void perform() {
060: String title = (p.name != null) ? p.name : ""; //$NON-NLS-1$
061: Rectangle rect = new Rectangle(p.x, p.y, p.w, p.h);
062: int style = getStyle(p);
063: int styleEx = getStyleEx(p);
064:
065: if (p.locationByPlatform) {
066: rect.x = rect.y = WindowsDefs.CW_USEDEFAULT;
067: }
068: if (p.parentId != 0 && p.child) {
069: Insets insets = getInsets(p.parentId);
070: rect.x -= insets.left;
071: rect.y -= insets.top;
072: }
073:
074: creationParams = p;
075: long hwnd = win32.CreateWindowExW(styleEx,
076: WindowProcHandler.windowClassName, title,
077: style, rect.x, rect.y, rect.width, rect.height,
078: p.parentId, 0, 0, null);
079:
080: creationParams = null;
081: NativeWindow win = getWindowById(hwnd);
082: assert win != null;
083:
084: returnValue = win;
085: }
086: };
087: eventQueue.performTask(task);
088: return (WinWindow) task.returnValue;
089: }
090:
091: public NativeWindow getWindowById(long id) {
092: return hwnd2winMap.get(new Long(id));
093: }
094:
095: /**
096: * @param id - HWND of Windows window
097: * @return WinWindow object representing Windows window,
098: * or null if given HWND doesn't belong to WTK
099: */
100: public WinWindow getWinWindowById(long id) {
101: return hwnd2winMap.get(new Long(id));
102: }
103:
104: /**
105: * @param p - point on the screen
106: * @return window whose client area contains p
107: */
108: public NativeWindow getWindowFromPoint(Point p) {
109: Win32.POINT pt = win32.createPOINT(false);
110: pt.set_x(p.x);
111: pt.set_y(p.y);
112: long hwnd = win32.WindowFromPoint(pt);
113: WinWindow wnd = getWinWindowById(hwnd);
114: return ((wnd != null) && wnd.contains(p)) ? wnd : null;
115: }
116:
117: void onCreateWindow(long hwnd) {
118: WinWindow win = new WinWindow(hwnd, this , creationParams);
119: hwnd2winMap.put(new Long(hwnd), win);
120: win.postCreate(creationParams);
121: }
122:
123: boolean isWindowBeingCreated() {
124: return creationParams != null;
125: }
126:
127: void remove(WinWindow win) {
128: hwnd2winMap.remove(win);
129: }
130:
131: public boolean isWindowStateSupported(int state) {
132: switch (state) {
133: case Frame.NORMAL:
134: case Frame.ICONIFIED:
135: case Frame.MAXIMIZED_BOTH:
136: return true;
137: default:
138: return false;
139: }
140: }
141:
142: private static int getStyle(CreationParams p) {
143: int style = WindowsDefs.WS_CLIPCHILDREN
144: | WindowsDefs.WS_CLIPSIBLINGS;
145: style |= p.child ? WindowsDefs.WS_CHILD : WindowsDefs.WS_POPUP;
146:
147: switch (p.decorType) {
148: case CreationParams.DECOR_TYPE_FRAME:
149: style |= WindowsDefs.WS_SYSMENU
150: | WindowsDefs.WS_MINIMIZEBOX;
151: if (!p.undecorated) {
152: style |= WindowsDefs.WS_CAPTION | WindowsDefs.WS_BORDER
153: | WindowsDefs.WS_MAXIMIZEBOX
154: | WindowsDefs.WS_SIZEBOX;
155: }
156: break;
157: case CreationParams.DECOR_TYPE_DIALOG:
158: style |= WindowsDefs.WS_SYSMENU;
159: if (!p.undecorated) {
160: style |= WindowsDefs.WS_CAPTION | WindowsDefs.WS_BORDER
161: | WindowsDefs.WS_SIZEBOX;
162: }
163: break;
164: case CreationParams.DECOR_TYPE_POPUP:
165: break;
166: case CreationParams.DECOR_TYPE_UNDECOR:
167: break;
168: }
169:
170: if (p.visible) {
171: style |= WindowsDefs.WS_VISIBLE;
172: }
173: if (p.disabled) {
174: style |= WindowsDefs.WS_DISABLED;
175: }
176: if (p.iconified) {
177: style |= WindowsDefs.WS_MINIMIZE;
178: }
179: if (p.maximizedState == p.MAXIMIZED) {
180: style |= WindowsDefs.WS_MAXIMIZE;
181: }
182: return style;
183: }
184:
185: private static int getStyleEx(CreationParams p) {
186: int styleEx = 0;
187: if (p.topmost) {
188: styleEx |= WindowsDefs.WS_EX_TOPMOST;
189: }
190:
191: switch (p.decorType) {
192: case CreationParams.DECOR_TYPE_FRAME:
193: styleEx |= WindowsDefs.WS_EX_APPWINDOW; // Show in taskbar
194: break;
195: case CreationParams.DECOR_TYPE_POPUP:
196: styleEx |= WindowsDefs.WS_EX_NOACTIVATE;
197: break;
198: }
199:
200: return styleEx;
201: }
202:
203: static final class MouseGrab implements WinEventQueue.Preprocessor {
204: private boolean manualGrabActive = false;
205: private boolean autoGrabActive = false;
206: private long grabHwnd = 0;
207: private boolean releasing = false;
208:
209: static final long mouseMask = (~WindowsDefs.MK_ALT
210: & ~WindowsDefs.MK_CONTROL & ~WindowsDefs.MK_SHIFT);
211:
212: /**
213: * @see org.apache.harmony.awt.wtk.windows.WinEventQueue.Preprocessor#preprocess(long, int, long, long, long[])
214: */
215: public boolean preprocess(long hwnd, int msg, long wParam,
216: long lParam, long[] result) {
217:
218: switch (msg) {
219: case WindowsDefs.WM_LBUTTONDOWN:
220: case WindowsDefs.WM_RBUTTONDOWN:
221: case WindowsDefs.WM_MBUTTONDOWN:
222: case WindowsDefs.WM_XBUTTONDOWN:
223: onMouseButtonDown(hwnd, wParam & mouseMask);
224: break;
225: case WindowsDefs.WM_LBUTTONUP:
226: case WindowsDefs.WM_RBUTTONUP:
227: case WindowsDefs.WM_MBUTTONUP:
228: case WindowsDefs.WM_XBUTTONUP:
229: onMouseButtonUp(wParam & mouseMask);
230: break;
231: case WindowsDefs.WM_CAPTURECHANGED:
232: if (onCaptureChanged(lParam)) {
233: result[0] = 0;
234: return true;
235: }
236: break;
237: case WindowsDefs.WM_MOUSEMOVE:
238: onMouseMove(wParam & mouseMask);
239: break;
240: case WindowsDefs.WM_ACTIVATE:
241: if ((wParam & 0xFFFF) == WindowsDefs.WA_ACTIVE) {
242: onActivate();
243: }
244: }
245: return false;
246: }
247:
248: boolean isMouseGrabbed() {
249: return grabHwnd != 0;
250: }
251:
252: void startAutoGrab(long hwnd) {
253: autoGrabActive = true;
254: if (grabHwnd == 0) {
255: grabImpl(hwnd);
256: }
257: }
258:
259: void startManualGrab(long hwnd) {
260: manualGrabActive = true;
261: grabImpl(hwnd);
262: }
263:
264: void endManualGrab() {
265: manualGrabActive = false;
266:
267: if (!autoGrabActive) {
268: ungrabImpl();
269: }
270: }
271:
272: void endAutoGrab() {
273: autoGrabActive = false;
274: if (!manualGrabActive && grabHwnd != 0) {
275: ungrabImpl();
276: }
277: }
278:
279: void restoreAutoGrab() {
280: long hwnd = win32.GetActiveWindow();
281: if (hwnd != 0) {
282: startAutoGrab(hwnd);
283: }
284: }
285:
286: void grabCanceled() {
287: autoGrabActive = manualGrabActive = false;
288: grabHwnd = 0;
289: }
290:
291: private void grabImpl(long hwnd) {
292: grabHwnd = hwnd;
293: win32.SetCapture(hwnd);
294: }
295:
296: private void ungrabImpl() {
297: releasing = true;
298: win32.ReleaseCapture();
299: releasing = false;
300: grabHwnd = 0;
301: }
302:
303: private void onMouseButtonUp(long mouseState) {
304: if (mouseState == 0) {
305: endAutoGrab();
306: }
307: }
308:
309: /**
310: * Preprocess mouse capture event
311: * @param otherHwnd - the event parameter
312: * @return true if capture change event shouldn't be processed
313: */
314: private boolean onCaptureChanged(long otherHwnd) {
315: if (otherHwnd == 0) {
316: grabCanceled();
317: }
318: return releasing;
319: }
320:
321: private void onMouseButtonDown(long hwnd, long mouseState) {
322: // Check that only one mouse button is pressed at the moment
323: if (mouseState == WindowsDefs.MK_LBUTTON
324: || mouseState == WindowsDefs.MK_MBUTTON
325: || mouseState == WindowsDefs.MK_RBUTTON
326: || mouseState == WindowsDefs.MK_XBUTTON1
327: || mouseState == WindowsDefs.MK_XBUTTON2) {
328:
329: startAutoGrab(hwnd);
330: }
331:
332: }
333:
334: private void onMouseMove(long mouseState) {
335: if ((mouseState != 0) && (grabHwnd == 0)) {
336: restoreAutoGrab();
337: }
338: }
339:
340: private void onActivate() {
341: if (isKeyPressed(WindowsDefs.VK_LBUTTON)
342: || isKeyPressed(WindowsDefs.VK_MBUTTON)
343: || isKeyPressed(WindowsDefs.VK_RBUTTON)
344: || isKeyPressed(WindowsDefs.VK_XBUTTON1)
345: || isKeyPressed(WindowsDefs.VK_XBUTTON2)) {
346: restoreAutoGrab();
347: }
348: }
349:
350: private boolean isKeyPressed(int vKey) {
351: return (win32.GetKeyState(vKey) & 0x80) != 0;
352: }
353: }
354:
355: /**
356: * @see org.apache.harmony.awt.wtk.WindowFactory#attachWindow(long)
357: */
358: public NativeWindow attachWindow(long nativeWindowId) {
359: return new WinWindow(nativeWindowId, this );
360: }
361:
362: /**
363: * @see org.apache.harmony.awt.wtk.WindowFactory#setCaretPosition(int, int)
364: */
365: public void setCaretPosition(final int x, final int y) {
366: WinEventQueue.Task task = new WinEventQueue.Task() {
367: @Override
368: public void perform() {
369: win32.SetCaretPos(x, y);
370: }
371: };
372: eventQueue.performTask(task);
373: }
374:
375: /**
376: * @see org.apache.harmony.awt.wtk.WindowFactory#getWindowSizeById(long)
377: */
378: public Dimension getWindowSizeById(long hwnd) {
379:
380: Win32.RECT nativeRect = win32.createRECT(false);
381: win32.GetWindowRect(hwnd, nativeRect);
382:
383: Dimension size = new Dimension();
384: size.width = nativeRect.get_right() - nativeRect.get_left();
385: size.height = nativeRect.get_bottom() - nativeRect.get_top();
386: return size;
387: }
388:
389: /**
390: * Obtain the window's native decorations size
391: * @param hwnd - window handle
392: * @return the insets. Never returns null.
393: */
394: Insets getInsets(long hwnd) {
395: Insets insets = new Insets(0, 0, 0, 0);
396: if ((getWindowStyle(hwnd) & WindowsDefs.WS_ICONIC) != 0) {
397: return insets;
398: }
399:
400: Win32.RECT rect = win32.createRECT(false);
401: win32.GetClientRect(hwnd, rect);
402: int width = rect.get_right();
403: int height = rect.get_bottom();
404:
405: win32.GetWindowRect(hwnd, rect);
406:
407: Win32.POINT topLeft = win32.createPOINT(false);
408: topLeft.set_x(rect.get_left());
409: topLeft.set_y(rect.get_top());
410: win32.MapWindowPoints(0, hwnd, topLeft, 1);
411:
412: Win32.POINT bottomRight = win32.createPOINT(false);
413: bottomRight.set_x(rect.get_right());
414: bottomRight.set_y(rect.get_bottom());
415: win32.MapWindowPoints(0, hwnd, bottomRight, 1);
416:
417: insets.left = -topLeft.get_x();
418: insets.right = bottomRight.get_x() - width;
419: insets.top = -topLeft.get_y();
420: insets.bottom = bottomRight.get_y() - height;
421:
422: return insets;
423: }
424:
425: int getWindowStyle(long hwnd) {
426: return win32.GetWindowLongW(hwnd, WindowsDefs.GWL_STYLE);
427: }
428:
429: void setWindowStyle(long hwnd, int style) {
430: win32.SetWindowLongW(hwnd, WindowsDefs.GWL_STYLE, style);
431: }
432:
433: int getWindowExStyle(long hwnd) {
434: return win32.GetWindowLongW(hwnd, WindowsDefs.GWL_EXSTYLE);
435: }
436:
437: void setWindowExStyle(long hwnd, int style) {
438: win32.SetWindowLongW(hwnd, WindowsDefs.GWL_EXSTYLE, style);
439: }
440:
441: boolean isChild(long hwnd) {
442: return ((getWindowStyle(hwnd) & WindowsDefs.WS_CHILD) != 0);
443: }
444:
445: /**
446: * Get window size and position relative to its parent
447: * @param hwnd - the window handle
448: * @return window bounds
449: */
450: Rectangle getWindowBounds(long hwnd) {
451:
452: Win32.RECT nativeRect = win32.createRECT(false);
453: win32.GetWindowRect(hwnd, nativeRect);
454:
455: Rectangle rect = getRectBounds(nativeRect);
456:
457: long hwndParent = win32.GetParent(hwnd);
458: if (hwndParent != 0 && isChild(hwnd)) {
459: win32.GetWindowRect(hwndParent, nativeRect);
460: rect.translate(-nativeRect.get_left(), -nativeRect
461: .get_top());
462: }
463: return rect;
464: }
465:
466: Rectangle getRectBounds(Win32.RECT nativeRect) {
467: Rectangle rect = new Rectangle();
468: rect.x = nativeRect.get_left();
469: rect.y = nativeRect.get_top();
470: rect.width = nativeRect.get_right() - rect.x;
471: rect.height = nativeRect.get_bottom() - rect.y;
472:
473: return rect;
474: }
475:
476: }
|