]> source.dussan.org Git - tigervnc.git/commitdiff
Have a history of used vnc servers to select from in the vncviewer 1176/head
authorJohannes <bensky@arcor.de>
Mon, 11 Jan 2021 21:46:26 +0000 (22:46 +0100)
committerJohannes <bensky@arcor.de>
Mon, 11 Jan 2021 21:46:26 +0000 (22:46 +0100)
vncviewer/ServerDialog.cxx
vncviewer/ServerDialog.h
vncviewer/parameters.cxx
vncviewer/parameters.h

index fec178964439f1b07aa92d3149748d9b33ecc315..9ed5c40847b53d9f02dffc407de84019b945b618 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <FL/Fl.H>
 #include <FL/Fl_Input.H>
+#include <FL/Fl_Input_Choice.H>
 #include <FL/Fl_Button.H>
 #include <FL/Fl_Return_Button.H>
 #include <FL/fl_draw.H>
 #include <FL/Fl_Box.H>
 #include <FL/Fl_File_Chooser.H>
 
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+#include <os/os.h>
+#include <rfb/Exception.h>
+
 #include "ServerDialog.h"
 #include "OptionsDialog.h"
 #include "fltk_layout.h"
 #include "i18n.h"
 #include "vncviewer.h"
 #include "parameters.h"
-#include "rfb/Exception.h"
+
+
+using namespace std;
+using namespace rfb;
+
+const char* SERVER_HISTORY="tigervnc.history";
 
 ServerDialog::ServerDialog()
   : Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
@@ -51,7 +64,11 @@ ServerDialog::ServerDialog()
   x = margin + server_label_width;
   y = margin;
   
