Hi Christopher, I am not sure if capturing the mouse is a great idea. I understand that we have the problem with Windows of not getting a mouse up event when the mouse leaves the current window. But this should be handled on another level. In most cases we are not interested in a mouse up, so why always capture it? This could disturb the interaction with other applications.
As for the change in windowbacking:, I could prove to you that it is not needed. But if you feel more comfortable with explicit code, it is fine for me. I feel a bit uncomfortable with the change to invalidateWindow(). This looks like a potential recursion problem. The back end here asks the front end to do some drawing and this of course will ask the back end to do it. I think it wont loop, but still it looks a bit dangerous. Perhaps some simplification and documentation of the code would help here. It looks like invalidateWindow is now only used in decodeWM_PAINTParams:::. So why not move the code to here? Cheers, Fred Christopher Armstrong wrote: > 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 <[EMAIL PROTECTED]> > + > + * 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 <[EMAIL PROTECTED]> > > * 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; > > > ------------------------------------------------------------------------ > > _______________________________________________ > Discuss-gnustep mailing list > [email protected] > http://lists.gnu.org/mailman/listinfo/discuss-gnustep _______________________________________________ Discuss-gnustep mailing list [email protected] http://lists.gnu.org/mailman/listinfo/discuss-gnustep
