diff --git a/proto.h b/proto.h index 7a32d7f..7fe30cd 100644 --- a/proto.h +++ b/proto.h @@ -84,7 +84,7 @@ void ui_deinit(void); BOOL ui_create_window(void); void ui_destroy_window(void); void xwin_toggle_fullscreen(void); -void ui_select(int rdp_socket); +int ui_select(int rdp_socket); void ui_move_pointer(int x, int y); HBITMAP ui_create_bitmap(int width, int height, uint8 * data); void ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data); diff --git a/tcp.c b/tcp.c index a5e77bc..6f3b19e 100644 --- a/tcp.c +++ b/tcp.c @@ -84,7 +84,9 @@ tcp_recv(int length) while (length > 0) { - ui_select(sock); + if (!ui_select(sock)) + /* User quit */ + return NULL; rcvd = recv(sock, in.end, length, 0); if (rcvd == -1) diff --git a/xwin.c b/xwin.c index bb6e8d1..6f61d61 100644 --- a/xwin.c +++ b/xwin.c @@ -47,6 +47,7 @@ static XIM IM; static XIC IC; static XModifierKeymap *mod_map; static Cursor current_cursor; +static Atom protocol_atom, kill_atom; /* endianness */ static BOOL host_be; @@ -436,6 +437,11 @@ ui_create_window(void) focused = False; mouse_in_wnd = False; + /* handle the WM_DELETE_WINDOW protocol */ + protocol_atom = XInternAtom(display, "WM_PROTOCOLS", True); + kill_atom = XInternAtom(display, "WM_DELETE_WINDOW", True); + XSetWMProtocols(display, wnd, &kill_atom, 1); + return True; } @@ -473,8 +479,9 @@ xwin_toggle_fullscreen(void) } } -/* Process all events in Xlib queue */ -static void +/* Process all events in Xlib queue + Returns 0 after user quit, 1 otherwise */ +static int xwin_process_events(void) { XEvent xevent; @@ -502,6 +509,14 @@ xwin_process_events(void) switch (xevent.type) { + case ClientMessage: + /* the window manager told us to quit */ + if ((xevent.xclient.message_type == protocol_atom) + && (xevent.xclient.data.l[0] == kill_atom)) + /* Quit */ + return 0; + break; + case KeyPress: if (IC != NULL) /* Multi_key compatible version */ @@ -645,9 +660,12 @@ xwin_process_events(void) } } + /* Keep going */ + return 1; } -void +/* Returns 0 after user quit, 1 otherwise */ +int ui_select(int rdp_socket) { int n = (rdp_socket > x_socket) ? rdp_socket + 1 : x_socket + 1; @@ -658,7 +676,9 @@ ui_select(int rdp_socket) while (True) { /* Process any events already waiting */ - xwin_process_events(); + if (!xwin_process_events()) + /* User quit */ + return 0; FD_ZERO(&rfds); FD_SET(rdp_socket, &rfds); @@ -674,7 +694,7 @@ ui_select(int rdp_socket) } if (FD_ISSET(rdp_socket, &rfds)) - return; + return 1; } }