-  serverName = new Fl_Input(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
+  serverName = new Fl_Input_Choice(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
+  loadServerHistory();
+  for(size_t i=0;i<serverHistory.size();++i) {
+    serverName->add(serverHistory[i].c_str());
+  }
 
   int adjust = (w() - 20) / 4;
   int button_width = adjust - margin/2;
@@ -112,7 +129,7 @@ void ServerDialog::run(const char* servername, char *newservername)
   ServerDialog dialog;
 
   dialog.serverName->value(servername);
-  
+
   dialog.show();
   while (dialog.shown()) Fl::wait();
 
@@ -154,7 +171,7 @@ void ServerDialog::handleLoad(Fl_Widget *widget, void *data)
 
   try {
     dialog->serverName->value(loadViewerParameters(filename));
-  } catch (rfb::Exception& e) {
+  } catch (Exception& e) {
     fl_alert("%s", e.str());
   }
 
@@ -209,7 +226,7 @@ void ServerDialog::handleSaveAs(Fl_Widget *widget, void *data)
   
   try {
     saveViewerParameters(filename, servername);
-  } catch (rfb::Exception& e) {
+  } catch (Exception& e) {
     fl_alert("%s", e.str());
   }
   
@@ -227,7 +244,7 @@ void ServerDialog::handleCancel(Fl_Widget *widget, void *data)
 {
   ServerDialog *dialog = (ServerDialog*)data;
 
-  dialog->serverName->value(NULL);
+  dialog->serverName->value("");
   dialog->hide();
 }
 
@@ -238,10 +255,90 @@ void ServerDialog::handleConnect(Fl_Widget *widget, void *data)
   const char* servername = dialog->serverName->value();
 
   dialog->hide();
-  
+
   try {
     saveViewerParameters(NULL, servername);
-  } catch (rfb::Exception& e) {
+
+    vector<string>::iterator elem = std::find(dialog->serverHistory.begin(), dialog->serverHistory.end(), servername);
+    // avoid duplicates in the history
+    if(dialog->serverHistory.end() == elem) {
+      dialog->serverHistory.insert(dialog->serverHistory.begin(), servername);
+      dialog->saveServerHistory();
+    }
+  } catch (Exception& e) {
     fl_alert("%s", e.str());
   }
 }
+
+
+void ServerDialog::loadServerHistory()
+{
+#ifdef _WIN32
+  loadHistoryFromRegKey(serverHistory);
+  return;
+#endif
+
+  char* homeDir = NULL;
+  if (getvnchomedir(&homeDir) == -1) {
+    throw Exception(_("Failed to read server history file, "
+                     "can't obtain home directory path."));
+  }
+
+  char filepath[PATH_MAX];
+  snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
+  delete[] homeDir;
+
+  /* Read server history from file */
+  ifstream f (filepath);
+  if (!f.is_open()) {
+    // no history file
+    return;
+  }
+
+  string line;
+  while(getline(f, line)) {
+    serverHistory.push_back(line);
+  }
+
+  if (f.bad()) {
+    throw Exception(_("Failed to read server history file, "
+                     "error while reading file."));
+  }
+  f.close();
+}
+
+void ServerDialog::saveServerHistory()
+{
+#ifdef _WIN32
+  saveHistoryToRegKey(serverHistory);
+  return;
+#endif
+
+  char* homeDir = NULL;
+  if (getvnchomedir(&homeDir) == -1) {
+    throw Exception(_("Failed to write server history file, "
+                     "can't obtain home directory path."));
+  }
+
+  char filepath[PATH_MAX];
+  snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
+  delete[] homeDir;
+
+  /* Write server history to file */
+  ofstream f (filepath);
+  if (!f.is_open()) {
+    throw Exception(_("Failed to write server history file, "
+                     "can't open file."));
+  }
+
+  // Save the last X elements to the config file.
+  for(size_t i=0; i < serverHistory.size() && i <= SERVER_HISTORY_SIZE; i++) {
+    f << serverHistory[i] << endl;
+  }
+
+  if (f.bad()) {
+    throw Exception(_("Failed to write server history file, "
+                     "error while writing file."));
+  }
+  f.close();
+}
index 7926849a0917374aafb6048340dd3b2a40842c3c..8363977765080433044925081cdbcd81ef90a444 100644 (file)
 #define __SERVERDIALOG_H__
 
 #include <FL/Fl_Window.H>
+#include <string>
+#include <vector>
 
 class Fl_Widget;
-class Fl_Input;
+class Fl_Input_Choice;
 
 class ServerDialog : public Fl_Window {
 protected:
@@ -40,8 +42,13 @@ protected:
   static void handleCancel(Fl_Widget *widget, void *data);
   static void handleConnect(Fl_Widget *widget, void *data);
 
+private:
+  void loadServerHistory();
+  void saveServerHistory();
+
 protected:
-  Fl_Input *serverName;
+  Fl_Input_Choice *serverName;
+  std::vector<std::string> serverHistory;
 };
 
 #endif
index bb8e47fa9d8e78f1bada15c60c7b734a318562e2..b28a1112854e1062a4051235a117ed8b8c61f664 100644 (file)
 #include <string.h>
 #include <limits.h>
 #include <errno.h>
+#include <assert.h>
 
 #include "i18n.h"
 
 using namespace rfb;
+using namespace std;
 
 static LogWriter vlog("Parameters");
 
@@ -398,6 +400,34 @@ static bool getKeyInt(const char* _name, int* dest, HKEY* hKey) {
 }
 
 
+void saveHistoryToRegKey(const vector<string>& serverHistory) {
+  HKEY hKey;
+  LONG res = RegCreateKeyExW(HKEY_CURRENT_USER,
+                             L"Software\\TigerVNC\\vncviewer\\history", 0, NULL,
+                             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
+                             &hKey, NULL);
+
+  if (res != ERROR_SUCCESS) {
+    vlog.error(_("Failed to create registry key: %ld"), res);
+    return;
+  }
+
+  size_t index = 0;
+  assert(SERVER_HISTORY_SIZE < 100);
+  char indexString[3];
+
+  while(index < serverHistory.size() && index <= SERVER_HISTORY_SIZE) {
+    snprintf(indexString, 3, "%d", index);
+    setKeyString(indexString, serverHistory[index].c_str(), &hKey);
+    index++;
+  }
+
+  res = RegCloseKey(hKey);
+  if (res != ERROR_SUCCESS) {
+    vlog.error(_("Failed to close registry key: %ld"), res);
+  }
+}
+
 static void saveToReg(const char* servername) {
   
   HKEY hKey;
@@ -432,6 +462,43 @@ static void saveToReg(const char* servername) {
   }
 }
 
+void loadHistoryFromRegKey(vector<string>& serverHistory) {
+  HKEY hKey;
+
+  LONG res = RegOpenKeyExW(HKEY_CURRENT_USER,
+                           L"Software\\TigerVNC\\vncviewer\\history", 0,
+                           KEY_READ, &hKey);
+  if (res != ERROR_SUCCESS) {
+    if (res == ERROR_FILE_NOT_FOUND) {
+      // The key does not exist, defaults will be used.
+    } else {
+      vlog.error(_("Failed to open registry key: %ld"), res);
+    }
+    return;
+  }
+
+  bool stop = false;
+  size_t index = 0;
+  const DWORD buffersize = 256;
+  char indexString[3];
+
+  while(!stop) {
+    snprintf(indexString, 3, "%d", index);
+    char servernameBuffer[buffersize];
+    if (getKeyString(indexString, servernameBuffer, buffersize, &hKey)) {
+      serverHistory.push_back(servernameBuffer);
+      index++;
+    }
+    else {
+      stop = true;
+    }
+  }
+
+  res = RegCloseKey(hKey);
+  if (res != ERROR_SUCCESS){
+    vlog.error(_("Failed to close registry key: %ld"), res);
+  }
+}
 
 static char* loadFromReg() {
 
@@ -521,9 +588,9 @@ void saveViewerParameters(const char *filename, const char *servername) {
   fprintf(f, "%s\r\n", IDENTIFIER_STRING);
   fprintf(f, "\r\n");
 
-  if (encodeValue(servername, encodingBuffer, buffersize))  
+  if (encodeValue(servername, encodingBuffer, buffersize))
     fprintf(f, "ServerName=%s\n", encodingBuffer);
-  
+
   for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
     if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
       if (encodeValue(*(StringParameter*)parameterArray[i], encodingBuffer, buffersize))
@@ -638,7 +705,7 @@ char* loadViewerParameters(const char *filename) {
       invalidParameterName = false;
 
     } else {
-    
+
       // Find and set the correct parameter
       for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
 
index 94aec9fa9f2c34d7266dac20494e335b9ce8208c..3d8ac24f3d76e715f27be7e3c622a89b1f99f728 100644 (file)
 
 #include <rfb/Configuration.h>
 
+#ifdef _WIN32
+#include <vector>
+#include <string>
+#endif
+
+#define SERVER_HISTORY_SIZE 20
+
+
 extern rfb::IntParameter pointerEventInterval;
 extern rfb::BoolParameter emulateMiddleButton;
 extern rfb::BoolParameter dotWhenNoCursor;
@@ -71,4 +79,9 @@ extern rfb::StringParameter via;
 void saveViewerParameters(const char *filename, const char *servername=NULL);
 char* loadViewerParameters(const char *filename);
 
+#ifdef _WIN32
+void loadHistoryFromRegKey(std::vector<std::string>& serverHistory);
+void saveHistoryToRegKey(const std::vector<std::string>& serverHistory);
+#endif
+
 #endif