major work and login screen
parent
6560bcc78b
commit
e856dc67ab
@ -0,0 +1,479 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
bitmap, drawable
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_bitmap* xrdp_bitmap_create(int width, int height, int bpp,
|
||||
int type)
|
||||
{
|
||||
struct xrdp_bitmap* self;
|
||||
int Bpp;
|
||||
|
||||
self = (struct xrdp_bitmap*)g_malloc(sizeof(struct xrdp_bitmap), 1);
|
||||
self->type = type;
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
self->bpp = bpp;
|
||||
Bpp = 4;
|
||||
switch (bpp)
|
||||
{
|
||||
case 8: Bpp = 1; break;
|
||||
case 15: Bpp = 2; break;
|
||||
case 16: Bpp = 2; break;
|
||||
}
|
||||
self->data = (char*)g_malloc(width * height * Bpp, 1);
|
||||
self->child_list = xrdp_list_create();
|
||||
self->line_size = ((width + 3) & ~3) * Bpp;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_bitmap_delete(struct xrdp_bitmap* self)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (self == 0)
|
||||
return;
|
||||
if (self->wm != 0)
|
||||
{
|
||||
if (self->wm->focused_window == self)
|
||||
self->wm->focused_window = 0;
|
||||
if (self->wm->dragging_window == self)
|
||||
self->wm->dragging_window = 0;
|
||||
if (self->wm->button_down == self)
|
||||
self->wm->button_down = 0;
|
||||
}
|
||||
for (i = 0; i < self->child_list->count; i++)
|
||||
xrdp_bitmap_delete((struct xrdp_bitmap*)self->child_list->items[i]);
|
||||
xrdp_list_delete(self->child_list);
|
||||
g_free(self->data);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_set_focus(struct xrdp_bitmap* self, int focused)
|
||||
{
|
||||
struct xrdp_painter* painter;
|
||||
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (self->type != 1)
|
||||
return 0;
|
||||
self->focused = focused;
|
||||
painter = xrdp_painter_create(self->wm);
|
||||
xrdp_painter_begin_update(painter);
|
||||
if (focused)
|
||||
{
|
||||
/* active title bar */
|
||||
painter->fg_color = self->wm->blue;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inactive title bar */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
}
|
||||
DEBUG(("1\n\r"));
|
||||
xrdp_painter_end_update(painter);
|
||||
DEBUG(("2\n\r"));
|
||||
xrdp_painter_delete(painter);
|
||||
DEBUG(("3\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_get_index(struct xrdp_bitmap* self, int* palette, int color)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
if (color == palette[i])
|
||||
return i;
|
||||
}
|
||||
for (i = 1; i < 256; i++)
|
||||
{
|
||||
if (palette[i] == 0)
|
||||
{
|
||||
palette[i] = color;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
g_printf("color %8.8x not found\n", color);
|
||||
return 255;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_resize(struct xrdp_bitmap* self, int width, int height)
|
||||
{
|
||||
int Bpp;
|
||||
|
||||
g_free(self->data);
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
Bpp = 4;
|
||||
switch (self->bpp)
|
||||
{
|
||||
case 8: Bpp = 1; break;
|
||||
case 15: Bpp = 2; break;
|
||||
case 16: Bpp = 2; break;
|
||||
}
|
||||
self->data = (char*)g_malloc(width * height * Bpp, 1);
|
||||
self->line_size = ((width + 3) & ~3) * Bpp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* load a bmp file */
|
||||
/* return 0 ok */
|
||||
/* return 1 error */
|
||||
int xrdp_bitmap_load(struct xrdp_bitmap* self, char* filename, int* palette)
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
int color;
|
||||
int size;
|
||||
int palette1[256];
|
||||
char type1[3];
|
||||
char* data;
|
||||
struct xrdp_bmp_header header;
|
||||
|
||||
fd = g_file_open(filename);
|
||||
if (fd != -1)
|
||||
{
|
||||
/* read file type */
|
||||
if (g_file_read(fd, type1, 2) != 2)
|
||||
{
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (type1[0] != 'B' || type1[1] != 'M')
|
||||
{
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
/* read file size */
|
||||
size = 0;
|
||||
g_file_read(fd, (char*)&size, 4);
|
||||
/* read bmp header */
|
||||
g_file_seek(fd, 14);
|
||||
g_file_read(fd, (char*)&header, sizeof(header));
|
||||
if (header.bit_count != 8 && header.bit_count != 24)
|
||||
{
|
||||
g_file_close(fd);
|
||||
return 1;
|
||||
}
|
||||
if (header.bit_count == 24) /* 24 bit bitmap */
|
||||
{
|
||||
g_file_seek(fd, 14 + header.size);
|
||||
}
|
||||
if (header.bit_count == 8) /* 8 bit bitmap */
|
||||
{
|
||||
/* read palette */
|
||||
g_file_seek(fd, 14 + header.size);
|
||||
g_file_read(fd, (char*)palette1, 256 * sizeof(int));
|
||||
/* read data */
|
||||
xrdp_bitmap_resize(self, header.image_width, header.image_height);
|
||||
data = (char*)g_malloc(header.image_width * header.image_height, 1);
|
||||
for (i = header.image_height - 1; i >= 0; i--)
|
||||
g_file_read(fd, data + i * header.image_width, header.image_width);
|
||||
for (i = 0; i < self->height; i++)
|
||||
{
|
||||
for (j = 0; j < self->width; j++)
|
||||
{
|
||||
k = (unsigned char)data[i * header.image_width + j];
|
||||
color = palette1[k];
|
||||
if (self->bpp == 8)
|
||||
color = xrdp_bitmap_get_index(self, palette, color);
|
||||
else if (self->bpp == 15)
|
||||
color = xrdp_wm_color15((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
else if (self->bpp == 16)
|
||||
color = xrdp_wm_color16((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
else if (self->bpp == 24)
|
||||
color = xrdp_wm_color24((color & 0xff0000) >> 16,
|
||||
(color & 0x00ff00) >> 8,
|
||||
(color & 0x0000ff) >> 0);
|
||||
xrdp_bitmap_set_pixel(self, j, i, color);
|
||||
}
|
||||
}
|
||||
g_free(data);
|
||||
}
|
||||
g_file_close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_get_pixel(struct xrdp_bitmap* self, int x, int y)
|
||||
{
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (self->data == 0)
|
||||
return 0;
|
||||
if (x >= 0 && x < self->width && y >= 0 && y < self->height)
|
||||
{
|
||||
if (self->bpp == 8)
|
||||
return self->data[y * self->width + x];
|
||||
else if (self->bpp == 15 || self->bpp == 16)
|
||||
return ((short*)self->data)[y * self->width + x];
|
||||
else if (self->bpp == 24)
|
||||
return ((int*)self->data)[y * self->width + x];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_set_pixel(struct xrdp_bitmap* self, int x, int y, int pixel)
|
||||
{
|
||||
if (x >= 0 && x < self->width && y >= 0 && y < self->height)
|
||||
{
|
||||
if (self->bpp == 8)
|
||||
self->data[y * self->width + x] = pixel;
|
||||
else if (self->bpp == 15 || self->bpp == 16)
|
||||
((short*)(self->data))[y * self->width + x] = pixel;
|
||||
else if (self->bpp == 24)
|
||||
((int*)(self->data))[y * self->width + x] = pixel;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_copy_box(struct xrdp_bitmap* self, struct xrdp_bitmap* dest,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (dest == 0)
|
||||
return 0;
|
||||
if (self->bpp != dest->bpp)
|
||||
return 0;
|
||||
for (i = 0; i < cy; i++)
|
||||
{
|
||||
for (j = 0; j < cx; j++)
|
||||
{
|
||||
xrdp_bitmap_set_pixel(dest, j, i,
|
||||
xrdp_bitmap_get_pixel(self, j + x, i + y));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_bitmap_compare(struct xrdp_bitmap* self, struct xrdp_bitmap* b)
|
||||
{
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (b == 0)
|
||||
return 0;
|
||||
if (self->bpp != b->bpp)
|
||||
return 0;
|
||||
if (self->width != b->width)
|
||||
return 0;
|
||||
if (self->height != b->height)
|
||||
return 0;
|
||||
if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* nil for rect means the whole thing */
|
||||
int xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect)
|
||||
{
|
||||
int i;
|
||||
struct xrdp_bitmap* b;
|
||||
struct xrdp_rect r1;
|
||||
struct xrdp_rect r2;
|
||||
struct xrdp_painter* painter;
|
||||
|
||||
if (self == 0) /* if no bitmap */
|
||||
return 0;
|
||||
if (self->type == 0) /* if bitmap, leave */
|
||||
return 0;
|
||||
painter = xrdp_painter_create(self->wm);
|
||||
painter->rop = 0xcc; /* copy */
|
||||
if (rect == 0)
|
||||
painter->use_clip = 0;
|
||||
else
|
||||
{
|
||||
if (xrdp_wm_rect_is_empty(rect))
|
||||
{
|
||||
xrdp_painter_delete(painter);
|
||||
return 0;
|
||||
}
|
||||
painter->clip = *rect;
|
||||
painter->use_clip = 1;
|
||||
}
|
||||
xrdp_painter_begin_update(painter);
|
||||
if (self->type == 1) /* normal window */
|
||||
{
|
||||
/* draw grey background */
|
||||
painter->fg_color = self->bg_color;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
|
||||
/* top white line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
|
||||
/* left white line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
|
||||
/* bottom dark grey line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
|
||||
self->width - 2, 1);
|
||||
/* right dark grey line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, self->width - 2, 1, 1,
|
||||
self->height - 2);
|
||||
/* bottom black line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 0, self->height - 1,
|
||||
self->width, 1);
|
||||
/* right black line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, self->width - 1, 0,
|
||||
1, self->height);
|
||||
if (self->focused)
|
||||
{
|
||||
/* active title bar */
|
||||
painter->fg_color = self->wm->blue;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inactive title bar */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
}
|
||||
}
|
||||
else if (self->type == 2) /* screen */
|
||||
{
|
||||
painter->fg_color = self->bg_color;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
|
||||
}
|
||||
else if (self->type == 3) /* button */
|
||||
{
|
||||
if (self->state == 0) /* button up */
|
||||
{
|
||||
/* gray box */
|
||||
painter->fg_color = self->wm->grey;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
|
||||
/* white top line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
|
||||
/* white left line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
|
||||
/* dark grey bottom line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 1, self->height - 2,
|
||||
self->width - 1, 1);
|
||||
/* dark grey right line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, self->width - 2, 1,
|
||||
1, self->height - 1);
|
||||
/* black bottom line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 0, self->height - 1, self->width, 1);
|
||||
/* black right line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
|
||||
}
|
||||
else if (self->state == 1) /* button down */
|
||||
{
|
||||
/* black top line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
|
||||
/* black left line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
|
||||
/* dark grey top line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
|
||||
/* dark grey left line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
|
||||
}
|
||||
}
|
||||
else if (self->type == 4) /* image */
|
||||
{
|
||||
xrdp_painter_draw_bitmap(painter, self, self, 0, 0, self->width,
|
||||
self->height);
|
||||
}
|
||||
else if (self->type == 5) /* edit */
|
||||
{
|
||||
/* draw gray box */
|
||||
painter->fg_color = self->wm->grey;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, self->height);
|
||||
/* main white background */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 3,
|
||||
self->height - 3);
|
||||
/* dark grey top line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, self->width, 1);
|
||||
/* dark grey left line */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 0, 0, 1, self->height);
|
||||
/* white bottom line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, 0, self->height- 1, self->width, 1);
|
||||
/* white right line */
|
||||
painter->fg_color = self->wm->white;
|
||||
xrdp_painter_fill_rect(painter, self, self->width - 1, 0, 1, self->height);
|
||||
/* black left line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, 1, self->height - 2);
|
||||
/* black top line */
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_fill_rect(painter, self, 1, 1, self->width - 2, 1);
|
||||
}
|
||||
/* draw any child windows in the area */
|
||||
for (i = 0; i < self->child_list->count; i++)
|
||||
{
|
||||
b = (struct xrdp_bitmap*)xrdp_list_get_item(self->child_list, i);
|
||||
if (rect == 0)
|
||||
xrdp_bitmap_invalidate(b, 0);
|
||||
else
|
||||
{
|
||||
xrdp_wm_rect(&r1, b->left, b->top, b->width, b->height);
|
||||
if (xrdp_wm_rect_intersect(rect, &r1, &r2))
|
||||
{
|
||||
xrdp_wm_rect_offset(&r2, -(b->left), -(b->top));
|
||||
xrdp_bitmap_invalidate(b, &r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
xrdp_painter_end_update(painter);
|
||||
xrdp_painter_delete(painter);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
cache
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_cache* xrdp_cache_create(struct xrdp_wm* owner,
|
||||
struct xrdp_orders* orders)
|
||||
{
|
||||
struct xrdp_cache* self;
|
||||
|
||||
self = (struct xrdp_cache*)g_malloc(sizeof(struct xrdp_cache), 1);
|
||||
self->wm = owner;
|
||||
self->orders = orders;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_cache_delete(struct xrdp_cache* self)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (self == 0)
|
||||
return;
|
||||
/* free all the cached bitmaps */
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 600; j++)
|
||||
xrdp_bitmap_delete(self->bitmap_items[i][j].bitmap);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns cache id */
|
||||
int xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int min_use;
|
||||
int min_use_index1;
|
||||
int min_use_index2;
|
||||
struct xrdp_bitmap* b;
|
||||
|
||||
/* look for match */
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (j = 0; j < 600; j++)
|
||||
{
|
||||
if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap))
|
||||
{
|
||||
self->bitmap_items[i][j].use_count++;
|
||||
DEBUG(("found bitmap at %d %d\n", i, j));
|
||||
return (i << 16) | j;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* look for least used */
|
||||
min_use_index1 = 0;
|
||||
min_use_index2 = 0;
|
||||
min_use = 999999;
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
for (j = 0; j < 600; j++)
|
||||
{
|
||||
if (self->bitmap_items[i][j].use_count < min_use)
|
||||
{
|
||||
min_use = self->bitmap_items[i][j].use_count;
|
||||
min_use_index1 = i;
|
||||
min_use_index2 = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG(("adding bitmap at %d %d\n", min_use_index1, min_use_index2));
|
||||
/* set, send bitmap and return */
|
||||
xrdp_bitmap_delete(self->bitmap_items[min_use_index1]
|
||||
[min_use_index2].bitmap);
|
||||
b = xrdp_bitmap_create(bitmap->width, bitmap->height, bitmap->bpp, 0);
|
||||
xrdp_bitmap_copy_box(bitmap, b, 0, 0, bitmap->width, bitmap->height);
|
||||
self->bitmap_items[min_use_index1][min_use_index2].bitmap = b;
|
||||
self->bitmap_items[min_use_index1][min_use_index2].use_count++;
|
||||
xrdp_orders_send_raw_bitmap(self->orders, b, min_use_index1,
|
||||
min_use_index2);
|
||||
return (min_use_index1 << 16) | min_use_index2;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_cache_add_palette(struct xrdp_cache* self, int* palette)
|
||||
{
|
||||
int i;
|
||||
int min_use;
|
||||
int min_use_index;
|
||||
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (palette == 0)
|
||||
return 0;
|
||||
if (self->wm->screen->bpp > 8)
|
||||
return 0;
|
||||
/* look for match */
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (g_memcmp(palette, self->palette_items[i].palette,
|
||||
256 * sizeof(int)) == 0)
|
||||
{
|
||||
self->palette_items[i].use_count++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
/* look for least used */
|
||||
min_use_index = 0;
|
||||
min_use = 999999;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (self->palette_items[i].use_count < min_use)
|
||||
{
|
||||
min_use = self->palette_items[i].use_count;
|
||||
min_use_index = i;
|
||||
}
|
||||
}
|
||||
/* set, send palette and return */
|
||||
g_memcpy(self->palette_items[min_use_index].palette, palette,
|
||||
256 * sizeof(int));
|
||||
self->palette_items[min_use_index].use_count++;
|
||||
xrdp_orders_send_palette(self->orders, palette, min_use_index);
|
||||
return min_use_index;
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
simple list
|
||||
|
||||
this list is used to track mem leaks so g_malloc1 and
|
||||
g_free1 should be used for internal allocs but not
|
||||
for auto_free items
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_list* xrdp_list_create(void)
|
||||
{
|
||||
struct xrdp_list* self;
|
||||
|
||||
self = (struct xrdp_list*)g_malloc1(sizeof(struct xrdp_list), 1);
|
||||
self->grow_by = 10;
|
||||
self->alloc_size = 10;
|
||||
self->items = (int*)g_malloc1(sizeof(int) * 10, 1);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_list_delete(struct xrdp_list* self)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (self == 0)
|
||||
return;
|
||||
if (self->auto_free)
|
||||
for (i = 0; i < self->count; i++)
|
||||
g_free((void*)self->items[i]);
|
||||
g_free1(self->items);
|
||||
g_free1(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_list_add_item(struct xrdp_list* self, int item)
|
||||
{
|
||||
int* p;
|
||||
int i;
|
||||
|
||||
if (self->count >= self->alloc_size)
|
||||
{
|
||||
i = self->alloc_size;
|
||||
self->alloc_size += self->grow_by;
|
||||
p = (int*)g_malloc1(sizeof(int) * self->alloc_size, 1);
|
||||
g_memcpy(p, self->items, sizeof(int) * i);
|
||||
g_free1(self->items);
|
||||
self->items = p;
|
||||
}
|
||||
self->items[self->count] = item;
|
||||
self->count++;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_list_get_item(struct xrdp_list* self, int index)
|
||||
{
|
||||
if (index < 0 || index >= self->count)
|
||||
return 0;
|
||||
return self->items[index];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_list_clear(struct xrdp_list* self)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (self->auto_free)
|
||||
for (i = 0; i < self->count; i++)
|
||||
g_free((void*)self->items[i]);
|
||||
g_free1(self->items);
|
||||
self->count = 0;
|
||||
self->grow_by = 10;
|
||||
self->alloc_size = 10;
|
||||
self->items = (int*)g_malloc1(sizeof(int) * 10, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_list_index_of(struct xrdp_list* self, int item)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < self->count; i++)
|
||||
if (self->items[i] == item)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_list_remove_item(struct xrdp_list* self, int index)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (index >= 0 && index < self->count)
|
||||
{
|
||||
if (self->auto_free)
|
||||
g_free((void*)self->items[index]);
|
||||
for (i = index; i < (self->count - 1); i++)
|
||||
self->items[i] = self->items[i + 1];
|
||||
self->count--;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_list_insert_item(struct xrdp_list* self, int index, int item)
|
||||
{
|
||||
int* p;
|
||||
int i;
|
||||
|
||||
if (index == self->count)
|
||||
{
|
||||
xrdp_list_add_item(self, item);
|
||||
return;
|
||||
}
|
||||
if (index >= 0 && index < self->count)
|
||||
{
|
||||
self->count++;
|
||||
if (self->count > self->alloc_size)
|
||||
{
|
||||
i = self->alloc_size;
|
||||
self->alloc_size += self->grow_by;
|
||||
p = (int*)g_malloc1(sizeof(int) * self->alloc_size, 1);
|
||||
g_memcpy(p, self->items, sizeof(int) * i);
|
||||
g_free1(self->items);
|
||||
self->items = p;
|
||||
}
|
||||
for (i = (self->count - 2); i >= index; i--)
|
||||
self->items[i + 1] = self->items[i];
|
||||
self->items[index] = item;
|
||||
}
|
||||
}
|
@ -0,0 +1,976 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
orders
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_orders* xrdp_orders_create(struct xrdp_process* owner)
|
||||
{
|
||||
struct xrdp_orders* self;
|
||||
|
||||
self = (struct xrdp_orders*)g_malloc(sizeof(struct xrdp_orders), 1);
|
||||
self->pro_layer = owner;
|
||||
self->rdp_layer = owner->rdp_layer;
|
||||
self->out_s = &owner->out_s;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_orders_delete(struct xrdp_orders* self)
|
||||
{
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int xrdp_orders_init(struct xrdp_orders* self)
|
||||
{
|
||||
self->order_level++;
|
||||
if (self->order_level == 1)
|
||||
{
|
||||
self->order_count = 0;
|
||||
if (xrdp_rdp_init_data(self->rdp_layer, 8192) != 0) /* is this big enough */
|
||||
return 1;
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
self->order_count_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int xrdp_orders_send(struct xrdp_orders* self)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = 0;
|
||||
if (self->order_level > 0)
|
||||
{
|
||||
self->order_level--;
|
||||
if (self->order_level == 0)
|
||||
{
|
||||
s_mark_end(self->out_s);
|
||||
*((short*)self->order_count_ptr) = self->order_count;
|
||||
if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int xrdp_orders_force_send(struct xrdp_orders* self)
|
||||
{
|
||||
if (self->order_count > 0)
|
||||
{
|
||||
s_mark_end(self->out_s);
|
||||
*((short*)self->order_count_ptr) = self->order_count;
|
||||
if (xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE) != 0)
|
||||
return 1;
|
||||
}
|
||||
self->order_count = 0;
|
||||
self->order_level = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_orders_check(struct xrdp_orders* self, int max_size)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (self->order_level < 1)
|
||||
{
|
||||
if (max_size > 8000)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
size = self->out_s->p - self->order_count_ptr;
|
||||
if (size < 0 || size > 8192)
|
||||
return 1;
|
||||
if (size + max_size + 100 > 8000)
|
||||
{
|
||||
xrdp_orders_force_send(self);
|
||||
xrdp_orders_init(self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns boolean */
|
||||
int xrdp_orders_last_bounds(struct xrdp_orders* self,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
if (rect == 0)
|
||||
return 0;
|
||||
if (rect->left == self->clip_left && rect->top == self->clip_top &&
|
||||
rect->right == self->clip_right && rect->bottom == self->clip_bottom)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns boolean */
|
||||
int xrdp_orders_send_delta(struct xrdp_orders* self, int* vals, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i += 2)
|
||||
if (g_abs(vals[i] - vals[i + 1]) >= 128)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
int xrdp_orders_out_bounds(struct xrdp_orders* self, struct xrdp_rect* rect)
|
||||
{
|
||||
char* bounds_flags_ptr;
|
||||
int bounds_flags;
|
||||
|
||||
bounds_flags = 0;
|
||||
bounds_flags_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 1);
|
||||
/* left */
|
||||
if (rect->left == self->clip_left) ;
|
||||
else if (g_abs(rect->left - self->clip_left) < 128)
|
||||
bounds_flags |= 0x10;
|
||||
else
|
||||
bounds_flags |= 0x01;
|
||||
/* top */
|
||||
if (rect->top == self->clip_top) ;
|
||||
else if (g_abs(rect->top - self->clip_top) < 128)
|
||||
bounds_flags |= 0x20;
|
||||
else
|
||||
bounds_flags |= 0x02;
|
||||
/* right */
|
||||
if (rect->right == self->clip_right) ;
|
||||
else if (g_abs(rect->right - self->clip_right) < 128)
|
||||
bounds_flags |= 0x40;
|
||||
else
|
||||
bounds_flags |= 0x04;
|
||||
/* bottom */
|
||||
if (rect->bottom == self->clip_bottom) ;
|
||||
else if (g_abs(rect->bottom - self->clip_bottom) < 128)
|
||||
bounds_flags |= 0x80;
|
||||
else
|
||||
bounds_flags |= 0x08;
|
||||
/* left */
|
||||
if (bounds_flags & 0x01)
|
||||
out_uint16_le(self->out_s, rect->left)
|
||||
else if (bounds_flags & 0x10)
|
||||
out_uint8(self->out_s, rect->left - self->clip_left)
|
||||
self->clip_left = rect->left;
|
||||
/* top */
|
||||
if (bounds_flags & 0x02)
|
||||
out_uint16_le(self->out_s, rect->top)
|
||||
else if (bounds_flags & 0x20)
|
||||
out_uint8(self->out_s, rect->top - self->clip_top)
|
||||
self->clip_top = rect->top;
|
||||
/* right */
|
||||
if (bounds_flags & 0x04)
|
||||
out_uint16_le(self->out_s, rect->right)
|
||||
else if (bounds_flags & 0x40)
|
||||
out_uint8(self->out_s, rect->right - self->clip_right)
|
||||
self->clip_right = rect->right;
|
||||
/* bottom */
|
||||
if (bounds_flags & 0x08)
|
||||
out_uint16_le(self->out_s, rect->bottom)
|
||||
else if (bounds_flags & 0x80)
|
||||
out_uint8(self->out_s, rect->bottom - self->clip_bottom)
|
||||
self->clip_bottom = rect->bottom;
|
||||
/* set flags */
|
||||
*bounds_flags_ptr = bounds_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a solid rect to client */
|
||||
/* max size 23 */
|
||||
int xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy,
|
||||
int color, struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[8];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
|
||||
xrdp_orders_check(self, 23);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_RECT)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_RECT;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = x; vals[1] = self->rect_x;
|
||||
vals[2] = y; vals[3] = self->rect_y;
|
||||
vals[4] = cx; vals[5] = self->rect_cx;
|
||||
vals[6] = cy; vals[7] = self->rect_cy;
|
||||
if (xrdp_orders_send_delta(self, vals, 8))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags)
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
||||
out_uint8s(self->out_s, 1)
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (x != self->rect_x)
|
||||
{
|
||||
present |= 0x01;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, x - self->rect_x)
|
||||
else
|
||||
out_uint16_le(self->out_s, x)
|
||||
self->rect_x = x;
|
||||
}
|
||||
if (y != self->rect_y)
|
||||
{
|
||||
present |= 0x02;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, y - self->rect_y)
|
||||
else
|
||||
out_uint16_le(self->out_s, y)
|
||||
self->rect_y = y;
|
||||
}
|
||||
if (cx != self->rect_cx)
|
||||
{
|
||||
present |= 0x04;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cx - self->rect_cx)
|
||||
else
|
||||
out_uint16_le(self->out_s, cx)
|
||||
self->rect_cx = cx;
|
||||
}
|
||||
if (cy != self->rect_cy)
|
||||
{
|
||||
present |= 0x08;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cy - self->rect_cy)
|
||||
else
|
||||
out_uint16_le(self->out_s, cy)
|
||||
self->rect_cy = cy;
|
||||
}
|
||||
if ((color & 0xff) != (self->rect_color & 0xff))
|
||||
{
|
||||
present |= 0x10;
|
||||
self->rect_color = (self->rect_color & 0xffff00) | (color & 0xff);
|
||||
out_uint8(self->out_s, color);
|
||||
}
|
||||
if ((color & 0xff00) != (self->rect_color & 0xff00))
|
||||
{
|
||||
present |= 0x20;
|
||||
self->rect_color = (self->rect_color & 0xff00ff) | (color & 0xff00);
|
||||
out_uint8(self->out_s, color >> 8);
|
||||
}
|
||||
if ((color & 0xff0000) != (self->rect_color & 0xff0000))
|
||||
{
|
||||
present |= 0x40;
|
||||
self->rect_color = (self->rect_color & 0x00ffff) | (color & 0xff0000);
|
||||
out_uint8(self->out_s, color >> 16);
|
||||
}
|
||||
*present_ptr = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a screen blt order */
|
||||
/* max size 25 */
|
||||
int xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int srcx, int srcy,
|
||||
int rop, struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[12];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
|
||||
xrdp_orders_check(self, 25);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_SCREENBLT)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_SCREENBLT;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = x; vals[1] = self->scr_blt_x;
|
||||
vals[2] = y; vals[3] = self->scr_blt_y;
|
||||
vals[4] = cx; vals[5] = self->scr_blt_cx;
|
||||
vals[6] = cy; vals[7] = self->scr_blt_cy;
|
||||
vals[8] = srcx; vals[9] = self->scr_blt_srcx;
|
||||
vals[10] = srcy; vals[11] = self->scr_blt_srcy;
|
||||
if (xrdp_orders_send_delta(self, vals, 12))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
||||
out_uint8s(self->out_s, 1)
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (x != self->scr_blt_x)
|
||||
{
|
||||
present |= 0x01;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, x - self->scr_blt_x)
|
||||
else
|
||||
out_uint16_le(self->out_s, x)
|
||||
self->scr_blt_x = x;
|
||||
}
|
||||
if (y != self->scr_blt_y)
|
||||
{
|
||||
present |= 0x02;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, y - self->scr_blt_y)
|
||||
else
|
||||
out_uint16_le(self->out_s, y)
|
||||
self->scr_blt_y = y;
|
||||
}
|
||||
if (cx != self->scr_blt_cx)
|
||||
{
|
||||
present |= 0x04;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cx - self->scr_blt_cx)
|
||||
else
|
||||
out_uint16_le(self->out_s, cx)
|
||||
self->scr_blt_cx = cx;
|
||||
}
|
||||
if (cy != self->scr_blt_cy)
|
||||
{
|
||||
present |= 0x08;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cy - self->scr_blt_cy)
|
||||
else
|
||||
out_uint16_le(self->out_s, cy)
|
||||
self->scr_blt_cy = cy;
|
||||
}
|
||||
if (rop != self->scr_blt_rop)
|
||||
{
|
||||
present |= 0x10;
|
||||
out_uint8(self->out_s, rop);
|
||||
self->scr_blt_rop = rop;
|
||||
}
|
||||
if (srcx != self->scr_blt_srcx)
|
||||
{
|
||||
present |= 0x20;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, srcx - self->scr_blt_srcx)
|
||||
else
|
||||
out_uint16_le(self->out_s, srcx)
|
||||
self->scr_blt_srcx = srcx;
|
||||
}
|
||||
if (srcy != self->scr_blt_srcy)
|
||||
{
|
||||
present |= 0x40;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, srcy - self->scr_blt_srcy)
|
||||
else
|
||||
out_uint16_le(self->out_s, srcy)
|
||||
self->scr_blt_srcy = srcy;
|
||||
}
|
||||
*present_ptr = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a pat blt order */
|
||||
/* max size 39 */
|
||||
int xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int rop, int bg_color,
|
||||
int fg_color, struct xrdp_brush* brush,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[8];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
struct xrdp_brush blank_brush;
|
||||
|
||||
xrdp_orders_check(self, 39);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_PATBLT)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_PATBLT;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = x; vals[1] = self->pat_blt_x;
|
||||
vals[2] = y; vals[3] = self->pat_blt_y;
|
||||
vals[4] = cx; vals[5] = self->pat_blt_cx;
|
||||
vals[6] = cy; vals[7] = self->pat_blt_cy;
|
||||
if (xrdp_orders_send_delta(self, vals, 8))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
|
||||
out_uint8s(self->out_s, 2) /* this can be smaller, */
|
||||
/* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (x != self->pat_blt_x)
|
||||
{
|
||||
present |= 0x0001;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, x - self->pat_blt_x)
|
||||
else
|
||||
out_uint16_le(self->out_s, x)
|
||||
self->pat_blt_x = x;
|
||||
}
|
||||
if (y != self->pat_blt_y)
|
||||
{
|
||||
present |= 0x0002;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, y - self->pat_blt_y)
|
||||
else
|
||||
out_uint16_le(self->out_s, y)
|
||||
self->pat_blt_y = y;
|
||||
}
|
||||
if (cx != self->pat_blt_cx)
|
||||
{
|
||||
present |= 0x0004;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cx - self->pat_blt_cx)
|
||||
else
|
||||
out_uint16_le(self->out_s, cx)
|
||||
self->pat_blt_cx = cx;
|
||||
}
|
||||
if (cy != self->pat_blt_cy)
|
||||
{
|
||||
present |= 0x0008;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cy - self->pat_blt_cy)
|
||||
else
|
||||
out_uint16_le(self->out_s, cy)
|
||||
self->pat_blt_cy = cy;
|
||||
}
|
||||
if (rop != self->pat_blt_rop)
|
||||
{
|
||||
present |= 0x0010;
|
||||
/* PATCOPY PATPAINT PATINVERT DSTINVERT BLACKNESS WHITENESS */
|
||||
out_uint8(self->out_s, rop);
|
||||
self->pat_blt_rop = rop;
|
||||
}
|
||||
if (bg_color != self->pat_blt_bg_color)
|
||||
{
|
||||
present |= 0x0020;
|
||||
out_uint8(self->out_s, bg_color);
|
||||
out_uint8(self->out_s, bg_color >> 8);
|
||||
out_uint8(self->out_s, bg_color >> 16);
|
||||
self->pat_blt_bg_color = bg_color;
|
||||
}
|
||||
if (fg_color != self->pat_blt_fg_color)
|
||||
{
|
||||
present |= 0x0040;
|
||||
out_uint8(self->out_s, fg_color);
|
||||
out_uint8(self->out_s, fg_color >> 8);
|
||||
out_uint8(self->out_s, fg_color >> 16);
|
||||
self->pat_blt_fg_color = fg_color;
|
||||
}
|
||||
if (brush == 0) /* if nil use blank one */
|
||||
{ /* todo can we just set style to zero */
|
||||
g_memset(&blank_brush, 0, sizeof(struct xrdp_brush));
|
||||
brush = &blank_brush;
|
||||
}
|
||||
if (brush->x_orgin != self->pat_blt_brush.x_orgin)
|
||||
{
|
||||
present |= 0x0080;
|
||||
out_uint8(self->out_s, brush->x_orgin);
|
||||
self->pat_blt_brush.x_orgin = brush->x_orgin;
|
||||
}
|
||||
if (brush->y_orgin != self->pat_blt_brush.y_orgin)
|
||||
{
|
||||
present |= 0x0100;
|
||||
out_uint8(self->out_s, brush->y_orgin);
|
||||
self->pat_blt_brush.y_orgin = brush->y_orgin;
|
||||
}
|
||||
if (brush->style != self->pat_blt_brush.style)
|
||||
{
|
||||
present |= 0x0200;
|
||||
out_uint8(self->out_s, brush->style);
|
||||
self->pat_blt_brush.style = brush->style;
|
||||
}
|
||||
if (brush->pattern[0] != self->pat_blt_brush.pattern[0])
|
||||
{
|
||||
present |= 0x0400;
|
||||
out_uint8(self->out_s, brush->pattern[0]);
|
||||
self->pat_blt_brush.pattern[0] = brush->pattern[0];
|
||||
}
|
||||
if (g_memcmp(brush->pattern + 1, self->pat_blt_brush.pattern + 1, 7) != 0)
|
||||
{
|
||||
present |= 0x0800;
|
||||
out_uint8a(self->out_s, brush->pattern + 1, 7);
|
||||
g_memcpy(self->pat_blt_brush.pattern + 1, brush->pattern + 1, 7);
|
||||
}
|
||||
*((short*)present_ptr) = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a dest blt order */
|
||||
/* max size 21 */
|
||||
int xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y,
|
||||
int cx, int cy, int rop,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[8];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
|
||||
xrdp_orders_check(self, 21);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_DESTBLT)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_DESTBLT;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = x; vals[1] = self->dest_blt_x;
|
||||
vals[2] = y; vals[3] = self->dest_blt_y;
|
||||
vals[4] = cx; vals[5] = self->dest_blt_cx;
|
||||
vals[6] = cy; vals[7] = self->dest_blt_cy;
|
||||
if (xrdp_orders_send_delta(self, vals, 8))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 1 byte present pointer */
|
||||
out_uint8s(self->out_s, 1)
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (x != self->dest_blt_x)
|
||||
{
|
||||
present |= 0x01;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, x - self->dest_blt_x)
|
||||
else
|
||||
out_uint16_le(self->out_s, x)
|
||||
self->dest_blt_x = x;
|
||||
}
|
||||
if (y != self->dest_blt_y)
|
||||
{
|
||||
present |= 0x02;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, y - self->dest_blt_y)
|
||||
else
|
||||
out_uint16_le(self->out_s, y)
|
||||
self->dest_blt_y = y;
|
||||
}
|
||||
if (cx != self->dest_blt_cx)
|
||||
{
|
||||
present |= 0x04;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cx - self->dest_blt_cx)
|
||||
else
|
||||
out_uint16_le(self->out_s, cx)
|
||||
self->dest_blt_cx = cx;
|
||||
}
|
||||
if (cy != self->dest_blt_cy)
|
||||
{
|
||||
present |= 0x08;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cy - self->dest_blt_cy)
|
||||
else
|
||||
out_uint16_le(self->out_s, cy)
|
||||
self->dest_blt_cy = cy;
|
||||
}
|
||||
if (rop != self->dest_blt_rop)
|
||||
{
|
||||
present |= 0x0010;
|
||||
out_uint8(self->out_s, rop);
|
||||
self->dest_blt_rop = rop;
|
||||
}
|
||||
*present_ptr = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a line order */
|
||||
/* max size 32 */
|
||||
int xrdp_orders_line(struct xrdp_orders* self, int mix_mode,
|
||||
int startx, int starty,
|
||||
int endx, int endy, int rop, int bg_color,
|
||||
struct xrdp_pen* pen,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[8];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
struct xrdp_pen blank_pen;
|
||||
|
||||
xrdp_orders_check(self, 32);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_LINE)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_LINE;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = startx; vals[1] = self->line_startx;
|
||||
vals[2] = starty; vals[3] = self->line_starty;
|
||||
vals[4] = endx; vals[5] = self->line_endx;
|
||||
vals[6] = endy; vals[7] = self->line_endy;
|
||||
if (xrdp_orders_send_delta(self, vals, 8))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 2 byte present pointer */
|
||||
out_uint8s(self->out_s, 2)
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (mix_mode != self->line_mix_mode)
|
||||
{
|
||||
present |= 0x0001;
|
||||
out_uint16_le(self->out_s, mix_mode)
|
||||
self->line_mix_mode = mix_mode;
|
||||
}
|
||||
if (startx != self->line_startx)
|
||||
{
|
||||
present |= 0x0002;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, startx - self->line_startx)
|
||||
else
|
||||
out_uint16_le(self->out_s, startx)
|
||||
self->line_startx = startx;
|
||||
}
|
||||
if (starty != self->line_starty)
|
||||
{
|
||||
present |= 0x0004;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, starty - self->line_starty)
|
||||
else
|
||||
out_uint16_le(self->out_s, starty)
|
||||
self->line_starty = starty;
|
||||
}
|
||||
if (endx != self->line_endx)
|
||||
{
|
||||
present |= 0x0008;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, endx - self->line_endx)
|
||||
else
|
||||
out_uint16_le(self->out_s, endx)
|
||||
self->line_endx = endx;
|
||||
}
|
||||
if (endy != self->line_endy)
|
||||
{
|
||||
present |= 0x0010;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, endy - self->line_endy)
|
||||
else
|
||||
out_uint16_le(self->out_s, endy)
|
||||
self->line_endy = endy;
|
||||
}
|
||||
if (bg_color != self->line_bg_color)
|
||||
{
|
||||
present |= 0x0020;
|
||||
out_uint8(self->out_s, bg_color)
|
||||
out_uint8(self->out_s, bg_color >> 8)
|
||||
out_uint8(self->out_s, bg_color >> 16)
|
||||
self->line_bg_color = bg_color;
|
||||
}
|
||||
if (rop != self->line_rop)
|
||||
{
|
||||
present |= 0x0040;
|
||||
out_uint8(self->out_s, rop)
|
||||
self->line_rop = rop;
|
||||
}
|
||||
if (pen == 0)
|
||||
{
|
||||
g_memset(&blank_pen, 0, sizeof(struct xrdp_pen));
|
||||
pen = &blank_pen;
|
||||
}
|
||||
if (pen->style != self->line_pen.style)
|
||||
{
|
||||
present |= 0x0080;
|
||||
out_uint8(self->out_s, pen->style)
|
||||
self->line_pen.style = pen->style;
|
||||
}
|
||||
if (pen->width != self->line_pen.width)
|
||||
{
|
||||
present |= 0x0100;
|
||||
out_uint8(self->out_s, pen->width)
|
||||
self->line_pen.width = pen->width;
|
||||
}
|
||||
if (pen->color != self->line_pen.color)
|
||||
{
|
||||
present |= 0x0200;
|
||||
out_uint8(self->out_s, pen->color)
|
||||
out_uint8(self->out_s, pen->color >> 8)
|
||||
out_uint8(self->out_s, pen->color >> 16)
|
||||
self->line_pen.color = pen->color;
|
||||
}
|
||||
*((short*)present_ptr) = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* send a mem blt order */
|
||||
/* max size 30 */
|
||||
int xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id,
|
||||
int color_table, int x, int y, int cx, int cy,
|
||||
int rop, int srcx, int srcy,
|
||||
int cache_idx, struct xrdp_rect* rect)
|
||||
{
|
||||
int order_flags;
|
||||
int vals[12];
|
||||
int present;
|
||||
char* present_ptr;
|
||||
|
||||
xrdp_orders_check(self, 30);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD;
|
||||
if (self->last_order != RDP_ORDER_MEMBLT)
|
||||
order_flags |= RDP_ORDER_CHANGE;
|
||||
self->last_order = RDP_ORDER_MEMBLT;
|
||||
if (rect != 0)
|
||||
{
|
||||
order_flags |= RDP_ORDER_BOUNDS;
|
||||
if (xrdp_orders_last_bounds(self, rect))
|
||||
order_flags |= RDP_ORDER_LASTBOUNDS;
|
||||
}
|
||||
vals[0] = x; vals[1] = self->mem_blt_x;
|
||||
vals[2] = y; vals[3] = self->mem_blt_y;
|
||||
vals[4] = cx; vals[5] = self->mem_blt_cx;
|
||||
vals[6] = cy; vals[7] = self->mem_blt_cy;
|
||||
vals[8] = srcx; vals[9] = self->mem_blt_srcx;
|
||||
vals[10] = srcy; vals[11] = self->mem_blt_srcy;
|
||||
if (xrdp_orders_send_delta(self, vals, 12))
|
||||
order_flags |= RDP_ORDER_DELTA;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
if (order_flags & RDP_ORDER_CHANGE)
|
||||
out_uint8(self->out_s, self->last_order)
|
||||
present = 0;
|
||||
present_ptr = self->out_s->p; /* hold 2 byte present pointer, todo */
|
||||
out_uint8s(self->out_s, 2) /* this can be smaller, */
|
||||
/* see RDP_ORDER_SMALL and RDP_ORDER_TINY */
|
||||
if ((order_flags & RDP_ORDER_BOUNDS) &&
|
||||
!(order_flags & RDP_ORDER_LASTBOUNDS))
|
||||
xrdp_orders_out_bounds(self, rect);
|
||||
if (cache_id != self->mem_blt_cache_id ||
|
||||
color_table != self->mem_blt_color_table)
|
||||
{
|
||||
present |= 0x0001;
|
||||
out_uint8(self->out_s, cache_id);
|
||||
out_uint8(self->out_s, color_table);
|
||||
self->mem_blt_cache_id = cache_id;
|
||||
self->mem_blt_color_table = color_table;
|
||||
}
|
||||
if (x != self->mem_blt_x)
|
||||
{
|
||||
present |= 0x0002;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, x - self->mem_blt_x)
|
||||
else
|
||||
out_uint16_le(self->out_s, x)
|
||||
self->mem_blt_x = x;
|
||||
}
|
||||
if (y != self->mem_blt_y)
|
||||
{
|
||||
present |= 0x0004;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, y - self->mem_blt_y)
|
||||
else
|
||||
out_uint16_le(self->out_s, y)
|
||||
self->mem_blt_y = y;
|
||||
}
|
||||
if (cx != self->mem_blt_cx)
|
||||
{
|
||||
present |= 0x0008;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cx - self->mem_blt_cx)
|
||||
else
|
||||
out_uint16_le(self->out_s, cx)
|
||||
self->mem_blt_cx = cx;
|
||||
}
|
||||
if (cy != self->mem_blt_cy)
|
||||
{
|
||||
present |= 0x0010;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, cy - self->mem_blt_cy)
|
||||
else
|
||||
out_uint16_le(self->out_s, cy)
|
||||
self->mem_blt_cy = cy;
|
||||
}
|
||||
if (rop != self->mem_blt_rop)
|
||||
{
|
||||
present |= 0x0020;
|
||||
out_uint8(self->out_s, rop);
|
||||
self->mem_blt_rop = rop;
|
||||
}
|
||||
if (srcx != self->mem_blt_srcx)
|
||||
{
|
||||
present |= 0x0040;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, srcx - self->mem_blt_srcx)
|
||||
else
|
||||
out_uint16_le(self->out_s, srcx)
|
||||
self->mem_blt_srcx = srcx;
|
||||
}
|
||||
if (srcy != self->mem_blt_srcy)
|
||||
{
|
||||
present |= 0x0080;
|
||||
if (order_flags & RDP_ORDER_DELTA)
|
||||
out_uint8(self->out_s, srcy - self->mem_blt_srcy)
|
||||
else
|
||||
out_uint16_le(self->out_s, srcy)
|
||||
self->mem_blt_srcy = srcy;
|
||||
}
|
||||
if (cache_idx != self->mem_blt_cache_idx)
|
||||
{
|
||||
present |= 0x0100;
|
||||
out_uint16_le(self->out_s, cache_idx);
|
||||
self->mem_blt_cache_idx = cache_idx;
|
||||
}
|
||||
*((short*)present_ptr) = present;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* when a palette gets sent, send the main palette too */
|
||||
/* don't need max size here */
|
||||
int xrdp_orders_send_palette(struct xrdp_orders* self, int* palette,
|
||||
int cache_id)
|
||||
{
|
||||
int order_flags;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
/* gota clear any build up orders and send the main palette */
|
||||
xrdp_orders_force_send(self);
|
||||
xrdp_wm_send_palette(self->pro_layer->wm);
|
||||
xrdp_orders_init(self);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
len = 1027 - 7; /* length after type minus 7 */
|
||||
out_uint16_le(self->out_s, len);
|
||||
out_uint16_le(self->out_s, 0); /* flags */
|
||||
out_uint8(self->out_s, RDP_ORDER_COLCACHE); /* type */
|
||||
out_uint8(self->out_s, cache_id);
|
||||
out_uint16_le(self->out_s, 256); /* num colors */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
out_uint8(self->out_s, palette[i]);
|
||||
out_uint8(self->out_s, palette[i] >> 8);
|
||||
out_uint8(self->out_s, palette[i] >> 16);
|
||||
out_uint8(self->out_s, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* max size width * height * Bpp + 16 */
|
||||
int xrdp_orders_send_raw_bitmap(struct xrdp_orders* self,
|
||||
struct xrdp_bitmap* bitmap,
|
||||
int cache_id, int cache_idx)
|
||||
{
|
||||
int order_flags;
|
||||
int len;
|
||||
int bufsize;
|
||||
int Bpp;
|
||||
int i;
|
||||
int j;
|
||||
int pixel;
|
||||
|
||||
Bpp = (bitmap->bpp + 7) / 8;
|
||||
bufsize = bitmap->width * bitmap->height * Bpp;
|
||||
xrdp_orders_check(self, bufsize + 16);
|
||||
self->order_count++;
|
||||
order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
len = (bufsize + 9) - 7;
|
||||
out_uint16_le(self->out_s, len);
|
||||
out_uint16_le(self->out_s, 8); /* flags */
|
||||
out_uint8(self->out_s, RDP_ORDER_RAW_BMPCACHE); /* type */
|
||||
out_uint8(self->out_s, cache_id);
|
||||
out_uint8s(self->out_s, 1); /* pad */
|
||||
out_uint8(self->out_s, bitmap->width);
|
||||
out_uint8(self->out_s, bitmap->height);
|
||||
out_uint8(self->out_s, bitmap->bpp);
|
||||
out_uint16_le(self->out_s, bufsize);
|
||||
out_uint16_le(self->out_s, cache_idx);
|
||||
for (i = bitmap->height - 1; i >= 0; i--)
|
||||
for (j = 0; j < bitmap->width; j++)
|
||||
{
|
||||
pixel = xrdp_bitmap_get_pixel(bitmap, j, i);
|
||||
if (Bpp == 3)
|
||||
{
|
||||
out_uint8(self->out_s, pixel >> 16);
|
||||
out_uint8(self->out_s, pixel >> 8);
|
||||
out_uint8(self->out_s, pixel);
|
||||
}
|
||||
else if (Bpp == 2)
|
||||
{
|
||||
out_uint8(self->out_s, pixel);
|
||||
out_uint8(self->out_s, pixel >> 8);
|
||||
}
|
||||
else if (Bpp == 1)
|
||||
out_uint8(self->out_s, pixel);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,333 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
painter, gc
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_painter* xrdp_painter_create(struct xrdp_wm* wm)
|
||||
{
|
||||
struct xrdp_painter* self;
|
||||
|
||||
self = (struct xrdp_painter*)g_malloc(sizeof(struct xrdp_painter), 1);
|
||||
self->wm = wm;
|
||||
self->orders = wm->orders;
|
||||
self->rop = 0xcc; /* copy */
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_painter_delete(struct xrdp_painter* self)
|
||||
{
|
||||
if (self == 0)
|
||||
return;
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_begin_update(struct xrdp_painter* self)
|
||||
{
|
||||
xrdp_orders_init(self->orders);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_end_update(struct xrdp_painter* self)
|
||||
{
|
||||
xrdp_orders_send(self->orders);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_clip_adj(struct xrdp_painter* self, int* x, int* y,
|
||||
int* cx, int* cy)
|
||||
{
|
||||
int dx;
|
||||
int dy;
|
||||
|
||||
if (!self->use_clip)
|
||||
return 1;
|
||||
if (self->clip.left > *x)
|
||||
dx = self->clip.left - *x;
|
||||
else
|
||||
dx = 0;
|
||||
if (self->clip.top > *y)
|
||||
dy = self->clip.top - *y;
|
||||
else
|
||||
dy = 0;
|
||||
if (*x + *cx > self->clip.right)
|
||||
*cx = *cx - ((*x + *cx) - self->clip.right);
|
||||
if (*y + *cy > self->clip.bottom)
|
||||
*cy = *cy - ((*y + *cy) - self->clip.bottom);
|
||||
*cx = *cx - dx;
|
||||
*cy = *cy - dy;
|
||||
if (*cx <= 0)
|
||||
return 0;
|
||||
if (*cy <= 0)
|
||||
return 0;
|
||||
*x = *x + dx;
|
||||
*y = *y + dy;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_set_clip(struct xrdp_painter* self,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
self->use_clip = 1;
|
||||
self->clip.left = x;
|
||||
self->clip.top = y;
|
||||
self->clip.right = x + cx;
|
||||
self->clip.bottom = y + cy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_clr_clip(struct xrdp_painter* self)
|
||||
{
|
||||
self->use_clip = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_rop(int rop, int src, int dst)
|
||||
{
|
||||
switch (rop & 0x0f)
|
||||
{
|
||||
case 0x0: return 0;
|
||||
case 0x1: return ~(src | dst);
|
||||
case 0x2: return (~src) & dst;
|
||||
case 0x3: return ~src;
|
||||
case 0x4: return src & (~dst);
|
||||
case 0x5: return ~(dst);
|
||||
case 0x6: return src ^ dst;
|
||||
case 0x7: return ~(src & dst);
|
||||
case 0x8: return src & dst;
|
||||
case 0x9: return ~(src) ^ dst;
|
||||
case 0xa: return dst;
|
||||
case 0xb: return (~src) | dst;
|
||||
case 0xc: return src;
|
||||
case 0xd: return src | (~dst);
|
||||
case 0xe: return src | dst;
|
||||
case 0xf: return ~0;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* fill in an area of the screen with one color */
|
||||
int xrdp_painter_fill_rect(struct xrdp_painter* self,
|
||||
struct xrdp_bitmap* bitmap,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int i;
|
||||
struct xrdp_region* region;
|
||||
struct xrdp_rect rect;
|
||||
|
||||
if (x >= bitmap->width) return 0;
|
||||
if (y >= bitmap->height) return 0;
|
||||
if (x < 0) { cx += x; x = 0; }
|
||||
if (y < 0) { cy += y; y = 0; }
|
||||
if (cx <= 0) return 0;
|
||||
if (cy <= 0) return 0;
|
||||
if (x + cx > bitmap->width) cx = bitmap->width - x;
|
||||
if (y + cy > bitmap->height) cy = bitmap->height - y;
|
||||
|
||||
if (!xrdp_painter_clip_adj(self, &x, &y, &cx, &cy))
|
||||
return 0;
|
||||
|
||||
if (bitmap->type == 0)
|
||||
return 0;
|
||||
region = xrdp_region_create(self->wm);
|
||||
xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
|
||||
i = 0;
|
||||
while (xrdp_region_get_rect(region, i, &rect) == 0)
|
||||
{
|
||||
DEBUG(("sending rect order %d %d %d %d\n\r", rect.left, rect.top,
|
||||
rect.right, rect.bottom));
|
||||
xrdp_orders_rect(self->orders, rect.left, rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
self->fg_color, 0);
|
||||
i++;
|
||||
}
|
||||
xrdp_region_delete(region);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* fill in an area of the screen with opcodes and patterns */
|
||||
/* todo, this needs work */
|
||||
int xrdp_painter_fill_rect2(struct xrdp_painter* self,
|
||||
struct xrdp_bitmap* bitmap,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int i;
|
||||
struct xrdp_region* region;
|
||||
struct xrdp_rect rect;
|
||||
|
||||
if (x >= bitmap->width) return 0;
|
||||
if (y >= bitmap->height) return 0;
|
||||
if (x < 0) { cx += x; x = 0; }
|
||||
if (y < 0) { cy += y; y = 0; }
|
||||
if (cx <= 0) return 0;
|
||||
if (cy <= 0) return 0;
|
||||
if (x + cx > bitmap->width) cx = bitmap->width - x;
|
||||
if (y + cy > bitmap->height) cy = bitmap->height - y;
|
||||
|
||||
if (!xrdp_painter_clip_adj(self, &x, &y, &cx, &cy))
|
||||
return 0;
|
||||
|
||||
if (bitmap->type == 0) /* bitmap */
|
||||
return 0;
|
||||
region = xrdp_region_create(self->wm);
|
||||
xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
|
||||
i = 0;
|
||||
while (xrdp_region_get_rect(region, i, &rect) == 0)
|
||||
{
|
||||
DEBUG(("sending rect order %d %d %d %d\n\r", rect.left, rect.top,
|
||||
rect.right, rect.bottom));
|
||||
xrdp_orders_pat_blt(self->orders, rect.left, rect.top,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
self->rop, self->bg_color, self->fg_color,
|
||||
&self->brush, 0);
|
||||
i++;
|
||||
}
|
||||
xrdp_region_delete(region);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SS 16
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_painter_draw_bitmap(struct xrdp_painter* self,
|
||||
struct xrdp_bitmap* bitmap,
|
||||
struct xrdp_bitmap* to_draw,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
int w;
|
||||
int h;
|
||||
int x1;
|
||||
int y1;
|
||||
int ok;
|
||||
int srcx;
|
||||
int srcy;
|
||||
int bitmap_id;
|
||||
int cache_id;
|
||||
int cache_idx;
|
||||
int palette_id;
|
||||
struct xrdp_region* region;
|
||||
struct xrdp_rect rect;
|
||||
struct xrdp_rect rect1;
|
||||
struct xrdp_rect rect2;
|
||||
struct xrdp_bitmap* b;
|
||||
|
||||
/* todo data */
|
||||
|
||||
if (bitmap->type == 0)
|
||||
return 0;
|
||||
region = xrdp_region_create(self->wm);
|
||||
xrdp_wm_get_vis_region(self->wm, bitmap, x, y, cx, cy, region);
|
||||
b = bitmap;
|
||||
while (b != 0)
|
||||
{
|
||||
x = x + b->left;
|
||||
y = y + b->top;
|
||||
b = b->parent;
|
||||
}
|
||||
palette_id = xrdp_cache_add_palette(self->wm->cache, self->wm->palette);
|
||||
i = 0;
|
||||
while (i < to_draw->width)
|
||||
{
|
||||
j = 0;
|
||||
while (j < to_draw->height)
|
||||
{
|
||||
x1 = x + i;
|
||||
y1 = y + j;
|
||||
MIN(w, SS, to_draw->width - i);
|
||||
MIN(h, SS, to_draw->height - j);
|
||||
b = xrdp_bitmap_create(w, h, self->wm->screen->bpp, 0);
|
||||
xrdp_bitmap_copy_box(to_draw, b, i, j, w, h);
|
||||
bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b);
|
||||
HIWORD(cache_id, bitmap_id);
|
||||
LOWORD(cache_idx, bitmap_id);
|
||||
k = 0;
|
||||
while (xrdp_region_get_rect(region, k, &rect) == 0)
|
||||
{
|
||||
xrdp_wm_rect(&rect1, x1, y1, w, h);
|
||||
if (xrdp_wm_rect_intersect(&rect, &rect1, &rect2))
|
||||
{
|
||||
ok = 1;
|
||||
if (self->use_clip)
|
||||
{
|
||||
rect = self->clip;
|
||||
xrdp_wm_rect_offset(&rect, x, y);
|
||||
if (!xrdp_wm_rect_intersect(&rect2, &rect, &rect1))
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
rect1 = rect2;
|
||||
if (ok)
|
||||
{
|
||||
rect1.right--;
|
||||
rect1.bottom--;
|
||||
/* check these so ms client don't crash */
|
||||
if (x1 + w >= self->wm->screen->width)
|
||||
w = self->wm->screen->width - x1;
|
||||
if (y1 + h >= self->wm->screen->height)
|
||||
h = self->wm->screen->height - y1;
|
||||
if (w > 0 && h > 0 && x1 + w > 0 && y1 + h > 0)
|
||||
{
|
||||
srcx = 0;
|
||||
srcy = 0;
|
||||
if (x1 < 0)
|
||||
{
|
||||
w = w + x1;
|
||||
srcx = srcx - x1;
|
||||
x1 = 0;
|
||||
}
|
||||
if (y1 < 0)
|
||||
{
|
||||
h = h + y1;
|
||||
srcy = srcy - y1;
|
||||
y1 = 0;
|
||||
}
|
||||
xrdp_orders_mem_blt(self->orders, cache_id, palette_id,
|
||||
x1, y1, w, h, self->rop, srcx, srcy,
|
||||
cache_idx, &rect1);
|
||||
}
|
||||
}
|
||||
}
|
||||
k++;
|
||||
}
|
||||
xrdp_bitmap_delete(b);
|
||||
j += SS;
|
||||
}
|
||||
i += SS;
|
||||
}
|
||||
xrdp_region_delete(region);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
region
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_region* xrdp_region_create(struct xrdp_wm* wm)
|
||||
{
|
||||
struct xrdp_region* self;
|
||||
|
||||
self = (struct xrdp_region*)g_malloc(sizeof(struct xrdp_region), 1);
|
||||
self->wm = wm;
|
||||
self->rects = xrdp_list_create();
|
||||
self->rects->auto_free = 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_region_delete(struct xrdp_region* self)
|
||||
{
|
||||
if (self == 0)
|
||||
return;
|
||||
xrdp_list_delete(self->rects);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_region_add_rect(struct xrdp_region* self, struct xrdp_rect* rect)
|
||||
{
|
||||
struct xrdp_rect* r;
|
||||
|
||||
r = (struct xrdp_rect*)g_malloc(sizeof(struct xrdp_rect), 1);
|
||||
*r = *rect;
|
||||
xrdp_list_add_item(self->rects, (int)r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_region_insert_rect(struct xrdp_region* self, int i, int left,
|
||||
int top, int right, int bottom)
|
||||
{
|
||||
struct xrdp_rect* r;
|
||||
|
||||
r = (struct xrdp_rect*)g_malloc(sizeof(struct xrdp_rect), 1);
|
||||
r->left = left;
|
||||
r->top = top;
|
||||
r->right = right;
|
||||
r->bottom = bottom;
|
||||
xrdp_list_insert_item(self->rects, i, (int)r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_region_subtract_rect(struct xrdp_region* self,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
struct xrdp_rect* r;
|
||||
struct xrdp_rect rect1;
|
||||
int i;
|
||||
|
||||
for (i = self->rects->count - 1; i >= 0; i--)
|
||||
{
|
||||
r = (struct xrdp_rect*)xrdp_list_get_item(self->rects, i);
|
||||
rect1 = *r;
|
||||
r = &rect1;
|
||||
//g_printf("r is %d %d %d %d\n", r->left, r->top, r->right, r->bottom);
|
||||
if (rect->left <= r->left &&
|
||||
rect->top <= r->top &&
|
||||
rect->right >= r->right &&
|
||||
rect->bottom >= r->bottom)
|
||||
{ /* rect is not visible */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
}
|
||||
else if (rect->right < r->left ||
|
||||
rect->bottom < r->top ||
|
||||
rect->top > r->bottom ||
|
||||
rect->left > r->right)
|
||||
{ /* rect are not related */
|
||||
}
|
||||
else if (rect->left <= r->left &&
|
||||
rect->right >= r->right &&
|
||||
rect->bottom < r->bottom &&
|
||||
rect->top <= r->top)
|
||||
{ /* partially covered(whole top) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->top <= r->top &&
|
||||
rect->bottom >= r->bottom &&
|
||||
rect->right < r->right &&
|
||||
rect->left <= r->left)
|
||||
{ /* partially covered(left) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, rect->right, r->top,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left <= r->left &&
|
||||
rect->right >= r->right &&
|
||||
rect->top > r->top &&
|
||||
rect->bottom >= r->bottom)
|
||||
{ /* partially covered(bottom) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
}
|
||||
else if (rect->top <= r->top &&
|
||||
rect->bottom >= r->bottom &&
|
||||
rect->left > r->left &&
|
||||
rect->right >= r->right)
|
||||
{ /* partially covered(right) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
rect->left, r->bottom);
|
||||
}
|
||||
else if (rect->left <= r->left &&
|
||||
rect->top <= r->top &&
|
||||
rect->right < r->right &&
|
||||
rect->bottom < r->bottom)
|
||||
{ /* partially covered(top left) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, rect->right, r->top,
|
||||
r->right, rect->bottom);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left <= r->left &&
|
||||
rect->bottom >= r->bottom &&
|
||||
rect->right < r->right &&
|
||||
rect->top > r->top)
|
||||
{ /* partially covered(bottom left) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, rect->right, rect->top,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->right >= r->right &&
|
||||
rect->top <= r->top &&
|
||||
rect->bottom < r->bottom)
|
||||
{ /* partially covered(top right) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
rect->left, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->right >= r->right &&
|
||||
rect->top > r->top &&
|
||||
rect->bottom >= r->bottom)
|
||||
{ /* partially covered(bottom right) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->top,
|
||||
rect->left, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->top <= r->top &&
|
||||
rect->right < r->right &&
|
||||
rect->bottom >= r->bottom)
|
||||
{ /* 2 rects, one on each end */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
rect->left, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->right, r->top,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left <= r->left &&
|
||||
rect->top > r->top &&
|
||||
rect->right >= r->right &&
|
||||
rect->bottom < r->bottom)
|
||||
{ /* 2 rects, one on each end */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->right < r->right &&
|
||||
rect->top <= r->top &&
|
||||
rect->bottom < r->bottom)
|
||||
{ /* partially covered(top) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
rect->left, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->left, rect->bottom,
|
||||
rect->right, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->right, r->top,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->top > r->top &&
|
||||
rect->bottom < r->bottom &&
|
||||
rect->left <= r->left &&
|
||||
rect->right < r->right)
|
||||
{ /* partially covered(left) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, rect->right, rect->top,
|
||||
r->right, rect->bottom);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->right < r->right &&
|
||||
rect->bottom >= r->bottom &&
|
||||
rect->top > r->top)
|
||||
{ /* partially covered(bottom) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
rect->left, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->left, r->top,
|
||||
rect->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, rect->right, r->top,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->top > r->top &&
|
||||
rect->bottom < r->bottom &&
|
||||
rect->right >= r->right &&
|
||||
rect->left > r->left)
|
||||
{ /* partially covered(right) */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->top,
|
||||
rect->left, rect->bottom);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
}
|
||||
else if (rect->left > r->left &&
|
||||
rect->top > r->top &&
|
||||
rect->right < r->right &&
|
||||
rect->bottom < r->bottom)
|
||||
{ /* totally contained, 4 rects */
|
||||
xrdp_list_remove_item(self->rects, i);
|
||||
xrdp_region_insert_rect(self, i, r->left, r->top,
|
||||
r->right, rect->top);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->top,
|
||||
rect->left, rect->bottom);
|
||||
xrdp_region_insert_rect(self, i, r->left, rect->bottom,
|
||||
r->right, r->bottom);
|
||||
xrdp_region_insert_rect(self, i, rect->right, rect->top,
|
||||
r->right, rect->bottom);
|
||||
}
|
||||
else
|
||||
g_printf("error in xrdp_region_subtract_rect\n\r");
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_region_get_rect(struct xrdp_region* self, int index,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
struct xrdp_rect* r;
|
||||
|
||||
r = (struct xrdp_rect*)xrdp_list_get_item(self->rects, index);
|
||||
if (r == 0)
|
||||
return 1;
|
||||
*rect = *r;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,886 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Copyright (C) Jay Sorg 2004
|
||||
|
||||
simple window manager
|
||||
|
||||
*/
|
||||
|
||||
#include "xrdp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_wm* xrdp_wm_create(struct xrdp_process* owner)
|
||||
{
|
||||
struct xrdp_wm* self;
|
||||
|
||||
self = (struct xrdp_wm*)g_malloc(sizeof(struct xrdp_wm), 1);
|
||||
self->screen = xrdp_bitmap_create(owner->rdp_layer->width,
|
||||
owner->rdp_layer->height,
|
||||
owner->rdp_layer->bpp, 2);
|
||||
self->screen->wm = self;
|
||||
self->pro_layer = owner;
|
||||
self->orders = owner->orders;
|
||||
self->painter = xrdp_painter_create(self);
|
||||
self->out_s = &owner->out_s;
|
||||
self->rdp_layer = owner->rdp_layer;
|
||||
self->cache = xrdp_cache_create(self, self->orders);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void xrdp_wm_delete(struct xrdp_wm* self)
|
||||
{
|
||||
if (self == 0)
|
||||
return;
|
||||
xrdp_cache_delete(self->cache);
|
||||
xrdp_painter_delete(self->painter);
|
||||
xrdp_bitmap_delete(self->screen);
|
||||
g_free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_send_palette(struct xrdp_wm* self)
|
||||
{
|
||||
int i;
|
||||
int color;
|
||||
|
||||
xrdp_rdp_init_data(self->rdp_layer, 776);
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_PALETTE);
|
||||
out_uint16_le(self->out_s, 0);
|
||||
out_uint16_le(self->out_s, 256); /* # of colors */
|
||||
out_uint16_le(self->out_s, 0);
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
color = self->palette[i];
|
||||
out_uint8(self->out_s, color >> 16);
|
||||
out_uint8(self->out_s, color >> 8);
|
||||
out_uint8(self->out_s, color);
|
||||
}
|
||||
s_mark_end(self->out_s);
|
||||
xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* todo */
|
||||
int xrdp_wm_send_bitmap(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
|
||||
int x, int y, int cx, int cy)
|
||||
{
|
||||
int data_size;
|
||||
int line_size;
|
||||
int i;
|
||||
int total_lines;
|
||||
int lines_sending;
|
||||
char* p;
|
||||
|
||||
data_size = bitmap->width * bitmap->height * ((bitmap->bpp + 7) / 8);
|
||||
line_size = bitmap->width * ((bitmap->bpp + 7) / 8);
|
||||
total_lines = data_size / line_size;
|
||||
i = 0;
|
||||
p = bitmap->data;
|
||||
lines_sending = 4096 / line_size;
|
||||
if (lines_sending > total_lines)
|
||||
lines_sending = total_lines;
|
||||
while (i < total_lines)
|
||||
{
|
||||
xrdp_rdp_init_data(self->rdp_layer, 8192);
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_BITMAP);
|
||||
out_uint16_le(self->out_s, 1); /* num updates */
|
||||
out_uint16_le(self->out_s, x);
|
||||
out_uint16_le(self->out_s, y + i);
|
||||
out_uint16_le(self->out_s, (x + cx) - 1);
|
||||
out_uint16_le(self->out_s, (y + i + cy) - 1);
|
||||
out_uint16_le(self->out_s, bitmap->width);
|
||||
out_uint16_le(self->out_s, lines_sending);
|
||||
out_uint16_le(self->out_s, bitmap->bpp); /* bpp */
|
||||
out_uint16_le(self->out_s, 0); /* compress */
|
||||
out_uint16_le(self->out_s, line_size * lines_sending); /* bufsize */
|
||||
out_uint8a(self->out_s, p, line_size * lines_sending);
|
||||
s_mark_end(self->out_s);
|
||||
xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_UPDATE);
|
||||
p = p + line_size * lines_sending;
|
||||
i = i + lines_sending;
|
||||
if (i + lines_sending > total_lines)
|
||||
lines_sending = total_lines - i;
|
||||
if (lines_sending <= 0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_color15(int r, int g, int b)
|
||||
{
|
||||
r = r >> 3;
|
||||
g = g >> 3;
|
||||
b = b >> 3;
|
||||
return (r << 10) | (g << 5) | b;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_color16(int r, int g, int b)
|
||||
{
|
||||
r = r >> 3;
|
||||
g = g >> 2;
|
||||
b = b >> 3;
|
||||
return (r << 11) | (g << 5) | b;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_color24(int r, int g, int b)
|
||||
{
|
||||
return r | (g << 8) | (b << 16);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* all login help screen events go here */
|
||||
int xrdp_wm_login_help_notify(struct xrdp_bitmap* wnd,
|
||||
struct xrdp_bitmap* sender,
|
||||
int msg, int param1, int param2)
|
||||
{
|
||||
if (wnd == 0)
|
||||
return 0;
|
||||
if (sender == 0)
|
||||
return 0;
|
||||
if (wnd->owner == 0)
|
||||
return 0;
|
||||
if (msg == 1) /* click */
|
||||
{
|
||||
if (sender->id == 1) /* ok button */
|
||||
{
|
||||
if (sender->owner->notify != 0)
|
||||
{
|
||||
wnd->owner->notify(wnd->owner, wnd, 100, 1, 0); /* ok */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_set_focused(struct xrdp_wm* self, struct xrdp_bitmap* wnd)
|
||||
{
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (self->focused_window == wnd)
|
||||
return 0;
|
||||
if (self->focused_window != 0)
|
||||
{
|
||||
xrdp_bitmap_set_focus(self->focused_window, 0);
|
||||
}
|
||||
self->focused_window = wnd;
|
||||
if (self->focused_window != 0)
|
||||
{
|
||||
xrdp_bitmap_set_focus(self->focused_window, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* all login screen events go here */
|
||||
int xrdp_wm_login_notify(struct xrdp_bitmap* wnd,
|
||||
struct xrdp_bitmap* sender,
|
||||
int msg, int param1, int param2)
|
||||
{
|
||||
struct xrdp_bitmap* help;
|
||||
struct xrdp_bitmap* but;
|
||||
struct xrdp_bitmap* b;
|
||||
struct xrdp_rect rect;
|
||||
int i;
|
||||
|
||||
if (msg == 1) /* click */
|
||||
{
|
||||
if (sender->id == 1) /* help button */
|
||||
{
|
||||
/* create help screen */
|
||||
help = xrdp_bitmap_create(300, 300, wnd->wm->screen->bpp, 1);
|
||||
xrdp_list_insert_item(wnd->wm->screen->child_list, 0, (int)help);
|
||||
help->parent = wnd->wm->screen;
|
||||
help->owner = wnd;
|
||||
wnd->modal_dialog = help;
|
||||
help->wm = wnd->wm;
|
||||
help->bg_color = wnd->wm->grey;
|
||||
help->left = wnd->wm->screen->width / 2 - help->width / 2;
|
||||
help->top = wnd->wm->screen->height / 2 - help->height / 2;
|
||||
help->notify = xrdp_wm_login_help_notify;
|
||||
/* ok button */
|
||||
but = xrdp_bitmap_create(60, 25, wnd->wm->screen->bpp, 3);
|
||||
xrdp_list_insert_item(help->child_list, 0, (int)but);
|
||||
but->parent = help;
|
||||
but->owner = help;
|
||||
but->wm = wnd->wm;
|
||||
but->left = 120;
|
||||
but->top = 260;
|
||||
but->id = 1;
|
||||
/* draw it */
|
||||
xrdp_bitmap_invalidate(help, 0);
|
||||
xrdp_wm_set_focused(wnd->wm, help);
|
||||
}
|
||||
else if (sender->id == 2) /* cancel button */
|
||||
{
|
||||
/*if (wnd != 0)
|
||||
if (wnd->wm != 0)
|
||||
if (wnd->wm->pro_layer != 0)
|
||||
wnd->wm->pro_layer->term = 1;*/
|
||||
}
|
||||
}
|
||||
else if (msg == 2) /* mouse move */
|
||||
{
|
||||
}
|
||||
else if (msg == 100) /* modal result is done */
|
||||
{
|
||||
i = xrdp_list_index_of(wnd->wm->screen->child_list, (int)sender);
|
||||
if (i >= 0)
|
||||
{
|
||||
b = (struct xrdp_bitmap*)
|
||||
xrdp_list_get_item(wnd->wm->screen->child_list, i);
|
||||
xrdp_list_remove_item(sender->wm->screen->child_list, i);
|
||||
xrdp_wm_rect(&rect, b->left, b->top, b->width, b->height);
|
||||
xrdp_bitmap_invalidate(wnd->wm->screen, &rect);
|
||||
xrdp_bitmap_delete(sender);
|
||||
wnd->modal_dialog = 0;
|
||||
xrdp_wm_set_focused(wnd->wm, wnd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_set_cursor(struct xrdp_wm* self, int cache_idx)
|
||||
{
|
||||
xrdp_rdp_init_data(self->rdp_layer, 8000);
|
||||
out_uint16_le(self->out_s, RDP_POINTER_CACHED);
|
||||
out_uint16_le(self->out_s, 0); /* pad */
|
||||
out_uint16_le(self->out_s, cache_idx); /* cache_idx */
|
||||
s_mark_end(self->out_s);
|
||||
xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_POINTER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* send a cursor from a file */
|
||||
int xrdp_send_cursor(struct xrdp_wm* self, char* file_name, int cache_idx)
|
||||
{
|
||||
int v;
|
||||
int fd;
|
||||
int w;
|
||||
int h;
|
||||
struct stream* s;
|
||||
|
||||
s = (struct stream*)g_malloc(sizeof(struct stream), 1);
|
||||
init_stream(s, 8001);
|
||||
fd = g_file_open(file_name);
|
||||
g_file_read(fd, s->data, 8000);
|
||||
g_file_close(fd);
|
||||
xrdp_rdp_init_data(self->rdp_layer, 8000);
|
||||
out_uint16_le(self->out_s, RDP_POINTER_COLOR);
|
||||
out_uint16_le(self->out_s, 0); /* pad */
|
||||
out_uint16_le(self->out_s, cache_idx); /* cache_idx */
|
||||
in_uint32_le(s, v);
|
||||
out_uint16_le(self->out_s, v); /* x */
|
||||
in_uint32_le(s, v);
|
||||
out_uint16_le(self->out_s, v); /* y */
|
||||
in_uint32_le(s, w);
|
||||
out_uint16_le(self->out_s, w); /* width */
|
||||
in_uint32_le(s, h);
|
||||
out_uint16_le(self->out_s, h); /* height */
|
||||
v = (w * h) / 8;
|
||||
out_uint16_le(self->out_s, v); /* mask len */
|
||||
v = (w * h) * 3;
|
||||
out_uint16_le(self->out_s, v); /* data len */
|
||||
v = ((w * h) / 8) + ((w * h) * 3);
|
||||
out_uint8a(self->out_s, s->p, v);
|
||||
s_mark_end(self->out_s);
|
||||
xrdp_rdp_send_data(self->rdp_layer, RDP_DATA_PDU_POINTER);
|
||||
g_free(s->data);
|
||||
g_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_init(struct xrdp_wm* self)
|
||||
{
|
||||
struct xrdp_bitmap* but;
|
||||
|
||||
if (self->screen->bpp == 8)
|
||||
{
|
||||
/* rgb */
|
||||
self->palette[250] = 0x00ff0000;
|
||||
self->palette[251] = 0x0000ff00;
|
||||
self->palette[252] = 0x00c0c0c0;
|
||||
self->palette[253] = 0x00808080;
|
||||
self->palette[254] = 0x000000ff;
|
||||
self->palette[255] = 0x00ffffff;
|
||||
self->black = 0;
|
||||
self->grey = 252;
|
||||
self->dark_grey = 253;
|
||||
self->blue = 254;
|
||||
self->white = 255;
|
||||
self->red = 250;
|
||||
self->green = 251;
|
||||
xrdp_wm_send_palette(self);
|
||||
|
||||
}
|
||||
else if (self->screen->bpp == 15)
|
||||
{
|
||||
self->black = xrdp_wm_color15(0, 0, 0);
|
||||
self->grey = xrdp_wm_color15(0xc0, 0xc0, 0xc0);
|
||||
self->dark_grey = xrdp_wm_color15(0x80, 0x80, 0x80);
|
||||
self->blue = xrdp_wm_color15(0x00, 0x00, 0xff);
|
||||
self->white = xrdp_wm_color15(0xff, 0xff, 0xff);
|
||||
self->red = xrdp_wm_color15(0xff, 0x00, 0x00);
|
||||
self->green = xrdp_wm_color15(0x00, 0xff, 0x00);
|
||||
}
|
||||
else if (self->screen->bpp == 16)
|
||||
{
|
||||
self->black = xrdp_wm_color16(0, 0, 0);
|
||||
self->grey = xrdp_wm_color16(0xc0, 0xc0, 0xc0);
|
||||
self->dark_grey = xrdp_wm_color16(0x80, 0x80, 0x80);
|
||||
self->blue = xrdp_wm_color16(0x00, 0x00, 0xff);
|
||||
self->white = xrdp_wm_color16(0xff, 0xff, 0xff);
|
||||
self->red = xrdp_wm_color16(0xff, 0x00, 0x00);
|
||||
self->green = xrdp_wm_color16(0x00, 0xff, 0x00);
|
||||
}
|
||||
else if (self->screen->bpp == 24)
|
||||
{
|
||||
self->black = xrdp_wm_color24(0, 0, 0);
|
||||
self->grey = xrdp_wm_color24(0xc0, 0xc0, 0xc0);
|
||||
self->dark_grey = xrdp_wm_color24(0x80, 0x80, 0x80);
|
||||
self->blue = xrdp_wm_color24(0x00, 0x00, 0xff);
|
||||
self->white = xrdp_wm_color24(0xff, 0xff, 0xff);
|
||||
self->red = xrdp_wm_color24(0xff, 0x00, 0x00);
|
||||
self->green = xrdp_wm_color24(0x00, 0xff, 0x00);
|
||||
}
|
||||
/* draw login window */
|
||||
self->login_window = xrdp_bitmap_create(400, 200, self->screen->bpp, 1);
|
||||
xrdp_list_add_item(self->screen->child_list, (int)self->login_window);
|
||||
self->login_window->parent = self->screen;
|
||||
self->login_window->owner = self->screen;
|
||||
self->login_window->wm = self;
|
||||
self->login_window->bg_color = self->grey;
|
||||
self->login_window->left = self->screen->width / 2 -
|
||||
self->login_window->width / 2;
|
||||
self->login_window->top = self->screen->height / 2 -
|
||||
self->login_window->height / 2;
|
||||
self->login_window->notify = xrdp_wm_login_notify;
|
||||
|
||||
/* image */
|
||||
but = xrdp_bitmap_create(4, 4, self->screen->bpp, 4);
|
||||
xrdp_bitmap_load(but, "xrdp256.bmp", self->palette);
|
||||
but->parent = self->screen;
|
||||
but->owner = self->screen;
|
||||
but->wm = self;
|
||||
but->left = self->screen->width - but->width;
|
||||
but->top = self->screen->height - but->height;
|
||||
xrdp_list_add_item(self->screen->child_list, (int)but);
|
||||
|
||||
/* image */
|
||||
but = xrdp_bitmap_create(4, 4, self->screen->bpp, 4);
|
||||
xrdp_bitmap_load(but, "ad256.bmp", self->palette);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 10;
|
||||
but->top = 30;
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
|
||||
but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 320;
|
||||
but->top = 160;
|
||||
but->id = 1;
|
||||
|
||||
but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 250;
|
||||
but->top = 160;
|
||||
but->id = 2;
|
||||
|
||||
but = xrdp_bitmap_create(60, 25, self->screen->bpp, 3);
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 180;
|
||||
but->top = 160;
|
||||
but->id = 3;
|
||||
|
||||
but = xrdp_bitmap_create(140, 20, self->screen->bpp, 5);
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 220;
|
||||
but->top = 50;
|
||||
but->id = 4;
|
||||
but->cursor = 1;
|
||||
|
||||
but = xrdp_bitmap_create(140, 20, self->screen->bpp, 5);
|
||||
xrdp_list_add_item(self->login_window->child_list, (int)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->wm = self;
|
||||
but->left = 220;
|
||||
but->top = 80;
|
||||
but->id = 5;
|
||||
but->cursor = 1;
|
||||
|
||||
/* clear screen */
|
||||
self->screen->bg_color = self->black;
|
||||
xrdp_bitmap_invalidate(self->screen, 0);
|
||||
|
||||
xrdp_wm_set_focused(self, self->login_window);
|
||||
|
||||
xrdp_send_cursor(self, "cursor1.cur", 1);
|
||||
xrdp_send_cursor(self, "cursor0.cur", 0);
|
||||
|
||||
//xrdp_set_cursor(self, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns the number for rects visible for an area relative to a drawable */
|
||||
/* putting the rects in region */
|
||||
int xrdp_wm_get_vis_region(struct xrdp_wm* self, struct xrdp_bitmap* bitmap,
|
||||
int x, int y, int cx, int cy,
|
||||
struct xrdp_region* region)
|
||||
{
|
||||
int i;
|
||||
struct xrdp_bitmap* p;
|
||||
struct xrdp_rect a;
|
||||
struct xrdp_rect b;
|
||||
|
||||
/* area we are drawing */
|
||||
xrdp_wm_rect(&a, bitmap->left + x, bitmap->top + y, cx, cy);
|
||||
|
||||
p = bitmap->parent;
|
||||
while (p != 0)
|
||||
{
|
||||
xrdp_wm_rect_offset(&a, p->left, p->top);
|
||||
p = p->parent;
|
||||
}
|
||||
|
||||
xrdp_region_add_rect(region, &a);
|
||||
|
||||
if (bitmap == self->screen)
|
||||
return 0;
|
||||
|
||||
/* loop through all windows in z order */
|
||||
for (i = 0; i < self->screen->child_list->count; i++)
|
||||
{
|
||||
p = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i);
|
||||
if (p == bitmap || p == bitmap->parent)
|
||||
return 0;
|
||||
xrdp_wm_rect(&b, p->left, p->top, p->width, p->height);
|
||||
xrdp_region_subtract_rect(region, &b);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* return the window at x, y on the screen */
|
||||
struct xrdp_bitmap* xrdp_wm_at_pos(struct xrdp_bitmap* wnd, int x, int y,
|
||||
struct xrdp_bitmap** wnd1)
|
||||
{
|
||||
int i;
|
||||
struct xrdp_bitmap* p;
|
||||
struct xrdp_bitmap* q;
|
||||
|
||||
/* loop through all windows in z order */
|
||||
for (i = 0; i < wnd->child_list->count; i++)
|
||||
{
|
||||
p = (struct xrdp_bitmap*)xrdp_list_get_item(wnd->child_list, i);
|
||||
if (x >= p->left && y >= p->top && x < p->left + p->width &&
|
||||
y < p->top + p->height)
|
||||
{
|
||||
if (wnd1 != 0)
|
||||
*wnd1 = p;
|
||||
q = xrdp_wm_at_pos(p, x - p->left, y - p->top, 0);
|
||||
if (q == 0)
|
||||
return p;
|
||||
else
|
||||
return q;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_xor_pat(struct xrdp_wm* self, int x, int y, int cx, int cy)
|
||||
{
|
||||
self->painter->rop = 0x5a;
|
||||
xrdp_painter_begin_update(self->painter);
|
||||
self->painter->use_clip = 0;
|
||||
self->painter->brush.pattern[0] = 0xaa;
|
||||
self->painter->brush.pattern[1] = 0x55;
|
||||
self->painter->brush.pattern[2] = 0xaa;
|
||||
self->painter->brush.pattern[3] = 0x55;
|
||||
self->painter->brush.pattern[4] = 0xaa;
|
||||
self->painter->brush.pattern[5] = 0x55;
|
||||
self->painter->brush.pattern[6] = 0xaa;
|
||||
self->painter->brush.pattern[7] = 0x55;
|
||||
self->painter->brush.x_orgin = 0;
|
||||
self->painter->brush.x_orgin = 0;
|
||||
self->painter->brush.style = 3;
|
||||
self->painter->bg_color = self->black;
|
||||
self->painter->fg_color = self->white;
|
||||
/* top */
|
||||
xrdp_painter_fill_rect2(self->painter, self->screen, x, y, cx, 5);
|
||||
/* bottom */
|
||||
xrdp_painter_fill_rect2(self->painter, self->screen, x, y + (cy - 5), cx, 5);
|
||||
/* left */
|
||||
xrdp_painter_fill_rect2(self->painter, self->screen, x, y + 5, 5, cy - 10);
|
||||
/* right */
|
||||
xrdp_painter_fill_rect2(self->painter, self->screen, x + (cx - 5), y + 5, 5,
|
||||
cy - 10);
|
||||
xrdp_painter_end_update(self->painter);
|
||||
self->painter->rop = 0xcc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* this don't are about nothing, just copy the bits */
|
||||
/* no clipping rects, no windows in the way, nothing */
|
||||
int xrdp_wm_bitblt(struct xrdp_wm* self,
|
||||
struct xrdp_bitmap* dst, int dx, int dy,
|
||||
struct xrdp_bitmap* src, int sx, int sy,
|
||||
int sw, int sh, int rop)
|
||||
{
|
||||
// int i;
|
||||
// int line_size;
|
||||
// int Bpp;
|
||||
// char* s;
|
||||
// char* d;
|
||||
|
||||
// if (sw <= 0 || sh <= 0)
|
||||
// return 0;
|
||||
if (self->screen == dst && self->screen == src)
|
||||
{ /* send a screen blt */
|
||||
// Bpp = (dst->bpp + 7) / 8;
|
||||
// line_size = sw * Bpp;
|
||||
// s = src->data + (sy * src->width + sx) * Bpp;
|
||||
// d = dst->data + (dy * dst->width + dx) * Bpp;
|
||||
// for (i = 0; i < sh; i++)
|
||||
// {
|
||||
// //g_memcpy(d, s, line_size);
|
||||
// s += src->width * Bpp;
|
||||
// d += dst->width * Bpp;
|
||||
// }
|
||||
xrdp_orders_init(self->orders);
|
||||
xrdp_orders_screen_blt(self->orders, dx, dy, sw, sh, sx, sy, rop, 0);
|
||||
xrdp_orders_send(self->orders);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* return true is rect is totaly exposed going in reverse z order */
|
||||
/* from wnd up */
|
||||
int xrdp_wm_is_rect_vis(struct xrdp_wm* self, struct xrdp_bitmap* wnd,
|
||||
struct xrdp_rect* rect)
|
||||
{
|
||||
struct xrdp_rect rect1;
|
||||
struct xrdp_rect rect2;
|
||||
struct xrdp_bitmap* b;
|
||||
int i;;
|
||||
|
||||
/* if rect is part off screen */
|
||||
if (rect->left < 0)
|
||||
return 0;
|
||||
if (rect->top < 0)
|
||||
return 0;
|
||||
if (rect->right >= self->screen->width)
|
||||
return 0;
|
||||
if (rect->bottom >= self->screen->height)
|
||||
return 0;
|
||||
|
||||
i = xrdp_list_index_of(self->screen->child_list, (int)wnd);
|
||||
i--;
|
||||
while (i >= 0)
|
||||
{
|
||||
b = (struct xrdp_bitmap*)xrdp_list_get_item(self->screen->child_list, i);
|
||||
xrdp_wm_rect(&rect1, b->left, b->top, b->width, b->height);
|
||||
if (xrdp_wm_rect_intersect(rect, &rect1, &rect2))
|
||||
return 0;
|
||||
i--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_move_window(struct xrdp_wm* self, struct xrdp_bitmap* wnd,
|
||||
int dx, int dy)
|
||||
{
|
||||
struct xrdp_rect rect1;
|
||||
struct xrdp_rect rect2;
|
||||
struct xrdp_region* r;
|
||||
int i;
|
||||
|
||||
xrdp_wm_rect(&rect1, wnd->left, wnd->top, wnd->width, wnd->height);
|
||||
if (xrdp_wm_is_rect_vis(self, wnd, &rect1))
|
||||
{
|
||||
rect2 = rect1;
|
||||
xrdp_wm_rect_offset(&rect2, dx, dy);
|
||||
if (xrdp_wm_is_rect_vis(self, wnd, &rect2))
|
||||
{ /* if both src and dst are unobscured, we can do a bitblt move */
|
||||
xrdp_wm_bitblt(self, self->screen, wnd->left + dx, wnd->top + dy,
|
||||
self->screen, wnd->left, wnd->top,
|
||||
wnd->width, wnd->height, 0xcc);
|
||||
wnd->left += dx;
|
||||
wnd->top += dy;
|
||||
r = xrdp_region_create(self);
|
||||
xrdp_region_add_rect(r, &rect1);
|
||||
xrdp_region_subtract_rect(r, &rect2);
|
||||
i = 0;
|
||||
while (xrdp_region_get_rect(r, i, &rect1) == 0)
|
||||
{
|
||||
xrdp_bitmap_invalidate(self->screen, &rect1);
|
||||
i++;
|
||||
}
|
||||
xrdp_region_delete(r);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
wnd->left += dx;
|
||||
wnd->top += dy;
|
||||
xrdp_bitmap_invalidate(self->screen, &rect1);
|
||||
xrdp_bitmap_invalidate(wnd, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_rect(struct xrdp_rect* r, int x, int y, int cx, int cy)
|
||||
{
|
||||
r->left = x;
|
||||
r->top = y;
|
||||
r->right = x + cx;
|
||||
r->bottom = y + cy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_rect_is_empty(struct xrdp_rect* in)
|
||||
{
|
||||
return (in->right <= in->left) || (in->bottom <= in->top);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_rect_contains_pt(struct xrdp_rect* in, int x, int y)
|
||||
{
|
||||
if (x < in->left)
|
||||
return 0;
|
||||
if (y < in->top)
|
||||
return 0;
|
||||
if (x >= in->right)
|
||||
return 0;
|
||||
if (y >= in->bottom)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_rect_intersect(struct xrdp_rect* in1, struct xrdp_rect* in2,
|
||||
struct xrdp_rect* out)
|
||||
{
|
||||
int rv;
|
||||
|
||||
*out = *in1;
|
||||
if (in2->left > in1->left)
|
||||
out->left = in2->left;
|
||||
if (in2->top > in1->top)
|
||||
out->top = in2->top;
|
||||
if (in2->right < in1->right)
|
||||
out->right = in2->right;
|
||||
if (in2->bottom < in1->bottom)
|
||||
out->bottom = in2->bottom;
|
||||
rv = !xrdp_wm_rect_is_empty(out);
|
||||
if (!rv)
|
||||
g_memset(out, 0, sizeof(struct xrdp_rect));
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_rect_offset(struct xrdp_rect* in, int dx, int dy)
|
||||
{
|
||||
in->left += dx;
|
||||
in->right += dx;
|
||||
in->top += dy;
|
||||
in->bottom += dy;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_mouse_move(struct xrdp_wm* self, int x, int y)
|
||||
{
|
||||
struct xrdp_bitmap* b;
|
||||
int boxx;
|
||||
int boxy;
|
||||
|
||||
DEBUG(("in mouse move\n\r"));
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (x >= self->screen->width)
|
||||
x = self->screen->width;
|
||||
if (y >= self->screen->height)
|
||||
y = self->screen->height;
|
||||
if (self->dragging)
|
||||
{
|
||||
xrdp_painter_begin_update(self->painter);
|
||||
boxx = self->draggingx - self->draggingdx;
|
||||
boxy = self->draggingy - self->draggingdy;
|
||||
xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
|
||||
self->draggingx = x;
|
||||
self->draggingy = y;
|
||||
boxx = self->draggingx - self->draggingdx;
|
||||
boxy = self->draggingy - self->draggingdy;
|
||||
xrdp_wm_xor_pat(self, boxx, boxy, self->draggingcx, self->draggingcy);
|
||||
xrdp_painter_end_update(self->painter);
|
||||
}
|
||||
b = xrdp_wm_at_pos(self->screen, x, y, 0);
|
||||
if (self->button_down != 0)
|
||||
{
|
||||
if (b == self->button_down && self->button_down->state == 0)
|
||||
{
|
||||
self->button_down->state = 1;
|
||||
xrdp_bitmap_invalidate(self->button_down, 0);
|
||||
}
|
||||
else if (b != self->button_down)
|
||||
{
|
||||
self->button_down->state = 0;
|
||||
xrdp_bitmap_invalidate(self->button_down, 0);
|
||||
}
|
||||
}
|
||||
if (b != 0)
|
||||
{
|
||||
if (!self->dragging)
|
||||
{
|
||||
if (b->cursor != self->current_cursor)
|
||||
{
|
||||
xrdp_set_cursor(self, b->cursor);
|
||||
self->current_cursor = b->cursor;
|
||||
}
|
||||
if (self->button_down == 0)
|
||||
if (b->notify != 0)
|
||||
b->notify(b->owner, b, 2, x, y);
|
||||
}
|
||||
}
|
||||
DEBUG(("out mouse move\n\r"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int xrdp_wm_mouse_click(struct xrdp_wm* self, int x, int y, int but, int down)
|
||||
{
|
||||
struct xrdp_bitmap* b;
|
||||
struct xrdp_bitmap* b1;
|
||||
int newx;
|
||||
int newy;
|
||||
int oldx;
|
||||
int oldy;
|
||||
|
||||
if (self == 0)
|
||||
return 0;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (x >= self->screen->width)
|
||||
x = self->screen->width;
|
||||
if (y >= self->screen->height)
|
||||
y = self->screen->height;
|
||||
if (self->dragging && but == 1 && !down && self->dragging_window != 0)
|
||||
{ /* if done dragging */
|
||||
self->draggingx = x;
|
||||
self->draggingy = y;
|
||||
newx = self->draggingx - self->draggingdx;
|
||||
newy = self->draggingy - self->draggingdy;
|
||||
oldx = self->dragging_window->left;
|
||||
oldy = self->dragging_window->top;
|
||||
/* draw xor box one more time */
|
||||
xrdp_wm_xor_pat(self, newx, newy, self->draggingcx, self->draggingcy);
|
||||
/* move screen to new location */
|
||||
xrdp_wm_move_window(self, self->dragging_window, newx - oldx, newy - oldy);
|
||||
self->dragging_window = 0;
|
||||
self->dragging = 0;
|
||||
}
|
||||
b = xrdp_wm_at_pos(self->screen, x, y, &b1);
|
||||
if (b != 0)
|
||||
{
|
||||
if (b->type == 3 && but == 1 && !down && self->button_down == b)
|
||||
{ /* if clicking up on a button that was clicked down */
|
||||
self->button_down = 0;
|
||||
b->state = 0;
|
||||
xrdp_bitmap_invalidate(b, 0);
|
||||
if (b->parent != 0)
|
||||
if (b->parent->notify != 0)
|
||||
/* b can be invalid after this */
|
||||
b->parent->notify(b->owner, b, 1, x, y);
|
||||
}
|
||||
else if (b->type == 3 && but == 1 && down)
|
||||
{ /* if clicking down on a button */
|
||||
self->button_down = b;
|
||||
b->state = 1;
|
||||
xrdp_bitmap_invalidate(b, 0);
|
||||
}
|
||||
else if (but == 1 && down)
|
||||
{
|
||||
xrdp_wm_set_focused(self, b1);
|
||||
if (b->type == 1 && y < (b->top + 21))
|
||||
{ /* if dragging */
|
||||
if (self->dragging) /* rarely happens */
|
||||
{
|
||||
newx = self->draggingx - self->draggingdx;
|
||||
newy = self->draggingy - self->draggingdy;
|
||||
xrdp_wm_xor_pat(self, newx, newy, self->draggingcx,
|
||||
self->draggingcy);
|
||||
}
|
||||
self->dragging = 1;
|
||||
self->dragging_window = b;
|
||||
self->draggingorgx = b->left;
|
||||
self->draggingorgy = b->top;
|
||||
self->draggingx = x;
|
||||
self->draggingy = y;
|
||||
self->draggingdx = x - b->left;
|
||||
self->draggingdy = y - b->top;
|
||||
self->draggingcx = b->width;
|
||||
self->draggingcy = b->height;
|
||||
newx = self->draggingx - self->draggingdx;
|
||||
newy = self->draggingy - self->draggingdy;
|
||||
xrdp_wm_xor_pat(self, newx, newy, self->draggingcx, self->draggingcy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
xrdp_wm_set_focused(self, 0);
|
||||
|
||||
/* no matter what, mouse is up, reset button_down */
|
||||
if (but == 1 && !down && self->button_down != 0)
|
||||
self->button_down = 0;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue