--- sourceforge.net/trunk/rdesktop/xwin.c 2005/04/16 11:57:19 887 +++ sourceforge.net/trunk/rdesktop/xwin.c 2005/11/23 13:26:29 1031 @@ -79,6 +79,7 @@ static BOOL g_moving_wnd; static int g_move_x_offset = 0; static int g_move_y_offset = 0; +static BOOL g_using_full_workarea = False; #ifdef WITH_RDPSND extern int g_dsp_fd; @@ -137,10 +138,9 @@ XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \ break; \ case 1: /* Filled */ \ - XFillArc(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, \ - cx, cy, 0, 360*64); \ + XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \ if (g_ownbackstore) \ - XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y); \ + XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \ break; \ } \ } @@ -1091,6 +1091,8 @@ else if (g_width < 0) { /* Percent of screen */ + if (-g_width >= 100) + g_using_full_workarea = True; g_height = HeightOfScreen(g_screen) * (-g_width) / 100; g_width = WidthOfScreen(g_screen) * (-g_width) / 100; } @@ -1098,6 +1100,7 @@ { /* Fetch geometry from _NET_WORKAREA */ uint32 x, y, cx, cy; + g_using_full_workarea = True; if (get_current_workarea(&x, &y, &cx, &cy) == 0) { @@ -1227,7 +1230,7 @@ } input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | - VisibilityChangeMask | FocusChangeMask; + VisibilityChangeMask | FocusChangeMask | StructureNotifyMask; if (g_sendmotion) input_mask |= PointerMotionMask; @@ -1341,6 +1344,78 @@ } } +static void +handle_button_event(XEvent xevent, BOOL down) +{ + uint16 button, flags = 0; + g_last_gesturetime = xevent.xbutton.time; + button = xkeymap_translate_button(xevent.xbutton.button); + if (button == 0) + return; + + if (down) + flags = MOUSE_FLAG_DOWN; + + /* Stop moving window when button is released, regardless of cursor position */ + if (g_moving_wnd && (xevent.type == ButtonRelease)) + g_moving_wnd = False; + + /* If win_button_size is nonzero, enable single app mode */ + if (xevent.xbutton.y < g_win_button_size) + { + /* Check from right to left: */ + if (xevent.xbutton.x >= g_width - g_win_button_size) + { + /* The close button, continue */ + ; + } + else if (xevent.xbutton.x >= g_width - g_win_button_size * 2) + { + /* The maximize/restore button. Do not send to + server. It might be a good idea to change the + cursor or give some other visible indication + that rdesktop inhibited this click */ + if (xevent.type == ButtonPress) + return; + } + else if (xevent.xbutton.x >= g_width - g_win_button_size * 3) + { + /* The minimize button. Iconify window. */ + if (xevent.type == ButtonRelease) + { + /* Release the mouse button outside the minimize button, to prevent the + actual minimazation to happen */ + rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1); + XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display)); + return; + } + } + else if (xevent.xbutton.x <= g_win_button_size) + { + /* The system menu. Ignore. */ + if (xevent.type == ButtonPress) + return; + } + else + { + /* The title bar. */ + if (xevent.type == ButtonPress) + { + if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea) + { + g_moving_wnd = True; + g_move_x_offset = xevent.xbutton.x; + g_move_y_offset = xevent.xbutton.y; + } + return; + } + } + } + + rdp_send_input(time(NULL), RDP_INPUT_MOUSE, + flags | button, xevent.xbutton.x, xevent.xbutton.y); +} + /* Process events in Xlib queue Returns 0 after user quit, 1 otherwise */ static int @@ -1348,9 +1423,7 @@ { XEvent xevent; KeySym keysym; - uint16 button, flags; uint32 ev_time; - key_translation tr; char str[256]; Status status; int events = 0; @@ -1365,8 +1438,6 @@ continue; } - flags = 0; - switch (xevent.type) { case VisibilityNotify: @@ -1403,24 +1474,15 @@ str, sizeof(str), &keysym, NULL); } - DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym, + DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym, get_ksname(keysym))); ev_time = time(NULL); if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True)) break; - tr = xkeymap_translate_key(keysym, - xevent.xkey.keycode, xevent.xkey.state); - - if (tr.scancode == 0) - break; - - save_remote_modifiers(tr.scancode); - ensure_remote_modifiers(ev_time, tr); - rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode); - restore_remote_modifiers(ev_time, tr.scancode); - + xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state, + ev_time, True, 0); break; case KeyRelease: @@ -1428,85 +1490,23 @@ XLookupString((XKeyEvent *) & xevent, str, sizeof(str), &keysym, NULL); - DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym, + DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym, get_ksname(keysym))); ev_time = time(NULL); if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False)) break; - tr = xkeymap_translate_key(keysym, - xevent.xkey.keycode, xevent.xkey.state); - - if (tr.scancode == 0) - break; - - rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode); + xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state, + ev_time, False, 0); break; case ButtonPress: - flags = MOUSE_FLAG_DOWN; - /* fall through */ + handle_button_event(xevent, True); + break; case ButtonRelease: - g_last_gesturetime = xevent.xbutton.time; - button = xkeymap_translate_button(xevent.xbutton.button); - if (button == 0) - break; - - /* If win_button_size is nonzero, enable single app mode */ - if (xevent.xbutton.y < g_win_button_size) - { - /* Stop moving window when button is released, regardless of cursor position */ - if (g_moving_wnd && (xevent.type == ButtonRelease)) - g_moving_wnd = False; - - /* Check from right to left: */ - - if (xevent.xbutton.x >= g_width - g_win_button_size) - { - /* The close button, continue */ - ; - } - else if (xevent.xbutton.x >= - g_width - g_win_button_size * 2) - { - /* The maximize/restore button. Do not send to - server. It might be a good idea to change the - cursor or give some other visible indication - that rdesktop inhibited this click */ - break; - } - else if (xevent.xbutton.x >= - g_width - g_win_button_size * 3) - { - /* The minimize button. Iconify window. */ - XIconifyWindow(g_display, g_wnd, - DefaultScreen(g_display)); - break; - } - else if (xevent.xbutton.x <= g_win_button_size) - { - /* The system menu. Ignore. */ - break; - } - else - { - /* The title bar. */ - if ((xevent.type == ButtonPress) && !g_fullscreen - && g_hide_decorations) - { - g_moving_wnd = True; - g_move_x_offset = xevent.xbutton.x; - g_move_y_offset = xevent.xbutton.y; - } - break; - - } - } - - rdp_send_input(time(NULL), RDP_INPUT_MOUSE, - flags | button, xevent.xbutton.x, xevent.xbutton.y); + handle_button_event(xevent, False); break; case MotionNotify: @@ -1599,6 +1599,12 @@ case PropertyNotify: xclip_handle_PropertyNotify(&xevent.xproperty); break; + case MapNotify: + rdp_send_client_window_status(1); + break; + case UnmapNotify: + rdp_send_client_window_status(0); + break; } } /* Keep going */ @@ -2439,25 +2445,40 @@ switch (text[i]) { case 0xff: - if (i + 2 < length) - cache_put_text(text[i + 1], text, text[i + 2]); - else + /* At least two bytes needs to follow */ + if (i + 3 > length) { - error("this shouldn't be happening\n"); - exit(1); + warning("Skipping short 0xff command:"); + for (j = 0; j < length; j++) + fprintf(stderr, "%02x ", text[j]); + fprintf(stderr, "\n"); + i = length = 0; + break; } + cache_put_text(text[i + 1], text, text[i + 2]); + i += 3; + length -= i; /* this will move pointer from start to first character after FF command */ - length -= i + 3; - text = &(text[i + 3]); + text = &(text[i]); i = 0; break; case 0xfe: + /* At least one byte needs to follow */ + if (i + 2 > length) + { + warning("Skipping short 0xfe command:"); + for (j = 0; j < length; j++) + fprintf(stderr, "%02x ", text[j]); + fprintf(stderr, "\n"); + i = length = 0; + break; + } entry = cache_get_text(text[i + 1]); - if (entry != NULL) + if (entry->data != NULL) { - if ((((uint8 *) (entry->data))[1] == - 0) && (!(flags & TEXT2_IMPLICIT_X))) + if ((((uint8 *) (entry->data))[1] == 0) + && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length)) { if (flags & TEXT2_VERTICAL) y += text[i + 2];