This is an automated email from the ASF dual-hosted git repository.

solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openmeetings.git


The following commit(s) were added to refs/heads/master by this push:
     new d993f16  [OPENMEETINGS-2078] shortcuts are refactored, shortcut for 
start quick-poll is added
d993f16 is described below

commit d993f1663a106b8c63c97a40ffd0cafcd6ce3366
Author: Maxim Solodovnik <[email protected]>
AuthorDate: Sun Jul 14 22:55:47 2019 +0700

    [OPENMEETINGS-2078] shortcuts are refactored, shortcut for start quick-poll 
is added
---
 .../db/dao/basic/ConfigurationDao.java             |  21 ++-
 .../db/entity/basic/Configuration.java             |  12 +-
 .../apache/openmeetings/backup/BackupImport.java   |  99 ++++++++------
 .../installation/ImportInitvalues.java             | 145 +++++++++++----------
 .../openmeetings/util/OpenmeetingsVariables.java   |   1 +
 .../web/admin/configurations/ConfigForm.java       |  43 +++---
 .../web/admin/configurations/ConfigsPanel.html     |  27 ++++
 .../openmeetings/web/room/menu/PollsSubMenu.java   |  19 +--
 .../org/apache/openmeetings/web/room/raw-room.js   |  42 +++---
 9 files changed, 240 insertions(+), 169 deletions(-)

diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
index 5daed32..da48610 100644
--- 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
@@ -39,6 +39,7 @@ import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_C
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_ARRANGE;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_MUTE;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_MUTE_OTHERS;
+import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_QUICKPOLL;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_LNAME_MIN_LENGTH;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_LOGIN_MIN_LENGTH;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_MAX_UPLOAD_SIZE;
@@ -97,7 +98,9 @@ import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.TimeZone;
 
 import javax.persistence.EntityManager;
