Merge branch 'master' of github.com:gnustep/libs-back into android-back

This commit is contained in:
Gregory Casamento 2020-01-20 23:28:50 -05:00
commit b9248d19a8
4 changed files with 283 additions and 231 deletions

View file

@ -1,3 +1,48 @@
2020-01-16 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerEvent.m (_handleTakeFocusAtom:forContext:): use
lowerCamelCase for objects and underscores for primitive types;
do not ignore TakeFocus request if no key window was set
and main application menu receives request.
2020-01-14 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (alphaMaskForImage): renamed from
image_mask().
(swapColors): new function to convert colors from ARGB order into RGBA
(big-endian systems) or BGRA (little-endian systems).
(_createAppIconPixmaps): use swapColors() and remove unused code.
(restrictWindow:toImage:): use alphaMaskForImage().
(imagecursor:::): use swapColors() and remove unused code.
(ALPHA_THRESHOLD): removed duplicate of definition.
2020-01-13 Sergii Stoian <stoyan255@gmail.com>
* Source/x11/XGServerWindow.m (_createNetIcon:result:size:): fixed
off-by-one mistake during alpha handling. Enable disabled code and
remove temprorary one.
(window::::): set NetWM icon to window for all EWMH capable WMs even
it's WindowMaker.
(image_mask): new function to create alpha mask for image. It's based
on xgps_cursor_mask() code with additional argument `alpha_treshold`.
This function may be used for images (alpha_treshold == 0) with real
alpha mask and for cursors (if no Xcursor library is used - no alpha
is used, no shadows in cursors, alpha_treshold == 158 is used to cut
transparent pixels).
(_createAppIconPixmaps): icon pixmap creation rewritten to support
images with alpha channel using wraster functions. Use image_mask().
(restrictWindow:toImage:): use image_mask() instead of
xgps_cursor_mask().
(xgps_cursor_mask): removed as image_mask() replaced it.
Guard xgps_cursor_image( with #if - will not be compiled if Xcursor
is used.
(imagecursor:::): use image_mask() instead of xgps_cursor_mask().
2019-12-24 Fred Kiefer <FredKiefer@gmx.de>
* Source/cairo/CairoFontInfo.m: Revert to the old defaults for
hinting and allow for all possible values to be set.
2019-05-19 Fred Kiefer <FredKiefer@gmx.de>
* Source/cairo/CairoFontInfo.m,

View file

@ -42,6 +42,80 @@
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
void set_font_options(cairo_font_options_t *options)
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
cairo_hint_metrics_t metrics = CAIRO_HINT_METRICS_ON;
cairo_hint_style_t style = CAIRO_HINT_STYLE_NONE;
int hinting = [ud integerForKey: @"GSFontHinting"];
int subpixel = 0;
if (hinting == 0)
{
/*
* This could be on purpose or a missing value.
* In the later case use the defaults.
*/
if (nil == [ud objectForKey: @"GSFontHinting"])
{
hinting = 33;
}
}
/*
* This part is only here to debug disabling the use of hinting for
* metrics, because doing so causes menus to get cut off on the right.
*/
switch (hinting >> 4)
{
case 0:
metrics = CAIRO_HINT_METRICS_DEFAULT;
break;
case 1:
metrics = CAIRO_HINT_METRICS_OFF;
break;
case 2:
metrics = CAIRO_HINT_METRICS_ON;
break;
}
switch (hinting & 0x0f)
{
case 0:
style = CAIRO_HINT_STYLE_DEFAULT;
break;
case 1:
style = CAIRO_HINT_STYLE_NONE;
break;
case 2:
style = CAIRO_HINT_STYLE_SLIGHT;
break;
case 3:
style = CAIRO_HINT_STYLE_MEDIUM;
break;
case 4:
style = CAIRO_HINT_STYLE_FULL;
break;
}
cairo_font_options_set_hint_metrics(options, metrics);
cairo_font_options_set_hint_style(options, style);
if ((subpixel = [ud integerForKey: @"back-art-subpixel-text"]))
{
cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
if (subpixel == 2)
{
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_BGR);
}
else
{
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_RGB);
}
}
}
@implementation CairoFontInfo
- (BOOL) setupAttributes
@ -51,10 +125,6 @@
cairo_matrix_t font_matrix;
cairo_matrix_t ctm;
cairo_font_options_t *options;
cairo_hint_metrics_t metrics = CAIRO_HINT_METRICS_ON;
cairo_hint_style_t style = CAIRO_HINT_STYLE_DEFAULT;
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
int hinting = 0, subpixel = 0;
if (![super setupAttributes])
{
@ -81,54 +151,8 @@
{
return NO;
}
if ((hinting = [ud integerForKey: @"GSFontHinting"]))
{ /*
* This part is only here to debug disabling the use of hinting for
* metrics, because doing so causes menus to get cut off on the right.
*/
switch (hinting >> 4)
{
case 1:
metrics = CAIRO_HINT_METRICS_OFF;
break;
case 2:
metrics = CAIRO_HINT_METRICS_ON;
break;
}
switch (hinting & 0x0f)
{
case 1:
style = CAIRO_HINT_STYLE_NONE;
break;
case 2:
style = CAIRO_HINT_STYLE_SLIGHT;
break;
case 3:
style = CAIRO_HINT_STYLE_MEDIUM;
break;
case 4:
style = CAIRO_HINT_STYLE_FULL;
break;
}
}
cairo_font_options_set_hint_metrics(options, metrics);
cairo_font_options_set_hint_style(options, style);
if ((subpixel = [ud integerForKey: @"back-art-subpixel-text"]))
{
cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
if (subpixel == 2)
{
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_BGR);
}
else
{
cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_RGB);
}
}
set_font_options(options);
_scaled = cairo_scaled_font_create(face, &font_matrix, &ctm, options);
cairo_font_options_destroy(options);

