Merge pull request #19 from gnustep/randr

Screens handling with RandR fixes
This commit is contained in:
Sergii Stoian 2020-02-08 02:51:58 +02:00 committed by GitHub
commit 74bab329ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 422 additions and 226 deletions

130
ChangeLog
View file

@ -1,4 +1,17 @@
2020-92-07 Fred Kiefer <FredKiefer@gmx.de>
2020-02-07 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (_XFrameToOSFrame:for:): use Xlib
screen height instead of monitor's because we convert coordinates
from Xlib area.
(movewindow::): use Xlib screen height because we're operating in
Xlib coordinate system.
(screenList): fill monitor depth with value returned by
windowPathForScreen with monitor at index 0 (screen_id already set so
method will get correct screen_id).
* Source/x11/XGServerEvent.m (processEvent:): fixed indentaion.
2020-02-07 Fred Kiefer <FredKiefer@gmx.de>
* Source/x11/XGServerWindow.m (swapColors): Made code more
explicit and removed additional copy before calling this function.
@ -6,16 +19,129 @@
(alphaMaskForImage): Slightly cleaner code.
* Source/x11/XGServerEvent.m: Prevent compiler warning by moving method.
2020-02-07 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (_OSFrameToXFrame:for:):,
(_OSFrameToXHints:for:): use Xlib screen height instead of monitor's
because we convert coordinates to Xlib area.
* Source/x11/XGServerEvent.m (processEvent:): update monitor_id from
NSWindow's screen number (it could change after event processing).
(mouseLocationOnScreen:window:): use Xlib screen height instead of
monitor's. Added comment to code that should be probably removed
later.
2020-02-03 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XWindowBuffer.m (windowBufferForWindow:depthInfo:): use
renamed XGServer's `screenVisual` and `screenDepth` methods.
* Source/x11/XIMInputServer.m (initWithDelegate:name:):
use `+xDisplay` instead of `xCurrentDisplay`.
(clientWindowRect:): ditto.
* Headers/x11/XGServerWindow.h (_gswindow_device_t):
renamed `screen` to `screen_id`. `monitor_id` element was added -
this is an index of element in MonitorDevice array.
* Source/x11/XGServerWindow.m:
Removed `screen` parameter from methods which contains it in name.
Methods were renamed to remove `Screen` and `FromScreen`.
(_OSFrameToXFrame:for:): use `monitor_id` instead of `screen`.
(_OSFrameToXHints:for:): ditto.
(_XFrameToOSFrame:for:): ditto.
(_checkStyle:): use renamed methods and `screen_id` window structure
element.
(_rootWindow): renamed from _rootWindowForScreen:, use `defScreen`
instead of removed parameter `screen`, set window structure element
`monitor_id` to 0.
(_createBuffer:): use `screen_id` window structure.
(window::::): use renamed methods, `defScreen`, `screen_id` and
`monitor_id` window scructure elements.
(nativeWindow:::::): ditto.
(setbackgroundcolor::): ditto.
(miniwindow:): ditto.
(_createAppIconPixmaps): removed unused `screen` local variable, use
renamed `screenRContext` method.
(orderwindow:::): use `screen_id` window structure element.
(movewindow::): use `screen_id` window structure element as a parameter
to `boundsForScreen`.
(windowbounds:): ditto.
(windowlist): use renamed `_rootWindow` method.
(setMouseLocation:onScreen:): user renamed methods.
(_blankCursor): ditto.
(imagecursor:::): ditto
(recolorcursor:::): ditto.
(screenList): change with assumption that Xlib screen is one per application.
Failback code to RandR-related always creates arrays with one element (no
enumeration needed). Create `monitor` structure in failback (non-RandR) code.
Use `screen_id` MonitorDevice structure element to hold Xlib screen ID.
(windowDepthForScreen:): assume that `screen` parameter is a Xlib screen ID,
simplify code - `screen` will be used with RandR or not.
(availableDepthsForScreen:): changed with assumption that `screen` is a index
of element in `monitors` structure.
* Source/x11/XGServerEvent.m:
use renamed methods and `screen_id` window structure element.
* Headers/x11/XGServer.h
Removed `screen` parameter from methods which contains it in name.
Methods were renamed to remove `Screen` and `FromScreen`.
(MonitorDevice): `screen_id` was added.
* Source/x11/XGServer.m:
use `screen_id` and rename mathods according to XGServer,h.
(_initXContext): initialize `monitors` array early here before first
use (calls to XGServerWindow methods).
* Source/x11/XGDragView.m (XDPY): use `monitor_id` in `boundForScreen:`
call.
* Source/cairo/XGCairoSurface.m: use `xDisplayRootWindow` XGServer's method.
* Source/art/ARTContext.m (setupDrawInfo:): use `xDisplayRootWindow`
XGServer's method.
2020-01-31 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (boundsForScreen:): check for number of
XRandR's ouputs.
2010-01-31 Riccardo Mottola <rm@gnu.org>
2020-01-31 Riccardo Mottola <rm@gnu.org>
* Source/x11/XGServerWindow.m (boundsForScreen:):
Check if Xrandr did not succeed and provide fallback.
2020-01-31 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (screenList): join RandR and non-RandR
code. Failback to Xlib generic method if any no RandR available or
RandR function call was unsuccessful. In Xlib generic method fill in
monitors array with values.
(boundsForScreen:): use values from cached `monitors` array since
-screenList fills it on both cases with or without RandR available.
2020-01-30 Sergii Stoian <stoyan255@gmail.com>
* Headers/x11/XGServer.h: new structure `MonitorDevice` and ivar
`monitors`for holding cache of monitor's parameters (depth, resolution,
frame). New ivar `monitorsCount` - holds number of items in `monitors` for
RandR or X11 screen count otherwise.
* Source/x11/XGServerWindow.m (screenList): new method for RandR mode -
enumerates monitors and caches their parameters. Returns array of monitors'
indices to get access to monitors` items.
(boundsForScreen:): use cached `frame` parameter of specified monitor.
Use `monitorsCount` instead of ScreenCount().
(windowDepthForScreen:): renamed method parameter; append `x_` prefix to
`Screen *` internal variable; validate `screen` parameter value; use
`defScreen` for RandR enabled code.
(availableDepthsForScreen:): ditto.
(resolutionForScreen:): renamed method parameter; validate `screen`
parameter value.
(boundsForScreen:): renamed method parameter.
* Source/x11/XGServer.m (dealloc): free `monitors` if it was used.
2020-01-26 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (boundsForScreen:): use `screen` variable

View file

@ -52,6 +52,13 @@ typedef enum {
XGDM_PORTABLE
} XGDrawMechanism;
typedef struct MonitorDevice {
int screen_id;
NSWindowDepth depth;
NSSize resolution;
NSRect frame;
} MonitorDevice;
@interface XGServer : GSDisplayServer
{
Display *dpy;
@ -62,21 +69,23 @@ typedef enum {
id inputServer;
int randrEventBase;
int randrErrorBase;
MonitorDevice *monitors;
unsigned monitorsCount;
}
+ (Display*) currentXDisplay;
- (Display*) xDisplay;
+ (Display *) xDisplay;
- (Display *) xDisplay;
- (Window) xDisplayRootWindow;
- (Window) xAppRootWindow;
- (void *) xrContextForScreen: (int)screen_number;
- (Visual *) visualForScreen: (int)screen_number;
- (int) depthForScreen: (int)screen_number;
- (void *) screenRContext;
- (Visual *) screenVisual;
- (int) screenDepth;
- (XGDrawMechanism) screenDrawMechanism;
- (XGDrawMechanism) drawMechanismForScreen: (int)screen_number;
- (void) getForScreen: (int)screen_number pixelFormat: (int *)bpp_number
masks: (int *)red_mask : (int *)green_mask : (int *)blue_mask;
- (Window) xDisplayRootWindowForScreen: (int)screen_number;
- (XColor) xColorFromColor: (XColor)color forScreen: (int)screen_number;
- (XColor) xColorFromColor: (XColor)color;
+ (void) waitAllContexts;
@end

View file

@ -84,8 +84,9 @@ typedef struct _gswindow_device_t {
Display *display; /* Display this window is on */
Window ident; /* Window handle */
Window root; /* Handle of root window */
Window parent; /* Handle of parent window */
int screen; /* Screeen this window is on */
Window parent; /* Handle of parent window */
int screen_id; /* Screeen this window is on */
int monitor_id; /* Physical monitor this window is on */
GC gc; /* GC for drawing */
long number; /* Globally unique identifier */
unsigned int depth; /* Window depth */

View file

@ -70,7 +70,7 @@
gswindow_device_t *gs_win;
gs_win = device;
[(XGServer *)server getForScreen: gs_win->screen pixelFormat: &bpp
[(XGServer *)server getForScreen: gs_win->screen_id pixelFormat: &bpp
masks: &red_mask : &green_mask : &blue_mask];
#endif
artcontext_setup_draw_info(&DI, red_mask, green_mask, blue_mask, bpp);

View file

@ -95,7 +95,7 @@
Window win;
XWindowAttributes attrs;
win = [self xDisplayRootWindowForScreen: screen];
win = [self xDisplayRootWindow];
if (XGetWindowAttributes(dpy, win, &attrs))
{

View file

@ -47,14 +47,14 @@
/* Size of the dragged window */
#define DWZ 48
#define XDPY [XGServer currentXDisplay]
#define XDPY [XGServer xDisplay]
#define SLIDE_TIME_STEP .02 /* in seconds */
#define SLIDE_NR_OF_STEPS 20
#define DRAGWINDEV [XGServer _windowWithTag: [_window windowNumber]]
#define XX(P) (P.x)
#define XY(P) ([GSCurrentServer() boundsForScreen: DRAGWINDEV->screen].size.height - P.y)
#define XY(P) ([GSCurrentServer() boundsForScreen: DRAGWINDEV->monitor_id].size.height - P.y)
@interface XGRawWindow : NSWindow
@end

View file

@ -141,7 +141,7 @@ _parse_display_name(NSString *name, int *dn, int *sn)
XGDrawMechanism drawMechanism;
}
- initForDisplay: (Display *)dpy screen: (int)screen_number;
- initForDisplay: (Display *)dpy screen: (int)screen_id;
- (XGDrawMechanism) drawMechanism;
- (RContext *) context;
@end
@ -173,7 +173,7 @@ _parse_display_name(NSString *name, int *dn, int *sn)
return attribs;
}
- initForDisplay: (Display *)dpy screen: (int)screen_number
- initForDisplay: (Display *)dpy screen: (int)screen_id
{
RContextAttributes *attribs;
XColor testColor;
@ -182,7 +182,7 @@ _parse_display_name(NSString *name, int *dn, int *sn)
/* Get the visual information */
attribs = NULL;
//attribs = [self _getXDefaults];
rcontext = RCreateContext(dpy, screen_number, attribs);
rcontext = RCreateContext(dpy, screen_id, attribs);
/*
* If we have shared memory available, only use it when the XGPS-Shm
@ -291,7 +291,7 @@ _parse_display_name(NSString *name, int *dn, int *sn)
drawMechanism = XGDM_PORTABLE;
}
NSDebugLLog(@"XGTrace", @"Draw mech %d for screen %d", drawMechanism,
screen_number);
screen_id);
return self;
}
@ -377,14 +377,14 @@ _parse_display_name(NSString *name, int *dn, int *sn)
Returns a pointer to the current X-Windows display variable for
the current context.
*/
+ (Display*) currentXDisplay
+ (Display *) xDisplay
{
return [(XGServer*)GSCurrentServer() xDisplay];
}
- (id) _initXContext
{
int screen_number, display_number;
int screen_id, display_id;
NSString *display_name;
display_name = [server_info objectForKey: GSDisplayName];
@ -436,13 +436,13 @@ _parse_display_name(NSString *name, int *dn, int *sn)
}
/* Parse display information */
_parse_display_name(display_name, &display_number, &screen_number);
_parse_display_name(display_name, &display_id, &screen_id);
NSDebugLog(@"Opened display %@, display %d screen %d",
display_name, display_number, screen_number);
display_name, display_id, screen_id);
[server_info setObject: display_name forKey: GSDisplayName];
[server_info setObject: [NSNumber numberWithInt: display_number]
[server_info setObject: [NSNumber numberWithInt: display_id]
forKey: GSDisplayNumber];
[server_info setObject: [NSNumber numberWithInt: screen_number]
[server_info setObject: [NSNumber numberWithInt: screen_id]
forKey: GSScreenNumber];
/* Setup screen*/
@ -450,7 +450,11 @@ _parse_display_name(NSString *name, int *dn, int *sn)
screenList = NSCreateMapTable(NSIntMapKeyCallBacks,
NSObjectMapValueCallBacks, 20);
defScreen = screen_number;
defScreen = screen_id;
/* Enumerate monitors */
if (monitors == NULL)
[self screenList];
XSetErrorHandler(XGErrorHandler);
@ -503,6 +507,10 @@ _parse_display_name(NSString *name, int *dn, int *sn)
DESTROY(inputServer);
[self _destroyServerWindows];
NSFreeMapTable(screenList);
if (monitors != NULL)
{
NSZoneFree([self zone], monitors);
}
XCloseDisplay(dpy);
[super dealloc];
}
@ -515,46 +523,57 @@ _parse_display_name(NSString *name, int *dn, int *sn)
return dpy;
}
- (XGScreenContext *) _screenContextForScreen: (int)screen_number
/**
Returns the root window of the display
*/
- (Window) xDisplayRootWindow;
{
int count = ScreenCount(dpy);
XGScreenContext *screen;
if (screen_number >= count)
{
[NSException raise: NSInvalidArgumentException
format: @"Request for invalid screen"];
}
screen = NSMapGet(screenList, (void *)(uintptr_t)screen_number);
if (screen == NULL)
{
screen = [[XGScreenContext alloc]
initForDisplay: dpy screen: screen_number];
NSMapInsert(screenList, (void *)(uintptr_t)screen_number, (void *)screen);
RELEASE(screen);
}
return screen;
return RootWindow(dpy, defScreen);
}
/**
Returns the application root window, which is used for many things
such as window hints
*/
- (Window) xAppRootWindow
{
return generic.appRootWindow;
}
- (XGScreenContext *) _defaultScreenContext
{
XGScreenContext *screenCtxt;
screenCtxt = NSMapGet(screenList, (void *)(uintptr_t)defScreen);
if (screenCtxt == NULL)
{
screenCtxt = [[XGScreenContext alloc] initForDisplay: dpy
screen: defScreen];
NSMapInsert(screenList, (void *)(uintptr_t)defScreen, (void *)screenCtxt);
RELEASE(screenCtxt);
}
return screenCtxt;
}
/**
Returns a pointer to a structure which describes aspects of the
X windows display
*/
- (void *) xrContextForScreen: (int)screen_number
- (void *) screenRContext
{
return [[self _screenContextForScreen: screen_number] context];
return [[self _defaultScreenContext] context];
}
- (Visual *) visualForScreen: (int)screen_number
- (Visual *) screenVisual
{
return [[self _screenContextForScreen: screen_number] context]->visual;
return [[self _defaultScreenContext] context]->visual;
}
- (int) depthForScreen: (int)screen_number
- (int) screenDepth
{
return [[self _screenContextForScreen: screen_number] context]->depth;
return [[self _defaultScreenContext] context]->depth;
}
/**
@ -562,9 +581,9 @@ _parse_display_name(NSString *name, int *dn, int *sn)
the screen and how pixels should be drawn to the screen for maximum
speed.
*/
- (XGDrawMechanism) drawMechanismForScreen: (int)screen_number
- (XGDrawMechanism) screenDrawMechanism
{
return [[self _screenContextForScreen: screen_number] drawMechanism];
return [[self _defaultScreenContext] drawMechanism];
}
// Could use NSSwapInt() instead
@ -596,48 +615,18 @@ static int byte_order(void)
/**
* Used by the art backend to determine the drawing mechanism.
*/
- (void) getForScreen: (int)screen_number pixelFormat: (int *)bpp_number
- (void) getForScreen: (int)screen_id pixelFormat: (int *)bpp_number
masks: (int *)red_mask : (int *)green_mask : (int *)blue_mask
{
Visual *visual;
XImage *i;
int bpp;
#if 0
XVisualInfo template;
XVisualInfo *visualInfo;
int numMatches;
/*
We need a visual that we can generate pixel values for by ourselves.
Thus, we try to find a DirectColor or TrueColor visual. If that fails,
we use the default visual and hope that it's usable.
*/
template.class = DirectColor;
visualInfo = XGetVisualInfo(dpy, VisualClassMask, &template, &numMatches);
if (!visualInfo)
{
template.class = TrueColor;
visualInfo = XGetVisualInfo(dpy, VisualClassMask, &template, &numMatches);
}
if (visualInfo)
{
visual = visualInfo->visual;
bpp = visualInfo->depth;
XFree(visualInfo);
}
else
{
visual = DefaultVisual(dpy, DefaultScreen(dpy));
bpp = DefaultDepth(dpy, DefaultScreen(dpy));
}
#else
RContext *context;
// Better to get the used visual from the context.
context = [self xrContextForScreen: screen_number];
context = [self screenRContext];
visual = context->visual;
bpp = context->depth;
#endif
i = XCreateImage(dpy, visual, bpp, ZPixmap, 0, NULL, 8, 8, 8, 0);
bpp = i->bits_per_pixel;
@ -673,44 +662,28 @@ static int byte_order(void)
}
}
/**
Returns the root window of the display
*/
- (Window) xDisplayRootWindowForScreen: (int)screen_number;
{
return RootWindow(dpy, screen_number);
}
/**
Returns the closest color in the current colormap to the indicated
X color
*/
- (XColor) xColorFromColor: (XColor)color forScreen: (int)screen_number
- (XColor) xColorFromColor: (XColor)color
{
Status ret;
RColor rcolor;
RContext *context = [self xrContextForScreen: screen_number];
RContext *context = [self screenRContext];
XAllocColor(dpy, context->cmap, &color);
rcolor.red = color.red / 256;
rcolor.green = color.green / 256;
rcolor.blue = color.blue / 256;
ret = RGetClosestXColor(context, &rcolor, &color);
if (ret == False)
NSLog(@"Failed to alloc color (%d,%d,%d)\n",
(int)rcolor.red, (int)rcolor.green, (int)rcolor.blue);
{
NSLog(@"Failed to alloc color (%d,%d,%d)\n",
(int)rcolor.red, (int)rcolor.green, (int)rcolor.blue);
}
return color;
}
/**
Returns the application root window, which is used for many things
such as window hints
*/
- (Window) xAppRootWindow
{
return generic.appRootWindow;
}
/**
Wait for all contexts to finish processing. Only used with XDPS graphics.
*/
@ -801,7 +774,6 @@ static int byte_order(void)
@end // XGServer (InputMethod)
//==== Additional code for NSTextView =========================================
//
// WARNING This section is not genuine part of the XGServer implementation.
@ -819,6 +791,11 @@ static int byte_order(void)
#include <AppKit/NSClipView.h>
#include <AppKit/NSTextView.h>
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
#endif
@implementation NSTextView (InputMethod)
- (void) _updateInputMethodState
@ -931,4 +908,8 @@ static int byte_order(void)
}
@end // NSTextView
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
//==== End: Additional Code for NSTextView ====================================

View file

@ -744,7 +744,7 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
else if ((Atom)xEvent.xclient.data.l[0]
== generic._NET_WM_PING_ATOM)
{
xEvent.xclient.window = RootWindow(dpy, cWin->screen);
xEvent.xclient.window = RootWindow(dpy, cWin->screen_id);
XSendEvent(dpy, xEvent.xclient.window, False,
(SubstructureRedirectMask | SubstructureNotifyMask),
&xEvent);
@ -796,7 +796,7 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
send ConfigureNotify events for app icons.
*/
XTranslateCoordinates(dpy, xEvent.xclient.window,
RootWindow(dpy, cWin->screen),
RootWindow(dpy, cWin->screen_id),
0, 0,
&root_x, &root_y,
&root_child);
@ -965,7 +965,7 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
int root_x, root_y;
Window root_child;
XTranslateCoordinates(dpy, xEvent.xconfigure.window,
RootWindow(dpy, cWin->screen),
RootWindow(dpy, cWin->screen_id),
0, 0,
&root_x, &root_y,
&root_child);
@ -1029,6 +1029,7 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
if (!NSEqualPoints(r.origin, x.origin))
{
NSEvent *r;
NSWindow *window;
r = [NSEvent otherEventWithType: NSAppKitDefined
location: eventLocation
@ -1045,7 +1046,12 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
* the programa can move/resize the window while we send
* this event, causing a confusion.
*/
[[NSApp windowWithWindowNumber: cWin->number] sendEvent: r];
window = [NSApp windowWithWindowNumber: cWin->number];
[window sendEvent: r];
/* Update monitor_id of the backend window.
NSWindow may change screen pointer while processing
the event. */
cWin->monitor_id = [[window screen] screenNumber];
}
}
break;
@ -2066,7 +2072,7 @@ static void
initialize_keyboard (void)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
Display *display = [XGServer currentXDisplay];
Display *display = [XGServer xDisplay];
// Below must be stored and checked as keysyms, not keycodes, since
// more than one keycode may be mapped t the same keysym
@ -2140,7 +2146,7 @@ set_up_num_lock (void)
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
Display *display = [XGServer currentXDisplay];
Display *display = [XGServer xDisplay];
KeyCode _num_lock_keycode;
// Get NumLock keycode
@ -2668,12 +2674,16 @@ process_modifier_flags(unsigned int state)
BOOL ok;
NSPoint p;
int height;
int screen_number;
screen_number = (screen >= 0) ? screen : defScreen;
ok = XQueryPointer (dpy, [self xDisplayRootWindowForScreen: screen_number],
&rootWin, &childWin, &currentX, &currentY, &winX, &winY, &mask);
int screen_id;
ok = XQueryPointer (dpy, [self xDisplayRootWindow],
&rootWin, &childWin, &currentX, &currentY,
&winX, &winY, &mask);
p = NSMakePoint(-1,-1);
/* FIXME: After multi-monitor support will be implemented `screen` method
parameter doesn't make sense. The `if{}` block should be removed since
we have only one screen and mouse can't be placed on "wrong" screen.
Also actually we need `height` of the whole Xlib screen (defScreen). */
if (ok == False)
{
/* Mouse not on the specified screen_number */
@ -2683,8 +2693,8 @@ process_modifier_flags(unsigned int state)
{
return p;
}
screen_number = XScreenNumberOfScreen(attribs.screen);
if (screen >= 0 && screen != screen_number)
screen_id = XScreenNumberOfScreen(attribs.screen);
if (screen >= 0 && screen != screen_id)
{
/* Mouse not on the requred screen, return an invalid point */
return p;
@ -2692,7 +2702,9 @@ process_modifier_flags(unsigned int state)
height = attribs.height;
}
else
height = [self boundsForScreen: screen_number].size.height;
{
height = DisplayHeight(dpy, defScreen);
}
p = NSMakePoint(currentX, height - currentY);
if (win)
{

View file

@ -444,7 +444,7 @@ BOOL AtomPresentAndPointsToItself(Display *dpy, Atom atom, Atom type)
}
@interface XGServer (WindowOps)
- (gswindow_device_t *) _rootWindowForScreen: (int)screen;
- (gswindow_device_t *) _rootWindow;
- (void) styleoffsets: (float *) l : (float *) r : (float *) t : (float *) b
: (unsigned int) style : (Window) win;
- (void) _setSupportedWMProtocols: (gswindow_device_t *) window;
@ -509,7 +509,7 @@ BOOL AtomPresentAndPointsToItself(Display *dpy, Atom atom, Atom type)
x.size.height = o.size.height - t - b;
x.origin.x = o.origin.x + l;
x.origin.y = o.origin.y + o.size.height - t;
x.origin.y = [self boundsForScreen: win->screen].size.height - x.origin.y;
x.origin.y = DisplayHeight(dpy, defScreen) - x.origin.y;
NSDebugLLog(@"Frame", @"O2X %lu, %x, %@, %@", win->number, style,
NSStringFromRect(o), NSStringFromRect(x));
return x;
@ -534,7 +534,7 @@ BOOL AtomPresentAndPointsToItself(Display *dpy, Atom atom, Atom type)
x.size.height = o.size.height - t - b;
x.origin.x = o.origin.x;
x.origin.y = o.origin.y + o.size.height;
x.origin.y = [self boundsForScreen: win->screen].size.height - x.origin.y;
x.origin.y = DisplayHeight(dpy, defScreen) - x.origin.y;
NSDebugLLog(@"Frame", @"O2H %lu, %x, %@, %@", win->number, style,
NSStringFromRect(o), NSStringFromRect(x));
return x;
@ -576,7 +576,7 @@ BOOL AtomPresentAndPointsToItself(Display *dpy, Atom atom, Atom type)
[self styleoffsets: &l : &r : &t : &b : style : win->ident];
o = x;
o.origin.y = [self boundsForScreen: win->screen].size.height - x.origin.y;
o.origin.y = DisplayHeight(dpy, defScreen) - x.origin.y;
o.origin.y = o.origin.y - x.size.height - b;
o.origin.x -= l;
o.size.width += l + r;
@ -816,13 +816,13 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
onScreen = [[NSUserDefaults standardUserDefaults] boolForKey:
@"GSBackChecksOffsetsOnScreen"];
root = [self _rootWindowForScreen: defScreen];
context = [self xrContextForScreen: defScreen];
root = [self _rootWindow];
context = [self screenRContext];
window = NSAllocateCollectable(sizeof(gswindow_device_t), NSScannedOption);
memset(window, '\0', sizeof(gswindow_device_t));
window->display = dpy;
window->screen = defScreen;
window->screen_id = defScreen;
window->win_attrs.flags |= GSWindowStyleAttr;
window->win_attrs.window_style = style;
@ -1239,14 +1239,14 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
return wmflags;
}
- (gswindow_device_t *) _rootWindowForScreen: (int)screen
- (gswindow_device_t *) _rootWindow
{
int x, y;
unsigned int width, height;
gswindow_device_t *window;
/* Screen number is negative to avoid conflict with windows */
window = WINDOW_WITH_TAG(-screen);
window = WINDOW_WITH_TAG(-defScreen);
if (window)
return window;
@ -1254,14 +1254,15 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
memset(window, '\0', sizeof(gswindow_device_t));
window->display = dpy;
window->screen = screen;
window->ident = RootWindow(dpy, screen);
window->screen_id = defScreen;
window->ident = RootWindow(dpy, defScreen);
window->root = window->ident;
window->type = NSBackingStoreNonretained;
window->number = -screen;
window->number = -defScreen;
window->map_state = IsViewable;
window->visibility = -1;
window->wm_state = NormalState;
window->monitor_id = 0;
if (window->ident)
{
XGetGeometry(dpy, window->ident, &window->root,
@ -1732,7 +1733,7 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
- (void) _createBuffer: (gswindow_device_t *)window
{
if (window->depth == 0)
window->depth = DefaultDepth(dpy, window->screen);
window->depth = DefaultDepth(dpy, window->screen_id);
if (NSWidth(window->xframe) == 0 && NSHeight(window->xframe) == 0)
{
NSDebugLLog(@"NSWindow", @"Cannot create buffer for ZeroRect frame");
@ -1894,15 +1895,16 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
_wmAppIcon = -1;
return win;
}
root = [self _rootWindowForScreen: screen];
context = [self xrContextForScreen: screen];
root = [self _rootWindow];
context = [self screenRContext];
/* Create the window structure and set the style early so we can use it to
convert frames. */
window = NSAllocateCollectable(sizeof(gswindow_device_t), NSScannedOption);
memset(window, '\0', sizeof(gswindow_device_t));
window->display = dpy;
window->screen = screen;
window->screen_id = defScreen;
window->monitor_id = screen;
window->win_attrs.flags |= GSWindowStyleAttr;
if (handlesWindowDecorations)
@ -2097,15 +2099,16 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
*screen = XScreenNumberOfScreen(win_attributes.screen);
*type = NSBackingStoreNonretained;
*style = NSBorderlessWindowMask;
root = [self _rootWindowForScreen: *screen];
context = [self xrContextForScreen: *screen];
root = [self _rootWindow];
context = [self screenRContext];
/* Create the window structure and set the style early so we can use it to
convert frames. */
window = NSAllocateCollectable(sizeof(gswindow_device_t), NSScannedOption);
memset(window, '\0', sizeof(gswindow_device_t));
window->display = dpy;
window->screen = *screen;
window->screen_id = *screen;
window->monitor_id = 0;
window->ident = windowRef;
window->root = root->ident;
window->parent = root->ident;
@ -2407,7 +2410,7 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
xf.green = 65535 * [color greenComponent];
xf.blue = 65535 * [color blueComponent];
NSDebugLLog(@"XGTrace", @"setbackgroundcolor: %@ %d", color, win);
xf = [self xColorFromColor: xf forScreen: window->screen];
xf = [self xColorFromColor: xf];
window->xwn_attrs.background_pixel = xf.pixel;
XSetWindowBackground(dpy, window->ident, window->xwn_attrs.background_pixel);
}
@ -2589,9 +2592,9 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
under metacity, which sets _NET_WM_STATE for shaded windows to both
_NET_WM_STATE_SHADED and _NET_WM_STATE_HIDDEN. */
if (generic.flags.appOwnsMiniwindow && !(generic.wm & XGWM_WINDOWMAKER))
XWithdrawWindow(dpy, window->ident, window->screen);
XWithdrawWindow(dpy, window->ident, window->screen_id);
else if (window->wm_state != IconicState)
XIconifyWindow(dpy, window->ident, window->screen);
XIconifyWindow(dpy, window->ident, window->screen_id);
}
/* Actually this is "hide application" action.
@ -2820,7 +2823,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
- (int) _createAppIconPixmaps
{
NSBitmapImageRep *rep;
int width, height, colors, screen;
int width, height, colors;
RContext *rcontext;
RXImage *rxImage;
@ -2832,8 +2835,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
if (rep == nil)
return 0;
screen = [[[self screenList] objectAtIndex: 0] intValue];
rcontext = [self xrContextForScreen: screen];
rcontext = [self screenRContext];
width = [rep pixelsWide];
height = [rep pixelsHigh];
colors = [rep samplesPerPixel];
@ -3008,14 +3010,14 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
XWindowChanges chg;
chg.sibling = other->ident;
chg.stack_mode = Below;
XReconfigureWMWindow(dpy, window->ident, window->screen,
XReconfigureWMWindow(dpy, window->ident, window->screen_id,
CWSibling|CWStackMode, &chg);
}
else
{
XWindowChanges chg;
chg.stack_mode = Below;
XReconfigureWMWindow(dpy, window->ident, window->screen,
XReconfigureWMWindow(dpy, window->ident, window->screen_id,
CWStackMode, &chg);
}
XMapWindow(dpy, window->ident);
@ -3027,21 +3029,21 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
XWindowChanges chg;
chg.sibling = other->ident;
chg.stack_mode = Above;
XReconfigureWMWindow(dpy, window->ident, window->screen,
XReconfigureWMWindow(dpy, window->ident, window->screen_id,
CWSibling|CWStackMode, &chg);
}
else
{
XWindowChanges chg;
chg.stack_mode = Above;
XReconfigureWMWindow(dpy, window->ident, window->screen,
XReconfigureWMWindow(dpy, window->ident, window->screen_id,
CWStackMode, &chg);
}
XMapWindow(dpy, window->ident);
break;
case NSWindowOut:
XWithdrawWindow (dpy, window->ident, window->screen);
XWithdrawWindow (dpy, window->ident, window->screen_id);
break;
}
/*
@ -3190,7 +3192,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
}
window->siz_hints.x = (int)loc.x;
window->siz_hints.y = (int)([self boundsForScreen: window->screen].size.height -
window->siz_hints.y = (int)(DisplayHeight(dpy, defScreen) -
loc.y - window->siz_hints.height);
XMoveWindow (dpy, window->ident, window->siz_hints.x, window->siz_hints.y);
setNormalHints(dpy, window);
@ -3324,7 +3326,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
&x, &y, &width, &height, &window->border, &window->depth);
window->xframe = NSMakeRect(x, y, width, height);
screenHeight = [self boundsForScreen: window->screen].size.height;
screenHeight = [self boundsForScreen: window->monitor_id].size.height;
rect = window->xframe;
rect.origin.y = screenHeight - NSMaxY(window->xframe);
return rect;
@ -3522,7 +3524,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
NSMutableArray *ret;
int c;
rootWindow = [self _rootWindowForScreen: defScreen];
rootWindow = [self _rootWindow];
windowOrder = (Window *)PropGetCheckProperty(dpy, rootWindow->ident,
generic._NET_CLIENT_LIST_STACKING_ATOM,
@ -3835,7 +3837,7 @@ swapColors(unsigned char *image_data, NSBitmapImageRep *rep)
destY = height - mouseLocation.y;
destX = mouseLocation.x;
XWarpPointer(dpy, None, [self xDisplayRootWindowForScreen: aScreen],
XWarpPointer(dpy, None, [self xDisplayRootWindow],
0, 0, 0, 0, destX, destY);
}
@ -4030,7 +4032,7 @@ static BOOL cursor_hidden = NO;
{
Pixmap shape, mask;
XColor black, white;
Drawable drw = [self xDisplayRootWindowForScreen: defScreen];
Drawable drw = [self xDisplayRootWindow];
shape = XCreatePixmapFromBitmapData(dpy, drw,
xgps_blank_cursor_bits,
@ -4039,9 +4041,9 @@ static BOOL cursor_hidden = NO;
xgps_blank_cursor_bits,
16, 16, 1, 0, 1);
black.red = black.green = black.blue = 0;
black = [self xColorFromColor: black forScreen: defScreen];
black = [self xColorFromColor: black];
white.red = white.green = white.blue = 65535;
white = [self xColorFromColor: white forScreen: defScreen];
white = [self xColorFromColor: white];
xgps_blank_cursor = XCreatePixmapCursor(dpy, shape, mask,
&white, &black, 0, 0);
@ -4320,8 +4322,8 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
source = xgps_cursor_image(dpy, ROOT, data, w, h, colors, &fg, &bg);
mask = alphaMaskForImage(dpy, ROOT, data, w, h, colors, ALPHA_THRESHOLD);
bg = [self xColorFromColor: bg forScreen: defScreen];
fg = [self xColorFromColor: fg forScreen: defScreen];
bg = [self xColorFromColor: bg];
fg = [self xColorFromColor: fg];
cursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg,
(int)hotp.x, (int)hotp.y);
@ -4359,8 +4361,8 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
xb.red = 65535 * [bg redComponent];
xb.green = 65535 * [bg greenComponent];
xb.blue = 65535 * [bg blueComponent];
xf = [self xColorFromColor: xf forScreen: defScreen];
xb = [self xColorFromColor: xb forScreen: defScreen];
xf = [self xColorFromColor: xf];
xb = [self xColorFromColor: xb];
XRecolorCursor(dpy, cursor, &xf, &xb);
}
@ -4393,6 +4395,10 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
XFreeCursor(dpy, cursor);
}
/*******************************************************************************
* Screens, monitors
*******************************************************************************/
static NSWindowDepth
_computeDepth(int class, int bpp)
{
@ -4430,67 +4436,146 @@ _computeDepth(int class, int bpp)
return depth;
}
/* This method assumes that we deal with one X11 screen - `defScreen`.
Basically it means that we have DISPLAY variable set to `:0.0`.
Where both digits have artbitrary values, but it defines once on
every application run.
AppKit and X11 use the same term "screen" with different meaning:
AppKit Screen - single monitor/display device.
X11 Screen - it's a plane where X Server can draw on.
XRandR - Xorg extension that helps to manipulate monitor layout providing
X11 Screen.
We map XRandR monitors (outputs) to NSScreen. */
- (NSArray *)screenList
{
/* I guess screen numbers are in order starting from zero, but we
put the main screen first */
int i;
int count = ScreenCount(dpy);
NSMutableArray *screens = [NSMutableArray arrayWithCapacity: count];
if (count > 0)
[screens addObject: [NSNumber numberWithInt: defScreen]];
for (i = 0; i < count; i++)
{
if (i != defScreen)
[screens addObject: [NSNumber numberWithInt: i]];
}
return screens;
NSArray *screens;
NSMutableArray *tmpScreens;
int i;
monitorsCount = 0;
if (monitors != NULL) {
NSZoneFree([self zone], monitors);
monitors = NULL;
}
#ifdef HAVE_XRANDR
XRRScreenResources *screen_res;
RROutput primary_output;
XRROutputInfo *output_info;
XRRCrtcInfo *crtc_info;
int mi;
screen_res = XRRGetScreenResources(dpy, RootWindow(dpy, defScreen));
if (screen_res != NULL)
{
monitorsCount = screen_res->noutput;
tmpScreens = [NSMutableArray arrayWithCapacity: monitorsCount];
monitors = NSZoneMalloc([self zone], monitorsCount * sizeof(MonitorDevice));
primary_output = XRRGetOutputPrimary(dpy, [self xDisplayRootWindow]);
for (i = 0, mi = 0; i < screen_res->noutput; i++)
{
output_info = XRRGetOutputInfo(dpy, screen_res, screen_res->outputs[i]);
if (output_info->crtc)
{
crtc_info = XRRGetCrtcInfo(dpy, screen_res, output_info->crtc);
monitors[mi].screen_id = defScreen;
monitors[mi].depth = [self windowDepthForScreen: mi];
monitors[mi].resolution = [self resolutionForScreen: defScreen];
monitors[mi].frame = NSMakeRect(crtc_info->x, crtc_info->y,
crtc_info->width, crtc_info->height);
/* Add monitor ID (index in monitors array).
Put primary monitor ID index 0 since NSScreen get this as main
screen if application has no key window. */
if (screen_res->outputs[i] == primary_output)
{
[tmpScreens insertObject: [NSNumber numberWithInt: mi] atIndex: 0];
}
else
{
[tmpScreens addObject: [NSNumber numberWithInt: mi]];
}
mi++;
}
}
XRRFreeScreenResources(screen_res);
screens = [NSArray arrayWithArray: tmpScreens];
}
#endif
if (monitorsCount == 0)
{
/* It is assumed that there is always only one screen per application.
We only need to know its number and it was saved in _initXContext as
`defScreen`. */
monitorsCount = 1;
monitors = NSZoneMalloc([self zone], sizeof(MonitorDevice));
monitors[0].screen_id = defScreen;
monitors[0].depth = [self windowDepthForScreen: 0];
monitors[0].resolution = [self resolutionForScreen: defScreen];
monitors[0].frame = NSMakeRect(0, 0,
DisplayWidth(dpy, defScreen),
DisplayHeight(dpy, defScreen));
screens = [NSArray arrayWithObject: [NSNumber numberWithInt: defScreen]];
}
return screens;
}
- (NSWindowDepth) windowDepthForScreen: (int) screen_num
// `screen` is a monitor index not X11 screen
- (NSWindowDepth) windowDepthForScreen: (int)screen
{
Screen *screen;
Screen *x_screen;
int class = 0, bpp = 0;
screen = XScreenOfDisplay(dpy, screen_num);
if (screen == NULL)
if (screen < 0 || screen >= monitorsCount)
{
return 0;
}
x_screen = XScreenOfDisplay(dpy, monitors[screen].screen_id);
if (x_screen == NULL)
{
return 0;
}
bpp = screen->root_depth;
class = screen->root_visual->class;
bpp = x_screen->root_depth;
class = x_screen->root_visual->class;
return _computeDepth(class, bpp);
}
- (const NSWindowDepth *) availableDepthsForScreen: (int) screen_num
// `screen` is a monitor index not X11 screen
- (const NSWindowDepth *) availableDepthsForScreen: (int)screen
{
Screen *screen;
Screen *x_screen;
int class = 0;
int index = 0;
int ndepths = 0;
NSZone *defaultZone = NSDefaultMallocZone();
NSWindowDepth *depths = 0;
if (dpy == NULL)
if (dpy == NULL || screen < 0 || screen >= monitorsCount)
{
return NULL;
}
screen = XScreenOfDisplay(dpy, screen_num);
if (screen == NULL)
x_screen = XScreenOfDisplay(dpy, monitors[screen].screen_id);
if (x_screen == NULL)
{
return NULL;
}
// Allocate the memory for the array and fill it in.
ndepths = screen->ndepths;
class = screen->root_visual->class;
ndepths = x_screen->ndepths;
class = x_screen->root_visual->class;
depths = NSZoneMalloc(defaultZone, sizeof(NSWindowDepth)*(ndepths + 1));
for (index = 0; index < ndepths; index++)
{
int depth = screen->depths[index].depth;
int depth = x_screen->depths[index].depth;
depths[index] = _computeDepth(class, depth);
}
depths[index] = 0; // terminate with a zero.
@ -4498,6 +4583,7 @@ _computeDepth(int class, int bpp)
return depths;
}
// `screen_num` is a Xlib screen number.
- (NSSize) resolutionForScreen: (int)screen_num
{
// NOTE:
@ -4516,56 +4602,37 @@ _computeDepth(int class, int bpp)
/*
int res_x, res_y;
if (screen_num < 0 || screen_num >= ScreenCount(dpy))
if (screen < 0 || screen_num >= ScreenCount(dpy))
{
NSLog(@"Invalidparam: no screen %d", screen_num);
NSLog(@"Invalidparam: no screen %d", screen);
return NSMakeSize(0,0);
}
// This does not take virtual displays into account!!
res_x = DisplayWidth(dpy, screen_num) /
(DisplayWidthMM(dpy, screen_num) / 25.4);
res_y = DisplayHeight(dpy, screen_num) /
(DisplayHeightMM(dpy, screen_num) / 25.4);
res_x = DisplayWidth(dpy, screen) /
(DisplayWidthMM(dpy, screen) / 25.4);
res_y = DisplayHeight(dpy, screen) /
(DisplayHeightMM(dpy, screen) / 25.4);
return NSMakeSize(res_x, res_y);
*/
}
// `screen` is a monitor index not X11 screen
- (NSRect) boundsForScreen: (int)screen
{
NSRect boundsRect = NSZeroRect;
if (screen < 0 || screen >= ScreenCount(dpy))
if (screen < 0 || screen >= monitorsCount)
{
NSLog(@"Invalidparam: no screen %d", screen);
return NSZeroRect;
}
#ifdef HAVE_XRANDR
XRRScreenResources *screen_res;
XRROutputInfo *output_info;
screen_res = XRRGetScreenResources(dpy, RootWindow(dpy, screen));
if (screen_res != NULL && screen_res->noutput > 0)
if (monitors != NULL)
{
output_info = XRRGetOutputInfo(dpy, screen_res, screen_res->outputs[screen]);
if (NULL != output_info && 0 != output_info->crtc)
{
XRRCrtcInfo *crtc_info;
crtc_info = XRRGetCrtcInfo(dpy, screen_res, output_info->crtc);
boundsRect = NSMakeRect(crtc_info->x, crtc_info->y,
crtc_info->width, crtc_info->height);
}
boundsRect = monitors[screen].frame;
}
XRRFreeScreenResources(screen_res);
#endif
// no XRandr available or XRR call failed
if (NSEqualRects(boundsRect, NSZeroRect))
{
boundsRect = NSMakeRect(0, 0, DisplayWidth(dpy, screen),
DisplayHeight(dpy, screen));
}
return boundsRect;
}

View file

@ -61,7 +61,7 @@
- (id) initWithDelegate: (id)aDelegate
name: (NSString *)name
{
Display *dpy = [XGServer currentXDisplay];
Display *dpy = [XGServer xDisplay];
return [self initWithDelegate: aDelegate display: dpy name: name];
}
@ -380,7 +380,7 @@ betterStyle(XIMStyle a, XIMStyle b, XIMStyle xim_requested_style)
}
else if (xim_style == OffTheSpotStyle || xim_style == OverTheSpotStyle)
{
Display *dpy = [XGServer currentXDisplay];
Display *dpy = [XGServer xDisplay];
XFontSet font_set;
char **missing_charset;
int num_missing_charset;
@ -556,7 +556,7 @@ finish:
if (XGetICValues(xics[num_xics - 1], XNClientWindow, &win, NULL))
return NO;
dpy = [XGServer currentXDisplay];
dpy = [XGServer xDisplay];
if (XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), 0, 0,
&abs_x, &abs_y, &dummy) == 0)
return NO;

View file

@ -222,8 +222,8 @@ no_xshm:
visual = DefaultVisual(wi->display, DefaultScreen(wi->display));
#else
// Better to get the used visual from the XGServer.
visual = [(XGServer*)GSCurrentServer() visualForScreen: awindow->screen];
drawing_depth = [(XGServer*)GSCurrentServer() depthForScreen: awindow->screen];
visual = [(XGServer*)GSCurrentServer() screenVisual];
drawing_depth = [(XGServer*)GSCurrentServer() screenDepth];
#endif
/* TODO: resolve properly.