Compare commits
3 commits
ef0b7607fe
...
0337398718
Author | SHA1 | Date | |
---|---|---|---|
0337398718 | |||
3931bc0345 | |||
9997bd3594 |
87 changed files with 2576 additions and 2 deletions
|
@ -17,5 +17,5 @@ RUN echo "none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0" > /etc/fstab
|
|||
COPY docker/entrypoint.sh /tmp
|
||||
COPY src/ /tmp
|
||||
WORKDIR /tmp
|
||||
CMD bash
|
||||
# CMD /tmp/entrypoint.sh
|
||||
#CMD bash
|
||||
CMD /tmp/entrypoint.sh
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
# Default config for sway
|
||||
#
|
||||
# Copy this to ~/.config/sway/config and edit it to your liking.
|
||||
#
|
||||
# Read `man 5 sway` for a complete reference.
|
||||
|
||||
### Variables
|
||||
#
|
||||
# Logo key. Use Mod1 for Alt.
|
||||
set $mod Mod4
|
||||
# Home row direction keys, like vim
|
||||
set $left left
|
||||
set $down down
|
||||
set $up up
|
||||
set $right right
|
||||
# Your preferred terminal emulator
|
||||
set $term xfce4-terminal
|
||||
# Your preferred application launcher
|
||||
# Note: it's recommended that you pass the final command to sway
|
||||
#set $menu dmenu_path | dmenu | xargs swaymsg exec --
|
||||
set $menu rofi -show drun -font "Inter Bold 24" -display-drun "" -theme mnt-reform | xargs swaymsg exec --
|
||||
|
||||
#xwayland disable
|
||||
|
||||
### Output configuration
|
||||
#
|
||||
# Default wallpaper (more resolutions are available in @datadir@/backgrounds/sway/)
|
||||
#output * bg "#000000" fill
|
||||
exec swaybg -c "#000000"
|
||||
|
||||
#
|
||||
# Example configuration:
|
||||
#
|
||||
# output HDMI-A-1 resolution 1920x1080 position 1920,0
|
||||
#
|
||||
# You can get the names of your outputs by running: swaymsg -t get_outputs
|
||||
|
||||
### Idle configuration
|
||||
#
|
||||
# Example configuration:
|
||||
#
|
||||
# exec swayidle -w \
|
||||
# timeout 300 'swaylock -f -c 000000' \
|
||||
# timeout 600 'swaymsg "output * dpms off"' \
|
||||
# resume 'swaymsg "output * dpms on"' \
|
||||
# before-sleep 'swaylock -f -c 000000'
|
||||
#
|
||||
# This will lock your screen after 300 seconds of inactivity, then turn off
|
||||
# your displays after another 300 seconds, and turn your screens back on when
|
||||
# resumed. It will also lock your screen before your computer goes to sleep.
|
||||
|
||||
### Input configuration
|
||||
#
|
||||
# Example configuration:
|
||||
#
|
||||
# input "2:14:SynPS/2_Synaptics_TouchPad" {
|
||||
# dwt enabled
|
||||
# tap enabled
|
||||
# natural_scroll enabled
|
||||
# middle_emulation enabled
|
||||
# }
|
||||
#
|
||||
# You can get the names of your inputs by running: swaymsg -t get_inputs
|
||||
# Read `man 5 sway-input` for more information about this section.
|
||||
#
|
||||
|
||||
default_border pixel 10
|
||||
hide_edge_borders both
|
||||
|
||||
### Key bindings
|
||||
#
|
||||
# Basics:
|
||||
#
|
||||
# Start a terminal
|
||||
bindsym $mod+Return exec $term
|
||||
bindsym $mod+Shift+s exec grim ~/Pictures/$(date +'screenshot-%Y-%m-%d-%H-%M-%S').png
|
||||
bindsym $mod+Shift+x exec grim -g "$(slurp)" ~/Pictures/$(date +'screenshot-%Y-%m-%d-%H-%M-%S').png
|
||||
bindsym $mod+Shift+v exec reform-pavucontrol.sh
|
||||
bindsym $mod+Shift+l exec swaylock
|
||||
|
||||
# Kill focused window
|
||||
bindsym $mod+Escape kill
|
||||
|
||||
# Start your launcher
|
||||
bindsym $mod+d exec $menu
|
||||
bindsym $mod+Tab exec $menu
|
||||
bindsym $mod+t exec thunar
|
||||
|
||||
# Drag floating windows by holding down $mod and left mouse button.
|
||||
# Resize them with right mouse button + $mod.
|
||||
# Despite the name, also works for non-floating windows.
|
||||
# Change normal to inverse to use left mouse button for resizing and right
|
||||
# mouse button for dragging.
|
||||
floating_modifier $mod normal
|
||||
|
||||
# Reload the configuration file
|
||||
bindsym $mod+Shift+c reload
|
||||
|
||||
# Exit sway (logs you out of your Wayland session)
|
||||
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
|
||||
#
|
||||
# Moving around:
|
||||
#
|
||||
# Move your focus around
|
||||
bindsym $mod+$left focus left
|
||||
bindsym $mod+$down focus down
|
||||
bindsym $mod+$up focus up
|
||||
bindsym $mod+$right focus right
|
||||
# Or use $mod+[up|down|left|right]
|
||||
#bindsym $mod+Left focus left
|
||||
#bindsym $mod+Down focus down
|
||||
#bindsym $mod+Up focus up
|
||||
#bindsym $mod+Right focus right
|
||||
|
||||
# Move the focused window with the same, but add Shift
|
||||
bindsym $mod+Shift+$left move left
|
||||
bindsym $mod+Shift+$down move down
|
||||
bindsym $mod+Shift+$up move up
|
||||
bindsym $mod+Shift+$right move right
|
||||
# Ditto, with arrow keys
|
||||
#bindsym $mod+Shift+Left move left
|
||||
#bindsym $mod+Shift+Down move down
|
||||
#bindsym $mod+Shift+Up move up
|
||||
#bindsym $mod+Shift+Right move right
|
||||
|
||||
bindsym $mod+F1 exec brightnessctl s 1-
|
||||
bindsym $mod+F2 exec brightnessctl s +1
|
||||
bindsym $mod+F3 exec pactl set-sink-volume @DEFAULT_SINK@ -5%
|
||||
bindsym $mod+F4 exec pactl set-sink-volume @DEFAULT_SINK@ +5%
|
||||
bindsym $mod+F5 exec pactl set-sink-mute @DEFAULT_SINK@ toggle
|
||||
#
|
||||
# Workspaces:
|
||||
#
|
||||
# Switch to workspace
|
||||
bindsym $mod+1 workspace 1
|
||||
bindsym $mod+2 workspace 2
|
||||
bindsym $mod+3 workspace 3
|
||||
bindsym $mod+4 workspace 4
|
||||
bindsym $mod+5 workspace 5
|
||||
bindsym $mod+6 workspace 6
|
||||
bindsym $mod+7 workspace 7
|
||||
bindsym $mod+8 workspace 8
|
||||
bindsym $mod+9 workspace 9
|
||||
bindsym $mod+0 workspace 10
|
||||
# Move focused container to workspace
|
||||
bindsym $mod+Shift+1 move container to workspace 1
|
||||
bindsym $mod+Shift+2 move container to workspace 2
|
||||
bindsym $mod+Shift+3 move container to workspace 3
|
||||
bindsym $mod+Shift+4 move container to workspace 4
|
||||
bindsym $mod+Shift+5 move container to workspace 5
|
||||
bindsym $mod+Shift+6 move container to workspace 6
|
||||
bindsym $mod+Shift+7 move container to workspace 7
|
||||
bindsym $mod+Shift+8 move container to workspace 8
|
||||
bindsym $mod+Shift+9 move container to workspace 9
|
||||
bindsym $mod+Shift+0 move container to workspace 10
|
||||
# Note: workspaces can have any name you want, not just numbers.
|
||||
# We just use 1-10 as the default.
|
||||
#
|
||||
# Layout stuff:
|
||||
#
|
||||
# You can "split" the current object of your focus with
|
||||
# $mod+b or $mod+v, for horizontal and vertical splits
|
||||
# respectively.
|
||||
bindsym $mod+h splith
|
||||
bindsym $mod+v splitv
|
||||
|
||||
# Switch the current container between different layout styles
|
||||
bindsym $mod+s layout stacking
|
||||
bindsym $mod+w layout tabbed
|
||||
bindsym $mod+e layout toggle split
|
||||
|
||||
# Make the current focus fullscreen
|
||||
bindsym $mod+f fullscreen
|
||||
|
||||
# Toggle the current focus between tiling and floating mode
|
||||
bindsym $mod+space floating toggle
|
||||
|
||||
# Swap focus between the tiling area and the floating area
|
||||
bindsym $mod+Shift+space focus mode_toggle
|
||||
|
||||
# Move focus to the parent container
|
||||
bindsym $mod+a focus parent
|
||||
#
|
||||
# Scratchpad:
|
||||
#
|
||||
# Sway has a "scratchpad", which is a bag of holding for windows.
|
||||
# You can send windows there and get them back later.
|
||||
|
||||
# Move the currently focused window to the scratchpad
|
||||
bindsym $mod+Shift+minus move scratchpad
|
||||
|
||||
# Show the next scratchpad window or hide the focused scratchpad window.
|
||||
# If there are multiple scratchpad windows, this command cycles through them.
|
||||
bindsym $mod+minus scratchpad show
|
||||
#
|
||||
# Resizing containers:
|
||||
#
|
||||
mode "resize" {
|
||||
# left will shrink the containers width
|
||||
# right will grow the containers width
|
||||
# up will shrink the containers height
|
||||
# down will grow the containers height
|
||||
bindsym $left resize shrink width 10px
|
||||
bindsym $down resize grow height 10px
|
||||
bindsym $up resize shrink height 10px
|
||||
bindsym $right resize grow width 10px
|
||||
|
||||
# Ditto, with arrow keys
|
||||
#bindsym Left resize shrink width 10px
|
||||
#bindsym Down resize grow height 10px
|
||||
#bindsym Up resize shrink height 10px
|
||||
#bindsym Right resize grow width 10px
|
||||
|
||||
# Return to default mode
|
||||
bindsym Return mode "default"
|
||||
bindsym Escape mode "default"
|
||||
}
|
||||
bindsym $mod+r mode "resize"
|
||||
|
||||
# class border backgr. text indicator child_border
|
||||
client.focused #000000 #ffffff #000000 #000000 #000000
|
||||
client.focused_inactive #000000 #eeeeee #000000 #000000 #000000
|
||||
client.unfocused #000000 #222222 #888888 #000000 #000000
|
||||
client.urgent #2f343a #900000 #ffffff #900000 #900000
|
||||
client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c
|
||||
|
||||
client.background #ffffff
|
||||
|
||||
font pango: Inter, Icons Bold 14
|
||||
|
||||
#
|
||||
# Status Bar:
|
||||
#
|
||||
# Read `man 5 sway-bar` for more information about this section.
|
||||
#bar {
|
||||
# position top
|
||||
#
|
||||
# # When the status_command prints a new line to stdout, swaybar updates.
|
||||
# # The default just shows the current date and time.
|
||||
# status_command while ~/bin/status; do sleep 60; done
|
||||
#
|
||||
# colors {
|
||||
# statusline #ffffff
|
||||
# background #000000
|
||||
# focused_workspace #ffffff #ffffff #000000
|
||||
# active_workspace #ffffff #888888 #000000
|
||||
# inactive_workspace #000000 #000000 #ffffff
|
||||
# }
|
||||
#
|
||||
# font pango: Inter, Icons Bold Italic 14
|
||||
#}
|
||||
|
||||
for_window [app_id="pavucontrol"] floating enable
|
||||
for_window [app_id="connman-gtk"] floating enable
|
||||
for_window [app_id="xfce4-appfinder"] floating enable
|
||||
|
||||
include @sysconfdir@/sway/config.d/*
|
||||
|
||||
# waybar
|
||||
exec /usr/local/bin/waybar
|
||||
|
||||
# autostart gnome settings daemon
|
||||
exec /usr/libexec/gsd-xsettings
|
||||
|
||||
# uncomment to have umlauts etc. on right alt
|
||||
#input "1003:8258:MNT_Reform_Keyboard" xkb_layout us-german-umlaut
|
||||
|
||||
# start a policykit agent
|
||||
exec lxpolkit
|
||||
|
||||
exec gsettings set org.gnome.desktop.interface font-name 'Inter 14'
|
||||
exec gsettings set org.gnome.desktop.interface monospace-font-name 'Iosevka Term Light 14'
|
||||
exec gsettings set org.gnome.desktop.interface gtk-theme 'Arc-Dark'
|
||||
|
||||
exec gsettings set org.gnome.gedit.preferences.editor scheme 'cobalt'
|
||||
|
||||
# autostart a terminal
|
||||
exec xfce4-terminal -e 'bash -c "reform-desktop-help; bash"'
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
// "layer": "top", // Waybar at top layer
|
||||
// "position": "bottom", // Waybar position (top|bottom|left|right)
|
||||
"height": 34, // Waybar height (to be removed for auto height)
|
||||
// "width": 1280, // Waybar width
|
||||
// Choose the order of the modules
|
||||
"modules-left": ["sway/workspaces", "sway/mode", "sway/window"],
|
||||
"modules-center": [],
|
||||
"modules-right": ["tray", "network", "custom/stat", "memory", "temperature", "pulseaudio", "clock"],
|
||||
"sway/window": {
|
||||
"on-click": "xfce4-appfinder"
|
||||
},
|
||||
"sway/mode": {
|
||||
"format": "<span>{}</span>"
|
||||
},
|
||||
"tray": {
|
||||
"icon-size": 32,
|
||||
"spacing": 16
|
||||
},
|
||||
"clock": {
|
||||
"tooltip-format": "{:%Y %B}",
|
||||
"format-alt": "{:%Y-%m-%d}",
|
||||
"tooltip": false
|
||||
},
|
||||
"cpu": {
|
||||
"format": "CPU {usage}%",
|
||||
"tooltip": false
|
||||
},
|
||||
"memory": {
|
||||
"format": "MEM {}%",
|
||||
"tooltip": false
|
||||
},
|
||||
"temperature": {
|
||||
"thermal-zone": 0,
|
||||
// "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input",
|
||||
"critical-threshold": 80,
|
||||
// "format-critical": "{temperatureC}°C {icon}",
|
||||
"format": "{temperatureC}°C"
|
||||
},
|
||||
"network": {
|
||||
// "interface": "wlp2*", // (Optional) To force the use of this interface
|
||||
"format-wifi": "NET {essid} {signalStrength}%",
|
||||
"format-ethernet": "NET {ifname}: {ipaddr}/{cidr}",
|
||||
"format-linked": "NET {ifname} NO IP",
|
||||
"format-disconnected": "NET ×",
|
||||
//"format-alt": "NET {ifname}: {ipaddr}/{cidr}"
|
||||
"on-click": "reform-connman-gtk.sh"
|
||||
},
|
||||
"pulseaudio": {
|
||||
// "scroll-step": 1,
|
||||
"format": "VOL {volume}%",
|
||||
"format-bluetooth": "{volume}% {icon} {format_source}",
|
||||
"format-bluetooth-muted": " {icon} {format_source}",
|
||||
"format-muted": "MUTED {format_source}",
|
||||
"format-source": "{volume}%",
|
||||
"format-source-muted": "MUTE",
|
||||
"on-click": "reform-pavucontrol.sh"
|
||||
},
|
||||
"custom/stat": {
|
||||
"format": "{}",
|
||||
"max-length": 20,
|
||||
"interval": 0,
|
||||
"exec": "reform-compstat.sh",
|
||||
"on-click": "gnome-system-monitor"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
* {
|
||||
font-size: 18px;
|
||||
font-family: Inter;
|
||||
font-weight: bold;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
window#waybar {
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#sway-mode {
|
||||
background-color: #330000;
|
||||
}
|
||||
|
||||
widget label {
|
||||
padding: 0px 20px;
|
||||
}
|
||||
|
||||
#workspaces label {
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
#workspaces button {
|
||||
color: #ffffff;
|
||||
font-size: 20px;
|
||||
font-style: italic;
|
||||
}
|
||||
#workspaces button.focused {
|
||||
background: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
#workspaces button:hover {
|
||||
box-shadow: inherit;
|
||||
text-shadow: inherit;
|
||||
}
|
||||
#workspaces button:hover {
|
||||
background: #888888;
|
||||
}
|
||||
|
||||
#clock {
|
||||
padding-right: 0px;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
[Configuration]
|
||||
MiscAlwaysShowTabs=FALSE
|
||||
MiscBell=FALSE
|
||||
MiscBellUrgent=FALSE
|
||||
MiscBordersDefault=TRUE
|
||||
MiscCursorBlinks=TRUE
|
||||
MiscCursorShape=TERMINAL_CURSOR_SHAPE_BLOCK
|
||||
MiscDefaultGeometry=80x24
|
||||
MiscInheritGeometry=FALSE
|
||||
MiscMenubarDefault=TRUE
|
||||
MiscMouseAutohide=FALSE
|
||||
MiscMouseWheelZoom=TRUE
|
||||
MiscToolbarDefault=FALSE
|
||||
MiscConfirmClose=TRUE
|
||||
MiscCycleTabs=TRUE
|
||||
MiscTabCloseButtons=TRUE
|
||||
MiscTabCloseMiddleClick=TRUE
|
||||
MiscTabPosition=GTK_POS_TOP
|
||||
MiscHighlightUrls=TRUE
|
||||
MiscMiddleClickOpensUri=FALSE
|
||||
MiscCopyOnSelect=FALSE
|
||||
MiscShowRelaunchDialog=TRUE
|
||||
MiscRewrapOnResize=TRUE
|
||||
MiscUseShiftArrowsToScroll=FALSE
|
||||
MiscSlimTabs=FALSE
|
||||
MiscNewTabAdjacent=FALSE
|
||||
MiscSearchDialogOpacity=100
|
||||
MiscShowUnsafePasteDialog=TRUE
|
||||
FontName=Iosevka Term Light 14
|
||||
ScrollingLines=10000
|
||||
TitleMode=TERMINAL_TITLE_REPLACE
|
||||
;
|
||||
; snazzy theme: https://github.com/tunnckoCore/xfce4-terminal-snazzy
|
||||
ColorBackground=#282a36
|
||||
ColorForeground=#ecf1f3
|
||||
ColorCursor=#ecf1f3
|
||||
ColorPalette=#2E3436;#ff5c57;#5af78e;#f3f99d;#57c7ff;#ff6ac1;#9aedfe;#f1f1f0;#686868;#ff5c57;#5af78e;#f3f99d;#57c7ff;#ff6ac1;#9aedfe;#f1f1f0
|
3
src/recipes/default/hook/data/overlay/etc/skel/.ircrc
Normal file
3
src/recipes/default/hook/data/overlay/etc/skel/.ircrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
/set INPUT_ENCODING UTF-8
|
||||
/set DISPLAY_ENCODING UTF-8
|
||||
/set IRC_ENCODING UTF-8
|
13
src/recipes/default/hook/data/overlay/etc/skel/.local/bin/gnome
Executable file
13
src/recipes/default/hook/data/overlay/etc/skel/.local/bin/gnome
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
# enable the connman integration (shell extension to manage network interfaces)
|
||||
gnome-shell-extension-tool -e gnome-extension-connman@jaakko.hannikainen.intel.com
|
||||
|
||||
# fix Xwayland (and anything using modifiers) graphics problems
|
||||
gsettings set org.gnome.mutter experimental-features "['kms-modifiers']"
|
||||
# disable autosuspend, because we need to suspend with reform-standby only
|
||||
gsettings set org.gnome.desktop.session idle-delay 0
|
||||
|
||||
# launch a GNOME session using mutter's wayland compositor
|
||||
export XDG_SESSION_TYPE=wayland
|
||||
dbus-run-session gnome-session
|
33
src/recipes/default/hook/data/overlay/etc/skel/.local/bin/reform-windowmaker
Executable file
33
src/recipes/default/hook/data/overlay/etc/skel/.local/bin/reform-windowmaker
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# This is a script to demonstrate cage + Xwayland as a replacement for standalone Xorg.
|
||||
# You can modify this to launch classic X window managers / DEs.
|
||||
#
|
||||
# Note that you should disable any x11 compositors. I.e. to launch xfce4:
|
||||
# xfwm4 --compositor=off &
|
||||
# exec xfce4-session
|
||||
#
|
||||
|
||||
DNUM=:0
|
||||
|
||||
cage -- /usr/local/bin/Xwayland $DNUM -retro -noreset &
|
||||
|
||||
export DISPLAY=$DNUM
|
||||
|
||||
# idea lifted from https://gist.github.com/tullmann/476cc71169295d5c3fe6
|
||||
MAX=10
|
||||
CT=0
|
||||
while ! xdpyinfo >/dev/null 2>&1; do
|
||||
sleep 0.50s
|
||||
CT=$(( CT + 1 ))
|
||||
if [ "$CT" -ge "$MAX" ]; then
|
||||
LOG "FATAL: $0: Gave up waiting for X server $DISPLAY"
|
||||
exit 11
|
||||
fi
|
||||
done
|
||||
|
||||
export WAYLAND_DISPLAY=null # Hack, but works
|
||||
export GDK_BACKEND=x11
|
||||
unset SDL_VIDEODRIVER
|
||||
|
||||
exec wmaker
|
|
@ -0,0 +1 @@
|
|||
814db1b1-f4fc-4c51-b66a-c701f568cd8d
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
e783b632-fd3f-493a-ad74-ca017985efa9
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
3cb7a8ba-f529-40b0-b27f-20335c73b69e
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GLib = imports.gi.GLib;
|
||||
const St = imports.gi.St;
|
||||
const Pango = imports.gi.Pango;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Ext = ExtensionUtils.getCurrentExtension();
|
||||
const Interface = Ext.imports.interface;
|
||||
const Logger = Ext.imports.logger;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-extension-connman');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
var DialogField = class DialogField {
|
||||
|
||||
constructor(label) {
|
||||
this.addLabel(label);
|
||||
this.addEntry();
|
||||
}
|
||||
|
||||
addLabel(label) {
|
||||
this.label = new St.Label({
|
||||
style_class: 'cm-prompt-dialog-password-label',
|
||||
text: label,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
y_align: Clutter.ActorAlign.CENTER
|
||||
});
|
||||
this.label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
}
|
||||
|
||||
addEntry() {
|
||||
this.entry = new St.PasswordEntry({
|
||||
style_class: 'cm-prompt-dialog-password-entry',
|
||||
can_focus: true,
|
||||
reactive: true,
|
||||
x_expand: true
|
||||
});
|
||||
ShellEntry.addContextMenu(this.entry);
|
||||
this.entry.clutter_text.set_password_char('\u25cf');
|
||||
}
|
||||
|
||||
getLabel() {
|
||||
return this.label.text;
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.entry.get_text();
|
||||
}
|
||||
|
||||
valid() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var Dialog = GObject.registerClass(class Dialog extends ModalDialog.ModalDialog {
|
||||
|
||||
_init(fields, callback) {
|
||||
super._init({
|
||||
styleClass: 'cm-prompt-dialog'
|
||||
});
|
||||
this._fields = [];
|
||||
this._callback = callback;
|
||||
let mainContentBox = new St.BoxLayout({
|
||||
style_class: 'cm-prompt-dialog-main-layout',
|
||||
vertical: false
|
||||
});
|
||||
let icon = new St.Icon({
|
||||
icon_name: 'dialog-password-symbolic'
|
||||
});
|
||||
let messageBox = new St.BoxLayout({
|
||||
style_class: 'cm-prompt-dialog-message-layout',
|
||||
vertical: true,
|
||||
x_expand: true
|
||||
});
|
||||
let subjectLabel = new St.Label({
|
||||
style_class: 'cm-prompt-dialog-headline headline',
|
||||
text: _("Connection requires authentication")
|
||||
});
|
||||
|
||||
icon.x_fill = true;
|
||||
icon.y_fill = true;
|
||||
icon.x_align = St.Align.END;
|
||||
icon.y_align = St.Align.START;
|
||||
messageBox.y_align = true;
|
||||
|
||||
mainContentBox.add_child(icon);
|
||||
mainContentBox.add_child(messageBox);
|
||||
|
||||
subjectLabel.x_fill = true;
|
||||
subjectLabel.y_fill = false;
|
||||
subjectLabel.y_align = St.Align.START;
|
||||
|
||||
messageBox.add_child(subjectLabel);
|
||||
|
||||
mainContentBox.x_fill = true;
|
||||
mainContentBox.y_fill = true;
|
||||
|
||||
this.contentLayout.add_child(mainContentBox);
|
||||
|
||||
let layout = new Clutter.GridLayout({
|
||||
orientation: Clutter.Orientation.VERTICAL
|
||||
});
|
||||
let secretTable = new St.Widget({
|
||||
style_class: 'cm-network-dialog-secret-table',
|
||||
layout_manager: layout
|
||||
});
|
||||
layout.hookup_style(secretTable);
|
||||
for(let i = 0; i < fields.length; i++) {
|
||||
let field = fields[i];
|
||||
layout.attach(field.label, 0, i, 1, 1);
|
||||
layout.attach(field.entry, 1, i, 1, 1);
|
||||
this._fields[i] = field;
|
||||
}
|
||||
messageBox.add(secretTable);
|
||||
|
||||
this._okButton = {
|
||||
label: _("Connect"),
|
||||
action: this._onOk.bind(this),
|
||||
default: true
|
||||
};
|
||||
this._cancelButton = {
|
||||
label: _("Cancel"),
|
||||
action: this._onCancel.bind(this),
|
||||
key: Clutter.KEY_Escape
|
||||
};
|
||||
this.setButtons([this._cancelButton, this._okButton]);
|
||||
this.open();
|
||||
}
|
||||
|
||||
_onOk() {
|
||||
this.close();
|
||||
if(!this._fields.reduce(function(a, b) {
|
||||
return a && b.valid()
|
||||
}, true))
|
||||
return;
|
||||
let values = {};
|
||||
Object.keys(this._fields).map(function(key) {
|
||||
values[this._fields[key].getLabel()] = this._fields[key].getValue();
|
||||
}.bind(this));
|
||||
this._callback(values);
|
||||
}
|
||||
|
||||
_onCancel() {
|
||||
this.close();
|
||||
this._callback();
|
||||
}
|
||||
});
|
||||
|
||||
var AbstractAgent = class AbstractAgent {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
Release() {
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
ReportErrorAsync([service, error], invocation) {
|
||||
Logger.logDebug('Service reported error: ' + error);
|
||||
invocation.return_dbus_error(this._retryError, '');
|
||||
}
|
||||
|
||||
RequestInputAsync([service, _fields], invocation) {
|
||||
Logger.logDebug('Requested password');
|
||||
var fields = _fields;
|
||||
fields = Object.keys(_fields)
|
||||
.map(function(key) {
|
||||
fields[key] = fields[key].deep_unpack();
|
||||
Object.keys(fields[key]).map(function(innerKey) {
|
||||
fields[key][innerKey] = fields[key][innerKey].deep_unpack();
|
||||
});
|
||||
return [key, fields[key]];
|
||||
});
|
||||
let dialogFields = [];
|
||||
for(let i = 0; i < fields.length; i++)
|
||||
if(fields[i][1]['Requirement'] == 'mandatory')
|
||||
dialogFields.push(new DialogField(fields[i][0]));
|
||||
|
||||
let callback = function(fields) {
|
||||
if(!fields) {
|
||||
invocation.return_dbus_error(this._canceledError,
|
||||
'User canceled password dialog');
|
||||
return;
|
||||
}
|
||||
Object.keys(fields).map(function(key) {
|
||||
fields[key] = GLib.Variant.new('s', fields[key]);
|
||||
});
|
||||
invocation.return_value(GLib.Variant.new('(a{sv})', [fields]));
|
||||
}.bind(this);
|
||||
this._dialog = new Dialog(dialogFields, callback);
|
||||
}
|
||||
|
||||
Cancel(params, invocation) {
|
||||
Logger.logDebug('Password dialog canceled');
|
||||
this._dialog._onCancel();
|
||||
this._dialog = null;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if(this._dialog)
|
||||
this._dialog._onCancel();
|
||||
this._dialog = null;
|
||||
}
|
||||
};
|
||||
|
||||
var Agent = class Agent extends AbstractAgent {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._dbusImpl = Interface.addAgentImplementation(this);
|
||||
this._canceledError = 'net.connman.Agent.Error.Canceled';
|
||||
this._retryError = 'net.connman.Agent.Error.Retry';
|
||||
}
|
||||
|
||||
RequestBrowser(service, url) {
|
||||
Logger.logDebug('Requested browser');
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
Interface.removeAgentImplementation(this._dbusImpl);
|
||||
}
|
||||
};
|
||||
|
||||
var VPNAgent = class VPNAgent extends AbstractAgent {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._dbusImpl = Interface.addVPNAgentImplementation(this);
|
||||
this._canceledError = 'net.connman.vpn.Agent.Error.Canceled';
|
||||
this._retryError = 'net.connman.vpn.Agent.Error.Retry';
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.destroy();
|
||||
Interface.removeVPNAgentImplementation(this._dbusImpl);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,413 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Ext = ExtensionUtils.getCurrentExtension();
|
||||
const Agent = Ext.imports.agent;
|
||||
const Interface = Ext.imports.interface;
|
||||
const Logger = Ext.imports.logger;
|
||||
const Service = Ext.imports.service;
|
||||
const Technology = Ext.imports.technology;
|
||||
|
||||
/* menu with technologies and services */
|
||||
var Menu = class extends PopupMenu.PopupMenuSection {
|
||||
|
||||
constructor(params) {
|
||||
super(params);
|
||||
this._technologies = {};
|
||||
this._serviceTypes = {};
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.actor.hide();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.actor.show();
|
||||
}
|
||||
|
||||
_addSorted(technology) {
|
||||
let items = this._getMenuItems();
|
||||
for(let i = 0; i < items.length; i++) {
|
||||
if(items[i].getValue() < technology.getValue())
|
||||
continue;
|
||||
this.addMenuItem(technology, i);
|
||||
return;
|
||||
}
|
||||
this.addMenuItem(technology);
|
||||
}
|
||||
|
||||
addTechnology(path, properties) {
|
||||
let type = properties.Type.deep_unpack();
|
||||
if(this._technologies[type])
|
||||
this.removeTechnology(path);
|
||||
let proxy = new Interface.TechnologyProxy(path);
|
||||
for(let i in properties)
|
||||
properties[i] = properties[i].deep_unpack();
|
||||
try {
|
||||
this._technologies[type] = Technology.createTechnology(type,
|
||||
properties, proxy, this._manager);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to add technology');
|
||||
return;
|
||||
}
|
||||
this._addSorted(this._technologies[type]);
|
||||
}
|
||||
|
||||
/* FIXME: for some reason destroying an item from the menu
|
||||
* leaves a hole, but for some reason this fixes it */
|
||||
fixMenu() {
|
||||
this.addMenuItem(new PopupMenu.PopupMenuItem('Connman'), 0);
|
||||
this.firstMenuItem.destroy();
|
||||
}
|
||||
|
||||
removeTechnology(path) {
|
||||
let type = path.split('/').pop();
|
||||
Logger.logInfo('Removing technology ' + type);
|
||||
let technology = this._technologies[type];
|
||||
if(!technology) {
|
||||
Logger.logInfo('Tried to remove unknown technology ' + type);
|
||||
return;
|
||||
}
|
||||
technology.destroy();
|
||||
delete this._technologies[type];
|
||||
this.fixMenu();
|
||||
}
|
||||
|
||||
getService(path) {
|
||||
if(!this._serviceTypes[path])
|
||||
return null;
|
||||
if(!this._technologies[this._serviceTypes[path]])
|
||||
return null;
|
||||
return this._technologies[this._serviceTypes[path]].getService(path);
|
||||
}
|
||||
|
||||
addService(path, properties, indicator) {
|
||||
if (!('Type' in properties)) return;
|
||||
let type;
|
||||
if(properties.Type.deep_unpack) {
|
||||
type = properties.Type.deep_unpack();
|
||||
if(type == 'vpn') {
|
||||
indicator.destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
type = 'vpn';
|
||||
properties.Type = {deep_unpack: function() {
|
||||
return 'vpn';
|
||||
}};
|
||||
}
|
||||
this._serviceTypes[path] = type;
|
||||
|
||||
let proxy;
|
||||
if(type != 'vpn')
|
||||
proxy = new Interface.ServiceProxy(path);
|
||||
else
|
||||
proxy = new Interface.ConnectionProxy(path);
|
||||
let service = Service.createService(type, proxy, indicator);
|
||||
service.update(properties);
|
||||
this._technologies[type].addService(path, service);
|
||||
}
|
||||
|
||||
updateService(path, properties) {
|
||||
if(this._serviceTypes[path]) {
|
||||
var type = this._serviceTypes[path];
|
||||
this._technologies[type].updateService(path, properties);
|
||||
return;
|
||||
} else
|
||||
this.addService(path, properties);
|
||||
}
|
||||
|
||||
removeService(path) {
|
||||
if(!this._serviceTypes[path]) {
|
||||
log('Tried to remove unknown service ' + path);
|
||||
return;
|
||||
}
|
||||
if(this._technologies[this._serviceTypes[path]]) {
|
||||
log('Removing service ' + path);
|
||||
this._technologies[this._serviceTypes[path]].removeService(path);
|
||||
}
|
||||
delete this._serviceTypes[path];
|
||||
this.fixMenu();
|
||||
}
|
||||
|
||||
clear() {
|
||||
for(let type in this._technologies) {
|
||||
try {
|
||||
if(type != "vpn") {
|
||||
this._technologies[type].destroy();
|
||||
delete this._technologies[type];
|
||||
}
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to clear technology ' + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vpnClear() {
|
||||
if(!this._technologies["vpn"])
|
||||
return;
|
||||
try {
|
||||
this._technologies["vpn"].destroy();
|
||||
delete this._technologies["vpn"];
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to clear VPN connections');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* main applet class handling everything */
|
||||
var Applet = GObject.registerClass(class Applet extends PanelMenu.SystemIndicator {
|
||||
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
this._menu = new Menu();
|
||||
this.menu.addMenuItem(this._menu);
|
||||
this.menu.actor.show();
|
||||
|
||||
log('Enabling Connman applet');
|
||||
this._watch = Gio.DBus.system.watch_name(Interface.BUS_NAME,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
this._connectEvent.bind(this),
|
||||
this._disconnectEvent.bind(this));
|
||||
this._vpnwatch = Gio.DBus.system.watch_name(Interface.VPN_BUS_NAME,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
this._vpnConnectEvent.bind(this),
|
||||
this._vpnDisconnectEvent.bind(this));
|
||||
}
|
||||
|
||||
_addIndicator() {
|
||||
let indicator = super._addIndicator();
|
||||
indicator.hide();
|
||||
return indicator;
|
||||
}
|
||||
|
||||
_updateService(path, properties) {
|
||||
if(path.indexOf("service/vpn") != -1)
|
||||
return;
|
||||
if(this._menu.getService(path))
|
||||
this._menu.updateService(path, properties);
|
||||
else
|
||||
this._menu.addService(path, properties, this._addIndicator());
|
||||
}
|
||||
|
||||
_updateAllServices() {
|
||||
this._manager.GetServicesRemote(function(result, exception) {
|
||||
if(!result || exception) {
|
||||
Logger.logError('Error fetching services: ' + exception);
|
||||
return;
|
||||
}
|
||||
let services = result[0];
|
||||
for (var o of services)
|
||||
this._updateService(o[0], o[1]);
|
||||
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
_updateAllTechnologies() {
|
||||
this._menu.clear();
|
||||
this._manager.GetTechnologiesRemote(function(result, exception) {
|
||||
if(!result || exception) {
|
||||
Logger.logError('Error fetching technologies: ' + exception);
|
||||
return;
|
||||
}
|
||||
let technologies = result[0];
|
||||
for (var o of technologies)
|
||||
this._menu.addTechnology(o[0], o[1]);
|
||||
this._updateAllServices();
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
_updateAllConnections() {
|
||||
this._menu.vpnClear();
|
||||
|
||||
this._menu._technologies['vpn'] = Technology.createTechnology('vpn',
|
||||
{Powered: true});
|
||||
this._menu.addMenuItem(this._menu._technologies['vpn']);
|
||||
|
||||
this._vpnManager.GetConnectionsRemote(function(result, exception) {
|
||||
if(!result || exception) {
|
||||
Logger.logError('Error fetching VPN connections: ' + exception);
|
||||
return;
|
||||
}
|
||||
let connections = result[0];
|
||||
for (var o of connections) {
|
||||
o[1]['Type'] = 'vpn';
|
||||
this._menu.addService(o[0], o[1], this._addIndicator());
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
_updateVisibility() {
|
||||
if(this._manager || this._vpnManager) {
|
||||
this.menu.actor.show();
|
||||
//this.indicators.show();
|
||||
}
|
||||
else {
|
||||
this.menu.actor.hide();
|
||||
//this.indicators.hide();
|
||||
}
|
||||
}
|
||||
|
||||
_connectEvent() {
|
||||
Logger.logInfo('Connected to Connman');
|
||||
|
||||
this._manager = new Interface.ManagerProxy();
|
||||
this._menu._manager = this._manager;
|
||||
this._agent = new Agent.Agent();
|
||||
|
||||
this._manager.RegisterAgentRemote(Interface.AGENT_PATH);
|
||||
this._asig = this._manager.connectSignal('TechnologyAdded',
|
||||
function(proxy, sender, o) {
|
||||
try {
|
||||
this._menu.addTechnology(o[0], o[1]);
|
||||
} catch(error) {
|
||||
Logger.logException(error);
|
||||
}
|
||||
}.bind(this));
|
||||
this._rsig = this._manager.connectSignal('TechnologyRemoved',
|
||||
function(proxy, sender, [path, properties]) {
|
||||
this._menu.removeTechnology(path);
|
||||
}.bind(this));
|
||||
this._psig = this._manager.connectSignal('PropertyChanged',
|
||||
function(proxy, sender, [property, value]) {
|
||||
Logger.logDebug('Global property ' + property +
|
||||
' changed: ' + value.deep_unpack());
|
||||
}.bind(this));
|
||||
this._ssig = this._manager.connectSignal('ServicesChanged',
|
||||
function(proxy, sender, [changed, removed]) {
|
||||
try {
|
||||
for (var o of changed)
|
||||
this._updateService(o[0], o[1]);
|
||||
for (var path of removed)
|
||||
this._menu.removeService(path);
|
||||
} catch(error) {
|
||||
Logger.logException(error);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this._updateAllTechnologies();
|
||||
this._updateVisibility();
|
||||
}
|
||||
|
||||
_vpnConnectEvent() {
|
||||
this._vpnManager = new Interface.VPNManagerProxy();
|
||||
this._vpnAgent = new Agent.VPNAgent();
|
||||
this._vpnManager.RegisterAgentRemote(Interface.VPN_AGENT_PATH);
|
||||
this._updateVisibility();
|
||||
|
||||
this._vasig = this._vpnManager.connectSignal('ConnectionAdded',
|
||||
function(proxy, sender, [path, properties]) {
|
||||
try {
|
||||
properties['Type'] = 'vpn';
|
||||
this._menu.addService(path, properties, this._addIndicator());
|
||||
} catch(error) {
|
||||
Logger.logException(error);
|
||||
}
|
||||
}.bind(this));
|
||||
this._vrsig = this._vpnManager.connectSignal('ConnectionRemoved',
|
||||
function(proxy, sender, [path, properties]) {
|
||||
this._menu.removeService(path);
|
||||
}.bind(this));
|
||||
|
||||
this._updateAllConnections();
|
||||
}
|
||||
|
||||
_vpnDisconnectEvent() {
|
||||
let signals = [this._vasig, this._vrsig];
|
||||
if(this._vpnManager) {
|
||||
Logger.logDebug('Disconnecting vpn signals');
|
||||
for(let signalId in signals) {
|
||||
try {
|
||||
Logger.logDebug('Disconnecting signal ' + signals[signalId]);
|
||||
this._vpnManager.disconnectSignal(signals[signalId]);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to disconnect signal');
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
if(this._vpnManager)
|
||||
this._vpnManager.UnregisterAgentRemote(Interface.VPN_AGENT_PATH);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to unregister vpn agent');
|
||||
}
|
||||
this._vpnManager = null;
|
||||
if(this._vpnAgent)
|
||||
this._vpnAgent.destroy();
|
||||
this.vpnAgent = null;
|
||||
this._updateVisibility();
|
||||
}
|
||||
|
||||
_disconnectEvent() {
|
||||
Logger.logInfo('Disconnected from Connman');
|
||||
this._menu.clear();
|
||||
this._menu._manager = null;
|
||||
let signals = [this._asig, this._rsig, this._ssig, this._psig];
|
||||
if(this._manager) {
|
||||
Logger.logDebug('Disconnecting signals');
|
||||
for(let signalId in signals) {
|
||||
try {
|
||||
Logger.logDebug('Disconnecting signal ' + signals[signalId]);
|
||||
this._manager.disconnectSignal(signals[signalId]);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to disconnect signal');
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
this._manager.UnregisterAgentRemote(Interface.AGENT_PATH);
|
||||
} catch(error) {
|
||||
}
|
||||
this._manager = null;
|
||||
if(this._agent)
|
||||
this._agent.destroy();
|
||||
this._agent = null;
|
||||
this._updateVisibility();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
Logger.logInfo('Destroying Connman applet');
|
||||
this._disconnectEvent();
|
||||
this._menu.clear();
|
||||
//this.indicators.destroy();
|
||||
this.menu.actor.destroy();
|
||||
if(this._watch)
|
||||
Gio.DBus.system.unwatch_name(this._watch);
|
||||
if(this._vpnwatch)
|
||||
Gio.DBus.system.unwatch_name(this._vpnwatch);
|
||||
if(this._agent)
|
||||
this._agent.destroy();
|
||||
if(this._vpnAgent)
|
||||
this._vpnAgent.destroy();
|
||||
this._agent = null;
|
||||
this._vpnAgent = null;
|
||||
this._watch = null;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Ext = ExtensionUtils.getCurrentExtension();
|
||||
const Applet = Ext.imports.applet;
|
||||
|
||||
let applet;
|
||||
let menu = Main.panel.statusArea.aggregateMenu;
|
||||
|
||||
function init() {
|
||||
}
|
||||
|
||||
function enable() {
|
||||
applet = new Applet.Applet();
|
||||
// XXX: Magic numbers
|
||||
menu.menu.addMenuItem(applet.menu, 3);
|
||||
menu._indicators.insert_child_at_index(applet.indicators, 3);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
if(applet)
|
||||
applet.destroy();
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
|
||||
var BUS_NAME = 'net.connman';
|
||||
var VPN_BUS_NAME = 'net.connman.vpn';
|
||||
var MANAGER_PATH = '/';
|
||||
var AGENT_PATH = '/net/connman/gnome3/agent';
|
||||
var VPN_AGENT_PATH = '/net/connman/gnome3/vpn/agent';
|
||||
|
||||
const _MANAGER_INTERFACE = '<node>\
|
||||
<interface name="net.connman.Manager">\
|
||||
<method name="GetProperties">\
|
||||
<arg name="properties" type="a{sv}" direction="out"/>\
|
||||
</method>\
|
||||
<method name="SetProperty">\
|
||||
<arg name="name" type="s" direction="in"/>\
|
||||
<arg name="value" type="v" direction="in"/>\
|
||||
</method>\
|
||||
<method name="GetTechnologies">\
|
||||
<arg name="technologies" type="a(oa{sv})" direction="out"/>\
|
||||
</method>\
|
||||
<method name="GetServices">\
|
||||
<arg name="services" type="a(oa{sv})" direction="out"/>\
|
||||
</method>\
|
||||
<method name="RegisterAgent">\
|
||||
<arg name="path" type="o" direction="in"/>\
|
||||
</method>\
|
||||
<method name="UnregisterAgent">\
|
||||
<arg name="path" type="o" direction="in"/>\
|
||||
</method>\
|
||||
<signal name="PropertyChanged">\
|
||||
<arg name="name" type="s"/>\
|
||||
<arg name="value" type="v"/>\
|
||||
</signal>\
|
||||
<signal name="TechnologyAdded">\
|
||||
<arg name="path" type="o"/>\
|
||||
<arg name="properties" type="a{sv}"/>\
|
||||
</signal>\
|
||||
<signal name="TechnologyRemoved">\
|
||||
<arg name="path" type="o"/>\
|
||||
</signal>\
|
||||
<signal name="ServicesChanged">\
|
||||
<arg name="changed" type="a(oa{sv})"/>\
|
||||
<arg name="removed" type="ao"/>\
|
||||
</signal>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _TECHNOLOGY_INTERFACE = '<node>\
|
||||
<interface name="net.connman.Technology">\
|
||||
<method name="SetProperty">\
|
||||
<arg name="name" type="s" direction="in"/>\
|
||||
<arg name="value" type="v" direction="in"/>\
|
||||
</method>\
|
||||
<method name="GetProperties">\
|
||||
<arg name="properties" type="a{sv}" direction="out"/>\
|
||||
</method>\
|
||||
<method name="Scan"></method>\
|
||||
<signal name="PropertyChanged">\
|
||||
<arg name="name" type="s"/>\
|
||||
<arg name="value" type="v"/>\
|
||||
</signal>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _SERVICE_INTERFACE = '<node>\
|
||||
<interface name="net.connman.Service">\
|
||||
<method name="SetProperty">\
|
||||
<arg name="name" type="s" direction="in"/>\
|
||||
<arg name="value" type="v" direction="in"/>\
|
||||
</method>\
|
||||
<method name="Connect"></method>\
|
||||
<method name="Disconnect"></method>\
|
||||
<signal name="PropertyChanged">\
|
||||
<arg name="name" type="s"/>\
|
||||
<arg name="value" type="v"/>\
|
||||
</signal>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _AGENT_INTERFACE = '<node>\
|
||||
<interface name="net.connman.Agent">\
|
||||
<method name="Release"></method>\
|
||||
<method name="ReportError">\
|
||||
<arg name="service" type="o" direction="in"/>\
|
||||
<arg name="error" type="s" direction="in"/>\
|
||||
</method>\
|
||||
<method name="RequestBrowser">\
|
||||
<arg name="service" type="o" direction="in"/>\
|
||||
<arg name="url" type="s" direction="in"/>\
|
||||
</method>\
|
||||
<method name="RequestInput">\
|
||||
<arg name="service" type="o" direction="in"/>\
|
||||
<arg name="fields" type="a{sv}" direction="in"/>\
|
||||
<arg name="values" type="a{sv}" direction="out"/>\
|
||||
</method>\
|
||||
<method name="Cancel"></method>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _CONNECTION_INTERFACE = '<node>\
|
||||
<interface name="net.connman.vpn.Connection">\
|
||||
<method name="SetProperty">\
|
||||
<arg name="name" type="s" direction="in"/>\
|
||||
<arg name="value" type="v" direction="in"/>\
|
||||
</method>\
|
||||
<method name="Connect"></method>\
|
||||
<method name="Disconnect"></method>\
|
||||
<signal name="PropertyChanged">\
|
||||
<arg name="name" type="s"/>\
|
||||
<arg name="value" type="v"/>\
|
||||
</signal>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
|
||||
const _VPN_MANAGER_INTERFACE = '<node>\
|
||||
<interface name="net.connman.vpn.Manager">\
|
||||
<method name="Create">\
|
||||
<arg name="settings" type="a{sv}" direction="in"/>\
|
||||
</method>\
|
||||
<method name="Remove">\
|
||||
<arg name="vpn" type="o" direction="in"/>\
|
||||
</method>\
|
||||
<method name="GetConnections">\
|
||||
<arg name="connections" type="a(oa{sv})" direction="out"/>\
|
||||
</method>\
|
||||
<method name="RegisterAgent">\
|
||||
<arg name="path" type="o" direction="in"/>\
|
||||
</method>\
|
||||
<method name="UnregisterAgent">\
|
||||
<arg name="path" type="o" direction="in"/>\
|
||||
</method>\
|
||||
<signal name="ConnectionAdded">\
|
||||
<arg name="path" type="o"/>\
|
||||
<arg name="properties" type="a{sv}"/>\
|
||||
</signal>\
|
||||
<signal name="ConnectionRemoved">\
|
||||
<arg name="path" type="o"/>\
|
||||
</signal>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _VPN_AGENT_INTERFACE = '<node>\
|
||||
<interface name="net.connman.vpn.Agent">\
|
||||
<method name="Release"></method>\
|
||||
<method name="ReportError">\
|
||||
<arg name="service" type="o" direction="in"/>\
|
||||
<arg name="error" type="s" direction="in"/>\
|
||||
</method>\
|
||||
<method name="RequestInput">\
|
||||
<arg name="service" type="o" direction="in"/>\
|
||||
<arg name="fields" type="a{sv}" direction="in"/>\
|
||||
<arg name="values" type="a{sv}" direction="out"/>\
|
||||
</method>\
|
||||
<method name="Cancel"></method>\
|
||||
</interface>\
|
||||
</node>';
|
||||
|
||||
const _ManagerProxyWrapper = Gio.DBusProxy.makeProxyWrapper(_MANAGER_INTERFACE);
|
||||
const _TechnologyProxyWrapper = Gio.DBusProxy.makeProxyWrapper(_TECHNOLOGY_INTERFACE);
|
||||
const _ServiceProxyWrapper = Gio.DBusProxy.makeProxyWrapper(_SERVICE_INTERFACE);
|
||||
const _ConnectionProxyWrapper = Gio.DBusProxy.makeProxyWrapper(_CONNECTION_INTERFACE);
|
||||
const _VPNManagerProxyWrapper = Gio.DBusProxy.makeProxyWrapper(_VPN_MANAGER_INTERFACE);
|
||||
|
||||
function ManagerProxy() {
|
||||
return new _ManagerProxyWrapper(Gio.DBus.system, BUS_NAME, MANAGER_PATH);
|
||||
}
|
||||
|
||||
function VPNManagerProxy() {
|
||||
return new _VPNManagerProxyWrapper(Gio.DBus.system, VPN_BUS_NAME, MANAGER_PATH);
|
||||
}
|
||||
|
||||
function TechnologyProxy(path) {
|
||||
return new _TechnologyProxyWrapper(Gio.DBus.system, BUS_NAME, path);
|
||||
}
|
||||
|
||||
function ServiceProxy(path) {
|
||||
return new _ServiceProxyWrapper(Gio.DBus.system, BUS_NAME, path);
|
||||
}
|
||||
|
||||
function ConnectionProxy(path) {
|
||||
return new _ConnectionProxyWrapper(Gio.DBus.system, VPN_BUS_NAME, path);
|
||||
}
|
||||
|
||||
function addAgentImplementation(agent) {
|
||||
let dbusImpl = Gio.DBusExportedObject.wrapJSObject(_AGENT_INTERFACE, agent);
|
||||
dbusImpl.export(Gio.DBus.system, AGENT_PATH);
|
||||
return dbusImpl;
|
||||
}
|
||||
|
||||
function removeAgentImplementation(dbusImpl) {
|
||||
dbusImpl.unexport(Gio.DBus.system, AGENT_PATH);
|
||||
}
|
||||
|
||||
function addVPNAgentImplementation(agent) {
|
||||
let dbusImpl = Gio.DBusExportedObject.wrapJSObject(_VPN_AGENT_INTERFACE, agent);
|
||||
dbusImpl.export(Gio.DBus.system, VPN_AGENT_PATH);
|
||||
return dbusImpl;
|
||||
}
|
||||
|
||||
function removeVPNAgentImplementation(dbusImpl) {
|
||||
dbusImpl.unexport(Gio.DBus.system, VPN_AGENT_PATH);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
|
||||
var enabled = true;
|
||||
var logLevel = 2;
|
||||
var infoEnabled = true;
|
||||
|
||||
function logMessage(msg) {
|
||||
log('Connman-applet: ' + msg);
|
||||
}
|
||||
|
||||
function logError(error) {
|
||||
logMessage('ERROR: ' + error);
|
||||
}
|
||||
|
||||
function logException(exception, msg) {
|
||||
if(msg)
|
||||
logMessage('Exception: ' + msg);
|
||||
logMessage('Exception: ' + exception + ': ' + exception.stack);
|
||||
}
|
||||
|
||||
function logWarning(error) {
|
||||
if(loglevel > 1)
|
||||
logMessage('WARNING: ' + error);
|
||||
}
|
||||
|
||||
function logInfo(msg) {
|
||||
if(logLevel > 2)
|
||||
logMessage('INFO: ' + msg);
|
||||
}
|
||||
|
||||
function logDebug(msg) {
|
||||
if(logLevel > 3)
|
||||
logMessage('DEBUG: ' + msg);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"uuid": "gnome-extension-connman@jaakko.hannikainen.intel.com",
|
||||
"name": "ConnMan Extension",
|
||||
"description": "Gnome-Shell ConnMan extension",
|
||||
"shell-version": ["3.14", "3.16", "3.18", "3.20"],
|
||||
"url": "https://github.com/mntmn/gnome-extension-connman"
|
||||
}
|
|
@ -0,0 +1,582 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const St = imports.gi.St;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Dialog = imports.ui.dialog;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-extension-connman');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Ext = ExtensionUtils.getCurrentExtension();
|
||||
const Version = Ext.imports.version;
|
||||
const version = Version.version();
|
||||
|
||||
const Logger = Ext.imports.logger;
|
||||
|
||||
const DialogServiceItem = class DialogServiceItem {
|
||||
|
||||
constructor(service, callback) {
|
||||
let name = service.name || service.label.text;
|
||||
if(!name)
|
||||
return;
|
||||
let icon = service.getIcon();
|
||||
let securityIcon = service.securityIcon ? service.securityIcon() : '';
|
||||
this.service = service;
|
||||
this.actor = new St.BoxLayout({
|
||||
style_class: 'cm-dialog-item',
|
||||
can_focus: true,
|
||||
reactive: true
|
||||
});
|
||||
this.actor.connect('key-focus-in', function() {
|
||||
callback(this);
|
||||
}.bind(this));
|
||||
let action = new Clutter.ClickAction();
|
||||
action.connect('clicked', function() {
|
||||
this.actor.grab_key_focus();
|
||||
}.bind(this));
|
||||
this.actor.add_action(action);
|
||||
|
||||
this._label = new St.Label({
|
||||
text: name
|
||||
});
|
||||
this.actor.label_actor = this._label;
|
||||
this._icons = new St.BoxLayout({
|
||||
style_class: 'cm-dialog-icons'
|
||||
});
|
||||
this._icon = new St.Icon({
|
||||
style_class: 'cm-dialog-icon'
|
||||
});
|
||||
this._securityIcon = new St.Icon({
|
||||
style_class: 'cm-dialog-icon'
|
||||
});
|
||||
this._icon.icon_name = icon;
|
||||
this._securityIcon.icon_name = securityIcon;
|
||||
if(service._properties['Favorite']) {
|
||||
let icon = new St.Icon({
|
||||
style_class: 'cm-dialog-icon',
|
||||
icon_name: 'object-select-symbolic'
|
||||
});
|
||||
icon.add_style_pseudo_class('favourite');
|
||||
this.actor.add_style_pseudo_class('favourite');
|
||||
this.actor.add(icon);
|
||||
}
|
||||
this._icons.add_actor(this._securityIcon);
|
||||
this._icons.add_actor(this._icon);
|
||||
this._label.x_align = St.Align.START;
|
||||
this.actor.add_child(this._label);
|
||||
this._icons.expand = true;
|
||||
this._icons.x_fill = true;
|
||||
this._icons.x_align = St.Align.END;
|
||||
this.actor.add_child(this._icons);
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.actor.can_focus = true;
|
||||
this.actor.reactive = true;
|
||||
this.actor.remove_style_pseudo_class('passive');
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.actor.can_focus = false;
|
||||
this.actor.reactive = false;
|
||||
this.actor.add_style_pseudo_class('passive');
|
||||
}
|
||||
};
|
||||
|
||||
var ServiceChooser = GObject.registerClass(class ServiceChooser extends ModalDialog.ModalDialog {
|
||||
|
||||
_init(proxy, services, callback) {
|
||||
super._init({});
|
||||
this._proxy = proxy;
|
||||
this._services = {};
|
||||
|
||||
let content = new Dialog.MessageDialogContent({ title: _('Select Wireless Network') });
|
||||
this.contentLayout.add_actor(content);
|
||||
|
||||
this._stack = new St.Widget({
|
||||
layout_manager: new Clutter.BinLayout()
|
||||
});
|
||||
this._itemBox = new St.BoxLayout({
|
||||
vertical: true,
|
||||
style_class: 'cm-dialog-box'
|
||||
});
|
||||
this._boxes = {};
|
||||
this._scrollView = new St.ScrollView({
|
||||
style_class: 'cm-dialog-scroll-view'
|
||||
});
|
||||
this._scrollView.set_x_expand(true);
|
||||
this._scrollView.set_y_expand(true);
|
||||
this._scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
this._scrollView.add_actor(this._itemBox);
|
||||
this._stack.add_child(this._scrollView);
|
||||
|
||||
this.contentLayout.x_expand = true;
|
||||
this.contentLayout.add_child(this._stack);
|
||||
|
||||
for(let id in services)
|
||||
this.addService(services[id]);
|
||||
this.scanRemote();
|
||||
this._closed = false;
|
||||
this._timeout = Mainloop.timeout_add_seconds(15, function() {
|
||||
this.scanRemote();
|
||||
return !this._closed;
|
||||
}.bind(this));
|
||||
|
||||
this._cancelButton = this.addButton({
|
||||
action: this.cancel.bind(this),
|
||||
label: _("Cancel"),
|
||||
key: Clutter.Escape
|
||||
});
|
||||
|
||||
this._connectButton = this.addButton({
|
||||
action: this.buttonEvent.bind(this),
|
||||
label: _("Connect"),
|
||||
key: Clutter.Enter
|
||||
});
|
||||
this._connectButton.reactive = true;
|
||||
this._connectButton.can_focus = true;
|
||||
|
||||
this._callback = callback;
|
||||
|
||||
this.open();
|
||||
}
|
||||
|
||||
scanRemote() {
|
||||
this._proxy.ScanRemote();
|
||||
}
|
||||
|
||||
selectedEvent(service) {
|
||||
if(this._selected)
|
||||
this._selected.actor.remove_style_pseudo_class('selected');
|
||||
Util.ensureActorVisibleInScrollView(this._scrollView, service.actor);
|
||||
this._selected = service;
|
||||
this._selected.actor.add_style_pseudo_class('selected');
|
||||
this._connectButton.reactive = true;
|
||||
this._connectButton.can_focus = true;
|
||||
}
|
||||
|
||||
close() {
|
||||
super.close();
|
||||
this._closed = true;
|
||||
Mainloop.source_remove(this._timeout);
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
buttonEvent() {
|
||||
this.close();
|
||||
this._callback(this._selected && this._selected.service);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this._callback();
|
||||
this.close();
|
||||
}
|
||||
|
||||
addService(service) {
|
||||
if(this._services[service[0].id]) {
|
||||
this._services[service[0].id].enable();
|
||||
return;
|
||||
}
|
||||
let item = new DialogServiceItem(service[0], this.selectedEvent.bind(this));
|
||||
if(!item.actor)
|
||||
return;
|
||||
let intf = service[1];
|
||||
if(!this._boxes[intf]) {
|
||||
if(Object.keys(this._boxes).length == 1)
|
||||
this._boxes[Object.keys(this._boxes)[0]]['label'].show();
|
||||
let label = new St.Label({
|
||||
text: intf,
|
||||
style_class: 'cm-dialog-interface',
|
||||
});
|
||||
let box = new St.BoxLayout({
|
||||
vertical: true,
|
||||
style_class: 'cm-dialog-box'
|
||||
});
|
||||
this._boxes[intf] = {};
|
||||
this._boxes[intf]['label'] = label;
|
||||
this._boxes[intf]['box'] = box;
|
||||
label.hide();
|
||||
if(Object.keys(this._boxes).length > 1)
|
||||
label.show();
|
||||
this._itemBox.add_child(label);
|
||||
this._itemBox.add_child(box);
|
||||
}
|
||||
this._boxes[intf]['box'].add_child(item.actor);
|
||||
this._services[service[0].id] = item;
|
||||
}
|
||||
|
||||
updateService(service) {
|
||||
if(this._closed)
|
||||
return;
|
||||
if(!this._services[service[0].id])
|
||||
this.addService(service);
|
||||
else
|
||||
this._services[service[0].id]._label.text = service[0].name || service[0].label.text;
|
||||
}
|
||||
|
||||
removeService(id) {
|
||||
if(this._services[id])
|
||||
this._services[id].disable();
|
||||
}
|
||||
});
|
||||
|
||||
var Service = GObject.registerClass(class Service extends PopupMenu.PopupSubMenuMenuItem {
|
||||
|
||||
_init(type, proxy, indicator) {
|
||||
super._init('', true);
|
||||
|
||||
this.type = type;
|
||||
|
||||
this._properties = {};
|
||||
|
||||
this._proxy = proxy;
|
||||
|
||||
this._connected = true;
|
||||
this._connectionSwitch = new PopupMenu.PopupMenuItem(_("Connect"));
|
||||
this._connectionSwitch.connect('activate', this.buttonEvent.bind(this));
|
||||
|
||||
this._sig = this._proxy.connectSignal('PropertyChanged',
|
||||
function(proxy, sender, [name, value]) {
|
||||
let obj = {};
|
||||
obj[name] = value;
|
||||
this.update(obj);
|
||||
}.bind(this));
|
||||
|
||||
this.state = 'idle'
|
||||
this.hidden = true;
|
||||
|
||||
this._icons = {
|
||||
'ok': 'network-transmit-receive-symbolic',
|
||||
'acquiring': 'network-no-route-symbolic',
|
||||
'offline': 'network-offline-symbolic',
|
||||
'error': 'network-error-symbolic'
|
||||
};
|
||||
|
||||
this._indicator = indicator;
|
||||
this.label.text = '';
|
||||
|
||||
this._settings = new PopupMenu.PopupMenuItem(_("Settings"));
|
||||
this._settings.connect('activate', this.openSettings.bind(this));
|
||||
|
||||
if(version < 318)
|
||||
this.status.text = this.state;
|
||||
else
|
||||
this.label.text = this.state;
|
||||
|
||||
this.menu.addMenuItem(this._connectionSwitch);
|
||||
this.menu.addMenuItem(this._settings);
|
||||
this.show();
|
||||
}
|
||||
|
||||
openSettings() {
|
||||
Util.spawnApp(['connman-gtk', '--page', this.type]);
|
||||
}
|
||||
|
||||
buttonEvent() {
|
||||
if(this.state == 'idle' || this.state == 'failure' || this.state == 'disconnect')
|
||||
this._proxy.ConnectRemote();
|
||||
else
|
||||
this._proxy.DisconnectRemote();
|
||||
}
|
||||
|
||||
update(properties) {
|
||||
for(let key in properties) {
|
||||
let newProperty = properties[key].deep_unpack();
|
||||
if(newProperty instanceof Object && !(newProperty instanceof Array)) {
|
||||
if(!this._properties[key])
|
||||
this._properties[key] = {};
|
||||
for(let innerKey in newProperty) {
|
||||
this._properties[key][innerKey] =
|
||||
newProperty[innerKey].deep_unpack();
|
||||
}
|
||||
} else {
|
||||
this._properties[key] = newProperty;
|
||||
}
|
||||
}
|
||||
if(properties.State)
|
||||
this.state = properties.State.deep_unpack();
|
||||
if(this.state == 'idle' || this.state == 'disconnect')
|
||||
this._connectionSwitch.label.text = _("Connect");
|
||||
else if(this.state == 'failure')
|
||||
this._connectionSwitch.label.text = _("Reconnect");
|
||||
else
|
||||
this._connectionSwitch.label.text = _("Disconnect");
|
||||
if(this._properties['Name']) {
|
||||
this.name = this._properties['Name'];
|
||||
this.hidden = false;
|
||||
}
|
||||
if(this.state == 'idle' || this.state == 'disconnect' ||
|
||||
this.state == 'failure')
|
||||
this._indicator.hide();
|
||||
else
|
||||
this._indicator.show();
|
||||
if(version < 318)
|
||||
this.status.text = this.getStateString();
|
||||
else
|
||||
this.label.text = this.name + " - " + this.getStateString();
|
||||
this.setIcon(this.getStatusIcon());
|
||||
}
|
||||
|
||||
signalToIcon() {
|
||||
let value = this._properties['Strength'];
|
||||
if(value > 80)
|
||||
return 'excellent';
|
||||
if(value > 55)
|
||||
return 'good';
|
||||
if(value > 30)
|
||||
return 'ok';
|
||||
if(value > 5)
|
||||
return 'weak';
|
||||
return 'none';
|
||||
}
|
||||
|
||||
getStateString() {
|
||||
let states = {
|
||||
idle: _("Idle"),
|
||||
failure: _("Failure"),
|
||||
association: _("Association"),
|
||||
configuration: _("Configuration"),
|
||||
ready: _("Ready"),
|
||||
disconnect: _("Disconnected"),
|
||||
online: _("Online") };
|
||||
return states[this.state] || this.state;
|
||||
}
|
||||
|
||||
setIcon(iconName) {
|
||||
this._indicator.icon_name = iconName;
|
||||
this.icon.icon_name = iconName;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._indicator.destroy();
|
||||
try {
|
||||
this._proxy.disconnectSignal(this._sig);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to disconnect service proxy');
|
||||
}
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return this._icons['ok'];
|
||||
}
|
||||
|
||||
getAcquiringIcon() {
|
||||
return this._icons['acquiring'];
|
||||
}
|
||||
|
||||
getOfflineIcon() {
|
||||
return this._icons['offline'];
|
||||
}
|
||||
|
||||
getErrorIcon() {
|
||||
return this._icons['error'];
|
||||
}
|
||||
|
||||
getStatusIcon() {
|
||||
let iconGetters = {
|
||||
online: this.getIcon,
|
||||
ready: this.getIcon,
|
||||
configuration: this.getAcquiringIcon,
|
||||
association: this.getAcquiringIcon,
|
||||
disconnect: this.getOfflineIcon,
|
||||
idle: this.getOfflineIcon,
|
||||
};
|
||||
if(iconGetters[this.state])
|
||||
return iconGetters[this.state].bind(this)();
|
||||
return this.getErrorIcon();
|
||||
}
|
||||
|
||||
show() {
|
||||
//this.actor.show();
|
||||
this._indicator.show();
|
||||
}
|
||||
|
||||
hide() {
|
||||
//this.actor.hide();
|
||||
this._indicator.hide();
|
||||
}
|
||||
});
|
||||
|
||||
var EthernetService = GObject.registerClass(class EthernetService extends Service {
|
||||
|
||||
_init(proxy, indicator) {
|
||||
super._init('ethernet', proxy, indicator);
|
||||
this.name = _("Wired");
|
||||
this.label.text = this.name;
|
||||
this._settings.label.text = _("Wired Settings");
|
||||
this._icons = {
|
||||
'ok': 'network-wired-symbolic',
|
||||
'acquiring': 'network-wired-acquiring-symbolic',
|
||||
'offline': 'network-wired-offline-symbolic',
|
||||
'error': 'network-error-symbolic'
|
||||
};
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
update(properties) {
|
||||
super.update(properties);
|
||||
if(version < 318 && this._properties['Name'] == 'Wired') {
|
||||
/* ensure translated name */
|
||||
this._properties['Name'] = _("Wired");
|
||||
this.label.text = _("Wired");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var WirelessService = GObject.registerClass(class WirelessService extends Service {
|
||||
|
||||
_init(proxy, indicator) {
|
||||
super._init('wifi', proxy, indicator);
|
||||
this.name = _("Hidden");
|
||||
this._settings.label.text = _("Wireless Settings");
|
||||
this._icons = {
|
||||
'ok': 'network-wireless-connected-symbolic',
|
||||
'acquiring': 'network-wireless-acquiring-symbolic',
|
||||
'offline': 'network-wireless-offline-symbolic',
|
||||
'error': 'network-error-symbolic'
|
||||
};
|
||||
}
|
||||
|
||||
securityIcon() {
|
||||
let security = this._properties['Security'][0];
|
||||
if(!security || security == 'none')
|
||||
return '';
|
||||
let icons = {
|
||||
ieee8021x: 'security-high-symbolic',
|
||||
wep: 'security-low-symbolic',
|
||||
};
|
||||
return icons[security] || 'security-medium-symbolic';
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return 'network-wireless-signal-' + this.signalToIcon() + '-symbolic';
|
||||
}
|
||||
|
||||
update(properties) {
|
||||
super.update(properties);
|
||||
|
||||
if(this.state == 'idle' || this.state == 'disconnect' ||
|
||||
this.state == 'failure')
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
|
||||
if(this.hidden) {
|
||||
let security = this._properties['Security'][0];
|
||||
if(!security)
|
||||
security = 'none';
|
||||
let names = {
|
||||
ieee8021x: _("Hidden ieee8021x secured network"),
|
||||
psk: _("Hidden WPA secured network"),
|
||||
wep: _("Hidden WEP secured network"),
|
||||
wps: _("Hidden WPS secured network"),
|
||||
none: _("Hidden unsecured network")
|
||||
};
|
||||
this.name = names[security] || _("Hidden network");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var BluetoothService = GObject.registerClass(class BluetoothService extends Service {
|
||||
|
||||
_init(proxy, indicator) {
|
||||
super._init('bluetooth', proxy, indicator);
|
||||
this._settings.label.text = _("Bluetooth Settings");
|
||||
this._icons = {
|
||||
'ok': 'bluetooth-active-symbolic',
|
||||
'acquiring': 'bluetooth-active-symbolic',
|
||||
'offline': 'bluetooth-disabled-symbolic',
|
||||
'error': 'network-error-symbolic'
|
||||
};
|
||||
|
||||
this.show();
|
||||
}
|
||||
});
|
||||
|
||||
var CellularService = GObject.registerClass(class CellularService extends Service {
|
||||
|
||||
_init(proxy, indicator) {
|
||||
super._init('cellular', proxy, indicator);
|
||||
this._settings.label.text = _("Cellular Settings");
|
||||
this._icons = {
|
||||
'ok': 'network-cellular-connected-symbolic',
|
||||
'acquiring': 'network-cellular-acquiring-symbolic',
|
||||
'offline': 'network-cellular-offline-symbolic',
|
||||
'error': 'network-error-symbolic'
|
||||
};
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return 'network-cellular-signal-' + this.signalToIcon() + '-symbolic';
|
||||
}
|
||||
});
|
||||
|
||||
var VPNService = GObject.registerClass(class VPNService extends Service {
|
||||
|
||||
_init(proxy, indicator) {
|
||||
super._init('vpn', proxy, indicator);
|
||||
this._settings.label.text = _("VPN Settings");
|
||||
this._icons = {
|
||||
'ok': 'network-vpn-symbolic',
|
||||
'acquiring': 'network-vpn-acquiring-symbolic',
|
||||
'offline': 'network-offline-symbolic',
|
||||
'error': 'network-error-symbolic',
|
||||
};
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
getAcquiringIcon() {
|
||||
return 'network-vpn-acquiring-symbolic';
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return 'network-vpn-symbolic';
|
||||
}
|
||||
});
|
||||
|
||||
function createService(type, proxy, indicator) {
|
||||
let services = {
|
||||
ethernet: EthernetService,
|
||||
wifi: WirelessService,
|
||||
bluetooth: BluetoothService,
|
||||
cellular: CellularService,
|
||||
vpn: VPNService
|
||||
};
|
||||
if (services[type])
|
||||
return new services[type](proxy, indicator);
|
||||
return new Service('other', proxy, indicator);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/* Password or Authentication Dialog */
|
||||
.cm-prompt-dialog {
|
||||
width: 500px;
|
||||
border: 3px solid rgba(238, 238, 236, 0.2); }
|
||||
|
||||
.cm-prompt-dialog-main-layout {
|
||||
spacing: 24px;
|
||||
padding: 10px; }
|
||||
|
||||
.cm-prompt-dialog-message-layout {
|
||||
spacing: 16px; }
|
||||
|
||||
.cm-prompt-dialog-headline {
|
||||
font-weight: bold;
|
||||
color: #b2b2a9; }
|
||||
|
||||
.cm-prompt-dialog-description:rtl {
|
||||
text-align: right; }
|
||||
|
||||
.cm-prompt-dialog-password-box {
|
||||
spacing: 1em;
|
||||
padding-bottom: 1em; }
|
||||
|
||||
.cm-prompt-dialog-error-label {
|
||||
font-size: 10pt;
|
||||
color: #cc0000;
|
||||
padding-bottom: 8px; }
|
||||
|
||||
.cm-prompt-dialog-info-label {
|
||||
font-size: 10pt;
|
||||
padding-bottom: 8px; }
|
||||
|
||||
.cm-hidden {
|
||||
color: transparent; }
|
||||
|
||||
.cm-prompt-dialog-null-label {
|
||||
font-size: 10pt;
|
||||
padding-bottom: 8px; }
|
||||
|
||||
/* NETWORK DIALOGS */
|
||||
.cm-dialog {
|
||||
max-height: 500px;
|
||||
min-height: 450px;
|
||||
min-width: 470px; }
|
||||
|
||||
.cm-dialog-content {
|
||||
spacing: 20px; }
|
||||
|
||||
.cm-dialog-interface {
|
||||
color: #606060;
|
||||
padding: 15px; }
|
||||
|
||||
.cm-dialog-header-hbox {
|
||||
spacing: 10px; }
|
||||
|
||||
.cm-dialog-header-icon {
|
||||
icon-size: 32px; }
|
||||
|
||||
.cm-dialog-scroll-view {
|
||||
border: 2px solid #1c1f1f; }
|
||||
|
||||
.cm-dialog-header {
|
||||
font-weight: bold; }
|
||||
|
||||
.cm-dialog-item {
|
||||
font-size: 110%;
|
||||
border-bottom: 1px solid #1c1f1f;
|
||||
padding: 12px 12px 12px 36px; }
|
||||
|
||||
.cm-dialog-item:favourite {
|
||||
padding: 12px 12px 12px 0px; }
|
||||
|
||||
.cm-dialog-item:selected {
|
||||
background-color: #215d9c;
|
||||
color: #ffffff; }
|
||||
|
||||
.cm-dialog-item:passive {
|
||||
color: #606060; }
|
||||
|
||||
.cm-dialog-icons {
|
||||
spacing: .5em; }
|
||||
|
||||
.cm-dialog-icon {
|
||||
icon-size: 16px;
|
||||
padding-left: 5px; }
|
||||
|
||||
.cm-dialog-icon:favourite {
|
||||
padding: 0px 10px 0px 10px;}
|
||||
|
||||
/* Network Agent Dialog */
|
||||
.cm-network-dialog-secret-table {
|
||||
spacing-rows: 15px;
|
||||
spacing-columns: 1em; }
|
||||
|
||||
.cm-keyring-dialog-control-table {
|
||||
spacing-rows: 15px;
|
||||
spacing-columns: 1em; }
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const Lang = imports.lang;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const GObject = imports.gi.GObject;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Ext = ExtensionUtils.getCurrentExtension();
|
||||
const Service = Ext.imports.service;
|
||||
const Logger = Ext.imports.logger;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-extension-connman');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Version = Ext.imports.version;
|
||||
const version = Version.version();
|
||||
|
||||
var Technology = class extends PopupMenu.PopupMenuSection {
|
||||
|
||||
constructor(properties, type, proxy) {
|
||||
super();
|
||||
this._type = type;
|
||||
this._services = {}
|
||||
this._dialog = null;
|
||||
this._properties = properties;
|
||||
|
||||
this._proxy = proxy;
|
||||
if (this._proxy)
|
||||
this._sig = this._proxy.connectSignal('PropertyChanged',
|
||||
function(proxy, sender, [name, value]) {
|
||||
this.propertyChanged(name, value.deep_unpack());
|
||||
}.bind(this));
|
||||
if (this._properties['Powered'])
|
||||
this.show();
|
||||
else
|
||||
this.hide();
|
||||
}
|
||||
|
||||
getValue() {
|
||||
let values = ["ethernet", "wifi", "bluetooth",
|
||||
"p2p", "cellular", "vpn", "other"];
|
||||
return values.indexOf(this._type);
|
||||
}
|
||||
|
||||
propertyChanged(name, value) {
|
||||
if(name == 'Powered') {
|
||||
if(value)
|
||||
this.show();
|
||||
else
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
addService(id, service) {
|
||||
if(this._services[id])
|
||||
this._services[id].destroy();
|
||||
this._services[id] = service;
|
||||
service.id = id;
|
||||
this.addMenuItem(service);
|
||||
this.serviceUpdated(id);
|
||||
this.updateIcon();
|
||||
}
|
||||
|
||||
getService(id) {
|
||||
return this._services[id];
|
||||
}
|
||||
|
||||
updateService(id, properties) {
|
||||
if(!this._services[id])
|
||||
return false;
|
||||
this._services[id].update(properties);
|
||||
this.serviceUpdated(id);
|
||||
this.updateIcon();
|
||||
return true;
|
||||
}
|
||||
|
||||
removeService(id) {
|
||||
if(!this._services[id])
|
||||
return false;
|
||||
this._services[id].destroy();
|
||||
delete this._services[id];
|
||||
this.serviceUpdated(id);
|
||||
this.updateIcon();
|
||||
return true;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
for(let path in this._services) {
|
||||
try {
|
||||
this.removeService(path);
|
||||
} catch(error) {}
|
||||
}
|
||||
try {
|
||||
if(this._proxy)
|
||||
this._proxy.disconnectSignal(this._sig);
|
||||
} catch(error) {
|
||||
Logger.logException(error, 'Failed to disconnect service proxy');
|
||||
}
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
serviceUpdated(id) {}
|
||||
|
||||
updateIcon() {
|
||||
if(Object.keys(this._services)) {
|
||||
this._indicator = this._services[Object.keys(this._services)[0]];
|
||||
for(let path in this._services) {
|
||||
let state = this._services[path]._properties['State'];
|
||||
if(state != 'idle')
|
||||
this._indicator = this._services[path]._indicator;
|
||||
}
|
||||
for(let path in this._services) {
|
||||
let state = this._services[path]._properties['State'];
|
||||
if(state != 'idle' && state != 'failure')
|
||||
this._indicator = this._services[path]._indicator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.actor.show();
|
||||
if(this._indicator)
|
||||
this._indicator.show();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.actor.hide();
|
||||
if(this._indicator)
|
||||
this._indicator.hide();
|
||||
}
|
||||
};
|
||||
|
||||
var EthernetTechnology = class extends Technology {
|
||||
|
||||
constructor(properties, proxy) {
|
||||
super(properties, 'ethernet', proxy);
|
||||
}
|
||||
};
|
||||
|
||||
var WirelessTechnology = class extends Technology {
|
||||
|
||||
constructor(properties, proxy, manager) {
|
||||
super(properties, 'wifi', proxy);
|
||||
|
||||
this._menu = new PopupMenu.PopupSubMenuMenuItem('', true);
|
||||
|
||||
this._settings = new PopupMenu.PopupMenuItem(_("Wireless Settings"));
|
||||
this._settings.connect('activate', this.openSettings.bind(this));
|
||||
|
||||
if (version < 318) {
|
||||
this._menu.label.text = _("Wireless");
|
||||
this._menu.status.text = _("Idle");
|
||||
} else {
|
||||
this._menu.label.text = _("Wireless") + " - " + _("Idle");
|
||||
}
|
||||
this._menu.icon.icon_name = 'network-wireless-signal-none-symbolic';
|
||||
this._manager = manager;
|
||||
this.addMenuItem(this._menu);
|
||||
this._menu.menu.addMenuItem(this._createConnectionMenuItem());
|
||||
this._menu.menu.addMenuItem(this._settings);
|
||||
this._connected = {};
|
||||
this._connectedCount = 0;
|
||||
this.show();
|
||||
}
|
||||
|
||||
openSettings() {
|
||||
Util.spawnApp(['connman-gtk', '--page', 'wifi']);
|
||||
}
|
||||
|
||||
_createConnectionMenuItem() {
|
||||
let connectionItem = new PopupMenu.PopupMenuItem(
|
||||
_("Select wireless network"));
|
||||
connectionItem.connect('activate', this.selectWifi.bind(this));
|
||||
return connectionItem;
|
||||
}
|
||||
|
||||
selectWifi() {
|
||||
let serviceList = [];
|
||||
let result = this._manager.GetServicesSync();
|
||||
let services = result[0];
|
||||
for(let i = 0; i < services.length; i++) {
|
||||
let service = this._services[services[i][0]];
|
||||
if(service && service._properties['Name'])
|
||||
serviceList.push([service, service._properties['Ethernet']['Interface']]);
|
||||
}
|
||||
let callback = function(service) {
|
||||
this._dialog = null;
|
||||
if(service)
|
||||
service.buttonEvent();
|
||||
else
|
||||
Logger.logInfo('User canceled wifi dialog');
|
||||
}.bind(this);
|
||||
this._dialog = new Service.ServiceChooser(this._proxy,
|
||||
serviceList, callback);
|
||||
}
|
||||
|
||||
addService(id, service) {
|
||||
super.addService(id, service);
|
||||
service.menu.addMenuItem(this._createConnectionMenuItem(), 1);
|
||||
let state = this._services[id].state;
|
||||
if(state != 'idle' && state != 'disconnect' && state != 'failure') {
|
||||
this._connected[id] = true;
|
||||
this._menu.actor.hide();
|
||||
this._connectedCount++;
|
||||
}
|
||||
if(this._dialog)
|
||||
this._dialog.addService([service, service._properties['Ethernet']['Interface']]);
|
||||
}
|
||||
|
||||
updateService(id, properties) {
|
||||
super.updateService(id, properties);
|
||||
let state = this._services[id]._properties['State'];
|
||||
if(state != 'idle' && state != 'disconnect' && state != 'failure') {
|
||||
if(!this._connected[id]) {
|
||||
this._connected[id] = true;
|
||||
this._connectedCount++;
|
||||
this._menu.actor.hide();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(this._connected[id]) {
|
||||
this._connected[id] = false;
|
||||
this._connectedCount--;
|
||||
if(!this._connectedCount)
|
||||
this._menu.actor.show();
|
||||
}
|
||||
}
|
||||
if(this._dialog)
|
||||
this._dialog.updateService([this._services[id],
|
||||
this._services[id]._properties['Ethernet']['Interface']]);
|
||||
}
|
||||
|
||||
removeService(id) {
|
||||
let state = this._services[id]._properties['State'];
|
||||
if(state != 'idle' && state != 'disconnect' && state != 'failure') {
|
||||
this._services[id].hide();
|
||||
if(this._connected[id]) {
|
||||
this._connected[id] = false;
|
||||
this._connectedCount--;
|
||||
if(!this._connectedCount)
|
||||
this._menu.actor.show();
|
||||
}
|
||||
}
|
||||
super.removeService(id);
|
||||
this.serviceUpdated(id);
|
||||
this.updateIcon();
|
||||
if(this._dialog)
|
||||
this._dialog.removeService(id);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._proxy = null;
|
||||
super.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
var BluetoothTechnology = class extends Technology {
|
||||
|
||||
constructor(properties, proxy) {
|
||||
super(properties, 'bluetooth', proxy);
|
||||
}
|
||||
};
|
||||
|
||||
var P2PTechnology = class extends Technology {
|
||||
|
||||
constructor(properties, proxy) {
|
||||
super(properties, 'p2p', proxy);
|
||||
}
|
||||
};
|
||||
|
||||
var CellularTechnology = class extends Technology {
|
||||
|
||||
constructor(properties, proxy) {
|
||||
super(properties, 'cellular', proxy);
|
||||
}
|
||||
};
|
||||
|
||||
class VPNTechnology extends Technology {
|
||||
|
||||
constructor(properties, proxy) {
|
||||
super(properties, 'vpn', proxy);
|
||||
}
|
||||
};
|
||||
|
||||
function createTechnology(type, properties, proxy, manager) {
|
||||
let technologies = {
|
||||
ethernet: EthernetTechnology,
|
||||
wifi: WirelessTechnology,
|
||||
bluetooth: BluetoothTechnology,
|
||||
p2p: P2PTechnology,
|
||||
cellular: CellularTechnology,
|
||||
vpn: VPNTechnology
|
||||
};
|
||||
if(technologies[type])
|
||||
return new technologies[type](properties, proxy, manager);
|
||||
return new Technology(properties, 'other', proxy);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Intel Corporation. All rights reserved.
|
||||
* Author: Jaakko Hannikainen <jaakko.hannikainen@intel.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
const Config = imports.misc.config;
|
||||
|
||||
function version() {
|
||||
var split = Config.PACKAGE_VERSION.split('.');
|
||||
return parseInt(split[0])*100 + parseInt(split[1]);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//! ------------------------------------------------------------------------------
|
||||
//! ROFI MNT Reform Color theme
|
||||
//! User: MNT Research GmbH
|
||||
//! ------------------------------------------------------------------------------
|
||||
|
||||
* {
|
||||
background-color: #000000;
|
||||
text-color: #ffffff;
|
||||
}
|
||||
|
||||
prompt {
|
||||
text-color: #000000;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
window {
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
element normal {
|
||||
text-color: #ffffff;
|
||||
}
|
||||
|
||||
element selected {
|
||||
background-color: #ffffff;
|
||||
text-color: #000000;
|
||||
}
|
||||
|
50
src/recipes/default/hook/data/overlay/etc/skel/.profile
Normal file
50
src/recipes/default/hook/data/overlay/etc/skel/.profile
Normal file
|
@ -0,0 +1,50 @@
|
|||
# ~/.profile: executed by the command interpreter for login shells.
|
||||
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
|
||||
# exists.
|
||||
# see /usr/share/doc/bash/examples/startup-files for examples.
|
||||
# the files are located in the bash-doc package.
|
||||
|
||||
# the default umask is set in /etc/profile; for setting the umask
|
||||
# for ssh logins, install and configure the libpam-umask package.
|
||||
#umask 022
|
||||
|
||||
# if running bash
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/bin" ] ; then
|
||||
PATH="$HOME/bin:$PATH"
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/.local/bin" ] ; then
|
||||
PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
||||
|
||||
|
||||
# Defaults for MNT Reform
|
||||
|
||||
# enable NIR shader path in mesa. without this,
|
||||
# some Xwayland applications will be blank
|
||||
export ETNA_MESA_DEBUG=nir
|
||||
|
||||
# set GTK2 theme
|
||||
export GTK2_RC_FILES=/usr/share/themes/Arc-Dark/gtk-2.0/gtkrc
|
||||
|
||||
unicode_start
|
||||
|
||||
if [ $(whoami) == "root" ]
|
||||
then
|
||||
cat /etc/reform-root-help
|
||||
elif [ ! -z $WAYLAND_DISPLAY ]
|
||||
then
|
||||
# do nothing
|
||||
true
|
||||
else
|
||||
cat /etc/reform-help
|
||||
fi
|
|
@ -5,6 +5,7 @@ breeze-icon-theme
|
|||
brightness-udev
|
||||
brightnessctl
|
||||
bsdmainutils
|
||||
busybox
|
||||
ca-certificates
|
||||
connman-gtk
|
||||
console-data
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue