/// <summary> /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary. /// </summary> private void GetRfbUpdates() { int rectangles; int enc; // Get the initial destkop from the host RequestScreenUpdate(true); while (true) { if (CheckIfThreadDone()) { break; } try { switch (rfb.ReadServerMessageType()) { case RfbProtocol.FRAMEBUFFER_UPDATE: rectangles = rfb.ReadFramebufferUpdate(); if (CheckIfThreadDone()) { break; } for (int i = 0; i < rectangles; ++i) { // Get the update rectangle's info Rectangle rectangle; rfb.ReadFramebufferUpdateRectHeader(out rectangle, out enc); // Build a derived EncodedRectangle type and pull-down all the pixel info EncodedRectangle er = factory.Build(rectangle, enc); er.Decode(); // Let the UI know that an updated rectangle is available, but check // to see if the user closed things down first. if (!CheckIfThreadDone() && VncUpdate != null) { VncEventArgs e = new VncEventArgs(er); // In order to play nicely with WinForms controls, we do a check here to // see if it is necessary to synchronize this event with the UI thread. if (VncUpdate.Target is System.Windows.Forms.Control) { Control target = VncUpdate.Target as Control; if (target != null) { target.Invoke(VncUpdate, new object[] { this, e }); } } else { // Target is not a WinForms control, so do it on this thread... VncUpdate(this, new VncEventArgs(er)); } } } break; case RfbProtocol.BELL: Beep(500, 300); // TODO: are there better values than these? break; case RfbProtocol.SERVER_CUT_TEXT: if (CheckIfThreadDone()) { break; } Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true); break; case RfbProtocol.SET_COLOUR_MAP_ENTRIES: // TODO: Needs to be implemented fully // rfb.ReadColourMapEntry(); break; } } catch { OnConnectionLost(); } } }
/// <summary> /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as /// necessary. /// </summary> private void GetRfbUpdates() { // Get the initial destkop from the host var connLostCount = 0; RequestScreenUpdate(true); while (true) { if (CheckIfThreadDone()) { break; } try { // ReSharper disable once SwitchStatementMissingSomeCases switch (rfb.ReadServerMessageType()) { case RfbProtocol.FRAMEBUFFER_UPDATE: var rectangles = rfb.ReadFramebufferUpdate(); var encodedRecangles = new List <Rectangle>(); if (CheckIfThreadDone()) { break; } // TODO: consider gathering all update rectangles in a batch and *then* posting the event back to the main thread. for (var i = 0; i < rectangles; ++i) { // Get the update rectangle's info rfb.ReadFramebufferUpdateRectHeader(out var rectangle, out var enc); if (enc == RfbProtocol.PSEUDO_LAST_RECT_ENCODING) { break; } // Build a derived EncodedRectangle type and pull-down all the pixel info var er = factory.Build(rectangle, enc); er.Decode(); encodedRecangles.Add(er.UpdateRectangle); } // Let the UI know that an updated rectangle is available, but check // to see if the user closed things down first. if (CheckIfThreadDone() || VncUpdate == null) { continue; } var e = new VncEventArgs(encodedRecangles, Framebuffer); // In order to play nicely with WinForms controls, we do a check here to // see if it is necessary to synchronize this event with the UI thread. if (VncUpdate.Target is Control control) { control.Invoke(VncUpdate, this, e); } else { // Target is not a WinForms control, so do it on this thread... VncUpdate(this, e); } break; case RfbProtocol.BELL: Beep(); break; case RfbProtocol.SERVER_CUT_TEXT: if (CheckIfThreadDone()) { break; } // TODO: This is invasive, should there be a bool property allowing this message to be ignored? Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true); OnServerCutText(); break; case RfbProtocol.SET_COLOUR_MAP_ENTRIES: rfb.ReadColourMapEntry(); break; } // Moved screen update request here to prevent it being called multiple times // This was the case when multiple rectangles were returned by the host RequestScreenUpdate(FullScreenRefresh); connLostCount = 0; } catch { // On the first time of no data being received we force a complete update // This is for times when the server has no update, and caused the timeout. if (connLostCount++ > 1) { OnConnectionLost(); } else { RequestScreenUpdate(true); } } FullScreenRefresh = false; } }
/// <summary> /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary. /// </summary> private void GetRfbUpdates() { // Get the initial destkop from the host RequestScreenUpdate(true); while (true) { if (CheckIfThreadDone()) { break; } try { // ReSharper disable once SwitchStatementMissingSomeCases switch (rfb.ReadServerMessageType()) { case RfbProtocol.FRAMEBUFFER_UPDATE: var rectangles = rfb.ReadFramebufferUpdate(); if (CheckIfThreadDone()) { break; } // TODO: consider gathering all update rectangles in a batch and *then* posting the event back to the main thread. for (var i = 0; i < rectangles; ++i) { // Get the update rectangle's info rfb.ReadFramebufferUpdateRectHeader(out Rectangle rectangle, out int enc); // Build a derived EncodedRectangle type and pull-down all the pixel info var er = factory.Build(rectangle, enc); er.Decode(); // Let the UI know that an updated rectangle is available, but check // to see if the user closed things down first. if (CheckIfThreadDone() || VncUpdate == null) { continue; } var e = new VncEventArgs(er); // In order to play nicely with WinForms controls, we do a check here to // see if it is necessary to synchronize this event with the UI thread. var control = VncUpdate.Target as Control; if (control != null) { control.Invoke(VncUpdate, this, e); } else { // Target is not a WinForms control, so do it on this thread... VncUpdate(this, new VncEventArgs(er)); } } break; case RfbProtocol.BELL: Beep(); break; case RfbProtocol.SERVER_CUT_TEXT: if (CheckIfThreadDone()) { break; } // TODO: This is invasive, should there be a bool property allowing this message to be ignored? Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true); OnServerCutText(); break; case RfbProtocol.SET_COLOUR_MAP_ENTRIES: rfb.ReadColourMapEntry(); break; } } catch { OnConnectionLost(); } } }