@@ -302,6 +305,7 @@ public class ConfigurationDao implements 
IDataProviderDao<Configuration> {
                        case CONFIG_KEYCODE_ARRANGE:
                        case CONFIG_KEYCODE_MUTE_OTHERS:
                        case CONFIG_KEYCODE_MUTE:
+                       case CONFIG_KEYCODE_QUICKPOLL:
                                reloadRoomSettings();
                                break;
                        case CONFIG_MAX_UPLOAD_SIZE:
@@ -554,13 +558,24 @@ public class ConfigurationDao implements 
IDataProviderDao<Configuration> {
                reloadDisplayNameEditable();
        }
 
+       private static JSONObject getHotkey(String value) {
+               List<String> partList = Arrays.asList(value.split("\\+"));
+               Set<String> parts = new HashSet<>(partList);
+               return new JSONObject()
+                               .put("alt", parts.contains("Alt"))
+                               .put("shift", parts.contains("Shift"))
+                               .put("ctrl", parts.contains("Ctrl"))
+                               .put("key", partList.get(partList.size() - 1));
+       }
+
        private JSONObject reloadRoomSettings() {
                try {
                        setRoomSettings(new JSONObject()
                                        .put("keycode", new JSONObject()
-                                                       .put("arrange", 
getLong(CONFIG_KEYCODE_ARRANGE, 119L))
-                                                       .put("muteothers", 
getLong(CONFIG_KEYCODE_MUTE_OTHERS, 123L))
-                                                       .put("mute", 
getLong(CONFIG_KEYCODE_MUTE, 118L))
+                                                       .put("arrange", 
getHotkey(getString(CONFIG_KEYCODE_ARRANGE, "Shift+F8")))
+                                                       .put("muteothers", 
getHotkey(getString(CONFIG_KEYCODE_MUTE_OTHERS, "Shift+F12")))
+                                                       .put("mute", 
getHotkey(getString(CONFIG_KEYCODE_MUTE, "Shift+F7")))
+                                                       .put("quickpoll", 
getHotkey(getString(CONFIG_KEYCODE_QUICKPOLL, "Ctrl+Alt+Q")))
                                                        )
                                        .put("camera", new 
JSONObject().put("fps", getLong(CONFIG_CAM_FPS, 30L)))
                                        .put("microphone", new JSONObject()
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Configuration.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Configuration.java
index 8b1ccd3..805acb0 100644
--- 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Configuration.java
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/basic/Configuration.java
@@ -22,6 +22,8 @@ import static java.lang.Boolean.TRUE;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
@@ -56,9 +58,10 @@ public class Configuration extends HistoricalEntity {
        private static final long serialVersionUID = 1L;
 
        public enum Type {
-               string
-               , number
-               , bool
+               STRING
+               , NUMBER
+               , BOOL
+               , HOTKEY
        }
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -68,7 +71,8 @@ public class Configuration extends HistoricalEntity {
 
        @Column(name = "type")
        @Element(name = "type", data = true, required = false)
-       private Type type = Type.string;
+       @Enumerated(EnumType.STRING)
+       private Type type = Type.STRING;
 
        @Column(name = "om_key", unique = true)
        @Element(name = "key", data = true, required = false)
diff --git 
a/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java
 
b/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java
index d34e427..8fca0b5 100644
--- 
a/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java
+++ 
b/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java
@@ -103,12 +103,14 @@ import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SMTP_USE
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.getDefaultTimezone;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.getMinLoginLength;
 
+import java.awt.event.KeyEvent;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -120,6 +122,7 @@ import java.util.zip.ZipInputStream;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.text.WordUtils;
 import org.apache.openmeetings.backup.converter.AppointmentConverter;
 import 
org.apache.openmeetings.backup.converter.AppointmentReminderTypeConverter;
 import org.apache.openmeetings.backup.converter.BaseFileItemConverter;
@@ -230,44 +233,44 @@ public class BackupImport {
                outdatedConfigKeys.put("swftools_zoom", CONFIG_DOCUMENT_DPI);
                outdatedConfigKeys.put("swftools_jpegquality", 
CONFIG_DOCUMENT_QUALITY);
                outdatedConfigKeys.put("sms.subject", CONFIG_REMINDER_MESSAGE);
-               configTypes.put(CONFIG_REGISTER_FRONTEND, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_REGISTER_SOAP, Configuration.Type.bool);
-               configTypes.put(CONFIG_REGISTER_OAUTH, Configuration.Type.bool);
-               configTypes.put(CONFIG_SMTP_TLS, Configuration.Type.bool);
-               configTypes.put(CONFIG_EMAIL_AT_REGISTER, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_EMAIL_VERIFICATION, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_SIP_ENABLED, Configuration.Type.bool);
-               configTypes.put(CONFIG_SCREENSHARING_FPS_SHOW, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_SCREENSHARING_ALLOW_REMOTE, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_DASHBOARD_SHOW_MYROOMS, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_DASHBOARD_SHOW_CHAT, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_DASHBOARD_SHOW_RSS, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_REPLY_TO_ORGANIZER, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_IGNORE_BAD_SSL, Configuration.Type.bool);
-               configTypes.put(CONFIG_MYROOMS_ENABLED, 
Configuration.Type.bool);
-               configTypes.put(CONFIG_DEFAULT_GROUP_ID, 
Configuration.Type.number);
-               configTypes.put(CONFIG_SMTP_PORT, Configuration.Type.number);
-               configTypes.put(CONFIG_SMTP_TIMEOUT_CON, 
Configuration.Type.number);
-               configTypes.put(CONFIG_SMTP_TIMEOUT, Configuration.Type.number);
-               configTypes.put(CONFIG_DEFAULT_LANG, Configuration.Type.number);
-               configTypes.put(CONFIG_DOCUMENT_DPI, Configuration.Type.number);
-               configTypes.put(CONFIG_DOCUMENT_QUALITY, 
Configuration.Type.number);
-               configTypes.put(CONFIG_SCREENSHARING_QUALITY, 
Configuration.Type.number);
-               configTypes.put(CONFIG_SCREENSHARING_FPS, 
Configuration.Type.number);
-               configTypes.put(CONFIG_MAX_UPLOAD_SIZE, 
Configuration.Type.number);
-               configTypes.put(CONFIG_APPOINTMENT_REMINDER_MINUTES, 
Configuration.Type.number);
-               configTypes.put(CONFIG_LOGIN_MIN_LENGTH, 
Configuration.Type.number);
-               configTypes.put(CONFIG_PASS_MIN_LENGTH, 
Configuration.Type.number);
-               configTypes.put(CONFIG_CALENDAR_ROOM_CAPACITY, 
Configuration.Type.number);
-               configTypes.put(CONFIG_KEYCODE_ARRANGE, 
Configuration.Type.number);
-               configTypes.put(CONFIG_KEYCODE_MUTE_OTHERS, 
Configuration.Type.number);
-               configTypes.put(CONFIG_KEYCODE_MUTE, Configuration.Type.number);
-               configTypes.put(CONFIG_DEFAULT_LDAP_ID, 
Configuration.Type.number);
-               configTypes.put(CONFIG_CAM_FPS, Configuration.Type.number);
-               configTypes.put(CONFIG_MIC_RATE, Configuration.Type.number);
-               configTypes.put(CONFIG_MIC_ECHO, Configuration.Type.bool);
-               configTypes.put(CONFIG_MIC_NOISE, Configuration.Type.bool);
-               configTypes.put(CONFIG_EXT_PROCESS_TTL, 
Configuration.Type.number);
+               configTypes.put(CONFIG_REGISTER_FRONTEND, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_REGISTER_SOAP, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_REGISTER_OAUTH, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_SMTP_TLS, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_EMAIL_AT_REGISTER, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_EMAIL_VERIFICATION, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_SIP_ENABLED, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_SCREENSHARING_FPS_SHOW, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_SCREENSHARING_ALLOW_REMOTE, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_DASHBOARD_SHOW_MYROOMS, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_DASHBOARD_SHOW_CHAT, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_DASHBOARD_SHOW_RSS, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_REPLY_TO_ORGANIZER, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_IGNORE_BAD_SSL, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_MYROOMS_ENABLED, 
Configuration.Type.BOOL);
+               configTypes.put(CONFIG_DEFAULT_GROUP_ID, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_SMTP_PORT, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_SMTP_TIMEOUT_CON, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_SMTP_TIMEOUT, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_DEFAULT_LANG, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_DOCUMENT_DPI, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_DOCUMENT_QUALITY, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_SCREENSHARING_QUALITY, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_SCREENSHARING_FPS, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_MAX_UPLOAD_SIZE, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_APPOINTMENT_REMINDER_MINUTES, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_LOGIN_MIN_LENGTH, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_PASS_MIN_LENGTH, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_CALENDAR_ROOM_CAPACITY, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_KEYCODE_ARRANGE, 
Configuration.Type.HOTKEY);
+               configTypes.put(CONFIG_KEYCODE_MUTE_OTHERS, 
Configuration.Type.HOTKEY);
+               configTypes.put(CONFIG_KEYCODE_MUTE, Configuration.Type.HOTKEY);
+               configTypes.put(CONFIG_DEFAULT_LDAP_ID, 
Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_CAM_FPS, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_MIC_RATE, Configuration.Type.NUMBER);
+               configTypes.put(CONFIG_MIC_ECHO, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_MIC_NOISE, Configuration.Type.BOOL);
+               configTypes.put(CONFIG_EXT_PROCESS_TTL, 
Configuration.Type.NUMBER);
        }
 
        @Autowired
@@ -444,6 +447,17 @@ public class BackupImport {
                registry.bind(Date.class, DateConverter.class);
                registry.bind(User.class, new UserConverter(userDao, userMap));
 
+               final Map<Integer, String> keyMap = new HashMap<>();
+               Arrays.asList(KeyEvent.class.getDeclaredFields()).stream()
+                               .filter(fld -> fld.getName().startsWith("VK_"))
+                               .forEach(fld -> {
+                                       try {
+                                               keyMap.put(fld.getInt(null), 
"Shift+" + WordUtils.capitalizeFully(fld.getName().substring(3)));
+                                       } catch 
(IllegalArgumentException|IllegalAccessException e) {
+                                               log.error("Unexpected exception 
while building KEY map {}", fld);
+                                       }
+                               });
+
                List<Configuration> list = readList(serializer, f, 
"configs.xml", "configs", Configuration.class);
                for (Configuration c : list) {
                        if (c.getKey() == null || c.isDeleted()) {
@@ -456,8 +470,15 @@ public class BackupImport {
                        Configuration.Type type = configTypes.get(c.getKey());
                        if (type != null) {
                                c.setType(type);
-                               if (Configuration.Type.bool == type) {
+                               if (Configuration.Type.BOOL == type) {
                                        
c.setValue(String.valueOf("1".equals(c.getValue()) || 
"yes".equals(c.getValue()) || "true".equals(c.getValue())));
+                               } else if (Configuration.Type.HOTKEY == type) {
+                                       try {
+                                               int val = 
c.getValueN().intValue();
+                                               c.setValue(keyMap.get(val));
+                                       } catch(Exception e) {
+                                               //no-op, value is already HOTKEY
+                                       }
                                }
                        }
                        Configuration cfg = cfgDao.forceGet(c.getKey());
diff --git 
a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
 
b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
index 740b5f6..4628e8f 100644
--- 
a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
+++ 
b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
@@ -54,6 +54,7 @@ import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_IGNORE_B
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_ARRANGE;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_MUTE;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_MUTE_OTHERS;
+import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_KEYCODE_QUICKPOLL;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_LNAME_MIN_LENGTH;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_LOGIN_MIN_LENGTH;
 import static 
org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_MAX_UPLOAD_SIZE;
@@ -187,170 +188,172 @@ public class ImportInitvalues {
         */
        public static List<Configuration> initialCfgs(InstallationConfig cfg) {
                List<Configuration> list = new ArrayList<>();
-               addCfg(list, CONFIG_CRYPT, cfg.getCryptClassName(), 
Configuration.Type.string,
+               addCfg(list, CONFIG_CRYPT, cfg.getCryptClassName(), 
Configuration.Type.STRING,
                                "This Class is used for 
Authentification-Crypting. "
                                                + "Be carefull what you do 
here! If you change it while "
                                                + "running previous Pass of 
users will not be workign anymore! "
                                                + "for more Information see 
https://openmeetings.apache.org/CustomCryptMechanism.html";
                                                , VER_1_9);
 
-               addCfg(list, CONFIG_REGISTER_FRONTEND, 
String.valueOf(cfg.isAllowFrontendRegister()), Configuration.Type.bool
+               addCfg(list, CONFIG_REGISTER_FRONTEND, 
String.valueOf(cfg.isAllowFrontendRegister()), Configuration.Type.BOOL
                                , "Is user register available on login screen", 
VER_1_8);
-               addCfg(list, CONFIG_REGISTER_SOAP, String.valueOf(true), 
Configuration.Type.bool, "Is user register available via SOAP/REST", VER_3_0);
-               addCfg(list, CONFIG_REGISTER_OAUTH, String.valueOf(true), 
Configuration.Type.bool, "Is user register available via OAuth", VER_3_0);
+               addCfg(list, CONFIG_REGISTER_SOAP, String.valueOf(true), 
Configuration.Type.BOOL, "Is user register available via SOAP/REST", VER_3_0);
+               addCfg(list, CONFIG_REGISTER_OAUTH, String.valueOf(true), 
Configuration.Type.BOOL, "Is user register available via OAuth", VER_3_0);
                // this group_id is the Group of users who register through the 
frontend or SOAP
-               addCfg(list, CONFIG_DEFAULT_GROUP_ID, 
String.valueOf(getDefaultGroup()), Configuration.Type.number, "", VER_1_8);
+               addCfg(list, CONFIG_DEFAULT_GROUP_ID, 
String.valueOf(getDefaultGroup()), Configuration.Type.NUMBER, "", VER_1_8);
 
-               addCfg(list, CONFIG_SMTP_SERVER, cfg.getSmtpServer(), 
Configuration.Type.string, "this is the smtp server to send messages", VER_1_9);
+               addCfg(list, CONFIG_SMTP_SERVER, cfg.getSmtpServer(), 
Configuration.Type.STRING, "this is the smtp server to send messages", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_PORT, 
String.valueOf(cfg.getSmtpPort()), Configuration.Type.number, "this is the smtp 
server port normally 25", VER_1_9);
+               addCfg(list, CONFIG_SMTP_PORT, 
String.valueOf(cfg.getSmtpPort()), Configuration.Type.NUMBER, "this is the smtp 
server port normally 25", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_SYSTEM_EMAIL, cfg.getMailReferer(), 
Configuration.Type.string, "all send e-mails by the system will have this 
address", VER_1_9);
+               addCfg(list, CONFIG_SMTP_SYSTEM_EMAIL, cfg.getMailReferer(), 
Configuration.Type.STRING, "all send e-mails by the system will have this 
address", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_USER, cfg.getMailAuthName(), 
Configuration.Type.string, "System auth email username", VER_1_9);
+               addCfg(list, CONFIG_SMTP_USER, cfg.getMailAuthName(), 
Configuration.Type.STRING, "System auth email username", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_PASS, cfg.getMailAuthPass(), 
Configuration.Type.string, "System auth email password", VER_1_9);
+               addCfg(list, CONFIG_SMTP_PASS, cfg.getMailAuthPass(), 
Configuration.Type.STRING, "System auth email password", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_TLS, 
String.valueOf(cfg.isMailUseTls()), Configuration.Type.bool, "Enable TLS", 
VER_1_9);
+               addCfg(list, CONFIG_SMTP_TLS, 
String.valueOf(cfg.isMailUseTls()), Configuration.Type.BOOL, "Enable TLS", 
VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_TIMEOUT_CON, "30000", 
Configuration.Type.number,
+               addCfg(list, CONFIG_SMTP_TIMEOUT_CON, "30000", 
Configuration.Type.NUMBER,
                                "Socket connection timeout value in 
milliseconds. Default is 30 seconds (30000).", VER_1_9);
 
-               addCfg(list, CONFIG_SMTP_TIMEOUT, "30000", 
Configuration.Type.number,
+               addCfg(list, CONFIG_SMTP_TIMEOUT, "30000", 
Configuration.Type.NUMBER,
                                "Socket I/O timeout value in milliseconds. 
Default is 30 seconds (30000).", VER_1_9);
 
-               addCfg(list, CONFIG_APPLICATION_NAME, DEFAULT_APP_NAME, 
Configuration.Type.string, "Name of the Browser Title window", VER_3_0);
+               addCfg(list, CONFIG_APPLICATION_NAME, DEFAULT_APP_NAME, 
Configuration.Type.STRING, "Name of the Browser Title window", VER_3_0);
 
                // "1" == "EN"
-               addCfg(list, CONFIG_DEFAULT_LANG, 
String.valueOf(cfg.getDefaultLangId()), Configuration.Type.number, "Default 
System Language ID see languages.xml", VER_1_8);
+               addCfg(list, CONFIG_DEFAULT_LANG, 
String.valueOf(cfg.getDefaultLangId()), Configuration.Type.NUMBER, "Default 
System Language ID see languages.xml", VER_1_8);
 
-               addCfg(list, CONFIG_DOCUMENT_DPI, 
String.valueOf(cfg.getDocDpi()), Configuration.Type.number,
+               addCfg(list, CONFIG_DOCUMENT_DPI, 
String.valueOf(cfg.getDocDpi()), Configuration.Type.NUMBER,
                                "dpi for conversion of PDF to images (should be 
an integer between 50 and  600 with a default value of 150 dpi)", VER_2_0);
 
-               addCfg(list, CONFIG_DOCUMENT_QUALITY, 
String.valueOf(cfg.getDocQuality()), Configuration.Type.number,
+               addCfg(list, CONFIG_DOCUMENT_QUALITY, 
String.valueOf(cfg.getDocQuality()), Configuration.Type.NUMBER,
                                "compression quality for conversion of PDF to 
images (should be an integer between 1 and 100, with a default value of 90)", 
VER_2_0);
 
-               addCfg(list, CONFIG_PATH_IMAGEMAGIC, cfg.getImageMagicPath(), 
Configuration.Type.string, "Path to ImageMagick tools", VER_2_0);
+               addCfg(list, CONFIG_PATH_IMAGEMAGIC, cfg.getImageMagicPath(), 
Configuration.Type.STRING, "Path to ImageMagick tools", VER_2_0);
 
-               addCfg(list, CONFIG_PATH_SOX, cfg.getSoxPath(), 
Configuration.Type.string, "Path To SoX-Tools", VER_2_0);
+               addCfg(list, CONFIG_PATH_SOX, cfg.getSoxPath(), 
Configuration.Type.STRING, "Path To SoX-Tools", VER_2_0);
 
-               addCfg(list, CONFIG_PATH_FFMPEG, cfg.getFfmpegPath(), 
Configuration.Type.string, "Path To FFMPEG", VER_2_0);
-               addCfg(list, CONFIG_PATH_OFFICE, cfg.getOfficePath(), 
Configuration.Type.string,
+               addCfg(list, CONFIG_PATH_FFMPEG, cfg.getFfmpegPath(), 
Configuration.Type.STRING, "Path To FFMPEG", VER_2_0);
+               addCfg(list, CONFIG_PATH_OFFICE, cfg.getOfficePath(), 
Configuration.Type.STRING,
                                "The path to OpenOffice/LibreOffice (optional) 
please set this to the real path in case jodconverter is unable to find 
OpenOffice/LibreOffice installation automatically", VER_2_0);
 
-               addCfg(list, CONFIG_DASHBOARD_RSS_FEED1, cfg.getUrlFeed(), 
Configuration.Type.string, "Feed URL 1", VER_1_9);
+               addCfg(list, CONFIG_DASHBOARD_RSS_FEED1, cfg.getUrlFeed(), 
Configuration.Type.STRING, "Feed URL 1", VER_1_9);
 
-               addCfg(list, CONFIG_DASHBOARD_RSS_FEED2, cfg.getUrlFeed2(), 
Configuration.Type.string, "Feed URL 2", VER_1_9);
+               addCfg(list, CONFIG_DASHBOARD_RSS_FEED2, cfg.getUrlFeed2(), 
Configuration.Type.STRING, "Feed URL 2", VER_1_9);
 
-               addCfg(list, CONFIG_EMAIL_AT_REGISTER, 
String.valueOf(cfg.isSendEmailAtRegister()), Configuration.Type.bool,
+               addCfg(list, CONFIG_EMAIL_AT_REGISTER, 
String.valueOf(cfg.isSendEmailAtRegister()), Configuration.Type.BOOL,
                                "User get a EMail with their Account data.", 
VER_2_0);
 
-               addCfg(list, CONFIG_EMAIL_VERIFICATION, 
String.valueOf(cfg.isSendEmailWithVerficationCode()), Configuration.Type.bool,
+               addCfg(list, CONFIG_EMAIL_VERIFICATION, 
String.valueOf(cfg.isSendEmailWithVerficationCode()), Configuration.Type.BOOL,
                                String.format("User must activate their account 
by clicking on the "
                                                + "activation-link in the 
registering Email "
                                                + "It makes no sense to make 
this(%s) 'true' while "
                                                + "%s is 'false' cause you need 
to send a EMail.", CONFIG_EMAIL_VERIFICATION, CONFIG_EMAIL_AT_REGISTER), 
VER_2_0);
 
-               addCfg(list, CONFIG_APPLICATION_BASE_URL, cfg.getBaseUrl(), 
Configuration.Type.string, "Base URL your OPenmeetings installation will be 
accessible at.", "3.0.2");
+               addCfg(list, CONFIG_APPLICATION_BASE_URL, cfg.getBaseUrl(), 
Configuration.Type.STRING, "Base URL your OPenmeetings installation will be 
accessible at.", "3.0.2");
 
                // ***************************************
                // ***************************************
                // SIP Integration Coniguration Values
                // ***************************************
 
-               addCfg(list, CONFIG_SIP_ENABLED, 
String.valueOf(cfg.isSipEnable()), Configuration.Type.bool, "Enable to enable 
the red5SIP integration ", VER_1_9);
-               addCfg(list, CONFIG_SIP_ROOM_PREFIX, cfg.getSipRoomPrefix(), 
Configuration.Type.string, "Numerical prefix for OM rooms created inside the 
SIP", VER_1_9);
-               addCfg(list, CONFIG_SIP_EXTEN_CONTEXT, 
cfg.getSipExtenContext(), Configuration.Type.string, "Enable to enable the 
red5SIP integration ", VER_1_9);
+               addCfg(list, CONFIG_SIP_ENABLED, 
String.valueOf(cfg.isSipEnable()), Configuration.Type.BOOL, "Enable to enable 
the red5SIP integration ", VER_1_9);
+               addCfg(list, CONFIG_SIP_ROOM_PREFIX, cfg.getSipRoomPrefix(), 
Configuration.Type.STRING, "Numerical prefix for OM rooms created inside the 
SIP", VER_1_9);
+               addCfg(list, CONFIG_SIP_EXTEN_CONTEXT, 
cfg.getSipExtenContext(), Configuration.Type.STRING, "Enable to enable the 
red5SIP integration ", VER_1_9);
 
                // ***************************************
                // ***************************************
                // Timezone settings
                // ***************************************
 
-               addCfg(list, CONFIG_DEFAULT_TIMEZONE, cfg.getTimeZone(), 
Configuration.Type.string, "This is the default timezone if nothing is 
specified", VER_1_9);
+               addCfg(list, CONFIG_DEFAULT_TIMEZONE, cfg.getTimeZone(), 
Configuration.Type.STRING, "This is the default timezone if nothing is 
specified", VER_1_9);
 
                // ***************************************
                // ***************************************
                // additional settings
                // ***************************************
 
-               addCfg(list, CONFIG_SCREENSHARING_QUALITY, "1", 
Configuration.Type.number,
+               addCfg(list, CONFIG_SCREENSHARING_QUALITY, "1", 
Configuration.Type.NUMBER,
                                "Default selection in ScreenSharing Quality:\n 
0 - bigger frame rate, no resize\n 1 - no resize\n 2 - size == 1/2 of selected 
area\n 3 - size == 3/8 of selected area", VER_3_0_3);
 
-               addCfg(list, CONFIG_SCREENSHARING_FPS, "10", 
Configuration.Type.number, "Default selection in ScreenSharing FPS", VER_3_0_3);
-               addCfg(list, CONFIG_SCREENSHARING_FPS_SHOW, 
String.valueOf(true), Configuration.Type.bool, "Is screensharing FPS should be 
displayed or not", VER_3_0_3);
-               addCfg(list, CONFIG_SCREENSHARING_ALLOW_REMOTE, 
String.valueOf(true), Configuration.Type.bool
+               addCfg(list, CONFIG_SCREENSHARING_FPS, "10", 
Configuration.Type.NUMBER, "Default selection in ScreenSharing FPS", VER_3_0_3);
+               addCfg(list, CONFIG_SCREENSHARING_FPS_SHOW, 
String.valueOf(true), Configuration.Type.BOOL, "Is screensharing FPS should be 
displayed or not", VER_3_0_3);
+               addCfg(list, CONFIG_SCREENSHARING_ALLOW_REMOTE, 
String.valueOf(true), Configuration.Type.BOOL
                                , "Is remote control will be enabled while 
screensharing. Allowing remote control will be not possible in case it is set 
to 'false'", "3.0.4");
 
-               addCfg(list, CONFIG_DASHBOARD_SHOW_MYROOMS, 
String.valueOf(true), Configuration.Type.bool, "Show 'My Rooms' widget on 
dashboard", VER_1_9);
+               addCfg(list, CONFIG_DASHBOARD_SHOW_MYROOMS, 
String.valueOf(true), Configuration.Type.BOOL, "Show 'My Rooms' widget on 
dashboard", VER_1_9);
 
-               addCfg(list, CONFIG_DASHBOARD_SHOW_CHAT, String.valueOf(true), 
Configuration.Type.bool, "Show 'Global Chat' outside the room", VER_1_9);
+               addCfg(list, CONFIG_DASHBOARD_SHOW_CHAT, String.valueOf(true), 
Configuration.Type.BOOL, "Show 'Global Chat' outside the room", VER_1_9);
 
-               addCfg(list, CONFIG_DASHBOARD_SHOW_RSS, String.valueOf(false), 
Configuration.Type.bool, "Show RSS widget on dashboard", VER_1_9);
+               addCfg(list, CONFIG_DASHBOARD_SHOW_RSS, String.valueOf(false), 
Configuration.Type.BOOL, "Show RSS widget on dashboard", VER_1_9);
 
-               addCfg(list, CONFIG_MAX_UPLOAD_SIZE, 
String.valueOf(DEFAULT_MAX_UPLOAD_SIZE), Configuration.Type.number,
+               addCfg(list, CONFIG_MAX_UPLOAD_SIZE, 
String.valueOf(DEFAULT_MAX_UPLOAD_SIZE), Configuration.Type.NUMBER,
                                "Maximum size of upload file (bytes)", VER_1_8);
 
-               addCfg(list, CONFIG_APPOINTMENT_REMINDER_MINUTES, 
String.valueOf(DEFAULT_MINUTES_REMINDER_SEND), Configuration.Type.number,
+               addCfg(list, CONFIG_APPOINTMENT_REMINDER_MINUTES, 
String.valueOf(DEFAULT_MINUTES_REMINDER_SEND), Configuration.Type.NUMBER,
                                "The number of minutes before reminder emails 
are send. Set to 0 to disable reminder emails", VER_1_9);
 
-               addCfg(list, CONFIG_LOGIN_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.number,
+               addCfg(list, CONFIG_LOGIN_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.NUMBER,
                                "Number of chars needed in a user login", 
VER_1_9);
 
-               addCfg(list, CONFIG_PASS_MIN_LENGTH, 
String.valueOf(USER_PASSWORD_MINIMUM_LENGTH), Configuration.Type.number,
+               addCfg(list, CONFIG_PASS_MIN_LENGTH, 
String.valueOf(USER_PASSWORD_MINIMUM_LENGTH), Configuration.Type.NUMBER,
                                "Number of chars needed in a user password", 
VER_1_9);
 
-               addCfg(list, CONFIG_CALENDAR_ROOM_CAPACITY, "50", 
Configuration.Type.number,
+               addCfg(list, CONFIG_CALENDAR_ROOM_CAPACITY, "50", 
Configuration.Type.NUMBER,
                                "Default number of participants conference room 
created via calendar", VER_1_9);
 
-               addCfg(list, CONFIG_KEYCODE_ARRANGE, "119", 
Configuration.Type.number
-                               , "A hot key code for arrange video windows 
functionality. Should be used with Shift key. (Keycode 119 is F8)", VER_2_0);
-               addCfg(list, CONFIG_KEYCODE_MUTE_OTHERS, "123", 
Configuration.Type.number
-                               , "A hot key code for the 'mute others' 
functionality. Should be used with Shift key. (Keycode 123 is F12)", VER_2_0);
-               addCfg(list, CONFIG_KEYCODE_MUTE, "118", 
Configuration.Type.number
-                               , "A hot key code for the 'mute/unmute audio' 
functionality. Should be used with Shift key. (Keycode 118 is F7)", VER_2_0);
+               addCfg(list, CONFIG_KEYCODE_ARRANGE, "Shift+F8", 
Configuration.Type.HOTKEY
+                               , "A hot key code for arrange video windows 
functionality", VER_2_0);
+               addCfg(list, CONFIG_KEYCODE_MUTE_OTHERS, "Shift+F12", 
Configuration.Type.HOTKEY
+                               , "A hot key code for the 'mute others' 
functionality", VER_2_0);
+               addCfg(list, CONFIG_KEYCODE_MUTE, "Shift+F7", 
Configuration.Type.HOTKEY
+                               , "A hot key code for the 'mute/unmute audio' 
functionality", VER_2_0);
 
                // system-wide ldap params
-               addCfg(list, CONFIG_DEFAULT_LDAP_ID, "0", 
Configuration.Type.number, "Ldap domain selected by default in the login 
screen", VER_1_9);
+               addCfg(list, CONFIG_DEFAULT_LDAP_ID, "0", 
Configuration.Type.NUMBER, "Ldap domain selected by default in the login 
screen", VER_1_9);
 
                // set inviter's email address as ReplyTo in email invitations
-               addCfg(list, CONFIG_REPLY_TO_ORGANIZER, 
String.valueOf(cfg.isReplyToOrganizer()), Configuration.Type.bool,
+               addCfg(list, CONFIG_REPLY_TO_ORGANIZER, 
String.valueOf(cfg.isReplyToOrganizer()), Configuration.Type.BOOL,
                                "Set inviter's email address as ReplyTo in 
email invitations", VER_2_0);
 
-               addCfg(list, CONFIG_DEFAULT_LANDING_ZONE, "user/dashboard", 
Configuration.Type.string
+               addCfg(list, CONFIG_DEFAULT_LANDING_ZONE, "user/dashboard", 
Configuration.Type.STRING
                                , "Area to be shown to the user after login. 
Possible values are: "
                                                + "user/dashboard, 
user/calendar, user/record, rooms/my, rooms/group, rooms/public, admin/user, 
admin/connection"
                                                + ", admin/group, admin/room, 
admin/config, admin/lang, admin/ldap, admin/backup, admin/server, 
admin/oauth2", "2.1.x");
 
                // oauth2 params
-               addCfg(list, CONFIG_IGNORE_BAD_SSL, String.valueOf(false), 
Configuration.Type.bool,
+               addCfg(list, CONFIG_IGNORE_BAD_SSL, String.valueOf(false), 
Configuration.Type.BOOL,
                                "Set \"yes\" or \"no\" to enable/disable ssl 
certifications checking for OAuth2", VER_3_0);
 
-               addCfg(list, CONFIG_REDIRECT_URL_FOR_EXTERNAL, "", 
Configuration.Type.string,
+               addCfg(list, CONFIG_REDIRECT_URL_FOR_EXTERNAL, "", 
Configuration.Type.STRING,
                                "Users entered the room via invitationHash or 
secureHash will be redirected to this URL on connection lost", VER_3_0);
-               addCfg(list, CONFIG_GOOGLE_ANALYTICS_CODE, null, 
Configuration.Type.string, "Code for Google Analytics", "3.1.0");
-               addCfg(list, CONFIG_HEADER_CSP, HEADER_CSP_SELF, 
Configuration.Type.string, String.format("Value for 'Content-Security-Policy' 
header (default: %s), have to be modified to enable Google analytics site: 
https://content-security-policy.com/";, HEADER_CSP_SELF), VER_3_3_0);
-               addCfg(list, CONFIG_EXT_PROCESS_TTL, 
String.valueOf(getExtProcessTtl()), Configuration.Type.number, 
String.format("Time to live in minutes for external processes such as 
conversion via ffmpeg (default %s minutes)", getExtProcessTtl()), VER_3_3_0);
-               addCfg(list, CONFIG_MYROOMS_ENABLED, String.valueOf(true), 
Configuration.Type.bool, "Users are allowed to create personal rooms", "3.3.2");
-               addCfg(list, CONFIG_REMINDER_MESSAGE, null, 
Configuration.Type.string, "Reminder message to notify about upcoming 
appointment, generated message will be used if not set", VER_2_0);
-               addCfg(list, CONFIG_MP4_AUDIO_RATE, 
String.valueOf(getAudioRate()), Configuration.Type.number, "Audio sampling rate 
(in Hz) for MP4 video", "4.0.1");
-               addCfg(list, CONFIG_MP4_AUDIO_BITRATE, 
String.valueOf(getAudioBitrate()), Configuration.Type.string, "Audio bitrate 
for MP4 video", "4.0.1");
-               addCfg(list, CONFIG_REST_ALLOW_ORIGIN, null, 
Configuration.Type.string, "List of addresses browser Ajax REST requests are 
allowed from", "4.0.2");
-               addCfg(list, CONFIG_FNAME_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.number,
+               addCfg(list, CONFIG_GOOGLE_ANALYTICS_CODE, null, 
Configuration.Type.STRING, "Code for Google Analytics", "3.1.0");
+               addCfg(list, CONFIG_HEADER_CSP, HEADER_CSP_SELF, 
Configuration.Type.STRING, String.format("Value for 'Content-Security-Policy' 
header (default: %s), have to be modified to enable Google analytics site: 
https://content-security-policy.com/";, HEADER_CSP_SELF), VER_3_3_0);
+               addCfg(list, CONFIG_EXT_PROCESS_TTL, 
String.valueOf(getExtProcessTtl()), Configuration.Type.NUMBER, 
String.format("Time to live in minutes for external processes such as 
conversion via ffmpeg (default %s minutes)", getExtProcessTtl()), VER_3_3_0);
+               addCfg(list, CONFIG_MYROOMS_ENABLED, String.valueOf(true), 
Configuration.Type.BOOL, "Users are allowed to create personal rooms", "3.3.2");
+               addCfg(list, CONFIG_REMINDER_MESSAGE, null, 
Configuration.Type.STRING, "Reminder message to notify about upcoming 
appointment, generated message will be used if not set", VER_2_0);
+               addCfg(list, CONFIG_MP4_AUDIO_RATE, 
String.valueOf(getAudioRate()), Configuration.Type.NUMBER, "Audio sampling rate 
(in Hz) for MP4 video", "4.0.1");
+               addCfg(list, CONFIG_MP4_AUDIO_BITRATE, 
String.valueOf(getAudioBitrate()), Configuration.Type.STRING, "Audio bitrate 
for MP4 video", "4.0.1");
+               addCfg(list, CONFIG_REST_ALLOW_ORIGIN, null, 
Configuration.Type.STRING, "List of addresses browser Ajax REST requests are 
allowed from", "4.0.2");
+               addCfg(list, CONFIG_FNAME_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.NUMBER,
                                "Number of chars needed in a user first name", 
"4.0.4");
-               addCfg(list, CONFIG_LNAME_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.number,
+               addCfg(list, CONFIG_LNAME_MIN_LENGTH, 
String.valueOf(USER_LOGIN_MINIMUM_LENGTH), Configuration.Type.NUMBER,
                                "Number of chars needed in a user last name", 
"4.0.4");
-               addCfg(list, CONFIG_CHAT_SEND_ON_ENTER, String.valueOf(false), 
Configuration.Type.bool,
+               addCfg(list, CONFIG_CHAT_SEND_ON_ENTER, String.valueOf(false), 
Configuration.Type.BOOL,
                                "Controls if chat message will be set on Enter 
(default: send on Ctrl+Enter)", "4.0.5");
-               addCfg(list, CONFIG_MP4_VIDEO_PRESET, "medium", 
Configuration.Type.bool,
+               addCfg(list, CONFIG_MP4_VIDEO_PRESET, "medium", 
Configuration.Type.BOOL,
                                "Preset (encoder optimization settings) to be 
used while performing mp4 conversion."
                                        + "Valid values are: ultrafast, 
superfast, veryfast, faster, fast, medium, slow, slower, veryslow", "4.0.5");
-               addCfg(list, CONFIG_CAM_FPS, "30", Configuration.Type.number, 
"Camera FPS, should be positive number in range (0, 60]", VER_5_0_0);
-               addCfg(list, CONFIG_MIC_RATE, "22", Configuration.Type.number, 
"The rate at which the microphone should capture sound, in kHz. The default 
value is 22 kHz.", VER_5_0_0);
-               addCfg(list, CONFIG_MIC_ECHO, String.valueOf(true), 
Configuration.Type.bool, "Whether or not echo cancellation is preferred and/or 
required.", VER_5_0_0);
-               addCfg(list, CONFIG_MIC_NOISE, String.valueOf(true), 
Configuration.Type.bool, "Whether noise suppression is preferred and/or 
required.", VER_5_0_0);
-               addCfg(list, CONFIG_CSP_XFRAME, HEADER_XFRAME_SELF, 
Configuration.Type.string, String.format("Value for 'frame-src' directive of 
'Content-Security-Policy' header (default: %s), more info: 
https://w3c.github.io/webappsec-csp/";, HEADER_XFRAME_SELF), VER_5_0_0);
-               addCfg(list, CONFIG_DISPLAY_NAME_EDITABLE, 
String.valueOf(false), Configuration.Type.bool, "Is user will be able to edit 
his/her display name (default false).", "4.0.7");
+               addCfg(list, CONFIG_CAM_FPS, "30", Configuration.Type.NUMBER, 
"Camera FPS, should be positive number in range (0, 60]", VER_5_0_0);
+               addCfg(list, CONFIG_MIC_RATE, "22", Configuration.Type.NUMBER, 
"The rate at which the microphone should capture sound, in kHz. The default 
value is 22 kHz.", VER_5_0_0);
+               addCfg(list, CONFIG_MIC_ECHO, String.valueOf(true), 
Configuration.Type.BOOL, "Whether or not echo cancellation is preferred and/or 
required.", VER_5_0_0);
+               addCfg(list, CONFIG_MIC_NOISE, String.valueOf(true), 
Configuration.Type.BOOL, "Whether noise suppression is preferred and/or 
required.", VER_5_0_0);
+               addCfg(list, CONFIG_CSP_XFRAME, HEADER_XFRAME_SELF, 
Configuration.Type.STRING, String.format("Value for 'frame-src' directive of 
'Content-Security-Policy' header (default: %s), more info: 
https://w3c.github.io/webappsec-csp/";, HEADER_XFRAME_SELF), VER_5_0_0);
+               addCfg(list, CONFIG_DISPLAY_NAME_EDITABLE, 
String.valueOf(false), Configuration.Type.BOOL, "Is user will be able to edit 
his/her display name (default false).", "4.0.7");
+               addCfg(list, CONFIG_KEYCODE_QUICKPOLL, "Ctrl+Alt+Q", 
Configuration.Type.HOTKEY
+                               , "A hot key code to start quick poll", 
"4.0.10");
                return list;
        }
        public void loadConfiguration(InstallationConfig cfg) {
diff --git 
a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
 
b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
index 4f91a6e..575e469 100644
--- 
a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
+++ 
b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
@@ -95,6 +95,7 @@ public class OpenmeetingsVariables {
        public static final String CONFIG_LNAME_MIN_LENGTH = 
"user.lname.minimum.length";
        public static final String CONFIG_CHAT_SEND_ON_ENTER = 
"chat.send.on.enter";
        public static final String CONFIG_DISPLAY_NAME_EDITABLE = 
"display.name.editable";
+       public static final String CONFIG_KEYCODE_QUICKPOLL = 
"start.quickpoll.keycode";
 
        public static final String HEADER_XFRAME_SELF = "'self'";
        public static final String HEADER_CSP_SELF = "default-src 'self'; 
style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 
'unsafe-eval'; img-src 'self' data:; media-src 'self' blob:;";
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigForm.java
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigForm.java
index 0eac1cf..4f35c30 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigForm.java
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigForm.java
@@ -55,9 +55,17 @@ import org.apache.wicket.validation.ValidationError;
 public class ConfigForm extends AdminBaseForm<Configuration> {
        private static final long serialVersionUID = 1L;
        private final WebMarkupContainer listContainer;
-       private final TextArea<String> valueS;
-       private final TextField<Long> valueN;
-       private final CheckBox valueB;
+       private final TextArea<String> valueS = new TextArea<>("valueS");
+       private final TextField<Long> valueN = new TextField<>("valueN") {
+               private static final long serialVersionUID = 1L;
+
+               @Override
+               protected String[] getInputTypes() {
+                       return new String[] {"number"};
+               }
+       };
+       private final CheckBox valueB = new CheckBox("valueB");
+       private final TextField<String> valueH = new TextField<>("value");
        @SpringBean
        private ConfigurationDao cfgDao;
 
@@ -65,20 +73,6 @@ public class ConfigForm extends AdminBaseForm<Configuration> 
{
                super(id, new CompoundPropertyModel<>(configuration));
                setOutputMarkupId(true);
                this.listContainer = listContainer;
-               valueS = new TextArea<>("valueS");
-               valueN = new TextField<>("valueN") {
-                       private static final long serialVersionUID = 1L;
-
-                       @Override
-                       protected String[] getInputTypes() {
-                               return new String[] {"number"};
-                       }
-               };
-               valueB = new CheckBox("valueB");
-               add(new DateLabel("updated"));
-               add(new Label("user.login"));
-               add(new TextArea<String>("comment"));
-               update(null);
        }
 
        private void refresh(AjaxRequestTarget target) {
@@ -87,11 +81,12 @@ public class ConfigForm extends 
AdminBaseForm<Configuration> {
 
        private void update(AjaxRequestTarget target) {
                Configuration c = getModelObject();
-               valueS.setVisible(Type.string == c.getType());
-               valueN.setVisible(Type.number == c.getType());
-               valueB.setVisible(Type.bool == c.getType());
+               valueS.setVisible(Type.STRING == c.getType());
+               valueN.setVisible(Type.NUMBER == c.getType());
+               valueB.setVisible(Type.BOOL == c.getType());
+               valueH.setVisible(Type.HOTKEY == c.getType());
                if (target != null) {
-                       target.add(valueS, valueN, valueB);
+                       target.add(valueS, valueN, valueB, valueH);
                }
        }
 
@@ -104,6 +99,11 @@ public class ConfigForm extends 
AdminBaseForm<Configuration> {
        @Override
        protected void onInitialize() {
                super.onInitialize();
+               add(new DateLabel("updated"));
+               add(new Label("user.login"));
+               add(new TextArea<String>("comment"));
+               update(null);
+
                add(new DropDownChoice<>("type", Arrays.asList(Type.values()), 
new IChoiceRenderer<Type>() {
                        private static final long serialVersionUID = 1L;
 
@@ -148,6 +148,7 @@ public class ConfigForm extends 
AdminBaseForm<Configuration> {
                add(valueS.setLabel(new 
ResourceModel("271")).setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
                add(valueN.setLabel(new 
ResourceModel("271")).setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
                add(valueB.setLabel(new 
ResourceModel("271")).setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
+               add(valueH.setLabel(new 
ResourceModel("271")).setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
        }
 
        @Override
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigsPanel.html
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigsPanel.html
index daaa8ec..52b651e 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigsPanel.html
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/admin/configurations/ConfigsPanel.html
@@ -20,6 +20,29 @@
 -->
 <!DOCTYPE html>
 <html xmlns:wicket="http://wicket.apache.org";>
+<wicket:head>
+       <script>
+               function configHandleKey(evt) {
+                       const inp = $(evt.target);
+                       evt.preventDefault();
+                       let val = '';
+                       if (evt.ctrlKey) {
+                               val += 'Ctrl+';
+                       }
+                       if (evt.altKey) {
+                               val += 'Alt+';
+                       }
+                       if (evt.shiftKey) {
+                               val += 'Shift+';
+                       }
+                       val += evt.key;
+                       console.info(val);
+                       if (evt.keyCode !== 16 && evt.keyCode !== 17 && 
evt.keyCode !== 18 && inp.length == 1) {
+                               inp.val(val);
+                       }
+               }
+       </script>
+</wicket:head>
 <wicket:extend>
        <div class="adminPanelColumnTable">
                <div class="adminNav" wicket:id="navigator">[dataview 
navigator]</div>
@@ -74,6 +97,10 @@
                                                                </label>
                                                        </div>
                                                </div>
+                                               <div wicket:enclosure="value">
+                                                       <label 
wicket:for="value"><wicket:message key="271" /></label>
+                                                       <input type="text" 
onkeydown="configHandleKey(event)" onpaste="return false;" wicket:id="value"/>
+                                               </div>
                                        </div>
                                        <div class="formelement">
                                                <label><wicket:message 
key="268" /></label><span wicket:id="updated"/>
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/PollsSubMenu.java
 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/PollsSubMenu.java
index 773d453..6978996 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/PollsSubMenu.java
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/menu/PollsSubMenu.java
@@ -18,6 +18,13 @@
  */
 package org.apache.openmeetings.web.room.menu;
 
+import static org.apache.openmeetings.web.app.WebSession.getUserId;
+import static 
org.apache.openmeetings.web.room.sidebar.RoomSidebar.PARAM_ACTION;
+import static 
org.apache.openmeetings.web.util.CallbackFunctionHelper.getNamedFunction;
+import static org.apache.wicket.ajax.attributes.CallbackParameter.explicit;
+
+import java.io.Serializable;
+
 import org.apache.openmeetings.db.dao.room.PollDao;
 import org.apache.openmeetings.db.entity.basic.Client;
 import org.apache.openmeetings.db.entity.room.Room;
@@ -39,19 +46,13 @@ import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.Serializable;
-
-import static org.apache.openmeetings.web.app.WebSession.getUserId;
-import static 
org.apache.openmeetings.web.room.sidebar.RoomSidebar.PARAM_ACTION;
-import static 
org.apache.openmeetings.web.util.CallbackFunctionHelper.getNamedFunction;
-import static org.apache.wicket.ajax.attributes.CallbackParameter.explicit;
-
 public class PollsSubMenu implements Serializable {
        private static final long serialVersionUID = 1L;
        private static final Logger log = 
LoggerFactory.getLogger(PollsSubMenu.class);
        private static final String FUNC_QPOLL_ACTION = "quickPollAction";
        private static final String PARAM_VOTE = "vote";
        private static final String ACTION_CLOSE = "close";
+       private static final String ACTION_OPEN = "open";
        private final RoomPanel room;
        private final RoomMenuPanel mp;
        private final CreatePollDialog createPoll;
@@ -73,7 +74,9 @@ public class PollsSubMenu implements Serializable {
                                }
                                String action = 
mp.getRequest().getRequestParameters().getParameterValue(PARAM_ACTION).toString();
                                Client c = room.getClient();
-                               if (ACTION_CLOSE.equals(action)) {
+                               if (ACTION_OPEN.equals(action)) {
+                                       qpollManager.start(room.getClient());
+                               } else if (ACTION_CLOSE.equals(action)) {
                                        qpollManager.close(c);
                                } else if (PARAM_VOTE.equals(action)) {
                                        final boolean curVote = 
mp.getRequest().getRequestParameters().getParameterValue(PARAM_VOTE).toBoolean();
diff --git 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
index 9cf512f..023f176 100644
--- 
a/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
+++ 
b/openmeetings-web/src/main/java/org/apache/openmeetings/web/room/raw-room.js
@@ -66,31 +66,27 @@ var Room = (function() {
                        return false;
                }
        }
+       function __keyPressed(hotkey, e) {
+               return hotkey.alt === e.altKey
+                       && hotkey.ctrl === e.ctrlKey
+                       && hotkey.shift === e.shiftKey
+                       && hotkey.key.toUpperCase() === e.key.toUpperCase();
+       }
        function _keyHandler(e) {
-               if (e.shiftKey) {
-                       switch (e.which) {
-                               case options.keycode.arrange: // Shift+F8 by 
default
-                                       VideoUtil.arrange();
-                                       break;
-                               case options.keycode.muteothers: // Shift+F12 
by default
-                               {
-                                       const v = _getSelfAudioClient();
-                                       if (v !== null) {
-                                               
VideoManager.clickMuteOthers(Room.getOptions().uid);
-                                       }
-                               }
-                                       break;
-                               case options.keycode.mute: // Shift+F7 by 
default
-                               {
-                                       const v = _getSelfAudioClient();
-                                       if (v !== null) {
-                                               v.mute(!v.isMuted());
-                                       }
-                               }
-                                       break;
-                               default:
-                                       // no-op
+               if (__keyPressed(options.keycode.arrange, e)) {
+                       VideoUtil.arrange();
+               } else if (__keyPressed(options.keycode.muteothers, e)) {
+                       const v = _getSelfAudioClient();
+                       if (v !== null) {
+                               
VideoManager.clickMuteOthers(Room.getOptions().uid);
+                       }
+               } else if (__keyPressed(options.keycode.mute, e)) {
+                       const v = _getSelfAudioClient();
+                       if (v !== null) {
+                               v.mute(!v.isMuted());
                        }
+               } else if (__keyPressed(options.keycode.quickpoll, e)) {
+                       quickPollAction('open');
                }
                if (e.which === 27) {
                        $('#wb-rename-menu').hide();

Reply via email to