View file

@ -1911,21 +1911,15 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
- (NSEvent *)_handleTakeFocusAtom: (XEvent)xEvent
forContext: (NSGraphicsContext *)gcontext
{
int key_num;
NSWindow *key_win;
NSWindow *keyWindow = [NSApp keyWindow];
int key_num = [keyWindow windowNumber];
NSEvent *e = nil;
key_win = [NSApp keyWindow];
key_num = [key_win windowNumber];
NSDebugLLog(@"Focus", @"take focus:%lu (current=%lu key=%d)",
cWin->number, generic.currentFocusWindow, key_num);
/* Sometimes window managers lose the setinputfocus on the key window
* e.g. when ordering out a window with focus then ordering in the key window.
* it might search for a window until one accepts its take focus request.
*/
if (key_num == cWin->number)
cWin->ignore_take_focus = NO;
NSDebugLLog(@"Focus",
@"TakeFocus received by: %li (%lu) (focused = %lu, key = %d)",
cWin->number, xEvent.xfocus.window,
generic.currentFocusWindow, key_num);
/* Invalidate the previous request. It's possible the app lost focus
before this request was fufilled and we are being focused again,
or ??? */
@ -1933,6 +1927,20 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
generic.focusRequestNumber = 0;
generic.desiredFocusWindow = 0;
}
/* Sometimes window managers lose the setinputfocus on the key window
* e.g. when ordering out a window with focus then ordering in the key window.
* it might search for a window until one accepts its take focus request.
*/
if (key_num == 0)
{
cWin->ignore_take_focus = NO;
}
else if (cWin->number == [[[NSApp mainMenu] window] windowNumber])
{
cWin->ignore_take_focus = NO;
}
/* We'd like to send this event directly to the front-end to handle,
but the front-end polls events so slowly compared the speed at
which X events could potentially come that we could easily get
@ -1953,23 +1961,31 @@ posixFileDescriptor: (NSPosixFileDescriptor*)fileDescriptor
else if (cWin->number == key_num)
{
NSDebugLLog(@"Focus", @"Reasserting key window");
[GSServerForWindow(key_win) setinputfocus: key_num];
[GSServerForWindow(keyWindow) setinputfocus: key_num];
}
else if (key_num
&& cWin->number == [[[NSApp mainMenu] window] windowNumber])
{
gswindow_device_t *key_window = [XGServer _windowWithTag:key_num];
/* This might occur when the window manager just wants someone
to become key, so it tells the main menu (typically the first
menu in the list), but since we already have a window that
was key before, use that instead */
NSDebugLLog(@"Focus", @"Key window is already %d", key_num);
[GSServerForWindow(key_win) setinputfocus: key_num];
if (key_window->map_state == IsUnmapped) {
/* `key_window` was unmapped by window manager.
this window and `key_window` are on the different workspace. */
[GSServerForWindow(keyWindow) setinputfocus: cWin->number];
}
else {
[GSServerForWindow(keyWindow) setinputfocus: key_num];
}
}
else
{
NSPoint eventLocation;
/*
* Here the app asked for this (if key_win==nil) or there was a
* Here the app asked for this (if keyWindow==nil) or there was a
* click on the title bar or some other reason (window mapped,
* etc). We don't necessarily want to forward the event for the
* last reason but we just have to deal with that since we can

View file

@ -1809,28 +1809,14 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
// blue
B = d[2];
// alpha
#if 0
/*
For unclear reasons the alpha handling does not work, so we simulate it.
*/
if (samples == 4)
{
A = d[4];
A = d[3];
}
else
{
A = 255;
}
#else
if (R || G || B)
{
A = 255;
}
else
{
A = 0;
}
#endif
iconPropertyData[index++] = A << 24 | R << 16 | G << 8 | B;
d += samples;
@ -2018,8 +2004,7 @@ _get_next_prop_new_event(Display *display, XEvent *event, char *arg)
// For window managers supporting EWMH, but not Window Maker,
// where we use a different solution, set the window icon.
if (((generic.wm & XGWM_EWMH) != 0)
&& ((generic.wm & XGWM_WINDOWMAKER) == 0))
if ((generic.wm & XGWM_EWMH) != 0)
{
[self _setNetWMIconFor: window->ident];
}
@ -2707,62 +2692,134 @@ static Pixmap xIconPixmap;
static Pixmap xIconMask;
static BOOL didCreatePixmaps;
-(int) _createAppIconPixmaps
Pixmap
alphaMaskForImage(Display *xdpy, Drawable draw, const unsigned char *data,
int w, int h, int colors, int alpha_treshold)
{
NSImage *image;
NSBitmapImageRep *rep;
int i, j, w, h, samples, screen;
int j, i;
unsigned char ialpha;
Pixmap pix;
int bitmapSize = ((w + 7) >> 3) * h; // (w/8) rounded up times height
char *aData = calloc(1, bitmapSize);
char *cData = aData;
if (colors == 4)
{
int k;
for (j = 0; j < h; j++)
{
k = 0;
for (i = 0; i < w; i++, k++)
{
if (k > 7)
{
cData++;
k = 0;
}
data += 3; // skip R, G, B
ialpha = (unsigned short)((char)*data++);
if (ialpha > alpha_treshold)
{
*cData |= (0x01 << k);
}
}
cData++;
}
}
else
{
for (j = 0; j < bitmapSize; j++)
{
*cData++ = 0xff;
}
}
pix = XCreatePixmapFromBitmapData(xdpy, draw, (char *)aData, w, h,
1L, 0L, 1);
free(aData);
return pix;
}
// Convert RGBA unpacked to ARGB packed.
// Packed ARGB values are layed out as ARGB on big endian systems
// and as BGRA on little endian systems
void
swapColors(unsigned char *image_data, int width, int height,
int samples_per_pixel, int bytes_per_row)
{
NSInteger x, y;
unsigned char *data;
XColor pixelColor;
GC pixgc;
RColor pixelRColor;
RContext *rcontext;
unsigned char *r, *g, *b, *a;
data = image_data;
r = data;
g = data + 1;
b = data + 2;
a = data + 3;
for (y = 0; y < height; y++)
{
unsigned char *d = data;
for (x = 0; x < width; x++)
{
#if GS_WORDS_BIGENDIAN
// RGBA -> ARGB
unsigned char _d = d[3];
*r = _d;
*g = d[0];
*b = d[1];
*a = d[2];
#else
// RGBA -> BGRA
unsigned char _d = d[0];
*r = d[2];
// *g = d[1];
*b = _d;
// *a = d[3];
#endif
r += 4;
g += 4;
b += 4;
a += 4;
d += samples_per_pixel;
}
data += bytes_per_row;
}
}
- (int) _createAppIconPixmaps
{
NSBitmapImageRep *rep;
int width, height, colors, screen;
RContext *rcontext;
RXImage *rxImage;
NSAssert(!didCreatePixmaps, @"called _createAppIconPixmap twice");
didCreatePixmaps = YES;
image = [NSApp applicationIconImage];
rep = getStandardBitmap(image);
rep = getStandardBitmap([NSApp applicationIconImage]);
if (rep == nil)
return 0;
data = [rep bitmapData];
screen = [[[self screenList] objectAtIndex: 0] intValue];
xIconPixmap = XCreatePixmap(dpy,
[self xDisplayRootWindowForScreen: screen],
[rep pixelsWide], [rep pixelsHigh],
DefaultDepth(dpy, screen));
pixgc = XCreateGC(dpy, xIconPixmap, 0, NULL);
h = [rep pixelsHigh];
w = [rep pixelsWide];
samples = [rep samplesPerPixel];
rcontext = [self xrContextForScreen: screen];
width = [rep pixelsWide];
height = [rep pixelsHigh];
colors = [rep samplesPerPixel];
for (i = 0; i < h; i++)
{
unsigned char *d = data;
for (j = 0; j < w; j++)
{
pixelRColor.red = d[0];
pixelRColor.green = d[1];
pixelRColor.blue = d[2];
RGetClosestXColor(rcontext, &pixelRColor, &pixelColor);
XSetForeground(dpy, pixgc, pixelColor. pixel);
XDrawPoint(dpy, xIconPixmap, pixgc, j, i);
d += samples;
}
data += [rep bytesPerRow];
}
XFreeGC(dpy, pixgc);
xIconMask = xgps_cursor_mask(dpy, ROOT, [rep bitmapData],
[rep pixelsWide],
[rep pixelsHigh],
[rep samplesPerPixel]);
rxImage = RCreateXImage(rcontext, rcontext->depth, width, height);
memcpy((char*)rxImage->image->data, [rep bitmapData], width * height * colors);
swapColors((unsigned char *)rxImage->image->data,
width, height, colors, [rep bytesPerRow]);
xIconPixmap = XCreatePixmap(dpy, rcontext->drawable,
width, height, rcontext->depth);
XPutImage(dpy, xIconPixmap, rcontext->copy_gc, rxImage->image,
0, 0, 0, 0, width, height);
RDestroyXImage(rcontext, rxImage);
xIconMask = alphaMaskForImage(dpy, ROOT, [rep bitmapData], width, height, colors, 0);
return 1;
}
@ -3072,10 +3129,11 @@ static BOOL didCreatePixmaps;
{
if ([rep samplesPerPixel] == 4)
{
pixmap = xgps_cursor_mask(dpy, GET_XDRAWABLE(window),
[rep bitmapData],
[rep pixelsWide], [rep pixelsHigh],
[rep samplesPerPixel]);
pixmap = alphaMaskForImage(dpy, GET_XDRAWABLE(window),
[rep bitmapData],
[rep pixelsWide], [rep pixelsHigh],
[rep samplesPerPixel],
ALPHA_THRESHOLD);
}
}
}
@ -4017,55 +4075,7 @@ static BOOL cursor_hidden = NO;
}
}
#define ALPHA_THRESHOLD 158
Pixmap
xgps_cursor_mask(Display *xdpy, Drawable draw, const unsigned char *data,
int w, int h, int colors)
{
int j, i;
unsigned char ialpha;
Pixmap pix;
int bitmapSize = ((w + 7) >> 3) * h; // (w/8) rounded up times height
char *aData = calloc(1, bitmapSize);
char *cData = aData;
if (colors == 4)
{
int k;
for (j = 0; j < h; j++)
{
k = 0;
for (i = 0; i < w; i++, k++)
{
if (k > 7)
{
cData++;
k = 0;
}
data += 3;
ialpha = (unsigned short)((char)*data++);
if (ialpha > ALPHA_THRESHOLD)
{
*cData |= (0x01 << k);
}
}
cData++;
}
}
else
{
for (j = 0; j < bitmapSize; j++)
{
*cData++ = 0xff;
}
}
pix = XCreatePixmapFromBitmapData(xdpy, draw, (char *)aData, w, h,
1L, 0L, 1);
free(aData);
return pix;
}
#if !HAVE_XCURSOR
Pixmap
xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
@ -4143,6 +4153,8 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
return pix;
}
#endif
- (void) hidecursor
{
if (cursor_hidden)
@ -4261,56 +4273,11 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
xcursorImage->yhot = hotp.y;
// Copy the data from the image rep to the Xcursor structure
{
int bytesPerRow;
size_t row;
bytesPerRow = [rep bytesPerRow];
for (row = 0; row < h; row++)
{
memcpy((char*)xcursorImage->pixels + (row * (w * 4)),
data + (row * bytesPerRow),
bytesPerRow);
}
}
// FIXME: Factor this out
// Convert RGBA unpacked to ARGB packed
// NB Packed ARGB values are layed out as ARGB on big endian systems
// and as BDRA on low endian systems
{
NSInteger stride;
NSInteger x, y;
unsigned char *cdata;
stride = 4 * w;
cdata = (unsigned char *)xcursorImage->pixels;
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
{
NSInteger i = (y * stride) + (x * 4);
#if GS_WORDS_BIGENDIAN
unsigned char d = cdata[i + 3];
cdata[i + 3] = cdata[i + 2];
cdata[i + 2] = cdata[i + 1];
cdata[i + 1] = cdata[i];
cdata[i] = d;
#else
unsigned char d = cdata[i];
cdata[i] = cdata[i + 2];
//cdata[i + 1] = cdata[i + 1];
cdata[i + 2] = d;
//cdata[i + 3] = cdata[i + 3];
#endif
}
}
}
memcpy((char*)xcursorImage->pixels, data, w * h * colors);
swapColors((unsigned char *)xcursorImage->pixels, w, h,
colors, [rep bytesPerRow]);
cursor = XcursorImageLoadCursor(dpy, xcursorImage);
XcursorImageDestroy(xcursorImage);
}
@ -4328,7 +4295,7 @@ xgps_cursor_image(Display *xdpy, Drawable draw, const unsigned char *data,
h = maxh;
source = xgps_cursor_image(dpy, ROOT, data, w, h, colors, &fg, &bg);
mask = xgps_cursor_mask(dpy, ROOT, data, w, h, colors);
mask = alphaMaskForImage(dpy, ROOT, data, w, h, colors, ALPHA_TRESHOLD);
bg = [self xColorFromColor: bg forScreen: defScreen];
fg = [self xColorFromColor: fg forScreen: defScreen];