xpra icon
Bug tracker and wiki

Ticket #2269: floating-menu.patch

File floating-menu.patch, 42.4 KB (added by Antoine Martin, 16 months ago)

work in progress patch

  • html5/connect.html

     
    236236                                        <input type="checkbox" id="swap_keys"> <span>Swap command and control key</span>
    237237                                  </li>
    238238                                  <li class="list-group-item">
    239                                         <input type="checkbox" id="top_bar"> <span>Show top bar</span>, <input type="checkbox" id="clock"> <span>show server clock</span>
     239                                        <input type="checkbox" id="floating_menu"> <span>Floating Menu</span>, <input type="checkbox" id="top_bar"> <span>Top Bar</span>, <input type="checkbox" id="clock"> <span>Server clock</span>
    240240                                  </li>
    241241                                  <li class="list-group-item">
    242242                                        <input type="checkbox" id="video"> <span>Video <input type="checkbox" id="mediasource_video"> Native decoding</span>
     
    323323                "exit_with_children", "exit_with_client",
    324324                "sharing", "steal", "reconnect", "swap_keys",
    325325                "video", "mediasource_video",
    326                 "ssl", "insecure", "top_bar", "clock",
     326                "ssl", "insecure", "top_bar", "floating_menu", "clock",
    327327                "debug_main", "debug_keyboard", "debug_geometry", "debug_mouse", "debug_clipboard", "debug_draw", "debug_audio", "debug_network",
    328328                ];
    329329        for (var i = 0; i < bool_props.length; i++) {
     
    538538        var bool_props = ["clipboard", "printing", "file_transfer",
    539539                        "exit_with_children", "exit_with_client",
    540540                        "sharing", "steal", "reconnect", "swap_keys",
    541                         "video", "mediasource_video", "top_bar", "clock",
     541                        "video", "mediasource_video", "top_bar", "floating_menu", "clock",
    542542                        "debug_main", "debug_keyboard", "debug_geometry", "debug_mouse", "debug_clipboard", "debug_draw", "debug_audio", "debug_network"];
    543         var default_on = ["steal", "clipboard", "printing", "file_transfer", "reconnect", "top_bar", "clock", "exit_with_children", "exit_with_client", "video"];
     543        var default_on = ["steal", "clipboard", "printing", "file_transfer", "reconnect", "floating_menu", "clock", "exit_with_children", "exit_with_client", "video"];
    544544        if (Utilities.isMacOS()) {
    545545                default_on.push("swap_keys");
    546546        }
     
    557557        toggle_mediasource_video();
    558558
    559559        var top_bar_checkbox = $("#top_bar");
     560        var floating_menu_checkbox = $("#floating_menu");
    560561        function set_clock_visibility() {
    561                 if (top_bar_checkbox.is(':checked')) {
     562                if (top_bar_checkbox.is(':checked') || floating_menu_checkbox.is(':checked')) {
    562563                        $("#clock").removeAttr("disabled");
    563564                }
    564565                else {
     
    565566                    $("#clock").attr("disabled", true);
    566567                }
    567568        }
    568         top_bar_checkbox.change(set_clock_visibility);
     569       
     570        function top_bar_change() {
     571                set_clock_visibility()
     572                if (top_bar_checkbox.is(':checked')) {
     573                        floating_menu_checkbox.prop('checked', false);;
     574                }
     575               
     576        }
     577       
     578        function floating_menu_change() {
     579                set_clock_visibility()
     580                if (floating_menu_checkbox.is(':checked')) {
     581                        top_bar_checkbox.prop('checked', false);;
     582                }
     583               
     584        }
     585
     586        top_bar_checkbox.change(top_bar_change);
     587        floating_menu_checkbox.change(floating_menu_change);
    569588        set_clock_visibility();
    570589
    571590        $("#expandopts").click(function() {
  • html5/css/client.css

     
    137137        padding-right: 5px;
    138138        cursor: pointer;
    139139        padding-top: 7px;
    140         background-color: #c0c0c0;
     140        background-color: transparent;
    141141}
    142142.above {
    143143        z-index: 10000;
     
    189189        width: 600px;
    190190        height: auto;
    191191        z-index: 10001;
     192        background-color: white;
    192193        transition: height 0.5s, opacity 0.5s, top 0.5s, box-shadow 0.5s, bottom 0.5s;
    193194        box-shadow: 0 1rem 2rem rgba(21, 36, 48, 0.75);
    194195        overflow: hidden;
  • html5/css/icon.css

     
     1@font-face {
     2    font-family: "materialicons";
     3    src: url(../icons/materialicons-regular.woff) format("woff");
     4}
     5
     6.Icon, *[data-icon]:before {
     7    display: inline-block;
     8    position: relative;
     9    width: 40px;
     10    height: 40px;
     11    line-height: 40px;
     12
     13    font-family: "materialicons";
     14    font-size: 24px;
     15    text-align: center;
     16
     17    content: attr(data-icon);
     18
     19    /* This is important for IE, which has it off by default */
     20    font-feature-settings: "liga" 1;
     21}
     22
     23.Icon.-small {
     24    font-size: 18px;
     25}
  • html5/css/menu-skin.css

     
     1/*
     2MIT License
     3
     4Copyright (c) 2019 Mark Harkin, 2016 Dylan Hicks (aka. dylanh333)
     5
     6Permission is hereby granted, free of charge, to any person obtaining a copy
     7of this software and associated documentation files (the "Software"), to deal
     8in the Software without restriction, including without limitation the rights
     9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10copies of the Software, and to permit persons to whom the Software is
     11furnished to do so, subject to the following conditions:
     12
     13The above copyright notice and this permission notice shall be included in all
     14copies or substantial portions of the Software.
     15
     16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22SOFTWARE.
     23
     24*/
     25
     26#float_menu {
     27    display: inline-block;
     28        height: 30px;
     29        padding: 0px 0px 0px 10px;
     30        z-index: 100000;
     31        background: repeating-linear-gradient(
     32                  90deg,
     33                  white,
     34                  white 1px,
     35                  black 1px,
     36                  black 2px
     37                );
     38
     39        border-color: grey;
     40        border-width: 1px;
     41        border-style: solid;
     42        box-shadow: 0px 10px 25px rgba(0, 0, 0, 0.5);
     43}
     44
     45.menu-divleft {
     46    float:left;
     47    clear:left;
     48}
     49
     50.menu-divright {
     51    float:right;
     52    clear:right;
     53}
     54
     55.menu-content-left {
     56    white-space: nowrap;
     57    float: left;
     58    width: 24px;
     59    height: 24px;
     60    padding: 3px 2px;
     61    vertical-align:middle;
     62    text-decoration: none;
     63    display: inline;
     64}
     65
     66.menu-content-right {
     67    white-space: nowrap;
     68    float: right;
     69    width: 16px;
     70    height: 16px;
     71    padding: 7px 2px;
     72    vertical-align:middle;
     73    text-decoration: none;
     74    display: inline;
     75}
     76
     77.windowlist-li {
     78    min-width: 400px;
     79}
     80
     81.Menu {
     82    color: black;
     83}
     84    /* Foreground */
     85    .Menu,
     86    .Menu li.-hasSubmenu > a:after {
     87        color: black;
     88        border-color: black; /* chevron colour */
     89    }
     90
     91    /* Background */
     92    .Menu,
     93    .Menu li ul {
     94        background: white;
     95    }
     96
     97    /* Border */
     98    .Menu,
     99    .Menu li ul {
     100        box-shadow: none;
     101    }
     102
     103    .Menu li ul,
     104    .Menu.-floating {
     105        border-radius: 3px;
     106    }
     107    .Menu.-horizontal > li > ul {
     108        border-top-left-radius: 0px;
     109        border-top-right-radius: 0px;
     110    }
     111    .Menu:not(.-alignRight) li > ul,
     112    .Menu.-floating:not(.-alignRight) {
     113        border-top-left-radius: 0px;
     114    }
     115    .Menu.-alignRight li > ul,
     116    .Menu.-floating.-alignRight {
     117        border-top-right-radius: 0px;
     118    }
     119
     120/* Drop shadow on Menus and header */
     121.Menu li ul,
     122.Menu.-floating {
     123    box-shadow:
     124        0px 0px 0px 1px rgba(0,0,0,0.2),
     125        0px 3px 1px 0px rgba(0,0,0,0.2),
     126        0px 6px 12px 0px rgba(0,0,0,0.15)
     127    ;
     128}
     129
  • html5/css/menu.css

     
     1/*
     2MIT License
     3
     4Copyright (c) 2019 Mark Harkin, 2016 Dylan Hicks (aka. dylanh333)
     5
     6Permission is hereby granted, free of charge, to any person obtaining a copy
     7of this software and associated documentation files (the "Software"), to deal
     8in the Software without restriction, including without limitation the rights
     9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10copies of the Software, and to permit persons to whom the Software is
     11furnished to do so, subject to the following conditions:
     12
     13The above copyright notice and this permission notice shall be included in all
     14copies or substantial portions of the Software.
     15
     16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22SOFTWARE.
     23
     24*/
     25
     26.Menu {
     27    display: none;
     28    position: relative;
     29    z-index: 100000;
     30}
     31    /* Three basic menu layouts */
     32    /* This also enforces that menu is a ul, and that
     33     * layout modifier is specified
     34     */
     35    ul.Menu.-horizontal,
     36    ul.Menu.-vertical {
     37        display: inline-block;
     38    }
     39    ul.Menu.-floating {
     40        display: block;
     41        position: absolute;
     42    }
     43
     44    /* Menu and menu-item layout */
     45    .Menu,
     46    .Menu li,
     47    .Menu li > ul {
     48        list-style: none;
     49        padding: 0px;
     50        margin: 0px;
     51    }
     52    .Menu li {
     53        display: block;
     54        position: relative;
     55        white-space: nowrap;
     56        word-break: keep-all;
     57    }
     58    .Menu.-horizontal > li {
     59        display: inline-block;
     60        float: left;
     61    }
     62    .Menu li > * {
     63        display: block;
     64        position: relative;
     65    }
     66    .Menu li > ul {
     67        position: absolute;
     68        min-width: 100%;
     69        top: 0px;
     70        left: 100%;
     71    }
     72    .Menu.-horizontal.-alignRight li > ul {
     73        left: auto;
     74        right: 100%;
     75    }
     76    .Menu.-horizontal.-alignRight > li > ul {
     77        right: 0px;
     78    }
     79    .Menu.-horizontal > li > ul {
     80        top: auto;
     81        left: auto;
     82    }
     83
     84    /* Menu behaviour */
     85    .Menu li > ul,
     86    .Menu.-floating {
     87        display: none;
     88    }
     89    .Menu li > ul.-visible,
     90    ul.Menu.-floating.-visible {
     91        display: block;
     92    }
     93
     94    /* Menu animation */
     95    .Menu li > ul,
     96    .Menu.-horizontal.-alignRight li > ul,
     97    .Menu.-floating {
     98        opacity: 1;
     99        transform: scale(1) translateY(0px);
     100        transform-origin: left top;
     101    }
     102    .Menu.-alignRight li > ul,
     103    .Menu.-floating.-alignRight {
     104        transform-origin: right top;
     105    }
     106    .Menu li > ul.-animating,
     107    .Menu.-floating.-animating {
     108        opacity: 0 !important;
     109        transform: scale(0.96) translateX(-16px);
     110    }
     111    .Menu li > ul.-animating {
     112        z-index: -1 !important;
     113    }
     114    .Menu.-horizontal > li > ul.-animating {
     115        transform: scale(0.96) translateY(-16px);
     116    }
     117    .Menu.-alignRight li > ul.-animating,
     118    .Menu.-floating.-alignRight.-animating {
     119        transform: scale(0.96) translateX(16px);
     120    }
     121    .Menu.-horizontal.-alignRight > li > ul.-animating {
     122        transform: scale(0.96) translateY(-16px);
     123    }
     124
     125    /* Menu item icons */
     126    .Menu *[data-icon]:before {
     127        position: absolute;
     128        left: 0px;
     129        top: 0px;
     130        bottom: 0px;
     131        margin: auto 0px;
     132    }
     133    .Menu .Icon,
     134    .Menu *[data-icon]:before {
     135        line-height: inherit;
     136    }
     137    .Menu .Icon {
     138        padding: 0px;
     139    }
     140    .Menu *:empty[data-icon] {
     141        padding-left: 0px !important;
     142        padding-right: 0px !important;
     143    }
     144
     145    /* Submenu chevrons */
     146    .Menu li.-hasSubmenu > a:after {
     147        display: block;
     148        position: absolute;
     149
     150        width: 8px;
     151        height: 8px;
     152        right: 8px;
     153        bottom: 0px;
     154        top: 0px;
     155        margin: auto 0px;
     156
     157        transform: rotate(45deg);
     158        border-width: 1px;
     159        border-color: black;
     160        border-style: solid solid none none;
     161
     162        content: "";
     163    }
     164    .Menu.-horizontal > li.-hasSubmenu > a:after {
     165        width: 4px;
     166        height: 4px;
     167        bottom: 4px;
     168        top: auto;
     169        left: 0px;
     170        right: 0px;
     171        margin: 0px auto;
     172
     173        border-style: none solid solid none;
     174    }
     175    .Menu li.-hasSubmenu.-noChevron > a:after {
     176        display: none;
     177    }
     178
     179/*
     180** Configurable values
     181*/
     182    /* Height of navbar, and menu items */
     183    /* All of these must be of equal value */
     184    .Menu {
     185        line-height: 30px;
     186    }
     187    .Menu.-horizontal,
     188    .Menu li,
     189    .Menu li > :first-child {
     190        height: 30px;
     191    }
     192    .Menu *[data-icon]:before,
     193    .Menu .Icon {
     194        width: 30px;
     195        height: 30px;
     196    }
     197    .Menu *[data-icon] {
     198        min-width: 30px;
     199        min-height: 30px;
     200        padding-left: 30px;
     201    }
     202
     203    /* Default font settings for menu */
     204    .Menu {
     205        font-family: Arial, Helvetica, Sans;
     206        font-size: 16px;
     207    }
     208
     209    /* Icon font sizes */
     210    .Menu *[data-icon]:before,
     211    .Menu .Icon {
     212        font-size: 24px;
     213    }
     214    /* For submenus */
     215    .Menu > li ul .Icon,
     216    .Menu.-floating .Icon,
     217    .Menu > li ul *[data-icon]:before,
     218    .Menu.-floating *[data-icon]:before,
     219    {
     220        font-size: 18px;
     221    }
     222
     223    /* Colouring of menus */
     224    /* Foreground */
     225    .Menu,
     226    .Menu li.-hasSubmenu > a:after {
     227        color: black;
     228        border-color: black; /* chevron colour */
     229    }
     230    /* Background */
     231    .Menu ul,
     232    .Menu.-floating {
     233        background: white;
     234    }
     235
     236    /* Padding for each menu item */
     237    .Menu li > * {
     238        padding: 0px 12px;
     239    }
     240    /* Indent of chevron */
     241    .Menu li li.-hasSubmenu > a:after,
     242    .Menu:not(.-horizontal) > li.-hasSubmenu > a:after {
     243        right: 12px;
     244    }
     245    .Menu li li.-hasSubmenu > a,
     246    .Menu:not(.-horizontal) > li.-hasSubmenu > a {
     247        padding-right: 28px;
     248    }
     249
     250    /* Minimum width of dropdown menus */
     251    .Menu.-horizontal li > ul,
     252    .Menu.-floating {
     253        min-width: 200px;
     254    }
     255
     256    /* Animation speed of dropdown menus */
     257    .Menu li > ul,
     258    .Menu.-floating {
     259        transition: width 0.1s, height 0.1s, transform 0.1s, opacity 0.1s;
     260    }
     261
     262    /* Styling of hyperlink text */
     263    .Menu li > a {
     264        text-decoration: none;
     265        color: inherit;
     266    }
     267
     268    /* Animation speed of :hover shading */
     269    .Menu li > a:first-child {
     270        transition: background-color 0.2s;
     271    }
     272
     273    /* Colour of :hover shading */
     274    .Menu li:hover > a:first-child,
     275    .Menu li.-active > a:first-child {
     276        background-color: rgba(0,0,0,0.1);
     277    }
     278
     279/*
     280** End configurable values
     281*/
  • html5/index.html

    Cannot display: file marked as a binary type.
    svn:mime-type = font/sfnt
    
    Property changes on: html5/icons/materialicons-regular.ttf
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +font/sfnt
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: html5/icons/materialicons-regular.woff
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: html5/icons/materialicons-regular.woff2
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
    4646                <script type="text/javascript" src="js/Utilities.js"></script>
    4747                <script type="text/javascript" src="js/MediaSourceUtil.js"></script>
    4848                <script type="text/javascript" src="js/Client.js"></script>
     49               
     50                <link rel="stylesheet" type="text/css" href="css/menu.css"/>
     51                <script type="application/javascript" src="js/Menu.js"></script>
     52                <script type="application/javascript" src="js/Menu-custom.js"></script>
     53                <link rel="stylesheet" type="text/css" href="css/menu-skin.css"/>
     54                <link rel="stylesheet" type="text/css" href="css/icon.css"/>
    4955        </head>
    5056
    5157        <body>
     
    5965                </div>
    6066
    6167                <div id="screen" style="width: 100%; height:100%;">
     68                        <div id="float_menu" onmouseOver="expand_float_menu()" onmouseOut="retract_float_menu()">
     69                                <ul class="Menu -horizontal">
     70                                        <li class="-hasSubmenu -noChevron">
     71                                                <a href="#" title="Xpra" class="noDrag" data-icon="menu"></a>
     72                                                <ul>
     73                                                        <li  class="-hasSubmenu" >
     74                                                                <a data-icon="apps" href="#">Start</a>
     75                                                                <ul id="startmenu">
     76                                                                </ul>
     77                                                        </li>
     78                                                        <li class="-hasSubmenu">
     79                                                                <a href="#" data-icon="kitchen">Server</a>
     80                                                                <ul>
     81                                                                        <li><a href="#" data-icon="access_time" onclick="return false" id="clock_menu_text"></a></li>
     82                                                                        <li><a href="#" data-icon="cloud_upload" onclick="upload_file(event); return false">Upload file</a></li>
     83                                                                        <li><a href="#" data-icon="exit_to_app" onclick="confirm_shutdown_server(event); return false">Shutdown Server</a></li>
     84                                                                </ul>
     85                                                        </li>
     86                                                        <!--
     87                                                        <li class="-hasSubmenu">
     88                                                                <a href="#" data-icon="list">Features</a>
     89                                                                <ul>
     90                                                                        <li><a href="#" data-icon="message">Notifications</a></li>
     91                                                                </ul>
     92                                                        </li>
     93                                                        -->
     94                                                        <li class="-hasSubmenu">
     95                                                                <a href="#" data-icon="info">Information</a>
     96                                                                <ul>
     97                                                                        <li><a href="#" data-icon="info" onclick="show_about(event); return false">About Xpra</a></li>
     98                                                                        <li><a href="#" data-icon="trending_up" onclick="show_sessioninfo(event); return false">Session Info</a></li>
     99                                                                        <li><a href="#" data-icon="bug_report" onclick="show_bugreport(event); return false">Bug Report</a></li>
     100                                                                </ul>
     101                                                        </li>
     102                                                        <li><a href="#" data-icon="exit_to_app" onclick="client.disconnect_reason='User request'; client.close(); return false">Disconnect</a></li>
     103                                                </ul>
     104                                        </li>
     105                                        <li class="-hasSubmenu -noChevron">
     106                                                <a href="#"   title="Open Windows" data-icon="filter"></a>
     107                                                <ul id="open_windows_list">
     108                                                </ul>
     109                                        </li>
     110                                        <li class="-hasSubmenu -noChevron">
     111                                                <a href="#"   id="fullscreen_button" title="Fullscreen" data-icon="fullscreen"></a>
     112                                        </li>
     113                                        <li class="-hasSubmenu -noChevron">
     114                                                <a href="#" id="sound_button"  title="Sound" data-icon="volume_off"></a>
     115                                                </ul>
     116                                        </li>
     117                                        <div id="float_tray"  class="menu-divright"></div>
     118                                </ul>
     119                        </div>
    62120                        <div id="top_bar">
    63121                                <div class="menu-block">
    64122                                        <button onclick="show_menu('xpra_menu', event);" class="menu-button">Xpra &#9660;</button>
     
    181239                <script>
    182240                        var getparam = Utilities.getparam;
    183241                        var getboolparam = Utilities.getboolparam;
     242                        var float_menu_width = 130;
     243                        var float_menu_item_size = 30;
     244                        var float_menu_padding = 10;
    184245
    185246                        // disable right click menu:
    186247                        window.oncontextmenu = function(e) {
     
    199260                                $("#top_bar").hide();
    200261                        }
    201262
     263                        if (!getboolparam("floating_menu", true)) {
     264                                $("#float_menu").hide();
     265                        }
     266
    202267                        function show_menu(menu_id, event) {
    203268                                var menu = $("#"+menu_id);
    204269                                if (menu.is(':visible')) {
     
    552617                                client.audio_mediasource_enabled = getboolparam("mediasource", true);
    553618                                client.audio_aurora_enabled = getboolparam("aurora", true);
    554619                                client.audio_httpstream_enabled = getboolparam("http-stream", true);
     620                                $('#sound_button').attr('data-icon', 'volume_up');
    555621                            }
    556622
    557623                            if(keyboard_layout) {
     
    781847                                        var clock_text = $("#clock_text");
    782848                                        var width = clock_text.width();
    783849                                        clock_text.text(date.toLocaleDateString()+" "+date.toLocaleTimeString());
     850                                        var clock_menu_text = $("#clock_menu_text");
     851                                        clock_menu_text.text(date.toLocaleDateString()+" "+date.toLocaleTimeString());
    784852                                        if (width != clock_text.width()) {
    785853                                                //trays have been shifted left or right:
    786854                                                client.reconfigure_all_trays();
     
    806874                                }
    807875                                wait_for_time();
    808876                        }
     877                       
     878                        function toggle_fullscreen() {
     879                                var f_el = document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement;
     880                                        if (!f_el) {
     881                                                var elem = document.getElementById("fullscreen");
     882                                        var req = elem.requestFullScreen || elem.webkitRequestFullScreen || elem.mozRequestFullScreen || elem.msRequestFullscreen;
     883                                                if (req) {
     884                                                        req.call(document.body);
     885                                                }
    809886
     887                                                $('#fullscreen').attr('src', './icons/unfullscreen.png');
     888                                                $('#fullscreen_button').attr('data-icon', 'fullscreen_exit');
     889
     890                                        } else {
     891                                                if (document.exitFullscreen) {
     892                                            document.exitFullscreen();
     893                                        } else if (document.webkitExitFullscreen) {
     894                                            document.webkitExitFullscreen();
     895                                        } else if (document.mozCancelFullScreen) {
     896                                            document.mozCancelFullScreen();
     897                                        } else if (document.msExitFullscreen) {
     898                                            document.msExitFullscreen();
     899                                        }
     900                                        }
     901                        }
     902                       
     903                        function expand_float_menu(){
     904                                document.getElementById('float_menu').style.width=float_menu_width-10+'px'; $('#float_menu').children().show();
     905                        }
     906                       
     907                        function retract_float_menu(){
     908                                document.getElementById('float_menu').style.width ='0px'; $('#float_menu').children().hide();
     909                        }
     910
    810911                        var client = null;
    811912                        $(document).ready(function() {
    812913                                var touchaction = getparam("touchaction") || "scroll";
     
    871972                                        }
    872973                                });
    873974                                $('#fullscreen').on('click', function (e) {
    874                                         var f_el = document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement;
    875                                         if (!f_el) {
    876                                                 var elem = document.getElementById("fullscreen");
    877                                         var req = elem.requestFullScreen || elem.webkitRequestFullScreen || elem.mozRequestFullScreen || elem.msRequestFullscreen;
    878                                                 if (req) {
    879                                                         req.call(document.getElementById("screen"));
    880                                                 }
    881                                                 //change icon to unfullscreen:
    882                                                 $('#fullscreen').attr('src', './icons/unfullscreen.png');
    883                                         } else {
    884                                                 if (document.exitFullscreen) {
    885                                             document.exitFullscreen();
    886                                         } else if (document.webkitExitFullscreen) {
    887                                             document.webkitExitFullscreen();
    888                                         } else if (document.mozCancelFullScreen) {
    889                                             document.mozCancelFullScreen();
    890                                         } else if (document.msExitFullscreen) {
    891                                             document.msExitFullscreen();
    892                                         }
    893                                         }
     975                                        toggle_fullscreen();
    894976                                });
     977
    895978                                var screen_change_events = "webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange";
    896979                                $(document).on(screen_change_events, function () {
    897980                                        var f_el = document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement;
     
    898981                                        clog("fullscreenchange:", f_el);
    899982                                    if (f_el == null) {
    900983                                        //we're not in fullscreen mode now, so show fullscreen icon again:
    901                                                 $('#fullscreen').attr('src', './icons/fullscreen.png');
     984                                                if (getboolparam("top_bar", true)) {
     985                                                        $('#fullscreen').attr('src', './icons/fullscreen.png');
     986                                                }else{ 
     987                                                        $('#fullscreen').attr('data-icon', 'fullscreen');
     988                                                }
    902989                                    }
    903990                                });
    904991                        });
  • html5/js/Client.js

     
    6464        this.file_transfer = false;
    6565        this.keyboard_layout = null;
    6666        this.printing = false;
     67
    6768        this.bandwidth_limit = 0;
    6869        this.reconnect = true;
    6970        this.reconnect_count = 5;
     
    159160
    160161    this.server_connection_data = false;
    161162
     163        this.xdg_menu = null;
    162164        // a list of our windows
    163165        this.id_to_window = {};
    164166        this.ui_events = 0;
     
    436438XpraClient.prototype.close_windows = function() {
    437439        for (var i in this.id_to_window) {
    438440                var iwin = this.id_to_window[i];
     441                window.removeWindowListItem(i);
    439442                iwin.destroy();
    440443        }
    441444}
     
    597600        index = modifiers.indexOf("alt");
    598601        if (index>=0 && alt)
    599602                new_modifiers[index] = alt;
    600        
     603
    601604        //add altgr?
    602605        if (this.altgr_state && altgr && !new_modifiers.includes(altgr)) {
    603606                new_modifiers.push(altgr);
     
    753756                        str = "control";
    754757                }
    755758        }
    756        
     759
    757760        if (this.topwindow != null) {
    758761                //send via a timer so we get a chance to capture the clipboard value,
    759762                //before we send control-V to the server:
     
    16871690                        }
    16881691                }
    16891692        }
     1693        ctx.xdg_menu = hello["xdg-menu"];
     1694        if (ctx.xdg_menu) {
     1695                ctx.process_xdg_menu();
     1696        }
     1697
     1698
    16901699    ctx.server_is_desktop = Boolean(hello["desktop"]);
    16911700    ctx.server_is_shadow = Boolean(hello["shadow"]);
    16921701    ctx.server_readonly = Boolean(hello["readonly"]);
     
    17331742        ctx.connected = true;
    17341743}
    17351744
     1745XpraClient.prototype.process_xdg_menu = function() {
     1746        var key;
     1747        for(key in this.xdg_menu){
     1748                var category = this.xdg_menu[key];
     1749                var li = document.createElement("li");
     1750                li.className = "-hasSubmenu";
     1751
     1752                var catDivLeft = document.createElement("div");
     1753                        catDivLeft.className="menu-divleft";
     1754                catDivLeft.appendChild(this.xdg_image(category.IconData, category.IconType));
     1755
     1756                var a = document.createElement("a");
     1757                a.appendChild(catDivLeft);
     1758                a.appendChild(document.createTextNode(this.xdg_menu[key].Name));
     1759                a.href = "#";
     1760                li.appendChild(a);
     1761
     1762                var ul = document.createElement("ul");
     1763
     1764                //TODO need to figure out how to do this properly
     1765                a.onmouseenter= function(){
     1766                        this.parentElement.childNodes[1].className="-visible";
     1767                };
     1768                a.onmouseleave= function(){
     1769                        this.parentElement.childNodes[1].className="";
     1770                };
     1771
     1772                var xdg_menu_cats = category.Entries;
     1773                for(key in xdg_menu_cats){
     1774                        var entry = xdg_menu_cats[key];
     1775                        var li2 = document.createElement("li");
     1776                        var a2 = document.createElement("a");
     1777
     1778                        var name = entry.Name;
     1779            name = Utilities.trimString(name,15);
     1780                        var command = entry.Exec.replace(/%[uUfF]/g,"");
     1781
     1782                        var divLeft = document.createElement("div");
     1783                        divLeft.className = "menu-divleft";
     1784                        divLeft.appendChild(this.xdg_image(entry.IconData, entry.IconType));
     1785
     1786                        var titleDiv = document.createElement("div");
     1787                        titleDiv.appendChild(document.createTextNode(name));
     1788                        titleDiv.className = "menu-content-left";
     1789                        divLeft.appendChild(titleDiv);
     1790
     1791                        a2.appendChild(divLeft);
     1792                        a2.title = command;
     1793
     1794                        var me = this;
     1795                        a2.onclick = function(){
     1796                                var ignore = "False";
     1797                                me.start_command(this.innerText, this.title, ignore);
     1798                                this.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.className="-hide";
     1799                        };
     1800                        a2.onmouseenter= function(){
     1801                                this.parentElement.parentElement.className="-visible";
     1802                        };
     1803                        a2.onmouseleave= function(){
     1804                                this.parentElement.parentElement.className="";
     1805                        };
     1806
     1807                        li2.appendChild(a2);
     1808                        ul.appendChild(li2);
     1809                }
     1810                li.appendChild(ul);
     1811                document.getElementById("startmenu").appendChild(li);
     1812        }
     1813}
     1814
     1815
     1816XpraClient.prototype.xdg_image = function(icon_data, icon_type) {
     1817        var img = new Image();
     1818        if (typeof icon_data !== 'undefined'){
     1819                if (typeof icon_data === 'string') {
     1820                        icon_data = Utilities.StringToUint8(icon_data);
     1821                }
     1822                if (icon_type=="svg") {
     1823                        img.src = "data:image/svg+xml;base64," + Utilities.ArrayBufferToBase64(icon_data);
     1824                }
     1825                else if (icon_type=="png" || icon_type=="jpeg") {
     1826                        img.src = "data:image/"+icon_type+";base64," + Utilities.ArrayBufferToBase64(icon_data);
     1827                }
     1828        }
     1829        img.className = "menu-content-left";
     1830        img.height = 24;
     1831        img.width = 24;
     1832        return img
     1833}
     1834
     1835
     1836
    17361837XpraClient.prototype.on_connect = function() {
    17371838        //this hook can be overriden
    17381839}
     
    19042005        mydiv.id = String(wid);
    19052006        var mycanvas = document.createElement("canvas");
    19062007        mydiv.appendChild(mycanvas);
    1907         var top_bar = document.getElementById("top_bar");
    1908         top_bar.appendChild(mydiv);
    1909         var x = 100;
     2008
     2009        var x = 0;
    19102010        var y = 0;
    1911         w = 48;
    1912         h = 48;
     2011        if (getboolparam("top_bar", true)) {
     2012            var top_bar = document.getElementById("top_bar");
     2013            top_bar.appendChild(mydiv);
     2014            x = 100;
     2015            y = 0;
     2016            w = 48;
     2017            h = 48;
     2018        } else {
     2019                var float_tray = document.getElementById("float_tray");
     2020                var float_menu = document.getElementById("float_menu");
     2021                $('#float_menu').children().show();
     2022                //increase size for tray icon
     2023                var new_width = float_menu_width + float_menu_item_size -float_menu_padding;
     2024                float_menu.style.width = new_width + "px";
     2025                float_menu_width=$('#float_menu').width() + 10;
     2026                mydiv.style.backgroundColor = "white";
     2027
     2028                float_tray.appendChild(mydiv);
     2029            x = 0;
     2030            y = 0;
     2031            w = float_menu_item_size;
     2032            h = float_menu_item_size;
     2033        }
     2034
    19132035        mycanvas.width = w;
    19142036        mycanvas.height = h;
    19152037        var win = new XpraWindow(ctx, mycanvas, wid, x, y, w, h,
     
    19332055        var x = Math.round(div.offset().left);
    19342056        var y = Math.round(div.offset().top);
    19352057        var w = 48, h = 48;
     2058        if (getboolparam("floating_menu", true)) {
     2059                w = float_menu_item_size;
     2060                h = float_menu_item_size;
     2061        }
    19362062        this.clog("tray", wid, "position:", x, y);
    19372063        this.send(["configure-window", Number(wid), x, y, w, h, {}]);
    19382064}
     
    19472073}
    19482074
    19492075XpraClient.prototype.reconfigure_all_trays = function() {
     2076        var float_menu = document.getElementById("float_menu");
     2077        // default width 4x30 (icons) + 10 (padding)
     2078        float_menu_width = 130;
    19502079        for (var twid in this.id_to_window) {
    19512080                var twin = this.id_to_window[twid];
    19522081                if (twin && twin.tray) {
     2082                    float_menu_width = float_menu_width + 30;
    19532083                        this.send_tray_configure(twid);
    19542084                }
    19552085        }
     2086
     2087        // only set if float_menu is visible
     2088        if($('#float_menu').width() > 0){
     2089                float_menu.style.width = float_menu_width;
     2090        }
    19562091}
    19572092
    19582093/**
     
    19832118                this._window_set_focus,
    19842119                this._window_closed
    19852120                );
     2121        if(win && !override_redirect && win.metadata["window-type"]=="NORMAL"){
     2122                var decodedTitle = decodeURIComponent(escape(win.title));
     2123                var trimmedTitle = Utilities.trimString(decodedTitle,30);
     2124                window.addWindowListItem(wid, trimmedTitle);
     2125        }
    19862126        this.id_to_window[wid] = win;
    19872127        if (!override_redirect) {
    19882128                var geom = win.get_internal_geometry();
     
    20832223XpraClient.prototype._process_lost_window = function(packet, ctx) {
    20842224        var wid = packet[1];
    20852225        var win = ctx.id_to_window[wid];
     2226        if(win && !win.override_redirect && win.metadata["window-type"]=="NORMAL"){
     2227                window.removeWindowListItem(wid);
     2228        }
    20862229        try {
    20872230                delete ctx.id_to_window[wid];
    20882231        }
     
    29033046        this.send(packet);
    29043047}
    29053048
     3049XpraClient.prototype.start_command = function(name, command, ignore) {
     3050        var packet = ["start-command", name, command, ignore];
     3051        this.send(packet);
     3052}
     3053
    29063054XpraClient.prototype._process_open_url = function(packet, ctx) {
    29073055    var url = packet[1];
    29083056    //var send_id = packet[2];
     
    29133061    }
    29143062    ctx.clog("opening url:", url);
    29153063    var new_window = window.open(url, '_blank');
    2916     if(!new_window || new_window.closed || typeof new_window.closed=='undefined') 
     3064    if(!new_window || new_window.closed || typeof new_window.closed=='undefined')
    29173065    {
    29183066                //Popup blocked, display link in notification
    29193067                var summary = "Open URL";
  • html5/js/Menu-custom.js

     
     1/**
     2MIT License
     3
     4Copyright (c) 2019 Mark Harkin
     5
     6Permission is hereby granted, free of charge, to any person obtaining a copy
     7of this software and associated documentation files (the "Software"), to deal
     8in the Software without restriction, including without limitation the rights
     9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10copies of the Software, and to permit persons to whom the Software is
     11furnished to do so, subject to the following conditions:
     12
     13The above copyright notice and this permission notice shall be included in all
     14copies or substantial portions of the Software.
     15
     16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22SOFTWARE.
     23
     24*/
     25
     26function addWindowListItem(wid, title){
     27        var li = document.createElement("li");
     28        li.className="windowlist-li";
     29        li.id = "windowlistitem"+wid;
     30       
     31        var a = document.createElement("a");
     32       
     33        a.id = "windowlistitemlink"+wid;
     34       
     35        a.onmouseover=function(e){
     36                if (e.ctrlKey) {
     37                        client._window_set_focus(client.id_to_window[wid]);
     38                }
     39        };
     40        a.onclick=function(){
     41                if(jQuery(client.id_to_window[wid].div).is(":hidden")){
     42                        jQuery(client.id_to_window[wid].div).show();
     43                }
     44                this.parentElement.parentElement.className="-hide";
     45                client._window_set_focus(client.id_to_window[wid]);
     46        };
     47       
     48        var divLeft = document.createElement("div");
     49        divLeft.id="windowlistdivleft"+wid;
     50        divLeft.className="menu-divleft";
     51        var img = new Image();
     52        img.id = "windowlistitemicon"+wid;
     53        img.src="/favicon.png";
     54        img.className="menu-content-left";
     55        divLeft.appendChild(img);
     56       
     57        var titleDiv = document.createElement("div");
     58        titleDiv.appendChild(document.createTextNode(title));
     59        titleDiv.id = "windowlistitemtitle"+wid;
     60        titleDiv.className="menu-content-left";
     61        divLeft.appendChild(titleDiv);
     62
     63        var divRight = document.createElement("div");
     64        divRight.className="menu-divright";
     65
     66        var img2 = new Image();
     67        img2.id = "windowlistitemclose"+wid;
     68        img2.src="icons/close.png";
     69        img2.title="Close";
     70        img2.className="menu-content-right";
     71        img2.onclick=function(){client._window_closed(client.id_to_window[wid])};
     72        var img3 = new Image();
     73        img3.id = "windowlistitemmax"+wid;
     74        img3.src="icons/maximize.png";
     75        img3.title="Maximize";
     76        img3.onclick=function(){client.id_to_window[wid].toggle_maximized()};
     77        img3.className="menu-content-right";
     78        var img4 = new Image();
     79        img4.id = "windowlistitemmin"+wid;
     80        img4.src="icons/minimize.png";
     81        img4.title="Minimize";
     82        img4.onclick=function(){client.id_to_window[wid].toggle_minimized()};
     83        img4.className="menu-content-right";
     84
     85        divRight.appendChild(img2);
     86        divRight.appendChild(img3);
     87        divRight.appendChild(img4);
     88        a.appendChild(divLeft);
     89        a.appendChild(divRight);
     90        li.appendChild(a);
     91
     92        document.getElementById("open_windows_list").appendChild(li);
     93}
     94
     95function removeWindowListItem(itemId){
     96        var element = document.getElementById("windowlistitem" + itemId);
     97        if(element && element.parentNode){
     98                element.parentNode.removeChild(element);
     99        }
     100}
     101
     102$(function() {
     103        $("#float_menu").draggable({
     104                cancel: '.noDrag'
     105        });
     106});
     107
  • html5/js/Menu.js

     
     1/**
     2MIT License
     3
     4Copyright (c) 2019 Mark Harkin, 2016 Dylan Hicks (aka. dylanh333)
     5
     6Permission is hereby granted, free of charge, to any person obtaining a copy
     7of this software and associated documentation files (the "Software"), to deal
     8in the Software without restriction, including without limitation the rights
     9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10copies of the Software, and to permit persons to whom the Software is
     11furnished to do so, subject to the following conditions:
     12
     13The above copyright notice and this permission notice shall be included in all
     14copies or substantial portions of the Software.
     15
     16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22SOFTWARE.
     23
     24*/
     25
     26
     27(function(){
     28    function $(selector, context){
     29        context = context || document;
     30        return context["querySelectorAll"](selector);
     31    }
     32
     33    function forEach(collection, iterator){
     34        for(var key in Object.keys(collection)){
     35            iterator(collection[key]);
     36        }
     37    }
     38
     39    function showMenu(menu){
     40        var menu = this;
     41        var ul = $("ul", menu)[0];
     42        //hack to hide the menu from javascript
     43        if(!ul){
     44                        return;
     45                }
     46
     47        if(ul.classList.contains("-hide")){
     48                        ul.classList.remove("-hide");
     49                        ul.parentElement.classList.remove("-active");
     50                        return;
     51                };
     52
     53        if(ul.classList.contains("-visible")){
     54                        return;
     55                }
     56
     57        menu.classList.add("-active");
     58        ul.classList.add("-animating");
     59        ul.classList.add("-visible");
     60        setTimeout(function(){
     61            ul.classList.remove("-animating")
     62        }, 25);
     63    }
     64
     65    function hideMenu(menu){
     66        var menu = this;
     67        var ul = $("ul", menu)[0];
     68
     69        if(!ul || !ul.classList.contains("-visible")) return;
     70
     71        menu.classList.remove("-active");
     72        ul.classList.add("-animating");
     73        setTimeout(function(){
     74            ul.classList.remove("-visible");
     75            ul.classList.remove("-animating");
     76        }, 300);
     77    }
     78
     79    function hideAllInactiveMenus(menu){
     80        var menu = this;
     81        forEach(
     82            $("li.-hasSubmenu.-active:not(:hover)", menu.parent),
     83            function(e){
     84                e.hideMenu && e.hideMenu();
     85            }
     86        );
     87    }
     88   
     89    function hideAllMenus(menu){
     90        var menu = this;
     91        forEach(
     92            $("li.-hasSubmenu", menu.parent),
     93            function(e){
     94                e.hideMenu && e.hideMenu();
     95            }
     96        );
     97    }
     98
     99    window.addEventListener("load", function(){
     100        forEach($(".Menu li.-hasSubmenu"), function(e){
     101            e.showMenu = showMenu;
     102            e.hideMenu = hideMenu;
     103        });
     104
     105        forEach($(".Menu > li.-hasSubmenu"), function(e){
     106            e.addEventListener("click", showMenu);
     107        });
     108
     109        forEach($(".Menu > li.-hasSubmenu li"), function(e){
     110            e.addEventListener("mouseenter", hideAllInactiveMenus);
     111        });
     112
     113        forEach($(".Menu > li.-hasSubmenu li.-hasSubmenu"), function(e){
     114            e.addEventListener("mouseenter", showMenu);
     115        });
     116       
     117       
     118       
     119        forEach($("a"), function(e){
     120            e.addEventListener("click", hideAllMenus);
     121        });
     122
     123        document.addEventListener("click", hideAllInactiveMenus);
     124    });
     125})();
  • html5/js/Utilities.js

     
    8181                }
    8282                return result;
    8383        },
     84       
     85        trimString: function(str, trimLength){
     86                var trimString = str.length > trimLength ?
     87                    str.substring(0, trimLength - 3) + "..." :
     88                    str;
     89                return trimString;
     90        },
    8491
    8592        getPlatformProcessor: function() {
    8693                //mozilla property:
  • html5/js/Window.js

     
    132132                                '<span class="windowicon"><img id="windowicon' + String(wid) + '" /></span> '+
    133133                                '<span class="windowtitle" id="title' + String(wid) + '">' + this.title + '</span> '+
    134134                                '<span class="windowbuttons"> '+
     135                                '<span id="minimize' + String(wid) + '"><img src="icons/minimize.png" /></span> '+
    135136                                '<span id="maximize' + String(wid) + '"><img src="icons/maximize.png" /></span> '+
    136137                                '<span id="close' + String(wid) + '"><img src="icons/close.png" /></span> '+
    137138                                '</span></div>');
     
    161162                this.d_header = '#head' + String(wid);
    162163                this.d_closebtn = '#close' + String(wid);
    163164                this.d_maximizebtn = '#maximize' + String(wid);
     165                this.d_minimizebtn = '#minimize' + String(wid);
    164166                if (this.resizable) {
    165167                        jQuery(this.d_header).dblclick(function() {
    166168                                me.toggle_maximized();
     
    171173                        jQuery(this.d_maximizebtn).click(function() {
    172174                                me.toggle_maximized();
    173175                        });
     176                        jQuery(this.d_minimizebtn).click(function() {
     177                                me.toggle_minimized();
     178                        });
    174179                }
    175180                else {
    176181                        jQuery(this.d_closebtn).hide();
    177182                        jQuery(this.d_maximizebtn).hide();
     183                        jQuery('#windowlistitemmax' + String(wid)).hide();
     184                        jQuery(this.d_minimizebtn).hide();
    178185                }
    179186                // adjust top offset
    180187                this.topoffset = this.topoffset + parseInt(jQuery(this.d_header).css('height'), 10);
     
    446453XpraWindow.prototype.set_metadata_safe = function(metadata) {
    447454        if ("title" in metadata) {
    448455                this.title = metadata["title"];
    449                 jQuery('#title' + this.wid).html(decodeURIComponent(escape(this.title)));
     456                var decodedTitle = decodeURIComponent(escape(this.title));
     457                jQuery('#title' + this.wid).html(decodedTitle);
     458        var trimmedTitle = Utilities.trimString(decodedTitle,30);
     459                jQuery('#windowlistitemtitle'+this.wid).text(trimmedTitle);
    450460        }
    451461        if ("has-alpha" in metadata) {
    452462                this.has_alpha = metadata["has-alpha"];
     
    545555        }
    546556        if(minw>0 && minw==maxw && minh>0 && minh==maxh) {
    547557                jQuery(this.d_maximizebtn).hide();
     558                jQuery('#windowlistitemmax' + String(this.wid)).hide();
    548559                jQuery(this.div).resizable('disable');
    549560        } else {
    550561                jQuery(this.d_maximizebtn).show();
     
    613624 * Maximize / unmaximizes the window.
    614625 */
    615626XpraWindow.prototype.set_maximized = function(maximized) {
     627        if(jQuery(this.div).is(":hidden")){
     628                jQuery(this.div).show();
     629        }
     630       
    616631        if (this.maximized==maximized) {
    617632                return;
    618633        }
     
    632647};
    633648
    634649/**
     650 * Minimizes / unminimizes the window.
     651 */
     652XpraWindow.prototype.set_minimized = function(minimized) {
     653        jQuery(this.div).toggle(200);
     654};
     655
     656
     657/**
     658 * Toggle minimized state
     659 */
     660XpraWindow.prototype.toggle_minimized = function() {
     661        this.set_minimized(!this.minimized);
     662};
     663
     664/**
    635665 * Fullscreen / unfullscreen the window.
    636666 */
    637667XpraWindow.prototype.set_fullscreen = function(fullscreen) {
     
    948978                src = "data:image/"+encoding+";base64," + Utilities.ArrayBufferToBase64(img_data);
    949979        }
    950980        jQuery('#windowicon' + String(this.wid)).attr('src', src);
     981        jQuery('#windowlistitemicon' + String(this.wid)).attr('src', src);
    951982        return src;
    952983};
    953984