[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Window managers
From: |
Christopher Armstrong |
Subject: |
Re: Window managers |
Date: |
Sat, 31 Mar 2007 09:51:00 +1000 |
User-agent: |
Thunderbird 1.5.0.10 (Windows/20070221) |
Hi
I have added Yen-Ju Chen's contributions to the wiki. Thank you very much for
helping out. If anyone has stuff to add, speak up! Please read and
contribute to the wiki page at
http://wiki.gnustep.org/index.php/Window_manager .
I was just reading Yen-Ju Chen's contribution and the bit about "windows
turning black" caught my eye. This problem exists on Microsoft Windows
as well when you activate native window borders. I found a partial
solution for this problem on Windows.
Another problem with window drawing is that non-retained (i.e.
unbuffered) windows on Microsoft Windows do not seem to update properly.
For example, when you drag items from the toolbox in Gorm.app to a
non-retained window, it doesn't show up. By dragging the window off the
screen and back on, a repaint is forced and then it shows up again. I
can't seem to remember if this problem exists on X11.
I have been sitting on some code to fix black windows on Windows (please
note the capitalisation carefully) and a fix for a problem where mouse
up events don't get sent when the mouse is released outside of a GNUstep
window. A patch is attached; please test with GNUstep window decorations
turned OFF. There is also a (partial, "seems to work") fix for incorrect
backbuffer blitting after a resize.
Regards
Chris
P.S: [Forwarding this to gnustep-dev]
Index: ChangeLog
===================================================================
--- ChangeLog (revision 24952)
+++ ChangeLog (working copy)
@@ -1,3 +1,16 @@
+2007-03-31 Christopher Armstrong <address@hidden>
+
+ * Source/win32/WIN32Server.m: Backend capture mouse when it
+ is clicked down, and releases the mouse capture when the mouse button
+ is released.
+ * Source/win32/w32_movesize.m: WM_SIZING sends
+ GSAppKitWindowResized events to the frontend so that frame rect is
+ updated during the resize.
+ * Headers/win32/WIN32Server.h
+ * Source/win32/w32_windowdisplay.m: Added a flag to the WIN_INTERN
+ structure so that we can tell when the backing store contains no
+ useful data and a repaint should occur.
+
2007-03-30 Fred Kiefer <address@hidden>
* header/xlib/XGGeometry.h: Replace calls to the now deprecated
Index: Source/win32/w32_windowdisplay.m
===================================================================
--- Source/win32/w32_windowdisplay.m (revision 24952)
+++ Source/win32/w32_windowdisplay.m (working copy)
@@ -35,6 +35,18 @@
{
WIN_INTERN *win = (WIN_INTERN *)GetWindowLong((HWND)hwnd, GWL_USERDATA);
+ if (!win->useHDC || win->backingStoreEmpty)
+ {
+ NSWindow *window = GSWindowWithNumber((int)hwnd);
+ NSRect r = MSWindowRectToGS(svr, (HWND)hwnd, rect);
+
+ /* Repaint the window's client area. */
+
+ [[[window contentView] superview] setNeedsDisplayInRect: r];
+ [[[window contentView] superview] displayIfNeeded];
+ win->backingStoreEmpty = NO;
+
+ }
if (win->useHDC)
{
HDC hdc = GetDC((HWND)hwnd);
@@ -49,18 +61,6 @@
}
ReleaseDC((HWND)hwnd, hdc);
}
- else
- {
- NSWindow *window = GSWindowWithNumber((int)hwnd);
- NSRect r = MSWindowRectToGS(svr, (HWND)hwnd, rect);
-
- /*
- NSLog(@"Invalidated window %d %@ (%d, %d, %d, %d)", hwnd,
- NSStringFromRect(r), rect.left, rect.top, rect.right, rect.bottom);
- */
- // Repaint the window's client area.
- [[[window contentView] superview] setNeedsDisplayInRect: r];
- }
}
@implementation WIN32Server (w32_windowdisplay)
@@ -206,6 +206,7 @@
RECT rect;
//LPPAINTSTRUCT lpPaint;
//HDC theHdc;
+ PAINTSTRUCT pPaint;
/*BOOL InvalidateRect(
HWND hWnd, // handle to window
@@ -216,14 +217,14 @@
//theHdc=BeginPaint(hwnd, lpPaint);
//if (flags.HOLD_PAINT_FOR_SIZING==FALSE)
// {
- if (GetUpdateRect(hwnd, &rect, NO))
+ if (GetUpdateRect(hwnd, &rect, TRUE))
{
- //InvalidateRect(hwnd, rect, YES);
-
+ BeginPaint(hwnd, &pPaint);
+
+ // Perform drawing (or blitting if buffered) in response to WM_PAINT
invalidateWindow(self, hwnd, rect);
- // validate the whole window, for in some cases an infinite series
- // of WM_PAINT is triggered
- ValidateRect(hwnd, NULL);
+
+ EndPaint(hwnd, &pPaint);
}
// }
flags._eventHandled=YES;
@@ -281,6 +282,7 @@
win->hdc = hdc2;
ReleaseDC((HWND)hwnd, hdc);
+ win->backingStoreEmpty = YES;
}
}
Index: Source/win32/WIN32Server.m
===================================================================
--- Source/win32/WIN32Server.m (revision 24952)
+++ Source/win32/WIN32Server.m (working copy)
@@ -418,8 +419,9 @@
/* stubs for window server events note other stubs should be
declared for mouse and keyboards
- these should be implmented in a subclass or a catagory
+ these should be implemented in a subclass or a catagory
*/
+
- (LRESULT) decodeWM_ACTIVEParams: (WPARAM)wParam : (LPARAM)lParam : (HWND)hwnd
{
[self subclassResponsibility: _cmd];
@@ -1084,6 +1086,11 @@
ReleaseDC((HWND)winNum, hdc);
}
+ else
+ {
+ win->useHDC = NO;
+ win->hdc = NULL;
+ }
}
- (void) titlewindow: (NSString*)window_title : (int) winNum
@@ -1706,14 +1713,15 @@
short deltaY = 0;
static int clickCount = 1;
static LONG lastTime = 0;
-
gcontext = GSCurrentContext();
eventLocation = MSWindowPointToGS(svr, hwnd, GET_X_LPARAM(lParam),
- GET_Y_LPARAM(lParam));
+ GET_Y_LPARAM(lParam));
ltime = GetMessageTime();
time = ltime / 1000;
tick = GetTickCount();
eventFlags = 0;
+
+
if (wParam & MK_CONTROL)
{
eventFlags |= NSControlKeyMask;
@@ -1765,7 +1773,30 @@
clickCount = 1;
lastTime = ltime;
}
+ /* Capture the mouse so we can receive a mouse up event outside of
+ a GNUstep window. Windows does not send mouse up events otherwise.*/
+ SetCapture(hwnd);
+
+ /* Store a copy of the button that went down so that we release
+ the capture on the correct mouse up event. */
+ if (svr->flags.lastButtonDownType)
+ svr->flags.lastButtonDownType = eventType;
}
+ else if ((eventType == NSLeftMouseUp)
+ || (eventType == NSRightMouseUp)
+ || (eventType == NSOtherMouseUp))
+ {
+ /* Release the mouse from this thread so that other threads can capture
+ it and that it is "best practice" to do so at this time. */
+ int lbdt = svr->flags.lastButtonDownType;
+ if ((eventType==NSLeftMouseUp && lbdt==NSLeftMouseDown) ||
+ (eventType==NSRightMouseUp && lbdt==NSRightMouseDown) ||
+ (eventType==NSOtherMouseUp && lbdt==NSOtherMouseDown))
+ {
+ ReleaseCapture();
+ svr->flags.lastButtonDownType = 0;
+ }
+ }
event = [NSEvent mouseEventWithType: eventType
location: eventLocation
Index: Source/win32/w32_movesize.m
===================================================================
--- Source/win32/w32_movesize.m (revision 24952)
+++ Source/win32/w32_movesize.m (working copy)
@@ -302,6 +302,27 @@
//printf("SIZING called\n");
//return TRUE;
+ NSPoint eventLocation;
+ NSRect rect;
+ RECT r;
+ NSEvent *ev =nil;
+
+ //GetWindowRect(hwnd, &r);
+ r = *((LPRECT)lParam);
+
+ rect = MSScreenRectToGS(r, [EVENT_WINDOW(hwnd) styleMask], self);
+ ev = [NSEvent otherEventWithType: NSAppKitDefined
+ location: eventLocation
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: (int)hwnd
+ context: GSCurrentContext()
+ subtype: GSAppKitWindowResized
+ data1: rect.size.width
+ data2: rect.size.height];
+ NSLog(@"Window SIZING, called with GSAppKitWindowResized and {%d,%d,%d,%d}",
+ r.left, r.top, r.right, r.bottom);
+ [self resizeBackingStoreFor:hwnd];
}
- (LRESULT) decodeWM_MOVINGParams:(HWND)hwnd : (WPARAM)wParam : (LPARAM)lParam
Index: Headers/win32/WIN32Server.h
===================================================================
--- Headers/win32/WIN32Server.h (revision 24952)
+++ Headers/win32/WIN32Server.h (working copy)
@@ -91,6 +91,7 @@
BOOL _hasGSClassName; // does the event window have a GSclassName
int lastEventType;
int hold;
+ int lastButtonDownType; // the button type of the last mouse down.
} serverFlags;
@interface WIN32Server : GSDisplayServer
@@ -171,6 +172,7 @@
typedef struct _win_intern {
BOOL useHDC;
+ BOOL backingStoreEmpty;
HDC hdc;
HGDIOBJ old;
MINMAXINFO minmax;
- Re: Window managers,
Christopher Armstrong <=