CVS: rdesktop seamless.c,NONE,1.1.2.1 seamless.h,NONE,1.1.2.1 Makefile.in,1.13,1.13.2.1 channels.c,1.15,1.15.2.1 constants.h,1.45,1.45.2.1 proto.h,1.87,1.87.2.1 rdesktop.c,1.144,1.144.2.1 xkeymap.c,1.88,1.88.2.1 xwin.c,1.205,1.205.2.1
Peter Ã
strand <[email protected]>
| Newsgroups | gmane.network.rdesktop.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/rdesktop/rdesktop
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22293
Modified Files:
Tag: seamlessrdp-branch
Makefile.in channels.c constants.h proto.h rdesktop.c
xkeymap.c xwin.c
Added Files:
Tag: seamlessrdp-branch
seamless.c seamless.h
Log Message:
Initial support for SeamlessRDP
--- NEW FILE: seamless.c ---
/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Seamless Windows support
Copyright (C) Peter Astrand <[email protected]> 2005-2006
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.
*/
#include "rdesktop.h"
/* #define WITH_DEBUG_SEAMLESS */
#ifdef WITH_DEBUG_SEAMLESS
#define DEBUG_SEAMLESS(args) printf args;
#else
#define DEBUG_SEAMLESS(args)
#endif
extern BOOL g_seamless_rdp;
static VCHANNEL *seamless_channel;
static char *
seamless_get_token(char **s)
{
char *comma, *head;
head = *s;
if (!head)
return NULL;
comma = strchr(head, ',');
if (comma)
{
*comma = '\0';
*s = comma + 1;
}
else
{
*s = NULL;
}
return head;
}
static BOOL
seamless_process_line(const char *line, void *data)
{
char *p, *l;
char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
unsigned long id, flags;
char *endptr;
l = xstrdup(line);
p = l;
DEBUG_SEAMLESS(("seamlessrdp line:%s\n", p));
if (!g_seamless_rdp)
return True;
tok1 = seamless_get_token(&p);
tok2 = seamless_get_token(&p);
tok3 = seamless_get_token(&p);
tok4 = seamless_get_token(&p);
tok5 = seamless_get_token(&p);
tok6 = seamless_get_token(&p);
tok7 = seamless_get_token(&p);
tok8 = seamless_get_token(&p);
if (!strcmp("CREATE1", tok1))
{
if (!tok3)
return False;
id = strtol(tok2, &endptr, 16);
if (*endptr)
return False;
flags = strtol(tok3, &endptr, 16);
if (*endptr)
return False;
ui_seamless_create_window(id, flags);
}
else if (!strcmp("DESTROY1", tok1))
{
if (!tok3)
return False;
id = strtol(tok2, &endptr, 16);
if (*endptr)
return False;
flags = strtol(tok3, &endptr, 16);
if (*endptr)
return False;
ui_seamless_destroy_window(id, flags);
}
else if (!strcmp("SETICON1", tok1))
{
unimpl("SeamlessRDP SETICON1\n");
}
else if (!strcmp("POSITION1", tok1))
{
int x, y, width, height;
if (!tok7)
return False;
id = strtol(tok2, &endptr, 16);
if (*endptr)
return False;
x = strtol(tok3, &endptr, 10);
if (*endptr)
return False;
y = strtol(tok4, &endptr, 10);
if (*endptr)
return False;
width = strtol(tok5, &endptr, 10);
if (*endptr)
return False;
height = strtol(tok6, &endptr, 10);
if (*endptr)
return False;
flags = strtol(tok7, &endptr, 16);
if (*endptr)
return False;
ui_seamless_move_window(id, x, y, width, height, flags);
}
else if (!strcmp("ZCHANGE1", tok1))
{
unimpl("SeamlessRDP ZCHANGE1\n");
}
else if (!strcmp("SETSTATE1", tok1))
{
unsigned int state;
if (!tok5)
return False;
id = strtol(tok2, &endptr, 16);
if (*endptr)
return False;
state = strtol(tok4, &endptr, 16); // XXX
if (*endptr)
return False;
flags = strtol(tok5, &endptr, 16);
if (*endptr)
return False;
/* FIXME */
ui_seamless_settitle(id, tok3);
ui_seamless_setstate(id, state, flags);
}
else if (!strcmp("DEBUG1", tok1))
{
printf("SeamlessRDP:%s\n", line);
}
xfree(l);
return True;
}
static BOOL
seamless_line_handler(const char *line, void *data)
{
if (!seamless_process_line(line, data))
{
warning("SeamlessRDP: Invalid request:%s\n", line);
}
return True;
}
static void
seamless_process(STREAM s)
{
unsigned int pkglen;
static char *rest = NULL;
char *buf;
pkglen = s->end - s->p;
/* str_handle_lines requires null terminated strings */
buf = xmalloc(pkglen + 1);
STRNCPY(buf, (char *) s->p, pkglen + 1);
#if 0
printf("seamless recv:\n");
hexdump(s->p, pkglen);
#endif
str_handle_lines(buf, &rest, seamless_line_handler, NULL);
xfree(buf);
}
BOOL
seamless_init(void)
{
seamless_channel =
channel_register("seamrdp", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
seamless_process);
return (seamless_channel != NULL);
}
static void
seamless_send(const char *output)
{
STREAM s;
size_t len;
len = strlen(output);
s = channel_init(seamless_channel, len);
out_uint8p(s, output, len) s_mark_end(s);
#if 0
printf("seamless send:\n");
hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
#endif
channel_send(s, seamless_channel);
}
void
seamless_send_sync()
{
seamless_send("SYNC\n");
}
--- NEW FILE: seamless.h ---
/*
rdesktop: A Remote Desktop Protocol client.
Seamless Windows support
Copyright (C) Peter Astrand <[email protected]> 2005-2006
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.
*/
Index: Makefile.in
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/Makefile.in,v
retrieving revision 1.13
retrieving revision 1.13.2.1
diff -C2 -d -r1.13 -r1.13.2.1
*** Makefile.in 2 Mar 2006 15:22:25 -0000 1.13
--- Makefile.in 10 Mar 2006 08:50:43 -0000 1.13.2.1
***************
*** 26,30 ****
SOUNDOBJ = @SOUNDOBJ@
! RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o lspci.o
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
--- 26,30 ----
SOUNDOBJ = @SOUNDOBJ@
! RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o lspci.o seamless.o
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
***************
*** 83,87 ****
iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c rdpsnd_oss.c \
! secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c >> proto.h
cat proto.tail >> proto.h
--- 83,87 ----
iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c rdpsnd_oss.c \
! secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c seamless.c >> proto.h
cat proto.tail >> proto.h
Index: channels.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/channels.c,v
retrieving revision 1.15
retrieving revision 1.15.2.1
diff -C2 -d -r1.15 -r1.15.2.1
*** channels.c 2 Mar 2006 15:22:25 -0000 1.15
--- channels.c 10 Mar 2006 08:50:43 -0000 1.15.2.1
***************
*** 22,26 ****
#include "rdesktop.h"
! #define MAX_CHANNELS 5
#define CHANNEL_CHUNK_LENGTH 1600
#define CHANNEL_FLAG_FIRST 0x01
--- 22,26 ----
#include "rdesktop.h"
! #define MAX_CHANNELS 6
#define CHANNEL_CHUNK_LENGTH 1600
#define CHANNEL_FLAG_FIRST 0x01
Index: constants.h
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/constants.h,v
retrieving revision 1.45
retrieving revision 1.45.2.1
diff -C2 -d -r1.45 -r1.45.2.1
*** constants.h 8 Aug 2005 19:15:53 -0000 1.45
--- constants.h 10 Mar 2006 08:50:43 -0000 1.45.2.1
***************
*** 413,414 ****
--- 413,419 ----
#define exDiscReasonLicenseCantUpgradeLicense 0x0109
#define exDiscReasonLicenseNoRemoteConnections 0x010a
+
+ /* SeamlessRDP constants */
+ #define SEAMLESSRDP_NORMAL 0
+ #define SEAMLESSRDP_MINIMIZED 1
+ #define SEAMLESSRDP_MAXIMIZED 2
Index: proto.h
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/proto.h,v
retrieving revision 1.87
retrieving revision 1.87.2.1
diff -C2 -d -r1.87 -r1.87.2.1
*** proto.h 2 Mar 2006 15:22:25 -0000 1.87
--- proto.h 10 Mar 2006 08:50:43 -0000 1.87.2.1
***************
*** 272,277 ****
--- 272,287 ----
void ui_begin_update(void);
void ui_end_update(void);
+ void ui_seamless_toggle(void);
+ void ui_seamless_create_window(unsigned long id, unsigned long flags);
+ void ui_seamless_destroy_window(unsigned long id, unsigned long flags);
+ void ui_seamless_move_window(unsigned long id, int x, int y, int width, int height,
+ unsigned long flags);
+ void ui_seamless_settitle(unsigned long id, const char *title);
+ void ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags);
/* lspci.c */
BOOL lspci_init(void);
+ /* seamless.c */
+ BOOL seamless_init(void);
+ void seamless_send_sync(void);
/* *INDENT-OFF* */
Index: rdesktop.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/rdesktop.c,v
retrieving revision 1.144
retrieving revision 1.144.2.1
diff -C2 -d -r1.144 -r1.144.2.1
*** rdesktop.c 2 Mar 2006 15:22:25 -0000 1.144
--- rdesktop.c 10 Mar 2006 08:50:43 -0000 1.144.2.1
***************
*** 90,93 ****
--- 90,94 ----
BOOL g_owncolmap = False;
BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */
+ BOOL g_seamless_rdp = False;
uint32 g_embed_wnd;
uint32 g_rdp5_performanceflags =
***************
*** 147,150 ****
--- 148,152 ----
fprintf(stderr, " -L: local codepage\n");
#endif
+ fprintf(stderr, " -A: enable SeamlessRDP mode\n");
fprintf(stderr, " -B: use BackingStore of X-server (if available)\n");
fprintf(stderr, " -e: disable encryption (French TS)\n");
***************
*** 391,394 ****
--- 393,397 ----
char *locale = NULL;
int username_option = 0;
+ BOOL geometry_option = False;
int run_count = 0; /* Session Directory support */
BOOL continue_connect = True; /* Session Directory support */
***************
*** 417,421 ****
while ((c = getopt(argc, argv,
! VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
{
switch (c)
--- 420,424 ----
while ((c = getopt(argc, argv,
! VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
{
switch (c)
***************
*** 435,438 ****
--- 438,445 ----
#endif
+ case 'A':
+ g_seamless_rdp = True;
+ break;
+
case 'u':
STRNCPY(g_username, optarg, sizeof(g_username));
***************
*** 485,488 ****
--- 492,496 ----
case 'g':
+ geometry_option = True;
g_fullscreen = False;
if (!strcmp(optarg, "workarea"))
***************
*** 733,736 ****
--- 741,781 ----
parse_server_and_port(server);
+ if (g_seamless_rdp)
+ {
+ if (g_win_button_size)
+ {
+ error("You cannot use -S and -A at the same time\n");
+ return 1;
+ }
+ g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
+ if (geometry_option)
+ {
+ error("You cannot use -g and -A at the same time\n");
+ return 1;
+ }
+ if (g_fullscreen)
+ {
+ error("You cannot use -f and -A at the same time\n");
+ return 1;
+ }
+ if (g_hide_decorations)
+ {
+ error("You cannot use -D and -A at the same time\n");
+ return 1;
+ }
+ if (g_embed_wnd)
+ {
+ error("You cannot use -X and -A at the same time\n");
+ return 1;
+ }
+ if (!g_use_rdp5)
+ {
+ error("You cannot use -4 and -A at the same time\n");
+ return 1;
+ }
+ g_width = -100;
+ g_grab_keyboard = False;
+ }
+
if (!username_option)
{
Index: xkeymap.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/xkeymap.c,v
retrieving revision 1.88
retrieving revision 1.88.2.1
diff -C2 -d -r1.88 -r1.88.2.1
*** xkeymap.c 30 Dec 2005 20:32:06 -0000 1.88
--- xkeymap.c 10 Mar 2006 08:50:43 -0000 1.88.2.1
***************
*** 590,593 ****
--- 590,598 ----
return True;
break;
+ case XK_Overlay1_Enable:
+ /* Toggle SeamlessRDP */
+ if (pressed)
+ ui_seamless_toggle();
+ break;
}
Index: xwin.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/xwin.c,v
retrieving revision 1.205
retrieving revision 1.205.2.1
diff -C2 -d -r1.205 -r1.205.2.1
*** xwin.c 7 Mar 2006 08:17:40 -0000 1.205
--- xwin.c 10 Mar 2006 08:50:43 -0000 1.205.2.1
***************
*** 49,52 ****
--- 49,65 ----
static Screen *g_screen;
Window g_wnd;
+
+ /* SeamlessRDP support */
+ typedef struct _seamless_window
+ {
+ Window wnd;
+ unsigned long id;
+ int xoffset, yoffset;
+ int width, height;
+ struct _seamless_window *next;
+ } seamless_window;
+ static seamless_window *g_seamless_windows = NULL;
+ extern BOOL g_seamless_rdp;
+
extern uint32 g_embed_wnd;
BOOL g_enable_compose = False;
***************
*** 55,58 ****
--- 68,72 ----
static GC g_create_bitmap_gc = NULL;
static GC g_create_glyph_gc = NULL;
+ static XRectangle g_clip_rectangle;
static Visual *g_visual;
/* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
***************
*** 134,141 ****
--- 148,190 ----
PixelColour;
+ #define ON_ALL_SEAMLESS_WINDOWS(func, args) \
+ do { \
+ seamless_window *sw; \
+ XRectangle rect; \
+ for (sw = g_seamless_windows; sw; sw = sw->next) { \
+ rect.x = g_clip_rectangle.x - sw->xoffset; \
+ rect.y = g_clip_rectangle.y - sw->yoffset; \
+ rect.width = g_clip_rectangle.width; \
+ rect.height = g_clip_rectangle.height; \
+ XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
+ func args; \
+ } \
+ XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
+ } while (0)
+
+ static void
+ seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
+ {
+ points[0].x -= xoffset;
+ points[0].y -= yoffset;
+ XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
+ points[0].x += xoffset;
+ points[0].y += yoffset;
+ }
+
+ static void
+ seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
+ {
+ points[0].x -= xoffset;
+ points[0].y -= yoffset;
+ XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
+ points[0].x += xoffset;
+ points[0].y += yoffset;
+ }
#define FILL_RECTANGLE(x,y,cx,cy)\
{ \
XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
+ ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
if (g_ownbackstore) \
XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
***************
*** 152,155 ****
--- 201,205 ----
if (g_ownbackstore) \
XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
+ ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
}
***************
*** 160,168 ****
case 0: /* Outline */ \
XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
if (g_ownbackstore) \
XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
break; \
case 1: /* Filled */ \
! XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
if (g_ownbackstore) \
XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
--- 210,221 ----
case 0: /* Outline */ \
XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
+ ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
if (g_ownbackstore) \
XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
break; \
case 1: /* Filled */ \
! XFillArc(g_display, g_wnd, g_gc, x, y, \
! cx, cy, 0, 360*64); \
! ON_ALL_SEAMLESS_WINDOWS(XCopyArea, (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc, x, y, cx, cy, x-sw->xoffset, y-sw->yoffset)); \
if (g_ownbackstore) \
XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
***************
*** 202,207 ****
#define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
static void
! mwm_hide_decorations(void)
{
PropMotifWmHints motif_hints;
--- 255,304 ----
#define RESET_FUNCTION(rop2) { if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
+ static seamless_window *
+ seamless_get_window_by_id(unsigned long id)
+ {
+ seamless_window *sw;
+ for (sw = g_seamless_windows; sw; sw = sw->next)
+ {
+ if (sw->id == id)
+ return sw;
+ }
+ return NULL;
+ }
+
+
+ static seamless_window *
+ seamless_get_window_by_wnd(Window wnd)
+ {
+ seamless_window *sw;
+ for (sw = g_seamless_windows; sw; sw = sw->next)
+ {
+ if (sw->wnd == wnd)
+ return sw;
+ }
+ return NULL;
+ }
+
+
static void
! seamless_remove_window(seamless_window * win)
! {
! seamless_window *sw, **prevnext = &g_seamless_windows;
! for (sw = g_seamless_windows; sw; sw = sw->next)
! {
! if (sw == win)
! {
! *prevnext = sw->next;
! xfree(sw);
! return;
! }
! prevnext = &sw->next;
! }
! return;
! }
!
!
! static void
! mwm_hide_decorations(Window wnd)
{
PropMotifWmHints motif_hints;
***************
*** 220,225 ****
}
! XChangeProperty(g_display, g_wnd, hintsatom, hintsatom, 32, PropModeReplace,
(unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
}
--- 317,323 ----
}
! XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
(unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+
}
***************
*** 1299,1302 ****
--- 1397,1402 ----
xclip_init();
+ if (g_seamless_rdp)
+ seamless_init();
DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
***************
*** 1324,1327 ****
--- 1424,1455 ----
}
+
+ static void
+ get_window_attribs(XSetWindowAttributes * attribs)
+ {
+ attribs->background_pixel = BlackPixelOfScreen(g_screen);
+ attribs->background_pixel = WhitePixelOfScreen(g_screen);
+ attribs->border_pixel = WhitePixelOfScreen(g_screen);
+ attribs->backing_store = g_ownbackstore ? NotUseful : Always;
+ attribs->override_redirect = g_fullscreen;
+ attribs->colormap = g_xcolmap;
+ }
+
+ static void
+ get_input_mask(long *input_mask)
+ {
+ *input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+ VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
+
+ if (g_sendmotion)
+ *input_mask |= PointerMotionMask;
+ if (g_ownbackstore)
+ *input_mask |= ExposureMask;
+ if (g_fullscreen || g_grab_keyboard)
+ *input_mask |= EnterWindowMask;
+ if (g_grab_keyboard)
+ *input_mask |= LeaveWindowMask;
+ }
+
BOOL
ui_create_window(void)
***************
*** 1346,1354 ****
g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
! attribs.background_pixel = BlackPixelOfScreen(g_screen);
! attribs.border_pixel = WhitePixelOfScreen(g_screen);
! attribs.backing_store = g_ownbackstore ? NotUseful : Always;
! attribs.override_redirect = g_fullscreen;
! attribs.colormap = g_xcolmap;
g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
--- 1474,1478 ----
g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
! get_window_attribs(&attribs);
g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
***************
*** 1358,1362 ****
--- 1482,1489 ----
if (g_gc == NULL)
+ {
g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
+ ui_reset_clip();
+ }
if (g_create_bitmap_gc == NULL)
***************
*** 1375,1379 ****
if (g_hide_decorations)
! mwm_hide_decorations();
classhints = XAllocClassHint();
--- 1502,1506 ----
if (g_hide_decorations)
! mwm_hide_decorations(g_wnd);
classhints = XAllocClassHint();
***************
*** 1402,1416 ****
}
! input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
! VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
!
! if (g_sendmotion)
! input_mask |= PointerMotionMask;
! if (g_ownbackstore)
! input_mask |= ExposureMask;
! if (g_fullscreen || g_grab_keyboard)
! input_mask |= EnterWindowMask;
! if (g_grab_keyboard)
! input_mask |= LeaveWindowMask;
if (g_IM != NULL)
--- 1529,1533 ----
}
! get_input_mask(&input_mask);
if (g_IM != NULL)
***************
*** 1425,1437 ****
XSelectInput(g_display, g_wnd, input_mask);
! XMapWindow(g_display, g_wnd);
!
! /* wait for VisibilityNotify */
! do
{
! XMaskEvent(g_display, VisibilityChangeMask, &xevent);
}
- while (xevent.type != VisibilityNotify);
- g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
g_focused = False;
--- 1542,1556 ----
XSelectInput(g_display, g_wnd, input_mask);
! if (!g_seamless_rdp)
{
! XMapWindow(g_display, g_wnd);
! /* wait for VisibilityNotify */
! do
! {
! XMaskEvent(g_display, VisibilityChangeMask, &xevent);
! }
! while (xevent.type != VisibilityNotify);
! g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
}
g_focused = False;
***************
*** 1497,1500 ****
--- 1616,1623 ----
Pixmap contents = 0;
+ if (g_seamless_rdp)
+ /* Turn off SeamlessRDP mode */
+ ui_seamless_toggle();
+
if (!g_ownbackstore)
{
***************
*** 1585,1590 ****
}
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
! flags | button, xevent.xbutton.x, xevent.xbutton.y);
}
--- 1708,1722 ----
}
! if (xevent.xmotion.window == g_wnd)
! {
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
! flags | button, xevent.xbutton.x, xevent.xbutton.y);
! }
! else
! {
! /* SeamlessRDP */
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
! flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
! }
}
***************
*** 1614,1618 ****
{
case VisibilityNotify:
! g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
break;
case ClientMessage:
--- 1746,1753 ----
{
case VisibilityNotify:
! if (xevent.xvisibility.window == g_wnd)
! g_Unobscured =
! xevent.xvisibility.state == VisibilityUnobscured;
!
break;
case ClientMessage:
***************
*** 1694,1699 ****
XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
CurrentTime);
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
! MOUSE_FLAG_MOVE, xevent.xmotion.x, xevent.xmotion.y);
break;
--- 1829,1845 ----
XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
CurrentTime);
!
! if (xevent.xmotion.window == g_wnd)
! {
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
! xevent.xmotion.x, xevent.xmotion.y);
! }
! else
! {
! /* SeamlessRDP */
! rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
! xevent.xmotion.x_root,
! xevent.xmotion.y_root);
! }
break;
***************
*** 1738,1746 ****
case Expose:
! XCopyArea(g_display, g_backstore, g_wnd, g_gc,
! xevent.xexpose.x, xevent.xexpose.y,
! xevent.xexpose.width,
! xevent.xexpose.height,
! xevent.xexpose.x, xevent.xexpose.y);
break;
--- 1884,1909 ----
case Expose:
! if (xevent.xexpose.window == g_wnd)
! {
! XCopyArea(g_display, g_backstore, xevent.xexpose.window,
! g_gc,
! xevent.xexpose.x, xevent.xexpose.y,
! xevent.xexpose.width, xevent.xexpose.height,
! xevent.xexpose.x, xevent.xexpose.y);
! }
! else
! {
! seamless_window *sw;
! sw = seamless_get_window_by_wnd(xevent.xexpose.window);
! if (sw)
! XCopyArea(g_display, g_backstore,
! xevent.xexpose.window, g_gc,
! xevent.xexpose.x + sw->xoffset,
! xevent.xexpose.y + sw->yoffset,
! xevent.xexpose.width,
! xevent.xexpose.height, xevent.xexpose.x,
! xevent.xexpose.y);
! }
!
break;
***************
*** 1773,1780 ****
break;
case MapNotify:
! rdp_send_client_window_status(1);
break;
case UnmapNotify:
! rdp_send_client_window_status(0);
break;
}
--- 1936,1945 ----
break;
case MapNotify:
! if (!g_seamless_rdp)
! rdp_send_client_window_status(1);
break;
case UnmapNotify:
! if (!g_seamless_rdp)
! rdp_send_client_window_status(0);
break;
}
***************
*** 1913,1920 ****
--- 2078,2091 ----
XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
+ x - sw->xoffset, y - sw->yoffset));
}
else
{
XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
+ x - sw->xoffset, y - sw->yoffset));
}
***************
*** 2037,2040 ****
--- 2208,2212 ----
g_current_cursor = (Cursor) cursor;
XDefineCursor(g_display, g_wnd, g_current_cursor);
+ ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
}
***************
*** 2178,2182 ****
--- 2350,2357 ----
}
else
+ {
XSetWindowColormap(g_display, g_wnd, (Colormap) map);
+ ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
+ }
}
***************
*** 2184,2194 ****
ui_set_clip(int x, int y, int cx, int cy)
{
! XRectangle rect;
!
! rect.x = x;
! rect.y = y;
! rect.width = cx;
! rect.height = cy;
! XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
}
--- 2359,2367 ----
ui_set_clip(int x, int y, int cx, int cy)
{
! g_clip_rectangle.x = x;
! g_clip_rectangle.y = y;
! g_clip_rectangle.width = cx;
! g_clip_rectangle.height = cy;
! XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
}
***************
*** 2196,2206 ****
ui_reset_clip(void)
{
! XRectangle rect;
!
! rect.x = 0;
! rect.y = 0;
! rect.width = g_width;
! rect.height = g_height;
! XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded);
}
--- 2369,2377 ----
ui_reset_clip(void)
{
! g_clip_rectangle.x = 0;
! g_clip_rectangle.y = 0;
! g_clip_rectangle.width = g_width;
! g_clip_rectangle.height = g_height;
! XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
}
***************
*** 2283,2286 ****
--- 2454,2460 ----
if (g_ownbackstore)
XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
+ x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
}
***************
*** 2293,2308 ****
if (g_ownbackstore)
{
! if (g_Unobscured)
! {
! XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
! XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
! y);
! }
! else
! {
! XCopyArea(g_display, g_backstore, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
! XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x,
! y);
! }
}
else
--- 2467,2473 ----
if (g_ownbackstore)
{
! XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
! g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
! XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
}
else
***************
*** 2310,2313 ****
--- 2475,2483 ----
XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
}
+
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_ownbackstore ? g_backstore : g_wnd,
+ sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
+
RESET_FUNCTION(opcode);
}
***************
*** 2320,2323 ****
--- 2490,2496 ----
SET_FUNCTION(opcode);
XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, (Pixmap) src, sw->wnd, g_gc,
+ srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
if (g_ownbackstore)
XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
***************
*** 2366,2369 ****
--- 2539,2545 ----
SET_FOREGROUND(pen->colour);
XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
+ ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
+ startx - sw->xoffset, starty - sw->yoffset,
+ endx - sw->xoffset, endy - sw->yoffset));
if (g_ownbackstore)
XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
***************
*** 2463,2466 ****
--- 2639,2646 ----
XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
CoordModePrevious);
+
+ ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
+ (sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
+
RESET_FUNCTION(opcode);
}
***************
*** 2683,2691 ****
--- 2863,2885 ----
{
if (boxcx > 1)
+ {
XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
boxy, boxcx, boxcy, boxx, boxy);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_backstore, sw->wnd, g_gc,
+ boxx, boxy,
+ boxcx, boxcy,
+ boxx - sw->xoffset, boxy - sw->yoffset));
+ }
else
+ {
XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
clipy, clipcx, clipcy, clipx, clipy);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_backstore, sw->wnd, g_gc,
+ clipx, clipy,
+ clipcx, clipcy, clipx - sw->xoffset,
+ clipy - sw->yoffset));
+ }
}
}
***************
*** 2733,2740 ****
--- 2927,2940 ----
XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_backstore, sw->wnd, g_gc,
+ x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
}
else
{
XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
+ ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+ (g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
+ x - sw->xoffset, y - sw->yoffset));
}
***************
*** 2752,2753 ****
--- 2952,3128 ----
{
}
+
+ void
+ ui_seamless_toggle()
+ {
+ if (g_seamless_rdp)
+ {
+ /* Deactivate */
+ while (g_seamless_windows)
+ {
+ XDestroyWindow(g_display, g_seamless_windows->wnd);
+ seamless_remove_window(g_seamless_windows);
+ }
+ XMapWindow(g_display, g_wnd);
+ }
+ else
+ {
+ /* Activate */
+ if (g_win_button_size)
+ {
+ error("SeamlessRDP mode cannot be activated when using single application mode\n");
+ return;
+ }
+ if (!g_using_full_workarea)
+ {
+ error("SeamlessRDP mode requires a session that covers the whole screen");
+ return;
+ }
+
+ XUnmapWindow(g_display, g_wnd);
+ seamless_send_sync();
+ }
+
+ g_seamless_rdp = !g_seamless_rdp;
+ }
+
+ void
+ ui_seamless_create_window(unsigned long id, unsigned long flags)
+ {
+ Window wnd;
+ XSetWindowAttributes attribs;
+ XClassHint *classhints;
+ long input_mask;
+ seamless_window *sw;
+
+ get_window_attribs(&attribs);
+
+ attribs.override_redirect = False;
+
+ /* FIXME: Do not assume that -1, -1 is outside screen Consider
+ wait with showing the window until STATE and others have
+ been recieved. */
+ wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, 0,
+ InputOutput, g_visual,
+ CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
+ CWBorderPixel, &attribs);
+
+ XStoreName(g_display, wnd, "rdesktop-seamless");
+
+ mwm_hide_decorations(wnd);
+
+ classhints = XAllocClassHint();
+ if (classhints != NULL)
+ {
+ classhints->res_name = classhints->res_class = "rdesktop";
+ XSetClassHint(g_display, wnd, classhints);
+ XFree(classhints);
+ }
+
+ /* FIXME: Support for Input Context:s */
+
+ get_input_mask(&input_mask);
+
+ XSelectInput(g_display, wnd, input_mask);
+
+ XMapWindow(g_display, wnd);
+
+ /* handle the WM_DELETE_WINDOW protocol. FIXME: When killing a
+ seamless window, we could try to close the window on the
+ serverside, instead of terminating rdesktop */
+ XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
+
+ sw = malloc(sizeof(seamless_window));
+ sw->wnd = wnd;
+ sw->id = id;
+ sw->xoffset = 0;
+ sw->yoffset = 0;
+ sw->width = 0;
+ sw->height = 0;
+ sw->next = g_seamless_windows;
+ g_seamless_windows = sw;
+ }
+
+
+ void
+ ui_seamless_destroy_window(unsigned long id, unsigned long flags)
+ {
+ seamless_window *sw;
+ sw = seamless_get_window_by_id(id);
+
+ if (!sw)
+ {
+ warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
+ return;
+ }
+
+ XDestroyWindow(g_display, sw->wnd);
+ seamless_remove_window(sw);
+ }
+
+
+ void
+ ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
+ {
+ seamless_window *sw;
+
+ sw = seamless_get_window_by_id(id);
+
+ if (!sw)
+ {
+ warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
+ return;
+ }
+
+ if (!width || !height)
+ /* X11 windows must be at least 1x1 */
+ return;
+
+ /* About MAX and MIN: Windows allows moving a window outside
+ the desktop. This happens, for example, when maximizing an
+ application. In this case, the position is set to something
+ like -4,-4,1288,1032. Many WMs does not allow windows
+ outside the desktop, however. Therefore, clip the window
+ ourselves. */
+ sw->xoffset = MAX(0, x);
+ sw->yoffset = MAX(0, y);
+ sw->width = MIN(MIN(width, width + x), g_width - sw->xoffset);
+ sw->height = MIN(MIN(height, height + y), g_height - sw->yoffset);
+
+ /* FIXME: Perhaps use ewmh_net_moveresize_window instead */
+ XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
+ }
+
+
+ void
+ ui_seamless_settitle(unsigned long id, const char *title)
+ {
+ seamless_window *sw;
+
+ sw = seamless_get_window_by_id(id);
+
+ XStoreName(g_display, sw->wnd, title);
+ }
+
+
+ void
+ ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
+ {
+ seamless_window *sw;
+
+ sw = seamless_get_window_by_id(id);
+
+ switch (state)
+ {
+ case SEAMLESSRDP_NORMAL:
+ case SEAMLESSRDP_MAXIMIZED:
+ /* FIXME */
+ break;
+ case SEAMLESSRDP_MINIMIZED:
+ XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
+ break;
+ default:
+ warning("SeamlessRDP: Invalid state %d\n", state);
+ break;
+ }
+ }
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642