/** * Created : Mar 30, 2012 * * @author pquiring */ import java.io.*; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.*; import java.util.*; import javax.swing.*; import javaforce.*; import javaforce.jbus.*; import javaforce.linux.*; import javaforce.utils.*; import jffile.*; public class Dock extends javax.swing.JWindow implements ActionListener, MouseListener, MouseMotionListener, LayoutManager, X11Listener, monitordir.Listener, FileClipboard { /** * Creates new form Dock */ public Dock() { try { initComponents(); IconCache.setPrefix("jfdesktop-"); arrowImage = IconCache.loadIcon("jfdesktop-arrow"); loadNetworkIcons(); dock = this; x11id = Linux.x11_get_id(this); JFLog.log("Dock.window=0x" + Long.toString(x11id, 16)); try { Linux.x11_set_dock(x11id); } catch (Throwable t) { JFLog.log(t); } addTo = buttons; loadConfig(); addAppsButton(); addArrows(); getDimensions(); loadButtons(); DisplayMode screen_mode = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode(); try { Linux.x11_set_strut(x11id, (config.autoHide ? 1 : panelHeight-borderSize), 0, 0, screen_mode.getWidth(), screen_mode.getHeight()); } catch (Throwable t) { JFLog.log(t); } JF.sleep(100); getScreenSize(); soundinit(); initUpgrades(); loadGlobalConfig(); addClock(); setClock(); addTrash(); addKeyboard(); addQuadControls(); addHalfControls(); setLayout(this); buttons.setLayout(this); setSize(sx, 1); setLocation(0, sy-1); calcDockHeight(); updateConfig(); if (config.autoHide) showDock(); DesktopCache.buildCache(); setupClockTimer(); addMouseListener(this); addMouseListener(TrashPopup); addMouseListener(PowerPopup); addMouseListener(ConfigPopup); addMouseListener(SoundPopup); addMouseListener(ClockPopup); addMouseListener(TaskbarPopup); //connect to JBus JFLog.log("jbusClient:package=org.jflinux.jfdesktop." + System.getenv("JID")); jbusClient = new JBusClient("org.jflinux.jfdesktop." + System.getenv("JID"), new JBusMethods()); jbusClient.start(); if (new File("/usr/sbin/hciconfig").exists()) { checkBluetooth(); } if (new File("/usr/bin/jfwelcome").exists()) { if (config.welcome) { showWelcome(); } } startTrashListener(); mkdirs(); keyboardWindow = new KeyboardWindow(); Linux.x11_set_listener(this); new Thread() { public void run() { try { //monitor system tray Linux.x11_tray_main(x11id, sx, trayPos, buttonHeight + 4); } catch (Throwable t) { JFLog.log(t); } } }.start(); new Thread() { public void run() { try { //monitor when top-level windows change Linux.x11_window_list_main(); } catch (Throwable t) { JFLog.log(t); } } }.start(); JF.sleep(250); //wait for threads to start if (new File("/usr/bin/acpi").exists()) { checkBattery(); } try { Linux.x11_set_dock(x11id); } catch (Throwable t) { JFLog.log(t); } new Thread() { public void run() { loadMappings(); //can take a while } }.start(); initDockDND(); getWAPList(); JFLog.log("Dock init complete"); } catch (Throwable t) { JFLog.log(t); } } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { TrashPopup = new javax.swing.JPopupMenu(); EmptyTrash = new javax.swing.JMenuItem(); PowerPopup = new javax.swing.JPopupMenu(); Logoff = new javax.swing.JMenuItem(); Reboot = new javax.swing.JMenuItem(); Shutdown = new javax.swing.JMenuItem(); Sleep = new javax.swing.JMenuItem(); ConfigPopup = new javax.swing.JPopupMenu(); ControlCenter = new javax.swing.JMenuItem(); DesktopSettings = new javax.swing.JMenuItem(); Upgrades = new javax.swing.JMenuItem(); Run = new javax.swing.JMenuItem(); Help = new javax.swing.JMenuItem(); SoundPopup = new javax.swing.JPopupMenu(); Settings = new javax.swing.JMenuItem(); ClockPopup = new javax.swing.JPopupMenu(); AdjustTime = new javax.swing.JMenuItem(); BatteryPopup = new java.awt.PopupMenu(); BatterySettings = new java.awt.MenuItem(); TaskbarPopup = new javax.swing.JPopupMenu(); MinimizeAll = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JPopupMenu.Separator(); TaskMgr = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JPopupMenu.Separator(); DockSettings = new javax.swing.JMenuItem(); buttons = new javax.swing.JPanel(); EmptyTrash.setText("Empty"); EmptyTrash.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { EmptyTrashActionPerformed(evt); } }); TrashPopup.add(EmptyTrash); Logoff.setText("Logff"); Logoff.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { LogoffActionPerformed(evt); } }); PowerPopup.add(Logoff); Reboot.setText("Reboot"); Reboot.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { RebootActionPerformed(evt); } }); PowerPopup.add(Reboot); Shutdown.setText("Shutdown"); Shutdown.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { ShutdownActionPerformed(evt); } }); PowerPopup.add(Shutdown); Sleep.setText("Sleep"); Sleep.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { SleepActionPerformed(evt); } }); PowerPopup.add(Sleep); ControlCenter.setText("Control Center"); ControlCenter.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { ControlCenterActionPerformed(evt); } }); ConfigPopup.add(ControlCenter); DesktopSettings.setText("Desktop Settings"); DesktopSettings.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { DesktopSettingsActionPerformed(evt); } }); ConfigPopup.add(DesktopSettings); Upgrades.setText("Upgrades"); Upgrades.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { UpgradesActionPerformed(evt); } }); ConfigPopup.add(Upgrades); Run.setText("Run"); Run.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { RunActionPerformed(evt); } }); ConfigPopup.add(Run); Help.setText("Help"); Help.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { HelpActionPerformed(evt); } }); ConfigPopup.add(Help); Settings.setText("Settings"); Settings.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { SettingsActionPerformed(evt); } }); SoundPopup.add(Settings); AdjustTime.setText("Adjust Date & Time"); AdjustTime.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { AdjustTimeActionPerformed(evt); } }); ClockPopup.add(AdjustTime); BatteryPopup.setName(""); BatterySettings.setLabel("Settings"); BatterySettings.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { BatterySettingsActionPerformed(evt); } }); BatteryPopup.add(BatterySettings); MinimizeAll.setText("Show the desktop"); MinimizeAll.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { MinimizeAllActionPerformed(evt); } }); TaskbarPopup.add(MinimizeAll); TaskbarPopup.add(jSeparator1); TaskMgr.setText("Start Task Manager"); TaskMgr.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { TaskMgrActionPerformed(evt); } }); TaskbarPopup.add(TaskMgr); TaskbarPopup.add(jSeparator2); DockSettings.setText("Settings"); DockSettings.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { DockSettingsActionPerformed(evt); } }); TaskbarPopup.add(DockSettings); setAlwaysOnTop(true); setMinimumSize(new java.awt.Dimension(1, 1)); setName("dock"); // NOI18N buttons.setMinimumSize(new java.awt.Dimension(1, 1)); buttons.setPreferredSize(new java.awt.Dimension(1, 1)); javax.swing.GroupLayout buttonsLayout = new javax.swing.GroupLayout(buttons); buttons.setLayout(buttonsLayout); buttonsLayout.setHorizontalGroup( buttonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 545, Short.MAX_VALUE) ); buttonsLayout.setVerticalGroup( buttonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGap(0, 1, Short.MAX_VALUE) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(buttons, javax.swing.GroupLayout.DEFAULT_SIZE, 545, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(buttons, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); pack(); }// </editor-fold>//GEN-END:initComponents private void EmptyTrashActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_EmptyTrashActionPerformed emptyTrash(); }//GEN-LAST:event_EmptyTrashActionPerformed private void LogoffActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LogoffActionPerformed if (!JF.showConfirm("Confirm", "Are you sure you want to logoff?")) return; closeAllApps(); System.exit(0); }//GEN-LAST:event_LogoffActionPerformed private void RebootActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RebootActionPerformed if (!JF.showConfirm("Confirm", "Are you sure you want to reboot?")) return; jbusClient.call("org.jflinux.jfsystemmgr", "reboot", ""); closeAllApps(); System.exit(0); }//GEN-LAST:event_RebootActionPerformed private void ShutdownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ShutdownActionPerformed if (!JF.showConfirm("Confirm", "Are you sure you want to shutdown?")) return; jbusClient.call("org.jflinux.jfsystemmgr", "shutdown", ""); closeAllApps(); System.exit(0); }//GEN-LAST:event_ShutdownActionPerformed private void ControlCenterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ControlCenterActionPerformed try { Runtime.getRuntime().exec("jconfig"); } catch (Exception e) { JFLog.log(e); } }//GEN-LAST:event_ControlCenterActionPerformed private void DesktopSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DesktopSettingsActionPerformed showConfig(); }//GEN-LAST:event_DesktopSettingsActionPerformed private void SleepActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SleepActionPerformed //disconnect all VPN jbusClient.call("org.jflinux", "closeAllVPN", ""); JF.sleep(500); jbusClient.call("org.jflinux.jfsystemmgr", "sleep" , ""); //reset clock after 10 seconds (hopefully after we resume from sleep) new java.util.Timer().schedule(new TimerTask() { public void run() { setClock(); } }, 10 * 1000); }//GEN-LAST:event_SleepActionPerformed private void SettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SettingsActionPerformed try { Runtime.getRuntime().exec(new String[] {"jconfig", "sound"}); } catch (Exception e) { JFLog.log(e); } }//GEN-LAST:event_SettingsActionPerformed private void AdjustTimeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AdjustTimeActionPerformed try { Runtime.getRuntime().exec(new String[] {"jconfig", "datetime"}); } catch (Exception e) { JFLog.log(e); } }//GEN-LAST:event_AdjustTimeActionPerformed private void HelpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_HelpActionPerformed try { Runtime.getRuntime().exec(new String[] {"jhelp", "jfdesktop"}); } catch (Exception e) { JFLog.log(e); } }//GEN-LAST:event_HelpActionPerformed private void RunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RunActionPerformed doRun(); }//GEN-LAST:event_RunActionPerformed private void UpgradesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_UpgradesActionPerformed try { Runtime.getRuntime().exec("jupgrade"); } catch (Exception e) {JFLog.log(e);} }//GEN-LAST:event_UpgradesActionPerformed private void BatterySettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BatterySettingsActionPerformed new BatteryDialog(null, true).setVisible(true); }//GEN-LAST:event_BatterySettingsActionPerformed private void DockSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_DockSettingsActionPerformed showConfig(); }//GEN-LAST:event_DockSettingsActionPerformed private void MinimizeAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_MinimizeAllActionPerformed Linux.x11_minimize_all(); }//GEN-LAST:event_MinimizeAllActionPerformed private void TaskMgrActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_TaskMgrActionPerformed try { Runtime.getRuntime().exec("jtaskmgr"); } catch (Exception e) { JFLog.log(e); } }//GEN-LAST:event_TaskMgrActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JMenuItem AdjustTime; private java.awt.PopupMenu BatteryPopup; private java.awt.MenuItem BatterySettings; private javax.swing.JPopupMenu ClockPopup; private javax.swing.JPopupMenu ConfigPopup; private javax.swing.JMenuItem ControlCenter; private javax.swing.JMenuItem DesktopSettings; private javax.swing.JMenuItem DockSettings; private javax.swing.JMenuItem EmptyTrash; private javax.swing.JMenuItem Help; private javax.swing.JMenuItem Logoff; private javax.swing.JMenuItem MinimizeAll; private javax.swing.JPopupMenu PowerPopup; private javax.swing.JMenuItem Reboot; private javax.swing.JMenuItem Run; private javax.swing.JMenuItem Settings; private javax.swing.JMenuItem Shutdown; private javax.swing.JMenuItem Sleep; private javax.swing.JPopupMenu SoundPopup; private javax.swing.JMenuItem TaskMgr; private javax.swing.JPopupMenu TaskbarPopup; private javax.swing.JPopupMenu TrashPopup; private javax.swing.JMenuItem Upgrades; private javax.swing.JPanel buttons; private javax.swing.JPopupMenu.Separator jSeparator1; private javax.swing.JPopupMenu.Separator jSeparator2; // End of variables declaration//GEN-END:variables public static class App { public String file; } public static class Card { public int idx; public String activeProfile; } public static class Sink { public int idx; public String activePort; public int volume; //% } public static class Source { public int idx; public String activePort; public int volume; //% } public static class Config { public Config() { dock = new App[0]; } public boolean showClock; public boolean showKeyboard; public boolean autoHide; public boolean welcome; public boolean compact; public boolean showIcons; //on Desktop public boolean arrangeIconsAuto; //on Desktop public boolean mountAudio; public int desktopMode; public String desktopFile; public App dock[]; //for Dock public Color bc, fc; //back fore color (desktop) //sound config public Card card[]; public Sink sink[]; public Source source[]; public int dockSize; //48, 32, 24 //video config (TODO) - for now in .xrandr.xml } public static class GlobalConfig { public boolean disableSleep; } public static class BlueToothDevice { String desc, mac; } public Config config = new Config(); private String configFile = ".jfdesktop.xml"; private GlobalConfig globalConfig = new GlobalConfig(); private String globalConfigFolder = "/etc/jconfig.d/"; private String globalConfigFile = "global.xml"; private int appIdx = 0; //where to insert next button private int viewIdx = 0; //first app to show if not all fit on dock private int overflowCnt = 0; private boolean needArrows = false; public static int sx, sy; //screen size private JFImage clockImage; private Font clockFont; private String clockLine1 = "MONTH DAY", clockLine2 = "HH:MM"; private JButton left, right, apps, trash, keyboard; private JButton soundQuad, networkQuad, powerQuad, settingsQuad; private JButton soundHalf, networkHalf, powerHalf, settingsHalf; private JFImage batteryImage, trashFullImage, trashEmptyImage; private JPanel quad; private SystemTray tray; private TrayIcon trayIcon; private boolean haveMouse = true; private boolean isDockHidden = true; private int panelHeight, buttonWidth, buttonHeight, halfWidth; private int panelHiddenHeight = 1; private CalendarWindow calWindow; private SoundWindow soundWindow; public KeyboardWindow keyboardWindow; private boolean keyboardShown = false; public static JBusClient jbusClient; private boolean isTrashFull; public static BlueToothDialog btDialog; private java.util.Timer clockTimer; private java.util.Timer flashTimer; private java.util.Timer autoHideTimer; private JPopupMenu NetworkPopup = new JPopupMenu(); public static Dock dock; private long x11id; public static ArrayList<BlueToothDevice> btDevices = new ArrayList<BlueToothDevice>(); private int buttonsCount = 0; //# of app buttons shown in dock (pinned & !pinned) private String fileSelection = ""; private static final int borderSize = 4; private int trayPos = 0; private final int trayPad = 2; private JButton newButton; private int newButtonIdx; public void trayIconAdded(int count) { JFLog.log("Dock:tray icon added"); } public void trayIconRemoved(int count) { JFLog.log("Dock:tray icon removed"); } private boolean updatePending = false; public void windowsChanged() { if (updatePending) return; updatePending = true; java.awt.EventQueue.invokeLater(new Runnable() { public void run() { updateWindowList(); } }); } private static class Window { public long xid; public String title; public Window(long xid, String title) { this.xid = xid; this.title = title; } public void show() { Linux.x11_map_window(xid); Linux.x11_raise_window(xid); } } private static class Group { public ArrayList<Window> windows = new ArrayList<Window>(); public void updateTitle(long xid, String title) { for(int a=0;a<windows.size();a++) { Window window = windows.get(a); if (window.xid == xid) { window.title = title; return; } } addWindow(xid, title); } public void addWindow(long xid, String title) { windows.add(new Window(xid, title)); } public void clearWindows() { windows.clear(); } public void removeWindow(int idx) { windows.remove(idx); } public void removeWindow(long xid) { for(int a=0;a<windows.size();a++) { Window window = windows.get(a); if (window.xid == xid) { windows.remove(a); return; } } } public boolean isEmpty() { return windows.isEmpty(); } public Window getWindow(int idx) { return windows.get(idx); } public int size() { return windows.size(); } } //updates the active windows list private synchronized void updateWindowList() { //add buttons updatePending = false; try { Linux.Window winList[] = Linux.x11_get_window_list(); Component buts[] = buttons.getComponents(); for(int w=0;w<winList.length;w++) { Linux.Window x11window = winList[w]; // JFLog.log("window:xid=" + Integer.toString(JF.atoi(x11window.xid.toString()), 16) + ",pid=" + x11window.pid + ",title=" + x11window.title + ",res_class=" + x11window.res_class + ",res_name=" + x11window.res_name); x11window.file = null; if (x11window.pid != -1) x11window.file = DesktopCache.getDesktopFromPID(x11window.pid); if (x11window.file == null && x11window.title.length() > 0) x11window.file = DesktopCache.getDesktopFromText(x11window.title); if (x11window.file == null && x11window.res_class.length() > 0) x11window.file = DesktopCache.getDesktopFromText(x11window.res_class); if (x11window.file == null) { //unable to match window (TODO : create a generic button? : would need to copy icon) JFLog.log("Dock:Unable to match window to application:" + x11window.title); continue; } boolean ok = false; for(int b=0;b<buts.length;b++) { if (!(buts[b] instanceof JButton)) continue; JButton button = (JButton)buts[b]; String file = (String)button.getClientProperty("file"); if (file.startsWith("#")) continue; Group group = (Group)button.getClientProperty("group"); if (file.equals(x11window.file)) { group.updateTitle(x11window.xid, x11window.title); ok = true; break; } } if (ok) continue; //add new button JButton button = addButton(x11window.file, false, -1); Group group = (Group)button.getClientProperty("group"); group.addWindow(x11window.xid, x11window.title); buts = buttons.getComponents(); } //remove buttons for(int b=0;b<buts.length;b++) { if (!(buts[b] instanceof JButton)) continue; JButton button = (JButton)buts[b]; String file = (String)button.getClientProperty("file"); if (file.startsWith("#")) continue; Group group = (Group)button.getClientProperty("group"); boolean group_ok = false; for(int g=0;g<group.size();) { Window window = group.getWindow(g); boolean window_ok = false; for(int w=0;w<winList.length;w++) { Linux.Window x11window = winList[w]; if (x11window.xid == window.xid) {group_ok = true; window_ok = true; break;} } if (!window_ok) { group.removeWindow(g); } else { g++; } } if (group_ok) { createAppPopupMenu(button); continue; } //remove button (if not pinned) Boolean pinned = (Boolean)button.getClientProperty("pinned"); if (!pinned) { removeButton(button); //NOTE:do NOT update buts list } else { createAppPopupMenu(button); //remove any windows } } } catch (Exception e) { JFLog.log(e); } } private void togglePinned(JButton button) { String file = (String)button.getClientProperty("file"); Boolean pinned = (Boolean)button.getClientProperty("pinned"); Group group = (Group)button.getClientProperty("group"); if (pinned) { if (group.isEmpty()) { removeButton(button); } else { button.putClientProperty("pinned", new Boolean(false)); } } else { button.putClientProperty("pinned", new Boolean(true)); addApp(file); saveConfig(); } createAppPopupMenu(button); } public void loadConfig() { config.card = new Card[0]; config.sink = new Sink[0]; config.source = new Source[0]; config.dock = new App[0]; config.showClock = true; config.showKeyboard = true; config.dockSize = 48; try { XML xml = new XML(); FileInputStream fis = new FileInputStream(JF.getUserPath() + "/" + configFile); byte data[] = JF.readAll(fis); String str = new String(data); str = str.replaceAll("app>", "dock>"); //convert pre 6.5 config xml.read(new ByteArrayInputStream(str.getBytes())); //remove old "desktop" config for(int a=0;a<xml.root.getChildCount();) { if (xml.root.getChildAt(a).getName().equals("desktop")) { xml.root.remove(a); } else { a++; } } xml.writeClass(config); } catch (FileNotFoundException e1) { defaultConfig(); } catch (Exception e2) { JFLog.log(e2); defaultConfig(); } validateConfig(); bx = config.dockSize; by = config.dockSize; } public void validateConfig() { if (config.dockSize != 48 && config.dockSize != 32 && config.dockSize != 24) { config.dockSize = 48; } } public void getDimensions() { Dimension d = apps.getPreferredSize(); buttonWidth = d.width; buttonHeight = d.height; panelHeight = d.height + borderSize * 2; d = left.getPreferredSize(); halfWidth = d.width; } public void loadGlobalConfig() { try { XML xml = new XML(); FileInputStream fis = new FileInputStream(globalConfigFolder + "/" + globalConfigFile); xml.read(fis); xml.writeClass(globalConfig); } catch (FileNotFoundException fnfe) { defaultGlobalConfig(); return; } catch (Exception e) { defaultGlobalConfig(); JFLog.log(e); } if (globalConfig.disableSleep) { PowerPopup.remove(Sleep); PowerPopup.remove(Reboot); PowerPopup.remove(Shutdown); } } private void defaultGlobalConfig() { globalConfig.disableSleep = false; } public synchronized void saveConfig() { try { XML xml = new XML(); FileOutputStream fos = new FileOutputStream(JF.getUserPath() + "/" + configFile); xml.readClass("jfdesktop", config); xml.write(fos); fos.close(); } catch (Exception e) { JFLog.log(e); } } public void defaultConfig() { config = new Config(); config.showClock = true; config.showKeyboard = true; config.autoHide = true; config.welcome = true; config.showIcons = true; config.mountAudio = true; config.dock = new App[0]; config.desktopFile = "/usr/share/icons/hicolor/48x48/apps/jfdesktop-wallpaper.png"; config.desktopMode = 3; config.bc = Color.BLUE; config.fc = Color.WHITE; config.dockSize = 48; //add jfile addAppIfExists("jfile"); //add jinstall if (new File("/etc/.live").exists()) { addAppIfExists("jinstall"); } //add Chrome (if installed) addAppIfExists("chromium-browser"); addAppIfExists("chrome"); addAppIfExists("google-chrome"); //add Firefox (if installed) addAppIfExists("firefox"); //add libre Office addAppIfExists("libreoffice-startcenter"); addAppIfExists("libreoffice-writer"); addAppIfExists("libreoffice-calc"); //add japps addAppIfExists("japps"); saveConfig(); } private void getScreenSize() { DisplayMode mode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode(); sx = mode.getWidth(); sy = mode.getHeight(); JFLog.log("ScreenSize:" + sx + "," + sy); } private void _setPosition() { if (config.autoHide) { setSize(sx, dockHeight); setLocation(0, sy - dockHeight); } else { setSize(sx, panelHeight - borderSize); setLocation(0, sy - (panelHeight - borderSize)); } } private void setPosition() { if (java.awt.EventQueue.isDispatchThread()) { _setPosition(); } else { try { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { _setPosition(); } }); } catch (Exception e) { JFLog.log(e); } } } private void removeButton(JButton b) { try { String file = (String)b.getClientProperty("file"); buttons.remove(b); appIdx--; if (!file.startsWith("#")) { buttonsCount--; } updateButtons(); for(int a=0;a<config.dock.length;a++) { if (config.dock[a].file.equals(file)) { removeApp(a); break; } } } catch (Exception e) { JFLog.log(e); } } private void copyButtonToDesktop(JButton b) { String src = (String)b.getClientProperty("file"); int idx = src.lastIndexOf("/"); String dest = JF.getUserPath() + "/Desktop" + src.substring(idx); boolean exists; int i = 1; do { exists = new File(dest).exists(); if (exists) { dest = dest.substring(0, dest.length() -8) + "(" + i++ + ").desktop"; } } while (exists); JF.copyAll(src, dest); } private void removeApp(int idx) { App newList[] = new App[config.dock.length - 1]; System.arraycopy(config.dock, 0, newList, 0, idx); System.arraycopy(config.dock, idx+1, newList, idx, config.dock.length - idx - 1); config.dock = newList; saveConfig(); } private int bx = 48, by = 48; //button size private JComponent addTo; private JFImage buttonImage, arrowImage; private boolean addArrow = false; private boolean halfSized = false; public JButton addButton(String icon, String name, String file, int idx, boolean pinned) { buttonImage = IconCache.loadIcon(icon); int _bx = bx; int _by = by; if (halfSized) { _bx /= 2; } if (addArrow) { buttonImage = IconCache.scaleIcon(buttonImage, _bx, _bx); JFImage tmpImage = new JFImage(_bx, _by); tmpImage.fill(0, 0, _bx, _by, 0, true); tmpImage.getGraphics().drawImage(buttonImage.getImage(), 0,(_by-_bx)/2 + 4, null); tmpImage.getGraphics().drawImage(arrowImage.getImage(), 0,0, _bx,_by/6, //dest 0,0, 24,8, //src null); buttonImage = tmpImage; } else { buttonImage = IconCache.scaleIcon(buttonImage, _bx, _by); } JButton button = new JButton(buttonImage); button.setMargin(new Insets(0,0,0,0)); button.setActionCommand(file); button.setContentAreaFilled(false); button.addActionListener(this); // button.setToolTipText(name); //mouse over the tooltip causes dock to hide button.addMouseListener(this); button.putClientProperty("file", file); button.putClientProperty("icon", icon); button.putClientProperty("arrow", new Boolean(addArrow)); button.putClientProperty("halfSized", new Boolean(halfSized)); button.putClientProperty("pinned", new Boolean(pinned)); button.putClientProperty("group", new Group()); if (!file.startsWith("#")) { createAppPopupMenu(button); button.addMouseMotionListener(this); buttonsCount++; } addTo.add(button, idx); updateButtons(); return button; } public JButton addButton(String file, boolean pinned, int idx) { String name = null, icon = null; try { FileInputStream fis = new FileInputStream(file); byte data[] = JF.readAll(fis); fis.close(); String str = new String(data); String lns[] = str.split("\n"); boolean desktopEntry = false; for(int a=0;a<lns.length;a++) { if (lns[a].startsWith("[Desktop Entry]")) { desktopEntry = true; continue; } if (lns[a].startsWith("[")) desktopEntry = false; if (!desktopEntry) continue; if (lns[a].startsWith("Name=")) { name = lns[a].substring(5); } if (lns[a].startsWith("Icon=")) { icon = lns[a].substring(5); } } if ((name == null) || (icon == null)) { JF.showError("Error", "Unable to add app:" + file); return null; } if (idx == -1) idx = appIdx++; else appIdx++; return addButton(icon, name, file, idx, pinned); } catch (Exception e) { JFLog.log(e); return null; } } public void updateButtonIcon(JButton b) { String icon = (String)b.getClientProperty("icon"); if (icon == null) return; Boolean arrow = (Boolean)b.getClientProperty("arrow"); Boolean half = (Boolean)b.getClientProperty("halfSized"); int _bx = bx; int _by = by; if (half) { _bx /= 2; } buttonImage = IconCache.loadIcon(icon); if (arrow) { buttonImage = IconCache.scaleIcon(buttonImage, _bx, _bx); JFImage tmpImage = new JFImage(_bx, _by); tmpImage.fill(0, 0, _bx, _by, 0, true); tmpImage.getGraphics().drawImage(buttonImage.getImage(), 0,(_by-_bx)/2 + 4, null); tmpImage.getGraphics().drawImage(arrowImage.getImage(), 0,0, _bx,_by/6, //dest 0,0, 24,8, //src null); buttonImage = tmpImage; } else { buttonImage = IconCache.scaleIcon(buttonImage, _bx, _by); } b.setIcon(buttonImage); } public void updateButtonsIcons() { //resize all button icons Component c[] = (Component[])buttons.getComponents(); for(int a=0;a<c.length;a++) { if (!(c[a] instanceof JButton)) continue; JButton b = (JButton)c[a]; updateButtonIcon(b); } } public void loadButtons() { //load buttons for config.app[] for(int a=0;a<config.dock.length;) { if (addButton(config.dock[a].file, true, -1) == null) { removeApp(a); } else { a++; } } } public boolean haveApp(String file) { Component buts[] = buttons.getComponents(); for(int a=0;a<buts.length;a++) { if (!(buts[a] instanceof JButton)) continue; JButton b = (JButton)buts[a]; String bfile = (String)b.getClientProperty("file"); if (bfile.equals(file)) return true; } return false; } public void updateConfig() { validateConfig(); bx = config.dockSize; by = config.dockSize; updateButtonIcon(apps); updateButtonIcon(left); updateButtonIcon(right); getDimensions(); DisplayMode screen_mode = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode(); JFLog.log("updateConfig:screen=" + screen_mode.getWidth() + "x" + screen_mode.getHeight()); try { Linux.x11_set_strut(x11id, (config.autoHide ? 1 : panelHeight-borderSize), 0, 0, screen_mode.getWidth(), screen_mode.getHeight()); } catch (Throwable t) { JFLog.log(t); } getScreenSize(); if (Desktop.desktop != null) { Desktop.desktop.browser.setWallPaper(config.desktopFile, config.desktopMode); Desktop.desktop.setPosition(); } if (!config.autoHide) { if (isDockHidden) { showDock(); } else { setPosition(); } } else { if (isDockHidden) { setPosition(); } else { hideDock(); } } if (config.showClock) { buttons.add(clockImage); } else { buttons.remove(clockImage); } if (config.compact) { buttons.add(quad); buttons.remove(powerHalf); buttons.remove(settingsHalf); buttons.remove(networkHalf); buttons.remove(soundHalf); } else { buttons.remove(quad); buttons.add(powerHalf); buttons.add(settingsHalf); buttons.add(networkHalf); buttons.add(soundHalf); } if (config.showKeyboard) { buttons.add(keyboard); } else { buttons.remove(keyboard); } bx = config.dockSize; by = config.dockSize; updateButtonsIcons(); updateButtons(); } public void addAppsButton() { apps = addButton("jfdesktop-apps", "Add", "#apps", appIdx++, true); } public void addClock() { clockImage = new JFImage() { public void paint(Graphics g) { FontMetrics fm = clockImage.getFontMetrics(clockImage.getFont()); Dimension size = clockImage.getPreferredSize(); int height = fm.getHeight(); g.setColor(Color.white); g.drawRect(0,0, size.width,size.height); g.setColor(Color.black); g.setFont(clockFont); if (config.dockSize >= 32) { int width = fm.stringWidth(clockLine1); g.drawBytes(clockLine1.getBytes(), 0, clockLine1.length(), (size.width - width) / 2, ((size.height/2 - height) / 2) + height); width = fm.stringWidth(clockLine2); g.drawBytes(clockLine2.getBytes(), 0, clockLine2.length(), (size.width - width) / 2, (size.height/2) + ((size.height/2 - height) / 2) + (height/2)); //BUG : last /2 shouldn't be needed but is } else { //can only do one line int width = fm.stringWidth(clockLine2); g.drawBytes(clockLine2.getBytes(), 0, clockLine2.length(), (size.width - width) / 2, ((size.height - height)/2) + height); } } public Dimension getPreferredSize() { Dimension size = new Dimension(); FontMetrics fm = clockImage.getFontMetrics(clockImage.getFont()); size.width = fm.stringWidth("88:88:88 AM"); size.height = buttonHeight; return size; } }; clockFont = new Font(null, Font.BOLD, 12); clockImage.setComponentPopupMenu(ClockPopup); clockImage.addMouseListener(this); clockImage.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { try { if (calWindow == null) showCalendar(); else hideCalendar(); } catch (Exception e) {JFLog.log(e);} } }); if (config.showClock) buttons.add(clockImage); } public int getLastIdx() { return buttons.getComponentCount()-1; } public void folderChangeEvent(String event, String file) { if (event.equals("CREATED")) { trashFull(); } else if (event.equals("DELETED")) { if (!isTrashFull()) { trashEmpty(); } } } private int monitor; private void startTrashListener() { File file = new File(System.getenv("HOME") + "/.local/share/Trash"); file.mkdirs(); JFLog.log("Starting Trash monitor"); monitor = monitordir.add(file.getAbsolutePath()); monitordir.setListener(monitor, this); } private boolean isTrashFull() { File file = new File(JF.getUserPath() + "/.local/share/Trash"); if (!file.exists()) return false; File files[] = file.listFiles(); if (files == null) return false; return files.length > 0; } public void trashFull() { if (isTrashFull) return; isTrashFull = true; trash.setIcon(trashFullImage); validate(); repaint(); } public void trashEmpty() { isTrashFull = false; trash.setIcon(trashEmptyImage); validate(); repaint(); } private void addTrash() { trashEmptyImage = IconCache.scaleIcon(IconCache.loadIcon("jfdesktop-trash-empty"), bx, by); trashFullImage = IconCache.scaleIcon(IconCache.loadIcon("jfdesktop-trash-full"), bx, by); trash = addButton((isTrashFull() ? "jfdesktop-trash-full" : "jfdesktop-trash-empty"), "Trash", "#trash", getLastIdx(), true); trash.setComponentPopupMenu(TrashPopup); initTrashDND(); } private void addKeyboard() { addArrow = true; halfSized = true; keyboard = addButton("jfdesktop-keyboard", "Keyboard", "#keyboard", getLastIdx(), true); bx = config.dockSize; addArrow = false; halfSized = false; } private void addQuadControls() { quad = new JPanel(); quad.setLayout(new GridLayout(2,2)); addTo = quad; halfSized = true; powerQuad = addButton("jfdesktop-power", "Power", "#power", 0, true); powerQuad.setComponentPopupMenu(PowerPopup); settingsQuad = addButton("jfdesktop-config", "Settings", "#config", 0, true); settingsQuad.setComponentPopupMenu(ConfigPopup); networkQuad = addButton("jfdesktop-network", "Network", "#network", 0, true); soundQuad = addButton("jfdesktop-sound", "Sound", "#sound", 0, true); soundQuad.setComponentPopupMenu(SoundPopup); addTo = buttons; halfSized = false; if (config.compact) buttons.add(quad, getLastIdx()); } private void addHalfControls() { if (config.compact) addTo = new JPanel(); addArrow = true; halfSized = true; powerHalf = addButton("jfdesktop-power", "Power", "#power", 0, true); powerHalf.setComponentPopupMenu(PowerPopup); settingsHalf = addButton("jfdesktop-config", "Settings", "#config", 0, true); settingsHalf.setComponentPopupMenu(ConfigPopup); networkHalf = addButton("jfdesktop-network", "Network", "#network", 0, true); soundHalf = addButton("jfdesktop-sound", "Sound", "#sound", 0, true); soundHalf.setComponentPopupMenu(SoundPopup); addTo = buttons; addArrow = false; halfSized = false; } public void addArrows() { halfSized = true; left = addButton("jfdesktop-left", "Left", "#left", getLastIdx(), true); buttons.remove(left); right = addButton("jfdesktop-right", "Right", "#right", getLastIdx(), true); buttons.remove(right); halfSized = false; } private void addApp(String desktop) { App app = new App(); app.file = desktop; App newList[] = new App[config.dock.length + 1]; System.arraycopy(config.dock, 0, newList, 0, config.dock.length); newList[config.dock.length] = app; config.dock = newList; } private void addAppIfExists(String filename) { File fullPath = new File("/usr/share/applications/" + filename + ".desktop"); if (fullPath.exists()) addApp(fullPath.getAbsolutePath()); } private int calcMenuHeight(JPopupMenu menu) { return menu.getComponentCount() * 18 + 9; } private AddAppWindow appsDialog; public void addAppDialogClosed() { appsDialog = null; } public void actionPerformed(ActionEvent ae) { try { if (dragged) { dragged = false; return; } String action = ae.getActionCommand(); if (calWindow != null) { hideCalendar(); } if ((soundWindow != null) && (!action.equals("#sound"))) { hideSound(); } if (action.equals("#battery")) { updateBattery(); return; } if (action.equals("#new")) { //BUG : user should never be able to click this removeNewButton(); updateButtons(); return; } if (action.equals("#apps")) { if (appsDialog != null) { appsDialog.toFront(); } else { appsDialog = new AddAppWindow(); appsDialog.setVisible(true); } return; } if (action.equals("#bt-connect")) { btDialog = new BlueToothDialog(); btDialog.setVisible(true); return; } if (action.equals("#vpn-configure")) { try { Runtime.getRuntime().exec(new String[] {"jconfig", "vpn"}); } catch (Exception e) { JFLog.log(e); } return; } if (action.startsWith("#bt#")) { blueToothDisconnect(action.substring(4)); return; } if (action.equals("#sound")) { try { if (soundWindow == null) showSound(); else hideSound(); } catch (Exception e) {JFLog.log(e);} return; } if (action.equals("#network")) { if (networkTimer != null) { cancelNetworkConnection(); } else { getVPNList(); //triggers showNetworkPopup() } return; } if (action.equals("#config")) { showSettingsPopup(); return; } if (action.equals("#left")) { if (viewIdx > 0) { viewIdx--; overflowCnt++; updateButtons(); } return; } if (action.equals("#right")) { if (overflowCnt > 0) { viewIdx++; overflowCnt--; updateButtons(); } return; } if (action.equals("#trash")) { try { Runtime.getRuntime().exec(new String[] {"jfile", JF.getUserPath() + "/.local/share/Trash"}); } catch (Exception e) {} return; } if (action.equals("#keyboard")) { if (!keyboardShown) showKeyboard(); else hideKeyboard(); return; } if (action.equals("#power")) { PowerPopup.show(config.compact ? powerQuad : powerHalf, 0, -calcMenuHeight(PowerPopup)); return; } if (action.startsWith("#vpn#")) { connectVPN(action.substring(5)); return; } if (action.startsWith("#wap#")) { int idx = Integer.valueOf(action.substring(5)); WAP wap = wapItems.get(idx); connectWAP(wap.dev, wap.ssid, wap.encType); return; } if (action.equals("#wap-disconnect")) { jbusClient.call("org.jflinux.jnetworkmgr", "disconnectWAP" ,""); return; } Object obj = ae.getSource(); if (obj instanceof JButton) { //check if window is already active for this app and show it JButton button = (JButton)obj; Group group = (Group)button.getClientProperty("group"); String open = (String)button.getClientProperty("open"); //open'ing a new window? if (!group.isEmpty() && open == null) { group.getWindow(0).show(); return; } else { flashButton((JButton)obj); } } File file = new File(action); if (file.isDirectory()) { //open with jfile Runtime.getRuntime().exec(new String[] {"jfile", action}); return; } if (action.endsWith(".lnk")) { //open with Wine (if installed) Runtime.getRuntime().exec(new String[] {"wine", action}); return; } if (!action.endsWith(".desktop")) { //regular file, open with jopen Runtime.getRuntime().exec(new String[] {"jopen", action}); return; } //.desktop file, get Exec= line and execute it Linux.executeDesktop(action, null); } catch (Exception e) { JFLog.log(e); } } public void flashButton(JButton button) { if (flashTimer != null) return; flashTimer = new java.util.Timer(); flashTimer.schedule(new TimerTask() { private JButton button; private int cnt = 7, fullcnt = 6; private int clr; private int org = 0; private boolean brighter = false; public void run() { if (org == 0) { org = getBackground().getRGB(); clr = org; button.setContentAreaFilled(true); } if (brighter) clr += 0x110011; else clr -= 0x110011; cnt--; if (cnt == 0) { cnt = 7; brighter = !brighter; fullcnt--; if (fullcnt == 0) { flashTimer.cancel(); flashTimer = null; clr = org; button.setContentAreaFilled(false); } } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { button.setBackground(new Color(clr)); button.repaint(); } }); } public TimerTask init(JButton button) { this.button = button; return this; } }.init(button), 100, 100); } private String vpnList = ""; private String wapList = ""; private void showSettingsPopup() { ConfigPopup.show(config.compact ? settingsQuad : settingsHalf, 0, -calcMenuHeight(ConfigPopup)); } private void getWAPList() { jbusClient.call("org.jflinux.jnetworkmgr", "getWAPList", JBusClient.quote(jbusClient.pack)); } private void getVPNList() { jbusClient.call("org.jflinux.jnetworkmgr", "getVPNList", JBusClient.quote(jbusClient.pack)); } private static class WAP { public String dev, ssid, encType; } ArrayList<WAP> wapItems = new ArrayList<WAP>(); private void showNetworkPopup() { NetworkPopup.removeAll(); if (checkWireless()) { JMenu subWireless = new JMenu("Wireless"); NetworkPopup.add(subWireless); //list wireless access points String lns[] = wapList.split("[|]"); boolean wapActive = false; int idx = 0; String dev = null; int cnt = 0; int w = 0; wapItems.clear(); while (idx < lns.length) { if (cnt == 0) { dev = lns[idx++]; cnt = JF.atoi(lns[idx++]); } if (cnt == 0) continue; String ssid = lns[idx++]; String encType = lns[idx++]; WAP wap = new WAP(); if (ssid.endsWith(" *")) { wapActive = true; } wap.dev = dev; wap.ssid = ssid; wap.encType = encType; wapItems.add(wap); JMenuItem w1 = new JMenuItem(ssid); w1.setActionCommand("#wap#" + (w++)); w1.addActionListener(this); addMouseListener(w1); subWireless.add(w1); cnt--; } if (wapActive) { JMenuItem w1 = new JMenuItem("Disconnect..."); w1.setActionCommand("#wap-disconnect"); w1.addActionListener(this); addMouseListener(w1); subWireless.add(w1); } addMouseListener(subWireless); } if (checkBluetooth()) { JMenu subBluetooth = new JMenu("Bluetooth"); NetworkPopup.add(subBluetooth); for(int a=0;a<btDevices.size();a++) { String desc = btDevices.get(a).desc; JMenuItem b1 = new JMenuItem(desc); b1.setActionCommand("#bt#" + desc); b1.addActionListener(this); addMouseListener(b1); subBluetooth.add(b1); } JMenuItem b1 = new JMenuItem("Connect..."); b1.setActionCommand("#bt-connect"); b1.addActionListener(this); addMouseListener(b1); subBluetooth.add(b1); addMouseListener(subBluetooth); } //list vpn JMenu subVPN = new JMenu("VPN"); NetworkPopup.add(subVPN); String vpns[] = vpnList.split("[|]"); for(int a=0;a<vpns.length;a++) { if (vpns[a].length() == 0) continue; String name = vpns[a]; JMenuItem vpn1 = new JMenuItem(name); vpn1.setActionCommand("#vpn#" + vpns[a]); vpn1.addActionListener(this); addMouseListener(vpn1); subVPN.add(vpn1); } JMenuItem vpn1 = new JMenuItem("Configure..."); vpn1.setActionCommand("#vpn-configure"); vpn1.addActionListener(this); addMouseListener(vpn1); subVPN.add(vpn1); addMouseListener(NetworkPopup); addMouseListener(subVPN); NetworkPopup.show(config.compact ? networkQuad : networkHalf, 0, -calcMenuHeight(NetworkPopup)); } private void emptyTrash() { JFLog.log("empty trash"); File file = new File(System.getenv("HOME") + "/.local/share/Trash"); //glob files ArrayList<String> cmd = new ArrayList<String>(); cmd.add("jrm"); File files[] = file.listFiles(); if (files == null) return; for(int a=0;a<files.length;a++) { cmd.add(files[a].getAbsolutePath()); } try { Runtime.getRuntime().exec(cmd.toArray(new String[0])); } catch (Exception e) { JFLog.log(e); } } private static String months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}; private void setClock() { Calendar now = Calendar.getInstance(); clockLine1 = String.format("%s %s", months[now.get(Calendar.MONTH)], now.get(Calendar.DAY_OF_MONTH)); int hour = now.get(Calendar.HOUR); if (hour == 0) hour = 12; clockLine2 = String.format("%d:%02d", hour, now.get(Calendar.MINUTE)); clockImage.repaint(); } public void updateClock() { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { setClock(); } }); } public void setupClockTimer() { if (clockTimer != null) clockTimer.cancel(); Calendar now = Calendar.getInstance(); clockTimer = new java.util.Timer(); clockTimer.scheduleAtFixedRate(new TimerTask() {public void run() {updateClock();}} ,60000 - now.get(Calendar.SECOND) * 1000, 60000); } private void calcDockHeight() { int pos = dockSliderPos; dockHeight = (panelHeight-borderSize) * pos / 100; if (dockHeight == 0) dockHeight = 1; } private class DockSliderTask extends TimerTask { public void run() { try { synchronized(sliderLock) { if (dockSliderShow) { if (dockSliderPos == 100) { dockSliderTimer.cancel(); dockSliderTimer = null; } else { dockSliderPos += 25; calcDockHeight(); setPosition(); } } else { if (dockSliderPos == 0) { dockSliderTimer.cancel(); dockSliderTimer = null; } else { dockSliderPos -= 25; calcDockHeight(); setPosition(); } } if (keyboardShown) { keyboardWindow.setPosition(keyboardHeight, dockHeight); } } } catch (Exception e) { JFLog.log(e); } } } private void removeNewButton() { buttons.remove(newButton); newButton = null; appIdx--; buttonsCount--; } private java.util.Timer dockSliderTimer = null; private final Object sliderLock = new Object(); private int dockSliderPos = 0; //percentage of dock visible private int dockHeight = 0; //actual size private boolean dockSliderShow = true; private void hideDock() { if (newButton != null) { removeNewButton(); } if (!config.autoHide) return; if (isDockHidden) return; isDockHidden = true; if (newButton != null) { removeNewButton(); } if (soundWindow != null) { hideSound(); } if (calWindow != null) { hideCalendar(); } if (PowerPopup.isVisible()) PowerPopup.setVisible(false); if (ConfigPopup.isVisible()) ConfigPopup.setVisible(false); if (NetworkPopup.isVisible()) NetworkPopup.setVisible(false); synchronized(sliderLock) { getScreenSize(); dockSliderShow = false; if (dockSliderTimer == null) { dockSliderTimer = new java.util.Timer(); dockSliderTimer.schedule(new DockSliderTask(), 50, 50); } } } private void showDock() { if (!isDockHidden) return; isDockHidden = false; synchronized(sliderLock) { dockSliderShow = true; if (dockSliderTimer == null) { dockSliderTimer = new java.util.Timer(); dockSliderTimer.schedule(new DockSliderTask(), 50, 50); } } if (!haveMouse) { autoHideTimer = new java.util.Timer(); autoHideTimer.schedule(new TimerTask() { public void run() { if (!haveMouse && !isDockHidden && drag == null) hideDock(); } }, 5*1000); } } private class KeyboardSliderTask extends TimerTask { public void run() { synchronized(sliderLock) { if (keyboardSliderShow) { if (keyboardHeight == 200) { keyboardSliderTimer.cancel(); keyboardSliderTimer = null; } else { keyboardHeight += 25; keyboardWindow.setPosition(keyboardHeight, dockHeight); } } else { if (keyboardHeight == 0) { keyboardSliderTimer.cancel(); keyboardSliderTimer = null; keyboardWindow.setVisible(false); keyboardShown = false; } else { keyboardHeight -= 25; keyboardWindow.setPosition(keyboardHeight, dockHeight); } } } } } private java.util.Timer keyboardSliderTimer = null; private int keyboardHeight = 0; //actual size of keyboard height (1-200) private boolean keyboardSliderShow = true; private void showKeyboard() { if (keyboardShown) return; synchronized(sliderLock) { keyboardWindow.setPosition(1, dockHeight); keyboardWindow.setVisible(true); keyboardShown = true; keyboardSliderShow = true; if (keyboardSliderTimer == null) { keyboardSliderTimer = new java.util.Timer(); keyboardSliderTimer.schedule(new KeyboardSliderTask(), 50, 50); } } } public void hideKeyboard() { if (!keyboardShown) return; synchronized(sliderLock) { keyboardSliderShow = false; if (keyboardSliderTimer == null) { keyboardSliderTimer = new java.util.Timer(); keyboardSliderTimer.schedule(new KeyboardSliderTask(), 50, 50); } } } private void showCalendar() { if (soundWindow != null) hideSound(); calWindow = new CalendarWindow(clockImage.getLocationOnScreen(), clockImage.getWidth()); calWindow.setVisible(true); calWindow.addMouseListener(this); } private void hideCalendar() { calWindow.setVisible(false); calWindow.dispose(); calWindow = null; } private void showSound() { if (calWindow != null) hideCalendar(); Point pos; int width; if (config.compact) { pos = soundQuad.getLocationOnScreen(); width = soundQuad.getWidth(); } else { pos = soundHalf.getLocationOnScreen(); width = soundHalf.getWidth(); } //sometimes pos.y is wrong so calc it instead pos.y = sy - buttonHeight + 1; soundWindow = new SoundWindow(pos, width); soundWindow.setVisible(true); soundWindow.addMouseListener(this); soundWindow.reload(config); } private void hideSound() { soundWindow.setVisible(false); soundWindow.dispose(); soundWindow = null; } public void mouseClicked(MouseEvent me) { if (me.getSource() == buttons) { if (x11id == 0) return; try { x11_set_dock(); } catch (Throwable t) { JFLog.log(t); } } } public void mousePressed(MouseEvent me) { // JFLog.log("press:" + me); draggable = me.getButton() == MouseEvent.BUTTON1; if (me.getSource() == this && me.getButton() == MouseEvent.BUTTON3) { TaskbarPopup.show(this, me.getX(), me.getY()); } } private volatile boolean showDockTimerActive = false; public void mouseEntered(MouseEvent me) { haveMouse = true; if (autoHideTimer != null) { autoHideTimer.cancel(); autoHideTimer = null; } if ((isDockHidden) && (!showDockTimerActive)) { showDockTimerActive = true; new java.util.Timer().schedule(new TimerTask() { public void run() { showDockTimerActive = false; if (haveMouse && isDockHidden) showDock(); } }, 250); } } private volatile boolean hideDockTimerActive = false; public void mouseExited(MouseEvent me) { haveMouse = false; if ((!isDockHidden) && (!hideDockTimerActive)) { hideDockTimerActive = true; new java.util.Timer().schedule(new TimerTask() { public void run() { hideDockTimerActive = false; if (!haveMouse && !isDockHidden && drag == null) hideDock(); } }, 250); } } public void mouseReleased(MouseEvent me) { // JFLog.log("release:" + me); try { draggable = false; if (drag == null) return; drag.setBackground(drag_org_color); drag = null; getContentPane().setCursor(Cursor.getDefaultCursor()); updateAppList(); } catch (Exception e) { JFLog.log(e); } } private JButton drag; private int dragx, dragy; private int drag_width; private Color drag_org_color; private int drag_component_idx; public boolean dragged, draggable; public void mouseDragged(MouseEvent me) { if (!draggable) return; dragged = true; //avoid click after dragging (not working) try { //move Button if (drag == null) { //start drag JButton button = (JButton)me.getSource(); String file = (String)button.getClientProperty("file"); if ((file == null) || (file.startsWith("#"))) return; drag = button; dragx = me.getXOnScreen(); dragy = me.getYOnScreen(); drag_width = button.getWidth(); getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); drag_org_color = button.getBackground(); button.setBackground(Color.green); drag_component_idx = -1; int cnt = buttons.getComponentCount(); for(int a=0;a<cnt;a++) { if (buttons.getComponent(a) == drag) { drag_component_idx = a; break; } } } else { //move drag if (drag_component_idx == -1) return; //error int newX = me.getXOnScreen(); if (needArrows) { newX += halfWidth; } int newIdx = newX / buttonWidth; if (newIdx < 1) newIdx = 1; if (newIdx >= appIdx) newIdx = appIdx-1; if (newIdx == drag_component_idx) return; drag_component_idx = newIdx; buttons.setComponentZOrder(drag, newIdx); updateButtons(); } } catch (Exception e) { JFLog.log(e); } } public void mouseMoved(MouseEvent me) { } private static void doRun() { try { RunDialog runDialog = new RunDialog(null, true); runDialog.setVisible(true); } catch (Exception e) { JFLog.log(e); } } private void addMouseListener(JComponent jc) { jc.addMouseListener(this); int cnt = jc.getComponentCount(); for(int a=0;a<cnt;a++) { jc.getComponent(a).addMouseListener(this); } } private void closeAllApps() { saveConfig(); //close open VPN connections jbusClient.call("org.jflinux", "closeAllVPN", ""); //close all apps belonging to this user //BUG : killall may kill other sessions of same user??? try { Runtime.getRuntime().exec(new String[] {"killall", "-u", System.getenv("USER")}); } catch (Exception e) {JFLog.log(e);} } public void showConfig() { ConfigDialog dialog = new ConfigDialog(null, true, config); dialog.setVisible(true); if (dialog.accepted) { dialog.updateConfig(config); updateConfig(); saveConfig(); } } private void checkBattery() { ShellProcess sp = new ShellProcess(); String output = sp.run(new String[] {"acpi"}, false); if (output.indexOf("Battery") == -1) return; batteryImage = IconCache.loadIcon("jfdesktop-battery"); try { tray = SystemTray.getSystemTray(); trayIcon = new TrayIcon(batteryImage.getImage(), "Battery", BatteryPopup); tray.add(trayIcon); } catch (Exception e) { JFLog.log(e); return; } new java.util.Timer().schedule(new TimerTask() {public void run() {updateBattery();}}, 0, 60000); } private boolean checkBluetooth() { ShellProcess sp = new ShellProcess(); String output = sp.run(new String[] {"hciconfig"}, false); if (output.indexOf("hci") == -1) return false; return true; } private boolean checkWireless() { ShellProcess sp = new ShellProcess(); String output = sp.run(new String[] {"iwconfig"}, false); if (output.indexOf("ESSID") == -1) return false; return true; } private JFImage plugImage; private void updateBattery() { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { ShellProcess sp = new ShellProcess(); String output = sp.run(new String[] {"acpi"}, false); String lns[] = output.split("\n"); String f[] = lns[0].split(","); //only show battery #1 //Battery 1: discharging, 44%, 00:18:48 remaining int percent = JF.atoi(f[1].trim().replaceAll("%", "")); Graphics g = batteryImage.getGraphics(); g.setColor(Color.white); g.fillRect(4,2,15,20); int h = percent * 20 / 100; int y = 2 + (20-h); if (percent < 15) { g.setColor(Color.yellow); } else if (percent < 5) { g.setColor(Color.red); } else { g.setColor(Color.green); } g.fillRect(4,y,15,h); if (lns[0].indexOf("Discharging") == -1) { if (plugImage == null) { plugImage = IconCache.loadIcon("jfdesktop-plug"); } g.drawImage(plugImage.getImage(), 0, 0, null); } trayIcon.setImage(batteryImage.getImage()); } }); } //LayoutManager public void addLayoutComponent(String string, Component cmpnt) { } public void removeLayoutComponent(Component cmpnt) { } public Dimension preferredLayoutSize(Container p) { if (isDockHidden) { return new Dimension(sx, panelHiddenHeight); } return new Dimension(sx, panelHeight + borderSize*2); } public Dimension minimumLayoutSize(Container p) { if (isDockHidden) { return new Dimension(sx, panelHiddenHeight); } return new Dimension(sx, panelHeight + borderSize*2); } public void layoutContainer(Container p) { try { if (p == getContentPane()) { synchronized(p.getParent().getTreeLock()) { buttons.setBounds(0,0,sx,panelHeight); } return; } synchronized(p.getParent().getTreeLock()) { Dimension d; //do we need arrows? int tWidth = 0, bWidth = 0; //tools width, buttons width bWidth += appIdx * buttonWidth; if (config.showClock) { d = clockImage.getPreferredSize(); tWidth += d.width; } if (config.showKeyboard) { d = keyboard.getPreferredSize(); tWidth += d.width; } if (config.compact) { //quad controls tWidth += buttonWidth; } else { //half controls tWidth += halfWidth * 4; } tWidth += buttonWidth; //trash int trayWidth = Linux.x11_tray_width(); // JFLog.log("dock widths:" + bWidth + "," + trayWidth + "," + tWidth); int cnt = 0; if (bWidth + trayWidth + tWidth > sx) { //need arrow buttons if (!needArrows) { needArrows = true; buttons.add(left,getLastIdx()); buttons.add(right,getLastIdx()); } int arrowsWidth = halfWidth * 2; //left + right arrows int appsWidth = buttonWidth; cnt = (sx - appsWidth - tWidth - arrowsWidth - trayWidth) / buttonWidth; bWidth = cnt * buttonWidth; overflowCnt = buttonsCount - cnt - viewIdx; } else { //no arrows - show all buttons if (needArrows) { needArrows = false; buttons.remove(left); buttons.remove(right); } cnt = buttonsCount; viewIdx = 0; overflowCnt = 0; } int cx = 0; apps.setBounds(cx, borderSize, buttonWidth, buttonHeight); cx += buttonWidth; if (needArrows) { left.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; for(int a=1;a<=viewIdx;a++) { p.getComponent(a).setVisible(false); } } int idx = 1 + viewIdx; while (cnt > 0) { Component c = p.getComponent(idx++); c.setVisible(true); c.setBounds(cx, borderSize, buttonWidth, buttonHeight); cx += buttonWidth; cnt--; } while (idx < appIdx) { p.getComponent(idx++).setVisible(false); } if (needArrows) { right.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; } cx = sx - tWidth; trayPos = cx; Linux.x11_tray_reposition(sx, trayPos, buttonHeight + trayPad); if (config.compact) { quad.setBounds(cx, borderSize, buttonWidth, buttonHeight); cx += buttonWidth; } else { powerHalf.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; settingsHalf.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; networkHalf.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; soundHalf.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; } if (config.showKeyboard) { keyboard.setBounds(cx, borderSize, halfWidth, buttonHeight); cx += halfWidth; } trash.setBounds(cx, borderSize, buttonWidth, buttonHeight); cx += buttonWidth; if (config.showClock) { d = clockImage.getPreferredSize(); clockImage.setBounds(cx, borderSize, d.width, buttonHeight); } } } catch (Exception e) { JFLog.log(e); } } private void disconnectVPN(String name) { jbusClient.call("org.jflinux.jnetworkmgr", "disconnectVPN", JBusClient.quote(name)); } private void connectVPN(String name) { if (name.endsWith(" *")) { disconnectVPN(name.substring(0, name.length() - 2)); } else { startNetworkTimer("cancelVPN"); jbusClient.call("org.jflinux.jnetworkmgr", "connectVPN", JBusClient.quote(jbusClient.pack) + "," + JBusClient.quote(name)); } } private void disconnectWAP(String ssid) { jbusClient.call("org.jflinux.jnetworkmgr", "disconnectWAP" , JBusClient.quote(ssid)); } private void connectWAP(String dev, String ssid, String encType) { if (ssid.endsWith(" *")) { disconnectWAP(ssid.substring(0, ssid.length() - 2)); } else { String key = ""; if (encType.equals("WEP")) { key = JF.getString("Enter WEP encryption key (26 or 10 hex digits)", ""); } else if (encType.equals("WPA")) { key = JF.getString("Enter WPA pass phrase", ""); } startNetworkTimer("cancelWAP"); jbusClient.call("org.jflinux.jnetworkmgr", "connectWAP", JBusClient.quote(jbusClient.pack) + "," + JBusClient.quote(dev) + "," + JBusClient.quote(ssid) + "," + JBusClient.quote(encType) + "," + JBusClient.quote(key)); } } private void blueToothDisconnect(String dev) { for(int a=0;a<btDevices.size();a++) { if (btDevices.get(a).desc.equals(dev)) { ShellProcess sp = new ShellProcess(); String output = sp.run(new String[] {"hcitool", "dc", btDevices.get(a).mac}, false); // if (output.startsWith("Not connected")) {} btDevices.remove(a); } } } private java.util.Timer networkTimer; private int networkIconIdx; private JFImage networkIconsQuad[]; private JFImage networkIconsHalf[]; private Icon networkOrgIcon; private final Object networkLock = new Object(); private int networkTimerCount; private String cancelNetworkMethod; private void loadNetworkIcons() { halfSized = true; networkIconsQuad = new JFImage[3]; networkIconsHalf = new JFImage[3]; for(int a=0;a<3;a++) { JFImage img = IconCache.loadIcon("jfdesktop-network-" + (a+1)); networkIconsQuad[a] = IconCache.scaleIcon(img, 21, 21); JFImage tmpImage = new JFImage(bx, by); tmpImage.fill(0, 0, bx, by, 0, true); tmpImage.getGraphics().drawImage(IconCache.scaleIcon(img, 24, 24).getImage(), 0,(by-bx)/2 + 4, null); tmpImage.getGraphics().drawImage(arrowImage.getImage(), 0,0, null); networkIconsHalf[a] = tmpImage; } halfSized = false; } private void startNetworkTimer(String cancelMethod) { if (networkTimer != null) return; cancelNetworkMethod = cancelMethod; networkIconIdx = 0; networkTimerCount = 0; networkTimer = new java.util.Timer(); networkTimer.schedule(new TimerTask() { public void run() { synchronized(networkLock) { if (networkTimer == null) return; networkTimerCount++; if (networkTimerCount == 60) { //after 30 seconds JFLog.log("30 seconds timeout network connection"); networkTimer.cancel(); networkTimer = null; resetNetworkIcon(); cancelNetworkConnection(); return; } try { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { if (config.compact) { if (networkOrgIcon == null) networkOrgIcon = networkQuad.getIcon(); networkIconIdx++; if (networkIconIdx == networkIconsQuad.length) networkIconIdx = 0; networkQuad.setIcon(networkIconsQuad[networkIconIdx]); } else { if (networkOrgIcon == null) networkOrgIcon = networkHalf.getIcon(); networkIconIdx++; if (networkIconIdx == networkIconsHalf.length) networkIconIdx = 0; networkHalf.setIcon(networkIconsHalf[networkIconIdx]); } } }); } catch (Exception e) {} } } }, 0, 500); } private void stopNetworkTimer() { synchronized(networkLock) { cancelNetworkMethod = null; networkTimer.cancel(); networkTimer = null; } resetNetworkIcon(); } private void resetNetworkIcon() { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { if (config.compact) { networkQuad.setIcon(networkOrgIcon); } else { networkHalf.setIcon(networkOrgIcon); } networkOrgIcon = null; } }); } private void cancelNetworkConnection() { if (cancelNetworkMethod == null) return; stopNetworkTimer(); jbusClient.call("org.jflinux.jnetworkmgr", cancelNetworkMethod, ""); cancelNetworkMethod = null; showNetworkFailed(); } private void showNetworkFailed() { JF.showError("Error", "Connection failed!"); } private void showWelcome() { try { Runtime.getRuntime().exec("jwelcome"); } catch (Exception e) { JFLog.log(e); } } private void mkdirs() { new File(JF.getUserPath() + "/Desktop").mkdir(); new File(JF.getUserPath() + "/Documents").mkdir(); new File(JF.getUserPath() + "/Music").mkdir(); new File(JF.getUserPath() + "/Pictures").mkdir(); new File(JF.getUserPath() + "/Videos").mkdir(); new File(JF.getUserPath() + "/Downloads").mkdir(); } public void soundinit() { new Thread() { public void run() { SoundWindow.init(config); saveConfig(); } }.start(); } public void initUpgrades() { try { File file = new File("/etc/upgrades.cnts"); if (!file.exists()) return; FileInputStream fis = new FileInputStream(file); String str = new String(JF.readAll(fis)); fis.close(); if (str.length() == 0) return; int idx = str.indexOf(" "); if (idx == -1) return; int cnts = JF.atoi(str.substring(0, idx)); setUpgradesAvailable(cnts); } catch (Exception e) { JFLog.log(e); } } public void setUpgradesAvailable(int cnt) { for(int a=0;a<ConfigPopup.getComponentCount();a++) { JMenuItem mi = (JMenuItem)ConfigPopup.getComponent(a); if (mi.getText().startsWith("Upgrades")) { mi.setText("Upgrades (" + cnt + ")"); break; } } } public void x11_set_dock() { try { Linux.x11_set_dock(x11id); } catch (Throwable t) { JFLog.log(t); } } public int getPanelHeight() { return panelHeight; } private void initTrashDND() { trash.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport info) { // we only import Files if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } // TransferHandler.DropLocation dl = (TransferHandler.DropLocation) info.getDropLocation(); // Point pt = dl.getDropPoint(); return true; } public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for file flavor if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } // TransferHandler.DropLocation dl = info.getDropLocation(); // Point pt = dl.getDropPoint(); String folder = JF.getUserPath() + "/.local/share/Trash"; // Get the file(s) that are being dropped. Transferable t = info.getTransferable(); java.util.List<File> data; try { data = (java.util.List<File>) t.getTransferData(DataFlavor.javaFileListFlavor); } catch (Exception e) { return false; } // Perform the actual import. ArrayList<String> cmd = new ArrayList<String>(); boolean move = false; boolean copy = false; for(int a=0;a<data.size();a++) { switch (info.getDropAction()) { case COPY: case MOVE: if (copy) return false; //Can that happen? move = true; cmd.add(((File)data.get(a)).getAbsolutePath()); break; case LINK: return false; //BUG : not supported : ??? } } if (cmd.isEmpty()) return false; cmd.add(0, "-v"); cmd.add(0, "-n"); if (copy) { cmd.add(0, "cp"); } else if (move) { cmd.add(0, "mv"); } else { return false; } cmd.add(folder); JFileBrowser.runCmd(null, cmd.toArray(new String[0])); return true; } public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } protected Transferable createTransferable(JComponent c) { //can not transfer out of trash from this icon return null; } protected void exportDone(JComponent source, Transferable data, int action) { } }); } private int getDragIdx(Point pt) { int x = pt.x; if (needArrows) { x += halfWidth; } x /= buttonWidth; if (x < 1) return 1; if (x >= appIdx) return appIdx-1; return x; } private void initDockDND() { this.setTransferHandler(new TransferHandler() { public boolean canImport(TransferHandler.TransferSupport info) { // we only import Files if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } TransferHandler.DropLocation dl = (TransferHandler.DropLocation) info.getDropLocation(); Point pt = dl.getDropPoint(); if (newButton == null) { newButtonIdx = getDragIdx(pt); newButton = addButton("jfdesktop-new", "New", "#new", newButtonIdx, false); appIdx++; buttonsCount++; } else { int newIdx = getDragIdx(pt); if (newIdx == newButtonIdx) return true; //no change newButtonIdx = newIdx; buttons.setComponentZOrder(newButton, newButtonIdx); } mouseEntered(null); //prevent dock for hiding updateButtons(); return true; } public boolean importData(TransferHandler.TransferSupport info) { if (!info.isDrop()) { return false; } // Check for file flavor if (!info.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { return false; } TransferHandler.DropLocation dl = info.getDropLocation(); Point pt = dl.getDropPoint(); int idx = getDragIdx(pt); // Get the file(s) that are being dropped. Transferable t = info.getTransferable(); java.util.List<File> data; try { data = (java.util.List<File>) t.getTransferData(DataFlavor.javaFileListFlavor); } catch (Exception e) { return false; } if (newButton != null) { removeNewButton(); } // Perform the actual import. String file; for(int a=0;a<data.size();a++) { switch (info.getDropAction()) { case COPY: case MOVE: file = ((File)data.get(a)).getAbsolutePath(); if (!file.endsWith(".desktop")) continue; if (!haveApp(file)) { addButton(file, true, idx); addApp(file); } break; case LINK: //BUG : not supported : ??? continue; } } saveConfig(); updateButtons(); return true; } public int getSourceActions(JComponent c) { return COPY_OR_MOVE; } protected Transferable createTransferable(JComponent c) { //can not transfer out of trash from this icon return null; } protected void exportDone(JComponent source, Transferable data, int action) { } }); } private void loadMappings() { Mappings.loadMaps(); Mappings.Maps maps = Mappings.getMaps(); if (maps == null || maps.map == null) return; JBusMethods methods = new JBusMethods(); for(int a=0;a<maps.map.length;a++) { methods.mount(null, maps.map[a].uri, maps.map[a].mount, maps.map[a].passwd, maps.map[a].wineDrive); } } private void openButton(JButton button) { button.putClientProperty("open", "true"); //ensure a NEW window is opened (not just select already active window) button.doClick(); button.putClientProperty("open", null); } private void createAppPopupMenu(JButton button) { JPopupMenu popup = new JPopupMenu(); JMenuItem item; Boolean pinned = (Boolean)button.getClientProperty("pinned"); Group group = (Group)button.getClientProperty("group"); item = new JMenuItem(group.isEmpty() ? "Open" : "Open new window"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JMenuItem mi = (JMenuItem)e.getSource(); JPopupMenu pm = (JPopupMenu)mi.getParent(); openButton((JButton)pm.getInvoker()); } }); popup.add(item); for(int a=0;a<group.size();a++) { final Window window = group.getWindow(a); item = new JMenuItem(window.title); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { window.show(); } }); popup.add(item); } item = new JMenuItem("Copy to Desktop"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JMenuItem mi = (JMenuItem)e.getSource(); JPopupMenu pm = (JPopupMenu)mi.getParent(); copyButtonToDesktop((JButton)pm.getInvoker()); } }); popup.add(item); item = new JMenuItem(pinned ? "Unpin" : "Pin"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JMenuItem mi = (JMenuItem)e.getSource(); JPopupMenu pm = (JPopupMenu)mi.getParent(); togglePinned((JButton)pm.getInvoker()); } }); popup.add(item); addMouseListener(popup); button.setComponentPopupMenu(popup); } private void updateAppList() { ArrayList<App> list = new ArrayList<App>(); Component buts[] = buttons.getComponents(); for(int a=0;a<buts.length;a++) { if (!(buts[a] instanceof JButton)) continue; JButton button = (JButton)buts[a]; String file = (String)button.getClientProperty("file"); if (file.startsWith("#")) continue; Boolean pinned = (Boolean)button.getClientProperty("pinned"); if (!pinned) continue; App app = new App(); app.file = (String)button.getClientProperty("file"); list.add(app); } config.dock = list.toArray(new App[0]); saveConfig(); } private void updateButtons() { buttons.revalidate(); buttons.repaint(); } public class JBusMethods { public void run() { doRun(); } public void show() { showDock(); } public void getWelcome(String pack) { jbusClient.call(pack, "setWelcome", JBusClient.quote("" + config.welcome)); } public void setWelcome(String state) { config.welcome = state.equals("true"); saveConfig(); } public void upgradesAvailable(int upgrades) { setUpgradesAvailable(upgrades); } public void volume(String lvl) { if ((lvl == null) || (lvl.length() == 0)) return; if (isDockHidden) showDock(); if (soundWindow == null) showSound(); if (lvl.equals("mute")) { soundWindow.mute(); } else if (lvl.charAt(0) == '+') { soundWindow.adjustVolume(JF.atoi(lvl.substring(1))); } else if (lvl.charAt(0) == '-') { soundWindow.adjustVolume(-JF.atoi(lvl.substring(1))); } } public void vpnFailed(String id) { stopNetworkTimer(); showNetworkFailed(); } public void vpnSuccess(String id) { stopNetworkTimer(); } public void wapFailed() { stopNetworkTimer(); showNetworkFailed(); } public void wapSuccess() { stopNetworkTimer(); } public void btFailed() { if (btDialog == null) return; btDialog.failed(); } public void btSuccess() { if (btDialog == null) return; btDialog.success(); } public void setBTdevices(String list) { if (btDialog == null) return; btDialog.devices(list); } public void soundSinkVolumeChanged(int idx, int volume) { if (idx == PulseAudio.sinks.get(0).idx) SoundWindow.setVolume(volume); for(int a=0;a<config.sink.length;a++) { if (config.sink[a].idx == idx) { config.sink[a].volume = volume; saveConfig(); return; } } } public void soundSourceVolumeChanged(int idx, int volume) { for(int a=0;a<config.source.length;a++) { if (config.source[a].idx == idx) { config.source[a].volume = volume; saveConfig(); return; } } } public void soundSinkPortChanged(int idx, String port) { for(int a=0;a<config.sink.length;a++) { if (config.sink[a].idx == idx) { config.sink[a].activePort = port; saveConfig(); return; } } } public void soundSourcePortChanged(int idx, String port) { for(int a=0;a<config.source.length;a++) { if (config.source[a].idx == idx) { config.source[a].activePort = port; saveConfig(); return; } } } public void soundProfileChanged(int idx, String profile) { for(int a=0;a<config.card.length;a++) { if (config.card[a].idx == idx) { config.card[a].activeProfile = profile; saveConfig(); return; } } } public void timeAdjusted() { setupClockTimer(); } public void videoChanged(String reason) { //TODO : popup window asking to load jconfig:display if (reason.equals("jconfig")) { updateConfig(); } else { //else udev event : need to call x11_rr_auto first java.awt.EventQueue.invokeLater(new Runnable() { public void run() { Linux.x11_rr_auto(); updateConfig(); } }); } } public void powerChanged() { updateBattery(); } public void mount(String callback, String uri, String mount, String pass, String link) { JFLog.log("mount:" + uri + "," + mount); final String _callback = callback; final String _uri = uri; new Thread() { public void run() { try { Process p = Runtime.getRuntime().exec(new String[] {"gnome-disk-image-mounter", _uri}); p.waitFor(); int result = p.exitValue(); if (_callback != null) jbusClient.call(_callback, result == 0 ? "mountSuccess" : "mountFail", JBusClient.quote(_uri)); } catch (Exception e) { JFLog.log(e); } } }.start(); } public void setWAPList(String list) { wapList = list; } public void setVPNList(String list) { vpnList = list; showNetworkPopup(); } //jfile : file ops (should use clipboard) public void setFileSelection(String selection) { JFLog.log("setSelection:" + selection); fileSelection = selection; } public void getFileSelection(String pack) { if (fileSelection == null) return; JFLog.log("getSelection:" + pack); jbusClient.call(pack, "getFileSelection", JBusClient.quote(fileSelection)); } public void clearFileSelection() { JFLog.log("clearSelection"); fileSelection = null; } } public void get() { if (fileSelection == null) return; Desktop.desktop.browser.paste(JBusClient.decodeString(fileSelection)); } public void set(String fileset) { fileSelection = fileset; } public void clear() { fileSelection = ""; } }