xfreerdp: fix fullscreen mode

This commit is contained in:
Marc-André Moreau 2011-08-24 00:46:34 -04:00
parent 9a3477f7ec
commit a0aea4f353
4 changed files with 196 additions and 177 deletions

View File

@ -41,30 +41,52 @@ struct _PropMotifWmHints
};
typedef struct _PropMotifWmHints PropMotifWmHints;
void desktop_fullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen)
void xf_SendClientMessage(xfInfo* xfi, xfWindow* window, Atom atom, long msg, long d1, long d2, long d3)
{
XEvent xevent;
xevent.xclient.type = ClientMessage;
xevent.xclient.message_type = atom;
xevent.xclient.window = window->handle;
xevent.xclient.format = 32;
xevent.xclient.data.l[0] = CurrentTime;
xevent.xclient.data.l[1] = msg;
xevent.xclient.data.l[2] = d1;
xevent.xclient.data.l[3] = d2;
xevent.xclient.data.l[4] = d3;
XSendEvent(xfi->display, window->handle, False, NoEventMask, &xevent);
XSync(xfi->display, False);
}
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen)
{
if (fullscreen)
{
if (window->decorations)
window_show_decorations(xfi, window, False);
xf_SetWindowDecorations(xfi, window, False);
XSetInputFocus(xfi->display, window->handle, RevertToParent, CurrentTime);
printf("width:%d height:%d\n", window->width, window->height);
XMoveResizeWindow(xfi->display, window->handle, 0, 0, window->width, window->height);
XMapRaised(xfi->display, window->handle);
//XGrabPointer(xfi->display, window->handle, True, 0, GrabModeAsync, GrabModeAsync, window->handle, 0L, CurrentTime);
//XGrabKeyboard(xfi->display, window->handle, False, GrabModeAsync, GrabModeAsync, CurrentTime);
//XSetInputFocus(xfi->display, window->handle, RevertToParent, CurrentTime);
window->fullscreen = True;
}
}
/* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */
boolean window_GetProperty(xfInfo* xfi, Window window, char* name, int length,
boolean xf_GetWindowProperty(xfInfo* xfi, Window window, Atom property, int length,
unsigned long* nitems, unsigned long* bytes, uint8** prop)
{
int status;
Atom property;
Atom actual_type;
int actual_format;
property = XInternAtom(xfi->display, name, True);
if (property == None)
return False;
@ -78,15 +100,15 @@ boolean window_GetProperty(xfInfo* xfi, Window window, char* name, int length,
return True;
}
boolean window_GetCurrentDesktop(xfInfo* xfi)
boolean xf_GetCurrentDesktop(xfInfo* xfi)
{
boolean status;
unsigned long nitems;
unsigned long bytes;
unsigned char* prop;
status = window_GetProperty(xfi, DefaultRootWindow(xfi->display),
"_NET_CURRENT_DESKTOP", 1, &nitems, &bytes, &prop);
status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display),
xfi->_NET_CURRENT_DESKTOP, 1, &nitems, &bytes, &prop);
if (status != True)
return False;
@ -97,7 +119,7 @@ boolean window_GetCurrentDesktop(xfInfo* xfi)
return True;
}
boolean window_GetWorkArea(xfInfo* xfi)
boolean xf_GetWorkArea(xfInfo* xfi)
{
long* plong;
boolean status;
@ -105,13 +127,13 @@ boolean window_GetWorkArea(xfInfo* xfi)
unsigned long bytes;
unsigned char* prop;
status = window_GetProperty(xfi, DefaultRootWindow(xfi->display),
"_NET_WORKAREA", 32 * 4, &nitems, &bytes, &prop);
status = xf_GetWindowProperty(xfi, DefaultRootWindow(xfi->display),
xfi->_NET_WORKAREA, 32 * 4, &nitems, &bytes, &prop);
if (status != True)
return False;
window_GetCurrentDesktop(xfi);
xf_GetCurrentDesktop(xfi);
plong = (long*) prop;
@ -124,34 +146,20 @@ boolean window_GetWorkArea(xfInfo* xfi)
return True;
}
void window_show_decorations(xfInfo* xfi, xfWindow* window, boolean show)
void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show)
{
Atom atom;
PropMotifWmHints hints;
hints.decorations = 0;
hints.decorations = show;
hints.flags = MWM_HINTS_DECORATIONS;
atom = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", True);
if (!atom)
{
printf("window_show_decorations: failed to obtain atom _MOTIF_WM_HINTS\n");
return;
}
else
{
if (show != True)
{
XChangeProperty(xfi->display, window->handle, atom, atom, 32,
PropModeReplace, (uint8*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
}
}
XChangeProperty(xfi->display, window->handle, xfi->_MOTIF_WM_HINTS, xfi->_MOTIF_WM_HINTS, 32,
PropModeReplace, (uint8*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
window->decorations = show;
}
xfWindow* desktop_create(xfInfo* xfi, char* name)
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height)
{
xfWindow* window;
@ -163,6 +171,8 @@ xfWindow* desktop_create(xfInfo* xfi, char* name)
XSizeHints* size_hints;
XClassHint* class_hints;
window->width = width;
window->height = height;
window->decorations = True;
window->fullscreen = True;
@ -206,7 +216,7 @@ xfWindow* desktop_create(xfInfo* xfi, char* name)
return window;
}
void xf_fix_window_coordinates(int* x, int* y, int* width, int* height)
void xf_FixWindowCoordinates(int* x, int* y, int* width, int* height)
{
if (*x < 0)
{
@ -231,7 +241,7 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
if ((width * height) < 1)
return NULL;
xf_fix_window_coordinates(&x, &y, &width, &height);
xf_FixWindowCoordinates(&x, &y, &width, &height);
window->left = x;
window->top = y;
@ -255,7 +265,7 @@ xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel, &xfi->attribs);
window_show_decorations(xfi, window, window->decorations);
xf_SetWindowDecorations(xfi, window, window->decorations);
class_hints = XAllocClassHint();
@ -308,7 +318,7 @@ void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int h
if ((width * height) < 1)
return;
xf_fix_window_coordinates(&x, &y, &width, &height);
xf_FixWindowCoordinates(&x, &y, &width, &height);
size_hints = XAllocSizeHints();
@ -367,7 +377,6 @@ void xf_ShowWindow(xfInfo* xfi, xfWindow* window, uint8 state)
void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon)
{
Atom atom;
int x, y;
int pixels;
int propsize;
@ -395,20 +404,10 @@ void xf_SetWindowIcon(xfInfo* xfi, xfWindow* window, rdpIcon* icon)
}
}
atom = XInternAtom(xfi->display, "_NET_WM_ICON", False);
XChangeProperty(xfi->display, window->handle, xfi->_NET_WM_ICON, XA_CARDINAL, 32,
PropModeReplace, (uint8*) propdata, propsize);
if (!atom)
{
printf("xf_SetWindowIcon: failed to obtain atom _NET_WM_ICON\n");
return;
}
else
{
XChangeProperty(xfi->display, window->handle, atom, XA_CARDINAL, 32,
PropModeReplace, (uint8*) propdata, propsize);
XFlush(xfi->display);
}
XFlush(xfi->display);
}
void xf_SetWindowVisibilityRects(xfInfo* xfi, xfWindow* window, RECTANGLE_16* rects, int nrects)

View File

@ -43,13 +43,15 @@ struct xf_window
boolean decorations;
};
boolean window_GetCurrentDesktop(xfInfo* xfi);
boolean window_GetWorkArea(xfInfo* xfi);
void xf_ewmhints_init(xfInfo* xfi);
void desktop_fullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
void window_show_decorations(xfInfo* xfi, xfWindow* window, boolean show);
boolean xf_GetCurrentDesktop(xfInfo* xfi);
boolean xf_GetWorkArea(xfInfo* xfi);
xfWindow* desktop_create(xfInfo* xfi, char* name);
void xf_SetWindowFullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen);
void xf_SetWindowDecorations(xfInfo* xfi, xfWindow* window, boolean show);
xfWindow* xf_CreateDesktopWindow(xfInfo* xfi, char* name, int width, int height);
xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, uint32 id);
void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height);

View File

@ -52,7 +52,6 @@ struct thread_data
void xf_begin_paint(rdpUpdate* update)
{
GDI* gdi;
gdi = GET_GDI(update);
gdi->primary->hdc->hwnd->invalid->null = 1;
}
@ -114,121 +113,6 @@ boolean xf_check_fds(freerdp* instance, fd_set* set)
return True;
}
boolean xf_pre_connect(freerdp* instance)
{
xfInfo* xfi;
rdpSettings* settings;
#ifdef WITH_XINERAMA
int n, ignored, ignored2;
XineramaScreenInfo* screen_info = NULL;
#endif
xfi = (xfInfo*) xzalloc(sizeof(xfInfo));
SET_XFI(instance, xfi);
xfi->instance = instance;
settings = instance->settings;
settings->order_support[NEG_DSTBLT_INDEX] = True;
settings->order_support[NEG_PATBLT_INDEX] = True;
settings->order_support[NEG_SCRBLT_INDEX] = True;
settings->order_support[NEG_OPAQUE_RECT_INDEX] = True;
settings->order_support[NEG_DRAWNINEGRID_INDEX] = False;
settings->order_support[NEG_MULTIDSTBLT_INDEX] = False;
settings->order_support[NEG_MULTIPATBLT_INDEX] = False;
settings->order_support[NEG_MULTISCRBLT_INDEX] = False;
settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = True;
settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = False;
settings->order_support[NEG_LINETO_INDEX] = True;
settings->order_support[NEG_POLYLINE_INDEX] = True;
settings->order_support[NEG_MEMBLT_INDEX] = True;
settings->order_support[NEG_MEM3BLT_INDEX] = False;
settings->order_support[NEG_SAVEBITMAP_INDEX] = True;
settings->order_support[NEG_GLYPH_INDEX_INDEX] = True;
settings->order_support[NEG_FAST_INDEX_INDEX] = True;
settings->order_support[NEG_FAST_GLYPH_INDEX] = True;
settings->order_support[NEG_POLYGON_SC_INDEX] = False;
settings->order_support[NEG_POLYGON_CB_INDEX] = False;
settings->order_support[NEG_ELLIPSE_SC_INDEX] = False;
settings->order_support[NEG_ELLIPSE_CB_INDEX] = False;
freerdp_chanman_pre_connect(GET_CHANMAN(instance), instance);
xfi->display = XOpenDisplay(NULL);
if (xfi->display == NULL)
{
printf("xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
return False;
}
xf_kbd_init(xfi);
xfi->xfds = ConnectionNumber(xfi->display);
xfi->screen_number = DefaultScreen(xfi->display);
xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number);
xfi->depth = DefaultDepthOfScreen(xfi->screen);
xfi->big_endian = (ImageByteOrder(xfi->display) == MSBFirst);
xfi->mouse_motion = True;
xfi->decoration = settings->decorations;
xfi->remote_app = settings->remote_app;
xfi->fullscreen = settings->fullscreen;
window_GetWorkArea(xfi);
if (settings->workarea)
{
settings->width = xfi->workArea.width;
settings->height = xfi->workArea.height;
}
if (settings->fullscreen != True && settings->workarea != True)
return True;
#ifdef WITH_XINERAMA
if (XineramaQueryExtension(xfi->display, &ignored, &ignored2))
{
if (XineramaIsActive(xfi->display))
{
screen_info = XineramaQueryScreens(xfi->display, &settings->num_monitors);
if (settings->num_monitors > 16)
settings->num_monitors = 0;
if (settings->num_monitors)
{
for (n = 0; n < settings->num_monitors; n++)
{
if (settings->workarea)
{
settings->monitors[n].x = screen_info[n].x_org;
settings->monitors[n].y = screen_info[n].y_org;
settings->monitors[n].width = screen_info[n].width;
settings->monitors[n].height = xfi->workArea.height;
}
else
{
settings->monitors[n].x = screen_info[n].x_org;
settings->monitors[n].y = screen_info[n].y_org;
settings->monitors[n].width = screen_info[n].width;
settings->monitors[n].height = screen_info[n].height;
}
settings->monitors[n].is_primary = screen_info[n].x_org == 0 && screen_info[n].y_org == 0;
}
}
XFree(screen_info);
}
}
#endif
return True;
}
void xf_toggle_fullscreen(xfInfo* xfi)
{
Pixmap contents = 0;
@ -236,9 +120,7 @@ void xf_toggle_fullscreen(xfInfo* xfi)
contents = XCreatePixmap(xfi->display, xfi->window->handle, xfi->width, xfi->height, xfi->depth);
XCopyArea(xfi->display, xfi->primary, contents, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
//xf_destroy_window(xfi);
xfi->fullscreen = (xfi->fullscreen) ? False : True;
//xf_post_connect(xfi);
XCopyArea(xfi->display, contents, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height, 0, 0);
XFreePixmap(xfi->display, contents);
@ -308,6 +190,135 @@ boolean xf_get_pixmap_info(xfInfo* xfi)
return True;
}
boolean xf_pre_connect(freerdp* instance)
{
xfInfo* xfi;
rdpSettings* settings;
#ifdef WITH_XINERAMA
int n, ignored, ignored2;
XineramaScreenInfo* screen_info = NULL;
#endif
xfi = (xfInfo*) xzalloc(sizeof(xfInfo));
SET_XFI(instance, xfi);
xfi->instance = instance;
settings = instance->settings;
settings->order_support[NEG_DSTBLT_INDEX] = True;
settings->order_support[NEG_PATBLT_INDEX] = True;
settings->order_support[NEG_SCRBLT_INDEX] = True;
settings->order_support[NEG_OPAQUE_RECT_INDEX] = True;
settings->order_support[NEG_DRAWNINEGRID_INDEX] = False;
settings->order_support[NEG_MULTIDSTBLT_INDEX] = False;
settings->order_support[NEG_MULTIPATBLT_INDEX] = False;
settings->order_support[NEG_MULTISCRBLT_INDEX] = False;
settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = True;
settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = False;
settings->order_support[NEG_LINETO_INDEX] = True;
settings->order_support[NEG_POLYLINE_INDEX] = True;
settings->order_support[NEG_MEMBLT_INDEX] = True;
settings->order_support[NEG_MEM3BLT_INDEX] = False;
settings->order_support[NEG_SAVEBITMAP_INDEX] = True;
settings->order_support[NEG_GLYPH_INDEX_INDEX] = True;
settings->order_support[NEG_FAST_INDEX_INDEX] = True;
settings->order_support[NEG_FAST_GLYPH_INDEX] = True;
settings->order_support[NEG_POLYGON_SC_INDEX] = False;
settings->order_support[NEG_POLYGON_CB_INDEX] = False;
settings->order_support[NEG_ELLIPSE_SC_INDEX] = False;
settings->order_support[NEG_ELLIPSE_CB_INDEX] = False;
freerdp_chanman_pre_connect(GET_CHANMAN(instance), instance);
xfi->display = XOpenDisplay(NULL);
if (xfi->display == NULL)
{
printf("xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
return False;
}
xfi->_NET_WM_ICON = XInternAtom(xfi->display, "_NET_WM_ICON", False);
xfi->_MOTIF_WM_HINTS = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", False);
xfi->_NET_CURRENT_DESKTOP = XInternAtom(xfi->display, "_NET_CURRENT_DESKTOP", False);
xfi->_NET_WORKAREA = XInternAtom(xfi->display, "_NET_WORKAREA", False);
xfi->_NET_WM_STATE = XInternAtom(xfi->display, "_NET_WM_STATE", False);
xfi->_NET_WM_STATE_FULLSCREEN = XInternAtom(xfi->display, "_NET_WM_STATE_FULLSCREEN", False);
xf_kbd_init(xfi);
xfi->xfds = ConnectionNumber(xfi->display);
xfi->screen_number = DefaultScreen(xfi->display);
xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number);
xfi->depth = DefaultDepthOfScreen(xfi->screen);
xfi->big_endian = (ImageByteOrder(xfi->display) == MSBFirst);
xfi->mouse_motion = True;
xfi->decoration = settings->decorations;
xfi->remote_app = settings->remote_app;
xfi->fullscreen = settings->fullscreen;
xf_GetWorkArea(xfi);
if (settings->workarea)
{
settings->width = xfi->workArea.width;
settings->height = xfi->workArea.height;
}
if (settings->fullscreen != True && settings->workarea != True)
return True;
#ifdef WITH_XINERAMA
if (XineramaQueryExtension(xfi->display, &ignored, &ignored2))
{
if (XineramaIsActive(xfi->display))
{
screen_info = XineramaQueryScreens(xfi->display, &settings->num_monitors);
if (settings->num_monitors > 16)
settings->num_monitors = 0;
settings->width = 0;
settings->height = 0;
if (settings->num_monitors)
{
for (n = 0; n < settings->num_monitors; n++)
{
if (settings->workarea)
{
settings->monitors[n].x = screen_info[n].x_org;
settings->monitors[n].y = screen_info[n].y_org;
settings->monitors[n].width = screen_info[n].width;
settings->monitors[n].height = xfi->workArea.height;
settings->width += settings->monitors[n].width;
settings->height = settings->monitors[n].height;
}
else
{
settings->monitors[n].x = screen_info[n].x_org;
settings->monitors[n].y = screen_info[n].y_org;
settings->monitors[n].width = screen_info[n].width;
settings->monitors[n].height = screen_info[n].height;
settings->width += settings->monitors[n].width;
settings->height = settings->monitors[n].height;
}
settings->monitors[n].is_primary = screen_info[n].x_org == 0 && screen_info[n].y_org == 0;
}
}
XFree(screen_info);
}
}
#endif
return True;
}
boolean xf_post_connect(freerdp* instance)
{
GDI* gdi;
@ -340,12 +351,12 @@ boolean xf_post_connect(freerdp* instance)
if (xfi->remote_app != True)
{
xfi->window = desktop_create(xfi, "xfreerdp");
xfi->window = xf_CreateDesktopWindow(xfi, "xfreerdp", xfi->width, xfi->height);
window_show_decorations(xfi, xfi->window, xfi->decoration);
xf_SetWindowDecorations(xfi, xfi->window, xfi->decoration);
if (xfi->fullscreen)
desktop_fullscreen(xfi, xfi->window, xfi->fullscreen);
xf_SetWindowFullscreen(xfi, xfi->window, xfi->fullscreen);
/* wait for VisibilityNotify */
do

View File

@ -81,6 +81,13 @@ struct xf_info
boolean pressed_keys[256];
XModifierKeymap* modifier_map;
XSetWindowAttributes attribs;
Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS;
Atom _NET_CURRENT_DESKTOP;
Atom _NET_WORKAREA;
Atom _NET_WM_STATE;
Atom _NET_WM_STATE_FULLSCREEN;
};
void xf_toggle_fullscreen(xfInfo* xfi);