Fix shaped windows on Windows. It uses regions.

Advantages:
 * it is the simplest method to implement

Disadvantages:
 * it's slow
 * it does not take into account transparency
 * it does not work with the composite manager (Windows >= Vista)

Layered windows should be used (all the disadvantaged above are
fixed), but i've never succeeded in making them work.

SVN revision: 52416
This commit is contained in:
Vincent Torri 2010-09-18 17:19:11 +00:00
parent 6f4d152810
commit 9acfb01811
5 changed files with 192 additions and 55 deletions

View File

@ -17,11 +17,11 @@ struct _Evas_Engine_Info_Software_Gdi
struct {
HWND window;
HBITMAP mask;
int depth;
int rotation;
unsigned int layered : 1;
unsigned int borderless : 1;
unsigned int fullscreen : 1;
unsigned int region : 1;
} info;
/* non-blocking or blocking mode */

View File

@ -25,10 +25,10 @@ _output_setup(int width,
int height,
int rot,
HWND window,
HBITMAP mask,
int depth,
unsigned int layered,
unsigned int fullscreen)
unsigned int borderless,
unsigned int fullscreen,
unsigned int region)
{
Render_Engine *re;
@ -59,7 +59,7 @@ _output_setup(int width,
re->ob = evas_software_gdi_outbuf_setup(width, height, rot,
OUTBUF_DEPTH_INHERIT,
window, mask, depth, layered, fullscreen,
window, depth, borderless, fullscreen, region,
0, 0);
if (!re->ob)
{
@ -122,10 +122,10 @@ eng_setup(Evas *e, void *in)
e->output.h,
info->info.rotation,
info->info.window,
info->info.mask,
info->info.depth,
info->info.layered,
info->info.fullscreen);
info->info.borderless,
info->info.fullscreen,
info->info.region);
else
{
int ponebuf = 0;
@ -138,10 +138,10 @@ eng_setup(Evas *e, void *in)
info->info.rotation,
OUTBUF_DEPTH_INHERIT,
info->info.window,
info->info.mask,
info->info.depth,
info->info.layered,
info->info.borderless,
info->info.fullscreen,
info->info.region,
0, 0);
re->ob->onebuf = ponebuf;
}
@ -176,6 +176,7 @@ eng_output_resize(void *data, int width, int height)
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
evas_software_gdi_outbuf_reconfigure(re->ob,
width,
@ -202,6 +203,7 @@ eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
}
@ -211,6 +213,7 @@ eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
}
@ -243,6 +246,7 @@ eng_output_redraws_next_update_get(void *data,
int uw;
int uh;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
if (re->end)
{
@ -291,6 +295,7 @@ eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
#ifdef BUILD_PIPE_RENDER
evas_common_pipe_map4_begin(surface);
@ -305,6 +310,7 @@ eng_output_flush(void *data)
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
evas_software_gdi_outbuf_flush(re->ob);
}
@ -314,6 +320,7 @@ eng_output_idle_flush(void *data)
{
Render_Engine *re;
printf ("%s\n", __FUNCTION__);
re = (Render_Engine *)data;
evas_software_gdi_outbuf_idle_flush(re->ob);
}

View File

@ -68,11 +68,11 @@ struct _Outbuf
struct {
BITMAPINFO_GDI *bitmap_info;
HWND window;
HBITMAP mask;
HDC dc;
int depth;
unsigned char layered : 1;
unsigned char borderless : 1;
unsigned char fullscreen : 1;
unsigned char region : 1;
} gdi;
/* 1 big buffer for updates - flush on idle_flush */
@ -88,6 +88,8 @@ struct _Outbuf
unsigned char destination_alpha : 1;
unsigned char debug : 1;
unsigned char synced : 1;
unsigned char region_built : 1;
} priv;
};
@ -116,10 +118,10 @@ struct _Gdi_Output_Buffer
/* evas_gdi_main.c */
int evas_software_gdi_init (HWND window,
HBITMAP mask,
int depth,
unsigned int layered,
unsigned int borderless,
unsigned int fullscreen,
unsigned int region,
Outbuf *buf);
void evas_software_gdi_shutdown(Outbuf *buf);
@ -157,10 +159,10 @@ Outbuf *evas_software_gdi_outbuf_setup(int width,
int rotation,
Outbuf_Depth depth,
HWND window,
HBITMAP mask,
int w_depth,
unsigned int layered,
unsigned int borderless,
unsigned int fullscreen,
unsigned int region,
int mask_dither,
int destination_alpha);

View File

@ -4,15 +4,12 @@
int
evas_software_gdi_init (HWND window,
HBITMAP mask,
int depth,
unsigned int layered,
unsigned int borderless,
unsigned int fullscreen __UNUSED__,
unsigned int region,
Outbuf *buf)
{
RECT window_rect;
SIZE mask_size;
if (!window)
{
ERR("[Engine] [GDI] Window is NULL");
@ -20,8 +17,9 @@ evas_software_gdi_init (HWND window,
}
buf->priv.gdi.window = window;
buf->priv.gdi.mask = mask;
buf->priv.gdi.dc = GetDC(window);
buf->priv.gdi.borderless = borderless;
buf->priv.gdi.region = region;
if (!buf->priv.gdi.dc)
{
ERR("[Engine] [GDI] Can not get DC");
@ -37,22 +35,6 @@ evas_software_gdi_init (HWND window,
}
buf->priv.gdi.depth = depth;
/* mask */
if (layered && mask)
{
if (GetBitmapDimensionEx(mask, &mask_size) &&
GetClientRect(window, &window_rect))
{
if ((mask_size.cx == window_rect.right) &&
(mask_size.cy == window_rect.bottom))
{
/* if (SetLayeredWindowAttributes(window, RGB(0, 0, 0), 255, LWA_COLORKEY)) */
/* { */
/* } */
}
}
}
/* FIXME: support fullscreen */
buf->priv.gdi.bitmap_info = (BITMAPINFO_GDI *)malloc(sizeof(BITMAPINFO_GDI));

View File

@ -10,8 +10,8 @@ static int gdicountlimit = 32;
static Gdi_Output_Buffer *
_find_gdiob(HDC dc, BITMAPINFO_GDI *bitmap_info, int depth, int w, int h, void *data)
{
Eina_List *l;
Eina_List *gdil;
Eina_List *l = NULL;
Eina_List *gdil = NULL;
Gdi_Output_Buffer *gdiob = NULL;
Gdi_Output_Buffer *gdiob2;
int sz;
@ -132,10 +132,10 @@ evas_software_gdi_outbuf_setup(int width,
int rotation,
Outbuf_Depth depth,
HWND window,
HBITMAP mask,
int w_depth,
unsigned int layered,
unsigned int borderless,
unsigned int fullscreen,
unsigned int region,
int mask_dither,
int destination_alpha)
{
@ -153,7 +153,7 @@ evas_software_gdi_outbuf_setup(int width,
buf->priv.mask_dither = mask_dither;
buf->priv.destination_alpha = destination_alpha;
if (!evas_software_gdi_init(window, mask, w_depth, layered, fullscreen, buf))
if (!evas_software_gdi_init(window, w_depth, borderless, fullscreen, region, buf))
{
free(buf);
return NULL;
@ -205,8 +205,6 @@ evas_software_gdi_outbuf_setup(int width,
buf->priv.gdi.bitmap_info->masks[2]);
}
}
if (buf->priv.gdi.mask != mask)
buf->priv.gdi.mask = mask;
}
return buf;
@ -226,6 +224,7 @@ evas_software_gdi_outbuf_reconfigure(Outbuf *buf,
buf->height = height;
buf->rot = rotation;
evas_software_gdi_bitmap_resize(buf);
buf->priv.region_built = 0;
}
RGBA_Image *
@ -254,7 +253,7 @@ evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
*cw = w;
*ch = h;
alpha = ((buf->priv.gdi.mask) || (buf->priv.destination_alpha));
alpha = ((buf->priv.gdi.region) || (buf->priv.destination_alpha));
if ((buf->rot == 0) &&
(buf->priv.gdi.bitmap_info->masks[0] == 0xff0000) &&
@ -319,7 +318,7 @@ evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
/* 1, */
/* w, h, NULL); */
}
if ((buf->priv.gdi.mask) || (buf->priv.destination_alpha))
if ((buf->priv.gdi.region) || (buf->priv.destination_alpha))
/* FIXME: faster memset! */
memset(im->image.data, 0, w * h * sizeof(DATA32));
@ -335,6 +334,7 @@ evas_software_gdi_outbuf_push_updated_region(Outbuf *buf,
int w,
int h)
{
HRGN regions = NULL;
Gfx_Func_Convert conv_func;
Outbuf_Region *obr;
DATA32 *src_data;
@ -404,13 +404,159 @@ evas_software_gdi_outbuf_push_updated_region(Outbuf *buf,
x,
y,
NULL);
/* if (obr->mxob) */
/* { */
/* int yy; */
/* for (yy = 0; yy < obr->h; yy++) */
/* evas_software_xlib_x_write_mask_line(buf, obr->mxob, */
/* src_data + */
/* (yy * obr->w), obr->w, yy); */
/* Region code */
if (!buf->priv.gdi.region)
{
if (regions)
DeleteObject(regions);
SetWindowRgn(buf->priv.gdi.window, NULL, 1);
return;
}
if (!buf->priv.region_built)
{
RECT rect;
POINT pt = { 0, 0 };
HRGN region;
int *tmp;
int i;
int j;
int ww;
int wh;
int dx;
int dy;
int xmin;
int xmax;
if (!GetClientRect(buf->priv.gdi.window, &rect))
return;
ww = rect.right - rect.left;
wh = rect.bottom - rect.top;
printf ("(%d,%d) (%d,%d)\n", w, h, ww, wh);
if (!GetWindowRect(buf->priv.gdi.window, &rect))
return;
if (!ClientToScreen(buf->priv.gdi.window, &pt))
return;
dx = x + pt.x - rect.left;
dy = y + pt.y - rect.top;
tmp = src_data;
for (j = 0; j < h; j++)
{
i = 0;
while (i < w)
{
if ((*tmp & 0xff000000) == 0xff000000)
{
xmin = dx + i;
if ((i + 1) == w)
{
xmax = dx + i;
region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
if (regions == NULL)
regions = region;
else
{
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
}
}
else
{
i++;
tmp++;
while (i < w)
{
if ((*tmp & 0xff000000) == 0xff000000)
{
if ((i + 1) == w)
{
xmax = dx + i;
region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
if (regions == NULL)
regions = region;
else
{
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
}
break;
}
}
else
{
xmax = dx + i - 1;
region = CreateRectRgn(xmin, dy + j, xmax + 1, dy + j + 1);
if (regions == NULL)
regions = region;
else
{
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
}
break;
}
i++;
tmp++;
}
}
}
i++;
tmp++;
}
}
if (!buf->priv.gdi.borderless)
{
RECT rnc;
RECT rc;
POINT pt = { 0, 0 };
LONG ncw;
LONG nch;
LONG cw;
LONG ch;
if (!GetWindowRect(buf->priv.gdi.window, &rnc))
return;
if (!GetClientRect(buf->priv.gdi.window, &rc))
return;
if (!ClientToScreen(buf->priv.gdi.window, &pt))
return;
ncw = rnc.right - rnc.left;
nch = rnc.bottom - rnc.top;
cw = rc.right - rc.left;
ch = rc.bottom - rc.top;
region = CreateRectRgn(0, 0, ncw, pt.y - rnc.top);
if (!regions)
regions = region;
else
{
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
}
region = CreateRectRgn(0, pt.y - rnc.top, pt.x - rnc.left, nch);
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
region = CreateRectRgn(pt.x - rnc.left, pt.y - rnc.top + ch, pt.x - rnc.left + cw, nch);
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
region = CreateRectRgn(pt.x - rnc.left + cw, pt.y - rnc.top, ncw, nch);
CombineRgn(regions, regions, region, RGN_OR);
DeleteObject(region);
}
if (regions)
SetWindowRgn(buf->priv.gdi.window, regions, 1);
buf->priv.region_built = 1;
}
}
void