diff --git a/ChangeLog b/ChangeLog index cccdc3f..5a71f8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2004-06-26 13:04 Alexander Malmberg + + * Source/x11/XGServerEvent.m (-processEvent: ConfigureNotify): + Don't ignore the event for unmapped windows. Use XTranslateCoordinates + to get the size and position right for both real and artificial + events. Only update the position hints if we're mapped. + + * Source/x11/XGServerWindow.m: Add handlesWindowDecorations variable. + (-handlesWindowDecorations): New method. + (setWindowHintsForStyle, -styleoffsets:::::): If we aren't handling + window decorations, treat all windows as borderless. + (-stylewindow::, -setinputstate::): Assert that we're handling window + decorations. + (-window::::): Create the window structure earlier so it can be used + to convert frames. + (-_setupRootWindow): Set handlesWindowDecorations based on the + GSX11HandlesWindowDecorations defaults value. + + * Documentation/Back/DefaultsSummary.gsdoc: Document + GSX11HandlesWindowDecorations. + 2004-06-19 Fred Kiefer * Source/win32/WIN32Server.m (-findWindowAt:windowRef:excluding:) diff --git a/Documentation/Back/DefaultsSummary.gsdoc b/Documentation/Back/DefaultsSummary.gsdoc index 3f03997..9ec427d 100644 --- a/Documentation/Back/DefaultsSummary.gsdoc +++ b/Documentation/Back/DefaultsSummary.gsdoc @@ -110,6 +110,16 @@ OverTheSpot.

+ GSX11HandlesWindowDecorations + +

[X11-based backends only] + A boolean value, by default YES, which indicates if + the backend should let the window manager handle window + decorations. When set to NO, GNUstep-GUI will handle + the window decorations, which is particularly useful if you aren't + running any window manager. +

+
GraphicCompositing

[Xlib backend only] diff --git a/Source/x11/XGServerEvent.m b/Source/x11/XGServerEvent.m index 5f1becf..1eed9c7 100644 --- a/Source/x11/XGServerEvent.m +++ b/Source/x11/XGServerEvent.m @@ -685,34 +685,45 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code) xEvent.xconfigure.send_event ? 'T' : 'F'); if (cWin == 0 || xEvent.xconfigure.window != cWin->ident) generic.cachedWindow = [XGServer _windowForXWindow:xEvent.xconfigure.window]; - /* - * Ignore events for unmapped windows. - */ - if (cWin != 0 && cWin->map_state == IsViewable) + + if (cWin != 0) { NSRect r, x, n, h; NSTimeInterval ts = (NSTimeInterval)generic.lastMotion; - /* - * Get OpenStep frame coordinates from X frame. - * If it's not from the window mmanager, ignore x and y. - */ r = cWin->xframe; + + x = NSMakeRect(xEvent.xconfigure.x, + xEvent.xconfigure.y, + xEvent.xconfigure.width, + xEvent.xconfigure.height); + + /* + According to the ICCCM, coordinates in synthetic events + (ie. non-zero send_event) are in root space, while coordinates + in real events are in the parent window's space. The parent + window might be some window manager window, so we can't + directly use those coordinates. + + Thus, if the event is real, we use XTranslateCoordinates to + get the root space coordinates. + */ if (xEvent.xconfigure.send_event == 0) { - x = NSMakeRect(r.origin.x, r.origin.y, - xEvent.xconfigure.width, xEvent.xconfigure.height); - } - else - { - x = NSMakeRect(xEvent.xconfigure.x, - xEvent.xconfigure.y, - xEvent.xconfigure.width, - xEvent.xconfigure.height); - cWin->xframe.origin = x.origin; + int root_x, root_y; + Window root_child; + XTranslateCoordinates(dpy, xEvent.xconfigure.window, + RootWindow(dpy, cWin->screen), + 0, 0, + &root_x, &root_y, + &root_child); + x.origin.x = root_x; + x.origin.y = root_y; } + + cWin->xframe = x; n = [self _XFrameToOSFrame: x for: cWin]; - NSDebugLLog(@"Moving", + NSDebugLLog(@"Moving", @"Update win %d:\n original:%@\n new:%@", cWin->number, NSStringFromRect(r), NSStringFromRect(x)); @@ -722,18 +733,26 @@ static inline int check_modifier (XEvent *xEvent, KeyCode key_code) h = [self _OSFrameToXHints: n for: cWin]; cWin->siz_hints.width = h.size.width; cWin->siz_hints.height = h.size.height; - //if (xEvent.xconfigure.send_event != 0) - { - cWin->siz_hints.x = h.origin.x; - cWin->siz_hints.y = h.origin.y; - } + + /* + We only update the position hints if we're on the screen. + Otherwise, the window manager might not have added decorations + (if any) to the window yet. Since we compensate for decorations + when we set the position, this will confuse us and we'll end + up compensating twice, which makes windows drift. + */ + if (cWin->map_state == IsViewable) + { + cWin->siz_hints.x = h.origin.x; + cWin->siz_hints.y = h.origin.y; + } /* * create GNUstep event(s) */ if (!NSEqualSizes(r.size, x.size)) { - /* Resize events move the origin. There's no goo + /* Resize events move the origin. There's no good place to pass this info back, so we put it in the event location field */ e = [NSEvent otherEventWithType: NSAppKitDefined diff --git a/Source/x11/XGServerWindow.m b/Source/x11/XGServerWindow.m index 01a7142..a00a8ea 100644 --- a/Source/x11/XGServerWindow.m +++ b/Source/x11/XGServerWindow.m @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,10 @@ #define ROOT generic.appRootWindow + +static BOOL handlesWindowDecorations = YES; + + /* * Name for application root window. */ @@ -232,7 +237,8 @@ static void setWindowHintsForStyle (Display *dpy, Window window, hints->functions = 0; /* Now add to the hints from the styleMask */ - if (styleMask == NSBorderlessWindowMask) + if (styleMask == NSBorderlessWindowMask + || !handlesWindowDecorations) { hints->flags |= MWM_HINTS_DECORATIONS; hints->flags |= MWM_HINTS_FUNCTIONS; @@ -321,6 +327,12 @@ static void setWindowHintsForStyle (Display *dpy, Window window, @implementation XGServer (WindowOps) +-(BOOL) handlesWindowDecorations +{ + return handlesWindowDecorations; +} + + /* * Where a window has been reparented by the wm, we use this method to * locate the window given knowledge of its border window. @@ -744,6 +756,10 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, * Now check user defaults. */ defs = [NSUserDefaults standardUserDefaults]; + + if ([defs objectForKey: @"GSX11HandlesWindowDecorations"]) + handlesWindowDecorations = [defs boolForKey: @"GSX11HandlesWindowDecorations"]; + generic.flags.useWindowMakerIcons = NO; if ((generic.wm & XGWM_WINDOWMAKER) != 0) { @@ -935,7 +951,20 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, root = [self _rootWindowForScreen: screen]; context = [self xrContextForScreen: screen]; - frame = [NSWindow contentRectForFrameRect: frame styleMask: style]; + /* Create the window structure and set the style early so we can use it to + convert frames. */ + window = objc_malloc(sizeof(gswindow_device_t)); + memset(window, '\0', sizeof(gswindow_device_t)); + window->display = dpy; + window->screen = screen; + + window->win_attrs.flags |= GSWindowStyleAttr; + if (handlesWindowDecorations) + window->win_attrs.window_style = style; + else + window->win_attrs.window_style = style & (NSIconWindowMask | NSMiniWindowMask); + + frame = [self _OSFrameToXFrame: frame for: window]; /* We're not allowed to create a zero rect window */ if (NSWidth(frame) <= 0 || NSHeight(frame) <= 0) @@ -943,13 +972,6 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, frame.size.width = 2; frame.size.height = 2; } - /* Translate to X coordinates */ - frame.origin.y = DisplayHeight(dpy, screen) - NSMaxY(frame); - - window = objc_malloc(sizeof(gswindow_device_t)); - memset(window, '\0', sizeof(gswindow_device_t)); - window->display = dpy; - window->screen = screen; window->xframe = frame; window->type = type; window->root = root->ident; @@ -966,7 +988,7 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, context->depth, CopyFromParent, context->visual, - (CWColormap | CWBackPixel|CWBorderPixel), + (CWColormap | CWBackPixel | CWBorderPixel), &window->xwn_attrs); /* @@ -1002,15 +1024,13 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, * Initial attributes for any GNUstep window tell Window Maker not to * create an app icon for us. */ - window->win_attrs.flags = GSExtraFlagsAttr; - window->win_attrs.extra_flags = GSNoApplicationIconFlag; + window->win_attrs.flags |= GSExtraFlagsAttr; + window->win_attrs.extra_flags |= GSNoApplicationIconFlag; /* * Prepare size/position hints, but don't set them now - ordering * the window in should automatically do it. */ - window->win_attrs.flags |= GSWindowStyleAttr; - window->win_attrs.window_style = style; frame = [self _XFrameToOSFrame: window->xframe for: window]; frame = [self _OSFrameToXHints: frame for: window]; window->siz_hints.x = NSMinX(frame); @@ -1125,6 +1145,17 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, - (void) styleoffsets: (float *) l : (float *) r : (float *) t : (float *) b : (unsigned int) style { + if (!handlesWindowDecorations) + { + /* + If we don't handle decorations, all our windows are going to be + border- and decorationless. In that case, -gui won't call this method, + but we still use it internally. + */ + *l = *r = *t = *b = 0.0; + return; + } + /* First try to get the offset information that we have obtained from the WM. This will only work if the application has already created a window that has been reparented by the WM. Otherwise we have to @@ -1212,6 +1243,8 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, { gswindow_device_t *window; + NSAssert(handlesWindowDecorations, @"-stylewindow:: called when handlesWindowDecorations==NO"); + window = WINDOW_WITH_TAG(win); if (!window) return; @@ -2369,6 +2402,9 @@ NSDebugLLog(@"Frame", @"X2O %d, %@, %@", win->number, */ - (void) setinputstate: (int)st : (int)win { + if (!handlesWindowDecorations) + return; + NSDebugLLog(@"XGTrace", @"DPSsetinputstate: %d : %d", st, win); if ((generic.wm & XGWM_WINDOWMAKER) != 0) {