📄 xwin.c
字号:
sw_all_to_desktop(This, sw->wnd, sw->desktop);
}
break;
case MapNotify:
if (!This->xwin.seamless_active)
rdp_send_client_window_status(This, 1);
break;
case UnmapNotify:
if (!This->xwin.seamless_active)
rdp_send_client_window_status(This, 0);
break;
case ConfigureNotify:
if (!This->xwin.seamless_active)
break;
sw = sw_get_window_by_wnd(This, xevent.xconfigure.window);
if (!sw)
break;
gettimeofday(sw->position_timer, NULL);
if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
1000000)
{
sw->position_timer->tv_usec +=
SEAMLESSRDP_POSITION_TIMER - 1000000;
sw->position_timer->tv_sec += 1;
}
else
{
sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
}
sw_handle_restack(This, sw);
break;
}
}
/* Keep going */
return 1;
}
/* Returns 0 after user quit, 1 otherwise */
int
ui_select(RDPCLIENT * This, int rdp_socket)
{
int n;
fd_set rfds, wfds;
struct timeval tv;
BOOL s_timeout = False;
while (True)
{
n = (rdp_socket > This->xwin.x_socket) ? rdp_socket : This->xwin.x_socket;
/* Process any events already waiting */
if (!xwin_process_events(This))
/* User quit */
return 0;
if (This->xwin.seamless_active)
sw_check_timers(This);
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(rdp_socket, &rfds);
FD_SET(This->xwin.x_socket, &rfds);
#ifdef WITH_RDPSND
/* FIXME: there should be an API for registering fds */
if (This->dsp_busy)
{
FD_SET(This->dsp_fd, &wfds);
n = (This->dsp_fd > n) ? This->dsp_fd : n;
}
#endif
/* default timeout */
tv.tv_sec = 60;
tv.tv_usec = 0;
/* add redirection handles */
rdpdr_add_fds(This, &n, &rfds, &wfds, &tv, &s_timeout);
seamless_select_timeout(This, &tv);
n++;
switch (select(n, &rfds, &wfds, NULL, &tv))
{
case -1:
error("select: %s\n", strerror(errno));
case 0:
/* Abort serial read calls */
if (s_timeout)
rdpdr_check_fds(This, &rfds, &wfds, (BOOL) True);
continue;
}
rdpdr_check_fds(This, &rfds, &wfds, (BOOL) False);
if (FD_ISSET(rdp_socket, &rfds))
return 1;
#ifdef WITH_RDPSND
if (This->dsp_busy && FD_ISSET(This->dsp_fd, &wfds))
wave_out_play();
#endif
}
}
void
ui_move_pointer(RDPCLIENT * This, int x, int y)
{
XWarpPointer(This->display, This->wnd, This->wnd, 0, 0, 0, 0, x, y);
}
HBITMAP
ui_create_bitmap(RDPCLIENT * This, int width, int height, uint8 * data)
{
XImage *image;
Pixmap bitmap;
uint8 *tdata;
int bitmap_pad;
if (This->server_depth == 8)
{
bitmap_pad = 8;
}
else
{
bitmap_pad = This->xwin.bpp;
if (This->xwin.bpp == 24)
bitmap_pad = 32;
}
tdata = (This->owncolmap ? data : translate_image(This, width, height, data));
bitmap = XCreatePixmap(This->display, This->wnd, width, height, This->xwin.depth);
image = XCreateImage(This->display, This->xwin.visual, This->xwin.depth, ZPixmap, 0,
(char *) tdata, width, height, bitmap_pad, 0);
XPutImage(This->display, bitmap, This->xwin.create_bitmap_gc, image, 0, 0, 0, 0, width, height);
XFree(image);
if (tdata != data)
xfree(tdata);
return (HBITMAP) bitmap;
}
void
ui_paint_bitmap(RDPCLIENT * This, int x, int y, int cx, int cy, int width, int height, uint8 * data)
{
XImage *image;
uint8 *tdata;
int bitmap_pad;
if (This->server_depth == 8)
{
bitmap_pad = 8;
}
else
{
bitmap_pad = This->xwin.bpp;
if (This->xwin.bpp == 24)
bitmap_pad = 32;
}
tdata = (This->owncolmap ? data : translate_image(This, width, height, data));
image = XCreateImage(This->display, This->xwin.visual, This->xwin.depth, ZPixmap, 0,
(char *) tdata, width, height, bitmap_pad, 0);
if (This->ownbackstore)
{
XPutImage(This->display, This->xwin.backstore, This->xwin.gc, image, 0, 0, x, y, cx, cy);
XCopyArea(This->display, This->xwin.backstore, This->wnd, This->xwin.gc, x, y, cx, cy, x, y);
ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
(This->display, This->xwin.backstore, sw->wnd, This->xwin.gc, x, y, cx, cy,
x - sw->xoffset, y - sw->yoffset));
}
else
{
XPutImage(This->display, This->wnd, This->xwin.gc, image, 0, 0, x, y, cx, cy);
ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
(This->display, This->wnd, sw->wnd, This->xwin.gc, x, y, cx, cy,
x - sw->xoffset, y - sw->yoffset));
}
XFree(image);
if (tdata != data)
xfree(tdata);
}
void
ui_destroy_bitmap(RDPCLIENT * This, HBITMAP bmp)
{
XFreePixmap(This->display, (Pixmap) bmp);
}
HGLYPH
ui_create_glyph(RDPCLIENT * This, int width, int height, const uint8 * data)
{
XImage *image;
Pixmap bitmap;
int scanline;
scanline = (width + 7) / 8;
bitmap = XCreatePixmap(This->display, This->wnd, width, height, 1);
if (This->xwin.create_glyph_gc == 0)
This->xwin.create_glyph_gc = XCreateGC(This->display, bitmap, 0, NULL);
image = XCreateImage(This->display, This->xwin.visual, 1, ZPixmap, 0, (char *) data,
width, height, 8, scanline);
image->byte_order = MSBFirst;
image->bitmap_bit_order = MSBFirst;
XInitImage(image);
XPutImage(This->display, bitmap, This->xwin.create_glyph_gc, image, 0, 0, 0, 0, width, height);
XFree(image);
return (HGLYPH) bitmap;
}
void
ui_destroy_glyph(RDPCLIENT * This, HGLYPH glyph)
{
XFreePixmap(This->display, (Pixmap) glyph);
}
HCURSOR
ui_create_cursor(RDPCLIENT * This, unsigned int x, unsigned int y, int width, int height,
uint8 * andmask, uint8 * xormask)
{
HGLYPH maskglyph, cursorglyph;
XColor bg, fg;
Cursor xcursor;
uint8 *cursor, *pcursor;
uint8 *mask, *pmask;
uint8 nextbit;
int scanline, offset;
int i, j;
scanline = (width + 7) / 8;
offset = scanline * height;
cursor = (uint8 *) xmalloc(offset);
memset(cursor, 0, offset);
mask = (uint8 *) xmalloc(offset);
memset(mask, 0, offset);
/* approximate AND and XOR masks with a monochrome X pointer */
for (i = 0; i < height; i++)
{
offset -= scanline;
pcursor = &cursor[offset];
pmask = &mask[offset];
for (j = 0; j < scanline; j++)
{
for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
{
if (xormask[0] || xormask[1] || xormask[2])
{
*pcursor |= (~(*andmask) & nextbit);
*pmask |= nextbit;
}
else
{
*pcursor |= ((*andmask) & nextbit);
*pmask |= (~(*andmask) & nextbit);
}
xormask += 3;
}
andmask++;
pcursor++;
pmask++;
}
}
fg.red = fg.blue = fg.green = 0xffff;
bg.red = bg.blue = bg.green = 0x0000;
fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
cursorglyph = ui_create_glyph(This, width, height, cursor);
maskglyph = ui_create_glyph(This, width, height, mask);
xcursor =
XCreatePixmapCursor(This->display, (Pixmap) cursorglyph,
(Pixmap) maskglyph, &fg, &bg, x, y);
ui_destroy_glyph(This, maskglyph);
ui_destroy_glyph(This, cursorglyph);
xfree(mask);
xfree(cursor);
return (HCURSOR) xcursor;
}
void
ui_set_cursor(RDPCLIENT * This, HCURSOR cursor)
{
This->xwin.current_cursor = (Cursor) cursor;
XDefineCursor(This->display, This->wnd, This->xwin.current_cursor);
ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (This->display, sw->wnd, This->xwin.current_cursor));
}
void
ui_destroy_cursor(RDPCLIENT * This, HCURSOR cursor)
{
XFreeCursor(This->display, (Cursor) cursor);
}
void
ui_set_null_cursor(RDPCLIENT * This)
{
ui_set_cursor(This, This->xwin.null_cursor);
}
#define MAKE_XCOLOR(xc,c) \
(xc)->red = ((c)->red << 8) | (c)->red; \
(xc)->green = ((c)->green << 8) | (c)->green; \
(xc)->blue = ((c)->blue << 8) | (c)->blue; \
(xc)->flags = DoRed | DoGreen | DoBlue;
HCOLOURMAP
ui_create_colourmap(RDPCLIENT * This, COLOURMAP * colours)
{
COLOURENTRY *entry;
int i, ncolours = colours->ncolours;
if (!This->owncolmap)
{
uint32 *map = (uint32 *) xmalloc(sizeof(*This->xwin.colmap) * ncolours);
XColor xentry;
XColor xc_cache[256];
uint32 colour;
int colLookup = 256;
for (i = 0; i < ncolours; i++)
{
entry = &colours->colours[i];
MAKE_XCOLOR(&xentry, entry);
if (XAllocColor(This->display, This->xwin.xcolmap, &xentry) == 0)
{
/* Allocation failed, find closest match. */
int j = 256;
int nMinDist = 3 * 256 * 256;
long nDist = nMinDist;
/* only get the colors once */
while (colLookup--)
{
xc_cache[colLookup].pixel = colLookup;
xc_cache[colLookup].red = xc_cache[colLookup].green =
xc_cache[colLookup].blue = 0;
xc_cache[colLookup].flags = 0;
XQueryColor(This->display,
DefaultColormap(This->display,
DefaultScreen(This->display)),
&xc_cache[colLookup]);
}
colLookup = 0;
/* approximate the pixel */
while (j--)
{
if (xc_cache[j].flags)
{
nDist = ((long) (xc_cache[j].red >> 8) -
(long) (xentry.red >> 8)) *
((long) (xc_cache[j].red >> 8) -
(long) (xentry.red >> 8)) +
((long) (xc_cache[j].green >> 8) -
(long) (xentry.green >> 8)) *
((long) (xc_cache[j].green >> 8) -
(long) (xentry.green >> 8)) +
((long) (xc_cache[j].blue >> 8) -
(long) (xentry.blue >> 8)) *
((long) (xc_cache[j].blue >> 8) -
(long) (xentry.blue >> 8));
}
if (nDist < nMinDist)
{
nMinDist = nDist;
xentry.pixel = j;
}
}
}
colour = xentry.pixel;
/* update our cache */
if (xentry.pixel < 256)
{
xc_cache[xentry.pixel].red = xentry.red;
xc_cache[xentry.pixel].green = xentry.green;
xc_cache[xentry.pixel].blue = xentry.blue;
}
map[i] = colour;
}
return map;
}
else
{
XColor *xcolours, *xentry;
Colormap map;
xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
for (i = 0; i < ncolours; i++)
{
entry = &colours->colours[i];
xentry = &xcolours[i];
xentry->pixel = i;
MAKE_XCOLOR(xentry, entry);
}
map = XCreateColormap(This->display, This->wnd, This->xwin.visual, AllocAll);
XStoreColors(This->display, map, xcolours, ncolours);
xfree(xcolours);
return (HCOLOURMAP) map;
}
}
void
ui_destroy_colourmap(RDPCLIENT * This, HCOLOURMAP map)
{
if (!This->owncolmap)
xfree(map);
else
XFreeColormap(This->display, (Colormap) map);
}
void
ui_set_colourmap(RDPCLIENT * This, HCOLOURMAP map)
{
if (!This->owncolmap)
{
if (This->xwin.colmap)
xfree(This->xwin.colmap);
This->xwin.colmap = (uint32 *) map;
}
else
{
XSetWindowColormap(This->display, This->wnd, (Colormap) map);
ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (This->display, sw->wnd, (Colormap) map));
}
}
void
ui_set_clip(RDPCLIENT * This, int x, int y, int cx, int cy)
{
This->xwin.clip_rectangle.x = x;
This->xwin.clip_rectangle.y = y;
This->xwin.clip_rectangle.width = cx;
This->xwin.clip_rectangle.height = cy;
XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &This->xwin.clip_rectangle, 1, YXBanded);
}
void
ui_reset_clip(RDPCLIENT * This)
{
This->xwin.clip_rectangle.x = 0;
This->xwin.clip_rectangle.y = 0;
This->xwin.clip_rectangle.width = This->width;
This->xwin.clip_rectangle.height = This->height;
XSetClipRectangles(This->display, This->xwin.gc, 0, 0, &This->xwin.clip_rectangle, 1, YXBanded);
}
void
ui_bell(RDPCLIENT * This)
{
XBell(This->display, 0);
}
void
ui_destblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy)
{
SET_FUNCTION(opcode);
FILL_RECTANGLE(x, y, cx, cy);
RESET_FUNCTION(opcode);
}
static const uint8 hatch_patterns[] = {
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
};
void
ui_patblt(RDPCLIENT * This, uint8 opcode,
/* dest */ int x, int y, int cx, int cy,
/* brush */ BRUSH * brush, int bgcolour, int fgcolour)
{
Pixmap fill;
uint8 i, ipattern[8];
SET_FUNCTION(opcode);
switch (brush->style)
{
case 0: /* Solid */
SET_FOREGROUND(fgcolour);
FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
break;
case 2: /* Hatch */
fill = (Pixmap) ui_create_glyph(This, 8, 8,
h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -