diff --git a/configure.ac b/configure.ac index d59bef1..000fefb 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,15 @@ LIBS="$LIBS $ssldir/lib/libcrypto.a" LIBS="$LIBS -L$ssldir/lib -lcrypto" rpath="$rpath:$ssldir/lib" ]) +# xrandr +if test -n "$PKG_CONFIG"; then + PKG_CHECK_MODULES(XRANDR, xrandr, [HAVE_XRANDR=1], [HAVE_XRANDR=0]) +fi +if test x"$HAVE_XRANDR" = "x1"; then + CFLAGS="$CFLAGS $XRANDR_CFLAGS" + LIBS="$LIBS $XRANDR_LIBS" + AC_DEFINE(HAVE_XRANDR) +fi AC_ARG_ENABLE(smartcard, [ --enable-smartcard Enables smart-card support. diff --git a/doc/rdesktop.1 b/doc/rdesktop.1 index 7e3f597..95f97d3 100644 --- a/doc/rdesktop.1 +++ b/doc/rdesktop.1 @@ -66,6 +66,11 @@ Desktop geometry (WxH). If geometry is the special word "workarea", the geometry will be fetched from the extended window manager hints property _NET_WORKAREA, from the root window. The geometry can also be specified as a percentage of the whole screen, e.g. "-g 80%". + +If the specified geometry depends on the screen size, and the screen +size is changed, rdesktop will automatically reconnect using the new +screen size. This requires that rdesktop has been compiled with RandR +support. .TP .BR "-f" Enable fullscreen mode. This overrides the window manager and causes the diff --git a/proto.h b/proto.h index 3486abc..5813a16 100644 --- a/proto.h +++ b/proto.h @@ -279,6 +279,7 @@ void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy); void ui_begin_update(void); void ui_end_update(void); void ui_seamless_begin(RD_BOOL hidden); +void ui_seamless_end(); void ui_seamless_hide_desktop(void); void ui_seamless_unhide_desktop(void); void ui_seamless_toggle(void); diff --git a/rdesktop.c b/rdesktop.c index 49cc7c8..6f11a4f 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -106,6 +106,7 @@ uint32 g_reconnect_logonid = 0; char g_reconnect_random[16]; RD_BOOL g_has_reconnect_random = False; uint8 g_client_random[SEC_RANDOM_SIZE]; +RD_BOOL g_pending_resize = False; #ifdef WITH_RDPSND RD_BOOL g_rdpsnd = False; @@ -1001,7 +1002,15 @@ main(int argc, char *argv[]) if (g_redirect) continue; + + ui_seamless_end(); ui_destroy_window(); + if (g_pending_resize) + { + /* If we have a pending resize, reconnect using the new size, rather than exit */ + g_pending_resize = False; + continue; + } break; } diff --git a/rdp.c b/rdp.c index 03d3bdd..318c44a 100644 --- a/rdp.c +++ b/rdp.c @@ -52,6 +52,7 @@ extern int g_height; extern RD_BOOL g_bitmap_cache; extern RD_BOOL g_bitmap_cache_persist_enable; extern RD_BOOL g_numlock_sync; +extern RD_BOOL g_pending_resize; uint8 *g_next_packet; uint32 g_rdp_shareid; @@ -1530,12 +1531,16 @@ process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ ) } /* Process incoming packets */ -/* nevers gets out of here till app is done */ void rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason) { while (rdp_loop(deactivated, ext_disc_reason)) - ; + { + if (g_pending_resize) + { + return; + } + } } /* used in uiports and rdp_main_loop, processes the rdp packets waiting */ diff --git a/xwin.c b/xwin.c index 52e2f78..e89b693 100644 --- a/xwin.c +++ b/xwin.c @@ -28,6 +28,9 @@ #include #include "rdesktop.h" #include "xproto.h" +#ifdef HAVE_XRANDR +#include +#endif extern int g_sizeopt; extern int g_width; @@ -39,6 +42,7 @@ extern RD_BOOL g_sendmotion; extern RD_BOOL g_fullscreen; extern RD_BOOL g_grab_keyboard; extern RD_BOOL g_hide_decorations; +extern RD_BOOL g_pending_resize; extern char g_title[]; /* Color depth of the RDP session. As of RDP 5.1, it may be 8, 15, 16 or 24. */ @@ -1946,12 +1950,6 @@ ui_init_connection(void) void ui_deinit(void) { - while (g_seamless_windows) - { - XDestroyWindow(g_display, g_seamless_windows->wnd); - sw_remove_window(g_seamless_windows); - } - xclip_deinit(); if (g_IM != NULL) @@ -2085,6 +2083,9 @@ ui_create_window(void) } XSelectInput(g_display, g_wnd, input_mask); +#ifdef HAVE_XRANDR + XSelectInput(g_display, RootWindowOfScreen(g_screen), StructureNotifyMask); +#endif XMapWindow(g_display, g_wnd); /* wait for VisibilityNotify */ @@ -2303,6 +2304,11 @@ xwin_process_events(void) /* Ignore events between ui_destroy_window and ui_create_window */ continue; + /* Also ignore root window events except ConfigureNotify */ + if (xevent.type != ConfigureNotify + && xevent.xany.window == DefaultRootWindow(g_display)) + continue; + if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True)) { DEBUG_KBD(("Filtering event\n")); @@ -2575,6 +2581,20 @@ xwin_process_events(void) rdp_send_client_window_status(0); break; case ConfigureNotify: +#ifdef HAVE_XRANDR + if ((g_sizeopt || g_fullscreen) + && xevent.xconfigure.window == DefaultRootWindow(g_display)) + { + if (xevent.xconfigure.width != WidthOfScreen(g_screen) + || xevent.xconfigure.height != HeightOfScreen(g_screen)) + { + XRRUpdateConfiguration(&xevent); + XSync(g_display, False); + g_pending_resize = True; + } + + } +#endif if (!g_seamless_active) break; @@ -3774,6 +3794,22 @@ ui_seamless_begin(RD_BOOL hidden) } +void +ui_seamless_end() +{ + /* Destroy all seamless windows */ + while (g_seamless_windows) + { + XDestroyWindow(g_display, g_seamless_windows->wnd); + sw_remove_window(g_seamless_windows); + } + + g_seamless_started = False; + g_seamless_active = False; + g_seamless_hidden = False; +} + + void ui_seamless_hide_desktop() {